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