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