Phase 1 of the ptid_t changes.
[deliverable/binutils-gdb.git] / gdb / m3-nat.c
CommitLineData
c906108c
SS
1/* Interface GDB to Mach 3.0 operating systems.
2 (Most) Mach 3.0 related routines live in this file.
3
b6ba6518 4 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
8e65ff28 5 Free Software Foundation, Inc.
c906108c 6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
c906108c 13
c5aa993b
JM
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
c906108c 18
c5aa993b
JM
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA. */
c906108c
SS
23
24/*
25 * Author: Jukka Virtanen <jtv@hut.fi>
c5aa993b 26 * Computing Centre
c906108c
SS
27 * Helsinki University of Technology
28 * Finland
29 *
30 * Thanks to my friends who helped with ideas and testing:
31 *
c5aa993b
JM
32 * Johannes Helander, Antti Louko, Tero Mononen,
33 * jvh@cs.hut.fi alo@hut.fi tmo@cs.hut.fi
c906108c
SS
34 *
35 * Tero Kivinen and Eamonn McManus
c5aa993b
JM
36 * kivinen@cs.hut.fi emcmanus@gr.osf.org
37 *
c906108c
SS
38 */
39
40#include <stdio.h>
41
42#include <mach.h>
43#include <servers/netname.h>
44#include <servers/machid.h>
45#include <mach/message.h>
46#include <mach/notify.h>
47#include <mach_error.h>
48#include <mach/exception.h>
49#include <mach/vm_attributes.h>
50
51#include "defs.h"
52#include "inferior.h"
53#include "symtab.h"
54#include "value.h"
55#include "language.h"
56#include "target.h"
03f2053f 57#include "gdb_wait.h"
c906108c
SS
58#include "gdbcmd.h"
59#include "gdbcore.h"
4e052eda 60#include "regcache.h"
c906108c
SS
61
62#if 0
63#include <servers/machid_lib.h>
64#else
65#define MACH_TYPE_TASK 1
66#define MACH_TYPE_THREAD 2
67#endif
68
69/* Included only for signal names and NSIG
c5aa993b 70
c906108c
SS
71 * note: There are many problems in signal handling with
72 * gdb in Mach 3.0 in general.
73 */
74#include <signal.h>
c5aa993b 75#define SIG_UNKNOWN 0 /* Exception that has no matching unix signal */
c906108c
SS
76
77#include <cthreads.h>
78
79/* This is what a cproc looks like. This is here partly because
80 cthread_internals.h is not a header we can just #include, partly with
81 an eye towards perhaps getting this to work with cross-debugging
82 someday. Best solution is if CMU publishes a real interface to this
83 stuff. */
84#define CPROC_NEXT_OFFSET 0
85#define CPROC_NEXT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
86#define CPROC_INCARNATION_OFFSET (CPROC_NEXT_OFFSET + CPROC_NEXT_SIZE)
87#define CPROC_INCARNATION_SIZE (sizeof (cthread_t))
88#define CPROC_LIST_OFFSET (CPROC_INCARNATION_OFFSET + CPROC_INCARNATION_SIZE)
89#define CPROC_LIST_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
90#define CPROC_WAIT_OFFSET (CPROC_LIST_OFFSET + CPROC_LIST_SIZE)
91#define CPROC_WAIT_SIZE (TARGET_PTR_BIT / HOST_CHAR_BIT)
92#define CPROC_REPLY_OFFSET (CPROC_WAIT_OFFSET + CPROC_WAIT_SIZE)
93#define CPROC_REPLY_SIZE (sizeof (mach_port_t))
94#define CPROC_CONTEXT_OFFSET (CPROC_REPLY_OFFSET + CPROC_REPLY_SIZE)
95#define CPROC_CONTEXT_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
96#define CPROC_LOCK_OFFSET (CPROC_CONTEXT_OFFSET + CPROC_CONTEXT_SIZE)
97#define CPROC_LOCK_SIZE (sizeof (spin_lock_t))
98#define CPROC_STATE_OFFSET (CPROC_LOCK_OFFSET + CPROC_LOCK_SIZE)
99#define CPROC_STATE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
100#define CPROC_WIRED_OFFSET (CPROC_STATE_OFFSET + CPROC_STATE_SIZE)
101#define CPROC_WIRED_SIZE (sizeof (mach_port_t))
102#define CPROC_BUSY_OFFSET (CPROC_WIRED_OFFSET + CPROC_WIRED_SIZE)
103#define CPROC_BUSY_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
104#define CPROC_MSG_OFFSET (CPROC_BUSY_OFFSET + CPROC_BUSY_SIZE)
105#define CPROC_MSG_SIZE (sizeof (mach_msg_header_t))
106#define CPROC_BASE_OFFSET (CPROC_MSG_OFFSET + CPROC_MSG_SIZE)
107#define CPROC_BASE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
108#define CPROC_SIZE_OFFSET (CPROC_BASE_OFFSET + CPROC_BASE_SIZE)
109#define CPROC_SIZE_SIZE (TARGET_INT_BIT / HOST_CHAR_BIT)
110#define CPROC_SIZE (CPROC_SIZE_OFFSET + CPROC_SIZE_SIZE)
111
112/* Values for the state field in the cproc. */
113#define CPROC_RUNNING 0
114#define CPROC_SWITCHING 1
115#define CPROC_BLOCKED 2
116#define CPROC_CONDWAIT 4
117
118/* For cproc and kernel thread mapping */
c5aa993b
JM
119typedef struct gdb_thread
120 {
121 mach_port_t name;
122 CORE_ADDR sp;
123 CORE_ADDR pc;
124 CORE_ADDR fp;
125 boolean_t in_emulator;
126 int slotid;
127
128 /* This is for the mthreads list. It points to the cproc list.
129 Perhaps the two lists should be merged (or perhaps it was a mistake
130 to make them both use a struct gdb_thread). */
131 struct gdb_thread *cproc;
132
133 /* These are for the cproc list, which is linked through the next field
134 of the struct gdb_thread. */
135 char raw_cproc[CPROC_SIZE];
136 /* The cthread which is pointed to by the incarnation field from the
137 cproc. This points to the copy we've read into GDB. */
138 cthread_t cthread;
139 /* Point back to the mthreads list. */
140 int reverse_map;
141 struct gdb_thread *next;
142 }
143 *gdb_thread_t;
c906108c
SS
144
145/*
146 * Actions for Mach exceptions.
147 *
148 * sigmap field maps the exception to corresponding Unix signal.
149 *
150 * I do not know how to map the exception to unix signal
151 * if SIG_UNKNOWN is specified.
152 */
153
c5aa993b
JM
154struct exception_list
155 {
156 char *name;
157 boolean_t forward;
158 boolean_t print;
159 int sigmap;
160 }
161exception_map[] =
162{
163 {
164 "not_mach3_exception", FALSE, TRUE, SIG_UNKNOWN
165 }
166 ,
167 {
168 "EXC_BAD_ACCESS", FALSE, TRUE, SIGSEGV
169 }
170 ,
171 {
172 "EXC_BAD_INSTRUCTION", FALSE, TRUE, SIGILL
173 }
174 ,
175 {
176 "EXC_ARITHMETIC", FALSE, TRUE, SIGFPE
177 }
178 ,
179 {
180 "EXC_EMULATION", FALSE, TRUE, SIGEMT
181 }
182 , /* ??? */
183 {
184 "EXC_SOFTWARE", FALSE, TRUE, SIG_UNKNOWN
185 }
186 ,
187 {
188 "EXC_BREAKPOINT", FALSE, FALSE, SIGTRAP
189 }
c906108c
SS
190};
191
192/* Mach exception table size */
c5aa993b 193int max_exception = sizeof (exception_map) / sizeof (struct exception_list) - 1;
c906108c
SS
194
195#define MAX_EXCEPTION max_exception
196
197WAITTYPE wait_status;
198
199/* If you define this, intercepted bsd server calls will be
200 * dumped while waiting the inferior to EXEC the correct
201 * program
202 */
c5aa993b 203/* #define DUMP_SYSCALL /* debugging interceptor */
c906108c
SS
204
205/* xx_debug() outputs messages if this is nonzero.
206 * If > 1, DUMP_SYSCALL will dump message contents.
207 */
208int debug_level = 0;
209
210/* "Temporary" debug stuff */
211void
fba45db2 212xx_debug (char *fmt, int a, int b, int c)
c906108c
SS
213{
214 if (debug_level)
215 warning (fmt, a, b, c);
216}
217
218/* This is in libmach.a */
c5aa993b 219extern mach_port_t name_server_port;
c906108c
SS
220
221/* Set in catch_exception_raise */
222int stop_exception, stop_code, stop_subcode;
223int stopped_in_exception;
224
225/* Thread that was the active thread when we stopped */
226thread_t stop_thread = MACH_PORT_NULL;
227
228char *hostname = "";
229
230/* Set when task is attached or created */
231boolean_t emulator_present = FALSE;
232
c5aa993b 233task_t inferior_task;
c906108c
SS
234thread_t current_thread;
235
236/* Exception ports for inferior task */
c5aa993b 237mach_port_t inferior_exception_port = MACH_PORT_NULL;
c906108c
SS
238mach_port_t inferior_old_exception_port = MACH_PORT_NULL;
239
240/* task exceptions and notifications */
c5aa993b
JM
241mach_port_t inferior_wait_port_set = MACH_PORT_NULL;
242mach_port_t our_notify_port = MACH_PORT_NULL;
c906108c
SS
243
244/* This is "inferior_wait_port_set" when not single stepping, and
245 * "singlestepped_thread_port" when we are single stepping.
246 *
247 * This is protected by a cleanup function: discard_single_step()
248 */
c5aa993b 249mach_port_t currently_waiting_for = MACH_PORT_NULL;
c906108c
SS
250
251/* A port for external messages to gdb.
252 * External in the meaning that they do not come
253 * from the inferior_task, but rather from external
254 * tasks.
255 *
256 * As a debugging feature:
257 * A debugger debugging another debugger can stop the
258 * inferior debugger by the following command sequence
259 * (without running external programs)
260 *
261 * (top-gdb) set stop_inferior_gdb ()
262 * (top-gdb) continue
263 */
c5aa993b 264mach_port_t our_message_port = MACH_PORT_NULL;
c906108c
SS
265
266/* For single stepping */
c5aa993b 267mach_port_t thread_exception_port = MACH_PORT_NULL;
c906108c 268mach_port_t thread_saved_exception_port = MACH_PORT_NULL;
c5aa993b 269mach_port_t singlestepped_thread_port = MACH_PORT_NULL;
c906108c
SS
270
271/* For machid calls */
272mach_port_t mid_server = MACH_PORT_NULL;
c5aa993b 273mach_port_t mid_auth = MACH_PORT_NULL;
c906108c
SS
274
275/* If gdb thinks the inferior task is not suspended, it
276 * must take suspend/abort the threads when it reads the state.
277 */
278int must_suspend_thread = 0;
279
280/* When single stepping, we switch the port that mach_really_wait() listens to.
281 * This cleanup is a guard to prevent the port set from being left to
282 * the singlestepped_thread_port when error() is called.
283 * This is nonzero only when we are single stepping.
284 */
285#define NULL_CLEANUP (struct cleanup *)0
286struct cleanup *cleanup_step = NULL_CLEANUP;
c906108c 287\f
c5aa993b 288
c906108c
SS
289static struct target_ops m3_ops;
290
291static void m3_kill_inferior ();
292\f
293#if 0
294#define MACH_TYPE_EXCEPTION_PORT -1
295#endif
296
297/* Chain of ports to remember requested notifications. */
298
c5aa993b
JM
299struct port_chain
300 {
301 struct port_chain *next;
302 mach_port_t port;
303 int type;
304 int mid; /* Now only valid with MACH_TYPE_THREAD and */
305 /* MACH_TYPE_THREAD */
306 };
c906108c
SS
307typedef struct port_chain *port_chain_t;
308
309/* Room for chain nodes comes from pchain_obstack */
310struct obstack pchain_obstack;
311struct obstack *port_chain_obstack = &pchain_obstack;
312
313/* For thread handling */
314struct obstack Cproc_obstack;
315struct obstack *cproc_obstack = &Cproc_obstack;
316
317/* the list of notified ports */
318port_chain_t notify_chain = (port_chain_t) NULL;
319
320port_chain_t
fba45db2 321port_chain_insert (port_chain_t list, mach_port_t name, int type)
c906108c
SS
322{
323 kern_return_t ret;
324 port_chain_t new;
325 int mid;
326
c5aa993b 327 if (!MACH_PORT_VALID (name))
c906108c 328 return list;
c5aa993b 329
c906108c
SS
330 if (type == MACH_TYPE_TASK || type == MACH_TYPE_THREAD)
331 {
c5aa993b 332 if (!MACH_PORT_VALID (mid_server))
c906108c
SS
333 {
334 warning ("Machid server port invalid, can not map port 0x%x to MID",
335 name);
336 mid = name;
337 }
338 else
339 {
340 ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
c5aa993b 341
c906108c
SS
342 if (ret != KERN_SUCCESS)
343 {
344 warning ("Can not map name (0x%x) to MID with machid", name);
345 mid = name;
346 }
347 }
348 }
349 else
e1e9e218 350 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c906108c
SS
351
352 new = (port_chain_t) obstack_alloc (port_chain_obstack,
353 sizeof (struct port_chain));
c5aa993b
JM
354 new->next = list;
355 new->port = name;
356 new->type = type;
357 new->mid = mid;
c906108c
SS
358
359 return new;
360}
361
362port_chain_t
fba45db2 363port_chain_delete (port_chain_t list, mach_port_t elem)
c906108c
SS
364{
365 if (list)
366 if (list->port == elem)
367 list = list->next;
368 else
369 while (list->next)
370 {
371 if (list->next->port == elem)
c5aa993b 372 list->next = list->next->next; /* GCd with obstack_free() */
c906108c
SS
373 else
374 list = list->next;
375 }
376 return list;
377}
378
379void
fba45db2 380port_chain_destroy (struct obstack *ostack)
c906108c
SS
381{
382 obstack_free (ostack, 0);
383 obstack_init (ostack);
384}
385
386port_chain_t
fba45db2 387port_chain_member (port_chain_t list, mach_port_t elem)
c906108c
SS
388{
389 while (list)
390 {
391 if (list->port == elem)
392 return list;
393 list = list->next;
394 }
395 return (port_chain_t) NULL;
396}
397\f
398int
fba45db2 399map_port_name_to_mid (mach_port_t name, int type)
c906108c
SS
400{
401 port_chain_t elem;
402
403 if (!MACH_PORT_VALID (name))
404 return -1;
405
406 elem = port_chain_member (notify_chain, name);
407
408 if (elem && (elem->type == type))
409 return elem->mid;
c5aa993b 410
c906108c
SS
411 if (elem)
412 return -1;
c5aa993b
JM
413
414 if (!MACH_PORT_VALID (mid_server))
c906108c
SS
415 {
416 warning ("Machid server port invalid, can not map port 0x%x to mid",
417 name);
418 return -1;
419 }
420 else
421 {
422 int mid;
423 kern_return_t ret;
424
425 ret = machid_mach_register (mid_server, mid_auth, name, type, &mid);
c5aa993b 426
c906108c
SS
427 if (ret != KERN_SUCCESS)
428 {
429 warning ("Can not map name (0x%x) to mid with machid", name);
430 return -1;
431 }
432 return mid;
433 }
434}
435\f
436/* Guard for currently_waiting_for and singlestepped_thread_port */
437static void
fba45db2 438discard_single_step (thread_t thread)
c906108c
SS
439{
440 currently_waiting_for = inferior_wait_port_set;
441
442 cleanup_step = NULL_CLEANUP;
443 if (MACH_PORT_VALID (thread) && MACH_PORT_VALID (singlestepped_thread_port))
444 setup_single_step (thread, FALSE);
445}
446
fba45db2 447setup_single_step (thread_t thread, boolean_t start_step)
c906108c
SS
448{
449 kern_return_t ret;
450
c5aa993b 451 if (!MACH_PORT_VALID (thread))
c906108c
SS
452 error ("Invalid thread supplied to setup_single_step");
453 else
454 {
455 mach_port_t teport;
456
457 /* Get the current thread exception port */
458 ret = thread_get_exception_port (thread, &teport);
459 CHK ("Getting thread's exception port", ret);
c5aa993b 460
c906108c
SS
461 if (start_step)
462 {
463 if (MACH_PORT_VALID (singlestepped_thread_port))
464 {
465 warning ("Singlestepped_thread_port (0x%x) is still valid?",
466 singlestepped_thread_port);
467 singlestepped_thread_port = MACH_PORT_NULL;
468 }
c5aa993b 469
c906108c
SS
470 /* If we are already stepping this thread */
471 if (MACH_PORT_VALID (teport) && teport == thread_exception_port)
472 {
473 ret = mach_port_deallocate (mach_task_self (), teport);
474 CHK ("Could not deallocate thread exception port", ret);
475 }
476 else
477 {
478 ret = thread_set_exception_port (thread, thread_exception_port);
479 CHK ("Setting exception port for thread", ret);
480#if 0
481 /* Insert thread exception port to wait port set */
c5aa993b 482 ret = mach_port_move_member (mach_task_self (),
c906108c
SS
483 thread_exception_port,
484 inferior_wait_port_set);
485 CHK ("Moving thread exception port to inferior_wait_port_set",
486 ret);
487#endif
488 thread_saved_exception_port = teport;
489 }
c5aa993b 490
c906108c 491 thread_trace (thread, TRUE);
c5aa993b
JM
492
493 singlestepped_thread_port = thread_exception_port;
494 currently_waiting_for = singlestepped_thread_port;
c906108c
SS
495 cleanup_step = make_cleanup (discard_single_step, thread);
496 }
497 else
498 {
c5aa993b 499 if (!MACH_PORT_VALID (teport))
c906108c
SS
500 error ("Single stepped thread had an invalid exception port?");
501
502 if (teport != thread_exception_port)
503 error ("Single stepped thread had an unknown exception port?");
c5aa993b 504
c906108c
SS
505 ret = mach_port_deallocate (mach_task_self (), teport);
506 CHK ("Couldn't deallocate thread exception port", ret);
507#if 0
508 /* Remove thread exception port from wait port set */
c5aa993b 509 ret = mach_port_move_member (mach_task_self (),
c906108c
SS
510 thread_exception_port,
511 MACH_PORT_NULL);
512 CHK ("Removing thread exception port from inferior_wait_port_set",
513 ret);
c5aa993b 514#endif
c906108c
SS
515 /* Restore thread's old exception port */
516 ret = thread_set_exception_port (thread,
517 thread_saved_exception_port);
518 CHK ("Restoring stepped thread's exception port", ret);
c5aa993b 519
c906108c
SS
520 if (MACH_PORT_VALID (thread_saved_exception_port))
521 (void) mach_port_deallocate (mach_task_self (),
522 thread_saved_exception_port);
c5aa993b 523
c906108c 524 thread_trace (thread, FALSE);
c5aa993b 525
c906108c
SS
526 singlestepped_thread_port = MACH_PORT_NULL;
527 currently_waiting_for = inferior_wait_port_set;
528 if (cleanup_step)
529 discard_cleanups (cleanup_step);
530 }
531 }
532}
533\f
534static
fba45db2 535request_notify (mach_port_t name, mach_msg_id_t variant, int type)
c906108c
SS
536{
537 kern_return_t ret;
c5aa993b
JM
538 mach_port_t previous_port_dummy = MACH_PORT_NULL;
539
540 if (!MACH_PORT_VALID (name))
c906108c 541 return;
c5aa993b 542
c906108c
SS
543 if (port_chain_member (notify_chain, name))
544 return;
545
c5aa993b 546 ret = mach_port_request_notification (mach_task_self (),
c906108c
SS
547 name,
548 variant,
549 1,
550 our_notify_port,
551 MACH_MSG_TYPE_MAKE_SEND_ONCE,
552 &previous_port_dummy);
553 CHK ("Serious: request_notify failed", ret);
554
555 (void) mach_port_deallocate (mach_task_self (),
556 previous_port_dummy);
557
558 notify_chain = port_chain_insert (notify_chain, name, type);
559}
560
fba45db2 561reverse_msg_bits (mach_msg_header_t *msgp, int type)
c906108c 562{
c5aa993b
JM
563 int rbits, lbits;
564 rbits = MACH_MSGH_BITS_REMOTE (msgp->msgh_bits);
c906108c
SS
565 lbits = type;
566 msgp->msgh_bits =
567 (msgp->msgh_bits & ~MACH_MSGH_BITS_PORTS_MASK) |
c5aa993b 568 MACH_MSGH_BITS (lbits, rbits);
c906108c
SS
569}
570\f
571/* On the third day He said:
572
c5aa993b
JM
573 Let this be global
574 and then it was global.
c906108c
SS
575
576 When creating the inferior fork, the
577 child code in inflow.c sets the name of the
578 bootstrap_port in its address space to this
579 variable.
580
581 The name is transferred to our address space
582 with mach3_read_inferior().
583
584 Thou shalt not do this with
585 task_get_bootstrap_port() in this task, since
586 the name in the inferior task is different than
587 the one we get.
588
589 For blessed are the meek, as they shall inherit
590 the address space.
591 */
592mach_port_t original_server_port_name = MACH_PORT_NULL;
593
594
595/* Called from inferior after FORK but before EXEC */
596static void
fba45db2 597m3_trace_me (void)
c906108c
SS
598{
599 kern_return_t ret;
c5aa993b 600
c906108c
SS
601 /* Get the NAME of the bootstrap port in this task
602 so that GDB can read it */
603 ret = task_get_bootstrap_port (mach_task_self (),
604 &original_server_port_name);
605 if (ret != KERN_SUCCESS)
e1e9e218 606 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c906108c
SS
607 ret = mach_port_deallocate (mach_task_self (),
608 original_server_port_name);
609 if (ret != KERN_SUCCESS)
e1e9e218 610 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c5aa993b 611
c906108c
SS
612 /* Suspend this task to let the parent change my ports.
613 Resumed by the debugger */
614 ret = task_suspend (mach_task_self ());
615 if (ret != KERN_SUCCESS)
e1e9e218 616 internal_error (__FILE__, __LINE__, "failed internal consistency check");
c906108c
SS
617}
618\f
619/*
620 * Intercept system calls to Unix server.
621 * After EXEC_COUNTER calls to exec(), return.
622 *
623 * Pre-assertion: Child is suspended. (Not verified)
624 * Post-condition: Child is suspended after EXEC_COUNTER exec() calls.
625 */
626
627void
fba45db2 628intercept_exec_calls (int exec_counter)
c906108c
SS
629{
630 int terminal_initted = 0;
631
c5aa993b
JM
632 struct syscall_msg_t
633 {
634 mach_msg_header_t header;
635 mach_msg_type_t type;
636 char room[2000]; /* Enuff space */
637 };
c906108c
SS
638
639 struct syscall_msg_t syscall_in, syscall_out;
640
641 mach_port_t fake_server;
642 mach_port_t original_server_send;
643 mach_port_t original_exec_reply;
644 mach_port_t exec_reply;
645 mach_port_t exec_reply_send;
646 mach_msg_type_name_t acquired;
647 mach_port_t emulator_server_port_name;
648 struct task_basic_info info;
649 mach_msg_type_number_t info_count;
650
651 kern_return_t ret;
652
653 if (exec_counter <= 0)
c5aa993b
JM
654 return; /* We are already set up in the correct program */
655
656 ret = mach_port_allocate (mach_task_self (),
657 MACH_PORT_RIGHT_RECEIVE,
658 &fake_server);
659 CHK ("create inferior_fake_server port failed", ret);
c906108c 660
c906108c 661 /* Wait for inferior_task to suspend itself */
c5aa993b 662 while (1)
c906108c
SS
663 {
664 info_count = sizeof (info);
665 ret = task_info (inferior_task,
666 TASK_BASIC_INFO,
c5aa993b 667 (task_info_t) & info,
c906108c
SS
668 &info_count);
669 CHK ("Task info", ret);
670
671 if (info.suspend_count)
672 break;
673
674 /* Note that the definition of the parameter was undefined
675 * at the time of this writing, so I just use an `ad hoc' value.
676 */
c5aa993b 677 (void) swtch_pri (42); /* Universal Priority Value */
c906108c
SS
678 }
679
680 /* Read the inferior's bootstrap port name */
681 if (!mach3_read_inferior (&original_server_port_name,
682 &original_server_port_name,
683 sizeof (original_server_port_name)))
684 error ("Can't read inferior task bootstrap port name");
685
686 /* @@ BUG: If more than 1 send right GDB will FAIL!!! */
687 /* Should get refs, and set them back when restoring */
688 /* Steal the original bsd server send right from inferior */
689 ret = mach_port_extract_right (inferior_task,
690 original_server_port_name,
691 MACH_MSG_TYPE_MOVE_SEND,
692 &original_server_send,
693 &acquired);
c5aa993b
JM
694 CHK ("mach_port_extract_right (bsd server send)", ret);
695
c906108c 696 if (acquired != MACH_MSG_TYPE_PORT_SEND)
8e1a459b 697 error ("Incorrect right extracted, send right to bsd server expected");
c906108c
SS
698
699 ret = mach_port_insert_right (inferior_task,
700 original_server_port_name,
701 fake_server,
702 MACH_MSG_TYPE_MAKE_SEND);
c5aa993b 703 CHK ("mach_port_insert_right (fake server send)", ret);
c906108c
SS
704
705 xx_debug ("inferior task bsd server ports set up \nfs %x, ospn %x, oss %x\n",
706 fake_server,
707 original_server_port_name, original_server_send);
708
709 /* A receive right to the reply generated by unix server exec() request */
c5aa993b
JM
710 ret = mach_port_allocate (mach_task_self (),
711 MACH_PORT_RIGHT_RECEIVE,
712 &exec_reply);
713 CHK ("create intercepted_reply_port port failed", ret);
714
c906108c
SS
715 /* Pass this send right to Unix server so it replies to us after exec() */
716 ret = mach_port_extract_right (mach_task_self (),
717 exec_reply,
718 MACH_MSG_TYPE_MAKE_SEND_ONCE,
719 &exec_reply_send,
720 &acquired);
c5aa993b 721 CHK ("mach_port_extract_right (exec_reply)", ret);
c906108c
SS
722
723 if (acquired != MACH_MSG_TYPE_PORT_SEND_ONCE)
8e1a459b 724 error ("Incorrect right extracted, send once expected for exec reply");
c906108c 725
c5aa993b
JM
726 ret = mach_port_move_member (mach_task_self (),
727 fake_server,
728 inferior_wait_port_set);
c906108c
SS
729 CHK ("Moving fake syscall port to inferior_wait_port_set", ret);
730
731 xx_debug ("syscall fake server set up, resuming inferior\n");
c5aa993b 732
c906108c 733 ret = task_resume (inferior_task);
c5aa993b
JM
734 CHK ("task_resume (startup)", ret);
735
c906108c
SS
736 /* Read requests from the inferior.
737 Pass directly through everything else except exec() calls.
738 */
c5aa993b 739 while (exec_counter > 0)
c906108c
SS
740 {
741 ret = mach_msg (&syscall_in.header, /* header */
c5aa993b
JM
742 MACH_RCV_MSG, /* options */
743 0, /* send size */
744 sizeof (struct syscall_msg_t), /* receive size */
745 inferior_wait_port_set, /* receive_name */
c906108c
SS
746 MACH_MSG_TIMEOUT_NONE,
747 MACH_PORT_NULL);
c5aa993b
JM
748 CHK ("mach_msg (intercepted sycall)", ret);
749
c906108c
SS
750#ifdef DUMP_SYSCALL
751 print_msg (&syscall_in.header);
752#endif
753
754 /* ASSERT : msgh_local_port == fake_server */
755
756 if (notify_server (&syscall_in.header, &syscall_out.header))
757 error ("received a notify while intercepting syscalls");
758
759 if (syscall_in.header.msgh_id == MIG_EXEC_SYSCALL_ID)
760 {
761 xx_debug ("Received EXEC SYSCALL, counter = %d\n", exec_counter);
762 if (exec_counter == 1)
763 {
764 original_exec_reply = syscall_in.header.msgh_remote_port;
765 syscall_in.header.msgh_remote_port = exec_reply_send;
766 }
767
768 if (!terminal_initted)
769 {
770 /* Now that the child has exec'd we know it has already set its
c5aa993b
JM
771 process group. On POSIX systems, tcsetpgrp will fail with
772 EPERM if we try it before the child's setpgid. */
c906108c
SS
773
774 /* Set up the "saved terminal modes" of the inferior
c5aa993b 775 based on what modes we are starting it with. */
c906108c
SS
776 target_terminal_init ();
777
778 /* Install inferior's terminal modes. */
779 target_terminal_inferior ();
780
781 terminal_initted = 1;
782 }
783
784 exec_counter--;
785 }
c5aa993b
JM
786
787 syscall_in.header.msgh_local_port = syscall_in.header.msgh_remote_port;
c906108c
SS
788 syscall_in.header.msgh_remote_port = original_server_send;
789
c5aa993b 790 reverse_msg_bits (&syscall_in.header, MACH_MSG_TYPE_COPY_SEND);
c906108c
SS
791
792 ret = mach_msg_send (&syscall_in.header);
793 CHK ("Forwarded syscall", ret);
794 }
c5aa993b
JM
795
796 ret = mach_port_move_member (mach_task_self (),
797 fake_server,
798 MACH_PORT_NULL);
c906108c
SS
799 CHK ("Moving fake syscall out of inferior_wait_port_set", ret);
800
c5aa993b
JM
801 ret = mach_port_move_member (mach_task_self (),
802 exec_reply,
803 inferior_wait_port_set);
c906108c
SS
804 CHK ("Moving exec_reply to inferior_wait_port_set", ret);
805
806 ret = mach_msg (&syscall_in.header, /* header */
c5aa993b
JM
807 MACH_RCV_MSG, /* options */
808 0, /* send size */
c906108c 809 sizeof (struct syscall_msg_t), /* receive size */
c5aa993b 810 inferior_wait_port_set, /* receive_name */
c906108c
SS
811 MACH_MSG_TIMEOUT_NONE,
812 MACH_PORT_NULL);
c5aa993b 813 CHK ("mach_msg (exec reply)", ret);
c906108c
SS
814
815 ret = task_suspend (inferior_task);
816 CHK ("Suspending inferior after last exec", ret);
817
818 must_suspend_thread = 0;
819
820 xx_debug ("Received exec reply from bsd server, suspended inferior task\n");
821
822#ifdef DUMP_SYSCALL
c5aa993b 823 print_msg (&syscall_in.header);
c906108c
SS
824#endif
825
826 /* Message should appear as if it came from the unix server */
827 syscall_in.header.msgh_local_port = MACH_PORT_NULL;
828
829 /* and go to the inferior task original reply port */
830 syscall_in.header.msgh_remote_port = original_exec_reply;
831
c5aa993b 832 reverse_msg_bits (&syscall_in.header, MACH_MSG_TYPE_MOVE_SEND_ONCE);
c906108c
SS
833
834 ret = mach_msg_send (&syscall_in.header);
835 CHK ("Forwarding exec reply to inferior", ret);
836
837 /* Garbage collect */
838 ret = mach_port_deallocate (inferior_task,
839 original_server_port_name);
840 CHK ("deallocating fake server send right", ret);
841
842 ret = mach_port_insert_right (inferior_task,
843 original_server_port_name,
844 original_server_send,
845 MACH_MSG_TYPE_MOVE_SEND);
846 CHK ("Restoring the original bsd server send right", ret);
847
848 ret = mach_port_destroy (mach_task_self (),
849 fake_server);
850 fake_server = MACH_PORT_DEAD;
c5aa993b 851 CHK ("mach_port_destroy (fake_server)", ret);
c906108c
SS
852
853 ret = mach_port_destroy (mach_task_self (),
854 exec_reply);
855 exec_reply = MACH_PORT_DEAD;
c5aa993b 856 CHK ("mach_port_destroy (exec_reply)", ret);
c906108c
SS
857
858 xx_debug ("Done with exec call interception\n");
859}
860
861void
fba45db2 862consume_send_rights (thread_array_t thread_list, int thread_count)
c906108c
SS
863{
864 int index;
865
866 if (!thread_count)
867 return;
868
869 for (index = 0; index < thread_count; index++)
870 {
871 /* Since thread kill command kills threads, don't check ret */
872 (void) mach_port_deallocate (mach_task_self (),
c5aa993b 873 thread_list[index]);
c906108c
SS
874 }
875}
876
877/* suspend/abort/resume a thread. */
fba45db2 878setup_thread (mach_port_t thread, int what)
c906108c
SS
879{
880 kern_return_t ret;
881
882 if (what)
883 {
884 ret = thread_suspend (thread);
885 CHK ("setup_thread thread_suspend", ret);
c5aa993b 886
c906108c
SS
887 ret = thread_abort (thread);
888 CHK ("setup_thread thread_abort", ret);
889 }
890 else
891 {
892 ret = thread_resume (thread);
893 CHK ("setup_thread thread_resume", ret);
894 }
895}
896
897int
fba45db2 898map_slot_to_mid (int slot, thread_array_t threads, int thread_count)
c906108c
SS
899{
900 kern_return_t ret;
901 int deallocate = 0;
902 int index;
903 int mid;
904
c5aa993b 905 if (!threads)
c906108c
SS
906 {
907 deallocate++;
908 ret = task_threads (inferior_task, &threads, &thread_count);
909 CHK ("Can not select a thread from a dead task", ret);
910 }
c5aa993b 911
c906108c
SS
912 if (slot < 0 || slot >= thread_count)
913 {
914 if (deallocate)
915 {
916 consume_send_rights (threads, thread_count);
c5aa993b
JM
917 (void) vm_deallocate (mach_task_self (), (vm_address_t) threads,
918 (thread_count * sizeof (mach_port_t)));
c906108c
SS
919 }
920 if (slot < 0)
921 error ("invalid slot number");
922 else
c5aa993b 923 return -(slot + 1);
c906108c
SS
924 }
925
c5aa993b 926 mid = map_port_name_to_mid (threads[slot], MACH_TYPE_THREAD);
c906108c
SS
927
928 if (deallocate)
929 {
930 consume_send_rights (threads, thread_count);
c5aa993b
JM
931 (void) vm_deallocate (mach_task_self (), (vm_address_t) threads,
932 (thread_count * sizeof (mach_port_t)));
c906108c
SS
933 }
934
935 return mid;
936}
937
938static int
fba45db2 939parse_thread_id (char *arg, int thread_count, int slots)
c906108c
SS
940{
941 kern_return_t ret;
942 int mid;
943 int slot;
944 int index;
c5aa993b 945
c906108c
SS
946 if (arg == 0)
947 return 0;
c5aa993b 948
c906108c
SS
949 while (*arg && (*arg == ' ' || *arg == '\t'))
950 arg++;
c5aa993b
JM
951
952 if (!*arg)
c906108c 953 return 0;
c5aa993b 954
c906108c
SS
955 /* Currently parse MID and @SLOTNUMBER */
956 if (*arg != '@')
957 {
958 mid = atoi (arg);
959 if (mid <= 0)
960 error ("valid thread mid expected");
961 return mid;
962 }
c5aa993b 963
c906108c
SS
964 arg++;
965 slot = atoi (arg);
966
967 if (slot < 0)
968 error ("invalid slot number");
969
970 /* If you want slot numbers to remain slot numbers, set slots.
c5aa993b 971
c906108c
SS
972 * Well, since 0 is reserved, return the ordinal number
973 * of the thread rather than the slot number. Awk, this
974 * counts as a kludge.
975 */
976 if (slots)
c5aa993b 977 return -(slot + 1);
c906108c
SS
978
979 if (thread_count && slot >= thread_count)
c5aa993b 980 return -(slot + 1);
c906108c
SS
981
982 mid = map_slot_to_mid (slot);
c5aa993b 983
c906108c
SS
984 return mid;
985}
986
987/* THREAD_ID 0 is special; it selects the first kernel
988 * thread from the list (i.e. SLOTNUMBER 0)
989 * This is used when starting the program with 'run' or when attaching.
990 *
991 * If FLAG is 0 the context is not changed, and the registers, frame, etc
992 * will continue to describe the old thread.
993 *
994 * If FLAG is nonzero, really select the thread.
995 * If FLAG is 2, the THREAD_ID is a slotnumber instead of a mid.
996 *
997 */
998kern_return_t
fba45db2 999select_thread (mach_port_t task, int thread_id, int flag)
c906108c
SS
1000{
1001 thread_array_t thread_list;
1002 int thread_count;
1003 kern_return_t ret;
1004 int index;
1005 thread_t new_thread = MACH_PORT_NULL;
1006
1007 if (thread_id < 0)
1008 error ("Can't select cprocs without kernel thread");
1009
1010 ret = task_threads (task, &thread_list, &thread_count);
1011 if (ret != KERN_SUCCESS)
1012 {
1013 warning ("Can not select a thread from a dead task");
1014 m3_kill_inferior ();
1015 return KERN_FAILURE;
1016 }
1017
1018 if (thread_count == 0)
1019 {
1020 /* The task can not do anything anymore, but it still
1021 * exists as a container for memory and ports.
1022 */
1023 registers_changed ();
1024 warning ("Task %d has no threads",
1025 map_port_name_to_mid (task, MACH_TYPE_TASK));
1026 current_thread = MACH_PORT_NULL;
c5aa993b
JM
1027 (void) vm_deallocate (mach_task_self (),
1028 (vm_address_t) thread_list,
1029 (thread_count * sizeof (mach_port_t)));
c906108c
SS
1030 return KERN_FAILURE;
1031 }
1032
c5aa993b 1033 if (!thread_id || flag == 2)
c906108c
SS
1034 {
1035 /* First thread or a slotnumber */
c5aa993b 1036 if (!thread_id)
c906108c
SS
1037 new_thread = thread_list[0];
1038 else
1039 {
1040 if (thread_id < thread_count)
c5aa993b 1041 new_thread = thread_list[thread_id];
c906108c
SS
1042 else
1043 {
c5aa993b
JM
1044 (void) vm_deallocate (mach_task_self (),
1045 (vm_address_t) thread_list,
1046 (thread_count * sizeof (mach_port_t)));
c906108c
SS
1047 error ("No such thread slot number : %d", thread_id);
1048 }
1049 }
1050 }
1051 else
1052 {
1053 for (index = 0; index < thread_count; index++)
c5aa993b 1054 if (thread_id == map_port_name_to_mid (thread_list[index],
c906108c
SS
1055 MACH_TYPE_THREAD))
1056 {
c5aa993b 1057 new_thread = thread_list[index];
c906108c
SS
1058 index = -1;
1059 break;
1060 }
c5aa993b 1061
c906108c
SS
1062 if (index != -1)
1063 error ("No thread with mid %d", thread_id);
1064 }
c5aa993b 1065
c906108c
SS
1066 /* Notify when the selected thread dies */
1067 request_notify (new_thread, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_THREAD);
c5aa993b
JM
1068
1069 ret = vm_deallocate (mach_task_self (),
1070 (vm_address_t) thread_list,
1071 (thread_count * sizeof (mach_port_t)));
c906108c 1072 CHK ("vm_deallocate", ret);
c5aa993b
JM
1073
1074 if (!flag)
c906108c
SS
1075 current_thread = new_thread;
1076 else
1077 {
1078#if 0
1079 if (MACH_PORT_VALID (current_thread))
1080 {
1081 /* Store the gdb's view of the thread we are deselecting
c5aa993b 1082
c906108c
SS
1083 * @@ I think gdb updates registers immediately when they are
1084 * changed, so don't do this.
1085 */
1086 ret = thread_abort (current_thread);
1087 CHK ("Could not abort system calls when saving state of old thread",
1088 ret);
1089 target_prepare_to_store ();
1090 target_store_registers (-1);
1091 }
1092#endif
1093
1094 registers_changed ();
1095
1096 current_thread = new_thread;
1097
1098 ret = thread_abort (current_thread);
1099 CHK ("Could not abort system calls when selecting a thread", ret);
1100
c5aa993b 1101 stop_pc = read_pc ();
c906108c
SS
1102 flush_cached_frames ();
1103
1104 select_frame (get_current_frame (), 0);
1105 }
1106
1107 return KERN_SUCCESS;
1108}
1109
1110/*
1111 * Switch to use thread named NEW_THREAD.
1112 * Return it's MID
1113 */
1114int
fba45db2 1115switch_to_thread (thread_t new_thread)
c906108c
SS
1116{
1117 thread_t saved_thread = current_thread;
1118 int mid;
1119
1120 mid = map_port_name_to_mid (new_thread,
1121 MACH_TYPE_THREAD);
1122 if (mid == -1)
1123 warning ("Can't map thread name 0x%x to mid", new_thread);
1124 else if (select_thread (inferior_task, mid, 1) != KERN_SUCCESS)
1125 {
1126 if (current_thread)
1127 current_thread = saved_thread;
1128 error ("Could not select thread %d", mid);
1129 }
c5aa993b 1130
c906108c
SS
1131 return mid;
1132}
1133
1134/* Do this in gdb after doing FORK but before STARTUP_INFERIOR.
1135 * Note that the registers are not yet valid in the inferior task.
1136 */
1137static int
fba45db2 1138m3_trace_him (int pid)
c906108c
SS
1139{
1140 kern_return_t ret;
1141
1142 push_target (&m3_ops);
1143
1144 inferior_task = task_by_pid (pid);
1145
c5aa993b 1146 if (!MACH_PORT_VALID (inferior_task))
c906108c
SS
1147 error ("Can not map Unix pid %d to Mach task", pid);
1148
1149 /* Clean up previous notifications and create new ones */
1150 setup_notify_port (1);
1151
1152 /* When notification appears, the inferior task has died */
1153 request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
1154
1155 emulator_present = have_emulator_p (inferior_task);
1156
1157 /* By default, select the first thread,
1158 * If task has no threads, gives a warning
1159 * Does not fetch registers, since they are not yet valid.
1160 */
1161 select_thread (inferior_task, 0, 0);
1162
1163 inferior_exception_port = MACH_PORT_NULL;
1164
1165 setup_exception_port ();
1166
1167 xx_debug ("Now the debugged task is created\n");
1168
1169 /* One trap to exec the shell, one to exec the program being debugged. */
1170 intercept_exec_calls (2);
1171
1172 return pid;
1173}
1174
fba45db2 1175setup_exception_port (void)
c906108c
SS
1176{
1177 kern_return_t ret;
1178
c5aa993b 1179 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
1180 MACH_PORT_RIGHT_RECEIVE,
1181 &inferior_exception_port);
c5aa993b 1182 CHK ("mach_port_allocate", ret);
c906108c
SS
1183
1184 /* add send right */
1185 ret = mach_port_insert_right (mach_task_self (),
1186 inferior_exception_port,
1187 inferior_exception_port,
1188 MACH_MSG_TYPE_MAKE_SEND);
c5aa993b 1189 CHK ("mach_port_insert_right", ret);
c906108c 1190
c5aa993b 1191 ret = mach_port_move_member (mach_task_self (),
c906108c
SS
1192 inferior_exception_port,
1193 inferior_wait_port_set);
c5aa993b 1194 CHK ("mach_port_move_member", ret);
c906108c 1195
c5aa993b 1196 ret = task_get_special_port (inferior_task,
c906108c
SS
1197 TASK_EXCEPTION_PORT,
1198 &inferior_old_exception_port);
c5aa993b 1199 CHK ("task_get_special_port(old exc)", ret);
c906108c
SS
1200
1201 ret = task_set_special_port (inferior_task,
c5aa993b 1202 TASK_EXCEPTION_PORT,
c906108c 1203 inferior_exception_port);
c5aa993b 1204 CHK ("task_set_special_port", ret);
c906108c
SS
1205
1206 ret = mach_port_deallocate (mach_task_self (),
1207 inferior_exception_port);
c5aa993b 1208 CHK ("mack_port_deallocate", ret);
c906108c
SS
1209
1210#if 0
1211 /* When notify appears, the inferior_task's exception
1212 * port has been destroyed.
1213 *
1214 * Not used, since the dead_name_notification already
1215 * appears when task dies.
1216 *
1217 */
1218 request_notify (inferior_exception_port,
1219 MACH_NOTIFY_NO_SENDERS,
1220 MACH_TYPE_EXCEPTION_PORT);
1221#endif
1222}
1223
1224/* Nonzero if gdb is waiting for a message */
1225int mach_really_waiting;
1226
1227/* Wait for the inferior to stop for some reason.
1228 - Loop on notifications until inferior_task dies.
1229 - Loop on exceptions until stopped_in_exception comes true.
c5aa993b 1230 (e.g. we receive a single step trace trap)
c906108c
SS
1231 - a message arrives to gdb's message port
1232
1233 There is no other way to exit this loop.
1234
39f77062 1235 Returns the inferior_ptid for rest of gdb.
c906108c 1236 Side effects: Set *OURSTATUS. */
39f77062
KB
1237ptid_t
1238mach_really_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
c906108c
SS
1239{
1240 kern_return_t ret;
1241 int w;
1242
c5aa993b
JM
1243 struct msg
1244 {
1245 mach_msg_header_t header;
1246 mach_msg_type_t foo;
1247 int data[8000];
1248 }
1249 in_msg, out_msg;
c906108c
SS
1250
1251 /* Either notify (death), exception or message can stop the inferior */
1252 stopped_in_exception = FALSE;
1253
1254 while (1)
1255 {
1256 QUIT;
1257
1258 stop_exception = stop_code = stop_subcode = -1;
1259 stop_thread = MACH_PORT_NULL;
1260
1261 mach_really_waiting = 1;
c5aa993b
JM
1262 ret = mach_msg (&in_msg.header, /* header */
1263 MACH_RCV_MSG, /* options */
1264 0, /* send size */
c906108c
SS
1265 sizeof (struct msg), /* receive size */
1266 currently_waiting_for, /* receive name */
1267 MACH_MSG_TIMEOUT_NONE,
1268 MACH_PORT_NULL);
1269 mach_really_waiting = 0;
c5aa993b 1270 CHK ("mach_msg (receive)", ret);
c906108c
SS
1271
1272 /* Check if we received a notify of the childs' death */
1273 if (notify_server (&in_msg.header, &out_msg.header))
1274 {
1275 /* If inferior_task is null then the inferior has
1276 gone away and we want to return to command level.
1277 Otherwise it was just an informative message and we
1278 need to look to see if there are any more. */
1279 if (inferior_task != MACH_PORT_NULL)
1280 continue;
1281 else
1282 {
1283 /* Collect Unix exit status for gdb */
1284
c5aa993b 1285 wait3 (&w, WNOHANG, 0);
c906108c
SS
1286
1287 /* This mess is here to check that the rest of
1288 * gdb knows that the inferior died. It also
1289 * tries to hack around the fact that Mach 3.0 (mk69)
1290 * unix server (ux28) does not always know what
1291 * has happened to it's children when mach-magic
1292 * is applied on them.
1293 */
c5aa993b
JM
1294 if ((!WIFEXITED (w) && WIFSTOPPED (w)) ||
1295 (WIFEXITED (w) && WEXITSTATUS (w) > 0377))
c906108c 1296 {
c5aa993b 1297 WSETEXIT (w, 0);
c906108c
SS
1298 warning ("Using exit value 0 for terminated task");
1299 }
c5aa993b 1300 else if (!WIFEXITED (w))
c906108c 1301 {
c5aa993b 1302 int sig = WTERMSIG (w);
c906108c
SS
1303
1304 /* Signals cause problems. Warn the user. */
c5aa993b 1305 if (sig != SIGKILL) /* Bad luck if garbage matches this */
c906108c
SS
1306 warning ("The terminating signal stuff may be nonsense");
1307 else if (sig > NSIG)
1308 {
c5aa993b 1309 WSETEXIT (w, 0);
c906108c
SS
1310 warning ("Using exit value 0 for terminated task");
1311 }
1312 }
1313 store_waitstatus (ourstatus, w);
39f77062 1314 return inferior_ptid;
c906108c
SS
1315 }
1316 }
1317
1318 /* Hmm. Check for exception, as it was not a notification.
c5aa993b
JM
1319 exc_server() does an upcall to catch_exception_raise()
1320 if this rpc is an exception. Further actions are decided
1321 there.
c906108c 1322 */
c5aa993b 1323 if (!exc_server (&in_msg.header, &out_msg.header))
c906108c
SS
1324 {
1325
1326 /* Not an exception, check for message.
c5aa993b 1327
c906108c
SS
1328 * Messages don't come from the inferior, or if they
1329 * do they better be asynchronous or it will hang.
1330 */
1331 if (gdb_message_server (&in_msg.header))
1332 continue;
1333
1334 error ("Unrecognized message received in mach_really_wait");
1335 }
1336
1337 /* Send the reply of the exception rpc to the suspended task */
1338 ret = mach_msg_send (&out_msg.header);
1339 CHK ("mach_msg_send (exc reply)", ret);
c5aa993b 1340
c906108c
SS
1341 if (stopped_in_exception)
1342 {
1343 /* Get unix state. May be changed in mach3_exception_actions() */
c5aa993b 1344 wait3 (&w, WNOHANG, 0);
c906108c
SS
1345
1346 mach3_exception_actions (&w, FALSE, "Task");
1347
1348 store_waitstatus (ourstatus, w);
39f77062 1349 return inferior_ptid;
c906108c
SS
1350 }
1351 }
1352}
1353
1354/* Called by macro DO_QUIT() in utils.c(quit).
1355 * This is called just before calling error() to return to command level
1356 */
1357void
fba45db2 1358mach3_quit (void)
c906108c
SS
1359{
1360 int mid;
1361 kern_return_t ret;
c5aa993b 1362
c906108c
SS
1363 if (mach_really_waiting)
1364 {
1365 ret = task_suspend (inferior_task);
c5aa993b 1366
c906108c
SS
1367 if (ret != KERN_SUCCESS)
1368 {
1369 warning ("Could not suspend task for interrupt: %s",
1370 mach_error_string (ret));
1371 mach_really_waiting = 0;
1372 return;
1373 }
1374 }
1375
1376 must_suspend_thread = 0;
1377 mach_really_waiting = 0;
1378
1379 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1380 if (mid == -1)
1381 {
1382 warning ("Selecting first existing kernel thread");
1383 mid = 0;
1384 }
1385
c5aa993b 1386 current_thread = MACH_PORT_NULL; /* Force setup */
c906108c
SS
1387 select_thread (inferior_task, mid, 1);
1388
1389 return;
1390}
1391
1392#if 0
1393/* bogus bogus bogus. It is NOT OK to quit out of target_wait. */
1394
1395/* If ^C is typed when we are waiting for a message
1396 * and your Unix server is able to notice that we
1397 * should quit now.
1398 *
1399 * Called by REQUEST_QUIT() from utils.c(request_quit)
1400 */
1401void
fba45db2 1402mach3_request_quit (void)
c906108c
SS
1403{
1404 if (mach_really_waiting)
1405 immediate_quit = 1;
c5aa993b 1406}
c906108c
SS
1407#endif
1408
1409/*
1410 * Gdb message server.
1411 * Currently implemented is the STOP message, that causes
1412 * gdb to return to the command level like ^C had been typed from terminal.
1413 */
1414int
fba45db2 1415gdb_message_server (mach_msg_header_t *InP)
c906108c
SS
1416{
1417 kern_return_t ret;
1418 int mid;
1419
1420 if (InP->msgh_local_port == our_message_port)
1421 {
1422 /* A message coming to our_message_port. Check validity */
c5aa993b
JM
1423 switch (InP->msgh_id)
1424 {
c906108c 1425
c5aa993b
JM
1426 case GDB_MESSAGE_ID_STOP:
1427 ret = task_suspend (inferior_task);
1428 if (ret != KERN_SUCCESS)
1429 warning ("Could not suspend task for stop message: %s",
1430 mach_error_string (ret));
c906108c 1431
c5aa993b
JM
1432 /* QUIT in mach_really_wait() loop. */
1433 request_quit (0);
1434 break;
c906108c 1435
c5aa993b
JM
1436 default:
1437 warning ("Invalid message id %d received, ignored.",
1438 InP->msgh_id);
1439 break;
1440 }
c906108c
SS
1441
1442 return 1;
1443 }
1444
1445 /* Message not handled by this server */
1446 return 0;
1447}
1448
1449/* NOTE: This is not an RPC call. It is a simpleroutine.
c5aa993b 1450
c906108c
SS
1451 * This is not called from this gdb code.
1452 *
1453 * It may be called by another debugger to cause this
1454 * debugger to enter command level:
1455 *
1456 * (gdb) set stop_inferior_gdb ()
1457 * (gdb) continue
1458 *
1459 * External program "stop-gdb" implements this also.
1460 */
1461void
fba45db2 1462stop_inferior_gdb (void)
c906108c
SS
1463{
1464 kern_return_t ret;
1465
1466 /* Code generated by mig, with minor cleanups :-)
c5aa993b 1467
c906108c
SS
1468 * simpleroutine stop_inferior_gdb (our_message_port : mach_port_t);
1469 */
1470
c5aa993b
JM
1471 typedef struct
1472 {
1473 mach_msg_header_t Head;
1474 }
1475 Request;
c906108c
SS
1476
1477 Request Mess;
1478
1479 register Request *InP = &Mess;
1480
c5aa993b 1481 InP->Head.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
c906108c
SS
1482
1483 /* msgh_size passed as argument */
1484 InP->Head.msgh_remote_port = our_message_port;
c5aa993b
JM
1485 InP->Head.msgh_local_port = MACH_PORT_NULL;
1486 InP->Head.msgh_seqno = 0;
1487 InP->Head.msgh_id = GDB_MESSAGE_ID_STOP;
c906108c
SS
1488
1489 ret = mach_msg (&InP->Head,
c5aa993b
JM
1490 MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
1491 sizeof (Request),
c906108c
SS
1492 0,
1493 MACH_PORT_NULL,
1494 MACH_MSG_TIMEOUT_NONE,
1495 MACH_PORT_NULL);
1496}
1497
1498#ifdef THREAD_ALLOWED_TO_BREAK
1499/*
1500 * Return 1 if the MID specifies the thread that caused the
1501 * last exception.
1502 * Since catch_exception_raise() selects the thread causing
1503 * the last exception to current_thread, we just check that
1504 * it is selected and the last exception was a breakpoint.
1505 */
1506int
fba45db2 1507mach_thread_for_breakpoint (int mid)
c906108c
SS
1508{
1509 int cmid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
1510
1511 if (mid < 0)
1512 {
c5aa993b 1513 mid = map_slot_to_mid (-(mid + 1), 0, 0);
c906108c
SS
1514 if (mid < 0)
1515 return 0; /* Don't stop, no such slot */
1516 }
1517
c5aa993b
JM
1518 if (!mid || cmid == -1)
1519 return 1; /* stop */
c906108c
SS
1520
1521 return cmid == mid && stop_exception == EXC_BREAKPOINT;
1522}
1523#endif /* THREAD_ALLOWED_TO_BREAK */
1524
1525#ifdef THREAD_PARSE_ID
1526/*
1527 * Map a thread id string (MID or a @SLOTNUMBER)
1528 * to a thread-id.
1529 *
1530 * 0 matches all threads.
1531 * Otherwise the meaning is defined only in this file.
1532 * (mach_thread_for_breakpoint uses it)
1533 *
1534 * @@ This allows non-existent MIDs to be specified.
1535 * It now also allows non-existent slots to be
1536 * specified. (Slot numbers stored are negative,
1537 * and the magnitude is one greater than the actual
1538 * slot index. (Since 0 is reserved))
1539 */
1540int
fba45db2 1541mach_thread_parse_id (char *arg)
c906108c
SS
1542{
1543 int mid;
1544 if (arg == 0)
8e1a459b 1545 error ("thread id expected");
c906108c
SS
1546 mid = parse_thread_id (arg, 0, 1);
1547
1548 return mid;
1549}
1550#endif /* THREAD_PARSE_ID */
1551
1552#ifdef THREAD_OUTPUT_ID
1553char *
fba45db2 1554mach_thread_output_id (int mid)
c906108c 1555{
c5aa993b 1556 static char foobar[20];
c906108c
SS
1557
1558 if (mid > 0)
1559 sprintf (foobar, "mid %d", mid);
1560 else if (mid < 0)
c5aa993b 1561 sprintf (foobar, "@%d", -(mid + 1));
c906108c
SS
1562 else
1563 sprintf (foobar, "*any thread*");
1564
1565 return foobar;
1566}
1567#endif /* THREAD_OUTPUT_ID */
1568
1569/* Called with hook PREPARE_TO_PROCEED() from infrun.c.
c5aa993b 1570
c906108c
SS
1571 * If we have switched threads and stopped at breakpoint return 1 otherwise 0.
1572 *
1573 * if SELECT_IT is nonzero, reselect the thread that was active when
1574 * we stopped at a breakpoint.
1575 *
e02bc4cc
DS
1576 * Note that this implementation is potentially redundant now that
1577 * default_prepare_to_proceed() has been added.
c906108c
SS
1578 */
1579
fba45db2 1580mach3_prepare_to_proceed (int select_it)
c906108c
SS
1581{
1582 if (stop_thread &&
1583 stop_thread != current_thread &&
1584 stop_exception == EXC_BREAKPOINT)
1585 {
1586 int mid;
1587
c5aa993b 1588 if (!select_it)
c906108c
SS
1589 return 1;
1590
1591 mid = switch_to_thread (stop_thread);
1592
1593 return 1;
1594 }
1595
1596 return 0;
1597}
1598
1599/* this stuff here is an upcall via libmach/excServer.c
1600 and mach_really_wait which does the actual upcall.
1601
1602 The code will pass the exception to the inferior if:
1603
c5aa993b
JM
1604 - The task that signaled is not the inferior task
1605 (e.g. when debugging another debugger)
c906108c 1606
c5aa993b
JM
1607 - The user has explicitely requested to pass on the exceptions.
1608 (e.g to the default unix exception handler, which maps
1609 exceptions to signals, or the user has her own exception handler)
c906108c 1610
c5aa993b
JM
1611 - If the thread that signaled is being single-stepped and it
1612 has set it's own exception port and the exception is not
1613 EXC_BREAKPOINT. (Maybe this is not desirable?)
c906108c
SS
1614 */
1615
1616kern_return_t
fba45db2
KB
1617catch_exception_raise (mach_port_t port, thread_t thread, task_t task,
1618 int exception, int code, int subcode)
c906108c
SS
1619{
1620 kern_return_t ret;
1621 boolean_t signal_thread;
1622 int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
1623
c5aa993b 1624 if (!MACH_PORT_VALID (thread))
c906108c
SS
1625 {
1626 /* If the exception was sent and thread dies before we
c5aa993b 1627 receive it, THREAD will be MACH_PORT_DEAD
c906108c
SS
1628 */
1629
1630 current_thread = thread = MACH_PORT_NULL;
1631 error ("Received exception from nonexistent thread");
1632 }
1633
1634 /* Check if the task died in transit.
1635 * @@ Isn't the thread also invalid in such case?
1636 */
c5aa993b 1637 if (!MACH_PORT_VALID (task))
c906108c
SS
1638 {
1639 current_thread = thread = MACH_PORT_NULL;
1640 error ("Received exception from nonexistent task");
1641 }
1642
1643 if (exception < 0 || exception > MAX_EXCEPTION)
8e65ff28
AC
1644 internal_error (__FILE__, __LINE__,
1645 "catch_exception_raise: unknown exception code %d thread %d",
96baa820
JM
1646 exception,
1647 mid);
c906108c 1648
c5aa993b 1649 if (!MACH_PORT_VALID (inferior_task))
c906108c 1650 error ("got an exception, but inferior_task is null or dead");
c5aa993b 1651
c906108c 1652 stop_exception = exception;
c5aa993b
JM
1653 stop_code = code;
1654 stop_subcode = subcode;
1655 stop_thread = thread;
1656
1657 signal_thread = exception != EXC_BREAKPOINT &&
1658 port == singlestepped_thread_port &&
1659 MACH_PORT_VALID (thread_saved_exception_port);
c906108c
SS
1660
1661 /* If it was not our inferior or if we want to forward
1662 * the exception to the inferior's handler, do it here
1663 *
1664 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1665 */
1666 if (task != inferior_task ||
c5aa993b
JM
1667 signal_thread ||
1668 exception_map[exception].forward)
c906108c
SS
1669 {
1670 mach_port_t eport = inferior_old_exception_port;
1671
1672 if (signal_thread)
1673 {
1674 /*
c5aa993b
JM
1675 GDB now forwards the exeption to thread's original handler,
1676 since the user propably knows what he is doing.
1677 Give a message, though.
c906108c
SS
1678 */
1679
c5aa993b 1680 mach3_exception_actions ((WAITTYPE *) NULL, TRUE, "Thread");
c906108c
SS
1681 eport = thread_saved_exception_port;
1682 }
1683
1684 /* Send the exception to the original handler */
1685 ret = exception_raise (eport,
c5aa993b 1686 thread,
c906108c
SS
1687 task,
1688 exception,
1689 code,
1690 subcode);
1691
1692 (void) mach_port_deallocate (mach_task_self (), task);
1693 (void) mach_port_deallocate (mach_task_self (), thread);
1694
1695 /* If we come here, we don't want to trace any more, since we
1696 * will never stop for tracing anyway.
1697 */
1698 discard_single_step (thread);
1699
1700 /* Do not stop the inferior */
1701 return ret;
1702 }
c5aa993b 1703
c906108c
SS
1704 /* Now gdb handles the exception */
1705 stopped_in_exception = TRUE;
1706
1707 ret = task_suspend (task);
1708 CHK ("Error suspending inferior after exception", ret);
1709
1710 must_suspend_thread = 0;
1711
1712 if (current_thread != thread)
1713 {
1714 if (MACH_PORT_VALID (singlestepped_thread_port))
1715 /* Cleanup discards single stepping */
1716 error ("Exception from thread %d while singlestepping thread %d",
1717 mid,
1718 map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
c5aa993b 1719
c906108c
SS
1720 /* Then select the thread that caused the exception */
1721 if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
1722 error ("Could not select thread %d causing exception", mid);
1723 else
1724 warning ("Gdb selected thread %d", mid);
1725 }
1726
1727 /* If we receive an exception that is not breakpoint
1728 * exception, we interrupt the single step and return to
1729 * debugger. Trace condition is cleared.
1730 */
1731 if (MACH_PORT_VALID (singlestepped_thread_port))
1732 {
1733 if (stop_exception != EXC_BREAKPOINT)
1734 warning ("Single step interrupted by exception");
1735 else if (port == singlestepped_thread_port)
1736 {
1737 /* Single step exception occurred, remove trace bit
1738 * and return to gdb.
1739 */
c5aa993b 1740 if (!MACH_PORT_VALID (current_thread))
c906108c 1741 error ("Single stepped thread is not valid");
c5aa993b 1742
c906108c
SS
1743 /* Resume threads, but leave the task suspended */
1744 resume_all_threads (0);
1745 }
1746 else
1747 warning ("Breakpoint while single stepping?");
1748
1749 discard_single_step (current_thread);
1750 }
c5aa993b 1751
c906108c
SS
1752 (void) mach_port_deallocate (mach_task_self (), task);
1753 (void) mach_port_deallocate (mach_task_self (), thread);
1754
1755 return KERN_SUCCESS;
1756}
1757\f
1758int
fba45db2 1759port_valid (mach_port_t port, int mask)
c906108c
SS
1760{
1761 kern_return_t ret;
1762 mach_port_type_t type;
1763
1764 ret = mach_port_type (mach_task_self (),
1765 port,
1766 &type);
1767 if (ret != KERN_SUCCESS || (type & mask) != mask)
1768 return 0;
1769 return 1;
1770}
1771\f
1772/* @@ No vm read cache implemented yet */
1773boolean_t vm_read_cache_valid = FALSE;
1774
1775/*
1776 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1777 * in gdb's address space.
1778 *
1779 * Return 0 on failure; number of bytes read otherwise.
1780 */
1781int
fba45db2 1782mach3_read_inferior (CORE_ADDR addr, char *myaddr, int length)
c906108c
SS
1783{
1784 kern_return_t ret;
c5aa993b
JM
1785 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1786 vm_size_t aligned_length =
1787 (vm_size_t) round_page (addr + length) - low_address;
1788 pointer_t copied_memory;
1789 int copy_count;
c906108c
SS
1790
1791 /* Get memory from inferior with page aligned addresses */
1792 ret = vm_read (inferior_task,
1793 low_address,
1794 aligned_length,
1795 &copied_memory,
1796 &copy_count);
1797 if (ret != KERN_SUCCESS)
1798 {
1799 /* the problem is that the inferior might be killed for whatever reason
1800 * before we go to mach_really_wait. This is one place that ought to
1801 * catch many of those errors.
1802 * @@ A better fix would be to make all external events to GDB
1803 * to arrive via a SINGLE port set. (Including user input!)
1804 */
1805
c5aa993b 1806 if (!port_valid (inferior_task, MACH_PORT_TYPE_SEND))
c906108c
SS
1807 {
1808 m3_kill_inferior ();
1809 error ("Inferior killed (task port invalid)");
1810 }
1811 else
1812 {
1813#ifdef OSF
1814 extern int errno;
1815 /* valprint.c gives nicer format if this does not
1816 screw it. Eamonn seems to like this, so I enable
1817 it if OSF is defined...
1818 */
1819 warning ("[read inferior %x failed: %s]",
1820 addr, mach_error_string (ret));
1821 errno = 0;
1822#endif
1823 return 0;
1824 }
1825 }
1826
c5aa993b 1827 memcpy (myaddr, (char *) addr - low_address + copied_memory, length);
c906108c
SS
1828
1829 ret = vm_deallocate (mach_task_self (),
1830 copied_memory,
1831 copy_count);
c5aa993b 1832 CHK ("mach3_read_inferior vm_deallocate failed", ret);
c906108c
SS
1833
1834 return length;
1835}
1836
c906108c
SS
1837#define CHK_GOTO_OUT(str,ret) \
1838 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
c906108c 1839
c5aa993b
JM
1840struct vm_region_list
1841{
c906108c 1842 struct vm_region_list *next;
c5aa993b
JM
1843 vm_prot_t protection;
1844 vm_address_t start;
1845 vm_size_t length;
c906108c
SS
1846};
1847
c5aa993b 1848struct obstack region_obstack;
c906108c
SS
1849
1850/*
1851 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1852 * in gdb's address space.
1853 */
1854int
fba45db2 1855mach3_write_inferior (CORE_ADDR addr, char *myaddr, int length)
c906108c
SS
1856{
1857 kern_return_t ret;
c5aa993b
JM
1858 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1859 vm_size_t aligned_length =
1860 (vm_size_t) round_page (addr + length) - low_address;
1861 pointer_t copied_memory;
1862 int copy_count;
1863 int deallocate = 0;
c906108c 1864
c5aa993b 1865 char *errstr = "Bug in mach3_write_inferior";
c906108c
SS
1866
1867 struct vm_region_list *region_element;
c5aa993b 1868 struct vm_region_list *region_head = (struct vm_region_list *) NULL;
c906108c
SS
1869
1870 /* Get memory from inferior with page aligned addresses */
1871 ret = vm_read (inferior_task,
1872 low_address,
1873 aligned_length,
1874 &copied_memory,
1875 &copy_count);
1876 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
1877
1878 deallocate++;
1879
c5aa993b 1880 memcpy ((char *) addr - low_address + copied_memory, myaddr, length);
c906108c
SS
1881
1882 obstack_init (&region_obstack);
1883
1884 /* Do writes atomically.
1885 * First check for holes and unwritable memory.
1886 */
1887 {
c5aa993b
JM
1888 vm_size_t remaining_length = aligned_length;
1889 vm_address_t region_address = low_address;
c906108c
SS
1890
1891 struct vm_region_list *scan;
1892
c5aa993b 1893 while (region_address < low_address + aligned_length)
c906108c
SS
1894 {
1895 vm_prot_t protection;
1896 vm_prot_t max_protection;
1897 vm_inherit_t inheritance;
1898 boolean_t shared;
1899 mach_port_t object_name;
1900 vm_offset_t offset;
c5aa993b
JM
1901 vm_size_t region_length = remaining_length;
1902 vm_address_t old_address = region_address;
1903
c906108c
SS
1904 ret = vm_region (inferior_task,
1905 &region_address,
1906 &region_length,
1907 &protection,
1908 &max_protection,
1909 &inheritance,
1910 &shared,
1911 &object_name,
1912 &offset);
1913 CHK_GOTO_OUT ("vm_region failed", ret);
1914
1915 /* Check for holes in memory */
1916 if (old_address != region_address)
1917 {
1918 warning ("No memory at 0x%x. Nothing written",
1919 old_address);
1920 ret = KERN_SUCCESS;
1921 length = 0;
1922 goto out;
1923 }
1924
1925 if (!(max_protection & VM_PROT_WRITE))
1926 {
1927 warning ("Memory at address 0x%x is unwritable. Nothing written",
1928 old_address);
1929 ret = KERN_SUCCESS;
1930 length = 0;
1931 goto out;
1932 }
1933
1934 /* Chain the regions for later use */
c5aa993b 1935 region_element =
c906108c 1936 (struct vm_region_list *)
c5aa993b
JM
1937 obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
1938
c906108c 1939 region_element->protection = protection;
c5aa993b
JM
1940 region_element->start = region_address;
1941 region_element->length = region_length;
c906108c
SS
1942
1943 /* Chain the regions along with protections */
1944 region_element->next = region_head;
c5aa993b
JM
1945 region_head = region_element;
1946
c906108c
SS
1947 region_address += region_length;
1948 remaining_length = remaining_length - region_length;
1949 }
1950
1951 /* If things fail after this, we give up.
1952 * Somebody is messing up inferior_task's mappings.
1953 */
c5aa993b 1954
c906108c
SS
1955 /* Enable writes to the chained vm regions */
1956 for (scan = region_head; scan; scan = scan->next)
1957 {
1958 boolean_t protection_changed = FALSE;
c5aa993b 1959
c906108c
SS
1960 if (!(scan->protection & VM_PROT_WRITE))
1961 {
1962 ret = vm_protect (inferior_task,
1963 scan->start,
1964 scan->length,
1965 FALSE,
1966 scan->protection | VM_PROT_WRITE);
1967 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1968 }
1969 }
1970
1971 ret = vm_write (inferior_task,
1972 low_address,
1973 copied_memory,
1974 aligned_length);
1975 CHK_GOTO_OUT ("vm_write failed", ret);
c5aa993b 1976
c906108c
SS
1977 /* Set up the original region protections, if they were changed */
1978 for (scan = region_head; scan; scan = scan->next)
1979 {
1980 boolean_t protection_changed = FALSE;
c5aa993b 1981
c906108c
SS
1982 if (!(scan->protection & VM_PROT_WRITE))
1983 {
1984 ret = vm_protect (inferior_task,
1985 scan->start,
1986 scan->length,
1987 FALSE,
1988 scan->protection);
1989 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1990 }
1991 }
1992 }
1993
c5aa993b 1994out:
c906108c
SS
1995 if (deallocate)
1996 {
1997 obstack_free (&region_obstack, 0);
c5aa993b 1998
c906108c
SS
1999 (void) vm_deallocate (mach_task_self (),
2000 copied_memory,
2001 copy_count);
2002 }
2003
2004 if (ret != KERN_SUCCESS)
2005 {
2006 warning ("%s %s", errstr, mach_error_string (ret));
2007 return 0;
2008 }
2009
2010 return length;
2011}
2012
ad525611
KB
2013/* Return 0 on failure, number of bytes handled otherwise. TARGET is
2014 ignored. */
c906108c 2015static int
ad525611
KB
2016m3_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
2017 struct target_ops *target)
c906108c
SS
2018{
2019 int result;
2020
2021 if (write)
2022 result = mach3_write_inferior (memaddr, myaddr, len);
2023 else
c5aa993b 2024 result = mach3_read_inferior (memaddr, myaddr, len);
c906108c
SS
2025
2026 return result;
2027}
c906108c 2028\f
c5aa993b 2029
c906108c 2030static char *
fba45db2 2031translate_state (int state)
c906108c 2032{
c5aa993b
JM
2033 switch (state)
2034 {
2035 case TH_STATE_RUNNING:
2036 return ("R");
2037 case TH_STATE_STOPPED:
2038 return ("S");
2039 case TH_STATE_WAITING:
2040 return ("W");
2041 case TH_STATE_UNINTERRUPTIBLE:
2042 return ("U");
2043 case TH_STATE_HALTED:
2044 return ("H");
2045 default:
2046 return ("?");
2047 }
c906108c
SS
2048}
2049
2050static char *
fba45db2 2051translate_cstate (int state)
c906108c
SS
2052{
2053 switch (state)
2054 {
c5aa993b
JM
2055 case CPROC_RUNNING:
2056 return "R";
2057 case CPROC_SWITCHING:
2058 return "S";
2059 case CPROC_BLOCKED:
2060 return "B";
2061 case CPROC_CONDWAIT:
2062 return "C";
2063 case CPROC_CONDWAIT | CPROC_SWITCHING:
2064 return "CS";
2065 default:
2066 return "?";
c906108c
SS
2067 }
2068}
2069
2070/* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2071
c5aa993b 2072mach_port_t /* no mach_port_name_t found in include files. */
fba45db2 2073map_inferior_port_name (mach_port_t inferior_name, mach_msg_type_name_t type)
c906108c 2074{
c5aa993b 2075 kern_return_t ret;
c906108c 2076 mach_msg_type_name_t acquired;
c5aa993b
JM
2077 mach_port_t iport;
2078
c906108c
SS
2079 ret = mach_port_extract_right (inferior_task,
2080 inferior_name,
2081 type,
2082 &iport,
2083 &acquired);
c5aa993b 2084 CHK ("mach_port_extract_right (map_inferior_port_name)", ret);
c906108c
SS
2085
2086 if (acquired != MACH_MSG_TYPE_PORT_SEND)
c5aa993b 2087 error ("Incorrect right extracted, (map_inferior_port_name)");
c906108c
SS
2088
2089 ret = mach_port_deallocate (mach_task_self (),
2090 iport);
2091 CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
2092
2093 return iport;
2094}
2095
2096/*
2097 * Naming convention:
2098 * Always return user defined name if found.
2099 * _K == A kernel thread with no matching CPROC
2100 * _C == A cproc with no current cthread
2101 * _t == A cthread with no user defined name
2102 *
2103 * The digits that follow the _names are the SLOT number of the
2104 * kernel thread if there is such a thing, otherwise just a negation
2105 * of the sequential number of such cprocs.
2106 */
2107
2108static char buf[7];
2109
2110static char *
fba45db2 2111get_thread_name (gdb_thread_t one_cproc, int id)
c906108c
SS
2112{
2113 if (one_cproc)
2114 if (one_cproc->cthread == NULL)
2115 {
2116 /* cproc not mapped to any cthread */
c5aa993b 2117 sprintf (buf, "_C%d", id);
c906108c 2118 }
c5aa993b 2119 else if (!one_cproc->cthread->name)
c906108c
SS
2120 {
2121 /* cproc and cthread, but no name */
c5aa993b 2122 sprintf (buf, "_t%d", id);
c906108c
SS
2123 }
2124 else
c5aa993b 2125 return (char *) (one_cproc->cthread->name);
c906108c
SS
2126 else
2127 {
2128 if (id < 0)
2129 warning ("Inconsistency in thread name id %d", id);
2130
2131 /* Kernel thread without cproc */
c5aa993b 2132 sprintf (buf, "_K%d", id);
c906108c
SS
2133 }
2134
2135 return buf;
2136}
2137
2138int
ad525611 2139fetch_thread_info (mach_port_t task, gdb_thread_t *mthreads_out)
c906108c 2140{
c5aa993b 2141 kern_return_t ret;
c906108c 2142 thread_array_t th_table;
c5aa993b 2143 int th_count;
c906108c 2144 gdb_thread_t mthreads = NULL;
c5aa993b 2145 int index;
c906108c
SS
2146
2147 ret = task_threads (task, &th_table, &th_count);
2148 if (ret != KERN_SUCCESS)
2149 {
2150 warning ("Error getting inferior's thread list:%s",
c5aa993b 2151 mach_error_string (ret));
c906108c
SS
2152 m3_kill_inferior ();
2153 return -1;
2154 }
c5aa993b 2155
c906108c 2156 mthreads = (gdb_thread_t)
c5aa993b
JM
2157 obstack_alloc
2158 (cproc_obstack,
2159 th_count * sizeof (struct gdb_thread));
c906108c
SS
2160
2161 for (index = 0; index < th_count; index++)
2162 {
2163 thread_t saved_thread = MACH_PORT_NULL;
2164 int mid;
2165
2166 if (must_suspend_thread)
c5aa993b 2167 setup_thread (th_table[index], 1);
c906108c
SS
2168
2169 if (th_table[index] != current_thread)
2170 {
2171 saved_thread = current_thread;
c5aa993b
JM
2172
2173 mid = switch_to_thread (th_table[index]);
c906108c
SS
2174 }
2175
c5aa993b 2176 mthreads[index].name = th_table[index];
c906108c
SS
2177 mthreads[index].cproc = NULL; /* map_cprocs_to_kernel_threads() */
2178 mthreads[index].in_emulator = FALSE;
2179 mthreads[index].slotid = index;
c5aa993b 2180
c906108c
SS
2181 mthreads[index].sp = read_register (SP_REGNUM);
2182 mthreads[index].fp = read_register (FP_REGNUM);
2183 mthreads[index].pc = read_pc ();
2184
2185 if (MACH_PORT_VALID (saved_thread))
2186 mid = switch_to_thread (saved_thread);
2187
2188 if (must_suspend_thread)
c5aa993b 2189 setup_thread (th_table[index], 0);
c906108c 2190 }
c5aa993b 2191
c906108c 2192 consume_send_rights (th_table, th_count);
c5aa993b
JM
2193 ret = vm_deallocate (mach_task_self (), (vm_address_t) th_table,
2194 (th_count * sizeof (mach_port_t)));
c906108c
SS
2195 if (ret != KERN_SUCCESS)
2196 {
2197 warning ("Error trying to deallocate thread list : %s",
2198 mach_error_string (ret));
2199 }
2200
2201 *mthreads_out = mthreads;
2202
2203 return th_count;
2204}
2205
2206
2207/*
2208 * Current emulator always saves the USP on top of
2209 * emulator stack below struct emul_stack_top stuff.
2210 */
2211CORE_ADDR
fba45db2 2212fetch_usp_from_emulator_stack (CORE_ADDR sp)
c906108c
SS
2213{
2214 CORE_ADDR stack_pointer;
2215
c5aa993b
JM
2216 sp = (sp & ~(EMULATOR_STACK_SIZE - 1)) +
2217 EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
2218
c906108c
SS
2219 if (mach3_read_inferior (sp,
2220 &stack_pointer,
2221 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2222 {
2223 warning ("Can't read user sp from emulator stack address 0x%x", sp);
2224 return 0;
2225 }
2226
2227 return stack_pointer;
2228}
2229
2230#ifdef MK67
2231
2232/* get_emulation_vector() interface was changed after mk67 */
2233#define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2234
2235#endif /* MK67 */
2236
2237/* Check if the emulator exists at task's address space.
2238 */
2239boolean_t
fba45db2 2240have_emulator_p (task_t task)
c906108c 2241{
c5aa993b 2242 kern_return_t ret;
c906108c 2243#ifndef EMUL_VECTOR_COUNT
c5aa993b
JM
2244 vm_offset_t *emulation_vector;
2245 int n;
c906108c 2246#else
c5aa993b
JM
2247 vm_offset_t emulation_vector[EMUL_VECTOR_COUNT];
2248 int n = EMUL_VECTOR_COUNT;
c906108c 2249#endif
c5aa993b
JM
2250 int i;
2251 int vector_start;
2252
c906108c
SS
2253 ret = task_get_emulation_vector (task,
2254 &vector_start,
2255#ifndef EMUL_VECTOR_COUNT
2256 &emulation_vector,
2257#else
2258 emulation_vector,
2259#endif
2260 &n);
c5aa993b 2261 CHK ("task_get_emulation_vector", ret);
c906108c
SS
2262 xx_debug ("%d vectors from %d at 0x%08x\n",
2263 n, vector_start, emulation_vector);
c5aa993b
JM
2264
2265 for (i = 0; i < n; i++)
c906108c 2266 {
c5aa993b 2267 vm_offset_t entry = emulation_vector[i];
c906108c
SS
2268
2269 if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
2270 return TRUE;
2271 else if (entry)
2272 {
2273 static boolean_t informed = FALSE;
2274 if (!informed)
2275 {
c5aa993b
JM
2276 warning ("Emulation vector address 0x08%x outside emulator space",
2277 entry);
c906108c
SS
2278 informed = TRUE;
2279 }
2280 }
2281 }
2282 return FALSE;
2283}
2284
2285/* Map cprocs to kernel threads and vice versa. */
2286
2287void
fba45db2
KB
2288map_cprocs_to_kernel_threads (gdb_thread_t cprocs, gdb_thread_t mthreads,
2289 int thread_count)
c906108c
SS
2290{
2291 int index;
2292 gdb_thread_t scan;
2293 boolean_t all_mapped = TRUE;
2294 LONGEST stack_base;
2295 LONGEST stack_size;
2296
2297 for (scan = cprocs; scan; scan = scan->next)
2298 {
2299 /* Default to: no kernel thread for this cproc */
2300 scan->reverse_map = -1;
2301
2302 /* Check if the cproc is found by its stack */
2303 for (index = 0; index < thread_count; index++)
2304 {
2305 stack_base =
2306 extract_signed_integer (scan->raw_cproc + CPROC_BASE_OFFSET,
2307 CPROC_BASE_SIZE);
c5aa993b 2308 stack_size =
c906108c
SS
2309 extract_signed_integer (scan->raw_cproc + CPROC_SIZE_OFFSET,
2310 CPROC_SIZE_SIZE);
2311 if ((mthreads + index)->sp > stack_base &&
2312 (mthreads + index)->sp <= stack_base + stack_size)
2313 {
2314 (mthreads + index)->cproc = scan;
2315 scan->reverse_map = index;
2316 break;
2317 }
2318 }
2319 all_mapped &= (scan->reverse_map != -1);
2320 }
2321
2322 /* Check for threads that are currently in the emulator.
2323 * If so, they have a different stack, and the still unmapped
2324 * cprocs may well get mapped to these threads.
2325 *
2326 * If:
2327 * - cproc stack does not match any kernel thread stack pointer
2328 * - there is at least one extra kernel thread
2329 * that has no cproc mapped above.
2330 * - some kernel thread stack pointer points to emulator space
2331 * then we find the user stack pointer saved in the emulator
2332 * stack, and try to map that to the cprocs.
2333 *
2334 * Also set in_emulator for kernel threads.
c5aa993b 2335 */
c906108c
SS
2336
2337 if (emulator_present)
2338 {
2339 for (index = 0; index < thread_count; index++)
2340 {
2341 CORE_ADDR emul_sp;
2342 CORE_ADDR usp;
2343
c5aa993b 2344 gdb_thread_t mthread = (mthreads + index);
c906108c
SS
2345 emul_sp = mthread->sp;
2346
2347 if (mthread->cproc == NULL &&
2348 EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
2349 {
2350 mthread->in_emulator = emulator_present;
c5aa993b 2351
c906108c
SS
2352 if (!all_mapped && cprocs)
2353 {
2354 usp = fetch_usp_from_emulator_stack (emul_sp);
c5aa993b 2355
c906108c 2356 /* @@ Could be more accurate */
c5aa993b 2357 if (!usp)
c906108c 2358 error ("Zero stack pointer read from emulator?");
c5aa993b 2359
c906108c
SS
2360 /* Try to match this stack pointer to the cprocs that
2361 * don't yet have a kernel thread.
2362 */
2363 for (scan = cprocs; scan; scan = scan->next)
2364 {
c5aa993b 2365
c906108c
SS
2366 /* Check is this unmapped CPROC stack contains
2367 * the user stack pointer saved in the
2368 * emulator.
2369 */
2370 if (scan->reverse_map == -1)
2371 {
2372 stack_base =
2373 extract_signed_integer
c5aa993b
JM
2374 (scan->raw_cproc + CPROC_BASE_OFFSET,
2375 CPROC_BASE_SIZE);
2376 stack_size =
c906108c 2377 extract_signed_integer
c5aa993b
JM
2378 (scan->raw_cproc + CPROC_SIZE_OFFSET,
2379 CPROC_SIZE_SIZE);
c906108c
SS
2380 if (usp > stack_base &&
2381 usp <= stack_base + stack_size)
2382 {
2383 mthread->cproc = scan;
2384 scan->reverse_map = index;
2385 break;
2386 }
2387 }
2388 }
2389 }
2390 }
2391 }
2392 }
2393}
2394\f
2395/*
2396 * Format of the thread_list command
2397 *
c5aa993b 2398 * slot mid sel name emul ks susp cstate wired address
c906108c
SS
2399 */
2400#define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2401
2402#define TL_HEADER "\n@ MID Name KState CState Where\n"
2403
2404void
fba45db2 2405print_tl_address (struct ui_file *stream, CORE_ADDR pc)
c906108c 2406{
c5aa993b
JM
2407 if (!lookup_minimal_symbol_by_pc (pc))
2408 fprintf_filtered (stream, local_hex_format (), pc);
c906108c
SS
2409 else
2410 {
2411 extern int addressprint;
2412 extern int asm_demangle;
2413
c5aa993b 2414 int store = addressprint;
c906108c
SS
2415 addressprint = 0;
2416 print_address_symbolic (pc, stream, asm_demangle, "");
2417 addressprint = store;
2418 }
2419}
2420\f
2421/* For thread names, but also for gdb_message_port external name */
2422#define MAX_NAME_LEN 50
2423
2424/* Returns the address of variable NAME or 0 if not found */
2425CORE_ADDR
fba45db2 2426lookup_address_of_variable (char *name)
c906108c
SS
2427{
2428 struct symbol *sym;
2429 CORE_ADDR symaddr = 0;
2430 struct minimal_symbol *msymbol;
2431
2432 sym = lookup_symbol (name,
c5aa993b 2433 (struct block *) NULL,
c906108c 2434 VAR_NAMESPACE,
c5aa993b
JM
2435 (int *) NULL,
2436 (struct symtab **) NULL);
c906108c
SS
2437
2438 if (sym)
2439 symaddr = SYMBOL_VALUE (sym);
2440
c5aa993b 2441 if (!symaddr)
c906108c
SS
2442 {
2443 msymbol = lookup_minimal_symbol (name, NULL, NULL);
2444
2445 if (msymbol && msymbol->type == mst_data)
2446 symaddr = SYMBOL_VALUE_ADDRESS (msymbol);
2447 }
2448
2449 return symaddr;
2450}
2451
2452static gdb_thread_t
fba45db2 2453get_cprocs (void)
c906108c
SS
2454{
2455 gdb_thread_t cproc_head;
2456 gdb_thread_t cproc_copy;
2457 CORE_ADDR their_cprocs;
35fc8285 2458 char *buf;
c906108c
SS
2459 char *name;
2460 cthread_t cthread;
2461 CORE_ADDR symaddr;
c5aa993b 2462
35fc8285 2463 buf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT);
c906108c
SS
2464 symaddr = lookup_address_of_variable ("cproc_list");
2465
c5aa993b 2466 if (!symaddr)
c906108c
SS
2467 {
2468 /* cproc_list is not in a file compiled with debugging
c5aa993b 2469 symbols, but don't give up yet */
c906108c
SS
2470
2471 symaddr = lookup_address_of_variable ("cprocs");
2472
2473 if (symaddr)
2474 {
2475 static int informed = 0;
2476 if (!informed)
2477 {
2478 informed++;
2479 warning ("Your program is loaded with an old threads library.");
2480 warning ("GDB does not know the old form of threads");
2481 warning ("so things may not work.");
2482 }
2483 }
2484 }
2485
2486 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
c5aa993b 2487 if (!symaddr)
c906108c
SS
2488 return NULL;
2489
2490 /* Get the address of the first cproc in the task */
2491 if (!mach3_read_inferior (symaddr,
2492 buf,
2493 TARGET_PTR_BIT / HOST_CHAR_BIT))
2494 error ("Can't read cproc master list at address (0x%x).", symaddr);
2495 their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
2496
2497 /* Scan the CPROCs in the task.
2498 CPROCs are chained with LIST field, not NEXT field, which
2499 chains mutexes, condition variables and queues */
2500
2501 cproc_head = NULL;
2502
c5aa993b 2503 while (their_cprocs != (CORE_ADDR) 0)
c906108c
SS
2504 {
2505 CORE_ADDR cproc_copy_incarnation;
2506 cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
2507 sizeof (struct gdb_thread));
2508
2509 if (!mach3_read_inferior (their_cprocs,
2510 &cproc_copy->raw_cproc[0],
2511 CPROC_SIZE))
c5aa993b 2512 error ("Can't read next cproc at 0x%x.", their_cprocs);
c906108c
SS
2513
2514 their_cprocs =
2515 extract_address (cproc_copy->raw_cproc + CPROC_LIST_OFFSET,
2516 CPROC_LIST_SIZE);
2517 cproc_copy_incarnation =
2518 extract_address (cproc_copy->raw_cproc + CPROC_INCARNATION_OFFSET,
2519 CPROC_INCARNATION_SIZE);
2520
c5aa993b 2521 if (cproc_copy_incarnation == (CORE_ADDR) 0)
c906108c
SS
2522 cproc_copy->cthread = NULL;
2523 else
2524 {
2525 /* This CPROC has an attached CTHREAD. Get its name */
c5aa993b
JM
2526 cthread = (cthread_t) obstack_alloc (cproc_obstack,
2527 sizeof (struct cthread));
c906108c
SS
2528
2529 if (!mach3_read_inferior (cproc_copy_incarnation,
2530 cthread,
c5aa993b
JM
2531 sizeof (struct cthread)))
2532 error ("Can't read next thread at 0x%x.",
2533 cproc_copy_incarnation);
c906108c
SS
2534
2535 cproc_copy->cthread = cthread;
2536
2537 if (cthread->name)
2538 {
2539 name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
2540
c5aa993b
JM
2541 if (!mach3_read_inferior (cthread->name, name, MAX_NAME_LEN))
2542 error ("Can't read next thread's name at 0x%x.", cthread->name);
c906108c
SS
2543
2544 cthread->name = name;
2545 }
2546 }
2547
2548 /* insert in front */
2549 cproc_copy->next = cproc_head;
2550 cproc_head = cproc_copy;
2551 }
2552 return cproc_head;
2553}
2554
2555#ifndef FETCH_CPROC_STATE
2556/*
2557 * Check if your machine does not grok the way this routine
2558 * fetches the FP,PC and SP of a cproc that is not
2559 * currently attached to any kernel thread (e.g. its cproc.context
2560 * field points to the place in stack where the context
2561 * is saved).
2562 *
2563 * If it doesn't, define your own routine.
2564 */
2565#define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2566
2567int
fba45db2 2568mach3_cproc_state (gdb_thread_t mthread)
c906108c
SS
2569{
2570 int context;
2571
c5aa993b 2572 if (!mthread || !mthread->cproc)
c906108c
SS
2573 return -1;
2574
2575 context = extract_signed_integer
2576 (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
2577 CPROC_CONTEXT_SIZE);
2578 if (context == 0)
2579 return -1;
2580
2581 mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
2582
2583 if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
2584 &mthread->pc,
2585 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2586 {
2587 warning ("Can't read cproc pc from inferior");
2588 return -1;
2589 }
2590
2591 if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
2592 &mthread->fp,
2593 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2594 {
2595 warning ("Can't read cproc fp from inferior");
2596 return -1;
2597 }
2598
2599 return 0;
2600}
2601#endif /* FETCH_CPROC_STATE */
c906108c 2602\f
c5aa993b 2603
c906108c 2604void
fba45db2 2605thread_list_command (void)
c906108c
SS
2606{
2607 thread_basic_info_data_t ths;
c5aa993b 2608 int thread_count;
c906108c
SS
2609 gdb_thread_t cprocs;
2610 gdb_thread_t scan;
c5aa993b
JM
2611 int index;
2612 char *name;
2613 char selected;
2614 char *wired;
2615 int infoCnt;
c906108c 2616 kern_return_t ret;
c5aa993b
JM
2617 mach_port_t mid_or_port;
2618 gdb_thread_t their_threads;
2619 gdb_thread_t kthread;
c906108c
SS
2620
2621 int neworder = 1;
2622
2623 char *fmt = "There are %d kernel threads in task %d.\n";
c5aa993b 2624
c906108c 2625 int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 2626
c906108c 2627 MACH_ERROR_NO_INFERIOR;
c5aa993b 2628
c906108c
SS
2629 thread_count = fetch_thread_info (inferior_task,
2630 &their_threads);
2631 if (thread_count == -1)
2632 return;
c5aa993b 2633
c906108c
SS
2634 if (thread_count == 1)
2635 fmt = "There is %d kernel thread in task %d.\n";
c5aa993b 2636
c906108c 2637 printf_filtered (fmt, thread_count, tmid);
c5aa993b 2638
c906108c 2639 puts_filtered (TL_HEADER);
c5aa993b
JM
2640
2641 cprocs = get_cprocs ();
2642
c906108c 2643 map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
c5aa993b 2644
c906108c
SS
2645 for (scan = cprocs; scan; scan = scan->next)
2646 {
2647 int mid;
2648 char buf[10];
2649 char slot[3];
2650 int cproc_state =
c5aa993b
JM
2651 extract_signed_integer
2652 (scan->raw_cproc + CPROC_STATE_OFFSET, CPROC_STATE_SIZE);
2653
c906108c 2654 selected = ' ';
c5aa993b 2655
c906108c
SS
2656 /* a wired cproc? */
2657 wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
2658 CPROC_WIRED_SIZE)
2659 ? "wired" : "");
2660
2661 if (scan->reverse_map != -1)
c5aa993b 2662 kthread = (their_threads + scan->reverse_map);
c906108c 2663 else
c5aa993b 2664 kthread = NULL;
c906108c
SS
2665
2666 if (kthread)
2667 {
2668 /* These cprocs have a kernel thread */
c5aa993b 2669
c906108c 2670 mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
c5aa993b 2671
c906108c 2672 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 2673
c906108c
SS
2674 ret = thread_info (kthread->name,
2675 THREAD_BASIC_INFO,
c5aa993b 2676 (thread_info_t) & ths,
c906108c 2677 &infoCnt);
c5aa993b 2678
c906108c
SS
2679 if (ret != KERN_SUCCESS)
2680 {
2681 warning ("Unable to get basic info on thread %d : %s",
2682 mid,
2683 mach_error_string (ret));
2684 continue;
2685 }
2686
2687 /* Who is the first to have more than 100 threads */
c5aa993b 2688 sprintf (slot, "%d", kthread->slotid % 100);
c906108c
SS
2689
2690 if (kthread->name == current_thread)
2691 selected = '*';
c5aa993b 2692
c906108c
SS
2693 if (ths.suspend_count)
2694 sprintf (buf, "%d", ths.suspend_count);
2695 else
2696 buf[0] = '\000';
2697
2698#if 0
2699 if (ths.flags & TH_FLAGS_SWAPPED)
2700 strcat (buf, "S");
2701#endif
2702
2703 if (ths.flags & TH_FLAGS_IDLE)
2704 strcat (buf, "I");
2705
2706 printf_filtered (TL_FORMAT,
2707 slot,
2708 mid,
2709 selected,
2710 get_thread_name (scan, kthread->slotid),
2711 kthread->in_emulator ? "E" : "",
2712 translate_state (ths.run_state),
2713 buf,
2714 translate_cstate (cproc_state),
2715 wired);
2716 print_tl_address (gdb_stdout, kthread->pc);
2717 }
2718 else
2719 {
2720 /* These cprocs don't have a kernel thread.
2721 * find out the calling frame with
2722 * FETCH_CPROC_STATE.
2723 */
2724
2725 struct gdb_thread state;
2726
2727#if 0
2728 /* jtv -> emcmanus: why do you want this here? */
2729 if (scan->incarnation == NULL)
c5aa993b 2730 continue; /* EMcM */
c906108c
SS
2731#endif
2732
2733 printf_filtered (TL_FORMAT,
2734 "-",
2735 -neworder, /* Pseudo MID */
2736 selected,
2737 get_thread_name (scan, -neworder),
2738 "",
2739 "-", /* kernel state */
2740 "",
2741 translate_cstate (cproc_state),
2742 "");
2743 state.cproc = scan;
2744
2745 if (FETCH_CPROC_STATE (&state) == -1)
2746 puts_filtered ("???");
2747 else
2748 print_tl_address (gdb_stdout, state.pc);
2749
2750 neworder++;
2751 }
2752 puts_filtered ("\n");
2753 }
c5aa993b 2754
c906108c
SS
2755 /* Scan for kernel threads without cprocs */
2756 for (index = 0; index < thread_count; index++)
2757 {
c5aa993b 2758 if (!their_threads[index].cproc)
c906108c
SS
2759 {
2760 int mid;
c5aa993b 2761
c906108c
SS
2762 char buf[10];
2763 char slot[3];
2764
2765 mach_port_t name = their_threads[index].name;
c5aa993b 2766
c906108c 2767 mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
c5aa993b 2768
c906108c 2769 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b
JM
2770
2771 ret = thread_info (name,
2772 THREAD_BASIC_INFO,
2773 (thread_info_t) & ths,
2774 &infoCnt);
2775
c906108c
SS
2776 if (ret != KERN_SUCCESS)
2777 {
2778 warning ("Unable to get basic info on thread %d : %s",
2779 mid,
2780 mach_error_string (ret));
2781 continue;
2782 }
2783
c5aa993b 2784 sprintf (slot, "%d", index % 100);
c906108c
SS
2785
2786 if (name == current_thread)
2787 selected = '*';
2788 else
2789 selected = ' ';
2790
2791 if (ths.suspend_count)
2792 sprintf (buf, "%d", ths.suspend_count);
2793 else
2794 buf[0] = '\000';
2795
2796#if 0
2797 if (ths.flags & TH_FLAGS_SWAPPED)
2798 strcat (buf, "S");
2799#endif
2800
2801 if (ths.flags & TH_FLAGS_IDLE)
2802 strcat (buf, "I");
2803
2804 printf_filtered (TL_FORMAT,
2805 slot,
2806 mid,
2807 selected,
2808 get_thread_name (NULL, index),
2809 their_threads[index].in_emulator ? "E" : "",
2810 translate_state (ths.run_state),
2811 buf,
c5aa993b 2812 "", /* No cproc state */
c906108c
SS
2813 ""); /* Can't be wired */
2814 print_tl_address (gdb_stdout, their_threads[index].pc);
2815 puts_filtered ("\n");
2816 }
2817 }
c5aa993b 2818
c906108c
SS
2819 obstack_free (cproc_obstack, 0);
2820 obstack_init (cproc_obstack);
2821}
2822\f
2823void
fba45db2 2824thread_select_command (char *args, int from_tty)
c906108c
SS
2825{
2826 int mid;
2827 thread_array_t thread_list;
2828 int thread_count;
2829 kern_return_t ret;
2830 int is_slot = 0;
2831
2832 MACH_ERROR_NO_INFERIOR;
2833
2834 if (!args)
2835 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2836
2837 while (*args == ' ' || *args == '\t')
2838 args++;
2839
2840 if (*args == '@')
2841 {
2842 is_slot++;
2843 args++;
2844 }
2845
c5aa993b 2846 mid = atoi (args);
c906108c
SS
2847
2848 if (mid == 0)
c5aa993b 2849 if (!is_slot || *args != '0') /* Rudimentary checks */
c906108c
SS
2850 error ("You must select threads by MID or @SLOTNUMBER");
2851
c5aa993b 2852 if (select_thread (inferior_task, mid, is_slot ? 2 : 1) != KERN_SUCCESS)
c906108c
SS
2853 return;
2854
2855 if (from_tty)
2856 printf_filtered ("Thread %d selected\n",
2857 is_slot ? map_port_name_to_mid (current_thread,
c5aa993b 2858 MACH_TYPE_THREAD) : mid);
c906108c
SS
2859}
2860\f
fba45db2 2861thread_trace (mach_port_t thread, boolean_t set)
c906108c 2862{
c5aa993b
JM
2863 int flavor = TRACE_FLAVOR;
2864 unsigned int stateCnt = TRACE_FLAVOR_SIZE;
2865 kern_return_t ret;
2866 thread_state_data_t state;
c906108c 2867
c5aa993b 2868 if (!MACH_PORT_VALID (thread))
c906108c
SS
2869 {
2870 warning ("thread_trace: invalid thread");
2871 return;
2872 }
2873
2874 if (must_suspend_thread)
2875 setup_thread (thread, 1);
2876
c5aa993b 2877 ret = thread_get_state (thread, flavor, state, &stateCnt);
c906108c 2878 CHK ("thread_trace: error reading thread state", ret);
c5aa993b 2879
c906108c
SS
2880 if (set)
2881 {
2882 TRACE_SET (thread, state);
2883 }
2884 else
2885 {
c5aa993b 2886 if (!TRACE_CLEAR (thread, state))
c906108c
SS
2887 {
2888 if (must_suspend_thread)
2889 setup_thread (thread, 0);
2890 return;
2891 }
2892 }
2893
c5aa993b 2894 ret = thread_set_state (thread, flavor, state, stateCnt);
c906108c
SS
2895 CHK ("thread_trace: error writing thread state", ret);
2896 if (must_suspend_thread)
2897 setup_thread (thread, 0);
c5aa993b 2898}
c906108c
SS
2899
2900#ifdef FLUSH_INFERIOR_CACHE
2901
2902/* When over-writing code on some machines the I-Cache must be flushed
2903 explicitly, because it is not kept coherent by the lazy hardware.
2904 This definitely includes breakpoints, for instance, or else we
2905 end up looping in mysterious Bpt traps */
2906
fba45db2 2907flush_inferior_icache (CORE_ADDR pc, int amount)
c906108c
SS
2908{
2909 vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
c5aa993b
JM
2910 kern_return_t ret;
2911
c906108c
SS
2912 ret = vm_machine_attribute (inferior_task,
2913 pc,
2914 amount,
2915 MATTR_CACHE,
2916 &flush);
2917 if (ret != KERN_SUCCESS)
2918 warning ("Error flushing inferior's cache : %s",
2919 mach_error_string (ret));
2920}
c5aa993b 2921#endif /* FLUSH_INFERIOR_CACHE */
c906108c 2922\f
c5aa993b 2923
c906108c 2924static
fba45db2 2925suspend_all_threads (int from_tty)
c906108c 2926{
c5aa993b
JM
2927 kern_return_t ret;
2928 thread_array_t thread_list;
2929 int thread_count, index;
2930 int infoCnt;
c906108c
SS
2931 thread_basic_info_data_t th_info;
2932
c5aa993b 2933
c906108c
SS
2934 ret = task_threads (inferior_task, &thread_list, &thread_count);
2935 if (ret != KERN_SUCCESS)
2936 {
2937 warning ("Could not suspend inferior threads.");
2938 m3_kill_inferior ();
2939 return_to_top_level (RETURN_ERROR);
2940 }
c5aa993b 2941
c906108c
SS
2942 for (index = 0; index < thread_count; index++)
2943 {
2944 int mid;
2945
c5aa993b 2946 mid = map_port_name_to_mid (thread_list[index],
c906108c 2947 MACH_TYPE_THREAD);
c5aa993b
JM
2948
2949 ret = thread_suspend (thread_list[index]);
c906108c
SS
2950
2951 if (ret != KERN_SUCCESS)
2952 warning ("Error trying to suspend thread %d : %s",
2953 mid, mach_error_string (ret));
2954
2955 if (from_tty)
2956 {
2957 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 2958 ret = thread_info (thread_list[index],
c906108c 2959 THREAD_BASIC_INFO,
c5aa993b 2960 (thread_info_t) & th_info,
c906108c
SS
2961 &infoCnt);
2962 CHK ("suspend can't get thread info", ret);
c5aa993b 2963
c906108c
SS
2964 warning ("Thread %d suspend count is %d",
2965 mid, th_info.suspend_count);
2966 }
2967 }
2968
2969 consume_send_rights (thread_list, thread_count);
c5aa993b
JM
2970 ret = vm_deallocate (mach_task_self (),
2971 (vm_address_t) thread_list,
2972 (thread_count * sizeof (int)));
c906108c
SS
2973 CHK ("Error trying to deallocate thread list", ret);
2974}
2975
2976void
fba45db2 2977thread_suspend_command (char *args, int from_tty)
c906108c
SS
2978{
2979 kern_return_t ret;
c5aa993b
JM
2980 int mid;
2981 mach_port_t saved_thread;
2982 int infoCnt;
c906108c 2983 thread_basic_info_data_t th_info;
c5aa993b 2984
c906108c
SS
2985 MACH_ERROR_NO_INFERIOR;
2986
c5aa993b
JM
2987 if (!strcasecmp (args, "all"))
2988 {
2989 suspend_all_threads (from_tty);
2990 return;
2991 }
c906108c
SS
2992
2993 saved_thread = current_thread;
2994
2995 mid = parse_thread_id (args, 0, 0);
2996
2997 if (mid < 0)
2998 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
2999
3000 if (mid == 0)
3001 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b
JM
3002 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3003 {
3004 if (current_thread)
3005 current_thread = saved_thread;
3006 error ("Could not select thread %d", mid);
3007 }
c906108c
SS
3008
3009 ret = thread_suspend (current_thread);
3010 if (ret != KERN_SUCCESS)
3011 warning ("thread_suspend failed : %s",
3012 mach_error_string (ret));
3013
3014 infoCnt = THREAD_BASIC_INFO_COUNT;
3015 ret = thread_info (current_thread,
3016 THREAD_BASIC_INFO,
c5aa993b 3017 (thread_info_t) & th_info,
c906108c
SS
3018 &infoCnt);
3019 CHK ("suspend can't get thread info", ret);
c5aa993b 3020
c906108c 3021 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
c5aa993b 3022
c906108c
SS
3023 current_thread = saved_thread;
3024}
3025
fba45db2 3026resume_all_threads (int from_tty)
c906108c 3027{
c5aa993b
JM
3028 kern_return_t ret;
3029 thread_array_t thread_list;
3030 int thread_count, index;
3031 int mid;
3032 int infoCnt;
3033 thread_basic_info_data_t th_info;
c906108c 3034
c5aa993b
JM
3035 ret = task_threads (inferior_task, &thread_list, &thread_count);
3036 if (ret != KERN_SUCCESS)
3037 {
3038 m3_kill_inferior ();
3039 error ("task_threads", mach_error_string (ret));
3040 }
c906108c 3041
c5aa993b
JM
3042 for (index = 0; index < thread_count; index++)
3043 {
3044 infoCnt = THREAD_BASIC_INFO_COUNT;
3045 ret = thread_info (thread_list[index],
3046 THREAD_BASIC_INFO,
3047 (thread_info_t) & th_info,
3048 &infoCnt);
3049 CHK ("resume_all can't get thread info", ret);
c906108c 3050
c5aa993b
JM
3051 mid = map_port_name_to_mid (thread_list[index],
3052 MACH_TYPE_THREAD);
c906108c 3053
c5aa993b
JM
3054 if (!th_info.suspend_count)
3055 {
3056 if (mid != -1 && from_tty)
3057 warning ("Thread %d is not suspended", mid);
3058 continue;
3059 }
c906108c 3060
c5aa993b
JM
3061 ret = thread_resume (thread_list[index]);
3062
3063 if (ret != KERN_SUCCESS)
3064 warning ("Error trying to resume thread %d : %s",
3065 mid, mach_error_string (ret));
3066 else if (mid != -1 && from_tty)
3067 warning ("Thread %d suspend count is %d",
3068 mid, --th_info.suspend_count);
3069 }
3070
3071 consume_send_rights (thread_list, thread_count);
3072 ret = vm_deallocate (mach_task_self (),
3073 (vm_address_t) thread_list,
3074 (thread_count * sizeof (int)));
3075 CHK ("Error trying to deallocate thread list", ret);
c906108c
SS
3076}
3077
3078void
fba45db2 3079thread_resume_command (char *args, int from_tty)
c906108c
SS
3080{
3081 int mid;
3082 mach_port_t saved_thread;
3083 kern_return_t ret;
3084 thread_basic_info_data_t th_info;
3085 int infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 3086
c906108c
SS
3087 MACH_ERROR_NO_INFERIOR;
3088
c5aa993b
JM
3089 if (!strcasecmp (args, "all"))
3090 {
3091 resume_all_threads (from_tty);
3092 return;
3093 }
c906108c
SS
3094
3095 saved_thread = current_thread;
3096
3097 mid = parse_thread_id (args, 0, 0);
3098
3099 if (mid < 0)
3100 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3101
3102 if (mid == 0)
3103 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b
JM
3104 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3105 {
3106 if (current_thread)
3107 current_thread = saved_thread;
3108 return_to_top_level (RETURN_ERROR);
3109 }
c906108c
SS
3110
3111 ret = thread_info (current_thread,
3112 THREAD_BASIC_INFO,
c5aa993b 3113 (thread_info_t) & th_info,
c906108c
SS
3114 &infoCnt);
3115 CHK ("resume can't get thread info", ret);
c5aa993b
JM
3116
3117 if (!th_info.suspend_count)
c906108c
SS
3118 {
3119 warning ("Thread %d is not suspended", mid);
3120 goto out;
3121 }
3122
3123 ret = thread_resume (current_thread);
3124 if (ret != KERN_SUCCESS)
3125 warning ("thread_resume failed : %s",
3126 mach_error_string (ret));
3127 else
3128 {
3129 th_info.suspend_count--;
3130 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
3131 }
c5aa993b
JM
3132
3133out:
c906108c
SS
3134 current_thread = saved_thread;
3135}
3136
3137void
fba45db2 3138thread_kill_command (char *args, int from_tty)
c906108c
SS
3139{
3140 int mid;
3141 kern_return_t ret;
3142 int thread_count;
3143 thread_array_t thread_table;
c5aa993b 3144 int index;
c906108c 3145 mach_port_t thread_to_kill = MACH_PORT_NULL;
c5aa993b
JM
3146
3147
c906108c
SS
3148 MACH_ERROR_NO_INFERIOR;
3149
3150 if (!args)
3151 error_no_arg ("thread mid to kill from the inferior task");
3152
3153 mid = parse_thread_id (args, 0, 0);
3154
3155 if (mid < 0)
3156 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3157
3158 if (mid)
3159 {
3160 ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
3161 CHK ("thread_kill_command: machid_mach_port map failed", ret);
3162 }
3163 else
3164 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b 3165
c906108c
SS
3166 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3167 ret = task_threads (inferior_task, &thread_table, &thread_count);
3168 CHK ("Error getting inferior's thread list", ret);
c5aa993b 3169
c906108c
SS
3170 if (thread_to_kill == current_thread)
3171 {
3172 ret = thread_terminate (thread_to_kill);
3173 CHK ("Thread could not be terminated", ret);
3174
3175 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3176 warning ("Last thread was killed, use \"kill\" command to kill task");
3177 }
3178 else
3179 for (index = 0; index < thread_count; index++)
c5aa993b 3180 if (thread_table[index] == thread_to_kill)
c906108c
SS
3181 {
3182 ret = thread_terminate (thread_to_kill);
3183 CHK ("Thread could not be terminated", ret);
3184 }
3185
3186 if (thread_count > 1)
3187 consume_send_rights (thread_table, thread_count);
c5aa993b
JM
3188
3189 ret = vm_deallocate (mach_task_self (), (vm_address_t) thread_table,
3190 (thread_count * sizeof (mach_port_t)));
c906108c 3191 CHK ("Error trying to deallocate thread list", ret);
c5aa993b 3192
c906108c
SS
3193 warning ("Thread %d killed", mid);
3194}
c906108c 3195\f
c5aa993b 3196
c906108c
SS
3197/* Task specific commands; add more if you like */
3198
3199void
fba45db2 3200task_resume_command (char *args, int from_tty)
c906108c
SS
3201{
3202 kern_return_t ret;
3203 task_basic_info_data_t ta_info;
3204 int infoCnt = TASK_BASIC_INFO_COUNT;
3205 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 3206
c906108c
SS
3207 MACH_ERROR_NO_INFERIOR;
3208
3209 /* Would be trivial to change, but is it desirable? */
3210 if (args)
3211 error ("Currently gdb can resume only it's inferior task");
3212
3213 ret = task_info (inferior_task,
3214 TASK_BASIC_INFO,
c5aa993b 3215 (task_info_t) & ta_info,
c906108c
SS
3216 &infoCnt);
3217 CHK ("task_resume_command: task_info failed", ret);
c5aa993b 3218
c906108c
SS
3219 if (ta_info.suspend_count == 0)
3220 error ("Inferior task %d is not suspended", mid);
3221 else if (ta_info.suspend_count == 1 &&
3222 from_tty &&
c5aa993b 3223 !query ("Suspend count is now 1. Do you know what you are doing? "))
c906108c
SS
3224 error ("Task not resumed");
3225
3226 ret = task_resume (inferior_task);
3227 CHK ("task_resume_command: task_resume", ret);
3228
3229 if (ta_info.suspend_count == 1)
3230 {
3231 warning ("Inferior task %d is no longer suspended", mid);
3232 must_suspend_thread = 1;
3233 /* @@ This is not complete: Registers change all the time when not
c5aa993b 3234 suspended! */
c906108c
SS
3235 registers_changed ();
3236 }
3237 else
3238 warning ("Inferior task %d suspend count is now %d",
c5aa993b 3239 mid, ta_info.suspend_count - 1);
c906108c
SS
3240}
3241
3242
3243void
fba45db2 3244task_suspend_command (char *args, int from_tty)
c906108c
SS
3245{
3246 kern_return_t ret;
3247 task_basic_info_data_t ta_info;
3248 int infoCnt = TASK_BASIC_INFO_COUNT;
3249 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 3250
c906108c
SS
3251 MACH_ERROR_NO_INFERIOR;
3252
3253 /* Would be trivial to change, but is it desirable? */
3254 if (args)
3255 error ("Currently gdb can suspend only it's inferior task");
3256
3257 ret = task_suspend (inferior_task);
3258 CHK ("task_suspend_command: task_suspend", ret);
3259
3260 must_suspend_thread = 0;
3261
3262 ret = task_info (inferior_task,
3263 TASK_BASIC_INFO,
c5aa993b 3264 (task_info_t) & ta_info,
c906108c
SS
3265 &infoCnt);
3266 CHK ("task_suspend_command: task_info failed", ret);
c5aa993b 3267
c906108c
SS
3268 warning ("Inferior task %d suspend count is now %d",
3269 mid, ta_info.suspend_count);
3270}
3271
3272static char *
fba45db2 3273get_size (int bytes)
c906108c 3274{
c5aa993b
JM
3275 static char size[30];
3276 int zz = bytes / 1024;
c906108c
SS
3277
3278 if (zz / 1024)
c5aa993b 3279 sprintf (size, "%-2.1f M", ((float) bytes) / (1024.0 * 1024.0));
c906108c
SS
3280 else
3281 sprintf (size, "%d K", zz);
3282
3283 return size;
3284}
3285
3286/* Does this require the target task to be suspended?? I don't think so. */
3287void
fba45db2 3288task_info_command (char *args, int from_tty)
c906108c
SS
3289{
3290 int mid = -5;
3291 mach_port_t task;
3292 kern_return_t ret;
3293 task_basic_info_data_t ta_info;
3294 int infoCnt = TASK_BASIC_INFO_COUNT;
c5aa993b 3295 int page_size = round_page (1);
c906108c 3296 int thread_count = 0;
c5aa993b 3297
c906108c
SS
3298 if (MACH_PORT_VALID (inferior_task))
3299 mid = map_port_name_to_mid (inferior_task,
3300 MACH_TYPE_TASK);
3301
3302 task = inferior_task;
3303
3304 if (args)
3305 {
3306 int tmid = atoi (args);
3307
3308 if (tmid <= 0)
3309 error ("Invalid mid %d for task info", tmid);
3310
3311 if (tmid != mid)
3312 {
3313 mid = tmid;
3314 ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
3315 CHK ("task_info_command: machid_mach_port map failed", ret);
3316 }
3317 }
3318
3319 if (mid < 0)
3320 error ("You have to give the task MID as an argument");
3321
3322 ret = task_info (task,
3323 TASK_BASIC_INFO,
c5aa993b 3324 (task_info_t) & ta_info,
c906108c
SS
3325 &infoCnt);
3326 CHK ("task_info_command: task_info failed", ret);
3327
3328 printf_filtered ("\nTask info for task %d:\n\n", mid);
3329 printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
3330 printf_filtered (" Base priority : %d\n", ta_info.base_priority);
3331 printf_filtered (" Virtual size : %s\n", get_size (ta_info.virtual_size));
3332 printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
3333
3334 {
3335 thread_array_t thread_list;
c5aa993b 3336
c906108c
SS
3337 ret = task_threads (task, &thread_list, &thread_count);
3338 CHK ("task_info_command: task_threads", ret);
c5aa993b 3339
c906108c
SS
3340 printf_filtered (" Thread count : %d\n", thread_count);
3341
3342 consume_send_rights (thread_list, thread_count);
c5aa993b
JM
3343 ret = vm_deallocate (mach_task_self (),
3344 (vm_address_t) thread_list,
3345 (thread_count * sizeof (int)));
3346 CHK ("Error trying to deallocate thread list", ret);
c906108c
SS
3347 }
3348 if (have_emulator_p (task))
3349 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3350 EMULATOR_BASE, EMULATOR_END);
3351 else
3352 printf_filtered (" No emulator.\n");
3353
3354 if (thread_count && task == inferior_task)
3355 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3356}
3357\f
3358/* You may either FORWARD the exception to the inferior, or KEEP
3359 * it and return to GDB command level.
3360 *
3361 * exception mid [ forward | keep ]
3362 */
3363
3364static void
fba45db2 3365exception_command (char *args, int from_tty)
c906108c
SS
3366{
3367 char *scan = args;
3368 int exception;
3369 int len;
3370
3371 if (!args)
3372 error_no_arg ("exception number action");
3373
c5aa993b
JM
3374 while (*scan == ' ' || *scan == '\t')
3375 scan++;
3376
c906108c
SS
3377 if ('0' <= *scan && *scan <= '9')
3378 while ('0' <= *scan && *scan <= '9')
3379 scan++;
3380 else
3381 error ("exception number action");
3382
3383 exception = atoi (args);
3384 if (exception <= 0 || exception > MAX_EXCEPTION)
3385 error ("Allowed exception numbers are in range 1..%d",
3386 MAX_EXCEPTION);
3387
3388 if (*scan != ' ' && *scan != '\t')
3389 error ("exception number must be followed by a space");
3390 else
c5aa993b
JM
3391 while (*scan == ' ' || *scan == '\t')
3392 scan++;
c906108c
SS
3393
3394 args = scan;
3395 len = 0;
3396 while (*scan)
3397 {
3398 len++;
3399 scan++;
3400 }
3401
3402 if (!len)
c5aa993b 3403 error ("exception number action");
c906108c
SS
3404
3405 if (!strncasecmp (args, "forward", len))
c5aa993b 3406 exception_map[exception].forward = TRUE;
c906108c 3407 else if (!strncasecmp (args, "keep", len))
c5aa993b 3408 exception_map[exception].forward = FALSE;
c906108c
SS
3409 else
3410 error ("exception action is either \"keep\" or \"forward\"");
3411}
3412
3413static void
fba45db2 3414print_exception_info (int exception)
c906108c 3415{
c5aa993b 3416 boolean_t forward = exception_map[exception].forward;
c906108c 3417
c5aa993b 3418 printf_filtered ("%s\t(%d): ", exception_map[exception].name,
c906108c
SS
3419 exception);
3420 if (!forward)
c5aa993b 3421 if (exception_map[exception].sigmap != SIG_UNKNOWN)
c906108c 3422 printf_filtered ("keep and handle as signal %d\n",
c5aa993b 3423 exception_map[exception].sigmap);
c906108c
SS
3424 else
3425 printf_filtered ("keep and handle as unknown signal %d\n",
c5aa993b 3426 exception_map[exception].sigmap);
c906108c
SS
3427 else
3428 printf_filtered ("forward exception to inferior\n");
3429}
3430
3431void
fba45db2 3432exception_info (char *args, int from_tty)
c906108c
SS
3433{
3434 int exception;
3435
3436 if (!args)
3437 for (exception = 1; exception <= MAX_EXCEPTION; exception++)
3438 print_exception_info (exception);
3439 else
3440 {
3441 exception = atoi (args);
3442
3443 if (exception <= 0 || exception > MAX_EXCEPTION)
3444 error ("Invalid exception number, values from 1 to %d allowed",
3445 MAX_EXCEPTION);
3446 print_exception_info (exception);
3447 }
3448}
3449\f
3450/* Check for actions for mach exceptions.
3451 */
fba45db2 3452mach3_exception_actions (WAITTYPE *w, boolean_t force_print_only, char *who)
c906108c
SS
3453{
3454 boolean_t force_print = FALSE;
3455
c5aa993b 3456
c906108c
SS
3457 if (force_print_only ||
3458 exception_map[stop_exception].sigmap == SIG_UNKNOWN)
3459 force_print = TRUE;
3460 else
3461 WSETSTOP (*w, exception_map[stop_exception].sigmap);
3462
3463 if (exception_map[stop_exception].print || force_print)
3464 {
3465 target_terminal_ours ();
c5aa993b 3466
c906108c
SS
3467 printf_filtered ("\n%s received %s exception : ",
3468 who,
3469 exception_map[stop_exception].name);
c5aa993b 3470
c906108c
SS
3471 wrap_here (" ");
3472
c5aa993b
JM
3473 switch (stop_exception)
3474 {
3475 case EXC_BAD_ACCESS:
3476 printf_filtered ("referencing address 0x%x : %s\n",
3477 stop_subcode,
3478 mach_error_string (stop_code));
3479 break;
3480 case EXC_BAD_INSTRUCTION:
3481 printf_filtered
3482 ("illegal or undefined instruction. code %d subcode %d\n",
3483 stop_code, stop_subcode);
3484 break;
3485 case EXC_ARITHMETIC:
3486 printf_filtered ("code %d\n", stop_code);
3487 break;
3488 case EXC_EMULATION:
3489 printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
3490 break;
3491 case EXC_SOFTWARE:
3492 printf_filtered ("%s specific, code 0x%x\n",
3493 stop_code < 0xffff ? "hardware" : "os emulation",
3494 stop_code);
3495 break;
3496 case EXC_BREAKPOINT:
3497 printf_filtered ("type %d (machine dependent)\n",
3498 stop_code);
3499 break;
3500 default:
8e65ff28
AC
3501 internal_error (__FILE__, __LINE__,
3502 "Unknown exception");
c5aa993b 3503 }
c906108c
SS
3504 }
3505}
3506\f
fba45db2 3507setup_notify_port (int create_new)
c906108c
SS
3508{
3509 kern_return_t ret;
3510
3511 if (MACH_PORT_VALID (our_notify_port))
3512 {
3513 ret = mach_port_destroy (mach_task_self (), our_notify_port);
3514 CHK ("Could not destroy our_notify_port", ret);
3515 }
3516
3517 our_notify_port = MACH_PORT_NULL;
c5aa993b 3518 notify_chain = (port_chain_t) NULL;
c906108c
SS
3519 port_chain_destroy (port_chain_obstack);
3520
3521 if (create_new)
3522 {
c5aa993b 3523 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
3524 MACH_PORT_RIGHT_RECEIVE,
3525 &our_notify_port);
3526 if (ret != KERN_SUCCESS)
8e65ff28
AC
3527 internal_error (__FILE__, __LINE__,
3528 "Creating notify port %s", mach_error_string (ret));
c5aa993b
JM
3529
3530 ret = mach_port_move_member (mach_task_self (),
3531 our_notify_port,
3532 inferior_wait_port_set);
c906108c 3533 if (ret != KERN_SUCCESS)
8e65ff28
AC
3534 internal_error (__FILE__, __LINE__,
3535 "initial move member %s", mach_error_string (ret));
c906108c
SS
3536 }
3537}
3538
3539/*
3540 * Register our message port to the net name server
3541 *
3542 * Currently used only by the external stop-gdb program
3543 * since ^C does not work if you would like to enter
3544 * gdb command level while debugging your program.
3545 *
3546 * NOTE: If the message port is sometimes used for other
3547 * purposes also, the NAME must not be a guessable one.
3548 * Then, there should be a way to change it.
3549 */
3550
c5aa993b 3551char registered_name[MAX_NAME_LEN];
c906108c
SS
3552
3553void
fba45db2 3554message_port_info (char *args, int from_tty)
c906108c
SS
3555{
3556 if (registered_name[0])
3557 printf_filtered ("gdb's message port name: '%s'\n",
3558 registered_name);
3559 else
3560 printf_filtered ("gdb's message port is not currently registered\n");
3561}
3562
3563void
fba45db2 3564gdb_register_port (char *name, mach_port_t port)
c906108c
SS
3565{
3566 kern_return_t ret;
3567 static int already_signed = 0;
3568 int len;
3569
c5aa993b 3570 if (!MACH_PORT_VALID (port) || !name || !*name)
c906108c
SS
3571 {
3572 warning ("Invalid registration request");
3573 return;
3574 }
3575
c5aa993b 3576 if (!already_signed)
c906108c
SS
3577 {
3578 ret = mach_port_insert_right (mach_task_self (),
3579 our_message_port,
3580 our_message_port,
3581 MACH_MSG_TYPE_MAKE_SEND);
3582 CHK ("Failed to create a signature to our_message_port", ret);
3583 already_signed = 1;
3584 }
3585 else if (already_signed > 1)
3586 {
3587 ret = netname_check_out (name_server_port,
3588 registered_name,
3589 our_message_port);
3590 CHK ("Failed to check out gdb's message port", ret);
3591 registered_name[0] = '\000';
3592 already_signed = 1;
3593 }
3594
3595 ret = netname_check_in (name_server_port, /* Name server port */
c5aa993b 3596 name, /* Name of service */
c906108c 3597 our_message_port, /* Signature */
c5aa993b
JM
3598 port); /* Creates a new send right */
3599 CHK ("Failed to check in the port", ret);
3600
c906108c 3601 len = 0;
c5aa993b 3602 while (len < MAX_NAME_LEN && *(name + len))
c906108c 3603 {
c5aa993b 3604 registered_name[len] = *(name + len);
c906108c
SS
3605 len++;
3606 }
3607 registered_name[len] = '\000';
3608 already_signed = 2;
c5aa993b 3609}
c906108c
SS
3610
3611struct cmd_list_element *cmd_thread_list;
3612struct cmd_list_element *cmd_task_list;
3613
c5aa993b 3614/*ARGSUSED */
c906108c 3615static void
fba45db2 3616thread_command (char *arg, int from_tty)
c906108c
SS
3617{
3618 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3619 help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
3620}
3621
c5aa993b 3622/*ARGSUSED */
c906108c 3623static void
fba45db2 3624task_command (char *arg, int from_tty)
c906108c
SS
3625{
3626 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3627 help_list (cmd_task_list, "task ", -1, gdb_stdout);
3628}
3629
fba45db2 3630add_mach_specific_commands (void)
c906108c
SS
3631{
3632 /* Thread handling commands */
3633
3634 /* FIXME: Move our thread support into the generic thread.c stuff so we
3635 can share that code. */
3636 add_prefix_cmd ("mthread", class_stack, thread_command,
c5aa993b
JM
3637 "Generic command for handling Mach threads in the debugged task.",
3638 &cmd_thread_list, "thread ", 0, &cmdlist);
c906108c
SS
3639
3640 add_com_alias ("th", "mthread", class_stack, 1);
3641
c5aa993b 3642 add_cmd ("select", class_stack, thread_select_command,
c906108c
SS
3643 "Select and print MID of the selected thread",
3644 &cmd_thread_list);
c5aa993b 3645 add_cmd ("list", class_stack, thread_list_command,
c906108c
SS
3646 "List info of task's threads. Selected thread is marked with '*'",
3647 &cmd_thread_list);
3648 add_cmd ("suspend", class_run, thread_suspend_command,
3649 "Suspend one or all of the threads in the selected task.",
3650 &cmd_thread_list);
3651 add_cmd ("resume", class_run, thread_resume_command,
3652 "Resume one or all of the threads in the selected task.",
3653 &cmd_thread_list);
3654 add_cmd ("kill", class_run, thread_kill_command,
3655 "Kill the specified thread MID from inferior task.",
3656 &cmd_thread_list);
3657#if 0
3658 /* The rest of this support (condition_thread) was not merged. It probably
3659 should not be merged in this form, but instead added to the generic GDB
3660 thread support. */
3661 add_cmd ("break", class_breakpoint, condition_thread,
3662 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3663 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3664 &cmd_thread_list);
3665#endif
3666 /* Thread command shorthands (for backward compatibility) */
3667 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
c5aa993b 3668 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist);
c906108c
SS
3669
3670 /* task handling commands */
3671
3672 add_prefix_cmd ("task", class_stack, task_command,
c5aa993b
JM
3673 "Generic command for handling debugged task.",
3674 &cmd_task_list, "task ", 0, &cmdlist);
c906108c
SS
3675
3676 add_com_alias ("ta", "task", class_stack, 1);
3677
3678 add_cmd ("suspend", class_run, task_suspend_command,
3679 "Suspend the inferior task.",
3680 &cmd_task_list);
3681 add_cmd ("resume", class_run, task_resume_command,
3682 "Resume the inferior task.",
3683 &cmd_task_list);
3684 add_cmd ("info", no_class, task_info_command,
3685 "Print information about the specified task.",
3686 &cmd_task_list);
3687
3688 /* Print my message port name */
3689
3690 add_info ("message-port", message_port_info,
3691 "Returns the name of gdb's message port in the netnameserver");
3692
3693 /* Exception commands */
3694
3695 add_info ("exceptions", exception_info,
3696 "What debugger does when program gets various exceptions.\n\
3697Specify an exception number as argument to print info on that\n\
3698exception only.");
3699
3700 add_com ("exception", class_run, exception_command,
3701 "Specify how to handle an exception.\n\
3702Args are exception number followed by \"forward\" or \"keep\".\n\
3703`Forward' means forward the exception to the program's normal exception\n\
3704handler.\n\
3705`Keep' means reenter debugger if this exception happens, and GDB maps\n\
3706the exception to some signal (see info exception)\n\
3707Normally \"keep\" is used to return to GDB on exception.");
3708}
3709
3710kern_return_t
fba45db2 3711do_mach_notify_dead_name (mach_port_t notify, mach_port_t name)
c906108c
SS
3712{
3713 kern_return_t kr = KERN_SUCCESS;
3714
3715 /* Find the thing that notified */
3716 port_chain_t element = port_chain_member (notify_chain, name);
3717
3718 /* Take name of from unreceived dead name notification list */
3719 notify_chain = port_chain_delete (notify_chain, name);
3720
c5aa993b 3721 if (!element)
c906108c 3722 error ("Received a dead name notify from unchained port (0x%x)", name);
c906108c 3723
c5aa993b
JM
3724 switch (element->type)
3725 {
c906108c 3726
c5aa993b
JM
3727 case MACH_TYPE_THREAD:
3728 target_terminal_ours_for_output ();
3729 if (name == current_thread)
3730 {
3731 printf_filtered ("\nCurrent thread %d died", element->mid);
3732 current_thread = MACH_PORT_NULL;
3733 }
3734 else
3735 printf_filtered ("\nThread %d died", element->mid);
c906108c 3736
c5aa993b 3737 break;
c906108c 3738
c5aa993b
JM
3739 case MACH_TYPE_TASK:
3740 target_terminal_ours_for_output ();
3741 if (name != inferior_task)
3742 printf_filtered ("Task %d died, but it was not the selected task",
3743 element->mid);
3744 else
3745 {
3746 printf_filtered ("Current task %d died", element->mid);
c906108c 3747
c5aa993b
JM
3748 mach_port_destroy (mach_task_self (), name);
3749 inferior_task = MACH_PORT_NULL;
3750
3751 if (notify_chain)
3752 warning ("There were still unreceived dead_name_notifications???");
3753
3754 /* Destroy the old notifications */
3755 setup_notify_port (0);
3756
3757 }
3758 break;
3759
3760 default:
3761 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3762 name, element->type, element->mid);
3763 break;
3764 }
c906108c
SS
3765
3766 return KERN_SUCCESS;
3767}
3768
3769kern_return_t
fba45db2 3770do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name)
c906108c
SS
3771{
3772 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3773 notify, name);
3774 return KERN_SUCCESS;
3775}
3776
3777kern_return_t
fba45db2 3778do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t mscount)
c906108c
SS
3779{
3780 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3781 notify, mscount);
3782 return KERN_SUCCESS;
3783}
3784
3785kern_return_t
fba45db2 3786do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name)
c906108c
SS
3787{
3788 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3789 notify, name);
3790 return KERN_SUCCESS;
3791}
3792
3793kern_return_t
fba45db2 3794do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t rights)
c906108c
SS
3795{
3796 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3797 notify, rights);
3798 return KERN_SUCCESS;
3799}
3800
3801kern_return_t
fba45db2 3802do_mach_notify_send_once (mach_port_t notify)
c906108c
SS
3803{
3804#ifdef DUMP_SYSCALL
3805 /* MANY of these are generated. */
3806 warning ("do_mach_notify_send_once : notify %x",
3807 notify);
3808#endif
3809 return KERN_SUCCESS;
3810}
3811
3812/* Kills the inferior. It's gone when you call this */
3813static void
fba45db2 3814kill_inferior_fast (void)
c906108c
SS
3815{
3816 WAITTYPE w;
3817
39f77062 3818 if (PIDGET (inferior_ptid) == 0 || PIDGET (inferior_ptid) == 1)
c906108c
SS
3819 return;
3820
3821 /* kill() it, since the Unix server does not otherwise notice when
3822 * killed with task_terminate().
3823 */
39f77062
KB
3824 if (PIDGET (inferior_ptid) > 0)
3825 kill (PIDGET (inferior_ptid), SIGKILL);
c906108c
SS
3826
3827 /* It's propably terminate already */
3828 (void) task_terminate (inferior_task);
3829
c5aa993b 3830 inferior_task = MACH_PORT_NULL;
c906108c
SS
3831 current_thread = MACH_PORT_NULL;
3832
3833 wait3 (&w, WNOHANG, 0);
3834
3835 setup_notify_port (0);
3836}
3837
3838static void
fba45db2 3839m3_kill_inferior (void)
c906108c
SS
3840{
3841 kill_inferior_fast ();
3842 target_mourn_inferior ();
3843}
3844
3845/* Clean up after the inferior dies. */
3846
3847static void
fba45db2 3848m3_mourn_inferior (void)
c906108c
SS
3849{
3850 unpush_target (&m3_ops);
3851 generic_mourn_inferior ();
3852}
c906108c 3853\f
c5aa993b 3854
c906108c
SS
3855/* Fork an inferior process, and start debugging it. */
3856
3857static void
fba45db2 3858m3_create_inferior (char *exec_file, char *allargs, char **env)
c906108c
SS
3859{
3860 fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL, NULL);
3861 /* We are at the first instruction we care about. */
3862 /* Pedal to the metal... */
2acceee2 3863 proceed ((CORE_ADDR) -1, 0, 0);
c906108c
SS
3864}
3865
3866/* Mark our target-struct as eligible for stray "run" and "attach"
3867 commands. */
3868static int
fba45db2 3869m3_can_run (void)
c906108c
SS
3870{
3871 return 1;
3872}
3873\f
3874/* Mach 3.0 does not need ptrace for anything
3875 * Make sure nobody uses it on mach.
3876 */
fba45db2 3877ptrace (int a, int b, int c, int d)
c906108c
SS
3878{
3879 error ("Lose, Lose! Somebody called ptrace\n");
3880}
3881
3882/* Resume execution of the inferior process.
3883 If STEP is nonzero, single-step it.
3884 If SIGNAL is nonzero, give it that signal. */
3885
3886void
39f77062 3887m3_resume (ptid_t ptid, int step, enum target_signal signal)
c906108c 3888{
c5aa993b 3889 kern_return_t ret;
c906108c
SS
3890
3891 if (step)
3892 {
3893 thread_basic_info_data_t th_info;
c5aa993b
JM
3894 unsigned int infoCnt = THREAD_BASIC_INFO_COUNT;
3895
c906108c
SS
3896 /* There is no point in single stepping when current_thread
3897 * is dead.
3898 */
c5aa993b 3899 if (!MACH_PORT_VALID (current_thread))
c906108c 3900 error ("No thread selected; can not single step");
c5aa993b 3901
c906108c
SS
3902 /* If current_thread is suspended, tracing it would never return.
3903 */
3904 ret = thread_info (current_thread,
3905 THREAD_BASIC_INFO,
c5aa993b 3906 (thread_info_t) & th_info,
c906108c
SS
3907 &infoCnt);
3908 CHK ("child_resume: can't get thread info", ret);
c5aa993b 3909
c906108c
SS
3910 if (th_info.suspend_count)
3911 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3912 }
3913
3914 vm_read_cache_valid = FALSE;
3915
39f77062
KB
3916 if (signal && PIDGET (inferior_ptid) > 0) /* Do not signal, if attached by MID */
3917 kill (PIDGET (inferior_ptid), target_signal_to_host (signal));
c906108c
SS
3918
3919 if (step)
3920 {
3921 suspend_all_threads (0);
3922
3923 setup_single_step (current_thread, TRUE);
c5aa993b 3924
c906108c
SS
3925 ret = thread_resume (current_thread);
3926 CHK ("thread_resume", ret);
3927 }
c5aa993b 3928
c906108c
SS
3929 ret = task_resume (inferior_task);
3930 if (ret == KERN_FAILURE)
3931 warning ("Task was not suspended");
3932 else
3933 CHK ("Resuming task", ret);
c5aa993b 3934
c906108c 3935 /* HACK HACK This is needed by the multiserver system HACK HACK */
c5aa993b
JM
3936 while ((ret = task_resume (inferior_task)) == KERN_SUCCESS)
3937 /* make sure it really runs */ ;
c906108c
SS
3938 /* HACK HACK This is needed by the multiserver system HACK HACK */
3939}
3940\f
3941#ifdef ATTACH_DETACH
3942
3943/* Start debugging the process with the given task */
3944void
fba45db2 3945task_attach (task_t tid)
c906108c
SS
3946{
3947 kern_return_t ret;
3948 inferior_task = tid;
3949
3950 ret = task_suspend (inferior_task);
c5aa993b 3951 CHK ("task_attach: task_suspend", ret);
c906108c
SS
3952
3953 must_suspend_thread = 0;
3954
3955 setup_notify_port (1);
3956
3957 request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
3958
3959 setup_exception_port ();
c5aa993b 3960
c906108c
SS
3961 emulator_present = have_emulator_p (inferior_task);
3962
3963 attach_flag = 1;
3964}
3965
3966/* Well, we can call error also here and leave the
3967 * target stack inconsistent. Sigh.
3968 * Fix this sometime (the only way to fail here is that
3969 * the task has no threads at all, which is rare, but
3970 * possible; or if the target task has died, which is also
3971 * possible, but unlikely, since it has been suspended.
3972 * (Someone must have killed it))
3973 */
3974void
fba45db2 3975attach_to_thread (void)
c906108c
SS
3976{
3977 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3978 error ("Could not select any threads to attach to");
3979}
3980
fba45db2 3981mid_attach (int mid)
c906108c 3982{
c5aa993b 3983 kern_return_t ret;
c906108c 3984
c5aa993b
JM
3985 ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
3986 CHK ("mid_attach: machid_mach_port", ret);
c906108c 3987
c5aa993b 3988 task_attach (inferior_task);
c906108c 3989
c5aa993b 3990 return mid;
c906108c
SS
3991}
3992
3993/*
3994 * Start debugging the process whose unix process-id is PID.
3995 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
3996 *
3997 * Prevent (possible unwanted) dangerous operations by enabled users
3998 * like "atta 0" or "atta foo" (equal to the previous :-) and
3999 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
4000 */
4001static int
fba45db2 4002m3_do_attach (int pid)
c906108c
SS
4003{
4004 kern_return_t ret;
4005
4006 if (pid == 0)
c5aa993b 4007 error ("MID=0, Debugging the master unix server does not compute");
c906108c
SS
4008
4009 /* Foo. This assumes gdb has a unix pid */
c5aa993b 4010 if (pid == getpid ())
c906108c
SS
4011 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4012
4013 if (pid < 0)
4014 {
4015 mid_attach (-(pid));
4016
39f77062
KB
4017 /* inferior_ptid will be NEGATIVE! */
4018 inferior_ptid = pid_to_ptid (pid);
c906108c 4019
39f77062 4020 return PIDGET (inferior_ptid);
c906108c
SS
4021 }
4022
4023 inferior_task = task_by_pid (pid);
c5aa993b
JM
4024 if (!MACH_PORT_VALID (inferior_task))
4025 error ("Cannot map Unix pid %d to Mach task port", pid);
c906108c
SS
4026
4027 task_attach (inferior_task);
4028
39f77062 4029 inferior_ptid = pid_to_ptid (pid);
c906108c 4030
39f77062 4031 return PIDGET (inferior_ptid);
c906108c
SS
4032}
4033
4034/* Attach to process PID, then initialize for debugging it
4035 and wait for the trace-trap that results from attaching. */
4036
4037static void
fba45db2 4038m3_attach (char *args, int from_tty)
c906108c
SS
4039{
4040 char *exec_file;
4041 int pid;
4042
4043 if (!args)
4044 error_no_arg ("process-id to attach");
4045
4046 pid = atoi (args);
4047
c5aa993b 4048 if (pid == getpid ()) /* Trying to masturbate? */
c906108c
SS
4049 error ("I refuse to debug myself!");
4050
4051 if (from_tty)
4052 {
4053 exec_file = (char *) get_exec_file (0);
4054
4055 if (exec_file)
39f77062
KB
4056 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
4057 target_pid_to_str (pid_to_ptid (pid)));
c906108c 4058 else
39f77062
KB
4059 printf_unfiltered ("Attaching to %s\n",
4060 target_pid_to_str (pid_to_ptid (pid)));
c906108c
SS
4061
4062 gdb_flush (gdb_stdout);
4063 }
4064
39f77062
KB
4065 m3_do_attach (pid_to_ptid (pid));
4066 inferior_ptid = pid_to_ptid (pid);
c906108c
SS
4067 push_target (&m3_ops);
4068}
4069\f
4070void
fba45db2 4071deallocate_inferior_ports (void)
c906108c 4072{
c5aa993b 4073 kern_return_t ret;
c906108c 4074 thread_array_t thread_list;
c5aa993b 4075 int thread_count, index;
c906108c
SS
4076
4077 if (!MACH_PORT_VALID (inferior_task))
4078 return;
4079
4080 ret = task_threads (inferior_task, &thread_list, &thread_count);
4081 if (ret != KERN_SUCCESS)
4082 {
4083 warning ("deallocate_inferior_ports: task_threads",
c5aa993b 4084 mach_error_string (ret));
c906108c
SS
4085 return;
4086 }
4087
4088 /* Get rid of send rights to task threads */
4089 for (index = 0; index < thread_count; index++)
4090 {
4091 int rights;
4092 ret = mach_port_get_refs (mach_task_self (),
4093 thread_list[index],
4094 MACH_PORT_RIGHT_SEND,
4095 &rights);
c5aa993b 4096 CHK ("deallocate_inferior_ports: get refs", ret);
c906108c
SS
4097
4098 if (rights > 0)
4099 {
4100 ret = mach_port_mod_refs (mach_task_self (),
4101 thread_list[index],
4102 MACH_PORT_RIGHT_SEND,
4103 -rights);
c5aa993b 4104 CHK ("deallocate_inferior_ports: mod refs", ret);
c906108c
SS
4105 }
4106 }
4107
4108 ret = mach_port_mod_refs (mach_task_self (),
4109 inferior_exception_port,
4110 MACH_PORT_RIGHT_RECEIVE,
4111 -1);
4112 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
4113
4114 ret = mach_port_deallocate (mach_task_self (),
4115 inferior_task);
4116 CHK ("deallocate_task_port: deallocating inferior_task", ret);
4117
4118 current_thread = MACH_PORT_NULL;
c5aa993b 4119 inferior_task = MACH_PORT_NULL;
c906108c
SS
4120}
4121
4122/* Stop debugging the process whose number is PID
4123 and continue it with signal number SIGNAL.
4124 SIGNAL = 0 means just continue it. */
4125
4126static void
fba45db2 4127m3_do_detach (int signal)
c906108c
SS
4128{
4129 kern_return_t ret;
4130
4131 MACH_ERROR_NO_INFERIOR;
4132
4133 if (current_thread != MACH_PORT_NULL)
4134 {
4135 /* Store the gdb's view of the thread we are deselecting
4136 * before we detach.
4137 * @@ I am really not sure if this is ever needeed.
4138 */
4139 target_prepare_to_store ();
4140 target_store_registers (-1);
4141 }
4142
4143 ret = task_set_special_port (inferior_task,
c5aa993b 4144 TASK_EXCEPTION_PORT,
c906108c
SS
4145 inferior_old_exception_port);
4146 CHK ("task_set_special_port", ret);
4147
4148 /* Discard all requested notifications */
4149 setup_notify_port (0);
4150
4151 if (remove_breakpoints ())
4152 warning ("Could not remove breakpoints when detaching");
c5aa993b 4153
39f77062
KB
4154 if (signal && PIDGET (inferior_ptid) > 0)
4155 kill (PIDGET (inferior_ptid), signal);
c5aa993b 4156
c906108c
SS
4157 /* the task might be dead by now */
4158 (void) task_resume (inferior_task);
c5aa993b 4159
c906108c 4160 deallocate_inferior_ports ();
c5aa993b 4161
c906108c
SS
4162 attach_flag = 0;
4163}
4164
4165/* Take a program previously attached to and detaches it.
4166 The program resumes execution and will no longer stop
4167 on signals, etc. We'd better not have left any breakpoints
4168 in the program or it'll die when it hits one. For this
4169 to work, it may be necessary for the process to have been
4170 previously attached. It *might* work if the program was
4171 started via fork. */
4172
4173static void
fba45db2 4174m3_detach (char *args, int from_tty)
c906108c
SS
4175{
4176 int siggnal = 0;
4177
4178 if (from_tty)
4179 {
4180 char *exec_file = get_exec_file (0);
4181 if (exec_file == 0)
4182 exec_file = "";
4183 printf_unfiltered ("Detaching from program: %s %s\n",
39f77062 4184 exec_file, target_pid_to_str (inferior_ptid));
c906108c
SS
4185 gdb_flush (gdb_stdout);
4186 }
4187 if (args)
4188 siggnal = atoi (args);
c5aa993b 4189
c906108c 4190 m3_do_detach (siggnal);
39f77062 4191 inferior_ptid = null_ptid;
c5aa993b 4192 unpush_target (&m3_ops); /* Pop out of handling an inferior */
c906108c
SS
4193}
4194#endif /* ATTACH_DETACH */
4195
4196/* Get ready to modify the registers array. On machines which store
4197 individual registers, this doesn't need to do anything. On machines
4198 which store all the registers in one fell swoop, this makes sure
4199 that registers contains all the registers from the program being
4200 debugged. */
4201
4202static void
fba45db2 4203m3_prepare_to_store (void)
c906108c
SS
4204{
4205#ifdef CHILD_PREPARE_TO_STORE
4206 CHILD_PREPARE_TO_STORE ();
4207#endif
4208}
4209
4210/* Print status information about what we're accessing. */
4211
4212static void
fba45db2 4213m3_files_info (struct target_ops *ignore)
c906108c
SS
4214{
4215 /* FIXME: should print MID and all that crap. */
4216 printf_unfiltered ("\tUsing the running image of %s %s.\n",
39f77062 4217 attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
c906108c
SS
4218}
4219
4220static void
fba45db2 4221m3_open (char *arg, int from_tty)
c906108c
SS
4222{
4223 error ("Use the \"run\" command to start a Unix child process.");
4224}
4225
4226#ifdef DUMP_SYSCALL
c906108c 4227#define STR(x) #x
c906108c 4228
c5aa993b
JM
4229char *bsd1_names[] =
4230{
c906108c
SS
4231 "execve",
4232 "fork",
4233 "take_signal",
4234 "sigreturn",
4235 "getrusage",
4236 "chdir",
4237 "chroot",
4238 "open",
4239 "creat",
4240 "mknod",
4241 "link",
4242 "symlink",
4243 "unlink",
4244 "access",
4245 "stat",
4246 "readlink",
4247 "chmod",
4248 "chown",
4249 "utimes",
4250 "truncate",
4251 "rename",
4252 "mkdir",
4253 "rmdir",
4254 "xutimes",
4255 "mount",
4256 "umount",
4257 "acct",
4258 "setquota",
4259 "write_short",
4260 "write_long",
4261 "send_short",
4262 "send_long",
4263 "sendto_short",
4264 "sendto_long",
4265 "select",
4266 "task_by_pid",
4267 "recvfrom_short",
4268 "recvfrom_long",
4269 "setgroups",
4270 "setrlimit",
4271 "sigvec",
4272 "sigstack",
4273 "settimeofday",
4274 "adjtime",
4275 "setitimer",
4276 "sethostname",
4277 "bind",
4278 "accept",
4279 "connect",
4280 "setsockopt",
4281 "getsockopt",
4282 "getsockname",
4283 "getpeername",
4284 "init_process",
4285 "table_set",
4286 "table_get",
4287 "pioctl",
4288 "emulator_error",
4289 "readwrite",
4290 "share_wakeup",
4291 0,
4292 "maprw_request_it",
4293 "maprw_release_it",
4294 "maprw_remap",
4295 "pid_by_task",
4296};
4297
c5aa993b 4298int bsd1_nnames = sizeof (bsd1_names) / sizeof (bsd1_names[0]);
c906108c 4299
c5aa993b 4300char *
fba45db2 4301name_str (int name, char *buf)
c906108c 4302{
c5aa993b
JM
4303 switch (name)
4304 {
4305 case MACH_MSG_TYPE_BOOLEAN:
4306 return "boolean";
4307 case MACH_MSG_TYPE_INTEGER_16:
4308 return "short";
4309 case MACH_MSG_TYPE_INTEGER_32:
4310 return "long";
4311 case MACH_MSG_TYPE_CHAR:
4312 return "char";
4313 case MACH_MSG_TYPE_BYTE:
4314 return "byte";
4315 case MACH_MSG_TYPE_REAL:
4316 return "real";
4317 case MACH_MSG_TYPE_STRING:
4318 return "string";
4319 default:
4320 sprintf (buf, "%d", name);
4321 return buf;
4322 }
c906108c
SS
4323}
4324
4325char *
fba45db2 4326id_str (int id, char *buf)
c906108c 4327{
c5aa993b
JM
4328 char *p;
4329 if (id >= 101000 && id < 101000 + bsd1_nnames)
4330 {
4331 if (p = bsd1_names[id - 101000])
4332 return p;
4333 }
c906108c
SS
4334 if (id == 102000)
4335 return "psignal_retry";
4336 if (id == 100000)
4337 return "syscall";
c5aa993b 4338 sprintf (buf, "%d", id);
c906108c
SS
4339 return buf;
4340}
4341
fba45db2 4342print_msg (mach_msg_header_t *mp)
c906108c 4343{
c5aa993b
JM
4344 char *fmt_x = "%20s : 0x%08x\n";
4345 char *fmt_d = "%20s : %10d\n";
4346 char *fmt_s = "%20s : %s\n";
4347 char buf[100];
c906108c
SS
4348
4349 puts_filtered ("\n");
4350#define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
c5aa993b
JM
4351 pr (fmt_x, (*mp), msgh_bits);
4352 pr (fmt_d, (*mp), msgh_size);
4353 pr (fmt_x, (*mp), msgh_remote_port);
4354 pr (fmt_x, (*mp), msgh_local_port);
4355 pr (fmt_d, (*mp), msgh_kind);
4356 printf_filtered (fmt_s, STR (msgh_id), id_str (mp->msgh_id, buf));
4357
c906108c 4358 if (debug_level > 1)
c5aa993b
JM
4359 {
4360 char *p, *ep, *dp;
4361 int plen;
4362 p = (char *) mp;
4363 ep = p + mp->msgh_size;
4364 p += sizeof (*mp);
4365 for (; p < ep; p += plen)
4366 {
4367 mach_msg_type_t *tp;
4368 mach_msg_type_long_t *tlp;
4369 int name, size, number;
4370 tp = (mach_msg_type_t *) p;
4371 if (tp->msgt_longform)
4372 {
4373 tlp = (mach_msg_type_long_t *) tp;
4374 name = tlp->msgtl_name;
4375 size = tlp->msgtl_size;
4376 number = tlp->msgtl_number;
4377 plen = sizeof (*tlp);
4378 }
4379 else
4380 {
4381 name = tp->msgt_name;
4382 size = tp->msgt_size;
4383 number = tp->msgt_number;
4384 plen = sizeof (*tp);
4385 }
4386 printf_filtered ("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4387 name_str (name, buf), size, number, tp->msgt_inline,
4388 tp->msgt_longform, tp->msgt_deallocate);
4389 dp = p + plen;
4390 if (tp->msgt_inline)
4391 {
4392 int l;
4393 l = size * number / 8;
4394 l = (l + sizeof (long) - 1) & ~((sizeof (long)) - 1);
4395 plen += l;
4396 print_data (dp, size, number);
4397 }
4398 else
4399 {
4400 plen += sizeof (int *);
4401 }
4402 printf_filtered ("plen=%d\n", plen);
4403 }
c906108c 4404 }
c906108c
SS
4405}
4406
fba45db2 4407print_data (char *p, int size, int number)
c906108c 4408{
c5aa993b
JM
4409 int *ip;
4410 short *sp;
4411 int i;
4412
4413 switch (size)
4414 {
4415 case 8:
4416 for (i = 0; i < number; i++)
4417 {
4418 printf_filtered (" %02x", p[i]);
4419 }
4420 break;
4421 case 16:
4422 sp = (short *) p;
4423 for (i = 0; i < number; i++)
4424 {
4425 printf_filtered (" %04x", sp[i]);
4426 }
4427 break;
4428 case 32:
4429 ip = (int *) p;
4430 for (i = 0; i < number; i++)
4431 {
4432 printf_filtered (" %08x", ip[i]);
4433 }
4434 break;
c906108c 4435 }
c5aa993b 4436 puts_filtered ("\n");
c906108c 4437}
c5aa993b 4438#endif /* DUMP_SYSCALL */
c906108c
SS
4439
4440static void
fba45db2 4441m3_stop (void)
c906108c
SS
4442{
4443 error ("to_stop target function not implemented");
4444}
4445
4446static char *
fba45db2 4447m3_pid_to_exec_file (int pid)
c906108c
SS
4448{
4449 error ("to_pid_to_exec_file target function not implemented");
c5aa993b 4450 return NULL; /* To keep all compilers happy. */
c906108c
SS
4451}
4452
4453static void
fba45db2 4454init_m3_ops (void)
c906108c
SS
4455{
4456 m3_ops.to_shortname = "mach";
4457 m3_ops.to_longname = "Mach child process";
4458 m3_ops.to_doc = "Mach child process (started by the \"run\" command).";
4459 m3_ops.to_open = m3_open;
4460 m3_ops.to_attach = m3_attach;
4461 m3_ops.to_detach = m3_detach;
4462 m3_ops.to_resume = m3_resume;
39f77062 4463 m3_ops.to_wait = mach_really_wait;
c906108c
SS
4464 m3_ops.to_fetch_registers = fetch_inferior_registers;
4465 m3_ops.to_store_registers = store_inferior_registers;
4466 m3_ops.to_prepare_to_store = m3_prepare_to_store;
4467 m3_ops.to_xfer_memory = m3_xfer_memory;
4468 m3_ops.to_files_info = m3_files_info;
4469 m3_ops.to_insert_breakpoint = memory_insert_breakpoint;
4470 m3_ops.to_remove_breakpoint = memory_remove_breakpoint;
4471 m3_ops.to_terminal_init = terminal_init_inferior;
4472 m3_ops.to_terminal_inferior = terminal_inferior;
4473 m3_ops.to_terminal_ours_for_output = terminal_ours_for_output;
4474 m3_ops.to_terminal_ours = terminal_ours;
4475 m3_ops.to_terminal_info = child_terminal_info;
4476 m3_ops.to_kill = m3_kill_inferior;
4477 m3_ops.to_create_inferior = m3_create_inferior;
4478 m3_ops.to_mourn_inferior = m3_mourn_inferior;
4479 m3_ops.to_can_run = m3_can_run;
4480 m3_ops.to_stop = m3_stop;
4481 m3_ops.to_pid_to_exec_file = m3_pid_to_exec_file;
4482 m3_ops.to_stratum = process_stratum;
4483 m3_ops.to_has_all_memory = 1;
4484 m3_ops.to_has_memory = 1;
4485 m3_ops.to_has_stack = 1;
4486 m3_ops.to_has_registers = 1;
4487 m3_ops.to_has_execution = 1;
4488 m3_ops.to_magic = OPS_MAGIC;
4489}
4490
4491void
fba45db2 4492_initialize_m3_nat (void)
c906108c
SS
4493{
4494 kern_return_t ret;
4495
4496 init_m3_ops ();
4497 add_target (&m3_ops);
4498
c5aa993b
JM
4499 ret = mach_port_allocate (mach_task_self (),
4500 MACH_PORT_RIGHT_PORT_SET,
4501 &inferior_wait_port_set);
c906108c 4502 if (ret != KERN_SUCCESS)
8e65ff28
AC
4503 internal_error (__FILE__, __LINE__,
4504 "initial port set %s", mach_error_string (ret));
c906108c
SS
4505
4506 /* mach_really_wait now waits for this */
4507 currently_waiting_for = inferior_wait_port_set;
4508
c5aa993b 4509 ret = netname_look_up (name_server_port, hostname, "MachID", &mid_server);
c906108c
SS
4510 if (ret != KERN_SUCCESS)
4511 {
4512 mid_server = MACH_PORT_NULL;
c5aa993b 4513
c906108c 4514 warning ("initialize machid: netname_lookup_up(MachID) : %s",
c5aa993b 4515 mach_error_string (ret));
c906108c
SS
4516 warning ("Some (most?) features disabled...");
4517 }
c5aa993b
JM
4518
4519 mid_auth = mach_privileged_host_port ();
c906108c 4520 if (mid_auth == MACH_PORT_NULL)
c5aa993b
JM
4521 mid_auth = mach_task_self ();
4522
c906108c
SS
4523 obstack_init (port_chain_obstack);
4524
c5aa993b 4525 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
4526 MACH_PORT_RIGHT_RECEIVE,
4527 &thread_exception_port);
4528 CHK ("Creating thread_exception_port for single stepping", ret);
c5aa993b 4529
c906108c
SS
4530 ret = mach_port_insert_right (mach_task_self (),
4531 thread_exception_port,
4532 thread_exception_port,
4533 MACH_MSG_TYPE_MAKE_SEND);
4534 CHK ("Inserting send right to thread_exception_port", ret);
4535
4536 /* Allocate message port */
4537 ret = mach_port_allocate (mach_task_self (),
4538 MACH_PORT_RIGHT_RECEIVE,
4539 &our_message_port);
4540 if (ret != KERN_SUCCESS)
4541 warning ("Creating message port %s", mach_error_string (ret));
4542 else
4543 {
c5aa993b
JM
4544 char buf[MAX_NAME_LEN];
4545 ret = mach_port_move_member (mach_task_self (),
4546 our_message_port,
4547 inferior_wait_port_set);
c906108c
SS
4548 if (ret != KERN_SUCCESS)
4549 warning ("message move member %s", mach_error_string (ret));
4550
4551
4552 /* @@@@ No way to change message port name currently */
4553 /* Foo. This assumes gdb has a unix pid */
4554 sprintf (buf, "gdb-%d", getpid ());
4555 gdb_register_port (buf, our_message_port);
4556 }
c5aa993b 4557
c906108c
SS
4558 /* Heap for thread commands */
4559 obstack_init (cproc_obstack);
4560
4561 add_mach_specific_commands ();
4562}
This page took 0.371778 seconds and 4 git commands to generate.