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