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>
58 #include <servers/machid_lib.h>
60 /* Included only for signal names and NSIG
62 * note: There are many problems in signal handling with
63 * gdb in Mach 3.0 in general.
66 #define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
70 /* This is what a cproc looks like. This is here partly because
71 cthread_internals.h is not a header we can just #include, partly with
72 an eye towards perhaps getting this to work with cross-debugging
73 someday. Best solution is if CMU publishes a real interface to this
75 #define CPROC_NEXT_OFFSET 0
76 #define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
77 #define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
78 #define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
79 #define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
80 #define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
81 #define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
82 #define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
83 #define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
84 #define CPROC_REPLY_SIZE (sizeof (mach_port_t))
85 #define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
86 #define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
87 #define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
88 #define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
89 #define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
90 #define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
91 #define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
92 #define CPROC_WIRED_SIZE (sizeof (mach_port_t))
93 #define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
94 #define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
95 #define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
96 #define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
97 #define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
98 #define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
99 #define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
100 #define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
101 #define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
103 /* Values for the state field in the cproc. */
104 #define CPROC_RUNNING 0
105 #define CPROC_SWITCHING 1
106 #define CPROC_BLOCKED 2
107 #define CPROC_CONDWAIT 4
109 /* For cproc and kernel thread mapping */
110 typedef struct gdb_thread
{
115 boolean_t in_emulator
;
118 /* This is for the mthreads list. It points to the cproc list.
119 Perhaps the two lists should be merged (or perhaps it was a mistake
120 to make them both use a struct gdb_thread). */
121 struct gdb_thread
*cproc
;
123 /* These are for the cproc list, which is linked through the next field
124 of the struct gdb_thread. */
125 char raw_cproc
[CPROC_SIZE
];
126 /* The cthread which is pointed to by the incarnation field from the
127 cproc. This points to the copy we've read into GDB. */
129 /* Point back to the mthreads list. */
131 struct gdb_thread
*next
;
135 * Actions for Mach exceptions.
137 * sigmap field maps the exception to corresponding Unix signal.
139 * I do not know how to map the exception to unix signal
140 * if SIG_UNKNOWN is specified.
143 struct exception_list
{
148 } exception_map
[] = {
149 {"not_mach3_exception", FALSE
, TRUE
, SIG_UNKNOWN
},
150 {"EXC_BAD_ACCESS", FALSE
, TRUE
, SIGSEGV
},
151 {"EXC_BAD_INSTRUCTION", FALSE
, TRUE
, SIGILL
},
152 {"EXC_ARITHMETIC", FALSE
, TRUE
, SIGFPE
},
153 {"EXC_EMULATION", FALSE
, TRUE
, SIGEMT
}, /* ??? */
154 {"EXC_SOFTWARE", FALSE
, TRUE
, SIG_UNKNOWN
},
155 {"EXC_BREAKPOINT", FALSE
, FALSE
, SIGTRAP
}
158 /* Mach exception table size */
159 int max_exception
= sizeof(exception_map
)/sizeof(struct exception_list
) - 1;
161 #define MAX_EXCEPTION max_exception
163 WAITTYPE wait_status
;
165 /* If you define this, intercepted bsd server calls will be
166 * dumped while waiting the inferior to EXEC the correct
169 /* #define DUMP_SYSCALL /* debugging interceptor */
171 /* xx_debug() outputs messages if this is nonzero.
172 * If > 1, DUMP_SYSCALL will dump message contents.
176 /* "Temporary" debug stuff */
178 xx_debug (fmt
, a
,b
,c
)
183 warning (fmt
, a
, b
, c
);
186 /* This is in libmach.a */
187 extern mach_port_t name_server_port
;
189 /* Set in catch_exception_raise */
190 int stop_exception
, stop_code
, stop_subcode
;
191 int stopped_in_exception
;
193 /* Thread that was the active thread when we stopped */
194 thread_t stop_thread
= MACH_PORT_NULL
;
198 /* Set when task is attached or created */
199 boolean_t emulator_present
= FALSE
;
201 task_t inferior_task
;
202 thread_t current_thread
;
204 /* Exception ports for inferior task */
205 mach_port_t inferior_exception_port
= MACH_PORT_NULL
;
206 mach_port_t inferior_old_exception_port
= MACH_PORT_NULL
;
208 /* task exceptions and notifications */
209 mach_port_t inferior_wait_port_set
= MACH_PORT_NULL
;
210 mach_port_t our_notify_port
= MACH_PORT_NULL
;
212 /* This is "inferior_wait_port_set" when not single stepping, and
213 * "singlestepped_thread_port" when we are single stepping.
215 * This is protected by a cleanup function: discard_single_step()
217 mach_port_t currently_waiting_for
= MACH_PORT_NULL
;
219 /* A port for external messages to gdb.
220 * External in the meaning that they do not come
221 * from the inferior_task, but rather from external
224 * As a debugging feature:
225 * A debugger debugging another debugger can stop the
226 * inferior debugger by the following command sequence
227 * (without running external programs)
229 * (top-gdb) set stop_inferior_gdb ()
232 mach_port_t our_message_port
= MACH_PORT_NULL
;
234 /* For single stepping */
235 mach_port_t thread_exception_port
= MACH_PORT_NULL
;
236 mach_port_t thread_saved_exception_port
= MACH_PORT_NULL
;
237 mach_port_t singlestepped_thread_port
= MACH_PORT_NULL
;
239 /* For machid calls */
240 mach_port_t mid_server
= MACH_PORT_NULL
;
241 mach_port_t mid_auth
= MACH_PORT_NULL
;
243 /* If gdb thinks the inferior task is not suspended, it
244 * must take suspend/abort the threads when it reads the state.
246 int must_suspend_thread
= 0;
248 /* When single stepping, we switch the port that mach_really_wait() listens to.
249 * This cleanup is a guard to prevent the port set from being left to
250 * the singlestepped_thread_port when error() is called.
251 * This is nonzero only when we are single stepping.
253 #define NULL_CLEANUP (struct cleanup *)0
254 struct cleanup
*cleanup_step
= NULL_CLEANUP
;
258 #define MACH_TYPE_EXCEPTION_PORT -1
261 /* Chain of ports to remember requested notifications. */
264 struct port_chain
*next
;
267 int mid
; /* Now only valid with MACH_TYPE_THREAD and */
268 /* MACH_TYPE_THREAD */
270 typedef struct port_chain
*port_chain_t
;
272 /* Room for chain nodes comes from pchain_obstack */
273 struct obstack pchain_obstack
;
274 struct obstack
*port_chain_obstack
= &pchain_obstack
;
276 /* For thread handling */
277 struct obstack Cproc_obstack
;
278 struct obstack
*cproc_obstack
= &Cproc_obstack
;
280 /* the list of notified ports */
281 port_chain_t notify_chain
= (port_chain_t
) NULL
;
284 port_chain_insert (list
, name
, type
)
293 if (! MACH_PORT_VALID (name
))
296 if (type
== MACH_TYPE_TASK
|| type
== MACH_TYPE_THREAD
)
298 if (! MACH_PORT_VALID (mid_server
))
300 warning ("Machid server port invalid, can not map port 0x%x to MID",
306 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
308 if (ret
!= KERN_SUCCESS
)
310 warning ("Can not map name (0x%x) to MID with machid", name
);
316 mid
= 3735928559; /* 0x? :-) */
318 new = (port_chain_t
) obstack_alloc (port_chain_obstack
,
319 sizeof (struct port_chain
));
329 port_chain_delete (list
, elem
)
334 if (list
->port
== elem
)
339 if (list
->next
->port
== elem
)
340 list
->next
= list
->next
->next
; /* GCd with obstack_free() */
348 port_chain_destroy (ostack
)
349 struct obstack
*ostack
;
351 obstack_free (ostack
, 0);
352 obstack_init (ostack
);
356 port_chain_member (list
, elem
)
362 if (list
->port
== elem
)
366 return (port_chain_t
) NULL
;
370 map_port_name_to_mid (name
, type
)
376 if (!MACH_PORT_VALID (name
))
379 elem
= port_chain_member (notify_chain
, name
);
381 if (elem
&& (elem
->type
== type
))
387 if (! MACH_PORT_VALID (mid_server
))
389 warning ("Machid server port invalid, can not map port 0x%x to mid",
398 ret
= machid_mach_register (mid_server
, mid_auth
, name
, type
, &mid
);
400 if (ret
!= KERN_SUCCESS
)
402 warning ("Can not map name (0x%x) to mid with machid", name
);
409 /* Guard for currently_waiting_for and singlestepped_thread_port */
411 discard_single_step (thread
)
414 currently_waiting_for
= inferior_wait_port_set
;
416 cleanup_step
= NULL_CLEANUP
;
417 if (MACH_PORT_VALID (thread
) && MACH_PORT_VALID (singlestepped_thread_port
))
418 setup_single_step (thread
, FALSE
);
421 setup_single_step (thread
, start_step
)
423 boolean_t start_step
;
427 if (! MACH_PORT_VALID (thread
))
428 error ("Invalid thread supplied to setup_single_step");
433 /* Get the current thread exception port */
434 ret
= thread_get_exception_port (thread
, &teport
);
435 CHK ("Getting thread's exception port", ret
);
439 if (MACH_PORT_VALID (singlestepped_thread_port
))
441 warning ("Singlestepped_thread_port (0x%x) is still valid?",
442 singlestepped_thread_port
);
443 singlestepped_thread_port
= MACH_PORT_NULL
;
446 /* If we are already stepping this thread */
447 if (MACH_PORT_VALID (teport
) && teport
== thread_exception_port
)
449 ret
= mach_port_deallocate (mach_task_self (), teport
);
450 CHK ("Could not deallocate thread exception port", ret
);
454 ret
= thread_set_exception_port (thread
, thread_exception_port
);
455 CHK ("Setting exception port for thread", ret
);
457 /* Insert thread exception port to wait port set */
458 ret
= mach_port_move_member (mach_task_self(),
459 thread_exception_port
,
460 inferior_wait_port_set
);
461 CHK ("Moving thread exception port to inferior_wait_port_set",
464 thread_saved_exception_port
= teport
;
467 thread_trace (thread
, TRUE
);
469 singlestepped_thread_port
= thread_exception_port
;
470 currently_waiting_for
= singlestepped_thread_port
;
471 cleanup_step
= make_cleanup (discard_single_step
, thread
);
475 if (! MACH_PORT_VALID (teport
))
476 error ("Single stepped thread had an invalid exception port?");
478 if (teport
!= thread_exception_port
)
479 error ("Single stepped thread had an unknown exception port?");
481 ret
= mach_port_deallocate (mach_task_self (), teport
);
482 CHK ("Couldn't deallocate thread exception port", ret
);
484 /* Remove thread exception port from wait port set */
485 ret
= mach_port_move_member (mach_task_self(),
486 thread_exception_port
,
488 CHK ("Removing thread exception port from inferior_wait_port_set",
491 /* Restore thread's old exception port */
492 ret
= thread_set_exception_port (thread
,
493 thread_saved_exception_port
);
494 CHK ("Restoring stepped thread's exception port", ret
);
496 if (MACH_PORT_VALID (thread_saved_exception_port
))
497 (void) mach_port_deallocate (mach_task_self (),
498 thread_saved_exception_port
);
500 thread_trace (thread
, FALSE
);
502 singlestepped_thread_port
= MACH_PORT_NULL
;
503 currently_waiting_for
= inferior_wait_port_set
;
505 discard_cleanups (cleanup_step
);
511 request_notify (name
, variant
, type
)
513 mach_msg_id_t variant
;
517 mach_port_t previous_port_dummy
= MACH_PORT_NULL
;
519 if (! MACH_PORT_VALID (name
))
522 if (port_chain_member (notify_chain
, name
))
525 ret
= mach_port_request_notification (mach_task_self(),
530 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
531 &previous_port_dummy
);
532 CHK ("Serious: request_notify failed", ret
);
534 (void) mach_port_deallocate (mach_task_self (),
535 previous_port_dummy
);
537 notify_chain
= port_chain_insert (notify_chain
, name
, type
);
540 reverse_msg_bits(msgp
, type
)
541 mach_msg_header_t
*msgp
;
545 rbits
= MACH_MSGH_BITS_REMOTE(msgp
->msgh_bits
);
548 (msgp
->msgh_bits
& ~MACH_MSGH_BITS_PORTS_MASK
) |
549 MACH_MSGH_BITS(lbits
,rbits
);
552 /* On the third day He said:
555 and then it was global.
557 When creating the inferior fork, the
558 child code in inflow.c sets the name of the
559 bootstrap_port in its address space to this
562 The name is transferred to our address space
563 with mach3_read_inferior().
565 Thou shalt not do this with
566 task_get_bootstrap_port() in this task, since
567 the name in the inferior task is different than
570 For blessed are the meek, as they shall inherit
573 mach_port_t original_server_port_name
= MACH_PORT_NULL
;
576 /* Called from inferior after FORK but before EXEC */
582 /* Get the NAME of the bootstrap port in this task
583 so that GDB can read it */
584 ret
= task_get_bootstrap_port (mach_task_self (),
585 &original_server_port_name
);
586 if (ret
!= KERN_SUCCESS
)
588 ret
= mach_port_deallocate (mach_task_self (),
589 original_server_port_name
);
590 if (ret
!= KERN_SUCCESS
)
593 /* Suspend this task to let the parent change my ports.
594 Resumed by the debugger */
595 ret
= task_suspend (mach_task_self ());
596 if (ret
!= KERN_SUCCESS
)
601 * Intercept system calls to Unix server.
602 * After EXEC_COUNTER calls to exec(), return.
604 * Pre-assertion: Child is suspended. (Not verified)
605 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
609 intercept_exec_calls (exec_counter
)
612 struct syscall_msg_t
{
613 mach_msg_header_t header
;
614 mach_msg_type_t type
;
615 char room
[ 2000 ]; /* Enuff space */
618 struct syscall_msg_t syscall_in
, syscall_out
;
620 mach_port_t fake_server
;
621 mach_port_t original_server_send
;
622 mach_port_t original_exec_reply
;
623 mach_port_t exec_reply
;
624 mach_port_t exec_reply_send
;
625 mach_msg_type_name_t acquired
;
626 mach_port_t emulator_server_port_name
;
627 struct task_basic_info info
;
628 mach_msg_type_number_t info_count
;
632 if (exec_counter
<= 0)
633 return; /* We are already set up in the correct program */
635 ret
= mach_port_allocate(mach_task_self(),
636 MACH_PORT_RIGHT_RECEIVE
,
638 CHK("create inferior_fake_server port failed", ret
);
640 /* Wait for inferior_task to suspend itself */
643 info_count
= sizeof (info
);
644 ret
= task_info (inferior_task
,
648 CHK ("Task info", ret
);
650 if (info
.suspend_count
)
653 /* Note that the definition of the parameter was undefined
654 * at the time of this writing, so I just use an `ad hoc' value.
656 (void) swtch_pri (42); /* Universal Priority Value */
659 /* Read the inferior's bootstrap port name */
660 if (!mach3_read_inferior (&original_server_port_name
,
661 &original_server_port_name
,
662 sizeof (original_server_port_name
)))
663 error ("Can't read inferior task bootstrap port name");
665 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
666 /* Should get refs, and set them back when restoring */
667 /* Steal the original bsd server send right from inferior */
668 ret
= mach_port_extract_right (inferior_task
,
669 original_server_port_name
,
670 MACH_MSG_TYPE_MOVE_SEND
,
671 &original_server_send
,
673 CHK("mach_port_extract_right (bsd server send)",ret
);
675 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
676 error("Incorrect right extracted, send right to bsd server excpected");
678 ret
= mach_port_insert_right (inferior_task
,
679 original_server_port_name
,
681 MACH_MSG_TYPE_MAKE_SEND
);
682 CHK("mach_port_insert_right (fake server send)",ret
);
684 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
686 original_server_port_name
, original_server_send
);
688 /* A receive right to the reply generated by unix server exec() request */
689 ret
= mach_port_allocate(mach_task_self(),
690 MACH_PORT_RIGHT_RECEIVE
,
692 CHK("create intercepted_reply_port port failed", ret
);
694 /* Pass this send right to Unix server so it replies to us after exec() */
695 ret
= mach_port_extract_right (mach_task_self (),
697 MACH_MSG_TYPE_MAKE_SEND_ONCE
,
700 CHK("mach_port_extract_right (exec_reply)",ret
);
702 if (acquired
!= MACH_MSG_TYPE_PORT_SEND_ONCE
)
703 error("Incorrect right extracted, send once excpected for exec reply");
705 ret
= mach_port_move_member(mach_task_self(),
707 inferior_wait_port_set
);
708 CHK ("Moving fake syscall port to inferior_wait_port_set", ret
);
710 xx_debug ("syscall fake server set up, resuming inferior\n");
712 ret
= task_resume (inferior_task
);
713 CHK("task_resume (startup)", ret
);
715 /* Read requests from the inferior.
716 Pass directly through everything else except exec() calls.
718 while(exec_counter
> 0)
720 ret
= mach_msg (&syscall_in
.header
, /* header */
721 MACH_RCV_MSG
, /* options */
723 sizeof (struct syscall_msg_t
), /* receive size */
724 inferior_wait_port_set
, /* receive_name */
725 MACH_MSG_TIMEOUT_NONE
,
727 CHK("mach_msg (intercepted sycall)", ret
);
730 print_msg (&syscall_in
.header
);
733 /* ASSERT : msgh_local_port == fake_server */
735 if (notify_server (&syscall_in
.header
, &syscall_out
.header
))
736 error ("received a notify while intercepting syscalls");
738 if (syscall_in
.header
.msgh_id
== MIG_EXEC_SYSCALL_ID
)
740 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter
);
741 if (exec_counter
== 1)
743 original_exec_reply
= syscall_in
.header
.msgh_remote_port
;
744 syscall_in
.header
.msgh_remote_port
= exec_reply_send
;
749 syscall_in
.header
.msgh_local_port
= syscall_in
.header
.msgh_remote_port
;
750 syscall_in
.header
.msgh_remote_port
= original_server_send
;
752 reverse_msg_bits(&syscall_in
.header
, MACH_MSG_TYPE_COPY_SEND
);
754 ret
= mach_msg_send (&syscall_in
.header
);
755 CHK ("Forwarded syscall", ret
);
758 ret
= mach_port_move_member(mach_task_self(),
761 CHK ("Moving fake syscall out of inferior_wait_port_set", ret
);
763 ret
= mach_port_move_member(mach_task_self(),
765 inferior_wait_port_set
);
766 CHK ("Moving exec_reply to inferior_wait_port_set", ret
);
768 ret
= mach_msg (&syscall_in
.header
, /* header */
769 MACH_RCV_MSG
, /* options */
771 sizeof (struct syscall_msg_t
), /* receive size */
772 inferior_wait_port_set
, /* receive_name */
773 MACH_MSG_TIMEOUT_NONE
,
775 CHK("mach_msg (exec reply)", ret
);
777 ret
= task_suspend (inferior_task
);
778 CHK ("Suspending inferior after last exec", ret
);
780 must_suspend_thread
= 0;
782 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
785 print_msg (&syscall_in
.header
);
788 /* Message should appear as if it came from the unix server */
789 syscall_in
.header
.msgh_local_port
= MACH_PORT_NULL
;
791 /* and go to the inferior task original reply port */
792 syscall_in
.header
.msgh_remote_port
= original_exec_reply
;
794 reverse_msg_bits(&syscall_in
.header
, MACH_MSG_TYPE_MOVE_SEND_ONCE
);
796 ret
= mach_msg_send (&syscall_in
.header
);
797 CHK ("Forwarding exec reply to inferior", ret
);
799 /* Garbage collect */
800 ret
= mach_port_deallocate (inferior_task
,
801 original_server_port_name
);
802 CHK ("deallocating fake server send right", ret
);
804 ret
= mach_port_insert_right (inferior_task
,
805 original_server_port_name
,
806 original_server_send
,
807 MACH_MSG_TYPE_MOVE_SEND
);
808 CHK ("Restoring the original bsd server send right", ret
);
810 ret
= mach_port_destroy (mach_task_self (),
812 fake_server
= MACH_PORT_DEAD
;
813 CHK("mach_port_destroy (fake_server)", ret
);
815 ret
= mach_port_destroy (mach_task_self (),
817 exec_reply
= MACH_PORT_DEAD
;
818 CHK("mach_port_destroy (exec_reply)", ret
);
820 xx_debug ("Done with exec call interception\n");
824 consume_send_rights (thread_list
, thread_count
)
825 thread_array_t thread_list
;
833 for (index
= 0; index
< thread_count
; index
++)
835 /* Since thread kill command kills threads, don't check ret */
836 (void) mach_port_deallocate (mach_task_self (),
837 thread_list
[ index
]);
841 /* suspend/abort/resume a thread. */
842 setup_thread (thread
, what
)
850 ret
= thread_suspend (thread
);
851 CHK ("setup_thread thread_suspend", ret
);
853 ret
= thread_abort (thread
);
854 CHK ("setup_thread thread_abort", ret
);
858 ret
= thread_resume (thread
);
859 CHK ("setup_thread thread_resume", ret
);
864 map_slot_to_mid (slot
, threads
, thread_count
)
866 thread_array_t threads
;
877 ret
= task_threads (inferior_task
, &threads
, &thread_count
);
878 CHK ("Can not select a thread from a dead task", ret
);
881 if (slot
< 0 || slot
>= thread_count
)
885 consume_send_rights (threads
, thread_count
);
886 (void) vm_deallocate (mach_task_self(), (vm_address_t
)threads
,
887 (thread_count
* sizeof(mach_port_t
)));
890 error ("invalid slot number");
895 mid
= map_port_name_to_mid (threads
[slot
], MACH_TYPE_THREAD
);
899 consume_send_rights (threads
, thread_count
);
900 (void) vm_deallocate (mach_task_self(), (vm_address_t
)threads
,
901 (thread_count
* sizeof(mach_port_t
)));
908 parse_thread_id (arg
, thread_count
, slots
)
921 while (*arg
&& (*arg
== ' ' || *arg
== '\t'))
927 /* Currently parse MID and @SLOTNUMBER */
932 error ("valid thread mid expected");
940 error ("invalid slot number");
942 /* If you want slot numbers to remain slot numbers, set slots.
944 * Well, since 0 is reserved, return the ordinal number
945 * of the thread rather than the slot number. Awk, this
946 * counts as a kludge.
951 if (thread_count
&& slot
>= thread_count
)
954 mid
= map_slot_to_mid (slot
);
959 /* THREAD_ID 0 is special; it selects the first kernel
960 * thread from the list (i.e. SLOTNUMBER 0)
961 * This is used when starting the program with 'run' or when attaching.
963 * If FLAG is 0 the context is not changed, and the registers, frame, etc
964 * will continue to describe the old thread.
966 * If FLAG is nonzero, really select the thread.
967 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
971 select_thread (task
, thread_id
, flag
)
976 thread_array_t thread_list
;
980 thread_t new_thread
= MACH_PORT_NULL
;
983 error ("Can't select cprocs without kernel thread");
985 ret
= task_threads (task
, &thread_list
, &thread_count
);
986 if (ret
!= KERN_SUCCESS
)
988 warning ("Can not select a thread from a dead task");
993 if (thread_count
== 0)
995 /* The task can not do anything anymore, but it still
996 * exists as a container for memory and ports.
998 registers_changed ();
999 warning ("Task %d has no threads",
1000 map_port_name_to_mid (task
, MACH_TYPE_TASK
));
1001 current_thread
= MACH_PORT_NULL
;
1002 (void) vm_deallocate(mach_task_self(),
1003 (vm_address_t
) thread_list
,
1004 (thread_count
* sizeof(mach_port_t
)));
1005 return KERN_FAILURE
;
1008 if (! thread_id
|| flag
== 2)
1010 /* First thread or a slotnumber */
1012 new_thread
= thread_list
[0];
1015 if (thread_id
< thread_count
)
1016 new_thread
= thread_list
[ thread_id
];
1019 (void) vm_deallocate(mach_task_self(),
1020 (vm_address_t
) thread_list
,
1021 (thread_count
* sizeof(mach_port_t
)));
1022 error ("No such thread slot number : %d", thread_id
);
1028 for (index
= 0; index
< thread_count
; index
++)
1029 if (thread_id
== map_port_name_to_mid (thread_list
[index
],
1032 new_thread
= thread_list
[index
];
1038 error ("No thread with mid %d", thread_id
);
1041 /* Notify when the selected thread dies */
1042 request_notify (new_thread
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_THREAD
);
1044 ret
= vm_deallocate(mach_task_self(),
1045 (vm_address_t
) thread_list
,
1046 (thread_count
* sizeof(mach_port_t
)));
1047 CHK ("vm_deallocate", ret
);
1050 current_thread
= new_thread
;
1054 if (MACH_PORT_VALID (current_thread
))
1056 /* Store the gdb's view of the thread we are deselecting
1058 * @@ I think gdb updates registers immediately when they are
1059 * changed, so don't do this.
1061 ret
= thread_abort (current_thread
);
1062 CHK ("Could not abort system calls when saving state of old thread",
1064 target_prepare_to_store ();
1065 target_store_registers (-1);
1069 registers_changed ();
1071 current_thread
= new_thread
;
1073 ret
= thread_abort (current_thread
);
1074 CHK ("Could not abort system calls when selecting a thread", ret
);
1076 stop_pc
= read_pc();
1077 set_current_frame (create_new_frame (read_register (FP_REGNUM
),
1080 select_frame (get_current_frame (), 0);
1082 stop_frame_address
= FRAME_FP (get_current_frame ());
1085 return KERN_SUCCESS
;
1089 * Switch to use thread named NEW_THREAD.
1093 switch_to_thread (new_thread
)
1094 thread_t new_thread
;
1096 thread_t saved_thread
= current_thread
;
1099 mid
= map_port_name_to_mid (new_thread
,
1102 warning ("Can't map thread name 0x%x to mid", new_thread
);
1103 else if (select_thread (inferior_task
, mid
, 1) != KERN_SUCCESS
)
1106 current_thread
= saved_thread
;
1107 error ("Could not select thread %d", mid
);
1113 /* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1114 * Note that the registers are not yet valid in the inferior task.
1122 inferior_task
= task_by_pid (pid
);
1124 if (! MACH_PORT_VALID (inferior_task
))
1125 error ("Can not map Unix pid %d to Mach task", pid
);
1127 /* Clean up previous notifications and create new ones */
1128 setup_notify_port (1);
1130 /* When notification appears, the inferior task has died */
1131 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
1133 emulator_present
= have_emulator_p (inferior_task
);
1135 /* By default, select the first thread,
1136 * If task has no threads, gives a warning
1137 * Does not fetch registers, since they are not yet valid.
1139 select_thread (inferior_task
, 0, 0);
1141 inferior_exception_port
= MACH_PORT_NULL
;
1143 setup_exception_port ();
1145 xx_debug ("Now the debugged task is created\n");
1147 /* One trap to exec the shell, one to exec the program being debugged. */
1148 intercept_exec_calls (2);
1151 setup_exception_port ()
1155 ret
= mach_port_allocate (mach_task_self(),
1156 MACH_PORT_RIGHT_RECEIVE
,
1157 &inferior_exception_port
);
1158 CHK("mach_port_allocate",ret
);
1160 /* add send right */
1161 ret
= mach_port_insert_right (mach_task_self (),
1162 inferior_exception_port
,
1163 inferior_exception_port
,
1164 MACH_MSG_TYPE_MAKE_SEND
);
1165 CHK("mach_port_insert_right",ret
);
1167 ret
= mach_port_move_member (mach_task_self(),
1168 inferior_exception_port
,
1169 inferior_wait_port_set
);
1170 CHK("mach_port_move_member",ret
);
1172 ret
= task_get_special_port (inferior_task
,
1173 TASK_EXCEPTION_PORT
,
1174 &inferior_old_exception_port
);
1175 CHK ("task_get_special_port(old exc)",ret
);
1177 ret
= task_set_special_port (inferior_task
,
1178 TASK_EXCEPTION_PORT
,
1179 inferior_exception_port
);
1180 CHK("task_set_special_port",ret
);
1182 ret
= mach_port_deallocate (mach_task_self (),
1183 inferior_exception_port
);
1184 CHK("mack_port_deallocate",ret
);
1187 /* When notify appears, the inferior_task's exception
1188 * port has been destroyed.
1190 * Not used, since the dead_name_notification already
1191 * appears when task dies.
1194 request_notify (inferior_exception_port
,
1195 MACH_NOTIFY_NO_SENDERS
,
1196 MACH_TYPE_EXCEPTION_PORT
);
1200 /* Nonzero if gdb is waiting for a message */
1201 int mach_really_waiting
;
1203 /* Wait for the inferior to stop for some reason.
1204 - Loop on notifications until inferior_task dies.
1205 - Loop on exceptions until stopped_in_exception comes true.
1206 (e.g. we receive a single step trace trap)
1207 - a message arrives to gdb's message port
1209 There is no other way to exit this loop.
1211 Returns the inferior_pid for rest of gdb.
1212 Side effects: Set *OURSTATUS. */
1214 mach_really_wait (w
)
1215 struct target_waitstatus
*ourstatus
;
1222 mach_msg_header_t header
;
1223 mach_msg_type_t foo
;
1227 /* Either notify (death), exception or message can stop the inferior */
1228 stopped_in_exception
= FALSE
;
1234 stop_exception
= stop_code
= stop_subcode
= -1;
1235 stop_thread
= MACH_PORT_NULL
;
1237 mach_really_waiting
= 1;
1238 ret
= mach_msg (&in_msg
.header
, /* header */
1239 MACH_RCV_MSG
, /* options */
1241 sizeof (struct msg
), /* receive size */
1242 currently_waiting_for
, /* receive name */
1243 MACH_MSG_TIMEOUT_NONE
,
1245 mach_really_waiting
= 0;
1246 CHK("mach_msg (receive)", ret
);
1248 /* Check if we received a notify of the childs' death */
1249 if (notify_server (&in_msg
.header
, &out_msg
.header
))
1251 /* If inferior_task is null then the inferior has
1252 gone away and we want to return to command level.
1253 Otherwise it was just an informative message and we
1254 need to look to see if there are any more. */
1255 if (inferior_task
!= MACH_PORT_NULL
)
1259 /* Collect Unix exit status for gdb */
1261 wait3(&w
, WNOHANG
, 0);
1263 /* This mess is here to check that the rest of
1264 * gdb knows that the inferior died. It also
1265 * tries to hack around the fact that Mach 3.0 (mk69)
1266 * unix server (ux28) does not always know what
1267 * has happened to it's children when mach-magic
1268 * is applied on them.
1270 if ((!WIFEXITED(w
) && WIFSTOPPED(w
)) ||
1271 (WIFEXITED(w
) && WEXITSTATUS(w
) > 0377))
1274 warning ("Using exit value 0 for terminated task");
1276 else if (!WIFEXITED(w
))
1278 int sig
= WTERMSIG(w
);
1280 /* Signals cause problems. Warn the user. */
1281 if (sig
!= SIGKILL
) /* Bad luck if garbage matches this */
1282 warning ("The terminating signal stuff may be nonsense");
1283 else if (sig
> NSIG
)
1286 warning ("Using exit value 0 for terminated task");
1289 store_waitstatus (ourstatus
, w
);
1290 return inferior_pid
;
1294 /* Hmm. Check for exception, as it was not a notification.
1295 exc_server() does an upcall to catch_exception_raise()
1296 if this rpc is an exception. Further actions are decided
1299 if (! exc_server (&in_msg
.header
, &out_msg
.header
))
1302 /* Not an exception, check for message.
1304 * Messages don't come from the inferior, or if they
1305 * do they better be asynchronous or it will hang.
1307 if (gdb_message_server (&in_msg
.header
))
1310 error ("Unrecognized message received in mach_really_wait");
1313 /* Send the reply of the exception rpc to the suspended task */
1314 ret
= mach_msg_send (&out_msg
.header
);
1315 CHK ("mach_msg_send (exc reply)", ret
);
1317 if (stopped_in_exception
)
1319 /* Get unix state. May be changed in mach3_exception_actions() */
1320 wait3(&w
, WNOHANG
, 0);
1322 mach3_exception_actions (&w
, FALSE
, "Task");
1324 store_waitstatus (ourstatus
, w
);
1325 return inferior_pid
;
1330 /* Called by macro DO_QUIT() in utils.c(quit).
1331 * This is called just before calling error() to return to command level
1339 if (mach_really_waiting
)
1341 ret
= task_suspend (inferior_task
);
1343 if (ret
!= KERN_SUCCESS
)
1345 warning ("Could not suspend task for interrupt: %s",
1346 mach_error_string (ret
));
1347 mach_really_waiting
= 0;
1352 must_suspend_thread
= 0;
1353 mach_really_waiting
= 0;
1355 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1358 warning ("Selecting first existing kernel thread");
1362 current_thread
= MACH_PORT_NULL
; /* Force setup */
1363 select_thread (inferior_task
, mid
, 1);
1368 /* If ^C is typed when we are waiting for a message
1369 * and your Unix server is able to notice that we
1372 * Called by REQUEST_QUIT() from utils.c(request_quit)
1375 mach3_request_quit ()
1377 if (mach_really_waiting
)
1382 * Gdb message server.
1383 * Currently implemented is the STOP message, that causes
1384 * gdb to return to the command level like ^C had been typed from terminal.
1387 gdb_message_server (InP
)
1388 mach_msg_header_t
*InP
;
1393 if (InP
->msgh_local_port
== our_message_port
)
1395 /* A message coming to our_message_port. Check validity */
1396 switch (InP
->msgh_id
) {
1398 case GDB_MESSAGE_ID_STOP
:
1399 ret
= task_suspend (inferior_task
);
1400 if (ret
!= KERN_SUCCESS
)
1401 warning ("Could not suspend task for stop message: %s",
1402 mach_error_string (ret
));
1404 /* QUIT in mach_really_wait() loop. */
1409 warning ("Invalid message id %d received, ignored.",
1417 /* Message not handled by this server */
1421 /* NOTE: This is not an RPC call. It is a simpleroutine.
1423 * This is not called from this gdb code.
1425 * It may be called by another debugger to cause this
1426 * debugger to enter command level:
1428 * (gdb) set stop_inferior_gdb ()
1431 * External program "stop-gdb" implements this also.
1434 stop_inferior_gdb ()
1438 /* Code generated by mig, with minor cleanups :-)
1440 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1444 mach_msg_header_t Head
;
1449 register Request
*InP
= &Mess
;
1451 InP
->Head
.msgh_bits
= MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND
, 0);
1453 /* msgh_size passed as argument */
1454 InP
->Head
.msgh_remote_port
= our_message_port
;
1455 InP
->Head
.msgh_local_port
= MACH_PORT_NULL
;
1456 InP
->Head
.msgh_seqno
= 0;
1457 InP
->Head
.msgh_id
= GDB_MESSAGE_ID_STOP
;
1459 ret
= mach_msg (&InP
->Head
,
1460 MACH_SEND_MSG
|MACH_MSG_OPTION_NONE
,
1464 MACH_MSG_TIMEOUT_NONE
,
1468 #ifdef THREAD_ALLOWED_TO_BREAK
1470 * Return 1 if the MID specifies the thread that caused the
1472 * Since catch_exception_raise() selects the thread causing
1473 * the last exception to current_thread, we just check that
1474 * it is selected and the last exception was a breakpoint.
1477 mach_thread_for_breakpoint (mid
)
1480 int cmid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
1484 mid
= map_slot_to_mid (-(mid
+1), 0, 0);
1486 return 0; /* Don't stop, no such slot */
1489 if (! mid
|| cmid
== -1)
1490 return 1; /* stop */
1492 return cmid
== mid
&& stop_exception
== EXC_BREAKPOINT
;
1494 #endif /* THREAD_ALLOWED_TO_BREAK */
1496 #ifdef THREAD_PARSE_ID
1498 * Map a thread id string (MID or a @SLOTNUMBER)
1501 * 0 matches all threads.
1502 * Otherwise the meaning is defined only in this file.
1503 * (mach_thread_for_breakpoint uses it)
1505 * @@ This allows non-existent MIDs to be specified.
1506 * It now also allows non-existent slots to be
1507 * specified. (Slot numbers stored are negative,
1508 * and the magnitude is one greater than the actual
1509 * slot index. (Since 0 is reserved))
1512 mach_thread_parse_id (arg
)
1517 error ("thread id excpected");
1518 mid
= parse_thread_id (arg
, 0, 1);
1522 #endif /* THREAD_PARSE_ID */
1524 #ifdef THREAD_OUTPUT_ID
1526 mach_thread_output_id (mid
)
1529 static char foobar
[20];
1532 sprintf (foobar
, "mid %d", mid
);
1534 sprintf (foobar
, "@%d", -(mid
+1));
1536 sprintf (foobar
, "*any thread*");
1540 #endif /* THREAD_OUTPUT_ID */
1542 /* Called with hook PREPARE_TO_PROCEED() from infrun.c.
1544 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1546 * if SELECT_IT is nonzero, reselect the thread that was active when
1547 * we stopped at a breakpoint.
1551 mach3_prepare_to_proceed (select_it
)
1555 stop_thread
!= current_thread
&&
1556 stop_exception
== EXC_BREAKPOINT
)
1563 mid
= switch_to_thread (stop_thread
);
1571 /* this stuff here is an upcall via libmach/excServer.c
1572 and mach_really_wait which does the actual upcall.
1574 The code will pass the exception to the inferior if:
1576 - The task that signaled is not the inferior task
1577 (e.g. when debugging another debugger)
1579 - The user has explicitely requested to pass on the exceptions.
1580 (e.g to the default unix exception handler, which maps
1581 exceptions to signals, or the user has her own exception handler)
1583 - If the thread that signaled is being single-stepped and it
1584 has set it's own exception port and the exception is not
1585 EXC_BREAKPOINT. (Maybe this is not desirable?)
1589 catch_exception_raise (port
, thread
, task
, exception
, code
, subcode
)
1593 int exception
, code
, subcode
;
1596 boolean_t signal_thread
;
1597 int mid
= map_port_name_to_mid (thread
, MACH_TYPE_THREAD
);
1599 if (! MACH_PORT_VALID (thread
))
1601 /* If the exception was sent and thread dies before we
1602 receive it, THREAD will be MACH_PORT_DEAD
1605 current_thread
= thread
= MACH_PORT_NULL
;
1606 error ("Received exception from nonexistent thread");
1609 /* Check if the task died in transit.
1610 * @@ Isn't the thread also invalid in such case?
1612 if (! MACH_PORT_VALID (task
))
1614 current_thread
= thread
= MACH_PORT_NULL
;
1615 error ("Received exception from nonexistent task");
1618 if (exception
< 0 || exception
> MAX_EXCEPTION
)
1619 fatal ("catch_exception_raise: unknown exception code %d thread %d",
1623 if (! MACH_PORT_VALID (inferior_task
))
1624 error ("got an exception, but inferior_task is null or dead");
1626 stop_exception
= exception
;
1628 stop_subcode
= subcode
;
1629 stop_thread
= thread
;
1631 signal_thread
= exception
!= EXC_BREAKPOINT
&&
1632 port
== singlestepped_thread_port
&&
1633 MACH_PORT_VALID (thread_saved_exception_port
);
1635 /* If it was not our inferior or if we want to forward
1636 * the exception to the inferior's handler, do it here
1638 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1640 if (task
!= inferior_task
||
1642 exception_map
[exception
].forward
)
1644 mach_port_t eport
= inferior_old_exception_port
;
1649 GDB now forwards the exeption to thread's original handler,
1650 since the user propably knows what he is doing.
1651 Give a message, though.
1654 mach3_exception_actions ((WAITTYPE
*)NULL
, TRUE
, "Thread");
1655 eport
= thread_saved_exception_port
;
1658 /* Send the exception to the original handler */
1659 ret
= exception_raise (eport
,
1666 (void) mach_port_deallocate (mach_task_self (), task
);
1667 (void) mach_port_deallocate (mach_task_self (), thread
);
1669 /* If we come here, we don't want to trace any more, since we
1670 * will never stop for tracing anyway.
1672 discard_single_step (thread
);
1674 /* Do not stop the inferior */
1678 /* Now gdb handles the exception */
1679 stopped_in_exception
= TRUE
;
1681 ret
= task_suspend (task
);
1682 CHK ("Error suspending inferior after exception", ret
);
1684 must_suspend_thread
= 0;
1686 if (current_thread
!= thread
)
1688 if (MACH_PORT_VALID (singlestepped_thread_port
))
1689 /* Cleanup discards single stepping */
1690 error ("Exception from thread %d while singlestepping thread %d",
1692 map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
));
1694 /* Then select the thread that caused the exception */
1695 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
1696 error ("Could not select thread %d causing exception", mid
);
1698 warning ("Gdb selected thread %d", mid
);
1701 /* If we receive an exception that is not breakpoint
1702 * exception, we interrupt the single step and return to
1703 * debugger. Trace condition is cleared.
1705 if (MACH_PORT_VALID (singlestepped_thread_port
))
1707 if (stop_exception
!= EXC_BREAKPOINT
)
1708 warning ("Single step interrupted by exception");
1709 else if (port
== singlestepped_thread_port
)
1711 /* Single step exception occurred, remove trace bit
1712 * and return to gdb.
1714 if (! MACH_PORT_VALID (current_thread
))
1715 error ("Single stepped thread is not valid");
1717 /* Resume threads, but leave the task suspended */
1718 resume_all_threads (0);
1721 warning ("Breakpoint while single stepping?");
1723 discard_single_step (current_thread
);
1726 (void) mach_port_deallocate (mach_task_self (), task
);
1727 (void) mach_port_deallocate (mach_task_self (), thread
);
1729 return KERN_SUCCESS
;
1733 port_valid (port
, mask
)
1738 mach_port_type_t type
;
1740 ret
= mach_port_type (mach_task_self (),
1743 if (ret
!= KERN_SUCCESS
|| (type
& mask
) != mask
)
1748 /* @@ No vm read cache implemented yet */
1749 boolean_t vm_read_cache_valid
= FALSE
;
1752 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1753 * in gdb's address space.
1755 * Return 0 on failure; number of bytes read otherwise.
1758 mach3_read_inferior (addr
, myaddr
, length
)
1764 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1765 vm_size_t aligned_length
=
1766 (vm_size_t
) round_page (addr
+length
) - low_address
;
1767 pointer_t copied_memory
;
1770 /* Get memory from inferior with page aligned addresses */
1771 ret
= vm_read (inferior_task
,
1776 if (ret
!= KERN_SUCCESS
)
1778 /* the problem is that the inferior might be killed for whatever reason
1779 * before we go to mach_really_wait. This is one place that ought to
1780 * catch many of those errors.
1781 * @@ A better fix would be to make all external events to GDB
1782 * to arrive via a SINGLE port set. (Including user input!)
1785 if (! port_valid (inferior_task
, MACH_PORT_TYPE_SEND
))
1788 error ("Inferior killed (task port invalid)");
1794 /* valprint.c gives nicer format if this does not
1795 screw it. Eamonn seems to like this, so I enable
1796 it if OSF is defined...
1798 warning ("[read inferior %x failed: %s]",
1799 addr
, mach_error_string (ret
));
1806 memcpy (myaddr
, (char *)addr
- low_address
+ copied_memory
, length
);
1808 ret
= vm_deallocate (mach_task_self (),
1811 CHK("mach3_read_inferior vm_deallocate failed", ret
);
1817 #define CHK_GOTO_OUT(str,ret) \
1818 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
1820 #define CHK_GOTO_OUT(str,ret) \
1821 do if (ret != KERN_SUCCESS) { errstr = str; goto out; } while(0)
1824 struct vm_region_list
{
1825 struct vm_region_list
*next
;
1826 vm_prot_t protection
;
1831 struct obstack region_obstack
;
1834 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1835 * in gdb's address space.
1838 mach3_write_inferior (addr
, myaddr
, length
)
1844 vm_address_t low_address
= (vm_address_t
) trunc_page (addr
);
1845 vm_size_t aligned_length
=
1846 (vm_size_t
) round_page (addr
+length
) - low_address
;
1847 pointer_t copied_memory
;
1851 char *errstr
= "Bug in mach3_write_inferior";
1853 struct vm_region_list
*region_element
;
1854 struct vm_region_list
*region_head
= (struct vm_region_list
*)NULL
;
1856 /* Get memory from inferior with page aligned addresses */
1857 ret
= vm_read (inferior_task
,
1862 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret
);
1866 memcpy ((char *)addr
- low_address
+ copied_memory
, myaddr
, length
);
1868 obstack_init (®ion_obstack
);
1870 /* Do writes atomically.
1871 * First check for holes and unwritable memory.
1874 vm_size_t remaining_length
= aligned_length
;
1875 vm_address_t region_address
= low_address
;
1877 struct vm_region_list
*scan
;
1879 while(region_address
< low_address
+ aligned_length
)
1881 vm_prot_t protection
;
1882 vm_prot_t max_protection
;
1883 vm_inherit_t inheritance
;
1885 mach_port_t object_name
;
1887 vm_size_t region_length
= remaining_length
;
1888 vm_address_t old_address
= region_address
;
1890 ret
= vm_region (inferior_task
,
1899 CHK_GOTO_OUT ("vm_region failed", ret
);
1901 /* Check for holes in memory */
1902 if (old_address
!= region_address
)
1904 warning ("No memory at 0x%x. Nothing written",
1911 if (!(max_protection
& VM_PROT_WRITE
))
1913 warning ("Memory at address 0x%x is unwritable. Nothing written",
1920 /* Chain the regions for later use */
1922 (struct vm_region_list
*)
1923 obstack_alloc (®ion_obstack
, sizeof (struct vm_region_list
));
1925 region_element
->protection
= protection
;
1926 region_element
->start
= region_address
;
1927 region_element
->length
= region_length
;
1929 /* Chain the regions along with protections */
1930 region_element
->next
= region_head
;
1931 region_head
= region_element
;
1933 region_address
+= region_length
;
1934 remaining_length
= remaining_length
- region_length
;
1937 /* If things fail after this, we give up.
1938 * Somebody is messing up inferior_task's mappings.
1941 /* Enable writes to the chained vm regions */
1942 for (scan
= region_head
; scan
; scan
= scan
->next
)
1944 boolean_t protection_changed
= FALSE
;
1946 if (!(scan
->protection
& VM_PROT_WRITE
))
1948 ret
= vm_protect (inferior_task
,
1952 scan
->protection
| VM_PROT_WRITE
);
1953 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1957 ret
= vm_write (inferior_task
,
1961 CHK_GOTO_OUT ("vm_write failed", ret
);
1963 /* Set up the original region protections, if they were changed */
1964 for (scan
= region_head
; scan
; scan
= scan
->next
)
1966 boolean_t protection_changed
= FALSE
;
1968 if (!(scan
->protection
& VM_PROT_WRITE
))
1970 ret
= vm_protect (inferior_task
,
1975 CHK_GOTO_OUT ("vm_protect: enable write failed", ret
);
1983 obstack_free (®ion_obstack
, 0);
1985 (void) vm_deallocate (mach_task_self (),
1990 if (ret
!= KERN_SUCCESS
)
1992 warning ("%s %s", errstr
, mach_error_string (ret
));
1999 /* Return 0 on failure, number of bytes handled otherwise. */
2001 m3_xfer_memory (memaddr
, myaddr
, len
, write
, target
)
2006 struct target_ops
*target
; /* IGNORED */
2011 result
= mach3_write_inferior (memaddr
, myaddr
, len
);
2013 result
= mach3_read_inferior (memaddr
, myaddr
, len
);
2020 translate_state(state
)
2024 case TH_STATE_RUNNING
: return("R");
2025 case TH_STATE_STOPPED
: return("S");
2026 case TH_STATE_WAITING
: return("W");
2027 case TH_STATE_UNINTERRUPTIBLE
: return("U");
2028 case TH_STATE_HALTED
: return("H");
2029 default: return("?");
2034 translate_cstate (state
)
2039 case CPROC_RUNNING
: return "R";
2040 case CPROC_SWITCHING
: return "S";
2041 case CPROC_BLOCKED
: return "B";
2042 case CPROC_CONDWAIT
: return "C";
2043 case CPROC_CONDWAIT
|CPROC_SWITCHING
: return "CS";
2044 default: return "?";
2048 /* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2050 mach_port_t
/* no mach_port_name_t found in include files. */
2051 map_inferior_port_name (inferior_name
, type
)
2052 mach_port_t inferior_name
;
2053 mach_msg_type_name_t type
;
2056 mach_msg_type_name_t acquired
;
2059 ret
= mach_port_extract_right (inferior_task
,
2064 CHK("mach_port_extract_right (map_inferior_port_name)", ret
);
2066 if (acquired
!= MACH_MSG_TYPE_PORT_SEND
)
2067 error("Incorrect right extracted, (map_inferior_port_name)");
2069 ret
= mach_port_deallocate (mach_task_self (),
2071 CHK ("Deallocating mapped port (map_inferior_port_name)", ret
);
2077 * Naming convention:
2078 * Always return user defined name if found.
2079 * _K == A kernel thread with no matching CPROC
2080 * _C == A cproc with no current cthread
2081 * _t == A cthread with no user defined name
2083 * The digits that follow the _names are the SLOT number of the
2084 * kernel thread if there is such a thing, otherwise just a negation
2085 * of the sequential number of such cprocs.
2091 get_thread_name (one_cproc
, id
)
2092 gdb_thread_t one_cproc
;
2096 if (one_cproc
->cthread
== NULL
)
2098 /* cproc not mapped to any cthread */
2099 sprintf(buf
, "_C%d", id
);
2101 else if (! one_cproc
->cthread
->name
)
2103 /* cproc and cthread, but no name */
2104 sprintf(buf
, "_t%d", id
);
2107 return (one_cproc
->cthread
->name
);
2111 warning ("Inconsistency in thread name id %d", id
);
2113 /* Kernel thread without cproc */
2114 sprintf(buf
, "_K%d", id
);
2121 fetch_thread_info (task
, mthreads_out
)
2123 gdb_thread_t
*mthreads_out
; /* out */
2126 thread_array_t th_table
;
2128 gdb_thread_t mthreads
= NULL
;
2131 ret
= task_threads (task
, &th_table
, &th_count
);
2132 if (ret
!= KERN_SUCCESS
)
2134 warning ("Error getting inferior's thread list:%s",
2135 mach_error_string(ret
));
2140 mthreads
= (gdb_thread_t
)
2143 th_count
* sizeof (struct gdb_thread
));
2145 for (index
= 0; index
< th_count
; index
++)
2147 thread_t saved_thread
= MACH_PORT_NULL
;
2150 if (must_suspend_thread
)
2151 setup_thread (th_table
[ index
], 1);
2153 if (th_table
[index
] != current_thread
)
2155 saved_thread
= current_thread
;
2157 mid
= switch_to_thread (th_table
[ index
]);
2160 mthreads
[index
].name
= th_table
[index
];
2161 mthreads
[index
].cproc
= NULL
; /* map_cprocs_to_kernel_threads() */
2162 mthreads
[index
].in_emulator
= FALSE
;
2163 mthreads
[index
].slotid
= index
;
2165 mthreads
[index
].sp
= read_register (SP_REGNUM
);
2166 mthreads
[index
].fp
= read_register (FP_REGNUM
);
2167 mthreads
[index
].pc
= read_pc ();
2169 if (MACH_PORT_VALID (saved_thread
))
2170 mid
= switch_to_thread (saved_thread
);
2172 if (must_suspend_thread
)
2173 setup_thread (th_table
[ index
], 0);
2176 consume_send_rights (th_table
, th_count
);
2177 ret
= vm_deallocate (mach_task_self(), (vm_address_t
)th_table
,
2178 (th_count
* sizeof(mach_port_t
)));
2179 if (ret
!= KERN_SUCCESS
)
2181 warning ("Error trying to deallocate thread list : %s",
2182 mach_error_string (ret
));
2185 *mthreads_out
= mthreads
;
2192 * Current emulator always saves the USP on top of
2193 * emulator stack below struct emul_stack_top stuff.
2196 fetch_usp_from_emulator_stack (sp
)
2199 CORE_ADDR stack_pointer
;
2201 sp
= (sp
& ~(EMULATOR_STACK_SIZE
-1)) +
2202 EMULATOR_STACK_SIZE
- sizeof (struct emul_stack_top
);
2204 if (mach3_read_inferior (sp
,
2206 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2208 warning ("Can't read user sp from emulator stack address 0x%x", sp
);
2212 return stack_pointer
;
2217 /* get_emulation_vector() interface was changed after mk67 */
2218 #define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2222 /* Check if the emulator exists at task's address space.
2225 have_emulator_p (task
)
2229 #ifndef EMUL_VECTOR_COUNT
2230 vm_offset_t
*emulation_vector
;
2233 vm_offset_t emulation_vector
[ EMUL_VECTOR_COUNT
];
2234 int n
= EMUL_VECTOR_COUNT
;
2239 ret
= task_get_emulation_vector (task
,
2241 #ifndef EMUL_VECTOR_COUNT
2247 CHK("task_get_emulation_vector", ret
);
2248 xx_debug ("%d vectors from %d at 0x%08x\n",
2249 n
, vector_start
, emulation_vector
);
2251 for(i
= 0; i
< n
; i
++)
2253 vm_offset_t entry
= emulation_vector
[i
];
2255 if (EMULATOR_BASE
<= entry
&& entry
<= EMULATOR_END
)
2259 static boolean_t informed
= FALSE
;
2262 warning("Emulation vector address 0x08%x outside emulator space",
2271 /* Map cprocs to kernel threads and vice versa. */
2274 map_cprocs_to_kernel_threads (cprocs
, mthreads
, thread_count
)
2275 gdb_thread_t cprocs
;
2276 gdb_thread_t mthreads
;
2281 boolean_t all_mapped
= TRUE
;
2283 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2285 /* Default to: no kernel thread for this cproc */
2286 scan
->reverse_map
= -1;
2288 /* Check if the cproc is found by its stack */
2289 for (index
= 0; index
< thread_count
; index
++)
2291 LONGEST stack_base
=
2292 extract_signed_integer (scan
.raw_cproc
+ CPROC_BASE_OFFSET
,
2294 LONGEST stack_size
=
2295 extract_signed_integer (scan
.raw_cproc
+ CPROC_SIZE_OFFSET
,
2297 if ((mthreads
+ index
)->sp
> stack_base
&&
2298 (mthreads
+ index
)->sp
<= stack_base
+ stack_size
)
2300 (mthreads
+ index
)->cproc
= scan
;
2301 scan
->reverse_map
= index
;
2305 all_mapped
&= (scan
->reverse_map
!= -1);
2308 /* Check for threads that are currently in the emulator.
2309 * If so, they have a different stack, and the still unmapped
2310 * cprocs may well get mapped to these threads.
2313 * - cproc stack does not match any kernel thread stack pointer
2314 * - there is at least one extra kernel thread
2315 * that has no cproc mapped above.
2316 * - some kernel thread stack pointer points to emulator space
2317 * then we find the user stack pointer saved in the emulator
2318 * stack, and try to map that to the cprocs.
2320 * Also set in_emulator for kernel threads.
2323 if (emulator_present
)
2325 for (index
= 0; index
< thread_count
; index
++)
2330 gdb_thread_t mthread
= (mthreads
+index
);
2331 emul_sp
= mthread
->sp
;
2333 if (mthread
->cproc
== NULL
&&
2334 EMULATOR_BASE
<= emul_sp
&& emul_sp
<= EMULATOR_END
)
2336 mthread
->in_emulator
= emulator_present
;
2338 if (!all_mapped
&& cprocs
)
2340 usp
= fetch_usp_from_emulator_stack (emul_sp
);
2342 /* @@ Could be more accurate */
2344 error ("Zero stack pointer read from emulator?");
2346 /* Try to match this stack pointer to the cprocs that
2347 * don't yet have a kernel thread.
2349 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2352 /* Check is this unmapped CPROC stack contains
2353 * the user stack pointer saved in the
2356 if (scan
->reverse_map
== -1 &&
2357 usp
> scan
->stack_base
&&
2358 usp
<= scan
->stack_base
+ scan
->stack_size
)
2360 mthread
->cproc
= scan
;
2361 scan
->reverse_map
= index
;
2372 * Format of the thread_list command
2374 * slot mid sel name emul ks susp cstate wired address
2376 #define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2378 #define TL_HEADER "\n@ MID Name KState CState Where\n"
2381 print_tl_address (stream
, pc
)
2385 if (! lookup_minimal_symbol_by_pc (pc
))
2386 fprintf_filtered (stream
, local_hex_format(), pc
);
2389 extern int addressprint
;
2390 extern int asm_demangle
;
2392 int store
= addressprint
;
2394 print_address_symbolic (pc
, stream
, asm_demangle
, "");
2395 addressprint
= store
;
2399 /* For thread names, but also for gdb_message_port external name */
2400 #define MAX_NAME_LEN 50
2402 /* Returns the address of variable NAME or 0 if not found */
2404 lookup_address_of_variable (name
)
2408 CORE_ADDR symaddr
= 0;
2409 struct minimal_symbol
*msymbol
;
2411 sym
= lookup_symbol (name
,
2412 (struct block
*)NULL
,
2415 (struct symtab
**)NULL
);
2418 symaddr
= SYMBOL_VALUE (sym
);
2422 msymbol
= lookup_minimal_symbol (name
, (struct objfile
*) NULL
);
2424 if (msymbol
&& msymbol
->type
== mst_data
)
2425 symaddr
= msymbol
->address
;
2434 gdb_thread_t cproc_head
;
2435 gdb_thread_t cproc_copy
;
2436 CORE_ADDR their_cprocs
;
2437 char *buf
[TARGET_PTR_BIT
/ HOST_CHAR_BIT
];
2442 symaddr
= lookup_address_of_variable ("cproc_list");
2446 /* cproc_list is not in a file compiled with debugging
2447 symbols, but don't give up yet */
2449 symaddr
= lookup_address_of_variable ("cprocs");
2453 static int informed
= 0;
2457 warning ("Your program is loaded with an old threads library.");
2458 warning ("GDB does not know the old form of threads");
2459 warning ("so things may not work.");
2464 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
2468 /* Get the address of the first cproc in the task */
2469 if (!mach3_read_inferior (symaddr
,
2471 TARGET_PTR_BIT
/ HOST_CHAR_BIT
))
2472 error ("Can't read cproc master list at address (0x%x).", symaddr
);
2473 their_cprocs
= extract_address (buf
, TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2475 /* Scan the CPROCs in the task.
2476 CPROCs are chained with LIST field, not NEXT field, which
2477 chains mutexes, condition variables and queues */
2481 while (their_cprocs
!= (CORE_ADDR
)0)
2483 CORE_ADDR cproc_copy_incarnation
;
2484 cproc_copy
= (gdb_thread_t
) obstack_alloc (cproc_obstack
,
2485 sizeof (struct gdb_thread
));
2487 if (!mach3_read_inferior (their_cprocs
,
2488 &cproc_copy
.raw_cproc
[0],
2490 error("Can't read next cproc at 0x%x.", their_cprocs
);
2491 cproc_copy
= extract_address (buf
, TARGET_PTR_BIT
/ HOST_CHAR_BIT
);
2494 extract_address (cproc_copy
.raw_cproc
+ CPROC_LIST_OFFSET
,
2496 cproc_copy_incarnation
=
2497 extract_address (cproc_copy
.raw_cproc
+ CPROC_INCARNATION_OFFSET
,
2498 CPROC_INCARNATION_SIZE
);
2500 if (cproc_copy_incarnation
== (CORE_ADDR
)0)
2501 cproc_copy
->cthread
= NULL
;
2504 /* This CPROC has an attached CTHREAD. Get its name */
2505 cthread
= (cthread_t
)obstack_alloc (cproc_obstack
,
2506 sizeof(struct cthread
));
2508 if (!mach3_read_inferior (cproc_copy_incarnation
,
2510 sizeof(struct cthread
)))
2511 error("Can't read next thread at 0x%x.",
2512 cproc_copy_incarnation
);
2514 cproc_copy
->cthread
= cthread
;
2518 name
= (char *) obstack_alloc (cproc_obstack
, MAX_NAME_LEN
);
2520 if (!mach3_read_inferior(cthread
->name
, name
, MAX_NAME_LEN
))
2521 error("Can't read next thread's name at 0x%x.", cthread
->name
);
2523 cthread
->name
= name
;
2527 /* insert in front */
2528 cproc_copy
->next
= cproc_head
;
2529 cproc_head
= cproc_copy
;
2534 #ifndef FETCH_CPROC_STATE
2536 * Check if your machine does not grok the way this routine
2537 * fetches the FP,PC and SP of a cproc that is not
2538 * currently attached to any kernel thread (e.g. its cproc.context
2539 * field points to the place in stack where the context
2542 * If it doesn't, define your own routine.
2544 #define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2547 mach3_cproc_state (mthread
)
2548 gdb_thread_t mthread
;
2552 if (! mthread
|| !mthread
->cproc
|| !mthread
->cproc
->context
)
2555 context
= extract_signed_integer
2556 (mthread
->cproc
->raw_cproc
+ CPROC_CONTEXT_OFFSET
,
2557 CPROC_CONTEXT_SIZE
);
2559 mthread
->sp
= context
+ MACHINE_CPROC_SP_OFFSET
;
2561 if (mach3_read_inferior (context
+ MACHINE_CPROC_PC_OFFSET
,
2563 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2565 warning ("Can't read cproc pc from inferior");
2569 if (mach3_read_inferior (context
+ MACHINE_CPROC_FP_OFFSET
,
2571 sizeof (CORE_ADDR
)) != sizeof (CORE_ADDR
))
2573 warning ("Can't read cproc fp from inferior");
2579 #endif /* FETCH_CPROC_STATE */
2583 thread_list_command()
2585 thread_basic_info_data_t ths
;
2587 gdb_thread_t cprocs
;
2595 mach_port_t mid_or_port
;
2596 gdb_thread_t their_threads
;
2597 gdb_thread_t kthread
;
2601 char *fmt
= "There are %d kernel threads in task %d.\n";
2603 int tmid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
2605 MACH_ERROR_NO_INFERIOR
;
2607 thread_count
= fetch_thread_info (inferior_task
,
2609 if (thread_count
== -1)
2612 if (thread_count
== 1)
2613 fmt
= "There is %d kernel thread in task %d.\n";
2615 printf_filtered (fmt
, thread_count
, tmid
);
2617 puts_filtered (TL_HEADER
);
2619 cprocs
= get_cprocs();
2621 map_cprocs_to_kernel_threads (cprocs
, their_threads
, thread_count
);
2623 for (scan
= cprocs
; scan
; scan
= scan
->next
)
2631 /* a wired cproc? */
2632 wired
= (extract_address (scan
->raw_cproc
+ CPROC_WIRED_OFFSET
,
2636 if (scan
->reverse_map
!= -1)
2637 kthread
= (their_threads
+ scan
->reverse_map
);
2643 /* These cprocs have a kernel thread */
2645 mid
= map_port_name_to_mid (kthread
->name
, MACH_TYPE_THREAD
);
2647 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2649 ret
= thread_info (kthread
->name
,
2651 (thread_info_t
)&ths
,
2654 if (ret
!= KERN_SUCCESS
)
2656 warning ("Unable to get basic info on thread %d : %s",
2658 mach_error_string (ret
));
2662 /* Who is the first to have more than 100 threads */
2663 sprintf (slot
, "%d", kthread
->slotid
%100);
2665 if (kthread
->name
== current_thread
)
2668 if (ths
.suspend_count
)
2669 sprintf (buf
, "%d", ths
.suspend_count
);
2674 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2678 if (ths
.flags
& TH_FLAGS_IDLE
)
2681 /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
2682 printf_filtered (TL_FORMAT
,
2686 get_thread_name (scan
, kthread
->slotid
),
2687 kthread
->in_emulator
? "E" : "",
2688 translate_state (ths
.run_state
),
2690 translate_cstate (scan
->state
),
2692 print_tl_address (gdb_stdout
, kthread
->pc
);
2696 /* These cprocs don't have a kernel thread.
2697 * find out the calling frame with
2698 * FETCH_CPROC_STATE.
2701 struct gdb_thread state
;
2704 /* jtv -> emcmanus: why do you want this here? */
2705 if (scan
->incarnation
== NULL
)
2706 continue; /* EMcM */
2709 /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
2710 printf_filtered (TL_FORMAT
,
2712 -neworder
, /* Pseudo MID */
2714 get_thread_name (scan
, -neworder
),
2716 "-", /* kernel state */
2718 translate_cstate (scan
->state
),
2722 if (FETCH_CPROC_STATE (&state
) == -1)
2723 puts_filtered ("???");
2725 print_tl_address (gdb_stdout
, state
.pc
);
2729 puts_filtered ("\n");
2732 /* Scan for kernel threads without cprocs */
2733 for (index
= 0; index
< thread_count
; index
++)
2735 if (! their_threads
[index
].cproc
)
2742 mach_port_t name
= their_threads
[index
].name
;
2744 mid
= map_port_name_to_mid (name
, MACH_TYPE_THREAD
);
2746 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2748 ret
= thread_info(name
,
2750 (thread_info_t
)&ths
,
2753 if (ret
!= KERN_SUCCESS
)
2755 warning ("Unable to get basic info on thread %d : %s",
2757 mach_error_string (ret
));
2761 sprintf (slot
, "%d", index
%100);
2763 if (name
== current_thread
)
2768 if (ths
.suspend_count
)
2769 sprintf (buf
, "%d", ths
.suspend_count
);
2774 if (ths
.flags
& TH_FLAGS_SWAPPED
)
2778 if (ths
.flags
& TH_FLAGS_IDLE
)
2781 /* FIXME: May run afloul of arbitrary limit in printf_filtered. */
2782 printf_filtered (TL_FORMAT
,
2786 get_thread_name (NULL
, index
),
2787 their_threads
[index
].in_emulator
? "E" : "",
2788 translate_state (ths
.run_state
),
2790 "", /* No cproc state */
2791 ""); /* Can't be wired */
2792 print_tl_address (gdb_stdout
, their_threads
[index
].pc
);
2793 puts_filtered ("\n");
2797 obstack_free (cproc_obstack
, 0);
2798 obstack_init (cproc_obstack
);
2802 thread_select_command(args
, from_tty
)
2807 thread_array_t thread_list
;
2812 MACH_ERROR_NO_INFERIOR
;
2815 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2817 while (*args
== ' ' || *args
== '\t')
2829 if (!is_slot
|| *args
!= '0') /* Rudimentary checks */
2830 error ("You must select threads by MID or @SLOTNUMBER");
2832 if (select_thread (inferior_task
, mid
, is_slot
?2:1) != KERN_SUCCESS
)
2836 printf_filtered ("Thread %d selected\n",
2837 is_slot
? map_port_name_to_mid (current_thread
,
2838 MACH_TYPE_THREAD
) : mid
);
2841 thread_trace (thread
, set
)
2845 int flavor
= TRACE_FLAVOR
;
2846 unsigned int stateCnt
= TRACE_FLAVOR_SIZE
;
2848 thread_state_data_t state
;
2850 if (! MACH_PORT_VALID (thread
))
2852 warning ("thread_trace: invalid thread");
2856 if (must_suspend_thread
)
2857 setup_thread (thread
, 1);
2859 ret
= thread_get_state(thread
, flavor
, state
, &stateCnt
);
2860 CHK ("thread_trace: error reading thread state", ret
);
2864 TRACE_SET (thread
, state
);
2868 if (! TRACE_CLEAR (thread
, state
))
2870 if (must_suspend_thread
)
2871 setup_thread (thread
, 0);
2876 ret
= thread_set_state(thread
, flavor
, state
, stateCnt
);
2877 CHK ("thread_trace: error writing thread state", ret
);
2878 if (must_suspend_thread
)
2879 setup_thread (thread
, 0);
2882 #ifdef FLUSH_INFERIOR_CACHE
2884 /* When over-writing code on some machines the I-Cache must be flushed
2885 explicitly, because it is not kept coherent by the lazy hardware.
2886 This definitely includes breakpoints, for instance, or else we
2887 end up looping in mysterious Bpt traps */
2889 flush_inferior_icache(pc
, amount
)
2892 vm_machine_attribute_val_t flush
= MATTR_VAL_ICACHE_FLUSH
;
2895 ret
= vm_machine_attribute (inferior_task
,
2900 if (ret
!= KERN_SUCCESS
)
2901 warning ("Error flushing inferior's cache : %s",
2902 mach_error_string (ret
));
2904 #endif FLUSH_INFERIOR_CACHE
2908 suspend_all_threads (from_tty
)
2912 thread_array_t thread_list
;
2913 int thread_count
, index
;
2915 thread_basic_info_data_t th_info
;
2918 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
2919 if (ret
!= KERN_SUCCESS
)
2921 warning ("Could not suspend inferior threads.");
2923 return_to_top_level ();
2926 for (index
= 0; index
< thread_count
; index
++)
2930 mid
= map_port_name_to_mid (thread_list
[ index
],
2933 ret
= thread_suspend(thread_list
[ index
]);
2935 if (ret
!= KERN_SUCCESS
)
2936 warning ("Error trying to suspend thread %d : %s",
2937 mid
, mach_error_string (ret
));
2941 infoCnt
= THREAD_BASIC_INFO_COUNT
;
2942 ret
= thread_info (thread_list
[ index
],
2944 (thread_info_t
) &th_info
,
2946 CHK ("suspend can't get thread info", ret
);
2948 warning ("Thread %d suspend count is %d",
2949 mid
, th_info
.suspend_count
);
2953 consume_send_rights (thread_list
, thread_count
);
2954 ret
= vm_deallocate(mach_task_self(),
2955 (vm_address_t
)thread_list
,
2956 (thread_count
* sizeof(int)));
2957 CHK ("Error trying to deallocate thread list", ret
);
2961 thread_suspend_command (args
, from_tty
)
2967 mach_port_t saved_thread
;
2969 thread_basic_info_data_t th_info
;
2971 MACH_ERROR_NO_INFERIOR
;
2973 if (!strcasecmp (args
, "all")) {
2974 suspend_all_threads (from_tty
);
2978 saved_thread
= current_thread
;
2980 mid
= parse_thread_id (args
, 0, 0);
2983 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
2986 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
2988 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
2991 current_thread
= saved_thread
;
2992 error ("Could not select thread %d", mid
);
2995 ret
= thread_suspend (current_thread
);
2996 if (ret
!= KERN_SUCCESS
)
2997 warning ("thread_suspend failed : %s",
2998 mach_error_string (ret
));
3000 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3001 ret
= thread_info (current_thread
,
3003 (thread_info_t
) &th_info
,
3005 CHK ("suspend can't get thread info", ret
);
3007 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3009 current_thread
= saved_thread
;
3012 resume_all_threads (from_tty
)
3016 thread_array_t thread_list
;
3017 int thread_count
, index
;
3020 thread_basic_info_data_t th_info
;
3022 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
3023 if (ret
!= KERN_SUCCESS
)
3026 error("task_threads", mach_error_string( ret
));
3029 for (index
= 0; index
< thread_count
; index
++)
3031 infoCnt
= THREAD_BASIC_INFO_COUNT
;
3032 ret
= thread_info (thread_list
[ index
],
3034 (thread_info_t
) &th_info
,
3036 CHK ("resume_all can't get thread info", ret
);
3038 mid
= map_port_name_to_mid (thread_list
[ index
],
3041 if (! th_info
.suspend_count
)
3043 if (mid
!= -1 && from_tty
)
3044 warning ("Thread %d is not suspended", mid
);
3048 ret
= thread_resume (thread_list
[ index
]);
3050 if (ret
!= KERN_SUCCESS
)
3051 warning ("Error trying to resume thread %d : %s",
3052 mid
, mach_error_string (ret
));
3053 else if (mid
!= -1 && from_tty
)
3054 warning ("Thread %d suspend count is %d",
3055 mid
, --th_info
.suspend_count
);
3058 consume_send_rights (thread_list
, thread_count
);
3059 ret
= vm_deallocate(mach_task_self(),
3060 (vm_address_t
)thread_list
,
3061 (thread_count
* sizeof(int)));
3062 CHK("Error trying to deallocate thread list", ret
);
3066 thread_resume_command (args
, from_tty
)
3071 mach_port_t saved_thread
;
3073 thread_basic_info_data_t th_info
;
3074 int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3076 MACH_ERROR_NO_INFERIOR
;
3078 if (!strcasecmp (args
, "all")) {
3079 resume_all_threads (from_tty
);
3083 saved_thread
= current_thread
;
3085 mid
= parse_thread_id (args
, 0, 0);
3088 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3091 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3093 if (select_thread (inferior_task
, mid
, 0) != KERN_SUCCESS
)
3096 current_thread
= saved_thread
;
3097 return_to_top_level ();
3100 ret
= thread_info (current_thread
,
3102 (thread_info_t
) &th_info
,
3104 CHK ("resume can't get thread info", ret
);
3106 if (! th_info
.suspend_count
)
3108 warning ("Thread %d is not suspended", mid
);
3112 ret
= thread_resume (current_thread
);
3113 if (ret
!= KERN_SUCCESS
)
3114 warning ("thread_resume failed : %s",
3115 mach_error_string (ret
));
3118 th_info
.suspend_count
--;
3119 warning ("Thread %d suspend count is %d", mid
, th_info
.suspend_count
);
3123 current_thread
= saved_thread
;
3127 thread_kill_command (args
, from_tty
)
3134 thread_array_t thread_table
;
3136 mach_port_t thread_to_kill
= MACH_PORT_NULL
;
3139 MACH_ERROR_NO_INFERIOR
;
3142 error_no_arg ("thread mid to kill from the inferior task");
3144 mid
= parse_thread_id (args
, 0, 0);
3147 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3151 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &thread_to_kill
);
3152 CHK ("thread_kill_command: machid_mach_port map failed", ret
);
3155 mid
= map_port_name_to_mid (current_thread
, MACH_TYPE_THREAD
);
3157 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3158 ret
= task_threads (inferior_task
, &thread_table
, &thread_count
);
3159 CHK ("Error getting inferior's thread list", ret
);
3161 if (thread_to_kill
== current_thread
)
3163 ret
= thread_terminate (thread_to_kill
);
3164 CHK ("Thread could not be terminated", ret
);
3166 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
3167 warning ("Last thread was killed, use \"kill\" command to kill task");
3170 for (index
= 0; index
< thread_count
; index
++)
3171 if (thread_table
[ index
] == thread_to_kill
)
3173 ret
= thread_terminate (thread_to_kill
);
3174 CHK ("Thread could not be terminated", ret
);
3177 if (thread_count
> 1)
3178 consume_send_rights (thread_table
, thread_count
);
3180 ret
= vm_deallocate (mach_task_self(), (vm_address_t
)thread_table
,
3181 (thread_count
* sizeof(mach_port_t
)));
3182 CHK ("Error trying to deallocate thread list", ret
);
3184 warning ("Thread %d killed", mid
);
3188 /* Task specific commands; add more if you like */
3191 task_resume_command (args
, from_tty
)
3196 task_basic_info_data_t ta_info
;
3197 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3198 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3200 MACH_ERROR_NO_INFERIOR
;
3202 /* Would be trivial to change, but is it desirable? */
3204 error ("Currently gdb can resume only it's inferior task");
3206 ret
= task_info (inferior_task
,
3208 (task_info_t
) &ta_info
,
3210 CHK ("task_resume_command: task_info failed", ret
);
3212 if (ta_info
.suspend_count
== 0)
3213 error ("Inferior task %d is not suspended", mid
);
3214 else if (ta_info
.suspend_count
== 1 &&
3216 !query ("Suspend count is now 1. Do you know what you are doing? "))
3217 error ("Task not resumed");
3219 ret
= task_resume (inferior_task
);
3220 CHK ("task_resume_command: task_resume", ret
);
3222 if (ta_info
.suspend_count
== 1)
3224 warning ("Inferior task %d is no longer suspended", mid
);
3225 must_suspend_thread
= 1;
3226 /* @@ This is not complete: Registers change all the time when not
3228 registers_changed ();
3231 warning ("Inferior task %d suspend count is now %d",
3232 mid
, ta_info
.suspend_count
-1);
3237 task_suspend_command (args
, from_tty
)
3242 task_basic_info_data_t ta_info
;
3243 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3244 int mid
= map_port_name_to_mid (inferior_task
, MACH_TYPE_TASK
);
3246 MACH_ERROR_NO_INFERIOR
;
3248 /* Would be trivial to change, but is it desirable? */
3250 error ("Currently gdb can suspend only it's inferior task");
3252 ret
= task_suspend (inferior_task
);
3253 CHK ("task_suspend_command: task_suspend", ret
);
3255 must_suspend_thread
= 0;
3257 ret
= task_info (inferior_task
,
3259 (task_info_t
) &ta_info
,
3261 CHK ("task_suspend_command: task_info failed", ret
);
3263 warning ("Inferior task %d suspend count is now %d",
3264 mid
, ta_info
.suspend_count
);
3271 static char size
[ 30 ];
3272 int zz
= bytes
/1024;
3275 sprintf (size
, "%-2.1f M", ((float)bytes
)/(1024.0*1024.0));
3277 sprintf (size
, "%d K", zz
);
3282 /* Does this require the target task to be suspended?? I don't think so. */
3284 task_info_command (args
, from_tty
)
3291 task_basic_info_data_t ta_info
;
3292 int infoCnt
= TASK_BASIC_INFO_COUNT
;
3293 int page_size
= round_page(1);
3294 int thread_count
= 0;
3296 if (MACH_PORT_VALID (inferior_task
))
3297 mid
= map_port_name_to_mid (inferior_task
,
3300 task
= inferior_task
;
3304 int tmid
= atoi (args
);
3307 error ("Invalid mid %d for task info", tmid
);
3312 ret
= machid_mach_port (mid_server
, mid_auth
, tmid
, &task
);
3313 CHK ("task_info_command: machid_mach_port map failed", ret
);
3318 error ("You have to give the task MID as an argument");
3320 ret
= task_info (task
,
3322 (task_info_t
) &ta_info
,
3324 CHK ("task_info_command: task_info failed", ret
);
3326 printf_filtered ("\nTask info for task %d:\n\n", mid
);
3327 printf_filtered (" Suspend count : %d\n", ta_info
.suspend_count
);
3328 printf_filtered (" Base priority : %d\n", ta_info
.base_priority
);
3329 printf_filtered (" Virtual size : %s\n", get_size (ta_info
.virtual_size
));
3330 printf_filtered (" Resident size : %s\n", get_size (ta_info
.resident_size
));
3333 thread_array_t thread_list
;
3335 ret
= task_threads (task
, &thread_list
, &thread_count
);
3336 CHK ("task_info_command: task_threads", ret
);
3338 printf_filtered (" Thread count : %d\n", thread_count
);
3340 consume_send_rights (thread_list
, thread_count
);
3341 ret
= vm_deallocate(mach_task_self(),
3342 (vm_address_t
)thread_list
,
3343 (thread_count
* sizeof(int)));
3344 CHK("Error trying to deallocate thread list", ret
);
3346 if (have_emulator_p (task
))
3347 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3348 EMULATOR_BASE
, EMULATOR_END
);
3350 printf_filtered (" No emulator.\n");
3352 if (thread_count
&& task
== inferior_task
)
3353 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3356 /* You may either FORWARD the exception to the inferior, or KEEP
3357 * it and return to GDB command level.
3359 * exception mid [ forward | keep ]
3363 exception_command (args
, from_tty
)
3372 error_no_arg ("exception number action");
3374 while (*scan
== ' ' || *scan
== '\t') scan
++;
3376 if ('0' <= *scan
&& *scan
<= '9')
3377 while ('0' <= *scan
&& *scan
<= '9')
3380 error ("exception number action");
3382 exception
= atoi (args
);
3383 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3384 error ("Allowed exception numbers are in range 1..%d",
3387 if (*scan
!= ' ' && *scan
!= '\t')
3388 error ("exception number must be followed by a space");
3390 while (*scan
== ' ' || *scan
== '\t') scan
++;
3401 error("exception number action");
3403 if (!strncasecmp (args
, "forward", len
))
3404 exception_map
[ exception
].forward
= TRUE
;
3405 else if (!strncasecmp (args
, "keep", len
))
3406 exception_map
[ exception
].forward
= FALSE
;
3408 error ("exception action is either \"keep\" or \"forward\"");
3412 print_exception_info (exception
)
3415 boolean_t forward
= exception_map
[ exception
].forward
;
3417 printf_filtered ("%s\t(%d): ", exception_map
[ exception
].name
,
3420 if (exception_map
[ exception
].sigmap
!= SIG_UNKNOWN
)
3421 printf_filtered ("keep and handle as signal %d\n",
3422 exception_map
[ exception
].sigmap
);
3424 printf_filtered ("keep and handle as unknown signal %d\n",
3425 exception_map
[ exception
].sigmap
);
3427 printf_filtered ("forward exception to inferior\n");
3431 exception_info (args
, from_tty
)
3438 for (exception
= 1; exception
<= MAX_EXCEPTION
; exception
++)
3439 print_exception_info (exception
);
3442 exception
= atoi (args
);
3444 if (exception
<= 0 || exception
> MAX_EXCEPTION
)
3445 error ("Invalid exception number, values from 1 to %d allowed",
3447 print_exception_info (exception
);
3451 /* Check for actions for mach exceptions.
3453 mach3_exception_actions (w
, force_print_only
, who
)
3455 boolean_t force_print_only
;
3458 boolean_t force_print
= FALSE
;
3461 if (force_print_only
||
3462 exception_map
[stop_exception
].sigmap
== SIG_UNKNOWN
)
3465 WSETSTOP (*w
, exception_map
[stop_exception
].sigmap
);
3467 if (exception_map
[stop_exception
].print
|| force_print
)
3469 int giveback
= grab_terminal ();
3471 printf_filtered ("\n%s received %s exception : ",
3473 exception_map
[stop_exception
].name
);
3477 switch(stop_exception
) {
3478 case EXC_BAD_ACCESS
:
3479 printf_filtered ("referencing address 0x%x : %s\n",
3481 mach_error_string (stop_code
));
3483 case EXC_BAD_INSTRUCTION
:
3485 ("illegal or undefined instruction. code %d subcode %d\n",
3486 stop_code
, stop_subcode
);
3488 case EXC_ARITHMETIC
:
3489 printf_filtered ("code %d\n", stop_code
);
3492 printf_filtered ("code %d subcode %d\n", stop_code
, stop_subcode
);
3495 printf_filtered ("%s specific, code 0x%x\n",
3496 stop_code
< 0xffff ? "hardware" : "os emulation",
3499 case EXC_BREAKPOINT
:
3500 printf_filtered ("type %d (machine dependent)\n",
3504 fatal ("Unknown exception");
3508 terminal_inferior ();
3512 setup_notify_port (create_new
)
3517 if (MACH_PORT_VALID (our_notify_port
))
3519 ret
= mach_port_destroy (mach_task_self (), our_notify_port
);
3520 CHK ("Could not destroy our_notify_port", ret
);
3523 our_notify_port
= MACH_PORT_NULL
;
3524 notify_chain
= (port_chain_t
) NULL
;
3525 port_chain_destroy (port_chain_obstack
);
3529 ret
= mach_port_allocate (mach_task_self(),
3530 MACH_PORT_RIGHT_RECEIVE
,
3532 if (ret
!= KERN_SUCCESS
)
3533 fatal("Creating notify port %s", mach_error_string(ret
));
3535 ret
= mach_port_move_member(mach_task_self(),
3537 inferior_wait_port_set
);
3538 if (ret
!= KERN_SUCCESS
)
3539 fatal("initial move member %s",mach_error_string(ret
));
3544 * Register our message port to the net name server
3546 * Currently used only by the external stop-gdb program
3547 * since ^C does not work if you would like to enter
3548 * gdb command level while debugging your program.
3550 * NOTE: If the message port is sometimes used for other
3551 * purposes also, the NAME must not be a guessable one.
3552 * Then, there should be a way to change it.
3555 char registered_name
[ MAX_NAME_LEN
];
3558 message_port_info (args
, from_tty
)
3562 if (registered_name
[0])
3563 printf_filtered ("gdb's message port name: '%s'\n",
3566 printf_filtered ("gdb's message port is not currently registered\n");
3570 gdb_register_port (name
, port
)
3575 static int already_signed
= 0;
3578 if (! MACH_PORT_VALID (port
) || !name
|| !*name
)
3580 warning ("Invalid registration request");
3584 if (! already_signed
)
3586 ret
= mach_port_insert_right (mach_task_self (),
3589 MACH_MSG_TYPE_MAKE_SEND
);
3590 CHK ("Failed to create a signature to our_message_port", ret
);
3593 else if (already_signed
> 1)
3595 ret
= netname_check_out (name_server_port
,
3598 CHK ("Failed to check out gdb's message port", ret
);
3599 registered_name
[0] = '\000';
3603 ret
= netname_check_in (name_server_port
, /* Name server port */
3604 name
, /* Name of service */
3605 our_message_port
, /* Signature */
3606 port
); /* Creates a new send right */
3607 CHK("Failed to check in the port", ret
);
3610 while(len
< MAX_NAME_LEN
&& *(name
+len
))
3612 registered_name
[len
] = *(name
+len
);
3615 registered_name
[len
] = '\000';
3619 struct cmd_list_element
*cmd_thread_list
;
3620 struct cmd_list_element
*cmd_task_list
;
3624 thread_command (arg
, from_tty
)
3628 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3629 help_list (cmd_thread_list
, "thread ", -1, gdb_stdout
);
3634 task_command (arg
, from_tty
)
3638 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3639 help_list (cmd_task_list
, "task ", -1, gdb_stdout
);
3642 add_mach_specific_commands ()
3644 extern void condition_thread ();
3646 /* Thread handling commands */
3648 /* FIXME: Move our thread support into the generic thread.c stuff so we
3649 can share that code. */
3650 add_prefix_cmd ("mthread", class_stack
, thread_command
,
3651 "Generic command for handling Mach threads in the debugged task.",
3652 &cmd_thread_list
, "thread ", 0, &cmdlist
);
3654 add_com_alias ("th", "mthread", class_stack
, 1);
3656 add_cmd ("select", class_stack
, thread_select_command
,
3657 "Select and print MID of the selected thread",
3659 add_cmd ("list", class_stack
, thread_list_command
,
3660 "List info of task's threads. Selected thread is marked with '*'",
3662 add_cmd ("suspend", class_run
, thread_suspend_command
,
3663 "Suspend one or all of the threads in the selected task.",
3665 add_cmd ("resume", class_run
, thread_resume_command
,
3666 "Resume one or all of the threads in the selected task.",
3668 add_cmd ("kill", class_run
, thread_kill_command
,
3669 "Kill the specified thread MID from inferior task.",
3671 add_cmd ("break", class_breakpoint
, condition_thread
,
3672 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3673 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3675 /* Thread command shorthands (for backward compatibility) */
3676 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist
);
3677 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist
);
3679 /* task handling commands */
3681 add_prefix_cmd ("task", class_stack
, task_command
,
3682 "Generic command for handling debugged task.",
3683 &cmd_task_list
, "task ", 0, &cmdlist
);
3685 add_com_alias ("ta", "task", class_stack
, 1);
3687 add_cmd ("suspend", class_run
, task_suspend_command
,
3688 "Suspend the inferior task.",
3690 add_cmd ("resume", class_run
, task_resume_command
,
3691 "Resume the inferior task.",
3693 add_cmd ("info", no_class
, task_info_command
,
3694 "Print information about the specified task.",
3697 /* Print my message port name */
3699 add_info ("message-port", message_port_info
,
3700 "Returns the name of gdb's message port in the netnameserver");
3702 /* Exception commands */
3704 add_info ("exceptions", exception_info
,
3705 "What debugger does when program gets various exceptions.\n\
3706 Specify an exception number as argument to print info on that\n\
3709 add_com ("exception", class_run
, exception_command
,
3710 "Specify how to handle an exception.\n\
3711 Args are exception number followed by \"forward\" or \"keep\".\n\
3712 `Forward' means forward the exception to the program's normal exception\n\
3714 `Keep' means reenter debugger if this exception happens, and GDB maps\n\
3715 the exception to some signal (see info exception)\n\
3716 Normally \"keep\" is used to return to GDB on exception.");
3720 do_mach_notify_dead_name (notify
, name
)
3724 kern_return_t kr
= KERN_SUCCESS
;
3726 /* Find the thing that notified */
3727 port_chain_t element
= port_chain_member (notify_chain
, name
);
3729 /* Take name of from unreceived dead name notification list */
3730 notify_chain
= port_chain_delete (notify_chain
, name
);
3733 error ("Received a dead name notify from unchained port (0x%x)", name
);
3735 switch (element
->type
) {
3737 case MACH_TYPE_THREAD
:
3738 target_terminal_ours_for_output ();
3739 if (name
== current_thread
)
3741 printf_filtered ("\nCurrent thread %d died", element
->mid
);
3742 current_thread
= MACH_PORT_NULL
;
3745 printf_filtered ("\nThread %d died", element
->mid
);
3749 case MACH_TYPE_TASK
:
3750 target_terminal_ours_for_output ();
3751 if (name
!= inferior_task
)
3752 printf_filtered ("Task %d died, but it was not the selected task",
3756 printf_filtered ("Current task %d died", element
->mid
);
3758 mach_port_destroy (mach_task_self(), name
);
3759 inferior_task
= MACH_PORT_NULL
;
3762 warning ("There were still unreceived dead_name_notifications???");
3764 /* Destroy the old notifications */
3765 setup_notify_port (0);
3771 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3772 name
, element
->type
, element
->mid
);
3776 return KERN_SUCCESS
;
3780 do_mach_notify_msg_accepted (notify
, name
)
3784 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3786 return KERN_SUCCESS
;
3790 do_mach_notify_no_senders (notify
, mscount
)
3792 mach_port_mscount_t mscount
;
3794 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3796 return KERN_SUCCESS
;
3800 do_mach_notify_port_deleted (notify
, name
)
3804 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3806 return KERN_SUCCESS
;
3810 do_mach_notify_port_destroyed (notify
, rights
)
3814 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3816 return KERN_SUCCESS
;
3820 do_mach_notify_send_once (notify
)
3824 /* MANY of these are generated. */
3825 warning ("do_mach_notify_send_once : notify %x",
3828 return KERN_SUCCESS
;
3831 /* Kills the inferior. It's gone when you call this */
3833 kill_inferior_fast ()
3837 if (inferior_pid
== 0 || inferior_pid
== 1)
3840 /* kill() it, since the Unix server does not otherwise notice when
3841 * killed with task_terminate().
3843 if (inferior_pid
> 0)
3844 kill (inferior_pid
, SIGKILL
);
3846 /* It's propably terminate already */
3847 (void) task_terminate (inferior_task
);
3849 inferior_task
= MACH_PORT_NULL
;
3850 current_thread
= MACH_PORT_NULL
;
3852 wait3 (&w
, WNOHANG
, 0);
3854 setup_notify_port (0);
3860 kill_inferior_fast ();
3861 target_mourn_inferior ();
3864 /* Clean up after the inferior dies. */
3867 m3_mourn_inferior ()
3869 unpush_target (&m3_ops
);
3870 generic_mourn_inferior ();
3874 /* Fork an inferior process, and start debugging it. */
3877 m3_create_inferior (exec_file
, allargs
, env
)
3882 fork_inferior (exec_file
, allargs
, env
, m3_trace_m3
, m3_trace_him
);
3883 /* We are at the first instruction we care about. */
3884 /* Pedal to the metal... */
3885 proceed ((CORE_ADDR
) -1, 0, 0);
3888 /* Mark our target-struct as eligible for stray "run" and "attach"
3896 /* Mach 3.0 does not need ptrace for anything
3897 * Make sure nobody uses it on mach.
3902 error ("Lose, Lose! Somebody called ptrace\n");
3905 /* Resume execution of the inferior process.
3906 If STEP is nonzero, single-step it.
3907 If SIGNAL is nonzero, give it that signal. */
3910 m3_resume (pid
, step
, signal
)
3913 enum target_signal signal
;
3919 thread_basic_info_data_t th_info
;
3920 unsigned int infoCnt
= THREAD_BASIC_INFO_COUNT
;
3922 /* There is no point in single stepping when current_thread
3925 if (! MACH_PORT_VALID (current_thread
))
3926 error ("No thread selected; can not single step");
3928 /* If current_thread is suspended, tracing it would never return.
3930 ret
= thread_info (current_thread
,
3932 (thread_info_t
) &th_info
,
3934 CHK ("child_resume: can't get thread info", ret
);
3936 if (th_info
.suspend_count
)
3937 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3940 vm_read_cache_valid
= FALSE
;
3942 if (signal
&& inferior_pid
> 0) /* Do not signal, if attached by MID */
3943 kill (inferior_pid
, target_signal_to_host (signal
));
3947 suspend_all_threads (0);
3949 setup_single_step (current_thread
, TRUE
);
3951 ret
= thread_resume (current_thread
);
3952 CHK ("thread_resume", ret
);
3955 ret
= task_resume (inferior_task
);
3956 if (ret
== KERN_FAILURE
)
3957 warning ("Task was not suspended");
3959 CHK ("Resuming task", ret
);
3961 /* HACK HACK This is needed by the multiserver system HACK HACK */
3962 while ((ret
= task_resume(inferior_task
)) == KERN_SUCCESS
)
3963 /* make sure it really runs */;
3964 /* HACK HACK This is needed by the multiserver system HACK HACK */
3967 #ifdef ATTACH_DETACH
3969 /* Start debugging the process with the given task */
3975 inferior_task
= tid
;
3977 ret
= task_suspend (inferior_task
);
3978 CHK("task_attach: task_suspend", ret
);
3980 must_suspend_thread
= 0;
3982 setup_notify_port (1);
3984 request_notify (inferior_task
, MACH_NOTIFY_DEAD_NAME
, MACH_TYPE_TASK
);
3986 setup_exception_port ();
3988 emulator_present
= have_emulator_p (inferior_task
);
3993 /* Well, we can call error also here and leave the
3994 * target stack inconsistent. Sigh.
3995 * Fix this sometime (the only way to fail here is that
3996 * the task has no threads at all, which is rare, but
3997 * possible; or if the target task has died, which is also
3998 * possible, but unlikely, since it has been suspended.
3999 * (Someone must have killed it))
4004 if (select_thread (inferior_task
, 0, 1) != KERN_SUCCESS
)
4005 error ("Could not select any threads to attach to");
4013 ret
= machid_mach_port (mid_server
, mid_auth
, mid
, &inferior_task
);
4014 CHK("mid_attach: machid_mach_port", ret
);
4016 task_attach (inferior_task
);
4022 * Start debugging the process whose unix process-id is PID.
4023 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
4025 * Prevent (possible unwanted) dangerous operations by enabled users
4026 * like "atta 0" or "atta foo" (equal to the previous :-) and
4027 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4036 error("MID=0, Debugging the master unix server does not compute");
4038 /* Foo. This assumes gdb has a unix pid */
4039 if (pid
== getpid())
4040 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4044 mid_attach (-(pid
));
4046 /* inferior_pid will be NEGATIVE! */
4049 return inferior_pid
;
4052 inferior_task
= task_by_pid (pid
);
4053 if (! MACH_PORT_VALID (inferior_task
))
4054 error("Cannot map Unix pid %d to Mach task port", pid
);
4056 task_attach (inferior_task
);
4060 return inferior_pid
;
4063 /* Attach to process PID, then initialize for debugging it
4064 and wait for the trace-trap that results from attaching. */
4067 m3_attach (args
, from_tty
)
4075 error_no_arg ("process-id to attach");
4079 if (pid
== getpid()) /* Trying to masturbate? */
4080 error ("I refuse to debug myself!");
4084 exec_file
= (char *) get_exec_file (0);
4087 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file
, target_pid_to_str (pid
));
4089 printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid
));
4091 gdb_flush (gdb_stdout
);
4096 push_target (&procfs_ops
);
4100 deallocate_inferior_ports ()
4103 thread_array_t thread_list
;
4104 int thread_count
, index
;
4106 if (!MACH_PORT_VALID (inferior_task
))
4109 ret
= task_threads (inferior_task
, &thread_list
, &thread_count
);
4110 if (ret
!= KERN_SUCCESS
)
4112 warning ("deallocate_inferior_ports: task_threads",
4113 mach_error_string(ret
));
4117 /* Get rid of send rights to task threads */
4118 for (index
= 0; index
< thread_count
; index
++)
4121 ret
= mach_port_get_refs (mach_task_self (),
4123 MACH_PORT_RIGHT_SEND
,
4125 CHK("deallocate_inferior_ports: get refs", ret
);
4129 ret
= mach_port_mod_refs (mach_task_self (),
4131 MACH_PORT_RIGHT_SEND
,
4133 CHK("deallocate_inferior_ports: mod refs", ret
);
4137 ret
= mach_port_mod_refs (mach_task_self (),
4138 inferior_exception_port
,
4139 MACH_PORT_RIGHT_RECEIVE
,
4141 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret
);
4143 ret
= mach_port_deallocate (mach_task_self (),
4145 CHK ("deallocate_task_port: deallocating inferior_task", ret
);
4147 current_thread
= MACH_PORT_NULL
;
4148 inferior_task
= MACH_PORT_NULL
;
4151 /* Stop debugging the process whose number is PID
4152 and continue it with signal number SIGNAL.
4153 SIGNAL = 0 means just continue it. */
4156 m3_do_detach (signal
)
4161 MACH_ERROR_NO_INFERIOR
;
4163 if (current_thread
!= MACH_PORT_NULL
)
4165 /* Store the gdb's view of the thread we are deselecting
4167 * @@ I am really not sure if this is ever needeed.
4169 target_prepare_to_store ();
4170 target_store_registers (-1);
4173 ret
= task_set_special_port (inferior_task
,
4174 TASK_EXCEPTION_PORT
,
4175 inferior_old_exception_port
);
4176 CHK ("task_set_special_port", ret
);
4178 /* Discard all requested notifications */
4179 setup_notify_port (0);
4181 if (remove_breakpoints ())
4182 warning ("Could not remove breakpoints when detaching");
4184 if (signal
&& inferior_pid
> 0)
4185 kill (inferior_pid
, signal
);
4187 /* the task might be dead by now */
4188 (void) task_resume (inferior_task
);
4190 deallocate_inferior_ports ();
4195 /* Take a program previously attached to and detaches it.
4196 The program resumes execution and will no longer stop
4197 on signals, etc. We'd better not have left any breakpoints
4198 in the program or it'll die when it hits one. For this
4199 to work, it may be necessary for the process to have been
4200 previously attached. It *might* work if the program was
4201 started via fork. */
4204 m3_detach (args
, from_tty
)
4212 char *exec_file
= get_exec_file (0);
4215 printf_unfiltered ("Detaching from program: %s %s\n",
4216 exec_file
, target_pid_to_str (inferior_pid
));
4217 gdb_flush (gdb_stdout
);
4220 siggnal
= atoi (args
);
4222 m3_do_detach (siggnal
);
4224 unpush_target (&m3_ops
); /* Pop out of handling an inferior */
4226 #endif /* ATTACH_DETACH */
4235 char *bsd1_names
[] = {
4303 int bsd1_nnames
= sizeof(bsd1_names
)/sizeof(bsd1_names
[0]);
4313 case MACH_MSG_TYPE_BOOLEAN
:
4315 case MACH_MSG_TYPE_INTEGER_16
:
4317 case MACH_MSG_TYPE_INTEGER_32
:
4319 case MACH_MSG_TYPE_CHAR
:
4321 case MACH_MSG_TYPE_BYTE
:
4323 case MACH_MSG_TYPE_REAL
:
4325 case MACH_MSG_TYPE_STRING
:
4328 sprintf(buf
,"%d",name
);
4341 if (id
>= 101000 && id
< 101000+bsd1_nnames
) {
4342 if (p
= bsd1_names
[id
-101000])
4346 return "psignal_retry";
4349 sprintf(buf
,"%d",id
);
4354 mach_msg_header_t
*mp
;
4356 char *fmt_x
= "%20s : 0x%08x\n";
4357 char *fmt_d
= "%20s : %10d\n";
4358 char *fmt_s
= "%20s : %s\n";
4361 puts_filtered ("\n");
4362 #define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
4363 pr(fmt_x
,(*mp
),msgh_bits
);
4364 pr(fmt_d
,(*mp
),msgh_size
);
4365 pr(fmt_x
,(*mp
),msgh_remote_port
);
4366 pr(fmt_x
,(*mp
),msgh_local_port
);
4367 pr(fmt_d
,(*mp
),msgh_kind
);
4368 printf_filtered(fmt_s
,STR(msgh_id
),id_str(mp
->msgh_id
,buf
));
4370 if (debug_level
> 1)
4375 ep
= p
+mp
->msgh_size
;
4377 for(; p
< ep
; p
+= plen
) {
4378 mach_msg_type_t
*tp
;
4379 mach_msg_type_long_t
*tlp
;
4380 int name
,size
,number
;
4381 tp
= (mach_msg_type_t
*)p
;
4382 if (tp
->msgt_longform
) {
4383 tlp
= (mach_msg_type_long_t
*)tp
;
4384 name
= tlp
->msgtl_name
;
4385 size
= tlp
->msgtl_size
;
4386 number
= tlp
->msgtl_number
;
4387 plen
= sizeof(*tlp
);
4389 name
= tp
->msgt_name
;
4390 size
= tp
->msgt_size
;
4391 number
= tp
->msgt_number
;
4394 printf_filtered("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4395 name_str(name
,buf
),size
,number
,tp
->msgt_inline
,
4396 tp
->msgt_longform
, tp
->msgt_deallocate
);
4398 if (tp
->msgt_inline
) {
4401 l
= (l
+sizeof(long)-1)&~((sizeof(long))-1);
4403 print_data(dp
,size
,number
);
4405 plen
+= sizeof(int*);
4407 printf_filtered("plen=%d\n",plen
);
4412 print_data(p
,size
,number
)
4423 for(i
= 0; i
< number
; i
++) {
4424 printf_filtered(" %02x",p
[i
]);
4429 for(i
= 0; i
< number
; i
++) {
4430 printf_filtered(" %04x",sp
[i
]);
4435 for(i
= 0; i
< number
; i
++) {
4436 printf_filtered(" %08x",ip
[i
]);
4440 puts_filtered("\n");
4444 struct target_ops m3_ops
= {
4445 "mach", /* to_shortname */
4446 "Mach child process", /* to_longname */
4447 "Mach child process (started by the \"run\" command).", /* to_doc */
4448 ??_open
, /* to_open */
4450 m3_attach
, /* to_attach */
4451 m3_detach
, /* to_detach */
4452 m3_resume
, /* to_resume */
4453 mach_really_wait
, /* to_wait */
4454 fetch_inferior_registers
, /* to_fetch_registers */
4455 store_inferior_registers
, /* to_store_registers */
4456 child_prepare_to_store
, /* to_prepare_to_store */
4457 m3_xfer_memory
, /* to_xfer_memory */
4459 /* FIXME: Should print MID and all that crap. */
4460 child_files_info
, /* to_files_info */
4462 memory_insert_breakpoint
, /* to_insert_breakpoint */
4463 memory_remove_breakpoint
, /* to_remove_breakpoint */
4464 terminal_init_inferior
, /* to_terminal_init */
4465 terminal_inferior
, /* to_terminal_inferior */
4466 terminal_ours_for_output
, /* to_terminal_ours_for_output */
4467 terminal_ours
, /* to_terminal_ours */
4468 child_terminal_info
, /* to_terminal_info */
4469 m3_kill_inferior
, /* to_kill */
4471 0, /* to_lookup_symbol */
4473 m3_create_inferior
, /* to_create_inferior */
4474 m3_mourn_inferior
, /* to_mourn_inferior */
4475 m3_can_run
, /* to_can_run */
4476 0, /* to_notice_signals */
4477 process_stratum
, /* to_stratum */
4479 1, /* to_has_all_memory */
4480 1, /* to_has_memory */
4481 1, /* to_has_stack */
4482 1, /* to_has_registers */
4483 1, /* to_has_execution */
4485 0, /* sections_end */
4486 OPS_MAGIC
/* to_magic */
4490 _initialize_m3_nat ()
4494 add_target (&m3_ops
);
4496 ret
= mach_port_allocate(mach_task_self(),
4497 MACH_PORT_RIGHT_PORT_SET
,
4498 &inferior_wait_port_set
);
4499 if (ret
!= KERN_SUCCESS
)
4500 fatal("initial port set %s",mach_error_string(ret
));
4502 /* mach_really_wait now waits for this */
4503 currently_waiting_for
= inferior_wait_port_set
;
4505 ret
= netname_look_up(name_server_port
, hostname
, "MachID", &mid_server
);
4506 if (ret
!= KERN_SUCCESS
)
4508 mid_server
= MACH_PORT_NULL
;
4510 warning ("initialize machid: netname_lookup_up(MachID) : %s",
4511 mach_error_string(ret
));
4512 warning ("Some (most?) features disabled...");
4515 mid_auth
= mach_privileged_host_port();
4516 if (mid_auth
== MACH_PORT_NULL
)
4517 mid_auth
= mach_task_self();
4519 obstack_init (port_chain_obstack
);
4521 ret
= mach_port_allocate (mach_task_self (),
4522 MACH_PORT_RIGHT_RECEIVE
,
4523 &thread_exception_port
);
4524 CHK ("Creating thread_exception_port for single stepping", ret
);
4526 ret
= mach_port_insert_right (mach_task_self (),
4527 thread_exception_port
,
4528 thread_exception_port
,
4529 MACH_MSG_TYPE_MAKE_SEND
);
4530 CHK ("Inserting send right to thread_exception_port", ret
);
4532 /* Allocate message port */
4533 ret
= mach_port_allocate (mach_task_self (),
4534 MACH_PORT_RIGHT_RECEIVE
,
4536 if (ret
!= KERN_SUCCESS
)
4537 warning ("Creating message port %s", mach_error_string (ret
));
4540 char buf
[ MAX_NAME_LEN
];
4541 ret
= mach_port_move_member(mach_task_self (),
4543 inferior_wait_port_set
);
4544 if (ret
!= KERN_SUCCESS
)
4545 warning ("message move member %s", mach_error_string (ret
));
4548 /* @@@@ No way to change message port name currently */
4549 /* Foo. This assumes gdb has a unix pid */
4550 sprintf (buf
, "gdb-%d", getpid ());
4551 gdb_register_port (buf
, our_message_port
);
4554 /* Heap for thread commands */
4555 obstack_init (cproc_obstack
);
4557 add_mach_specific_commands ();