* target.h: Add enum target_waitkind, enum target_signal, and
[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   /* One trap to exec the shell, one to exec the program being debugged.  */
1148   intercept_exec_calls (2);
1149 }
1150
1151 setup_exception_port ()
1152 {
1153   kern_return_t ret;
1154
1155   ret = mach_port_allocate (mach_task_self(), 
1156                             MACH_PORT_RIGHT_RECEIVE,
1157                             &inferior_exception_port);
1158   CHK("mach_port_allocate",ret);
1159
1160   /* add send right */
1161   ret = mach_port_insert_right (mach_task_self (),
1162                                 inferior_exception_port,
1163                                 inferior_exception_port,
1164                                 MACH_MSG_TYPE_MAKE_SEND);
1165   CHK("mach_port_insert_right",ret);
1166
1167   ret = mach_port_move_member (mach_task_self(), 
1168                                inferior_exception_port,
1169                                inferior_wait_port_set);
1170   CHK("mach_port_move_member",ret);
1171
1172   ret = task_get_special_port (inferior_task, 
1173                                TASK_EXCEPTION_PORT,
1174                                &inferior_old_exception_port);
1175   CHK ("task_get_special_port(old exc)",ret);
1176
1177   ret = task_set_special_port (inferior_task,
1178                                TASK_EXCEPTION_PORT, 
1179                                inferior_exception_port);
1180   CHK("task_set_special_port",ret);
1181
1182   ret = mach_port_deallocate (mach_task_self (),
1183                               inferior_exception_port);
1184   CHK("mack_port_deallocate",ret);
1185
1186 #if 0
1187   /* When notify appears, the inferior_task's exception
1188    * port has been destroyed.
1189    *
1190    * Not used, since the dead_name_notification already
1191    * appears when task dies.
1192    *
1193    */
1194   request_notify (inferior_exception_port,
1195                   MACH_NOTIFY_NO_SENDERS,
1196                   MACH_TYPE_EXCEPTION_PORT);
1197 #endif
1198 }
1199
1200 /* Nonzero if gdb is waiting for a message */
1201 int mach_really_waiting;
1202
1203 /* Wait for the inferior to stop for some reason.
1204    - Loop on notifications until inferior_task dies.
1205    - Loop on exceptions until stopped_in_exception comes true.
1206      (e.g. we receive a single step trace trap)
1207    - a message arrives to gdb's message port
1208
1209    There is no other way to exit this loop.
1210
1211    Returns the inferior_pid for rest of gdb.
1212    Side effects: Set *OURSTATUS.  */
1213 int
1214 mach_really_wait (w)
1215      struct target_waitstatus *ourstatus;
1216 {
1217   int pid;
1218   kern_return_t ret;
1219   int w;
1220
1221   struct msg {
1222     mach_msg_header_t    header;
1223     mach_msg_type_t foo;
1224     int             data[8000];
1225   } in_msg, out_msg;
1226
1227   /* Either notify (death), exception or message can stop the inferior */
1228   stopped_in_exception = FALSE;
1229
1230   while (1)
1231     {
1232       QUIT;
1233
1234       stop_exception = stop_code = stop_subcode = -1;
1235       stop_thread = MACH_PORT_NULL;
1236
1237       mach_really_waiting = 1;
1238       ret = mach_msg (&in_msg.header,           /* header */
1239                       MACH_RCV_MSG,             /* options */
1240                       0,                        /* send size */
1241                       sizeof (struct msg),      /* receive size */
1242                       currently_waiting_for,    /* receive name */
1243                       MACH_MSG_TIMEOUT_NONE,
1244                       MACH_PORT_NULL);
1245       mach_really_waiting = 0;
1246       CHK("mach_msg (receive)", ret);
1247
1248       /* Check if we received a notify of the childs' death */
1249       if (notify_server (&in_msg.header, &out_msg.header))
1250         {
1251           /* If inferior_task is null then the inferior has
1252              gone away and we want to return to command level.
1253              Otherwise it was just an informative message and we
1254              need to look to see if there are any more. */
1255           if (inferior_task != MACH_PORT_NULL)
1256             continue;
1257           else
1258             {
1259               /* Collect Unix exit status for gdb */
1260
1261               wait3(&w, WNOHANG, 0);
1262
1263               /* This mess is here to check that the rest of
1264                * gdb knows that the inferior died. It also
1265                * tries to hack around the fact that Mach 3.0 (mk69)
1266                * unix server (ux28) does not always know what
1267                * has happened to it's children when mach-magic
1268                * is applied on them.
1269                */
1270               if ((!WIFEXITED(w) && WIFSTOPPED(w))         ||
1271                   (WIFEXITED(w)  && WEXITSTATUS(w) > 0377))
1272                 {
1273                   WSETEXIT(w, 0);
1274                   warning ("Using exit value 0 for terminated task");
1275                 }
1276               else if (!WIFEXITED(w))
1277                 {
1278                   int sig = WTERMSIG(w);
1279
1280                   /* Signals cause problems. Warn the user. */
1281                   if (sig != SIGKILL) /* Bad luck if garbage matches this */
1282                     warning ("The terminating signal stuff may be nonsense");
1283                   else if (sig > NSIG)
1284                     {
1285                       WSETEXIT(w, 0);
1286                       warning ("Using exit value 0 for terminated task");
1287                     }
1288                 }
1289               store_waitstatus (ourstatus, w);
1290               return inferior_pid;
1291             }
1292         }
1293
1294       /* Hmm. Check for exception, as it was not a notification.
1295          exc_server() does an upcall to catch_exception_raise()
1296          if this rpc is an exception. Further actions are decided
1297          there.
1298        */
1299       if (! exc_server (&in_msg.header, &out_msg.header))
1300         {
1301
1302           /* Not an exception, check for message.
1303            *
1304            * Messages don't come from the inferior, or if they
1305            * do they better be asynchronous or it will hang.
1306            */
1307           if (gdb_message_server (&in_msg.header))
1308             continue;
1309
1310           error ("Unrecognized message received in mach_really_wait");
1311         }
1312
1313       /* Send the reply of the exception rpc to the suspended task */
1314       ret = mach_msg_send (&out_msg.header);
1315       CHK ("mach_msg_send (exc reply)", ret);
1316       
1317       if (stopped_in_exception)
1318         {
1319           /* Get unix state. May be changed in mach3_exception_actions() */
1320           wait3(&w, WNOHANG, 0);
1321
1322           mach3_exception_actions (&w, FALSE, "Task");
1323
1324           store_waitstatus (ourstatus, w);
1325           return inferior_pid;
1326         }
1327     }
1328 }
1329
1330 /* Called by macro DO_QUIT() in utils.c(quit).
1331  * This is called just before calling error() to return to command level
1332  */
1333 void
1334 mach3_quit ()
1335 {
1336   int mid;
1337   kern_return_t ret;
1338   
1339   if (mach_really_waiting)
1340     {
1341       ret = task_suspend (inferior_task);
1342       
1343       if (ret != KERN_SUCCESS)
1344         {
1345           warning ("Could not suspend task for interrupt: %s",
1346                    mach_error_string (ret));
1347           mach_really_waiting = 0;
1348           return;
1349         }
1350     }
1351
1352   must_suspend_thread = 0;
1353   mach_really_waiting = 0;
1354
1355   mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1356   if (mid == -1)
1357     {
1358       warning ("Selecting first existing kernel thread");
1359       mid = 0;
1360     }
1361
1362   current_thread = MACH_PORT_NULL; /* Force setup */
1363   select_thread (inferior_task, mid, 1);
1364
1365   return;
1366 }
1367
1368 /* If ^C is typed when we are waiting for a message
1369  * and your Unix server is able to notice that we 
1370  * should quit now.
1371  *
1372  * Called by REQUEST_QUIT() from utils.c(request_quit)
1373  */
1374 void
1375 mach3_request_quit ()
1376 {
1377   if (mach_really_waiting)
1378     immediate_quit = 1;
1379 }      
1380
1381 /*
1382  * Gdb message server.
1383  * Currently implemented is the STOP message, that causes
1384  * gdb to return to the command level like ^C had been typed from terminal.
1385  */
1386 int
1387 gdb_message_server (InP)
1388      mach_msg_header_t *InP;
1389 {
1390   kern_return_t ret;
1391   int mid;
1392
1393   if (InP->msgh_local_port == our_message_port)
1394     {
1395       /* A message coming to our_message_port. Check validity */
1396       switch (InP->msgh_id) {
1397
1398       case GDB_MESSAGE_ID_STOP:
1399         ret = task_suspend (inferior_task);
1400         if (ret != KERN_SUCCESS)
1401           warning ("Could not suspend task for stop message: %s",
1402                    mach_error_string (ret));
1403
1404         /* QUIT in mach_really_wait() loop. */
1405         request_quit (0);
1406         break;
1407
1408       default:
1409         warning ("Invalid message id %d received, ignored.",
1410                  InP->msgh_id);
1411         break;
1412       }
1413
1414       return 1;
1415     }
1416
1417   /* Message not handled by this server */
1418   return 0;
1419 }
1420
1421 /* NOTE: This is not an RPC call. It is a simpleroutine.
1422  *
1423  * This is not called from this gdb code.
1424  *
1425  * It may be called by another debugger to cause this
1426  * debugger to enter command level:
1427  *
1428  *            (gdb) set stop_inferior_gdb ()
1429  *            (gdb) continue
1430  *
1431  * External program "stop-gdb" implements this also.
1432  */
1433 void
1434 stop_inferior_gdb ()
1435 {
1436   kern_return_t ret;
1437
1438   /* Code generated by mig, with minor cleanups :-)
1439    *
1440    * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1441    */
1442
1443   typedef struct {
1444     mach_msg_header_t Head;
1445   } Request;
1446
1447   Request Mess;
1448
1449   register Request *InP = &Mess;
1450
1451   InP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0);
1452
1453   /* msgh_size passed as argument */
1454   InP->Head.msgh_remote_port = our_message_port;
1455   InP->Head.msgh_local_port  = MACH_PORT_NULL;
1456   InP->Head.msgh_seqno       = 0;
1457   InP->Head.msgh_id          = GDB_MESSAGE_ID_STOP;
1458
1459   ret = mach_msg (&InP->Head,
1460                   MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
1461                   sizeof(Request),
1462                   0,
1463                   MACH_PORT_NULL,
1464                   MACH_MSG_TIMEOUT_NONE,
1465                   MACH_PORT_NULL);
1466 }
1467
1468 #ifdef THREAD_ALLOWED_TO_BREAK
1469 /*
1470  * Return 1 if the MID specifies the thread that caused the
1471  * last exception.
1472  *  Since catch_exception_raise() selects the thread causing
1473  * the last exception to current_thread, we just check that
1474  * it is selected and the last exception was a breakpoint.
1475  */
1476 int
1477 mach_thread_for_breakpoint (mid)
1478      int mid;
1479 {
1480   int cmid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1481
1482   if (mid < 0)
1483     {
1484       mid = map_slot_to_mid (-(mid+1), 0, 0);
1485       if (mid < 0)
1486         return 0;               /* Don't stop, no such slot */
1487     }
1488
1489   if (! mid || cmid == -1)
1490     return 1;   /* stop */
1491
1492   return cmid == mid && stop_exception == EXC_BREAKPOINT;
1493 }
1494 #endif /* THREAD_ALLOWED_TO_BREAK */
1495
1496 #ifdef THREAD_PARSE_ID
1497 /*
1498  * Map a thread id string (MID or a @SLOTNUMBER)
1499  * to a thread-id.
1500  *
1501  *   0  matches all threads.
1502  *   Otherwise the meaning is defined only in this file.
1503  *   (mach_thread_for_breakpoint uses it)
1504  *
1505  * @@ This allows non-existent MIDs to be specified.
1506  *    It now also allows non-existent slots to be
1507  *    specified. (Slot numbers stored are negative,
1508  *    and the magnitude is one greater than the actual
1509  *    slot index. (Since 0 is reserved))
1510  */
1511 int
1512 mach_thread_parse_id (arg)
1513      char *arg;
1514 {
1515   int mid;
1516   if (arg == 0)
1517     error ("thread id excpected");
1518   mid = parse_thread_id (arg, 0, 1);
1519
1520   return mid;
1521 }
1522 #endif /* THREAD_PARSE_ID */
1523
1524 #ifdef THREAD_OUTPUT_ID
1525 char *
1526 mach_thread_output_id (mid)
1527      int mid;
1528 {
1529   static char foobar [20];
1530
1531   if (mid > 0)
1532     sprintf (foobar, "mid %d", mid);
1533   else if (mid < 0)
1534     sprintf (foobar, "@%d", -(mid+1));
1535   else
1536     sprintf (foobar, "*any thread*");
1537
1538   return foobar;
1539 }
1540 #endif /* THREAD_OUTPUT_ID */
1541
1542 /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
1543  *
1544  * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1545  *
1546  *  if SELECT_IT is nonzero, reselect the thread that was active when
1547  *  we stopped at a breakpoint.
1548  *
1549  */
1550
1551 mach3_prepare_to_proceed (select_it)
1552      int select_it;
1553 {
1554   if (stop_thread &&
1555       stop_thread != current_thread &&
1556       stop_exception == EXC_BREAKPOINT)
1557     {
1558       int mid;
1559
1560       if (! select_it)
1561         return 1;
1562
1563       mid = switch_to_thread (stop_thread);
1564
1565       return 1;
1566     }
1567
1568   return 0;
1569 }
1570
1571 /* this stuff here is an upcall via libmach/excServer.c 
1572    and mach_really_wait which does the actual upcall.
1573
1574    The code will pass the exception to the inferior if:
1575
1576      - The task that signaled is not the inferior task
1577        (e.g. when debugging another debugger)
1578
1579      - The user has explicitely requested to pass on the exceptions.
1580        (e.g to the default unix exception handler, which maps
1581         exceptions to signals, or the user has her own exception handler)
1582
1583      - If the thread that signaled is being single-stepped and it
1584        has set it's own exception port and the exception is not
1585        EXC_BREAKPOINT. (Maybe this is not desirable?)
1586  */
1587
1588 kern_return_t
1589 catch_exception_raise (port, thread, task, exception, code, subcode)
1590      mach_port_t port;
1591      thread_t thread;
1592      task_t task;
1593      int exception, code, subcode;
1594 {
1595   kern_return_t ret;
1596   boolean_t signal_thread;
1597   int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
1598
1599   if (! MACH_PORT_VALID (thread))
1600     {
1601       /* If the exception was sent and thread dies before we
1602          receive it, THREAD will be MACH_PORT_DEAD
1603        */
1604
1605       current_thread = thread = MACH_PORT_NULL;
1606       error ("Received exception from nonexistent thread");
1607     }
1608
1609   /* Check if the task died in transit.
1610    * @@ Isn't the thread also invalid in such case?
1611    */
1612   if (! MACH_PORT_VALID (task))
1613     {
1614       current_thread = thread = MACH_PORT_NULL;
1615       error ("Received exception from nonexistent task");
1616     }
1617
1618   if (exception < 0 || exception > MAX_EXCEPTION)
1619     fatal ("catch_exception_raise: unknown exception code %d thread %d",
1620            exception,
1621            mid);
1622
1623   if (! MACH_PORT_VALID (inferior_task))
1624     error ("got an exception, but inferior_task is null or dead");
1625   
1626   stop_exception = exception;
1627   stop_code      = code;
1628   stop_subcode   = subcode;  
1629   stop_thread    = thread;
1630   
1631   signal_thread = exception != EXC_BREAKPOINT       &&
1632                   port == singlestepped_thread_port &&
1633                   MACH_PORT_VALID (thread_saved_exception_port);
1634
1635   /* If it was not our inferior or if we want to forward
1636    * the exception to the inferior's handler, do it here
1637    *
1638    * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1639    */
1640   if (task != inferior_task ||
1641       signal_thread         ||
1642       exception_map [exception].forward)
1643     {
1644       mach_port_t eport = inferior_old_exception_port;
1645
1646       if (signal_thread)
1647         {
1648           /*
1649             GDB now forwards the exeption to thread's original handler,
1650             since the user propably knows what he is doing.
1651             Give a message, though.
1652            */
1653
1654           mach3_exception_actions ((WAITTYPE *)NULL, TRUE, "Thread");
1655           eport = thread_saved_exception_port;
1656         }
1657
1658       /* Send the exception to the original handler */
1659       ret = exception_raise (eport,
1660                              thread, 
1661                              task,
1662                              exception,
1663                              code,
1664                              subcode);
1665
1666       (void) mach_port_deallocate (mach_task_self (), task);
1667       (void) mach_port_deallocate (mach_task_self (), thread);
1668
1669       /* If we come here, we don't want to trace any more, since we
1670        * will never stop for tracing anyway.
1671        */
1672       discard_single_step (thread);
1673
1674       /* Do not stop the inferior */
1675       return ret;
1676     }
1677   
1678   /* Now gdb handles the exception */
1679   stopped_in_exception = TRUE;
1680
1681   ret = task_suspend (task);
1682   CHK ("Error suspending inferior after exception", ret);
1683
1684   must_suspend_thread = 0;
1685
1686   if (current_thread != thread)
1687     {
1688       if (MACH_PORT_VALID (singlestepped_thread_port))
1689         /* Cleanup discards single stepping */
1690         error ("Exception from thread %d while singlestepping thread %d",
1691                mid,
1692                map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
1693       
1694       /* Then select the thread that caused the exception */
1695       if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
1696         error ("Could not select thread %d causing exception", mid);
1697       else
1698         warning ("Gdb selected thread %d", mid);
1699     }
1700
1701   /* If we receive an exception that is not breakpoint
1702    * exception, we interrupt the single step and return to
1703    * debugger. Trace condition is cleared.
1704    */
1705   if (MACH_PORT_VALID (singlestepped_thread_port))
1706     {
1707       if (stop_exception != EXC_BREAKPOINT)
1708         warning ("Single step interrupted by exception");
1709       else if (port == singlestepped_thread_port)
1710         {
1711           /* Single step exception occurred, remove trace bit
1712            * and return to gdb.
1713            */
1714           if (! MACH_PORT_VALID (current_thread))
1715             error ("Single stepped thread is not valid");
1716         
1717           /* Resume threads, but leave the task suspended */
1718           resume_all_threads (0);
1719         }
1720       else
1721         warning ("Breakpoint while single stepping?");
1722
1723       discard_single_step (current_thread);
1724     }
1725   
1726   (void) mach_port_deallocate (mach_task_self (), task);
1727   (void) mach_port_deallocate (mach_task_self (), thread);
1728
1729   return KERN_SUCCESS;
1730 }
1731 \f
1732 int
1733 port_valid (port, mask)
1734   mach_port_t port;
1735   int         mask;
1736 {
1737   kern_return_t ret;
1738   mach_port_type_t type;
1739
1740   ret = mach_port_type (mach_task_self (),
1741                         port,
1742                         &type);
1743   if (ret != KERN_SUCCESS || (type & mask) != mask)
1744     return 0;
1745   return 1;
1746 }
1747 \f
1748 /* @@ No vm read cache implemented yet */
1749 boolean_t vm_read_cache_valid = FALSE;
1750
1751 /*
1752  * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1753  * in gdb's address space.
1754  *
1755  * Return 0 on failure; number of bytes read otherwise.
1756  */
1757 int
1758 mach3_read_inferior (addr, myaddr, length)
1759      CORE_ADDR addr;
1760      char *myaddr;
1761      int length;
1762 {
1763   kern_return_t ret;
1764   vm_address_t low_address       = (vm_address_t) trunc_page (addr);
1765   vm_size_t    aligned_length = 
1766                         (vm_size_t) round_page (addr+length) - low_address;
1767   pointer_t    copied_memory;
1768   int          copy_count;
1769
1770   /* Get memory from inferior with page aligned addresses */
1771   ret = vm_read (inferior_task,
1772                  low_address,
1773                  aligned_length,
1774                  &copied_memory,
1775                  &copy_count);
1776   if (ret != KERN_SUCCESS)
1777     {
1778       /* the problem is that the inferior might be killed for whatever reason
1779        * before we go to mach_really_wait. This is one place that ought to
1780        * catch many of those errors.
1781        * @@ A better fix would be to make all external events to GDB
1782        * to arrive via a SINGLE port set. (Including user input!)
1783        */
1784
1785       if (! port_valid (inferior_task, MACH_PORT_TYPE_SEND))
1786         {
1787           kill_inferior ();
1788           error ("Inferior killed (task port invalid)");
1789         }
1790       else
1791         {
1792 #ifdef OSF
1793           extern int errno;
1794           /* valprint.c gives nicer format if this does not
1795              screw it. Eamonn seems to like this, so I enable
1796              it if OSF is defined...
1797            */
1798           warning ("[read inferior %x failed: %s]",
1799                    addr, mach_error_string (ret));
1800           errno = 0;
1801 #endif
1802           return 0;
1803         }
1804     }
1805
1806   memcpy (myaddr, (char *)addr - low_address + copied_memory, length);
1807
1808   ret = vm_deallocate (mach_task_self (),
1809                        copied_memory,
1810                        copy_count);
1811   CHK("mach3_read_inferior vm_deallocate failed", ret);
1812
1813   return length;
1814 }
1815
1816 #ifdef __STDC__
1817 #define CHK_GOTO_OUT(str,ret) \
1818   do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
1819 #else
1820 #define CHK_GOTO_OUT(str,ret) \
1821   do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
1822 #endif
1823
1824 struct vm_region_list {
1825   struct vm_region_list *next;
1826   vm_prot_t     protection;
1827   vm_address_t  start;
1828   vm_size_t     length;
1829 };
1830
1831 struct obstack  region_obstack;
1832
1833 /*
1834  * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1835  * in gdb's address space.
1836  */
1837 int
1838 mach3_write_inferior (addr, myaddr, length)
1839      CORE_ADDR addr;
1840      char *myaddr;
1841      int length;
1842 {
1843   kern_return_t ret;
1844   vm_address_t low_address       = (vm_address_t) trunc_page (addr);
1845   vm_size_t    aligned_length = 
1846                         (vm_size_t) round_page (addr+length) - low_address;
1847   pointer_t    copied_memory;
1848   int          copy_count;
1849   int          deallocate = 0;
1850
1851   char         *errstr = "Bug in mach3_write_inferior";
1852
1853   struct vm_region_list *region_element;
1854   struct vm_region_list *region_head = (struct vm_region_list *)NULL;
1855
1856   /* Get memory from inferior with page aligned addresses */
1857   ret = vm_read (inferior_task,
1858                  low_address,
1859                  aligned_length,
1860                  &copied_memory,
1861                  &copy_count);
1862   CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
1863
1864   deallocate++;
1865
1866   memcpy ((char *)addr - low_address + copied_memory, myaddr, length);
1867
1868   obstack_init (&region_obstack);
1869
1870   /* Do writes atomically.
1871    * First check for holes and unwritable memory.
1872    */
1873   {
1874     vm_size_t    remaining_length  = aligned_length;
1875     vm_address_t region_address    = low_address;
1876
1877     struct vm_region_list *scan;
1878
1879     while(region_address < low_address + aligned_length)
1880       {
1881         vm_prot_t protection;
1882         vm_prot_t max_protection;
1883         vm_inherit_t inheritance;
1884         boolean_t shared;
1885         mach_port_t object_name;
1886         vm_offset_t offset;
1887         vm_size_t   region_length = remaining_length;
1888         vm_address_t old_address  = region_address;
1889     
1890         ret = vm_region (inferior_task,
1891                          &region_address,
1892                          &region_length,
1893                          &protection,
1894                          &max_protection,
1895                          &inheritance,
1896                          &shared,
1897                          &object_name,
1898                          &offset);
1899         CHK_GOTO_OUT ("vm_region failed", ret);
1900
1901         /* Check for holes in memory */
1902         if (old_address != region_address)
1903           {
1904             warning ("No memory at 0x%x. Nothing written",
1905                      old_address);
1906             ret = KERN_SUCCESS;
1907             length = 0;
1908             goto out;
1909           }
1910
1911         if (!(max_protection & VM_PROT_WRITE))
1912           {
1913             warning ("Memory at address 0x%x is unwritable. Nothing written",
1914                      old_address);
1915             ret = KERN_SUCCESS;
1916             length = 0;
1917             goto out;
1918           }
1919
1920         /* Chain the regions for later use */
1921         region_element = 
1922           (struct vm_region_list *)
1923             obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
1924     
1925         region_element->protection = protection;
1926         region_element->start      = region_address;
1927         region_element->length     = region_length;
1928
1929         /* Chain the regions along with protections */
1930         region_element->next = region_head;
1931         region_head          = region_element;
1932         
1933         region_address += region_length;
1934         remaining_length = remaining_length - region_length;
1935       }
1936
1937     /* If things fail after this, we give up.
1938      * Somebody is messing up inferior_task's mappings.
1939      */
1940     
1941     /* Enable writes to the chained vm regions */
1942     for (scan = region_head; scan; scan = scan->next)
1943       {
1944         boolean_t protection_changed = FALSE;
1945         
1946         if (!(scan->protection & VM_PROT_WRITE))
1947           {
1948             ret = vm_protect (inferior_task,
1949                               scan->start,
1950                               scan->length,
1951                               FALSE,
1952                               scan->protection | VM_PROT_WRITE);
1953             CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1954           }
1955       }
1956
1957     ret = vm_write (inferior_task,
1958                     low_address,
1959                     copied_memory,
1960                     aligned_length);
1961     CHK_GOTO_OUT ("vm_write failed", ret);
1962         
1963     /* Set up the original region protections, if they were changed */
1964     for (scan = region_head; scan; scan = scan->next)
1965       {
1966         boolean_t protection_changed = FALSE;
1967         
1968         if (!(scan->protection & VM_PROT_WRITE))
1969           {
1970             ret = vm_protect (inferior_task,
1971                               scan->start,
1972                               scan->length,
1973                               FALSE,
1974                               scan->protection);
1975             CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1976           }
1977       }
1978   }
1979
1980  out:
1981   if (deallocate)
1982     {
1983       obstack_free (&region_obstack, 0);
1984       
1985       (void) vm_deallocate (mach_task_self (),
1986                             copied_memory,
1987                             copy_count);
1988     }
1989
1990   if (ret != KERN_SUCCESS)
1991     {
1992       warning ("%s %s", errstr, mach_error_string (ret));
1993       return 0;
1994     }
1995
1996   return length;
1997 }
1998
1999 /* Return 0 on failure, number of bytes handled otherwise.  */
2000 static int
2001 m3_xfer_memory (memaddr, myaddr, len, write, target)
2002      CORE_ADDR memaddr;
2003      char *myaddr;
2004      int len;
2005      int write;
2006      struct target_ops *target; /* IGNORED */
2007 {
2008   int result;
2009
2010   if (write)
2011     result = mach3_write_inferior (memaddr, myaddr, len);
2012   else
2013     result = mach3_read_inferior  (memaddr, myaddr, len);
2014
2015   return result;
2016 }
2017
2018 \f
2019 static char *
2020 translate_state(state)
2021 int     state;
2022 {
2023   switch (state) {
2024   case TH_STATE_RUNNING:        return("R");
2025   case TH_STATE_STOPPED:        return("S");
2026   case TH_STATE_WAITING:        return("W");
2027   case TH_STATE_UNINTERRUPTIBLE: return("U");
2028   case TH_STATE_HALTED:         return("H");
2029   default:                      return("?");
2030   }
2031 }
2032
2033 static char *
2034 translate_cstate (state)
2035      int state;
2036 {
2037   switch (state)
2038     {
2039     case CPROC_RUNNING: return "R";
2040     case CPROC_SWITCHING: return "S";
2041     case CPROC_BLOCKED: return "B";
2042     case CPROC_CONDWAIT: return "C";
2043     case CPROC_CONDWAIT|CPROC_SWITCHING: return "CS";
2044     default: return "?";
2045     }
2046 }
2047
2048 /* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2049
2050 mach_port_t           /* no mach_port_name_t found in include files. */
2051 map_inferior_port_name (inferior_name, type)
2052      mach_port_t inferior_name;
2053      mach_msg_type_name_t type;
2054 {
2055   kern_return_t        ret;
2056   mach_msg_type_name_t acquired;
2057   mach_port_t          iport;
2058   
2059   ret = mach_port_extract_right (inferior_task,
2060                                  inferior_name,
2061                                  type,
2062                                  &iport,
2063                                  &acquired);
2064   CHK("mach_port_extract_right (map_inferior_port_name)", ret);
2065
2066   if (acquired != MACH_MSG_TYPE_PORT_SEND)
2067     error("Incorrect right extracted, (map_inferior_port_name)");
2068
2069   ret = mach_port_deallocate (mach_task_self (),
2070                               iport);
2071   CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
2072
2073   return iport;
2074 }
2075
2076 /*
2077  * Naming convention:
2078  *  Always return user defined name if found.
2079  *  _K == A kernel thread with no matching CPROC
2080  *  _C == A cproc with no current cthread
2081  *  _t == A cthread with no user defined name
2082  *
2083  * The digits that follow the _names are the SLOT number of the
2084  * kernel thread if there is such a thing, otherwise just a negation
2085  * of the sequential number of such cprocs.
2086  */
2087
2088 static char buf[7];
2089
2090 static char *
2091 get_thread_name (one_cproc, id)
2092      gdb_thread_t one_cproc;
2093      int id;
2094 {
2095   if (one_cproc)
2096     if (one_cproc->cthread == NULL)
2097       {
2098         /* cproc not mapped to any cthread */
2099         sprintf(buf, "_C%d", id);
2100       }
2101     else if (! one_cproc->cthread->name)
2102       {
2103         /* cproc and cthread, but no name */
2104         sprintf(buf, "_t%d", id);
2105       }
2106     else
2107       return (one_cproc->cthread->name);
2108   else
2109     {
2110       if (id < 0)
2111         warning ("Inconsistency in thread name id %d", id);
2112
2113       /* Kernel thread without cproc */
2114       sprintf(buf, "_K%d", id);
2115     }
2116
2117   return buf;
2118 }
2119
2120 int
2121 fetch_thread_info (task, mthreads_out)
2122      mach_port_t        task;
2123      gdb_thread_t       *mthreads_out;  /* out */
2124 {
2125   kern_return_t  ret;
2126   thread_array_t th_table;
2127   int            th_count;
2128   gdb_thread_t mthreads = NULL;
2129   int            index;
2130
2131   ret = task_threads (task, &th_table, &th_count);
2132   if (ret != KERN_SUCCESS)
2133     {
2134       warning ("Error getting inferior's thread list:%s",
2135                mach_error_string(ret));
2136       kill_inferior ();
2137       return -1;
2138     }
2139   
2140   mthreads = (gdb_thread_t)
2141                 obstack_alloc
2142                   (cproc_obstack,
2143                    th_count * sizeof (struct gdb_thread));
2144
2145   for (index = 0; index < th_count; index++)
2146     {
2147       thread_t saved_thread = MACH_PORT_NULL;
2148       int mid;
2149
2150       if (must_suspend_thread)
2151         setup_thread (th_table[ index ], 1);
2152
2153       if (th_table[index] != current_thread)
2154         {
2155           saved_thread = current_thread;
2156           
2157           mid = switch_to_thread (th_table[ index ]);
2158         }
2159
2160       mthreads[index].name  = th_table[index];
2161       mthreads[index].cproc = NULL;     /* map_cprocs_to_kernel_threads() */
2162       mthreads[index].in_emulator = FALSE;
2163       mthreads[index].slotid = index;
2164       
2165       mthreads[index].sp = read_register (SP_REGNUM);
2166       mthreads[index].fp = read_register (FP_REGNUM);
2167       mthreads[index].pc = read_pc ();
2168
2169       if (MACH_PORT_VALID (saved_thread))
2170         mid = switch_to_thread (saved_thread);
2171
2172       if (must_suspend_thread)
2173         setup_thread (th_table[ index ], 0);
2174     }
2175   
2176   consume_send_rights (th_table, th_count);
2177   ret = vm_deallocate (mach_task_self(), (vm_address_t)th_table, 
2178                        (th_count * sizeof(mach_port_t)));
2179   if (ret != KERN_SUCCESS)
2180     {
2181       warning ("Error trying to deallocate thread list : %s",
2182                mach_error_string (ret));
2183     }
2184
2185   *mthreads_out = mthreads;
2186
2187   return th_count;
2188 }
2189
2190
2191 /*
2192  * Current emulator always saves the USP on top of
2193  * emulator stack below struct emul_stack_top stuff.
2194  */
2195 CORE_ADDR
2196 fetch_usp_from_emulator_stack (sp)
2197      CORE_ADDR sp;
2198 {
2199   CORE_ADDR stack_pointer;
2200
2201   sp = (sp & ~(EMULATOR_STACK_SIZE-1)) +
2202         EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
2203   
2204   if (mach3_read_inferior (sp,
2205                            &stack_pointer,
2206                            sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2207     {
2208       warning ("Can't read user sp from emulator stack address 0x%x", sp);
2209       return 0;
2210     }
2211
2212   return stack_pointer;
2213 }
2214
2215 #ifdef MK67
2216
2217 /* get_emulation_vector() interface was changed after mk67 */
2218 #define EMUL_VECTOR_COUNT 400   /* Value does not matter too much */
2219
2220 #endif /* MK67 */
2221
2222 /* Check if the emulator exists at task's address space.
2223  */
2224 boolean_t
2225 have_emulator_p (task)
2226      task_t task;
2227 {
2228   kern_return_t ret;
2229 #ifndef EMUL_VECTOR_COUNT
2230   vm_offset_t   *emulation_vector;
2231   int           n;
2232 #else
2233   vm_offset_t   emulation_vector[ EMUL_VECTOR_COUNT ];
2234   int           n = EMUL_VECTOR_COUNT;
2235 #endif
2236   int           i;
2237   int           vector_start;
2238   
2239   ret = task_get_emulation_vector (task,
2240                                    &vector_start,
2241 #ifndef EMUL_VECTOR_COUNT
2242                                    &emulation_vector,
2243 #else
2244                                    emulation_vector,
2245 #endif
2246                                    &n);
2247   CHK("task_get_emulation_vector", ret);
2248   xx_debug ("%d vectors from %d at 0x%08x\n",
2249             n, vector_start, emulation_vector);
2250   
2251   for(i = 0; i < n; i++)
2252     {
2253       vm_offset_t entry = emulation_vector [i];
2254
2255       if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
2256         return TRUE;
2257       else if (entry)
2258         {
2259           static boolean_t informed = FALSE;
2260           if (!informed)
2261             {
2262               warning("Emulation vector address 0x08%x outside emulator space",
2263                       entry);
2264               informed = TRUE;
2265             }
2266         }
2267     }
2268   return FALSE;
2269 }
2270
2271 /* Map cprocs to kernel threads and vice versa.  */
2272
2273 void
2274 map_cprocs_to_kernel_threads (cprocs, mthreads, thread_count)
2275      gdb_thread_t cprocs;
2276      gdb_thread_t mthreads;
2277      int thread_count;
2278 {
2279   int index;
2280   gdb_thread_t scan;
2281   boolean_t all_mapped = TRUE;
2282
2283   for (scan = cprocs; scan; scan = scan->next)
2284     {
2285       /* Default to: no kernel thread for this cproc */
2286       scan->reverse_map = -1;
2287
2288       /* Check if the cproc is found by its stack */
2289       for (index = 0; index < thread_count; index++)
2290         {
2291           LONGEST stack_base =
2292             extract_signed_integer (scan.raw_cproc + CPROC_BASE_OFFSET,
2293                                     CPROC_BASE_SIZE);
2294           LONGEST stack_size = 
2295             extract_signed_integer (scan.raw_cproc + CPROC_SIZE_OFFSET,
2296                                     CPROC_SIZE_SIZE);
2297           if ((mthreads + index)->sp > stack_base &&
2298               (mthreads + index)->sp <= stack_base + stack_size)
2299             {
2300               (mthreads + index)->cproc = scan;
2301               scan->reverse_map = index;
2302               break;
2303             }
2304         }
2305       all_mapped &= (scan->reverse_map != -1);
2306     }
2307
2308   /* Check for threads that are currently in the emulator.
2309    * If so, they have a different stack, and the still unmapped
2310    * cprocs may well get mapped to these threads.
2311    * 
2312    * If:
2313    *  - cproc stack does not match any kernel thread stack pointer
2314    *  - there is at least one extra kernel thread
2315    *    that has no cproc mapped above.
2316    *  - some kernel thread stack pointer points to emulator space
2317    *  then we find the user stack pointer saved in the emulator
2318    *  stack, and try to map that to the cprocs.
2319    *
2320    * Also set in_emulator for kernel threads.
2321    */ 
2322
2323   if (emulator_present)
2324     {
2325       for (index = 0; index < thread_count; index++)
2326         {
2327           CORE_ADDR emul_sp;
2328           CORE_ADDR usp;
2329
2330           gdb_thread_t mthread = (mthreads+index);
2331           emul_sp = mthread->sp;
2332
2333           if (mthread->cproc == NULL &&
2334               EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
2335             {
2336               mthread->in_emulator = emulator_present;
2337               
2338               if (!all_mapped && cprocs)
2339                 {
2340                   usp = fetch_usp_from_emulator_stack (emul_sp);
2341                   
2342                   /* @@ Could be more accurate */
2343                   if (! usp)
2344                     error ("Zero stack pointer read from emulator?");
2345                   
2346                   /* Try to match this stack pointer to the cprocs that
2347                    * don't yet have a kernel thread.
2348                    */
2349                   for (scan = cprocs; scan; scan = scan->next)
2350                     {
2351                       
2352                       /* Check is this unmapped CPROC stack contains
2353                        * the user stack pointer saved in the
2354                        * emulator.
2355                        */
2356                       if (scan->reverse_map == -1 &&
2357                           usp > scan->stack_base &&
2358                           usp <= scan->stack_base + scan->stack_size)
2359                         {
2360                           mthread->cproc = scan;
2361                           scan->reverse_map = index;
2362                           break;
2363                         }
2364                     }
2365                 }
2366             }
2367         }
2368     }
2369 }
2370 \f
2371 /*
2372  * Format of the thread_list command
2373  *
2374  *                   slot mid sel   name  emul ks susp  cstate wired   address
2375  */
2376 #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2377
2378 #define TL_HEADER "\n@    MID  Name        KState CState   Where\n"
2379
2380 void
2381 print_tl_address (stream, pc)
2382      GDB_FILE *stream;
2383      CORE_ADDR pc;
2384 {
2385   if (! lookup_minimal_symbol_by_pc (pc))
2386     fprintf_filtered (stream, local_hex_format(), pc);
2387   else
2388     {
2389       extern int addressprint;
2390       extern int asm_demangle;
2391
2392       int store    = addressprint;
2393       addressprint = 0;
2394       print_address_symbolic (pc, stream, asm_demangle, "");
2395       addressprint = store;
2396     }
2397 }
2398 \f
2399 /* For thread names, but also for gdb_message_port external name */
2400 #define MAX_NAME_LEN 50
2401
2402 /* Returns the address of variable NAME or 0 if not found */
2403 CORE_ADDR
2404 lookup_address_of_variable (name)
2405      char *name;
2406 {
2407   struct symbol *sym;
2408   CORE_ADDR symaddr = 0;
2409   struct minimal_symbol *msymbol;
2410
2411   sym = lookup_symbol (name,
2412                        (struct block *)NULL,
2413                        VAR_NAMESPACE,
2414                        (int *)NULL,
2415                        (struct symtab **)NULL);
2416
2417   if (sym)
2418     symaddr = SYMBOL_VALUE (sym);
2419
2420   if (! symaddr)
2421     {
2422       msymbol = lookup_minimal_symbol (name, (struct objfile *) NULL);
2423
2424       if (msymbol && msymbol->type == mst_data)
2425         symaddr = msymbol->address;
2426     }
2427
2428   return symaddr;
2429 }
2430
2431 static gdb_thread_t
2432 get_cprocs()
2433 {
2434   gdb_thread_t cproc_head;
2435   gdb_thread_t cproc_copy;
2436   CORE_ADDR their_cprocs;
2437   char *buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
2438   char *name;
2439   cthread_t cthread;
2440   CORE_ADDR symaddr;
2441   
2442   symaddr = lookup_address_of_variable ("cproc_list");
2443
2444   if (! symaddr)
2445     {
2446       /* cproc_list is not in a file compiled with debugging
2447          symbols, but don't give up yet */
2448
2449       symaddr = lookup_address_of_variable ("cprocs");
2450
2451       if (symaddr)
2452         {
2453           static int informed = 0;
2454           if (!informed)
2455             {
2456               informed++;
2457               warning ("Your program is loaded with an old threads library.");
2458               warning ("GDB does not know the old form of threads");
2459               warning ("so things may not work.");
2460             }
2461         }
2462     }
2463
2464   /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
2465   if (! symaddr)
2466     return NULL;
2467
2468   /* Get the address of the first cproc in the task */
2469   if (!mach3_read_inferior (symaddr,
2470                             buf,
2471                             TARGET_PTR_BIT / HOST_CHAR_BIT))
2472     error ("Can't read cproc master list at address (0x%x).", symaddr);
2473   their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
2474
2475   /* Scan the CPROCs in the task.
2476      CPROCs are chained with LIST field, not NEXT field, which
2477      chains mutexes, condition variables and queues */
2478
2479   cproc_head = NULL;
2480
2481   while (their_cprocs != (CORE_ADDR)0)
2482     {
2483       CORE_ADDR cproc_copy_incarnation;
2484       cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
2485                                                  sizeof (struct gdb_thread));
2486
2487       if (!mach3_read_inferior (their_cprocs,
2488                                 &cproc_copy.raw_cproc[0],
2489                                 CPROC_SIZE))
2490         error("Can't read next cproc at 0x%x.", their_cprocs);
2491       cproc_copy = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
2492
2493       their_cprocs =
2494         extract_address (cproc_copy.raw_cproc + CPROC_LIST_OFFSET,
2495                          CPROC_LIST_SIZE);
2496       cproc_copy_incarnation =
2497         extract_address (cproc_copy.raw_cproc + CPROC_INCARNATION_OFFSET,
2498                          CPROC_INCARNATION_SIZE);
2499
2500       if (cproc_copy_incarnation == (CORE_ADDR)0)
2501         cproc_copy->cthread = NULL;
2502       else
2503         {
2504           /* This CPROC has an attached CTHREAD. Get its name */
2505           cthread = (cthread_t)obstack_alloc (cproc_obstack,
2506                                               sizeof(struct cthread));
2507
2508           if (!mach3_read_inferior (cproc_copy_incarnation,
2509                                     cthread,
2510                                     sizeof(struct cthread)))
2511             error("Can't read next thread at 0x%x.",
2512                   cproc_copy_incarnation);
2513
2514           cproc_copy->cthread = cthread;
2515
2516           if (cthread->name)
2517             {
2518               name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
2519
2520               if (!mach3_read_inferior(cthread->name, name, MAX_NAME_LEN))
2521                 error("Can't read next thread's name at 0x%x.", cthread->name);
2522
2523               cthread->name = name;
2524             }
2525         }
2526
2527       /* insert in front */
2528       cproc_copy->next = cproc_head;
2529       cproc_head = cproc_copy;
2530     }
2531   return cproc_head;
2532 }
2533
2534 #ifndef FETCH_CPROC_STATE
2535 /*
2536  * Check if your machine does not grok the way this routine
2537  * fetches the FP,PC and SP of a cproc that is not
2538  * currently attached to any kernel thread (e.g. its cproc.context
2539  * field points to the place in stack where the context
2540  * is saved).
2541  *
2542  * If it doesn't, define your own routine.
2543  */
2544 #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2545
2546 int
2547 mach3_cproc_state (mthread)
2548      gdb_thread_t mthread;
2549 {
2550   int context;
2551
2552   if (! mthread || !mthread->cproc || !mthread->cproc->context)
2553     return -1;
2554
2555   context = extract_signed_integer
2556     (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
2557      CPROC_CONTEXT_SIZE);
2558
2559   mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
2560
2561   if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
2562                            &mthread->pc,
2563                            sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2564     {
2565       warning ("Can't read cproc pc from inferior");
2566       return -1;
2567     }
2568
2569   if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
2570                            &mthread->fp,
2571                            sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2572     {
2573       warning ("Can't read cproc fp from inferior");
2574       return -1;
2575     }
2576
2577   return 0;
2578 }
2579 #endif /* FETCH_CPROC_STATE */
2580
2581 \f
2582 void
2583 thread_list_command()
2584 {
2585   thread_basic_info_data_t ths;
2586   int     thread_count;
2587   gdb_thread_t cprocs;
2588   gdb_thread_t scan;
2589   int     index;
2590   char   *name;
2591   char    selected;
2592   char   *wired;
2593   int     infoCnt;
2594   kern_return_t ret;
2595   mach_port_t   mid_or_port;
2596   gdb_thread_t  their_threads;
2597   gdb_thread_t  kthread;
2598
2599   int neworder = 1;
2600
2601   char *fmt = "There are %d kernel threads in task %d.\n";
2602   
2603   int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
2604   
2605   MACH_ERROR_NO_INFERIOR;
2606   
2607   thread_count = fetch_thread_info (inferior_task,
2608                                     &their_threads);
2609   if (thread_count == -1)
2610     return;
2611   
2612   if (thread_count == 1)
2613     fmt = "There is %d kernel thread in task %d.\n";
2614   
2615   printf_filtered (fmt, thread_count, tmid);
2616   
2617   puts_filtered (TL_HEADER);
2618   
2619   cprocs = get_cprocs();
2620   
2621   map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
2622   
2623   for (scan = cprocs; scan; scan = scan->next)
2624     {
2625       int mid;
2626       char buf[10];
2627       char slot[3];
2628       
2629       selected = ' ';
2630       
2631       /* a wired cproc? */
2632       wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
2633                                 CPROC_WIRED_SIZE)
2634                ? "wired" : "");
2635
2636       if (scan->reverse_map != -1)
2637         kthread  = (their_threads + scan->reverse_map);
2638       else
2639         kthread  = NULL;
2640
2641       if (kthread)
2642         {
2643           /* These cprocs have a kernel thread */
2644           
2645           mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
2646           
2647           infoCnt = THREAD_BASIC_INFO_COUNT;
2648           
2649           ret = thread_info (kthread->name,
2650                              THREAD_BASIC_INFO,
2651                              (thread_info_t)&ths,
2652                              &infoCnt);
2653           
2654           if (ret != KERN_SUCCESS)
2655             {
2656               warning ("Unable to get basic info on thread %d : %s",
2657                        mid,
2658                        mach_error_string (ret));
2659               continue;
2660             }
2661
2662           /* Who is the first to have more than 100 threads */
2663           sprintf (slot, "%d", kthread->slotid%100);
2664
2665           if (kthread->name == current_thread)
2666             selected = '*';
2667           
2668           if (ths.suspend_count)
2669             sprintf (buf, "%d", ths.suspend_count);
2670           else
2671             buf[0] = '\000';
2672
2673 #if 0
2674           if (ths.flags & TH_FLAGS_SWAPPED)
2675             strcat (buf, "S");
2676 #endif
2677
2678           if (ths.flags & TH_FLAGS_IDLE)
2679             strcat (buf, "I");
2680
2681           /* FIXME: May run afloul of arbitrary limit in printf_filtered.  */
2682           printf_filtered (TL_FORMAT,
2683                            slot,
2684                            mid,
2685                            selected,
2686                            get_thread_name (scan, kthread->slotid),
2687                            kthread->in_emulator ? "E" : "",
2688                            translate_state (ths.run_state),
2689                            buf,
2690                            translate_cstate (scan->state),
2691                            wired);
2692           print_tl_address (gdb_stdout, kthread->pc);
2693         }
2694       else
2695         {
2696           /* These cprocs don't have a kernel thread.
2697            * find out the calling frame with 
2698            * FETCH_CPROC_STATE.
2699            */
2700
2701           struct gdb_thread state;
2702
2703 #if 0
2704           /* jtv -> emcmanus: why do you want this here? */
2705           if (scan->incarnation == NULL)
2706             continue; /* EMcM */
2707 #endif
2708
2709           /* FIXME: May run afloul of arbitrary limit in printf_filtered.  */
2710           printf_filtered (TL_FORMAT,
2711                            "-",
2712                            -neworder,   /* Pseudo MID */
2713                            selected,
2714                            get_thread_name (scan, -neworder),
2715                            "",
2716                            "-", /* kernel state */
2717                            "",
2718                            translate_cstate (scan->state),
2719                            "");
2720           state.cproc = scan;
2721
2722           if (FETCH_CPROC_STATE (&state) == -1)
2723             puts_filtered ("???");
2724           else
2725             print_tl_address (gdb_stdout, state.pc);
2726
2727           neworder++;
2728         }
2729       puts_filtered ("\n");
2730     }
2731   
2732   /* Scan for kernel threads without cprocs */
2733   for (index = 0; index < thread_count; index++)
2734     {
2735       if (! their_threads[index].cproc)
2736         {
2737           int mid;
2738           
2739           char buf[10];
2740           char slot[3];
2741
2742           mach_port_t name = their_threads[index].name;
2743           
2744           mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
2745           
2746           infoCnt = THREAD_BASIC_INFO_COUNT;
2747           
2748           ret = thread_info(name,
2749                             THREAD_BASIC_INFO,
2750                             (thread_info_t)&ths,
2751                             &infoCnt);
2752             
2753           if (ret != KERN_SUCCESS)
2754             {
2755               warning ("Unable to get basic info on thread %d : %s",
2756                        mid,
2757                        mach_error_string (ret));
2758               continue;
2759             }
2760
2761           sprintf (slot, "%d", index%100);
2762
2763           if (name == current_thread)
2764             selected = '*';
2765           else
2766             selected = ' ';
2767
2768           if (ths.suspend_count)
2769             sprintf (buf, "%d", ths.suspend_count);
2770           else
2771             buf[0] = '\000';
2772
2773 #if 0
2774           if (ths.flags & TH_FLAGS_SWAPPED)
2775             strcat (buf, "S");
2776 #endif
2777
2778           if (ths.flags & TH_FLAGS_IDLE)
2779             strcat (buf, "I");
2780
2781           /* FIXME: May run afloul of arbitrary limit in printf_filtered.  */
2782           printf_filtered (TL_FORMAT,
2783                            slot,
2784                            mid,
2785                            selected,
2786                            get_thread_name (NULL, index),
2787                            their_threads[index].in_emulator ? "E" : "",
2788                            translate_state (ths.run_state),
2789                            buf,
2790                            "",   /* No cproc state */
2791                            ""); /* Can't be wired */
2792           print_tl_address (gdb_stdout, their_threads[index].pc);
2793           puts_filtered ("\n");
2794         }
2795     }
2796   
2797   obstack_free (cproc_obstack, 0);
2798   obstack_init (cproc_obstack);
2799 }
2800 \f
2801 void
2802 thread_select_command(args, from_tty)
2803      char *args;
2804      int from_tty;
2805 {
2806   int mid;
2807   thread_array_t thread_list;
2808   int thread_count;
2809   kern_return_t ret;
2810   int is_slot = 0;
2811
2812   MACH_ERROR_NO_INFERIOR;
2813
2814   if (!args)
2815     error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2816
2817   while (*args == ' ' || *args == '\t')
2818     args++;
2819
2820   if (*args == '@')
2821     {
2822       is_slot++;
2823       args++;
2824     }
2825
2826   mid = atoi(args);
2827
2828   if (mid == 0)
2829     if (!is_slot || *args != '0') /* Rudimentary checks */
2830       error ("You must select threads by MID or @SLOTNUMBER");
2831
2832   if (select_thread (inferior_task, mid, is_slot?2:1) != KERN_SUCCESS)
2833     return;
2834
2835   if (from_tty)
2836     printf_filtered ("Thread %d selected\n",
2837                      is_slot ? map_port_name_to_mid (current_thread,
2838                                                      MACH_TYPE_THREAD) : mid);
2839 }
2840 \f
2841 thread_trace (thread, set)
2842 mach_port_t thread;
2843 boolean_t   set;
2844 {
2845   int                   flavor   = TRACE_FLAVOR;
2846   unsigned int          stateCnt = TRACE_FLAVOR_SIZE;
2847   kern_return_t         ret;
2848   thread_state_data_t   state;
2849
2850   if (! MACH_PORT_VALID (thread))
2851     {
2852       warning ("thread_trace: invalid thread");
2853       return;
2854     }
2855
2856   if (must_suspend_thread)
2857     setup_thread (thread, 1);
2858
2859   ret = thread_get_state(thread, flavor, state, &stateCnt);
2860   CHK ("thread_trace: error reading thread state", ret);
2861   
2862   if (set)
2863     {
2864       TRACE_SET (thread, state);
2865     }
2866   else
2867     {
2868       if (! TRACE_CLEAR (thread, state))
2869         {
2870           if (must_suspend_thread)
2871             setup_thread (thread, 0);
2872           return;
2873         }
2874     }
2875
2876   ret = thread_set_state(thread, flavor, state, stateCnt);
2877   CHK ("thread_trace: error writing thread state", ret);
2878   if (must_suspend_thread)
2879     setup_thread (thread, 0);
2880 }  
2881
2882 #ifdef  FLUSH_INFERIOR_CACHE
2883
2884 /* When over-writing code on some machines the I-Cache must be flushed
2885    explicitly, because it is not kept coherent by the lazy hardware.
2886    This definitely includes breakpoints, for instance, or else we
2887    end up looping in mysterious Bpt traps */
2888
2889 flush_inferior_icache(pc, amount)
2890      CORE_ADDR pc;
2891 {
2892   vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
2893   kern_return_t   ret;
2894   
2895   ret = vm_machine_attribute (inferior_task,
2896                               pc,
2897                               amount,
2898                               MATTR_CACHE,
2899                               &flush);
2900   if (ret != KERN_SUCCESS)
2901     warning ("Error flushing inferior's cache : %s",
2902              mach_error_string (ret));
2903 }
2904 #endif  FLUSH_INFERIOR_CACHE
2905
2906 \f
2907 static
2908 suspend_all_threads (from_tty)
2909      int from_tty;
2910 {
2911   kern_return_t    ret;
2912   thread_array_t   thread_list;
2913   int              thread_count, index;
2914   int              infoCnt;
2915   thread_basic_info_data_t th_info;
2916
2917   
2918   ret = task_threads (inferior_task, &thread_list, &thread_count);
2919   if (ret != KERN_SUCCESS)
2920     {
2921       warning ("Could not suspend inferior threads.");
2922       kill_inferior ();
2923       return_to_top_level ();
2924     }
2925   
2926   for (index = 0; index < thread_count; index++)
2927     {
2928       int mid;
2929
2930       mid = map_port_name_to_mid (thread_list[ index ],
2931                                   MACH_TYPE_THREAD);
2932           
2933       ret = thread_suspend(thread_list[ index ]);
2934
2935       if (ret != KERN_SUCCESS)
2936         warning ("Error trying to suspend thread %d : %s",
2937                  mid, mach_error_string (ret));
2938
2939       if (from_tty)
2940         {
2941           infoCnt = THREAD_BASIC_INFO_COUNT;
2942           ret = thread_info (thread_list[ index ],
2943                              THREAD_BASIC_INFO,
2944                              (thread_info_t) &th_info,
2945                              &infoCnt);
2946           CHK ("suspend can't get thread info", ret);
2947           
2948           warning ("Thread %d suspend count is %d",
2949                    mid, th_info.suspend_count);
2950         }
2951     }
2952
2953   consume_send_rights (thread_list, thread_count);
2954   ret = vm_deallocate(mach_task_self(),
2955                       (vm_address_t)thread_list, 
2956                       (thread_count * sizeof(int)));
2957   CHK ("Error trying to deallocate thread list", ret);
2958 }
2959
2960 void
2961 thread_suspend_command (args, from_tty)
2962      char *args;
2963      int from_tty;
2964 {
2965   kern_return_t ret;
2966   int           mid;
2967   mach_port_t   saved_thread;
2968   int           infoCnt;
2969   thread_basic_info_data_t th_info;
2970   
2971   MACH_ERROR_NO_INFERIOR;
2972
2973   if (!strcasecmp (args, "all")) {
2974     suspend_all_threads (from_tty);
2975     return;
2976   }
2977
2978   saved_thread = current_thread;
2979
2980   mid = parse_thread_id (args, 0, 0);
2981
2982   if (mid < 0)
2983     error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
2984
2985   if (mid == 0)
2986     mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
2987   else
2988     if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
2989       {
2990         if (current_thread)
2991           current_thread = saved_thread;
2992         error ("Could not select thread %d", mid);
2993       }
2994
2995   ret = thread_suspend (current_thread);
2996   if (ret != KERN_SUCCESS)
2997     warning ("thread_suspend failed : %s",
2998              mach_error_string (ret));
2999
3000   infoCnt = THREAD_BASIC_INFO_COUNT;
3001   ret = thread_info (current_thread,
3002                      THREAD_BASIC_INFO,
3003                      (thread_info_t) &th_info,
3004                      &infoCnt);
3005   CHK ("suspend can't get thread info", ret);
3006   
3007   warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
3008   
3009   current_thread = saved_thread;
3010 }
3011
3012 resume_all_threads (from_tty)
3013      int from_tty;
3014 {
3015     kern_return_t  ret;
3016     thread_array_t thread_list;
3017     int            thread_count, index;
3018     int            mid;
3019     int            infoCnt;
3020     thread_basic_info_data_t th_info;
3021
3022     ret = task_threads (inferior_task, &thread_list, &thread_count);
3023     if (ret != KERN_SUCCESS)
3024       {
3025         kill_inferior ();
3026         error("task_threads", mach_error_string( ret));
3027       }
3028
3029     for (index = 0; index < thread_count; index++)
3030       {
3031         infoCnt = THREAD_BASIC_INFO_COUNT;
3032         ret = thread_info (thread_list [ index ],
3033                            THREAD_BASIC_INFO,
3034                            (thread_info_t) &th_info,
3035                            &infoCnt);
3036         CHK ("resume_all can't get thread info", ret);
3037         
3038         mid = map_port_name_to_mid (thread_list[ index ],
3039                                     MACH_TYPE_THREAD);
3040         
3041         if (! th_info.suspend_count)
3042           {
3043             if (mid != -1 && from_tty)
3044               warning ("Thread %d is not suspended", mid);
3045             continue;
3046           }
3047
3048         ret = thread_resume (thread_list[ index ]);
3049
3050         if (ret != KERN_SUCCESS)
3051           warning ("Error trying to resume thread %d : %s",
3052                    mid, mach_error_string (ret));
3053         else if (mid != -1 && from_tty)
3054           warning ("Thread %d suspend count is %d",
3055                    mid, --th_info.suspend_count);
3056       }
3057
3058     consume_send_rights (thread_list, thread_count);
3059     ret = vm_deallocate(mach_task_self(),
3060                         (vm_address_t)thread_list, 
3061                         (thread_count * sizeof(int)));
3062     CHK("Error trying to deallocate thread list", ret);
3063 }
3064
3065 void
3066 thread_resume_command (args, from_tty)
3067      char *args;
3068      int from_tty;
3069 {
3070   int mid;
3071   mach_port_t saved_thread;
3072   kern_return_t ret;
3073   thread_basic_info_data_t th_info;
3074   int infoCnt = THREAD_BASIC_INFO_COUNT;
3075   
3076   MACH_ERROR_NO_INFERIOR;
3077
3078   if (!strcasecmp (args, "all")) {
3079     resume_all_threads (from_tty);
3080     return;
3081   }
3082
3083   saved_thread = current_thread;
3084
3085   mid = parse_thread_id (args, 0, 0);
3086
3087   if (mid < 0)
3088     error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3089
3090   if (mid == 0)
3091     mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
3092   else
3093     if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3094       {
3095         if (current_thread)
3096           current_thread = saved_thread;
3097         return_to_top_level ();
3098       }
3099
3100   ret = thread_info (current_thread,
3101                      THREAD_BASIC_INFO,
3102                      (thread_info_t) &th_info,
3103                      &infoCnt);
3104   CHK ("resume can't get thread info", ret);
3105   
3106   if (! th_info.suspend_count)
3107     {
3108       warning ("Thread %d is not suspended", mid);
3109       goto out;
3110     }
3111
3112   ret = thread_resume (current_thread);
3113   if (ret != KERN_SUCCESS)
3114     warning ("thread_resume failed : %s",
3115              mach_error_string (ret));
3116   else
3117     {
3118       th_info.suspend_count--;
3119       warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
3120     }
3121       
3122  out:
3123   current_thread = saved_thread;
3124 }
3125
3126 void
3127 thread_kill_command (args, from_tty)
3128      char *args;
3129      int from_tty;
3130 {
3131   int mid;
3132   kern_return_t ret;
3133   int thread_count;
3134   thread_array_t thread_table;
3135   int   index;
3136   mach_port_t thread_to_kill = MACH_PORT_NULL;
3137   
3138   
3139   MACH_ERROR_NO_INFERIOR;
3140
3141   if (!args)
3142     error_no_arg ("thread mid to kill from the inferior task");
3143
3144   mid = parse_thread_id (args, 0, 0);
3145
3146   if (mid < 0)
3147     error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3148
3149   if (mid)
3150     {
3151       ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
3152       CHK ("thread_kill_command: machid_mach_port map failed", ret);
3153     }
3154   else
3155     mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
3156       
3157   /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3158   ret = task_threads (inferior_task, &thread_table, &thread_count);
3159   CHK ("Error getting inferior's thread list", ret);
3160   
3161   if (thread_to_kill == current_thread)
3162     {
3163       ret = thread_terminate (thread_to_kill);
3164       CHK ("Thread could not be terminated", ret);
3165
3166       if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3167         warning ("Last thread was killed, use \"kill\" command to kill task");
3168     }
3169   else
3170     for (index = 0; index < thread_count; index++)
3171       if (thread_table [ index ] == thread_to_kill)
3172         {
3173           ret = thread_terminate (thread_to_kill);
3174           CHK ("Thread could not be terminated", ret);
3175         }
3176
3177   if (thread_count > 1)
3178     consume_send_rights (thread_table, thread_count);
3179   
3180   ret = vm_deallocate (mach_task_self(), (vm_address_t)thread_table, 
3181                        (thread_count * sizeof(mach_port_t)));
3182   CHK ("Error trying to deallocate thread list", ret);
3183   
3184   warning ("Thread %d killed", mid);
3185 }
3186
3187 \f
3188 /* Task specific commands; add more if you like */
3189
3190 void
3191 task_resume_command (args, from_tty)
3192      char *args;
3193      int from_tty;
3194 {
3195   kern_return_t ret;
3196   task_basic_info_data_t ta_info;
3197   int infoCnt = TASK_BASIC_INFO_COUNT;
3198   int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
3199   
3200   MACH_ERROR_NO_INFERIOR;
3201
3202   /* Would be trivial to change, but is it desirable? */
3203   if (args)
3204     error ("Currently gdb can resume only it's inferior task");
3205
3206   ret = task_info (inferior_task,
3207                    TASK_BASIC_INFO,
3208                    (task_info_t) &ta_info,
3209                    &infoCnt);
3210   CHK ("task_resume_command: task_info failed", ret);
3211   
3212   if (ta_info.suspend_count == 0)
3213     error ("Inferior task %d is not suspended", mid);
3214   else if (ta_info.suspend_count == 1 &&
3215            from_tty &&
3216            !query ("Suspend count is now 1. Do you know what you are doing? "))
3217     error ("Task not resumed");
3218
3219   ret = task_resume (inferior_task);
3220   CHK ("task_resume_command: task_resume", ret);
3221
3222   if (ta_info.suspend_count == 1)
3223     {
3224       warning ("Inferior task %d is no longer suspended", mid);
3225       must_suspend_thread = 1;
3226       /* @@ This is not complete: Registers change all the time when not
3227          suspended! */
3228       registers_changed ();
3229     }
3230   else
3231     warning ("Inferior task %d suspend count is now %d",
3232              mid, ta_info.suspend_count-1);
3233 }
3234
3235
3236 void
3237 task_suspend_command (args, from_tty)
3238      char *args;
3239      int from_tty;
3240 {
3241   kern_return_t ret;
3242   task_basic_info_data_t ta_info;
3243   int infoCnt = TASK_BASIC_INFO_COUNT;
3244   int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
3245   
3246   MACH_ERROR_NO_INFERIOR;
3247
3248   /* Would be trivial to change, but is it desirable? */
3249   if (args)
3250     error ("Currently gdb can suspend only it's inferior task");
3251
3252   ret = task_suspend (inferior_task);
3253   CHK ("task_suspend_command: task_suspend", ret);
3254
3255   must_suspend_thread = 0;
3256
3257   ret = task_info (inferior_task,
3258                    TASK_BASIC_INFO,
3259                    (task_info_t) &ta_info,
3260                    &infoCnt);
3261   CHK ("task_suspend_command: task_info failed", ret);
3262   
3263   warning ("Inferior task %d suspend count is now %d",
3264            mid, ta_info.suspend_count);
3265 }
3266
3267 static char *
3268 get_size (bytes)
3269      int bytes;
3270 {
3271   static char size [ 30 ];
3272   int zz = bytes/1024;
3273
3274   if (zz / 1024)
3275     sprintf (size, "%-2.1f M", ((float)bytes)/(1024.0*1024.0));
3276   else
3277     sprintf (size, "%d K", zz);
3278
3279   return size;
3280 }
3281
3282 /* Does this require the target task to be suspended?? I don't think so. */
3283 void
3284 task_info_command (args, from_tty)
3285      char *args;
3286      int from_tty;
3287 {
3288   int mid = -5;
3289   mach_port_t task;
3290   kern_return_t ret;
3291   task_basic_info_data_t ta_info;
3292   int infoCnt = TASK_BASIC_INFO_COUNT;
3293   int page_size = round_page(1);
3294   int thread_count = 0;
3295   
3296   if (MACH_PORT_VALID (inferior_task))
3297     mid = map_port_name_to_mid (inferior_task,
3298                                 MACH_TYPE_TASK);
3299
3300   task = inferior_task;
3301
3302   if (args)
3303     {
3304       int tmid = atoi (args);
3305
3306       if (tmid <= 0)
3307         error ("Invalid mid %d for task info", tmid);
3308
3309       if (tmid != mid)
3310         {
3311           mid = tmid;
3312           ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
3313           CHK ("task_info_command: machid_mach_port map failed", ret);
3314         }
3315     }
3316
3317   if (mid < 0)
3318     error ("You have to give the task MID as an argument");
3319
3320   ret = task_info (task,
3321                    TASK_BASIC_INFO,
3322                    (task_info_t) &ta_info,
3323                    &infoCnt);
3324   CHK ("task_info_command: task_info failed", ret);
3325
3326   printf_filtered ("\nTask info for task %d:\n\n", mid);
3327   printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
3328   printf_filtered (" Base priority : %d\n", ta_info.base_priority);
3329   printf_filtered (" Virtual size  : %s\n", get_size (ta_info.virtual_size));
3330   printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
3331
3332   {
3333     thread_array_t thread_list;
3334     
3335     ret = task_threads (task, &thread_list, &thread_count);
3336     CHK ("task_info_command: task_threads", ret);
3337     
3338     printf_filtered (" Thread count  : %d\n", thread_count);
3339
3340     consume_send_rights (thread_list, thread_count);
3341     ret = vm_deallocate(mach_task_self(),
3342                         (vm_address_t)thread_list, 
3343                         (thread_count * sizeof(int)));
3344     CHK("Error trying to deallocate thread list", ret);
3345   }
3346   if (have_emulator_p (task))
3347     printf_filtered (" Emulator at   : 0x%x..0x%x\n",
3348                      EMULATOR_BASE, EMULATOR_END);
3349   else
3350     printf_filtered (" No emulator.\n");
3351
3352   if (thread_count && task == inferior_task)
3353     printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3354 }
3355 \f
3356 /* You may either FORWARD the exception to the inferior, or KEEP
3357  * it and return to GDB command level.
3358  *
3359  * exception mid [ forward | keep ]
3360  */
3361
3362 static void
3363 exception_command (args, from_tty)
3364      char *args;
3365      int from_tty;
3366 {
3367   char *scan = args;
3368   int exception;
3369   int len;
3370
3371   if (!args)
3372     error_no_arg ("exception number action");
3373
3374   while (*scan == ' ' || *scan == '\t') scan++;
3375   
3376   if ('0' <= *scan && *scan <= '9')
3377     while ('0' <= *scan && *scan <= '9')
3378       scan++;
3379   else
3380     error ("exception number action");
3381
3382   exception = atoi (args);
3383   if (exception <= 0 || exception > MAX_EXCEPTION)
3384     error ("Allowed exception numbers are in range 1..%d",
3385            MAX_EXCEPTION);
3386
3387   if (*scan != ' ' && *scan != '\t')
3388     error ("exception number must be followed by a space");
3389   else
3390     while (*scan == ' ' || *scan == '\t') scan++;
3391
3392   args = scan;
3393   len = 0;
3394   while (*scan)
3395     {
3396       len++;
3397       scan++;
3398     }
3399
3400   if (!len)
3401     error("exception number action");
3402
3403   if (!strncasecmp (args, "forward", len))
3404     exception_map[ exception ].forward = TRUE;
3405   else if (!strncasecmp (args, "keep", len))
3406     exception_map[ exception ].forward = FALSE;
3407   else
3408     error ("exception action is either \"keep\" or \"forward\"");
3409 }
3410
3411 static void
3412 print_exception_info (exception)
3413      int exception;
3414 {
3415   boolean_t forward = exception_map[ exception ].forward;
3416
3417   printf_filtered ("%s\t(%d): ", exception_map[ exception ].name,
3418                    exception);
3419   if (!forward)
3420     if (exception_map[ exception ].sigmap != SIG_UNKNOWN)
3421       printf_filtered ("keep and handle as signal %d\n",
3422                        exception_map[ exception ].sigmap);
3423     else
3424       printf_filtered ("keep and handle as unknown signal %d\n",
3425                        exception_map[ exception ].sigmap);
3426   else
3427     printf_filtered ("forward exception to inferior\n");
3428 }
3429
3430 void
3431 exception_info (args, from_tty)
3432      char *args;
3433      int from_tty;
3434 {
3435   int exception;
3436
3437   if (!args)
3438     for (exception = 1; exception <= MAX_EXCEPTION; exception++)
3439       print_exception_info (exception);
3440   else
3441     {
3442       exception = atoi (args);
3443
3444       if (exception <= 0 || exception > MAX_EXCEPTION)
3445         error ("Invalid exception number, values from 1 to %d allowed",
3446                MAX_EXCEPTION);
3447       print_exception_info (exception);
3448     }
3449 }
3450 \f
3451 /* Check for actions for mach exceptions.
3452  */
3453 mach3_exception_actions (w, force_print_only, who)
3454      WAITTYPE *w;
3455      boolean_t force_print_only;
3456      char *who;
3457 {
3458   boolean_t force_print = FALSE;
3459
3460   
3461   if (force_print_only ||
3462       exception_map[stop_exception].sigmap == SIG_UNKNOWN)
3463     force_print = TRUE;
3464   else
3465     WSETSTOP (*w, exception_map[stop_exception].sigmap);
3466
3467   if (exception_map[stop_exception].print || force_print)
3468     {
3469       int giveback = grab_terminal ();
3470       
3471       printf_filtered ("\n%s received %s exception : ",
3472                        who,
3473                        exception_map[stop_exception].name);
3474       
3475       wrap_here ("   ");
3476
3477       switch(stop_exception) {
3478       case EXC_BAD_ACCESS:
3479         printf_filtered ("referencing address 0x%x : %s\n",
3480                          stop_subcode,
3481                          mach_error_string (stop_code));
3482         break;
3483       case EXC_BAD_INSTRUCTION:
3484         printf_filtered
3485           ("illegal or undefined instruction. code %d subcode %d\n",
3486            stop_code, stop_subcode);
3487         break;
3488       case EXC_ARITHMETIC:
3489         printf_filtered ("code %d\n", stop_code);
3490         break;
3491       case EXC_EMULATION:
3492         printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
3493         break;
3494       case EXC_SOFTWARE:
3495         printf_filtered ("%s specific, code 0x%x\n",
3496                          stop_code < 0xffff ? "hardware" : "os emulation",
3497                          stop_code);
3498         break;
3499       case EXC_BREAKPOINT:
3500         printf_filtered ("type %d (machine dependent)\n",
3501                          stop_code);
3502         break;
3503       default:
3504         fatal ("Unknown exception");
3505       }
3506       
3507       if (giveback)
3508         terminal_inferior ();
3509     }
3510 }
3511 \f
3512 setup_notify_port (create_new)
3513      int create_new;
3514 {
3515   kern_return_t ret;
3516
3517   if (MACH_PORT_VALID (our_notify_port))
3518     {
3519       ret = mach_port_destroy (mach_task_self (), our_notify_port);
3520       CHK ("Could not destroy our_notify_port", ret);
3521     }
3522
3523   our_notify_port = MACH_PORT_NULL;
3524   notify_chain    = (port_chain_t) NULL;
3525   port_chain_destroy (port_chain_obstack);
3526
3527   if (create_new)
3528     {
3529       ret = mach_port_allocate (mach_task_self(),
3530                                 MACH_PORT_RIGHT_RECEIVE,
3531                                 &our_notify_port);
3532       if (ret != KERN_SUCCESS)
3533         fatal("Creating notify port %s", mach_error_string(ret));
3534       
3535       ret = mach_port_move_member(mach_task_self(), 
3536                                   our_notify_port,
3537                                   inferior_wait_port_set);
3538       if (ret != KERN_SUCCESS)
3539         fatal("initial move member %s",mach_error_string(ret));
3540     }
3541 }
3542
3543 /*
3544  * Register our message port to the net name server
3545  *
3546  * Currently used only by the external stop-gdb program
3547  * since ^C does not work if you would like to enter
3548  * gdb command level while debugging your program.
3549  *
3550  * NOTE: If the message port is sometimes used for other
3551  * purposes also, the NAME must not be a guessable one.
3552  * Then, there should be a way to change it.
3553  */
3554
3555 char registered_name[ MAX_NAME_LEN ];
3556
3557 void
3558 message_port_info (args, from_tty)
3559      char *args;
3560      int from_tty;
3561 {
3562   if (registered_name[0])
3563     printf_filtered ("gdb's message port name: '%s'\n",
3564                      registered_name);
3565   else
3566     printf_filtered ("gdb's message port is not currently registered\n");
3567 }
3568
3569 void
3570 gdb_register_port (name, port)
3571      char *name;
3572      mach_port_t port;
3573 {
3574   kern_return_t ret;
3575   static int already_signed = 0;
3576   int len;
3577
3578   if (! MACH_PORT_VALID (port) || !name || !*name)
3579     {
3580       warning ("Invalid registration request");
3581       return;
3582     }
3583
3584   if (! already_signed)
3585     {
3586       ret = mach_port_insert_right (mach_task_self (),
3587                                     our_message_port,
3588                                     our_message_port,
3589                                     MACH_MSG_TYPE_MAKE_SEND);
3590       CHK ("Failed to create a signature to our_message_port", ret);
3591       already_signed = 1;
3592     }
3593   else if (already_signed > 1)
3594     {
3595       ret = netname_check_out (name_server_port,
3596                                registered_name,
3597                                our_message_port);
3598       CHK ("Failed to check out gdb's message port", ret);
3599       registered_name[0] = '\000';
3600       already_signed = 1;
3601     }
3602
3603   ret = netname_check_in (name_server_port,     /* Name server port */
3604                           name,                 /* Name of service */
3605                           our_message_port,     /* Signature */
3606                           port);                /* Creates a new send right */
3607   CHK("Failed to check in the port", ret);
3608   
3609   len = 0;
3610   while(len < MAX_NAME_LEN && *(name+len))
3611     {
3612       registered_name[len] = *(name+len);
3613       len++;
3614     }
3615   registered_name[len] = '\000';
3616   already_signed = 2;
3617 }  
3618
3619 struct cmd_list_element *cmd_thread_list;
3620 struct cmd_list_element *cmd_task_list;
3621
3622 /*ARGSUSED*/
3623 static void
3624 thread_command (arg, from_tty)
3625      char *arg;
3626      int from_tty;
3627 {
3628   printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3629   help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
3630 }
3631
3632 /*ARGSUSED*/
3633 static void
3634 task_command (arg, from_tty)
3635      char *arg;
3636      int from_tty;
3637 {
3638   printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3639   help_list (cmd_task_list, "task ", -1, gdb_stdout);
3640 }
3641
3642 add_mach_specific_commands ()
3643 {
3644   extern void condition_thread ();
3645
3646   /* Thread handling commands */
3647
3648   /* FIXME: Move our thread support into the generic thread.c stuff so we
3649      can share that code.  */
3650   add_prefix_cmd ("mthread", class_stack, thread_command,
3651       "Generic command for handling Mach threads in the debugged task.",
3652       &cmd_thread_list, "thread ", 0, &cmdlist);
3653
3654   add_com_alias ("th", "mthread", class_stack, 1);
3655
3656   add_cmd ("select", class_stack, thread_select_command, 
3657            "Select and print MID of the selected thread",
3658            &cmd_thread_list);
3659   add_cmd ("list",   class_stack, thread_list_command,
3660            "List info of task's threads. Selected thread is marked with '*'",
3661            &cmd_thread_list);
3662   add_cmd ("suspend", class_run, thread_suspend_command,
3663            "Suspend one or all of the threads in the selected task.",
3664            &cmd_thread_list);
3665   add_cmd ("resume", class_run, thread_resume_command,
3666            "Resume one or all of the threads in the selected task.",
3667            &cmd_thread_list);
3668   add_cmd ("kill", class_run, thread_kill_command,
3669            "Kill the specified thread MID from inferior task.",
3670            &cmd_thread_list);
3671   add_cmd ("break", class_breakpoint, condition_thread,
3672            "Breakpoint N will only be effective for thread MID or @SLOT\n\
3673             If MID/@SLOT is omitted allow all threads to break at breakpoint",
3674            &cmd_thread_list);
3675   /* Thread command shorthands (for backward compatibility) */
3676   add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
3677   add_alias_cmd ("tl", "mthread list",   0, 0, &cmdlist);
3678
3679   /* task handling commands */
3680
3681   add_prefix_cmd ("task", class_stack, task_command,
3682       "Generic command for handling debugged task.",
3683       &cmd_task_list, "task ", 0, &cmdlist);
3684
3685   add_com_alias ("ta", "task", class_stack, 1);
3686
3687   add_cmd ("suspend", class_run, task_suspend_command,
3688            "Suspend the inferior task.",
3689            &cmd_task_list);
3690   add_cmd ("resume", class_run, task_resume_command,
3691            "Resume the inferior task.",
3692            &cmd_task_list);
3693   add_cmd ("info", no_class, task_info_command,
3694            "Print information about the specified task.",
3695            &cmd_task_list);
3696
3697   /* Print my message port name */
3698
3699   add_info ("message-port", message_port_info,
3700             "Returns the name of gdb's message port in the netnameserver");
3701
3702   /* Exception commands */
3703
3704   add_info ("exceptions", exception_info,
3705             "What debugger does when program gets various exceptions.\n\
3706 Specify an exception number as argument to print info on that\n\
3707 exception only.");
3708
3709   add_com ("exception", class_run, exception_command,
3710            "Specify how to handle an exception.\n\
3711 Args are exception number followed by \"forward\" or \"keep\".\n\
3712 `Forward' means forward the exception to the program's normal exception\n\
3713 handler.\n\
3714 `Keep' means reenter debugger if this exception happens, and GDB maps\n\
3715 the exception to some signal (see info exception)\n\
3716 Normally \"keep\" is used to return to GDB on exception.");
3717 }
3718
3719 kern_return_t
3720 do_mach_notify_dead_name (notify, name)
3721      mach_port_t notify;
3722      mach_port_t name;
3723 {
3724   kern_return_t kr = KERN_SUCCESS;
3725
3726   /* Find the thing that notified */
3727   port_chain_t element = port_chain_member (notify_chain, name);
3728
3729   /* Take name of from unreceived dead name notification list */
3730   notify_chain = port_chain_delete (notify_chain, name);
3731
3732   if (! element)
3733     error ("Received a dead name notify from unchained port (0x%x)", name);
3734   
3735   switch (element->type) {
3736
3737   case MACH_TYPE_THREAD:
3738     target_terminal_ours_for_output ();
3739     if (name == current_thread)
3740       {
3741         printf_filtered ("\nCurrent thread %d died", element->mid);
3742         current_thread = MACH_PORT_NULL;
3743       }
3744     else
3745       printf_filtered ("\nThread %d died", element->mid);
3746
3747     break;
3748
3749   case MACH_TYPE_TASK:
3750     target_terminal_ours_for_output ();
3751     if (name != inferior_task)
3752       printf_filtered ("Task %d died, but it was not the selected task",
3753                element->mid);
3754     else               
3755       {
3756         printf_filtered ("Current task %d died", element->mid);
3757         
3758         mach_port_destroy (mach_task_self(), name);
3759         inferior_task = MACH_PORT_NULL;
3760         
3761         if (notify_chain)
3762           warning ("There were still unreceived dead_name_notifications???");
3763         
3764         /* Destroy the old notifications */
3765         setup_notify_port (0);
3766
3767       }
3768     break;
3769
3770   default:
3771     error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3772            name, element->type, element->mid);
3773     break;
3774   }
3775
3776   return KERN_SUCCESS;
3777 }
3778
3779 kern_return_t
3780 do_mach_notify_msg_accepted (notify, name)
3781      mach_port_t notify;
3782      mach_port_t name;
3783 {
3784   warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3785            notify, name);
3786   return KERN_SUCCESS;
3787 }
3788
3789 kern_return_t
3790 do_mach_notify_no_senders (notify, mscount)
3791      mach_port_t notify;
3792      mach_port_mscount_t mscount;
3793 {
3794   warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3795            notify, mscount);
3796   return KERN_SUCCESS;
3797 }
3798
3799 kern_return_t
3800 do_mach_notify_port_deleted (notify, name)
3801      mach_port_t notify;
3802      mach_port_t name;
3803 {
3804   warning ("do_mach_notify_port_deleted : notify %x, name %x",
3805            notify, name);
3806   return KERN_SUCCESS;
3807 }
3808
3809 kern_return_t
3810 do_mach_notify_port_destroyed (notify, rights)
3811      mach_port_t notify;
3812      mach_port_t rights;
3813 {
3814   warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3815            notify, rights);
3816   return KERN_SUCCESS;
3817 }
3818
3819 kern_return_t
3820 do_mach_notify_send_once (notify)
3821      mach_port_t notify;
3822 {
3823 #ifdef DUMP_SYSCALL
3824   /* MANY of these are generated. */
3825   warning ("do_mach_notify_send_once : notify %x",
3826            notify);
3827 #endif
3828   return KERN_SUCCESS;
3829 }
3830
3831 /* Kills the inferior. It's gone when you call this */
3832 static void
3833 kill_inferior_fast ()
3834 {
3835   WAITTYPE w;
3836
3837   if (inferior_pid == 0 || inferior_pid == 1)
3838     return;
3839
3840   /* kill() it, since the Unix server does not otherwise notice when
3841    * killed with task_terminate().
3842    */
3843   if (inferior_pid > 0)
3844     kill (inferior_pid, SIGKILL);
3845
3846   /* It's propably terminate already */
3847   (void) task_terminate (inferior_task);
3848
3849   inferior_task  = MACH_PORT_NULL;
3850   current_thread = MACH_PORT_NULL;
3851
3852   wait3 (&w, WNOHANG, 0);
3853
3854   setup_notify_port (0);
3855 }
3856
3857 static void
3858 m3_kill_inferior ()
3859 {
3860   kill_inferior_fast ();
3861   target_mourn_inferior ();
3862 }
3863
3864 /* Clean up after the inferior dies.  */
3865
3866 static void
3867 m3_mourn_inferior ()
3868 {
3869   unpush_target (&m3_ops);
3870   generic_mourn_inferior ();
3871 }
3872
3873 \f
3874 /* Fork an inferior process, and start debugging it.  */
3875
3876 static void
3877 m3_create_inferior (exec_file, allargs, env)
3878      char *exec_file;
3879      char *allargs;
3880      char **env;
3881 {
3882   fork_inferior (exec_file, allargs, env, m3_trace_m3, m3_trace_him);
3883   /* We are at the first instruction we care about.  */
3884   /* Pedal to the metal... */
3885   proceed ((CORE_ADDR) -1, 0, 0);
3886 }
3887
3888 /* Mark our target-struct as eligible for stray "run" and "attach"
3889    commands.  */
3890 static int
3891 m3_can_run ()
3892 {
3893   return 1;
3894 }
3895 \f
3896 /* Mach 3.0 does not need ptrace for anything
3897  * Make sure nobody uses it on mach.
3898  */
3899 ptrace (a,b,c,d)
3900 int a,b,c,d;
3901 {
3902   error ("Lose, Lose! Somebody called ptrace\n");
3903 }
3904
3905 /* Resume execution of the inferior process.
3906    If STEP is nonzero, single-step it.
3907    If SIGNAL is nonzero, give it that signal.  */
3908
3909 void
3910 m3_resume (pid, step, signal)
3911      int pid;
3912      int step;
3913      enum target_signal signal;
3914 {
3915   kern_return_t ret;
3916
3917   if (step)
3918     {
3919       thread_basic_info_data_t th_info;
3920       unsigned int             infoCnt = THREAD_BASIC_INFO_COUNT;
3921       
3922       /* There is no point in single stepping when current_thread
3923        * is dead.
3924        */
3925       if (! MACH_PORT_VALID (current_thread))
3926         error ("No thread selected; can not single step");
3927       
3928       /* If current_thread is suspended, tracing it would never return.
3929        */
3930       ret = thread_info (current_thread,
3931                          THREAD_BASIC_INFO,
3932                          (thread_info_t) &th_info,
3933                          &infoCnt);
3934       CHK ("child_resume: can't get thread info", ret);
3935       
3936       if (th_info.suspend_count)
3937         error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3938     }
3939
3940   vm_read_cache_valid = FALSE;
3941
3942   if (signal && inferior_pid > 0) /* Do not signal, if attached by MID */
3943     kill (inferior_pid, target_signal_to_host (signal));
3944
3945   if (step)
3946     {
3947       suspend_all_threads (0);
3948
3949       setup_single_step (current_thread, TRUE);
3950       
3951       ret = thread_resume (current_thread);
3952       CHK ("thread_resume", ret);
3953     }
3954   
3955   ret = task_resume (inferior_task);
3956   if (ret == KERN_FAILURE)
3957     warning ("Task was not suspended");
3958   else
3959     CHK ("Resuming task", ret);
3960   
3961   /* HACK HACK This is needed by the multiserver system HACK HACK */
3962   while ((ret = task_resume(inferior_task)) == KERN_SUCCESS)
3963     /* make sure it really runs */;
3964   /* HACK HACK This is needed by the multiserver system HACK HACK */
3965 }
3966 \f
3967 #ifdef ATTACH_DETACH
3968
3969 /* Start debugging the process with the given task */
3970 void
3971 task_attach (tid)
3972   task_t tid;
3973 {
3974   kern_return_t ret;
3975   inferior_task = tid;
3976
3977   ret = task_suspend (inferior_task);
3978   CHK("task_attach: task_suspend", ret);
3979
3980   must_suspend_thread = 0;
3981
3982   setup_notify_port (1);
3983
3984   request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
3985
3986   setup_exception_port ();
3987   
3988   emulator_present = have_emulator_p (inferior_task);
3989
3990   attach_flag = 1;
3991 }
3992
3993 /* Well, we can call error also here and leave the
3994  * target stack inconsistent. Sigh.
3995  * Fix this sometime (the only way to fail here is that
3996  * the task has no threads at all, which is rare, but
3997  * possible; or if the target task has died, which is also
3998  * possible, but unlikely, since it has been suspended.
3999  * (Someone must have killed it))
4000  */
4001 void
4002 attach_to_thread ()
4003 {
4004   if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
4005     error ("Could not select any threads to attach to");
4006 }
4007
4008 mid_attach (mid)
4009     int mid;
4010 {
4011     kern_return_t ret;
4012
4013     ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
4014     CHK("mid_attach: machid_mach_port", ret);
4015
4016     task_attach (inferior_task);
4017
4018     return mid;
4019 }
4020
4021 /* 
4022  * Start debugging the process whose unix process-id is PID.
4023  * A negative "pid" value is legal and signifies a mach_id not a unix pid.
4024  *
4025  * Prevent (possible unwanted) dangerous operations by enabled users
4026  * like "atta 0" or "atta foo" (equal to the previous :-) and
4027  * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4028  */
4029 static int
4030 m3_do_attach (pid)
4031      int pid;
4032 {
4033   kern_return_t ret;
4034
4035   if (pid == 0)
4036     error("MID=0, Debugging the master unix server does not compute");
4037
4038   /* Foo. This assumes gdb has a unix pid */
4039   if (pid == getpid())
4040     error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4041
4042   if (pid < 0)
4043     {
4044       mid_attach (-(pid));
4045
4046       /* inferior_pid will be NEGATIVE! */
4047       inferior_pid = pid;
4048
4049       return inferior_pid;
4050     }
4051
4052   inferior_task = task_by_pid (pid);
4053   if (! MACH_PORT_VALID (inferior_task))
4054     error("Cannot map Unix pid %d to Mach task port", pid);
4055
4056   task_attach (inferior_task);
4057
4058   inferior_pid = pid;
4059
4060   return inferior_pid;
4061 }
4062
4063 /* Attach to process PID, then initialize for debugging it
4064    and wait for the trace-trap that results from attaching.  */
4065
4066 static void
4067 m3_attach (args, from_tty)
4068      char *args;
4069      int from_tty;
4070 {
4071   char *exec_file;
4072   int pid;
4073
4074   if (!args)
4075     error_no_arg ("process-id to attach");
4076
4077   pid = atoi (args);
4078
4079   if (pid == getpid())          /* Trying to masturbate? */
4080     error ("I refuse to debug myself!");
4081
4082   if (from_tty)
4083     {
4084       exec_file = (char *) get_exec_file (0);
4085
4086       if (exec_file)
4087         printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
4088       else
4089         printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
4090
4091       gdb_flush (gdb_stdout);
4092     }
4093
4094   m3_do_attach (pid);
4095   inferior_pid = pid;
4096   push_target (&procfs_ops);
4097 }
4098 \f
4099 void
4100 deallocate_inferior_ports ()
4101 {
4102   kern_return_t  ret;
4103   thread_array_t thread_list;
4104   int            thread_count, index;
4105
4106   if (!MACH_PORT_VALID (inferior_task))
4107     return;
4108
4109   ret = task_threads (inferior_task, &thread_list, &thread_count);
4110   if (ret != KERN_SUCCESS)
4111     {
4112       warning ("deallocate_inferior_ports: task_threads",
4113                mach_error_string(ret));
4114       return;
4115     }
4116
4117   /* Get rid of send rights to task threads */
4118   for (index = 0; index < thread_count; index++)
4119     {
4120       int rights;
4121       ret = mach_port_get_refs (mach_task_self (),
4122                                 thread_list[index],
4123                                 MACH_PORT_RIGHT_SEND,
4124                                 &rights);
4125       CHK("deallocate_inferior_ports: get refs", ret);
4126
4127       if (rights > 0)
4128         {
4129           ret = mach_port_mod_refs (mach_task_self (),
4130                                     thread_list[index],
4131                                     MACH_PORT_RIGHT_SEND,
4132                                     -rights);
4133           CHK("deallocate_inferior_ports: mod refs", ret);
4134         }
4135     }
4136
4137   ret = mach_port_mod_refs (mach_task_self (),
4138                             inferior_exception_port,
4139                             MACH_PORT_RIGHT_RECEIVE,
4140                             -1);
4141   CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
4142
4143   ret = mach_port_deallocate (mach_task_self (),
4144                               inferior_task);
4145   CHK ("deallocate_task_port: deallocating inferior_task", ret);
4146
4147   current_thread = MACH_PORT_NULL;
4148   inferior_task  = MACH_PORT_NULL;
4149 }
4150
4151 /* Stop debugging the process whose number is PID
4152    and continue it with signal number SIGNAL.
4153    SIGNAL = 0 means just continue it.  */
4154
4155 static void
4156 m3_do_detach (signal)
4157      int signal;
4158 {
4159   kern_return_t ret;
4160
4161   MACH_ERROR_NO_INFERIOR;
4162
4163   if (current_thread != MACH_PORT_NULL)
4164     {
4165       /* Store the gdb's view of the thread we are deselecting
4166        * before we detach.
4167        * @@ I am really not sure if this is ever needeed.
4168        */
4169       target_prepare_to_store ();
4170       target_store_registers (-1);
4171     }
4172
4173   ret = task_set_special_port (inferior_task,
4174                                TASK_EXCEPTION_PORT, 
4175                                inferior_old_exception_port);
4176   CHK ("task_set_special_port", ret);
4177
4178   /* Discard all requested notifications */
4179   setup_notify_port (0);
4180
4181   if (remove_breakpoints ())
4182     warning ("Could not remove breakpoints when detaching");
4183   
4184   if (signal && inferior_pid > 0)
4185     kill (inferior_pid, signal);
4186   
4187   /* the task might be dead by now */
4188   (void) task_resume (inferior_task);
4189   
4190   deallocate_inferior_ports ();
4191   
4192   attach_flag = 0;
4193 }
4194
4195 /* Take a program previously attached to and detaches it.
4196    The program resumes execution and will no longer stop
4197    on signals, etc.  We'd better not have left any breakpoints
4198    in the program or it'll die when it hits one.  For this
4199    to work, it may be necessary for the process to have been
4200    previously attached.  It *might* work if the program was
4201    started via fork.  */
4202
4203 static void
4204 m3_detach (args, from_tty)
4205      char *args;
4206      int from_tty;
4207 {
4208   int siggnal = 0;
4209
4210   if (from_tty)
4211     {
4212       char *exec_file = get_exec_file (0);
4213       if (exec_file == 0)
4214         exec_file = "";
4215       printf_unfiltered ("Detaching from program: %s %s\n",
4216               exec_file, target_pid_to_str (inferior_pid));
4217       gdb_flush (gdb_stdout);
4218     }
4219   if (args)
4220     siggnal = atoi (args);
4221   
4222   m3_do_detach (siggnal);
4223   inferior_pid = 0;
4224   unpush_target (&m3_ops);              /* Pop out of handling an inferior */
4225 }
4226 #endif /* ATTACH_DETACH */
4227
4228 #ifdef DUMP_SYSCALL
4229 #ifdef __STDC__
4230 #define STR(x) #x
4231 #else
4232 #define STR(x) "x"
4233 #endif
4234
4235 char    *bsd1_names[] = {
4236   "execve",
4237   "fork",
4238   "take_signal",
4239   "sigreturn",
4240   "getrusage",
4241   "chdir",
4242   "chroot",
4243   "open",
4244   "creat",
4245   "mknod",
4246   "link",
4247   "symlink",
4248   "unlink",
4249   "access",
4250   "stat",
4251   "readlink",
4252   "chmod",
4253   "chown",
4254   "utimes",
4255   "truncate",
4256   "rename",
4257   "mkdir",
4258   "rmdir",
4259   "xutimes",
4260   "mount",
4261   "umount",
4262   "acct",
4263   "setquota",
4264   "write_short",
4265   "write_long",
4266   "send_short",
4267   "send_long",
4268   "sendto_short",
4269   "sendto_long",
4270   "select",
4271   "task_by_pid",
4272   "recvfrom_short",
4273   "recvfrom_long",
4274   "setgroups",
4275   "setrlimit",
4276   "sigvec",
4277   "sigstack",
4278   "settimeofday",
4279   "adjtime",
4280   "setitimer",
4281   "sethostname",
4282   "bind",
4283   "accept",
4284   "connect",
4285   "setsockopt",
4286   "getsockopt",
4287   "getsockname",
4288   "getpeername",
4289   "init_process",
4290   "table_set",
4291   "table_get",
4292   "pioctl",
4293   "emulator_error",
4294   "readwrite",
4295   "share_wakeup",
4296   0,
4297   "maprw_request_it",
4298   "maprw_release_it",
4299   "maprw_remap",
4300   "pid_by_task",
4301 };
4302
4303 int     bsd1_nnames = sizeof(bsd1_names)/sizeof(bsd1_names[0]);
4304
4305 char*
4306 name_str(name,buf)
4307
4308 int     name;
4309 char    *buf;
4310
4311 {
4312   switch (name) {
4313   case MACH_MSG_TYPE_BOOLEAN:
4314     return "boolean";
4315   case MACH_MSG_TYPE_INTEGER_16:
4316     return "short";
4317   case MACH_MSG_TYPE_INTEGER_32:
4318     return "long";
4319   case MACH_MSG_TYPE_CHAR:
4320     return "char";
4321   case MACH_MSG_TYPE_BYTE:
4322     return "byte";
4323   case MACH_MSG_TYPE_REAL:
4324     return "real";
4325   case MACH_MSG_TYPE_STRING:
4326     return "string";
4327   default:
4328     sprintf(buf,"%d",name);
4329     return buf;
4330   }
4331 }
4332
4333 char *
4334 id_str(id,buf)
4335
4336 int     id;
4337 char    *buf;
4338
4339 {
4340   char  *p;
4341   if (id >= 101000 && id < 101000+bsd1_nnames) {
4342     if (p = bsd1_names[id-101000])
4343       return p;
4344   }
4345   if (id == 102000)
4346     return "psignal_retry";
4347   if (id == 100000)
4348     return "syscall";
4349   sprintf(buf,"%d",id);
4350   return buf;
4351 }
4352
4353 print_msg(mp)
4354 mach_msg_header_t       *mp;
4355 {
4356   char  *fmt_x = "%20s : 0x%08x\n";
4357   char  *fmt_d = "%20s : %10d\n";
4358   char  *fmt_s = "%20s : %s\n";
4359   char  buf[100];
4360
4361   puts_filtered ("\n");
4362 #define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
4363   pr(fmt_x,(*mp),msgh_bits);
4364   pr(fmt_d,(*mp),msgh_size);
4365   pr(fmt_x,(*mp),msgh_remote_port);
4366   pr(fmt_x,(*mp),msgh_local_port);
4367   pr(fmt_d,(*mp),msgh_kind);
4368   printf_filtered(fmt_s,STR(msgh_id),id_str(mp->msgh_id,buf));
4369   
4370   if (debug_level > 1)
4371   {
4372     char        *p,*ep,*dp;
4373     int         plen;
4374     p = (char*)mp;
4375     ep = p+mp->msgh_size;
4376     p += sizeof(*mp);
4377     for(; p < ep; p += plen) {
4378       mach_msg_type_t   *tp;
4379       mach_msg_type_long_t      *tlp;
4380       int       name,size,number;
4381       tp = (mach_msg_type_t*)p;
4382       if (tp->msgt_longform) {
4383         tlp = (mach_msg_type_long_t*)tp;
4384         name = tlp->msgtl_name;
4385         size = tlp->msgtl_size;
4386         number = tlp->msgtl_number;
4387         plen = sizeof(*tlp);
4388       } else {
4389         name = tp->msgt_name;
4390         size = tp->msgt_size;
4391         number = tp->msgt_number;
4392         plen = sizeof(*tp);
4393       }
4394       printf_filtered("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4395                       name_str(name,buf),size,number,tp->msgt_inline,
4396                       tp->msgt_longform, tp->msgt_deallocate);
4397       dp = p+plen;
4398       if (tp->msgt_inline) {
4399         int     l;
4400         l = size*number/8;
4401         l = (l+sizeof(long)-1)&~((sizeof(long))-1);
4402         plen += l;
4403         print_data(dp,size,number);
4404       } else {
4405         plen += sizeof(int*);
4406       }
4407       printf_filtered("plen=%d\n",plen);
4408     }
4409   }
4410 }
4411
4412 print_data(p,size,number)
4413
4414 char    *p;
4415
4416 {
4417   int   *ip;
4418   short *sp;
4419   int   i;
4420
4421   switch (size) {
4422   case 8:
4423     for(i = 0; i < number; i++) {
4424       printf_filtered(" %02x",p[i]);
4425     }
4426     break;
4427   case 16:
4428     sp = (short*)p;
4429     for(i = 0; i < number; i++) {
4430       printf_filtered(" %04x",sp[i]);
4431     }
4432     break;
4433   case 32:
4434     ip = (int*)p;
4435     for(i = 0; i < number; i++) {
4436       printf_filtered(" %08x",ip[i]);
4437     }
4438     break;
4439   }
4440   puts_filtered("\n");
4441 }
4442 #endif  DUMP_SYSCALL
4443
4444 struct target_ops m3_ops = {
4445   "mach",                       /* to_shortname */
4446   "Mach child process", /* to_longname */
4447   "Mach child process (started by the \"run\" command).",       /* to_doc */
4448   ??_open,                      /* to_open */
4449   0,                            /* to_close */
4450   m3_attach,                    /* to_attach */
4451   m3_detach,            /* to_detach */
4452   m3_resume,                    /* to_resume */
4453   mach_really_wait,                     /* to_wait */
4454   fetch_inferior_registers,     /* to_fetch_registers */
4455   store_inferior_registers,     /* to_store_registers */
4456   child_prepare_to_store,       /* to_prepare_to_store */
4457   m3_xfer_memory,               /* to_xfer_memory */
4458
4459   /* FIXME: Should print MID and all that crap.  */
4460   child_files_info,             /* to_files_info */
4461
4462   memory_insert_breakpoint,     /* to_insert_breakpoint */
4463   memory_remove_breakpoint,     /* to_remove_breakpoint */
4464   terminal_init_inferior,       /* to_terminal_init */
4465   terminal_inferior,            /* to_terminal_inferior */
4466   terminal_ours_for_output,     /* to_terminal_ours_for_output */
4467   terminal_ours,                /* to_terminal_ours */
4468   child_terminal_info,          /* to_terminal_info */
4469   m3_kill_inferior,             /* to_kill */
4470   0,                            /* to_load */
4471   0,                            /* to_lookup_symbol */
4472
4473   m3_create_inferior,   /* to_create_inferior */
4474   m3_mourn_inferior,    /* to_mourn_inferior */
4475   m3_can_run,           /* to_can_run */
4476   0,                            /* to_notice_signals */
4477   process_stratum,              /* to_stratum */
4478   0,                            /* to_next */
4479   1,                            /* to_has_all_memory */
4480   1,                            /* to_has_memory */
4481   1,                            /* to_has_stack */
4482   1,                            /* to_has_registers */
4483   1,                            /* to_has_execution */
4484   0,                            /* sections */
4485   0,                            /* sections_end */
4486   OPS_MAGIC                     /* to_magic */
4487 };
4488
4489 void
4490 _initialize_m3_nat ()
4491 {
4492   kern_return_t ret;
4493
4494   add_target (&m3_ops);
4495
4496   ret = mach_port_allocate(mach_task_self(), 
4497                            MACH_PORT_RIGHT_PORT_SET,
4498                            &inferior_wait_port_set);
4499   if (ret != KERN_SUCCESS)
4500     fatal("initial port set %s",mach_error_string(ret));
4501
4502   /* mach_really_wait now waits for this */
4503   currently_waiting_for = inferior_wait_port_set;
4504
4505   ret = netname_look_up(name_server_port, hostname, "MachID", &mid_server);
4506   if (ret != KERN_SUCCESS)
4507     {
4508       mid_server = MACH_PORT_NULL;
4509       
4510       warning ("initialize machid: netname_lookup_up(MachID) : %s",
4511                mach_error_string(ret));
4512       warning ("Some (most?) features disabled...");
4513     }
4514   
4515   mid_auth = mach_privileged_host_port();
4516   if (mid_auth == MACH_PORT_NULL)
4517     mid_auth = mach_task_self();
4518   
4519   obstack_init (port_chain_obstack);
4520
4521   ret = mach_port_allocate (mach_task_self (), 
4522                             MACH_PORT_RIGHT_RECEIVE,
4523                             &thread_exception_port);
4524   CHK ("Creating thread_exception_port for single stepping", ret);
4525   
4526   ret = mach_port_insert_right (mach_task_self (),
4527                                 thread_exception_port,
4528                                 thread_exception_port,
4529                                 MACH_MSG_TYPE_MAKE_SEND);
4530   CHK ("Inserting send right to thread_exception_port", ret);
4531
4532   /* Allocate message port */
4533   ret = mach_port_allocate (mach_task_self (),
4534                             MACH_PORT_RIGHT_RECEIVE,
4535                             &our_message_port);
4536   if (ret != KERN_SUCCESS)
4537     warning ("Creating message port %s", mach_error_string (ret));
4538   else
4539     {
4540       char buf[ MAX_NAME_LEN ];
4541       ret = mach_port_move_member(mach_task_self (),
4542                                   our_message_port,
4543                                   inferior_wait_port_set);
4544       if (ret != KERN_SUCCESS)
4545         warning ("message move member %s", mach_error_string (ret));
4546
4547
4548       /* @@@@ No way to change message port name currently */
4549       /* Foo. This assumes gdb has a unix pid */
4550       sprintf (buf, "gdb-%d", getpid ());
4551       gdb_register_port (buf, our_message_port);
4552     }
4553   
4554   /* Heap for thread commands */
4555   obstack_init (cproc_obstack);
4556
4557   add_mach_specific_commands ();
4558 }