* gdb.base/maint.exp: Treat $EXEEXT as optional in output.
[deliverable/binutils-gdb.git] / gdb / m3-nat.c
CommitLineData
c906108c
SS
1/* Interface GDB to Mach 3.0 operating systems.
2 (Most) Mach 3.0 related routines live in this file.
3
b6ba6518 4 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
8e65ff28 5 Free Software Foundation, Inc.
c906108c 6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
c906108c 13
c5aa993b
JM
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
c906108c 18
c5aa993b
JM
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
c906108c
SS
23
24/*
25 * Author: Jukka Virtanen <jtv@hut.fi>
c5aa993b 26 * Computing Centre
c906108c
SS
27 * Helsinki University of Technology
28 * Finland
29 *
30 * Thanks to my friends who helped with ideas and testing:
31 *
c5aa993b
JM
32 * Johannes Helander, Antti Louko, Tero Mononen,
33 * jvh@cs.hut.fi alo@hut.fi tmo@cs.hut.fi
c906108c
SS
34 *
35 * Tero Kivinen and Eamonn McManus
c5aa993b
JM
36 * kivinen@cs.hut.fi emcmanus@gr.osf.org
37 *
c906108c
SS
38 */
39
40#include <stdio.h>
41
42#include <mach.h>
43#include <servers/netname.h>
44#include <servers/machid.h>
45#include <mach/message.h>
46#include <mach/notify.h>
47#include <mach_error.h>
48#include <mach/exception.h>
49#include <mach/vm_attributes.h>
50
51#include "defs.h"
52#include "inferior.h"
53#include "symtab.h"
54#include "value.h"
55#include "language.h"
56#include "target.h"
03f2053f 57#include "gdb_wait.h"
c906108c
SS
58#include "gdbcmd.h"
59#include "gdbcore.h"
4e052eda 60#include "regcache.h"
c906108c
SS
61
62#if 0
63#include <servers/machid_lib.h>
64#else
65#define MACH_TYPE_TASK 1
66#define MACH_TYPE_THREAD 2
67#endif
68
69/* Included only for signal names and NSIG
c5aa993b 70
c906108c
SS
71 * note: There are many problems in signal handling with
72 * gdb in Mach 3.0 in general.
73 */
74#include <signal.h>
c5aa993b 75#define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
c906108c
SS
76
77#include <cthreads.h>
78
79/* This is what a cproc looks like. This is here partly because
80 cthread_internals.h is not a header we can just #include, partly with
81 an eye towards perhaps getting this to work with cross-debugging
82 someday. Best solution is if CMU publishes a real interface to this
83 stuff. */
84#define CPROC_NEXT_OFFSET 0
85#define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
86#define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
87#define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
88#define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
89#define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
90#define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
91#define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
92#define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
93#define CPROC_REPLY_SIZE (sizeof (mach_port_t))
94#define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
95#define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
96#define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
97#define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
98#define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
99#define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
100#define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
101#define CPROC_WIRED_SIZE (sizeof (mach_port_t))
102#define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
103#define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
104#define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
105#define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
106#define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
107#define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
108#define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
109#define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
110#define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
111
112/* Values for the state field in the cproc. */
113#define CPROC_RUNNING 0
114#define CPROC_SWITCHING 1
115#define CPROC_BLOCKED 2
116#define CPROC_CONDWAIT 4
117
118/* For cproc and kernel thread mapping */
c5aa993b
JM
119typedef struct gdb_thread
120 {
121 mach_port_t name;
122 CORE_ADDR sp;
123 CORE_ADDR pc;
124 CORE_ADDR fp;
125 boolean_t in_emulator;
126 int slotid;
127
128 /* This is for the mthreads list. It points to the cproc list.
129 Perhaps the two lists should be merged (or perhaps it was a mistake
130 to make them both use a struct gdb_thread). */
131 struct gdb_thread *cproc;
132
133 /* These are for the cproc list, which is linked through the next field
134 of the struct gdb_thread. */
135 char raw_cproc[CPROC_SIZE];
136 /* The cthread which is pointed to by the incarnation field from the
137 cproc. This points to the copy we've read into GDB. */
138 cthread_t cthread;
139 /* Point back to the mthreads list. */
140 int reverse_map;
141 struct gdb_thread *next;
142 }
143 *gdb_thread_t;
c906108c
SS
144
145/*
146 * Actions for Mach exceptions.
147 *
148 * sigmap field maps the exception to corresponding Unix signal.
149 *
150 * I do not know how to map the exception to unix signal
151 * if SIG_UNKNOWN is specified.
152 */
153
c5aa993b
JM
154struct exception_list
155 {
156 char *name;
157 boolean_t forward;
158 boolean_t print;
159 int sigmap;
160 }
161exception_map[] =
162{
163 {
164 "not_mach3_exception", FALSE, TRUE, SIG_UNKNOWN
165 }
166 ,
167 {
168 "EXC_BAD_ACCESS", FALSE, TRUE, SIGSEGV
169 }
170 ,
171 {
172 "EXC_BAD_INSTRUCTION", FALSE, TRUE, SIGILL
173 }
174 ,
175 {
176 "EXC_ARITHMETIC", FALSE, TRUE, SIGFPE
177 }
178 ,
179 {
180 "EXC_EMULATION", FALSE, TRUE, SIGEMT
181 }
182 , /* ??? */
183 {
184 "EXC_SOFTWARE", FALSE, TRUE, SIG_UNKNOWN
185 }
186 ,
187 {
188 "EXC_BREAKPOINT", FALSE, FALSE, SIGTRAP
189 }
c906108c
SS
190};
191
192/* Mach exception table size */
c5aa993b 193int max_exception = sizeof (exception_map) / sizeof (struct exception_list) - 1;
c906108c
SS
194
195#define MAX_EXCEPTION max_exception
196
197WAITTYPE wait_status;
198
199/* If you define this, intercepted bsd server calls will be
200 * dumped while waiting the inferior to EXEC the correct
201 * program
202 */
c5aa993b 203/* #define DUMP_SYSCALL /* debugging interceptor */
c906108c
SS
204
205/* xx_debug() outputs messages if this is nonzero.
206 * If > 1, DUMP_SYSCALL will dump message contents.
207 */
208int debug_level = 0;
209
210/* "Temporary" debug stuff */
211void
fba45db2 212xx_debug (char *fmt, int a, int b, int c)
c906108c
SS
213{
214 if (debug_level)
215 warning (fmt, a, b, c);
216}
217
218/* This is in libmach.a */
c5aa993b 219extern mach_port_t name_server_port;
c906108c
SS
220
221/* Set in catch_exception_raise */
222int stop_exception, stop_code, stop_subcode;
223int stopped_in_exception;
224
225/* Thread that was the active thread when we stopped */
226thread_t stop_thread = MACH_PORT_NULL;
227
228char *hostname = "";
229
230/* Set when task is attached or created */
231boolean_t emulator_present = FALSE;
232
c5aa993b 233task_t inferior_task;
c906108c
SS
234thread_t current_thread;
235
236/* Exception ports for inferior task */
c5aa993b 237mach_port_t inferior_exception_port = MACH_PORT_NULL;
c906108c
SS
238mach_port_t inferior_old_exception_port = MACH_PORT_NULL;
239
240/* task exceptions and notifications */
c5aa993b
JM
241mach_port_t inferior_wait_port_set = MACH_PORT_NULL;
242mach_port_t our_notify_port = MACH_PORT_NULL;
c906108c
SS
243
244/* This is "inferior_wait_port_set" when not single stepping, and
245 * "singlestepped_thread_port" when we are single stepping.
246 *
247 * This is protected by a cleanup function: discard_single_step()
248 */
c5aa993b 249mach_port_t currently_waiting_for = MACH_PORT_NULL;
c906108c
SS
250
251/* A port for external messages to gdb.
252 * External in the meaning that they do not come
253 * from the inferior_task, but rather from external
254 * tasks.
255 *
256 * As a debugging feature:
257 * A debugger debugging another debugger can stop the
258 * inferior debugger by the following command sequence
259 * (without running external programs)
260 *
261 * (top-gdb) set stop_inferior_gdb ()
262 * (top-gdb) continue
263 */
c5aa993b 264mach_port_t our_message_port = MACH_PORT_NULL;
c906108c
SS
265
266/* For single stepping */
c5aa993b 267mach_port_t thread_exception_port = MACH_PORT_NULL;
c906108c 268mach_port_t thread_saved_exception_port = MACH_PORT_NULL;
c5aa993b 269mach_port_t singlestepped_thread_port = MACH_PORT_NULL;
c906108c
SS
270
271/* For machid calls */
272mach_port_t mid_server = MACH_PORT_NULL;
c5aa993b 273mach_port_t mid_auth = MACH_PORT_NULL;
c906108c
SS
274
275/* If gdb thinks the inferior task is not suspended, it
276 * must take suspend/abort the threads when it reads the state.
277 */
278int must_suspend_thread = 0;
279
280/* When single stepping, we switch the port that mach_really_wait() listens to.
281 * This cleanup is a guard to prevent the port set from being left to
282 * the singlestepped_thread_port when error() is called.
283 * This is nonzero only when we are single stepping.
284 */
285#define NULL_CLEANUP (struct cleanup *)0
286struct cleanup *cleanup_step = NULL_CLEANUP;
c906108c 287\f
c5aa993b 288
c906108c
SS
289static struct target_ops m3_ops;
290
291static void m3_kill_inferior ();
292\f
293#if 0
294#define MACH_TYPE_EXCEPTION_PORT -1
295#endif
296
297/* Chain of ports to remember requested notifications. */
298
c5aa993b
JM
299struct port_chain
300 {
301 struct port_chain *next;
302 mach_port_t port;
303 int type;
304 int mid; /* Now only valid with MACH_TYPE_THREAD and */
305 /* MACH_TYPE_THREAD */
306 };
c906108c
SS
307typedef struct port_chain *port_chain_t;
308
309/* Room for chain nodes comes from pchain_obstack */
310struct obstack pchain_obstack;
311struct obstack *port_chain_obstack = &pchain_obstack;
312
313/* For thread handling */
314struct obstack Cproc_obstack;
315struct obstack *cproc_obstack = &Cproc_obstack;
316
317/* the list of notified ports */
318port_chain_t notify_chain = (port_chain_t) NULL;
319
320port_chain_t
fba45db2 321port_chain_insert (port_chain_t list, mach_port_t name, int type)
c906108c
SS
322{
323 kern_return_t ret;
324 port_chain_t new;
325 int mid;
326
c5aa993b 327 if (!MACH_PORT_VALID (name))
c906108c 328 return list;
c5aa993b 329
c906108c
SS
330 if (type == MACH_TYPE_TASK || type == MACH_TYPE_THREAD)
331 {
c5aa993b 332 if (!MACH_PORT_VALID (mid_server))
c906108c
SS
333 {
334 warning ("Machid server port invalid, can not map port 0x%x to MID",
335 name);
336 mid = name;
337 }
338 else
339 {
340 ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
c5aa993b 341
c906108c
SS
342 if (ret != KERN_SUCCESS)
343 {
344 warning ("Can not map name (0x%x) to MID with machid", name);
345 mid = name;
346 }
347 }
348 }
349 else
e1e9e218 350 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c906108c
SS
351
352 new = (port_chain_t) obstack_alloc (port_chain_obstack,
353 sizeof (struct port_chain));
c5aa993b
JM
354 new->next = list;
355 new->port = name;
356 new->type = type;
357 new->mid = mid;
c906108c
SS
358
359 return new;
360}
361
362port_chain_t
fba45db2 363port_chain_delete (port_chain_t list, mach_port_t elem)
c906108c
SS
364{
365 if (list)
366 if (list->port == elem)
367 list = list->next;
368 else
369 while (list->next)
370 {
371 if (list->next->port == elem)
c5aa993b 372 list->next = list->next->next; /* GCd with obstack_free() */
c906108c
SS
373 else
374 list = list->next;
375 }
376 return list;
377}
378
379void
fba45db2 380port_chain_destroy (struct obstack *ostack)
c906108c
SS
381{
382 obstack_free (ostack, 0);
383 obstack_init (ostack);
384}
385
386port_chain_t
fba45db2 387port_chain_member (port_chain_t list, mach_port_t elem)
c906108c
SS
388{
389 while (list)
390 {
391 if (list->port == elem)
392 return list;
393 list = list->next;
394 }
395 return (port_chain_t) NULL;
396}
397\f
398int
fba45db2 399map_port_name_to_mid (mach_port_t name, int type)
c906108c
SS
400{
401 port_chain_t elem;
402
403 if (!MACH_PORT_VALID (name))
404 return -1;
405
406 elem = port_chain_member (notify_chain, name);
407
408 if (elem && (elem->type == type))
409 return elem->mid;
c5aa993b 410
c906108c
SS
411 if (elem)
412 return -1;
c5aa993b
JM
413
414 if (!MACH_PORT_VALID (mid_server))
c906108c
SS
415 {
416 warning ("Machid server port invalid, can not map port 0x%x to mid",
417 name);
418 return -1;
419 }
420 else
421 {
422 int mid;
423 kern_return_t ret;
424
425 ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
c5aa993b 426
c906108c
SS
427 if (ret != KERN_SUCCESS)
428 {
429 warning ("Can not map name (0x%x) to mid with machid", name);
430 return -1;
431 }
432 return mid;
433 }
434}
435\f
436/* Guard for currently_waiting_for and singlestepped_thread_port */
437static void
fba45db2 438discard_single_step (thread_t thread)
c906108c
SS
439{
440 currently_waiting_for = inferior_wait_port_set;
441
442 cleanup_step = NULL_CLEANUP;
443 if (MACH_PORT_VALID (thread) && MACH_PORT_VALID (singlestepped_thread_port))
444 setup_single_step (thread, FALSE);
445}
446
fba45db2 447setup_single_step (thread_t thread, boolean_t start_step)
c906108c
SS
448{
449 kern_return_t ret;
450
c5aa993b 451 if (!MACH_PORT_VALID (thread))
c906108c
SS
452 error ("Invalid thread supplied to setup_single_step");
453 else
454 {
455 mach_port_t teport;
456
457 /* Get the current thread exception port */
458 ret = thread_get_exception_port (thread, &teport);
459 CHK ("Getting thread's exception port", ret);
c5aa993b 460
c906108c
SS
461 if (start_step)
462 {
463 if (MACH_PORT_VALID (singlestepped_thread_port))
464 {
465 warning ("Singlestepped_thread_port (0x%x) is still valid?",
466 singlestepped_thread_port);
467 singlestepped_thread_port = MACH_PORT_NULL;
468 }
c5aa993b 469
c906108c
SS
470 /* If we are already stepping this thread */
471 if (MACH_PORT_VALID (teport) && teport == thread_exception_port)
472 {
473 ret = mach_port_deallocate (mach_task_self (), teport);
474 CHK ("Could not deallocate thread exception port", ret);
475 }
476 else
477 {
478 ret = thread_set_exception_port (thread, thread_exception_port);
479 CHK ("Setting exception port for thread", ret);
480#if 0
481 /* Insert thread exception port to wait port set */
c5aa993b 482 ret = mach_port_move_member (mach_task_self (),
c906108c
SS
483 thread_exception_port,
484 inferior_wait_port_set);
485 CHK ("Moving thread exception port to inferior_wait_port_set",
486 ret);
487#endif
488 thread_saved_exception_port = teport;
489 }
c5aa993b 490
c906108c 491 thread_trace (thread, TRUE);
c5aa993b
JM
492
493 singlestepped_thread_port = thread_exception_port;
494 currently_waiting_for = singlestepped_thread_port;
c906108c
SS
495 cleanup_step = make_cleanup (discard_single_step, thread);
496 }
497 else
498 {
c5aa993b 499 if (!MACH_PORT_VALID (teport))
c906108c
SS
500 error ("Single stepped thread had an invalid exception port?");
501
502 if (teport != thread_exception_port)
503 error ("Single stepped thread had an unknown exception port?");
c5aa993b 504
c906108c
SS
505 ret = mach_port_deallocate (mach_task_self (), teport);
506 CHK ("Couldn't deallocate thread exception port", ret);
507#if 0
508 /* Remove thread exception port from wait port set */
c5aa993b 509 ret = mach_port_move_member (mach_task_self (),
c906108c
SS
510 thread_exception_port,
511 MACH_PORT_NULL);
512 CHK ("Removing thread exception port from inferior_wait_port_set",
513 ret);
c5aa993b 514#endif
c906108c
SS
515 /* Restore thread's old exception port */
516 ret = thread_set_exception_port (thread,
517 thread_saved_exception_port);
518 CHK ("Restoring stepped thread's exception port", ret);
c5aa993b 519
c906108c
SS
520 if (MACH_PORT_VALID (thread_saved_exception_port))
521 (void) mach_port_deallocate (mach_task_self (),
522 thread_saved_exception_port);
c5aa993b 523
c906108c 524 thread_trace (thread, FALSE);
c5aa993b 525
c906108c
SS
526 singlestepped_thread_port = MACH_PORT_NULL;
527 currently_waiting_for = inferior_wait_port_set;
528 if (cleanup_step)
529 discard_cleanups (cleanup_step);
530 }
531 }
532}
533\f
534static
fba45db2 535request_notify (mach_port_t name, mach_msg_id_t variant, int type)
c906108c
SS
536{
537 kern_return_t ret;
c5aa993b
JM
538 mach_port_t previous_port_dummy = MACH_PORT_NULL;
539
540 if (!MACH_PORT_VALID (name))
c906108c 541 return;
c5aa993b 542
c906108c
SS
543 if (port_chain_member (notify_chain, name))
544 return;
545
c5aa993b 546 ret = mach_port_request_notification (mach_task_self (),
c906108c
SS
547 name,
548 variant,
549 1,
550 our_notify_port,
551 MACH_MSG_TYPE_MAKE_SEND_ONCE,
552 &previous_port_dummy);
553 CHK ("Serious: request_notify failed", ret);
554
555 (void) mach_port_deallocate (mach_task_self (),
556 previous_port_dummy);
557
558 notify_chain = port_chain_insert (notify_chain, name, type);
559}
560
fba45db2 561reverse_msg_bits (mach_msg_header_t *msgp, int type)
c906108c 562{
c5aa993b
JM
563 int rbits, lbits;
564 rbits = MACH_MSGH_BITS_REMOTE (msgp->msgh_bits);
c906108c
SS
565 lbits = type;
566 msgp->msgh_bits =
567 (msgp->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
c5aa993b 568 MACH_MSGH_BITS (lbits, rbits);
c906108c
SS
569}
570\f
571/* On the third day He said:
572
c5aa993b
JM
573 Let this be global
574 and then it was global.
c906108c
SS
575
576 When creating the inferior fork, the
577 child code in inflow.c sets the name of the
578 bootstrap_port in its address space to this
579 variable.
580
581 The name is transferred to our address space
582 with mach3_read_inferior().
583
584 Thou shalt not do this with
585 task_get_bootstrap_port() in this task, since
586 the name in the inferior task is different than
587 the one we get.
588
589 For blessed are the meek, as they shall inherit
590 the address space.
591 */
592mach_port_t original_server_port_name = MACH_PORT_NULL;
593
594
595/* Called from inferior after FORK but before EXEC */
596static void
fba45db2 597m3_trace_me (void)
c906108c
SS
598{
599 kern_return_t ret;
c5aa993b 600
c906108c
SS
601 /* Get the NAME of the bootstrap port in this task
602 so that GDB can read it */
603 ret = task_get_bootstrap_port (mach_task_self (),
604 &original_server_port_name);
605 if (ret != KERN_SUCCESS)
e1e9e218 606 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c906108c
SS
607 ret = mach_port_deallocate (mach_task_self (),
608 original_server_port_name);
609 if (ret != KERN_SUCCESS)
e1e9e218 610 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c5aa993b 611
c906108c
SS
612 /* Suspend this task to let the parent change my ports.
613 Resumed by the debugger */
614 ret = task_suspend (mach_task_self ());
615 if (ret != KERN_SUCCESS)
e1e9e218 616 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c906108c
SS
617}
618\f
619/*
620 * Intercept system calls to Unix server.
621 * After EXEC_COUNTER calls to exec(), return.
622 *
623 * Pre-assertion: Child is suspended. (Not verified)
624 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
625 */
626
627void
fba45db2 628intercept_exec_calls (int exec_counter)
c906108c
SS
629{
630 int terminal_initted = 0;
631
c5aa993b
JM
632 struct syscall_msg_t
633 {
634 mach_msg_header_t header;
635 mach_msg_type_t type;
636 char room[2000]; /* Enuff space */
637 };
c906108c
SS
638
639 struct syscall_msg_t syscall_in, syscall_out;
640
641 mach_port_t fake_server;
642 mach_port_t original_server_send;
643 mach_port_t original_exec_reply;
644 mach_port_t exec_reply;
645 mach_port_t exec_reply_send;
646 mach_msg_type_name_t acquired;
647 mach_port_t emulator_server_port_name;
648 struct task_basic_info info;
649 mach_msg_type_number_t info_count;
650
651 kern_return_t ret;
652
653 if (exec_counter <= 0)
c5aa993b
JM
654 return; /* We are already set up in the correct program */
655
656 ret = mach_port_allocate (mach_task_self (),
657 MACH_PORT_RIGHT_RECEIVE,
658 &fake_server);
659 CHK ("create inferior_fake_server port failed", ret);
c906108c 660
c906108c 661 /* Wait for inferior_task to suspend itself */
c5aa993b 662 while (1)
c906108c
SS
663 {
664 info_count = sizeof (info);
665 ret = task_info (inferior_task,
666 TASK_BASIC_INFO,
c5aa993b 667 (task_info_t) & info,
c906108c
SS
668 &info_count);
669 CHK ("Task info", ret);
670
671 if (info.suspend_count)
672 break;
673
674 /* Note that the definition of the parameter was undefined
675 * at the time of this writing, so I just use an `ad hoc' value.
676 */
c5aa993b 677 (void) swtch_pri (42); /* Universal Priority Value */
c906108c
SS
678 }
679
680 /* Read the inferior's bootstrap port name */
681 if (!mach3_read_inferior (&original_server_port_name,
682 &original_server_port_name,
683 sizeof (original_server_port_name)))
684 error ("Can't read inferior task bootstrap port name");
685
686 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
687 /* Should get refs, and set them back when restoring */
688 /* Steal the original bsd server send right from inferior */
689 ret = mach_port_extract_right (inferior_task,
690 original_server_port_name,
691 MACH_MSG_TYPE_MOVE_SEND,
692 &original_server_send,
693 &acquired);
c5aa993b
JM
694 CHK ("mach_port_extract_right (bsd server send)", ret);
695
c906108c 696 if (acquired != MACH_MSG_TYPE_PORT_SEND)
8e1a459b 697 error ("Incorrect right extracted, send right to bsd server expected");
c906108c
SS
698
699 ret = mach_port_insert_right (inferior_task,
700 original_server_port_name,
701 fake_server,
702 MACH_MSG_TYPE_MAKE_SEND);
c5aa993b 703 CHK ("mach_port_insert_right (fake server send)", ret);
c906108c
SS
704
705 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
706 fake_server,
707 original_server_port_name, original_server_send);
708
709 /* A receive right to the reply generated by unix server exec() request */
c5aa993b
JM
710 ret = mach_port_allocate (mach_task_self (),
711 MACH_PORT_RIGHT_RECEIVE,
712 &exec_reply);
713 CHK ("create intercepted_reply_port port failed", ret);
714
c906108c
SS
715 /* Pass this send right to Unix server so it replies to us after exec() */
716 ret = mach_port_extract_right (mach_task_self (),
717 exec_reply,
718 MACH_MSG_TYPE_MAKE_SEND_ONCE,
719 &exec_reply_send,
720 &acquired);
c5aa993b 721 CHK ("mach_port_extract_right (exec_reply)", ret);
c906108c
SS
722
723 if (acquired != MACH_MSG_TYPE_PORT_SEND_ONCE)
8e1a459b 724 error ("Incorrect right extracted, send once expected for exec reply");
c906108c 725
c5aa993b
JM
726 ret = mach_port_move_member (mach_task_self (),
727 fake_server,
728 inferior_wait_port_set);
c906108c
SS
729 CHK ("Moving fake syscall port to inferior_wait_port_set", ret);
730
731 xx_debug ("syscall fake server set up, resuming inferior\n");
c5aa993b 732
c906108c 733 ret = task_resume (inferior_task);
c5aa993b
JM
734 CHK ("task_resume (startup)", ret);
735
c906108c
SS
736 /* Read requests from the inferior.
737 Pass directly through everything else except exec() calls.
738 */
c5aa993b 739 while (exec_counter > 0)
c906108c
SS
740 {
741 ret = mach_msg (&syscall_in.header, /* header */
c5aa993b
JM
742 MACH_RCV_MSG, /* options */
743 0, /* send size */
744 sizeof (struct syscall_msg_t), /* receive size */
745 inferior_wait_port_set, /* receive_name */
c906108c
SS
746 MACH_MSG_TIMEOUT_NONE,
747 MACH_PORT_NULL);
c5aa993b
JM
748 CHK ("mach_msg (intercepted sycall)", ret);
749
c906108c
SS
750#ifdef DUMP_SYSCALL
751 print_msg (&syscall_in.header);
752#endif
753
754 /* ASSERT : msgh_local_port == fake_server */
755
756 if (notify_server (&syscall_in.header, &syscall_out.header))
757 error ("received a notify while intercepting syscalls");
758
759 if (syscall_in.header.msgh_id == MIG_EXEC_SYSCALL_ID)
760 {
761 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter);
762 if (exec_counter == 1)
763 {
764 original_exec_reply = syscall_in.header.msgh_remote_port;
765 syscall_in.header.msgh_remote_port = exec_reply_send;
766 }
767
768 if (!terminal_initted)
769 {
770 /* Now that the child has exec'd we know it has already set its
c5aa993b
JM
771 process group. On POSIX systems, tcsetpgrp will fail with
772 EPERM if we try it before the child's setpgid. */
c906108c
SS
773
774 /* Set up the "saved terminal modes" of the inferior
c5aa993b 775 based on what modes we are starting it with. */
c906108c
SS
776 target_terminal_init ();
777
778 /* Install inferior's terminal modes. */
779 target_terminal_inferior ();
780
781 terminal_initted = 1;
782 }
783
784 exec_counter--;
785 }
c5aa993b
JM
786
787 syscall_in.header.msgh_local_port = syscall_in.header.msgh_remote_port;
c906108c
SS
788 syscall_in.header.msgh_remote_port = original_server_send;
789
c5aa993b 790 reverse_msg_bits (&syscall_in.header, MACH_MSG_TYPE_COPY_SEND);
c906108c
SS
791
792 ret = mach_msg_send (&syscall_in.header);
793 CHK ("Forwarded syscall", ret);
794 }
c5aa993b
JM
795
796 ret = mach_port_move_member (mach_task_self (),
797 fake_server,
798 MACH_PORT_NULL);
c906108c
SS
799 CHK ("Moving fake syscall out of inferior_wait_port_set", ret);
800
c5aa993b
JM
801 ret = mach_port_move_member (mach_task_self (),
802 exec_reply,
803 inferior_wait_port_set);
c906108c
SS
804 CHK ("Moving exec_reply to inferior_wait_port_set", ret);
805
806 ret = mach_msg (&syscall_in.header, /* header */
c5aa993b
JM
807 MACH_RCV_MSG, /* options */
808 0, /* send size */
c906108c 809 sizeof (struct syscall_msg_t), /* receive size */
c5aa993b 810 inferior_wait_port_set, /* receive_name */
c906108c
SS
811 MACH_MSG_TIMEOUT_NONE,
812 MACH_PORT_NULL);
c5aa993b 813 CHK ("mach_msg (exec reply)", ret);
c906108c
SS
814
815 ret = task_suspend (inferior_task);
816 CHK ("Suspending inferior after last exec", ret);
817
818 must_suspend_thread = 0;
819
820 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
821
822#ifdef DUMP_SYSCALL
c5aa993b 823 print_msg (&syscall_in.header);
c906108c
SS
824#endif
825
826 /* Message should appear as if it came from the unix server */
827 syscall_in.header.msgh_local_port = MACH_PORT_NULL;
828
829 /* and go to the inferior task original reply port */
830 syscall_in.header.msgh_remote_port = original_exec_reply;
831
c5aa993b 832 reverse_msg_bits (&syscall_in.header, MACH_MSG_TYPE_MOVE_SEND_ONCE);
c906108c
SS
833
834 ret = mach_msg_send (&syscall_in.header);
835 CHK ("Forwarding exec reply to inferior", ret);
836
837 /* Garbage collect */
838 ret = mach_port_deallocate (inferior_task,
839 original_server_port_name);
840 CHK ("deallocating fake server send right", ret);
841
842 ret = mach_port_insert_right (inferior_task,
843 original_server_port_name,
844 original_server_send,
845 MACH_MSG_TYPE_MOVE_SEND);
846 CHK ("Restoring the original bsd server send right", ret);
847
848 ret = mach_port_destroy (mach_task_self (),
849 fake_server);
850 fake_server = MACH_PORT_DEAD;
c5aa993b 851 CHK ("mach_port_destroy (fake_server)", ret);
c906108c
SS
852
853 ret = mach_port_destroy (mach_task_self (),
854 exec_reply);
855 exec_reply = MACH_PORT_DEAD;
c5aa993b 856 CHK ("mach_port_destroy (exec_reply)", ret);
c906108c
SS
857
858 xx_debug ("Done with exec call interception\n");
859}
860
861void
fba45db2 862consume_send_rights (thread_array_t thread_list, int thread_count)
c906108c
SS
863{
864 int index;
865
866 if (!thread_count)
867 return;
868
869 for (index = 0; index < thread_count; index++)
870 {
871 /* Since thread kill command kills threads, don't check ret */
872 (void) mach_port_deallocate (mach_task_self (),
c5aa993b 873 thread_list[index]);
c906108c
SS
874 }
875}
876
877/* suspend/abort/resume a thread. */
fba45db2 878setup_thread (mach_port_t thread, int what)
c906108c
SS
879{
880 kern_return_t ret;
881
882 if (what)
883 {
884 ret = thread_suspend (thread);
885 CHK ("setup_thread thread_suspend", ret);
c5aa993b 886
c906108c
SS
887 ret = thread_abort (thread);
888 CHK ("setup_thread thread_abort", ret);
889 }
890 else
891 {
892 ret = thread_resume (thread);
893 CHK ("setup_thread thread_resume", ret);
894 }
895}
896
897int
fba45db2 898map_slot_to_mid (int slot, thread_array_t threads, int thread_count)
c906108c
SS
899{
900 kern_return_t ret;
901 int deallocate = 0;
902 int index;
903 int mid;
904
c5aa993b 905 if (!threads)
c906108c
SS
906 {
907 deallocate++;
908 ret = task_threads (inferior_task, &threads, &thread_count);
909 CHK ("Can not select a thread from a dead task", ret);
910 }
c5aa993b 911
c906108c
SS
912 if (slot < 0 || slot >= thread_count)
913 {
914 if (deallocate)
915 {
916 consume_send_rights (threads, thread_count);
c5aa993b
JM
917 (void) vm_deallocate (mach_task_self (), (vm_address_t) threads,
918 (thread_count * sizeof (mach_port_t)));
c906108c
SS
919 }
920 if (slot < 0)
921 error ("invalid slot number");
922 else
c5aa993b 923 return -(slot + 1);
c906108c
SS
924 }
925
c5aa993b 926 mid = map_port_name_to_mid (threads[slot], MACH_TYPE_THREAD);
c906108c
SS
927
928 if (deallocate)
929 {
930 consume_send_rights (threads, thread_count);
c5aa993b
JM
931 (void) vm_deallocate (mach_task_self (), (vm_address_t) threads,
932 (thread_count * sizeof (mach_port_t)));
c906108c
SS
933 }
934
935 return mid;
936}
937
938static int
fba45db2 939parse_thread_id (char *arg, int thread_count, int slots)
c906108c
SS
940{
941 kern_return_t ret;
942 int mid;
943 int slot;
944 int index;
c5aa993b 945
c906108c
SS
946 if (arg == 0)
947 return 0;
c5aa993b 948
c906108c
SS
949 while (*arg && (*arg == ' ' || *arg == '\t'))
950 arg++;
c5aa993b
JM
951
952 if (!*arg)
c906108c 953 return 0;
c5aa993b 954
c906108c
SS
955 /* Currently parse MID and @SLOTNUMBER */
956 if (*arg != '@')
957 {
958 mid = atoi (arg);
959 if (mid <= 0)
960 error ("valid thread mid expected");
961 return mid;
962 }
c5aa993b 963
c906108c
SS
964 arg++;
965 slot = atoi (arg);
966
967 if (slot < 0)
968 error ("invalid slot number");
969
970 /* If you want slot numbers to remain slot numbers, set slots.
c5aa993b 971
c906108c
SS
972 * Well, since 0 is reserved, return the ordinal number
973 * of the thread rather than the slot number. Awk, this
974 * counts as a kludge.
975 */
976 if (slots)
c5aa993b 977 return -(slot + 1);
c906108c
SS
978
979 if (thread_count && slot >= thread_count)
c5aa993b 980 return -(slot + 1);
c906108c
SS
981
982 mid = map_slot_to_mid (slot);
c5aa993b 983
c906108c
SS
984 return mid;
985}
986
987/* THREAD_ID 0 is special; it selects the first kernel
988 * thread from the list (i.e. SLOTNUMBER 0)
989 * This is used when starting the program with 'run' or when attaching.
990 *
991 * If FLAG is 0 the context is not changed, and the registers, frame, etc
992 * will continue to describe the old thread.
993 *
994 * If FLAG is nonzero, really select the thread.
995 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
996 *
997 */
998kern_return_t
fba45db2 999select_thread (mach_port_t task, int thread_id, int flag)
c906108c
SS
1000{
1001 thread_array_t thread_list;
1002 int thread_count;
1003 kern_return_t ret;
1004 int index;
1005 thread_t new_thread = MACH_PORT_NULL;
1006
1007 if (thread_id < 0)
1008 error ("Can't select cprocs without kernel thread");
1009
1010 ret = task_threads (task, &thread_list, &thread_count);
1011 if (ret != KERN_SUCCESS)
1012 {
1013 warning ("Can not select a thread from a dead task");
1014 m3_kill_inferior ();
1015 return KERN_FAILURE;
1016 }
1017
1018 if (thread_count == 0)
1019 {
1020 /* The task can not do anything anymore, but it still
1021 * exists as a container for memory and ports.
1022 */
1023 registers_changed ();
1024 warning ("Task %d has no threads",
1025 map_port_name_to_mid (task, MACH_TYPE_TASK));
1026 current_thread = MACH_PORT_NULL;
c5aa993b
JM
1027 (void) vm_deallocate (mach_task_self (),
1028 (vm_address_t) thread_list,
1029 (thread_count * sizeof (mach_port_t)));
c906108c
SS
1030 return KERN_FAILURE;
1031 }
1032
c5aa993b 1033 if (!thread_id || flag == 2)
c906108c
SS
1034 {
1035 /* First thread or a slotnumber */
c5aa993b 1036 if (!thread_id)
c906108c
SS
1037 new_thread = thread_list[0];
1038 else
1039 {
1040 if (thread_id < thread_count)
c5aa993b 1041 new_thread = thread_list[thread_id];
c906108c
SS
1042 else
1043 {
c5aa993b
JM
1044 (void) vm_deallocate (mach_task_self (),
1045 (vm_address_t) thread_list,
1046 (thread_count * sizeof (mach_port_t)));
c906108c
SS
1047 error ("No such thread slot number : %d", thread_id);
1048 }
1049 }
1050 }
1051 else
1052 {
1053 for (index = 0; index < thread_count; index++)
c5aa993b 1054 if (thread_id == map_port_name_to_mid (thread_list[index],
c906108c
SS
1055 MACH_TYPE_THREAD))
1056 {
c5aa993b 1057 new_thread = thread_list[index];
c906108c
SS
1058 index = -1;
1059 break;
1060 }
c5aa993b 1061
c906108c
SS
1062 if (index != -1)
1063 error ("No thread with mid %d", thread_id);
1064 }
c5aa993b 1065
c906108c
SS
1066 /* Notify when the selected thread dies */
1067 request_notify (new_thread, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_THREAD);
c5aa993b
JM
1068
1069 ret = vm_deallocate (mach_task_self (),
1070 (vm_address_t) thread_list,
1071 (thread_count * sizeof (mach_port_t)));
c906108c 1072 CHK ("vm_deallocate", ret);
c5aa993b
JM
1073
1074 if (!flag)
c906108c
SS
1075 current_thread = new_thread;
1076 else
1077 {
1078#if 0
1079 if (MACH_PORT_VALID (current_thread))
1080 {
1081 /* Store the gdb's view of the thread we are deselecting
c5aa993b 1082
c906108c
SS
1083 * @@ I think gdb updates registers immediately when they are
1084 * changed, so don't do this.
1085 */
1086 ret = thread_abort (current_thread);
1087 CHK ("Could not abort system calls when saving state of old thread",
1088 ret);
1089 target_prepare_to_store ();
1090 target_store_registers (-1);
1091 }
1092#endif
1093
1094 registers_changed ();
1095
1096 current_thread = new_thread;
1097
1098 ret = thread_abort (current_thread);
1099 CHK ("Could not abort system calls when selecting a thread", ret);
1100
c5aa993b 1101 stop_pc = read_pc ();
c906108c
SS
1102 flush_cached_frames ();
1103
1104 select_frame (get_current_frame (), 0);
1105 }
1106
1107 return KERN_SUCCESS;
1108}
1109
1110/*
1111 * Switch to use thread named NEW_THREAD.
1112 * Return it's MID
1113 */
1114int
fba45db2 1115switch_to_thread (thread_t new_thread)
c906108c
SS
1116{
1117 thread_t saved_thread = current_thread;
1118 int mid;
1119
1120 mid = map_port_name_to_mid (new_thread,
1121 MACH_TYPE_THREAD);
1122 if (mid == -1)
1123 warning ("Can't map thread name 0x%x to mid", new_thread);
1124 else if (select_thread (inferior_task, mid, 1) != KERN_SUCCESS)
1125 {
1126 if (current_thread)
1127 current_thread = saved_thread;
1128 error ("Could not select thread %d", mid);
1129 }
c5aa993b 1130
c906108c
SS
1131 return mid;
1132}
1133
1134/* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1135 * Note that the registers are not yet valid in the inferior task.
1136 */
1137static int
fba45db2 1138m3_trace_him (int pid)
c906108c
SS
1139{
1140 kern_return_t ret;
1141
1142 push_target (&m3_ops);
1143
1144 inferior_task = task_by_pid (pid);
1145
c5aa993b 1146 if (!MACH_PORT_VALID (inferior_task))
c906108c
SS
1147 error ("Can not map Unix pid %d to Mach task", pid);
1148
1149 /* Clean up previous notifications and create new ones */
1150 setup_notify_port (1);
1151
1152 /* When notification appears, the inferior task has died */
1153 request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
1154
1155 emulator_present = have_emulator_p (inferior_task);
1156
1157 /* By default, select the first thread,
1158 * If task has no threads, gives a warning
1159 * Does not fetch registers, since they are not yet valid.
1160 */
1161 select_thread (inferior_task, 0, 0);
1162
1163 inferior_exception_port = MACH_PORT_NULL;
1164
1165 setup_exception_port ();
1166
1167 xx_debug ("Now the debugged task is created\n");
1168
1169 /* One trap to exec the shell, one to exec the program being debugged. */
1170 intercept_exec_calls (2);
1171
1172 return pid;
1173}
1174
fba45db2 1175setup_exception_port (void)
c906108c
SS
1176{
1177 kern_return_t ret;
1178
c5aa993b 1179 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
1180 MACH_PORT_RIGHT_RECEIVE,
1181 &inferior_exception_port);
c5aa993b 1182 CHK ("mach_port_allocate", ret);
c906108c
SS
1183
1184 /* add send right */
1185 ret = mach_port_insert_right (mach_task_self (),
1186 inferior_exception_port,
1187 inferior_exception_port,
1188 MACH_MSG_TYPE_MAKE_SEND);
c5aa993b 1189 CHK ("mach_port_insert_right", ret);
c906108c 1190
c5aa993b 1191 ret = mach_port_move_member (mach_task_self (),
c906108c
SS
1192 inferior_exception_port,
1193 inferior_wait_port_set);
c5aa993b 1194 CHK ("mach_port_move_member", ret);
c906108c 1195
c5aa993b 1196 ret = task_get_special_port (inferior_task,
c906108c
SS
1197 TASK_EXCEPTION_PORT,
1198 &inferior_old_exception_port);
c5aa993b 1199 CHK ("task_get_special_port(old exc)", ret);
c906108c
SS
1200
1201 ret = task_set_special_port (inferior_task,
c5aa993b 1202 TASK_EXCEPTION_PORT,
c906108c 1203 inferior_exception_port);
c5aa993b 1204 CHK ("task_set_special_port", ret);
c906108c
SS
1205
1206 ret = mach_port_deallocate (mach_task_self (),
1207 inferior_exception_port);
c5aa993b 1208 CHK ("mack_port_deallocate", ret);
c906108c
SS
1209
1210#if 0
1211 /* When notify appears, the inferior_task's exception
1212 * port has been destroyed.
1213 *
1214 * Not used, since the dead_name_notification already
1215 * appears when task dies.
1216 *
1217 */
1218 request_notify (inferior_exception_port,
1219 MACH_NOTIFY_NO_SENDERS,
1220 MACH_TYPE_EXCEPTION_PORT);
1221#endif
1222}
1223
1224/* Nonzero if gdb is waiting for a message */
1225int mach_really_waiting;
1226
1227/* Wait for the inferior to stop for some reason.
1228 - Loop on notifications until inferior_task dies.
1229 - Loop on exceptions until stopped_in_exception comes true.
c5aa993b 1230 (e.g. we receive a single step trace trap)
c906108c
SS
1231 - a message arrives to gdb's message port
1232
1233 There is no other way to exit this loop.
1234
39f77062 1235 Returns the inferior_ptid for rest of gdb.
c906108c 1236 Side effects: Set *OURSTATUS. */
39f77062
KB
1237ptid_t
1238mach_really_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c
SS
1239{
1240 kern_return_t ret;
1241 int w;
1242
c5aa993b
JM
1243 struct msg
1244 {
1245 mach_msg_header_t header;
1246 mach_msg_type_t foo;
1247 int data[8000];
1248 }
1249 in_msg, out_msg;
c906108c
SS
1250
1251 /* Either notify (death), exception or message can stop the inferior */
1252 stopped_in_exception = FALSE;
1253
1254 while (1)
1255 {
1256 QUIT;
1257
1258 stop_exception = stop_code = stop_subcode = -1;
1259 stop_thread = MACH_PORT_NULL;
1260
1261 mach_really_waiting = 1;
c5aa993b
JM
1262 ret = mach_msg (&in_msg.header, /* header */
1263 MACH_RCV_MSG, /* options */
1264 0, /* send size */
c906108c
SS
1265 sizeof (struct msg), /* receive size */
1266 currently_waiting_for, /* receive name */
1267 MACH_MSG_TIMEOUT_NONE,
1268 MACH_PORT_NULL);
1269 mach_really_waiting = 0;
c5aa993b 1270 CHK ("mach_msg (receive)", ret);
c906108c
SS
1271
1272 /* Check if we received a notify of the childs' death */
1273 if (notify_server (&in_msg.header, &out_msg.header))
1274 {
1275 /* If inferior_task is null then the inferior has
1276 gone away and we want to return to command level.
1277 Otherwise it was just an informative message and we
1278 need to look to see if there are any more. */
1279 if (inferior_task != MACH_PORT_NULL)
1280 continue;
1281 else
1282 {
1283 /* Collect Unix exit status for gdb */
1284
c5aa993b 1285 wait3 (&w, WNOHANG, 0);
c906108c
SS
1286
1287 /* This mess is here to check that the rest of
1288 * gdb knows that the inferior died. It also
1289 * tries to hack around the fact that Mach 3.0 (mk69)
1290 * unix server (ux28) does not always know what
1291 * has happened to it's children when mach-magic
1292 * is applied on them.
1293 */
c5aa993b
JM
1294 if ((!WIFEXITED (w) && WIFSTOPPED (w)) ||
1295 (WIFEXITED (w) && WEXITSTATUS (w) > 0377))
c906108c 1296 {
c5aa993b 1297 WSETEXIT (w, 0);
c906108c
SS
1298 warning ("Using exit value 0 for terminated task");
1299 }
c5aa993b 1300 else if (!WIFEXITED (w))
c906108c 1301 {
c5aa993b 1302 int sig = WTERMSIG (w);
c906108c
SS
1303
1304 /* Signals cause problems. Warn the user. */
c5aa993b 1305 if (sig != SIGKILL) /* Bad luck if garbage matches this */
c906108c
SS
1306 warning ("The terminating signal stuff may be nonsense");
1307 else if (sig > NSIG)
1308 {
c5aa993b 1309 WSETEXIT (w, 0);
c906108c
SS
1310 warning ("Using exit value 0 for terminated task");
1311 }
1312 }
1313 store_waitstatus (ourstatus, w);
39f77062 1314 return inferior_ptid;
c906108c
SS
1315 }
1316 }
1317
1318 /* Hmm. Check for exception, as it was not a notification.
c5aa993b
JM
1319 exc_server() does an upcall to catch_exception_raise()
1320 if this rpc is an exception. Further actions are decided
1321 there.
c906108c 1322 */
c5aa993b 1323 if (!exc_server (&in_msg.header, &out_msg.header))
c906108c
SS
1324 {
1325
1326 /* Not an exception, check for message.
c5aa993b 1327
c906108c
SS
1328 * Messages don't come from the inferior, or if they
1329 * do they better be asynchronous or it will hang.
1330 */
1331 if (gdb_message_server (&in_msg.header))
1332 continue;
1333
1334 error ("Unrecognized message received in mach_really_wait");
1335 }
1336
1337 /* Send the reply of the exception rpc to the suspended task */
1338 ret = mach_msg_send (&out_msg.header);
1339 CHK ("mach_msg_send (exc reply)", ret);
c5aa993b 1340
c906108c
SS
1341 if (stopped_in_exception)
1342 {
1343 /* Get unix state. May be changed in mach3_exception_actions() */
c5aa993b 1344 wait3 (&w, WNOHANG, 0);
c906108c
SS
1345
1346 mach3_exception_actions (&w, FALSE, "Task");
1347
1348 store_waitstatus (ourstatus, w);
39f77062 1349 return inferior_ptid;
c906108c
SS
1350 }
1351 }
1352}
1353
1354/* Called by macro DO_QUIT() in utils.c(quit).
1355 * This is called just before calling error() to return to command level
1356 */
1357void
fba45db2 1358mach3_quit (void)
c906108c
SS
1359{
1360 int mid;
1361 kern_return_t ret;
c5aa993b 1362
c906108c
SS
1363 if (mach_really_waiting)
1364 {
1365 ret = task_suspend (inferior_task);
c5aa993b 1366
c906108c
SS
1367 if (ret != KERN_SUCCESS)
1368 {
1369 warning ("Could not suspend task for interrupt: %s",
1370 mach_error_string (ret));
1371 mach_really_waiting = 0;
1372 return;
1373 }
1374 }
1375
1376 must_suspend_thread = 0;
1377 mach_really_waiting = 0;
1378
1379 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1380 if (mid == -1)
1381 {
1382 warning ("Selecting first existing kernel thread");
1383 mid = 0;
1384 }
1385
c5aa993b 1386 current_thread = MACH_PORT_NULL; /* Force setup */
c906108c
SS
1387 select_thread (inferior_task, mid, 1);
1388
1389 return;
1390}
1391
1392#if 0
1393/* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
1394
1395/* If ^C is typed when we are waiting for a message
1396 * and your Unix server is able to notice that we
1397 * should quit now.
1398 *
1399 * Called by REQUEST_QUIT() from utils.c(request_quit)
1400 */
1401void
fba45db2 1402mach3_request_quit (void)
c906108c
SS
1403{
1404 if (mach_really_waiting)
1405 immediate_quit = 1;
c5aa993b 1406}
c906108c
SS
1407#endif
1408
1409/*
1410 * Gdb message server.
1411 * Currently implemented is the STOP message, that causes
1412 * gdb to return to the command level like ^C had been typed from terminal.
1413 */
1414int
fba45db2 1415gdb_message_server (mach_msg_header_t *InP)
c906108c
SS
1416{
1417 kern_return_t ret;
1418 int mid;
1419
1420 if (InP->msgh_local_port == our_message_port)
1421 {
1422 /* A message coming to our_message_port. Check validity */
c5aa993b
JM
1423 switch (InP->msgh_id)
1424 {
c906108c 1425
c5aa993b
JM
1426 case GDB_MESSAGE_ID_STOP:
1427 ret = task_suspend (inferior_task);
1428 if (ret != KERN_SUCCESS)
1429 warning ("Could not suspend task for stop message: %s",
1430 mach_error_string (ret));
c906108c 1431
c5aa993b
JM
1432 /* QUIT in mach_really_wait() loop. */
1433 request_quit (0);
1434 break;
c906108c 1435
c5aa993b
JM
1436 default:
1437 warning ("Invalid message id %d received, ignored.",
1438 InP->msgh_id);
1439 break;
1440 }
c906108c
SS
1441
1442 return 1;
1443 }
1444
1445 /* Message not handled by this server */
1446 return 0;
1447}
1448
1449/* NOTE: This is not an RPC call. It is a simpleroutine.
c5aa993b 1450
c906108c
SS
1451 * This is not called from this gdb code.
1452 *
1453 * It may be called by another debugger to cause this
1454 * debugger to enter command level:
1455 *
1456 * (gdb) set stop_inferior_gdb ()
1457 * (gdb) continue
1458 *
1459 * External program "stop-gdb" implements this also.
1460 */
1461void
fba45db2 1462stop_inferior_gdb (void)
c906108c
SS
1463{
1464 kern_return_t ret;
1465
1466 /* Code generated by mig, with minor cleanups :-)
c5aa993b 1467
c906108c
SS
1468 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1469 */
1470
c5aa993b
JM
1471 typedef struct
1472 {
1473 mach_msg_header_t Head;
1474 }
1475 Request;
c906108c
SS
1476
1477 Request Mess;
1478
1479 register Request *InP = &Mess;
1480
c5aa993b 1481 InP->Head.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
c906108c
SS
1482
1483 /* msgh_size passed as argument */
1484 InP->Head.msgh_remote_port = our_message_port;
c5aa993b
JM
1485 InP->Head.msgh_local_port = MACH_PORT_NULL;
1486 InP->Head.msgh_seqno = 0;
1487 InP->Head.msgh_id = GDB_MESSAGE_ID_STOP;
c906108c
SS
1488
1489 ret = mach_msg (&InP->Head,
c5aa993b
JM
1490 MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
1491 sizeof (Request),
c906108c
SS
1492 0,
1493 MACH_PORT_NULL,
1494 MACH_MSG_TIMEOUT_NONE,
1495 MACH_PORT_NULL);
1496}
1497
1498#ifdef THREAD_ALLOWED_TO_BREAK
1499/*
1500 * Return 1 if the MID specifies the thread that caused the
1501 * last exception.
1502 * Since catch_exception_raise() selects the thread causing
1503 * the last exception to current_thread, we just check that
1504 * it is selected and the last exception was a breakpoint.
1505 */
1506int
fba45db2 1507mach_thread_for_breakpoint (int mid)
c906108c
SS
1508{
1509 int cmid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1510
1511 if (mid < 0)
1512 {
c5aa993b 1513 mid = map_slot_to_mid (-(mid + 1), 0, 0);
c906108c
SS
1514 if (mid < 0)
1515 return 0; /* Don't stop, no such slot */
1516 }
1517
c5aa993b
JM
1518 if (!mid || cmid == -1)
1519 return 1; /* stop */
c906108c
SS
1520
1521 return cmid == mid && stop_exception == EXC_BREAKPOINT;
1522}
1523#endif /* THREAD_ALLOWED_TO_BREAK */
1524
1525#ifdef THREAD_PARSE_ID
1526/*
1527 * Map a thread id string (MID or a @SLOTNUMBER)
1528 * to a thread-id.
1529 *
1530 * 0 matches all threads.
1531 * Otherwise the meaning is defined only in this file.
1532 * (mach_thread_for_breakpoint uses it)
1533 *
1534 * @@ This allows non-existent MIDs to be specified.
1535 * It now also allows non-existent slots to be
1536 * specified. (Slot numbers stored are negative,
1537 * and the magnitude is one greater than the actual
1538 * slot index. (Since 0 is reserved))
1539 */
1540int
fba45db2 1541mach_thread_parse_id (char *arg)
c906108c
SS
1542{
1543 int mid;
1544 if (arg == 0)
8e1a459b 1545 error ("thread id expected");
c906108c
SS
1546 mid = parse_thread_id (arg, 0, 1);
1547
1548 return mid;
1549}
1550#endif /* THREAD_PARSE_ID */
1551
1552#ifdef THREAD_OUTPUT_ID
1553char *
fba45db2 1554mach_thread_output_id (int mid)
c906108c 1555{
c5aa993b 1556 static char foobar[20];
c906108c
SS
1557
1558 if (mid > 0)
1559 sprintf (foobar, "mid %d", mid);
1560 else if (mid < 0)
c5aa993b 1561 sprintf (foobar, "@%d", -(mid + 1));
c906108c
SS
1562 else
1563 sprintf (foobar, "*any thread*");
1564
1565 return foobar;
1566}
1567#endif /* THREAD_OUTPUT_ID */
1568
1569/* Called with hook PREPARE_TO_PROCEED() from infrun.c.
c5aa993b 1570
c906108c
SS
1571 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1572 *
1573 * if SELECT_IT is nonzero, reselect the thread that was active when
1574 * we stopped at a breakpoint.
1575 *
e02bc4cc
DS
1576 * Note that this implementation is potentially redundant now that
1577 * default_prepare_to_proceed() has been added.
8849f47d
JL
1578 *
1579 * FIXME This may not support switching threads after Ctrl-C
1580 * correctly. The default implementation does support this.
c906108c
SS
1581 */
1582
fba45db2 1583mach3_prepare_to_proceed (int select_it)
c906108c
SS
1584{
1585 if (stop_thread &&
1586 stop_thread != current_thread &&
1587 stop_exception == EXC_BREAKPOINT)
1588 {
1589 int mid;
1590
c5aa993b 1591 if (!select_it)
c906108c
SS
1592 return 1;
1593
1594 mid = switch_to_thread (stop_thread);
1595
1596 return 1;
1597 }
1598
1599 return 0;
1600}
1601
1602/* this stuff here is an upcall via libmach/excServer.c
1603 and mach_really_wait which does the actual upcall.
1604
1605 The code will pass the exception to the inferior if:
1606
c5aa993b
JM
1607 - The task that signaled is not the inferior task
1608 (e.g. when debugging another debugger)
c906108c 1609
c5aa993b
JM
1610 - The user has explicitely requested to pass on the exceptions.
1611 (e.g to the default unix exception handler, which maps
1612 exceptions to signals, or the user has her own exception handler)
c906108c 1613
c5aa993b
JM
1614 - If the thread that signaled is being single-stepped and it
1615 has set it's own exception port and the exception is not
1616 EXC_BREAKPOINT. (Maybe this is not desirable?)
c906108c
SS
1617 */
1618
1619kern_return_t
fba45db2
KB
1620catch_exception_raise (mach_port_t port, thread_t thread, task_t task,
1621 int exception, int code, int subcode)
c906108c
SS
1622{
1623 kern_return_t ret;
1624 boolean_t signal_thread;
1625 int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
1626
c5aa993b 1627 if (!MACH_PORT_VALID (thread))
c906108c
SS
1628 {
1629 /* If the exception was sent and thread dies before we
c5aa993b 1630 receive it, THREAD will be MACH_PORT_DEAD
c906108c
SS
1631 */
1632
1633 current_thread = thread = MACH_PORT_NULL;
1634 error ("Received exception from nonexistent thread");
1635 }
1636
1637 /* Check if the task died in transit.
1638 * @@ Isn't the thread also invalid in such case?
1639 */
c5aa993b 1640 if (!MACH_PORT_VALID (task))
c906108c
SS
1641 {
1642 current_thread = thread = MACH_PORT_NULL;
1643 error ("Received exception from nonexistent task");
1644 }
1645
1646 if (exception < 0 || exception > MAX_EXCEPTION)
8e65ff28
AC
1647 internal_error (__FILE__, __LINE__,
1648 "catch_exception_raise: unknown exception code %d thread %d",
96baa820
JM
1649 exception,
1650 mid);
c906108c 1651
c5aa993b 1652 if (!MACH_PORT_VALID (inferior_task))
c906108c 1653 error ("got an exception, but inferior_task is null or dead");
c5aa993b 1654
c906108c 1655 stop_exception = exception;
c5aa993b
JM
1656 stop_code = code;
1657 stop_subcode = subcode;
1658 stop_thread = thread;
1659
1660 signal_thread = exception != EXC_BREAKPOINT &&
1661 port == singlestepped_thread_port &&
1662 MACH_PORT_VALID (thread_saved_exception_port);
c906108c
SS
1663
1664 /* If it was not our inferior or if we want to forward
1665 * the exception to the inferior's handler, do it here
1666 *
1667 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1668 */
1669 if (task != inferior_task ||
c5aa993b
JM
1670 signal_thread ||
1671 exception_map[exception].forward)
c906108c
SS
1672 {
1673 mach_port_t eport = inferior_old_exception_port;
1674
1675 if (signal_thread)
1676 {
1677 /*
c5aa993b
JM
1678 GDB now forwards the exeption to thread's original handler,
1679 since the user propably knows what he is doing.
1680 Give a message, though.
c906108c
SS
1681 */
1682
c5aa993b 1683 mach3_exception_actions ((WAITTYPE *) NULL, TRUE, "Thread");
c906108c
SS
1684 eport = thread_saved_exception_port;
1685 }
1686
1687 /* Send the exception to the original handler */
1688 ret = exception_raise (eport,
c5aa993b 1689 thread,
c906108c
SS
1690 task,
1691 exception,
1692 code,
1693 subcode);
1694
1695 (void) mach_port_deallocate (mach_task_self (), task);
1696 (void) mach_port_deallocate (mach_task_self (), thread);
1697
1698 /* If we come here, we don't want to trace any more, since we
1699 * will never stop for tracing anyway.
1700 */
1701 discard_single_step (thread);
1702
1703 /* Do not stop the inferior */
1704 return ret;
1705 }
c5aa993b 1706
c906108c
SS
1707 /* Now gdb handles the exception */
1708 stopped_in_exception = TRUE;
1709
1710 ret = task_suspend (task);
1711 CHK ("Error suspending inferior after exception", ret);
1712
1713 must_suspend_thread = 0;
1714
1715 if (current_thread != thread)
1716 {
1717 if (MACH_PORT_VALID (singlestepped_thread_port))
1718 /* Cleanup discards single stepping */
1719 error ("Exception from thread %d while singlestepping thread %d",
1720 mid,
1721 map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
c5aa993b 1722
c906108c
SS
1723 /* Then select the thread that caused the exception */
1724 if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
1725 error ("Could not select thread %d causing exception", mid);
1726 else
1727 warning ("Gdb selected thread %d", mid);
1728 }
1729
1730 /* If we receive an exception that is not breakpoint
1731 * exception, we interrupt the single step and return to
1732 * debugger. Trace condition is cleared.
1733 */
1734 if (MACH_PORT_VALID (singlestepped_thread_port))
1735 {
1736 if (stop_exception != EXC_BREAKPOINT)
1737 warning ("Single step interrupted by exception");
1738 else if (port == singlestepped_thread_port)
1739 {
1740 /* Single step exception occurred, remove trace bit
1741 * and return to gdb.
1742 */
c5aa993b 1743 if (!MACH_PORT_VALID (current_thread))
c906108c 1744 error ("Single stepped thread is not valid");
c5aa993b 1745
c906108c
SS
1746 /* Resume threads, but leave the task suspended */
1747 resume_all_threads (0);
1748 }
1749 else
1750 warning ("Breakpoint while single stepping?");
1751
1752 discard_single_step (current_thread);
1753 }
c5aa993b 1754
c906108c
SS
1755 (void) mach_port_deallocate (mach_task_self (), task);
1756 (void) mach_port_deallocate (mach_task_self (), thread);
1757
1758 return KERN_SUCCESS;
1759}
1760\f
1761int
fba45db2 1762port_valid (mach_port_t port, int mask)
c906108c
SS
1763{
1764 kern_return_t ret;
1765 mach_port_type_t type;
1766
1767 ret = mach_port_type (mach_task_self (),
1768 port,
1769 &type);
1770 if (ret != KERN_SUCCESS || (type & mask) != mask)
1771 return 0;
1772 return 1;
1773}
1774\f
1775/* @@ No vm read cache implemented yet */
1776boolean_t vm_read_cache_valid = FALSE;
1777
1778/*
1779 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1780 * in gdb's address space.
1781 *
1782 * Return 0 on failure; number of bytes read otherwise.
1783 */
1784int
fba45db2 1785mach3_read_inferior (CORE_ADDR addr, char *myaddr, int length)
c906108c
SS
1786{
1787 kern_return_t ret;
c5aa993b
JM
1788 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1789 vm_size_t aligned_length =
1790 (vm_size_t) round_page (addr + length) - low_address;
1791 pointer_t copied_memory;
1792 int copy_count;
c906108c
SS
1793
1794 /* Get memory from inferior with page aligned addresses */
1795 ret = vm_read (inferior_task,
1796 low_address,
1797 aligned_length,
1798 &copied_memory,
1799 &copy_count);
1800 if (ret != KERN_SUCCESS)
1801 {
1802 /* the problem is that the inferior might be killed for whatever reason
1803 * before we go to mach_really_wait. This is one place that ought to
1804 * catch many of those errors.
1805 * @@ A better fix would be to make all external events to GDB
1806 * to arrive via a SINGLE port set. (Including user input!)
1807 */
1808
c5aa993b 1809 if (!port_valid (inferior_task, MACH_PORT_TYPE_SEND))
c906108c
SS
1810 {
1811 m3_kill_inferior ();
1812 error ("Inferior killed (task port invalid)");
1813 }
1814 else
1815 {
1816#ifdef OSF
1817 extern int errno;
1818 /* valprint.c gives nicer format if this does not
1819 screw it. Eamonn seems to like this, so I enable
1820 it if OSF is defined...
1821 */
1822 warning ("[read inferior %x failed: %s]",
1823 addr, mach_error_string (ret));
1824 errno = 0;
1825#endif
1826 return 0;
1827 }
1828 }
1829
c5aa993b 1830 memcpy (myaddr, (char *) addr - low_address + copied_memory, length);
c906108c
SS
1831
1832 ret = vm_deallocate (mach_task_self (),
1833 copied_memory,
1834 copy_count);
c5aa993b 1835 CHK ("mach3_read_inferior vm_deallocate failed", ret);
c906108c
SS
1836
1837 return length;
1838}
1839
c906108c
SS
1840#define CHK_GOTO_OUT(str,ret) \
1841 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
c906108c 1842
c5aa993b
JM
1843struct vm_region_list
1844{
c906108c 1845 struct vm_region_list *next;
c5aa993b
JM
1846 vm_prot_t protection;
1847 vm_address_t start;
1848 vm_size_t length;
c906108c
SS
1849};
1850
c5aa993b 1851struct obstack region_obstack;
c906108c
SS
1852
1853/*
1854 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1855 * in gdb's address space.
1856 */
1857int
fba45db2 1858mach3_write_inferior (CORE_ADDR addr, char *myaddr, int length)
c906108c
SS
1859{
1860 kern_return_t ret;
c5aa993b
JM
1861 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1862 vm_size_t aligned_length =
1863 (vm_size_t) round_page (addr + length) - low_address;
1864 pointer_t copied_memory;
1865 int copy_count;
1866 int deallocate = 0;
c906108c 1867
c5aa993b 1868 char *errstr = "Bug in mach3_write_inferior";
c906108c
SS
1869
1870 struct vm_region_list *region_element;
c5aa993b 1871 struct vm_region_list *region_head = (struct vm_region_list *) NULL;
c906108c
SS
1872
1873 /* Get memory from inferior with page aligned addresses */
1874 ret = vm_read (inferior_task,
1875 low_address,
1876 aligned_length,
1877 &copied_memory,
1878 &copy_count);
1879 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
1880
1881 deallocate++;
1882
c5aa993b 1883 memcpy ((char *) addr - low_address + copied_memory, myaddr, length);
c906108c
SS
1884
1885 obstack_init (&region_obstack);
1886
1887 /* Do writes atomically.
1888 * First check for holes and unwritable memory.
1889 */
1890 {
c5aa993b
JM
1891 vm_size_t remaining_length = aligned_length;
1892 vm_address_t region_address = low_address;
c906108c
SS
1893
1894 struct vm_region_list *scan;
1895
c5aa993b 1896 while (region_address < low_address + aligned_length)
c906108c
SS
1897 {
1898 vm_prot_t protection;
1899 vm_prot_t max_protection;
1900 vm_inherit_t inheritance;
1901 boolean_t shared;
1902 mach_port_t object_name;
1903 vm_offset_t offset;
c5aa993b
JM
1904 vm_size_t region_length = remaining_length;
1905 vm_address_t old_address = region_address;
1906
c906108c
SS
1907 ret = vm_region (inferior_task,
1908 &region_address,
1909 &region_length,
1910 &protection,
1911 &max_protection,
1912 &inheritance,
1913 &shared,
1914 &object_name,
1915 &offset);
1916 CHK_GOTO_OUT ("vm_region failed", ret);
1917
1918 /* Check for holes in memory */
1919 if (old_address != region_address)
1920 {
1921 warning ("No memory at 0x%x. Nothing written",
1922 old_address);
1923 ret = KERN_SUCCESS;
1924 length = 0;
1925 goto out;
1926 }
1927
1928 if (!(max_protection & VM_PROT_WRITE))
1929 {
1930 warning ("Memory at address 0x%x is unwritable. Nothing written",
1931 old_address);
1932 ret = KERN_SUCCESS;
1933 length = 0;
1934 goto out;
1935 }
1936
1937 /* Chain the regions for later use */
c5aa993b 1938 region_element =
c906108c 1939 (struct vm_region_list *)
c5aa993b
JM
1940 obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
1941
c906108c 1942 region_element->protection = protection;
c5aa993b
JM
1943 region_element->start = region_address;
1944 region_element->length = region_length;
c906108c
SS
1945
1946 /* Chain the regions along with protections */
1947 region_element->next = region_head;
c5aa993b
JM
1948 region_head = region_element;
1949
c906108c
SS
1950 region_address += region_length;
1951 remaining_length = remaining_length - region_length;
1952 }
1953
1954 /* If things fail after this, we give up.
1955 * Somebody is messing up inferior_task's mappings.
1956 */
c5aa993b 1957
c906108c
SS
1958 /* Enable writes to the chained vm regions */
1959 for (scan = region_head; scan; scan = scan->next)
1960 {
1961 boolean_t protection_changed = FALSE;
c5aa993b 1962
c906108c
SS
1963 if (!(scan->protection & VM_PROT_WRITE))
1964 {
1965 ret = vm_protect (inferior_task,
1966 scan->start,
1967 scan->length,
1968 FALSE,
1969 scan->protection | VM_PROT_WRITE);
1970 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1971 }
1972 }
1973
1974 ret = vm_write (inferior_task,
1975 low_address,
1976 copied_memory,
1977 aligned_length);
1978 CHK_GOTO_OUT ("vm_write failed", ret);
c5aa993b 1979
c906108c
SS
1980 /* Set up the original region protections, if they were changed */
1981 for (scan = region_head; scan; scan = scan->next)
1982 {
1983 boolean_t protection_changed = FALSE;
c5aa993b 1984
c906108c
SS
1985 if (!(scan->protection & VM_PROT_WRITE))
1986 {
1987 ret = vm_protect (inferior_task,
1988 scan->start,
1989 scan->length,
1990 FALSE,
1991 scan->protection);
1992 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1993 }
1994 }
1995 }
1996
c5aa993b 1997out:
c906108c
SS
1998 if (deallocate)
1999 {
2000 obstack_free (&region_obstack, 0);
c5aa993b 2001
c906108c
SS
2002 (void) vm_deallocate (mach_task_self (),
2003 copied_memory,
2004 copy_count);
2005 }
2006
2007 if (ret != KERN_SUCCESS)
2008 {
2009 warning ("%s %s", errstr, mach_error_string (ret));
2010 return 0;
2011 }
2012
2013 return length;
2014}
2015
ad525611
KB
2016/* Return 0 on failure, number of bytes handled otherwise. TARGET is
2017 ignored. */
c906108c 2018static int
ad525611
KB
2019m3_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
2020 struct target_ops *target)
c906108c
SS
2021{
2022 int result;
2023
2024 if (write)
2025 result = mach3_write_inferior (memaddr, myaddr, len);
2026 else
c5aa993b 2027 result = mach3_read_inferior (memaddr, myaddr, len);
c906108c
SS
2028
2029 return result;
2030}
c906108c 2031\f
c5aa993b 2032
c906108c 2033static char *
fba45db2 2034translate_state (int state)
c906108c 2035{
c5aa993b
JM
2036 switch (state)
2037 {
2038 case TH_STATE_RUNNING:
2039 return ("R");
2040 case TH_STATE_STOPPED:
2041 return ("S");
2042 case TH_STATE_WAITING:
2043 return ("W");
2044 case TH_STATE_UNINTERRUPTIBLE:
2045 return ("U");
2046 case TH_STATE_HALTED:
2047 return ("H");
2048 default:
2049 return ("?");
2050 }
c906108c
SS
2051}
2052
2053static char *
fba45db2 2054translate_cstate (int state)
c906108c
SS
2055{
2056 switch (state)
2057 {
c5aa993b
JM
2058 case CPROC_RUNNING:
2059 return "R";
2060 case CPROC_SWITCHING:
2061 return "S";
2062 case CPROC_BLOCKED:
2063 return "B";
2064 case CPROC_CONDWAIT:
2065 return "C";
2066 case CPROC_CONDWAIT | CPROC_SWITCHING:
2067 return "CS";
2068 default:
2069 return "?";
c906108c
SS
2070 }
2071}
2072
2073/* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2074
c5aa993b 2075mach_port_t /* no mach_port_name_t found in include files. */
fba45db2 2076map_inferior_port_name (mach_port_t inferior_name, mach_msg_type_name_t type)
c906108c 2077{
c5aa993b 2078 kern_return_t ret;
c906108c 2079 mach_msg_type_name_t acquired;
c5aa993b
JM
2080 mach_port_t iport;
2081
c906108c
SS
2082 ret = mach_port_extract_right (inferior_task,
2083 inferior_name,
2084 type,
2085 &iport,
2086 &acquired);
c5aa993b 2087 CHK ("mach_port_extract_right (map_inferior_port_name)", ret);
c906108c
SS
2088
2089 if (acquired != MACH_MSG_TYPE_PORT_SEND)
c5aa993b 2090 error ("Incorrect right extracted, (map_inferior_port_name)");
c906108c
SS
2091
2092 ret = mach_port_deallocate (mach_task_self (),
2093 iport);
2094 CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
2095
2096 return iport;
2097}
2098
2099/*
2100 * Naming convention:
2101 * Always return user defined name if found.
2102 * _K == A kernel thread with no matching CPROC
2103 * _C == A cproc with no current cthread
2104 * _t == A cthread with no user defined name
2105 *
2106 * The digits that follow the _names are the SLOT number of the
2107 * kernel thread if there is such a thing, otherwise just a negation
2108 * of the sequential number of such cprocs.
2109 */
2110
2111static char buf[7];
2112
2113static char *
fba45db2 2114get_thread_name (gdb_thread_t one_cproc, int id)
c906108c
SS
2115{
2116 if (one_cproc)
2117 if (one_cproc->cthread == NULL)
2118 {
2119 /* cproc not mapped to any cthread */
c5aa993b 2120 sprintf (buf, "_C%d", id);
c906108c 2121 }
c5aa993b 2122 else if (!one_cproc->cthread->name)
c906108c
SS
2123 {
2124 /* cproc and cthread, but no name */
c5aa993b 2125 sprintf (buf, "_t%d", id);
c906108c
SS
2126 }
2127 else
c5aa993b 2128 return (char *) (one_cproc->cthread->name);
c906108c
SS
2129 else
2130 {
2131 if (id < 0)
2132 warning ("Inconsistency in thread name id %d", id);
2133
2134 /* Kernel thread without cproc */
c5aa993b 2135 sprintf (buf, "_K%d", id);
c906108c
SS
2136 }
2137
2138 return buf;
2139}
2140
2141int
ad525611 2142fetch_thread_info (mach_port_t task, gdb_thread_t *mthreads_out)
c906108c 2143{
c5aa993b 2144 kern_return_t ret;
c906108c 2145 thread_array_t th_table;
c5aa993b 2146 int th_count;
c906108c 2147 gdb_thread_t mthreads = NULL;
c5aa993b 2148 int index;
c906108c
SS
2149
2150 ret = task_threads (task, &th_table, &th_count);
2151 if (ret != KERN_SUCCESS)
2152 {
2153 warning ("Error getting inferior's thread list:%s",
c5aa993b 2154 mach_error_string (ret));
c906108c
SS
2155 m3_kill_inferior ();
2156 return -1;
2157 }
c5aa993b 2158
c906108c 2159 mthreads = (gdb_thread_t)
c5aa993b
JM
2160 obstack_alloc
2161 (cproc_obstack,
2162 th_count * sizeof (struct gdb_thread));
c906108c
SS
2163
2164 for (index = 0; index < th_count; index++)
2165 {
2166 thread_t saved_thread = MACH_PORT_NULL;
2167 int mid;
2168
2169 if (must_suspend_thread)
c5aa993b 2170 setup_thread (th_table[index], 1);
c906108c
SS
2171
2172 if (th_table[index] != current_thread)
2173 {
2174 saved_thread = current_thread;
c5aa993b
JM
2175
2176 mid = switch_to_thread (th_table[index]);
c906108c
SS
2177 }
2178
c5aa993b 2179 mthreads[index].name = th_table[index];
c906108c
SS
2180 mthreads[index].cproc = NULL; /* map_cprocs_to_kernel_threads() */
2181 mthreads[index].in_emulator = FALSE;
2182 mthreads[index].slotid = index;
c5aa993b 2183
c906108c
SS
2184 mthreads[index].sp = read_register (SP_REGNUM);
2185 mthreads[index].fp = read_register (FP_REGNUM);
2186 mthreads[index].pc = read_pc ();
2187
2188 if (MACH_PORT_VALID (saved_thread))
2189 mid = switch_to_thread (saved_thread);
2190
2191 if (must_suspend_thread)
c5aa993b 2192 setup_thread (th_table[index], 0);
c906108c 2193 }
c5aa993b 2194
c906108c 2195 consume_send_rights (th_table, th_count);
c5aa993b
JM
2196 ret = vm_deallocate (mach_task_self (), (vm_address_t) th_table,
2197 (th_count * sizeof (mach_port_t)));
c906108c
SS
2198 if (ret != KERN_SUCCESS)
2199 {
2200 warning ("Error trying to deallocate thread list : %s",
2201 mach_error_string (ret));
2202 }
2203
2204 *mthreads_out = mthreads;
2205
2206 return th_count;
2207}
2208
2209
2210/*
2211 * Current emulator always saves the USP on top of
2212 * emulator stack below struct emul_stack_top stuff.
2213 */
2214CORE_ADDR
fba45db2 2215fetch_usp_from_emulator_stack (CORE_ADDR sp)
c906108c
SS
2216{
2217 CORE_ADDR stack_pointer;
2218
c5aa993b
JM
2219 sp = (sp & ~(EMULATOR_STACK_SIZE - 1)) +
2220 EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
2221
c906108c
SS
2222 if (mach3_read_inferior (sp,
2223 &stack_pointer,
2224 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2225 {
2226 warning ("Can't read user sp from emulator stack address 0x%x", sp);
2227 return 0;
2228 }
2229
2230 return stack_pointer;
2231}
2232
2233#ifdef MK67
2234
2235/* get_emulation_vector() interface was changed after mk67 */
2236#define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2237
2238#endif /* MK67 */
2239
2240/* Check if the emulator exists at task's address space.
2241 */
2242boolean_t
fba45db2 2243have_emulator_p (task_t task)
c906108c 2244{
c5aa993b 2245 kern_return_t ret;
c906108c 2246#ifndef EMUL_VECTOR_COUNT
c5aa993b
JM
2247 vm_offset_t *emulation_vector;
2248 int n;
c906108c 2249#else
c5aa993b
JM
2250 vm_offset_t emulation_vector[EMUL_VECTOR_COUNT];
2251 int n = EMUL_VECTOR_COUNT;
c906108c 2252#endif
c5aa993b
JM
2253 int i;
2254 int vector_start;
2255
c906108c
SS
2256 ret = task_get_emulation_vector (task,
2257 &vector_start,
2258#ifndef EMUL_VECTOR_COUNT
2259 &emulation_vector,
2260#else
2261 emulation_vector,
2262#endif
2263 &n);
c5aa993b 2264 CHK ("task_get_emulation_vector", ret);
c906108c
SS
2265 xx_debug ("%d vectors from %d at 0x%08x\n",
2266 n, vector_start, emulation_vector);
c5aa993b
JM
2267
2268 for (i = 0; i < n; i++)
c906108c 2269 {
c5aa993b 2270 vm_offset_t entry = emulation_vector[i];
c906108c
SS
2271
2272 if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
2273 return TRUE;
2274 else if (entry)
2275 {
2276 static boolean_t informed = FALSE;
2277 if (!informed)
2278 {
c5aa993b
JM
2279 warning ("Emulation vector address 0x08%x outside emulator space",
2280 entry);
c906108c
SS
2281 informed = TRUE;
2282 }
2283 }
2284 }
2285 return FALSE;
2286}
2287
2288/* Map cprocs to kernel threads and vice versa. */
2289
2290void
fba45db2
KB
2291map_cprocs_to_kernel_threads (gdb_thread_t cprocs, gdb_thread_t mthreads,
2292 int thread_count)
c906108c
SS
2293{
2294 int index;
2295 gdb_thread_t scan;
2296 boolean_t all_mapped = TRUE;
2297 LONGEST stack_base;
2298 LONGEST stack_size;
2299
2300 for (scan = cprocs; scan; scan = scan->next)
2301 {
2302 /* Default to: no kernel thread for this cproc */
2303 scan->reverse_map = -1;
2304
2305 /* Check if the cproc is found by its stack */
2306 for (index = 0; index < thread_count; index++)
2307 {
2308 stack_base =
2309 extract_signed_integer (scan->raw_cproc + CPROC_BASE_OFFSET,
2310 CPROC_BASE_SIZE);
c5aa993b 2311 stack_size =
c906108c
SS
2312 extract_signed_integer (scan->raw_cproc + CPROC_SIZE_OFFSET,
2313 CPROC_SIZE_SIZE);
2314 if ((mthreads + index)->sp > stack_base &&
2315 (mthreads + index)->sp <= stack_base + stack_size)
2316 {
2317 (mthreads + index)->cproc = scan;
2318 scan->reverse_map = index;
2319 break;
2320 }
2321 }
2322 all_mapped &= (scan->reverse_map != -1);
2323 }
2324
2325 /* Check for threads that are currently in the emulator.
2326 * If so, they have a different stack, and the still unmapped
2327 * cprocs may well get mapped to these threads.
2328 *
2329 * If:
2330 * - cproc stack does not match any kernel thread stack pointer
2331 * - there is at least one extra kernel thread
2332 * that has no cproc mapped above.
2333 * - some kernel thread stack pointer points to emulator space
2334 * then we find the user stack pointer saved in the emulator
2335 * stack, and try to map that to the cprocs.
2336 *
2337 * Also set in_emulator for kernel threads.
c5aa993b 2338 */
c906108c
SS
2339
2340 if (emulator_present)
2341 {
2342 for (index = 0; index < thread_count; index++)
2343 {
2344 CORE_ADDR emul_sp;
2345 CORE_ADDR usp;
2346
c5aa993b 2347 gdb_thread_t mthread = (mthreads + index);
c906108c
SS
2348 emul_sp = mthread->sp;
2349
2350 if (mthread->cproc == NULL &&
2351 EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
2352 {
2353 mthread->in_emulator = emulator_present;
c5aa993b 2354
c906108c
SS
2355 if (!all_mapped && cprocs)
2356 {
2357 usp = fetch_usp_from_emulator_stack (emul_sp);
c5aa993b 2358
c906108c 2359 /* @@ Could be more accurate */
c5aa993b 2360 if (!usp)
c906108c 2361 error ("Zero stack pointer read from emulator?");
c5aa993b 2362
c906108c
SS
2363 /* Try to match this stack pointer to the cprocs that
2364 * don't yet have a kernel thread.
2365 */
2366 for (scan = cprocs; scan; scan = scan->next)
2367 {
c5aa993b 2368
c906108c
SS
2369 /* Check is this unmapped CPROC stack contains
2370 * the user stack pointer saved in the
2371 * emulator.
2372 */
2373 if (scan->reverse_map == -1)
2374 {
2375 stack_base =
2376 extract_signed_integer
c5aa993b
JM
2377 (scan->raw_cproc + CPROC_BASE_OFFSET,
2378 CPROC_BASE_SIZE);
2379 stack_size =
c906108c 2380 extract_signed_integer
c5aa993b
JM
2381 (scan->raw_cproc + CPROC_SIZE_OFFSET,
2382 CPROC_SIZE_SIZE);
c906108c
SS
2383 if (usp > stack_base &&
2384 usp <= stack_base + stack_size)
2385 {
2386 mthread->cproc = scan;
2387 scan->reverse_map = index;
2388 break;
2389 }
2390 }
2391 }
2392 }
2393 }
2394 }
2395 }
2396}
2397\f
2398/*
2399 * Format of the thread_list command
2400 *
c5aa993b 2401 * slot mid sel name emul ks susp cstate wired address
c906108c
SS
2402 */
2403#define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2404
2405#define TL_HEADER "\n@ MID Name KState CState Where\n"
2406
2407void
fba45db2 2408print_tl_address (struct ui_file *stream, CORE_ADDR pc)
c906108c 2409{
c5aa993b
JM
2410 if (!lookup_minimal_symbol_by_pc (pc))
2411 fprintf_filtered (stream, local_hex_format (), pc);
c906108c
SS
2412 else
2413 {
2414 extern int addressprint;
2415 extern int asm_demangle;
2416
c5aa993b 2417 int store = addressprint;
c906108c
SS
2418 addressprint = 0;
2419 print_address_symbolic (pc, stream, asm_demangle, "");
2420 addressprint = store;
2421 }
2422}
2423\f
2424/* For thread names, but also for gdb_message_port external name */
2425#define MAX_NAME_LEN 50
2426
2427/* Returns the address of variable NAME or 0 if not found */
2428CORE_ADDR
fba45db2 2429lookup_address_of_variable (char *name)
c906108c
SS
2430{
2431 struct symbol *sym;
2432 CORE_ADDR symaddr = 0;
2433 struct minimal_symbol *msymbol;
2434
2435 sym = lookup_symbol (name,
c5aa993b 2436 (struct block *) NULL,
c906108c 2437 VAR_NAMESPACE,
c5aa993b
JM
2438 (int *) NULL,
2439 (struct symtab **) NULL);
c906108c
SS
2440
2441 if (sym)
2442 symaddr = SYMBOL_VALUE (sym);
2443
c5aa993b 2444 if (!symaddr)
c906108c
SS
2445 {
2446 msymbol = lookup_minimal_symbol (name, NULL, NULL);
2447
2448 if (msymbol && msymbol->type == mst_data)
2449 symaddr = SYMBOL_VALUE_ADDRESS (msymbol);
2450 }
2451
2452 return symaddr;
2453}
2454
2455static gdb_thread_t
fba45db2 2456get_cprocs (void)
c906108c
SS
2457{
2458 gdb_thread_t cproc_head;
2459 gdb_thread_t cproc_copy;
2460 CORE_ADDR their_cprocs;
35fc8285 2461 char *buf;
c906108c
SS
2462 char *name;
2463 cthread_t cthread;
2464 CORE_ADDR symaddr;
c5aa993b 2465
35fc8285 2466 buf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT);
c906108c
SS
2467 symaddr = lookup_address_of_variable ("cproc_list");
2468
c5aa993b 2469 if (!symaddr)
c906108c
SS
2470 {
2471 /* cproc_list is not in a file compiled with debugging
c5aa993b 2472 symbols, but don't give up yet */
c906108c
SS
2473
2474 symaddr = lookup_address_of_variable ("cprocs");
2475
2476 if (symaddr)
2477 {
2478 static int informed = 0;
2479 if (!informed)
2480 {
2481 informed++;
2482 warning ("Your program is loaded with an old threads library.");
2483 warning ("GDB does not know the old form of threads");
2484 warning ("so things may not work.");
2485 }
2486 }
2487 }
2488
2489 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
c5aa993b 2490 if (!symaddr)
c906108c
SS
2491 return NULL;
2492
2493 /* Get the address of the first cproc in the task */
2494 if (!mach3_read_inferior (symaddr,
2495 buf,
2496 TARGET_PTR_BIT / HOST_CHAR_BIT))
2497 error ("Can't read cproc master list at address (0x%x).", symaddr);
2498 their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
2499
2500 /* Scan the CPROCs in the task.
2501 CPROCs are chained with LIST field, not NEXT field, which
2502 chains mutexes, condition variables and queues */
2503
2504 cproc_head = NULL;
2505
c5aa993b 2506 while (their_cprocs != (CORE_ADDR) 0)
c906108c
SS
2507 {
2508 CORE_ADDR cproc_copy_incarnation;
2509 cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
2510 sizeof (struct gdb_thread));
2511
2512 if (!mach3_read_inferior (their_cprocs,
2513 &cproc_copy->raw_cproc[0],
2514 CPROC_SIZE))
c5aa993b 2515 error ("Can't read next cproc at 0x%x.", their_cprocs);
c906108c
SS
2516
2517 their_cprocs =
2518 extract_address (cproc_copy->raw_cproc + CPROC_LIST_OFFSET,
2519 CPROC_LIST_SIZE);
2520 cproc_copy_incarnation =
2521 extract_address (cproc_copy->raw_cproc + CPROC_INCARNATION_OFFSET,
2522 CPROC_INCARNATION_SIZE);
2523
c5aa993b 2524 if (cproc_copy_incarnation == (CORE_ADDR) 0)
c906108c
SS
2525 cproc_copy->cthread = NULL;
2526 else
2527 {
2528 /* This CPROC has an attached CTHREAD. Get its name */
c5aa993b
JM
2529 cthread = (cthread_t) obstack_alloc (cproc_obstack,
2530 sizeof (struct cthread));
c906108c
SS
2531
2532 if (!mach3_read_inferior (cproc_copy_incarnation,
2533 cthread,
c5aa993b
JM
2534 sizeof (struct cthread)))
2535 error ("Can't read next thread at 0x%x.",
2536 cproc_copy_incarnation);
c906108c
SS
2537
2538 cproc_copy->cthread = cthread;
2539
2540 if (cthread->name)
2541 {
2542 name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
2543
c5aa993b
JM
2544 if (!mach3_read_inferior (cthread->name, name, MAX_NAME_LEN))
2545 error ("Can't read next thread's name at 0x%x.", cthread->name);
c906108c
SS
2546
2547 cthread->name = name;
2548 }
2549 }
2550
2551 /* insert in front */
2552 cproc_copy->next = cproc_head;
2553 cproc_head = cproc_copy;
2554 }
2555 return cproc_head;
2556}
2557
2558#ifndef FETCH_CPROC_STATE
2559/*
2560 * Check if your machine does not grok the way this routine
2561 * fetches the FP,PC and SP of a cproc that is not
2562 * currently attached to any kernel thread (e.g. its cproc.context
2563 * field points to the place in stack where the context
2564 * is saved).
2565 *
2566 * If it doesn't, define your own routine.
2567 */
2568#define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2569
2570int
fba45db2 2571mach3_cproc_state (gdb_thread_t mthread)
c906108c
SS
2572{
2573 int context;
2574
c5aa993b 2575 if (!mthread || !mthread->cproc)
c906108c
SS
2576 return -1;
2577
2578 context = extract_signed_integer
2579 (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
2580 CPROC_CONTEXT_SIZE);
2581 if (context == 0)
2582 return -1;
2583
2584 mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
2585
2586 if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
2587 &mthread->pc,
2588 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2589 {
2590 warning ("Can't read cproc pc from inferior");
2591 return -1;
2592 }
2593
2594 if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
2595 &mthread->fp,
2596 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2597 {
2598 warning ("Can't read cproc fp from inferior");
2599 return -1;
2600 }
2601
2602 return 0;
2603}
2604#endif /* FETCH_CPROC_STATE */
c906108c 2605\f
c5aa993b 2606
c906108c 2607void
fba45db2 2608thread_list_command (void)
c906108c
SS
2609{
2610 thread_basic_info_data_t ths;
c5aa993b 2611 int thread_count;
c906108c
SS
2612 gdb_thread_t cprocs;
2613 gdb_thread_t scan;
c5aa993b
JM
2614 int index;
2615 char *name;
2616 char selected;
2617 char *wired;
2618 int infoCnt;
c906108c 2619 kern_return_t ret;
c5aa993b
JM
2620 mach_port_t mid_or_port;
2621 gdb_thread_t their_threads;
2622 gdb_thread_t kthread;
c906108c
SS
2623
2624 int neworder = 1;
2625
2626 char *fmt = "There are %d kernel threads in task %d.\n";
c5aa993b 2627
c906108c 2628 int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 2629
c906108c 2630 MACH_ERROR_NO_INFERIOR;
c5aa993b 2631
c906108c
SS
2632 thread_count = fetch_thread_info (inferior_task,
2633 &their_threads);
2634 if (thread_count == -1)
2635 return;
c5aa993b 2636
c906108c
SS
2637 if (thread_count == 1)
2638 fmt = "There is %d kernel thread in task %d.\n";
c5aa993b 2639
c906108c 2640 printf_filtered (fmt, thread_count, tmid);
c5aa993b 2641
c906108c 2642 puts_filtered (TL_HEADER);
c5aa993b
JM
2643
2644 cprocs = get_cprocs ();
2645
c906108c 2646 map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
c5aa993b 2647
c906108c
SS
2648 for (scan = cprocs; scan; scan = scan->next)
2649 {
2650 int mid;
2651 char buf[10];
2652 char slot[3];
2653 int cproc_state =
c5aa993b
JM
2654 extract_signed_integer
2655 (scan->raw_cproc + CPROC_STATE_OFFSET, CPROC_STATE_SIZE);
2656
c906108c 2657 selected = ' ';
c5aa993b 2658
c906108c
SS
2659 /* a wired cproc? */
2660 wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
2661 CPROC_WIRED_SIZE)
2662 ? "wired" : "");
2663
2664 if (scan->reverse_map != -1)
c5aa993b 2665 kthread = (their_threads + scan->reverse_map);
c906108c 2666 else
c5aa993b 2667 kthread = NULL;
c906108c
SS
2668
2669 if (kthread)
2670 {
2671 /* These cprocs have a kernel thread */
c5aa993b 2672
c906108c 2673 mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
c5aa993b 2674
c906108c 2675 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 2676
c906108c
SS
2677 ret = thread_info (kthread->name,
2678 THREAD_BASIC_INFO,
c5aa993b 2679 (thread_info_t) & ths,
c906108c 2680 &infoCnt);
c5aa993b 2681
c906108c
SS
2682 if (ret != KERN_SUCCESS)
2683 {
2684 warning ("Unable to get basic info on thread %d : %s",
2685 mid,
2686 mach_error_string (ret));
2687 continue;
2688 }
2689
2690 /* Who is the first to have more than 100 threads */
c5aa993b 2691 sprintf (slot, "%d", kthread->slotid % 100);
c906108c
SS
2692
2693 if (kthread->name == current_thread)
2694 selected = '*';
c5aa993b 2695
c906108c
SS
2696 if (ths.suspend_count)
2697 sprintf (buf, "%d", ths.suspend_count);
2698 else
2699 buf[0] = '\000';
2700
2701#if 0
2702 if (ths.flags & TH_FLAGS_SWAPPED)
2703 strcat (buf, "S");
2704#endif
2705
2706 if (ths.flags & TH_FLAGS_IDLE)
2707 strcat (buf, "I");
2708
2709 printf_filtered (TL_FORMAT,
2710 slot,
2711 mid,
2712 selected,
2713 get_thread_name (scan, kthread->slotid),
2714 kthread->in_emulator ? "E" : "",
2715 translate_state (ths.run_state),
2716 buf,
2717 translate_cstate (cproc_state),
2718 wired);
2719 print_tl_address (gdb_stdout, kthread->pc);
2720 }
2721 else
2722 {
2723 /* These cprocs don't have a kernel thread.
2724 * find out the calling frame with
2725 * FETCH_CPROC_STATE.
2726 */
2727
2728 struct gdb_thread state;
2729
2730#if 0
2731 /* jtv -> emcmanus: why do you want this here? */
2732 if (scan->incarnation == NULL)
c5aa993b 2733 continue; /* EMcM */
c906108c
SS
2734#endif
2735
2736 printf_filtered (TL_FORMAT,
2737 "-",
2738 -neworder, /* Pseudo MID */
2739 selected,
2740 get_thread_name (scan, -neworder),
2741 "",
2742 "-", /* kernel state */
2743 "",
2744 translate_cstate (cproc_state),
2745 "");
2746 state.cproc = scan;
2747
2748 if (FETCH_CPROC_STATE (&state) == -1)
2749 puts_filtered ("???");
2750 else
2751 print_tl_address (gdb_stdout, state.pc);
2752
2753 neworder++;
2754 }
2755 puts_filtered ("\n");
2756 }
c5aa993b 2757
c906108c
SS
2758 /* Scan for kernel threads without cprocs */
2759 for (index = 0; index < thread_count; index++)
2760 {
c5aa993b 2761 if (!their_threads[index].cproc)
c906108c
SS
2762 {
2763 int mid;
c5aa993b 2764
c906108c
SS
2765 char buf[10];
2766 char slot[3];
2767
2768 mach_port_t name = their_threads[index].name;
c5aa993b 2769
c906108c 2770 mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
c5aa993b 2771
c906108c 2772 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b
JM
2773
2774 ret = thread_info (name,
2775 THREAD_BASIC_INFO,
2776 (thread_info_t) & ths,
2777 &infoCnt);
2778
c906108c
SS
2779 if (ret != KERN_SUCCESS)
2780 {
2781 warning ("Unable to get basic info on thread %d : %s",
2782 mid,
2783 mach_error_string (ret));
2784 continue;
2785 }
2786
c5aa993b 2787 sprintf (slot, "%d", index % 100);
c906108c
SS
2788
2789 if (name == current_thread)
2790 selected = '*';
2791 else
2792 selected = ' ';
2793
2794 if (ths.suspend_count)
2795 sprintf (buf, "%d", ths.suspend_count);
2796 else
2797 buf[0] = '\000';
2798
2799#if 0
2800 if (ths.flags & TH_FLAGS_SWAPPED)
2801 strcat (buf, "S");
2802#endif
2803
2804 if (ths.flags & TH_FLAGS_IDLE)
2805 strcat (buf, "I");
2806
2807 printf_filtered (TL_FORMAT,
2808 slot,
2809 mid,
2810 selected,
2811 get_thread_name (NULL, index),
2812 their_threads[index].in_emulator ? "E" : "",
2813 translate_state (ths.run_state),
2814 buf,
c5aa993b 2815 "", /* No cproc state */
c906108c
SS
2816 ""); /* Can't be wired */
2817 print_tl_address (gdb_stdout, their_threads[index].pc);
2818 puts_filtered ("\n");
2819 }
2820 }
c5aa993b 2821
c906108c
SS
2822 obstack_free (cproc_obstack, 0);
2823 obstack_init (cproc_obstack);
2824}
2825\f
2826void
fba45db2 2827thread_select_command (char *args, int from_tty)
c906108c
SS
2828{
2829 int mid;
2830 thread_array_t thread_list;
2831 int thread_count;
2832 kern_return_t ret;
2833 int is_slot = 0;
2834
2835 MACH_ERROR_NO_INFERIOR;
2836
2837 if (!args)
2838 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2839
2840 while (*args == ' ' || *args == '\t')
2841 args++;
2842
2843 if (*args == '@')
2844 {
2845 is_slot++;
2846 args++;
2847 }
2848
c5aa993b 2849 mid = atoi (args);
c906108c
SS
2850
2851 if (mid == 0)
c5aa993b 2852 if (!is_slot || *args != '0') /* Rudimentary checks */
c906108c
SS
2853 error ("You must select threads by MID or @SLOTNUMBER");
2854
c5aa993b 2855 if (select_thread (inferior_task, mid, is_slot ? 2 : 1) != KERN_SUCCESS)
c906108c
SS
2856 return;
2857
2858 if (from_tty)
2859 printf_filtered ("Thread %d selected\n",
2860 is_slot ? map_port_name_to_mid (current_thread,
c5aa993b 2861 MACH_TYPE_THREAD) : mid);
c906108c
SS
2862}
2863\f
fba45db2 2864thread_trace (mach_port_t thread, boolean_t set)
c906108c 2865{
c5aa993b
JM
2866 int flavor = TRACE_FLAVOR;
2867 unsigned int stateCnt = TRACE_FLAVOR_SIZE;
2868 kern_return_t ret;
2869 thread_state_data_t state;
c906108c 2870
c5aa993b 2871 if (!MACH_PORT_VALID (thread))
c906108c
SS
2872 {
2873 warning ("thread_trace: invalid thread");
2874 return;
2875 }
2876
2877 if (must_suspend_thread)
2878 setup_thread (thread, 1);
2879
c5aa993b 2880 ret = thread_get_state (thread, flavor, state, &stateCnt);
c906108c 2881 CHK ("thread_trace: error reading thread state", ret);
c5aa993b 2882
c906108c
SS
2883 if (set)
2884 {
2885 TRACE_SET (thread, state);
2886 }
2887 else
2888 {
c5aa993b 2889 if (!TRACE_CLEAR (thread, state))
c906108c
SS
2890 {
2891 if (must_suspend_thread)
2892 setup_thread (thread, 0);
2893 return;
2894 }
2895 }
2896
c5aa993b 2897 ret = thread_set_state (thread, flavor, state, stateCnt);
c906108c
SS
2898 CHK ("thread_trace: error writing thread state", ret);
2899 if (must_suspend_thread)
2900 setup_thread (thread, 0);
c5aa993b 2901}
c906108c
SS
2902
2903#ifdef FLUSH_INFERIOR_CACHE
2904
2905/* When over-writing code on some machines the I-Cache must be flushed
2906 explicitly, because it is not kept coherent by the lazy hardware.
2907 This definitely includes breakpoints, for instance, or else we
2908 end up looping in mysterious Bpt traps */
2909
fba45db2 2910flush_inferior_icache (CORE_ADDR pc, int amount)
c906108c
SS
2911{
2912 vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
c5aa993b
JM
2913 kern_return_t ret;
2914
c906108c
SS
2915 ret = vm_machine_attribute (inferior_task,
2916 pc,
2917 amount,
2918 MATTR_CACHE,
2919 &flush);
2920 if (ret != KERN_SUCCESS)
2921 warning ("Error flushing inferior's cache : %s",
2922 mach_error_string (ret));
2923}
c5aa993b 2924#endif /* FLUSH_INFERIOR_CACHE */
c906108c 2925\f
c5aa993b 2926
c906108c 2927static
fba45db2 2928suspend_all_threads (int from_tty)
c906108c 2929{
c5aa993b
JM
2930 kern_return_t ret;
2931 thread_array_t thread_list;
2932 int thread_count, index;
2933 int infoCnt;
c906108c
SS
2934 thread_basic_info_data_t th_info;
2935
c5aa993b 2936
c906108c
SS
2937 ret = task_threads (inferior_task, &thread_list, &thread_count);
2938 if (ret != KERN_SUCCESS)
2939 {
2940 warning ("Could not suspend inferior threads.");
2941 m3_kill_inferior ();
2942 return_to_top_level (RETURN_ERROR);
2943 }
c5aa993b 2944
c906108c
SS
2945 for (index = 0; index < thread_count; index++)
2946 {
2947 int mid;
2948
c5aa993b 2949 mid = map_port_name_to_mid (thread_list[index],
c906108c 2950 MACH_TYPE_THREAD);
c5aa993b
JM
2951
2952 ret = thread_suspend (thread_list[index]);
c906108c
SS
2953
2954 if (ret != KERN_SUCCESS)
2955 warning ("Error trying to suspend thread %d : %s",
2956 mid, mach_error_string (ret));
2957
2958 if (from_tty)
2959 {
2960 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 2961 ret = thread_info (thread_list[index],
c906108c 2962 THREAD_BASIC_INFO,
c5aa993b 2963 (thread_info_t) & th_info,
c906108c
SS
2964 &infoCnt);
2965 CHK ("suspend can't get thread info", ret);
c5aa993b 2966
c906108c
SS
2967 warning ("Thread %d suspend count is %d",
2968 mid, th_info.suspend_count);
2969 }
2970 }
2971
2972 consume_send_rights (thread_list, thread_count);
c5aa993b
JM
2973 ret = vm_deallocate (mach_task_self (),
2974 (vm_address_t) thread_list,
2975 (thread_count * sizeof (int)));
c906108c
SS
2976 CHK ("Error trying to deallocate thread list", ret);
2977}
2978
2979void
fba45db2 2980thread_suspend_command (char *args, int from_tty)
c906108c
SS
2981{
2982 kern_return_t ret;
c5aa993b
JM
2983 int mid;
2984 mach_port_t saved_thread;
2985 int infoCnt;
c906108c 2986 thread_basic_info_data_t th_info;
c5aa993b 2987
c906108c
SS
2988 MACH_ERROR_NO_INFERIOR;
2989
c5aa993b
JM
2990 if (!strcasecmp (args, "all"))
2991 {
2992 suspend_all_threads (from_tty);
2993 return;
2994 }
c906108c
SS
2995
2996 saved_thread = current_thread;
2997
2998 mid = parse_thread_id (args, 0, 0);
2999
3000 if (mid < 0)
3001 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
3002
3003 if (mid == 0)
3004 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b
JM
3005 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3006 {
3007 if (current_thread)
3008 current_thread = saved_thread;
3009 error ("Could not select thread %d", mid);
3010 }
c906108c
SS
3011
3012 ret = thread_suspend (current_thread);
3013 if (ret != KERN_SUCCESS)
3014 warning ("thread_suspend failed : %s",
3015 mach_error_string (ret));
3016
3017 infoCnt = THREAD_BASIC_INFO_COUNT;
3018 ret = thread_info (current_thread,
3019 THREAD_BASIC_INFO,
c5aa993b 3020 (thread_info_t) & th_info,
c906108c
SS
3021 &infoCnt);
3022 CHK ("suspend can't get thread info", ret);
c5aa993b 3023
c906108c 3024 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
c5aa993b 3025
c906108c
SS
3026 current_thread = saved_thread;
3027}
3028
fba45db2 3029resume_all_threads (int from_tty)
c906108c 3030{
c5aa993b
JM
3031 kern_return_t ret;
3032 thread_array_t thread_list;
3033 int thread_count, index;
3034 int mid;
3035 int infoCnt;
3036 thread_basic_info_data_t th_info;
c906108c 3037
c5aa993b
JM
3038 ret = task_threads (inferior_task, &thread_list, &thread_count);
3039 if (ret != KERN_SUCCESS)
3040 {
3041 m3_kill_inferior ();
3042 error ("task_threads", mach_error_string (ret));
3043 }
c906108c 3044
c5aa993b
JM
3045 for (index = 0; index < thread_count; index++)
3046 {
3047 infoCnt = THREAD_BASIC_INFO_COUNT;
3048 ret = thread_info (thread_list[index],
3049 THREAD_BASIC_INFO,
3050 (thread_info_t) & th_info,
3051 &infoCnt);
3052 CHK ("resume_all can't get thread info", ret);
c906108c 3053
c5aa993b
JM
3054 mid = map_port_name_to_mid (thread_list[index],
3055 MACH_TYPE_THREAD);
c906108c 3056
c5aa993b
JM
3057 if (!th_info.suspend_count)
3058 {
3059 if (mid != -1 && from_tty)
3060 warning ("Thread %d is not suspended", mid);
3061 continue;
3062 }
c906108c 3063
c5aa993b
JM
3064 ret = thread_resume (thread_list[index]);
3065
3066 if (ret != KERN_SUCCESS)
3067 warning ("Error trying to resume thread %d : %s",
3068 mid, mach_error_string (ret));
3069 else if (mid != -1 && from_tty)
3070 warning ("Thread %d suspend count is %d",
3071 mid, --th_info.suspend_count);
3072 }
3073
3074 consume_send_rights (thread_list, thread_count);
3075 ret = vm_deallocate (mach_task_self (),
3076 (vm_address_t) thread_list,
3077 (thread_count * sizeof (int)));
3078 CHK ("Error trying to deallocate thread list", ret);
c906108c
SS
3079}
3080
3081void
fba45db2 3082thread_resume_command (char *args, int from_tty)
c906108c
SS
3083{
3084 int mid;
3085 mach_port_t saved_thread;
3086 kern_return_t ret;
3087 thread_basic_info_data_t th_info;
3088 int infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 3089
c906108c
SS
3090 MACH_ERROR_NO_INFERIOR;
3091
c5aa993b
JM
3092 if (!strcasecmp (args, "all"))
3093 {
3094 resume_all_threads (from_tty);
3095 return;
3096 }
c906108c
SS
3097
3098 saved_thread = current_thread;
3099
3100 mid = parse_thread_id (args, 0, 0);
3101
3102 if (mid < 0)
3103 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3104
3105 if (mid == 0)
3106 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b
JM
3107 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3108 {
3109 if (current_thread)
3110 current_thread = saved_thread;
3111 return_to_top_level (RETURN_ERROR);
3112 }
c906108c
SS
3113
3114 ret = thread_info (current_thread,
3115 THREAD_BASIC_INFO,
c5aa993b 3116 (thread_info_t) & th_info,
c906108c
SS
3117 &infoCnt);
3118 CHK ("resume can't get thread info", ret);
c5aa993b
JM
3119
3120 if (!th_info.suspend_count)
c906108c
SS
3121 {
3122 warning ("Thread %d is not suspended", mid);
3123 goto out;
3124 }
3125
3126 ret = thread_resume (current_thread);
3127 if (ret != KERN_SUCCESS)
3128 warning ("thread_resume failed : %s",
3129 mach_error_string (ret));
3130 else
3131 {
3132 th_info.suspend_count--;
3133 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
3134 }
c5aa993b
JM
3135
3136out:
c906108c
SS
3137 current_thread = saved_thread;
3138}
3139
3140void
fba45db2 3141thread_kill_command (char *args, int from_tty)
c906108c
SS
3142{
3143 int mid;
3144 kern_return_t ret;
3145 int thread_count;
3146 thread_array_t thread_table;
c5aa993b 3147 int index;
c906108c 3148 mach_port_t thread_to_kill = MACH_PORT_NULL;
c5aa993b
JM
3149
3150
c906108c
SS
3151 MACH_ERROR_NO_INFERIOR;
3152
3153 if (!args)
3154 error_no_arg ("thread mid to kill from the inferior task");
3155
3156 mid = parse_thread_id (args, 0, 0);
3157
3158 if (mid < 0)
3159 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3160
3161 if (mid)
3162 {
3163 ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
3164 CHK ("thread_kill_command: machid_mach_port map failed", ret);
3165 }
3166 else
3167 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b 3168
c906108c
SS
3169 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3170 ret = task_threads (inferior_task, &thread_table, &thread_count);
3171 CHK ("Error getting inferior's thread list", ret);
c5aa993b 3172
c906108c
SS
3173 if (thread_to_kill == current_thread)
3174 {
3175 ret = thread_terminate (thread_to_kill);
3176 CHK ("Thread could not be terminated", ret);
3177
3178 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3179 warning ("Last thread was killed, use \"kill\" command to kill task");
3180 }
3181 else
3182 for (index = 0; index < thread_count; index++)
c5aa993b 3183 if (thread_table[index] == thread_to_kill)
c906108c
SS
3184 {
3185 ret = thread_terminate (thread_to_kill);
3186 CHK ("Thread could not be terminated", ret);
3187 }
3188
3189 if (thread_count > 1)
3190 consume_send_rights (thread_table, thread_count);
c5aa993b
JM
3191
3192 ret = vm_deallocate (mach_task_self (), (vm_address_t) thread_table,
3193 (thread_count * sizeof (mach_port_t)));
c906108c 3194 CHK ("Error trying to deallocate thread list", ret);
c5aa993b 3195
c906108c
SS
3196 warning ("Thread %d killed", mid);
3197}
c906108c 3198\f
c5aa993b 3199
c906108c
SS
3200/* Task specific commands; add more if you like */
3201
3202void
fba45db2 3203task_resume_command (char *args, int from_tty)
c906108c
SS
3204{
3205 kern_return_t ret;
3206 task_basic_info_data_t ta_info;
3207 int infoCnt = TASK_BASIC_INFO_COUNT;
3208 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 3209
c906108c
SS
3210 MACH_ERROR_NO_INFERIOR;
3211
3212 /* Would be trivial to change, but is it desirable? */
3213 if (args)
3214 error ("Currently gdb can resume only it's inferior task");
3215
3216 ret = task_info (inferior_task,
3217 TASK_BASIC_INFO,
c5aa993b 3218 (task_info_t) & ta_info,
c906108c
SS
3219 &infoCnt);
3220 CHK ("task_resume_command: task_info failed", ret);
c5aa993b 3221
c906108c
SS
3222 if (ta_info.suspend_count == 0)
3223 error ("Inferior task %d is not suspended", mid);
3224 else if (ta_info.suspend_count == 1 &&
3225 from_tty &&
c5aa993b 3226 !query ("Suspend count is now 1. Do you know what you are doing? "))
c906108c
SS
3227 error ("Task not resumed");
3228
3229 ret = task_resume (inferior_task);
3230 CHK ("task_resume_command: task_resume", ret);
3231
3232 if (ta_info.suspend_count == 1)
3233 {
3234 warning ("Inferior task %d is no longer suspended", mid);
3235 must_suspend_thread = 1;
3236 /* @@ This is not complete: Registers change all the time when not
c5aa993b 3237 suspended! */
c906108c
SS
3238 registers_changed ();
3239 }
3240 else
3241 warning ("Inferior task %d suspend count is now %d",
c5aa993b 3242 mid, ta_info.suspend_count - 1);
c906108c
SS
3243}
3244
3245
3246void
fba45db2 3247task_suspend_command (char *args, int from_tty)
c906108c
SS
3248{
3249 kern_return_t ret;
3250 task_basic_info_data_t ta_info;
3251 int infoCnt = TASK_BASIC_INFO_COUNT;
3252 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 3253
c906108c
SS
3254 MACH_ERROR_NO_INFERIOR;
3255
3256 /* Would be trivial to change, but is it desirable? */
3257 if (args)
3258 error ("Currently gdb can suspend only it's inferior task");
3259
3260 ret = task_suspend (inferior_task);
3261 CHK ("task_suspend_command: task_suspend", ret);
3262
3263 must_suspend_thread = 0;
3264
3265 ret = task_info (inferior_task,
3266 TASK_BASIC_INFO,
c5aa993b 3267 (task_info_t) & ta_info,
c906108c
SS
3268 &infoCnt);
3269 CHK ("task_suspend_command: task_info failed", ret);
c5aa993b 3270
c906108c
SS
3271 warning ("Inferior task %d suspend count is now %d",
3272 mid, ta_info.suspend_count);
3273}
3274
3275static char *
fba45db2 3276get_size (int bytes)
c906108c 3277{
c5aa993b
JM
3278 static char size[30];
3279 int zz = bytes / 1024;
c906108c
SS
3280
3281 if (zz / 1024)
c5aa993b 3282 sprintf (size, "%-2.1f M", ((float) bytes) / (1024.0 * 1024.0));
c906108c
SS
3283 else
3284 sprintf (size, "%d K", zz);
3285
3286 return size;
3287}
3288
3289/* Does this require the target task to be suspended?? I don't think so. */
3290void
fba45db2 3291task_info_command (char *args, int from_tty)
c906108c
SS
3292{
3293 int mid = -5;
3294 mach_port_t task;
3295 kern_return_t ret;
3296 task_basic_info_data_t ta_info;
3297 int infoCnt = TASK_BASIC_INFO_COUNT;
c5aa993b 3298 int page_size = round_page (1);
c906108c 3299 int thread_count = 0;
c5aa993b 3300
c906108c
SS
3301 if (MACH_PORT_VALID (inferior_task))
3302 mid = map_port_name_to_mid (inferior_task,
3303 MACH_TYPE_TASK);
3304
3305 task = inferior_task;
3306
3307 if (args)
3308 {
3309 int tmid = atoi (args);
3310
3311 if (tmid <= 0)
3312 error ("Invalid mid %d for task info", tmid);
3313
3314 if (tmid != mid)
3315 {
3316 mid = tmid;
3317 ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
3318 CHK ("task_info_command: machid_mach_port map failed", ret);
3319 }
3320 }
3321
3322 if (mid < 0)
3323 error ("You have to give the task MID as an argument");
3324
3325 ret = task_info (task,
3326 TASK_BASIC_INFO,
c5aa993b 3327 (task_info_t) & ta_info,
c906108c
SS
3328 &infoCnt);
3329 CHK ("task_info_command: task_info failed", ret);
3330
3331 printf_filtered ("\nTask info for task %d:\n\n", mid);
3332 printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
3333 printf_filtered (" Base priority : %d\n", ta_info.base_priority);
3334 printf_filtered (" Virtual size : %s\n", get_size (ta_info.virtual_size));
3335 printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
3336
3337 {
3338 thread_array_t thread_list;
c5aa993b 3339
c906108c
SS
3340 ret = task_threads (task, &thread_list, &thread_count);
3341 CHK ("task_info_command: task_threads", ret);
c5aa993b 3342
c906108c
SS
3343 printf_filtered (" Thread count : %d\n", thread_count);
3344
3345 consume_send_rights (thread_list, thread_count);
c5aa993b
JM
3346 ret = vm_deallocate (mach_task_self (),
3347 (vm_address_t) thread_list,
3348 (thread_count * sizeof (int)));
3349 CHK ("Error trying to deallocate thread list", ret);
c906108c
SS
3350 }
3351 if (have_emulator_p (task))
3352 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3353 EMULATOR_BASE, EMULATOR_END);
3354 else
3355 printf_filtered (" No emulator.\n");
3356
3357 if (thread_count && task == inferior_task)
3358 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3359}
3360\f
3361/* You may either FORWARD the exception to the inferior, or KEEP
3362 * it and return to GDB command level.
3363 *
3364 * exception mid [ forward | keep ]
3365 */
3366
3367static void
fba45db2 3368exception_command (char *args, int from_tty)
c906108c
SS
3369{
3370 char *scan = args;
3371 int exception;
3372 int len;
3373
3374 if (!args)
3375 error_no_arg ("exception number action");
3376
c5aa993b
JM
3377 while (*scan == ' ' || *scan == '\t')
3378 scan++;
3379
c906108c
SS
3380 if ('0' <= *scan && *scan <= '9')
3381 while ('0' <= *scan && *scan <= '9')
3382 scan++;
3383 else
3384 error ("exception number action");
3385
3386 exception = atoi (args);
3387 if (exception <= 0 || exception > MAX_EXCEPTION)
3388 error ("Allowed exception numbers are in range 1..%d",
3389 MAX_EXCEPTION);
3390
3391 if (*scan != ' ' && *scan != '\t')
3392 error ("exception number must be followed by a space");
3393 else
c5aa993b
JM
3394 while (*scan == ' ' || *scan == '\t')
3395 scan++;
c906108c
SS
3396
3397 args = scan;
3398 len = 0;
3399 while (*scan)
3400 {
3401 len++;
3402 scan++;
3403 }
3404
3405 if (!len)
c5aa993b 3406 error ("exception number action");
c906108c
SS
3407
3408 if (!strncasecmp (args, "forward", len))
c5aa993b 3409 exception_map[exception].forward = TRUE;
c906108c 3410 else if (!strncasecmp (args, "keep", len))
c5aa993b 3411 exception_map[exception].forward = FALSE;
c906108c
SS
3412 else
3413 error ("exception action is either \"keep\" or \"forward\"");
3414}
3415
3416static void
fba45db2 3417print_exception_info (int exception)
c906108c 3418{
c5aa993b 3419 boolean_t forward = exception_map[exception].forward;
c906108c 3420
c5aa993b 3421 printf_filtered ("%s\t(%d): ", exception_map[exception].name,
c906108c
SS
3422 exception);
3423 if (!forward)
c5aa993b 3424 if (exception_map[exception].sigmap != SIG_UNKNOWN)
c906108c 3425 printf_filtered ("keep and handle as signal %d\n",
c5aa993b 3426 exception_map[exception].sigmap);
c906108c
SS
3427 else
3428 printf_filtered ("keep and handle as unknown signal %d\n",
c5aa993b 3429 exception_map[exception].sigmap);
c906108c
SS
3430 else
3431 printf_filtered ("forward exception to inferior\n");
3432}
3433
3434void
fba45db2 3435exception_info (char *args, int from_tty)
c906108c
SS
3436{
3437 int exception;
3438
3439 if (!args)
3440 for (exception = 1; exception <= MAX_EXCEPTION; exception++)
3441 print_exception_info (exception);
3442 else
3443 {
3444 exception = atoi (args);
3445
3446 if (exception <= 0 || exception > MAX_EXCEPTION)
3447 error ("Invalid exception number, values from 1 to %d allowed",
3448 MAX_EXCEPTION);
3449 print_exception_info (exception);
3450 }
3451}
3452\f
3453/* Check for actions for mach exceptions.
3454 */
fba45db2 3455mach3_exception_actions (WAITTYPE *w, boolean_t force_print_only, char *who)
c906108c
SS
3456{
3457 boolean_t force_print = FALSE;
3458
c5aa993b 3459
c906108c
SS
3460 if (force_print_only ||
3461 exception_map[stop_exception].sigmap == SIG_UNKNOWN)
3462 force_print = TRUE;
3463 else
3464 WSETSTOP (*w, exception_map[stop_exception].sigmap);
3465
3466 if (exception_map[stop_exception].print || force_print)
3467 {
3468 target_terminal_ours ();
c5aa993b 3469
c906108c
SS
3470 printf_filtered ("\n%s received %s exception : ",
3471 who,
3472 exception_map[stop_exception].name);
c5aa993b 3473
c906108c
SS
3474 wrap_here (" ");
3475
c5aa993b
JM
3476 switch (stop_exception)
3477 {
3478 case EXC_BAD_ACCESS:
3479 printf_filtered ("referencing address 0x%x : %s\n",
3480 stop_subcode,
3481 mach_error_string (stop_code));
3482 break;
3483 case EXC_BAD_INSTRUCTION:
3484 printf_filtered
3485 ("illegal or undefined instruction. code %d subcode %d\n",
3486 stop_code, stop_subcode);
3487 break;
3488 case EXC_ARITHMETIC:
3489 printf_filtered ("code %d\n", stop_code);
3490 break;
3491 case EXC_EMULATION:
3492 printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
3493 break;
3494 case EXC_SOFTWARE:
3495 printf_filtered ("%s specific, code 0x%x\n",
3496 stop_code < 0xffff ? "hardware" : "os emulation",
3497 stop_code);
3498 break;
3499 case EXC_BREAKPOINT:
3500 printf_filtered ("type %d (machine dependent)\n",
3501 stop_code);
3502 break;
3503 default:
8e65ff28
AC
3504 internal_error (__FILE__, __LINE__,
3505 "Unknown exception");
c5aa993b 3506 }
c906108c
SS
3507 }
3508}
3509\f
fba45db2 3510setup_notify_port (int create_new)
c906108c
SS
3511{
3512 kern_return_t ret;
3513
3514 if (MACH_PORT_VALID (our_notify_port))
3515 {
3516 ret = mach_port_destroy (mach_task_self (), our_notify_port);
3517 CHK ("Could not destroy our_notify_port", ret);
3518 }
3519
3520 our_notify_port = MACH_PORT_NULL;
c5aa993b 3521 notify_chain = (port_chain_t) NULL;
c906108c
SS
3522 port_chain_destroy (port_chain_obstack);
3523
3524 if (create_new)
3525 {
c5aa993b 3526 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
3527 MACH_PORT_RIGHT_RECEIVE,
3528 &our_notify_port);
3529 if (ret != KERN_SUCCESS)
8e65ff28
AC
3530 internal_error (__FILE__, __LINE__,
3531 "Creating notify port %s", mach_error_string (ret));
c5aa993b
JM
3532
3533 ret = mach_port_move_member (mach_task_self (),
3534 our_notify_port,
3535 inferior_wait_port_set);
c906108c 3536 if (ret != KERN_SUCCESS)
8e65ff28
AC
3537 internal_error (__FILE__, __LINE__,
3538 "initial move member %s", mach_error_string (ret));
c906108c
SS
3539 }
3540}
3541
3542/*
3543 * Register our message port to the net name server
3544 *
3545 * Currently used only by the external stop-gdb program
3546 * since ^C does not work if you would like to enter
3547 * gdb command level while debugging your program.
3548 *
3549 * NOTE: If the message port is sometimes used for other
3550 * purposes also, the NAME must not be a guessable one.
3551 * Then, there should be a way to change it.
3552 */
3553
c5aa993b 3554char registered_name[MAX_NAME_LEN];
c906108c
SS
3555
3556void
fba45db2 3557message_port_info (char *args, int from_tty)
c906108c
SS
3558{
3559 if (registered_name[0])
3560 printf_filtered ("gdb's message port name: '%s'\n",
3561 registered_name);
3562 else
3563 printf_filtered ("gdb's message port is not currently registered\n");
3564}
3565
3566void
fba45db2 3567gdb_register_port (char *name, mach_port_t port)
c906108c
SS
3568{
3569 kern_return_t ret;
3570 static int already_signed = 0;
3571 int len;
3572
c5aa993b 3573 if (!MACH_PORT_VALID (port) || !name || !*name)
c906108c
SS
3574 {
3575 warning ("Invalid registration request");
3576 return;
3577 }
3578
c5aa993b 3579 if (!already_signed)
c906108c
SS
3580 {
3581 ret = mach_port_insert_right (mach_task_self (),
3582 our_message_port,
3583 our_message_port,
3584 MACH_MSG_TYPE_MAKE_SEND);
3585 CHK ("Failed to create a signature to our_message_port", ret);
3586 already_signed = 1;
3587 }
3588 else if (already_signed > 1)
3589 {
3590 ret = netname_check_out (name_server_port,
3591 registered_name,
3592 our_message_port);
3593 CHK ("Failed to check out gdb's message port", ret);
3594 registered_name[0] = '\000';
3595 already_signed = 1;
3596 }
3597
3598 ret = netname_check_in (name_server_port, /* Name server port */
c5aa993b 3599 name, /* Name of service */
c906108c 3600 our_message_port, /* Signature */
c5aa993b
JM
3601 port); /* Creates a new send right */
3602 CHK ("Failed to check in the port", ret);
3603
c906108c 3604 len = 0;
c5aa993b 3605 while (len < MAX_NAME_LEN && *(name + len))
c906108c 3606 {
c5aa993b 3607 registered_name[len] = *(name + len);
c906108c
SS
3608 len++;
3609 }
3610 registered_name[len] = '\000';
3611 already_signed = 2;
c5aa993b 3612}
c906108c
SS
3613
3614struct cmd_list_element *cmd_thread_list;
3615struct cmd_list_element *cmd_task_list;
3616
c5aa993b 3617/*ARGSUSED */
c906108c 3618static void
fba45db2 3619thread_command (char *arg, int from_tty)
c906108c
SS
3620{
3621 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3622 help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
3623}
3624
c5aa993b 3625/*ARGSUSED */
c906108c 3626static void
fba45db2 3627task_command (char *arg, int from_tty)
c906108c
SS
3628{
3629 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3630 help_list (cmd_task_list, "task ", -1, gdb_stdout);
3631}
3632
fba45db2 3633add_mach_specific_commands (void)
c906108c
SS
3634{
3635 /* Thread handling commands */
3636
3637 /* FIXME: Move our thread support into the generic thread.c stuff so we
3638 can share that code. */
3639 add_prefix_cmd ("mthread", class_stack, thread_command,
c5aa993b
JM
3640 "Generic command for handling Mach threads in the debugged task.",
3641 &cmd_thread_list, "thread ", 0, &cmdlist);
c906108c
SS
3642
3643 add_com_alias ("th", "mthread", class_stack, 1);
3644
c5aa993b 3645 add_cmd ("select", class_stack, thread_select_command,
c906108c
SS
3646 "Select and print MID of the selected thread",
3647 &cmd_thread_list);
c5aa993b 3648 add_cmd ("list", class_stack, thread_list_command,
c906108c
SS
3649 "List info of task's threads. Selected thread is marked with '*'",
3650 &cmd_thread_list);
3651 add_cmd ("suspend", class_run, thread_suspend_command,
3652 "Suspend one or all of the threads in the selected task.",
3653 &cmd_thread_list);
3654 add_cmd ("resume", class_run, thread_resume_command,
3655 "Resume one or all of the threads in the selected task.",
3656 &cmd_thread_list);
3657 add_cmd ("kill", class_run, thread_kill_command,
3658 "Kill the specified thread MID from inferior task.",
3659 &cmd_thread_list);
3660#if 0
3661 /* The rest of this support (condition_thread) was not merged. It probably
3662 should not be merged in this form, but instead added to the generic GDB
3663 thread support. */
3664 add_cmd ("break", class_breakpoint, condition_thread,
3665 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3666 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3667 &cmd_thread_list);
3668#endif
3669 /* Thread command shorthands (for backward compatibility) */
3670 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
c5aa993b 3671 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist);
c906108c
SS
3672
3673 /* task handling commands */
3674
3675 add_prefix_cmd ("task", class_stack, task_command,
c5aa993b
JM
3676 "Generic command for handling debugged task.",
3677 &cmd_task_list, "task ", 0, &cmdlist);
c906108c
SS
3678
3679 add_com_alias ("ta", "task", class_stack, 1);
3680
3681 add_cmd ("suspend", class_run, task_suspend_command,
3682 "Suspend the inferior task.",
3683 &cmd_task_list);
3684 add_cmd ("resume", class_run, task_resume_command,
3685 "Resume the inferior task.",
3686 &cmd_task_list);
3687 add_cmd ("info", no_class, task_info_command,
3688 "Print information about the specified task.",
3689 &cmd_task_list);
3690
3691 /* Print my message port name */
3692
3693 add_info ("message-port", message_port_info,
3694 "Returns the name of gdb's message port in the netnameserver");
3695
3696 /* Exception commands */
3697
3698 add_info ("exceptions", exception_info,
3699 "What debugger does when program gets various exceptions.\n\
3700Specify an exception number as argument to print info on that\n\
3701exception only.");
3702
3703 add_com ("exception", class_run, exception_command,
3704 "Specify how to handle an exception.\n\
3705Args are exception number followed by \"forward\" or \"keep\".\n\
3706`Forward' means forward the exception to the program's normal exception\n\
3707handler.\n\
3708`Keep' means reenter debugger if this exception happens, and GDB maps\n\
3709the exception to some signal (see info exception)\n\
3710Normally \"keep\" is used to return to GDB on exception.");
3711}
3712
3713kern_return_t
fba45db2 3714do_mach_notify_dead_name (mach_port_t notify, mach_port_t name)
c906108c
SS
3715{
3716 kern_return_t kr = KERN_SUCCESS;
3717
3718 /* Find the thing that notified */
3719 port_chain_t element = port_chain_member (notify_chain, name);
3720
3721 /* Take name of from unreceived dead name notification list */
3722 notify_chain = port_chain_delete (notify_chain, name);
3723
c5aa993b 3724 if (!element)
c906108c 3725 error ("Received a dead name notify from unchained port (0x%x)", name);
c906108c 3726
c5aa993b
JM
3727 switch (element->type)
3728 {
c906108c 3729
c5aa993b
JM
3730 case MACH_TYPE_THREAD:
3731 target_terminal_ours_for_output ();
3732 if (name == current_thread)
3733 {
3734 printf_filtered ("\nCurrent thread %d died", element->mid);
3735 current_thread = MACH_PORT_NULL;
3736 }
3737 else
3738 printf_filtered ("\nThread %d died", element->mid);
c906108c 3739
c5aa993b 3740 break;
c906108c 3741
c5aa993b
JM
3742 case MACH_TYPE_TASK:
3743 target_terminal_ours_for_output ();
3744 if (name != inferior_task)
3745 printf_filtered ("Task %d died, but it was not the selected task",
3746 element->mid);
3747 else
3748 {
3749 printf_filtered ("Current task %d died", element->mid);
c906108c 3750
c5aa993b
JM
3751 mach_port_destroy (mach_task_self (), name);
3752 inferior_task = MACH_PORT_NULL;
3753
3754 if (notify_chain)
3755 warning ("There were still unreceived dead_name_notifications???");
3756
3757 /* Destroy the old notifications */
3758 setup_notify_port (0);
3759
3760 }
3761 break;
3762
3763 default:
3764 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3765 name, element->type, element->mid);
3766 break;
3767 }
c906108c
SS
3768
3769 return KERN_SUCCESS;
3770}
3771
3772kern_return_t
fba45db2 3773do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name)
c906108c
SS
3774{
3775 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3776 notify, name);
3777 return KERN_SUCCESS;
3778}
3779
3780kern_return_t
fba45db2 3781do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t mscount)
c906108c
SS
3782{
3783 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3784 notify, mscount);
3785 return KERN_SUCCESS;
3786}
3787
3788kern_return_t
fba45db2 3789do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name)
c906108c
SS
3790{
3791 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3792 notify, name);
3793 return KERN_SUCCESS;
3794}
3795
3796kern_return_t
fba45db2 3797do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t rights)
c906108c
SS
3798{
3799 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3800 notify, rights);
3801 return KERN_SUCCESS;
3802}
3803
3804kern_return_t
fba45db2 3805do_mach_notify_send_once (mach_port_t notify)
c906108c
SS
3806{
3807#ifdef DUMP_SYSCALL
3808 /* MANY of these are generated. */
3809 warning ("do_mach_notify_send_once : notify %x",
3810 notify);
3811#endif
3812 return KERN_SUCCESS;
3813}
3814
3815/* Kills the inferior. It's gone when you call this */
3816static void
fba45db2 3817kill_inferior_fast (void)
c906108c
SS
3818{
3819 WAITTYPE w;
3820
39f77062 3821 if (PIDGET (inferior_ptid) == 0 || PIDGET (inferior_ptid) == 1)
c906108c
SS
3822 return;
3823
3824 /* kill() it, since the Unix server does not otherwise notice when
3825 * killed with task_terminate().
3826 */
39f77062
KB
3827 if (PIDGET (inferior_ptid) > 0)
3828 kill (PIDGET (inferior_ptid), SIGKILL);
c906108c
SS
3829
3830 /* It's propably terminate already */
3831 (void) task_terminate (inferior_task);
3832
c5aa993b 3833 inferior_task = MACH_PORT_NULL;
c906108c
SS
3834 current_thread = MACH_PORT_NULL;
3835
3836 wait3 (&w, WNOHANG, 0);
3837
3838 setup_notify_port (0);
3839}
3840
3841static void
fba45db2 3842m3_kill_inferior (void)
c906108c
SS
3843{
3844 kill_inferior_fast ();
3845 target_mourn_inferior ();
3846}
3847
3848/* Clean up after the inferior dies. */
3849
3850static void
fba45db2 3851m3_mourn_inferior (void)
c906108c
SS
3852{
3853 unpush_target (&m3_ops);
3854 generic_mourn_inferior ();
3855}
c906108c 3856\f
c5aa993b 3857
c906108c
SS
3858/* Fork an inferior process, and start debugging it. */
3859
3860static void
fba45db2 3861m3_create_inferior (char *exec_file, char *allargs, char **env)
c906108c
SS
3862{
3863 fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL, NULL);
3864 /* We are at the first instruction we care about. */
3865 /* Pedal to the metal... */
2acceee2 3866 proceed ((CORE_ADDR) -1, 0, 0);
c906108c
SS
3867}
3868
3869/* Mark our target-struct as eligible for stray "run" and "attach"
3870 commands. */
3871static int
fba45db2 3872m3_can_run (void)
c906108c
SS
3873{
3874 return 1;
3875}
3876\f
3877/* Mach 3.0 does not need ptrace for anything
3878 * Make sure nobody uses it on mach.
3879 */
fba45db2 3880ptrace (int a, int b, int c, int d)
c906108c
SS
3881{
3882 error ("Lose, Lose! Somebody called ptrace\n");
3883}
3884
3885/* Resume execution of the inferior process.
3886 If STEP is nonzero, single-step it.
3887 If SIGNAL is nonzero, give it that signal. */
3888
3889void
39f77062 3890m3_resume (ptid_t ptid, int step, enum target_signal signal)
c906108c 3891{
c5aa993b 3892 kern_return_t ret;
c906108c
SS
3893
3894 if (step)
3895 {
3896 thread_basic_info_data_t th_info;
c5aa993b
JM
3897 unsigned int infoCnt = THREAD_BASIC_INFO_COUNT;
3898
c906108c
SS
3899 /* There is no point in single stepping when current_thread
3900 * is dead.
3901 */
c5aa993b 3902 if (!MACH_PORT_VALID (current_thread))
c906108c 3903 error ("No thread selected; can not single step");
c5aa993b 3904
c906108c
SS
3905 /* If current_thread is suspended, tracing it would never return.
3906 */
3907 ret = thread_info (current_thread,
3908 THREAD_BASIC_INFO,
c5aa993b 3909 (thread_info_t) & th_info,
c906108c
SS
3910 &infoCnt);
3911 CHK ("child_resume: can't get thread info", ret);
c5aa993b 3912
c906108c
SS
3913 if (th_info.suspend_count)
3914 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3915 }
3916
3917 vm_read_cache_valid = FALSE;
3918
39f77062
KB
3919 if (signal && PIDGET (inferior_ptid) > 0) /* Do not signal, if attached by MID */
3920 kill (PIDGET (inferior_ptid), target_signal_to_host (signal));
c906108c
SS
3921
3922 if (step)
3923 {
3924 suspend_all_threads (0);
3925
3926 setup_single_step (current_thread, TRUE);
c5aa993b 3927
c906108c
SS
3928 ret = thread_resume (current_thread);
3929 CHK ("thread_resume", ret);
3930 }
c5aa993b 3931
c906108c
SS
3932 ret = task_resume (inferior_task);
3933 if (ret == KERN_FAILURE)
3934 warning ("Task was not suspended");
3935 else
3936 CHK ("Resuming task", ret);
c5aa993b 3937
c906108c 3938 /* HACK HACK This is needed by the multiserver system HACK HACK */
c5aa993b
JM
3939 while ((ret = task_resume (inferior_task)) == KERN_SUCCESS)
3940 /* make sure it really runs */ ;
c906108c
SS
3941 /* HACK HACK This is needed by the multiserver system HACK HACK */
3942}
3943\f
3944#ifdef ATTACH_DETACH
3945
3946/* Start debugging the process with the given task */
3947void
fba45db2 3948task_attach (task_t tid)
c906108c
SS
3949{
3950 kern_return_t ret;
3951 inferior_task = tid;
3952
3953 ret = task_suspend (inferior_task);
c5aa993b 3954 CHK ("task_attach: task_suspend", ret);
c906108c
SS
3955
3956 must_suspend_thread = 0;
3957
3958 setup_notify_port (1);
3959
3960 request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
3961
3962 setup_exception_port ();
c5aa993b 3963
c906108c
SS
3964 emulator_present = have_emulator_p (inferior_task);
3965
3966 attach_flag = 1;
3967}
3968
3969/* Well, we can call error also here and leave the
3970 * target stack inconsistent. Sigh.
3971 * Fix this sometime (the only way to fail here is that
3972 * the task has no threads at all, which is rare, but
3973 * possible; or if the target task has died, which is also
3974 * possible, but unlikely, since it has been suspended.
3975 * (Someone must have killed it))
3976 */
3977void
fba45db2 3978attach_to_thread (void)
c906108c
SS
3979{
3980 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3981 error ("Could not select any threads to attach to");
3982}
3983
fba45db2 3984mid_attach (int mid)
c906108c 3985{
c5aa993b 3986 kern_return_t ret;
c906108c 3987
c5aa993b
JM
3988 ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
3989 CHK ("mid_attach: machid_mach_port", ret);
c906108c 3990
c5aa993b 3991 task_attach (inferior_task);
c906108c 3992
c5aa993b 3993 return mid;
c906108c
SS
3994}
3995
3996/*
3997 * Start debugging the process whose unix process-id is PID.
3998 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
3999 *
4000 * Prevent (possible unwanted) dangerous operations by enabled users
4001 * like "atta 0" or "atta foo" (equal to the previous :-) and
4002 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4003 */
4004static int
fba45db2 4005m3_do_attach (int pid)
c906108c
SS
4006{
4007 kern_return_t ret;
4008
4009 if (pid == 0)
c5aa993b 4010 error ("MID=0, Debugging the master unix server does not compute");
c906108c
SS
4011
4012 /* Foo. This assumes gdb has a unix pid */
c5aa993b 4013 if (pid == getpid ())
c906108c
SS
4014 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4015
4016 if (pid < 0)
4017 {
4018 mid_attach (-(pid));
4019
39f77062
KB
4020 /* inferior_ptid will be NEGATIVE! */
4021 inferior_ptid = pid_to_ptid (pid);
c906108c 4022
39f77062 4023 return PIDGET (inferior_ptid);
c906108c
SS
4024 }
4025
4026 inferior_task = task_by_pid (pid);
c5aa993b
JM
4027 if (!MACH_PORT_VALID (inferior_task))
4028 error ("Cannot map Unix pid %d to Mach task port", pid);
c906108c
SS
4029
4030 task_attach (inferior_task);
4031
39f77062 4032 inferior_ptid = pid_to_ptid (pid);
c906108c 4033
39f77062 4034 return PIDGET (inferior_ptid);
c906108c
SS
4035}
4036
4037/* Attach to process PID, then initialize for debugging it
4038 and wait for the trace-trap that results from attaching. */
4039
4040static void
fba45db2 4041m3_attach (char *args, int from_tty)
c906108c
SS
4042{
4043 char *exec_file;
4044 int pid;
4045
4046 if (!args)
4047 error_no_arg ("process-id to attach");
4048
4049 pid = atoi (args);
4050
c5aa993b 4051 if (pid == getpid ()) /* Trying to masturbate? */
c906108c
SS
4052 error ("I refuse to debug myself!");
4053
4054 if (from_tty)
4055 {
4056 exec_file = (char *) get_exec_file (0);
4057
4058 if (exec_file)
39f77062
KB
4059 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
4060 target_pid_to_str (pid_to_ptid (pid)));
c906108c 4061 else
39f77062
KB
4062 printf_unfiltered ("Attaching to %s\n",
4063 target_pid_to_str (pid_to_ptid (pid)));
c906108c
SS
4064
4065 gdb_flush (gdb_stdout);
4066 }
4067
39f77062
KB
4068 m3_do_attach (pid_to_ptid (pid));
4069 inferior_ptid = pid_to_ptid (pid);
c906108c
SS
4070 push_target (&m3_ops);
4071}
4072\f
4073void
fba45db2 4074deallocate_inferior_ports (void)
c906108c 4075{
c5aa993b 4076 kern_return_t ret;
c906108c 4077 thread_array_t thread_list;
c5aa993b 4078 int thread_count, index;
c906108c
SS
4079
4080 if (!MACH_PORT_VALID (inferior_task))
4081 return;
4082
4083 ret = task_threads (inferior_task, &thread_list, &thread_count);
4084 if (ret != KERN_SUCCESS)
4085 {
4086 warning ("deallocate_inferior_ports: task_threads",
c5aa993b 4087 mach_error_string (ret));
c906108c
SS
4088 return;
4089 }
4090
4091 /* Get rid of send rights to task threads */
4092 for (index = 0; index < thread_count; index++)
4093 {
4094 int rights;
4095 ret = mach_port_get_refs (mach_task_self (),
4096 thread_list[index],
4097 MACH_PORT_RIGHT_SEND,
4098 &rights);
c5aa993b 4099 CHK ("deallocate_inferior_ports: get refs", ret);
c906108c
SS
4100
4101 if (rights > 0)
4102 {
4103 ret = mach_port_mod_refs (mach_task_self (),
4104 thread_list[index],
4105 MACH_PORT_RIGHT_SEND,
4106 -rights);
c5aa993b 4107 CHK ("deallocate_inferior_ports: mod refs", ret);
c906108c
SS
4108 }
4109 }
4110
4111 ret = mach_port_mod_refs (mach_task_self (),
4112 inferior_exception_port,
4113 MACH_PORT_RIGHT_RECEIVE,
4114 -1);
4115 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
4116
4117 ret = mach_port_deallocate (mach_task_self (),
4118 inferior_task);
4119 CHK ("deallocate_task_port: deallocating inferior_task", ret);
4120
4121 current_thread = MACH_PORT_NULL;
c5aa993b 4122 inferior_task = MACH_PORT_NULL;
c906108c
SS
4123}
4124
4125/* Stop debugging the process whose number is PID
4126 and continue it with signal number SIGNAL.
4127 SIGNAL = 0 means just continue it. */
4128
4129static void
fba45db2 4130m3_do_detach (int signal)
c906108c
SS
4131{
4132 kern_return_t ret;
4133
4134 MACH_ERROR_NO_INFERIOR;
4135
4136 if (current_thread != MACH_PORT_NULL)
4137 {
4138 /* Store the gdb's view of the thread we are deselecting
4139 * before we detach.
4140 * @@ I am really not sure if this is ever needeed.
4141 */
4142 target_prepare_to_store ();
4143 target_store_registers (-1);
4144 }
4145
4146 ret = task_set_special_port (inferior_task,
c5aa993b 4147 TASK_EXCEPTION_PORT,
c906108c
SS
4148 inferior_old_exception_port);
4149 CHK ("task_set_special_port", ret);
4150
4151 /* Discard all requested notifications */
4152 setup_notify_port (0);
4153
4154 if (remove_breakpoints ())
4155 warning ("Could not remove breakpoints when detaching");
c5aa993b 4156
39f77062
KB
4157 if (signal && PIDGET (inferior_ptid) > 0)
4158 kill (PIDGET (inferior_ptid), signal);
c5aa993b 4159
c906108c
SS
4160 /* the task might be dead by now */
4161 (void) task_resume (inferior_task);
c5aa993b 4162
c906108c 4163 deallocate_inferior_ports ();
c5aa993b 4164
c906108c
SS
4165 attach_flag = 0;
4166}
4167
4168/* Take a program previously attached to and detaches it.
4169 The program resumes execution and will no longer stop
4170 on signals, etc. We'd better not have left any breakpoints
4171 in the program or it'll die when it hits one. For this
4172 to work, it may be necessary for the process to have been
4173 previously attached. It *might* work if the program was
4174 started via fork. */
4175
4176static void
fba45db2 4177m3_detach (char *args, int from_tty)
c906108c
SS
4178{
4179 int siggnal = 0;
4180
4181 if (from_tty)
4182 {
4183 char *exec_file = get_exec_file (0);
4184 if (exec_file == 0)
4185 exec_file = "";
4186 printf_unfiltered ("Detaching from program: %s %s\n",
39f77062 4187 exec_file, target_pid_to_str (inferior_ptid));
c906108c
SS
4188 gdb_flush (gdb_stdout);
4189 }
4190 if (args)
4191 siggnal = atoi (args);
c5aa993b 4192
c906108c 4193 m3_do_detach (siggnal);
39f77062 4194 inferior_ptid = null_ptid;
c5aa993b 4195 unpush_target (&m3_ops); /* Pop out of handling an inferior */
c906108c
SS
4196}
4197#endif /* ATTACH_DETACH */
4198
4199/* Get ready to modify the registers array. On machines which store
4200 individual registers, this doesn't need to do anything. On machines
4201 which store all the registers in one fell swoop, this makes sure
4202 that registers contains all the registers from the program being
4203 debugged. */
4204
4205static void
fba45db2 4206m3_prepare_to_store (void)
c906108c
SS
4207{
4208#ifdef CHILD_PREPARE_TO_STORE
4209 CHILD_PREPARE_TO_STORE ();
4210#endif
4211}
4212
4213/* Print status information about what we're accessing. */
4214
4215static void
fba45db2 4216m3_files_info (struct target_ops *ignore)
c906108c
SS
4217{
4218 /* FIXME: should print MID and all that crap. */
4219 printf_unfiltered ("\tUsing the running image of %s %s.\n",
39f77062 4220 attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
c906108c
SS
4221}
4222
4223static void
fba45db2 4224m3_open (char *arg, int from_tty)
c906108c
SS
4225{
4226 error ("Use the \"run\" command to start a Unix child process.");
4227}
4228
4229#ifdef DUMP_SYSCALL
c906108c 4230#define STR(x) #x
c906108c 4231
c5aa993b
JM
4232char *bsd1_names[] =
4233{
c906108c
SS
4234 "execve",
4235 "fork",
4236 "take_signal",
4237 "sigreturn",
4238 "getrusage",
4239 "chdir",
4240 "chroot",
4241 "open",
4242 "creat",
4243 "mknod",
4244 "link",
4245 "symlink",
4246 "unlink",
4247 "access",
4248 "stat",
4249 "readlink",
4250 "chmod",
4251 "chown",
4252 "utimes",
4253 "truncate",
4254 "rename",
4255 "mkdir",
4256 "rmdir",
4257 "xutimes",
4258 "mount",
4259 "umount",
4260 "acct",
4261 "setquota",
4262 "write_short",
4263 "write_long",
4264 "send_short",
4265 "send_long",
4266 "sendto_short",
4267 "sendto_long",
4268 "select",
4269 "task_by_pid",
4270 "recvfrom_short",
4271 "recvfrom_long",
4272 "setgroups",
4273 "setrlimit",
4274 "sigvec",
4275 "sigstack",
4276 "settimeofday",
4277 "adjtime",
4278 "setitimer",
4279 "sethostname",
4280 "bind",
4281 "accept",
4282 "connect",
4283 "setsockopt",
4284 "getsockopt",
4285 "getsockname",
4286 "getpeername",
4287 "init_process",
4288 "table_set",
4289 "table_get",
4290 "pioctl",
4291 "emulator_error",
4292 "readwrite",
4293 "share_wakeup",
4294 0,
4295 "maprw_request_it",
4296 "maprw_release_it",
4297 "maprw_remap",
4298 "pid_by_task",
4299};
4300
c5aa993b 4301int bsd1_nnames = sizeof (bsd1_names) / sizeof (bsd1_names[0]);
c906108c 4302
c5aa993b 4303char *
fba45db2 4304name_str (int name, char *buf)
c906108c 4305{
c5aa993b
JM
4306 switch (name)
4307 {
4308 case MACH_MSG_TYPE_BOOLEAN:
4309 return "boolean";
4310 case MACH_MSG_TYPE_INTEGER_16:
4311 return "short";
4312 case MACH_MSG_TYPE_INTEGER_32:
4313 return "long";
4314 case MACH_MSG_TYPE_CHAR:
4315 return "char";
4316 case MACH_MSG_TYPE_BYTE:
4317 return "byte";
4318 case MACH_MSG_TYPE_REAL:
4319 return "real";
4320 case MACH_MSG_TYPE_STRING:
4321 return "string";
4322 default:
4323 sprintf (buf, "%d", name);
4324 return buf;
4325 }
c906108c
SS
4326}
4327
4328char *
fba45db2 4329id_str (int id, char *buf)
c906108c 4330{
c5aa993b
JM
4331 char *p;
4332 if (id >= 101000 && id < 101000 + bsd1_nnames)
4333 {
4334 if (p = bsd1_names[id - 101000])
4335 return p;
4336 }
c906108c
SS
4337 if (id == 102000)
4338 return "psignal_retry";
4339 if (id == 100000)
4340 return "syscall";
c5aa993b 4341 sprintf (buf, "%d", id);
c906108c
SS
4342 return buf;
4343}
4344
fba45db2 4345print_msg (mach_msg_header_t *mp)
c906108c 4346{
c5aa993b
JM
4347 char *fmt_x = "%20s : 0x%08x\n";
4348 char *fmt_d = "%20s : %10d\n";
4349 char *fmt_s = "%20s : %s\n";
4350 char buf[100];
c906108c
SS
4351
4352 puts_filtered ("\n");
4353#define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
c5aa993b
JM
4354 pr (fmt_x, (*mp), msgh_bits);
4355 pr (fmt_d, (*mp), msgh_size);
4356 pr (fmt_x, (*mp), msgh_remote_port);
4357 pr (fmt_x, (*mp), msgh_local_port);
4358 pr (fmt_d, (*mp), msgh_kind);
4359 printf_filtered (fmt_s, STR (msgh_id), id_str (mp->msgh_id, buf));
4360
c906108c 4361 if (debug_level > 1)
c5aa993b
JM
4362 {
4363 char *p, *ep, *dp;
4364 int plen;
4365 p = (char *) mp;
4366 ep = p + mp->msgh_size;
4367 p += sizeof (*mp);
4368 for (; p < ep; p += plen)
4369 {
4370 mach_msg_type_t *tp;
4371 mach_msg_type_long_t *tlp;
4372 int name, size, number;
4373 tp = (mach_msg_type_t *) p;
4374 if (tp->msgt_longform)
4375 {
4376 tlp = (mach_msg_type_long_t *) tp;
4377 name = tlp->msgtl_name;
4378 size = tlp->msgtl_size;
4379 number = tlp->msgtl_number;
4380 plen = sizeof (*tlp);
4381 }
4382 else
4383 {
4384 name = tp->msgt_name;
4385 size = tp->msgt_size;
4386 number = tp->msgt_number;
4387 plen = sizeof (*tp);
4388 }
4389 printf_filtered ("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4390 name_str (name, buf), size, number, tp->msgt_inline,
4391 tp->msgt_longform, tp->msgt_deallocate);
4392 dp = p + plen;
4393 if (tp->msgt_inline)
4394 {
4395 int l;
4396 l = size * number / 8;
4397 l = (l + sizeof (long) - 1) & ~((sizeof (long)) - 1);
4398 plen += l;
4399 print_data (dp, size, number);
4400 }
4401 else
4402 {
4403 plen += sizeof (int *);
4404 }
4405 printf_filtered ("plen=%d\n", plen);
4406 }
c906108c 4407 }
c906108c
SS
4408}
4409
fba45db2 4410print_data (char *p, int size, int number)
c906108c 4411{
c5aa993b
JM
4412 int *ip;
4413 short *sp;
4414 int i;
4415
4416 switch (size)
4417 {
4418 case 8:
4419 for (i = 0; i < number; i++)
4420 {
4421 printf_filtered (" %02x", p[i]);
4422 }
4423 break;
4424 case 16:
4425 sp = (short *) p;
4426 for (i = 0; i < number; i++)
4427 {
4428 printf_filtered (" %04x", sp[i]);
4429 }
4430 break;
4431 case 32:
4432 ip = (int *) p;
4433 for (i = 0; i < number; i++)
4434 {
4435 printf_filtered (" %08x", ip[i]);
4436 }
4437 break;
c906108c 4438 }
c5aa993b 4439 puts_filtered ("\n");
c906108c 4440}
c5aa993b 4441#endif /* DUMP_SYSCALL */
c906108c
SS
4442
4443static void
fba45db2 4444m3_stop (void)
c906108c
SS
4445{
4446 error ("to_stop target function not implemented");
4447}
4448
4449static char *
fba45db2 4450m3_pid_to_exec_file (int pid)
c906108c
SS
4451{
4452 error ("to_pid_to_exec_file target function not implemented");
c5aa993b 4453 return NULL; /* To keep all compilers happy. */
c906108c
SS
4454}
4455
4456static void
fba45db2 4457init_m3_ops (void)
c906108c
SS
4458{
4459 m3_ops.to_shortname = "mach";
4460 m3_ops.to_longname = "Mach child process";
4461 m3_ops.to_doc = "Mach child process (started by the \"run\" command).";
4462 m3_ops.to_open = m3_open;
4463 m3_ops.to_attach = m3_attach;
4464 m3_ops.to_detach = m3_detach;
4465 m3_ops.to_resume = m3_resume;
39f77062 4466 m3_ops.to_wait = mach_really_wait;
c906108c
SS
4467 m3_ops.to_fetch_registers = fetch_inferior_registers;
4468 m3_ops.to_store_registers = store_inferior_registers;
4469 m3_ops.to_prepare_to_store = m3_prepare_to_store;
4470 m3_ops.to_xfer_memory = m3_xfer_memory;
4471 m3_ops.to_files_info = m3_files_info;
4472 m3_ops.to_insert_breakpoint = memory_insert_breakpoint;
4473 m3_ops.to_remove_breakpoint = memory_remove_breakpoint;
4474 m3_ops.to_terminal_init = terminal_init_inferior;
4475 m3_ops.to_terminal_inferior = terminal_inferior;
4476 m3_ops.to_terminal_ours_for_output = terminal_ours_for_output;
4477 m3_ops.to_terminal_ours = terminal_ours;
4478 m3_ops.to_terminal_info = child_terminal_info;
4479 m3_ops.to_kill = m3_kill_inferior;
4480 m3_ops.to_create_inferior = m3_create_inferior;
4481 m3_ops.to_mourn_inferior = m3_mourn_inferior;
4482 m3_ops.to_can_run = m3_can_run;
4483 m3_ops.to_stop = m3_stop;
4484 m3_ops.to_pid_to_exec_file = m3_pid_to_exec_file;
4485 m3_ops.to_stratum = process_stratum;
4486 m3_ops.to_has_all_memory = 1;
4487 m3_ops.to_has_memory = 1;
4488 m3_ops.to_has_stack = 1;
4489 m3_ops.to_has_registers = 1;
4490 m3_ops.to_has_execution = 1;
4491 m3_ops.to_magic = OPS_MAGIC;
4492}
4493
4494void
fba45db2 4495_initialize_m3_nat (void)
c906108c
SS
4496{
4497 kern_return_t ret;
4498
4499 init_m3_ops ();
4500 add_target (&m3_ops);
4501
c5aa993b
JM
4502 ret = mach_port_allocate (mach_task_self (),
4503 MACH_PORT_RIGHT_PORT_SET,
4504 &inferior_wait_port_set);
c906108c 4505 if (ret != KERN_SUCCESS)
8e65ff28
AC
4506 internal_error (__FILE__, __LINE__,
4507 "initial port set %s", mach_error_string (ret));
c906108c
SS
4508
4509 /* mach_really_wait now waits for this */
4510 currently_waiting_for = inferior_wait_port_set;
4511
c5aa993b 4512 ret = netname_look_up (name_server_port, hostname, "MachID", &mid_server);
c906108c
SS
4513 if (ret != KERN_SUCCESS)
4514 {
4515 mid_server = MACH_PORT_NULL;
c5aa993b 4516
c906108c 4517 warning ("initialize machid: netname_lookup_up(MachID) : %s",
c5aa993b 4518 mach_error_string (ret));
c906108c
SS
4519 warning ("Some (most?) features disabled...");
4520 }
c5aa993b
JM
4521
4522 mid_auth = mach_privileged_host_port ();
c906108c 4523 if (mid_auth == MACH_PORT_NULL)
c5aa993b
JM
4524 mid_auth = mach_task_self ();
4525
c906108c
SS
4526 obstack_init (port_chain_obstack);
4527
c5aa993b 4528 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
4529 MACH_PORT_RIGHT_RECEIVE,
4530 &thread_exception_port);
4531 CHK ("Creating thread_exception_port for single stepping", ret);
c5aa993b 4532
c906108c
SS
4533 ret = mach_port_insert_right (mach_task_self (),
4534 thread_exception_port,
4535 thread_exception_port,
4536 MACH_MSG_TYPE_MAKE_SEND);
4537 CHK ("Inserting send right to thread_exception_port", ret);
4538
4539 /* Allocate message port */
4540 ret = mach_port_allocate (mach_task_self (),
4541 MACH_PORT_RIGHT_RECEIVE,
4542 &our_message_port);
4543 if (ret != KERN_SUCCESS)
4544 warning ("Creating message port %s", mach_error_string (ret));
4545 else
4546 {
c5aa993b
JM
4547 char buf[MAX_NAME_LEN];
4548 ret = mach_port_move_member (mach_task_self (),
4549 our_message_port,
4550 inferior_wait_port_set);
c906108c
SS
4551 if (ret != KERN_SUCCESS)
4552 warning ("message move member %s", mach_error_string (ret));
4553
4554
4555 /* @@@@ No way to change message port name currently */
4556 /* Foo. This assumes gdb has a unix pid */
4557 sprintf (buf, "gdb-%d", getpid ());
4558 gdb_register_port (buf, our_message_port);
4559 }
c5aa993b 4560
c906108c
SS
4561 /* Heap for thread commands */
4562 obstack_init (cproc_obstack);
4563
4564 add_mach_specific_commands ();
4565}
This page took 0.363516 seconds and 4 git commands to generate.