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