1 /* Interface GDB to Mach 3.0 operating systems.
2 (Most) Mach 3.0 related routines live in this file.
4 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
5 Free Software Foundation, Inc.
7 This file is part of GDB.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
25 * Author: Jukka Virtanen <jtv@hut.fi>
27 * Helsinki University of Technology
30 * Thanks to my friends who helped with ideas and testing:
32 * Johannes Helander, Antti Louko, Tero Mononen,
33 * jvh@cs.hut.fi alo@hut.fi tmo@cs.hut.fi
35 * Tero Kivinen and Eamonn McManus
36 * kivinen@cs.hut.fi emcmanus@gr.osf.org
43 #include <servers/netname.h>
44 #include <servers/machid.h>
45 #include <mach/message.h>
46 #include <mach/notify.h>
47 #include <mach_error.h>
48 #include <mach/exception.h>
49 #include <mach/vm_attributes.h>
63 #include <servers/machid_lib.h>
65 #define MACH_TYPE_TASK 1
66 #define MACH_TYPE_THREAD 2
69 /* Included only for signal names and NSIG
71 * note: There are many problems in signal handling with
72 * gdb in Mach 3.0 in general.
75 #define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
79 /* This is what a cproc looks like. This is here partly because
80 cthread_internals.h is not a header we can just #include, partly with
81 an eye towards perhaps getting this to work with cross-debugging
82 someday. Best solution is if CMU publishes a real interface to this
84 #define CPROC_NEXT_OFFSET 0
85 #define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
86 #define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
87 #define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
88 #define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
89 #define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
90 #define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
91 #define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
92 #define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
93 #define CPROC_REPLY_SIZE (sizeof (mach_port_t))
94 #define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
95 #define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
96 #define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
97 #define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
98 #define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
99 #define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
100 #define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
101 #define CPROC_WIRED_SIZE (sizeof (mach_port_t))
102 #define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
103 #define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
104 #define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
105 #define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
106 #define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
107 #define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
108 #define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
109 #define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
110 #define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
112 /* Values for the state field in the cproc. */
113 #define CPROC_RUNNING 0
114 #define CPROC_SWITCHING 1
115 #define CPROC_BLOCKED 2
116 #define CPROC_CONDWAIT 4
118 /* For cproc and kernel thread mapping */
119 typedef struct gdb_thread
125 boolean_t in_emulator
;
128 /* This is for the mthreads list. It points to the cproc list.
129 Perhaps the two lists should be merged (or perhaps it was a mistake
130 to make them both use a struct gdb_thread). */
131 struct gdb_thread
*cproc
;
133 /* These are for the cproc list, which is linked through the next field
134 of the struct gdb_thread. */
135 char raw_cproc
[CPROC_SIZE
];
136 /* The cthread which is pointed to by the incarnation field from the
137 cproc. This points to the copy we've read into GDB. */
139 /* Point back to the mthreads list. */
141 struct gdb_thread
*next
;
146 * Actions for Mach exceptions.
148 * sigmap field maps the exception to corresponding Unix signal.
150 * I do not know how to map the exception to unix signal
151 * if SIG_UNKNOWN is specified.
154 struct exception_list
164 "not_mach3_exception", FALSE
, TRUE
, SIG_UNKNOWN
168 "EXC_BAD_ACCESS", FALSE
, TRUE
, SIGSEGV
172 "EXC_BAD_INSTRUCTION", FALSE
, TRUE
, SIGILL
176 "EXC_ARITHMETIC", FALSE
, TRUE
, SIGFPE
180 "EXC_EMULATION", FALSE
, TRUE
, SIGEMT
184 "EXC_SOFTWARE", FALSE
, TRUE
, SIG_UNKNOWN
188 "EXC_BREAKPOINT", FALSE
, FALSE
, SIGTRAP
192 /* Mach exception table size */
193 int max_exception
= sizeof (exception_map
) / sizeof (struct exception_list
) - 1;
195 #define MAX_EXCEPTION max_exception
197 WAITTYPE wait_status
;
199 /* If you define this, intercepted bsd server calls will be
200 * dumped while waiting the inferior to EXEC the correct
203 /* #define DUMP_SYSCALL /* debugging interceptor */
205 /* xx_debug() outputs messages if this is nonzero.
206 * If > 1, DUMP_SYSCALL will dump message contents.
210 /* "Temporary" debug stuff */
212 xx_debug (char *fmt
, int a
, int b
, int c
)
215 warning (fmt
, a
, b
, c
);
218 /* This is in libmach.a */
219 extern mach_port_t name_server_port
;
221 /* Set in catch_exception_raise */
222 int stop_exception
, stop_code
, stop_subcode
;
223 int stopped_in_exception
;
225 /* Thread that was the active thread when we stopped */
226 thread_t stop_thread
= MACH_PORT_NULL
;
230 /* Set when task is attached or created */
231 boolean_t emulator_present
= FALSE
;
233 task_t inferior_task
;
234 thread_t current_thread
;
236 /* Exception ports for inferior task */
237 mach_port_t inferior_exception_port
= MACH_PORT_NULL
;
238 mach_port_t inferior_old_exception_port
= MACH_PORT_NULL
;
240 /* task exceptions and notifications */
241 mach_port_t inferior_wait_port_set
= MACH_PORT_NULL
;
242 mach_port_t our_notify_port
= MACH_PORT_NULL
;
244 /* This is "inferior_wait_port_set" when not single stepping, and
245 * "singlestepped_thread_port" when we are single stepping.
247 * This is protected by a cleanup function: discard_single_step()
249 mach_port_t currently_waiting_for
= MACH_PORT_NULL
;
251 /* A port for external messages to gdb.
252 * External in the meaning that they do not come
253 * from the inferior_task, but rather from external
256 * As a debugging feature:
257 * A debugger debugging another debugger can stop the
258 * inferior debugger by the following command sequence
259 * (without running external programs)
261 * (top-gdb) set stop_inferior_gdb ()
264 mach_port_t our_message_port
= MACH_PORT_NULL
;
266 /* For single stepping */
267 mach_port_t thread_exception_port
= MACH_PORT_NULL
;
268 mach_port_t thread_saved_exception_port
= MACH_PORT_NULL
;
269 mach_port_t singlestepped_thread_port
= MACH_PORT_NULL
;
271 /* For machid calls */
272 mach_port_t mid_server
= MACH_PORT_NULL
;
273 mach_port_t mid_auth
= MACH_PORT_NULL
;
275 /* If gdb thinks the inferior task is not suspended, it
276 * must take suspend/abort the threads when it reads the state.
278 int must_suspend_thread
= 0;
280 /* When single stepping, we switch the port that mach_really_wait() listens to.
281 * This cleanup is a guard to prevent the port set from being left to
282 * the singlestepped_thread_port when error() is called.
283 * This is nonzero only when we are single stepping.
285 #define NULL_CLEANUP (struct cleanup *)0
286 struct cleanup
*cleanup_step
= NULL_CLEANUP
;
289 static struct target_ops m3_ops
;
291 static void m3_kill_inferior ();
294 #define MACH_TYPE_EXCEPTION_PORT -1
297 /* Chain of ports to remember requested notifications. */
301 struct port_chain
*next
;
304 int mid
; /* Now only valid with MACH_TYPE_THREAD and */
305 /* MACH_TYPE_THREAD */
307 typedef struct port_chain
*port_chain_t
;
309 /* Room for chain nodes comes from pchain_obstack */
310 struct obstack pchain_obstack
;
311 struct obstack
*port_chain_obstack
= &pchain_obstack
;
313 /* For thread handling */
314 struct obstack Cproc_obstack
;
315 struct obstack
*cproc_obstack
= &Cproc_obstack
;
317 /* the list of notified ports */
318 port_chain_t notify_chain
= (port_chain_t
) NULL
;
321 port_chain_insert (port_chain_t list
, mach_port_t name
, int type
)
327 if (!MACH_PORT_VALID (name
))
330 if (type
== MACH_TYPE_TASK
|| type
== MACH_TYPE_THREAD
)
332 if (!MACH_PORT_VALID (mid_server
))
334 warning ("Machid server port invalid, can not map port 0x%x to MID",
340 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
342 if (ret
!= KERN_SUCCESS
)
344 warning ("Can not map name (0x%x) to MID with machid", name
);
350 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
352 new = (port_chain_t
) obstack_alloc (port_chain_obstack
,
353 sizeof (struct port_chain
));
363 port_chain_delete (port_chain_t list
, mach_port_t elem
)
366 if (list
->port
== elem
)
371 if (list
->next
->port
== elem
)
372 list
->next
= list
->next
->next
; /* GCd with obstack_free() */
380 port_chain_destroy (struct obstack
*ostack
)
382 obstack_free (ostack
, 0);
383 obstack_init (ostack
);
387 port_chain_member (port_chain_t list
, mach_port_t elem
)
391 if (list
->port
== elem
)
395 return (port_chain_t
) NULL
;
399 map_port_name_to_mid (mach_port_t name
, int type
)
403 if (!MACH_PORT_VALID (name
))
406 elem
= port_chain_member (notify_chain
, name
);
408 if (elem
&& (elem
->type
== type
))
414 if (!MACH_PORT_VALID (mid_server
))
416 warning ("Machid server port invalid, can not map port 0x%x to mid",
425 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
427 if (ret
!= KERN_SUCCESS
)
429 warning ("Can not map name (0x%x) to mid with machid", name
);
436 /* Guard for currently_waiting_for and singlestepped_thread_port */
438 discard_single_step (thread_t thread
)
440 currently_waiting_for
= inferior_wait_port_set
;
442 cleanup_step
= NULL_CLEANUP
;
443 if (MACH_PORT_VALID (thread
) && MACH_PORT_VALID (singlestepped_thread_port
))
444 setup_single_step (thread
, FALSE
);
447 setup_single_step (thread_t thread
, boolean_t start_step
)
451 if (!MACH_PORT_VALID (thread
))
452 error ("Invalid thread supplied to setup_single_step");
457 /* Get the current thread exception port */
458 ret
= thread_get_exception_port (thread
, &teport
);
459 CHK ("Getting thread's exception port", ret
);
463 if (MACH_PORT_VALID (singlestepped_thread_port
))
465 warning ("Singlestepped_thread_port (0x%x) is still valid?",
466 singlestepped_thread_port
);
467 singlestepped_thread_port
= MACH_PORT_NULL
;
470 /* If we are already stepping this thread */
471 if (MACH_PORT_VALID (teport
) && teport
== thread_exception_port
)
473 ret
= mach_port_deallocate (mach_task_self (), teport
);
474 CHK ("Could not deallocate thread exception port", ret
);
478 ret
= thread_set_exception_port (thread
, thread_exception_port
);
479 CHK ("Setting exception port for thread", ret
);
481 /* Insert thread exception port to wait port set */
482 ret
= mach_port_move_member (mach_task_self (),
483 thread_exception_port
,
484 inferior_wait_port_set
);
485 CHK ("Moving thread exception port to inferior_wait_port_set",
488 thread_saved_exception_port
= teport
;
491 thread_trace (thread
, TRUE
);
493 singlestepped_thread_port
= thread_exception_port
;
494 currently_waiting_for
= singlestepped_thread_port
;
495 cleanup_step
= make_cleanup (discard_single_step
, thread
);
499 if (!MACH_PORT_VALID (teport
))
500 error ("Single stepped thread had an invalid exception port?");
502 if (teport
!= thread_exception_port
)
503 error ("Single stepped thread had an unknown exception port?");
505 ret
= mach_port_deallocate (mach_task_self (), teport
);
506 CHK ("Couldn't deallocate thread exception port", ret
);
508 /* Remove thread exception port from wait port set */
509 ret
= mach_port_move_member (mach_task_self (),
510 thread_exception_port
,
512 CHK ("Removing thread exception port from inferior_wait_port_set",
515 /* Restore thread's old exception port */
516 ret
= thread_set_exception_port (thread
,
517 thread_saved_exception_port
);
518 CHK ("Restoring stepped thread's exception port", ret
);
520 if (MACH_PORT_VALID (thread_saved_exception_port
))
521 (void) mach_port_deallocate (mach_task_self (),
522 thread_saved_exception_port
);
524 thread_trace (thread
, FALSE
);
526 singlestepped_thread_port
= MACH_PORT_NULL
;
527 currently_waiting_for
= inferior_wait_port_set
;
529 discard_cleanups (cleanup_step
);
535 request_notify (mach_port_t name
, mach_msg_id_t variant
, int type
)
538 mach_port_t previous_port_dummy
= MACH_PORT_NULL
;
540 if (!MACH_PORT_VALID (name
))
543 if (port_chain_member (notify_chain
, name
))
546 ret
= mach_port_request_notification (mach_task_self (),
551 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
552 &previous_port_dummy
);
553 CHK ("Serious: request_notify failed", ret
);
555 (void) mach_port_deallocate (mach_task_self (),
556 previous_port_dummy
);
558 notify_chain
= port_chain_insert (notify_chain
, name
, type
);
561 reverse_msg_bits (mach_msg_header_t
*msgp
, int type
)
564 rbits
= MACH_MSGH_BITS_REMOTE (msgp
->msgh_bits
);
567 (msgp
->msgh_bits
& ~MACH_MSGH_BITS_PORTS_MASK
) |
568 MACH_MSGH_BITS (lbits
, rbits
);
571 /* On the third day He said:
574 and then it was global.
576 When creating the inferior fork, the
577 child code in inflow.c sets the name of the
578 bootstrap_port in its address space to this
581 The name is transferred to our address space
582 with mach3_read_inferior().
584 Thou shalt not do this with
585 task_get_bootstrap_port() in this task, since
586 the name in the inferior task is different than
589 For blessed are the meek, as they shall inherit
592 mach_port_t original_server_port_name
= MACH_PORT_NULL
;
595 /* Called from inferior after FORK but before EXEC */
601 /* Get the NAME of the bootstrap port in this task
602 so that GDB can read it */
603 ret
= task_get_bootstrap_port (mach_task_self (),
604 &original_server_port_name
);
605 if (ret
!= KERN_SUCCESS
)
606 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
607 ret
= mach_port_deallocate (mach_task_self (),
608 original_server_port_name
);
609 if (ret
!= KERN_SUCCESS
)
610 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
612 /* Suspend this task to let the parent change my ports.
613 Resumed by the debugger */
614 ret
= task_suspend (mach_task_self ());
615 if (ret
!= KERN_SUCCESS
)
616 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
620 * Intercept system calls to Unix server.
621 * After EXEC_COUNTER calls to exec(), return.
623 * Pre-assertion: Child is suspended. (Not verified)
624 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
628 intercept_exec_calls (int exec_counter
)
630 int terminal_initted
= 0;
634 mach_msg_header_t header
;
635 mach_msg_type_t type
;
636 char room
[2000]; /* Enuff space */
639 struct syscall_msg_t syscall_in
, syscall_out
;
641 mach_port_t fake_server
;
642 mach_port_t original_server_send
;
643 mach_port_t original_exec_reply
;
644 mach_port_t exec_reply
;
645 mach_port_t exec_reply_send
;
646 mach_msg_type_name_t acquired
;
647 mach_port_t emulator_server_port_name
;
648 struct task_basic_info info
;
649 mach_msg_type_number_t info_count
;
653 if (exec_counter
<= 0)
654 return; /* We are already set up in the correct program */
656 ret
= mach_port_allocate (mach_task_self (),
657 MACH_PORT_RIGHT_RECEIVE
,
659 CHK ("create inferior_fake_server port failed", ret
);
661 /* Wait for inferior_task to suspend itself */
664 info_count
= sizeof (info
);
665 ret
= task_info (inferior_task
,
667 (task_info_t
) & info
,
669 CHK ("Task info", ret
);
671 if (info
.suspend_count
)
674 /* Note that the definition of the parameter was undefined
675 * at the time of this writing, so I just use an `ad hoc' value.
677 (void) swtch_pri (42); /* Universal Priority Value */
680 /* Read the inferior's bootstrap port name */
681 if (!mach3_read_inferior (&original_server_port_name
,
682 &original_server_port_name
,
683 sizeof (original_server_port_name
)))
684 error ("Can't read inferior task bootstrap port name");
686 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
687 /* Should get refs, and set them back when restoring */
688 /* Steal the original bsd server send right from inferior */
689 ret
= mach_port_extract_right (inferior_task
,
690 original_server_port_name
,
691 MACH_MSG_TYPE_MOVE_SEND
,
692 &original_server_send
,
694 CHK ("mach_port_extract_right (bsd server send)", ret
);
696 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
697 error ("Incorrect right extracted, send right to bsd server expected");
699 ret
= mach_port_insert_right (inferior_task
,
700 original_server_port_name
,
702 MACH_MSG_TYPE_MAKE_SEND
);
703 CHK ("mach_port_insert_right (fake server send)", ret
);
705 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
707 original_server_port_name
, original_server_send
);
709 /* A receive right to the reply generated by unix server exec() request */
710 ret
= mach_port_allocate (mach_task_self (),
711 MACH_PORT_RIGHT_RECEIVE
,
713 CHK ("create intercepted_reply_port port failed", ret
);
715 /* Pass this send right to Unix server so it replies to us after exec() */
716 ret
= mach_port_extract_right (mach_task_self (),
718 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
721 CHK ("mach_port_extract_right (exec_reply)", ret
);
723 if (acquired
!= MACH_MSG_TYPE_PORT_SEND_ONCE
)
724 error ("Incorrect right extracted, send once expected for exec reply");
726 ret
= mach_port_move_member (mach_task_self (),
728 inferior_wait_port_set
);
729 CHK ("Moving fake syscall port to inferior_wait_port_set", ret
);
731 xx_debug ("syscall fake server set up, resuming inferior\n");
733 ret
= task_resume (inferior_task
);
734 CHK ("task_resume (startup)", ret
);
736 /* Read requests from the inferior.
737 Pass directly through everything else except exec() calls.
739 while (exec_counter
> 0)
741 ret
= mach_msg (&syscall_in
.header
, /* header */
742 MACH_RCV_MSG
, /* options */
744 sizeof (struct syscall_msg_t
), /* receive size */
745 inferior_wait_port_set
, /* receive_name */
746 MACH_MSG_TIMEOUT_NONE
,
748 CHK ("mach_msg (intercepted sycall)", ret
);
751 print_msg (&syscall_in
.header
);
754 /* ASSERT : msgh_local_port == fake_server */
756 if (notify_server (&syscall_in
.header
, &syscall_out
.header
))
757 error ("received a notify while intercepting syscalls");
759 if (syscall_in
.header
.msgh_id
== MIG_EXEC_SYSCALL_ID
)
761 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter
);
762 if (exec_counter
== 1)
764 original_exec_reply
= syscall_in
.header
.msgh_remote_port
;
765 syscall_in
.header
.msgh_remote_port
= exec_reply_send
;
768 if (!terminal_initted
)
770 /* Now that the child has exec'd we know it has already set its
771 process group. On POSIX systems, tcsetpgrp will fail with
772 EPERM if we try it before the child's setpgid. */
774 /* Set up the "saved terminal modes" of the inferior
775 based on what modes we are starting it with. */
776 target_terminal_init ();
778 /* Install inferior's terminal modes. */
779 target_terminal_inferior ();
781 terminal_initted
= 1;
787 syscall_in
.header
.msgh_local_port
= syscall_in
.header
.msgh_remote_port
;
788 syscall_in
.header
.msgh_remote_port
= original_server_send
;
790 reverse_msg_bits (&syscall_in
.header
, MACH_MSG_TYPE_COPY_SEND
);
792 ret
= mach_msg_send (&syscall_in
.header
);
793 CHK ("Forwarded syscall", ret
);
796 ret
= mach_port_move_member (mach_task_self (),
799 CHK ("Moving fake syscall out of inferior_wait_port_set", ret
);
801 ret
= mach_port_move_member (mach_task_self (),
803 inferior_wait_port_set
);
804 CHK ("Moving exec_reply to inferior_wait_port_set", ret
);
806 ret
= mach_msg (&syscall_in
.header
, /* header */
807 MACH_RCV_MSG
, /* options */
809 sizeof (struct syscall_msg_t
), /* receive size */
810 inferior_wait_port_set
, /* receive_name */
811 MACH_MSG_TIMEOUT_NONE
,
813 CHK ("mach_msg (exec reply)", ret
);
815 ret
= task_suspend (inferior_task
);
816 CHK ("Suspending inferior after last exec", ret
);
818 must_suspend_thread
= 0;
820 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
823 print_msg (&syscall_in
.header
);
826 /* Message should appear as if it came from the unix server */
827 syscall_in
.header
.msgh_local_port
= MACH_PORT_NULL
;
829 /* and go to the inferior task original reply port */
830 syscall_in
.header
.msgh_remote_port
= original_exec_reply
;
832 reverse_msg_bits (&syscall_in
.header
, MACH_MSG_TYPE_MOVE_SEND_ONCE
);
834 ret
= mach_msg_send (&syscall_in
.header
);
835 CHK ("Forwarding exec reply to inferior", ret
);
837 /* Garbage collect */
838 ret
= mach_port_deallocate (inferior_task
,
839 original_server_port_name
);
840 CHK ("deallocating fake server send right", ret
);
842 ret
= mach_port_insert_right (inferior_task
,
843 original_server_port_name
,
844 original_server_send
,
845 MACH_MSG_TYPE_MOVE_SEND
);
846 CHK ("Restoring the original bsd server send right", ret
);
848 ret
= mach_port_destroy (mach_task_self (),
850 fake_server
= MACH_PORT_DEAD
;
851 CHK ("mach_port_destroy (fake_server)", ret
);
853 ret
= mach_port_destroy (mach_task_self (),
855 exec_reply
= MACH_PORT_DEAD
;
856 CHK ("mach_port_destroy (exec_reply)", ret
);
858 xx_debug ("Done with exec call interception\n");
862 consume_send_rights (thread_array_t thread_list
, int thread_count
)
869 for (index
= 0; index
< thread_count
; index
++)
871 /* Since thread kill command kills threads, don't check ret */
872 (void) mach_port_deallocate (mach_task_self (),
877 /* suspend/abort/resume a thread. */
878 setup_thread (mach_port_t thread
, int what
)
884 ret
= thread_suspend (thread
);
885 CHK ("setup_thread thread_suspend", ret
);
887 ret
= thread_abort (thread
);
888 CHK ("setup_thread thread_abort", ret
);
892 ret
= thread_resume (thread
);
893 CHK ("setup_thread thread_resume", ret
);
898 map_slot_to_mid (int slot
, thread_array_t threads
, int thread_count
)
908 ret
= task_threads (inferior_task
, &threads
, &thread_count
);
909 CHK ("Can not select a thread from a dead task", ret
);
912 if (slot
< 0 || slot
>= thread_count
)
916 consume_send_rights (threads
, thread_count
);
917 (void) vm_deallocate (mach_task_self (), (vm_address_t
) threads
,
918 (thread_count
* sizeof (mach_port_t
)));
921 error ("invalid slot number");
926 mid
= map_port_name_to_mid (threads
[slot
], MACH_TYPE_THREAD
);
930 consume_send_rights (threads
, thread_count
);
931 (void) vm_deallocate (mach_task_self (), (vm_address_t
) threads
,
932 (thread_count
* sizeof (mach_port_t
)));
939 parse_thread_id (char *arg
, int thread_count
, int slots
)
949 while (*arg
&& (*arg
== ' ' || *arg
== '\t'))
955 /* Currently parse MID and @SLOTNUMBER */
960 error ("valid thread mid expected");
968 error ("invalid slot number");
970 /* If you want slot numbers to remain slot numbers, set slots.
972 * Well, since 0 is reserved, return the ordinal number
973 * of the thread rather than the slot number. Awk, this
974 * counts as a kludge.
979 if (thread_count
&& slot
>= thread_count
)
982 mid
= map_slot_to_mid (slot
);
987 /* THREAD_ID 0 is special; it selects the first kernel
988 * thread from the list (i.e. SLOTNUMBER 0)
989 * This is used when starting the program with 'run' or when attaching.
991 * If FLAG is 0 the context is not changed, and the registers, frame, etc
992 * will continue to describe the old thread.
994 * If FLAG is nonzero, really select the thread.
995 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
999 select_thread (mach_port_t task
, int thread_id
, int flag
)
1001 thread_array_t thread_list
;
1005 thread_t new_thread
= MACH_PORT_NULL
;
1008 error ("Can't select cprocs without kernel thread");
1010 ret
= task_threads (task
, &thread_list
, &thread_count
);
1011 if (ret
!= KERN_SUCCESS
)
1013 warning ("Can not select a thread from a dead task");
1014 m3_kill_inferior ();
1015 return KERN_FAILURE
;
1018 if (thread_count
== 0)
1020 /* The task can not do anything anymore, but it still
1021 * exists as a container for memory and ports.
1023 registers_changed ();
1024 warning ("Task %d has no threads",
1025 map_port_name_to_mid (task
, MACH_TYPE_TASK
));
1026 current_thread
= MACH_PORT_NULL
;
1027 (void) vm_deallocate (mach_task_self (),
1028 (vm_address_t
) thread_list
,
1029 (thread_count
* sizeof (mach_port_t
)));
1030 return KERN_FAILURE
;
1033 if (!thread_id
|| flag
== 2)
1035 /* First thread or a slotnumber */
1037 new_thread
= thread_list
[0];
1040 if (thread_id
< thread_count
)
1041 new_thread
= thread_list
[thread_id
];
1044 (void) vm_deallocate (mach_task_self (),
1045 (vm_address_t
) thread_list
,
1046 (thread_count
* sizeof (mach_port_t
)));
1047 error ("No such thread slot number : %d", thread_id
);
1053 for (index
= 0; index
< thread_count
; index
++)
1054 if (thread_id
== map_port_name_to_mid (thread_list
[index
],
1057 new_thread
= thread_list
[index
];
1063 error ("No thread with mid %d", thread_id
);
1066 /* Notify when the selected thread dies */
1067 request_notify (new_thread
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_THREAD
);
1069 ret
= vm_deallocate (mach_task_self (),
1070 (vm_address_t
) thread_list
,
1071 (thread_count
* sizeof (mach_port_t
)));
1072 CHK ("vm_deallocate", ret
);
1075 current_thread
= new_thread
;
1079 if (MACH_PORT_VALID (current_thread
))
1081 /* Store the gdb's view of the thread we are deselecting
1083 * @@ I think gdb updates registers immediately when they are
1084 * changed, so don't do this.
1086 ret
= thread_abort (current_thread
);
1087 CHK ("Could not abort system calls when saving state of old thread",
1089 target_prepare_to_store ();
1090 target_store_registers (-1);
1094 registers_changed ();
1096 current_thread
= new_thread
;
1098 ret
= thread_abort (current_thread
);
1099 CHK ("Could not abort system calls when selecting a thread", ret
);
1101 stop_pc
= read_pc ();
1102 flush_cached_frames ();
1104 select_frame (get_current_frame (), 0);
1107 return KERN_SUCCESS
;
1111 * Switch to use thread named NEW_THREAD.
1115 switch_to_thread (thread_t new_thread
)
1117 thread_t saved_thread
= current_thread
;
1120 mid
= map_port_name_to_mid (new_thread
,
1123 warning ("Can't map thread name 0x%x to mid", new_thread
);
1124 else if (select_thread (inferior_task
, mid
, 1) != KERN_SUCCESS
)
1127 current_thread
= saved_thread
;
1128 error ("Could not select thread %d", mid
);
1134 /* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1135 * Note that the registers are not yet valid in the inferior task.
1138 m3_trace_him (int pid
)
1142 push_target (&m3_ops
);
1144 inferior_task
= task_by_pid (pid
);
1146 if (!MACH_PORT_VALID (inferior_task
))
1147 error ("Can not map Unix pid %d to Mach task", pid
);
1149 /* Clean up previous notifications and create new ones */
1150 setup_notify_port (1);
1152 /* When notification appears, the inferior task has died */
1153 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
1155 emulator_present
= have_emulator_p (inferior_task
);
1157 /* By default, select the first thread,
1158 * If task has no threads, gives a warning
1159 * Does not fetch registers, since they are not yet valid.
1161 select_thread (inferior_task
, 0, 0);
1163 inferior_exception_port
= MACH_PORT_NULL
;
1165 setup_exception_port ();
1167 xx_debug ("Now the debugged task is created\n");
1169 /* One trap to exec the shell, one to exec the program being debugged. */
1170 intercept_exec_calls (2);
1175 setup_exception_port (void)
1179 ret
= mach_port_allocate (mach_task_self (),
1180 MACH_PORT_RIGHT_RECEIVE
,
1181 &inferior_exception_port
);
1182 CHK ("mach_port_allocate", ret
);
1184 /* add send right */
1185 ret
= mach_port_insert_right (mach_task_self (),
1186 inferior_exception_port
,
1187 inferior_exception_port
,
1188 MACH_MSG_TYPE_MAKE_SEND
);
1189 CHK ("mach_port_insert_right", ret
);
1191 ret
= mach_port_move_member (mach_task_self (),
1192 inferior_exception_port
,
1193 inferior_wait_port_set
);
1194 CHK ("mach_port_move_member", ret
);
1196 ret
= task_get_special_port (inferior_task
,
1197 TASK_EXCEPTION_PORT
,
1198 &inferior_old_exception_port
);
1199 CHK ("task_get_special_port(old exc)", ret
);
1201 ret
= task_set_special_port (inferior_task
,
1202 TASK_EXCEPTION_PORT
,
1203 inferior_exception_port
);
1204 CHK ("task_set_special_port", ret
);
1206 ret
= mach_port_deallocate (mach_task_self (),
1207 inferior_exception_port
);
1208 CHK ("mack_port_deallocate", ret
);
1211 /* When notify appears, the inferior_task's exception
1212 * port has been destroyed.
1214 * Not used, since the dead_name_notification already
1215 * appears when task dies.
1218 request_notify (inferior_exception_port
,
1219 MACH_NOTIFY_NO_SENDERS
,
1220 MACH_TYPE_EXCEPTION_PORT
);
1224 /* Nonzero if gdb is waiting for a message */
1225 int mach_really_waiting
;
1227 /* Wait for the inferior to stop for some reason.
1228 - Loop on notifications until inferior_task dies.
1229 - Loop on exceptions until stopped_in_exception comes true.
1230 (e.g. we receive a single step trace trap)
1231 - a message arrives to gdb's message port
1233 There is no other way to exit this loop.
1235 Returns the inferior_ptid for rest of gdb.
1236 Side effects: Set *OURSTATUS. */
1238 mach_really_wait (ptid_t ptid
, struct target_waitstatus
*ourstatus
)
1245 mach_msg_header_t header
;
1246 mach_msg_type_t foo
;
1251 /* Either notify (death), exception or message can stop the inferior */
1252 stopped_in_exception
= FALSE
;
1258 stop_exception
= stop_code
= stop_subcode
= -1;
1259 stop_thread
= MACH_PORT_NULL
;
1261 mach_really_waiting
= 1;
1262 ret
= mach_msg (&in_msg
.header
, /* header */
1263 MACH_RCV_MSG
, /* options */
1265 sizeof (struct msg
), /* receive size */
1266 currently_waiting_for
, /* receive name */
1267 MACH_MSG_TIMEOUT_NONE
,
1269 mach_really_waiting
= 0;
1270 CHK ("mach_msg (receive)", ret
);
1272 /* Check if we received a notify of the childs' death */
1273 if (notify_server (&in_msg
.header
, &out_msg
.header
))
1275 /* If inferior_task is null then the inferior has
1276 gone away and we want to return to command level.
1277 Otherwise it was just an informative message and we
1278 need to look to see if there are any more. */
1279 if (inferior_task
!= MACH_PORT_NULL
)
1283 /* Collect Unix exit status for gdb */
1285 wait3 (&w
, WNOHANG
, 0);
1287 /* This mess is here to check that the rest of
1288 * gdb knows that the inferior died. It also
1289 * tries to hack around the fact that Mach 3.0 (mk69)
1290 * unix server (ux28) does not always know what
1291 * has happened to it's children when mach-magic
1292 * is applied on them.
1294 if ((!WIFEXITED (w
) && WIFSTOPPED (w
)) ||
1295 (WIFEXITED (w
) && WEXITSTATUS (w
) > 0377))
1298 warning ("Using exit value 0 for terminated task");
1300 else if (!WIFEXITED (w
))
1302 int sig
= WTERMSIG (w
);
1304 /* Signals cause problems. Warn the user. */
1305 if (sig
!= SIGKILL
) /* Bad luck if garbage matches this */
1306 warning ("The terminating signal stuff may be nonsense");
1307 else if (sig
> NSIG
)
1310 warning ("Using exit value 0 for terminated task");
1313 store_waitstatus (ourstatus
, w
);
1314 return inferior_ptid
;
1318 /* Hmm. Check for exception, as it was not a notification.
1319 exc_server() does an upcall to catch_exception_raise()
1320 if this rpc is an exception. Further actions are decided
1323 if (!exc_server (&in_msg
.header
, &out_msg
.header
))
1326 /* Not an exception, check for message.
1328 * Messages don't come from the inferior, or if they
1329 * do they better be asynchronous or it will hang.
1331 if (gdb_message_server (&in_msg
.header
))
1334 error ("Unrecognized message received in mach_really_wait");
1337 /* Send the reply of the exception rpc to the suspended task */
1338 ret
= mach_msg_send (&out_msg
.header
);
1339 CHK ("mach_msg_send (exc reply)", ret
);
1341 if (stopped_in_exception
)
1343 /* Get unix state. May be changed in mach3_exception_actions() */
1344 wait3 (&w
, WNOHANG
, 0);
1346 mach3_exception_actions (&w
, FALSE
, "Task");
1348 store_waitstatus (ourstatus
, w
);
1349 return inferior_ptid
;
1354 /* Called by macro DO_QUIT() in utils.c(quit).
1355 * This is called just before calling error() to return to command level
1363 if (mach_really_waiting
)
1365 ret
= task_suspend (inferior_task
);
1367 if (ret
!= KERN_SUCCESS
)
1369 warning ("Could not suspend task for interrupt: %s",
1370 mach_error_string (ret
));
1371 mach_really_waiting
= 0;
1376 must_suspend_thread
= 0;
1377 mach_really_waiting
= 0;
1379 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1382 warning ("Selecting first existing kernel thread");
1386 current_thread
= MACH_PORT_NULL
; /* Force setup */
1387 select_thread (inferior_task
, mid
, 1);
1393 /* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
1395 /* If ^C is typed when we are waiting for a message
1396 * and your Unix server is able to notice that we
1399 * Called by REQUEST_QUIT() from utils.c(request_quit)
1402 mach3_request_quit (void)
1404 if (mach_really_waiting
)
1410 * Gdb message server.
1411 * Currently implemented is the STOP message, that causes
1412 * gdb to return to the command level like ^C had been typed from terminal.
1415 gdb_message_server (mach_msg_header_t
*InP
)
1420 if (InP
->msgh_local_port
== our_message_port
)
1422 /* A message coming to our_message_port. Check validity */
1423 switch (InP
->msgh_id
)
1426 case GDB_MESSAGE_ID_STOP
:
1427 ret
= task_suspend (inferior_task
);
1428 if (ret
!= KERN_SUCCESS
)
1429 warning ("Could not suspend task for stop message: %s",
1430 mach_error_string (ret
));
1432 /* QUIT in mach_really_wait() loop. */
1437 warning ("Invalid message id %d received, ignored.",
1445 /* Message not handled by this server */
1449 /* NOTE: This is not an RPC call. It is a simpleroutine.
1451 * This is not called from this gdb code.
1453 * It may be called by another debugger to cause this
1454 * debugger to enter command level:
1456 * (gdb) set stop_inferior_gdb ()
1459 * External program "stop-gdb" implements this also.
1462 stop_inferior_gdb (void)
1466 /* Code generated by mig, with minor cleanups :-)
1468 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1473 mach_msg_header_t Head
;
1479 register Request
*InP
= &Mess
;
1481 InP
->Head
.msgh_bits
= MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND
, 0);
1483 /* msgh_size passed as argument */
1484 InP
->Head
.msgh_remote_port
= our_message_port
;
1485 InP
->Head
.msgh_local_port
= MACH_PORT_NULL
;
1486 InP
->Head
.msgh_seqno
= 0;
1487 InP
->Head
.msgh_id
= GDB_MESSAGE_ID_STOP
;
1489 ret
= mach_msg (&InP
->Head
,
1490 MACH_SEND_MSG
| MACH_MSG_OPTION_NONE
,
1494 MACH_MSG_TIMEOUT_NONE
,
1498 #ifdef THREAD_ALLOWED_TO_BREAK
1500 * Return 1 if the MID specifies the thread that caused the
1502 * Since catch_exception_raise() selects the thread causing
1503 * the last exception to current_thread, we just check that
1504 * it is selected and the last exception was a breakpoint.
1507 mach_thread_for_breakpoint (int mid
)
1509 int cmid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1513 mid
= map_slot_to_mid (-(mid
+ 1), 0, 0);
1515 return 0; /* Don't stop, no such slot */
1518 if (!mid
|| cmid
== -1)
1519 return 1; /* stop */
1521 return cmid
== mid
&& stop_exception
== EXC_BREAKPOINT
;
1523 #endif /* THREAD_ALLOWED_TO_BREAK */
1525 #ifdef THREAD_PARSE_ID
1527 * Map a thread id string (MID or a @SLOTNUMBER)
1530 * 0 matches all threads.
1531 * Otherwise the meaning is defined only in this file.
1532 * (mach_thread_for_breakpoint uses it)
1534 * @@ This allows non-existent MIDs to be specified.
1535 * It now also allows non-existent slots to be
1536 * specified. (Slot numbers stored are negative,
1537 * and the magnitude is one greater than the actual
1538 * slot index. (Since 0 is reserved))
1541 mach_thread_parse_id (char *arg
)
1545 error ("thread id expected");
1546 mid
= parse_thread_id (arg
, 0, 1);
1550 #endif /* THREAD_PARSE_ID */
1552 #ifdef THREAD_OUTPUT_ID
1554 mach_thread_output_id (int mid
)
1556 static char foobar
[20];
1559 sprintf (foobar
, "mid %d", mid
);
1561 sprintf (foobar
, "@%d", -(mid
+ 1));
1563 sprintf (foobar
, "*any thread*");
1567 #endif /* THREAD_OUTPUT_ID */
1569 /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
1571 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1573 * if SELECT_IT is nonzero, reselect the thread that was active when
1574 * we stopped at a breakpoint.
1576 * Note that this implementation is potentially redundant now that
1577 * default_prepare_to_proceed() has been added.
1579 * FIXME This may not support switching threads after Ctrl-C
1580 * correctly. The default implementation does support this.
1583 mach3_prepare_to_proceed (int select_it
)
1586 stop_thread
!= current_thread
&&
1587 stop_exception
== EXC_BREAKPOINT
)
1594 mid
= switch_to_thread (stop_thread
);
1602 /* this stuff here is an upcall via libmach/excServer.c
1603 and mach_really_wait which does the actual upcall.
1605 The code will pass the exception to the inferior if:
1607 - The task that signaled is not the inferior task
1608 (e.g. when debugging another debugger)
1610 - The user has explicitely requested to pass on the exceptions.
1611 (e.g to the default unix exception handler, which maps
1612 exceptions to signals, or the user has her own exception handler)
1614 - If the thread that signaled is being single-stepped and it
1615 has set it's own exception port and the exception is not
1616 EXC_BREAKPOINT. (Maybe this is not desirable?)
1620 catch_exception_raise (mach_port_t port
, thread_t thread
, task_t task
,
1621 int exception
, int code
, int subcode
)
1624 boolean_t signal_thread
;
1625 int mid
= map_port_name_to_mid (thread
, MACH_TYPE_THREAD
);
1627 if (!MACH_PORT_VALID (thread
))
1629 /* If the exception was sent and thread dies before we
1630 receive it, THREAD will be MACH_PORT_DEAD
1633 current_thread
= thread
= MACH_PORT_NULL
;
1634 error ("Received exception from nonexistent thread");
1637 /* Check if the task died in transit.
1638 * @@ Isn't the thread also invalid in such case?
1640 if (!MACH_PORT_VALID (task
))
1642 current_thread
= thread
= MACH_PORT_NULL
;
1643 error ("Received exception from nonexistent task");
1646 if (exception
< 0 || exception
> MAX_EXCEPTION
)
1647 internal_error (__FILE__
, __LINE__
,
1648 "catch_exception_raise: unknown exception code %d thread %d",
1652 if (!MACH_PORT_VALID (inferior_task
))
1653 error ("got an exception, but inferior_task is null or dead");
1655 stop_exception
= exception
;
1657 stop_subcode
= subcode
;
1658 stop_thread
= thread
;
1660 signal_thread
= exception
!= EXC_BREAKPOINT
&&
1661 port
== singlestepped_thread_port
&&
1662 MACH_PORT_VALID (thread_saved_exception_port
);
1664 /* If it was not our inferior or if we want to forward
1665 * the exception to the inferior's handler, do it here
1667 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1669 if (task
!= inferior_task
||
1671 exception_map
[exception
].forward
)
1673 mach_port_t eport
= inferior_old_exception_port
;
1678 GDB now forwards the exeption to thread's original handler,
1679 since the user propably knows what he is doing.
1680 Give a message, though.
1683 mach3_exception_actions ((WAITTYPE
*) NULL
, TRUE
, "Thread");
1684 eport
= thread_saved_exception_port
;
1687 /* Send the exception to the original handler */
1688 ret
= exception_raise (eport
,
1695 (void) mach_port_deallocate (mach_task_self (), task
);
1696 (void) mach_port_deallocate (mach_task_self (), thread
);
1698 /* If we come here, we don't want to trace any more, since we
1699 * will never stop for tracing anyway.
1701 discard_single_step (thread
);
1703 /* Do not stop the inferior */
1707 /* Now gdb handles the exception */
1708 stopped_in_exception
= TRUE
;
1710 ret
= task_suspend (task
);
1711 CHK ("Error suspending inferior after exception", ret
);
1713 must_suspend_thread
= 0;
1715 if (current_thread
!= thread
)
1717 if (MACH_PORT_VALID (singlestepped_thread_port
))
1718 /* Cleanup discards single stepping */
1719 error ("Exception from thread %d while singlestepping thread %d",
1721 map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
));
1723 /* Then select the thread that caused the exception */
1724 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
1725 error ("Could not select thread %d causing exception", mid
);
1727 warning ("Gdb selected thread %d", mid
);
1730 /* If we receive an exception that is not breakpoint
1731 * exception, we interrupt the single step and return to
1732 * debugger. Trace condition is cleared.
1734 if (MACH_PORT_VALID (singlestepped_thread_port
))
1736 if (stop_exception
!= EXC_BREAKPOINT
)
1737 warning ("Single step interrupted by exception");
1738 else if (port
== singlestepped_thread_port
)
1740 /* Single step exception occurred, remove trace bit
1741 * and return to gdb.
1743 if (!MACH_PORT_VALID (current_thread
))
1744 error ("Single stepped thread is not valid");
1746 /* Resume threads, but leave the task suspended */
1747 resume_all_threads (0);
1750 warning ("Breakpoint while single stepping?");
1752 discard_single_step (current_thread
);
1755 (void) mach_port_deallocate (mach_task_self (), task
);
1756 (void) mach_port_deallocate (mach_task_self (), thread
);
1758 return KERN_SUCCESS
;
1762 port_valid (mach_port_t port
, int mask
)
1765 mach_port_type_t type
;
1767 ret
= mach_port_type (mach_task_self (),
1770 if (ret
!= KERN_SUCCESS
|| (type
& mask
) != mask
)
1775 /* @@ No vm read cache implemented yet */
1776 boolean_t vm_read_cache_valid
= FALSE
;
1779 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1780 * in gdb's address space.
1782 * Return 0 on failure; number of bytes read otherwise.
1785 mach3_read_inferior (CORE_ADDR addr
, char *myaddr
, int length
)
1788 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1789 vm_size_t aligned_length
=
1790 (vm_size_t
) round_page (addr
+ length
) - low_address
;
1791 pointer_t copied_memory
;
1794 /* Get memory from inferior with page aligned addresses */
1795 ret
= vm_read (inferior_task
,
1800 if (ret
!= KERN_SUCCESS
)
1802 /* the problem is that the inferior might be killed for whatever reason
1803 * before we go to mach_really_wait. This is one place that ought to
1804 * catch many of those errors.
1805 * @@ A better fix would be to make all external events to GDB
1806 * to arrive via a SINGLE port set. (Including user input!)
1809 if (!port_valid (inferior_task
, MACH_PORT_TYPE_SEND
))
1811 m3_kill_inferior ();
1812 error ("Inferior killed (task port invalid)");
1818 /* valprint.c gives nicer format if this does not
1819 screw it. Eamonn seems to like this, so I enable
1820 it if OSF is defined...
1822 warning ("[read inferior %x failed: %s]",
1823 addr
, mach_error_string (ret
));
1830 memcpy (myaddr
, (char *) addr
- low_address
+ copied_memory
, length
);
1832 ret
= vm_deallocate (mach_task_self (),
1835 CHK ("mach3_read_inferior vm_deallocate failed", ret
);
1840 #define CHK_GOTO_OUT(str,ret) \
1841 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
1843 struct vm_region_list
1845 struct vm_region_list
*next
;
1846 vm_prot_t protection
;
1851 struct obstack region_obstack
;
1854 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1855 * in gdb's address space.
1858 mach3_write_inferior (CORE_ADDR addr
, char *myaddr
, int length
)
1861 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1862 vm_size_t aligned_length
=
1863 (vm_size_t
) round_page (addr
+ length
) - low_address
;
1864 pointer_t copied_memory
;
1868 char *errstr
= "Bug in mach3_write_inferior";
1870 struct vm_region_list
*region_element
;
1871 struct vm_region_list
*region_head
= (struct vm_region_list
*) NULL
;
1873 /* Get memory from inferior with page aligned addresses */
1874 ret
= vm_read (inferior_task
,
1879 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret
);
1883 memcpy ((char *) addr
- low_address
+ copied_memory
, myaddr
, length
);
1885 obstack_init (®ion_obstack
);
1887 /* Do writes atomically.
1888 * First check for holes and unwritable memory.
1891 vm_size_t remaining_length
= aligned_length
;
1892 vm_address_t region_address
= low_address
;
1894 struct vm_region_list
*scan
;
1896 while (region_address
< low_address
+ aligned_length
)
1898 vm_prot_t protection
;
1899 vm_prot_t max_protection
;
1900 vm_inherit_t inheritance
;
1902 mach_port_t object_name
;
1904 vm_size_t region_length
= remaining_length
;
1905 vm_address_t old_address
= region_address
;
1907 ret
= vm_region (inferior_task
,
1916 CHK_GOTO_OUT ("vm_region failed", ret
);
1918 /* Check for holes in memory */
1919 if (old_address
!= region_address
)
1921 warning ("No memory at 0x%x. Nothing written",
1928 if (!(max_protection
& VM_PROT_WRITE
))
1930 warning ("Memory at address 0x%x is unwritable. Nothing written",
1937 /* Chain the regions for later use */
1939 (struct vm_region_list
*)
1940 obstack_alloc (®ion_obstack
, sizeof (struct vm_region_list
));
1942 region_element
->protection
= protection
;
1943 region_element
->start
= region_address
;
1944 region_element
->length
= region_length
;
1946 /* Chain the regions along with protections */
1947 region_element
->next
= region_head
;
1948 region_head
= region_element
;
1950 region_address
+= region_length
;
1951 remaining_length
= remaining_length
- region_length
;
1954 /* If things fail after this, we give up.
1955 * Somebody is messing up inferior_task's mappings.
1958 /* Enable writes to the chained vm regions */
1959 for (scan
= region_head
; scan
; scan
= scan
->next
)
1961 boolean_t protection_changed
= FALSE
;
1963 if (!(scan
->protection
& VM_PROT_WRITE
))
1965 ret
= vm_protect (inferior_task
,
1969 scan
->protection
| VM_PROT_WRITE
);
1970 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1974 ret
= vm_write (inferior_task
,
1978 CHK_GOTO_OUT ("vm_write failed", ret
);
1980 /* Set up the original region protections, if they were changed */
1981 for (scan
= region_head
; scan
; scan
= scan
->next
)
1983 boolean_t protection_changed
= FALSE
;
1985 if (!(scan
->protection
& VM_PROT_WRITE
))
1987 ret
= vm_protect (inferior_task
,
1992 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
2000 obstack_free (®ion_obstack
, 0);
2002 (void) vm_deallocate (mach_task_self (),
2007 if (ret
!= KERN_SUCCESS
)
2009 warning ("%s %s", errstr
, mach_error_string (ret
));
2016 /* Return 0 on failure, number of bytes handled otherwise. TARGET is
2019 m3_xfer_memory (CORE_ADDR memaddr
, char *myaddr
, int len
, int write
,
2020 struct target_ops
*target
)
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 (mach_port_t task
, gdb_thread_t
*mthreads_out
)
2145 thread_array_t th_table
;
2147 gdb_thread_t mthreads
= NULL
;
2150 ret
= task_threads (task
, &th_table
, &th_count
);
2151 if (ret
!= KERN_SUCCESS
)
2153 warning ("Error getting inferior's thread list:%s",
2154 mach_error_string (ret
));
2155 m3_kill_inferior ();
2159 mthreads
= (gdb_thread_t
)
2162 th_count
* sizeof (struct gdb_thread
));
2164 for (index
= 0; index
< th_count
; index
++)
2166 thread_t saved_thread
= MACH_PORT_NULL
;
2169 if (must_suspend_thread
)
2170 setup_thread (th_table
[index
], 1);
2172 if (th_table
[index
] != current_thread
)
2174 saved_thread
= current_thread
;
2176 mid
= switch_to_thread (th_table
[index
]);
2179 mthreads
[index
].name
= th_table
[index
];
2180 mthreads
[index
].cproc
= NULL
; /* map_cprocs_to_kernel_threads() */
2181 mthreads
[index
].in_emulator
= FALSE
;
2182 mthreads
[index
].slotid
= index
;
2184 mthreads
[index
].sp
= read_register (SP_REGNUM
);
2185 mthreads
[index
].fp
= read_register (FP_REGNUM
);
2186 mthreads
[index
].pc
= read_pc ();
2188 if (MACH_PORT_VALID (saved_thread
))
2189 mid
= switch_to_thread (saved_thread
);
2191 if (must_suspend_thread
)
2192 setup_thread (th_table
[index
], 0);
2195 consume_send_rights (th_table
, th_count
);
2196 ret
= vm_deallocate (mach_task_self (), (vm_address_t
) th_table
,
2197 (th_count
* sizeof (mach_port_t
)));
2198 if (ret
!= KERN_SUCCESS
)
2200 warning ("Error trying to deallocate thread list : %s",
2201 mach_error_string (ret
));
2204 *mthreads_out
= mthreads
;
2211 * Current emulator always saves the USP on top of
2212 * emulator stack below struct emul_stack_top stuff.
2215 fetch_usp_from_emulator_stack (CORE_ADDR sp
)
2217 CORE_ADDR stack_pointer
;
2219 sp
= (sp
& ~(EMULATOR_STACK_SIZE
- 1)) +
2220 EMULATOR_STACK_SIZE
- sizeof (struct emul_stack_top
);
2222 if (mach3_read_inferior (sp
,
2224 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2226 warning ("Can't read user sp from emulator stack address 0x%x", sp
);
2230 return stack_pointer
;
2235 /* get_emulation_vector() interface was changed after mk67 */
2236 #define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2240 /* Check if the emulator exists at task's address space.
2243 have_emulator_p (task_t task
)
2246 #ifndef EMUL_VECTOR_COUNT
2247 vm_offset_t
*emulation_vector
;
2250 vm_offset_t emulation_vector
[EMUL_VECTOR_COUNT
];
2251 int n
= EMUL_VECTOR_COUNT
;
2256 ret
= task_get_emulation_vector (task
,
2258 #ifndef EMUL_VECTOR_COUNT
2264 CHK ("task_get_emulation_vector", ret
);
2265 xx_debug ("%d vectors from %d at 0x%08x\n",
2266 n
, vector_start
, emulation_vector
);
2268 for (i
= 0; i
< n
; i
++)
2270 vm_offset_t entry
= emulation_vector
[i
];
2272 if (EMULATOR_BASE
<= entry
&& entry
<= EMULATOR_END
)
2276 static boolean_t informed
= FALSE
;
2279 warning ("Emulation vector address 0x08%x outside emulator space",
2288 /* Map cprocs to kernel threads and vice versa. */
2291 map_cprocs_to_kernel_threads (gdb_thread_t cprocs
, gdb_thread_t mthreads
,
2296 boolean_t all_mapped
= TRUE
;
2300 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2302 /* Default to: no kernel thread for this cproc */
2303 scan
->reverse_map
= -1;
2305 /* Check if the cproc is found by its stack */
2306 for (index
= 0; index
< thread_count
; index
++)
2309 extract_signed_integer (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2312 extract_signed_integer (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2314 if ((mthreads
+ index
)->sp
> stack_base
&&
2315 (mthreads
+ index
)->sp
<= stack_base
+ stack_size
)
2317 (mthreads
+ index
)->cproc
= scan
;
2318 scan
->reverse_map
= index
;
2322 all_mapped
&= (scan
->reverse_map
!= -1);
2325 /* Check for threads that are currently in the emulator.
2326 * If so, they have a different stack, and the still unmapped
2327 * cprocs may well get mapped to these threads.
2330 * - cproc stack does not match any kernel thread stack pointer
2331 * - there is at least one extra kernel thread
2332 * that has no cproc mapped above.
2333 * - some kernel thread stack pointer points to emulator space
2334 * then we find the user stack pointer saved in the emulator
2335 * stack, and try to map that to the cprocs.
2337 * Also set in_emulator for kernel threads.
2340 if (emulator_present
)
2342 for (index
= 0; index
< thread_count
; index
++)
2347 gdb_thread_t mthread
= (mthreads
+ index
);
2348 emul_sp
= mthread
->sp
;
2350 if (mthread
->cproc
== NULL
&&
2351 EMULATOR_BASE
<= emul_sp
&& emul_sp
<= EMULATOR_END
)
2353 mthread
->in_emulator
= emulator_present
;
2355 if (!all_mapped
&& cprocs
)
2357 usp
= fetch_usp_from_emulator_stack (emul_sp
);
2359 /* @@ Could be more accurate */
2361 error ("Zero stack pointer read from emulator?");
2363 /* Try to match this stack pointer to the cprocs that
2364 * don't yet have a kernel thread.
2366 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2369 /* Check is this unmapped CPROC stack contains
2370 * the user stack pointer saved in the
2373 if (scan
->reverse_map
== -1)
2376 extract_signed_integer
2377 (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2380 extract_signed_integer
2381 (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2383 if (usp
> stack_base
&&
2384 usp
<= stack_base
+ stack_size
)
2386 mthread
->cproc
= scan
;
2387 scan
->reverse_map
= index
;
2399 * Format of the thread_list command
2401 * slot mid sel name emul ks susp cstate wired address
2403 #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2405 #define TL_HEADER "\n@ MID Name KState CState Where\n"
2408 print_tl_address (struct ui_file
*stream
, CORE_ADDR pc
)
2410 if (!lookup_minimal_symbol_by_pc (pc
))
2411 fprintf_filtered (stream
, local_hex_format (), pc
);
2414 extern int addressprint
;
2415 extern int asm_demangle
;
2417 int store
= addressprint
;
2419 print_address_symbolic (pc
, stream
, asm_demangle
, "");
2420 addressprint
= store
;
2424 /* For thread names, but also for gdb_message_port external name */
2425 #define MAX_NAME_LEN 50
2427 /* Returns the address of variable NAME or 0 if not found */
2429 lookup_address_of_variable (char *name
)
2432 CORE_ADDR symaddr
= 0;
2433 struct minimal_symbol
*msymbol
;
2435 sym
= lookup_symbol (name
,
2436 (struct block
*) NULL
,
2439 (struct symtab
**) NULL
);
2442 symaddr
= SYMBOL_VALUE (sym
);
2446 msymbol
= lookup_minimal_symbol (name
, NULL
, NULL
);
2448 if (msymbol
&& msymbol
->type
== mst_data
)
2449 symaddr
= SYMBOL_VALUE_ADDRESS (msymbol
);
2458 gdb_thread_t cproc_head
;
2459 gdb_thread_t cproc_copy
;
2460 CORE_ADDR their_cprocs
;
2466 buf
= alloca (TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2467 symaddr
= lookup_address_of_variable ("cproc_list");
2471 /* cproc_list is not in a file compiled with debugging
2472 symbols, but don't give up yet */
2474 symaddr
= lookup_address_of_variable ("cprocs");
2478 static int informed
= 0;
2482 warning ("Your program is loaded with an old threads library.");
2483 warning ("GDB does not know the old form of threads");
2484 warning ("so things may not work.");
2489 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
2493 /* Get the address of the first cproc in the task */
2494 if (!mach3_read_inferior (symaddr
,
2496 TARGET_PTR_BIT
/ HOST_CHAR_BIT
))
2497 error ("Can't read cproc master list at address (0x%x).", symaddr
);
2498 their_cprocs
= extract_address (buf
, TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2500 /* Scan the CPROCs in the task.
2501 CPROCs are chained with LIST field, not NEXT field, which
2502 chains mutexes, condition variables and queues */
2506 while (their_cprocs
!= (CORE_ADDR
) 0)
2508 CORE_ADDR cproc_copy_incarnation
;
2509 cproc_copy
= (gdb_thread_t
) obstack_alloc (cproc_obstack
,
2510 sizeof (struct gdb_thread
));
2512 if (!mach3_read_inferior (their_cprocs
,
2513 &cproc_copy
->raw_cproc
[0],
2515 error ("Can't read next cproc at 0x%x.", their_cprocs
);
2518 extract_address (cproc_copy
->raw_cproc
+ CPROC_LIST_OFFSET
,
2520 cproc_copy_incarnation
=
2521 extract_address (cproc_copy
->raw_cproc
+ CPROC_INCARNATION_OFFSET
,
2522 CPROC_INCARNATION_SIZE
);
2524 if (cproc_copy_incarnation
== (CORE_ADDR
) 0)
2525 cproc_copy
->cthread
= NULL
;
2528 /* This CPROC has an attached CTHREAD. Get its name */
2529 cthread
= (cthread_t
) obstack_alloc (cproc_obstack
,
2530 sizeof (struct cthread
));
2532 if (!mach3_read_inferior (cproc_copy_incarnation
,
2534 sizeof (struct cthread
)))
2535 error ("Can't read next thread at 0x%x.",
2536 cproc_copy_incarnation
);
2538 cproc_copy
->cthread
= cthread
;
2542 name
= (char *) obstack_alloc (cproc_obstack
, MAX_NAME_LEN
);
2544 if (!mach3_read_inferior (cthread
->name
, name
, MAX_NAME_LEN
))
2545 error ("Can't read next thread's name at 0x%x.", cthread
->name
);
2547 cthread
->name
= name
;
2551 /* insert in front */
2552 cproc_copy
->next
= cproc_head
;
2553 cproc_head
= cproc_copy
;
2558 #ifndef FETCH_CPROC_STATE
2560 * Check if your machine does not grok the way this routine
2561 * fetches the FP,PC and SP of a cproc that is not
2562 * currently attached to any kernel thread (e.g. its cproc.context
2563 * field points to the place in stack where the context
2566 * If it doesn't, define your own routine.
2568 #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2571 mach3_cproc_state (gdb_thread_t mthread
)
2575 if (!mthread
|| !mthread
->cproc
)
2578 context
= extract_signed_integer
2579 (mthread
->cproc
->raw_cproc
+ CPROC_CONTEXT_OFFSET
,
2580 CPROC_CONTEXT_SIZE
);
2584 mthread
->sp
= context
+ MACHINE_CPROC_SP_OFFSET
;
2586 if (mach3_read_inferior (context
+ MACHINE_CPROC_PC_OFFSET
,
2588 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2590 warning ("Can't read cproc pc from inferior");
2594 if (mach3_read_inferior (context
+ MACHINE_CPROC_FP_OFFSET
,
2596 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2598 warning ("Can't read cproc fp from inferior");
2604 #endif /* FETCH_CPROC_STATE */
2608 thread_list_command (void)
2610 thread_basic_info_data_t ths
;
2612 gdb_thread_t cprocs
;
2620 mach_port_t mid_or_port
;
2621 gdb_thread_t their_threads
;
2622 gdb_thread_t kthread
;
2626 char *fmt
= "There are %d kernel threads in task %d.\n";
2628 int tmid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
2630 MACH_ERROR_NO_INFERIOR
;
2632 thread_count
= fetch_thread_info (inferior_task
,
2634 if (thread_count
== -1)
2637 if (thread_count
== 1)
2638 fmt
= "There is %d kernel thread in task %d.\n";
2640 printf_filtered (fmt
, thread_count
, tmid
);
2642 puts_filtered (TL_HEADER
);
2644 cprocs
= get_cprocs ();
2646 map_cprocs_to_kernel_threads (cprocs
, their_threads
, thread_count
);
2648 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2654 extract_signed_integer
2655 (scan
->raw_cproc
+ CPROC_STATE_OFFSET
, CPROC_STATE_SIZE
);
2659 /* a wired cproc? */
2660 wired
= (extract_address (scan
->raw_cproc
+ CPROC_WIRED_OFFSET
,
2664 if (scan
->reverse_map
!= -1)
2665 kthread
= (their_threads
+ scan
->reverse_map
);
2671 /* These cprocs have a kernel thread */
2673 mid
= map_port_name_to_mid (kthread
->name
, MACH_TYPE_THREAD
);
2675 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2677 ret
= thread_info (kthread
->name
,
2679 (thread_info_t
) & ths
,
2682 if (ret
!= KERN_SUCCESS
)
2684 warning ("Unable to get basic info on thread %d : %s",
2686 mach_error_string (ret
));
2690 /* Who is the first to have more than 100 threads */
2691 sprintf (slot
, "%d", kthread
->slotid
% 100);
2693 if (kthread
->name
== current_thread
)
2696 if (ths
.suspend_count
)
2697 sprintf (buf
, "%d", ths
.suspend_count
);
2702 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2706 if (ths
.flags
& TH_FLAGS_IDLE
)
2709 printf_filtered (TL_FORMAT
,
2713 get_thread_name (scan
, kthread
->slotid
),
2714 kthread
->in_emulator
? "E" : "",
2715 translate_state (ths
.run_state
),
2717 translate_cstate (cproc_state
),
2719 print_tl_address (gdb_stdout
, kthread
->pc
);
2723 /* These cprocs don't have a kernel thread.
2724 * find out the calling frame with
2725 * FETCH_CPROC_STATE.
2728 struct gdb_thread state
;
2731 /* jtv -> emcmanus: why do you want this here? */
2732 if (scan
->incarnation
== NULL
)
2733 continue; /* EMcM */
2736 printf_filtered (TL_FORMAT
,
2738 -neworder
, /* Pseudo MID */
2740 get_thread_name (scan
, -neworder
),
2742 "-", /* kernel state */
2744 translate_cstate (cproc_state
),
2748 if (FETCH_CPROC_STATE (&state
) == -1)
2749 puts_filtered ("???");
2751 print_tl_address (gdb_stdout
, state
.pc
);
2755 puts_filtered ("\n");
2758 /* Scan for kernel threads without cprocs */
2759 for (index
= 0; index
< thread_count
; index
++)
2761 if (!their_threads
[index
].cproc
)
2768 mach_port_t name
= their_threads
[index
].name
;
2770 mid
= map_port_name_to_mid (name
, MACH_TYPE_THREAD
);
2772 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2774 ret
= thread_info (name
,
2776 (thread_info_t
) & ths
,
2779 if (ret
!= KERN_SUCCESS
)
2781 warning ("Unable to get basic info on thread %d : %s",
2783 mach_error_string (ret
));
2787 sprintf (slot
, "%d", index
% 100);
2789 if (name
== current_thread
)
2794 if (ths
.suspend_count
)
2795 sprintf (buf
, "%d", ths
.suspend_count
);
2800 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2804 if (ths
.flags
& TH_FLAGS_IDLE
)
2807 printf_filtered (TL_FORMAT
,
2811 get_thread_name (NULL
, index
),
2812 their_threads
[index
].in_emulator
? "E" : "",
2813 translate_state (ths
.run_state
),
2815 "", /* No cproc state */
2816 ""); /* Can't be wired */
2817 print_tl_address (gdb_stdout
, their_threads
[index
].pc
);
2818 puts_filtered ("\n");
2822 obstack_free (cproc_obstack
, 0);
2823 obstack_init (cproc_obstack
);
2827 thread_select_command (char *args
, int from_tty
)
2830 thread_array_t thread_list
;
2835 MACH_ERROR_NO_INFERIOR
;
2838 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2840 while (*args
== ' ' || *args
== '\t')
2852 if (!is_slot
|| *args
!= '0') /* Rudimentary checks */
2853 error ("You must select threads by MID or @SLOTNUMBER");
2855 if (select_thread (inferior_task
, mid
, is_slot
? 2 : 1) != KERN_SUCCESS
)
2859 printf_filtered ("Thread %d selected\n",
2860 is_slot
? map_port_name_to_mid (current_thread
,
2861 MACH_TYPE_THREAD
) : mid
);
2864 thread_trace (mach_port_t thread
, boolean_t set
)
2866 int flavor
= TRACE_FLAVOR
;
2867 unsigned int stateCnt
= TRACE_FLAVOR_SIZE
;
2869 thread_state_data_t state
;
2871 if (!MACH_PORT_VALID (thread
))
2873 warning ("thread_trace: invalid thread");
2877 if (must_suspend_thread
)
2878 setup_thread (thread
, 1);
2880 ret
= thread_get_state (thread
, flavor
, state
, &stateCnt
);
2881 CHK ("thread_trace: error reading thread state", ret
);
2885 TRACE_SET (thread
, state
);
2889 if (!TRACE_CLEAR (thread
, state
))
2891 if (must_suspend_thread
)
2892 setup_thread (thread
, 0);
2897 ret
= thread_set_state (thread
, flavor
, state
, stateCnt
);
2898 CHK ("thread_trace: error writing thread state", ret
);
2899 if (must_suspend_thread
)
2900 setup_thread (thread
, 0);
2903 #ifdef FLUSH_INFERIOR_CACHE
2905 /* When over-writing code on some machines the I-Cache must be flushed
2906 explicitly, because it is not kept coherent by the lazy hardware.
2907 This definitely includes breakpoints, for instance, or else we
2908 end up looping in mysterious Bpt traps */
2910 flush_inferior_icache (CORE_ADDR pc
, int amount
)
2912 vm_machine_attribute_val_t flush
= MATTR_VAL_ICACHE_FLUSH
;
2915 ret
= vm_machine_attribute (inferior_task
,
2920 if (ret
!= KERN_SUCCESS
)
2921 warning ("Error flushing inferior's cache : %s",
2922 mach_error_string (ret
));
2924 #endif /* FLUSH_INFERIOR_CACHE */
2928 suspend_all_threads (int from_tty
)
2931 thread_array_t thread_list
;
2932 int thread_count
, index
;
2934 thread_basic_info_data_t th_info
;
2937 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
2938 if (ret
!= KERN_SUCCESS
)
2940 warning ("Could not suspend inferior threads.");
2941 m3_kill_inferior ();
2942 return_to_top_level (RETURN_ERROR
);
2945 for (index
= 0; index
< thread_count
; index
++)
2949 mid
= map_port_name_to_mid (thread_list
[index
],
2952 ret
= thread_suspend (thread_list
[index
]);
2954 if (ret
!= KERN_SUCCESS
)
2955 warning ("Error trying to suspend thread %d : %s",
2956 mid
, mach_error_string (ret
));
2960 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2961 ret
= thread_info (thread_list
[index
],
2963 (thread_info_t
) & th_info
,
2965 CHK ("suspend can't get thread info", ret
);
2967 warning ("Thread %d suspend count is %d",
2968 mid
, th_info
.suspend_count
);
2972 consume_send_rights (thread_list
, thread_count
);
2973 ret
= vm_deallocate (mach_task_self (),
2974 (vm_address_t
) thread_list
,
2975 (thread_count
* sizeof (int)));
2976 CHK ("Error trying to deallocate thread list", ret
);
2980 thread_suspend_command (char *args
, int from_tty
)
2984 mach_port_t saved_thread
;
2986 thread_basic_info_data_t th_info
;
2988 MACH_ERROR_NO_INFERIOR
;
2990 if (!strcasecmp (args
, "all"))
2992 suspend_all_threads (from_tty
);
2996 saved_thread
= current_thread
;
2998 mid
= parse_thread_id (args
, 0, 0);
3001 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
3004 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3005 else if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3008 current_thread
= saved_thread
;
3009 error ("Could not select thread %d", mid
);
3012 ret
= thread_suspend (current_thread
);
3013 if (ret
!= KERN_SUCCESS
)
3014 warning ("thread_suspend failed : %s",
3015 mach_error_string (ret
));
3017 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3018 ret
= thread_info (current_thread
,
3020 (thread_info_t
) & th_info
,
3022 CHK ("suspend can't get thread info", ret
);
3024 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3026 current_thread
= saved_thread
;
3029 resume_all_threads (int from_tty
)
3032 thread_array_t thread_list
;
3033 int thread_count
, index
;
3036 thread_basic_info_data_t th_info
;
3038 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
3039 if (ret
!= KERN_SUCCESS
)
3041 m3_kill_inferior ();
3042 error ("task_threads", mach_error_string (ret
));
3045 for (index
= 0; index
< thread_count
; index
++)
3047 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3048 ret
= thread_info (thread_list
[index
],
3050 (thread_info_t
) & th_info
,
3052 CHK ("resume_all can't get thread info", ret
);
3054 mid
= map_port_name_to_mid (thread_list
[index
],
3057 if (!th_info
.suspend_count
)
3059 if (mid
!= -1 && from_tty
)
3060 warning ("Thread %d is not suspended", mid
);
3064 ret
= thread_resume (thread_list
[index
]);
3066 if (ret
!= KERN_SUCCESS
)
3067 warning ("Error trying to resume thread %d : %s",
3068 mid
, mach_error_string (ret
));
3069 else if (mid
!= -1 && from_tty
)
3070 warning ("Thread %d suspend count is %d",
3071 mid
, --th_info
.suspend_count
);
3074 consume_send_rights (thread_list
, thread_count
);
3075 ret
= vm_deallocate (mach_task_self (),
3076 (vm_address_t
) thread_list
,
3077 (thread_count
* sizeof (int)));
3078 CHK ("Error trying to deallocate thread list", ret
);
3082 thread_resume_command (char *args
, int from_tty
)
3085 mach_port_t saved_thread
;
3087 thread_basic_info_data_t th_info
;
3088 int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3090 MACH_ERROR_NO_INFERIOR
;
3092 if (!strcasecmp (args
, "all"))
3094 resume_all_threads (from_tty
);
3098 saved_thread
= current_thread
;
3100 mid
= parse_thread_id (args
, 0, 0);
3103 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3106 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3107 else if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3110 current_thread
= saved_thread
;
3111 return_to_top_level (RETURN_ERROR
);
3114 ret
= thread_info (current_thread
,
3116 (thread_info_t
) & th_info
,
3118 CHK ("resume can't get thread info", ret
);
3120 if (!th_info
.suspend_count
)
3122 warning ("Thread %d is not suspended", mid
);
3126 ret
= thread_resume (current_thread
);
3127 if (ret
!= KERN_SUCCESS
)
3128 warning ("thread_resume failed : %s",
3129 mach_error_string (ret
));
3132 th_info
.suspend_count
--;
3133 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3137 current_thread
= saved_thread
;
3141 thread_kill_command (char *args
, int from_tty
)
3146 thread_array_t thread_table
;
3148 mach_port_t thread_to_kill
= MACH_PORT_NULL
;
3151 MACH_ERROR_NO_INFERIOR
;
3154 error_no_arg ("thread mid to kill from the inferior task");
3156 mid
= parse_thread_id (args
, 0, 0);
3159 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3163 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &thread_to_kill
);
3164 CHK ("thread_kill_command: machid_mach_port map failed", ret
);
3167 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3169 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3170 ret
= task_threads (inferior_task
, &thread_table
, &thread_count
);
3171 CHK ("Error getting inferior's thread list", ret
);
3173 if (thread_to_kill
== current_thread
)
3175 ret
= thread_terminate (thread_to_kill
);
3176 CHK ("Thread could not be terminated", ret
);
3178 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3179 warning ("Last thread was killed, use \"kill\" command to kill task");
3182 for (index
= 0; index
< thread_count
; index
++)
3183 if (thread_table
[index
] == thread_to_kill
)
3185 ret
= thread_terminate (thread_to_kill
);
3186 CHK ("Thread could not be terminated", ret
);
3189 if (thread_count
> 1)
3190 consume_send_rights (thread_table
, thread_count
);
3192 ret
= vm_deallocate (mach_task_self (), (vm_address_t
) thread_table
,
3193 (thread_count
* sizeof (mach_port_t
)));
3194 CHK ("Error trying to deallocate thread list", ret
);
3196 warning ("Thread %d killed", mid
);
3200 /* Task specific commands; add more if you like */
3203 task_resume_command (char *args
, int from_tty
)
3206 task_basic_info_data_t ta_info
;
3207 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3208 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3210 MACH_ERROR_NO_INFERIOR
;
3212 /* Would be trivial to change, but is it desirable? */
3214 error ("Currently gdb can resume only it's inferior task");
3216 ret
= task_info (inferior_task
,
3218 (task_info_t
) & ta_info
,
3220 CHK ("task_resume_command: task_info failed", ret
);
3222 if (ta_info
.suspend_count
== 0)
3223 error ("Inferior task %d is not suspended", mid
);
3224 else if (ta_info
.suspend_count
== 1 &&
3226 !query ("Suspend count is now 1. Do you know what you are doing? "))
3227 error ("Task not resumed");
3229 ret
= task_resume (inferior_task
);
3230 CHK ("task_resume_command: task_resume", ret
);
3232 if (ta_info
.suspend_count
== 1)
3234 warning ("Inferior task %d is no longer suspended", mid
);
3235 must_suspend_thread
= 1;
3236 /* @@ This is not complete: Registers change all the time when not
3238 registers_changed ();
3241 warning ("Inferior task %d suspend count is now %d",
3242 mid
, ta_info
.suspend_count
- 1);
3247 task_suspend_command (char *args
, int from_tty
)
3250 task_basic_info_data_t ta_info
;
3251 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3252 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3254 MACH_ERROR_NO_INFERIOR
;
3256 /* Would be trivial to change, but is it desirable? */
3258 error ("Currently gdb can suspend only it's inferior task");
3260 ret
= task_suspend (inferior_task
);
3261 CHK ("task_suspend_command: task_suspend", ret
);
3263 must_suspend_thread
= 0;
3265 ret
= task_info (inferior_task
,
3267 (task_info_t
) & ta_info
,
3269 CHK ("task_suspend_command: task_info failed", ret
);
3271 warning ("Inferior task %d suspend count is now %d",
3272 mid
, ta_info
.suspend_count
);
3276 get_size (int bytes
)
3278 static char size
[30];
3279 int zz
= bytes
/ 1024;
3282 sprintf (size
, "%-2.1f M", ((float) bytes
) / (1024.0 * 1024.0));
3284 sprintf (size
, "%d K", zz
);
3289 /* Does this require the target task to be suspended?? I don't think so. */
3291 task_info_command (char *args
, int from_tty
)
3296 task_basic_info_data_t ta_info
;
3297 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3298 int page_size
= round_page (1);
3299 int thread_count
= 0;
3301 if (MACH_PORT_VALID (inferior_task
))
3302 mid
= map_port_name_to_mid (inferior_task
,
3305 task
= inferior_task
;
3309 int tmid
= atoi (args
);
3312 error ("Invalid mid %d for task info", tmid
);
3317 ret
= machid_mach_port (mid_server
, mid_auth
, tmid
, &task
);
3318 CHK ("task_info_command: machid_mach_port map failed", ret
);
3323 error ("You have to give the task MID as an argument");
3325 ret
= task_info (task
,
3327 (task_info_t
) & ta_info
,
3329 CHK ("task_info_command: task_info failed", ret
);
3331 printf_filtered ("\nTask info for task %d:\n\n", mid
);
3332 printf_filtered (" Suspend count : %d\n", ta_info
.suspend_count
);
3333 printf_filtered (" Base priority : %d\n", ta_info
.base_priority
);
3334 printf_filtered (" Virtual size : %s\n", get_size (ta_info
.virtual_size
));
3335 printf_filtered (" Resident size : %s\n", get_size (ta_info
.resident_size
));
3338 thread_array_t thread_list
;
3340 ret
= task_threads (task
, &thread_list
, &thread_count
);
3341 CHK ("task_info_command: task_threads", ret
);
3343 printf_filtered (" Thread count : %d\n", thread_count
);
3345 consume_send_rights (thread_list
, thread_count
);
3346 ret
= vm_deallocate (mach_task_self (),
3347 (vm_address_t
) thread_list
,
3348 (thread_count
* sizeof (int)));
3349 CHK ("Error trying to deallocate thread list", ret
);
3351 if (have_emulator_p (task
))
3352 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3353 EMULATOR_BASE
, EMULATOR_END
);
3355 printf_filtered (" No emulator.\n");
3357 if (thread_count
&& task
== inferior_task
)
3358 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3361 /* You may either FORWARD the exception to the inferior, or KEEP
3362 * it and return to GDB command level.
3364 * exception mid [ forward | keep ]
3368 exception_command (char *args
, int from_tty
)
3375 error_no_arg ("exception number action");
3377 while (*scan
== ' ' || *scan
== '\t')
3380 if ('0' <= *scan
&& *scan
<= '9')
3381 while ('0' <= *scan
&& *scan
<= '9')
3384 error ("exception number action");
3386 exception
= atoi (args
);
3387 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3388 error ("Allowed exception numbers are in range 1..%d",
3391 if (*scan
!= ' ' && *scan
!= '\t')
3392 error ("exception number must be followed by a space");
3394 while (*scan
== ' ' || *scan
== '\t')
3406 error ("exception number action");
3408 if (!strncasecmp (args
, "forward", len
))
3409 exception_map
[exception
].forward
= TRUE
;
3410 else if (!strncasecmp (args
, "keep", len
))
3411 exception_map
[exception
].forward
= FALSE
;
3413 error ("exception action is either \"keep\" or \"forward\"");
3417 print_exception_info (int exception
)
3419 boolean_t forward
= exception_map
[exception
].forward
;
3421 printf_filtered ("%s\t(%d): ", exception_map
[exception
].name
,
3424 if (exception_map
[exception
].sigmap
!= SIG_UNKNOWN
)
3425 printf_filtered ("keep and handle as signal %d\n",
3426 exception_map
[exception
].sigmap
);
3428 printf_filtered ("keep and handle as unknown signal %d\n",
3429 exception_map
[exception
].sigmap
);
3431 printf_filtered ("forward exception to inferior\n");
3435 exception_info (char *args
, int from_tty
)
3440 for (exception
= 1; exception
<= MAX_EXCEPTION
; exception
++)
3441 print_exception_info (exception
);
3444 exception
= atoi (args
);
3446 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3447 error ("Invalid exception number, values from 1 to %d allowed",
3449 print_exception_info (exception
);
3453 /* Check for actions for mach exceptions.
3455 mach3_exception_actions (WAITTYPE
*w
, boolean_t force_print_only
, char *who
)
3457 boolean_t force_print
= FALSE
;
3460 if (force_print_only
||
3461 exception_map
[stop_exception
].sigmap
== SIG_UNKNOWN
)
3464 WSETSTOP (*w
, exception_map
[stop_exception
].sigmap
);
3466 if (exception_map
[stop_exception
].print
|| force_print
)
3468 target_terminal_ours ();
3470 printf_filtered ("\n%s received %s exception : ",
3472 exception_map
[stop_exception
].name
);
3476 switch (stop_exception
)
3478 case EXC_BAD_ACCESS
:
3479 printf_filtered ("referencing address 0x%x : %s\n",
3481 mach_error_string (stop_code
));
3483 case EXC_BAD_INSTRUCTION
:
3485 ("illegal or undefined instruction. code %d subcode %d\n",
3486 stop_code
, stop_subcode
);
3488 case EXC_ARITHMETIC
:
3489 printf_filtered ("code %d\n", stop_code
);
3492 printf_filtered ("code %d subcode %d\n", stop_code
, stop_subcode
);
3495 printf_filtered ("%s specific, code 0x%x\n",
3496 stop_code
< 0xffff ? "hardware" : "os emulation",
3499 case EXC_BREAKPOINT
:
3500 printf_filtered ("type %d (machine dependent)\n",
3504 internal_error (__FILE__
, __LINE__
,
3505 "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 (__FILE__
, __LINE__
,
3531 "Creating notify port %s", mach_error_string (ret
));
3533 ret
= mach_port_move_member (mach_task_self (),
3535 inferior_wait_port_set
);
3536 if (ret
!= KERN_SUCCESS
)
3537 internal_error (__FILE__
, __LINE__
,
3538 "initial move member %s", mach_error_string (ret
));
3543 * Register our message port to the net name server
3545 * Currently used only by the external stop-gdb program
3546 * since ^C does not work if you would like to enter
3547 * gdb command level while debugging your program.
3549 * NOTE: If the message port is sometimes used for other
3550 * purposes also, the NAME must not be a guessable one.
3551 * Then, there should be a way to change it.
3554 char registered_name
[MAX_NAME_LEN
];
3557 message_port_info (char *args
, int from_tty
)
3559 if (registered_name
[0])
3560 printf_filtered ("gdb's message port name: '%s'\n",
3563 printf_filtered ("gdb's message port is not currently registered\n");
3567 gdb_register_port (char *name
, mach_port_t port
)
3570 static int already_signed
= 0;
3573 if (!MACH_PORT_VALID (port
) || !name
|| !*name
)
3575 warning ("Invalid registration request");
3579 if (!already_signed
)
3581 ret
= mach_port_insert_right (mach_task_self (),
3584 MACH_MSG_TYPE_MAKE_SEND
);
3585 CHK ("Failed to create a signature to our_message_port", ret
);
3588 else if (already_signed
> 1)
3590 ret
= netname_check_out (name_server_port
,
3593 CHK ("Failed to check out gdb's message port", ret
);
3594 registered_name
[0] = '\000';
3598 ret
= netname_check_in (name_server_port
, /* Name server port */
3599 name
, /* Name of service */
3600 our_message_port
, /* Signature */
3601 port
); /* Creates a new send right */
3602 CHK ("Failed to check in the port", ret
);
3605 while (len
< MAX_NAME_LEN
&& *(name
+ len
))
3607 registered_name
[len
] = *(name
+ len
);
3610 registered_name
[len
] = '\000';
3614 struct cmd_list_element
*cmd_thread_list
;
3615 struct cmd_list_element
*cmd_task_list
;
3619 thread_command (char *arg
, int from_tty
)
3621 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3622 help_list (cmd_thread_list
, "thread ", -1, gdb_stdout
);
3627 task_command (char *arg
, int from_tty
)
3629 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3630 help_list (cmd_task_list
, "task ", -1, gdb_stdout
);
3633 add_mach_specific_commands (void)
3635 /* Thread handling commands */
3637 /* FIXME: Move our thread support into the generic thread.c stuff so we
3638 can share that code. */
3639 add_prefix_cmd ("mthread", class_stack
, thread_command
,
3640 "Generic command for handling Mach threads in the debugged task.",
3641 &cmd_thread_list
, "thread ", 0, &cmdlist
);
3643 add_com_alias ("th", "mthread", class_stack
, 1);
3645 add_cmd ("select", class_stack
, thread_select_command
,
3646 "Select and print MID of the selected thread",
3648 add_cmd ("list", class_stack
, thread_list_command
,
3649 "List info of task's threads. Selected thread is marked with '*'",
3651 add_cmd ("suspend", class_run
, thread_suspend_command
,
3652 "Suspend one or all of the threads in the selected task.",
3654 add_cmd ("resume", class_run
, thread_resume_command
,
3655 "Resume one or all of the threads in the selected task.",
3657 add_cmd ("kill", class_run
, thread_kill_command
,
3658 "Kill the specified thread MID from inferior task.",
3661 /* The rest of this support (condition_thread) was not merged. It probably
3662 should not be merged in this form, but instead added to the generic GDB
3664 add_cmd ("break", class_breakpoint
, condition_thread
,
3665 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3666 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3669 /* Thread command shorthands (for backward compatibility) */
3670 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist
);
3671 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist
);
3673 /* task handling commands */
3675 add_prefix_cmd ("task", class_stack
, task_command
,
3676 "Generic command for handling debugged task.",
3677 &cmd_task_list
, "task ", 0, &cmdlist
);
3679 add_com_alias ("ta", "task", class_stack
, 1);
3681 add_cmd ("suspend", class_run
, task_suspend_command
,
3682 "Suspend the inferior task.",
3684 add_cmd ("resume", class_run
, task_resume_command
,
3685 "Resume the inferior task.",
3687 add_cmd ("info", no_class
, task_info_command
,
3688 "Print information about the specified task.",
3691 /* Print my message port name */
3693 add_info ("message-port", message_port_info
,
3694 "Returns the name of gdb's message port in the netnameserver");
3696 /* Exception commands */
3698 add_info ("exceptions", exception_info
,
3699 "What debugger does when program gets various exceptions.\n\
3700 Specify an exception number as argument to print info on that\n\
3703 add_com ("exception", class_run
, exception_command
,
3704 "Specify how to handle an exception.\n\
3705 Args are exception number followed by \"forward\" or \"keep\".\n\
3706 `Forward' means forward the exception to the program's normal exception\n\
3708 `Keep' means reenter debugger if this exception happens, and GDB maps\n\
3709 the exception to some signal (see info exception)\n\
3710 Normally \"keep\" is used to return to GDB on exception.");
3714 do_mach_notify_dead_name (mach_port_t notify
, mach_port_t name
)
3716 kern_return_t kr
= KERN_SUCCESS
;
3718 /* Find the thing that notified */
3719 port_chain_t element
= port_chain_member (notify_chain
, name
);
3721 /* Take name of from unreceived dead name notification list */
3722 notify_chain
= port_chain_delete (notify_chain
, name
);
3725 error ("Received a dead name notify from unchained port (0x%x)", name
);
3727 switch (element
->type
)
3730 case MACH_TYPE_THREAD
:
3731 target_terminal_ours_for_output ();
3732 if (name
== current_thread
)
3734 printf_filtered ("\nCurrent thread %d died", element
->mid
);
3735 current_thread
= MACH_PORT_NULL
;
3738 printf_filtered ("\nThread %d died", element
->mid
);
3742 case MACH_TYPE_TASK
:
3743 target_terminal_ours_for_output ();
3744 if (name
!= inferior_task
)
3745 printf_filtered ("Task %d died, but it was not the selected task",
3749 printf_filtered ("Current task %d died", element
->mid
);
3751 mach_port_destroy (mach_task_self (), name
);
3752 inferior_task
= MACH_PORT_NULL
;
3755 warning ("There were still unreceived dead_name_notifications???");
3757 /* Destroy the old notifications */
3758 setup_notify_port (0);
3764 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3765 name
, element
->type
, element
->mid
);
3769 return KERN_SUCCESS
;
3773 do_mach_notify_msg_accepted (mach_port_t notify
, mach_port_t name
)
3775 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3777 return KERN_SUCCESS
;
3781 do_mach_notify_no_senders (mach_port_t notify
, mach_port_mscount_t mscount
)
3783 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3785 return KERN_SUCCESS
;
3789 do_mach_notify_port_deleted (mach_port_t notify
, mach_port_t name
)
3791 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3793 return KERN_SUCCESS
;
3797 do_mach_notify_port_destroyed (mach_port_t notify
, mach_port_t rights
)
3799 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3801 return KERN_SUCCESS
;
3805 do_mach_notify_send_once (mach_port_t notify
)
3808 /* MANY of these are generated. */
3809 warning ("do_mach_notify_send_once : notify %x",
3812 return KERN_SUCCESS
;
3815 /* Kills the inferior. It's gone when you call this */
3817 kill_inferior_fast (void)
3821 if (PIDGET (inferior_ptid
) == 0 || PIDGET (inferior_ptid
) == 1)
3824 /* kill() it, since the Unix server does not otherwise notice when
3825 * killed with task_terminate().
3827 if (PIDGET (inferior_ptid
) > 0)
3828 kill (PIDGET (inferior_ptid
), SIGKILL
);
3830 /* It's propably terminate already */
3831 (void) task_terminate (inferior_task
);
3833 inferior_task
= MACH_PORT_NULL
;
3834 current_thread
= MACH_PORT_NULL
;
3836 wait3 (&w
, WNOHANG
, 0);
3838 setup_notify_port (0);
3842 m3_kill_inferior (void)
3844 kill_inferior_fast ();
3845 target_mourn_inferior ();
3848 /* Clean up after the inferior dies. */
3851 m3_mourn_inferior (void)
3853 unpush_target (&m3_ops
);
3854 generic_mourn_inferior ();
3858 /* Fork an inferior process, and start debugging it. */
3861 m3_create_inferior (char *exec_file
, char *allargs
, char **env
)
3863 fork_inferior (exec_file
, allargs
, env
, m3_trace_me
, m3_trace_him
, NULL
, NULL
);
3864 /* We are at the first instruction we care about. */
3865 /* Pedal to the metal... */
3866 proceed ((CORE_ADDR
) -1, 0, 0);
3869 /* Mark our target-struct as eligible for stray "run" and "attach"
3877 /* Mach 3.0 does not need ptrace for anything
3878 * Make sure nobody uses it on mach.
3880 ptrace (int a
, int b
, int c
, int d
)
3882 error ("Lose, Lose! Somebody called ptrace\n");
3885 /* Resume execution of the inferior process.
3886 If STEP is nonzero, single-step it.
3887 If SIGNAL is nonzero, give it that signal. */
3890 m3_resume (ptid_t ptid
, int step
, enum target_signal signal
)
3896 thread_basic_info_data_t th_info
;
3897 unsigned int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3899 /* There is no point in single stepping when current_thread
3902 if (!MACH_PORT_VALID (current_thread
))
3903 error ("No thread selected; can not single step");
3905 /* If current_thread is suspended, tracing it would never return.
3907 ret
= thread_info (current_thread
,
3909 (thread_info_t
) & th_info
,
3911 CHK ("child_resume: can't get thread info", ret
);
3913 if (th_info
.suspend_count
)
3914 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3917 vm_read_cache_valid
= FALSE
;
3919 if (signal
&& PIDGET (inferior_ptid
) > 0) /* Do not signal, if attached by MID */
3920 kill (PIDGET (inferior_ptid
), target_signal_to_host (signal
));
3924 suspend_all_threads (0);
3926 setup_single_step (current_thread
, TRUE
);
3928 ret
= thread_resume (current_thread
);
3929 CHK ("thread_resume", ret
);
3932 ret
= task_resume (inferior_task
);
3933 if (ret
== KERN_FAILURE
)
3934 warning ("Task was not suspended");
3936 CHK ("Resuming task", ret
);
3938 /* HACK HACK This is needed by the multiserver system HACK HACK */
3939 while ((ret
= task_resume (inferior_task
)) == KERN_SUCCESS
)
3940 /* make sure it really runs */ ;
3941 /* HACK HACK This is needed by the multiserver system HACK HACK */
3944 #ifdef ATTACH_DETACH
3946 /* Start debugging the process with the given task */
3948 task_attach (task_t tid
)
3951 inferior_task
= tid
;
3953 ret
= task_suspend (inferior_task
);
3954 CHK ("task_attach: task_suspend", ret
);
3956 must_suspend_thread
= 0;
3958 setup_notify_port (1);
3960 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
3962 setup_exception_port ();
3964 emulator_present
= have_emulator_p (inferior_task
);
3969 /* Well, we can call error also here and leave the
3970 * target stack inconsistent. Sigh.
3971 * Fix this sometime (the only way to fail here is that
3972 * the task has no threads at all, which is rare, but
3973 * possible; or if the target task has died, which is also
3974 * possible, but unlikely, since it has been suspended.
3975 * (Someone must have killed it))
3978 attach_to_thread (void)
3980 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3981 error ("Could not select any threads to attach to");
3984 mid_attach (int mid
)
3988 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &inferior_task
);
3989 CHK ("mid_attach: machid_mach_port", ret
);
3991 task_attach (inferior_task
);
3997 * Start debugging the process whose unix process-id is PID.
3998 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
4000 * Prevent (possible unwanted) dangerous operations by enabled users
4001 * like "atta 0" or "atta foo" (equal to the previous :-) and
4002 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4005 m3_do_attach (int pid
)
4010 error ("MID=0, Debugging the master unix server does not compute");
4012 /* Foo. This assumes gdb has a unix pid */
4013 if (pid
== getpid ())
4014 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4018 mid_attach (-(pid
));
4020 /* inferior_ptid will be NEGATIVE! */
4021 inferior_ptid
= pid_to_ptid (pid
);
4023 return PIDGET (inferior_ptid
);
4026 inferior_task
= task_by_pid (pid
);
4027 if (!MACH_PORT_VALID (inferior_task
))
4028 error ("Cannot map Unix pid %d to Mach task port", pid
);
4030 task_attach (inferior_task
);
4032 inferior_ptid
= pid_to_ptid (pid
);
4034 return PIDGET (inferior_ptid
);
4037 /* Attach to process PID, then initialize for debugging it
4038 and wait for the trace-trap that results from attaching. */
4041 m3_attach (char *args
, int from_tty
)
4047 error_no_arg ("process-id to attach");
4051 if (pid
== getpid ()) /* Trying to masturbate? */
4052 error ("I refuse to debug myself!");
4056 exec_file
= (char *) get_exec_file (0);
4059 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file
,
4060 target_pid_to_str (pid_to_ptid (pid
)));
4062 printf_unfiltered ("Attaching to %s\n",
4063 target_pid_to_str (pid_to_ptid (pid
)));
4065 gdb_flush (gdb_stdout
);
4068 m3_do_attach (pid_to_ptid (pid
));
4069 inferior_ptid
= pid_to_ptid (pid
);
4070 push_target (&m3_ops
);
4074 deallocate_inferior_ports (void)
4077 thread_array_t thread_list
;
4078 int thread_count
, index
;
4080 if (!MACH_PORT_VALID (inferior_task
))
4083 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
4084 if (ret
!= KERN_SUCCESS
)
4086 warning ("deallocate_inferior_ports: task_threads",
4087 mach_error_string (ret
));
4091 /* Get rid of send rights to task threads */
4092 for (index
= 0; index
< thread_count
; index
++)
4095 ret
= mach_port_get_refs (mach_task_self (),
4097 MACH_PORT_RIGHT_SEND
,
4099 CHK ("deallocate_inferior_ports: get refs", ret
);
4103 ret
= mach_port_mod_refs (mach_task_self (),
4105 MACH_PORT_RIGHT_SEND
,
4107 CHK ("deallocate_inferior_ports: mod refs", ret
);
4111 ret
= mach_port_mod_refs (mach_task_self (),
4112 inferior_exception_port
,
4113 MACH_PORT_RIGHT_RECEIVE
,
4115 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret
);
4117 ret
= mach_port_deallocate (mach_task_self (),
4119 CHK ("deallocate_task_port: deallocating inferior_task", ret
);
4121 current_thread
= MACH_PORT_NULL
;
4122 inferior_task
= MACH_PORT_NULL
;
4125 /* Stop debugging the process whose number is PID
4126 and continue it with signal number SIGNAL.
4127 SIGNAL = 0 means just continue it. */
4130 m3_do_detach (int signal
)
4134 MACH_ERROR_NO_INFERIOR
;
4136 if (current_thread
!= MACH_PORT_NULL
)
4138 /* Store the gdb's view of the thread we are deselecting
4140 * @@ I am really not sure if this is ever needeed.
4142 target_prepare_to_store ();
4143 target_store_registers (-1);
4146 ret
= task_set_special_port (inferior_task
,
4147 TASK_EXCEPTION_PORT
,
4148 inferior_old_exception_port
);
4149 CHK ("task_set_special_port", ret
);
4151 /* Discard all requested notifications */
4152 setup_notify_port (0);
4154 if (remove_breakpoints ())
4155 warning ("Could not remove breakpoints when detaching");
4157 if (signal
&& PIDGET (inferior_ptid
) > 0)
4158 kill (PIDGET (inferior_ptid
), signal
);
4160 /* the task might be dead by now */
4161 (void) task_resume (inferior_task
);
4163 deallocate_inferior_ports ();
4168 /* Take a program previously attached to and detaches it.
4169 The program resumes execution and will no longer stop
4170 on signals, etc. We'd better not have left any breakpoints
4171 in the program or it'll die when it hits one. For this
4172 to work, it may be necessary for the process to have been
4173 previously attached. It *might* work if the program was
4174 started via fork. */
4177 m3_detach (char *args
, int from_tty
)
4183 char *exec_file
= get_exec_file (0);
4186 printf_unfiltered ("Detaching from program: %s %s\n",
4187 exec_file
, target_pid_to_str (inferior_ptid
));
4188 gdb_flush (gdb_stdout
);
4191 siggnal
= atoi (args
);
4193 m3_do_detach (siggnal
);
4194 inferior_ptid
= null_ptid
;
4195 unpush_target (&m3_ops
); /* Pop out of handling an inferior */
4197 #endif /* ATTACH_DETACH */
4199 /* Get ready to modify the registers array. On machines which store
4200 individual registers, this doesn't need to do anything. On machines
4201 which store all the registers in one fell swoop, this makes sure
4202 that registers contains all the registers from the program being
4206 m3_prepare_to_store (void)
4208 #ifdef CHILD_PREPARE_TO_STORE
4209 CHILD_PREPARE_TO_STORE ();
4213 /* Print status information about what we're accessing. */
4216 m3_files_info (struct target_ops
*ignore
)
4218 /* FIXME: should print MID and all that crap. */
4219 printf_unfiltered ("\tUsing the running image of %s %s.\n",
4220 attach_flag
? "attached" : "child", target_pid_to_str (inferior_ptid
));
4224 m3_open (char *arg
, int from_tty
)
4226 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 (__FILE__
, __LINE__
,
4507 "initial port set %s", mach_error_string (ret
));
4509 /* mach_really_wait now waits for this */
4510 currently_waiting_for
= inferior_wait_port_set
;
4512 ret
= netname_look_up (name_server_port
, hostname
, "MachID", &mid_server
);
4513 if (ret
!= KERN_SUCCESS
)
4515 mid_server
= MACH_PORT_NULL
;
4517 warning ("initialize machid: netname_lookup_up(MachID) : %s",
4518 mach_error_string (ret
));
4519 warning ("Some (most?) features disabled...");
4522 mid_auth
= mach_privileged_host_port ();
4523 if (mid_auth
== MACH_PORT_NULL
)
4524 mid_auth
= mach_task_self ();
4526 obstack_init (port_chain_obstack
);
4528 ret
= mach_port_allocate (mach_task_self (),
4529 MACH_PORT_RIGHT_RECEIVE
,
4530 &thread_exception_port
);
4531 CHK ("Creating thread_exception_port for single stepping", ret
);
4533 ret
= mach_port_insert_right (mach_task_self (),
4534 thread_exception_port
,
4535 thread_exception_port
,
4536 MACH_MSG_TYPE_MAKE_SEND
);
4537 CHK ("Inserting send right to thread_exception_port", ret
);
4539 /* Allocate message port */
4540 ret
= mach_port_allocate (mach_task_self (),
4541 MACH_PORT_RIGHT_RECEIVE
,
4543 if (ret
!= KERN_SUCCESS
)
4544 warning ("Creating message port %s", mach_error_string (ret
));
4547 char buf
[MAX_NAME_LEN
];
4548 ret
= mach_port_move_member (mach_task_self (),
4550 inferior_wait_port_set
);
4551 if (ret
!= KERN_SUCCESS
)
4552 warning ("message move member %s", mach_error_string (ret
));
4555 /* @@@@ No way to change message port name currently */
4556 /* Foo. This assumes gdb has a unix pid */
4557 sprintf (buf
, "gdb-%d", getpid ());
4558 gdb_register_port (buf
, our_message_port
);
4561 /* Heap for thread commands */
4562 obstack_init (cproc_obstack
);
4564 add_mach_specific_commands ();