OSDN Git Service

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