1 /* Interface GDB to Mach 3.0 operating systems.
2 (Most) Mach 3.0 related routines live in this file.
4 Copyright (C) 1992, 1996, 1999-2000 Free Software Foundation, Inc.
6 This file is part of GDB.
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.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
26 * Helsinki University of Technology
29 * Thanks to my friends who helped with ideas and testing:
31 * Johannes Helander, Antti Louko, Tero Mononen,
34 * Tero Kivinen and Eamonn McManus
42 #include <servers/netname.h>
43 #include <servers/machid.h>
44 #include <mach/message.h>
45 #include <mach/notify.h>
46 #include <mach_error.h>
47 #include <mach/exception.h>
48 #include <mach/vm_attributes.h>
61 #include <servers/machid_lib.h>
63 #define MACH_TYPE_TASK 1
64 #define MACH_TYPE_THREAD 2
67 /* Included only for signal names and NSIG
69 * note: There are many problems in signal handling with
70 * gdb in Mach 3.0 in general.
73 #define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
77 /* This is what a cproc looks like. This is here partly because
78 cthread_internals.h is not a header we can just #include, partly with
79 an eye towards perhaps getting this to work with cross-debugging
80 someday. Best solution is if CMU publishes a real interface to this
82 #define CPROC_NEXT_OFFSET 0
83 #define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
84 #define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
85 #define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
86 #define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
87 #define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
88 #define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
89 #define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
90 #define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
91 #define CPROC_REPLY_SIZE (sizeof (mach_port_t))
92 #define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
93 #define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
94 #define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
95 #define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
96 #define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
97 #define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
98 #define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
99 #define CPROC_WIRED_SIZE (sizeof (mach_port_t))
100 #define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
101 #define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
102 #define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
103 #define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
104 #define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
105 #define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
106 #define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
107 #define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
108 #define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
110 /* Values for the state field in the cproc. */
111 #define CPROC_RUNNING 0
112 #define CPROC_SWITCHING 1
113 #define CPROC_BLOCKED 2
114 #define CPROC_CONDWAIT 4
116 /* For cproc and kernel thread mapping */
117 typedef struct gdb_thread
123 boolean_t in_emulator;
126 /* This is for the mthreads list. It points to the cproc list.
127 Perhaps the two lists should be merged (or perhaps it was a mistake
128 to make them both use a struct gdb_thread). */
129 struct gdb_thread *cproc;
131 /* These are for the cproc list, which is linked through the next field
132 of the struct gdb_thread. */
133 char raw_cproc[CPROC_SIZE];
134 /* The cthread which is pointed to by the incarnation field from the
135 cproc. This points to the copy we've read into GDB. */
137 /* Point back to the mthreads list. */
139 struct gdb_thread *next;
144 * Actions for Mach exceptions.
146 * sigmap field maps the exception to corresponding Unix signal.
148 * I do not know how to map the exception to unix signal
149 * if SIG_UNKNOWN is specified.
152 struct exception_list
162 "not_mach3_exception", FALSE, TRUE, SIG_UNKNOWN
166 "EXC_BAD_ACCESS", FALSE, TRUE, SIGSEGV
170 "EXC_BAD_INSTRUCTION", FALSE, TRUE, SIGILL
174 "EXC_ARITHMETIC", FALSE, TRUE, SIGFPE
178 "EXC_EMULATION", FALSE, TRUE, SIGEMT
182 "EXC_SOFTWARE", FALSE, TRUE, SIG_UNKNOWN
186 "EXC_BREAKPOINT", FALSE, FALSE, SIGTRAP
190 /* Mach exception table size */
191 int max_exception = sizeof (exception_map) / sizeof (struct exception_list) - 1;
193 #define MAX_EXCEPTION max_exception
195 WAITTYPE wait_status;
197 /* If you define this, intercepted bsd server calls will be
198 * dumped while waiting the inferior to EXEC the correct
201 /* #define DUMP_SYSCALL /* debugging interceptor */
203 /* xx_debug() outputs messages if this is nonzero.
204 * If > 1, DUMP_SYSCALL will dump message contents.
208 /* "Temporary" debug stuff */
210 xx_debug (fmt, a, b, c)
215 warning (fmt, a, b, c);
218 /* This is in libmach.a */
219 extern mach_port_t name_server_port;
221 /* Set in catch_exception_raise */
222 int stop_exception, stop_code, stop_subcode;
223 int stopped_in_exception;
225 /* Thread that was the active thread when we stopped */
226 thread_t stop_thread = MACH_PORT_NULL;
230 /* Set when task is attached or created */
231 boolean_t emulator_present = FALSE;
233 task_t inferior_task;
234 thread_t current_thread;
236 /* Exception ports for inferior task */
237 mach_port_t inferior_exception_port = MACH_PORT_NULL;
238 mach_port_t inferior_old_exception_port = MACH_PORT_NULL;
240 /* task exceptions and notifications */
241 mach_port_t inferior_wait_port_set = MACH_PORT_NULL;
242 mach_port_t our_notify_port = MACH_PORT_NULL;
244 /* This is "inferior_wait_port_set" when not single stepping, and
245 * "singlestepped_thread_port" when we are single stepping.
247 * This is protected by a cleanup function: discard_single_step()
249 mach_port_t currently_waiting_for = MACH_PORT_NULL;
251 /* A port for external messages to gdb.
252 * External in the meaning that they do not come
253 * from the inferior_task, but rather from external
256 * As a debugging feature:
257 * A debugger debugging another debugger can stop the
258 * inferior debugger by the following command sequence
259 * (without running external programs)
261 * (top-gdb) set stop_inferior_gdb ()
264 mach_port_t our_message_port = MACH_PORT_NULL;
266 /* For single stepping */
267 mach_port_t thread_exception_port = MACH_PORT_NULL;
268 mach_port_t thread_saved_exception_port = MACH_PORT_NULL;
269 mach_port_t singlestepped_thread_port = MACH_PORT_NULL;
271 /* For machid calls */
272 mach_port_t mid_server = MACH_PORT_NULL;
273 mach_port_t mid_auth = MACH_PORT_NULL;
275 /* If gdb thinks the inferior task is not suspended, it
276 * must take suspend/abort the threads when it reads the state.
278 int must_suspend_thread = 0;
280 /* When single stepping, we switch the port that mach_really_wait() listens to.
281 * This cleanup is a guard to prevent the port set from being left to
282 * the singlestepped_thread_port when error() is called.
283 * This is nonzero only when we are single stepping.
285 #define NULL_CLEANUP (struct cleanup *)0
286 struct cleanup *cleanup_step = NULL_CLEANUP;
289 static struct target_ops m3_ops;
291 static void m3_kill_inferior ();
294 #define MACH_TYPE_EXCEPTION_PORT -1
297 /* Chain of ports to remember requested notifications. */
301 struct port_chain *next;
304 int mid; /* Now only valid with MACH_TYPE_THREAD and */
305 /* MACH_TYPE_THREAD */
307 typedef struct port_chain *port_chain_t;
309 /* Room for chain nodes comes from pchain_obstack */
310 struct obstack pchain_obstack;
311 struct obstack *port_chain_obstack = &pchain_obstack;
313 /* For thread handling */
314 struct obstack Cproc_obstack;
315 struct obstack *cproc_obstack = &Cproc_obstack;
317 /* the list of notified ports */
318 port_chain_t notify_chain = (port_chain_t) NULL;
321 port_chain_insert (list, name, type)
330 if (!MACH_PORT_VALID (name))
333 if (type == MACH_TYPE_TASK || type == MACH_TYPE_THREAD)
335 if (!MACH_PORT_VALID (mid_server))
337 warning ("Machid server port invalid, can not map port 0x%x to MID",
343 ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
345 if (ret != KERN_SUCCESS)
347 warning ("Can not map name (0x%x) to MID with machid", name);
355 new = (port_chain_t) obstack_alloc (port_chain_obstack,
356 sizeof (struct port_chain));
366 port_chain_delete (list, elem)
371 if (list->port == elem)
376 if (list->next->port == elem)
377 list->next = list->next->next; /* GCd with obstack_free() */
385 port_chain_destroy (ostack)
386 struct obstack *ostack;
388 obstack_free (ostack, 0);
389 obstack_init (ostack);
393 port_chain_member (list, elem)
399 if (list->port == elem)
403 return (port_chain_t) NULL;
407 map_port_name_to_mid (name, type)
413 if (!MACH_PORT_VALID (name))
416 elem = port_chain_member (notify_chain, name);
418 if (elem && (elem->type == type))
424 if (!MACH_PORT_VALID (mid_server))
426 warning ("Machid server port invalid, can not map port 0x%x to mid",
435 ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
437 if (ret != KERN_SUCCESS)
439 warning ("Can not map name (0x%x) to mid with machid", name);
446 /* Guard for currently_waiting_for and singlestepped_thread_port */
448 discard_single_step (thread)
451 currently_waiting_for = inferior_wait_port_set;
453 cleanup_step = NULL_CLEANUP;
454 if (MACH_PORT_VALID (thread) && MACH_PORT_VALID (singlestepped_thread_port))
455 setup_single_step (thread, FALSE);
458 setup_single_step (thread, start_step)
460 boolean_t start_step;
464 if (!MACH_PORT_VALID (thread))
465 error ("Invalid thread supplied to setup_single_step");
470 /* Get the current thread exception port */
471 ret = thread_get_exception_port (thread, &teport);
472 CHK ("Getting thread's exception port", ret);
476 if (MACH_PORT_VALID (singlestepped_thread_port))
478 warning ("Singlestepped_thread_port (0x%x) is still valid?",
479 singlestepped_thread_port);
480 singlestepped_thread_port = MACH_PORT_NULL;
483 /* If we are already stepping this thread */
484 if (MACH_PORT_VALID (teport) && teport == thread_exception_port)
486 ret = mach_port_deallocate (mach_task_self (), teport);
487 CHK ("Could not deallocate thread exception port", ret);
491 ret = thread_set_exception_port (thread, thread_exception_port);
492 CHK ("Setting exception port for thread", ret);
494 /* Insert thread exception port to wait port set */
495 ret = mach_port_move_member (mach_task_self (),
496 thread_exception_port,
497 inferior_wait_port_set);
498 CHK ("Moving thread exception port to inferior_wait_port_set",
501 thread_saved_exception_port = teport;
504 thread_trace (thread, TRUE);
506 singlestepped_thread_port = thread_exception_port;
507 currently_waiting_for = singlestepped_thread_port;
508 cleanup_step = make_cleanup (discard_single_step, thread);
512 if (!MACH_PORT_VALID (teport))
513 error ("Single stepped thread had an invalid exception port?");
515 if (teport != thread_exception_port)
516 error ("Single stepped thread had an unknown exception port?");
518 ret = mach_port_deallocate (mach_task_self (), teport);
519 CHK ("Couldn't deallocate thread exception port", ret);
521 /* Remove thread exception port from wait port set */
522 ret = mach_port_move_member (mach_task_self (),
523 thread_exception_port,
525 CHK ("Removing thread exception port from inferior_wait_port_set",
528 /* Restore thread's old exception port */
529 ret = thread_set_exception_port (thread,
530 thread_saved_exception_port);
531 CHK ("Restoring stepped thread's exception port", ret);
533 if (MACH_PORT_VALID (thread_saved_exception_port))
534 (void) mach_port_deallocate (mach_task_self (),
535 thread_saved_exception_port);
537 thread_trace (thread, FALSE);
539 singlestepped_thread_port = MACH_PORT_NULL;
540 currently_waiting_for = inferior_wait_port_set;
542 discard_cleanups (cleanup_step);
548 request_notify (name, variant, type)
550 mach_msg_id_t variant;
554 mach_port_t previous_port_dummy = MACH_PORT_NULL;
556 if (!MACH_PORT_VALID (name))
559 if (port_chain_member (notify_chain, name))
562 ret = mach_port_request_notification (mach_task_self (),
567 MACH_MSG_TYPE_MAKE_SEND_ONCE,
568 &previous_port_dummy);
569 CHK ("Serious: request_notify failed", ret);
571 (void) mach_port_deallocate (mach_task_self (),
572 previous_port_dummy);
574 notify_chain = port_chain_insert (notify_chain, name, type);
577 reverse_msg_bits (msgp, type)
578 mach_msg_header_t *msgp;
582 rbits = MACH_MSGH_BITS_REMOTE (msgp->msgh_bits);
585 (msgp->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
586 MACH_MSGH_BITS (lbits, rbits);
589 /* On the third day He said:
592 and then it was global.
594 When creating the inferior fork, the
595 child code in inflow.c sets the name of the
596 bootstrap_port in its address space to this
599 The name is transferred to our address space
600 with mach3_read_inferior().
602 Thou shalt not do this with
603 task_get_bootstrap_port() in this task, since
604 the name in the inferior task is different than
607 For blessed are the meek, as they shall inherit
610 mach_port_t original_server_port_name = MACH_PORT_NULL;
613 /* Called from inferior after FORK but before EXEC */
619 /* Get the NAME of the bootstrap port in this task
620 so that GDB can read it */
621 ret = task_get_bootstrap_port (mach_task_self (),
622 &original_server_port_name);
623 if (ret != KERN_SUCCESS)
625 ret = mach_port_deallocate (mach_task_self (),
626 original_server_port_name);
627 if (ret != KERN_SUCCESS)
630 /* Suspend this task to let the parent change my ports.
631 Resumed by the debugger */
632 ret = task_suspend (mach_task_self ());
633 if (ret != KERN_SUCCESS)
638 * Intercept system calls to Unix server.
639 * After EXEC_COUNTER calls to exec(), return.
641 * Pre-assertion: Child is suspended. (Not verified)
642 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
646 intercept_exec_calls (exec_counter)
649 int terminal_initted = 0;
653 mach_msg_header_t header;
654 mach_msg_type_t type;
655 char room[2000]; /* Enuff space */
658 struct syscall_msg_t syscall_in, syscall_out;
660 mach_port_t fake_server;
661 mach_port_t original_server_send;
662 mach_port_t original_exec_reply;
663 mach_port_t exec_reply;
664 mach_port_t exec_reply_send;
665 mach_msg_type_name_t acquired;
666 mach_port_t emulator_server_port_name;
667 struct task_basic_info info;
668 mach_msg_type_number_t info_count;
672 if (exec_counter <= 0)
673 return; /* We are already set up in the correct program */
675 ret = mach_port_allocate (mach_task_self (),
676 MACH_PORT_RIGHT_RECEIVE,
678 CHK ("create inferior_fake_server port failed", ret);
680 /* Wait for inferior_task to suspend itself */
683 info_count = sizeof (info);
684 ret = task_info (inferior_task,
686 (task_info_t) & info,
688 CHK ("Task info", ret);
690 if (info.suspend_count)
693 /* Note that the definition of the parameter was undefined
694 * at the time of this writing, so I just use an `ad hoc' value.
696 (void) swtch_pri (42); /* Universal Priority Value */
699 /* Read the inferior's bootstrap port name */
700 if (!mach3_read_inferior (&original_server_port_name,
701 &original_server_port_name,
702 sizeof (original_server_port_name)))
703 error ("Can't read inferior task bootstrap port name");
705 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
706 /* Should get refs, and set them back when restoring */
707 /* Steal the original bsd server send right from inferior */
708 ret = mach_port_extract_right (inferior_task,
709 original_server_port_name,
710 MACH_MSG_TYPE_MOVE_SEND,
711 &original_server_send,
713 CHK ("mach_port_extract_right (bsd server send)", ret);
715 if (acquired != MACH_MSG_TYPE_PORT_SEND)
716 error ("Incorrect right extracted, send right to bsd server excpected");
718 ret = mach_port_insert_right (inferior_task,
719 original_server_port_name,
721 MACH_MSG_TYPE_MAKE_SEND);
722 CHK ("mach_port_insert_right (fake server send)", ret);
724 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
726 original_server_port_name, original_server_send);
728 /* A receive right to the reply generated by unix server exec() request */
729 ret = mach_port_allocate (mach_task_self (),
730 MACH_PORT_RIGHT_RECEIVE,
732 CHK ("create intercepted_reply_port port failed", ret);
734 /* Pass this send right to Unix server so it replies to us after exec() */
735 ret = mach_port_extract_right (mach_task_self (),
737 MACH_MSG_TYPE_MAKE_SEND_ONCE,
740 CHK ("mach_port_extract_right (exec_reply)", ret);
742 if (acquired != MACH_MSG_TYPE_PORT_SEND_ONCE)
743 error ("Incorrect right extracted, send once excpected for exec reply");
745 ret = mach_port_move_member (mach_task_self (),
747 inferior_wait_port_set);
748 CHK ("Moving fake syscall port to inferior_wait_port_set", ret);
750 xx_debug ("syscall fake server set up, resuming inferior\n");
752 ret = task_resume (inferior_task);
753 CHK ("task_resume (startup)", ret);
755 /* Read requests from the inferior.
756 Pass directly through everything else except exec() calls.
758 while (exec_counter > 0)
760 ret = mach_msg (&syscall_in.header, /* header */
761 MACH_RCV_MSG, /* options */
763 sizeof (struct syscall_msg_t), /* receive size */
764 inferior_wait_port_set, /* receive_name */
765 MACH_MSG_TIMEOUT_NONE,
767 CHK ("mach_msg (intercepted sycall)", ret);
770 print_msg (&syscall_in.header);
773 /* ASSERT : msgh_local_port == fake_server */
775 if (notify_server (&syscall_in.header, &syscall_out.header))
776 error ("received a notify while intercepting syscalls");
778 if (syscall_in.header.msgh_id == MIG_EXEC_SYSCALL_ID)
780 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter);
781 if (exec_counter == 1)
783 original_exec_reply = syscall_in.header.msgh_remote_port;
784 syscall_in.header.msgh_remote_port = exec_reply_send;
787 if (!terminal_initted)
789 /* Now that the child has exec'd we know it has already set its
790 process group. On POSIX systems, tcsetpgrp will fail with
791 EPERM if we try it before the child's setpgid. */
793 /* Set up the "saved terminal modes" of the inferior
794 based on what modes we are starting it with. */
795 target_terminal_init ();
797 /* Install inferior's terminal modes. */
798 target_terminal_inferior ();
800 terminal_initted = 1;
806 syscall_in.header.msgh_local_port = syscall_in.header.msgh_remote_port;
807 syscall_in.header.msgh_remote_port = original_server_send;
809 reverse_msg_bits (&syscall_in.header, MACH_MSG_TYPE_COPY_SEND);
811 ret = mach_msg_send (&syscall_in.header);
812 CHK ("Forwarded syscall", ret);
815 ret = mach_port_move_member (mach_task_self (),
818 CHK ("Moving fake syscall out of inferior_wait_port_set", ret);
820 ret = mach_port_move_member (mach_task_self (),
822 inferior_wait_port_set);
823 CHK ("Moving exec_reply to inferior_wait_port_set", ret);
825 ret = mach_msg (&syscall_in.header, /* header */
826 MACH_RCV_MSG, /* options */
828 sizeof (struct syscall_msg_t), /* receive size */
829 inferior_wait_port_set, /* receive_name */
830 MACH_MSG_TIMEOUT_NONE,
832 CHK ("mach_msg (exec reply)", ret);
834 ret = task_suspend (inferior_task);
835 CHK ("Suspending inferior after last exec", ret);
837 must_suspend_thread = 0;
839 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
842 print_msg (&syscall_in.header);
845 /* Message should appear as if it came from the unix server */
846 syscall_in.header.msgh_local_port = MACH_PORT_NULL;
848 /* and go to the inferior task original reply port */
849 syscall_in.header.msgh_remote_port = original_exec_reply;
851 reverse_msg_bits (&syscall_in.header, MACH_MSG_TYPE_MOVE_SEND_ONCE);
853 ret = mach_msg_send (&syscall_in.header);
854 CHK ("Forwarding exec reply to inferior", ret);
856 /* Garbage collect */
857 ret = mach_port_deallocate (inferior_task,
858 original_server_port_name);
859 CHK ("deallocating fake server send right", ret);
861 ret = mach_port_insert_right (inferior_task,
862 original_server_port_name,
863 original_server_send,
864 MACH_MSG_TYPE_MOVE_SEND);
865 CHK ("Restoring the original bsd server send right", ret);
867 ret = mach_port_destroy (mach_task_self (),
869 fake_server = MACH_PORT_DEAD;
870 CHK ("mach_port_destroy (fake_server)", ret);
872 ret = mach_port_destroy (mach_task_self (),
874 exec_reply = MACH_PORT_DEAD;
875 CHK ("mach_port_destroy (exec_reply)", ret);
877 xx_debug ("Done with exec call interception\n");
881 consume_send_rights (thread_list, thread_count)
882 thread_array_t thread_list;
890 for (index = 0; index < thread_count; index++)
892 /* Since thread kill command kills threads, don't check ret */
893 (void) mach_port_deallocate (mach_task_self (),
898 /* suspend/abort/resume a thread. */
899 setup_thread (thread, what)
907 ret = thread_suspend (thread);
908 CHK ("setup_thread thread_suspend", ret);
910 ret = thread_abort (thread);
911 CHK ("setup_thread thread_abort", ret);
915 ret = thread_resume (thread);
916 CHK ("setup_thread thread_resume", ret);
921 map_slot_to_mid (slot, threads, thread_count)
923 thread_array_t threads;
934 ret = task_threads (inferior_task, &threads, &thread_count);
935 CHK ("Can not select a thread from a dead task", ret);
938 if (slot < 0 || slot >= thread_count)
942 consume_send_rights (threads, thread_count);
943 (void) vm_deallocate (mach_task_self (), (vm_address_t) threads,
944 (thread_count * sizeof (mach_port_t)));
947 error ("invalid slot number");
952 mid = map_port_name_to_mid (threads[slot], MACH_TYPE_THREAD);
956 consume_send_rights (threads, thread_count);
957 (void) vm_deallocate (mach_task_self (), (vm_address_t) threads,
958 (thread_count * sizeof (mach_port_t)));
965 parse_thread_id (arg, thread_count, slots)
978 while (*arg && (*arg == ' ' || *arg == '\t'))
984 /* Currently parse MID and @SLOTNUMBER */
989 error ("valid thread mid expected");
997 error ("invalid slot number");
999 /* If you want slot numbers to remain slot numbers, set slots.
1001 * Well, since 0 is reserved, return the ordinal number
1002 * of the thread rather than the slot number. Awk, this
1003 * counts as a kludge.
1008 if (thread_count && slot >= thread_count)
1011 mid = map_slot_to_mid (slot);
1016 /* THREAD_ID 0 is special; it selects the first kernel
1017 * thread from the list (i.e. SLOTNUMBER 0)
1018 * This is used when starting the program with 'run' or when attaching.
1020 * If FLAG is 0 the context is not changed, and the registers, frame, etc
1021 * will continue to describe the old thread.
1023 * If FLAG is nonzero, really select the thread.
1024 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
1028 select_thread (task, thread_id, flag)
1033 thread_array_t thread_list;
1037 thread_t new_thread = MACH_PORT_NULL;
1040 error ("Can't select cprocs without kernel thread");
1042 ret = task_threads (task, &thread_list, &thread_count);
1043 if (ret != KERN_SUCCESS)
1045 warning ("Can not select a thread from a dead task");
1046 m3_kill_inferior ();
1047 return KERN_FAILURE;
1050 if (thread_count == 0)
1052 /* The task can not do anything anymore, but it still
1053 * exists as a container for memory and ports.
1055 registers_changed ();
1056 warning ("Task %d has no threads",
1057 map_port_name_to_mid (task, MACH_TYPE_TASK));
1058 current_thread = MACH_PORT_NULL;
1059 (void) vm_deallocate (mach_task_self (),
1060 (vm_address_t) thread_list,
1061 (thread_count * sizeof (mach_port_t)));
1062 return KERN_FAILURE;
1065 if (!thread_id || flag == 2)
1067 /* First thread or a slotnumber */
1069 new_thread = thread_list[0];
1072 if (thread_id < thread_count)
1073 new_thread = thread_list[thread_id];
1076 (void) vm_deallocate (mach_task_self (),
1077 (vm_address_t) thread_list,
1078 (thread_count * sizeof (mach_port_t)));
1079 error ("No such thread slot number : %d", thread_id);
1085 for (index = 0; index < thread_count; index++)
1086 if (thread_id == map_port_name_to_mid (thread_list[index],
1089 new_thread = thread_list[index];
1095 error ("No thread with mid %d", thread_id);
1098 /* Notify when the selected thread dies */
1099 request_notify (new_thread, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_THREAD);
1101 ret = vm_deallocate (mach_task_self (),
1102 (vm_address_t) thread_list,
1103 (thread_count * sizeof (mach_port_t)));
1104 CHK ("vm_deallocate", ret);
1107 current_thread = new_thread;
1111 if (MACH_PORT_VALID (current_thread))
1113 /* Store the gdb's view of the thread we are deselecting
1115 * @@ I think gdb updates registers immediately when they are
1116 * changed, so don't do this.
1118 ret = thread_abort (current_thread);
1119 CHK ("Could not abort system calls when saving state of old thread",
1121 target_prepare_to_store ();
1122 target_store_registers (-1);
1126 registers_changed ();
1128 current_thread = new_thread;
1130 ret = thread_abort (current_thread);
1131 CHK ("Could not abort system calls when selecting a thread", ret);
1133 stop_pc = read_pc ();
1134 flush_cached_frames ();
1136 select_frame (get_current_frame (), 0);
1139 return KERN_SUCCESS;
1143 * Switch to use thread named NEW_THREAD.
1147 switch_to_thread (new_thread)
1148 thread_t new_thread;
1150 thread_t saved_thread = current_thread;
1153 mid = map_port_name_to_mid (new_thread,
1156 warning ("Can't map thread name 0x%x to mid", new_thread);
1157 else if (select_thread (inferior_task, mid, 1) != KERN_SUCCESS)
1160 current_thread = saved_thread;
1161 error ("Could not select thread %d", mid);
1167 /* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1168 * Note that the registers are not yet valid in the inferior task.
1176 push_target (&m3_ops);
1178 inferior_task = task_by_pid (pid);
1180 if (!MACH_PORT_VALID (inferior_task))
1181 error ("Can not map Unix pid %d to Mach task", pid);
1183 /* Clean up previous notifications and create new ones */
1184 setup_notify_port (1);
1186 /* When notification appears, the inferior task has died */
1187 request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
1189 emulator_present = have_emulator_p (inferior_task);
1191 /* By default, select the first thread,
1192 * If task has no threads, gives a warning
1193 * Does not fetch registers, since they are not yet valid.
1195 select_thread (inferior_task, 0, 0);
1197 inferior_exception_port = MACH_PORT_NULL;
1199 setup_exception_port ();
1201 xx_debug ("Now the debugged task is created\n");
1203 /* One trap to exec the shell, one to exec the program being debugged. */
1204 intercept_exec_calls (2);
1209 setup_exception_port ()
1213 ret = mach_port_allocate (mach_task_self (),
1214 MACH_PORT_RIGHT_RECEIVE,
1215 &inferior_exception_port);
1216 CHK ("mach_port_allocate", ret);
1218 /* add send right */
1219 ret = mach_port_insert_right (mach_task_self (),
1220 inferior_exception_port,
1221 inferior_exception_port,
1222 MACH_MSG_TYPE_MAKE_SEND);
1223 CHK ("mach_port_insert_right", ret);
1225 ret = mach_port_move_member (mach_task_self (),
1226 inferior_exception_port,
1227 inferior_wait_port_set);
1228 CHK ("mach_port_move_member", ret);
1230 ret = task_get_special_port (inferior_task,
1231 TASK_EXCEPTION_PORT,
1232 &inferior_old_exception_port);
1233 CHK ("task_get_special_port(old exc)", ret);
1235 ret = task_set_special_port (inferior_task,
1236 TASK_EXCEPTION_PORT,
1237 inferior_exception_port);
1238 CHK ("task_set_special_port", ret);
1240 ret = mach_port_deallocate (mach_task_self (),
1241 inferior_exception_port);
1242 CHK ("mack_port_deallocate", ret);
1245 /* When notify appears, the inferior_task's exception
1246 * port has been destroyed.
1248 * Not used, since the dead_name_notification already
1249 * appears when task dies.
1252 request_notify (inferior_exception_port,
1253 MACH_NOTIFY_NO_SENDERS,
1254 MACH_TYPE_EXCEPTION_PORT);
1258 /* Nonzero if gdb is waiting for a message */
1259 int mach_really_waiting;
1261 /* Wait for the inferior to stop for some reason.
1262 - Loop on notifications until inferior_task dies.
1263 - Loop on exceptions until stopped_in_exception comes true.
1264 (e.g. we receive a single step trace trap)
1265 - a message arrives to gdb's message port
1267 There is no other way to exit this loop.
1269 Returns the inferior_pid for rest of gdb.
1270 Side effects: Set *OURSTATUS. */
1272 mach_really_wait (pid, ourstatus)
1274 struct target_waitstatus *ourstatus;
1281 mach_msg_header_t header;
1282 mach_msg_type_t foo;
1287 /* Either notify (death), exception or message can stop the inferior */
1288 stopped_in_exception = FALSE;
1294 stop_exception = stop_code = stop_subcode = -1;
1295 stop_thread = MACH_PORT_NULL;
1297 mach_really_waiting = 1;
1298 ret = mach_msg (&in_msg.header, /* header */
1299 MACH_RCV_MSG, /* options */
1301 sizeof (struct msg), /* receive size */
1302 currently_waiting_for, /* receive name */
1303 MACH_MSG_TIMEOUT_NONE,
1305 mach_really_waiting = 0;
1306 CHK ("mach_msg (receive)", ret);
1308 /* Check if we received a notify of the childs' death */
1309 if (notify_server (&in_msg.header, &out_msg.header))
1311 /* If inferior_task is null then the inferior has
1312 gone away and we want to return to command level.
1313 Otherwise it was just an informative message and we
1314 need to look to see if there are any more. */
1315 if (inferior_task != MACH_PORT_NULL)
1319 /* Collect Unix exit status for gdb */
1321 wait3 (&w, WNOHANG, 0);
1323 /* This mess is here to check that the rest of
1324 * gdb knows that the inferior died. It also
1325 * tries to hack around the fact that Mach 3.0 (mk69)
1326 * unix server (ux28) does not always know what
1327 * has happened to it's children when mach-magic
1328 * is applied on them.
1330 if ((!WIFEXITED (w) && WIFSTOPPED (w)) ||
1331 (WIFEXITED (w) && WEXITSTATUS (w) > 0377))
1334 warning ("Using exit value 0 for terminated task");
1336 else if (!WIFEXITED (w))
1338 int sig = WTERMSIG (w);
1340 /* Signals cause problems. Warn the user. */
1341 if (sig != SIGKILL) /* Bad luck if garbage matches this */
1342 warning ("The terminating signal stuff may be nonsense");
1343 else if (sig > NSIG)
1346 warning ("Using exit value 0 for terminated task");
1349 store_waitstatus (ourstatus, w);
1350 return inferior_pid;
1354 /* Hmm. Check for exception, as it was not a notification.
1355 exc_server() does an upcall to catch_exception_raise()
1356 if this rpc is an exception. Further actions are decided
1359 if (!exc_server (&in_msg.header, &out_msg.header))
1362 /* Not an exception, check for message.
1364 * Messages don't come from the inferior, or if they
1365 * do they better be asynchronous or it will hang.
1367 if (gdb_message_server (&in_msg.header))
1370 error ("Unrecognized message received in mach_really_wait");
1373 /* Send the reply of the exception rpc to the suspended task */
1374 ret = mach_msg_send (&out_msg.header);
1375 CHK ("mach_msg_send (exc reply)", ret);
1377 if (stopped_in_exception)
1379 /* Get unix state. May be changed in mach3_exception_actions() */
1380 wait3 (&w, WNOHANG, 0);
1382 mach3_exception_actions (&w, FALSE, "Task");
1384 store_waitstatus (ourstatus, w);
1385 return inferior_pid;
1390 /* Called by macro DO_QUIT() in utils.c(quit).
1391 * This is called just before calling error() to return to command level
1399 if (mach_really_waiting)
1401 ret = task_suspend (inferior_task);
1403 if (ret != KERN_SUCCESS)
1405 warning ("Could not suspend task for interrupt: %s",
1406 mach_error_string (ret));
1407 mach_really_waiting = 0;
1412 must_suspend_thread = 0;
1413 mach_really_waiting = 0;
1415 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1418 warning ("Selecting first existing kernel thread");
1422 current_thread = MACH_PORT_NULL; /* Force setup */
1423 select_thread (inferior_task, mid, 1);
1429 /* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
1431 /* If ^C is typed when we are waiting for a message
1432 * and your Unix server is able to notice that we
1435 * Called by REQUEST_QUIT() from utils.c(request_quit)
1438 mach3_request_quit ()
1440 if (mach_really_waiting)
1446 * Gdb message server.
1447 * Currently implemented is the STOP message, that causes
1448 * gdb to return to the command level like ^C had been typed from terminal.
1451 gdb_message_server (InP)
1452 mach_msg_header_t *InP;
1457 if (InP->msgh_local_port == our_message_port)
1459 /* A message coming to our_message_port. Check validity */
1460 switch (InP->msgh_id)
1463 case GDB_MESSAGE_ID_STOP:
1464 ret = task_suspend (inferior_task);
1465 if (ret != KERN_SUCCESS)
1466 warning ("Could not suspend task for stop message: %s",
1467 mach_error_string (ret));
1469 /* QUIT in mach_really_wait() loop. */
1474 warning ("Invalid message id %d received, ignored.",
1482 /* Message not handled by this server */
1486 /* NOTE: This is not an RPC call. It is a simpleroutine.
1488 * This is not called from this gdb code.
1490 * It may be called by another debugger to cause this
1491 * debugger to enter command level:
1493 * (gdb) set stop_inferior_gdb ()
1496 * External program "stop-gdb" implements this also.
1499 stop_inferior_gdb ()
1503 /* Code generated by mig, with minor cleanups :-)
1505 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1510 mach_msg_header_t Head;
1516 register Request *InP = &Mess;
1518 InP->Head.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
1520 /* msgh_size passed as argument */
1521 InP->Head.msgh_remote_port = our_message_port;
1522 InP->Head.msgh_local_port = MACH_PORT_NULL;
1523 InP->Head.msgh_seqno = 0;
1524 InP->Head.msgh_id = GDB_MESSAGE_ID_STOP;
1526 ret = mach_msg (&InP->Head,
1527 MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
1531 MACH_MSG_TIMEOUT_NONE,
1535 #ifdef THREAD_ALLOWED_TO_BREAK
1537 * Return 1 if the MID specifies the thread that caused the
1539 * Since catch_exception_raise() selects the thread causing
1540 * the last exception to current_thread, we just check that
1541 * it is selected and the last exception was a breakpoint.
1544 mach_thread_for_breakpoint (mid)
1547 int cmid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1551 mid = map_slot_to_mid (-(mid + 1), 0, 0);
1553 return 0; /* Don't stop, no such slot */
1556 if (!mid || cmid == -1)
1557 return 1; /* stop */
1559 return cmid == mid && stop_exception == EXC_BREAKPOINT;
1561 #endif /* THREAD_ALLOWED_TO_BREAK */
1563 #ifdef THREAD_PARSE_ID
1565 * Map a thread id string (MID or a @SLOTNUMBER)
1568 * 0 matches all threads.
1569 * Otherwise the meaning is defined only in this file.
1570 * (mach_thread_for_breakpoint uses it)
1572 * @@ This allows non-existent MIDs to be specified.
1573 * It now also allows non-existent slots to be
1574 * specified. (Slot numbers stored are negative,
1575 * and the magnitude is one greater than the actual
1576 * slot index. (Since 0 is reserved))
1579 mach_thread_parse_id (arg)
1584 error ("thread id excpected");
1585 mid = parse_thread_id (arg, 0, 1);
1589 #endif /* THREAD_PARSE_ID */
1591 #ifdef THREAD_OUTPUT_ID
1593 mach_thread_output_id (mid)
1596 static char foobar[20];
1599 sprintf (foobar, "mid %d", mid);
1601 sprintf (foobar, "@%d", -(mid + 1));
1603 sprintf (foobar, "*any thread*");
1607 #endif /* THREAD_OUTPUT_ID */
1609 /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
1611 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1613 * if SELECT_IT is nonzero, reselect the thread that was active when
1614 * we stopped at a breakpoint.
1618 mach3_prepare_to_proceed (select_it)
1622 stop_thread != current_thread &&
1623 stop_exception == EXC_BREAKPOINT)
1630 mid = switch_to_thread (stop_thread);
1638 /* this stuff here is an upcall via libmach/excServer.c
1639 and mach_really_wait which does the actual upcall.
1641 The code will pass the exception to the inferior if:
1643 - The task that signaled is not the inferior task
1644 (e.g. when debugging another debugger)
1646 - The user has explicitely requested to pass on the exceptions.
1647 (e.g to the default unix exception handler, which maps
1648 exceptions to signals, or the user has her own exception handler)
1650 - If the thread that signaled is being single-stepped and it
1651 has set it's own exception port and the exception is not
1652 EXC_BREAKPOINT. (Maybe this is not desirable?)
1656 catch_exception_raise (port, thread, task, exception, code, subcode)
1660 int exception, code, subcode;
1663 boolean_t signal_thread;
1664 int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
1666 if (!MACH_PORT_VALID (thread))
1668 /* If the exception was sent and thread dies before we
1669 receive it, THREAD will be MACH_PORT_DEAD
1672 current_thread = thread = MACH_PORT_NULL;
1673 error ("Received exception from nonexistent thread");
1676 /* Check if the task died in transit.
1677 * @@ Isn't the thread also invalid in such case?
1679 if (!MACH_PORT_VALID (task))
1681 current_thread = thread = MACH_PORT_NULL;
1682 error ("Received exception from nonexistent task");
1685 if (exception < 0 || exception > MAX_EXCEPTION)
1686 internal_error ("catch_exception_raise: unknown exception code %d thread %d",
1690 if (!MACH_PORT_VALID (inferior_task))
1691 error ("got an exception, but inferior_task is null or dead");
1693 stop_exception = exception;
1695 stop_subcode = subcode;
1696 stop_thread = thread;
1698 signal_thread = exception != EXC_BREAKPOINT &&
1699 port == singlestepped_thread_port &&
1700 MACH_PORT_VALID (thread_saved_exception_port);
1702 /* If it was not our inferior or if we want to forward
1703 * the exception to the inferior's handler, do it here
1705 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1707 if (task != inferior_task ||
1709 exception_map[exception].forward)
1711 mach_port_t eport = inferior_old_exception_port;
1716 GDB now forwards the exeption to thread's original handler,
1717 since the user propably knows what he is doing.
1718 Give a message, though.
1721 mach3_exception_actions ((WAITTYPE *) NULL, TRUE, "Thread");
1722 eport = thread_saved_exception_port;
1725 /* Send the exception to the original handler */
1726 ret = exception_raise (eport,
1733 (void) mach_port_deallocate (mach_task_self (), task);
1734 (void) mach_port_deallocate (mach_task_self (), thread);
1736 /* If we come here, we don't want to trace any more, since we
1737 * will never stop for tracing anyway.
1739 discard_single_step (thread);
1741 /* Do not stop the inferior */
1745 /* Now gdb handles the exception */
1746 stopped_in_exception = TRUE;
1748 ret = task_suspend (task);
1749 CHK ("Error suspending inferior after exception", ret);
1751 must_suspend_thread = 0;
1753 if (current_thread != thread)
1755 if (MACH_PORT_VALID (singlestepped_thread_port))
1756 /* Cleanup discards single stepping */
1757 error ("Exception from thread %d while singlestepping thread %d",
1759 map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
1761 /* Then select the thread that caused the exception */
1762 if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
1763 error ("Could not select thread %d causing exception", mid);
1765 warning ("Gdb selected thread %d", mid);
1768 /* If we receive an exception that is not breakpoint
1769 * exception, we interrupt the single step and return to
1770 * debugger. Trace condition is cleared.
1772 if (MACH_PORT_VALID (singlestepped_thread_port))
1774 if (stop_exception != EXC_BREAKPOINT)
1775 warning ("Single step interrupted by exception");
1776 else if (port == singlestepped_thread_port)
1778 /* Single step exception occurred, remove trace bit
1779 * and return to gdb.
1781 if (!MACH_PORT_VALID (current_thread))
1782 error ("Single stepped thread is not valid");
1784 /* Resume threads, but leave the task suspended */
1785 resume_all_threads (0);
1788 warning ("Breakpoint while single stepping?");
1790 discard_single_step (current_thread);
1793 (void) mach_port_deallocate (mach_task_self (), task);
1794 (void) mach_port_deallocate (mach_task_self (), thread);
1796 return KERN_SUCCESS;
1800 port_valid (port, mask)
1805 mach_port_type_t type;
1807 ret = mach_port_type (mach_task_self (),
1810 if (ret != KERN_SUCCESS || (type & mask) != mask)
1815 /* @@ No vm read cache implemented yet */
1816 boolean_t vm_read_cache_valid = FALSE;
1819 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1820 * in gdb's address space.
1822 * Return 0 on failure; number of bytes read otherwise.
1825 mach3_read_inferior (addr, myaddr, length)
1831 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1832 vm_size_t aligned_length =
1833 (vm_size_t) round_page (addr + length) - low_address;
1834 pointer_t copied_memory;
1837 /* Get memory from inferior with page aligned addresses */
1838 ret = vm_read (inferior_task,
1843 if (ret != KERN_SUCCESS)
1845 /* the problem is that the inferior might be killed for whatever reason
1846 * before we go to mach_really_wait. This is one place that ought to
1847 * catch many of those errors.
1848 * @@ A better fix would be to make all external events to GDB
1849 * to arrive via a SINGLE port set. (Including user input!)
1852 if (!port_valid (inferior_task, MACH_PORT_TYPE_SEND))
1854 m3_kill_inferior ();
1855 error ("Inferior killed (task port invalid)");
1861 /* valprint.c gives nicer format if this does not
1862 screw it. Eamonn seems to like this, so I enable
1863 it if OSF is defined...
1865 warning ("[read inferior %x failed: %s]",
1866 addr, mach_error_string (ret));
1873 memcpy (myaddr, (char *) addr - low_address + copied_memory, length);
1875 ret = vm_deallocate (mach_task_self (),
1878 CHK ("mach3_read_inferior vm_deallocate failed", ret);
1884 #define CHK_GOTO_OUT(str,ret) \
1885 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
1887 #define CHK_GOTO_OUT(str,ret) \
1888 do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
1891 struct vm_region_list
1893 struct vm_region_list *next;
1894 vm_prot_t protection;
1899 struct obstack region_obstack;
1902 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1903 * in gdb's address space.
1906 mach3_write_inferior (addr, myaddr, length)
1912 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1913 vm_size_t aligned_length =
1914 (vm_size_t) round_page (addr + length) - low_address;
1915 pointer_t copied_memory;
1919 char *errstr = "Bug in mach3_write_inferior";
1921 struct vm_region_list *region_element;
1922 struct vm_region_list *region_head = (struct vm_region_list *) NULL;
1924 /* Get memory from inferior with page aligned addresses */
1925 ret = vm_read (inferior_task,
1930 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
1934 memcpy ((char *) addr - low_address + copied_memory, myaddr, length);
1936 obstack_init (®ion_obstack);
1938 /* Do writes atomically.
1939 * First check for holes and unwritable memory.
1942 vm_size_t remaining_length = aligned_length;
1943 vm_address_t region_address = low_address;
1945 struct vm_region_list *scan;
1947 while (region_address < low_address + aligned_length)
1949 vm_prot_t protection;
1950 vm_prot_t max_protection;
1951 vm_inherit_t inheritance;
1953 mach_port_t object_name;
1955 vm_size_t region_length = remaining_length;
1956 vm_address_t old_address = region_address;
1958 ret = vm_region (inferior_task,
1967 CHK_GOTO_OUT ("vm_region failed", ret);
1969 /* Check for holes in memory */
1970 if (old_address != region_address)
1972 warning ("No memory at 0x%x. Nothing written",
1979 if (!(max_protection & VM_PROT_WRITE))
1981 warning ("Memory at address 0x%x is unwritable. Nothing written",
1988 /* Chain the regions for later use */
1990 (struct vm_region_list *)
1991 obstack_alloc (®ion_obstack, sizeof (struct vm_region_list));
1993 region_element->protection = protection;
1994 region_element->start = region_address;
1995 region_element->length = region_length;
1997 /* Chain the regions along with protections */
1998 region_element->next = region_head;
1999 region_head = region_element;
2001 region_address += region_length;
2002 remaining_length = remaining_length - region_length;
2005 /* If things fail after this, we give up.
2006 * Somebody is messing up inferior_task's mappings.
2009 /* Enable writes to the chained vm regions */
2010 for (scan = region_head; scan; scan = scan->next)
2012 boolean_t protection_changed = FALSE;
2014 if (!(scan->protection & VM_PROT_WRITE))
2016 ret = vm_protect (inferior_task,
2020 scan->protection | VM_PROT_WRITE);
2021 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
2025 ret = vm_write (inferior_task,
2029 CHK_GOTO_OUT ("vm_write failed", ret);
2031 /* Set up the original region protections, if they were changed */
2032 for (scan = region_head; scan; scan = scan->next)
2034 boolean_t protection_changed = FALSE;
2036 if (!(scan->protection & VM_PROT_WRITE))
2038 ret = vm_protect (inferior_task,
2043 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
2051 obstack_free (®ion_obstack, 0);
2053 (void) vm_deallocate (mach_task_self (),
2058 if (ret != KERN_SUCCESS)
2060 warning ("%s %s", errstr, mach_error_string (ret));
2067 /* Return 0 on failure, number of bytes handled otherwise. */
2069 m3_xfer_memory (memaddr, myaddr, len, write, target)
2074 struct target_ops *target; /* IGNORED */
2079 result = mach3_write_inferior (memaddr, myaddr, len);
2081 result = mach3_read_inferior (memaddr, myaddr, len);
2088 translate_state (state)
2093 case TH_STATE_RUNNING:
2095 case TH_STATE_STOPPED:
2097 case TH_STATE_WAITING:
2099 case TH_STATE_UNINTERRUPTIBLE:
2101 case TH_STATE_HALTED:
2109 translate_cstate (state)
2116 case CPROC_SWITCHING:
2120 case CPROC_CONDWAIT:
2122 case CPROC_CONDWAIT | CPROC_SWITCHING:
2129 /* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2131 mach_port_t /* no mach_port_name_t found in include files. */
2132 map_inferior_port_name (inferior_name, type)
2133 mach_port_t inferior_name;
2134 mach_msg_type_name_t type;
2137 mach_msg_type_name_t acquired;
2140 ret = mach_port_extract_right (inferior_task,
2145 CHK ("mach_port_extract_right (map_inferior_port_name)", ret);
2147 if (acquired != MACH_MSG_TYPE_PORT_SEND)
2148 error ("Incorrect right extracted, (map_inferior_port_name)");
2150 ret = mach_port_deallocate (mach_task_self (),
2152 CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
2158 * Naming convention:
2159 * Always return user defined name if found.
2160 * _K == A kernel thread with no matching CPROC
2161 * _C == A cproc with no current cthread
2162 * _t == A cthread with no user defined name
2164 * The digits that follow the _names are the SLOT number of the
2165 * kernel thread if there is such a thing, otherwise just a negation
2166 * of the sequential number of such cprocs.
2172 get_thread_name (one_cproc, id)
2173 gdb_thread_t one_cproc;
2177 if (one_cproc->cthread == NULL)
2179 /* cproc not mapped to any cthread */
2180 sprintf (buf, "_C%d", id);
2182 else if (!one_cproc->cthread->name)
2184 /* cproc and cthread, but no name */
2185 sprintf (buf, "_t%d", id);
2188 return (char *) (one_cproc->cthread->name);
2192 warning ("Inconsistency in thread name id %d", id);
2194 /* Kernel thread without cproc */
2195 sprintf (buf, "_K%d", id);
2202 fetch_thread_info (task, mthreads_out)
2204 gdb_thread_t *mthreads_out; /* out */
2207 thread_array_t th_table;
2209 gdb_thread_t mthreads = NULL;
2212 ret = task_threads (task, &th_table, &th_count);
2213 if (ret != KERN_SUCCESS)
2215 warning ("Error getting inferior's thread list:%s",
2216 mach_error_string (ret));
2217 m3_kill_inferior ();
2221 mthreads = (gdb_thread_t)
2224 th_count * sizeof (struct gdb_thread));
2226 for (index = 0; index < th_count; index++)
2228 thread_t saved_thread = MACH_PORT_NULL;
2231 if (must_suspend_thread)
2232 setup_thread (th_table[index], 1);
2234 if (th_table[index] != current_thread)
2236 saved_thread = current_thread;
2238 mid = switch_to_thread (th_table[index]);
2241 mthreads[index].name = th_table[index];
2242 mthreads[index].cproc = NULL; /* map_cprocs_to_kernel_threads() */
2243 mthreads[index].in_emulator = FALSE;
2244 mthreads[index].slotid = index;
2246 mthreads[index].sp = read_register (SP_REGNUM);
2247 mthreads[index].fp = read_register (FP_REGNUM);
2248 mthreads[index].pc = read_pc ();
2250 if (MACH_PORT_VALID (saved_thread))
2251 mid = switch_to_thread (saved_thread);
2253 if (must_suspend_thread)
2254 setup_thread (th_table[index], 0);
2257 consume_send_rights (th_table, th_count);
2258 ret = vm_deallocate (mach_task_self (), (vm_address_t) th_table,
2259 (th_count * sizeof (mach_port_t)));
2260 if (ret != KERN_SUCCESS)
2262 warning ("Error trying to deallocate thread list : %s",
2263 mach_error_string (ret));
2266 *mthreads_out = mthreads;
2273 * Current emulator always saves the USP on top of
2274 * emulator stack below struct emul_stack_top stuff.
2277 fetch_usp_from_emulator_stack (sp)
2280 CORE_ADDR stack_pointer;
2282 sp = (sp & ~(EMULATOR_STACK_SIZE - 1)) +
2283 EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
2285 if (mach3_read_inferior (sp,
2287 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2289 warning ("Can't read user sp from emulator stack address 0x%x", sp);
2293 return stack_pointer;
2298 /* get_emulation_vector() interface was changed after mk67 */
2299 #define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2303 /* Check if the emulator exists at task's address space.
2306 have_emulator_p (task)
2310 #ifndef EMUL_VECTOR_COUNT
2311 vm_offset_t *emulation_vector;
2314 vm_offset_t emulation_vector[EMUL_VECTOR_COUNT];
2315 int n = EMUL_VECTOR_COUNT;
2320 ret = task_get_emulation_vector (task,
2322 #ifndef EMUL_VECTOR_COUNT
2328 CHK ("task_get_emulation_vector", ret);
2329 xx_debug ("%d vectors from %d at 0x%08x\n",
2330 n, vector_start, emulation_vector);
2332 for (i = 0; i < n; i++)
2334 vm_offset_t entry = emulation_vector[i];
2336 if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
2340 static boolean_t informed = FALSE;
2343 warning ("Emulation vector address 0x08%x outside emulator space",
2352 /* Map cprocs to kernel threads and vice versa. */
2355 map_cprocs_to_kernel_threads (cprocs, mthreads, thread_count)
2356 gdb_thread_t cprocs;
2357 gdb_thread_t mthreads;
2362 boolean_t all_mapped = TRUE;
2366 for (scan = cprocs; scan; scan = scan->next)
2368 /* Default to: no kernel thread for this cproc */
2369 scan->reverse_map = -1;
2371 /* Check if the cproc is found by its stack */
2372 for (index = 0; index < thread_count; index++)
2375 extract_signed_integer (scan->raw_cproc + CPROC_BASE_OFFSET,
2378 extract_signed_integer (scan->raw_cproc + CPROC_SIZE_OFFSET,
2380 if ((mthreads + index)->sp > stack_base &&
2381 (mthreads + index)->sp <= stack_base + stack_size)
2383 (mthreads + index)->cproc = scan;
2384 scan->reverse_map = index;
2388 all_mapped &= (scan->reverse_map != -1);
2391 /* Check for threads that are currently in the emulator.
2392 * If so, they have a different stack, and the still unmapped
2393 * cprocs may well get mapped to these threads.
2396 * - cproc stack does not match any kernel thread stack pointer
2397 * - there is at least one extra kernel thread
2398 * that has no cproc mapped above.
2399 * - some kernel thread stack pointer points to emulator space
2400 * then we find the user stack pointer saved in the emulator
2401 * stack, and try to map that to the cprocs.
2403 * Also set in_emulator for kernel threads.
2406 if (emulator_present)
2408 for (index = 0; index < thread_count; index++)
2413 gdb_thread_t mthread = (mthreads + index);
2414 emul_sp = mthread->sp;
2416 if (mthread->cproc == NULL &&
2417 EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
2419 mthread->in_emulator = emulator_present;
2421 if (!all_mapped && cprocs)
2423 usp = fetch_usp_from_emulator_stack (emul_sp);
2425 /* @@ Could be more accurate */
2427 error ("Zero stack pointer read from emulator?");
2429 /* Try to match this stack pointer to the cprocs that
2430 * don't yet have a kernel thread.
2432 for (scan = cprocs; scan; scan = scan->next)
2435 /* Check is this unmapped CPROC stack contains
2436 * the user stack pointer saved in the
2439 if (scan->reverse_map == -1)
2442 extract_signed_integer
2443 (scan->raw_cproc + CPROC_BASE_OFFSET,
2446 extract_signed_integer
2447 (scan->raw_cproc + CPROC_SIZE_OFFSET,
2449 if (usp > stack_base &&
2450 usp <= stack_base + stack_size)
2452 mthread->cproc = scan;
2453 scan->reverse_map = index;
2465 * Format of the thread_list command
2467 * slot mid sel name emul ks susp cstate wired address
2469 #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2471 #define TL_HEADER "\n@ MID Name KState CState Where\n"
2474 print_tl_address (stream, pc)
2475 struct ui_file *stream;
2478 if (!lookup_minimal_symbol_by_pc (pc))
2479 fprintf_filtered (stream, local_hex_format (), pc);
2482 extern int addressprint;
2483 extern int asm_demangle;
2485 int store = addressprint;
2487 print_address_symbolic (pc, stream, asm_demangle, "");
2488 addressprint = store;
2492 /* For thread names, but also for gdb_message_port external name */
2493 #define MAX_NAME_LEN 50
2495 /* Returns the address of variable NAME or 0 if not found */
2497 lookup_address_of_variable (name)
2501 CORE_ADDR symaddr = 0;
2502 struct minimal_symbol *msymbol;
2504 sym = lookup_symbol (name,
2505 (struct block *) NULL,
2508 (struct symtab **) NULL);
2511 symaddr = SYMBOL_VALUE (sym);
2515 msymbol = lookup_minimal_symbol (name, NULL, NULL);
2517 if (msymbol && msymbol->type == mst_data)
2518 symaddr = SYMBOL_VALUE_ADDRESS (msymbol);
2527 gdb_thread_t cproc_head;
2528 gdb_thread_t cproc_copy;
2529 CORE_ADDR their_cprocs;
2530 char *buf[TARGET_PTR_BIT / HOST_CHAR_BIT];
2535 symaddr = lookup_address_of_variable ("cproc_list");
2539 /* cproc_list is not in a file compiled with debugging
2540 symbols, but don't give up yet */
2542 symaddr = lookup_address_of_variable ("cprocs");
2546 static int informed = 0;
2550 warning ("Your program is loaded with an old threads library.");
2551 warning ("GDB does not know the old form of threads");
2552 warning ("so things may not work.");
2557 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
2561 /* Get the address of the first cproc in the task */
2562 if (!mach3_read_inferior (symaddr,
2564 TARGET_PTR_BIT / HOST_CHAR_BIT))
2565 error ("Can't read cproc master list at address (0x%x).", symaddr);
2566 their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
2568 /* Scan the CPROCs in the task.
2569 CPROCs are chained with LIST field, not NEXT field, which
2570 chains mutexes, condition variables and queues */
2574 while (their_cprocs != (CORE_ADDR) 0)
2576 CORE_ADDR cproc_copy_incarnation;
2577 cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
2578 sizeof (struct gdb_thread));
2580 if (!mach3_read_inferior (their_cprocs,
2581 &cproc_copy->raw_cproc[0],
2583 error ("Can't read next cproc at 0x%x.", their_cprocs);
2586 extract_address (cproc_copy->raw_cproc + CPROC_LIST_OFFSET,
2588 cproc_copy_incarnation =
2589 extract_address (cproc_copy->raw_cproc + CPROC_INCARNATION_OFFSET,
2590 CPROC_INCARNATION_SIZE);
2592 if (cproc_copy_incarnation == (CORE_ADDR) 0)
2593 cproc_copy->cthread = NULL;
2596 /* This CPROC has an attached CTHREAD. Get its name */
2597 cthread = (cthread_t) obstack_alloc (cproc_obstack,
2598 sizeof (struct cthread));
2600 if (!mach3_read_inferior (cproc_copy_incarnation,
2602 sizeof (struct cthread)))
2603 error ("Can't read next thread at 0x%x.",
2604 cproc_copy_incarnation);
2606 cproc_copy->cthread = cthread;
2610 name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
2612 if (!mach3_read_inferior (cthread->name, name, MAX_NAME_LEN))
2613 error ("Can't read next thread's name at 0x%x.", cthread->name);
2615 cthread->name = name;
2619 /* insert in front */
2620 cproc_copy->next = cproc_head;
2621 cproc_head = cproc_copy;
2626 #ifndef FETCH_CPROC_STATE
2628 * Check if your machine does not grok the way this routine
2629 * fetches the FP,PC and SP of a cproc that is not
2630 * currently attached to any kernel thread (e.g. its cproc.context
2631 * field points to the place in stack where the context
2634 * If it doesn't, define your own routine.
2636 #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2639 mach3_cproc_state (mthread)
2640 gdb_thread_t mthread;
2644 if (!mthread || !mthread->cproc)
2647 context = extract_signed_integer
2648 (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
2649 CPROC_CONTEXT_SIZE);
2653 mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
2655 if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
2657 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2659 warning ("Can't read cproc pc from inferior");
2663 if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
2665 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2667 warning ("Can't read cproc fp from inferior");
2673 #endif /* FETCH_CPROC_STATE */
2677 thread_list_command ()
2679 thread_basic_info_data_t ths;
2681 gdb_thread_t cprocs;
2689 mach_port_t mid_or_port;
2690 gdb_thread_t their_threads;
2691 gdb_thread_t kthread;
2695 char *fmt = "There are %d kernel threads in task %d.\n";
2697 int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
2699 MACH_ERROR_NO_INFERIOR;
2701 thread_count = fetch_thread_info (inferior_task,
2703 if (thread_count == -1)
2706 if (thread_count == 1)
2707 fmt = "There is %d kernel thread in task %d.\n";
2709 printf_filtered (fmt, thread_count, tmid);
2711 puts_filtered (TL_HEADER);
2713 cprocs = get_cprocs ();
2715 map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
2717 for (scan = cprocs; scan; scan = scan->next)
2723 extract_signed_integer
2724 (scan->raw_cproc + CPROC_STATE_OFFSET, CPROC_STATE_SIZE);
2728 /* a wired cproc? */
2729 wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
2733 if (scan->reverse_map != -1)
2734 kthread = (their_threads + scan->reverse_map);
2740 /* These cprocs have a kernel thread */
2742 mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
2744 infoCnt = THREAD_BASIC_INFO_COUNT;
2746 ret = thread_info (kthread->name,
2748 (thread_info_t) & ths,
2751 if (ret != KERN_SUCCESS)
2753 warning ("Unable to get basic info on thread %d : %s",
2755 mach_error_string (ret));
2759 /* Who is the first to have more than 100 threads */
2760 sprintf (slot, "%d", kthread->slotid % 100);
2762 if (kthread->name == current_thread)
2765 if (ths.suspend_count)
2766 sprintf (buf, "%d", ths.suspend_count);
2771 if (ths.flags & TH_FLAGS_SWAPPED)
2775 if (ths.flags & TH_FLAGS_IDLE)
2778 printf_filtered (TL_FORMAT,
2782 get_thread_name (scan, kthread->slotid),
2783 kthread->in_emulator ? "E" : "",
2784 translate_state (ths.run_state),
2786 translate_cstate (cproc_state),
2788 print_tl_address (gdb_stdout, kthread->pc);
2792 /* These cprocs don't have a kernel thread.
2793 * find out the calling frame with
2794 * FETCH_CPROC_STATE.
2797 struct gdb_thread state;
2800 /* jtv -> emcmanus: why do you want this here? */
2801 if (scan->incarnation == NULL)
2802 continue; /* EMcM */
2805 printf_filtered (TL_FORMAT,
2807 -neworder, /* Pseudo MID */
2809 get_thread_name (scan, -neworder),
2811 "-", /* kernel state */
2813 translate_cstate (cproc_state),
2817 if (FETCH_CPROC_STATE (&state) == -1)
2818 puts_filtered ("???");
2820 print_tl_address (gdb_stdout, state.pc);
2824 puts_filtered ("\n");
2827 /* Scan for kernel threads without cprocs */
2828 for (index = 0; index < thread_count; index++)
2830 if (!their_threads[index].cproc)
2837 mach_port_t name = their_threads[index].name;
2839 mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
2841 infoCnt = THREAD_BASIC_INFO_COUNT;
2843 ret = thread_info (name,
2845 (thread_info_t) & ths,
2848 if (ret != KERN_SUCCESS)
2850 warning ("Unable to get basic info on thread %d : %s",
2852 mach_error_string (ret));
2856 sprintf (slot, "%d", index % 100);
2858 if (name == current_thread)
2863 if (ths.suspend_count)
2864 sprintf (buf, "%d", ths.suspend_count);
2869 if (ths.flags & TH_FLAGS_SWAPPED)
2873 if (ths.flags & TH_FLAGS_IDLE)
2876 printf_filtered (TL_FORMAT,
2880 get_thread_name (NULL, index),
2881 their_threads[index].in_emulator ? "E" : "",
2882 translate_state (ths.run_state),
2884 "", /* No cproc state */
2885 ""); /* Can't be wired */
2886 print_tl_address (gdb_stdout, their_threads[index].pc);
2887 puts_filtered ("\n");
2891 obstack_free (cproc_obstack, 0);
2892 obstack_init (cproc_obstack);
2896 thread_select_command (args, from_tty)
2901 thread_array_t thread_list;
2906 MACH_ERROR_NO_INFERIOR;
2909 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2911 while (*args == ' ' || *args == '\t')
2923 if (!is_slot || *args != '0') /* Rudimentary checks */
2924 error ("You must select threads by MID or @SLOTNUMBER");
2926 if (select_thread (inferior_task, mid, is_slot ? 2 : 1) != KERN_SUCCESS)
2930 printf_filtered ("Thread %d selected\n",
2931 is_slot ? map_port_name_to_mid (current_thread,
2932 MACH_TYPE_THREAD) : mid);
2935 thread_trace (thread, set)
2939 int flavor = TRACE_FLAVOR;
2940 unsigned int stateCnt = TRACE_FLAVOR_SIZE;
2942 thread_state_data_t state;
2944 if (!MACH_PORT_VALID (thread))
2946 warning ("thread_trace: invalid thread");
2950 if (must_suspend_thread)
2951 setup_thread (thread, 1);
2953 ret = thread_get_state (thread, flavor, state, &stateCnt);
2954 CHK ("thread_trace: error reading thread state", ret);
2958 TRACE_SET (thread, state);
2962 if (!TRACE_CLEAR (thread, state))
2964 if (must_suspend_thread)
2965 setup_thread (thread, 0);
2970 ret = thread_set_state (thread, flavor, state, stateCnt);
2971 CHK ("thread_trace: error writing thread state", ret);
2972 if (must_suspend_thread)
2973 setup_thread (thread, 0);
2976 #ifdef FLUSH_INFERIOR_CACHE
2978 /* When over-writing code on some machines the I-Cache must be flushed
2979 explicitly, because it is not kept coherent by the lazy hardware.
2980 This definitely includes breakpoints, for instance, or else we
2981 end up looping in mysterious Bpt traps */
2983 flush_inferior_icache (pc, amount)
2986 vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
2989 ret = vm_machine_attribute (inferior_task,
2994 if (ret != KERN_SUCCESS)
2995 warning ("Error flushing inferior's cache : %s",
2996 mach_error_string (ret));
2998 #endif /* FLUSH_INFERIOR_CACHE */
3002 suspend_all_threads (from_tty)
3006 thread_array_t thread_list;
3007 int thread_count, index;
3009 thread_basic_info_data_t th_info;
3012 ret = task_threads (inferior_task, &thread_list, &thread_count);
3013 if (ret != KERN_SUCCESS)
3015 warning ("Could not suspend inferior threads.");
3016 m3_kill_inferior ();
3017 return_to_top_level (RETURN_ERROR);
3020 for (index = 0; index < thread_count; index++)
3024 mid = map_port_name_to_mid (thread_list[index],
3027 ret = thread_suspend (thread_list[index]);
3029 if (ret != KERN_SUCCESS)
3030 warning ("Error trying to suspend thread %d : %s",
3031 mid, mach_error_string (ret));
3035 infoCnt = THREAD_BASIC_INFO_COUNT;
3036 ret = thread_info (thread_list[index],
3038 (thread_info_t) & th_info,
3040 CHK ("suspend can't get thread info", ret);
3042 warning ("Thread %d suspend count is %d",
3043 mid, th_info.suspend_count);
3047 consume_send_rights (thread_list, thread_count);
3048 ret = vm_deallocate (mach_task_self (),
3049 (vm_address_t) thread_list,
3050 (thread_count * sizeof (int)));
3051 CHK ("Error trying to deallocate thread list", ret);
3055 thread_suspend_command (args, from_tty)
3061 mach_port_t saved_thread;
3063 thread_basic_info_data_t th_info;
3065 MACH_ERROR_NO_INFERIOR;
3067 if (!strcasecmp (args, "all"))
3069 suspend_all_threads (from_tty);
3073 saved_thread = current_thread;
3075 mid = parse_thread_id (args, 0, 0);
3078 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
3081 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
3082 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3085 current_thread = saved_thread;
3086 error ("Could not select thread %d", mid);
3089 ret = thread_suspend (current_thread);
3090 if (ret != KERN_SUCCESS)
3091 warning ("thread_suspend failed : %s",
3092 mach_error_string (ret));
3094 infoCnt = THREAD_BASIC_INFO_COUNT;
3095 ret = thread_info (current_thread,
3097 (thread_info_t) & th_info,
3099 CHK ("suspend can't get thread info", ret);
3101 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
3103 current_thread = saved_thread;
3106 resume_all_threads (from_tty)
3110 thread_array_t thread_list;
3111 int thread_count, index;
3114 thread_basic_info_data_t th_info;
3116 ret = task_threads (inferior_task, &thread_list, &thread_count);
3117 if (ret != KERN_SUCCESS)
3119 m3_kill_inferior ();
3120 error ("task_threads", mach_error_string (ret));
3123 for (index = 0; index < thread_count; index++)
3125 infoCnt = THREAD_BASIC_INFO_COUNT;
3126 ret = thread_info (thread_list[index],
3128 (thread_info_t) & th_info,
3130 CHK ("resume_all can't get thread info", ret);
3132 mid = map_port_name_to_mid (thread_list[index],
3135 if (!th_info.suspend_count)
3137 if (mid != -1 && from_tty)
3138 warning ("Thread %d is not suspended", mid);
3142 ret = thread_resume (thread_list[index]);
3144 if (ret != KERN_SUCCESS)
3145 warning ("Error trying to resume thread %d : %s",
3146 mid, mach_error_string (ret));
3147 else if (mid != -1 && from_tty)
3148 warning ("Thread %d suspend count is %d",
3149 mid, --th_info.suspend_count);
3152 consume_send_rights (thread_list, thread_count);
3153 ret = vm_deallocate (mach_task_self (),
3154 (vm_address_t) thread_list,
3155 (thread_count * sizeof (int)));
3156 CHK ("Error trying to deallocate thread list", ret);
3160 thread_resume_command (args, from_tty)
3165 mach_port_t saved_thread;
3167 thread_basic_info_data_t th_info;
3168 int infoCnt = THREAD_BASIC_INFO_COUNT;
3170 MACH_ERROR_NO_INFERIOR;
3172 if (!strcasecmp (args, "all"))
3174 resume_all_threads (from_tty);
3178 saved_thread = current_thread;
3180 mid = parse_thread_id (args, 0, 0);
3183 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3186 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
3187 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3190 current_thread = saved_thread;
3191 return_to_top_level (RETURN_ERROR);
3194 ret = thread_info (current_thread,
3196 (thread_info_t) & th_info,
3198 CHK ("resume can't get thread info", ret);
3200 if (!th_info.suspend_count)
3202 warning ("Thread %d is not suspended", mid);
3206 ret = thread_resume (current_thread);
3207 if (ret != KERN_SUCCESS)
3208 warning ("thread_resume failed : %s",
3209 mach_error_string (ret));
3212 th_info.suspend_count--;
3213 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
3217 current_thread = saved_thread;
3221 thread_kill_command (args, from_tty)
3228 thread_array_t thread_table;
3230 mach_port_t thread_to_kill = MACH_PORT_NULL;
3233 MACH_ERROR_NO_INFERIOR;
3236 error_no_arg ("thread mid to kill from the inferior task");
3238 mid = parse_thread_id (args, 0, 0);
3241 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3245 ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
3246 CHK ("thread_kill_command: machid_mach_port map failed", ret);
3249 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
3251 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3252 ret = task_threads (inferior_task, &thread_table, &thread_count);
3253 CHK ("Error getting inferior's thread list", ret);
3255 if (thread_to_kill == current_thread)
3257 ret = thread_terminate (thread_to_kill);
3258 CHK ("Thread could not be terminated", ret);
3260 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3261 warning ("Last thread was killed, use \"kill\" command to kill task");
3264 for (index = 0; index < thread_count; index++)
3265 if (thread_table[index] == thread_to_kill)
3267 ret = thread_terminate (thread_to_kill);
3268 CHK ("Thread could not be terminated", ret);
3271 if (thread_count > 1)
3272 consume_send_rights (thread_table, thread_count);
3274 ret = vm_deallocate (mach_task_self (), (vm_address_t) thread_table,
3275 (thread_count * sizeof (mach_port_t)));
3276 CHK ("Error trying to deallocate thread list", ret);
3278 warning ("Thread %d killed", mid);
3282 /* Task specific commands; add more if you like */
3285 task_resume_command (args, from_tty)
3290 task_basic_info_data_t ta_info;
3291 int infoCnt = TASK_BASIC_INFO_COUNT;
3292 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
3294 MACH_ERROR_NO_INFERIOR;
3296 /* Would be trivial to change, but is it desirable? */
3298 error ("Currently gdb can resume only it's inferior task");
3300 ret = task_info (inferior_task,
3302 (task_info_t) & ta_info,
3304 CHK ("task_resume_command: task_info failed", ret);
3306 if (ta_info.suspend_count == 0)
3307 error ("Inferior task %d is not suspended", mid);
3308 else if (ta_info.suspend_count == 1 &&
3310 !query ("Suspend count is now 1. Do you know what you are doing? "))
3311 error ("Task not resumed");
3313 ret = task_resume (inferior_task);
3314 CHK ("task_resume_command: task_resume", ret);
3316 if (ta_info.suspend_count == 1)
3318 warning ("Inferior task %d is no longer suspended", mid);
3319 must_suspend_thread = 1;
3320 /* @@ This is not complete: Registers change all the time when not
3322 registers_changed ();
3325 warning ("Inferior task %d suspend count is now %d",
3326 mid, ta_info.suspend_count - 1);
3331 task_suspend_command (args, from_tty)
3336 task_basic_info_data_t ta_info;
3337 int infoCnt = TASK_BASIC_INFO_COUNT;
3338 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
3340 MACH_ERROR_NO_INFERIOR;
3342 /* Would be trivial to change, but is it desirable? */
3344 error ("Currently gdb can suspend only it's inferior task");
3346 ret = task_suspend (inferior_task);
3347 CHK ("task_suspend_command: task_suspend", ret);
3349 must_suspend_thread = 0;
3351 ret = task_info (inferior_task,
3353 (task_info_t) & ta_info,
3355 CHK ("task_suspend_command: task_info failed", ret);
3357 warning ("Inferior task %d suspend count is now %d",
3358 mid, ta_info.suspend_count);
3365 static char size[30];
3366 int zz = bytes / 1024;
3369 sprintf (size, "%-2.1f M", ((float) bytes) / (1024.0 * 1024.0));
3371 sprintf (size, "%d K", zz);
3376 /* Does this require the target task to be suspended?? I don't think so. */
3378 task_info_command (args, from_tty)
3385 task_basic_info_data_t ta_info;
3386 int infoCnt = TASK_BASIC_INFO_COUNT;
3387 int page_size = round_page (1);
3388 int thread_count = 0;
3390 if (MACH_PORT_VALID (inferior_task))
3391 mid = map_port_name_to_mid (inferior_task,
3394 task = inferior_task;
3398 int tmid = atoi (args);
3401 error ("Invalid mid %d for task info", tmid);
3406 ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
3407 CHK ("task_info_command: machid_mach_port map failed", ret);
3412 error ("You have to give the task MID as an argument");
3414 ret = task_info (task,
3416 (task_info_t) & ta_info,
3418 CHK ("task_info_command: task_info failed", ret);
3420 printf_filtered ("\nTask info for task %d:\n\n", mid);
3421 printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
3422 printf_filtered (" Base priority : %d\n", ta_info.base_priority);
3423 printf_filtered (" Virtual size : %s\n", get_size (ta_info.virtual_size));
3424 printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
3427 thread_array_t thread_list;
3429 ret = task_threads (task, &thread_list, &thread_count);
3430 CHK ("task_info_command: task_threads", ret);
3432 printf_filtered (" Thread count : %d\n", thread_count);
3434 consume_send_rights (thread_list, thread_count);
3435 ret = vm_deallocate (mach_task_self (),
3436 (vm_address_t) thread_list,
3437 (thread_count * sizeof (int)));
3438 CHK ("Error trying to deallocate thread list", ret);
3440 if (have_emulator_p (task))
3441 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3442 EMULATOR_BASE, EMULATOR_END);
3444 printf_filtered (" No emulator.\n");
3446 if (thread_count && task == inferior_task)
3447 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3450 /* You may either FORWARD the exception to the inferior, or KEEP
3451 * it and return to GDB command level.
3453 * exception mid [ forward | keep ]
3457 exception_command (args, from_tty)
3466 error_no_arg ("exception number action");
3468 while (*scan == ' ' || *scan == '\t')
3471 if ('0' <= *scan && *scan <= '9')
3472 while ('0' <= *scan && *scan <= '9')
3475 error ("exception number action");
3477 exception = atoi (args);
3478 if (exception <= 0 || exception > MAX_EXCEPTION)
3479 error ("Allowed exception numbers are in range 1..%d",
3482 if (*scan != ' ' && *scan != '\t')
3483 error ("exception number must be followed by a space");
3485 while (*scan == ' ' || *scan == '\t')
3497 error ("exception number action");
3499 if (!strncasecmp (args, "forward", len))
3500 exception_map[exception].forward = TRUE;
3501 else if (!strncasecmp (args, "keep", len))
3502 exception_map[exception].forward = FALSE;
3504 error ("exception action is either \"keep\" or \"forward\"");
3508 print_exception_info (exception)
3511 boolean_t forward = exception_map[exception].forward;
3513 printf_filtered ("%s\t(%d): ", exception_map[exception].name,
3516 if (exception_map[exception].sigmap != SIG_UNKNOWN)
3517 printf_filtered ("keep and handle as signal %d\n",
3518 exception_map[exception].sigmap);
3520 printf_filtered ("keep and handle as unknown signal %d\n",
3521 exception_map[exception].sigmap);
3523 printf_filtered ("forward exception to inferior\n");
3527 exception_info (args, from_tty)
3534 for (exception = 1; exception <= MAX_EXCEPTION; exception++)
3535 print_exception_info (exception);
3538 exception = atoi (args);
3540 if (exception <= 0 || exception > MAX_EXCEPTION)
3541 error ("Invalid exception number, values from 1 to %d allowed",
3543 print_exception_info (exception);
3547 /* Check for actions for mach exceptions.
3549 mach3_exception_actions (w, force_print_only, who)
3551 boolean_t force_print_only;
3554 boolean_t force_print = FALSE;
3557 if (force_print_only ||
3558 exception_map[stop_exception].sigmap == SIG_UNKNOWN)
3561 WSETSTOP (*w, exception_map[stop_exception].sigmap);
3563 if (exception_map[stop_exception].print || force_print)
3565 target_terminal_ours ();
3567 printf_filtered ("\n%s received %s exception : ",
3569 exception_map[stop_exception].name);
3573 switch (stop_exception)
3575 case EXC_BAD_ACCESS:
3576 printf_filtered ("referencing address 0x%x : %s\n",
3578 mach_error_string (stop_code));
3580 case EXC_BAD_INSTRUCTION:
3582 ("illegal or undefined instruction. code %d subcode %d\n",
3583 stop_code, stop_subcode);
3585 case EXC_ARITHMETIC:
3586 printf_filtered ("code %d\n", stop_code);
3589 printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
3592 printf_filtered ("%s specific, code 0x%x\n",
3593 stop_code < 0xffff ? "hardware" : "os emulation",
3596 case EXC_BREAKPOINT:
3597 printf_filtered ("type %d (machine dependent)\n",
3601 internal_error ("Unknown exception");
3606 setup_notify_port (create_new)
3611 if (MACH_PORT_VALID (our_notify_port))
3613 ret = mach_port_destroy (mach_task_self (), our_notify_port);
3614 CHK ("Could not destroy our_notify_port", ret);
3617 our_notify_port = MACH_PORT_NULL;
3618 notify_chain = (port_chain_t) NULL;
3619 port_chain_destroy (port_chain_obstack);
3623 ret = mach_port_allocate (mach_task_self (),
3624 MACH_PORT_RIGHT_RECEIVE,
3626 if (ret != KERN_SUCCESS)
3627 internal_error ("Creating notify port %s", mach_error_string (ret));
3629 ret = mach_port_move_member (mach_task_self (),
3631 inferior_wait_port_set);
3632 if (ret != KERN_SUCCESS)
3633 internal_error ("initial move member %s", mach_error_string (ret));
3638 * Register our message port to the net name server
3640 * Currently used only by the external stop-gdb program
3641 * since ^C does not work if you would like to enter
3642 * gdb command level while debugging your program.
3644 * NOTE: If the message port is sometimes used for other
3645 * purposes also, the NAME must not be a guessable one.
3646 * Then, there should be a way to change it.
3649 char registered_name[MAX_NAME_LEN];
3652 message_port_info (args, from_tty)
3656 if (registered_name[0])
3657 printf_filtered ("gdb's message port name: '%s'\n",
3660 printf_filtered ("gdb's message port is not currently registered\n");
3664 gdb_register_port (name, port)
3669 static int already_signed = 0;
3672 if (!MACH_PORT_VALID (port) || !name || !*name)
3674 warning ("Invalid registration request");
3678 if (!already_signed)
3680 ret = mach_port_insert_right (mach_task_self (),
3683 MACH_MSG_TYPE_MAKE_SEND);
3684 CHK ("Failed to create a signature to our_message_port", ret);
3687 else if (already_signed > 1)
3689 ret = netname_check_out (name_server_port,
3692 CHK ("Failed to check out gdb's message port", ret);
3693 registered_name[0] = '\000';
3697 ret = netname_check_in (name_server_port, /* Name server port */
3698 name, /* Name of service */
3699 our_message_port, /* Signature */
3700 port); /* Creates a new send right */
3701 CHK ("Failed to check in the port", ret);
3704 while (len < MAX_NAME_LEN && *(name + len))
3706 registered_name[len] = *(name + len);
3709 registered_name[len] = '\000';
3713 struct cmd_list_element *cmd_thread_list;
3714 struct cmd_list_element *cmd_task_list;
3718 thread_command (arg, from_tty)
3722 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3723 help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
3728 task_command (arg, from_tty)
3732 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3733 help_list (cmd_task_list, "task ", -1, gdb_stdout);
3736 add_mach_specific_commands ()
3738 /* Thread handling commands */
3740 /* FIXME: Move our thread support into the generic thread.c stuff so we
3741 can share that code. */
3742 add_prefix_cmd ("mthread", class_stack, thread_command,
3743 "Generic command for handling Mach threads in the debugged task.",
3744 &cmd_thread_list, "thread ", 0, &cmdlist);
3746 add_com_alias ("th", "mthread", class_stack, 1);
3748 add_cmd ("select", class_stack, thread_select_command,
3749 "Select and print MID of the selected thread",
3751 add_cmd ("list", class_stack, thread_list_command,
3752 "List info of task's threads. Selected thread is marked with '*'",
3754 add_cmd ("suspend", class_run, thread_suspend_command,
3755 "Suspend one or all of the threads in the selected task.",
3757 add_cmd ("resume", class_run, thread_resume_command,
3758 "Resume one or all of the threads in the selected task.",
3760 add_cmd ("kill", class_run, thread_kill_command,
3761 "Kill the specified thread MID from inferior task.",
3764 /* The rest of this support (condition_thread) was not merged. It probably
3765 should not be merged in this form, but instead added to the generic GDB
3767 add_cmd ("break", class_breakpoint, condition_thread,
3768 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3769 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3772 /* Thread command shorthands (for backward compatibility) */
3773 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
3774 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist);
3776 /* task handling commands */
3778 add_prefix_cmd ("task", class_stack, task_command,
3779 "Generic command for handling debugged task.",
3780 &cmd_task_list, "task ", 0, &cmdlist);
3782 add_com_alias ("ta", "task", class_stack, 1);
3784 add_cmd ("suspend", class_run, task_suspend_command,
3785 "Suspend the inferior task.",
3787 add_cmd ("resume", class_run, task_resume_command,
3788 "Resume the inferior task.",
3790 add_cmd ("info", no_class, task_info_command,
3791 "Print information about the specified task.",
3794 /* Print my message port name */
3796 add_info ("message-port", message_port_info,
3797 "Returns the name of gdb's message port in the netnameserver");
3799 /* Exception commands */
3801 add_info ("exceptions", exception_info,
3802 "What debugger does when program gets various exceptions.\n\
3803 Specify an exception number as argument to print info on that\n\
3806 add_com ("exception", class_run, exception_command,
3807 "Specify how to handle an exception.\n\
3808 Args are exception number followed by \"forward\" or \"keep\".\n\
3809 `Forward' means forward the exception to the program's normal exception\n\
3811 `Keep' means reenter debugger if this exception happens, and GDB maps\n\
3812 the exception to some signal (see info exception)\n\
3813 Normally \"keep\" is used to return to GDB on exception.");
3817 do_mach_notify_dead_name (notify, name)
3821 kern_return_t kr = KERN_SUCCESS;
3823 /* Find the thing that notified */
3824 port_chain_t element = port_chain_member (notify_chain, name);
3826 /* Take name of from unreceived dead name notification list */
3827 notify_chain = port_chain_delete (notify_chain, name);
3830 error ("Received a dead name notify from unchained port (0x%x)", name);
3832 switch (element->type)
3835 case MACH_TYPE_THREAD:
3836 target_terminal_ours_for_output ();
3837 if (name == current_thread)
3839 printf_filtered ("\nCurrent thread %d died", element->mid);
3840 current_thread = MACH_PORT_NULL;
3843 printf_filtered ("\nThread %d died", element->mid);
3847 case MACH_TYPE_TASK:
3848 target_terminal_ours_for_output ();
3849 if (name != inferior_task)
3850 printf_filtered ("Task %d died, but it was not the selected task",
3854 printf_filtered ("Current task %d died", element->mid);
3856 mach_port_destroy (mach_task_self (), name);
3857 inferior_task = MACH_PORT_NULL;
3860 warning ("There were still unreceived dead_name_notifications???");
3862 /* Destroy the old notifications */
3863 setup_notify_port (0);
3869 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3870 name, element->type, element->mid);
3874 return KERN_SUCCESS;
3878 do_mach_notify_msg_accepted (notify, name)
3882 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3884 return KERN_SUCCESS;
3888 do_mach_notify_no_senders (notify, mscount)
3890 mach_port_mscount_t mscount;
3892 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3894 return KERN_SUCCESS;
3898 do_mach_notify_port_deleted (notify, name)
3902 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3904 return KERN_SUCCESS;
3908 do_mach_notify_port_destroyed (notify, rights)
3912 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3914 return KERN_SUCCESS;
3918 do_mach_notify_send_once (notify)
3922 /* MANY of these are generated. */
3923 warning ("do_mach_notify_send_once : notify %x",
3926 return KERN_SUCCESS;
3929 /* Kills the inferior. It's gone when you call this */
3931 kill_inferior_fast ()
3935 if (inferior_pid == 0 || inferior_pid == 1)
3938 /* kill() it, since the Unix server does not otherwise notice when
3939 * killed with task_terminate().
3941 if (inferior_pid > 0)
3942 kill (inferior_pid, SIGKILL);
3944 /* It's propably terminate already */
3945 (void) task_terminate (inferior_task);
3947 inferior_task = MACH_PORT_NULL;
3948 current_thread = MACH_PORT_NULL;
3950 wait3 (&w, WNOHANG, 0);
3952 setup_notify_port (0);
3958 kill_inferior_fast ();
3959 target_mourn_inferior ();
3962 /* Clean up after the inferior dies. */
3965 m3_mourn_inferior ()
3967 unpush_target (&m3_ops);
3968 generic_mourn_inferior ();
3972 /* Fork an inferior process, and start debugging it. */
3975 m3_create_inferior (exec_file, allargs, env)
3980 fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL, NULL);
3981 /* We are at the first instruction we care about. */
3982 /* Pedal to the metal... */
3983 proceed ((CORE_ADDR) -1, 0, 0);
3986 /* Mark our target-struct as eligible for stray "run" and "attach"
3994 /* Mach 3.0 does not need ptrace for anything
3995 * Make sure nobody uses it on mach.
4000 error ("Lose, Lose! Somebody called ptrace\n");
4003 /* Resume execution of the inferior process.
4004 If STEP is nonzero, single-step it.
4005 If SIGNAL is nonzero, give it that signal. */
4008 m3_resume (pid, step, signal)
4011 enum target_signal signal;
4017 thread_basic_info_data_t th_info;
4018 unsigned int infoCnt = THREAD_BASIC_INFO_COUNT;
4020 /* There is no point in single stepping when current_thread
4023 if (!MACH_PORT_VALID (current_thread))
4024 error ("No thread selected; can not single step");
4026 /* If current_thread is suspended, tracing it would never return.
4028 ret = thread_info (current_thread,
4030 (thread_info_t) & th_info,
4032 CHK ("child_resume: can't get thread info", ret);
4034 if (th_info.suspend_count)
4035 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
4038 vm_read_cache_valid = FALSE;
4040 if (signal && inferior_pid > 0) /* Do not signal, if attached by MID */
4041 kill (inferior_pid, target_signal_to_host (signal));
4045 suspend_all_threads (0);
4047 setup_single_step (current_thread, TRUE);
4049 ret = thread_resume (current_thread);
4050 CHK ("thread_resume", ret);
4053 ret = task_resume (inferior_task);
4054 if (ret == KERN_FAILURE)
4055 warning ("Task was not suspended");
4057 CHK ("Resuming task", ret);
4059 /* HACK HACK This is needed by the multiserver system HACK HACK */
4060 while ((ret = task_resume (inferior_task)) == KERN_SUCCESS)
4061 /* make sure it really runs */ ;
4062 /* HACK HACK This is needed by the multiserver system HACK HACK */
4065 #ifdef ATTACH_DETACH
4067 /* Start debugging the process with the given task */
4073 inferior_task = tid;
4075 ret = task_suspend (inferior_task);
4076 CHK ("task_attach: task_suspend", ret);
4078 must_suspend_thread = 0;
4080 setup_notify_port (1);
4082 request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
4084 setup_exception_port ();
4086 emulator_present = have_emulator_p (inferior_task);
4091 /* Well, we can call error also here and leave the
4092 * target stack inconsistent. Sigh.
4093 * Fix this sometime (the only way to fail here is that
4094 * the task has no threads at all, which is rare, but
4095 * possible; or if the target task has died, which is also
4096 * possible, but unlikely, since it has been suspended.
4097 * (Someone must have killed it))
4102 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
4103 error ("Could not select any threads to attach to");
4111 ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
4112 CHK ("mid_attach: machid_mach_port", ret);
4114 task_attach (inferior_task);
4120 * Start debugging the process whose unix process-id is PID.
4121 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
4123 * Prevent (possible unwanted) dangerous operations by enabled users
4124 * like "atta 0" or "atta foo" (equal to the previous :-) and
4125 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4134 error ("MID=0, Debugging the master unix server does not compute");
4136 /* Foo. This assumes gdb has a unix pid */
4137 if (pid == getpid ())
4138 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4142 mid_attach (-(pid));
4144 /* inferior_pid will be NEGATIVE! */
4147 return inferior_pid;
4150 inferior_task = task_by_pid (pid);
4151 if (!MACH_PORT_VALID (inferior_task))
4152 error ("Cannot map Unix pid %d to Mach task port", pid);
4154 task_attach (inferior_task);
4158 return inferior_pid;
4161 /* Attach to process PID, then initialize for debugging it
4162 and wait for the trace-trap that results from attaching. */
4165 m3_attach (args, from_tty)
4173 error_no_arg ("process-id to attach");
4177 if (pid == getpid ()) /* Trying to masturbate? */
4178 error ("I refuse to debug myself!");
4182 exec_file = (char *) get_exec_file (0);
4185 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
4187 printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
4189 gdb_flush (gdb_stdout);
4194 push_target (&m3_ops);
4198 deallocate_inferior_ports ()
4201 thread_array_t thread_list;
4202 int thread_count, index;
4204 if (!MACH_PORT_VALID (inferior_task))
4207 ret = task_threads (inferior_task, &thread_list, &thread_count);
4208 if (ret != KERN_SUCCESS)
4210 warning ("deallocate_inferior_ports: task_threads",
4211 mach_error_string (ret));
4215 /* Get rid of send rights to task threads */
4216 for (index = 0; index < thread_count; index++)
4219 ret = mach_port_get_refs (mach_task_self (),
4221 MACH_PORT_RIGHT_SEND,
4223 CHK ("deallocate_inferior_ports: get refs", ret);
4227 ret = mach_port_mod_refs (mach_task_self (),
4229 MACH_PORT_RIGHT_SEND,
4231 CHK ("deallocate_inferior_ports: mod refs", ret);
4235 ret = mach_port_mod_refs (mach_task_self (),
4236 inferior_exception_port,
4237 MACH_PORT_RIGHT_RECEIVE,
4239 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
4241 ret = mach_port_deallocate (mach_task_self (),
4243 CHK ("deallocate_task_port: deallocating inferior_task", ret);
4245 current_thread = MACH_PORT_NULL;
4246 inferior_task = MACH_PORT_NULL;
4249 /* Stop debugging the process whose number is PID
4250 and continue it with signal number SIGNAL.
4251 SIGNAL = 0 means just continue it. */
4254 m3_do_detach (signal)
4259 MACH_ERROR_NO_INFERIOR;
4261 if (current_thread != MACH_PORT_NULL)
4263 /* Store the gdb's view of the thread we are deselecting
4265 * @@ I am really not sure if this is ever needeed.
4267 target_prepare_to_store ();
4268 target_store_registers (-1);
4271 ret = task_set_special_port (inferior_task,
4272 TASK_EXCEPTION_PORT,
4273 inferior_old_exception_port);
4274 CHK ("task_set_special_port", ret);
4276 /* Discard all requested notifications */
4277 setup_notify_port (0);
4279 if (remove_breakpoints ())
4280 warning ("Could not remove breakpoints when detaching");
4282 if (signal && inferior_pid > 0)
4283 kill (inferior_pid, signal);
4285 /* the task might be dead by now */
4286 (void) task_resume (inferior_task);
4288 deallocate_inferior_ports ();
4293 /* Take a program previously attached to and detaches it.
4294 The program resumes execution and will no longer stop
4295 on signals, etc. We'd better not have left any breakpoints
4296 in the program or it'll die when it hits one. For this
4297 to work, it may be necessary for the process to have been
4298 previously attached. It *might* work if the program was
4299 started via fork. */
4302 m3_detach (args, from_tty)
4310 char *exec_file = get_exec_file (0);
4313 printf_unfiltered ("Detaching from program: %s %s\n",
4314 exec_file, target_pid_to_str (inferior_pid));
4315 gdb_flush (gdb_stdout);
4318 siggnal = atoi (args);
4320 m3_do_detach (siggnal);
4322 unpush_target (&m3_ops); /* Pop out of handling an inferior */
4324 #endif /* ATTACH_DETACH */
4326 /* Get ready to modify the registers array. On machines which store
4327 individual registers, this doesn't need to do anything. On machines
4328 which store all the registers in one fell swoop, this makes sure
4329 that registers contains all the registers from the program being
4333 m3_prepare_to_store ()
4335 #ifdef CHILD_PREPARE_TO_STORE
4336 CHILD_PREPARE_TO_STORE ();
4340 /* Print status information about what we're accessing. */
4343 m3_files_info (ignore)
4344 struct target_ops *ignore;
4346 /* FIXME: should print MID and all that crap. */
4347 printf_unfiltered ("\tUsing the running image of %s %s.\n",
4348 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
4352 m3_open (arg, from_tty)
4356 error ("Use the \"run\" command to start a Unix child process.");
4366 char *bsd1_names[] =
4435 int bsd1_nnames = sizeof (bsd1_names) / sizeof (bsd1_names[0]);
4438 name_str (name, buf)
4446 case MACH_MSG_TYPE_BOOLEAN:
4448 case MACH_MSG_TYPE_INTEGER_16:
4450 case MACH_MSG_TYPE_INTEGER_32:
4452 case MACH_MSG_TYPE_CHAR:
4454 case MACH_MSG_TYPE_BYTE:
4456 case MACH_MSG_TYPE_REAL:
4458 case MACH_MSG_TYPE_STRING:
4461 sprintf (buf, "%d", name);
4474 if (id >= 101000 && id < 101000 + bsd1_nnames)
4476 if (p = bsd1_names[id - 101000])
4480 return "psignal_retry";
4483 sprintf (buf, "%d", id);
4488 mach_msg_header_t *mp;
4490 char *fmt_x = "%20s : 0x%08x\n";
4491 char *fmt_d = "%20s : %10d\n";
4492 char *fmt_s = "%20s : %s\n";
4495 puts_filtered ("\n");
4496 #define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
4497 pr (fmt_x, (*mp), msgh_bits);
4498 pr (fmt_d, (*mp), msgh_size);
4499 pr (fmt_x, (*mp), msgh_remote_port);
4500 pr (fmt_x, (*mp), msgh_local_port);
4501 pr (fmt_d, (*mp), msgh_kind);
4502 printf_filtered (fmt_s, STR (msgh_id), id_str (mp->msgh_id, buf));
4504 if (debug_level > 1)
4509 ep = p + mp->msgh_size;
4511 for (; p < ep; p += plen)
4513 mach_msg_type_t *tp;
4514 mach_msg_type_long_t *tlp;
4515 int name, size, number;
4516 tp = (mach_msg_type_t *) p;
4517 if (tp->msgt_longform)
4519 tlp = (mach_msg_type_long_t *) tp;
4520 name = tlp->msgtl_name;
4521 size = tlp->msgtl_size;
4522 number = tlp->msgtl_number;
4523 plen = sizeof (*tlp);
4527 name = tp->msgt_name;
4528 size = tp->msgt_size;
4529 number = tp->msgt_number;
4530 plen = sizeof (*tp);
4532 printf_filtered ("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4533 name_str (name, buf), size, number, tp->msgt_inline,
4534 tp->msgt_longform, tp->msgt_deallocate);
4536 if (tp->msgt_inline)
4539 l = size * number / 8;
4540 l = (l + sizeof (long) - 1) & ~((sizeof (long)) - 1);
4542 print_data (dp, size, number);
4546 plen += sizeof (int *);
4548 printf_filtered ("plen=%d\n", plen);
4553 print_data (p, size, number)
4565 for (i = 0; i < number; i++)
4567 printf_filtered (" %02x", p[i]);
4572 for (i = 0; i < number; i++)
4574 printf_filtered (" %04x", sp[i]);
4579 for (i = 0; i < number; i++)
4581 printf_filtered (" %08x", ip[i]);
4585 puts_filtered ("\n");
4587 #endif /* DUMP_SYSCALL */
4592 error ("to_stop target function not implemented");
4596 m3_pid_to_exec_file (pid)
4599 error ("to_pid_to_exec_file target function not implemented");
4600 return NULL; /* To keep all compilers happy. */
4606 m3_ops.to_shortname = "mach";
4607 m3_ops.to_longname = "Mach child process";
4608 m3_ops.to_doc = "Mach child process (started by the \"run\" command).";
4609 m3_ops.to_open = m3_open;
4610 m3_ops.to_attach = m3_attach;
4611 m3_ops.to_detach = m3_detach;
4612 m3_ops.to_resume = m3_resume;
4613 m3_ops.to_wait = mach_really__wait;
4614 m3_ops.to_fetch_registers = fetch_inferior_registers;
4615 m3_ops.to_store_registers = store_inferior_registers;
4616 m3_ops.to_prepare_to_store = m3_prepare_to_store;
4617 m3_ops.to_xfer_memory = m3_xfer_memory;
4618 m3_ops.to_files_info = m3_files_info;
4619 m3_ops.to_insert_breakpoint = memory_insert_breakpoint;
4620 m3_ops.to_remove_breakpoint = memory_remove_breakpoint;
4621 m3_ops.to_terminal_init = terminal_init_inferior;
4622 m3_ops.to_terminal_inferior = terminal_inferior;
4623 m3_ops.to_terminal_ours_for_output = terminal_ours_for_output;
4624 m3_ops.to_terminal_ours = terminal_ours;
4625 m3_ops.to_terminal_info = child_terminal_info;
4626 m3_ops.to_kill = m3_kill_inferior;
4627 m3_ops.to_create_inferior = m3_create_inferior;
4628 m3_ops.to_mourn_inferior = m3_mourn_inferior;
4629 m3_ops.to_can_run = m3_can_run;
4630 m3_ops.to_stop = m3_stop;
4631 m3_ops.to_pid_to_exec_file = m3_pid_to_exec_file;
4632 m3_ops.to_stratum = process_stratum;
4633 m3_ops.to_has_all_memory = 1;
4634 m3_ops.to_has_memory = 1;
4635 m3_ops.to_has_stack = 1;
4636 m3_ops.to_has_registers = 1;
4637 m3_ops.to_has_execution = 1;
4638 m3_ops.to_magic = OPS_MAGIC;
4642 _initialize_m3_nat ()
4647 add_target (&m3_ops);
4649 ret = mach_port_allocate (mach_task_self (),
4650 MACH_PORT_RIGHT_PORT_SET,
4651 &inferior_wait_port_set);
4652 if (ret != KERN_SUCCESS)
4653 internal_error ("initial port set %s", mach_error_string (ret));
4655 /* mach_really_wait now waits for this */
4656 currently_waiting_for = inferior_wait_port_set;
4658 ret = netname_look_up (name_server_port, hostname, "MachID", &mid_server);
4659 if (ret != KERN_SUCCESS)
4661 mid_server = MACH_PORT_NULL;
4663 warning ("initialize machid: netname_lookup_up(MachID) : %s",
4664 mach_error_string (ret));
4665 warning ("Some (most?) features disabled...");
4668 mid_auth = mach_privileged_host_port ();
4669 if (mid_auth == MACH_PORT_NULL)
4670 mid_auth = mach_task_self ();
4672 obstack_init (port_chain_obstack);
4674 ret = mach_port_allocate (mach_task_self (),
4675 MACH_PORT_RIGHT_RECEIVE,
4676 &thread_exception_port);
4677 CHK ("Creating thread_exception_port for single stepping", ret);
4679 ret = mach_port_insert_right (mach_task_self (),
4680 thread_exception_port,
4681 thread_exception_port,
4682 MACH_MSG_TYPE_MAKE_SEND);
4683 CHK ("Inserting send right to thread_exception_port", ret);
4685 /* Allocate message port */
4686 ret = mach_port_allocate (mach_task_self (),
4687 MACH_PORT_RIGHT_RECEIVE,
4689 if (ret != KERN_SUCCESS)
4690 warning ("Creating message port %s", mach_error_string (ret));
4693 char buf[MAX_NAME_LEN];
4694 ret = mach_port_move_member (mach_task_self (),
4696 inferior_wait_port_set);
4697 if (ret != KERN_SUCCESS)
4698 warning ("message move member %s", mach_error_string (ret));
4701 /* @@@@ No way to change message port name currently */
4702 /* Foo. This assumes gdb has a unix pid */
4703 sprintf (buf, "gdb-%d", getpid ());
4704 gdb_register_port (buf, our_message_port);
4707 /* Heap for thread commands */
4708 obstack_init (cproc_obstack);
4710 add_mach_specific_commands ();