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