1 /* Interface GDB to Mach 3.0 operating systems.
2 (Most) Mach 3.0 related routines live in this file.
4 Copyright (C) 1992 Free Software Foundation, Inc.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
23 * Author: Jukka Virtanen <jtv@hut.fi>
25 * Helsinki University of Technology
28 * Thanks to my friends who helped with ideas and testing:
30 * Johannes Helander, Antti Louko, Tero Mononen,
31 * jvh@cs.hut.fi alo@hut.fi tmo@cs.hut.fi
33 * Tero Kivinen and Eamonn McManus
34 * kivinen@cs.hut.fi emcmanus@gr.osf.org
41 #include <servers/netname.h>
42 #include <servers/machid.h>
43 #include <mach/message.h>
44 #include <mach/notify.h>
45 #include <mach_error.h>
46 #include <mach/exception.h>
47 #include <mach/vm_attributes.h>
60 #include <servers/machid_lib.h>
62 #define MACH_TYPE_TASK 1
63 #define MACH_TYPE_THREAD 2
66 /* Included only for signal names and NSIG
68 * note: There are many problems in signal handling with
69 * gdb in Mach 3.0 in general.
72 #define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
76 /* This is what a cproc looks like. This is here partly because
77 cthread_internals.h is not a header we can just #include, partly with
78 an eye towards perhaps getting this to work with cross-debugging
79 someday. Best solution is if CMU publishes a real interface to this
81 #define CPROC_NEXT_OFFSET 0
82 #define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
83 #define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
84 #define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
85 #define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
86 #define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
87 #define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
88 #define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
89 #define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
90 #define CPROC_REPLY_SIZE (sizeof (mach_port_t))
91 #define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
92 #define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
93 #define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
94 #define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
95 #define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
96 #define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
97 #define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
98 #define CPROC_WIRED_SIZE (sizeof (mach_port_t))
99 #define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
100 #define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
101 #define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
102 #define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
103 #define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
104 #define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
105 #define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
106 #define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
107 #define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
109 /* Values for the state field in the cproc. */
110 #define CPROC_RUNNING 0
111 #define CPROC_SWITCHING 1
112 #define CPROC_BLOCKED 2
113 #define CPROC_CONDWAIT 4
115 /* For cproc and kernel thread mapping */
116 typedef struct gdb_thread
{
121 boolean_t in_emulator
;
124 /* This is for the mthreads list. It points to the cproc list.
125 Perhaps the two lists should be merged (or perhaps it was a mistake
126 to make them both use a struct gdb_thread). */
127 struct gdb_thread
*cproc
;
129 /* These are for the cproc list, which is linked through the next field
130 of the struct gdb_thread. */
131 char raw_cproc
[CPROC_SIZE
];
132 /* The cthread which is pointed to by the incarnation field from the
133 cproc. This points to the copy we've read into GDB. */
135 /* Point back to the mthreads list. */
137 struct gdb_thread
*next
;
141 * Actions for Mach exceptions.
143 * sigmap field maps the exception to corresponding Unix signal.
145 * I do not know how to map the exception to unix signal
146 * if SIG_UNKNOWN is specified.
149 struct exception_list
{
154 } exception_map
[] = {
155 {"not_mach3_exception", FALSE
, TRUE
, SIG_UNKNOWN
},
156 {"EXC_BAD_ACCESS", FALSE
, TRUE
, SIGSEGV
},
157 {"EXC_BAD_INSTRUCTION", FALSE
, TRUE
, SIGILL
},
158 {"EXC_ARITHMETIC", FALSE
, TRUE
, SIGFPE
},
159 {"EXC_EMULATION", FALSE
, TRUE
, SIGEMT
}, /* ??? */
160 {"EXC_SOFTWARE", FALSE
, TRUE
, SIG_UNKNOWN
},
161 {"EXC_BREAKPOINT", FALSE
, FALSE
, SIGTRAP
}
164 /* Mach exception table size */
165 int max_exception
= sizeof(exception_map
)/sizeof(struct exception_list
) - 1;
167 #define MAX_EXCEPTION max_exception
169 WAITTYPE wait_status
;
171 /* If you define this, intercepted bsd server calls will be
172 * dumped while waiting the inferior to EXEC the correct
175 /* #define DUMP_SYSCALL /* debugging interceptor */
177 /* xx_debug() outputs messages if this is nonzero.
178 * If > 1, DUMP_SYSCALL will dump message contents.
182 /* "Temporary" debug stuff */
184 xx_debug (fmt
, a
,b
,c
)
189 warning (fmt
, a
, b
, c
);
192 /* This is in libmach.a */
193 extern mach_port_t name_server_port
;
195 /* Set in catch_exception_raise */
196 int stop_exception
, stop_code
, stop_subcode
;
197 int stopped_in_exception
;
199 /* Thread that was the active thread when we stopped */
200 thread_t stop_thread
= MACH_PORT_NULL
;
204 /* Set when task is attached or created */
205 boolean_t emulator_present
= FALSE
;
207 task_t inferior_task
;
208 thread_t current_thread
;
210 /* Exception ports for inferior task */
211 mach_port_t inferior_exception_port
= MACH_PORT_NULL
;
212 mach_port_t inferior_old_exception_port
= MACH_PORT_NULL
;
214 /* task exceptions and notifications */
215 mach_port_t inferior_wait_port_set
= MACH_PORT_NULL
;
216 mach_port_t our_notify_port
= MACH_PORT_NULL
;
218 /* This is "inferior_wait_port_set" when not single stepping, and
219 * "singlestepped_thread_port" when we are single stepping.
221 * This is protected by a cleanup function: discard_single_step()
223 mach_port_t currently_waiting_for
= MACH_PORT_NULL
;
225 /* A port for external messages to gdb.
226 * External in the meaning that they do not come
227 * from the inferior_task, but rather from external
230 * As a debugging feature:
231 * A debugger debugging another debugger can stop the
232 * inferior debugger by the following command sequence
233 * (without running external programs)
235 * (top-gdb) set stop_inferior_gdb ()
238 mach_port_t our_message_port
= MACH_PORT_NULL
;
240 /* For single stepping */
241 mach_port_t thread_exception_port
= MACH_PORT_NULL
;
242 mach_port_t thread_saved_exception_port
= MACH_PORT_NULL
;
243 mach_port_t singlestepped_thread_port
= MACH_PORT_NULL
;
245 /* For machid calls */
246 mach_port_t mid_server
= MACH_PORT_NULL
;
247 mach_port_t mid_auth
= MACH_PORT_NULL
;
249 /* If gdb thinks the inferior task is not suspended, it
250 * must take suspend/abort the threads when it reads the state.
252 int must_suspend_thread
= 0;
254 /* When single stepping, we switch the port that mach_really_wait() listens to.
255 * This cleanup is a guard to prevent the port set from being left to
256 * the singlestepped_thread_port when error() is called.
257 * This is nonzero only when we are single stepping.
259 #define NULL_CLEANUP (struct cleanup *)0
260 struct cleanup
*cleanup_step
= NULL_CLEANUP
;
263 extern struct target_ops m3_ops
;
264 static void m3_kill_inferior ();
267 #define MACH_TYPE_EXCEPTION_PORT -1
270 /* Chain of ports to remember requested notifications. */
273 struct port_chain
*next
;
276 int mid
; /* Now only valid with MACH_TYPE_THREAD and */
277 /* MACH_TYPE_THREAD */
279 typedef struct port_chain
*port_chain_t
;
281 /* Room for chain nodes comes from pchain_obstack */
282 struct obstack pchain_obstack
;
283 struct obstack
*port_chain_obstack
= &pchain_obstack
;
285 /* For thread handling */
286 struct obstack Cproc_obstack
;
287 struct obstack
*cproc_obstack
= &Cproc_obstack
;
289 /* the list of notified ports */
290 port_chain_t notify_chain
= (port_chain_t
) NULL
;
293 port_chain_insert (list
, name
, type
)
302 if (! MACH_PORT_VALID (name
))
305 if (type
== MACH_TYPE_TASK
|| type
== MACH_TYPE_THREAD
)
307 if (! MACH_PORT_VALID (mid_server
))
309 warning ("Machid server port invalid, can not map port 0x%x to MID",
315 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
317 if (ret
!= KERN_SUCCESS
)
319 warning ("Can not map name (0x%x) to MID with machid", name
);
327 new = (port_chain_t
) obstack_alloc (port_chain_obstack
,
328 sizeof (struct port_chain
));
338 port_chain_delete (list
, elem
)
343 if (list
->port
== elem
)
348 if (list
->next
->port
== elem
)
349 list
->next
= list
->next
->next
; /* GCd with obstack_free() */
357 port_chain_destroy (ostack
)
358 struct obstack
*ostack
;
360 obstack_free (ostack
, 0);
361 obstack_init (ostack
);
365 port_chain_member (list
, elem
)
371 if (list
->port
== elem
)
375 return (port_chain_t
) NULL
;
379 map_port_name_to_mid (name
, type
)
385 if (!MACH_PORT_VALID (name
))
388 elem
= port_chain_member (notify_chain
, name
);
390 if (elem
&& (elem
->type
== type
))
396 if (! MACH_PORT_VALID (mid_server
))
398 warning ("Machid server port invalid, can not map port 0x%x to mid",
407 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
409 if (ret
!= KERN_SUCCESS
)
411 warning ("Can not map name (0x%x) to mid with machid", name
);
418 /* Guard for currently_waiting_for and singlestepped_thread_port */
420 discard_single_step (thread
)
423 currently_waiting_for
= inferior_wait_port_set
;
425 cleanup_step
= NULL_CLEANUP
;
426 if (MACH_PORT_VALID (thread
) && MACH_PORT_VALID (singlestepped_thread_port
))
427 setup_single_step (thread
, FALSE
);
430 setup_single_step (thread
, start_step
)
432 boolean_t start_step
;
436 if (! MACH_PORT_VALID (thread
))
437 error ("Invalid thread supplied to setup_single_step");
442 /* Get the current thread exception port */
443 ret
= thread_get_exception_port (thread
, &teport
);
444 CHK ("Getting thread's exception port", ret
);
448 if (MACH_PORT_VALID (singlestepped_thread_port
))
450 warning ("Singlestepped_thread_port (0x%x) is still valid?",
451 singlestepped_thread_port
);
452 singlestepped_thread_port
= MACH_PORT_NULL
;
455 /* If we are already stepping this thread */
456 if (MACH_PORT_VALID (teport
) && teport
== thread_exception_port
)
458 ret
= mach_port_deallocate (mach_task_self (), teport
);
459 CHK ("Could not deallocate thread exception port", ret
);
463 ret
= thread_set_exception_port (thread
, thread_exception_port
);
464 CHK ("Setting exception port for thread", ret
);
466 /* Insert thread exception port to wait port set */
467 ret
= mach_port_move_member (mach_task_self(),
468 thread_exception_port
,
469 inferior_wait_port_set
);
470 CHK ("Moving thread exception port to inferior_wait_port_set",
473 thread_saved_exception_port
= teport
;
476 thread_trace (thread
, TRUE
);
478 singlestepped_thread_port
= thread_exception_port
;
479 currently_waiting_for
= singlestepped_thread_port
;
480 cleanup_step
= make_cleanup (discard_single_step
, thread
);
484 if (! MACH_PORT_VALID (teport
))
485 error ("Single stepped thread had an invalid exception port?");
487 if (teport
!= thread_exception_port
)
488 error ("Single stepped thread had an unknown exception port?");
490 ret
= mach_port_deallocate (mach_task_self (), teport
);
491 CHK ("Couldn't deallocate thread exception port", ret
);
493 /* Remove thread exception port from wait port set */
494 ret
= mach_port_move_member (mach_task_self(),
495 thread_exception_port
,
497 CHK ("Removing thread exception port from inferior_wait_port_set",
500 /* Restore thread's old exception port */
501 ret
= thread_set_exception_port (thread
,
502 thread_saved_exception_port
);
503 CHK ("Restoring stepped thread's exception port", ret
);
505 if (MACH_PORT_VALID (thread_saved_exception_port
))
506 (void) mach_port_deallocate (mach_task_self (),
507 thread_saved_exception_port
);
509 thread_trace (thread
, FALSE
);
511 singlestepped_thread_port
= MACH_PORT_NULL
;
512 currently_waiting_for
= inferior_wait_port_set
;
514 discard_cleanups (cleanup_step
);
520 request_notify (name
, variant
, type
)
522 mach_msg_id_t variant
;
526 mach_port_t previous_port_dummy
= MACH_PORT_NULL
;
528 if (! MACH_PORT_VALID (name
))
531 if (port_chain_member (notify_chain
, name
))
534 ret
= mach_port_request_notification (mach_task_self(),
539 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
540 &previous_port_dummy
);
541 CHK ("Serious: request_notify failed", ret
);
543 (void) mach_port_deallocate (mach_task_self (),
544 previous_port_dummy
);
546 notify_chain
= port_chain_insert (notify_chain
, name
, type
);
549 reverse_msg_bits(msgp
, type
)
550 mach_msg_header_t
*msgp
;
554 rbits
= MACH_MSGH_BITS_REMOTE(msgp
->msgh_bits
);
557 (msgp
->msgh_bits
& ~MACH_MSGH_BITS_PORTS_MASK
) |
558 MACH_MSGH_BITS(lbits
,rbits
);
561 /* On the third day He said:
564 and then it was global.
566 When creating the inferior fork, the
567 child code in inflow.c sets the name of the
568 bootstrap_port in its address space to this
571 The name is transferred to our address space
572 with mach3_read_inferior().
574 Thou shalt not do this with
575 task_get_bootstrap_port() in this task, since
576 the name in the inferior task is different than
579 For blessed are the meek, as they shall inherit
582 mach_port_t original_server_port_name
= MACH_PORT_NULL
;
585 /* Called from inferior after FORK but before EXEC */
591 /* Get the NAME of the bootstrap port in this task
592 so that GDB can read it */
593 ret
= task_get_bootstrap_port (mach_task_self (),
594 &original_server_port_name
);
595 if (ret
!= KERN_SUCCESS
)
597 ret
= mach_port_deallocate (mach_task_self (),
598 original_server_port_name
);
599 if (ret
!= KERN_SUCCESS
)
602 /* Suspend this task to let the parent change my ports.
603 Resumed by the debugger */
604 ret
= task_suspend (mach_task_self ());
605 if (ret
!= KERN_SUCCESS
)
610 * Intercept system calls to Unix server.
611 * After EXEC_COUNTER calls to exec(), return.
613 * Pre-assertion: Child is suspended. (Not verified)
614 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
618 intercept_exec_calls (exec_counter
)
621 int terminal_initted
= 0;
623 struct syscall_msg_t
{
624 mach_msg_header_t header
;
625 mach_msg_type_t type
;
626 char room
[ 2000 ]; /* Enuff space */
629 struct syscall_msg_t syscall_in
, syscall_out
;
631 mach_port_t fake_server
;
632 mach_port_t original_server_send
;
633 mach_port_t original_exec_reply
;
634 mach_port_t exec_reply
;
635 mach_port_t exec_reply_send
;
636 mach_msg_type_name_t acquired
;
637 mach_port_t emulator_server_port_name
;
638 struct task_basic_info info
;
639 mach_msg_type_number_t info_count
;
643 if (exec_counter
<= 0)
644 return; /* We are already set up in the correct program */
646 ret
= mach_port_allocate(mach_task_self(),
647 MACH_PORT_RIGHT_RECEIVE
,
649 CHK("create inferior_fake_server port failed", ret
);
651 /* Wait for inferior_task to suspend itself */
654 info_count
= sizeof (info
);
655 ret
= task_info (inferior_task
,
659 CHK ("Task info", ret
);
661 if (info
.suspend_count
)
664 /* Note that the definition of the parameter was undefined
665 * at the time of this writing, so I just use an `ad hoc' value.
667 (void) swtch_pri (42); /* Universal Priority Value */
670 /* Read the inferior's bootstrap port name */
671 if (!mach3_read_inferior (&original_server_port_name
,
672 &original_server_port_name
,
673 sizeof (original_server_port_name
)))
674 error ("Can't read inferior task bootstrap port name");
676 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
677 /* Should get refs, and set them back when restoring */
678 /* Steal the original bsd server send right from inferior */
679 ret
= mach_port_extract_right (inferior_task
,
680 original_server_port_name
,
681 MACH_MSG_TYPE_MOVE_SEND
,
682 &original_server_send
,
684 CHK("mach_port_extract_right (bsd server send)",ret
);
686 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
687 error("Incorrect right extracted, send right to bsd server excpected");
689 ret
= mach_port_insert_right (inferior_task
,
690 original_server_port_name
,
692 MACH_MSG_TYPE_MAKE_SEND
);
693 CHK("mach_port_insert_right (fake server send)",ret
);
695 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
697 original_server_port_name
, original_server_send
);
699 /* A receive right to the reply generated by unix server exec() request */
700 ret
= mach_port_allocate(mach_task_self(),
701 MACH_PORT_RIGHT_RECEIVE
,
703 CHK("create intercepted_reply_port port failed", ret
);
705 /* Pass this send right to Unix server so it replies to us after exec() */
706 ret
= mach_port_extract_right (mach_task_self (),
708 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
711 CHK("mach_port_extract_right (exec_reply)",ret
);
713 if (acquired
!= MACH_MSG_TYPE_PORT_SEND_ONCE
)
714 error("Incorrect right extracted, send once excpected for exec reply");
716 ret
= mach_port_move_member(mach_task_self(),
718 inferior_wait_port_set
);
719 CHK ("Moving fake syscall port to inferior_wait_port_set", ret
);
721 xx_debug ("syscall fake server set up, resuming inferior\n");
723 ret
= task_resume (inferior_task
);
724 CHK("task_resume (startup)", ret
);
726 /* Read requests from the inferior.
727 Pass directly through everything else except exec() calls.
729 while(exec_counter
> 0)
731 ret
= mach_msg (&syscall_in
.header
, /* header */
732 MACH_RCV_MSG
, /* options */
734 sizeof (struct syscall_msg_t
), /* receive size */
735 inferior_wait_port_set
, /* receive_name */
736 MACH_MSG_TIMEOUT_NONE
,
738 CHK("mach_msg (intercepted sycall)", ret
);
741 print_msg (&syscall_in
.header
);
744 /* ASSERT : msgh_local_port == fake_server */
746 if (notify_server (&syscall_in
.header
, &syscall_out
.header
))
747 error ("received a notify while intercepting syscalls");
749 if (syscall_in
.header
.msgh_id
== MIG_EXEC_SYSCALL_ID
)
751 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter
);
752 if (exec_counter
== 1)
754 original_exec_reply
= syscall_in
.header
.msgh_remote_port
;
755 syscall_in
.header
.msgh_remote_port
= exec_reply_send
;
758 if (!terminal_initted
)
760 /* Now that the child has exec'd we know it has already set its
761 process group. On POSIX systems, tcsetpgrp will fail with
762 EPERM if we try it before the child's setpgid. */
764 /* Set up the "saved terminal modes" of the inferior
765 based on what modes we are starting it with. */
766 target_terminal_init ();
768 /* Install inferior's terminal modes. */
769 target_terminal_inferior ();
771 terminal_initted
= 1;
777 syscall_in
.header
.msgh_local_port
= syscall_in
.header
.msgh_remote_port
;
778 syscall_in
.header
.msgh_remote_port
= original_server_send
;
780 reverse_msg_bits(&syscall_in
.header
, MACH_MSG_TYPE_COPY_SEND
);
782 ret
= mach_msg_send (&syscall_in
.header
);
783 CHK ("Forwarded syscall", ret
);
786 ret
= mach_port_move_member(mach_task_self(),
789 CHK ("Moving fake syscall out of inferior_wait_port_set", ret
);
791 ret
= mach_port_move_member(mach_task_self(),
793 inferior_wait_port_set
);
794 CHK ("Moving exec_reply to inferior_wait_port_set", ret
);
796 ret
= mach_msg (&syscall_in
.header
, /* header */
797 MACH_RCV_MSG
, /* options */
799 sizeof (struct syscall_msg_t
), /* receive size */
800 inferior_wait_port_set
, /* receive_name */
801 MACH_MSG_TIMEOUT_NONE
,
803 CHK("mach_msg (exec reply)", ret
);
805 ret
= task_suspend (inferior_task
);
806 CHK ("Suspending inferior after last exec", ret
);
808 must_suspend_thread
= 0;
810 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
813 print_msg (&syscall_in
.header
);
816 /* Message should appear as if it came from the unix server */
817 syscall_in
.header
.msgh_local_port
= MACH_PORT_NULL
;
819 /* and go to the inferior task original reply port */
820 syscall_in
.header
.msgh_remote_port
= original_exec_reply
;
822 reverse_msg_bits(&syscall_in
.header
, MACH_MSG_TYPE_MOVE_SEND_ONCE
);
824 ret
= mach_msg_send (&syscall_in
.header
);
825 CHK ("Forwarding exec reply to inferior", ret
);
827 /* Garbage collect */
828 ret
= mach_port_deallocate (inferior_task
,
829 original_server_port_name
);
830 CHK ("deallocating fake server send right", ret
);
832 ret
= mach_port_insert_right (inferior_task
,
833 original_server_port_name
,
834 original_server_send
,
835 MACH_MSG_TYPE_MOVE_SEND
);
836 CHK ("Restoring the original bsd server send right", ret
);
838 ret
= mach_port_destroy (mach_task_self (),
840 fake_server
= MACH_PORT_DEAD
;
841 CHK("mach_port_destroy (fake_server)", ret
);
843 ret
= mach_port_destroy (mach_task_self (),
845 exec_reply
= MACH_PORT_DEAD
;
846 CHK("mach_port_destroy (exec_reply)", ret
);
848 xx_debug ("Done with exec call interception\n");
852 consume_send_rights (thread_list
, thread_count
)
853 thread_array_t thread_list
;
861 for (index
= 0; index
< thread_count
; index
++)
863 /* Since thread kill command kills threads, don't check ret */
864 (void) mach_port_deallocate (mach_task_self (),
865 thread_list
[ index
]);
869 /* suspend/abort/resume a thread. */
870 setup_thread (thread
, what
)
878 ret
= thread_suspend (thread
);
879 CHK ("setup_thread thread_suspend", ret
);
881 ret
= thread_abort (thread
);
882 CHK ("setup_thread thread_abort", ret
);
886 ret
= thread_resume (thread
);
887 CHK ("setup_thread thread_resume", ret
);
892 map_slot_to_mid (slot
, threads
, thread_count
)
894 thread_array_t threads
;
905 ret
= task_threads (inferior_task
, &threads
, &thread_count
);
906 CHK ("Can not select a thread from a dead task", ret
);
909 if (slot
< 0 || slot
>= thread_count
)
913 consume_send_rights (threads
, thread_count
);
914 (void) vm_deallocate (mach_task_self(), (vm_address_t
)threads
,
915 (thread_count
* sizeof(mach_port_t
)));
918 error ("invalid slot number");
923 mid
= map_port_name_to_mid (threads
[slot
], MACH_TYPE_THREAD
);
927 consume_send_rights (threads
, thread_count
);
928 (void) vm_deallocate (mach_task_self(), (vm_address_t
)threads
,
929 (thread_count
* sizeof(mach_port_t
)));
936 parse_thread_id (arg
, thread_count
, slots
)
949 while (*arg
&& (*arg
== ' ' || *arg
== '\t'))
955 /* Currently parse MID and @SLOTNUMBER */
960 error ("valid thread mid expected");
968 error ("invalid slot number");
970 /* If you want slot numbers to remain slot numbers, set slots.
972 * Well, since 0 is reserved, return the ordinal number
973 * of the thread rather than the slot number. Awk, this
974 * counts as a kludge.
979 if (thread_count
&& slot
>= thread_count
)
982 mid
= map_slot_to_mid (slot
);
987 /* THREAD_ID 0 is special; it selects the first kernel
988 * thread from the list (i.e. SLOTNUMBER 0)
989 * This is used when starting the program with 'run' or when attaching.
991 * If FLAG is 0 the context is not changed, and the registers, frame, etc
992 * will continue to describe the old thread.
994 * If FLAG is nonzero, really select the thread.
995 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
999 select_thread (task
, thread_id
, flag
)
1004 thread_array_t thread_list
;
1008 thread_t new_thread
= MACH_PORT_NULL
;
1011 error ("Can't select cprocs without kernel thread");
1013 ret
= task_threads (task
, &thread_list
, &thread_count
);
1014 if (ret
!= KERN_SUCCESS
)
1016 warning ("Can not select a thread from a dead task");
1017 m3_kill_inferior ();
1018 return KERN_FAILURE
;
1021 if (thread_count
== 0)
1023 /* The task can not do anything anymore, but it still
1024 * exists as a container for memory and ports.
1026 registers_changed ();
1027 warning ("Task %d has no threads",
1028 map_port_name_to_mid (task
, MACH_TYPE_TASK
));
1029 current_thread
= MACH_PORT_NULL
;
1030 (void) vm_deallocate(mach_task_self(),
1031 (vm_address_t
) thread_list
,
1032 (thread_count
* sizeof(mach_port_t
)));
1033 return KERN_FAILURE
;
1036 if (! thread_id
|| flag
== 2)
1038 /* First thread or a slotnumber */
1040 new_thread
= thread_list
[0];
1043 if (thread_id
< thread_count
)
1044 new_thread
= thread_list
[ thread_id
];
1047 (void) vm_deallocate(mach_task_self(),
1048 (vm_address_t
) thread_list
,
1049 (thread_count
* sizeof(mach_port_t
)));
1050 error ("No such thread slot number : %d", thread_id
);
1056 for (index
= 0; index
< thread_count
; index
++)
1057 if (thread_id
== map_port_name_to_mid (thread_list
[index
],
1060 new_thread
= thread_list
[index
];
1066 error ("No thread with mid %d", thread_id
);
1069 /* Notify when the selected thread dies */
1070 request_notify (new_thread
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_THREAD
);
1072 ret
= vm_deallocate(mach_task_self(),
1073 (vm_address_t
) thread_list
,
1074 (thread_count
* sizeof(mach_port_t
)));
1075 CHK ("vm_deallocate", ret
);
1078 current_thread
= new_thread
;
1082 if (MACH_PORT_VALID (current_thread
))
1084 /* Store the gdb's view of the thread we are deselecting
1086 * @@ I think gdb updates registers immediately when they are
1087 * changed, so don't do this.
1089 ret
= thread_abort (current_thread
);
1090 CHK ("Could not abort system calls when saving state of old thread",
1092 target_prepare_to_store ();
1093 target_store_registers (-1);
1097 registers_changed ();
1099 current_thread
= new_thread
;
1101 ret
= thread_abort (current_thread
);
1102 CHK ("Could not abort system calls when selecting a thread", ret
);
1104 stop_pc
= read_pc();
1105 flush_cached_frames ();
1107 select_frame (get_current_frame (), 0);
1110 return KERN_SUCCESS
;
1114 * Switch to use thread named NEW_THREAD.
1118 switch_to_thread (new_thread
)
1119 thread_t new_thread
;
1121 thread_t saved_thread
= current_thread
;
1124 mid
= map_port_name_to_mid (new_thread
,
1127 warning ("Can't map thread name 0x%x to mid", new_thread
);
1128 else if (select_thread (inferior_task
, mid
, 1) != KERN_SUCCESS
)
1131 current_thread
= saved_thread
;
1132 error ("Could not select thread %d", mid
);
1138 /* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1139 * Note that the registers are not yet valid in the inferior task.
1147 push_target (&m3_ops
);
1149 inferior_task
= task_by_pid (pid
);
1151 if (! MACH_PORT_VALID (inferior_task
))
1152 error ("Can not map Unix pid %d to Mach task", pid
);
1154 /* Clean up previous notifications and create new ones */
1155 setup_notify_port (1);
1157 /* When notification appears, the inferior task has died */
1158 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
1160 emulator_present
= have_emulator_p (inferior_task
);
1162 /* By default, select the first thread,
1163 * If task has no threads, gives a warning
1164 * Does not fetch registers, since they are not yet valid.
1166 select_thread (inferior_task
, 0, 0);
1168 inferior_exception_port
= MACH_PORT_NULL
;
1170 setup_exception_port ();
1172 xx_debug ("Now the debugged task is created\n");
1174 /* One trap to exec the shell, one to exec the program being debugged. */
1175 intercept_exec_calls (2);
1178 setup_exception_port ()
1182 ret
= mach_port_allocate (mach_task_self(),
1183 MACH_PORT_RIGHT_RECEIVE
,
1184 &inferior_exception_port
);
1185 CHK("mach_port_allocate",ret
);
1187 /* add send right */
1188 ret
= mach_port_insert_right (mach_task_self (),
1189 inferior_exception_port
,
1190 inferior_exception_port
,
1191 MACH_MSG_TYPE_MAKE_SEND
);
1192 CHK("mach_port_insert_right",ret
);
1194 ret
= mach_port_move_member (mach_task_self(),
1195 inferior_exception_port
,
1196 inferior_wait_port_set
);
1197 CHK("mach_port_move_member",ret
);
1199 ret
= task_get_special_port (inferior_task
,
1200 TASK_EXCEPTION_PORT
,
1201 &inferior_old_exception_port
);
1202 CHK ("task_get_special_port(old exc)",ret
);
1204 ret
= task_set_special_port (inferior_task
,
1205 TASK_EXCEPTION_PORT
,
1206 inferior_exception_port
);
1207 CHK("task_set_special_port",ret
);
1209 ret
= mach_port_deallocate (mach_task_self (),
1210 inferior_exception_port
);
1211 CHK("mack_port_deallocate",ret
);
1214 /* When notify appears, the inferior_task's exception
1215 * port has been destroyed.
1217 * Not used, since the dead_name_notification already
1218 * appears when task dies.
1221 request_notify (inferior_exception_port
,
1222 MACH_NOTIFY_NO_SENDERS
,
1223 MACH_TYPE_EXCEPTION_PORT
);
1227 /* Nonzero if gdb is waiting for a message */
1228 int mach_really_waiting
;
1230 /* Wait for the inferior to stop for some reason.
1231 - Loop on notifications until inferior_task dies.
1232 - Loop on exceptions until stopped_in_exception comes true.
1233 (e.g. we receive a single step trace trap)
1234 - a message arrives to gdb's message port
1236 There is no other way to exit this loop.
1238 Returns the inferior_pid for rest of gdb.
1239 Side effects: Set *OURSTATUS. */
1241 mach_really_wait (pid
, ourstatus
)
1243 struct target_waitstatus
*ourstatus
;
1249 mach_msg_header_t header
;
1250 mach_msg_type_t foo
;
1254 /* Either notify (death), exception or message can stop the inferior */
1255 stopped_in_exception
= FALSE
;
1261 stop_exception
= stop_code
= stop_subcode
= -1;
1262 stop_thread
= MACH_PORT_NULL
;
1264 mach_really_waiting
= 1;
1265 ret
= mach_msg (&in_msg
.header
, /* header */
1266 MACH_RCV_MSG
, /* options */
1268 sizeof (struct msg
), /* receive size */
1269 currently_waiting_for
, /* receive name */
1270 MACH_MSG_TIMEOUT_NONE
,
1272 mach_really_waiting
= 0;
1273 CHK("mach_msg (receive)", ret
);
1275 /* Check if we received a notify of the childs' death */
1276 if (notify_server (&in_msg
.header
, &out_msg
.header
))
1278 /* If inferior_task is null then the inferior has
1279 gone away and we want to return to command level.
1280 Otherwise it was just an informative message and we
1281 need to look to see if there are any more. */
1282 if (inferior_task
!= MACH_PORT_NULL
)
1286 /* Collect Unix exit status for gdb */
1288 wait3(&w
, WNOHANG
, 0);
1290 /* This mess is here to check that the rest of
1291 * gdb knows that the inferior died. It also
1292 * tries to hack around the fact that Mach 3.0 (mk69)
1293 * unix server (ux28) does not always know what
1294 * has happened to it's children when mach-magic
1295 * is applied on them.
1297 if ((!WIFEXITED(w
) && WIFSTOPPED(w
)) ||
1298 (WIFEXITED(w
) && WEXITSTATUS(w
) > 0377))
1301 warning ("Using exit value 0 for terminated task");
1303 else if (!WIFEXITED(w
))
1305 int sig
= WTERMSIG(w
);
1307 /* Signals cause problems. Warn the user. */
1308 if (sig
!= SIGKILL
) /* Bad luck if garbage matches this */
1309 warning ("The terminating signal stuff may be nonsense");
1310 else if (sig
> NSIG
)
1313 warning ("Using exit value 0 for terminated task");
1316 store_waitstatus (ourstatus
, w
);
1317 return inferior_pid
;
1321 /* Hmm. Check for exception, as it was not a notification.
1322 exc_server() does an upcall to catch_exception_raise()
1323 if this rpc is an exception. Further actions are decided
1326 if (! exc_server (&in_msg
.header
, &out_msg
.header
))
1329 /* Not an exception, check for message.
1331 * Messages don't come from the inferior, or if they
1332 * do they better be asynchronous or it will hang.
1334 if (gdb_message_server (&in_msg
.header
))
1337 error ("Unrecognized message received in mach_really_wait");
1340 /* Send the reply of the exception rpc to the suspended task */
1341 ret
= mach_msg_send (&out_msg
.header
);
1342 CHK ("mach_msg_send (exc reply)", ret
);
1344 if (stopped_in_exception
)
1346 /* Get unix state. May be changed in mach3_exception_actions() */
1347 wait3(&w
, WNOHANG
, 0);
1349 mach3_exception_actions (&w
, FALSE
, "Task");
1351 store_waitstatus (ourstatus
, w
);
1352 return inferior_pid
;
1357 /* Called by macro DO_QUIT() in utils.c(quit).
1358 * This is called just before calling error() to return to command level
1366 if (mach_really_waiting
)
1368 ret
= task_suspend (inferior_task
);
1370 if (ret
!= KERN_SUCCESS
)
1372 warning ("Could not suspend task for interrupt: %s",
1373 mach_error_string (ret
));
1374 mach_really_waiting
= 0;
1379 must_suspend_thread
= 0;
1380 mach_really_waiting
= 0;
1382 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1385 warning ("Selecting first existing kernel thread");
1389 current_thread
= MACH_PORT_NULL
; /* Force setup */
1390 select_thread (inferior_task
, mid
, 1);
1396 /* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
1398 /* If ^C is typed when we are waiting for a message
1399 * and your Unix server is able to notice that we
1402 * Called by REQUEST_QUIT() from utils.c(request_quit)
1405 mach3_request_quit ()
1407 if (mach_really_waiting
)
1413 * Gdb message server.
1414 * Currently implemented is the STOP message, that causes
1415 * gdb to return to the command level like ^C had been typed from terminal.
1418 gdb_message_server (InP
)
1419 mach_msg_header_t
*InP
;
1424 if (InP
->msgh_local_port
== our_message_port
)
1426 /* A message coming to our_message_port. Check validity */
1427 switch (InP
->msgh_id
) {
1429 case GDB_MESSAGE_ID_STOP
:
1430 ret
= task_suspend (inferior_task
);
1431 if (ret
!= KERN_SUCCESS
)
1432 warning ("Could not suspend task for stop message: %s",
1433 mach_error_string (ret
));
1435 /* QUIT in mach_really_wait() loop. */
1440 warning ("Invalid message id %d received, ignored.",
1448 /* Message not handled by this server */
1452 /* NOTE: This is not an RPC call. It is a simpleroutine.
1454 * This is not called from this gdb code.
1456 * It may be called by another debugger to cause this
1457 * debugger to enter command level:
1459 * (gdb) set stop_inferior_gdb ()
1462 * External program "stop-gdb" implements this also.
1465 stop_inferior_gdb ()
1469 /* Code generated by mig, with minor cleanups :-)
1471 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1475 mach_msg_header_t Head
;
1480 register Request
*InP
= &Mess
;
1482 InP
->Head
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0);
1484 /* msgh_size passed as argument */
1485 InP
->Head
.msgh_remote_port
= our_message_port
;
1486 InP
->Head
.msgh_local_port
= MACH_PORT_NULL
;
1487 InP
->Head
.msgh_seqno
= 0;
1488 InP
->Head
.msgh_id
= GDB_MESSAGE_ID_STOP
;
1490 ret
= mach_msg (&InP
->Head
,
1491 MACH_SEND_MSG
|MACH_MSG_OPTION_NONE
,
1495 MACH_MSG_TIMEOUT_NONE
,
1499 #ifdef THREAD_ALLOWED_TO_BREAK
1501 * Return 1 if the MID specifies the thread that caused the
1503 * Since catch_exception_raise() selects the thread causing
1504 * the last exception to current_thread, we just check that
1505 * it is selected and the last exception was a breakpoint.
1508 mach_thread_for_breakpoint (mid
)
1511 int cmid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1515 mid
= map_slot_to_mid (-(mid
+1), 0, 0);
1517 return 0; /* Don't stop, no such slot */
1520 if (! mid
|| cmid
== -1)
1521 return 1; /* stop */
1523 return cmid
== mid
&& stop_exception
== EXC_BREAKPOINT
;
1525 #endif /* THREAD_ALLOWED_TO_BREAK */
1527 #ifdef THREAD_PARSE_ID
1529 * Map a thread id string (MID or a @SLOTNUMBER)
1532 * 0 matches all threads.
1533 * Otherwise the meaning is defined only in this file.
1534 * (mach_thread_for_breakpoint uses it)
1536 * @@ This allows non-existent MIDs to be specified.
1537 * It now also allows non-existent slots to be
1538 * specified. (Slot numbers stored are negative,
1539 * and the magnitude is one greater than the actual
1540 * slot index. (Since 0 is reserved))
1543 mach_thread_parse_id (arg
)
1548 error ("thread id excpected");
1549 mid
= parse_thread_id (arg
, 0, 1);
1553 #endif /* THREAD_PARSE_ID */
1555 #ifdef THREAD_OUTPUT_ID
1557 mach_thread_output_id (mid
)
1560 static char foobar
[20];
1563 sprintf (foobar
, "mid %d", mid
);
1565 sprintf (foobar
, "@%d", -(mid
+1));
1567 sprintf (foobar
, "*any thread*");
1571 #endif /* THREAD_OUTPUT_ID */
1573 /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
1575 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1577 * if SELECT_IT is nonzero, reselect the thread that was active when
1578 * we stopped at a breakpoint.
1582 mach3_prepare_to_proceed (select_it
)
1586 stop_thread
!= current_thread
&&
1587 stop_exception
== EXC_BREAKPOINT
)
1594 mid
= switch_to_thread (stop_thread
);
1602 /* this stuff here is an upcall via libmach/excServer.c
1603 and mach_really_wait which does the actual upcall.
1605 The code will pass the exception to the inferior if:
1607 - The task that signaled is not the inferior task
1608 (e.g. when debugging another debugger)
1610 - The user has explicitely requested to pass on the exceptions.
1611 (e.g to the default unix exception handler, which maps
1612 exceptions to signals, or the user has her own exception handler)
1614 - If the thread that signaled is being single-stepped and it
1615 has set it's own exception port and the exception is not
1616 EXC_BREAKPOINT. (Maybe this is not desirable?)
1620 catch_exception_raise (port
, thread
, task
, exception
, code
, subcode
)
1624 int exception
, code
, subcode
;
1627 boolean_t signal_thread
;
1628 int mid
= map_port_name_to_mid (thread
, MACH_TYPE_THREAD
);
1630 if (! MACH_PORT_VALID (thread
))
1632 /* If the exception was sent and thread dies before we
1633 receive it, THREAD will be MACH_PORT_DEAD
1636 current_thread
= thread
= MACH_PORT_NULL
;
1637 error ("Received exception from nonexistent thread");
1640 /* Check if the task died in transit.
1641 * @@ Isn't the thread also invalid in such case?
1643 if (! MACH_PORT_VALID (task
))
1645 current_thread
= thread
= MACH_PORT_NULL
;
1646 error ("Received exception from nonexistent task");
1649 if (exception
< 0 || exception
> MAX_EXCEPTION
)
1650 fatal ("catch_exception_raise: unknown exception code %d thread %d",
1654 if (! MACH_PORT_VALID (inferior_task
))
1655 error ("got an exception, but inferior_task is null or dead");
1657 stop_exception
= exception
;
1659 stop_subcode
= subcode
;
1660 stop_thread
= thread
;
1662 signal_thread
= exception
!= EXC_BREAKPOINT
&&
1663 port
== singlestepped_thread_port
&&
1664 MACH_PORT_VALID (thread_saved_exception_port
);
1666 /* If it was not our inferior or if we want to forward
1667 * the exception to the inferior's handler, do it here
1669 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1671 if (task
!= inferior_task
||
1673 exception_map
[exception
].forward
)
1675 mach_port_t eport
= inferior_old_exception_port
;
1680 GDB now forwards the exeption to thread's original handler,
1681 since the user propably knows what he is doing.
1682 Give a message, though.
1685 mach3_exception_actions ((WAITTYPE
*)NULL
, TRUE
, "Thread");
1686 eport
= thread_saved_exception_port
;
1689 /* Send the exception to the original handler */
1690 ret
= exception_raise (eport
,
1697 (void) mach_port_deallocate (mach_task_self (), task
);
1698 (void) mach_port_deallocate (mach_task_self (), thread
);
1700 /* If we come here, we don't want to trace any more, since we
1701 * will never stop for tracing anyway.
1703 discard_single_step (thread
);
1705 /* Do not stop the inferior */
1709 /* Now gdb handles the exception */
1710 stopped_in_exception
= TRUE
;
1712 ret
= task_suspend (task
);
1713 CHK ("Error suspending inferior after exception", ret
);
1715 must_suspend_thread
= 0;
1717 if (current_thread
!= thread
)
1719 if (MACH_PORT_VALID (singlestepped_thread_port
))
1720 /* Cleanup discards single stepping */
1721 error ("Exception from thread %d while singlestepping thread %d",
1723 map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
));
1725 /* Then select the thread that caused the exception */
1726 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
1727 error ("Could not select thread %d causing exception", mid
);
1729 warning ("Gdb selected thread %d", mid
);
1732 /* If we receive an exception that is not breakpoint
1733 * exception, we interrupt the single step and return to
1734 * debugger. Trace condition is cleared.
1736 if (MACH_PORT_VALID (singlestepped_thread_port
))
1738 if (stop_exception
!= EXC_BREAKPOINT
)
1739 warning ("Single step interrupted by exception");
1740 else if (port
== singlestepped_thread_port
)
1742 /* Single step exception occurred, remove trace bit
1743 * and return to gdb.
1745 if (! MACH_PORT_VALID (current_thread
))
1746 error ("Single stepped thread is not valid");
1748 /* Resume threads, but leave the task suspended */
1749 resume_all_threads (0);
1752 warning ("Breakpoint while single stepping?");
1754 discard_single_step (current_thread
);
1757 (void) mach_port_deallocate (mach_task_self (), task
);
1758 (void) mach_port_deallocate (mach_task_self (), thread
);
1760 return KERN_SUCCESS
;
1764 port_valid (port
, mask
)
1769 mach_port_type_t type
;
1771 ret
= mach_port_type (mach_task_self (),
1774 if (ret
!= KERN_SUCCESS
|| (type
& mask
) != mask
)
1779 /* @@ No vm read cache implemented yet */
1780 boolean_t vm_read_cache_valid
= FALSE
;
1783 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1784 * in gdb's address space.
1786 * Return 0 on failure; number of bytes read otherwise.
1789 mach3_read_inferior (addr
, myaddr
, length
)
1795 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1796 vm_size_t aligned_length
=
1797 (vm_size_t
) round_page (addr
+length
) - low_address
;
1798 pointer_t copied_memory
;
1801 /* Get memory from inferior with page aligned addresses */
1802 ret
= vm_read (inferior_task
,
1807 if (ret
!= KERN_SUCCESS
)
1809 /* the problem is that the inferior might be killed for whatever reason
1810 * before we go to mach_really_wait. This is one place that ought to
1811 * catch many of those errors.
1812 * @@ A better fix would be to make all external events to GDB
1813 * to arrive via a SINGLE port set. (Including user input!)
1816 if (! port_valid (inferior_task
, MACH_PORT_TYPE_SEND
))
1818 m3_kill_inferior ();
1819 error ("Inferior killed (task port invalid)");
1825 /* valprint.c gives nicer format if this does not
1826 screw it. Eamonn seems to like this, so I enable
1827 it if OSF is defined...
1829 warning ("[read inferior %x failed: %s]",
1830 addr
, mach_error_string (ret
));
1837 memcpy (myaddr
, (char *)addr
- low_address
+ copied_memory
, length
);
1839 ret
= vm_deallocate (mach_task_self (),
1842 CHK("mach3_read_inferior vm_deallocate failed", ret
);
1848 #define CHK_GOTO_OUT(str,ret) \
1849 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
1851 #define CHK_GOTO_OUT(str,ret) \
1852 do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
1855 struct vm_region_list
{
1856 struct vm_region_list
*next
;
1857 vm_prot_t protection
;
1862 struct obstack region_obstack
;
1865 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1866 * in gdb's address space.
1869 mach3_write_inferior (addr
, myaddr
, length
)
1875 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1876 vm_size_t aligned_length
=
1877 (vm_size_t
) round_page (addr
+length
) - low_address
;
1878 pointer_t copied_memory
;
1882 char *errstr
= "Bug in mach3_write_inferior";
1884 struct vm_region_list
*region_element
;
1885 struct vm_region_list
*region_head
= (struct vm_region_list
*)NULL
;
1887 /* Get memory from inferior with page aligned addresses */
1888 ret
= vm_read (inferior_task
,
1893 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret
);
1897 memcpy ((char *)addr
- low_address
+ copied_memory
, myaddr
, length
);
1899 obstack_init (®ion_obstack
);
1901 /* Do writes atomically.
1902 * First check for holes and unwritable memory.
1905 vm_size_t remaining_length
= aligned_length
;
1906 vm_address_t region_address
= low_address
;
1908 struct vm_region_list
*scan
;
1910 while(region_address
< low_address
+ aligned_length
)
1912 vm_prot_t protection
;
1913 vm_prot_t max_protection
;
1914 vm_inherit_t inheritance
;
1916 mach_port_t object_name
;
1918 vm_size_t region_length
= remaining_length
;
1919 vm_address_t old_address
= region_address
;
1921 ret
= vm_region (inferior_task
,
1930 CHK_GOTO_OUT ("vm_region failed", ret
);
1932 /* Check for holes in memory */
1933 if (old_address
!= region_address
)
1935 warning ("No memory at 0x%x. Nothing written",
1942 if (!(max_protection
& VM_PROT_WRITE
))
1944 warning ("Memory at address 0x%x is unwritable. Nothing written",
1951 /* Chain the regions for later use */
1953 (struct vm_region_list
*)
1954 obstack_alloc (®ion_obstack
, sizeof (struct vm_region_list
));
1956 region_element
->protection
= protection
;
1957 region_element
->start
= region_address
;
1958 region_element
->length
= region_length
;
1960 /* Chain the regions along with protections */
1961 region_element
->next
= region_head
;
1962 region_head
= region_element
;
1964 region_address
+= region_length
;
1965 remaining_length
= remaining_length
- region_length
;
1968 /* If things fail after this, we give up.
1969 * Somebody is messing up inferior_task's mappings.
1972 /* Enable writes to the chained vm regions */
1973 for (scan
= region_head
; scan
; scan
= scan
->next
)
1975 boolean_t protection_changed
= FALSE
;
1977 if (!(scan
->protection
& VM_PROT_WRITE
))
1979 ret
= vm_protect (inferior_task
,
1983 scan
->protection
| VM_PROT_WRITE
);
1984 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1988 ret
= vm_write (inferior_task
,
1992 CHK_GOTO_OUT ("vm_write failed", ret
);
1994 /* Set up the original region protections, if they were changed */
1995 for (scan
= region_head
; scan
; scan
= scan
->next
)
1997 boolean_t protection_changed
= FALSE
;
1999 if (!(scan
->protection
& VM_PROT_WRITE
))
2001 ret
= vm_protect (inferior_task
,
2006 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
2014 obstack_free (®ion_obstack
, 0);
2016 (void) vm_deallocate (mach_task_self (),
2021 if (ret
!= KERN_SUCCESS
)
2023 warning ("%s %s", errstr
, mach_error_string (ret
));
2030 /* Return 0 on failure, number of bytes handled otherwise. */
2032 m3_xfer_memory (memaddr
, myaddr
, len
, write
, target
)
2037 struct target_ops
*target
; /* IGNORED */
2042 result
= mach3_write_inferior (memaddr
, myaddr
, len
);
2044 result
= mach3_read_inferior (memaddr
, myaddr
, len
);
2051 translate_state(state
)
2055 case TH_STATE_RUNNING
: return("R");
2056 case TH_STATE_STOPPED
: return("S");
2057 case TH_STATE_WAITING
: return("W");
2058 case TH_STATE_UNINTERRUPTIBLE
: return("U");
2059 case TH_STATE_HALTED
: return("H");
2060 default: return("?");
2065 translate_cstate (state
)
2070 case CPROC_RUNNING
: return "R";
2071 case CPROC_SWITCHING
: return "S";
2072 case CPROC_BLOCKED
: return "B";
2073 case CPROC_CONDWAIT
: return "C";
2074 case CPROC_CONDWAIT
|CPROC_SWITCHING
: return "CS";
2075 default: return "?";
2079 /* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2081 mach_port_t
/* no mach_port_name_t found in include files. */
2082 map_inferior_port_name (inferior_name
, type
)
2083 mach_port_t inferior_name
;
2084 mach_msg_type_name_t type
;
2087 mach_msg_type_name_t acquired
;
2090 ret
= mach_port_extract_right (inferior_task
,
2095 CHK("mach_port_extract_right (map_inferior_port_name)", ret
);
2097 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
2098 error("Incorrect right extracted, (map_inferior_port_name)");
2100 ret
= mach_port_deallocate (mach_task_self (),
2102 CHK ("Deallocating mapped port (map_inferior_port_name)", ret
);
2108 * Naming convention:
2109 * Always return user defined name if found.
2110 * _K == A kernel thread with no matching CPROC
2111 * _C == A cproc with no current cthread
2112 * _t == A cthread with no user defined name
2114 * The digits that follow the _names are the SLOT number of the
2115 * kernel thread if there is such a thing, otherwise just a negation
2116 * of the sequential number of such cprocs.
2122 get_thread_name (one_cproc
, id
)
2123 gdb_thread_t one_cproc
;
2127 if (one_cproc
->cthread
== NULL
)
2129 /* cproc not mapped to any cthread */
2130 sprintf(buf
, "_C%d", id
);
2132 else if (! one_cproc
->cthread
->name
)
2134 /* cproc and cthread, but no name */
2135 sprintf(buf
, "_t%d", id
);
2138 return (char *)(one_cproc
->cthread
->name
);
2142 warning ("Inconsistency in thread name id %d", id
);
2144 /* Kernel thread without cproc */
2145 sprintf(buf
, "_K%d", id
);
2152 fetch_thread_info (task
, mthreads_out
)
2154 gdb_thread_t
*mthreads_out
; /* out */
2157 thread_array_t th_table
;
2159 gdb_thread_t mthreads
= NULL
;
2162 ret
= task_threads (task
, &th_table
, &th_count
);
2163 if (ret
!= KERN_SUCCESS
)
2165 warning ("Error getting inferior's thread list:%s",
2166 mach_error_string(ret
));
2167 m3_kill_inferior ();
2171 mthreads
= (gdb_thread_t
)
2174 th_count
* sizeof (struct gdb_thread
));
2176 for (index
= 0; index
< th_count
; index
++)
2178 thread_t saved_thread
= MACH_PORT_NULL
;
2181 if (must_suspend_thread
)
2182 setup_thread (th_table
[ index
], 1);
2184 if (th_table
[index
] != current_thread
)
2186 saved_thread
= current_thread
;
2188 mid
= switch_to_thread (th_table
[ index
]);
2191 mthreads
[index
].name
= th_table
[index
];
2192 mthreads
[index
].cproc
= NULL
; /* map_cprocs_to_kernel_threads() */
2193 mthreads
[index
].in_emulator
= FALSE
;
2194 mthreads
[index
].slotid
= index
;
2196 mthreads
[index
].sp
= read_register (SP_REGNUM
);
2197 mthreads
[index
].fp
= read_register (FP_REGNUM
);
2198 mthreads
[index
].pc
= read_pc ();
2200 if (MACH_PORT_VALID (saved_thread
))
2201 mid
= switch_to_thread (saved_thread
);
2203 if (must_suspend_thread
)
2204 setup_thread (th_table
[ index
], 0);
2207 consume_send_rights (th_table
, th_count
);
2208 ret
= vm_deallocate (mach_task_self(), (vm_address_t
)th_table
,
2209 (th_count
* sizeof(mach_port_t
)));
2210 if (ret
!= KERN_SUCCESS
)
2212 warning ("Error trying to deallocate thread list : %s",
2213 mach_error_string (ret
));
2216 *mthreads_out
= mthreads
;
2223 * Current emulator always saves the USP on top of
2224 * emulator stack below struct emul_stack_top stuff.
2227 fetch_usp_from_emulator_stack (sp
)
2230 CORE_ADDR stack_pointer
;
2232 sp
= (sp
& ~(EMULATOR_STACK_SIZE
-1)) +
2233 EMULATOR_STACK_SIZE
- sizeof (struct emul_stack_top
);
2235 if (mach3_read_inferior (sp
,
2237 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2239 warning ("Can't read user sp from emulator stack address 0x%x", sp
);
2243 return stack_pointer
;
2248 /* get_emulation_vector() interface was changed after mk67 */
2249 #define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2253 /* Check if the emulator exists at task's address space.
2256 have_emulator_p (task
)
2260 #ifndef EMUL_VECTOR_COUNT
2261 vm_offset_t
*emulation_vector
;
2264 vm_offset_t emulation_vector
[ EMUL_VECTOR_COUNT
];
2265 int n
= EMUL_VECTOR_COUNT
;
2270 ret
= task_get_emulation_vector (task
,
2272 #ifndef EMUL_VECTOR_COUNT
2278 CHK("task_get_emulation_vector", ret
);
2279 xx_debug ("%d vectors from %d at 0x%08x\n",
2280 n
, vector_start
, emulation_vector
);
2282 for(i
= 0; i
< n
; i
++)
2284 vm_offset_t entry
= emulation_vector
[i
];
2286 if (EMULATOR_BASE
<= entry
&& entry
<= EMULATOR_END
)
2290 static boolean_t informed
= FALSE
;
2293 warning("Emulation vector address 0x08%x outside emulator space",
2302 /* Map cprocs to kernel threads and vice versa. */
2305 map_cprocs_to_kernel_threads (cprocs
, mthreads
, thread_count
)
2306 gdb_thread_t cprocs
;
2307 gdb_thread_t mthreads
;
2312 boolean_t all_mapped
= TRUE
;
2316 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2318 /* Default to: no kernel thread for this cproc */
2319 scan
->reverse_map
= -1;
2321 /* Check if the cproc is found by its stack */
2322 for (index
= 0; index
< thread_count
; index
++)
2325 extract_signed_integer (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2328 extract_signed_integer (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2330 if ((mthreads
+ index
)->sp
> stack_base
&&
2331 (mthreads
+ index
)->sp
<= stack_base
+ stack_size
)
2333 (mthreads
+ index
)->cproc
= scan
;
2334 scan
->reverse_map
= index
;
2338 all_mapped
&= (scan
->reverse_map
!= -1);
2341 /* Check for threads that are currently in the emulator.
2342 * If so, they have a different stack, and the still unmapped
2343 * cprocs may well get mapped to these threads.
2346 * - cproc stack does not match any kernel thread stack pointer
2347 * - there is at least one extra kernel thread
2348 * that has no cproc mapped above.
2349 * - some kernel thread stack pointer points to emulator space
2350 * then we find the user stack pointer saved in the emulator
2351 * stack, and try to map that to the cprocs.
2353 * Also set in_emulator for kernel threads.
2356 if (emulator_present
)
2358 for (index
= 0; index
< thread_count
; index
++)
2363 gdb_thread_t mthread
= (mthreads
+index
);
2364 emul_sp
= mthread
->sp
;
2366 if (mthread
->cproc
== NULL
&&
2367 EMULATOR_BASE
<= emul_sp
&& emul_sp
<= EMULATOR_END
)
2369 mthread
->in_emulator
= emulator_present
;
2371 if (!all_mapped
&& cprocs
)
2373 usp
= fetch_usp_from_emulator_stack (emul_sp
);
2375 /* @@ Could be more accurate */
2377 error ("Zero stack pointer read from emulator?");
2379 /* Try to match this stack pointer to the cprocs that
2380 * don't yet have a kernel thread.
2382 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2385 /* Check is this unmapped CPROC stack contains
2386 * the user stack pointer saved in the
2389 if (scan
->reverse_map
== -1)
2392 extract_signed_integer
2393 (scan
->raw_cproc
+ CPROC_BASE_OFFSET
,
2396 extract_signed_integer
2397 (scan
->raw_cproc
+ CPROC_SIZE_OFFSET
,
2399 if (usp
> stack_base
&&
2400 usp
<= stack_base
+ stack_size
)
2402 mthread
->cproc
= scan
;
2403 scan
->reverse_map
= index
;
2415 * Format of the thread_list command
2417 * slot mid sel name emul ks susp cstate wired address
2419 #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2421 #define TL_HEADER "\n@ MID Name KState CState Where\n"
2424 print_tl_address (stream
, pc
)
2428 if (! lookup_minimal_symbol_by_pc (pc
))
2429 fprintf_filtered (stream
, local_hex_format(), pc
);
2432 extern int addressprint
;
2433 extern int asm_demangle
;
2435 int store
= addressprint
;
2437 print_address_symbolic (pc
, stream
, asm_demangle
, "");
2438 addressprint
= store
;
2442 /* For thread names, but also for gdb_message_port external name */
2443 #define MAX_NAME_LEN 50
2445 /* Returns the address of variable NAME or 0 if not found */
2447 lookup_address_of_variable (name
)
2451 CORE_ADDR symaddr
= 0;
2452 struct minimal_symbol
*msymbol
;
2454 sym
= lookup_symbol (name
,
2455 (struct block
*)NULL
,
2458 (struct symtab
**)NULL
);
2461 symaddr
= SYMBOL_VALUE (sym
);
2465 msymbol
= lookup_minimal_symbol (name
, (struct objfile
*) NULL
);
2467 if (msymbol
&& msymbol
->type
== mst_data
)
2468 symaddr
= SYMBOL_VALUE_ADDRESS (msymbol
);
2477 gdb_thread_t cproc_head
;
2478 gdb_thread_t cproc_copy
;
2479 CORE_ADDR their_cprocs
;
2480 char *buf
[TARGET_PTR_BIT
/ HOST_CHAR_BIT
];
2485 symaddr
= lookup_address_of_variable ("cproc_list");
2489 /* cproc_list is not in a file compiled with debugging
2490 symbols, but don't give up yet */
2492 symaddr
= lookup_address_of_variable ("cprocs");
2496 static int informed
= 0;
2500 warning ("Your program is loaded with an old threads library.");
2501 warning ("GDB does not know the old form of threads");
2502 warning ("so things may not work.");
2507 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
2511 /* Get the address of the first cproc in the task */
2512 if (!mach3_read_inferior (symaddr
,
2514 TARGET_PTR_BIT
/ HOST_CHAR_BIT
))
2515 error ("Can't read cproc master list at address (0x%x).", symaddr
);
2516 their_cprocs
= extract_address (buf
, TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2518 /* Scan the CPROCs in the task.
2519 CPROCs are chained with LIST field, not NEXT field, which
2520 chains mutexes, condition variables and queues */
2524 while (their_cprocs
!= (CORE_ADDR
)0)
2526 CORE_ADDR cproc_copy_incarnation
;
2527 cproc_copy
= (gdb_thread_t
) obstack_alloc (cproc_obstack
,
2528 sizeof (struct gdb_thread
));
2530 if (!mach3_read_inferior (their_cprocs
,
2531 &cproc_copy
->raw_cproc
[0],
2533 error("Can't read next cproc at 0x%x.", their_cprocs
);
2536 extract_address (cproc_copy
->raw_cproc
+ CPROC_LIST_OFFSET
,
2538 cproc_copy_incarnation
=
2539 extract_address (cproc_copy
->raw_cproc
+ CPROC_INCARNATION_OFFSET
,
2540 CPROC_INCARNATION_SIZE
);
2542 if (cproc_copy_incarnation
== (CORE_ADDR
)0)
2543 cproc_copy
->cthread
= NULL
;
2546 /* This CPROC has an attached CTHREAD. Get its name */
2547 cthread
= (cthread_t
)obstack_alloc (cproc_obstack
,
2548 sizeof(struct cthread
));
2550 if (!mach3_read_inferior (cproc_copy_incarnation
,
2552 sizeof(struct cthread
)))
2553 error("Can't read next thread at 0x%x.",
2554 cproc_copy_incarnation
);
2556 cproc_copy
->cthread
= cthread
;
2560 name
= (char *) obstack_alloc (cproc_obstack
, MAX_NAME_LEN
);
2562 if (!mach3_read_inferior(cthread
->name
, name
, MAX_NAME_LEN
))
2563 error("Can't read next thread's name at 0x%x.", cthread
->name
);
2565 cthread
->name
= name
;
2569 /* insert in front */
2570 cproc_copy
->next
= cproc_head
;
2571 cproc_head
= cproc_copy
;
2576 #ifndef FETCH_CPROC_STATE
2578 * Check if your machine does not grok the way this routine
2579 * fetches the FP,PC and SP of a cproc that is not
2580 * currently attached to any kernel thread (e.g. its cproc.context
2581 * field points to the place in stack where the context
2584 * If it doesn't, define your own routine.
2586 #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2589 mach3_cproc_state (mthread
)
2590 gdb_thread_t mthread
;
2594 if (! mthread
|| !mthread
->cproc
)
2597 context
= extract_signed_integer
2598 (mthread
->cproc
->raw_cproc
+ CPROC_CONTEXT_OFFSET
,
2599 CPROC_CONTEXT_SIZE
);
2603 mthread
->sp
= context
+ MACHINE_CPROC_SP_OFFSET
;
2605 if (mach3_read_inferior (context
+ MACHINE_CPROC_PC_OFFSET
,
2607 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2609 warning ("Can't read cproc pc from inferior");
2613 if (mach3_read_inferior (context
+ MACHINE_CPROC_FP_OFFSET
,
2615 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2617 warning ("Can't read cproc fp from inferior");
2623 #endif /* FETCH_CPROC_STATE */
2627 thread_list_command()
2629 thread_basic_info_data_t ths
;
2631 gdb_thread_t cprocs
;
2639 mach_port_t mid_or_port
;
2640 gdb_thread_t their_threads
;
2641 gdb_thread_t kthread
;
2645 char *fmt
= "There are %d kernel threads in task %d.\n";
2647 int tmid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
2649 MACH_ERROR_NO_INFERIOR
;
2651 thread_count
= fetch_thread_info (inferior_task
,
2653 if (thread_count
== -1)
2656 if (thread_count
== 1)
2657 fmt
= "There is %d kernel thread in task %d.\n";
2659 printf_filtered (fmt
, thread_count
, tmid
);
2661 puts_filtered (TL_HEADER
);
2663 cprocs
= get_cprocs();
2665 map_cprocs_to_kernel_threads (cprocs
, their_threads
, thread_count
);
2667 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2673 extract_signed_integer
2674 (scan
->raw_cproc
+ CPROC_STATE_OFFSET
, CPROC_STATE_SIZE
);
2678 /* a wired cproc? */
2679 wired
= (extract_address (scan
->raw_cproc
+ CPROC_WIRED_OFFSET
,
2683 if (scan
->reverse_map
!= -1)
2684 kthread
= (their_threads
+ scan
->reverse_map
);
2690 /* These cprocs have a kernel thread */
2692 mid
= map_port_name_to_mid (kthread
->name
, MACH_TYPE_THREAD
);
2694 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2696 ret
= thread_info (kthread
->name
,
2698 (thread_info_t
)&ths
,
2701 if (ret
!= KERN_SUCCESS
)
2703 warning ("Unable to get basic info on thread %d : %s",
2705 mach_error_string (ret
));
2709 /* Who is the first to have more than 100 threads */
2710 sprintf (slot
, "%d", kthread
->slotid
%100);
2712 if (kthread
->name
== current_thread
)
2715 if (ths
.suspend_count
)
2716 sprintf (buf
, "%d", ths
.suspend_count
);
2721 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2725 if (ths
.flags
& TH_FLAGS_IDLE
)
2728 /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
2729 printf_filtered (TL_FORMAT
,
2733 get_thread_name (scan
, kthread
->slotid
),
2734 kthread
->in_emulator
? "E" : "",
2735 translate_state (ths
.run_state
),
2737 translate_cstate (cproc_state
),
2739 print_tl_address (gdb_stdout
, kthread
->pc
);
2743 /* These cprocs don't have a kernel thread.
2744 * find out the calling frame with
2745 * FETCH_CPROC_STATE.
2748 struct gdb_thread state
;
2751 /* jtv -> emcmanus: why do you want this here? */
2752 if (scan
->incarnation
== NULL
)
2753 continue; /* EMcM */
2756 /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
2757 printf_filtered (TL_FORMAT
,
2759 -neworder
, /* Pseudo MID */
2761 get_thread_name (scan
, -neworder
),
2763 "-", /* kernel state */
2765 translate_cstate (cproc_state
),
2769 if (FETCH_CPROC_STATE (&state
) == -1)
2770 puts_filtered ("???");
2772 print_tl_address (gdb_stdout
, state
.pc
);
2776 puts_filtered ("\n");
2779 /* Scan for kernel threads without cprocs */
2780 for (index
= 0; index
< thread_count
; index
++)
2782 if (! their_threads
[index
].cproc
)
2789 mach_port_t name
= their_threads
[index
].name
;
2791 mid
= map_port_name_to_mid (name
, MACH_TYPE_THREAD
);
2793 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2795 ret
= thread_info(name
,
2797 (thread_info_t
)&ths
,
2800 if (ret
!= KERN_SUCCESS
)
2802 warning ("Unable to get basic info on thread %d : %s",
2804 mach_error_string (ret
));
2808 sprintf (slot
, "%d", index
%100);
2810 if (name
== current_thread
)
2815 if (ths
.suspend_count
)
2816 sprintf (buf
, "%d", ths
.suspend_count
);
2821 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2825 if (ths
.flags
& TH_FLAGS_IDLE
)
2828 /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
2829 printf_filtered (TL_FORMAT
,
2833 get_thread_name (NULL
, index
),
2834 their_threads
[index
].in_emulator
? "E" : "",
2835 translate_state (ths
.run_state
),
2837 "", /* No cproc state */
2838 ""); /* Can't be wired */
2839 print_tl_address (gdb_stdout
, their_threads
[index
].pc
);
2840 puts_filtered ("\n");
2844 obstack_free (cproc_obstack
, 0);
2845 obstack_init (cproc_obstack
);
2849 thread_select_command(args
, from_tty
)
2854 thread_array_t thread_list
;
2859 MACH_ERROR_NO_INFERIOR
;
2862 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2864 while (*args
== ' ' || *args
== '\t')
2876 if (!is_slot
|| *args
!= '0') /* Rudimentary checks */
2877 error ("You must select threads by MID or @SLOTNUMBER");
2879 if (select_thread (inferior_task
, mid
, is_slot
?2:1) != KERN_SUCCESS
)
2883 printf_filtered ("Thread %d selected\n",
2884 is_slot
? map_port_name_to_mid (current_thread
,
2885 MACH_TYPE_THREAD
) : mid
);
2888 thread_trace (thread
, set
)
2892 int flavor
= TRACE_FLAVOR
;
2893 unsigned int stateCnt
= TRACE_FLAVOR_SIZE
;
2895 thread_state_data_t state
;
2897 if (! MACH_PORT_VALID (thread
))
2899 warning ("thread_trace: invalid thread");
2903 if (must_suspend_thread
)
2904 setup_thread (thread
, 1);
2906 ret
= thread_get_state(thread
, flavor
, state
, &stateCnt
);
2907 CHK ("thread_trace: error reading thread state", ret
);
2911 TRACE_SET (thread
, state
);
2915 if (! TRACE_CLEAR (thread
, state
))
2917 if (must_suspend_thread
)
2918 setup_thread (thread
, 0);
2923 ret
= thread_set_state(thread
, flavor
, state
, stateCnt
);
2924 CHK ("thread_trace: error writing thread state", ret
);
2925 if (must_suspend_thread
)
2926 setup_thread (thread
, 0);
2929 #ifdef FLUSH_INFERIOR_CACHE
2931 /* When over-writing code on some machines the I-Cache must be flushed
2932 explicitly, because it is not kept coherent by the lazy hardware.
2933 This definitely includes breakpoints, for instance, or else we
2934 end up looping in mysterious Bpt traps */
2936 flush_inferior_icache(pc
, amount
)
2939 vm_machine_attribute_val_t flush
= MATTR_VAL_ICACHE_FLUSH
;
2942 ret
= vm_machine_attribute (inferior_task
,
2947 if (ret
!= KERN_SUCCESS
)
2948 warning ("Error flushing inferior's cache : %s",
2949 mach_error_string (ret
));
2951 #endif FLUSH_INFERIOR_CACHE
2955 suspend_all_threads (from_tty
)
2959 thread_array_t thread_list
;
2960 int thread_count
, index
;
2962 thread_basic_info_data_t th_info
;
2965 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
2966 if (ret
!= KERN_SUCCESS
)
2968 warning ("Could not suspend inferior threads.");
2969 m3_kill_inferior ();
2970 return_to_top_level (RETURN_ERROR
);
2973 for (index
= 0; index
< thread_count
; index
++)
2977 mid
= map_port_name_to_mid (thread_list
[ index
],
2980 ret
= thread_suspend(thread_list
[ index
]);
2982 if (ret
!= KERN_SUCCESS
)
2983 warning ("Error trying to suspend thread %d : %s",
2984 mid
, mach_error_string (ret
));
2988 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2989 ret
= thread_info (thread_list
[ index
],
2991 (thread_info_t
) &th_info
,
2993 CHK ("suspend can't get thread info", ret
);
2995 warning ("Thread %d suspend count is %d",
2996 mid
, th_info
.suspend_count
);
3000 consume_send_rights (thread_list
, thread_count
);
3001 ret
= vm_deallocate(mach_task_self(),
3002 (vm_address_t
)thread_list
,
3003 (thread_count
* sizeof(int)));
3004 CHK ("Error trying to deallocate thread list", ret
);
3008 thread_suspend_command (args
, from_tty
)
3014 mach_port_t saved_thread
;
3016 thread_basic_info_data_t th_info
;
3018 MACH_ERROR_NO_INFERIOR
;
3020 if (!strcasecmp (args
, "all")) {
3021 suspend_all_threads (from_tty
);
3025 saved_thread
= current_thread
;
3027 mid
= parse_thread_id (args
, 0, 0);
3030 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
3033 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3035 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3038 current_thread
= saved_thread
;
3039 error ("Could not select thread %d", mid
);
3042 ret
= thread_suspend (current_thread
);
3043 if (ret
!= KERN_SUCCESS
)
3044 warning ("thread_suspend failed : %s",
3045 mach_error_string (ret
));
3047 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3048 ret
= thread_info (current_thread
,
3050 (thread_info_t
) &th_info
,
3052 CHK ("suspend can't get thread info", ret
);
3054 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3056 current_thread
= saved_thread
;
3059 resume_all_threads (from_tty
)
3063 thread_array_t thread_list
;
3064 int thread_count
, index
;
3067 thread_basic_info_data_t th_info
;
3069 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
3070 if (ret
!= KERN_SUCCESS
)
3072 m3_kill_inferior ();
3073 error("task_threads", mach_error_string( ret
));
3076 for (index
= 0; index
< thread_count
; index
++)
3078 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3079 ret
= thread_info (thread_list
[ index
],
3081 (thread_info_t
) &th_info
,
3083 CHK ("resume_all can't get thread info", ret
);
3085 mid
= map_port_name_to_mid (thread_list
[ index
],
3088 if (! th_info
.suspend_count
)
3090 if (mid
!= -1 && from_tty
)
3091 warning ("Thread %d is not suspended", mid
);
3095 ret
= thread_resume (thread_list
[ index
]);
3097 if (ret
!= KERN_SUCCESS
)
3098 warning ("Error trying to resume thread %d : %s",
3099 mid
, mach_error_string (ret
));
3100 else if (mid
!= -1 && from_tty
)
3101 warning ("Thread %d suspend count is %d",
3102 mid
, --th_info
.suspend_count
);
3105 consume_send_rights (thread_list
, thread_count
);
3106 ret
= vm_deallocate(mach_task_self(),
3107 (vm_address_t
)thread_list
,
3108 (thread_count
* sizeof(int)));
3109 CHK("Error trying to deallocate thread list", ret
);
3113 thread_resume_command (args
, from_tty
)
3118 mach_port_t saved_thread
;
3120 thread_basic_info_data_t th_info
;
3121 int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3123 MACH_ERROR_NO_INFERIOR
;
3125 if (!strcasecmp (args
, "all")) {
3126 resume_all_threads (from_tty
);
3130 saved_thread
= current_thread
;
3132 mid
= parse_thread_id (args
, 0, 0);
3135 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3138 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3140 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3143 current_thread
= saved_thread
;
3144 return_to_top_level (RETURN_ERROR
);
3147 ret
= thread_info (current_thread
,
3149 (thread_info_t
) &th_info
,
3151 CHK ("resume can't get thread info", ret
);
3153 if (! th_info
.suspend_count
)
3155 warning ("Thread %d is not suspended", mid
);
3159 ret
= thread_resume (current_thread
);
3160 if (ret
!= KERN_SUCCESS
)
3161 warning ("thread_resume failed : %s",
3162 mach_error_string (ret
));
3165 th_info
.suspend_count
--;
3166 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3170 current_thread
= saved_thread
;
3174 thread_kill_command (args
, from_tty
)
3181 thread_array_t thread_table
;
3183 mach_port_t thread_to_kill
= MACH_PORT_NULL
;
3186 MACH_ERROR_NO_INFERIOR
;
3189 error_no_arg ("thread mid to kill from the inferior task");
3191 mid
= parse_thread_id (args
, 0, 0);
3194 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3198 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &thread_to_kill
);
3199 CHK ("thread_kill_command: machid_mach_port map failed", ret
);
3202 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3204 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3205 ret
= task_threads (inferior_task
, &thread_table
, &thread_count
);
3206 CHK ("Error getting inferior's thread list", ret
);
3208 if (thread_to_kill
== current_thread
)
3210 ret
= thread_terminate (thread_to_kill
);
3211 CHK ("Thread could not be terminated", ret
);
3213 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3214 warning ("Last thread was killed, use \"kill\" command to kill task");
3217 for (index
= 0; index
< thread_count
; index
++)
3218 if (thread_table
[ index
] == thread_to_kill
)
3220 ret
= thread_terminate (thread_to_kill
);
3221 CHK ("Thread could not be terminated", ret
);
3224 if (thread_count
> 1)
3225 consume_send_rights (thread_table
, thread_count
);
3227 ret
= vm_deallocate (mach_task_self(), (vm_address_t
)thread_table
,
3228 (thread_count
* sizeof(mach_port_t
)));
3229 CHK ("Error trying to deallocate thread list", ret
);
3231 warning ("Thread %d killed", mid
);
3235 /* Task specific commands; add more if you like */
3238 task_resume_command (args
, from_tty
)
3243 task_basic_info_data_t ta_info
;
3244 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3245 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3247 MACH_ERROR_NO_INFERIOR
;
3249 /* Would be trivial to change, but is it desirable? */
3251 error ("Currently gdb can resume only it's inferior task");
3253 ret
= task_info (inferior_task
,
3255 (task_info_t
) &ta_info
,
3257 CHK ("task_resume_command: task_info failed", ret
);
3259 if (ta_info
.suspend_count
== 0)
3260 error ("Inferior task %d is not suspended", mid
);
3261 else if (ta_info
.suspend_count
== 1 &&
3263 !query ("Suspend count is now 1. Do you know what you are doing? "))
3264 error ("Task not resumed");
3266 ret
= task_resume (inferior_task
);
3267 CHK ("task_resume_command: task_resume", ret
);
3269 if (ta_info
.suspend_count
== 1)
3271 warning ("Inferior task %d is no longer suspended", mid
);
3272 must_suspend_thread
= 1;
3273 /* @@ This is not complete: Registers change all the time when not
3275 registers_changed ();
3278 warning ("Inferior task %d suspend count is now %d",
3279 mid
, ta_info
.suspend_count
-1);
3284 task_suspend_command (args
, from_tty
)
3289 task_basic_info_data_t ta_info
;
3290 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3291 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3293 MACH_ERROR_NO_INFERIOR
;
3295 /* Would be trivial to change, but is it desirable? */
3297 error ("Currently gdb can suspend only it's inferior task");
3299 ret
= task_suspend (inferior_task
);
3300 CHK ("task_suspend_command: task_suspend", ret
);
3302 must_suspend_thread
= 0;
3304 ret
= task_info (inferior_task
,
3306 (task_info_t
) &ta_info
,
3308 CHK ("task_suspend_command: task_info failed", ret
);
3310 warning ("Inferior task %d suspend count is now %d",
3311 mid
, ta_info
.suspend_count
);
3318 static char size
[ 30 ];
3319 int zz
= bytes
/1024;
3322 sprintf (size
, "%-2.1f M", ((float)bytes
)/(1024.0*1024.0));
3324 sprintf (size
, "%d K", zz
);
3329 /* Does this require the target task to be suspended?? I don't think so. */
3331 task_info_command (args
, from_tty
)
3338 task_basic_info_data_t ta_info
;
3339 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3340 int page_size
= round_page(1);
3341 int thread_count
= 0;
3343 if (MACH_PORT_VALID (inferior_task
))
3344 mid
= map_port_name_to_mid (inferior_task
,
3347 task
= inferior_task
;
3351 int tmid
= atoi (args
);
3354 error ("Invalid mid %d for task info", tmid
);
3359 ret
= machid_mach_port (mid_server
, mid_auth
, tmid
, &task
);
3360 CHK ("task_info_command: machid_mach_port map failed", ret
);
3365 error ("You have to give the task MID as an argument");
3367 ret
= task_info (task
,
3369 (task_info_t
) &ta_info
,
3371 CHK ("task_info_command: task_info failed", ret
);
3373 printf_filtered ("\nTask info for task %d:\n\n", mid
);
3374 printf_filtered (" Suspend count : %d\n", ta_info
.suspend_count
);
3375 printf_filtered (" Base priority : %d\n", ta_info
.base_priority
);
3376 printf_filtered (" Virtual size : %s\n", get_size (ta_info
.virtual_size
));
3377 printf_filtered (" Resident size : %s\n", get_size (ta_info
.resident_size
));
3380 thread_array_t thread_list
;
3382 ret
= task_threads (task
, &thread_list
, &thread_count
);
3383 CHK ("task_info_command: task_threads", ret
);
3385 printf_filtered (" Thread count : %d\n", thread_count
);
3387 consume_send_rights (thread_list
, thread_count
);
3388 ret
= vm_deallocate(mach_task_self(),
3389 (vm_address_t
)thread_list
,
3390 (thread_count
* sizeof(int)));
3391 CHK("Error trying to deallocate thread list", ret
);
3393 if (have_emulator_p (task
))
3394 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3395 EMULATOR_BASE
, EMULATOR_END
);
3397 printf_filtered (" No emulator.\n");
3399 if (thread_count
&& task
== inferior_task
)
3400 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3403 /* You may either FORWARD the exception to the inferior, or KEEP
3404 * it and return to GDB command level.
3406 * exception mid [ forward | keep ]
3410 exception_command (args
, from_tty
)
3419 error_no_arg ("exception number action");
3421 while (*scan
== ' ' || *scan
== '\t') scan
++;
3423 if ('0' <= *scan
&& *scan
<= '9')
3424 while ('0' <= *scan
&& *scan
<= '9')
3427 error ("exception number action");
3429 exception
= atoi (args
);
3430 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3431 error ("Allowed exception numbers are in range 1..%d",
3434 if (*scan
!= ' ' && *scan
!= '\t')
3435 error ("exception number must be followed by a space");
3437 while (*scan
== ' ' || *scan
== '\t') scan
++;
3448 error("exception number action");
3450 if (!strncasecmp (args
, "forward", len
))
3451 exception_map
[ exception
].forward
= TRUE
;
3452 else if (!strncasecmp (args
, "keep", len
))
3453 exception_map
[ exception
].forward
= FALSE
;
3455 error ("exception action is either \"keep\" or \"forward\"");
3459 print_exception_info (exception
)
3462 boolean_t forward
= exception_map
[ exception
].forward
;
3464 printf_filtered ("%s\t(%d): ", exception_map
[ exception
].name
,
3467 if (exception_map
[ exception
].sigmap
!= SIG_UNKNOWN
)
3468 printf_filtered ("keep and handle as signal %d\n",
3469 exception_map
[ exception
].sigmap
);
3471 printf_filtered ("keep and handle as unknown signal %d\n",
3472 exception_map
[ exception
].sigmap
);
3474 printf_filtered ("forward exception to inferior\n");
3478 exception_info (args
, from_tty
)
3485 for (exception
= 1; exception
<= MAX_EXCEPTION
; exception
++)
3486 print_exception_info (exception
);
3489 exception
= atoi (args
);
3491 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3492 error ("Invalid exception number, values from 1 to %d allowed",
3494 print_exception_info (exception
);
3498 /* Check for actions for mach exceptions.
3500 mach3_exception_actions (w
, force_print_only
, who
)
3502 boolean_t force_print_only
;
3505 boolean_t force_print
= FALSE
;
3508 if (force_print_only
||
3509 exception_map
[stop_exception
].sigmap
== SIG_UNKNOWN
)
3512 WSETSTOP (*w
, exception_map
[stop_exception
].sigmap
);
3514 if (exception_map
[stop_exception
].print
|| force_print
)
3516 target_terminal_ours ();
3518 printf_filtered ("\n%s received %s exception : ",
3520 exception_map
[stop_exception
].name
);
3524 switch(stop_exception
) {
3525 case EXC_BAD_ACCESS
:
3526 printf_filtered ("referencing address 0x%x : %s\n",
3528 mach_error_string (stop_code
));
3530 case EXC_BAD_INSTRUCTION
:
3532 ("illegal or undefined instruction. code %d subcode %d\n",
3533 stop_code
, stop_subcode
);
3535 case EXC_ARITHMETIC
:
3536 printf_filtered ("code %d\n", stop_code
);
3539 printf_filtered ("code %d subcode %d\n", stop_code
, stop_subcode
);
3542 printf_filtered ("%s specific, code 0x%x\n",
3543 stop_code
< 0xffff ? "hardware" : "os emulation",
3546 case EXC_BREAKPOINT
:
3547 printf_filtered ("type %d (machine dependent)\n",
3551 fatal ("Unknown exception");
3556 setup_notify_port (create_new
)
3561 if (MACH_PORT_VALID (our_notify_port
))
3563 ret
= mach_port_destroy (mach_task_self (), our_notify_port
);
3564 CHK ("Could not destroy our_notify_port", ret
);
3567 our_notify_port
= MACH_PORT_NULL
;
3568 notify_chain
= (port_chain_t
) NULL
;
3569 port_chain_destroy (port_chain_obstack
);
3573 ret
= mach_port_allocate (mach_task_self(),
3574 MACH_PORT_RIGHT_RECEIVE
,
3576 if (ret
!= KERN_SUCCESS
)
3577 fatal("Creating notify port %s", mach_error_string(ret
));
3579 ret
= mach_port_move_member(mach_task_self(),
3581 inferior_wait_port_set
);
3582 if (ret
!= KERN_SUCCESS
)
3583 fatal("initial move member %s",mach_error_string(ret
));
3588 * Register our message port to the net name server
3590 * Currently used only by the external stop-gdb program
3591 * since ^C does not work if you would like to enter
3592 * gdb command level while debugging your program.
3594 * NOTE: If the message port is sometimes used for other
3595 * purposes also, the NAME must not be a guessable one.
3596 * Then, there should be a way to change it.
3599 char registered_name
[ MAX_NAME_LEN
];
3602 message_port_info (args
, from_tty
)
3606 if (registered_name
[0])
3607 printf_filtered ("gdb's message port name: '%s'\n",
3610 printf_filtered ("gdb's message port is not currently registered\n");
3614 gdb_register_port (name
, port
)
3619 static int already_signed
= 0;
3622 if (! MACH_PORT_VALID (port
) || !name
|| !*name
)
3624 warning ("Invalid registration request");
3628 if (! already_signed
)
3630 ret
= mach_port_insert_right (mach_task_self (),
3633 MACH_MSG_TYPE_MAKE_SEND
);
3634 CHK ("Failed to create a signature to our_message_port", ret
);
3637 else if (already_signed
> 1)
3639 ret
= netname_check_out (name_server_port
,
3642 CHK ("Failed to check out gdb's message port", ret
);
3643 registered_name
[0] = '\000';
3647 ret
= netname_check_in (name_server_port
, /* Name server port */
3648 name
, /* Name of service */
3649 our_message_port
, /* Signature */
3650 port
); /* Creates a new send right */
3651 CHK("Failed to check in the port", ret
);
3654 while(len
< MAX_NAME_LEN
&& *(name
+len
))
3656 registered_name
[len
] = *(name
+len
);
3659 registered_name
[len
] = '\000';
3663 struct cmd_list_element
*cmd_thread_list
;
3664 struct cmd_list_element
*cmd_task_list
;
3668 thread_command (arg
, from_tty
)
3672 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3673 help_list (cmd_thread_list
, "thread ", -1, gdb_stdout
);
3678 task_command (arg
, from_tty
)
3682 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3683 help_list (cmd_task_list
, "task ", -1, gdb_stdout
);
3686 add_mach_specific_commands ()
3688 /* Thread handling commands */
3690 /* FIXME: Move our thread support into the generic thread.c stuff so we
3691 can share that code. */
3692 add_prefix_cmd ("mthread", class_stack
, thread_command
,
3693 "Generic command for handling Mach threads in the debugged task.",
3694 &cmd_thread_list
, "thread ", 0, &cmdlist
);
3696 add_com_alias ("th", "mthread", class_stack
, 1);
3698 add_cmd ("select", class_stack
, thread_select_command
,
3699 "Select and print MID of the selected thread",
3701 add_cmd ("list", class_stack
, thread_list_command
,
3702 "List info of task's threads. Selected thread is marked with '*'",
3704 add_cmd ("suspend", class_run
, thread_suspend_command
,
3705 "Suspend one or all of the threads in the selected task.",
3707 add_cmd ("resume", class_run
, thread_resume_command
,
3708 "Resume one or all of the threads in the selected task.",
3710 add_cmd ("kill", class_run
, thread_kill_command
,
3711 "Kill the specified thread MID from inferior task.",
3714 /* The rest of this support (condition_thread) was not merged. It probably
3715 should not be merged in this form, but instead added to the generic GDB
3717 add_cmd ("break", class_breakpoint
, condition_thread
,
3718 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3719 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3722 /* Thread command shorthands (for backward compatibility) */
3723 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist
);
3724 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist
);
3726 /* task handling commands */
3728 add_prefix_cmd ("task", class_stack
, task_command
,
3729 "Generic command for handling debugged task.",
3730 &cmd_task_list
, "task ", 0, &cmdlist
);
3732 add_com_alias ("ta", "task", class_stack
, 1);
3734 add_cmd ("suspend", class_run
, task_suspend_command
,
3735 "Suspend the inferior task.",
3737 add_cmd ("resume", class_run
, task_resume_command
,
3738 "Resume the inferior task.",
3740 add_cmd ("info", no_class
, task_info_command
,
3741 "Print information about the specified task.",
3744 /* Print my message port name */
3746 add_info ("message-port", message_port_info
,
3747 "Returns the name of gdb's message port in the netnameserver");
3749 /* Exception commands */
3751 add_info ("exceptions", exception_info
,
3752 "What debugger does when program gets various exceptions.\n\
3753 Specify an exception number as argument to print info on that\n\
3756 add_com ("exception", class_run
, exception_command
,
3757 "Specify how to handle an exception.\n\
3758 Args are exception number followed by \"forward\" or \"keep\".\n\
3759 `Forward' means forward the exception to the program's normal exception\n\
3761 `Keep' means reenter debugger if this exception happens, and GDB maps\n\
3762 the exception to some signal (see info exception)\n\
3763 Normally \"keep\" is used to return to GDB on exception.");
3767 do_mach_notify_dead_name (notify
, name
)
3771 kern_return_t kr
= KERN_SUCCESS
;
3773 /* Find the thing that notified */
3774 port_chain_t element
= port_chain_member (notify_chain
, name
);
3776 /* Take name of from unreceived dead name notification list */
3777 notify_chain
= port_chain_delete (notify_chain
, name
);
3780 error ("Received a dead name notify from unchained port (0x%x)", name
);
3782 switch (element
->type
) {
3784 case MACH_TYPE_THREAD
:
3785 target_terminal_ours_for_output ();
3786 if (name
== current_thread
)
3788 printf_filtered ("\nCurrent thread %d died", element
->mid
);
3789 current_thread
= MACH_PORT_NULL
;
3792 printf_filtered ("\nThread %d died", element
->mid
);
3796 case MACH_TYPE_TASK
:
3797 target_terminal_ours_for_output ();
3798 if (name
!= inferior_task
)
3799 printf_filtered ("Task %d died, but it was not the selected task",
3803 printf_filtered ("Current task %d died", element
->mid
);
3805 mach_port_destroy (mach_task_self(), name
);
3806 inferior_task
= MACH_PORT_NULL
;
3809 warning ("There were still unreceived dead_name_notifications???");
3811 /* Destroy the old notifications */
3812 setup_notify_port (0);
3818 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3819 name
, element
->type
, element
->mid
);
3823 return KERN_SUCCESS
;
3827 do_mach_notify_msg_accepted (notify
, name
)
3831 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3833 return KERN_SUCCESS
;
3837 do_mach_notify_no_senders (notify
, mscount
)
3839 mach_port_mscount_t mscount
;
3841 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3843 return KERN_SUCCESS
;
3847 do_mach_notify_port_deleted (notify
, name
)
3851 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3853 return KERN_SUCCESS
;
3857 do_mach_notify_port_destroyed (notify
, rights
)
3861 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3863 return KERN_SUCCESS
;
3867 do_mach_notify_send_once (notify
)
3871 /* MANY of these are generated. */
3872 warning ("do_mach_notify_send_once : notify %x",
3875 return KERN_SUCCESS
;
3878 /* Kills the inferior. It's gone when you call this */
3880 kill_inferior_fast ()
3884 if (inferior_pid
== 0 || inferior_pid
== 1)
3887 /* kill() it, since the Unix server does not otherwise notice when
3888 * killed with task_terminate().
3890 if (inferior_pid
> 0)
3891 kill (inferior_pid
, SIGKILL
);
3893 /* It's propably terminate already */
3894 (void) task_terminate (inferior_task
);
3896 inferior_task
= MACH_PORT_NULL
;
3897 current_thread
= MACH_PORT_NULL
;
3899 wait3 (&w
, WNOHANG
, 0);
3901 setup_notify_port (0);
3907 kill_inferior_fast ();
3908 target_mourn_inferior ();
3911 /* Clean up after the inferior dies. */
3914 m3_mourn_inferior ()
3916 unpush_target (&m3_ops
);
3917 generic_mourn_inferior ();
3921 /* Fork an inferior process, and start debugging it. */
3924 m3_create_inferior (exec_file
, allargs
, env
)
3929 fork_inferior (exec_file
, allargs
, env
, m3_trace_me
, m3_trace_him
, NULL
);
3930 /* We are at the first instruction we care about. */
3931 /* Pedal to the metal... */
3932 proceed ((CORE_ADDR
) -1, 0, 0);
3935 /* Mark our target-struct as eligible for stray "run" and "attach"
3943 /* Mach 3.0 does not need ptrace for anything
3944 * Make sure nobody uses it on mach.
3949 error ("Lose, Lose! Somebody called ptrace\n");
3952 /* Resume execution of the inferior process.
3953 If STEP is nonzero, single-step it.
3954 If SIGNAL is nonzero, give it that signal. */
3957 m3_resume (pid
, step
, signal
)
3960 enum target_signal signal
;
3966 thread_basic_info_data_t th_info
;
3967 unsigned int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3969 /* There is no point in single stepping when current_thread
3972 if (! MACH_PORT_VALID (current_thread
))
3973 error ("No thread selected; can not single step");
3975 /* If current_thread is suspended, tracing it would never return.
3977 ret
= thread_info (current_thread
,
3979 (thread_info_t
) &th_info
,
3981 CHK ("child_resume: can't get thread info", ret
);
3983 if (th_info
.suspend_count
)
3984 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3987 vm_read_cache_valid
= FALSE
;
3989 if (signal
&& inferior_pid
> 0) /* Do not signal, if attached by MID */
3990 kill (inferior_pid
, target_signal_to_host (signal
));
3994 suspend_all_threads (0);
3996 setup_single_step (current_thread
, TRUE
);
3998 ret
= thread_resume (current_thread
);
3999 CHK ("thread_resume", ret
);
4002 ret
= task_resume (inferior_task
);
4003 if (ret
== KERN_FAILURE
)
4004 warning ("Task was not suspended");
4006 CHK ("Resuming task", ret
);
4008 /* HACK HACK This is needed by the multiserver system HACK HACK */
4009 while ((ret
= task_resume(inferior_task
)) == KERN_SUCCESS
)
4010 /* make sure it really runs */;
4011 /* HACK HACK This is needed by the multiserver system HACK HACK */
4014 #ifdef ATTACH_DETACH
4016 /* Start debugging the process with the given task */
4022 inferior_task
= tid
;
4024 ret
= task_suspend (inferior_task
);
4025 CHK("task_attach: task_suspend", ret
);
4027 must_suspend_thread
= 0;
4029 setup_notify_port (1);
4031 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
4033 setup_exception_port ();
4035 emulator_present
= have_emulator_p (inferior_task
);
4040 /* Well, we can call error also here and leave the
4041 * target stack inconsistent. Sigh.
4042 * Fix this sometime (the only way to fail here is that
4043 * the task has no threads at all, which is rare, but
4044 * possible; or if the target task has died, which is also
4045 * possible, but unlikely, since it has been suspended.
4046 * (Someone must have killed it))
4051 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
4052 error ("Could not select any threads to attach to");
4060 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &inferior_task
);
4061 CHK("mid_attach: machid_mach_port", ret
);
4063 task_attach (inferior_task
);
4069 * Start debugging the process whose unix process-id is PID.
4070 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
4072 * Prevent (possible unwanted) dangerous operations by enabled users
4073 * like "atta 0" or "atta foo" (equal to the previous :-) and
4074 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4083 error("MID=0, Debugging the master unix server does not compute");
4085 /* Foo. This assumes gdb has a unix pid */
4086 if (pid
== getpid())
4087 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4091 mid_attach (-(pid
));
4093 /* inferior_pid will be NEGATIVE! */
4096 return inferior_pid
;
4099 inferior_task
= task_by_pid (pid
);
4100 if (! MACH_PORT_VALID (inferior_task
))
4101 error("Cannot map Unix pid %d to Mach task port", pid
);
4103 task_attach (inferior_task
);
4107 return inferior_pid
;
4110 /* Attach to process PID, then initialize for debugging it
4111 and wait for the trace-trap that results from attaching. */
4114 m3_attach (args
, from_tty
)
4122 error_no_arg ("process-id to attach");
4126 if (pid
== getpid()) /* Trying to masturbate? */
4127 error ("I refuse to debug myself!");
4131 exec_file
= (char *) get_exec_file (0);
4134 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file
, target_pid_to_str (pid
));
4136 printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid
));
4138 gdb_flush (gdb_stdout
);
4143 push_target (&m3_ops
);
4147 deallocate_inferior_ports ()
4150 thread_array_t thread_list
;
4151 int thread_count
, index
;
4153 if (!MACH_PORT_VALID (inferior_task
))
4156 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
4157 if (ret
!= KERN_SUCCESS
)
4159 warning ("deallocate_inferior_ports: task_threads",
4160 mach_error_string(ret
));
4164 /* Get rid of send rights to task threads */
4165 for (index
= 0; index
< thread_count
; index
++)
4168 ret
= mach_port_get_refs (mach_task_self (),
4170 MACH_PORT_RIGHT_SEND
,
4172 CHK("deallocate_inferior_ports: get refs", ret
);
4176 ret
= mach_port_mod_refs (mach_task_self (),
4178 MACH_PORT_RIGHT_SEND
,
4180 CHK("deallocate_inferior_ports: mod refs", ret
);
4184 ret
= mach_port_mod_refs (mach_task_self (),
4185 inferior_exception_port
,
4186 MACH_PORT_RIGHT_RECEIVE
,
4188 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret
);
4190 ret
= mach_port_deallocate (mach_task_self (),
4192 CHK ("deallocate_task_port: deallocating inferior_task", ret
);
4194 current_thread
= MACH_PORT_NULL
;
4195 inferior_task
= MACH_PORT_NULL
;
4198 /* Stop debugging the process whose number is PID
4199 and continue it with signal number SIGNAL.
4200 SIGNAL = 0 means just continue it. */
4203 m3_do_detach (signal
)
4208 MACH_ERROR_NO_INFERIOR
;
4210 if (current_thread
!= MACH_PORT_NULL
)
4212 /* Store the gdb's view of the thread we are deselecting
4214 * @@ I am really not sure if this is ever needeed.
4216 target_prepare_to_store ();
4217 target_store_registers (-1);
4220 ret
= task_set_special_port (inferior_task
,
4221 TASK_EXCEPTION_PORT
,
4222 inferior_old_exception_port
);
4223 CHK ("task_set_special_port", ret
);
4225 /* Discard all requested notifications */
4226 setup_notify_port (0);
4228 if (remove_breakpoints ())
4229 warning ("Could not remove breakpoints when detaching");
4231 if (signal
&& inferior_pid
> 0)
4232 kill (inferior_pid
, signal
);
4234 /* the task might be dead by now */
4235 (void) task_resume (inferior_task
);
4237 deallocate_inferior_ports ();
4242 /* Take a program previously attached to and detaches it.
4243 The program resumes execution and will no longer stop
4244 on signals, etc. We'd better not have left any breakpoints
4245 in the program or it'll die when it hits one. For this
4246 to work, it may be necessary for the process to have been
4247 previously attached. It *might* work if the program was
4248 started via fork. */
4251 m3_detach (args
, from_tty
)
4259 char *exec_file
= get_exec_file (0);
4262 printf_unfiltered ("Detaching from program: %s %s\n",
4263 exec_file
, target_pid_to_str (inferior_pid
));
4264 gdb_flush (gdb_stdout
);
4267 siggnal
= atoi (args
);
4269 m3_do_detach (siggnal
);
4271 unpush_target (&m3_ops
); /* Pop out of handling an inferior */
4273 #endif /* ATTACH_DETACH */
4275 /* Get ready to modify the registers array. On machines which store
4276 individual registers, this doesn't need to do anything. On machines
4277 which store all the registers in one fell swoop, this makes sure
4278 that registers contains all the registers from the program being
4282 m3_prepare_to_store ()
4284 #ifdef CHILD_PREPARE_TO_STORE
4285 CHILD_PREPARE_TO_STORE ();
4289 /* Print status information about what we're accessing. */
4292 m3_files_info (ignore
)
4293 struct target_ops
*ignore
;
4295 /* FIXME: should print MID and all that crap. */
4296 printf_unfiltered ("\tUsing the running image of %s %s.\n",
4297 attach_flag
? "attached": "child", target_pid_to_str (inferior_pid
));
4301 m3_open (arg
, from_tty
)
4305 error ("Use the \"run\" command to start a Unix child process.");
4315 char *bsd1_names
[] = {
4383 int bsd1_nnames
= sizeof(bsd1_names
)/sizeof(bsd1_names
[0]);
4393 case MACH_MSG_TYPE_BOOLEAN
:
4395 case MACH_MSG_TYPE_INTEGER_16
:
4397 case MACH_MSG_TYPE_INTEGER_32
:
4399 case MACH_MSG_TYPE_CHAR
:
4401 case MACH_MSG_TYPE_BYTE
:
4403 case MACH_MSG_TYPE_REAL
:
4405 case MACH_MSG_TYPE_STRING
:
4408 sprintf(buf
,"%d",name
);
4421 if (id
>= 101000 && id
< 101000+bsd1_nnames
) {
4422 if (p
= bsd1_names
[id
-101000])
4426 return "psignal_retry";
4429 sprintf(buf
,"%d",id
);
4434 mach_msg_header_t
*mp
;
4436 char *fmt_x
= "%20s : 0x%08x\n";
4437 char *fmt_d
= "%20s : %10d\n";
4438 char *fmt_s
= "%20s : %s\n";
4441 puts_filtered ("\n");
4442 #define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
4443 pr(fmt_x
,(*mp
),msgh_bits
);
4444 pr(fmt_d
,(*mp
),msgh_size
);
4445 pr(fmt_x
,(*mp
),msgh_remote_port
);
4446 pr(fmt_x
,(*mp
),msgh_local_port
);
4447 pr(fmt_d
,(*mp
),msgh_kind
);
4448 printf_filtered(fmt_s
,STR(msgh_id
),id_str(mp
->msgh_id
,buf
));
4450 if (debug_level
> 1)
4455 ep
= p
+mp
->msgh_size
;
4457 for(; p
< ep
; p
+= plen
) {
4458 mach_msg_type_t
*tp
;
4459 mach_msg_type_long_t
*tlp
;
4460 int name
,size
,number
;
4461 tp
= (mach_msg_type_t
*)p
;
4462 if (tp
->msgt_longform
) {
4463 tlp
= (mach_msg_type_long_t
*)tp
;
4464 name
= tlp
->msgtl_name
;
4465 size
= tlp
->msgtl_size
;
4466 number
= tlp
->msgtl_number
;
4467 plen
= sizeof(*tlp
);
4469 name
= tp
->msgt_name
;
4470 size
= tp
->msgt_size
;
4471 number
= tp
->msgt_number
;
4474 printf_filtered("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4475 name_str(name
,buf
),size
,number
,tp
->msgt_inline
,
4476 tp
->msgt_longform
, tp
->msgt_deallocate
);
4478 if (tp
->msgt_inline
) {
4481 l
= (l
+sizeof(long)-1)&~((sizeof(long))-1);
4483 print_data(dp
,size
,number
);
4485 plen
+= sizeof(int*);
4487 printf_filtered("plen=%d\n",plen
);
4492 print_data(p
,size
,number
)
4503 for(i
= 0; i
< number
; i
++) {
4504 printf_filtered(" %02x",p
[i
]);
4509 for(i
= 0; i
< number
; i
++) {
4510 printf_filtered(" %04x",sp
[i
]);
4515 for(i
= 0; i
< number
; i
++) {
4516 printf_filtered(" %08x",ip
[i
]);
4520 puts_filtered("\n");
4527 error ("to_stop target function not implemented");
4530 struct target_ops m3_ops
= {
4531 "mach", /* to_shortname */
4532 "Mach child process", /* to_longname */
4533 "Mach child process (started by the \"run\" command).", /* to_doc */
4534 m3_open
, /* to_open */
4536 m3_attach
, /* to_attach */
4537 m3_detach
, /* to_detach */
4538 m3_resume
, /* to_resume */
4539 mach_really_wait
, /* to_wait */
4540 fetch_inferior_registers
, /* to_fetch_registers */
4541 store_inferior_registers
, /* to_store_registers */
4542 m3_prepare_to_store
, /* to_prepare_to_store */
4543 m3_xfer_memory
, /* to_xfer_memory */
4544 m3_files_info
, /* to_files_info */
4545 memory_insert_breakpoint
, /* to_insert_breakpoint */
4546 memory_remove_breakpoint
, /* to_remove_breakpoint */
4547 terminal_init_inferior
, /* to_terminal_init */
4548 terminal_inferior
, /* to_terminal_inferior */
4549 terminal_ours_for_output
, /* to_terminal_ours_for_output */
4550 terminal_ours
, /* to_terminal_ours */
4551 child_terminal_info
, /* to_terminal_info */
4552 m3_kill_inferior
, /* to_kill */
4554 0, /* to_lookup_symbol */
4556 m3_create_inferior
, /* to_create_inferior */
4557 m3_mourn_inferior
, /* to_mourn_inferior */
4558 m3_can_run
, /* to_can_run */
4559 0, /* to_notice_signals */
4560 m3_stop
, /* to_stop */
4561 process_stratum
, /* to_stratum */
4563 1, /* to_has_all_memory */
4564 1, /* to_has_memory */
4565 1, /* to_has_stack */
4566 1, /* to_has_registers */
4567 1, /* to_has_execution */
4569 0, /* sections_end */
4570 OPS_MAGIC
/* to_magic */
4574 _initialize_m3_nat ()
4578 add_target (&m3_ops
);
4580 ret
= mach_port_allocate(mach_task_self(),
4581 MACH_PORT_RIGHT_PORT_SET
,
4582 &inferior_wait_port_set
);
4583 if (ret
!= KERN_SUCCESS
)
4584 fatal("initial port set %s",mach_error_string(ret
));
4586 /* mach_really_wait now waits for this */
4587 currently_waiting_for
= inferior_wait_port_set
;
4589 ret
= netname_look_up(name_server_port
, hostname
, "MachID", &mid_server
);
4590 if (ret
!= KERN_SUCCESS
)
4592 mid_server
= MACH_PORT_NULL
;
4594 warning ("initialize machid: netname_lookup_up(MachID) : %s",
4595 mach_error_string(ret
));
4596 warning ("Some (most?) features disabled...");
4599 mid_auth
= mach_privileged_host_port();
4600 if (mid_auth
== MACH_PORT_NULL
)
4601 mid_auth
= mach_task_self();
4603 obstack_init (port_chain_obstack
);
4605 ret
= mach_port_allocate (mach_task_self (),
4606 MACH_PORT_RIGHT_RECEIVE
,
4607 &thread_exception_port
);
4608 CHK ("Creating thread_exception_port for single stepping", ret
);
4610 ret
= mach_port_insert_right (mach_task_self (),
4611 thread_exception_port
,
4612 thread_exception_port
,
4613 MACH_MSG_TYPE_MAKE_SEND
);
4614 CHK ("Inserting send right to thread_exception_port", ret
);
4616 /* Allocate message port */
4617 ret
= mach_port_allocate (mach_task_self (),
4618 MACH_PORT_RIGHT_RECEIVE
,
4620 if (ret
!= KERN_SUCCESS
)
4621 warning ("Creating message port %s", mach_error_string (ret
));
4624 char buf
[ MAX_NAME_LEN
];
4625 ret
= mach_port_move_member(mach_task_self (),
4627 inferior_wait_port_set
);
4628 if (ret
!= KERN_SUCCESS
)
4629 warning ("message move member %s", mach_error_string (ret
));
4632 /* @@@@ No way to change message port name currently */
4633 /* Foo. This assumes gdb has a unix pid */
4634 sprintf (buf
, "gdb-%d", getpid ());
4635 gdb_register_port (buf
, our_message_port
);
4638 /* Heap for thread commands */
4639 obstack_init (cproc_obstack
);
4641 add_mach_specific_commands ();