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