home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / gdb-4.14-src.lha / gdb-4.14 / gdb / m3-nat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-10  |  114.1 KB  |  4,640 lines

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