1 /* Interface GDB to Mach 3.0 operating systems.
2 (Most) Mach 3.0 related routines live in this file.
4 Copyright (C) 1992, 1996, 1999, 2000, 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>
62 #include <servers/machid_lib.h>
64 #define MACH_TYPE_TASK 1
65 #define MACH_TYPE_THREAD 2
68 /* Included only for signal names and NSIG
70 * note: There are many problems in signal handling with
71 * gdb in Mach 3.0 in general.
74 #define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
78 /* This is what a cproc looks like. This is here partly because
79 cthread_internals.h is not a header we can just #include, partly with
80 an eye towards perhaps getting this to work with cross-debugging
81 someday. Best solution is if CMU publishes a real interface to this
83 #define CPROC_NEXT_OFFSET 0
84 #define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
85 #define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
86 #define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
87 #define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
88 #define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
89 #define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
90 #define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
91 #define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
92 #define CPROC_REPLY_SIZE (sizeof (mach_port_t))
93 #define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
94 #define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
95 #define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
96 #define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
97 #define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
98 #define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
99 #define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
100 #define CPROC_WIRED_SIZE (sizeof (mach_port_t))
101 #define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
102 #define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
103 #define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
104 #define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
105 #define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
106 #define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
107 #define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
108 #define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
109 #define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
111 /* Values for the state field in the cproc. */
112 #define CPROC_RUNNING 0
113 #define CPROC_SWITCHING 1
114 #define CPROC_BLOCKED 2
115 #define CPROC_CONDWAIT 4
117 /* For cproc and kernel thread mapping */
118 typedef struct gdb_thread
124 boolean_t in_emulator
;
127 /* This is for the mthreads list. It points to the cproc list.
128 Perhaps the two lists should be merged (or perhaps it was a mistake
129 to make them both use a struct gdb_thread). */
130 struct gdb_thread
*cproc
;
132 /* These are for the cproc list, which is linked through the next field
133 of the struct gdb_thread. */
134 char raw_cproc
[CPROC_SIZE
];
135 /* The cthread which is pointed to by the incarnation field from the
136 cproc. This points to the copy we've read into GDB. */
138 /* Point back to the mthreads list. */
140 struct gdb_thread
*next
;
145 * Actions for Mach exceptions.
147 * sigmap field maps the exception to corresponding Unix signal.
149 * I do not know how to map the exception to unix signal
150 * if SIG_UNKNOWN is specified.
153 struct exception_list
163 "not_mach3_exception", FALSE
, TRUE
, SIG_UNKNOWN
167 "EXC_BAD_ACCESS", FALSE
, TRUE
, SIGSEGV
171 "EXC_BAD_INSTRUCTION", FALSE
, TRUE
, SIGILL
175 "EXC_ARITHMETIC", FALSE
, TRUE
, SIGFPE
179 "EXC_EMULATION", FALSE
, TRUE
, SIGEMT
183 "EXC_SOFTWARE", FALSE
, TRUE
, SIG_UNKNOWN
187 "EXC_BREAKPOINT", FALSE
, FALSE
, SIGTRAP
191 /* Mach exception table size */
192 int max_exception
= sizeof (exception_map
) / sizeof (struct exception_list
) - 1;
194 #define MAX_EXCEPTION max_exception
196 WAITTYPE wait_status
;
198 /* If you define this, intercepted bsd server calls will be
199 * dumped while waiting the inferior to EXEC the correct
202 /* #define DUMP_SYSCALL /* debugging interceptor */
204 /* xx_debug() outputs messages if this is nonzero.
205 * If > 1, DUMP_SYSCALL will dump message contents.
209 /* "Temporary" debug stuff */
211 xx_debug (char *fmt
, int a
, int b
, int c
)
214 warning (fmt
, a
, b
, c
);
217 /* This is in libmach.a */
218 extern mach_port_t name_server_port
;
220 /* Set in catch_exception_raise */
221 int stop_exception
, stop_code
, stop_subcode
;
222 int stopped_in_exception
;
224 /* Thread that was the active thread when we stopped */
225 thread_t stop_thread
= MACH_PORT_NULL
;
229 /* Set when task is attached or created */
230 boolean_t emulator_present
= FALSE
;
232 task_t inferior_task
;
233 thread_t current_thread
;
235 /* Exception ports for inferior task */
236 mach_port_t inferior_exception_port
= MACH_PORT_NULL
;
237 mach_port_t inferior_old_exception_port
= MACH_PORT_NULL
;
239 /* task exceptions and notifications */
240 mach_port_t inferior_wait_port_set
= MACH_PORT_NULL
;
241 mach_port_t our_notify_port
= MACH_PORT_NULL
;
243 /* This is "inferior_wait_port_set" when not single stepping, and
244 * "singlestepped_thread_port" when we are single stepping.
246 * This is protected by a cleanup function: discard_single_step()
248 mach_port_t currently_waiting_for
= MACH_PORT_NULL
;
250 /* A port for external messages to gdb.
251 * External in the meaning that they do not come
252 * from the inferior_task, but rather from external
255 * As a debugging feature:
256 * A debugger debugging another debugger can stop the
257 * inferior debugger by the following command sequence
258 * (without running external programs)
260 * (top-gdb) set stop_inferior_gdb ()
263 mach_port_t our_message_port
= MACH_PORT_NULL
;
265 /* For single stepping */
266 mach_port_t thread_exception_port
= MACH_PORT_NULL
;
267 mach_port_t thread_saved_exception_port
= MACH_PORT_NULL
;
268 mach_port_t singlestepped_thread_port
= MACH_PORT_NULL
;
270 /* For machid calls */
271 mach_port_t mid_server
= MACH_PORT_NULL
;
272 mach_port_t mid_auth
= MACH_PORT_NULL
;
274 /* If gdb thinks the inferior task is not suspended, it
275 * must take suspend/abort the threads when it reads the state.
277 int must_suspend_thread
= 0;
279 /* When single stepping, we switch the port that mach_really_wait() listens to.
280 * This cleanup is a guard to prevent the port set from being left to
281 * the singlestepped_thread_port when error() is called.
282 * This is nonzero only when we are single stepping.
284 #define NULL_CLEANUP (struct cleanup *)0
285 struct cleanup
*cleanup_step
= NULL_CLEANUP
;
288 static struct target_ops m3_ops
;
290 static void m3_kill_inferior ();
293 #define MACH_TYPE_EXCEPTION_PORT -1
296 /* Chain of ports to remember requested notifications. */
300 struct port_chain
*next
;
303 int mid
; /* Now only valid with MACH_TYPE_THREAD and */
304 /* MACH_TYPE_THREAD */
306 typedef struct port_chain
*port_chain_t
;
308 /* Room for chain nodes comes from pchain_obstack */
309 struct obstack pchain_obstack
;
310 struct obstack
*port_chain_obstack
= &pchain_obstack
;
312 /* For thread handling */
313 struct obstack Cproc_obstack
;
314 struct obstack
*cproc_obstack
= &Cproc_obstack
;
316 /* the list of notified ports */
317 port_chain_t notify_chain
= (port_chain_t
) NULL
;
320 port_chain_insert (port_chain_t list
, mach_port_t name
, int type
)
326 if (!MACH_PORT_VALID (name
))
329 if (type
== MACH_TYPE_TASK
|| type
== MACH_TYPE_THREAD
)
331 if (!MACH_PORT_VALID (mid_server
))
333 warning ("Machid server port invalid, can not map port 0x%x to MID",
339 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
341 if (ret
!= KERN_SUCCESS
)
343 warning ("Can not map name (0x%x) to MID with machid", name
);
349 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
351 new = (port_chain_t
) obstack_alloc (port_chain_obstack
,
352 sizeof (struct port_chain
));
362 port_chain_delete (port_chain_t list
, mach_port_t elem
)
365 if (list
->port
== elem
)
370 if (list
->next
->port
== elem
)
371 list
->next
= list
->next
->next
; /* GCd with obstack_free() */
379 port_chain_destroy (struct obstack
*ostack
)
381 obstack_free (ostack
, 0);
382 obstack_init (ostack
);
386 port_chain_member (port_chain_t list
, mach_port_t elem
)
390 if (list
->port
== elem
)
394 return (port_chain_t
) NULL
;
398 map_port_name_to_mid (mach_port_t name
, int type
)
402 if (!MACH_PORT_VALID (name
))
405 elem
= port_chain_member (notify_chain
, name
);
407 if (elem
&& (elem
->type
== type
))
413 if (!MACH_PORT_VALID (mid_server
))
415 warning ("Machid server port invalid, can not map port 0x%x to mid",
424 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
426 if (ret
!= KERN_SUCCESS
)
428 warning ("Can not map name (0x%x) to mid with machid", name
);
435 /* Guard for currently_waiting_for and singlestepped_thread_port */
437 discard_single_step (thread_t thread
)
439 currently_waiting_for
= inferior_wait_port_set
;
441 cleanup_step
= NULL_CLEANUP
;
442 if (MACH_PORT_VALID (thread
) && MACH_PORT_VALID (singlestepped_thread_port
))
443 setup_single_step (thread
, FALSE
);
446 setup_single_step (thread_t thread
, boolean_t start_step
)
450 if (!MACH_PORT_VALID (thread
))
451 error ("Invalid thread supplied to setup_single_step");
456 /* Get the current thread exception port */
457 ret
= thread_get_exception_port (thread
, &teport
);
458 CHK ("Getting thread's exception port", ret
);
462 if (MACH_PORT_VALID (singlestepped_thread_port
))
464 warning ("Singlestepped_thread_port (0x%x) is still valid?",
465 singlestepped_thread_port
);
466 singlestepped_thread_port
= MACH_PORT_NULL
;
469 /* If we are already stepping this thread */
470 if (MACH_PORT_VALID (teport
) && teport
== thread_exception_port
)
472 ret
= mach_port_deallocate (mach_task_self (), teport
);
473 CHK ("Could not deallocate thread exception port", ret
);
477 ret
= thread_set_exception_port (thread
, thread_exception_port
);
478 CHK ("Setting exception port for thread", ret
);
480 /* Insert thread exception port to wait port set */
481 ret
= mach_port_move_member (mach_task_self (),
482 thread_exception_port
,
483 inferior_wait_port_set
);
484 CHK ("Moving thread exception port to inferior_wait_port_set",
487 thread_saved_exception_port
= teport
;
490 thread_trace (thread
, TRUE
);
492 singlestepped_thread_port
= thread_exception_port
;
493 currently_waiting_for
= singlestepped_thread_port
;
494 cleanup_step
= make_cleanup (discard_single_step
, thread
);
498 if (!MACH_PORT_VALID (teport
))
499 error ("Single stepped thread had an invalid exception port?");
501 if (teport
!= thread_exception_port
)
502 error ("Single stepped thread had an unknown exception port?");
504 ret
= mach_port_deallocate (mach_task_self (), teport
);
505 CHK ("Couldn't deallocate thread exception port", ret
);
507 /* Remove thread exception port from wait port set */
508 ret
= mach_port_move_member (mach_task_self (),
509 thread_exception_port
,
511 CHK ("Removing thread exception port from inferior_wait_port_set",
514 /* Restore thread's old exception port */
515 ret
= thread_set_exception_port (thread
,
516 thread_saved_exception_port
);
517 CHK ("Restoring stepped thread's exception port", ret
);
519 if (MACH_PORT_VALID (thread_saved_exception_port
))
520 (void) mach_port_deallocate (mach_task_self (),
521 thread_saved_exception_port
);
523 thread_trace (thread
, FALSE
);
525 singlestepped_thread_port
= MACH_PORT_NULL
;
526 currently_waiting_for
= inferior_wait_port_set
;
528 discard_cleanups (cleanup_step
);
534 request_notify (mach_port_t name
, mach_msg_id_t variant
, int type
)
537 mach_port_t previous_port_dummy
= MACH_PORT_NULL
;
539 if (!MACH_PORT_VALID (name
))
542 if (port_chain_member (notify_chain
, name
))
545 ret
= mach_port_request_notification (mach_task_self (),
550 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
551 &previous_port_dummy
);
552 CHK ("Serious: request_notify failed", ret
);
554 (void) mach_port_deallocate (mach_task_self (),
555 previous_port_dummy
);
557 notify_chain
= port_chain_insert (notify_chain
, name
, type
);
560 reverse_msg_bits (mach_msg_header_t
*msgp
, int type
)
563 rbits
= MACH_MSGH_BITS_REMOTE (msgp
->msgh_bits
);
566 (msgp
->msgh_bits
& ~MACH_MSGH_BITS_PORTS_MASK
) |
567 MACH_MSGH_BITS (lbits
, rbits
);
570 /* On the third day He said:
573 and then it was global.
575 When creating the inferior fork, the
576 child code in inflow.c sets the name of the
577 bootstrap_port in its address space to this
580 The name is transferred to our address space
581 with mach3_read_inferior().
583 Thou shalt not do this with
584 task_get_bootstrap_port() in this task, since
585 the name in the inferior task is different than
588 For blessed are the meek, as they shall inherit
591 mach_port_t original_server_port_name
= MACH_PORT_NULL
;
594 /* Called from inferior after FORK but before EXEC */
600 /* Get the NAME of the bootstrap port in this task
601 so that GDB can read it */
602 ret
= task_get_bootstrap_port (mach_task_self (),
603 &original_server_port_name
);
604 if (ret
!= KERN_SUCCESS
)
605 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
606 ret
= mach_port_deallocate (mach_task_self (),
607 original_server_port_name
);
608 if (ret
!= KERN_SUCCESS
)
609 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
611 /* Suspend this task to let the parent change my ports.
612 Resumed by the debugger */
613 ret
= task_suspend (mach_task_self ());
614 if (ret
!= KERN_SUCCESS
)
615 internal_error (__FILE__
, __LINE__
, "failed internal consistency check");
619 * Intercept system calls to Unix server.
620 * After EXEC_COUNTER calls to exec(), return.
622 * Pre-assertion: Child is suspended. (Not verified)
623 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
627 intercept_exec_calls (int exec_counter
)
629 int terminal_initted
= 0;
633 mach_msg_header_t header
;
634 mach_msg_type_t type
;
635 char room
[2000]; /* Enuff space */
638 struct syscall_msg_t syscall_in
, syscall_out
;
640 mach_port_t fake_server
;
641 mach_port_t original_server_send
;
642 mach_port_t original_exec_reply
;
643 mach_port_t exec_reply
;
644 mach_port_t exec_reply_send
;
645 mach_msg_type_name_t acquired
;
646 mach_port_t emulator_server_port_name
;
647 struct task_basic_info info
;
648 mach_msg_type_number_t info_count
;
652 if (exec_counter
<= 0)
653 return; /* We are already set up in the correct program */
655 ret
= mach_port_allocate (mach_task_self (),
656 MACH_PORT_RIGHT_RECEIVE
,
658 CHK ("create inferior_fake_server port failed", ret
);
660 /* Wait for inferior_task to suspend itself */
663 info_count
= sizeof (info
);
664 ret
= task_info (inferior_task
,
666 (task_info_t
) & info
,
668 CHK ("Task info", ret
);
670 if (info
.suspend_count
)
673 /* Note that the definition of the parameter was undefined
674 * at the time of this writing, so I just use an `ad hoc' value.
676 (void) swtch_pri (42); /* Universal Priority Value */
679 /* Read the inferior's bootstrap port name */
680 if (!mach3_read_inferior (&original_server_port_name
,
681 &original_server_port_name
,
682 sizeof (original_server_port_name
)))
683 error ("Can't read inferior task bootstrap port name");
685 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
686 /* Should get refs, and set them back when restoring */
687 /* Steal the original bsd server send right from inferior */
688 ret
= mach_port_extract_right (inferior_task
,
689 original_server_port_name
,
690 MACH_MSG_TYPE_MOVE_SEND
,
691 &original_server_send
,
693 CHK ("mach_port_extract_right (bsd server send)", ret
);
695 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
696 error ("Incorrect right extracted, send right to bsd server expected");
698 ret
= mach_port_insert_right (inferior_task
,
699 original_server_port_name
,
701 MACH_MSG_TYPE_MAKE_SEND
);
702 CHK ("mach_port_insert_right (fake server send)", ret
);
704 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
706 original_server_port_name
, original_server_send
);
708 /* A receive right to the reply generated by unix server exec() request */
709 ret
= mach_port_allocate (mach_task_self (),
710 MACH_PORT_RIGHT_RECEIVE
,
712 CHK ("create intercepted_reply_port port failed", ret
);
714 /* Pass this send right to Unix server so it replies to us after exec() */
715 ret
= mach_port_extract_right (mach_task_self (),
717 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
720 CHK ("mach_port_extract_right (exec_reply)", ret
);
722 if (acquired
!= MACH_MSG_TYPE_PORT_SEND_ONCE
)
723 error ("Incorrect right extracted, send once expected for exec reply");
725 ret
= mach_port_move_member (mach_task_self (),
727 inferior_wait_port_set
);
728 CHK ("Moving fake syscall port to inferior_wait_port_set", ret
);
730 xx_debug ("syscall fake server set up, resuming inferior\n");
732 ret
= task_resume (inferior_task
);
733 CHK ("task_resume (startup)", ret
);
735 /* Read requests from the inferior.
736 Pass directly through everything else except exec() calls.
738 while (exec_counter
> 0)
740 ret
= mach_msg (&syscall_in
.header
, /* header */
741 MACH_RCV_MSG
, /* options */
743 sizeof (struct syscall_msg_t
), /* receive size */
744 inferior_wait_port_set
, /* receive_name */
745 MACH_MSG_TIMEOUT_NONE
,
747 CHK ("mach_msg (intercepted sycall)", ret
);
750 print_msg (&syscall_in
.header
);
753 /* ASSERT : msgh_local_port == fake_server */
755 if (notify_server (&syscall_in
.header
, &syscall_out
.header
))
756 error ("received a notify while intercepting syscalls");
758 if (syscall_in
.header
.msgh_id
== MIG_EXEC_SYSCALL_ID
)
760 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter
);
761 if (exec_counter
== 1)
763 original_exec_reply
= syscall_in
.header
.msgh_remote_port
;
764 syscall_in
.header
.msgh_remote_port
= exec_reply_send
;
767 if (!terminal_initted
)
769 /* Now that the child has exec'd we know it has already set its
770 process group. On POSIX systems, tcsetpgrp will fail with
771 EPERM if we try it before the child's setpgid. */
773 /* Set up the "saved terminal modes" of the inferior
774 based on what modes we are starting it with. */
775 target_terminal_init ();
777 /* Install inferior's terminal modes. */
778 target_terminal_inferior ();
780 terminal_initted
= 1;
786 syscall_in
.header
.msgh_local_port
= syscall_in
.header
.msgh_remote_port
;
787 syscall_in
.header
.msgh_remote_port
= original_server_send
;
789 reverse_msg_bits (&syscall_in
.header
, MACH_MSG_TYPE_COPY_SEND
);
791 ret
= mach_msg_send (&syscall_in
.header
);
792 CHK ("Forwarded syscall", ret
);
795 ret
= mach_port_move_member (mach_task_self (),
798 CHK ("Moving fake syscall out of inferior_wait_port_set", ret
);
800 ret
= mach_port_move_member (mach_task_self (),
802 inferior_wait_port_set
);
803 CHK ("Moving exec_reply to inferior_wait_port_set", ret
);
805 ret
= mach_msg (&syscall_in
.header
, /* header */
806 MACH_RCV_MSG
, /* options */
808 sizeof (struct syscall_msg_t
), /* receive size */
809 inferior_wait_port_set
, /* receive_name */
810 MACH_MSG_TIMEOUT_NONE
,
812 CHK ("mach_msg (exec reply)", ret
);
814 ret
= task_suspend (inferior_task
);
815 CHK ("Suspending inferior after last exec", ret
);
817 must_suspend_thread
= 0;
819 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
822 print_msg (&syscall_in
.header
);
825 /* Message should appear as if it came from the unix server */
826 syscall_in
.header
.msgh_local_port
= MACH_PORT_NULL
;
828 /* and go to the inferior task original reply port */
829 syscall_in
.header
.msgh_remote_port
= original_exec_reply
;
831 reverse_msg_bits (&syscall_in
.header
, MACH_MSG_TYPE_MOVE_SEND_ONCE
);
833 ret
= mach_msg_send (&syscall_in
.header
);
834 CHK ("Forwarding exec reply to inferior", ret
);
836 /* Garbage collect */
837 ret
= mach_port_deallocate (inferior_task
,
838 original_server_port_name
);
839 CHK ("deallocating fake server send right", ret
);
841 ret
= mach_port_insert_right (inferior_task
,
842 original_server_port_name
,
843 original_server_send
,
844 MACH_MSG_TYPE_MOVE_SEND
);
845 CHK ("Restoring the original bsd server send right", ret
);
847 ret
= mach_port_destroy (mach_task_self (),
849 fake_server
= MACH_PORT_DEAD
;
850 CHK ("mach_port_destroy (fake_server)", ret
);
852 ret
= mach_port_destroy (mach_task_self (),
854 exec_reply
= MACH_PORT_DEAD
;
855 CHK ("mach_port_destroy (exec_reply)", ret
);
857 xx_debug ("Done with exec call interception\n");
861 consume_send_rights (thread_array_t thread_list
, int thread_count
)
868 for (index
= 0; index
< thread_count
; index
++)
870 /* Since thread kill command kills threads, don't check ret */
871 (void) mach_port_deallocate (mach_task_self (),
876 /* suspend/abort/resume a thread. */
877 setup_thread (mach_port_t thread
, int what
)
883 ret
= thread_suspend (thread
);
884 CHK ("setup_thread thread_suspend", ret
);
886 ret
= thread_abort (thread
);
887 CHK ("setup_thread thread_abort", ret
);
891 ret
= thread_resume (thread
);
892 CHK ("setup_thread thread_resume", ret
);
897 map_slot_to_mid (int slot
, thread_array_t threads
, int thread_count
)
907 ret
= task_threads (inferior_task
, &threads
, &thread_count
);
908 CHK ("Can not select a thread from a dead task", ret
);
911 if (slot
< 0 || slot
>= thread_count
)
915 consume_send_rights (threads
, thread_count
);
916 (void) vm_deallocate (mach_task_self (), (vm_address_t
) threads
,
917 (thread_count
* sizeof (mach_port_t
)));
920 error ("invalid slot number");
925 mid
= map_port_name_to_mid (threads
[slot
], MACH_TYPE_THREAD
);
929 consume_send_rights (threads
, thread_count
);
930 (void) vm_deallocate (mach_task_self (), (vm_address_t
) threads
,
931 (thread_count
* sizeof (mach_port_t
)));
938 parse_thread_id (char *arg
, int thread_count
, int slots
)
948 while (*arg
&& (*arg
== ' ' || *arg
== '\t'))
954 /* Currently parse MID and @SLOTNUMBER */
959 error ("valid thread mid expected");
967 error ("invalid slot number");
969 /* If you want slot numbers to remain slot numbers, set slots.
971 * Well, since 0 is reserved, return the ordinal number
972 * of the thread rather than the slot number. Awk, this
973 * counts as a kludge.
978 if (thread_count
&& slot
>= thread_count
)
981 mid
= map_slot_to_mid (slot
);
986 /* THREAD_ID 0 is special; it selects the first kernel
987 * thread from the list (i.e. SLOTNUMBER 0)
988 * This is used when starting the program with 'run' or when attaching.
990 * If FLAG is 0 the context is not changed, and the registers, frame, etc
991 * will continue to describe the old thread.
993 * If FLAG is nonzero, really select the thread.
994 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
998 select_thread (mach_port_t task
, int thread_id
, int flag
)
1000 thread_array_t thread_list
;
1004 thread_t new_thread
= MACH_PORT_NULL
;
1007 error ("Can't select cprocs without kernel thread");
1009 ret
= task_threads (task
, &thread_list
, &thread_count
);
1010 if (ret
!= KERN_SUCCESS
)
1012 warning ("Can not select a thread from a dead task");
1013 m3_kill_inferior ();
1014 return KERN_FAILURE
;
1017 if (thread_count
== 0)
1019 /* The task can not do anything anymore, but it still
1020 * exists as a container for memory and ports.
1022 registers_changed ();
1023 warning ("Task %d has no threads",
1024 map_port_name_to_mid (task
, MACH_TYPE_TASK
));
1025 current_thread
= MACH_PORT_NULL
;
1026 (void) vm_deallocate (mach_task_self (),
1027 (vm_address_t
) thread_list
,
1028 (thread_count
* sizeof (mach_port_t
)));
1029 return KERN_FAILURE
;
1032 if (!thread_id
|| flag
== 2)
1034 /* First thread or a slotnumber */
1036 new_thread
= thread_list
[0];
1039 if (thread_id
< thread_count
)
1040 new_thread
= thread_list
[thread_id
];
1043 (void) vm_deallocate (mach_task_self (),
1044 (vm_address_t
) thread_list
,
1045 (thread_count
* sizeof (mach_port_t
)));
1046 error ("No such thread slot number : %d", thread_id
);
1052 for (index
= 0; index
< thread_count
; index
++)
1053 if (thread_id
== map_port_name_to_mid (thread_list
[index
],
1056 new_thread
= thread_list
[index
];
1062 error ("No thread with mid %d", thread_id
);
1065 /* Notify when the selected thread dies */
1066 request_notify (new_thread
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_THREAD
);
1068 ret
= vm_deallocate (mach_task_self (),
1069 (vm_address_t
) thread_list
,
1070 (thread_count
* sizeof (mach_port_t
)));
1071 CHK ("vm_deallocate", ret
);
1074 current_thread
= new_thread
;
1078 if (MACH_PORT_VALID (current_thread
))
1080 /* Store the gdb's view of the thread we are deselecting
1082 * @@ I think gdb updates registers immediately when they are
1083 * changed, so don't do this.
1085 ret
= thread_abort (current_thread
);
1086 CHK ("Could not abort system calls when saving state of old thread",
1088 target_prepare_to_store ();
1089 target_store_registers (-1);
1093 registers_changed ();
1095 current_thread
= new_thread
;
1097 ret
= thread_abort (current_thread
);
1098 CHK ("Could not abort system calls when selecting a thread", ret
);
1100 stop_pc
= read_pc ();
1101 flush_cached_frames ();
1103 select_frame (get_current_frame (), 0);
1106 return KERN_SUCCESS
;
1110 * Switch to use thread named NEW_THREAD.
1114 switch_to_thread (thread_t new_thread
)
1116 thread_t saved_thread
= current_thread
;
1119 mid
= map_port_name_to_mid (new_thread
,
1122 warning ("Can't map thread name 0x%x to mid", new_thread
);
1123 else if (select_thread (inferior_task
, mid
, 1) != KERN_SUCCESS
)
1126 current_thread
= saved_thread
;
1127 error ("Could not select thread %d", mid
);
1133 /* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1134 * Note that the registers are not yet valid in the inferior task.
1137 m3_trace_him (int pid
)
1141 push_target (&m3_ops
);
1143 inferior_task
= task_by_pid (pid
);
1145 if (!MACH_PORT_VALID (inferior_task
))
1146 error ("Can not map Unix pid %d to Mach task", pid
);
1148 /* Clean up previous notifications and create new ones */
1149 setup_notify_port (1);
1151 /* When notification appears, the inferior task has died */
1152 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
1154 emulator_present
= have_emulator_p (inferior_task
);
1156 /* By default, select the first thread,
1157 * If task has no threads, gives a warning
1158 * Does not fetch registers, since they are not yet valid.
1160 select_thread (inferior_task
, 0, 0);
1162 inferior_exception_port
= MACH_PORT_NULL
;
1164 setup_exception_port ();
1166 xx_debug ("Now the debugged task is created\n");
1168 /* One trap to exec the shell, one to exec the program being debugged. */
1169 intercept_exec_calls (2);
1174 setup_exception_port (void)
1178 ret
= mach_port_allocate (mach_task_self (),
1179 MACH_PORT_RIGHT_RECEIVE
,
1180 &inferior_exception_port
);
1181 CHK ("mach_port_allocate", ret
);
1183 /* add send right */
1184 ret
= mach_port_insert_right (mach_task_self (),
1185 inferior_exception_port
,
1186 inferior_exception_port
,
1187 MACH_MSG_TYPE_MAKE_SEND
);
1188 CHK ("mach_port_insert_right", ret
);
1190 ret
= mach_port_move_member (mach_task_self (),
1191 inferior_exception_port
,
1192 inferior_wait_port_set
);
1193 CHK ("mach_port_move_member", ret
);
1195 ret
= task_get_special_port (inferior_task
,
1196 TASK_EXCEPTION_PORT
,
1197 &inferior_old_exception_port
);
1198 CHK ("task_get_special_port(old exc)", ret
);
1200 ret
= task_set_special_port (inferior_task
,
1201 TASK_EXCEPTION_PORT
,
1202 inferior_exception_port
);
1203 CHK ("task_set_special_port", ret
);
1205 ret
= mach_port_deallocate (mach_task_self (),
1206 inferior_exception_port
);
1207 CHK ("mack_port_deallocate", ret
);
1210 /* When notify appears, the inferior_task's exception
1211 * port has been destroyed.
1213 * Not used, since the dead_name_notification already
1214 * appears when task dies.
1217 request_notify (inferior_exception_port
,
1218 MACH_NOTIFY_NO_SENDERS
,
1219 MACH_TYPE_EXCEPTION_PORT
);
1223 /* Nonzero if gdb is waiting for a message */
1224 int mach_really_waiting
;
1226 /* Wait for the inferior to stop for some reason.
1227 - Loop on notifications until inferior_task dies.
1228 - Loop on exceptions until stopped_in_exception comes true.
1229 (e.g. we receive a single step trace trap)
1230 - a message arrives to gdb's message port
1232 There is no other way to exit this loop.
1234 Returns the inferior_pid for rest of gdb.
1235 Side effects: Set *OURSTATUS. */
1237 mach_really_wait (int pid
, struct target_waitstatus
*ourstatus
)
1244 mach_msg_header_t header
;
1245 mach_msg_type_t foo
;
1250 /* Either notify (death), exception or message can stop the inferior */
1251 stopped_in_exception
= FALSE
;
1257 stop_exception
= stop_code
= stop_subcode
= -1;
1258 stop_thread
= MACH_PORT_NULL
;
1260 mach_really_waiting
= 1;
1261 ret
= mach_msg (&in_msg
.header
, /* header */
1262 MACH_RCV_MSG
, /* options */
1264 sizeof (struct msg
), /* receive size */
1265 currently_waiting_for
, /* receive name */
1266 MACH_MSG_TIMEOUT_NONE
,
1268 mach_really_waiting
= 0;
1269 CHK ("mach_msg (receive)", ret
);
1271 /* Check if we received a notify of the childs' death */
1272 if (notify_server (&in_msg
.header
, &out_msg
.header
))
1274 /* If inferior_task is null then the inferior has
1275 gone away and we want to return to command level.
1276 Otherwise it was just an informative message and we
1277 need to look to see if there are any more. */
1278 if (inferior_task
!= MACH_PORT_NULL
)
1282 /* Collect Unix exit status for gdb */
1284 wait3 (&w
, WNOHANG
, 0);
1286 /* This mess is here to check that the rest of
1287 * gdb knows that the inferior died. It also
1288 * tries to hack around the fact that Mach 3.0 (mk69)
1289 * unix server (ux28) does not always know what
1290 * has happened to it's children when mach-magic
1291 * is applied on them.
1293 if ((!WIFEXITED (w
) && WIFSTOPPED (w
)) ||
1294 (WIFEXITED (w
) && WEXITSTATUS (w
) > 0377))
1297 warning ("Using exit value 0 for terminated task");
1299 else if (!WIFEXITED (w
))
1301 int sig
= WTERMSIG (w
);
1303 /* Signals cause problems. Warn the user. */
1304 if (sig
!= SIGKILL
) /* Bad luck if garbage matches this */
1305 warning ("The terminating signal stuff may be nonsense");
1306 else if (sig
> NSIG
)
1309 warning ("Using exit value 0 for terminated task");
1312 store_waitstatus (ourstatus
, w
);
1313 return inferior_pid
;
1317 /* Hmm. Check for exception, as it was not a notification.
1318 exc_server() does an upcall to catch_exception_raise()
1319 if this rpc is an exception. Further actions are decided
1322 if (!exc_server (&in_msg
.header
, &out_msg
.header
))
1325 /* Not an exception, check for message.
1327 * Messages don't come from the inferior, or if they
1328 * do they better be asynchronous or it will hang.
1330 if (gdb_message_server (&in_msg
.header
))
1333 error ("Unrecognized message received in mach_really_wait");
1336 /* Send the reply of the exception rpc to the suspended task */
1337 ret
= mach_msg_send (&out_msg
.header
);
1338 CHK ("mach_msg_send (exc reply)", ret
);
1340 if (stopped_in_exception
)
1342 /* Get unix state. May be changed in mach3_exception_actions() */
1343 wait3 (&w
, WNOHANG
, 0);
1345 mach3_exception_actions (&w
, FALSE
, "Task");
1347 store_waitstatus (ourstatus
, w
);
1348 return inferior_pid
;
1353 /* Called by macro DO_QUIT() in utils.c(quit).
1354 * This is called just before calling error() to return to command level
1362 if (mach_really_waiting
)
1364 ret
= task_suspend (inferior_task
);
1366 if (ret
!= KERN_SUCCESS
)
1368 warning ("Could not suspend task for interrupt: %s",
1369 mach_error_string (ret
));
1370 mach_really_waiting
= 0;
1375 must_suspend_thread
= 0;
1376 mach_really_waiting
= 0;
1378 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1381 warning ("Selecting first existing kernel thread");
1385 current_thread
= MACH_PORT_NULL
; /* Force setup */
1386 select_thread (inferior_task
, mid
, 1);
1392 /* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
1394 /* If ^C is typed when we are waiting for a message
1395 * and your Unix server is able to notice that we
1398 * Called by REQUEST_QUIT() from utils.c(request_quit)
1401 mach3_request_quit (void)
1403 if (mach_really_waiting
)
1409 * Gdb message server.
1410 * Currently implemented is the STOP message, that causes
1411 * gdb to return to the command level like ^C had been typed from terminal.
1414 gdb_message_server (mach_msg_header_t
*InP
)
1419 if (InP
->msgh_local_port
== our_message_port
)
1421 /* A message coming to our_message_port. Check validity */
1422 switch (InP
->msgh_id
)
1425 case GDB_MESSAGE_ID_STOP
:
1426 ret
= task_suspend (inferior_task
);
1427 if (ret
!= KERN_SUCCESS
)
1428 warning ("Could not suspend task for stop message: %s",
1429 mach_error_string (ret
));
1431 /* QUIT in mach_really_wait() loop. */
1436 warning ("Invalid message id %d received, ignored.",
1444 /* Message not handled by this server */
1448 /* NOTE: This is not an RPC call. It is a simpleroutine.
1450 * This is not called from this gdb code.
1452 * It may be called by another debugger to cause this
1453 * debugger to enter command level:
1455 * (gdb) set stop_inferior_gdb ()
1458 * External program "stop-gdb" implements this also.
1461 stop_inferior_gdb (void)
1465 /* Code generated by mig, with minor cleanups :-)
1467 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1472 mach_msg_header_t Head
;
1478 register Request
*InP
= &Mess
;
1480 InP
->Head
.msgh_bits
= MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND
, 0);
1482 /* msgh_size passed as argument */
1483 InP
->Head
.msgh_remote_port
= our_message_port
;
1484 InP
->Head
.msgh_local_port
= MACH_PORT_NULL
;
1485 InP
->Head
.msgh_seqno
= 0;
1486 InP
->Head
.msgh_id
= GDB_MESSAGE_ID_STOP
;
1488 ret
= mach_msg (&InP
->Head
,
1489 MACH_SEND_MSG
| MACH_MSG_OPTION_NONE
,
1493 MACH_MSG_TIMEOUT_NONE
,
1497 #ifdef THREAD_ALLOWED_TO_BREAK
1499 * Return 1 if the MID specifies the thread that caused the
1501 * Since catch_exception_raise() selects the thread causing
1502 * the last exception to current_thread, we just check that
1503 * it is selected and the last exception was a breakpoint.
1506 mach_thread_for_breakpoint (int mid
)
1508 int cmid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1512 mid
= map_slot_to_mid (-(mid
+ 1), 0, 0);
1514 return 0; /* Don't stop, no such slot */
1517 if (!mid
|| cmid
== -1)
1518 return 1; /* stop */
1520 return cmid
== mid
&& stop_exception
== EXC_BREAKPOINT
;
1522 #endif /* THREAD_ALLOWED_TO_BREAK */
1524 #ifdef THREAD_PARSE_ID
1526 * Map a thread id string (MID or a @SLOTNUMBER)
1529 * 0 matches all threads.
1530 * Otherwise the meaning is defined only in this file.
1531 * (mach_thread_for_breakpoint uses it)
1533 * @@ This allows non-existent MIDs to be specified.
1534 * It now also allows non-existent slots to be
1535 * specified. (Slot numbers stored are negative,
1536 * and the magnitude is one greater than the actual
1537 * slot index. (Since 0 is reserved))
1540 mach_thread_parse_id (char *arg
)
1544 error ("thread id expected");
1545 mid
= parse_thread_id (arg
, 0, 1);
1549 #endif /* THREAD_PARSE_ID */
1551 #ifdef THREAD_OUTPUT_ID
1553 mach_thread_output_id (int mid
)
1555 static char foobar
[20];
1558 sprintf (foobar
, "mid %d", mid
);
1560 sprintf (foobar
, "@%d", -(mid
+ 1));
1562 sprintf (foobar
, "*any thread*");
1566 #endif /* THREAD_OUTPUT_ID */
1568 /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
1570 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1572 * if SELECT_IT is nonzero, reselect the thread that was active when
1573 * we stopped at a breakpoint.
1577 mach3_prepare_to_proceed (int select_it
)
1580 stop_thread
!= current_thread
&&
1581 stop_exception
== EXC_BREAKPOINT
)
1588 mid
= switch_to_thread (stop_thread
);
1596 /* this stuff here is an upcall via libmach/excServer.c
1597 and mach_really_wait which does the actual upcall.
1599 The code will pass the exception to the inferior if:
1601 - The task that signaled is not the inferior task
1602 (e.g. when debugging another debugger)
1604 - The user has explicitely requested to pass on the exceptions.
1605 (e.g to the default unix exception handler, which maps
1606 exceptions to signals, or the user has her own exception handler)
1608 - If the thread that signaled is being single-stepped and it
1609 has set it's own exception port and the exception is not
1610 EXC_BREAKPOINT. (Maybe this is not desirable?)
1614 catch_exception_raise (mach_port_t port
, thread_t thread
, task_t task
,
1615 int exception
, int code
, int subcode
)
1618 boolean_t signal_thread
;
1619 int mid
= map_port_name_to_mid (thread
, MACH_TYPE_THREAD
);
1621 if (!MACH_PORT_VALID (thread
))
1623 /* If the exception was sent and thread dies before we
1624 receive it, THREAD will be MACH_PORT_DEAD
1627 current_thread
= thread
= MACH_PORT_NULL
;
1628 error ("Received exception from nonexistent thread");
1631 /* Check if the task died in transit.
1632 * @@ Isn't the thread also invalid in such case?
1634 if (!MACH_PORT_VALID (task
))
1636 current_thread
= thread
= MACH_PORT_NULL
;
1637 error ("Received exception from nonexistent task");
1640 if (exception
< 0 || exception
> MAX_EXCEPTION
)
1641 internal_error (__FILE__
, __LINE__
,
1642 "catch_exception_raise: unknown exception code %d thread %d",
1646 if (!MACH_PORT_VALID (inferior_task
))
1647 error ("got an exception, but inferior_task is null or dead");
1649 stop_exception
= exception
;
1651 stop_subcode
= subcode
;
1652 stop_thread
= thread
;
1654 signal_thread
= exception
!= EXC_BREAKPOINT
&&
1655 port
== singlestepped_thread_port
&&
1656 MACH_PORT_VALID (thread_saved_exception_port
);
1658 /* If it was not our inferior or if we want to forward
1659 * the exception to the inferior's handler, do it here
1661 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1663 if (task
!= inferior_task
||
1665 exception_map
[exception
].forward
)
1667 mach_port_t eport
= inferior_old_exception_port
;
1672 GDB now forwards the exeption to thread's original handler,
1673 since the user propably knows what he is doing.
1674 Give a message, though.
1677 mach3_exception_actions ((WAITTYPE
*) NULL
, TRUE
, "Thread");
1678 eport
= thread_saved_exception_port
;
1681 /* Send the exception to the original handler */
1682 ret
= exception_raise (eport
,
1689 (void) mach_port_deallocate (mach_task_self (), task
);
1690 (void) mach_port_deallocate (mach_task_self (), thread
);
1692 /* If we come here, we don't want to trace any more, since we
1693 * will never stop for tracing anyway.
1695 discard_single_step (thread
);
1697 /* Do not stop the inferior */
1701 /* Now gdb handles the exception */
1702 stopped_in_exception
= TRUE
;
1704 ret
= task_suspend (task
);
1705 CHK ("Error suspending inferior after exception", ret
);
1707 must_suspend_thread
= 0;
1709 if (current_thread
!= thread
)
1711 if (MACH_PORT_VALID (singlestepped_thread_port
))
1712 /* Cleanup discards single stepping */
1713 error ("Exception from thread %d while singlestepping thread %d",
1715 map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
));
1717 /* Then select the thread that caused the exception */
1718 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
1719 error ("Could not select thread %d causing exception", mid
);
1721 warning ("Gdb selected thread %d", mid
);
1724 /* If we receive an exception that is not breakpoint
1725 * exception, we interrupt the single step and return to
1726 * debugger. Trace condition is cleared.
1728 if (MACH_PORT_VALID (singlestepped_thread_port
))
1730 if (stop_exception
!= EXC_BREAKPOINT
)
1731 warning ("Single step interrupted by exception");
1732 else if (port
== singlestepped_thread_port
)
1734 /* Single step exception occurred, remove trace bit
1735 * and return to gdb.
1737 if (!MACH_PORT_VALID (current_thread
))
1738 error ("Single stepped thread is not valid");
1740 /* Resume threads, but leave the task suspended */
1741 resume_all_threads (0);
1744 warning ("Breakpoint while single stepping?");
1746 discard_single_step (current_thread
);
1749 (void) mach_port_deallocate (mach_task_self (), task
);
1750 (void) mach_port_deallocate (mach_task_self (), thread
);
1752 return KERN_SUCCESS
;
1756 port_valid (mach_port_t port
, int mask
)
1759 mach_port_type_t type
;
1761 ret
= mach_port_type (mach_task_self (),
1764 if (ret
!= KERN_SUCCESS
|| (type
& mask
) != mask
)
1769 /* @@ No vm read cache implemented yet */
1770 boolean_t vm_read_cache_valid
= FALSE
;
1773 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1774 * in gdb's address space.
1776 * Return 0 on failure; number of bytes read otherwise.
1779 mach3_read_inferior (CORE_ADDR addr
, char *myaddr
, int length
)
1782 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1783 vm_size_t aligned_length
=
1784 (vm_size_t
) round_page (addr
+ length
) - low_address
;
1785 pointer_t copied_memory
;
1788 /* Get memory from inferior with page aligned addresses */
1789 ret
= vm_read (inferior_task
,
1794 if (ret
!= KERN_SUCCESS
)
1796 /* the problem is that the inferior might be killed for whatever reason
1797 * before we go to mach_really_wait. This is one place that ought to
1798 * catch many of those errors.
1799 * @@ A better fix would be to make all external events to GDB
1800 * to arrive via a SINGLE port set. (Including user input!)
1803 if (!port_valid (inferior_task
, MACH_PORT_TYPE_SEND
))
1805 m3_kill_inferior ();
1806 error ("Inferior killed (task port invalid)");
1812 /* valprint.c gives nicer format if this does not
1813 screw it. Eamonn seems to like this, so I enable
1814 it if OSF is defined...
1816 warning ("[read inferior %x failed: %s]",
1817 addr
, mach_error_string (ret
));
1824 memcpy (myaddr
, (char *) addr
- low_address
+ copied_memory
, length
);
1826 ret
= vm_deallocate (mach_task_self (),
1829 CHK ("mach3_read_inferior vm_deallocate failed", ret
);
1835 #define CHK_GOTO_OUT(str,ret) \
1836 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
1838 #define CHK_GOTO_OUT(str,ret) \
1839 do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
1842 struct vm_region_list
1844 struct vm_region_list
*next
;
1845 vm_prot_t protection
;
1850 struct obstack region_obstack
;
1853 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1854 * in gdb's address space.
1857 mach3_write_inferior (CORE_ADDR addr
, char *myaddr
, int length
)
1860 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1861 vm_size_t aligned_length
=
1862 (vm_size_t
) round_page (addr
+ length
) - low_address
;
1863 pointer_t copied_memory
;
1867 char *errstr
= "Bug in mach3_write_inferior";
1869 struct vm_region_list
*region_element
;
1870 struct vm_region_list
*region_head
= (struct vm_region_list
*) NULL
;
1872 /* Get memory from inferior with page aligned addresses */
1873 ret
= vm_read (inferior_task
,
1878 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret
);
1882 memcpy ((char *) addr
- low_address
+ copied_memory
, myaddr
, length
);
1884 obstack_init (®ion_obstack
);
1886 /* Do writes atomically.
1887 * First check for holes and unwritable memory.
1890 vm_size_t remaining_length
= aligned_length
;
1891 vm_address_t region_address
= low_address
;
1893 struct vm_region_list
*scan
;
1895 while (region_address
< low_address
+ aligned_length
)
1897 vm_prot_t protection
;
1898 vm_prot_t max_protection
;
1899 vm_inherit_t inheritance
;
1901 mach_port_t object_name
;
1903 vm_size_t region_length
= remaining_length
;
1904 vm_address_t old_address
= region_address
;
1906 ret
= vm_region (inferior_task
,
1915 CHK_GOTO_OUT ("vm_region failed", ret
);
1917 /* Check for holes in memory */
1918 if (old_address
!= region_address
)
1920 warning ("No memory at 0x%x. Nothing written",
1927 if (!(max_protection
& VM_PROT_WRITE
))
1929 warning ("Memory at address 0x%x is unwritable. Nothing written",
1936 /* Chain the regions for later use */
1938 (struct vm_region_list
*)
1939 obstack_alloc (®ion_obstack
, sizeof (struct vm_region_list
));
1941 region_element
->protection
= protection
;
1942 region_element
->start
= region_address
;
1943 region_element
->length
= region_length
;
1945 /* Chain the regions along with protections */
1946 region_element
->next
= region_head
;
1947 region_head
= region_element
;
1949 region_address
+= region_length
;
1950 remaining_length
= remaining_length
- region_length
;
1953 /* If things fail after this, we give up.
1954 * Somebody is messing up inferior_task's mappings.
1957 /* Enable writes to the chained vm regions */
1958 for (scan
= region_head
; scan
; scan
= scan
->next
)
1960 boolean_t protection_changed
= FALSE
;
1962 if (!(scan
->protection
& VM_PROT_WRITE
))
1964 ret
= vm_protect (inferior_task
,
1968 scan
->protection
| VM_PROT_WRITE
);
1969 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1973 ret
= vm_write (inferior_task
,
1977 CHK_GOTO_OUT ("vm_write failed", ret
);
1979 /* Set up the original region protections, if they were changed */
1980 for (scan
= region_head
; scan
; scan
= scan
->next
)
1982 boolean_t protection_changed
= FALSE
;
1984 if (!(scan
->protection
& VM_PROT_WRITE
))
1986 ret
= vm_protect (inferior_task
,
1991 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1999 obstack_free (®ion_obstack
, 0);
2001 (void) vm_deallocate (mach_task_self (),
2006 if (ret
!= KERN_SUCCESS
)
2008 warning ("%s %s", errstr
, mach_error_string (ret
));
2015 /* Return 0 on failure, number of bytes handled otherwise. TARGET is
2018 m3_xfer_memory (CORE_ADDR memaddr
, char *myaddr
, int len
, int write
,
2019 struct target_ops
*target
)
2024 result
= mach3_write_inferior (memaddr
, myaddr
, len
);
2026 result
= mach3_read_inferior (memaddr
, myaddr
, len
);
2033 translate_state (int state
)
2037 case TH_STATE_RUNNING
:
2039 case TH_STATE_STOPPED
:
2041 case TH_STATE_WAITING
:
2043 case TH_STATE_UNINTERRUPTIBLE
:
2045 case TH_STATE_HALTED
:
2053 translate_cstate (int state
)
2059 case CPROC_SWITCHING
:
2063 case CPROC_CONDWAIT
:
2065 case CPROC_CONDWAIT
| CPROC_SWITCHING
:
2072 /* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2074 mach_port_t
/* no mach_port_name_t found in include files. */
2075 map_inferior_port_name (mach_port_t inferior_name
, mach_msg_type_name_t type
)
2078 mach_msg_type_name_t acquired
;
2081 ret
= mach_port_extract_right (inferior_task
,
2086 CHK ("mach_port_extract_right (map_inferior_port_name)", ret
);
2088 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
2089 error ("Incorrect right extracted, (map_inferior_port_name)");
2091 ret
= mach_port_deallocate (mach_task_self (),
2093 CHK ("Deallocating mapped port (map_inferior_port_name)", ret
);
2099 * Naming convention:
2100 * Always return user defined name if found.
2101 * _K == A kernel thread with no matching CPROC
2102 * _C == A cproc with no current cthread
2103 * _t == A cthread with no user defined name
2105 * The digits that follow the _names are the SLOT number of the
2106 * kernel thread if there is such a thing, otherwise just a negation
2107 * of the sequential number of such cprocs.
2113 get_thread_name (gdb_thread_t one_cproc
, int id
)
2116 if (one_cproc
->cthread
== NULL
)
2118 /* cproc not mapped to any cthread */
2119 sprintf (buf
, "_C%d", id
);
2121 else if (!one_cproc
->cthread
->name
)
2123 /* cproc and cthread, but no name */
2124 sprintf (buf
, "_t%d", id
);
2127 return (char *) (one_cproc
->cthread
->name
);
2131 warning ("Inconsistency in thread name id %d", id
);
2133 /* Kernel thread without cproc */
2134 sprintf (buf
, "_K%d", id
);
2141 fetch_thread_info (mach_port_t task
, gdb_thread_t
*mthreads_out
)
2144 thread_array_t th_table
;
2146 gdb_thread_t mthreads
= NULL
;
2149 ret
= task_threads (task
, &th_table
, &th_count
);
2150 if (ret
!= KERN_SUCCESS
)
2152 warning ("Error getting inferior's thread list:%s",
2153 mach_error_string (ret
));
2154 m3_kill_inferior ();
2158 mthreads
= (gdb_thread_t
)
2161 th_count
* sizeof (struct gdb_thread
));
2163 for (index
= 0; index
< th_count
; index
++)
2165 thread_t saved_thread
= MACH_PORT_NULL
;
2168 if (must_suspend_thread
)
2169 setup_thread (th_table
[index
], 1);
2171 if (th_table
[index
] != current_thread
)
2173 saved_thread
= current_thread
;
2175 mid
= switch_to_thread (th_table
[index
]);
2178 mthreads
[index
].name
= th_table
[index
];
2179 mthreads
[index
].cproc
= NULL
; /* map_cprocs_to_kernel_threads() */
2180 mthreads
[index
].in_emulator
= FALSE
;
2181 mthreads
[index
].slotid
= index
;
2183 mthreads
[index
].sp
= read_register (SP_REGNUM
);
2184 mthreads
[index
].fp
= read_register (FP_REGNUM
);
2185 mthreads
[index
].pc
= read_pc ();
2187 if (MACH_PORT_VALID (saved_thread
))
2188 mid
= switch_to_thread (saved_thread
);
2190 if (must_suspend_thread
)
2191 setup_thread (th_table
[index
], 0);
2194 consume_send_rights (th_table
, th_count
);
2195 ret
= vm_deallocate (mach_task_self (), (vm_address_t
) th_table
,
2196 (th_count
* sizeof (mach_port_t
)));
2197 if (ret
!= KERN_SUCCESS
)
2199 warning ("Error trying to deallocate thread list : %s",
2200 mach_error_string (ret
));
2203 *mthreads_out
= mthreads
;
2210 * Current emulator always saves the USP on top of
2211 * emulator stack below struct emul_stack_top stuff.
2214 fetch_usp_from_emulator_stack (CORE_ADDR sp
)
2216 CORE_ADDR stack_pointer
;
2218 sp
= (sp
& ~(EMULATOR_STACK_SIZE
- 1)) +
2219 EMULATOR_STACK_SIZE
- sizeof (struct emul_stack_top
);
2221 if (mach3_read_inferior (sp
,
2223 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2225 warning ("Can't read user sp from emulator stack address 0x%x", sp
);
2229 return stack_pointer
;
2234 /* get_emulation_vector() interface was changed after mk67 */
2235 #define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2239 /* Check if the emulator exists at task's address space.
2242 have_emulator_p (task_t task
)
2245 #ifndef EMUL_VECTOR_COUNT
2246 vm_offset_t
*emulation_vector
;
2249 vm_offset_t emulation_vector
[EMUL_VECTOR_COUNT
];
2250 int n
= EMUL_VECTOR_COUNT
;
2255 ret
= task_get_emulation_vector (task
,
2257 #ifndef EMUL_VECTOR_COUNT
2263 CHK ("task_get_emulation_vector", ret
);
2264 xx_debug ("%d vectors from %d at 0x%08x\n",
2265 n
, vector_start
, emulation_vector
);
2267 for (i
= 0; i
< n
; i
++)
2269 vm_offset_t entry
= emulation_vector
[i
];
2271 if (EMULATOR_BASE
<= entry
&& entry
<= EMULATOR_END
)
2275 static boolean_t informed
= FALSE
;
2278 warning ("Emulation vector address 0x08%x outside emulator space",
2287 /* Map cprocs to kernel threads and vice versa. */
2290 map_cprocs_to_kernel_threads (gdb_thread_t cprocs
, gdb_thread_t mthreads
,
2295 boolean_t all_mapped
= TRUE
;
2299 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2301 /* Default to: no kernel thread for this cproc */
2302 scan
->reverse_map
= -1;
2304 /* Check if the cproc is found by its stack */
2305 for (index
= 0; index
< thread_count
; index
++)
2308 extract_signed_integer (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2311 extract_signed_integer (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2313 if ((mthreads
+ index
)->sp
> stack_base
&&
2314 (mthreads
+ index
)->sp
<= stack_base
+ stack_size
)
2316 (mthreads
+ index
)->cproc
= scan
;
2317 scan
->reverse_map
= index
;
2321 all_mapped
&= (scan
->reverse_map
!= -1);
2324 /* Check for threads that are currently in the emulator.
2325 * If so, they have a different stack, and the still unmapped
2326 * cprocs may well get mapped to these threads.
2329 * - cproc stack does not match any kernel thread stack pointer
2330 * - there is at least one extra kernel thread
2331 * that has no cproc mapped above.
2332 * - some kernel thread stack pointer points to emulator space
2333 * then we find the user stack pointer saved in the emulator
2334 * stack, and try to map that to the cprocs.
2336 * Also set in_emulator for kernel threads.
2339 if (emulator_present
)
2341 for (index
= 0; index
< thread_count
; index
++)
2346 gdb_thread_t mthread
= (mthreads
+ index
);
2347 emul_sp
= mthread
->sp
;
2349 if (mthread
->cproc
== NULL
&&
2350 EMULATOR_BASE
<= emul_sp
&& emul_sp
<= EMULATOR_END
)
2352 mthread
->in_emulator
= emulator_present
;
2354 if (!all_mapped
&& cprocs
)
2356 usp
= fetch_usp_from_emulator_stack (emul_sp
);
2358 /* @@ Could be more accurate */
2360 error ("Zero stack pointer read from emulator?");
2362 /* Try to match this stack pointer to the cprocs that
2363 * don't yet have a kernel thread.
2365 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2368 /* Check is this unmapped CPROC stack contains
2369 * the user stack pointer saved in the
2372 if (scan
->reverse_map
== -1)
2375 extract_signed_integer
2376 (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2379 extract_signed_integer
2380 (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2382 if (usp
> stack_base
&&
2383 usp
<= stack_base
+ stack_size
)
2385 mthread
->cproc
= scan
;
2386 scan
->reverse_map
= index
;
2398 * Format of the thread_list command
2400 * slot mid sel name emul ks susp cstate wired address
2402 #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2404 #define TL_HEADER "\n@ MID Name KState CState Where\n"
2407 print_tl_address (struct ui_file
*stream
, CORE_ADDR pc
)
2409 if (!lookup_minimal_symbol_by_pc (pc
))
2410 fprintf_filtered (stream
, local_hex_format (), pc
);
2413 extern int addressprint
;
2414 extern int asm_demangle
;
2416 int store
= addressprint
;
2418 print_address_symbolic (pc
, stream
, asm_demangle
, "");
2419 addressprint
= store
;
2423 /* For thread names, but also for gdb_message_port external name */
2424 #define MAX_NAME_LEN 50
2426 /* Returns the address of variable NAME or 0 if not found */
2428 lookup_address_of_variable (char *name
)
2431 CORE_ADDR symaddr
= 0;
2432 struct minimal_symbol
*msymbol
;
2434 sym
= lookup_symbol (name
,
2435 (struct block
*) NULL
,
2438 (struct symtab
**) NULL
);
2441 symaddr
= SYMBOL_VALUE (sym
);
2445 msymbol
= lookup_minimal_symbol (name
, NULL
, NULL
);
2447 if (msymbol
&& msymbol
->type
== mst_data
)
2448 symaddr
= SYMBOL_VALUE_ADDRESS (msymbol
);
2457 gdb_thread_t cproc_head
;
2458 gdb_thread_t cproc_copy
;
2459 CORE_ADDR their_cprocs
;
2465 buf
= alloca (TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2466 symaddr
= lookup_address_of_variable ("cproc_list");
2470 /* cproc_list is not in a file compiled with debugging
2471 symbols, but don't give up yet */
2473 symaddr
= lookup_address_of_variable ("cprocs");
2477 static int informed
= 0;
2481 warning ("Your program is loaded with an old threads library.");
2482 warning ("GDB does not know the old form of threads");
2483 warning ("so things may not work.");
2488 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
2492 /* Get the address of the first cproc in the task */
2493 if (!mach3_read_inferior (symaddr
,
2495 TARGET_PTR_BIT
/ HOST_CHAR_BIT
))
2496 error ("Can't read cproc master list at address (0x%x).", symaddr
);
2497 their_cprocs
= extract_address (buf
, TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2499 /* Scan the CPROCs in the task.
2500 CPROCs are chained with LIST field, not NEXT field, which
2501 chains mutexes, condition variables and queues */
2505 while (their_cprocs
!= (CORE_ADDR
) 0)
2507 CORE_ADDR cproc_copy_incarnation
;
2508 cproc_copy
= (gdb_thread_t
) obstack_alloc (cproc_obstack
,
2509 sizeof (struct gdb_thread
));
2511 if (!mach3_read_inferior (their_cprocs
,
2512 &cproc_copy
->raw_cproc
[0],
2514 error ("Can't read next cproc at 0x%x.", their_cprocs
);
2517 extract_address (cproc_copy
->raw_cproc
+ CPROC_LIST_OFFSET
,
2519 cproc_copy_incarnation
=
2520 extract_address (cproc_copy
->raw_cproc
+ CPROC_INCARNATION_OFFSET
,
2521 CPROC_INCARNATION_SIZE
);
2523 if (cproc_copy_incarnation
== (CORE_ADDR
) 0)
2524 cproc_copy
->cthread
= NULL
;
2527 /* This CPROC has an attached CTHREAD. Get its name */
2528 cthread
= (cthread_t
) obstack_alloc (cproc_obstack
,
2529 sizeof (struct cthread
));
2531 if (!mach3_read_inferior (cproc_copy_incarnation
,
2533 sizeof (struct cthread
)))
2534 error ("Can't read next thread at 0x%x.",
2535 cproc_copy_incarnation
);
2537 cproc_copy
->cthread
= cthread
;
2541 name
= (char *) obstack_alloc (cproc_obstack
, MAX_NAME_LEN
);
2543 if (!mach3_read_inferior (cthread
->name
, name
, MAX_NAME_LEN
))
2544 error ("Can't read next thread's name at 0x%x.", cthread
->name
);
2546 cthread
->name
= name
;
2550 /* insert in front */
2551 cproc_copy
->next
= cproc_head
;
2552 cproc_head
= cproc_copy
;
2557 #ifndef FETCH_CPROC_STATE
2559 * Check if your machine does not grok the way this routine
2560 * fetches the FP,PC and SP of a cproc that is not
2561 * currently attached to any kernel thread (e.g. its cproc.context
2562 * field points to the place in stack where the context
2565 * If it doesn't, define your own routine.
2567 #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2570 mach3_cproc_state (gdb_thread_t mthread
)
2574 if (!mthread
|| !mthread
->cproc
)
2577 context
= extract_signed_integer
2578 (mthread
->cproc
->raw_cproc
+ CPROC_CONTEXT_OFFSET
,
2579 CPROC_CONTEXT_SIZE
);
2583 mthread
->sp
= context
+ MACHINE_CPROC_SP_OFFSET
;
2585 if (mach3_read_inferior (context
+ MACHINE_CPROC_PC_OFFSET
,
2587 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2589 warning ("Can't read cproc pc from inferior");
2593 if (mach3_read_inferior (context
+ MACHINE_CPROC_FP_OFFSET
,
2595 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2597 warning ("Can't read cproc fp from inferior");
2603 #endif /* FETCH_CPROC_STATE */
2607 thread_list_command (void)
2609 thread_basic_info_data_t ths
;
2611 gdb_thread_t cprocs
;
2619 mach_port_t mid_or_port
;
2620 gdb_thread_t their_threads
;
2621 gdb_thread_t kthread
;
2625 char *fmt
= "There are %d kernel threads in task %d.\n";
2627 int tmid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
2629 MACH_ERROR_NO_INFERIOR
;
2631 thread_count
= fetch_thread_info (inferior_task
,
2633 if (thread_count
== -1)
2636 if (thread_count
== 1)
2637 fmt
= "There is %d kernel thread in task %d.\n";
2639 printf_filtered (fmt
, thread_count
, tmid
);
2641 puts_filtered (TL_HEADER
);
2643 cprocs
= get_cprocs ();
2645 map_cprocs_to_kernel_threads (cprocs
, their_threads
, thread_count
);
2647 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2653 extract_signed_integer
2654 (scan
->raw_cproc
+ CPROC_STATE_OFFSET
, CPROC_STATE_SIZE
);
2658 /* a wired cproc? */
2659 wired
= (extract_address (scan
->raw_cproc
+ CPROC_WIRED_OFFSET
,
2663 if (scan
->reverse_map
!= -1)
2664 kthread
= (their_threads
+ scan
->reverse_map
);
2670 /* These cprocs have a kernel thread */
2672 mid
= map_port_name_to_mid (kthread
->name
, MACH_TYPE_THREAD
);
2674 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2676 ret
= thread_info (kthread
->name
,
2678 (thread_info_t
) & ths
,
2681 if (ret
!= KERN_SUCCESS
)
2683 warning ("Unable to get basic info on thread %d : %s",
2685 mach_error_string (ret
));
2689 /* Who is the first to have more than 100 threads */
2690 sprintf (slot
, "%d", kthread
->slotid
% 100);
2692 if (kthread
->name
== current_thread
)
2695 if (ths
.suspend_count
)
2696 sprintf (buf
, "%d", ths
.suspend_count
);
2701 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2705 if (ths
.flags
& TH_FLAGS_IDLE
)
2708 printf_filtered (TL_FORMAT
,
2712 get_thread_name (scan
, kthread
->slotid
),
2713 kthread
->in_emulator
? "E" : "",
2714 translate_state (ths
.run_state
),
2716 translate_cstate (cproc_state
),
2718 print_tl_address (gdb_stdout
, kthread
->pc
);
2722 /* These cprocs don't have a kernel thread.
2723 * find out the calling frame with
2724 * FETCH_CPROC_STATE.
2727 struct gdb_thread state
;
2730 /* jtv -> emcmanus: why do you want this here? */
2731 if (scan
->incarnation
== NULL
)
2732 continue; /* EMcM */
2735 printf_filtered (TL_FORMAT
,
2737 -neworder
, /* Pseudo MID */
2739 get_thread_name (scan
, -neworder
),
2741 "-", /* kernel state */
2743 translate_cstate (cproc_state
),
2747 if (FETCH_CPROC_STATE (&state
) == -1)
2748 puts_filtered ("???");
2750 print_tl_address (gdb_stdout
, state
.pc
);
2754 puts_filtered ("\n");
2757 /* Scan for kernel threads without cprocs */
2758 for (index
= 0; index
< thread_count
; index
++)
2760 if (!their_threads
[index
].cproc
)
2767 mach_port_t name
= their_threads
[index
].name
;
2769 mid
= map_port_name_to_mid (name
, MACH_TYPE_THREAD
);
2771 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2773 ret
= thread_info (name
,
2775 (thread_info_t
) & ths
,
2778 if (ret
!= KERN_SUCCESS
)
2780 warning ("Unable to get basic info on thread %d : %s",
2782 mach_error_string (ret
));
2786 sprintf (slot
, "%d", index
% 100);
2788 if (name
== current_thread
)
2793 if (ths
.suspend_count
)
2794 sprintf (buf
, "%d", ths
.suspend_count
);
2799 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2803 if (ths
.flags
& TH_FLAGS_IDLE
)
2806 printf_filtered (TL_FORMAT
,
2810 get_thread_name (NULL
, index
),
2811 their_threads
[index
].in_emulator
? "E" : "",
2812 translate_state (ths
.run_state
),
2814 "", /* No cproc state */
2815 ""); /* Can't be wired */
2816 print_tl_address (gdb_stdout
, their_threads
[index
].pc
);
2817 puts_filtered ("\n");
2821 obstack_free (cproc_obstack
, 0);
2822 obstack_init (cproc_obstack
);
2826 thread_select_command (char *args
, int from_tty
)
2829 thread_array_t thread_list
;
2834 MACH_ERROR_NO_INFERIOR
;
2837 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2839 while (*args
== ' ' || *args
== '\t')
2851 if (!is_slot
|| *args
!= '0') /* Rudimentary checks */
2852 error ("You must select threads by MID or @SLOTNUMBER");
2854 if (select_thread (inferior_task
, mid
, is_slot
? 2 : 1) != KERN_SUCCESS
)
2858 printf_filtered ("Thread %d selected\n",
2859 is_slot
? map_port_name_to_mid (current_thread
,
2860 MACH_TYPE_THREAD
) : mid
);
2863 thread_trace (mach_port_t thread
, boolean_t set
)
2865 int flavor
= TRACE_FLAVOR
;
2866 unsigned int stateCnt
= TRACE_FLAVOR_SIZE
;
2868 thread_state_data_t state
;
2870 if (!MACH_PORT_VALID (thread
))
2872 warning ("thread_trace: invalid thread");
2876 if (must_suspend_thread
)
2877 setup_thread (thread
, 1);
2879 ret
= thread_get_state (thread
, flavor
, state
, &stateCnt
);
2880 CHK ("thread_trace: error reading thread state", ret
);
2884 TRACE_SET (thread
, state
);
2888 if (!TRACE_CLEAR (thread
, state
))
2890 if (must_suspend_thread
)
2891 setup_thread (thread
, 0);
2896 ret
= thread_set_state (thread
, flavor
, state
, stateCnt
);
2897 CHK ("thread_trace: error writing thread state", ret
);
2898 if (must_suspend_thread
)
2899 setup_thread (thread
, 0);
2902 #ifdef FLUSH_INFERIOR_CACHE
2904 /* When over-writing code on some machines the I-Cache must be flushed
2905 explicitly, because it is not kept coherent by the lazy hardware.
2906 This definitely includes breakpoints, for instance, or else we
2907 end up looping in mysterious Bpt traps */
2909 flush_inferior_icache (CORE_ADDR pc
, int amount
)
2911 vm_machine_attribute_val_t flush
= MATTR_VAL_ICACHE_FLUSH
;
2914 ret
= vm_machine_attribute (inferior_task
,
2919 if (ret
!= KERN_SUCCESS
)
2920 warning ("Error flushing inferior's cache : %s",
2921 mach_error_string (ret
));
2923 #endif /* FLUSH_INFERIOR_CACHE */
2927 suspend_all_threads (int from_tty
)
2930 thread_array_t thread_list
;
2931 int thread_count
, index
;
2933 thread_basic_info_data_t th_info
;
2936 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
2937 if (ret
!= KERN_SUCCESS
)
2939 warning ("Could not suspend inferior threads.");
2940 m3_kill_inferior ();
2941 return_to_top_level (RETURN_ERROR
);
2944 for (index
= 0; index
< thread_count
; index
++)
2948 mid
= map_port_name_to_mid (thread_list
[index
],
2951 ret
= thread_suspend (thread_list
[index
]);
2953 if (ret
!= KERN_SUCCESS
)
2954 warning ("Error trying to suspend thread %d : %s",
2955 mid
, mach_error_string (ret
));
2959 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2960 ret
= thread_info (thread_list
[index
],
2962 (thread_info_t
) & th_info
,
2964 CHK ("suspend can't get thread info", ret
);
2966 warning ("Thread %d suspend count is %d",
2967 mid
, th_info
.suspend_count
);
2971 consume_send_rights (thread_list
, thread_count
);
2972 ret
= vm_deallocate (mach_task_self (),
2973 (vm_address_t
) thread_list
,
2974 (thread_count
* sizeof (int)));
2975 CHK ("Error trying to deallocate thread list", ret
);
2979 thread_suspend_command (char *args
, int from_tty
)
2983 mach_port_t saved_thread
;
2985 thread_basic_info_data_t th_info
;
2987 MACH_ERROR_NO_INFERIOR
;
2989 if (!strcasecmp (args
, "all"))
2991 suspend_all_threads (from_tty
);
2995 saved_thread
= current_thread
;
2997 mid
= parse_thread_id (args
, 0, 0);
3000 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
3003 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3004 else if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3007 current_thread
= saved_thread
;
3008 error ("Could not select thread %d", mid
);
3011 ret
= thread_suspend (current_thread
);
3012 if (ret
!= KERN_SUCCESS
)
3013 warning ("thread_suspend failed : %s",
3014 mach_error_string (ret
));
3016 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3017 ret
= thread_info (current_thread
,
3019 (thread_info_t
) & th_info
,
3021 CHK ("suspend can't get thread info", ret
);
3023 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3025 current_thread
= saved_thread
;
3028 resume_all_threads (int from_tty
)
3031 thread_array_t thread_list
;
3032 int thread_count
, index
;
3035 thread_basic_info_data_t th_info
;
3037 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
3038 if (ret
!= KERN_SUCCESS
)
3040 m3_kill_inferior ();
3041 error ("task_threads", mach_error_string (ret
));
3044 for (index
= 0; index
< thread_count
; index
++)
3046 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3047 ret
= thread_info (thread_list
[index
],
3049 (thread_info_t
) & th_info
,
3051 CHK ("resume_all can't get thread info", ret
);
3053 mid
= map_port_name_to_mid (thread_list
[index
],
3056 if (!th_info
.suspend_count
)
3058 if (mid
!= -1 && from_tty
)
3059 warning ("Thread %d is not suspended", mid
);
3063 ret
= thread_resume (thread_list
[index
]);
3065 if (ret
!= KERN_SUCCESS
)
3066 warning ("Error trying to resume thread %d : %s",
3067 mid
, mach_error_string (ret
));
3068 else if (mid
!= -1 && from_tty
)
3069 warning ("Thread %d suspend count is %d",
3070 mid
, --th_info
.suspend_count
);
3073 consume_send_rights (thread_list
, thread_count
);
3074 ret
= vm_deallocate (mach_task_self (),
3075 (vm_address_t
) thread_list
,
3076 (thread_count
* sizeof (int)));
3077 CHK ("Error trying to deallocate thread list", ret
);
3081 thread_resume_command (char *args
, int from_tty
)
3084 mach_port_t saved_thread
;
3086 thread_basic_info_data_t th_info
;
3087 int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3089 MACH_ERROR_NO_INFERIOR
;
3091 if (!strcasecmp (args
, "all"))
3093 resume_all_threads (from_tty
);
3097 saved_thread
= current_thread
;
3099 mid
= parse_thread_id (args
, 0, 0);
3102 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3105 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3106 else if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3109 current_thread
= saved_thread
;
3110 return_to_top_level (RETURN_ERROR
);
3113 ret
= thread_info (current_thread
,
3115 (thread_info_t
) & th_info
,
3117 CHK ("resume can't get thread info", ret
);
3119 if (!th_info
.suspend_count
)
3121 warning ("Thread %d is not suspended", mid
);
3125 ret
= thread_resume (current_thread
);
3126 if (ret
!= KERN_SUCCESS
)
3127 warning ("thread_resume failed : %s",
3128 mach_error_string (ret
));
3131 th_info
.suspend_count
--;
3132 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3136 current_thread
= saved_thread
;
3140 thread_kill_command (char *args
, int from_tty
)
3145 thread_array_t thread_table
;
3147 mach_port_t thread_to_kill
= MACH_PORT_NULL
;
3150 MACH_ERROR_NO_INFERIOR
;
3153 error_no_arg ("thread mid to kill from the inferior task");
3155 mid
= parse_thread_id (args
, 0, 0);
3158 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3162 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &thread_to_kill
);
3163 CHK ("thread_kill_command: machid_mach_port map failed", ret
);
3166 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3168 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3169 ret
= task_threads (inferior_task
, &thread_table
, &thread_count
);
3170 CHK ("Error getting inferior's thread list", ret
);
3172 if (thread_to_kill
== current_thread
)
3174 ret
= thread_terminate (thread_to_kill
);
3175 CHK ("Thread could not be terminated", ret
);
3177 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3178 warning ("Last thread was killed, use \"kill\" command to kill task");
3181 for (index
= 0; index
< thread_count
; index
++)
3182 if (thread_table
[index
] == thread_to_kill
)
3184 ret
= thread_terminate (thread_to_kill
);
3185 CHK ("Thread could not be terminated", ret
);
3188 if (thread_count
> 1)
3189 consume_send_rights (thread_table
, thread_count
);
3191 ret
= vm_deallocate (mach_task_self (), (vm_address_t
) thread_table
,
3192 (thread_count
* sizeof (mach_port_t
)));
3193 CHK ("Error trying to deallocate thread list", ret
);
3195 warning ("Thread %d killed", mid
);
3199 /* Task specific commands; add more if you like */
3202 task_resume_command (char *args
, int from_tty
)
3205 task_basic_info_data_t ta_info
;
3206 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3207 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3209 MACH_ERROR_NO_INFERIOR
;
3211 /* Would be trivial to change, but is it desirable? */
3213 error ("Currently gdb can resume only it's inferior task");
3215 ret
= task_info (inferior_task
,
3217 (task_info_t
) & ta_info
,
3219 CHK ("task_resume_command: task_info failed", ret
);
3221 if (ta_info
.suspend_count
== 0)
3222 error ("Inferior task %d is not suspended", mid
);
3223 else if (ta_info
.suspend_count
== 1 &&
3225 !query ("Suspend count is now 1. Do you know what you are doing? "))
3226 error ("Task not resumed");
3228 ret
= task_resume (inferior_task
);
3229 CHK ("task_resume_command: task_resume", ret
);
3231 if (ta_info
.suspend_count
== 1)
3233 warning ("Inferior task %d is no longer suspended", mid
);
3234 must_suspend_thread
= 1;
3235 /* @@ This is not complete: Registers change all the time when not
3237 registers_changed ();
3240 warning ("Inferior task %d suspend count is now %d",
3241 mid
, ta_info
.suspend_count
- 1);
3246 task_suspend_command (char *args
, int from_tty
)
3249 task_basic_info_data_t ta_info
;
3250 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3251 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3253 MACH_ERROR_NO_INFERIOR
;
3255 /* Would be trivial to change, but is it desirable? */
3257 error ("Currently gdb can suspend only it's inferior task");
3259 ret
= task_suspend (inferior_task
);
3260 CHK ("task_suspend_command: task_suspend", ret
);
3262 must_suspend_thread
= 0;
3264 ret
= task_info (inferior_task
,
3266 (task_info_t
) & ta_info
,
3268 CHK ("task_suspend_command: task_info failed", ret
);
3270 warning ("Inferior task %d suspend count is now %d",
3271 mid
, ta_info
.suspend_count
);
3275 get_size (int bytes
)
3277 static char size
[30];
3278 int zz
= bytes
/ 1024;
3281 sprintf (size
, "%-2.1f M", ((float) bytes
) / (1024.0 * 1024.0));
3283 sprintf (size
, "%d K", zz
);
3288 /* Does this require the target task to be suspended?? I don't think so. */
3290 task_info_command (char *args
, int from_tty
)
3295 task_basic_info_data_t ta_info
;
3296 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3297 int page_size
= round_page (1);
3298 int thread_count
= 0;
3300 if (MACH_PORT_VALID (inferior_task
))
3301 mid
= map_port_name_to_mid (inferior_task
,
3304 task
= inferior_task
;
3308 int tmid
= atoi (args
);
3311 error ("Invalid mid %d for task info", tmid
);
3316 ret
= machid_mach_port (mid_server
, mid_auth
, tmid
, &task
);
3317 CHK ("task_info_command: machid_mach_port map failed", ret
);
3322 error ("You have to give the task MID as an argument");
3324 ret
= task_info (task
,
3326 (task_info_t
) & ta_info
,
3328 CHK ("task_info_command: task_info failed", ret
);
3330 printf_filtered ("\nTask info for task %d:\n\n", mid
);
3331 printf_filtered (" Suspend count : %d\n", ta_info
.suspend_count
);
3332 printf_filtered (" Base priority : %d\n", ta_info
.base_priority
);
3333 printf_filtered (" Virtual size : %s\n", get_size (ta_info
.virtual_size
));
3334 printf_filtered (" Resident size : %s\n", get_size (ta_info
.resident_size
));
3337 thread_array_t thread_list
;
3339 ret
= task_threads (task
, &thread_list
, &thread_count
);
3340 CHK ("task_info_command: task_threads", ret
);
3342 printf_filtered (" Thread count : %d\n", thread_count
);
3344 consume_send_rights (thread_list
, thread_count
);
3345 ret
= vm_deallocate (mach_task_self (),
3346 (vm_address_t
) thread_list
,
3347 (thread_count
* sizeof (int)));
3348 CHK ("Error trying to deallocate thread list", ret
);
3350 if (have_emulator_p (task
))
3351 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3352 EMULATOR_BASE
, EMULATOR_END
);
3354 printf_filtered (" No emulator.\n");
3356 if (thread_count
&& task
== inferior_task
)
3357 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3360 /* You may either FORWARD the exception to the inferior, or KEEP
3361 * it and return to GDB command level.
3363 * exception mid [ forward | keep ]
3367 exception_command (char *args
, int from_tty
)
3374 error_no_arg ("exception number action");
3376 while (*scan
== ' ' || *scan
== '\t')
3379 if ('0' <= *scan
&& *scan
<= '9')
3380 while ('0' <= *scan
&& *scan
<= '9')
3383 error ("exception number action");
3385 exception
= atoi (args
);
3386 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3387 error ("Allowed exception numbers are in range 1..%d",
3390 if (*scan
!= ' ' && *scan
!= '\t')
3391 error ("exception number must be followed by a space");
3393 while (*scan
== ' ' || *scan
== '\t')
3405 error ("exception number action");
3407 if (!strncasecmp (args
, "forward", len
))
3408 exception_map
[exception
].forward
= TRUE
;
3409 else if (!strncasecmp (args
, "keep", len
))
3410 exception_map
[exception
].forward
= FALSE
;
3412 error ("exception action is either \"keep\" or \"forward\"");
3416 print_exception_info (int exception
)
3418 boolean_t forward
= exception_map
[exception
].forward
;
3420 printf_filtered ("%s\t(%d): ", exception_map
[exception
].name
,
3423 if (exception_map
[exception
].sigmap
!= SIG_UNKNOWN
)
3424 printf_filtered ("keep and handle as signal %d\n",
3425 exception_map
[exception
].sigmap
);
3427 printf_filtered ("keep and handle as unknown signal %d\n",
3428 exception_map
[exception
].sigmap
);
3430 printf_filtered ("forward exception to inferior\n");
3434 exception_info (char *args
, int from_tty
)
3439 for (exception
= 1; exception
<= MAX_EXCEPTION
; exception
++)
3440 print_exception_info (exception
);
3443 exception
= atoi (args
);
3445 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3446 error ("Invalid exception number, values from 1 to %d allowed",
3448 print_exception_info (exception
);
3452 /* Check for actions for mach exceptions.
3454 mach3_exception_actions (WAITTYPE
*w
, boolean_t force_print_only
, char *who
)
3456 boolean_t force_print
= FALSE
;
3459 if (force_print_only
||
3460 exception_map
[stop_exception
].sigmap
== SIG_UNKNOWN
)
3463 WSETSTOP (*w
, exception_map
[stop_exception
].sigmap
);
3465 if (exception_map
[stop_exception
].print
|| force_print
)
3467 target_terminal_ours ();
3469 printf_filtered ("\n%s received %s exception : ",
3471 exception_map
[stop_exception
].name
);
3475 switch (stop_exception
)
3477 case EXC_BAD_ACCESS
:
3478 printf_filtered ("referencing address 0x%x : %s\n",
3480 mach_error_string (stop_code
));
3482 case EXC_BAD_INSTRUCTION
:
3484 ("illegal or undefined instruction. code %d subcode %d\n",
3485 stop_code
, stop_subcode
);
3487 case EXC_ARITHMETIC
:
3488 printf_filtered ("code %d\n", stop_code
);
3491 printf_filtered ("code %d subcode %d\n", stop_code
, stop_subcode
);
3494 printf_filtered ("%s specific, code 0x%x\n",
3495 stop_code
< 0xffff ? "hardware" : "os emulation",
3498 case EXC_BREAKPOINT
:
3499 printf_filtered ("type %d (machine dependent)\n",
3503 internal_error (__FILE__
, __LINE__
,
3504 "Unknown exception");
3509 setup_notify_port (int create_new
)
3513 if (MACH_PORT_VALID (our_notify_port
))
3515 ret
= mach_port_destroy (mach_task_self (), our_notify_port
);
3516 CHK ("Could not destroy our_notify_port", ret
);
3519 our_notify_port
= MACH_PORT_NULL
;
3520 notify_chain
= (port_chain_t
) NULL
;
3521 port_chain_destroy (port_chain_obstack
);
3525 ret
= mach_port_allocate (mach_task_self (),
3526 MACH_PORT_RIGHT_RECEIVE
,
3528 if (ret
!= KERN_SUCCESS
)
3529 internal_error (__FILE__
, __LINE__
,
3530 "Creating notify port %s", mach_error_string (ret
));
3532 ret
= mach_port_move_member (mach_task_self (),
3534 inferior_wait_port_set
);
3535 if (ret
!= KERN_SUCCESS
)
3536 internal_error (__FILE__
, __LINE__
,
3537 "initial move member %s", mach_error_string (ret
));
3542 * Register our message port to the net name server
3544 * Currently used only by the external stop-gdb program
3545 * since ^C does not work if you would like to enter
3546 * gdb command level while debugging your program.
3548 * NOTE: If the message port is sometimes used for other
3549 * purposes also, the NAME must not be a guessable one.
3550 * Then, there should be a way to change it.
3553 char registered_name
[MAX_NAME_LEN
];
3556 message_port_info (char *args
, int from_tty
)
3558 if (registered_name
[0])
3559 printf_filtered ("gdb's message port name: '%s'\n",
3562 printf_filtered ("gdb's message port is not currently registered\n");
3566 gdb_register_port (char *name
, mach_port_t port
)
3569 static int already_signed
= 0;
3572 if (!MACH_PORT_VALID (port
) || !name
|| !*name
)
3574 warning ("Invalid registration request");
3578 if (!already_signed
)
3580 ret
= mach_port_insert_right (mach_task_self (),
3583 MACH_MSG_TYPE_MAKE_SEND
);
3584 CHK ("Failed to create a signature to our_message_port", ret
);
3587 else if (already_signed
> 1)
3589 ret
= netname_check_out (name_server_port
,
3592 CHK ("Failed to check out gdb's message port", ret
);
3593 registered_name
[0] = '\000';
3597 ret
= netname_check_in (name_server_port
, /* Name server port */
3598 name
, /* Name of service */
3599 our_message_port
, /* Signature */
3600 port
); /* Creates a new send right */
3601 CHK ("Failed to check in the port", ret
);
3604 while (len
< MAX_NAME_LEN
&& *(name
+ len
))
3606 registered_name
[len
] = *(name
+ len
);
3609 registered_name
[len
] = '\000';
3613 struct cmd_list_element
*cmd_thread_list
;
3614 struct cmd_list_element
*cmd_task_list
;
3618 thread_command (char *arg
, int from_tty
)
3620 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3621 help_list (cmd_thread_list
, "thread ", -1, gdb_stdout
);
3626 task_command (char *arg
, int from_tty
)
3628 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3629 help_list (cmd_task_list
, "task ", -1, gdb_stdout
);
3632 add_mach_specific_commands (void)
3634 /* Thread handling commands */
3636 /* FIXME: Move our thread support into the generic thread.c stuff so we
3637 can share that code. */
3638 add_prefix_cmd ("mthread", class_stack
, thread_command
,
3639 "Generic command for handling Mach threads in the debugged task.",
3640 &cmd_thread_list
, "thread ", 0, &cmdlist
);
3642 add_com_alias ("th", "mthread", class_stack
, 1);
3644 add_cmd ("select", class_stack
, thread_select_command
,
3645 "Select and print MID of the selected thread",
3647 add_cmd ("list", class_stack
, thread_list_command
,
3648 "List info of task's threads. Selected thread is marked with '*'",
3650 add_cmd ("suspend", class_run
, thread_suspend_command
,
3651 "Suspend one or all of the threads in the selected task.",
3653 add_cmd ("resume", class_run
, thread_resume_command
,
3654 "Resume one or all of the threads in the selected task.",
3656 add_cmd ("kill", class_run
, thread_kill_command
,
3657 "Kill the specified thread MID from inferior task.",
3660 /* The rest of this support (condition_thread) was not merged. It probably
3661 should not be merged in this form, but instead added to the generic GDB
3663 add_cmd ("break", class_breakpoint
, condition_thread
,
3664 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3665 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3668 /* Thread command shorthands (for backward compatibility) */
3669 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist
);
3670 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist
);
3672 /* task handling commands */
3674 add_prefix_cmd ("task", class_stack
, task_command
,
3675 "Generic command for handling debugged task.",
3676 &cmd_task_list
, "task ", 0, &cmdlist
);
3678 add_com_alias ("ta", "task", class_stack
, 1);
3680 add_cmd ("suspend", class_run
, task_suspend_command
,
3681 "Suspend the inferior task.",
3683 add_cmd ("resume", class_run
, task_resume_command
,
3684 "Resume the inferior task.",
3686 add_cmd ("info", no_class
, task_info_command
,
3687 "Print information about the specified task.",
3690 /* Print my message port name */
3692 add_info ("message-port", message_port_info
,
3693 "Returns the name of gdb's message port in the netnameserver");
3695 /* Exception commands */
3697 add_info ("exceptions", exception_info
,
3698 "What debugger does when program gets various exceptions.\n\
3699 Specify an exception number as argument to print info on that\n\
3702 add_com ("exception", class_run
, exception_command
,
3703 "Specify how to handle an exception.\n\
3704 Args are exception number followed by \"forward\" or \"keep\".\n\
3705 `Forward' means forward the exception to the program's normal exception\n\
3707 `Keep' means reenter debugger if this exception happens, and GDB maps\n\
3708 the exception to some signal (see info exception)\n\
3709 Normally \"keep\" is used to return to GDB on exception.");
3713 do_mach_notify_dead_name (mach_port_t notify
, mach_port_t name
)
3715 kern_return_t kr
= KERN_SUCCESS
;
3717 /* Find the thing that notified */
3718 port_chain_t element
= port_chain_member (notify_chain
, name
);
3720 /* Take name of from unreceived dead name notification list */
3721 notify_chain
= port_chain_delete (notify_chain
, name
);
3724 error ("Received a dead name notify from unchained port (0x%x)", name
);
3726 switch (element
->type
)
3729 case MACH_TYPE_THREAD
:
3730 target_terminal_ours_for_output ();
3731 if (name
== current_thread
)
3733 printf_filtered ("\nCurrent thread %d died", element
->mid
);
3734 current_thread
= MACH_PORT_NULL
;
3737 printf_filtered ("\nThread %d died", element
->mid
);
3741 case MACH_TYPE_TASK
:
3742 target_terminal_ours_for_output ();
3743 if (name
!= inferior_task
)
3744 printf_filtered ("Task %d died, but it was not the selected task",
3748 printf_filtered ("Current task %d died", element
->mid
);
3750 mach_port_destroy (mach_task_self (), name
);
3751 inferior_task
= MACH_PORT_NULL
;
3754 warning ("There were still unreceived dead_name_notifications???");
3756 /* Destroy the old notifications */
3757 setup_notify_port (0);
3763 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3764 name
, element
->type
, element
->mid
);
3768 return KERN_SUCCESS
;
3772 do_mach_notify_msg_accepted (mach_port_t notify
, mach_port_t name
)
3774 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3776 return KERN_SUCCESS
;
3780 do_mach_notify_no_senders (mach_port_t notify
, mach_port_mscount_t mscount
)
3782 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3784 return KERN_SUCCESS
;
3788 do_mach_notify_port_deleted (mach_port_t notify
, mach_port_t name
)
3790 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3792 return KERN_SUCCESS
;
3796 do_mach_notify_port_destroyed (mach_port_t notify
, mach_port_t rights
)
3798 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3800 return KERN_SUCCESS
;
3804 do_mach_notify_send_once (mach_port_t notify
)
3807 /* MANY of these are generated. */
3808 warning ("do_mach_notify_send_once : notify %x",
3811 return KERN_SUCCESS
;
3814 /* Kills the inferior. It's gone when you call this */
3816 kill_inferior_fast (void)
3820 if (inferior_pid
== 0 || inferior_pid
== 1)
3823 /* kill() it, since the Unix server does not otherwise notice when
3824 * killed with task_terminate().
3826 if (inferior_pid
> 0)
3827 kill (inferior_pid
, SIGKILL
);
3829 /* It's propably terminate already */
3830 (void) task_terminate (inferior_task
);
3832 inferior_task
= MACH_PORT_NULL
;
3833 current_thread
= MACH_PORT_NULL
;
3835 wait3 (&w
, WNOHANG
, 0);
3837 setup_notify_port (0);
3841 m3_kill_inferior (void)
3843 kill_inferior_fast ();
3844 target_mourn_inferior ();
3847 /* Clean up after the inferior dies. */
3850 m3_mourn_inferior (void)
3852 unpush_target (&m3_ops
);
3853 generic_mourn_inferior ();
3857 /* Fork an inferior process, and start debugging it. */
3860 m3_create_inferior (char *exec_file
, char *allargs
, char **env
)
3862 fork_inferior (exec_file
, allargs
, env
, m3_trace_me
, m3_trace_him
, NULL
, NULL
);
3863 /* We are at the first instruction we care about. */
3864 /* Pedal to the metal... */
3865 proceed ((CORE_ADDR
) -1, 0, 0);
3868 /* Mark our target-struct as eligible for stray "run" and "attach"
3876 /* Mach 3.0 does not need ptrace for anything
3877 * Make sure nobody uses it on mach.
3879 ptrace (int a
, int b
, int c
, int d
)
3881 error ("Lose, Lose! Somebody called ptrace\n");
3884 /* Resume execution of the inferior process.
3885 If STEP is nonzero, single-step it.
3886 If SIGNAL is nonzero, give it that signal. */
3889 m3_resume (int pid
, int step
, enum target_signal signal
)
3895 thread_basic_info_data_t th_info
;
3896 unsigned int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3898 /* There is no point in single stepping when current_thread
3901 if (!MACH_PORT_VALID (current_thread
))
3902 error ("No thread selected; can not single step");
3904 /* If current_thread is suspended, tracing it would never return.
3906 ret
= thread_info (current_thread
,
3908 (thread_info_t
) & th_info
,
3910 CHK ("child_resume: can't get thread info", ret
);
3912 if (th_info
.suspend_count
)
3913 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3916 vm_read_cache_valid
= FALSE
;
3918 if (signal
&& inferior_pid
> 0) /* Do not signal, if attached by MID */
3919 kill (inferior_pid
, target_signal_to_host (signal
));
3923 suspend_all_threads (0);
3925 setup_single_step (current_thread
, TRUE
);
3927 ret
= thread_resume (current_thread
);
3928 CHK ("thread_resume", ret
);
3931 ret
= task_resume (inferior_task
);
3932 if (ret
== KERN_FAILURE
)
3933 warning ("Task was not suspended");
3935 CHK ("Resuming task", ret
);
3937 /* HACK HACK This is needed by the multiserver system HACK HACK */
3938 while ((ret
= task_resume (inferior_task
)) == KERN_SUCCESS
)
3939 /* make sure it really runs */ ;
3940 /* HACK HACK This is needed by the multiserver system HACK HACK */
3943 #ifdef ATTACH_DETACH
3945 /* Start debugging the process with the given task */
3947 task_attach (task_t tid
)
3950 inferior_task
= tid
;
3952 ret
= task_suspend (inferior_task
);
3953 CHK ("task_attach: task_suspend", ret
);
3955 must_suspend_thread
= 0;
3957 setup_notify_port (1);
3959 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
3961 setup_exception_port ();
3963 emulator_present
= have_emulator_p (inferior_task
);
3968 /* Well, we can call error also here and leave the
3969 * target stack inconsistent. Sigh.
3970 * Fix this sometime (the only way to fail here is that
3971 * the task has no threads at all, which is rare, but
3972 * possible; or if the target task has died, which is also
3973 * possible, but unlikely, since it has been suspended.
3974 * (Someone must have killed it))
3977 attach_to_thread (void)
3979 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3980 error ("Could not select any threads to attach to");
3983 mid_attach (int mid
)
3987 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &inferior_task
);
3988 CHK ("mid_attach: machid_mach_port", ret
);
3990 task_attach (inferior_task
);
3996 * Start debugging the process whose unix process-id is PID.
3997 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
3999 * Prevent (possible unwanted) dangerous operations by enabled users
4000 * like "atta 0" or "atta foo" (equal to the previous :-) and
4001 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4004 m3_do_attach (int pid
)
4009 error ("MID=0, Debugging the master unix server does not compute");
4011 /* Foo. This assumes gdb has a unix pid */
4012 if (pid
== getpid ())
4013 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4017 mid_attach (-(pid
));
4019 /* inferior_pid will be NEGATIVE! */
4022 return inferior_pid
;
4025 inferior_task
= task_by_pid (pid
);
4026 if (!MACH_PORT_VALID (inferior_task
))
4027 error ("Cannot map Unix pid %d to Mach task port", pid
);
4029 task_attach (inferior_task
);
4033 return inferior_pid
;
4036 /* Attach to process PID, then initialize for debugging it
4037 and wait for the trace-trap that results from attaching. */
4040 m3_attach (char *args
, int from_tty
)
4046 error_no_arg ("process-id to attach");
4050 if (pid
== getpid ()) /* Trying to masturbate? */
4051 error ("I refuse to debug myself!");
4055 exec_file
= (char *) get_exec_file (0);
4058 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file
, target_pid_to_str (pid
));
4060 printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid
));
4062 gdb_flush (gdb_stdout
);
4067 push_target (&m3_ops
);
4071 deallocate_inferior_ports (void)
4074 thread_array_t thread_list
;
4075 int thread_count
, index
;
4077 if (!MACH_PORT_VALID (inferior_task
))
4080 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
4081 if (ret
!= KERN_SUCCESS
)
4083 warning ("deallocate_inferior_ports: task_threads",
4084 mach_error_string (ret
));
4088 /* Get rid of send rights to task threads */
4089 for (index
= 0; index
< thread_count
; index
++)
4092 ret
= mach_port_get_refs (mach_task_self (),
4094 MACH_PORT_RIGHT_SEND
,
4096 CHK ("deallocate_inferior_ports: get refs", ret
);
4100 ret
= mach_port_mod_refs (mach_task_self (),
4102 MACH_PORT_RIGHT_SEND
,
4104 CHK ("deallocate_inferior_ports: mod refs", ret
);
4108 ret
= mach_port_mod_refs (mach_task_self (),
4109 inferior_exception_port
,
4110 MACH_PORT_RIGHT_RECEIVE
,
4112 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret
);
4114 ret
= mach_port_deallocate (mach_task_self (),
4116 CHK ("deallocate_task_port: deallocating inferior_task", ret
);
4118 current_thread
= MACH_PORT_NULL
;
4119 inferior_task
= MACH_PORT_NULL
;
4122 /* Stop debugging the process whose number is PID
4123 and continue it with signal number SIGNAL.
4124 SIGNAL = 0 means just continue it. */
4127 m3_do_detach (int signal
)
4131 MACH_ERROR_NO_INFERIOR
;
4133 if (current_thread
!= MACH_PORT_NULL
)
4135 /* Store the gdb's view of the thread we are deselecting
4137 * @@ I am really not sure if this is ever needeed.
4139 target_prepare_to_store ();
4140 target_store_registers (-1);
4143 ret
= task_set_special_port (inferior_task
,
4144 TASK_EXCEPTION_PORT
,
4145 inferior_old_exception_port
);
4146 CHK ("task_set_special_port", ret
);
4148 /* Discard all requested notifications */
4149 setup_notify_port (0);
4151 if (remove_breakpoints ())
4152 warning ("Could not remove breakpoints when detaching");
4154 if (signal
&& inferior_pid
> 0)
4155 kill (inferior_pid
, signal
);
4157 /* the task might be dead by now */
4158 (void) task_resume (inferior_task
);
4160 deallocate_inferior_ports ();
4165 /* Take a program previously attached to and detaches it.
4166 The program resumes execution and will no longer stop
4167 on signals, etc. We'd better not have left any breakpoints
4168 in the program or it'll die when it hits one. For this
4169 to work, it may be necessary for the process to have been
4170 previously attached. It *might* work if the program was
4171 started via fork. */
4174 m3_detach (char *args
, int from_tty
)
4180 char *exec_file
= get_exec_file (0);
4183 printf_unfiltered ("Detaching from program: %s %s\n",
4184 exec_file
, target_pid_to_str (inferior_pid
));
4185 gdb_flush (gdb_stdout
);
4188 siggnal
= atoi (args
);
4190 m3_do_detach (siggnal
);
4192 unpush_target (&m3_ops
); /* Pop out of handling an inferior */
4194 #endif /* ATTACH_DETACH */
4196 /* Get ready to modify the registers array. On machines which store
4197 individual registers, this doesn't need to do anything. On machines
4198 which store all the registers in one fell swoop, this makes sure
4199 that registers contains all the registers from the program being
4203 m3_prepare_to_store (void)
4205 #ifdef CHILD_PREPARE_TO_STORE
4206 CHILD_PREPARE_TO_STORE ();
4210 /* Print status information about what we're accessing. */
4213 m3_files_info (struct target_ops
*ignore
)
4215 /* FIXME: should print MID and all that crap. */
4216 printf_unfiltered ("\tUsing the running image of %s %s.\n",
4217 attach_flag
? "attached" : "child", target_pid_to_str (inferior_pid
));
4221 m3_open (char *arg
, int from_tty
)
4223 error ("Use the \"run\" command to start a Unix child process.");
4233 char *bsd1_names
[] =
4302 int bsd1_nnames
= sizeof (bsd1_names
) / sizeof (bsd1_names
[0]);
4305 name_str (int name
, char *buf
)
4309 case MACH_MSG_TYPE_BOOLEAN
:
4311 case MACH_MSG_TYPE_INTEGER_16
:
4313 case MACH_MSG_TYPE_INTEGER_32
:
4315 case MACH_MSG_TYPE_CHAR
:
4317 case MACH_MSG_TYPE_BYTE
:
4319 case MACH_MSG_TYPE_REAL
:
4321 case MACH_MSG_TYPE_STRING
:
4324 sprintf (buf
, "%d", name
);
4330 id_str (int id
, char *buf
)
4333 if (id
>= 101000 && id
< 101000 + bsd1_nnames
)
4335 if (p
= bsd1_names
[id
- 101000])
4339 return "psignal_retry";
4342 sprintf (buf
, "%d", id
);
4346 print_msg (mach_msg_header_t
*mp
)
4348 char *fmt_x
= "%20s : 0x%08x\n";
4349 char *fmt_d
= "%20s : %10d\n";
4350 char *fmt_s
= "%20s : %s\n";
4353 puts_filtered ("\n");
4354 #define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
4355 pr (fmt_x
, (*mp
), msgh_bits
);
4356 pr (fmt_d
, (*mp
), msgh_size
);
4357 pr (fmt_x
, (*mp
), msgh_remote_port
);
4358 pr (fmt_x
, (*mp
), msgh_local_port
);
4359 pr (fmt_d
, (*mp
), msgh_kind
);
4360 printf_filtered (fmt_s
, STR (msgh_id
), id_str (mp
->msgh_id
, buf
));
4362 if (debug_level
> 1)
4367 ep
= p
+ mp
->msgh_size
;
4369 for (; p
< ep
; p
+= plen
)
4371 mach_msg_type_t
*tp
;
4372 mach_msg_type_long_t
*tlp
;
4373 int name
, size
, number
;
4374 tp
= (mach_msg_type_t
*) p
;
4375 if (tp
->msgt_longform
)
4377 tlp
= (mach_msg_type_long_t
*) tp
;
4378 name
= tlp
->msgtl_name
;
4379 size
= tlp
->msgtl_size
;
4380 number
= tlp
->msgtl_number
;
4381 plen
= sizeof (*tlp
);
4385 name
= tp
->msgt_name
;
4386 size
= tp
->msgt_size
;
4387 number
= tp
->msgt_number
;
4388 plen
= sizeof (*tp
);
4390 printf_filtered ("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4391 name_str (name
, buf
), size
, number
, tp
->msgt_inline
,
4392 tp
->msgt_longform
, tp
->msgt_deallocate
);
4394 if (tp
->msgt_inline
)
4397 l
= size
* number
/ 8;
4398 l
= (l
+ sizeof (long) - 1) & ~((sizeof (long)) - 1);
4400 print_data (dp
, size
, number
);
4404 plen
+= sizeof (int *);
4406 printf_filtered ("plen=%d\n", plen
);
4411 print_data (char *p
, int size
, int number
)
4420 for (i
= 0; i
< number
; i
++)
4422 printf_filtered (" %02x", p
[i
]);
4427 for (i
= 0; i
< number
; i
++)
4429 printf_filtered (" %04x", sp
[i
]);
4434 for (i
= 0; i
< number
; i
++)
4436 printf_filtered (" %08x", ip
[i
]);
4440 puts_filtered ("\n");
4442 #endif /* DUMP_SYSCALL */
4447 error ("to_stop target function not implemented");
4451 m3_pid_to_exec_file (int pid
)
4453 error ("to_pid_to_exec_file target function not implemented");
4454 return NULL
; /* To keep all compilers happy. */
4460 m3_ops
.to_shortname
= "mach";
4461 m3_ops
.to_longname
= "Mach child process";
4462 m3_ops
.to_doc
= "Mach child process (started by the \"run\" command).";
4463 m3_ops
.to_open
= m3_open
;
4464 m3_ops
.to_attach
= m3_attach
;
4465 m3_ops
.to_detach
= m3_detach
;
4466 m3_ops
.to_resume
= m3_resume
;
4467 m3_ops
.to_wait
= mach_really__wait
;
4468 m3_ops
.to_fetch_registers
= fetch_inferior_registers
;
4469 m3_ops
.to_store_registers
= store_inferior_registers
;
4470 m3_ops
.to_prepare_to_store
= m3_prepare_to_store
;
4471 m3_ops
.to_xfer_memory
= m3_xfer_memory
;
4472 m3_ops
.to_files_info
= m3_files_info
;
4473 m3_ops
.to_insert_breakpoint
= memory_insert_breakpoint
;
4474 m3_ops
.to_remove_breakpoint
= memory_remove_breakpoint
;
4475 m3_ops
.to_terminal_init
= terminal_init_inferior
;
4476 m3_ops
.to_terminal_inferior
= terminal_inferior
;
4477 m3_ops
.to_terminal_ours_for_output
= terminal_ours_for_output
;
4478 m3_ops
.to_terminal_ours
= terminal_ours
;
4479 m3_ops
.to_terminal_info
= child_terminal_info
;
4480 m3_ops
.to_kill
= m3_kill_inferior
;
4481 m3_ops
.to_create_inferior
= m3_create_inferior
;
4482 m3_ops
.to_mourn_inferior
= m3_mourn_inferior
;
4483 m3_ops
.to_can_run
= m3_can_run
;
4484 m3_ops
.to_stop
= m3_stop
;
4485 m3_ops
.to_pid_to_exec_file
= m3_pid_to_exec_file
;
4486 m3_ops
.to_stratum
= process_stratum
;
4487 m3_ops
.to_has_all_memory
= 1;
4488 m3_ops
.to_has_memory
= 1;
4489 m3_ops
.to_has_stack
= 1;
4490 m3_ops
.to_has_registers
= 1;
4491 m3_ops
.to_has_execution
= 1;
4492 m3_ops
.to_magic
= OPS_MAGIC
;
4496 _initialize_m3_nat (void)
4501 add_target (&m3_ops
);
4503 ret
= mach_port_allocate (mach_task_self (),
4504 MACH_PORT_RIGHT_PORT_SET
,
4505 &inferior_wait_port_set
);
4506 if (ret
!= KERN_SUCCESS
)
4507 internal_error (__FILE__
, __LINE__
,
4508 "initial port set %s", mach_error_string (ret
));
4510 /* mach_really_wait now waits for this */
4511 currently_waiting_for
= inferior_wait_port_set
;
4513 ret
= netname_look_up (name_server_port
, hostname
, "MachID", &mid_server
);
4514 if (ret
!= KERN_SUCCESS
)
4516 mid_server
= MACH_PORT_NULL
;
4518 warning ("initialize machid: netname_lookup_up(MachID) : %s",
4519 mach_error_string (ret
));
4520 warning ("Some (most?) features disabled...");
4523 mid_auth
= mach_privileged_host_port ();
4524 if (mid_auth
== MACH_PORT_NULL
)
4525 mid_auth
= mach_task_self ();
4527 obstack_init (port_chain_obstack
);
4529 ret
= mach_port_allocate (mach_task_self (),
4530 MACH_PORT_RIGHT_RECEIVE
,
4531 &thread_exception_port
);
4532 CHK ("Creating thread_exception_port for single stepping", ret
);
4534 ret
= mach_port_insert_right (mach_task_self (),
4535 thread_exception_port
,
4536 thread_exception_port
,
4537 MACH_MSG_TYPE_MAKE_SEND
);
4538 CHK ("Inserting send right to thread_exception_port", ret
);
4540 /* Allocate message port */
4541 ret
= mach_port_allocate (mach_task_self (),
4542 MACH_PORT_RIGHT_RECEIVE
,
4544 if (ret
!= KERN_SUCCESS
)
4545 warning ("Creating message port %s", mach_error_string (ret
));
4548 char buf
[MAX_NAME_LEN
];
4549 ret
= mach_port_move_member (mach_task_self (),
4551 inferior_wait_port_set
);
4552 if (ret
!= KERN_SUCCESS
)
4553 warning ("message move member %s", mach_error_string (ret
));
4556 /* @@@@ No way to change message port name currently */
4557 /* Foo. This assumes gdb has a unix pid */
4558 sprintf (buf
, "gdb-%d", getpid ());
4559 gdb_register_port (buf
, our_message_port
);
4562 /* Heap for thread commands */
4563 obstack_init (cproc_obstack
);
4565 add_mach_specific_commands ();