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. */
24 * Author: Jukka Virtanen <jtv@hut.fi>
26 * Helsinki University of Technology
29 * Thanks to my friends who helped with ideas and testing:
31 * Johannes Helander, Antti Louko, Tero Mononen,
32 * jvh@cs.hut.fi alo@hut.fi tmo@cs.hut.fi
34 * Tero Kivinen and Eamonn McManus
35 * kivinen@cs.hut.fi emcmanus@gr.osf.org
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 (char *fmt
, int a
, int b
, int c
)
213 warning (fmt
, a
, b
, c
);
216 /* This is in libmach.a */
217 extern mach_port_t name_server_port
;
219 /* Set in catch_exception_raise */
220 int stop_exception
, stop_code
, stop_subcode
;
221 int stopped_in_exception
;
223 /* Thread that was the active thread when we stopped */
224 thread_t stop_thread
= MACH_PORT_NULL
;
228 /* Set when task is attached or created */
229 boolean_t emulator_present
= FALSE
;
231 task_t inferior_task
;
232 thread_t current_thread
;
234 /* Exception ports for inferior task */
235 mach_port_t inferior_exception_port
= MACH_PORT_NULL
;
236 mach_port_t inferior_old_exception_port
= MACH_PORT_NULL
;
238 /* task exceptions and notifications */
239 mach_port_t inferior_wait_port_set
= MACH_PORT_NULL
;
240 mach_port_t our_notify_port
= MACH_PORT_NULL
;
242 /* This is "inferior_wait_port_set" when not single stepping, and
243 * "singlestepped_thread_port" when we are single stepping.
245 * This is protected by a cleanup function: discard_single_step()
247 mach_port_t currently_waiting_for
= MACH_PORT_NULL
;
249 /* A port for external messages to gdb.
250 * External in the meaning that they do not come
251 * from the inferior_task, but rather from external
254 * As a debugging feature:
255 * A debugger debugging another debugger can stop the
256 * inferior debugger by the following command sequence
257 * (without running external programs)
259 * (top-gdb) set stop_inferior_gdb ()
262 mach_port_t our_message_port
= MACH_PORT_NULL
;
264 /* For single stepping */
265 mach_port_t thread_exception_port
= MACH_PORT_NULL
;
266 mach_port_t thread_saved_exception_port
= MACH_PORT_NULL
;
267 mach_port_t singlestepped_thread_port
= MACH_PORT_NULL
;
269 /* For machid calls */
270 mach_port_t mid_server
= MACH_PORT_NULL
;
271 mach_port_t mid_auth
= MACH_PORT_NULL
;
273 /* If gdb thinks the inferior task is not suspended, it
274 * must take suspend/abort the threads when it reads the state.
276 int must_suspend_thread
= 0;
278 /* When single stepping, we switch the port that mach_really_wait() listens to.
279 * This cleanup is a guard to prevent the port set from being left to
280 * the singlestepped_thread_port when error() is called.
281 * This is nonzero only when we are single stepping.
283 #define NULL_CLEANUP (struct cleanup *)0
284 struct cleanup
*cleanup_step
= NULL_CLEANUP
;
287 static struct target_ops m3_ops
;
289 static void m3_kill_inferior ();
292 #define MACH_TYPE_EXCEPTION_PORT -1
295 /* Chain of ports to remember requested notifications. */
299 struct port_chain
*next
;
302 int mid
; /* Now only valid with MACH_TYPE_THREAD and */
303 /* MACH_TYPE_THREAD */
305 typedef struct port_chain
*port_chain_t
;
307 /* Room for chain nodes comes from pchain_obstack */
308 struct obstack pchain_obstack
;
309 struct obstack
*port_chain_obstack
= &pchain_obstack
;
311 /* For thread handling */
312 struct obstack Cproc_obstack
;
313 struct obstack
*cproc_obstack
= &Cproc_obstack
;
315 /* the list of notified ports */
316 port_chain_t notify_chain
= (port_chain_t
) NULL
;
319 port_chain_insert (port_chain_t list
, mach_port_t name
, int type
)
325 if (!MACH_PORT_VALID (name
))
328 if (type
== MACH_TYPE_TASK
|| type
== MACH_TYPE_THREAD
)
330 if (!MACH_PORT_VALID (mid_server
))
332 warning ("Machid server port invalid, can not map port 0x%x to MID",
338 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
340 if (ret
!= KERN_SUCCESS
)
342 warning ("Can not map name (0x%x) to MID with machid", name
);
350 new = (port_chain_t
) obstack_alloc (port_chain_obstack
,
351 sizeof (struct port_chain
));
361 port_chain_delete (port_chain_t list
, mach_port_t elem
)
364 if (list
->port
== elem
)
369 if (list
->next
->port
== elem
)
370 list
->next
= list
->next
->next
; /* GCd with obstack_free() */
378 port_chain_destroy (struct obstack
*ostack
)
380 obstack_free (ostack
, 0);
381 obstack_init (ostack
);
385 port_chain_member (port_chain_t list
, mach_port_t elem
)
389 if (list
->port
== elem
)
393 return (port_chain_t
) NULL
;
397 map_port_name_to_mid (mach_port_t name
, int type
)
401 if (!MACH_PORT_VALID (name
))
404 elem
= port_chain_member (notify_chain
, name
);
406 if (elem
&& (elem
->type
== type
))
412 if (!MACH_PORT_VALID (mid_server
))
414 warning ("Machid server port invalid, can not map port 0x%x to mid",
423 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
425 if (ret
!= KERN_SUCCESS
)
427 warning ("Can not map name (0x%x) to mid with machid", name
);
434 /* Guard for currently_waiting_for and singlestepped_thread_port */
436 discard_single_step (thread_t thread
)
438 currently_waiting_for
= inferior_wait_port_set
;
440 cleanup_step
= NULL_CLEANUP
;
441 if (MACH_PORT_VALID (thread
) && MACH_PORT_VALID (singlestepped_thread_port
))
442 setup_single_step (thread
, FALSE
);
445 setup_single_step (thread_t thread
, boolean_t start_step
)
449 if (!MACH_PORT_VALID (thread
))
450 error ("Invalid thread supplied to setup_single_step");
455 /* Get the current thread exception port */
456 ret
= thread_get_exception_port (thread
, &teport
);
457 CHK ("Getting thread's exception port", ret
);
461 if (MACH_PORT_VALID (singlestepped_thread_port
))
463 warning ("Singlestepped_thread_port (0x%x) is still valid?",
464 singlestepped_thread_port
);
465 singlestepped_thread_port
= MACH_PORT_NULL
;
468 /* If we are already stepping this thread */
469 if (MACH_PORT_VALID (teport
) && teport
== thread_exception_port
)
471 ret
= mach_port_deallocate (mach_task_self (), teport
);
472 CHK ("Could not deallocate thread exception port", ret
);
476 ret
= thread_set_exception_port (thread
, thread_exception_port
);
477 CHK ("Setting exception port for thread", ret
);
479 /* Insert thread exception port to wait port set */
480 ret
= mach_port_move_member (mach_task_self (),
481 thread_exception_port
,
482 inferior_wait_port_set
);
483 CHK ("Moving thread exception port to inferior_wait_port_set",
486 thread_saved_exception_port
= teport
;
489 thread_trace (thread
, TRUE
);
491 singlestepped_thread_port
= thread_exception_port
;
492 currently_waiting_for
= singlestepped_thread_port
;
493 cleanup_step
= make_cleanup (discard_single_step
, thread
);
497 if (!MACH_PORT_VALID (teport
))
498 error ("Single stepped thread had an invalid exception port?");
500 if (teport
!= thread_exception_port
)
501 error ("Single stepped thread had an unknown exception port?");
503 ret
= mach_port_deallocate (mach_task_self (), teport
);
504 CHK ("Couldn't deallocate thread exception port", ret
);
506 /* Remove thread exception port from wait port set */
507 ret
= mach_port_move_member (mach_task_self (),
508 thread_exception_port
,
510 CHK ("Removing thread exception port from inferior_wait_port_set",
513 /* Restore thread's old exception port */
514 ret
= thread_set_exception_port (thread
,
515 thread_saved_exception_port
);
516 CHK ("Restoring stepped thread's exception port", ret
);
518 if (MACH_PORT_VALID (thread_saved_exception_port
))
519 (void) mach_port_deallocate (mach_task_self (),
520 thread_saved_exception_port
);
522 thread_trace (thread
, FALSE
);
524 singlestepped_thread_port
= MACH_PORT_NULL
;
525 currently_waiting_for
= inferior_wait_port_set
;
527 discard_cleanups (cleanup_step
);
533 request_notify (mach_port_t name
, mach_msg_id_t variant
, int type
)
536 mach_port_t previous_port_dummy
= MACH_PORT_NULL
;
538 if (!MACH_PORT_VALID (name
))
541 if (port_chain_member (notify_chain
, name
))
544 ret
= mach_port_request_notification (mach_task_self (),
549 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
550 &previous_port_dummy
);
551 CHK ("Serious: request_notify failed", ret
);
553 (void) mach_port_deallocate (mach_task_self (),
554 previous_port_dummy
);
556 notify_chain
= port_chain_insert (notify_chain
, name
, type
);
559 reverse_msg_bits (mach_msg_header_t
*msgp
, int type
)
562 rbits
= MACH_MSGH_BITS_REMOTE (msgp
->msgh_bits
);
565 (msgp
->msgh_bits
& ~MACH_MSGH_BITS_PORTS_MASK
) |
566 MACH_MSGH_BITS (lbits
, rbits
);
569 /* On the third day He said:
572 and then it was global.
574 When creating the inferior fork, the
575 child code in inflow.c sets the name of the
576 bootstrap_port in its address space to this
579 The name is transferred to our address space
580 with mach3_read_inferior().
582 Thou shalt not do this with
583 task_get_bootstrap_port() in this task, since
584 the name in the inferior task is different than
587 For blessed are the meek, as they shall inherit
590 mach_port_t original_server_port_name
= MACH_PORT_NULL
;
593 /* Called from inferior after FORK but before EXEC */
599 /* Get the NAME of the bootstrap port in this task
600 so that GDB can read it */
601 ret
= task_get_bootstrap_port (mach_task_self (),
602 &original_server_port_name
);
603 if (ret
!= KERN_SUCCESS
)
605 ret
= mach_port_deallocate (mach_task_self (),
606 original_server_port_name
);
607 if (ret
!= KERN_SUCCESS
)
610 /* Suspend this task to let the parent change my ports.
611 Resumed by the debugger */
612 ret
= task_suspend (mach_task_self ());
613 if (ret
!= KERN_SUCCESS
)
618 * Intercept system calls to Unix server.
619 * After EXEC_COUNTER calls to exec(), return.
621 * Pre-assertion: Child is suspended. (Not verified)
622 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
626 intercept_exec_calls (int exec_counter
)
628 int terminal_initted
= 0;
632 mach_msg_header_t header
;
633 mach_msg_type_t type
;
634 char room
[2000]; /* Enuff space */
637 struct syscall_msg_t syscall_in
, syscall_out
;
639 mach_port_t fake_server
;
640 mach_port_t original_server_send
;
641 mach_port_t original_exec_reply
;
642 mach_port_t exec_reply
;
643 mach_port_t exec_reply_send
;
644 mach_msg_type_name_t acquired
;
645 mach_port_t emulator_server_port_name
;
646 struct task_basic_info info
;
647 mach_msg_type_number_t info_count
;
651 if (exec_counter
<= 0)
652 return; /* We are already set up in the correct program */
654 ret
= mach_port_allocate (mach_task_self (),
655 MACH_PORT_RIGHT_RECEIVE
,
657 CHK ("create inferior_fake_server port failed", ret
);
659 /* Wait for inferior_task to suspend itself */
662 info_count
= sizeof (info
);
663 ret
= task_info (inferior_task
,
665 (task_info_t
) & info
,
667 CHK ("Task info", ret
);
669 if (info
.suspend_count
)
672 /* Note that the definition of the parameter was undefined
673 * at the time of this writing, so I just use an `ad hoc' value.
675 (void) swtch_pri (42); /* Universal Priority Value */
678 /* Read the inferior's bootstrap port name */
679 if (!mach3_read_inferior (&original_server_port_name
,
680 &original_server_port_name
,
681 sizeof (original_server_port_name
)))
682 error ("Can't read inferior task bootstrap port name");
684 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
685 /* Should get refs, and set them back when restoring */
686 /* Steal the original bsd server send right from inferior */
687 ret
= mach_port_extract_right (inferior_task
,
688 original_server_port_name
,
689 MACH_MSG_TYPE_MOVE_SEND
,
690 &original_server_send
,
692 CHK ("mach_port_extract_right (bsd server send)", ret
);
694 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
695 error ("Incorrect right extracted, send right to bsd server excpected");
697 ret
= mach_port_insert_right (inferior_task
,
698 original_server_port_name
,
700 MACH_MSG_TYPE_MAKE_SEND
);
701 CHK ("mach_port_insert_right (fake server send)", ret
);
703 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
705 original_server_port_name
, original_server_send
);
707 /* A receive right to the reply generated by unix server exec() request */
708 ret
= mach_port_allocate (mach_task_self (),
709 MACH_PORT_RIGHT_RECEIVE
,
711 CHK ("create intercepted_reply_port port failed", ret
);
713 /* Pass this send right to Unix server so it replies to us after exec() */
714 ret
= mach_port_extract_right (mach_task_self (),
716 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
719 CHK ("mach_port_extract_right (exec_reply)", ret
);
721 if (acquired
!= MACH_MSG_TYPE_PORT_SEND_ONCE
)
722 error ("Incorrect right extracted, send once excpected for exec reply");
724 ret
= mach_port_move_member (mach_task_self (),
726 inferior_wait_port_set
);
727 CHK ("Moving fake syscall port to inferior_wait_port_set", ret
);
729 xx_debug ("syscall fake server set up, resuming inferior\n");
731 ret
= task_resume (inferior_task
);
732 CHK ("task_resume (startup)", ret
);
734 /* Read requests from the inferior.
735 Pass directly through everything else except exec() calls.
737 while (exec_counter
> 0)
739 ret
= mach_msg (&syscall_in
.header
, /* header */
740 MACH_RCV_MSG
, /* options */
742 sizeof (struct syscall_msg_t
), /* receive size */
743 inferior_wait_port_set
, /* receive_name */
744 MACH_MSG_TIMEOUT_NONE
,
746 CHK ("mach_msg (intercepted sycall)", ret
);
749 print_msg (&syscall_in
.header
);
752 /* ASSERT : msgh_local_port == fake_server */
754 if (notify_server (&syscall_in
.header
, &syscall_out
.header
))
755 error ("received a notify while intercepting syscalls");
757 if (syscall_in
.header
.msgh_id
== MIG_EXEC_SYSCALL_ID
)
759 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter
);
760 if (exec_counter
== 1)
762 original_exec_reply
= syscall_in
.header
.msgh_remote_port
;
763 syscall_in
.header
.msgh_remote_port
= exec_reply_send
;
766 if (!terminal_initted
)
768 /* Now that the child has exec'd we know it has already set its
769 process group. On POSIX systems, tcsetpgrp will fail with
770 EPERM if we try it before the child's setpgid. */
772 /* Set up the "saved terminal modes" of the inferior
773 based on what modes we are starting it with. */
774 target_terminal_init ();
776 /* Install inferior's terminal modes. */
777 target_terminal_inferior ();
779 terminal_initted
= 1;
785 syscall_in
.header
.msgh_local_port
= syscall_in
.header
.msgh_remote_port
;
786 syscall_in
.header
.msgh_remote_port
= original_server_send
;
788 reverse_msg_bits (&syscall_in
.header
, MACH_MSG_TYPE_COPY_SEND
);
790 ret
= mach_msg_send (&syscall_in
.header
);
791 CHK ("Forwarded syscall", ret
);
794 ret
= mach_port_move_member (mach_task_self (),
797 CHK ("Moving fake syscall out of inferior_wait_port_set", ret
);
799 ret
= mach_port_move_member (mach_task_self (),
801 inferior_wait_port_set
);
802 CHK ("Moving exec_reply to inferior_wait_port_set", ret
);
804 ret
= mach_msg (&syscall_in
.header
, /* header */
805 MACH_RCV_MSG
, /* options */
807 sizeof (struct syscall_msg_t
), /* receive size */
808 inferior_wait_port_set
, /* receive_name */
809 MACH_MSG_TIMEOUT_NONE
,
811 CHK ("mach_msg (exec reply)", ret
);
813 ret
= task_suspend (inferior_task
);
814 CHK ("Suspending inferior after last exec", ret
);
816 must_suspend_thread
= 0;
818 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
821 print_msg (&syscall_in
.header
);
824 /* Message should appear as if it came from the unix server */
825 syscall_in
.header
.msgh_local_port
= MACH_PORT_NULL
;
827 /* and go to the inferior task original reply port */
828 syscall_in
.header
.msgh_remote_port
= original_exec_reply
;
830 reverse_msg_bits (&syscall_in
.header
, MACH_MSG_TYPE_MOVE_SEND_ONCE
);
832 ret
= mach_msg_send (&syscall_in
.header
);
833 CHK ("Forwarding exec reply to inferior", ret
);
835 /* Garbage collect */
836 ret
= mach_port_deallocate (inferior_task
,
837 original_server_port_name
);
838 CHK ("deallocating fake server send right", ret
);
840 ret
= mach_port_insert_right (inferior_task
,
841 original_server_port_name
,
842 original_server_send
,
843 MACH_MSG_TYPE_MOVE_SEND
);
844 CHK ("Restoring the original bsd server send right", ret
);
846 ret
= mach_port_destroy (mach_task_self (),
848 fake_server
= MACH_PORT_DEAD
;
849 CHK ("mach_port_destroy (fake_server)", ret
);
851 ret
= mach_port_destroy (mach_task_self (),
853 exec_reply
= MACH_PORT_DEAD
;
854 CHK ("mach_port_destroy (exec_reply)", ret
);
856 xx_debug ("Done with exec call interception\n");
860 consume_send_rights (thread_array_t thread_list
, int thread_count
)
867 for (index
= 0; index
< thread_count
; index
++)
869 /* Since thread kill command kills threads, don't check ret */
870 (void) mach_port_deallocate (mach_task_self (),
875 /* suspend/abort/resume a thread. */
876 setup_thread (mach_port_t thread
, int what
)
882 ret
= thread_suspend (thread
);
883 CHK ("setup_thread thread_suspend", ret
);
885 ret
= thread_abort (thread
);
886 CHK ("setup_thread thread_abort", ret
);
890 ret
= thread_resume (thread
);
891 CHK ("setup_thread thread_resume", ret
);
896 map_slot_to_mid (int slot
, thread_array_t threads
, int thread_count
)
906 ret
= task_threads (inferior_task
, &threads
, &thread_count
);
907 CHK ("Can not select a thread from a dead task", ret
);
910 if (slot
< 0 || slot
>= thread_count
)
914 consume_send_rights (threads
, thread_count
);
915 (void) vm_deallocate (mach_task_self (), (vm_address_t
) threads
,
916 (thread_count
* sizeof (mach_port_t
)));
919 error ("invalid slot number");
924 mid
= map_port_name_to_mid (threads
[slot
], MACH_TYPE_THREAD
);
928 consume_send_rights (threads
, thread_count
);
929 (void) vm_deallocate (mach_task_self (), (vm_address_t
) threads
,
930 (thread_count
* sizeof (mach_port_t
)));
937 parse_thread_id (char *arg
, int thread_count
, int slots
)
947 while (*arg
&& (*arg
== ' ' || *arg
== '\t'))
953 /* Currently parse MID and @SLOTNUMBER */
958 error ("valid thread mid expected");
966 error ("invalid slot number");
968 /* If you want slot numbers to remain slot numbers, set slots.
970 * Well, since 0 is reserved, return the ordinal number
971 * of the thread rather than the slot number. Awk, this
972 * counts as a kludge.
977 if (thread_count
&& slot
>= thread_count
)
980 mid
= map_slot_to_mid (slot
);
985 /* THREAD_ID 0 is special; it selects the first kernel
986 * thread from the list (i.e. SLOTNUMBER 0)
987 * This is used when starting the program with 'run' or when attaching.
989 * If FLAG is 0 the context is not changed, and the registers, frame, etc
990 * will continue to describe the old thread.
992 * If FLAG is nonzero, really select the thread.
993 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
997 select_thread (mach_port_t task
, int thread_id
, int flag
)
999 thread_array_t thread_list
;
1003 thread_t new_thread
= MACH_PORT_NULL
;
1006 error ("Can't select cprocs without kernel thread");
1008 ret
= task_threads (task
, &thread_list
, &thread_count
);
1009 if (ret
!= KERN_SUCCESS
)
1011 warning ("Can not select a thread from a dead task");
1012 m3_kill_inferior ();
1013 return KERN_FAILURE
;
1016 if (thread_count
== 0)
1018 /* The task can not do anything anymore, but it still
1019 * exists as a container for memory and ports.
1021 registers_changed ();
1022 warning ("Task %d has no threads",
1023 map_port_name_to_mid (task
, MACH_TYPE_TASK
));
1024 current_thread
= MACH_PORT_NULL
;
1025 (void) vm_deallocate (mach_task_self (),
1026 (vm_address_t
) thread_list
,
1027 (thread_count
* sizeof (mach_port_t
)));
1028 return KERN_FAILURE
;
1031 if (!thread_id
|| flag
== 2)
1033 /* First thread or a slotnumber */
1035 new_thread
= thread_list
[0];
1038 if (thread_id
< thread_count
)
1039 new_thread
= thread_list
[thread_id
];
1042 (void) vm_deallocate (mach_task_self (),
1043 (vm_address_t
) thread_list
,
1044 (thread_count
* sizeof (mach_port_t
)));
1045 error ("No such thread slot number : %d", thread_id
);
1051 for (index
= 0; index
< thread_count
; index
++)
1052 if (thread_id
== map_port_name_to_mid (thread_list
[index
],
1055 new_thread
= thread_list
[index
];
1061 error ("No thread with mid %d", thread_id
);
1064 /* Notify when the selected thread dies */
1065 request_notify (new_thread
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_THREAD
);
1067 ret
= vm_deallocate (mach_task_self (),
1068 (vm_address_t
) thread_list
,
1069 (thread_count
* sizeof (mach_port_t
)));
1070 CHK ("vm_deallocate", ret
);
1073 current_thread
= new_thread
;
1077 if (MACH_PORT_VALID (current_thread
))
1079 /* Store the gdb's view of the thread we are deselecting
1081 * @@ I think gdb updates registers immediately when they are
1082 * changed, so don't do this.
1084 ret
= thread_abort (current_thread
);
1085 CHK ("Could not abort system calls when saving state of old thread",
1087 target_prepare_to_store ();
1088 target_store_registers (-1);
1092 registers_changed ();
1094 current_thread
= new_thread
;
1096 ret
= thread_abort (current_thread
);
1097 CHK ("Could not abort system calls when selecting a thread", ret
);
1099 stop_pc
= read_pc ();
1100 flush_cached_frames ();
1102 select_frame (get_current_frame (), 0);
1105 return KERN_SUCCESS
;
1109 * Switch to use thread named NEW_THREAD.
1113 switch_to_thread (thread_t new_thread
)
1115 thread_t saved_thread
= current_thread
;
1118 mid
= map_port_name_to_mid (new_thread
,
1121 warning ("Can't map thread name 0x%x to mid", new_thread
);
1122 else if (select_thread (inferior_task
, mid
, 1) != KERN_SUCCESS
)
1125 current_thread
= saved_thread
;
1126 error ("Could not select thread %d", mid
);
1132 /* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1133 * Note that the registers are not yet valid in the inferior task.
1136 m3_trace_him (int pid
)
1140 push_target (&m3_ops
);
1142 inferior_task
= task_by_pid (pid
);
1144 if (!MACH_PORT_VALID (inferior_task
))
1145 error ("Can not map Unix pid %d to Mach task", pid
);
1147 /* Clean up previous notifications and create new ones */
1148 setup_notify_port (1);
1150 /* When notification appears, the inferior task has died */
1151 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
1153 emulator_present
= have_emulator_p (inferior_task
);
1155 /* By default, select the first thread,
1156 * If task has no threads, gives a warning
1157 * Does not fetch registers, since they are not yet valid.
1159 select_thread (inferior_task
, 0, 0);
1161 inferior_exception_port
= MACH_PORT_NULL
;
1163 setup_exception_port ();
1165 xx_debug ("Now the debugged task is created\n");
1167 /* One trap to exec the shell, one to exec the program being debugged. */
1168 intercept_exec_calls (2);
1173 setup_exception_port (void)
1177 ret
= mach_port_allocate (mach_task_self (),
1178 MACH_PORT_RIGHT_RECEIVE
,
1179 &inferior_exception_port
);
1180 CHK ("mach_port_allocate", ret
);
1182 /* add send right */
1183 ret
= mach_port_insert_right (mach_task_self (),
1184 inferior_exception_port
,
1185 inferior_exception_port
,
1186 MACH_MSG_TYPE_MAKE_SEND
);
1187 CHK ("mach_port_insert_right", ret
);
1189 ret
= mach_port_move_member (mach_task_self (),
1190 inferior_exception_port
,
1191 inferior_wait_port_set
);
1192 CHK ("mach_port_move_member", ret
);
1194 ret
= task_get_special_port (inferior_task
,
1195 TASK_EXCEPTION_PORT
,
1196 &inferior_old_exception_port
);
1197 CHK ("task_get_special_port(old exc)", ret
);
1199 ret
= task_set_special_port (inferior_task
,
1200 TASK_EXCEPTION_PORT
,
1201 inferior_exception_port
);
1202 CHK ("task_set_special_port", ret
);
1204 ret
= mach_port_deallocate (mach_task_self (),
1205 inferior_exception_port
);
1206 CHK ("mack_port_deallocate", ret
);
1209 /* When notify appears, the inferior_task's exception
1210 * port has been destroyed.
1212 * Not used, since the dead_name_notification already
1213 * appears when task dies.
1216 request_notify (inferior_exception_port
,
1217 MACH_NOTIFY_NO_SENDERS
,
1218 MACH_TYPE_EXCEPTION_PORT
);
1222 /* Nonzero if gdb is waiting for a message */
1223 int mach_really_waiting
;
1225 /* Wait for the inferior to stop for some reason.
1226 - Loop on notifications until inferior_task dies.
1227 - Loop on exceptions until stopped_in_exception comes true.
1228 (e.g. we receive a single step trace trap)
1229 - a message arrives to gdb's message port
1231 There is no other way to exit this loop.
1233 Returns the inferior_pid for rest of gdb.
1234 Side effects: Set *OURSTATUS. */
1236 mach_really_wait (int pid
, struct target_waitstatus
*ourstatus
)
1243 mach_msg_header_t header
;
1244 mach_msg_type_t foo
;
1249 /* Either notify (death), exception or message can stop the inferior */
1250 stopped_in_exception
= FALSE
;
1256 stop_exception
= stop_code
= stop_subcode
= -1;
1257 stop_thread
= MACH_PORT_NULL
;
1259 mach_really_waiting
= 1;
1260 ret
= mach_msg (&in_msg
.header
, /* header */
1261 MACH_RCV_MSG
, /* options */
1263 sizeof (struct msg
), /* receive size */
1264 currently_waiting_for
, /* receive name */
1265 MACH_MSG_TIMEOUT_NONE
,
1267 mach_really_waiting
= 0;
1268 CHK ("mach_msg (receive)", ret
);
1270 /* Check if we received a notify of the childs' death */
1271 if (notify_server (&in_msg
.header
, &out_msg
.header
))
1273 /* If inferior_task is null then the inferior has
1274 gone away and we want to return to command level.
1275 Otherwise it was just an informative message and we
1276 need to look to see if there are any more. */
1277 if (inferior_task
!= MACH_PORT_NULL
)
1281 /* Collect Unix exit status for gdb */
1283 wait3 (&w
, WNOHANG
, 0);
1285 /* This mess is here to check that the rest of
1286 * gdb knows that the inferior died. It also
1287 * tries to hack around the fact that Mach 3.0 (mk69)
1288 * unix server (ux28) does not always know what
1289 * has happened to it's children when mach-magic
1290 * is applied on them.
1292 if ((!WIFEXITED (w
) && WIFSTOPPED (w
)) ||
1293 (WIFEXITED (w
) && WEXITSTATUS (w
) > 0377))
1296 warning ("Using exit value 0 for terminated task");
1298 else if (!WIFEXITED (w
))
1300 int sig
= WTERMSIG (w
);
1302 /* Signals cause problems. Warn the user. */
1303 if (sig
!= SIGKILL
) /* Bad luck if garbage matches this */
1304 warning ("The terminating signal stuff may be nonsense");
1305 else if (sig
> NSIG
)
1308 warning ("Using exit value 0 for terminated task");
1311 store_waitstatus (ourstatus
, w
);
1312 return inferior_pid
;
1316 /* Hmm. Check for exception, as it was not a notification.
1317 exc_server() does an upcall to catch_exception_raise()
1318 if this rpc is an exception. Further actions are decided
1321 if (!exc_server (&in_msg
.header
, &out_msg
.header
))
1324 /* Not an exception, check for message.
1326 * Messages don't come from the inferior, or if they
1327 * do they better be asynchronous or it will hang.
1329 if (gdb_message_server (&in_msg
.header
))
1332 error ("Unrecognized message received in mach_really_wait");
1335 /* Send the reply of the exception rpc to the suspended task */
1336 ret
= mach_msg_send (&out_msg
.header
);
1337 CHK ("mach_msg_send (exc reply)", ret
);
1339 if (stopped_in_exception
)
1341 /* Get unix state. May be changed in mach3_exception_actions() */
1342 wait3 (&w
, WNOHANG
, 0);
1344 mach3_exception_actions (&w
, FALSE
, "Task");
1346 store_waitstatus (ourstatus
, w
);
1347 return inferior_pid
;
1352 /* Called by macro DO_QUIT() in utils.c(quit).
1353 * This is called just before calling error() to return to command level
1361 if (mach_really_waiting
)
1363 ret
= task_suspend (inferior_task
);
1365 if (ret
!= KERN_SUCCESS
)
1367 warning ("Could not suspend task for interrupt: %s",
1368 mach_error_string (ret
));
1369 mach_really_waiting
= 0;
1374 must_suspend_thread
= 0;
1375 mach_really_waiting
= 0;
1377 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1380 warning ("Selecting first existing kernel thread");
1384 current_thread
= MACH_PORT_NULL
; /* Force setup */
1385 select_thread (inferior_task
, mid
, 1);
1391 /* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
1393 /* If ^C is typed when we are waiting for a message
1394 * and your Unix server is able to notice that we
1397 * Called by REQUEST_QUIT() from utils.c(request_quit)
1400 mach3_request_quit (void)
1402 if (mach_really_waiting
)
1408 * Gdb message server.
1409 * Currently implemented is the STOP message, that causes
1410 * gdb to return to the command level like ^C had been typed from terminal.
1413 gdb_message_server (mach_msg_header_t
*InP
)
1418 if (InP
->msgh_local_port
== our_message_port
)
1420 /* A message coming to our_message_port. Check validity */
1421 switch (InP
->msgh_id
)
1424 case GDB_MESSAGE_ID_STOP
:
1425 ret
= task_suspend (inferior_task
);
1426 if (ret
!= KERN_SUCCESS
)
1427 warning ("Could not suspend task for stop message: %s",
1428 mach_error_string (ret
));
1430 /* QUIT in mach_really_wait() loop. */
1435 warning ("Invalid message id %d received, ignored.",
1443 /* Message not handled by this server */
1447 /* NOTE: This is not an RPC call. It is a simpleroutine.
1449 * This is not called from this gdb code.
1451 * It may be called by another debugger to cause this
1452 * debugger to enter command level:
1454 * (gdb) set stop_inferior_gdb ()
1457 * External program "stop-gdb" implements this also.
1460 stop_inferior_gdb (void)
1464 /* Code generated by mig, with minor cleanups :-)
1466 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1471 mach_msg_header_t Head
;
1477 register Request
*InP
= &Mess
;
1479 InP
->Head
.msgh_bits
= MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND
, 0);
1481 /* msgh_size passed as argument */
1482 InP
->Head
.msgh_remote_port
= our_message_port
;
1483 InP
->Head
.msgh_local_port
= MACH_PORT_NULL
;
1484 InP
->Head
.msgh_seqno
= 0;
1485 InP
->Head
.msgh_id
= GDB_MESSAGE_ID_STOP
;
1487 ret
= mach_msg (&InP
->Head
,
1488 MACH_SEND_MSG
| MACH_MSG_OPTION_NONE
,
1492 MACH_MSG_TIMEOUT_NONE
,
1496 #ifdef THREAD_ALLOWED_TO_BREAK
1498 * Return 1 if the MID specifies the thread that caused the
1500 * Since catch_exception_raise() selects the thread causing
1501 * the last exception to current_thread, we just check that
1502 * it is selected and the last exception was a breakpoint.
1505 mach_thread_for_breakpoint (int mid
)
1507 int cmid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1511 mid
= map_slot_to_mid (-(mid
+ 1), 0, 0);
1513 return 0; /* Don't stop, no such slot */
1516 if (!mid
|| cmid
== -1)
1517 return 1; /* stop */
1519 return cmid
== mid
&& stop_exception
== EXC_BREAKPOINT
;
1521 #endif /* THREAD_ALLOWED_TO_BREAK */
1523 #ifdef THREAD_PARSE_ID
1525 * Map a thread id string (MID or a @SLOTNUMBER)
1528 * 0 matches all threads.
1529 * Otherwise the meaning is defined only in this file.
1530 * (mach_thread_for_breakpoint uses it)
1532 * @@ This allows non-existent MIDs to be specified.
1533 * It now also allows non-existent slots to be
1534 * specified. (Slot numbers stored are negative,
1535 * and the magnitude is one greater than the actual
1536 * slot index. (Since 0 is reserved))
1539 mach_thread_parse_id (char *arg
)
1543 error ("thread id excpected");
1544 mid
= parse_thread_id (arg
, 0, 1);
1548 #endif /* THREAD_PARSE_ID */
1550 #ifdef THREAD_OUTPUT_ID
1552 mach_thread_output_id (int mid
)
1554 static char foobar
[20];
1557 sprintf (foobar
, "mid %d", mid
);
1559 sprintf (foobar
, "@%d", -(mid
+ 1));
1561 sprintf (foobar
, "*any thread*");
1565 #endif /* THREAD_OUTPUT_ID */
1567 /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
1569 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1571 * if SELECT_IT is nonzero, reselect the thread that was active when
1572 * we stopped at a breakpoint.
1576 mach3_prepare_to_proceed (int select_it
)
1579 stop_thread
!= current_thread
&&
1580 stop_exception
== EXC_BREAKPOINT
)
1587 mid
= switch_to_thread (stop_thread
);
1595 /* this stuff here is an upcall via libmach/excServer.c
1596 and mach_really_wait which does the actual upcall.
1598 The code will pass the exception to the inferior if:
1600 - The task that signaled is not the inferior task
1601 (e.g. when debugging another debugger)
1603 - The user has explicitely requested to pass on the exceptions.
1604 (e.g to the default unix exception handler, which maps
1605 exceptions to signals, or the user has her own exception handler)
1607 - If the thread that signaled is being single-stepped and it
1608 has set it's own exception port and the exception is not
1609 EXC_BREAKPOINT. (Maybe this is not desirable?)
1613 catch_exception_raise (mach_port_t port
, thread_t thread
, task_t task
,
1614 int exception
, int code
, int subcode
)
1617 boolean_t signal_thread
;
1618 int mid
= map_port_name_to_mid (thread
, MACH_TYPE_THREAD
);
1620 if (!MACH_PORT_VALID (thread
))
1622 /* If the exception was sent and thread dies before we
1623 receive it, THREAD will be MACH_PORT_DEAD
1626 current_thread
= thread
= MACH_PORT_NULL
;
1627 error ("Received exception from nonexistent thread");
1630 /* Check if the task died in transit.
1631 * @@ Isn't the thread also invalid in such case?
1633 if (!MACH_PORT_VALID (task
))
1635 current_thread
= thread
= MACH_PORT_NULL
;
1636 error ("Received exception from nonexistent task");
1639 if (exception
< 0 || exception
> MAX_EXCEPTION
)
1640 internal_error ("catch_exception_raise: unknown exception code %d thread %d",
1644 if (!MACH_PORT_VALID (inferior_task
))
1645 error ("got an exception, but inferior_task is null or dead");
1647 stop_exception
= exception
;
1649 stop_subcode
= subcode
;
1650 stop_thread
= thread
;
1652 signal_thread
= exception
!= EXC_BREAKPOINT
&&
1653 port
== singlestepped_thread_port
&&
1654 MACH_PORT_VALID (thread_saved_exception_port
);
1656 /* If it was not our inferior or if we want to forward
1657 * the exception to the inferior's handler, do it here
1659 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1661 if (task
!= inferior_task
||
1663 exception_map
[exception
].forward
)
1665 mach_port_t eport
= inferior_old_exception_port
;
1670 GDB now forwards the exeption to thread's original handler,
1671 since the user propably knows what he is doing.
1672 Give a message, though.
1675 mach3_exception_actions ((WAITTYPE
*) NULL
, TRUE
, "Thread");
1676 eport
= thread_saved_exception_port
;
1679 /* Send the exception to the original handler */
1680 ret
= exception_raise (eport
,
1687 (void) mach_port_deallocate (mach_task_self (), task
);
1688 (void) mach_port_deallocate (mach_task_self (), thread
);
1690 /* If we come here, we don't want to trace any more, since we
1691 * will never stop for tracing anyway.
1693 discard_single_step (thread
);
1695 /* Do not stop the inferior */
1699 /* Now gdb handles the exception */
1700 stopped_in_exception
= TRUE
;
1702 ret
= task_suspend (task
);
1703 CHK ("Error suspending inferior after exception", ret
);
1705 must_suspend_thread
= 0;
1707 if (current_thread
!= thread
)
1709 if (MACH_PORT_VALID (singlestepped_thread_port
))
1710 /* Cleanup discards single stepping */
1711 error ("Exception from thread %d while singlestepping thread %d",
1713 map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
));
1715 /* Then select the thread that caused the exception */
1716 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
1717 error ("Could not select thread %d causing exception", mid
);
1719 warning ("Gdb selected thread %d", mid
);
1722 /* If we receive an exception that is not breakpoint
1723 * exception, we interrupt the single step and return to
1724 * debugger. Trace condition is cleared.
1726 if (MACH_PORT_VALID (singlestepped_thread_port
))
1728 if (stop_exception
!= EXC_BREAKPOINT
)
1729 warning ("Single step interrupted by exception");
1730 else if (port
== singlestepped_thread_port
)
1732 /* Single step exception occurred, remove trace bit
1733 * and return to gdb.
1735 if (!MACH_PORT_VALID (current_thread
))
1736 error ("Single stepped thread is not valid");
1738 /* Resume threads, but leave the task suspended */
1739 resume_all_threads (0);
1742 warning ("Breakpoint while single stepping?");
1744 discard_single_step (current_thread
);
1747 (void) mach_port_deallocate (mach_task_self (), task
);
1748 (void) mach_port_deallocate (mach_task_self (), thread
);
1750 return KERN_SUCCESS
;
1754 port_valid (mach_port_t port
, int mask
)
1757 mach_port_type_t type
;
1759 ret
= mach_port_type (mach_task_self (),
1762 if (ret
!= KERN_SUCCESS
|| (type
& mask
) != mask
)
1767 /* @@ No vm read cache implemented yet */
1768 boolean_t vm_read_cache_valid
= FALSE
;
1771 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1772 * in gdb's address space.
1774 * Return 0 on failure; number of bytes read otherwise.
1777 mach3_read_inferior (CORE_ADDR addr
, char *myaddr
, int length
)
1780 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1781 vm_size_t aligned_length
=
1782 (vm_size_t
) round_page (addr
+ length
) - low_address
;
1783 pointer_t copied_memory
;
1786 /* Get memory from inferior with page aligned addresses */
1787 ret
= vm_read (inferior_task
,
1792 if (ret
!= KERN_SUCCESS
)
1794 /* the problem is that the inferior might be killed for whatever reason
1795 * before we go to mach_really_wait. This is one place that ought to
1796 * catch many of those errors.
1797 * @@ A better fix would be to make all external events to GDB
1798 * to arrive via a SINGLE port set. (Including user input!)
1801 if (!port_valid (inferior_task
, MACH_PORT_TYPE_SEND
))
1803 m3_kill_inferior ();
1804 error ("Inferior killed (task port invalid)");
1810 /* valprint.c gives nicer format if this does not
1811 screw it. Eamonn seems to like this, so I enable
1812 it if OSF is defined...
1814 warning ("[read inferior %x failed: %s]",
1815 addr
, mach_error_string (ret
));
1822 memcpy (myaddr
, (char *) addr
- low_address
+ copied_memory
, length
);
1824 ret
= vm_deallocate (mach_task_self (),
1827 CHK ("mach3_read_inferior vm_deallocate failed", ret
);
1833 #define CHK_GOTO_OUT(str,ret) \
1834 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
1836 #define CHK_GOTO_OUT(str,ret) \
1837 do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
1840 struct vm_region_list
1842 struct vm_region_list
*next
;
1843 vm_prot_t protection
;
1848 struct obstack region_obstack
;
1851 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1852 * in gdb's address space.
1855 mach3_write_inferior (CORE_ADDR addr
, char *myaddr
, int length
)
1858 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1859 vm_size_t aligned_length
=
1860 (vm_size_t
) round_page (addr
+ length
) - low_address
;
1861 pointer_t copied_memory
;
1865 char *errstr
= "Bug in mach3_write_inferior";
1867 struct vm_region_list
*region_element
;
1868 struct vm_region_list
*region_head
= (struct vm_region_list
*) NULL
;
1870 /* Get memory from inferior with page aligned addresses */
1871 ret
= vm_read (inferior_task
,
1876 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret
);
1880 memcpy ((char *) addr
- low_address
+ copied_memory
, myaddr
, length
);
1882 obstack_init (®ion_obstack
);
1884 /* Do writes atomically.
1885 * First check for holes and unwritable memory.
1888 vm_size_t remaining_length
= aligned_length
;
1889 vm_address_t region_address
= low_address
;
1891 struct vm_region_list
*scan
;
1893 while (region_address
< low_address
+ aligned_length
)
1895 vm_prot_t protection
;
1896 vm_prot_t max_protection
;
1897 vm_inherit_t inheritance
;
1899 mach_port_t object_name
;
1901 vm_size_t region_length
= remaining_length
;
1902 vm_address_t old_address
= region_address
;
1904 ret
= vm_region (inferior_task
,
1913 CHK_GOTO_OUT ("vm_region failed", ret
);
1915 /* Check for holes in memory */
1916 if (old_address
!= region_address
)
1918 warning ("No memory at 0x%x. Nothing written",
1925 if (!(max_protection
& VM_PROT_WRITE
))
1927 warning ("Memory at address 0x%x is unwritable. Nothing written",
1934 /* Chain the regions for later use */
1936 (struct vm_region_list
*)
1937 obstack_alloc (®ion_obstack
, sizeof (struct vm_region_list
));
1939 region_element
->protection
= protection
;
1940 region_element
->start
= region_address
;
1941 region_element
->length
= region_length
;
1943 /* Chain the regions along with protections */
1944 region_element
->next
= region_head
;
1945 region_head
= region_element
;
1947 region_address
+= region_length
;
1948 remaining_length
= remaining_length
- region_length
;
1951 /* If things fail after this, we give up.
1952 * Somebody is messing up inferior_task's mappings.
1955 /* Enable writes to the chained vm regions */
1956 for (scan
= region_head
; scan
; scan
= scan
->next
)
1958 boolean_t protection_changed
= FALSE
;
1960 if (!(scan
->protection
& VM_PROT_WRITE
))
1962 ret
= vm_protect (inferior_task
,
1966 scan
->protection
| VM_PROT_WRITE
);
1967 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1971 ret
= vm_write (inferior_task
,
1975 CHK_GOTO_OUT ("vm_write failed", ret
);
1977 /* Set up the original region protections, if they were changed */
1978 for (scan
= region_head
; scan
; scan
= scan
->next
)
1980 boolean_t protection_changed
= FALSE
;
1982 if (!(scan
->protection
& VM_PROT_WRITE
))
1984 ret
= vm_protect (inferior_task
,
1989 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1997 obstack_free (®ion_obstack
, 0);
1999 (void) vm_deallocate (mach_task_self (),
2004 if (ret
!= KERN_SUCCESS
)
2006 warning ("%s %s", errstr
, mach_error_string (ret
));
2013 /* Return 0 on failure, number of bytes handled otherwise. */
2015 m3_xfer_memory (memaddr
, myaddr
, len
, write
, target
)
2020 struct target_ops
*target
; /* IGNORED */
2025 result
= mach3_write_inferior (memaddr
, myaddr
, len
);
2027 result
= mach3_read_inferior (memaddr
, myaddr
, len
);
2034 translate_state (int state
)
2038 case TH_STATE_RUNNING
:
2040 case TH_STATE_STOPPED
:
2042 case TH_STATE_WAITING
:
2044 case TH_STATE_UNINTERRUPTIBLE
:
2046 case TH_STATE_HALTED
:
2054 translate_cstate (int state
)
2060 case CPROC_SWITCHING
:
2064 case CPROC_CONDWAIT
:
2066 case CPROC_CONDWAIT
| CPROC_SWITCHING
:
2073 /* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2075 mach_port_t
/* no mach_port_name_t found in include files. */
2076 map_inferior_port_name (mach_port_t inferior_name
, mach_msg_type_name_t type
)
2079 mach_msg_type_name_t acquired
;
2082 ret
= mach_port_extract_right (inferior_task
,
2087 CHK ("mach_port_extract_right (map_inferior_port_name)", ret
);
2089 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
2090 error ("Incorrect right extracted, (map_inferior_port_name)");
2092 ret
= mach_port_deallocate (mach_task_self (),
2094 CHK ("Deallocating mapped port (map_inferior_port_name)", ret
);
2100 * Naming convention:
2101 * Always return user defined name if found.
2102 * _K == A kernel thread with no matching CPROC
2103 * _C == A cproc with no current cthread
2104 * _t == A cthread with no user defined name
2106 * The digits that follow the _names are the SLOT number of the
2107 * kernel thread if there is such a thing, otherwise just a negation
2108 * of the sequential number of such cprocs.
2114 get_thread_name (gdb_thread_t one_cproc
, int id
)
2117 if (one_cproc
->cthread
== NULL
)
2119 /* cproc not mapped to any cthread */
2120 sprintf (buf
, "_C%d", id
);
2122 else if (!one_cproc
->cthread
->name
)
2124 /* cproc and cthread, but no name */
2125 sprintf (buf
, "_t%d", id
);
2128 return (char *) (one_cproc
->cthread
->name
);
2132 warning ("Inconsistency in thread name id %d", id
);
2134 /* Kernel thread without cproc */
2135 sprintf (buf
, "_K%d", id
);
2142 fetch_thread_info (task
, mthreads_out
)
2144 gdb_thread_t
*mthreads_out
; /* out */
2147 thread_array_t th_table
;
2149 gdb_thread_t mthreads
= NULL
;
2152 ret
= task_threads (task
, &th_table
, &th_count
);
2153 if (ret
!= KERN_SUCCESS
)
2155 warning ("Error getting inferior's thread list:%s",
2156 mach_error_string (ret
));
2157 m3_kill_inferior ();
2161 mthreads
= (gdb_thread_t
)
2164 th_count
* sizeof (struct gdb_thread
));
2166 for (index
= 0; index
< th_count
; index
++)
2168 thread_t saved_thread
= MACH_PORT_NULL
;
2171 if (must_suspend_thread
)
2172 setup_thread (th_table
[index
], 1);
2174 if (th_table
[index
] != current_thread
)
2176 saved_thread
= current_thread
;
2178 mid
= switch_to_thread (th_table
[index
]);
2181 mthreads
[index
].name
= th_table
[index
];
2182 mthreads
[index
].cproc
= NULL
; /* map_cprocs_to_kernel_threads() */
2183 mthreads
[index
].in_emulator
= FALSE
;
2184 mthreads
[index
].slotid
= index
;
2186 mthreads
[index
].sp
= read_register (SP_REGNUM
);
2187 mthreads
[index
].fp
= read_register (FP_REGNUM
);
2188 mthreads
[index
].pc
= read_pc ();
2190 if (MACH_PORT_VALID (saved_thread
))
2191 mid
= switch_to_thread (saved_thread
);
2193 if (must_suspend_thread
)
2194 setup_thread (th_table
[index
], 0);
2197 consume_send_rights (th_table
, th_count
);
2198 ret
= vm_deallocate (mach_task_self (), (vm_address_t
) th_table
,
2199 (th_count
* sizeof (mach_port_t
)));
2200 if (ret
!= KERN_SUCCESS
)
2202 warning ("Error trying to deallocate thread list : %s",
2203 mach_error_string (ret
));
2206 *mthreads_out
= mthreads
;
2213 * Current emulator always saves the USP on top of
2214 * emulator stack below struct emul_stack_top stuff.
2217 fetch_usp_from_emulator_stack (CORE_ADDR sp
)
2219 CORE_ADDR stack_pointer
;
2221 sp
= (sp
& ~(EMULATOR_STACK_SIZE
- 1)) +
2222 EMULATOR_STACK_SIZE
- sizeof (struct emul_stack_top
);
2224 if (mach3_read_inferior (sp
,
2226 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2228 warning ("Can't read user sp from emulator stack address 0x%x", sp
);
2232 return stack_pointer
;
2237 /* get_emulation_vector() interface was changed after mk67 */
2238 #define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2242 /* Check if the emulator exists at task's address space.
2245 have_emulator_p (task_t task
)
2248 #ifndef EMUL_VECTOR_COUNT
2249 vm_offset_t
*emulation_vector
;
2252 vm_offset_t emulation_vector
[EMUL_VECTOR_COUNT
];
2253 int n
= EMUL_VECTOR_COUNT
;
2258 ret
= task_get_emulation_vector (task
,
2260 #ifndef EMUL_VECTOR_COUNT
2266 CHK ("task_get_emulation_vector", ret
);
2267 xx_debug ("%d vectors from %d at 0x%08x\n",
2268 n
, vector_start
, emulation_vector
);
2270 for (i
= 0; i
< n
; i
++)
2272 vm_offset_t entry
= emulation_vector
[i
];
2274 if (EMULATOR_BASE
<= entry
&& entry
<= EMULATOR_END
)
2278 static boolean_t informed
= FALSE
;
2281 warning ("Emulation vector address 0x08%x outside emulator space",
2290 /* Map cprocs to kernel threads and vice versa. */
2293 map_cprocs_to_kernel_threads (gdb_thread_t cprocs
, gdb_thread_t mthreads
,
2298 boolean_t all_mapped
= TRUE
;
2302 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2304 /* Default to: no kernel thread for this cproc */
2305 scan
->reverse_map
= -1;
2307 /* Check if the cproc is found by its stack */
2308 for (index
= 0; index
< thread_count
; index
++)
2311 extract_signed_integer (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2314 extract_signed_integer (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2316 if ((mthreads
+ index
)->sp
> stack_base
&&
2317 (mthreads
+ index
)->sp
<= stack_base
+ stack_size
)
2319 (mthreads
+ index
)->cproc
= scan
;
2320 scan
->reverse_map
= index
;
2324 all_mapped
&= (scan
->reverse_map
!= -1);
2327 /* Check for threads that are currently in the emulator.
2328 * If so, they have a different stack, and the still unmapped
2329 * cprocs may well get mapped to these threads.
2332 * - cproc stack does not match any kernel thread stack pointer
2333 * - there is at least one extra kernel thread
2334 * that has no cproc mapped above.
2335 * - some kernel thread stack pointer points to emulator space
2336 * then we find the user stack pointer saved in the emulator
2337 * stack, and try to map that to the cprocs.
2339 * Also set in_emulator for kernel threads.
2342 if (emulator_present
)
2344 for (index
= 0; index
< thread_count
; index
++)
2349 gdb_thread_t mthread
= (mthreads
+ index
);
2350 emul_sp
= mthread
->sp
;
2352 if (mthread
->cproc
== NULL
&&
2353 EMULATOR_BASE
<= emul_sp
&& emul_sp
<= EMULATOR_END
)
2355 mthread
->in_emulator
= emulator_present
;
2357 if (!all_mapped
&& cprocs
)
2359 usp
= fetch_usp_from_emulator_stack (emul_sp
);
2361 /* @@ Could be more accurate */
2363 error ("Zero stack pointer read from emulator?");
2365 /* Try to match this stack pointer to the cprocs that
2366 * don't yet have a kernel thread.
2368 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2371 /* Check is this unmapped CPROC stack contains
2372 * the user stack pointer saved in the
2375 if (scan
->reverse_map
== -1)
2378 extract_signed_integer
2379 (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2382 extract_signed_integer
2383 (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2385 if (usp
> stack_base
&&
2386 usp
<= stack_base
+ stack_size
)
2388 mthread
->cproc
= scan
;
2389 scan
->reverse_map
= index
;
2401 * Format of the thread_list command
2403 * slot mid sel name emul ks susp cstate wired address
2405 #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2407 #define TL_HEADER "\n@ MID Name KState CState Where\n"
2410 print_tl_address (struct ui_file
*stream
, CORE_ADDR pc
)
2412 if (!lookup_minimal_symbol_by_pc (pc
))
2413 fprintf_filtered (stream
, local_hex_format (), pc
);
2416 extern int addressprint
;
2417 extern int asm_demangle
;
2419 int store
= addressprint
;
2421 print_address_symbolic (pc
, stream
, asm_demangle
, "");
2422 addressprint
= store
;
2426 /* For thread names, but also for gdb_message_port external name */
2427 #define MAX_NAME_LEN 50
2429 /* Returns the address of variable NAME or 0 if not found */
2431 lookup_address_of_variable (char *name
)
2434 CORE_ADDR symaddr
= 0;
2435 struct minimal_symbol
*msymbol
;
2437 sym
= lookup_symbol (name
,
2438 (struct block
*) NULL
,
2441 (struct symtab
**) NULL
);
2444 symaddr
= SYMBOL_VALUE (sym
);
2448 msymbol
= lookup_minimal_symbol (name
, NULL
, NULL
);
2450 if (msymbol
&& msymbol
->type
== mst_data
)
2451 symaddr
= SYMBOL_VALUE_ADDRESS (msymbol
);
2460 gdb_thread_t cproc_head
;
2461 gdb_thread_t cproc_copy
;
2462 CORE_ADDR their_cprocs
;
2463 char *buf
[TARGET_PTR_BIT
/ HOST_CHAR_BIT
];
2468 symaddr
= lookup_address_of_variable ("cproc_list");
2472 /* cproc_list is not in a file compiled with debugging
2473 symbols, but don't give up yet */
2475 symaddr
= lookup_address_of_variable ("cprocs");
2479 static int informed
= 0;
2483 warning ("Your program is loaded with an old threads library.");
2484 warning ("GDB does not know the old form of threads");
2485 warning ("so things may not work.");
2490 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
2494 /* Get the address of the first cproc in the task */
2495 if (!mach3_read_inferior (symaddr
,
2497 TARGET_PTR_BIT
/ HOST_CHAR_BIT
))
2498 error ("Can't read cproc master list at address (0x%x).", symaddr
);
2499 their_cprocs
= extract_address (buf
, TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2501 /* Scan the CPROCs in the task.
2502 CPROCs are chained with LIST field, not NEXT field, which
2503 chains mutexes, condition variables and queues */
2507 while (their_cprocs
!= (CORE_ADDR
) 0)
2509 CORE_ADDR cproc_copy_incarnation
;
2510 cproc_copy
= (gdb_thread_t
) obstack_alloc (cproc_obstack
,
2511 sizeof (struct gdb_thread
));
2513 if (!mach3_read_inferior (their_cprocs
,
2514 &cproc_copy
->raw_cproc
[0],
2516 error ("Can't read next cproc at 0x%x.", their_cprocs
);
2519 extract_address (cproc_copy
->raw_cproc
+ CPROC_LIST_OFFSET
,
2521 cproc_copy_incarnation
=
2522 extract_address (cproc_copy
->raw_cproc
+ CPROC_INCARNATION_OFFSET
,
2523 CPROC_INCARNATION_SIZE
);
2525 if (cproc_copy_incarnation
== (CORE_ADDR
) 0)
2526 cproc_copy
->cthread
= NULL
;
2529 /* This CPROC has an attached CTHREAD. Get its name */
2530 cthread
= (cthread_t
) obstack_alloc (cproc_obstack
,
2531 sizeof (struct cthread
));
2533 if (!mach3_read_inferior (cproc_copy_incarnation
,
2535 sizeof (struct cthread
)))
2536 error ("Can't read next thread at 0x%x.",
2537 cproc_copy_incarnation
);
2539 cproc_copy
->cthread
= cthread
;
2543 name
= (char *) obstack_alloc (cproc_obstack
, MAX_NAME_LEN
);
2545 if (!mach3_read_inferior (cthread
->name
, name
, MAX_NAME_LEN
))
2546 error ("Can't read next thread's name at 0x%x.", cthread
->name
);
2548 cthread
->name
= name
;
2552 /* insert in front */
2553 cproc_copy
->next
= cproc_head
;
2554 cproc_head
= cproc_copy
;
2559 #ifndef FETCH_CPROC_STATE
2561 * Check if your machine does not grok the way this routine
2562 * fetches the FP,PC and SP of a cproc that is not
2563 * currently attached to any kernel thread (e.g. its cproc.context
2564 * field points to the place in stack where the context
2567 * If it doesn't, define your own routine.
2569 #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2572 mach3_cproc_state (gdb_thread_t mthread
)
2576 if (!mthread
|| !mthread
->cproc
)
2579 context
= extract_signed_integer
2580 (mthread
->cproc
->raw_cproc
+ CPROC_CONTEXT_OFFSET
,
2581 CPROC_CONTEXT_SIZE
);
2585 mthread
->sp
= context
+ MACHINE_CPROC_SP_OFFSET
;
2587 if (mach3_read_inferior (context
+ MACHINE_CPROC_PC_OFFSET
,
2589 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2591 warning ("Can't read cproc pc from inferior");
2595 if (mach3_read_inferior (context
+ MACHINE_CPROC_FP_OFFSET
,
2597 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2599 warning ("Can't read cproc fp from inferior");
2605 #endif /* FETCH_CPROC_STATE */
2609 thread_list_command (void)
2611 thread_basic_info_data_t ths
;
2613 gdb_thread_t cprocs
;
2621 mach_port_t mid_or_port
;
2622 gdb_thread_t their_threads
;
2623 gdb_thread_t kthread
;
2627 char *fmt
= "There are %d kernel threads in task %d.\n";
2629 int tmid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
2631 MACH_ERROR_NO_INFERIOR
;
2633 thread_count
= fetch_thread_info (inferior_task
,
2635 if (thread_count
== -1)
2638 if (thread_count
== 1)
2639 fmt
= "There is %d kernel thread in task %d.\n";
2641 printf_filtered (fmt
, thread_count
, tmid
);
2643 puts_filtered (TL_HEADER
);
2645 cprocs
= get_cprocs ();
2647 map_cprocs_to_kernel_threads (cprocs
, their_threads
, thread_count
);
2649 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2655 extract_signed_integer
2656 (scan
->raw_cproc
+ CPROC_STATE_OFFSET
, CPROC_STATE_SIZE
);
2660 /* a wired cproc? */
2661 wired
= (extract_address (scan
->raw_cproc
+ CPROC_WIRED_OFFSET
,
2665 if (scan
->reverse_map
!= -1)
2666 kthread
= (their_threads
+ scan
->reverse_map
);
2672 /* These cprocs have a kernel thread */
2674 mid
= map_port_name_to_mid (kthread
->name
, MACH_TYPE_THREAD
);
2676 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2678 ret
= thread_info (kthread
->name
,
2680 (thread_info_t
) & ths
,
2683 if (ret
!= KERN_SUCCESS
)
2685 warning ("Unable to get basic info on thread %d : %s",
2687 mach_error_string (ret
));
2691 /* Who is the first to have more than 100 threads */
2692 sprintf (slot
, "%d", kthread
->slotid
% 100);
2694 if (kthread
->name
== current_thread
)
2697 if (ths
.suspend_count
)
2698 sprintf (buf
, "%d", ths
.suspend_count
);
2703 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2707 if (ths
.flags
& TH_FLAGS_IDLE
)
2710 printf_filtered (TL_FORMAT
,
2714 get_thread_name (scan
, kthread
->slotid
),
2715 kthread
->in_emulator
? "E" : "",
2716 translate_state (ths
.run_state
),
2718 translate_cstate (cproc_state
),
2720 print_tl_address (gdb_stdout
, kthread
->pc
);
2724 /* These cprocs don't have a kernel thread.
2725 * find out the calling frame with
2726 * FETCH_CPROC_STATE.
2729 struct gdb_thread state
;
2732 /* jtv -> emcmanus: why do you want this here? */
2733 if (scan
->incarnation
== NULL
)
2734 continue; /* EMcM */
2737 printf_filtered (TL_FORMAT
,
2739 -neworder
, /* Pseudo MID */
2741 get_thread_name (scan
, -neworder
),
2743 "-", /* kernel state */
2745 translate_cstate (cproc_state
),
2749 if (FETCH_CPROC_STATE (&state
) == -1)
2750 puts_filtered ("???");
2752 print_tl_address (gdb_stdout
, state
.pc
);
2756 puts_filtered ("\n");
2759 /* Scan for kernel threads without cprocs */
2760 for (index
= 0; index
< thread_count
; index
++)
2762 if (!their_threads
[index
].cproc
)
2769 mach_port_t name
= their_threads
[index
].name
;
2771 mid
= map_port_name_to_mid (name
, MACH_TYPE_THREAD
);
2773 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2775 ret
= thread_info (name
,
2777 (thread_info_t
) & ths
,
2780 if (ret
!= KERN_SUCCESS
)
2782 warning ("Unable to get basic info on thread %d : %s",
2784 mach_error_string (ret
));
2788 sprintf (slot
, "%d", index
% 100);
2790 if (name
== current_thread
)
2795 if (ths
.suspend_count
)
2796 sprintf (buf
, "%d", ths
.suspend_count
);
2801 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2805 if (ths
.flags
& TH_FLAGS_IDLE
)
2808 printf_filtered (TL_FORMAT
,
2812 get_thread_name (NULL
, index
),
2813 their_threads
[index
].in_emulator
? "E" : "",
2814 translate_state (ths
.run_state
),
2816 "", /* No cproc state */
2817 ""); /* Can't be wired */
2818 print_tl_address (gdb_stdout
, their_threads
[index
].pc
);
2819 puts_filtered ("\n");
2823 obstack_free (cproc_obstack
, 0);
2824 obstack_init (cproc_obstack
);
2828 thread_select_command (char *args
, int from_tty
)
2831 thread_array_t thread_list
;
2836 MACH_ERROR_NO_INFERIOR
;
2839 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2841 while (*args
== ' ' || *args
== '\t')
2853 if (!is_slot
|| *args
!= '0') /* Rudimentary checks */
2854 error ("You must select threads by MID or @SLOTNUMBER");
2856 if (select_thread (inferior_task
, mid
, is_slot
? 2 : 1) != KERN_SUCCESS
)
2860 printf_filtered ("Thread %d selected\n",
2861 is_slot
? map_port_name_to_mid (current_thread
,
2862 MACH_TYPE_THREAD
) : mid
);
2865 thread_trace (mach_port_t thread
, boolean_t set
)
2867 int flavor
= TRACE_FLAVOR
;
2868 unsigned int stateCnt
= TRACE_FLAVOR_SIZE
;
2870 thread_state_data_t state
;
2872 if (!MACH_PORT_VALID (thread
))
2874 warning ("thread_trace: invalid thread");
2878 if (must_suspend_thread
)
2879 setup_thread (thread
, 1);
2881 ret
= thread_get_state (thread
, flavor
, state
, &stateCnt
);
2882 CHK ("thread_trace: error reading thread state", ret
);
2886 TRACE_SET (thread
, state
);
2890 if (!TRACE_CLEAR (thread
, state
))
2892 if (must_suspend_thread
)
2893 setup_thread (thread
, 0);
2898 ret
= thread_set_state (thread
, flavor
, state
, stateCnt
);
2899 CHK ("thread_trace: error writing thread state", ret
);
2900 if (must_suspend_thread
)
2901 setup_thread (thread
, 0);
2904 #ifdef FLUSH_INFERIOR_CACHE
2906 /* When over-writing code on some machines the I-Cache must be flushed
2907 explicitly, because it is not kept coherent by the lazy hardware.
2908 This definitely includes breakpoints, for instance, or else we
2909 end up looping in mysterious Bpt traps */
2911 flush_inferior_icache (CORE_ADDR pc
, int amount
)
2913 vm_machine_attribute_val_t flush
= MATTR_VAL_ICACHE_FLUSH
;
2916 ret
= vm_machine_attribute (inferior_task
,
2921 if (ret
!= KERN_SUCCESS
)
2922 warning ("Error flushing inferior's cache : %s",
2923 mach_error_string (ret
));
2925 #endif /* FLUSH_INFERIOR_CACHE */
2929 suspend_all_threads (int from_tty
)
2932 thread_array_t thread_list
;
2933 int thread_count
, index
;
2935 thread_basic_info_data_t th_info
;
2938 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
2939 if (ret
!= KERN_SUCCESS
)
2941 warning ("Could not suspend inferior threads.");
2942 m3_kill_inferior ();
2943 return_to_top_level (RETURN_ERROR
);
2946 for (index
= 0; index
< thread_count
; index
++)
2950 mid
= map_port_name_to_mid (thread_list
[index
],
2953 ret
= thread_suspend (thread_list
[index
]);
2955 if (ret
!= KERN_SUCCESS
)
2956 warning ("Error trying to suspend thread %d : %s",
2957 mid
, mach_error_string (ret
));
2961 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2962 ret
= thread_info (thread_list
[index
],
2964 (thread_info_t
) & th_info
,
2966 CHK ("suspend can't get thread info", ret
);
2968 warning ("Thread %d suspend count is %d",
2969 mid
, th_info
.suspend_count
);
2973 consume_send_rights (thread_list
, thread_count
);
2974 ret
= vm_deallocate (mach_task_self (),
2975 (vm_address_t
) thread_list
,
2976 (thread_count
* sizeof (int)));
2977 CHK ("Error trying to deallocate thread list", ret
);
2981 thread_suspend_command (char *args
, int from_tty
)
2985 mach_port_t saved_thread
;
2987 thread_basic_info_data_t th_info
;
2989 MACH_ERROR_NO_INFERIOR
;
2991 if (!strcasecmp (args
, "all"))
2993 suspend_all_threads (from_tty
);
2997 saved_thread
= current_thread
;
2999 mid
= parse_thread_id (args
, 0, 0);
3002 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
3005 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3006 else if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3009 current_thread
= saved_thread
;
3010 error ("Could not select thread %d", mid
);
3013 ret
= thread_suspend (current_thread
);
3014 if (ret
!= KERN_SUCCESS
)
3015 warning ("thread_suspend failed : %s",
3016 mach_error_string (ret
));
3018 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3019 ret
= thread_info (current_thread
,
3021 (thread_info_t
) & th_info
,
3023 CHK ("suspend can't get thread info", ret
);
3025 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3027 current_thread
= saved_thread
;
3030 resume_all_threads (int from_tty
)
3033 thread_array_t thread_list
;
3034 int thread_count
, index
;
3037 thread_basic_info_data_t th_info
;
3039 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
3040 if (ret
!= KERN_SUCCESS
)
3042 m3_kill_inferior ();
3043 error ("task_threads", mach_error_string (ret
));
3046 for (index
= 0; index
< thread_count
; index
++)
3048 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3049 ret
= thread_info (thread_list
[index
],
3051 (thread_info_t
) & th_info
,
3053 CHK ("resume_all can't get thread info", ret
);
3055 mid
= map_port_name_to_mid (thread_list
[index
],
3058 if (!th_info
.suspend_count
)
3060 if (mid
!= -1 && from_tty
)
3061 warning ("Thread %d is not suspended", mid
);
3065 ret
= thread_resume (thread_list
[index
]);
3067 if (ret
!= KERN_SUCCESS
)
3068 warning ("Error trying to resume thread %d : %s",
3069 mid
, mach_error_string (ret
));
3070 else if (mid
!= -1 && from_tty
)
3071 warning ("Thread %d suspend count is %d",
3072 mid
, --th_info
.suspend_count
);
3075 consume_send_rights (thread_list
, thread_count
);
3076 ret
= vm_deallocate (mach_task_self (),
3077 (vm_address_t
) thread_list
,
3078 (thread_count
* sizeof (int)));
3079 CHK ("Error trying to deallocate thread list", ret
);
3083 thread_resume_command (char *args
, int from_tty
)
3086 mach_port_t saved_thread
;
3088 thread_basic_info_data_t th_info
;
3089 int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3091 MACH_ERROR_NO_INFERIOR
;
3093 if (!strcasecmp (args
, "all"))
3095 resume_all_threads (from_tty
);
3099 saved_thread
= current_thread
;
3101 mid
= parse_thread_id (args
, 0, 0);
3104 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3107 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3108 else if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3111 current_thread
= saved_thread
;
3112 return_to_top_level (RETURN_ERROR
);
3115 ret
= thread_info (current_thread
,
3117 (thread_info_t
) & th_info
,
3119 CHK ("resume can't get thread info", ret
);
3121 if (!th_info
.suspend_count
)
3123 warning ("Thread %d is not suspended", mid
);
3127 ret
= thread_resume (current_thread
);
3128 if (ret
!= KERN_SUCCESS
)
3129 warning ("thread_resume failed : %s",
3130 mach_error_string (ret
));
3133 th_info
.suspend_count
--;
3134 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3138 current_thread
= saved_thread
;
3142 thread_kill_command (char *args
, int from_tty
)
3147 thread_array_t thread_table
;
3149 mach_port_t thread_to_kill
= MACH_PORT_NULL
;
3152 MACH_ERROR_NO_INFERIOR
;
3155 error_no_arg ("thread mid to kill from the inferior task");
3157 mid
= parse_thread_id (args
, 0, 0);
3160 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3164 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &thread_to_kill
);
3165 CHK ("thread_kill_command: machid_mach_port map failed", ret
);
3168 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3170 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3171 ret
= task_threads (inferior_task
, &thread_table
, &thread_count
);
3172 CHK ("Error getting inferior's thread list", ret
);
3174 if (thread_to_kill
== current_thread
)
3176 ret
= thread_terminate (thread_to_kill
);
3177 CHK ("Thread could not be terminated", ret
);
3179 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3180 warning ("Last thread was killed, use \"kill\" command to kill task");
3183 for (index
= 0; index
< thread_count
; index
++)
3184 if (thread_table
[index
] == thread_to_kill
)
3186 ret
= thread_terminate (thread_to_kill
);
3187 CHK ("Thread could not be terminated", ret
);
3190 if (thread_count
> 1)
3191 consume_send_rights (thread_table
, thread_count
);
3193 ret
= vm_deallocate (mach_task_self (), (vm_address_t
) thread_table
,
3194 (thread_count
* sizeof (mach_port_t
)));
3195 CHK ("Error trying to deallocate thread list", ret
);
3197 warning ("Thread %d killed", mid
);
3201 /* Task specific commands; add more if you like */
3204 task_resume_command (char *args
, int from_tty
)
3207 task_basic_info_data_t ta_info
;
3208 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3209 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3211 MACH_ERROR_NO_INFERIOR
;
3213 /* Would be trivial to change, but is it desirable? */
3215 error ("Currently gdb can resume only it's inferior task");
3217 ret
= task_info (inferior_task
,
3219 (task_info_t
) & ta_info
,
3221 CHK ("task_resume_command: task_info failed", ret
);
3223 if (ta_info
.suspend_count
== 0)
3224 error ("Inferior task %d is not suspended", mid
);
3225 else if (ta_info
.suspend_count
== 1 &&
3227 !query ("Suspend count is now 1. Do you know what you are doing? "))
3228 error ("Task not resumed");
3230 ret
= task_resume (inferior_task
);
3231 CHK ("task_resume_command: task_resume", ret
);
3233 if (ta_info
.suspend_count
== 1)
3235 warning ("Inferior task %d is no longer suspended", mid
);
3236 must_suspend_thread
= 1;
3237 /* @@ This is not complete: Registers change all the time when not
3239 registers_changed ();
3242 warning ("Inferior task %d suspend count is now %d",
3243 mid
, ta_info
.suspend_count
- 1);
3248 task_suspend_command (char *args
, int from_tty
)
3251 task_basic_info_data_t ta_info
;
3252 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3253 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3255 MACH_ERROR_NO_INFERIOR
;
3257 /* Would be trivial to change, but is it desirable? */
3259 error ("Currently gdb can suspend only it's inferior task");
3261 ret
= task_suspend (inferior_task
);
3262 CHK ("task_suspend_command: task_suspend", ret
);
3264 must_suspend_thread
= 0;
3266 ret
= task_info (inferior_task
,
3268 (task_info_t
) & ta_info
,
3270 CHK ("task_suspend_command: task_info failed", ret
);
3272 warning ("Inferior task %d suspend count is now %d",
3273 mid
, ta_info
.suspend_count
);
3277 get_size (int bytes
)
3279 static char size
[30];
3280 int zz
= bytes
/ 1024;
3283 sprintf (size
, "%-2.1f M", ((float) bytes
) / (1024.0 * 1024.0));
3285 sprintf (size
, "%d K", zz
);
3290 /* Does this require the target task to be suspended?? I don't think so. */
3292 task_info_command (char *args
, int from_tty
)
3297 task_basic_info_data_t ta_info
;
3298 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3299 int page_size
= round_page (1);
3300 int thread_count
= 0;
3302 if (MACH_PORT_VALID (inferior_task
))
3303 mid
= map_port_name_to_mid (inferior_task
,
3306 task
= inferior_task
;
3310 int tmid
= atoi (args
);
3313 error ("Invalid mid %d for task info", tmid
);
3318 ret
= machid_mach_port (mid_server
, mid_auth
, tmid
, &task
);
3319 CHK ("task_info_command: machid_mach_port map failed", ret
);
3324 error ("You have to give the task MID as an argument");
3326 ret
= task_info (task
,
3328 (task_info_t
) & ta_info
,
3330 CHK ("task_info_command: task_info failed", ret
);
3332 printf_filtered ("\nTask info for task %d:\n\n", mid
);
3333 printf_filtered (" Suspend count : %d\n", ta_info
.suspend_count
);
3334 printf_filtered (" Base priority : %d\n", ta_info
.base_priority
);
3335 printf_filtered (" Virtual size : %s\n", get_size (ta_info
.virtual_size
));
3336 printf_filtered (" Resident size : %s\n", get_size (ta_info
.resident_size
));
3339 thread_array_t thread_list
;
3341 ret
= task_threads (task
, &thread_list
, &thread_count
);
3342 CHK ("task_info_command: task_threads", ret
);
3344 printf_filtered (" Thread count : %d\n", thread_count
);
3346 consume_send_rights (thread_list
, thread_count
);
3347 ret
= vm_deallocate (mach_task_self (),
3348 (vm_address_t
) thread_list
,
3349 (thread_count
* sizeof (int)));
3350 CHK ("Error trying to deallocate thread list", ret
);
3352 if (have_emulator_p (task
))
3353 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3354 EMULATOR_BASE
, EMULATOR_END
);
3356 printf_filtered (" No emulator.\n");
3358 if (thread_count
&& task
== inferior_task
)
3359 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3362 /* You may either FORWARD the exception to the inferior, or KEEP
3363 * it and return to GDB command level.
3365 * exception mid [ forward | keep ]
3369 exception_command (char *args
, int from_tty
)
3376 error_no_arg ("exception number action");
3378 while (*scan
== ' ' || *scan
== '\t')
3381 if ('0' <= *scan
&& *scan
<= '9')
3382 while ('0' <= *scan
&& *scan
<= '9')
3385 error ("exception number action");
3387 exception
= atoi (args
);
3388 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3389 error ("Allowed exception numbers are in range 1..%d",
3392 if (*scan
!= ' ' && *scan
!= '\t')
3393 error ("exception number must be followed by a space");
3395 while (*scan
== ' ' || *scan
== '\t')
3407 error ("exception number action");
3409 if (!strncasecmp (args
, "forward", len
))
3410 exception_map
[exception
].forward
= TRUE
;
3411 else if (!strncasecmp (args
, "keep", len
))
3412 exception_map
[exception
].forward
= FALSE
;
3414 error ("exception action is either \"keep\" or \"forward\"");
3418 print_exception_info (int exception
)
3420 boolean_t forward
= exception_map
[exception
].forward
;
3422 printf_filtered ("%s\t(%d): ", exception_map
[exception
].name
,
3425 if (exception_map
[exception
].sigmap
!= SIG_UNKNOWN
)
3426 printf_filtered ("keep and handle as signal %d\n",
3427 exception_map
[exception
].sigmap
);
3429 printf_filtered ("keep and handle as unknown signal %d\n",
3430 exception_map
[exception
].sigmap
);
3432 printf_filtered ("forward exception to inferior\n");
3436 exception_info (char *args
, int from_tty
)
3441 for (exception
= 1; exception
<= MAX_EXCEPTION
; exception
++)
3442 print_exception_info (exception
);
3445 exception
= atoi (args
);
3447 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3448 error ("Invalid exception number, values from 1 to %d allowed",
3450 print_exception_info (exception
);
3454 /* Check for actions for mach exceptions.
3456 mach3_exception_actions (WAITTYPE
*w
, boolean_t force_print_only
, char *who
)
3458 boolean_t force_print
= FALSE
;
3461 if (force_print_only
||
3462 exception_map
[stop_exception
].sigmap
== SIG_UNKNOWN
)
3465 WSETSTOP (*w
, exception_map
[stop_exception
].sigmap
);
3467 if (exception_map
[stop_exception
].print
|| force_print
)
3469 target_terminal_ours ();
3471 printf_filtered ("\n%s received %s exception : ",
3473 exception_map
[stop_exception
].name
);
3477 switch (stop_exception
)
3479 case EXC_BAD_ACCESS
:
3480 printf_filtered ("referencing address 0x%x : %s\n",
3482 mach_error_string (stop_code
));
3484 case EXC_BAD_INSTRUCTION
:
3486 ("illegal or undefined instruction. code %d subcode %d\n",
3487 stop_code
, stop_subcode
);
3489 case EXC_ARITHMETIC
:
3490 printf_filtered ("code %d\n", stop_code
);
3493 printf_filtered ("code %d subcode %d\n", stop_code
, stop_subcode
);
3496 printf_filtered ("%s specific, code 0x%x\n",
3497 stop_code
< 0xffff ? "hardware" : "os emulation",
3500 case EXC_BREAKPOINT
:
3501 printf_filtered ("type %d (machine dependent)\n",
3505 internal_error ("Unknown exception");
3510 setup_notify_port (int create_new
)
3514 if (MACH_PORT_VALID (our_notify_port
))
3516 ret
= mach_port_destroy (mach_task_self (), our_notify_port
);
3517 CHK ("Could not destroy our_notify_port", ret
);
3520 our_notify_port
= MACH_PORT_NULL
;
3521 notify_chain
= (port_chain_t
) NULL
;
3522 port_chain_destroy (port_chain_obstack
);
3526 ret
= mach_port_allocate (mach_task_self (),
3527 MACH_PORT_RIGHT_RECEIVE
,
3529 if (ret
!= KERN_SUCCESS
)
3530 internal_error ("Creating notify port %s", mach_error_string (ret
));
3532 ret
= mach_port_move_member (mach_task_self (),
3534 inferior_wait_port_set
);
3535 if (ret
!= KERN_SUCCESS
)
3536 internal_error ("initial move member %s", mach_error_string (ret
));
3541 * Register our message port to the net name server
3543 * Currently used only by the external stop-gdb program
3544 * since ^C does not work if you would like to enter
3545 * gdb command level while debugging your program.
3547 * NOTE: If the message port is sometimes used for other
3548 * purposes also, the NAME must not be a guessable one.
3549 * Then, there should be a way to change it.
3552 char registered_name
[MAX_NAME_LEN
];
3555 message_port_info (char *args
, int from_tty
)
3557 if (registered_name
[0])
3558 printf_filtered ("gdb's message port name: '%s'\n",
3561 printf_filtered ("gdb's message port is not currently registered\n");
3565 gdb_register_port (char *name
, mach_port_t port
)
3568 static int already_signed
= 0;
3571 if (!MACH_PORT_VALID (port
) || !name
|| !*name
)
3573 warning ("Invalid registration request");
3577 if (!already_signed
)
3579 ret
= mach_port_insert_right (mach_task_self (),
3582 MACH_MSG_TYPE_MAKE_SEND
);
3583 CHK ("Failed to create a signature to our_message_port", ret
);
3586 else if (already_signed
> 1)
3588 ret
= netname_check_out (name_server_port
,
3591 CHK ("Failed to check out gdb's message port", ret
);
3592 registered_name
[0] = '\000';
3596 ret
= netname_check_in (name_server_port
, /* Name server port */
3597 name
, /* Name of service */
3598 our_message_port
, /* Signature */
3599 port
); /* Creates a new send right */
3600 CHK ("Failed to check in the port", ret
);
3603 while (len
< MAX_NAME_LEN
&& *(name
+ len
))
3605 registered_name
[len
] = *(name
+ len
);
3608 registered_name
[len
] = '\000';
3612 struct cmd_list_element
*cmd_thread_list
;
3613 struct cmd_list_element
*cmd_task_list
;
3617 thread_command (char *arg
, int from_tty
)
3619 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3620 help_list (cmd_thread_list
, "thread ", -1, gdb_stdout
);
3625 task_command (char *arg
, int from_tty
)
3627 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3628 help_list (cmd_task_list
, "task ", -1, gdb_stdout
);
3631 add_mach_specific_commands (void)
3633 /* Thread handling commands */
3635 /* FIXME: Move our thread support into the generic thread.c stuff so we
3636 can share that code. */
3637 add_prefix_cmd ("mthread", class_stack
, thread_command
,
3638 "Generic command for handling Mach threads in the debugged task.",
3639 &cmd_thread_list
, "thread ", 0, &cmdlist
);
3641 add_com_alias ("th", "mthread", class_stack
, 1);
3643 add_cmd ("select", class_stack
, thread_select_command
,
3644 "Select and print MID of the selected thread",
3646 add_cmd ("list", class_stack
, thread_list_command
,
3647 "List info of task's threads. Selected thread is marked with '*'",
3649 add_cmd ("suspend", class_run
, thread_suspend_command
,
3650 "Suspend one or all of the threads in the selected task.",
3652 add_cmd ("resume", class_run
, thread_resume_command
,
3653 "Resume one or all of the threads in the selected task.",
3655 add_cmd ("kill", class_run
, thread_kill_command
,
3656 "Kill the specified thread MID from inferior task.",
3659 /* The rest of this support (condition_thread) was not merged. It probably
3660 should not be merged in this form, but instead added to the generic GDB
3662 add_cmd ("break", class_breakpoint
, condition_thread
,
3663 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3664 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3667 /* Thread command shorthands (for backward compatibility) */
3668 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist
);
3669 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist
);
3671 /* task handling commands */
3673 add_prefix_cmd ("task", class_stack
, task_command
,
3674 "Generic command for handling debugged task.",
3675 &cmd_task_list
, "task ", 0, &cmdlist
);
3677 add_com_alias ("ta", "task", class_stack
, 1);
3679 add_cmd ("suspend", class_run
, task_suspend_command
,
3680 "Suspend the inferior task.",
3682 add_cmd ("resume", class_run
, task_resume_command
,
3683 "Resume the inferior task.",
3685 add_cmd ("info", no_class
, task_info_command
,
3686 "Print information about the specified task.",
3689 /* Print my message port name */
3691 add_info ("message-port", message_port_info
,
3692 "Returns the name of gdb's message port in the netnameserver");
3694 /* Exception commands */
3696 add_info ("exceptions", exception_info
,
3697 "What debugger does when program gets various exceptions.\n\
3698 Specify an exception number as argument to print info on that\n\
3701 add_com ("exception", class_run
, exception_command
,
3702 "Specify how to handle an exception.\n\
3703 Args are exception number followed by \"forward\" or \"keep\".\n\
3704 `Forward' means forward the exception to the program's normal exception\n\
3706 `Keep' means reenter debugger if this exception happens, and GDB maps\n\
3707 the exception to some signal (see info exception)\n\
3708 Normally \"keep\" is used to return to GDB on exception.");
3712 do_mach_notify_dead_name (mach_port_t notify
, mach_port_t name
)
3714 kern_return_t kr
= KERN_SUCCESS
;
3716 /* Find the thing that notified */
3717 port_chain_t element
= port_chain_member (notify_chain
, name
);
3719 /* Take name of from unreceived dead name notification list */
3720 notify_chain
= port_chain_delete (notify_chain
, name
);
3723 error ("Received a dead name notify from unchained port (0x%x)", name
);
3725 switch (element
->type
)
3728 case MACH_TYPE_THREAD
:
3729 target_terminal_ours_for_output ();
3730 if (name
== current_thread
)
3732 printf_filtered ("\nCurrent thread %d died", element
->mid
);
3733 current_thread
= MACH_PORT_NULL
;
3736 printf_filtered ("\nThread %d died", element
->mid
);
3740 case MACH_TYPE_TASK
:
3741 target_terminal_ours_for_output ();
3742 if (name
!= inferior_task
)
3743 printf_filtered ("Task %d died, but it was not the selected task",
3747 printf_filtered ("Current task %d died", element
->mid
);
3749 mach_port_destroy (mach_task_self (), name
);
3750 inferior_task
= MACH_PORT_NULL
;
3753 warning ("There were still unreceived dead_name_notifications???");
3755 /* Destroy the old notifications */
3756 setup_notify_port (0);
3762 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3763 name
, element
->type
, element
->mid
);
3767 return KERN_SUCCESS
;
3771 do_mach_notify_msg_accepted (mach_port_t notify
, mach_port_t name
)
3773 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3775 return KERN_SUCCESS
;
3779 do_mach_notify_no_senders (mach_port_t notify
, mach_port_mscount_t mscount
)
3781 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3783 return KERN_SUCCESS
;
3787 do_mach_notify_port_deleted (mach_port_t notify
, mach_port_t name
)
3789 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3791 return KERN_SUCCESS
;
3795 do_mach_notify_port_destroyed (mach_port_t notify
, mach_port_t rights
)
3797 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3799 return KERN_SUCCESS
;
3803 do_mach_notify_send_once (mach_port_t notify
)
3806 /* MANY of these are generated. */
3807 warning ("do_mach_notify_send_once : notify %x",
3810 return KERN_SUCCESS
;
3813 /* Kills the inferior. It's gone when you call this */
3815 kill_inferior_fast (void)
3819 if (inferior_pid
== 0 || inferior_pid
== 1)
3822 /* kill() it, since the Unix server does not otherwise notice when
3823 * killed with task_terminate().
3825 if (inferior_pid
> 0)
3826 kill (inferior_pid
, SIGKILL
);
3828 /* It's propably terminate already */
3829 (void) task_terminate (inferior_task
);
3831 inferior_task
= MACH_PORT_NULL
;
3832 current_thread
= MACH_PORT_NULL
;
3834 wait3 (&w
, WNOHANG
, 0);
3836 setup_notify_port (0);
3840 m3_kill_inferior (void)
3842 kill_inferior_fast ();
3843 target_mourn_inferior ();
3846 /* Clean up after the inferior dies. */
3849 m3_mourn_inferior (void)
3851 unpush_target (&m3_ops
);
3852 generic_mourn_inferior ();
3856 /* Fork an inferior process, and start debugging it. */
3859 m3_create_inferior (char *exec_file
, char *allargs
, char **env
)
3861 fork_inferior (exec_file
, allargs
, env
, m3_trace_me
, m3_trace_him
, NULL
, NULL
);
3862 /* We are at the first instruction we care about. */
3863 /* Pedal to the metal... */
3864 proceed ((CORE_ADDR
) -1, 0, 0);
3867 /* Mark our target-struct as eligible for stray "run" and "attach"
3875 /* Mach 3.0 does not need ptrace for anything
3876 * Make sure nobody uses it on mach.
3878 ptrace (int a
, int b
, int c
, int d
)
3880 error ("Lose, Lose! Somebody called ptrace\n");
3883 /* Resume execution of the inferior process.
3884 If STEP is nonzero, single-step it.
3885 If SIGNAL is nonzero, give it that signal. */
3888 m3_resume (int pid
, int step
, enum target_signal signal
)
3894 thread_basic_info_data_t th_info
;
3895 unsigned int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3897 /* There is no point in single stepping when current_thread
3900 if (!MACH_PORT_VALID (current_thread
))
3901 error ("No thread selected; can not single step");
3903 /* If current_thread is suspended, tracing it would never return.
3905 ret
= thread_info (current_thread
,
3907 (thread_info_t
) & th_info
,
3909 CHK ("child_resume: can't get thread info", ret
);
3911 if (th_info
.suspend_count
)
3912 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3915 vm_read_cache_valid
= FALSE
;
3917 if (signal
&& inferior_pid
> 0) /* Do not signal, if attached by MID */
3918 kill (inferior_pid
, target_signal_to_host (signal
));
3922 suspend_all_threads (0);
3924 setup_single_step (current_thread
, TRUE
);
3926 ret
= thread_resume (current_thread
);
3927 CHK ("thread_resume", ret
);
3930 ret
= task_resume (inferior_task
);
3931 if (ret
== KERN_FAILURE
)
3932 warning ("Task was not suspended");
3934 CHK ("Resuming task", ret
);
3936 /* HACK HACK This is needed by the multiserver system HACK HACK */
3937 while ((ret
= task_resume (inferior_task
)) == KERN_SUCCESS
)
3938 /* make sure it really runs */ ;
3939 /* HACK HACK This is needed by the multiserver system HACK HACK */
3942 #ifdef ATTACH_DETACH
3944 /* Start debugging the process with the given task */
3946 task_attach (task_t tid
)
3949 inferior_task
= tid
;
3951 ret
= task_suspend (inferior_task
);
3952 CHK ("task_attach: task_suspend", ret
);
3954 must_suspend_thread
= 0;
3956 setup_notify_port (1);
3958 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
3960 setup_exception_port ();
3962 emulator_present
= have_emulator_p (inferior_task
);
3967 /* Well, we can call error also here and leave the
3968 * target stack inconsistent. Sigh.
3969 * Fix this sometime (the only way to fail here is that
3970 * the task has no threads at all, which is rare, but
3971 * possible; or if the target task has died, which is also
3972 * possible, but unlikely, since it has been suspended.
3973 * (Someone must have killed it))
3976 attach_to_thread (void)
3978 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3979 error ("Could not select any threads to attach to");
3982 mid_attach (int mid
)
3986 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &inferior_task
);
3987 CHK ("mid_attach: machid_mach_port", ret
);
3989 task_attach (inferior_task
);
3995 * Start debugging the process whose unix process-id is PID.
3996 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
3998 * Prevent (possible unwanted) dangerous operations by enabled users
3999 * like "atta 0" or "atta foo" (equal to the previous :-) and
4000 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4003 m3_do_attach (int pid
)
4008 error ("MID=0, Debugging the master unix server does not compute");
4010 /* Foo. This assumes gdb has a unix pid */
4011 if (pid
== getpid ())
4012 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4016 mid_attach (-(pid
));
4018 /* inferior_pid will be NEGATIVE! */
4021 return inferior_pid
;
4024 inferior_task
= task_by_pid (pid
);
4025 if (!MACH_PORT_VALID (inferior_task
))
4026 error ("Cannot map Unix pid %d to Mach task port", pid
);
4028 task_attach (inferior_task
);
4032 return inferior_pid
;
4035 /* Attach to process PID, then initialize for debugging it
4036 and wait for the trace-trap that results from attaching. */
4039 m3_attach (char *args
, int from_tty
)
4045 error_no_arg ("process-id to attach");
4049 if (pid
== getpid ()) /* Trying to masturbate? */
4050 error ("I refuse to debug myself!");
4054 exec_file
= (char *) get_exec_file (0);
4057 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file
, target_pid_to_str (pid
));
4059 printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid
));
4061 gdb_flush (gdb_stdout
);
4066 push_target (&m3_ops
);
4070 deallocate_inferior_ports (void)
4073 thread_array_t thread_list
;
4074 int thread_count
, index
;
4076 if (!MACH_PORT_VALID (inferior_task
))
4079 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
4080 if (ret
!= KERN_SUCCESS
)
4082 warning ("deallocate_inferior_ports: task_threads",
4083 mach_error_string (ret
));
4087 /* Get rid of send rights to task threads */
4088 for (index
= 0; index
< thread_count
; index
++)
4091 ret
= mach_port_get_refs (mach_task_self (),
4093 MACH_PORT_RIGHT_SEND
,
4095 CHK ("deallocate_inferior_ports: get refs", ret
);
4099 ret
= mach_port_mod_refs (mach_task_self (),
4101 MACH_PORT_RIGHT_SEND
,
4103 CHK ("deallocate_inferior_ports: mod refs", ret
);
4107 ret
= mach_port_mod_refs (mach_task_self (),
4108 inferior_exception_port
,
4109 MACH_PORT_RIGHT_RECEIVE
,
4111 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret
);
4113 ret
= mach_port_deallocate (mach_task_self (),
4115 CHK ("deallocate_task_port: deallocating inferior_task", ret
);
4117 current_thread
= MACH_PORT_NULL
;
4118 inferior_task
= MACH_PORT_NULL
;
4121 /* Stop debugging the process whose number is PID
4122 and continue it with signal number SIGNAL.
4123 SIGNAL = 0 means just continue it. */
4126 m3_do_detach (int signal
)
4130 MACH_ERROR_NO_INFERIOR
;
4132 if (current_thread
!= MACH_PORT_NULL
)
4134 /* Store the gdb's view of the thread we are deselecting
4136 * @@ I am really not sure if this is ever needeed.
4138 target_prepare_to_store ();
4139 target_store_registers (-1);
4142 ret
= task_set_special_port (inferior_task
,
4143 TASK_EXCEPTION_PORT
,
4144 inferior_old_exception_port
);
4145 CHK ("task_set_special_port", ret
);
4147 /* Discard all requested notifications */
4148 setup_notify_port (0);
4150 if (remove_breakpoints ())
4151 warning ("Could not remove breakpoints when detaching");
4153 if (signal
&& inferior_pid
> 0)
4154 kill (inferior_pid
, signal
);
4156 /* the task might be dead by now */
4157 (void) task_resume (inferior_task
);
4159 deallocate_inferior_ports ();
4164 /* Take a program previously attached to and detaches it.
4165 The program resumes execution and will no longer stop
4166 on signals, etc. We'd better not have left any breakpoints
4167 in the program or it'll die when it hits one. For this
4168 to work, it may be necessary for the process to have been
4169 previously attached. It *might* work if the program was
4170 started via fork. */
4173 m3_detach (char *args
, int from_tty
)
4179 char *exec_file
= get_exec_file (0);
4182 printf_unfiltered ("Detaching from program: %s %s\n",
4183 exec_file
, target_pid_to_str (inferior_pid
));
4184 gdb_flush (gdb_stdout
);
4187 siggnal
= atoi (args
);
4189 m3_do_detach (siggnal
);
4191 unpush_target (&m3_ops
); /* Pop out of handling an inferior */
4193 #endif /* ATTACH_DETACH */
4195 /* Get ready to modify the registers array. On machines which store
4196 individual registers, this doesn't need to do anything. On machines
4197 which store all the registers in one fell swoop, this makes sure
4198 that registers contains all the registers from the program being
4202 m3_prepare_to_store (void)
4204 #ifdef CHILD_PREPARE_TO_STORE
4205 CHILD_PREPARE_TO_STORE ();
4209 /* Print status information about what we're accessing. */
4212 m3_files_info (struct target_ops
*ignore
)
4214 /* FIXME: should print MID and all that crap. */
4215 printf_unfiltered ("\tUsing the running image of %s %s.\n",
4216 attach_flag
? "attached" : "child", target_pid_to_str (inferior_pid
));
4220 m3_open (char *arg
, int from_tty
)
4222 error ("Use the \"run\" command to start a Unix child process.");
4232 char *bsd1_names
[] =
4301 int bsd1_nnames
= sizeof (bsd1_names
) / sizeof (bsd1_names
[0]);
4304 name_str (int name
, char *buf
)
4308 case MACH_MSG_TYPE_BOOLEAN
:
4310 case MACH_MSG_TYPE_INTEGER_16
:
4312 case MACH_MSG_TYPE_INTEGER_32
:
4314 case MACH_MSG_TYPE_CHAR
:
4316 case MACH_MSG_TYPE_BYTE
:
4318 case MACH_MSG_TYPE_REAL
:
4320 case MACH_MSG_TYPE_STRING
:
4323 sprintf (buf
, "%d", name
);
4329 id_str (int id
, char *buf
)
4332 if (id
>= 101000 && id
< 101000 + bsd1_nnames
)
4334 if (p
= bsd1_names
[id
- 101000])
4338 return "psignal_retry";
4341 sprintf (buf
, "%d", id
);
4345 print_msg (mach_msg_header_t
*mp
)
4347 char *fmt_x
= "%20s : 0x%08x\n";
4348 char *fmt_d
= "%20s : %10d\n";
4349 char *fmt_s
= "%20s : %s\n";
4352 puts_filtered ("\n");
4353 #define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
4354 pr (fmt_x
, (*mp
), msgh_bits
);
4355 pr (fmt_d
, (*mp
), msgh_size
);
4356 pr (fmt_x
, (*mp
), msgh_remote_port
);
4357 pr (fmt_x
, (*mp
), msgh_local_port
);
4358 pr (fmt_d
, (*mp
), msgh_kind
);
4359 printf_filtered (fmt_s
, STR (msgh_id
), id_str (mp
->msgh_id
, buf
));
4361 if (debug_level
> 1)
4366 ep
= p
+ mp
->msgh_size
;
4368 for (; p
< ep
; p
+= plen
)
4370 mach_msg_type_t
*tp
;
4371 mach_msg_type_long_t
*tlp
;
4372 int name
, size
, number
;
4373 tp
= (mach_msg_type_t
*) p
;
4374 if (tp
->msgt_longform
)
4376 tlp
= (mach_msg_type_long_t
*) tp
;
4377 name
= tlp
->msgtl_name
;
4378 size
= tlp
->msgtl_size
;
4379 number
= tlp
->msgtl_number
;
4380 plen
= sizeof (*tlp
);
4384 name
= tp
->msgt_name
;
4385 size
= tp
->msgt_size
;
4386 number
= tp
->msgt_number
;
4387 plen
= sizeof (*tp
);
4389 printf_filtered ("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4390 name_str (name
, buf
), size
, number
, tp
->msgt_inline
,
4391 tp
->msgt_longform
, tp
->msgt_deallocate
);
4393 if (tp
->msgt_inline
)
4396 l
= size
* number
/ 8;
4397 l
= (l
+ sizeof (long) - 1) & ~((sizeof (long)) - 1);
4399 print_data (dp
, size
, number
);
4403 plen
+= sizeof (int *);
4405 printf_filtered ("plen=%d\n", plen
);
4410 print_data (char *p
, int size
, int number
)
4419 for (i
= 0; i
< number
; i
++)
4421 printf_filtered (" %02x", p
[i
]);
4426 for (i
= 0; i
< number
; i
++)
4428 printf_filtered (" %04x", sp
[i
]);
4433 for (i
= 0; i
< number
; i
++)
4435 printf_filtered (" %08x", ip
[i
]);
4439 puts_filtered ("\n");
4441 #endif /* DUMP_SYSCALL */
4446 error ("to_stop target function not implemented");
4450 m3_pid_to_exec_file (int pid
)
4452 error ("to_pid_to_exec_file target function not implemented");
4453 return NULL
; /* To keep all compilers happy. */
4459 m3_ops
.to_shortname
= "mach";
4460 m3_ops
.to_longname
= "Mach child process";
4461 m3_ops
.to_doc
= "Mach child process (started by the \"run\" command).";
4462 m3_ops
.to_open
= m3_open
;
4463 m3_ops
.to_attach
= m3_attach
;
4464 m3_ops
.to_detach
= m3_detach
;
4465 m3_ops
.to_resume
= m3_resume
;
4466 m3_ops
.to_wait
= mach_really__wait
;
4467 m3_ops
.to_fetch_registers
= fetch_inferior_registers
;
4468 m3_ops
.to_store_registers
= store_inferior_registers
;
4469 m3_ops
.to_prepare_to_store
= m3_prepare_to_store
;
4470 m3_ops
.to_xfer_memory
= m3_xfer_memory
;
4471 m3_ops
.to_files_info
= m3_files_info
;
4472 m3_ops
.to_insert_breakpoint
= memory_insert_breakpoint
;
4473 m3_ops
.to_remove_breakpoint
= memory_remove_breakpoint
;
4474 m3_ops
.to_terminal_init
= terminal_init_inferior
;
4475 m3_ops
.to_terminal_inferior
= terminal_inferior
;
4476 m3_ops
.to_terminal_ours_for_output
= terminal_ours_for_output
;
4477 m3_ops
.to_terminal_ours
= terminal_ours
;
4478 m3_ops
.to_terminal_info
= child_terminal_info
;
4479 m3_ops
.to_kill
= m3_kill_inferior
;
4480 m3_ops
.to_create_inferior
= m3_create_inferior
;
4481 m3_ops
.to_mourn_inferior
= m3_mourn_inferior
;
4482 m3_ops
.to_can_run
= m3_can_run
;
4483 m3_ops
.to_stop
= m3_stop
;
4484 m3_ops
.to_pid_to_exec_file
= m3_pid_to_exec_file
;
4485 m3_ops
.to_stratum
= process_stratum
;
4486 m3_ops
.to_has_all_memory
= 1;
4487 m3_ops
.to_has_memory
= 1;
4488 m3_ops
.to_has_stack
= 1;
4489 m3_ops
.to_has_registers
= 1;
4490 m3_ops
.to_has_execution
= 1;
4491 m3_ops
.to_magic
= OPS_MAGIC
;
4495 _initialize_m3_nat (void)
4500 add_target (&m3_ops
);
4502 ret
= mach_port_allocate (mach_task_self (),
4503 MACH_PORT_RIGHT_PORT_SET
,
4504 &inferior_wait_port_set
);
4505 if (ret
!= KERN_SUCCESS
)
4506 internal_error ("initial port set %s", mach_error_string (ret
));
4508 /* mach_really_wait now waits for this */
4509 currently_waiting_for
= inferior_wait_port_set
;
4511 ret
= netname_look_up (name_server_port
, hostname
, "MachID", &mid_server
);
4512 if (ret
!= KERN_SUCCESS
)
4514 mid_server
= MACH_PORT_NULL
;
4516 warning ("initialize machid: netname_lookup_up(MachID) : %s",
4517 mach_error_string (ret
));
4518 warning ("Some (most?) features disabled...");
4521 mid_auth
= mach_privileged_host_port ();
4522 if (mid_auth
== MACH_PORT_NULL
)
4523 mid_auth
= mach_task_self ();
4525 obstack_init (port_chain_obstack
);
4527 ret
= mach_port_allocate (mach_task_self (),
4528 MACH_PORT_RIGHT_RECEIVE
,
4529 &thread_exception_port
);
4530 CHK ("Creating thread_exception_port for single stepping", ret
);
4532 ret
= mach_port_insert_right (mach_task_self (),
4533 thread_exception_port
,
4534 thread_exception_port
,
4535 MACH_MSG_TYPE_MAKE_SEND
);
4536 CHK ("Inserting send right to thread_exception_port", ret
);
4538 /* Allocate message port */
4539 ret
= mach_port_allocate (mach_task_self (),
4540 MACH_PORT_RIGHT_RECEIVE
,
4542 if (ret
!= KERN_SUCCESS
)
4543 warning ("Creating message port %s", mach_error_string (ret
));
4546 char buf
[MAX_NAME_LEN
];
4547 ret
= mach_port_move_member (mach_task_self (),
4549 inferior_wait_port_set
);
4550 if (ret
!= KERN_SUCCESS
)
4551 warning ("message move member %s", mach_error_string (ret
));
4554 /* @@@@ No way to change message port name currently */
4555 /* Foo. This assumes gdb has a unix pid */
4556 sprintf (buf
, "gdb-%d", getpid ());
4557 gdb_register_port (buf
, our_message_port
);
4560 /* Heap for thread commands */
4561 obstack_init (cproc_obstack
);
4563 add_mach_specific_commands ();