Eliminate some uses of __STDC__.
[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
1235 Returns the inferior_pid for rest of gdb.
1236 Side effects: Set *OURSTATUS. */
1237int
fba45db2 1238mach_really_wait (int pid, 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);
1314 return inferior_pid;
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);
1349 return inferior_pid;
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 *
1576 */
1577
fba45db2 1578mach3_prepare_to_proceed (int select_it)
c906108c
SS
1579{
1580 if (stop_thread &&
1581 stop_thread != current_thread &&
1582 stop_exception == EXC_BREAKPOINT)
1583 {
1584 int mid;
1585
c5aa993b 1586 if (!select_it)
c906108c
SS
1587 return 1;
1588
1589 mid = switch_to_thread (stop_thread);
1590
1591 return 1;
1592 }
1593
1594 return 0;
1595}
1596
1597/* this stuff here is an upcall via libmach/excServer.c
1598 and mach_really_wait which does the actual upcall.
1599
1600 The code will pass the exception to the inferior if:
1601
c5aa993b
JM
1602 - The task that signaled is not the inferior task
1603 (e.g. when debugging another debugger)
c906108c 1604
c5aa993b
JM
1605 - The user has explicitely requested to pass on the exceptions.
1606 (e.g to the default unix exception handler, which maps
1607 exceptions to signals, or the user has her own exception handler)
c906108c 1608
c5aa993b
JM
1609 - If the thread that signaled is being single-stepped and it
1610 has set it's own exception port and the exception is not
1611 EXC_BREAKPOINT. (Maybe this is not desirable?)
c906108c
SS
1612 */
1613
1614kern_return_t
fba45db2
KB
1615catch_exception_raise (mach_port_t port, thread_t thread, task_t task,
1616 int exception, int code, int subcode)
c906108c
SS
1617{
1618 kern_return_t ret;
1619 boolean_t signal_thread;
1620 int mid = map_port_name_to_mid (thread, MACH_TYPE_THREAD);
1621
c5aa993b 1622 if (!MACH_PORT_VALID (thread))
c906108c
SS
1623 {
1624 /* If the exception was sent and thread dies before we
c5aa993b 1625 receive it, THREAD will be MACH_PORT_DEAD
c906108c
SS
1626 */
1627
1628 current_thread = thread = MACH_PORT_NULL;
1629 error ("Received exception from nonexistent thread");
1630 }
1631
1632 /* Check if the task died in transit.
1633 * @@ Isn't the thread also invalid in such case?
1634 */
c5aa993b 1635 if (!MACH_PORT_VALID (task))
c906108c
SS
1636 {
1637 current_thread = thread = MACH_PORT_NULL;
1638 error ("Received exception from nonexistent task");
1639 }
1640
1641 if (exception < 0 || exception > MAX_EXCEPTION)
8e65ff28
AC
1642 internal_error (__FILE__, __LINE__,
1643 "catch_exception_raise: unknown exception code %d thread %d",
96baa820
JM
1644 exception,
1645 mid);
c906108c 1646
c5aa993b 1647 if (!MACH_PORT_VALID (inferior_task))
c906108c 1648 error ("got an exception, but inferior_task is null or dead");
c5aa993b 1649
c906108c 1650 stop_exception = exception;
c5aa993b
JM
1651 stop_code = code;
1652 stop_subcode = subcode;
1653 stop_thread = thread;
1654
1655 signal_thread = exception != EXC_BREAKPOINT &&
1656 port == singlestepped_thread_port &&
1657 MACH_PORT_VALID (thread_saved_exception_port);
c906108c
SS
1658
1659 /* If it was not our inferior or if we want to forward
1660 * the exception to the inferior's handler, do it here
1661 *
1662 * Note: If you have forwarded EXC_BREAKPOINT I trust you know why.
1663 */
1664 if (task != inferior_task ||
c5aa993b
JM
1665 signal_thread ||
1666 exception_map[exception].forward)
c906108c
SS
1667 {
1668 mach_port_t eport = inferior_old_exception_port;
1669
1670 if (signal_thread)
1671 {
1672 /*
c5aa993b
JM
1673 GDB now forwards the exeption to thread's original handler,
1674 since the user propably knows what he is doing.
1675 Give a message, though.
c906108c
SS
1676 */
1677
c5aa993b 1678 mach3_exception_actions ((WAITTYPE *) NULL, TRUE, "Thread");
c906108c
SS
1679 eport = thread_saved_exception_port;
1680 }
1681
1682 /* Send the exception to the original handler */
1683 ret = exception_raise (eport,
c5aa993b 1684 thread,
c906108c
SS
1685 task,
1686 exception,
1687 code,
1688 subcode);
1689
1690 (void) mach_port_deallocate (mach_task_self (), task);
1691 (void) mach_port_deallocate (mach_task_self (), thread);
1692
1693 /* If we come here, we don't want to trace any more, since we
1694 * will never stop for tracing anyway.
1695 */
1696 discard_single_step (thread);
1697
1698 /* Do not stop the inferior */
1699 return ret;
1700 }
c5aa993b 1701
c906108c
SS
1702 /* Now gdb handles the exception */
1703 stopped_in_exception = TRUE;
1704
1705 ret = task_suspend (task);
1706 CHK ("Error suspending inferior after exception", ret);
1707
1708 must_suspend_thread = 0;
1709
1710 if (current_thread != thread)
1711 {
1712 if (MACH_PORT_VALID (singlestepped_thread_port))
1713 /* Cleanup discards single stepping */
1714 error ("Exception from thread %d while singlestepping thread %d",
1715 mid,
1716 map_port_name_to_mid (current_thread, MACH_TYPE_THREAD));
c5aa993b 1717
c906108c
SS
1718 /* Then select the thread that caused the exception */
1719 if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
1720 error ("Could not select thread %d causing exception", mid);
1721 else
1722 warning ("Gdb selected thread %d", mid);
1723 }
1724
1725 /* If we receive an exception that is not breakpoint
1726 * exception, we interrupt the single step and return to
1727 * debugger. Trace condition is cleared.
1728 */
1729 if (MACH_PORT_VALID (singlestepped_thread_port))
1730 {
1731 if (stop_exception != EXC_BREAKPOINT)
1732 warning ("Single step interrupted by exception");
1733 else if (port == singlestepped_thread_port)
1734 {
1735 /* Single step exception occurred, remove trace bit
1736 * and return to gdb.
1737 */
c5aa993b 1738 if (!MACH_PORT_VALID (current_thread))
c906108c 1739 error ("Single stepped thread is not valid");
c5aa993b 1740
c906108c
SS
1741 /* Resume threads, but leave the task suspended */
1742 resume_all_threads (0);
1743 }
1744 else
1745 warning ("Breakpoint while single stepping?");
1746
1747 discard_single_step (current_thread);
1748 }
c5aa993b 1749
c906108c
SS
1750 (void) mach_port_deallocate (mach_task_self (), task);
1751 (void) mach_port_deallocate (mach_task_self (), thread);
1752
1753 return KERN_SUCCESS;
1754}
1755\f
1756int
fba45db2 1757port_valid (mach_port_t port, int mask)
c906108c
SS
1758{
1759 kern_return_t ret;
1760 mach_port_type_t type;
1761
1762 ret = mach_port_type (mach_task_self (),
1763 port,
1764 &type);
1765 if (ret != KERN_SUCCESS || (type & mask) != mask)
1766 return 0;
1767 return 1;
1768}
1769\f
1770/* @@ No vm read cache implemented yet */
1771boolean_t vm_read_cache_valid = FALSE;
1772
1773/*
1774 * Read inferior task's LEN bytes from ADDR and copy it to MYADDR
1775 * in gdb's address space.
1776 *
1777 * Return 0 on failure; number of bytes read otherwise.
1778 */
1779int
fba45db2 1780mach3_read_inferior (CORE_ADDR addr, char *myaddr, int length)
c906108c
SS
1781{
1782 kern_return_t ret;
c5aa993b
JM
1783 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1784 vm_size_t aligned_length =
1785 (vm_size_t) round_page (addr + length) - low_address;
1786 pointer_t copied_memory;
1787 int copy_count;
c906108c
SS
1788
1789 /* Get memory from inferior with page aligned addresses */
1790 ret = vm_read (inferior_task,
1791 low_address,
1792 aligned_length,
1793 &copied_memory,
1794 &copy_count);
1795 if (ret != KERN_SUCCESS)
1796 {
1797 /* the problem is that the inferior might be killed for whatever reason
1798 * before we go to mach_really_wait. This is one place that ought to
1799 * catch many of those errors.
1800 * @@ A better fix would be to make all external events to GDB
1801 * to arrive via a SINGLE port set. (Including user input!)
1802 */
1803
c5aa993b 1804 if (!port_valid (inferior_task, MACH_PORT_TYPE_SEND))
c906108c
SS
1805 {
1806 m3_kill_inferior ();
1807 error ("Inferior killed (task port invalid)");
1808 }
1809 else
1810 {
1811#ifdef OSF
1812 extern int errno;
1813 /* valprint.c gives nicer format if this does not
1814 screw it. Eamonn seems to like this, so I enable
1815 it if OSF is defined...
1816 */
1817 warning ("[read inferior %x failed: %s]",
1818 addr, mach_error_string (ret));
1819 errno = 0;
1820#endif
1821 return 0;
1822 }
1823 }
1824
c5aa993b 1825 memcpy (myaddr, (char *) addr - low_address + copied_memory, length);
c906108c
SS
1826
1827 ret = vm_deallocate (mach_task_self (),
1828 copied_memory,
1829 copy_count);
c5aa993b 1830 CHK ("mach3_read_inferior vm_deallocate failed", ret);
c906108c
SS
1831
1832 return length;
1833}
1834
c906108c
SS
1835#define CHK_GOTO_OUT(str,ret) \
1836 do if (ret != KERN_SUCCESS) { errstr = #str; goto out; } while(0)
c906108c 1837
c5aa993b
JM
1838struct vm_region_list
1839{
c906108c 1840 struct vm_region_list *next;
c5aa993b
JM
1841 vm_prot_t protection;
1842 vm_address_t start;
1843 vm_size_t length;
c906108c
SS
1844};
1845
c5aa993b 1846struct obstack region_obstack;
c906108c
SS
1847
1848/*
1849 * Write inferior task's LEN bytes from ADDR and copy it to MYADDR
1850 * in gdb's address space.
1851 */
1852int
fba45db2 1853mach3_write_inferior (CORE_ADDR addr, char *myaddr, int length)
c906108c
SS
1854{
1855 kern_return_t ret;
c5aa993b
JM
1856 vm_address_t low_address = (vm_address_t) trunc_page (addr);
1857 vm_size_t aligned_length =
1858 (vm_size_t) round_page (addr + length) - low_address;
1859 pointer_t copied_memory;
1860 int copy_count;
1861 int deallocate = 0;
c906108c 1862
c5aa993b 1863 char *errstr = "Bug in mach3_write_inferior";
c906108c
SS
1864
1865 struct vm_region_list *region_element;
c5aa993b 1866 struct vm_region_list *region_head = (struct vm_region_list *) NULL;
c906108c
SS
1867
1868 /* Get memory from inferior with page aligned addresses */
1869 ret = vm_read (inferior_task,
1870 low_address,
1871 aligned_length,
1872 &copied_memory,
1873 &copy_count);
1874 CHK_GOTO_OUT ("mach3_write_inferior vm_read failed", ret);
1875
1876 deallocate++;
1877
c5aa993b 1878 memcpy ((char *) addr - low_address + copied_memory, myaddr, length);
c906108c
SS
1879
1880 obstack_init (&region_obstack);
1881
1882 /* Do writes atomically.
1883 * First check for holes and unwritable memory.
1884 */
1885 {
c5aa993b
JM
1886 vm_size_t remaining_length = aligned_length;
1887 vm_address_t region_address = low_address;
c906108c
SS
1888
1889 struct vm_region_list *scan;
1890
c5aa993b 1891 while (region_address < low_address + aligned_length)
c906108c
SS
1892 {
1893 vm_prot_t protection;
1894 vm_prot_t max_protection;
1895 vm_inherit_t inheritance;
1896 boolean_t shared;
1897 mach_port_t object_name;
1898 vm_offset_t offset;
c5aa993b
JM
1899 vm_size_t region_length = remaining_length;
1900 vm_address_t old_address = region_address;
1901
c906108c
SS
1902 ret = vm_region (inferior_task,
1903 &region_address,
1904 &region_length,
1905 &protection,
1906 &max_protection,
1907 &inheritance,
1908 &shared,
1909 &object_name,
1910 &offset);
1911 CHK_GOTO_OUT ("vm_region failed", ret);
1912
1913 /* Check for holes in memory */
1914 if (old_address != region_address)
1915 {
1916 warning ("No memory at 0x%x. Nothing written",
1917 old_address);
1918 ret = KERN_SUCCESS;
1919 length = 0;
1920 goto out;
1921 }
1922
1923 if (!(max_protection & VM_PROT_WRITE))
1924 {
1925 warning ("Memory at address 0x%x is unwritable. Nothing written",
1926 old_address);
1927 ret = KERN_SUCCESS;
1928 length = 0;
1929 goto out;
1930 }
1931
1932 /* Chain the regions for later use */
c5aa993b 1933 region_element =
c906108c 1934 (struct vm_region_list *)
c5aa993b
JM
1935 obstack_alloc (&region_obstack, sizeof (struct vm_region_list));
1936
c906108c 1937 region_element->protection = protection;
c5aa993b
JM
1938 region_element->start = region_address;
1939 region_element->length = region_length;
c906108c
SS
1940
1941 /* Chain the regions along with protections */
1942 region_element->next = region_head;
c5aa993b
JM
1943 region_head = region_element;
1944
c906108c
SS
1945 region_address += region_length;
1946 remaining_length = remaining_length - region_length;
1947 }
1948
1949 /* If things fail after this, we give up.
1950 * Somebody is messing up inferior_task's mappings.
1951 */
c5aa993b 1952
c906108c
SS
1953 /* Enable writes to the chained vm regions */
1954 for (scan = region_head; scan; scan = scan->next)
1955 {
1956 boolean_t protection_changed = FALSE;
c5aa993b 1957
c906108c
SS
1958 if (!(scan->protection & VM_PROT_WRITE))
1959 {
1960 ret = vm_protect (inferior_task,
1961 scan->start,
1962 scan->length,
1963 FALSE,
1964 scan->protection | VM_PROT_WRITE);
1965 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1966 }
1967 }
1968
1969 ret = vm_write (inferior_task,
1970 low_address,
1971 copied_memory,
1972 aligned_length);
1973 CHK_GOTO_OUT ("vm_write failed", ret);
c5aa993b 1974
c906108c
SS
1975 /* Set up the original region protections, if they were changed */
1976 for (scan = region_head; scan; scan = scan->next)
1977 {
1978 boolean_t protection_changed = FALSE;
c5aa993b 1979
c906108c
SS
1980 if (!(scan->protection & VM_PROT_WRITE))
1981 {
1982 ret = vm_protect (inferior_task,
1983 scan->start,
1984 scan->length,
1985 FALSE,
1986 scan->protection);
1987 CHK_GOTO_OUT ("vm_protect: enable write failed", ret);
1988 }
1989 }
1990 }
1991
c5aa993b 1992out:
c906108c
SS
1993 if (deallocate)
1994 {
1995 obstack_free (&region_obstack, 0);
c5aa993b 1996
c906108c
SS
1997 (void) vm_deallocate (mach_task_self (),
1998 copied_memory,
1999 copy_count);
2000 }
2001
2002 if (ret != KERN_SUCCESS)
2003 {
2004 warning ("%s %s", errstr, mach_error_string (ret));
2005 return 0;
2006 }
2007
2008 return length;
2009}
2010
ad525611
KB
2011/* Return 0 on failure, number of bytes handled otherwise. TARGET is
2012 ignored. */
c906108c 2013static int
ad525611
KB
2014m3_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
2015 struct target_ops *target)
c906108c
SS
2016{
2017 int result;
2018
2019 if (write)
2020 result = mach3_write_inferior (memaddr, myaddr, len);
2021 else
c5aa993b 2022 result = mach3_read_inferior (memaddr, myaddr, len);
c906108c
SS
2023
2024 return result;
2025}
c906108c 2026\f
c5aa993b 2027
c906108c 2028static char *
fba45db2 2029translate_state (int state)
c906108c 2030{
c5aa993b
JM
2031 switch (state)
2032 {
2033 case TH_STATE_RUNNING:
2034 return ("R");
2035 case TH_STATE_STOPPED:
2036 return ("S");
2037 case TH_STATE_WAITING:
2038 return ("W");
2039 case TH_STATE_UNINTERRUPTIBLE:
2040 return ("U");
2041 case TH_STATE_HALTED:
2042 return ("H");
2043 default:
2044 return ("?");
2045 }
c906108c
SS
2046}
2047
2048static char *
fba45db2 2049translate_cstate (int state)
c906108c
SS
2050{
2051 switch (state)
2052 {
c5aa993b
JM
2053 case CPROC_RUNNING:
2054 return "R";
2055 case CPROC_SWITCHING:
2056 return "S";
2057 case CPROC_BLOCKED:
2058 return "B";
2059 case CPROC_CONDWAIT:
2060 return "C";
2061 case CPROC_CONDWAIT | CPROC_SWITCHING:
2062 return "CS";
2063 default:
2064 return "?";
c906108c
SS
2065 }
2066}
2067
2068/* type == MACH_MSG_TYPE_COPY_SEND || type == MACH_MSG_TYPE_MAKE_SEND */
2069
c5aa993b 2070mach_port_t /* no mach_port_name_t found in include files. */
fba45db2 2071map_inferior_port_name (mach_port_t inferior_name, mach_msg_type_name_t type)
c906108c 2072{
c5aa993b 2073 kern_return_t ret;
c906108c 2074 mach_msg_type_name_t acquired;
c5aa993b
JM
2075 mach_port_t iport;
2076
c906108c
SS
2077 ret = mach_port_extract_right (inferior_task,
2078 inferior_name,
2079 type,
2080 &iport,
2081 &acquired);
c5aa993b 2082 CHK ("mach_port_extract_right (map_inferior_port_name)", ret);
c906108c
SS
2083
2084 if (acquired != MACH_MSG_TYPE_PORT_SEND)
c5aa993b 2085 error ("Incorrect right extracted, (map_inferior_port_name)");
c906108c
SS
2086
2087 ret = mach_port_deallocate (mach_task_self (),
2088 iport);
2089 CHK ("Deallocating mapped port (map_inferior_port_name)", ret);
2090
2091 return iport;
2092}
2093
2094/*
2095 * Naming convention:
2096 * Always return user defined name if found.
2097 * _K == A kernel thread with no matching CPROC
2098 * _C == A cproc with no current cthread
2099 * _t == A cthread with no user defined name
2100 *
2101 * The digits that follow the _names are the SLOT number of the
2102 * kernel thread if there is such a thing, otherwise just a negation
2103 * of the sequential number of such cprocs.
2104 */
2105
2106static char buf[7];
2107
2108static char *
fba45db2 2109get_thread_name (gdb_thread_t one_cproc, int id)
c906108c
SS
2110{
2111 if (one_cproc)
2112 if (one_cproc->cthread == NULL)
2113 {
2114 /* cproc not mapped to any cthread */
c5aa993b 2115 sprintf (buf, "_C%d", id);
c906108c 2116 }
c5aa993b 2117 else if (!one_cproc->cthread->name)
c906108c
SS
2118 {
2119 /* cproc and cthread, but no name */
c5aa993b 2120 sprintf (buf, "_t%d", id);
c906108c
SS
2121 }
2122 else
c5aa993b 2123 return (char *) (one_cproc->cthread->name);
c906108c
SS
2124 else
2125 {
2126 if (id < 0)
2127 warning ("Inconsistency in thread name id %d", id);
2128
2129 /* Kernel thread without cproc */
c5aa993b 2130 sprintf (buf, "_K%d", id);
c906108c
SS
2131 }
2132
2133 return buf;
2134}
2135
2136int
ad525611 2137fetch_thread_info (mach_port_t task, gdb_thread_t *mthreads_out)
c906108c 2138{
c5aa993b 2139 kern_return_t ret;
c906108c 2140 thread_array_t th_table;
c5aa993b 2141 int th_count;
c906108c 2142 gdb_thread_t mthreads = NULL;
c5aa993b 2143 int index;
c906108c
SS
2144
2145 ret = task_threads (task, &th_table, &th_count);
2146 if (ret != KERN_SUCCESS)
2147 {
2148 warning ("Error getting inferior's thread list:%s",
c5aa993b 2149 mach_error_string (ret));
c906108c
SS
2150 m3_kill_inferior ();
2151 return -1;
2152 }
c5aa993b 2153
c906108c 2154 mthreads = (gdb_thread_t)
c5aa993b
JM
2155 obstack_alloc
2156 (cproc_obstack,
2157 th_count * sizeof (struct gdb_thread));
c906108c
SS
2158
2159 for (index = 0; index < th_count; index++)
2160 {
2161 thread_t saved_thread = MACH_PORT_NULL;
2162 int mid;
2163
2164 if (must_suspend_thread)
c5aa993b 2165 setup_thread (th_table[index], 1);
c906108c
SS
2166
2167 if (th_table[index] != current_thread)
2168 {
2169 saved_thread = current_thread;
c5aa993b
JM
2170
2171 mid = switch_to_thread (th_table[index]);
c906108c
SS
2172 }
2173
c5aa993b 2174 mthreads[index].name = th_table[index];
c906108c
SS
2175 mthreads[index].cproc = NULL; /* map_cprocs_to_kernel_threads() */
2176 mthreads[index].in_emulator = FALSE;
2177 mthreads[index].slotid = index;
c5aa993b 2178
c906108c
SS
2179 mthreads[index].sp = read_register (SP_REGNUM);
2180 mthreads[index].fp = read_register (FP_REGNUM);
2181 mthreads[index].pc = read_pc ();
2182
2183 if (MACH_PORT_VALID (saved_thread))
2184 mid = switch_to_thread (saved_thread);
2185
2186 if (must_suspend_thread)
c5aa993b 2187 setup_thread (th_table[index], 0);
c906108c 2188 }
c5aa993b 2189
c906108c 2190 consume_send_rights (th_table, th_count);
c5aa993b
JM
2191 ret = vm_deallocate (mach_task_self (), (vm_address_t) th_table,
2192 (th_count * sizeof (mach_port_t)));
c906108c
SS
2193 if (ret != KERN_SUCCESS)
2194 {
2195 warning ("Error trying to deallocate thread list : %s",
2196 mach_error_string (ret));
2197 }
2198
2199 *mthreads_out = mthreads;
2200
2201 return th_count;
2202}
2203
2204
2205/*
2206 * Current emulator always saves the USP on top of
2207 * emulator stack below struct emul_stack_top stuff.
2208 */
2209CORE_ADDR
fba45db2 2210fetch_usp_from_emulator_stack (CORE_ADDR sp)
c906108c
SS
2211{
2212 CORE_ADDR stack_pointer;
2213
c5aa993b
JM
2214 sp = (sp & ~(EMULATOR_STACK_SIZE - 1)) +
2215 EMULATOR_STACK_SIZE - sizeof (struct emul_stack_top);
2216
c906108c
SS
2217 if (mach3_read_inferior (sp,
2218 &stack_pointer,
2219 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2220 {
2221 warning ("Can't read user sp from emulator stack address 0x%x", sp);
2222 return 0;
2223 }
2224
2225 return stack_pointer;
2226}
2227
2228#ifdef MK67
2229
2230/* get_emulation_vector() interface was changed after mk67 */
2231#define EMUL_VECTOR_COUNT 400 /* Value does not matter too much */
2232
2233#endif /* MK67 */
2234
2235/* Check if the emulator exists at task's address space.
2236 */
2237boolean_t
fba45db2 2238have_emulator_p (task_t task)
c906108c 2239{
c5aa993b 2240 kern_return_t ret;
c906108c 2241#ifndef EMUL_VECTOR_COUNT
c5aa993b
JM
2242 vm_offset_t *emulation_vector;
2243 int n;
c906108c 2244#else
c5aa993b
JM
2245 vm_offset_t emulation_vector[EMUL_VECTOR_COUNT];
2246 int n = EMUL_VECTOR_COUNT;
c906108c 2247#endif
c5aa993b
JM
2248 int i;
2249 int vector_start;
2250
c906108c
SS
2251 ret = task_get_emulation_vector (task,
2252 &vector_start,
2253#ifndef EMUL_VECTOR_COUNT
2254 &emulation_vector,
2255#else
2256 emulation_vector,
2257#endif
2258 &n);
c5aa993b 2259 CHK ("task_get_emulation_vector", ret);
c906108c
SS
2260 xx_debug ("%d vectors from %d at 0x%08x\n",
2261 n, vector_start, emulation_vector);
c5aa993b
JM
2262
2263 for (i = 0; i < n; i++)
c906108c 2264 {
c5aa993b 2265 vm_offset_t entry = emulation_vector[i];
c906108c
SS
2266
2267 if (EMULATOR_BASE <= entry && entry <= EMULATOR_END)
2268 return TRUE;
2269 else if (entry)
2270 {
2271 static boolean_t informed = FALSE;
2272 if (!informed)
2273 {
c5aa993b
JM
2274 warning ("Emulation vector address 0x08%x outside emulator space",
2275 entry);
c906108c
SS
2276 informed = TRUE;
2277 }
2278 }
2279 }
2280 return FALSE;
2281}
2282
2283/* Map cprocs to kernel threads and vice versa. */
2284
2285void
fba45db2
KB
2286map_cprocs_to_kernel_threads (gdb_thread_t cprocs, gdb_thread_t mthreads,
2287 int thread_count)
c906108c
SS
2288{
2289 int index;
2290 gdb_thread_t scan;
2291 boolean_t all_mapped = TRUE;
2292 LONGEST stack_base;
2293 LONGEST stack_size;
2294
2295 for (scan = cprocs; scan; scan = scan->next)
2296 {
2297 /* Default to: no kernel thread for this cproc */
2298 scan->reverse_map = -1;
2299
2300 /* Check if the cproc is found by its stack */
2301 for (index = 0; index < thread_count; index++)
2302 {
2303 stack_base =
2304 extract_signed_integer (scan->raw_cproc + CPROC_BASE_OFFSET,
2305 CPROC_BASE_SIZE);
c5aa993b 2306 stack_size =
c906108c
SS
2307 extract_signed_integer (scan->raw_cproc + CPROC_SIZE_OFFSET,
2308 CPROC_SIZE_SIZE);
2309 if ((mthreads + index)->sp > stack_base &&
2310 (mthreads + index)->sp <= stack_base + stack_size)
2311 {
2312 (mthreads + index)->cproc = scan;
2313 scan->reverse_map = index;
2314 break;
2315 }
2316 }
2317 all_mapped &= (scan->reverse_map != -1);
2318 }
2319
2320 /* Check for threads that are currently in the emulator.
2321 * If so, they have a different stack, and the still unmapped
2322 * cprocs may well get mapped to these threads.
2323 *
2324 * If:
2325 * - cproc stack does not match any kernel thread stack pointer
2326 * - there is at least one extra kernel thread
2327 * that has no cproc mapped above.
2328 * - some kernel thread stack pointer points to emulator space
2329 * then we find the user stack pointer saved in the emulator
2330 * stack, and try to map that to the cprocs.
2331 *
2332 * Also set in_emulator for kernel threads.
c5aa993b 2333 */
c906108c
SS
2334
2335 if (emulator_present)
2336 {
2337 for (index = 0; index < thread_count; index++)
2338 {
2339 CORE_ADDR emul_sp;
2340 CORE_ADDR usp;
2341
c5aa993b 2342 gdb_thread_t mthread = (mthreads + index);
c906108c
SS
2343 emul_sp = mthread->sp;
2344
2345 if (mthread->cproc == NULL &&
2346 EMULATOR_BASE <= emul_sp && emul_sp <= EMULATOR_END)
2347 {
2348 mthread->in_emulator = emulator_present;
c5aa993b 2349
c906108c
SS
2350 if (!all_mapped && cprocs)
2351 {
2352 usp = fetch_usp_from_emulator_stack (emul_sp);
c5aa993b 2353
c906108c 2354 /* @@ Could be more accurate */
c5aa993b 2355 if (!usp)
c906108c 2356 error ("Zero stack pointer read from emulator?");
c5aa993b 2357
c906108c
SS
2358 /* Try to match this stack pointer to the cprocs that
2359 * don't yet have a kernel thread.
2360 */
2361 for (scan = cprocs; scan; scan = scan->next)
2362 {
c5aa993b 2363
c906108c
SS
2364 /* Check is this unmapped CPROC stack contains
2365 * the user stack pointer saved in the
2366 * emulator.
2367 */
2368 if (scan->reverse_map == -1)
2369 {
2370 stack_base =
2371 extract_signed_integer
c5aa993b
JM
2372 (scan->raw_cproc + CPROC_BASE_OFFSET,
2373 CPROC_BASE_SIZE);
2374 stack_size =
c906108c 2375 extract_signed_integer
c5aa993b
JM
2376 (scan->raw_cproc + CPROC_SIZE_OFFSET,
2377 CPROC_SIZE_SIZE);
c906108c
SS
2378 if (usp > stack_base &&
2379 usp <= stack_base + stack_size)
2380 {
2381 mthread->cproc = scan;
2382 scan->reverse_map = index;
2383 break;
2384 }
2385 }
2386 }
2387 }
2388 }
2389 }
2390 }
2391}
2392\f
2393/*
2394 * Format of the thread_list command
2395 *
c5aa993b 2396 * slot mid sel name emul ks susp cstate wired address
c906108c
SS
2397 */
2398#define TL_FORMAT "%-2.2s %5d%c %-10.10s %1.1s%s%-5.5s %-2.2s %-5.5s "
2399
2400#define TL_HEADER "\n@ MID Name KState CState Where\n"
2401
2402void
fba45db2 2403print_tl_address (struct ui_file *stream, CORE_ADDR pc)
c906108c 2404{
c5aa993b
JM
2405 if (!lookup_minimal_symbol_by_pc (pc))
2406 fprintf_filtered (stream, local_hex_format (), pc);
c906108c
SS
2407 else
2408 {
2409 extern int addressprint;
2410 extern int asm_demangle;
2411
c5aa993b 2412 int store = addressprint;
c906108c
SS
2413 addressprint = 0;
2414 print_address_symbolic (pc, stream, asm_demangle, "");
2415 addressprint = store;
2416 }
2417}
2418\f
2419/* For thread names, but also for gdb_message_port external name */
2420#define MAX_NAME_LEN 50
2421
2422/* Returns the address of variable NAME or 0 if not found */
2423CORE_ADDR
fba45db2 2424lookup_address_of_variable (char *name)
c906108c
SS
2425{
2426 struct symbol *sym;
2427 CORE_ADDR symaddr = 0;
2428 struct minimal_symbol *msymbol;
2429
2430 sym = lookup_symbol (name,
c5aa993b 2431 (struct block *) NULL,
c906108c 2432 VAR_NAMESPACE,
c5aa993b
JM
2433 (int *) NULL,
2434 (struct symtab **) NULL);
c906108c
SS
2435
2436 if (sym)
2437 symaddr = SYMBOL_VALUE (sym);
2438
c5aa993b 2439 if (!symaddr)
c906108c
SS
2440 {
2441 msymbol = lookup_minimal_symbol (name, NULL, NULL);
2442
2443 if (msymbol && msymbol->type == mst_data)
2444 symaddr = SYMBOL_VALUE_ADDRESS (msymbol);
2445 }
2446
2447 return symaddr;
2448}
2449
2450static gdb_thread_t
fba45db2 2451get_cprocs (void)
c906108c
SS
2452{
2453 gdb_thread_t cproc_head;
2454 gdb_thread_t cproc_copy;
2455 CORE_ADDR their_cprocs;
35fc8285 2456 char *buf;
c906108c
SS
2457 char *name;
2458 cthread_t cthread;
2459 CORE_ADDR symaddr;
c5aa993b 2460
35fc8285 2461 buf = alloca (TARGET_PTR_BIT / HOST_CHAR_BIT);
c906108c
SS
2462 symaddr = lookup_address_of_variable ("cproc_list");
2463
c5aa993b 2464 if (!symaddr)
c906108c
SS
2465 {
2466 /* cproc_list is not in a file compiled with debugging
c5aa993b 2467 symbols, but don't give up yet */
c906108c
SS
2468
2469 symaddr = lookup_address_of_variable ("cprocs");
2470
2471 if (symaddr)
2472 {
2473 static int informed = 0;
2474 if (!informed)
2475 {
2476 informed++;
2477 warning ("Your program is loaded with an old threads library.");
2478 warning ("GDB does not know the old form of threads");
2479 warning ("so things may not work.");
2480 }
2481 }
2482 }
2483
2484 /* Stripped or no -lthreads loaded or "cproc_list" is in wrong segment. */
c5aa993b 2485 if (!symaddr)
c906108c
SS
2486 return NULL;
2487
2488 /* Get the address of the first cproc in the task */
2489 if (!mach3_read_inferior (symaddr,
2490 buf,
2491 TARGET_PTR_BIT / HOST_CHAR_BIT))
2492 error ("Can't read cproc master list at address (0x%x).", symaddr);
2493 their_cprocs = extract_address (buf, TARGET_PTR_BIT / HOST_CHAR_BIT);
2494
2495 /* Scan the CPROCs in the task.
2496 CPROCs are chained with LIST field, not NEXT field, which
2497 chains mutexes, condition variables and queues */
2498
2499 cproc_head = NULL;
2500
c5aa993b 2501 while (their_cprocs != (CORE_ADDR) 0)
c906108c
SS
2502 {
2503 CORE_ADDR cproc_copy_incarnation;
2504 cproc_copy = (gdb_thread_t) obstack_alloc (cproc_obstack,
2505 sizeof (struct gdb_thread));
2506
2507 if (!mach3_read_inferior (their_cprocs,
2508 &cproc_copy->raw_cproc[0],
2509 CPROC_SIZE))
c5aa993b 2510 error ("Can't read next cproc at 0x%x.", their_cprocs);
c906108c
SS
2511
2512 their_cprocs =
2513 extract_address (cproc_copy->raw_cproc + CPROC_LIST_OFFSET,
2514 CPROC_LIST_SIZE);
2515 cproc_copy_incarnation =
2516 extract_address (cproc_copy->raw_cproc + CPROC_INCARNATION_OFFSET,
2517 CPROC_INCARNATION_SIZE);
2518
c5aa993b 2519 if (cproc_copy_incarnation == (CORE_ADDR) 0)
c906108c
SS
2520 cproc_copy->cthread = NULL;
2521 else
2522 {
2523 /* This CPROC has an attached CTHREAD. Get its name */
c5aa993b
JM
2524 cthread = (cthread_t) obstack_alloc (cproc_obstack,
2525 sizeof (struct cthread));
c906108c
SS
2526
2527 if (!mach3_read_inferior (cproc_copy_incarnation,
2528 cthread,
c5aa993b
JM
2529 sizeof (struct cthread)))
2530 error ("Can't read next thread at 0x%x.",
2531 cproc_copy_incarnation);
c906108c
SS
2532
2533 cproc_copy->cthread = cthread;
2534
2535 if (cthread->name)
2536 {
2537 name = (char *) obstack_alloc (cproc_obstack, MAX_NAME_LEN);
2538
c5aa993b
JM
2539 if (!mach3_read_inferior (cthread->name, name, MAX_NAME_LEN))
2540 error ("Can't read next thread's name at 0x%x.", cthread->name);
c906108c
SS
2541
2542 cthread->name = name;
2543 }
2544 }
2545
2546 /* insert in front */
2547 cproc_copy->next = cproc_head;
2548 cproc_head = cproc_copy;
2549 }
2550 return cproc_head;
2551}
2552
2553#ifndef FETCH_CPROC_STATE
2554/*
2555 * Check if your machine does not grok the way this routine
2556 * fetches the FP,PC and SP of a cproc that is not
2557 * currently attached to any kernel thread (e.g. its cproc.context
2558 * field points to the place in stack where the context
2559 * is saved).
2560 *
2561 * If it doesn't, define your own routine.
2562 */
2563#define FETCH_CPROC_STATE(mth) mach3_cproc_state (mth)
2564
2565int
fba45db2 2566mach3_cproc_state (gdb_thread_t mthread)
c906108c
SS
2567{
2568 int context;
2569
c5aa993b 2570 if (!mthread || !mthread->cproc)
c906108c
SS
2571 return -1;
2572
2573 context = extract_signed_integer
2574 (mthread->cproc->raw_cproc + CPROC_CONTEXT_OFFSET,
2575 CPROC_CONTEXT_SIZE);
2576 if (context == 0)
2577 return -1;
2578
2579 mthread->sp = context + MACHINE_CPROC_SP_OFFSET;
2580
2581 if (mach3_read_inferior (context + MACHINE_CPROC_PC_OFFSET,
2582 &mthread->pc,
2583 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2584 {
2585 warning ("Can't read cproc pc from inferior");
2586 return -1;
2587 }
2588
2589 if (mach3_read_inferior (context + MACHINE_CPROC_FP_OFFSET,
2590 &mthread->fp,
2591 sizeof (CORE_ADDR)) != sizeof (CORE_ADDR))
2592 {
2593 warning ("Can't read cproc fp from inferior");
2594 return -1;
2595 }
2596
2597 return 0;
2598}
2599#endif /* FETCH_CPROC_STATE */
c906108c 2600\f
c5aa993b 2601
c906108c 2602void
fba45db2 2603thread_list_command (void)
c906108c
SS
2604{
2605 thread_basic_info_data_t ths;
c5aa993b 2606 int thread_count;
c906108c
SS
2607 gdb_thread_t cprocs;
2608 gdb_thread_t scan;
c5aa993b
JM
2609 int index;
2610 char *name;
2611 char selected;
2612 char *wired;
2613 int infoCnt;
c906108c 2614 kern_return_t ret;
c5aa993b
JM
2615 mach_port_t mid_or_port;
2616 gdb_thread_t their_threads;
2617 gdb_thread_t kthread;
c906108c
SS
2618
2619 int neworder = 1;
2620
2621 char *fmt = "There are %d kernel threads in task %d.\n";
c5aa993b 2622
c906108c 2623 int tmid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 2624
c906108c 2625 MACH_ERROR_NO_INFERIOR;
c5aa993b 2626
c906108c
SS
2627 thread_count = fetch_thread_info (inferior_task,
2628 &their_threads);
2629 if (thread_count == -1)
2630 return;
c5aa993b 2631
c906108c
SS
2632 if (thread_count == 1)
2633 fmt = "There is %d kernel thread in task %d.\n";
c5aa993b 2634
c906108c 2635 printf_filtered (fmt, thread_count, tmid);
c5aa993b 2636
c906108c 2637 puts_filtered (TL_HEADER);
c5aa993b
JM
2638
2639 cprocs = get_cprocs ();
2640
c906108c 2641 map_cprocs_to_kernel_threads (cprocs, their_threads, thread_count);
c5aa993b 2642
c906108c
SS
2643 for (scan = cprocs; scan; scan = scan->next)
2644 {
2645 int mid;
2646 char buf[10];
2647 char slot[3];
2648 int cproc_state =
c5aa993b
JM
2649 extract_signed_integer
2650 (scan->raw_cproc + CPROC_STATE_OFFSET, CPROC_STATE_SIZE);
2651
c906108c 2652 selected = ' ';
c5aa993b 2653
c906108c
SS
2654 /* a wired cproc? */
2655 wired = (extract_address (scan->raw_cproc + CPROC_WIRED_OFFSET,
2656 CPROC_WIRED_SIZE)
2657 ? "wired" : "");
2658
2659 if (scan->reverse_map != -1)
c5aa993b 2660 kthread = (their_threads + scan->reverse_map);
c906108c 2661 else
c5aa993b 2662 kthread = NULL;
c906108c
SS
2663
2664 if (kthread)
2665 {
2666 /* These cprocs have a kernel thread */
c5aa993b 2667
c906108c 2668 mid = map_port_name_to_mid (kthread->name, MACH_TYPE_THREAD);
c5aa993b 2669
c906108c 2670 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 2671
c906108c
SS
2672 ret = thread_info (kthread->name,
2673 THREAD_BASIC_INFO,
c5aa993b 2674 (thread_info_t) & ths,
c906108c 2675 &infoCnt);
c5aa993b 2676
c906108c
SS
2677 if (ret != KERN_SUCCESS)
2678 {
2679 warning ("Unable to get basic info on thread %d : %s",
2680 mid,
2681 mach_error_string (ret));
2682 continue;
2683 }
2684
2685 /* Who is the first to have more than 100 threads */
c5aa993b 2686 sprintf (slot, "%d", kthread->slotid % 100);
c906108c
SS
2687
2688 if (kthread->name == current_thread)
2689 selected = '*';
c5aa993b 2690
c906108c
SS
2691 if (ths.suspend_count)
2692 sprintf (buf, "%d", ths.suspend_count);
2693 else
2694 buf[0] = '\000';
2695
2696#if 0
2697 if (ths.flags & TH_FLAGS_SWAPPED)
2698 strcat (buf, "S");
2699#endif
2700
2701 if (ths.flags & TH_FLAGS_IDLE)
2702 strcat (buf, "I");
2703
2704 printf_filtered (TL_FORMAT,
2705 slot,
2706 mid,
2707 selected,
2708 get_thread_name (scan, kthread->slotid),
2709 kthread->in_emulator ? "E" : "",
2710 translate_state (ths.run_state),
2711 buf,
2712 translate_cstate (cproc_state),
2713 wired);
2714 print_tl_address (gdb_stdout, kthread->pc);
2715 }
2716 else
2717 {
2718 /* These cprocs don't have a kernel thread.
2719 * find out the calling frame with
2720 * FETCH_CPROC_STATE.
2721 */
2722
2723 struct gdb_thread state;
2724
2725#if 0
2726 /* jtv -> emcmanus: why do you want this here? */
2727 if (scan->incarnation == NULL)
c5aa993b 2728 continue; /* EMcM */
c906108c
SS
2729#endif
2730
2731 printf_filtered (TL_FORMAT,
2732 "-",
2733 -neworder, /* Pseudo MID */
2734 selected,
2735 get_thread_name (scan, -neworder),
2736 "",
2737 "-", /* kernel state */
2738 "",
2739 translate_cstate (cproc_state),
2740 "");
2741 state.cproc = scan;
2742
2743 if (FETCH_CPROC_STATE (&state) == -1)
2744 puts_filtered ("???");
2745 else
2746 print_tl_address (gdb_stdout, state.pc);
2747
2748 neworder++;
2749 }
2750 puts_filtered ("\n");
2751 }
c5aa993b 2752
c906108c
SS
2753 /* Scan for kernel threads without cprocs */
2754 for (index = 0; index < thread_count; index++)
2755 {
c5aa993b 2756 if (!their_threads[index].cproc)
c906108c
SS
2757 {
2758 int mid;
c5aa993b 2759
c906108c
SS
2760 char buf[10];
2761 char slot[3];
2762
2763 mach_port_t name = their_threads[index].name;
c5aa993b 2764
c906108c 2765 mid = map_port_name_to_mid (name, MACH_TYPE_THREAD);
c5aa993b 2766
c906108c 2767 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b
JM
2768
2769 ret = thread_info (name,
2770 THREAD_BASIC_INFO,
2771 (thread_info_t) & ths,
2772 &infoCnt);
2773
c906108c
SS
2774 if (ret != KERN_SUCCESS)
2775 {
2776 warning ("Unable to get basic info on thread %d : %s",
2777 mid,
2778 mach_error_string (ret));
2779 continue;
2780 }
2781
c5aa993b 2782 sprintf (slot, "%d", index % 100);
c906108c
SS
2783
2784 if (name == current_thread)
2785 selected = '*';
2786 else
2787 selected = ' ';
2788
2789 if (ths.suspend_count)
2790 sprintf (buf, "%d", ths.suspend_count);
2791 else
2792 buf[0] = '\000';
2793
2794#if 0
2795 if (ths.flags & TH_FLAGS_SWAPPED)
2796 strcat (buf, "S");
2797#endif
2798
2799 if (ths.flags & TH_FLAGS_IDLE)
2800 strcat (buf, "I");
2801
2802 printf_filtered (TL_FORMAT,
2803 slot,
2804 mid,
2805 selected,
2806 get_thread_name (NULL, index),
2807 their_threads[index].in_emulator ? "E" : "",
2808 translate_state (ths.run_state),
2809 buf,
c5aa993b 2810 "", /* No cproc state */
c906108c
SS
2811 ""); /* Can't be wired */
2812 print_tl_address (gdb_stdout, their_threads[index].pc);
2813 puts_filtered ("\n");
2814 }
2815 }
c5aa993b 2816
c906108c
SS
2817 obstack_free (cproc_obstack, 0);
2818 obstack_init (cproc_obstack);
2819}
2820\f
2821void
fba45db2 2822thread_select_command (char *args, int from_tty)
c906108c
SS
2823{
2824 int mid;
2825 thread_array_t thread_list;
2826 int thread_count;
2827 kern_return_t ret;
2828 int is_slot = 0;
2829
2830 MACH_ERROR_NO_INFERIOR;
2831
2832 if (!args)
2833 error_no_arg ("MID or @SLOTNUMBER to specify a thread to select");
2834
2835 while (*args == ' ' || *args == '\t')
2836 args++;
2837
2838 if (*args == '@')
2839 {
2840 is_slot++;
2841 args++;
2842 }
2843
c5aa993b 2844 mid = atoi (args);
c906108c
SS
2845
2846 if (mid == 0)
c5aa993b 2847 if (!is_slot || *args != '0') /* Rudimentary checks */
c906108c
SS
2848 error ("You must select threads by MID or @SLOTNUMBER");
2849
c5aa993b 2850 if (select_thread (inferior_task, mid, is_slot ? 2 : 1) != KERN_SUCCESS)
c906108c
SS
2851 return;
2852
2853 if (from_tty)
2854 printf_filtered ("Thread %d selected\n",
2855 is_slot ? map_port_name_to_mid (current_thread,
c5aa993b 2856 MACH_TYPE_THREAD) : mid);
c906108c
SS
2857}
2858\f
fba45db2 2859thread_trace (mach_port_t thread, boolean_t set)
c906108c 2860{
c5aa993b
JM
2861 int flavor = TRACE_FLAVOR;
2862 unsigned int stateCnt = TRACE_FLAVOR_SIZE;
2863 kern_return_t ret;
2864 thread_state_data_t state;
c906108c 2865
c5aa993b 2866 if (!MACH_PORT_VALID (thread))
c906108c
SS
2867 {
2868 warning ("thread_trace: invalid thread");
2869 return;
2870 }
2871
2872 if (must_suspend_thread)
2873 setup_thread (thread, 1);
2874
c5aa993b 2875 ret = thread_get_state (thread, flavor, state, &stateCnt);
c906108c 2876 CHK ("thread_trace: error reading thread state", ret);
c5aa993b 2877
c906108c
SS
2878 if (set)
2879 {
2880 TRACE_SET (thread, state);
2881 }
2882 else
2883 {
c5aa993b 2884 if (!TRACE_CLEAR (thread, state))
c906108c
SS
2885 {
2886 if (must_suspend_thread)
2887 setup_thread (thread, 0);
2888 return;
2889 }
2890 }
2891
c5aa993b 2892 ret = thread_set_state (thread, flavor, state, stateCnt);
c906108c
SS
2893 CHK ("thread_trace: error writing thread state", ret);
2894 if (must_suspend_thread)
2895 setup_thread (thread, 0);
c5aa993b 2896}
c906108c
SS
2897
2898#ifdef FLUSH_INFERIOR_CACHE
2899
2900/* When over-writing code on some machines the I-Cache must be flushed
2901 explicitly, because it is not kept coherent by the lazy hardware.
2902 This definitely includes breakpoints, for instance, or else we
2903 end up looping in mysterious Bpt traps */
2904
fba45db2 2905flush_inferior_icache (CORE_ADDR pc, int amount)
c906108c
SS
2906{
2907 vm_machine_attribute_val_t flush = MATTR_VAL_ICACHE_FLUSH;
c5aa993b
JM
2908 kern_return_t ret;
2909
c906108c
SS
2910 ret = vm_machine_attribute (inferior_task,
2911 pc,
2912 amount,
2913 MATTR_CACHE,
2914 &flush);
2915 if (ret != KERN_SUCCESS)
2916 warning ("Error flushing inferior's cache : %s",
2917 mach_error_string (ret));
2918}
c5aa993b 2919#endif /* FLUSH_INFERIOR_CACHE */
c906108c 2920\f
c5aa993b 2921
c906108c 2922static
fba45db2 2923suspend_all_threads (int from_tty)
c906108c 2924{
c5aa993b
JM
2925 kern_return_t ret;
2926 thread_array_t thread_list;
2927 int thread_count, index;
2928 int infoCnt;
c906108c
SS
2929 thread_basic_info_data_t th_info;
2930
c5aa993b 2931
c906108c
SS
2932 ret = task_threads (inferior_task, &thread_list, &thread_count);
2933 if (ret != KERN_SUCCESS)
2934 {
2935 warning ("Could not suspend inferior threads.");
2936 m3_kill_inferior ();
2937 return_to_top_level (RETURN_ERROR);
2938 }
c5aa993b 2939
c906108c
SS
2940 for (index = 0; index < thread_count; index++)
2941 {
2942 int mid;
2943
c5aa993b 2944 mid = map_port_name_to_mid (thread_list[index],
c906108c 2945 MACH_TYPE_THREAD);
c5aa993b
JM
2946
2947 ret = thread_suspend (thread_list[index]);
c906108c
SS
2948
2949 if (ret != KERN_SUCCESS)
2950 warning ("Error trying to suspend thread %d : %s",
2951 mid, mach_error_string (ret));
2952
2953 if (from_tty)
2954 {
2955 infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 2956 ret = thread_info (thread_list[index],
c906108c 2957 THREAD_BASIC_INFO,
c5aa993b 2958 (thread_info_t) & th_info,
c906108c
SS
2959 &infoCnt);
2960 CHK ("suspend can't get thread info", ret);
c5aa993b 2961
c906108c
SS
2962 warning ("Thread %d suspend count is %d",
2963 mid, th_info.suspend_count);
2964 }
2965 }
2966
2967 consume_send_rights (thread_list, thread_count);
c5aa993b
JM
2968 ret = vm_deallocate (mach_task_self (),
2969 (vm_address_t) thread_list,
2970 (thread_count * sizeof (int)));
c906108c
SS
2971 CHK ("Error trying to deallocate thread list", ret);
2972}
2973
2974void
fba45db2 2975thread_suspend_command (char *args, int from_tty)
c906108c
SS
2976{
2977 kern_return_t ret;
c5aa993b
JM
2978 int mid;
2979 mach_port_t saved_thread;
2980 int infoCnt;
c906108c 2981 thread_basic_info_data_t th_info;
c5aa993b 2982
c906108c
SS
2983 MACH_ERROR_NO_INFERIOR;
2984
c5aa993b
JM
2985 if (!strcasecmp (args, "all"))
2986 {
2987 suspend_all_threads (from_tty);
2988 return;
2989 }
c906108c
SS
2990
2991 saved_thread = current_thread;
2992
2993 mid = parse_thread_id (args, 0, 0);
2994
2995 if (mid < 0)
2996 error ("You can suspend only existing kernel threads with MID or @SLOTNUMBER");
2997
2998 if (mid == 0)
2999 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b
JM
3000 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3001 {
3002 if (current_thread)
3003 current_thread = saved_thread;
3004 error ("Could not select thread %d", mid);
3005 }
c906108c
SS
3006
3007 ret = thread_suspend (current_thread);
3008 if (ret != KERN_SUCCESS)
3009 warning ("thread_suspend failed : %s",
3010 mach_error_string (ret));
3011
3012 infoCnt = THREAD_BASIC_INFO_COUNT;
3013 ret = thread_info (current_thread,
3014 THREAD_BASIC_INFO,
c5aa993b 3015 (thread_info_t) & th_info,
c906108c
SS
3016 &infoCnt);
3017 CHK ("suspend can't get thread info", ret);
c5aa993b 3018
c906108c 3019 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
c5aa993b 3020
c906108c
SS
3021 current_thread = saved_thread;
3022}
3023
fba45db2 3024resume_all_threads (int from_tty)
c906108c 3025{
c5aa993b
JM
3026 kern_return_t ret;
3027 thread_array_t thread_list;
3028 int thread_count, index;
3029 int mid;
3030 int infoCnt;
3031 thread_basic_info_data_t th_info;
c906108c 3032
c5aa993b
JM
3033 ret = task_threads (inferior_task, &thread_list, &thread_count);
3034 if (ret != KERN_SUCCESS)
3035 {
3036 m3_kill_inferior ();
3037 error ("task_threads", mach_error_string (ret));
3038 }
c906108c 3039
c5aa993b
JM
3040 for (index = 0; index < thread_count; index++)
3041 {
3042 infoCnt = THREAD_BASIC_INFO_COUNT;
3043 ret = thread_info (thread_list[index],
3044 THREAD_BASIC_INFO,
3045 (thread_info_t) & th_info,
3046 &infoCnt);
3047 CHK ("resume_all can't get thread info", ret);
c906108c 3048
c5aa993b
JM
3049 mid = map_port_name_to_mid (thread_list[index],
3050 MACH_TYPE_THREAD);
c906108c 3051
c5aa993b
JM
3052 if (!th_info.suspend_count)
3053 {
3054 if (mid != -1 && from_tty)
3055 warning ("Thread %d is not suspended", mid);
3056 continue;
3057 }
c906108c 3058
c5aa993b
JM
3059 ret = thread_resume (thread_list[index]);
3060
3061 if (ret != KERN_SUCCESS)
3062 warning ("Error trying to resume thread %d : %s",
3063 mid, mach_error_string (ret));
3064 else if (mid != -1 && from_tty)
3065 warning ("Thread %d suspend count is %d",
3066 mid, --th_info.suspend_count);
3067 }
3068
3069 consume_send_rights (thread_list, thread_count);
3070 ret = vm_deallocate (mach_task_self (),
3071 (vm_address_t) thread_list,
3072 (thread_count * sizeof (int)));
3073 CHK ("Error trying to deallocate thread list", ret);
c906108c
SS
3074}
3075
3076void
fba45db2 3077thread_resume_command (char *args, int from_tty)
c906108c
SS
3078{
3079 int mid;
3080 mach_port_t saved_thread;
3081 kern_return_t ret;
3082 thread_basic_info_data_t th_info;
3083 int infoCnt = THREAD_BASIC_INFO_COUNT;
c5aa993b 3084
c906108c
SS
3085 MACH_ERROR_NO_INFERIOR;
3086
c5aa993b
JM
3087 if (!strcasecmp (args, "all"))
3088 {
3089 resume_all_threads (from_tty);
3090 return;
3091 }
c906108c
SS
3092
3093 saved_thread = current_thread;
3094
3095 mid = parse_thread_id (args, 0, 0);
3096
3097 if (mid < 0)
3098 error ("You can resume only existing kernel threads with MID or @SLOTNUMBER");
3099
3100 if (mid == 0)
3101 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b
JM
3102 else if (select_thread (inferior_task, mid, 0) != KERN_SUCCESS)
3103 {
3104 if (current_thread)
3105 current_thread = saved_thread;
3106 return_to_top_level (RETURN_ERROR);
3107 }
c906108c
SS
3108
3109 ret = thread_info (current_thread,
3110 THREAD_BASIC_INFO,
c5aa993b 3111 (thread_info_t) & th_info,
c906108c
SS
3112 &infoCnt);
3113 CHK ("resume can't get thread info", ret);
c5aa993b
JM
3114
3115 if (!th_info.suspend_count)
c906108c
SS
3116 {
3117 warning ("Thread %d is not suspended", mid);
3118 goto out;
3119 }
3120
3121 ret = thread_resume (current_thread);
3122 if (ret != KERN_SUCCESS)
3123 warning ("thread_resume failed : %s",
3124 mach_error_string (ret));
3125 else
3126 {
3127 th_info.suspend_count--;
3128 warning ("Thread %d suspend count is %d", mid, th_info.suspend_count);
3129 }
c5aa993b
JM
3130
3131out:
c906108c
SS
3132 current_thread = saved_thread;
3133}
3134
3135void
fba45db2 3136thread_kill_command (char *args, int from_tty)
c906108c
SS
3137{
3138 int mid;
3139 kern_return_t ret;
3140 int thread_count;
3141 thread_array_t thread_table;
c5aa993b 3142 int index;
c906108c 3143 mach_port_t thread_to_kill = MACH_PORT_NULL;
c5aa993b
JM
3144
3145
c906108c
SS
3146 MACH_ERROR_NO_INFERIOR;
3147
3148 if (!args)
3149 error_no_arg ("thread mid to kill from the inferior task");
3150
3151 mid = parse_thread_id (args, 0, 0);
3152
3153 if (mid < 0)
3154 error ("You can kill only existing kernel threads with MID or @SLOTNUMBER");
3155
3156 if (mid)
3157 {
3158 ret = machid_mach_port (mid_server, mid_auth, mid, &thread_to_kill);
3159 CHK ("thread_kill_command: machid_mach_port map failed", ret);
3160 }
3161 else
3162 mid = map_port_name_to_mid (current_thread, MACH_TYPE_THREAD);
c5aa993b 3163
c906108c
SS
3164 /* Don't allow gdb to kill *any* thread in the system. Use mkill program for that */
3165 ret = task_threads (inferior_task, &thread_table, &thread_count);
3166 CHK ("Error getting inferior's thread list", ret);
c5aa993b 3167
c906108c
SS
3168 if (thread_to_kill == current_thread)
3169 {
3170 ret = thread_terminate (thread_to_kill);
3171 CHK ("Thread could not be terminated", ret);
3172
3173 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3174 warning ("Last thread was killed, use \"kill\" command to kill task");
3175 }
3176 else
3177 for (index = 0; index < thread_count; index++)
c5aa993b 3178 if (thread_table[index] == thread_to_kill)
c906108c
SS
3179 {
3180 ret = thread_terminate (thread_to_kill);
3181 CHK ("Thread could not be terminated", ret);
3182 }
3183
3184 if (thread_count > 1)
3185 consume_send_rights (thread_table, thread_count);
c5aa993b
JM
3186
3187 ret = vm_deallocate (mach_task_self (), (vm_address_t) thread_table,
3188 (thread_count * sizeof (mach_port_t)));
c906108c 3189 CHK ("Error trying to deallocate thread list", ret);
c5aa993b 3190
c906108c
SS
3191 warning ("Thread %d killed", mid);
3192}
c906108c 3193\f
c5aa993b 3194
c906108c
SS
3195/* Task specific commands; add more if you like */
3196
3197void
fba45db2 3198task_resume_command (char *args, int from_tty)
c906108c
SS
3199{
3200 kern_return_t ret;
3201 task_basic_info_data_t ta_info;
3202 int infoCnt = TASK_BASIC_INFO_COUNT;
3203 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 3204
c906108c
SS
3205 MACH_ERROR_NO_INFERIOR;
3206
3207 /* Would be trivial to change, but is it desirable? */
3208 if (args)
3209 error ("Currently gdb can resume only it's inferior task");
3210
3211 ret = task_info (inferior_task,
3212 TASK_BASIC_INFO,
c5aa993b 3213 (task_info_t) & ta_info,
c906108c
SS
3214 &infoCnt);
3215 CHK ("task_resume_command: task_info failed", ret);
c5aa993b 3216
c906108c
SS
3217 if (ta_info.suspend_count == 0)
3218 error ("Inferior task %d is not suspended", mid);
3219 else if (ta_info.suspend_count == 1 &&
3220 from_tty &&
c5aa993b 3221 !query ("Suspend count is now 1. Do you know what you are doing? "))
c906108c
SS
3222 error ("Task not resumed");
3223
3224 ret = task_resume (inferior_task);
3225 CHK ("task_resume_command: task_resume", ret);
3226
3227 if (ta_info.suspend_count == 1)
3228 {
3229 warning ("Inferior task %d is no longer suspended", mid);
3230 must_suspend_thread = 1;
3231 /* @@ This is not complete: Registers change all the time when not
c5aa993b 3232 suspended! */
c906108c
SS
3233 registers_changed ();
3234 }
3235 else
3236 warning ("Inferior task %d suspend count is now %d",
c5aa993b 3237 mid, ta_info.suspend_count - 1);
c906108c
SS
3238}
3239
3240
3241void
fba45db2 3242task_suspend_command (char *args, int from_tty)
c906108c
SS
3243{
3244 kern_return_t ret;
3245 task_basic_info_data_t ta_info;
3246 int infoCnt = TASK_BASIC_INFO_COUNT;
3247 int mid = map_port_name_to_mid (inferior_task, MACH_TYPE_TASK);
c5aa993b 3248
c906108c
SS
3249 MACH_ERROR_NO_INFERIOR;
3250
3251 /* Would be trivial to change, but is it desirable? */
3252 if (args)
3253 error ("Currently gdb can suspend only it's inferior task");
3254
3255 ret = task_suspend (inferior_task);
3256 CHK ("task_suspend_command: task_suspend", ret);
3257
3258 must_suspend_thread = 0;
3259
3260 ret = task_info (inferior_task,
3261 TASK_BASIC_INFO,
c5aa993b 3262 (task_info_t) & ta_info,
c906108c
SS
3263 &infoCnt);
3264 CHK ("task_suspend_command: task_info failed", ret);
c5aa993b 3265
c906108c
SS
3266 warning ("Inferior task %d suspend count is now %d",
3267 mid, ta_info.suspend_count);
3268}
3269
3270static char *
fba45db2 3271get_size (int bytes)
c906108c 3272{
c5aa993b
JM
3273 static char size[30];
3274 int zz = bytes / 1024;
c906108c
SS
3275
3276 if (zz / 1024)
c5aa993b 3277 sprintf (size, "%-2.1f M", ((float) bytes) / (1024.0 * 1024.0));
c906108c
SS
3278 else
3279 sprintf (size, "%d K", zz);
3280
3281 return size;
3282}
3283
3284/* Does this require the target task to be suspended?? I don't think so. */
3285void
fba45db2 3286task_info_command (char *args, int from_tty)
c906108c
SS
3287{
3288 int mid = -5;
3289 mach_port_t task;
3290 kern_return_t ret;
3291 task_basic_info_data_t ta_info;
3292 int infoCnt = TASK_BASIC_INFO_COUNT;
c5aa993b 3293 int page_size = round_page (1);
c906108c 3294 int thread_count = 0;
c5aa993b 3295
c906108c
SS
3296 if (MACH_PORT_VALID (inferior_task))
3297 mid = map_port_name_to_mid (inferior_task,
3298 MACH_TYPE_TASK);
3299
3300 task = inferior_task;
3301
3302 if (args)
3303 {
3304 int tmid = atoi (args);
3305
3306 if (tmid <= 0)
3307 error ("Invalid mid %d for task info", tmid);
3308
3309 if (tmid != mid)
3310 {
3311 mid = tmid;
3312 ret = machid_mach_port (mid_server, mid_auth, tmid, &task);
3313 CHK ("task_info_command: machid_mach_port map failed", ret);
3314 }
3315 }
3316
3317 if (mid < 0)
3318 error ("You have to give the task MID as an argument");
3319
3320 ret = task_info (task,
3321 TASK_BASIC_INFO,
c5aa993b 3322 (task_info_t) & ta_info,
c906108c
SS
3323 &infoCnt);
3324 CHK ("task_info_command: task_info failed", ret);
3325
3326 printf_filtered ("\nTask info for task %d:\n\n", mid);
3327 printf_filtered (" Suspend count : %d\n", ta_info.suspend_count);
3328 printf_filtered (" Base priority : %d\n", ta_info.base_priority);
3329 printf_filtered (" Virtual size : %s\n", get_size (ta_info.virtual_size));
3330 printf_filtered (" Resident size : %s\n", get_size (ta_info.resident_size));
3331
3332 {
3333 thread_array_t thread_list;
c5aa993b 3334
c906108c
SS
3335 ret = task_threads (task, &thread_list, &thread_count);
3336 CHK ("task_info_command: task_threads", ret);
c5aa993b 3337
c906108c
SS
3338 printf_filtered (" Thread count : %d\n", thread_count);
3339
3340 consume_send_rights (thread_list, thread_count);
c5aa993b
JM
3341 ret = vm_deallocate (mach_task_self (),
3342 (vm_address_t) thread_list,
3343 (thread_count * sizeof (int)));
3344 CHK ("Error trying to deallocate thread list", ret);
c906108c
SS
3345 }
3346 if (have_emulator_p (task))
3347 printf_filtered (" Emulator at : 0x%x..0x%x\n",
3348 EMULATOR_BASE, EMULATOR_END);
3349 else
3350 printf_filtered (" No emulator.\n");
3351
3352 if (thread_count && task == inferior_task)
3353 printf_filtered ("\nUse the \"thread list\" command to see the threads\n");
3354}
3355\f
3356/* You may either FORWARD the exception to the inferior, or KEEP
3357 * it and return to GDB command level.
3358 *
3359 * exception mid [ forward | keep ]
3360 */
3361
3362static void
fba45db2 3363exception_command (char *args, int from_tty)
c906108c
SS
3364{
3365 char *scan = args;
3366 int exception;
3367 int len;
3368
3369 if (!args)
3370 error_no_arg ("exception number action");
3371
c5aa993b
JM
3372 while (*scan == ' ' || *scan == '\t')
3373 scan++;
3374
c906108c
SS
3375 if ('0' <= *scan && *scan <= '9')
3376 while ('0' <= *scan && *scan <= '9')
3377 scan++;
3378 else
3379 error ("exception number action");
3380
3381 exception = atoi (args);
3382 if (exception <= 0 || exception > MAX_EXCEPTION)
3383 error ("Allowed exception numbers are in range 1..%d",
3384 MAX_EXCEPTION);
3385
3386 if (*scan != ' ' && *scan != '\t')
3387 error ("exception number must be followed by a space");
3388 else
c5aa993b
JM
3389 while (*scan == ' ' || *scan == '\t')
3390 scan++;
c906108c
SS
3391
3392 args = scan;
3393 len = 0;
3394 while (*scan)
3395 {
3396 len++;
3397 scan++;
3398 }
3399
3400 if (!len)
c5aa993b 3401 error ("exception number action");
c906108c
SS
3402
3403 if (!strncasecmp (args, "forward", len))
c5aa993b 3404 exception_map[exception].forward = TRUE;
c906108c 3405 else if (!strncasecmp (args, "keep", len))
c5aa993b 3406 exception_map[exception].forward = FALSE;
c906108c
SS
3407 else
3408 error ("exception action is either \"keep\" or \"forward\"");
3409}
3410
3411static void
fba45db2 3412print_exception_info (int exception)
c906108c 3413{
c5aa993b 3414 boolean_t forward = exception_map[exception].forward;
c906108c 3415
c5aa993b 3416 printf_filtered ("%s\t(%d): ", exception_map[exception].name,
c906108c
SS
3417 exception);
3418 if (!forward)
c5aa993b 3419 if (exception_map[exception].sigmap != SIG_UNKNOWN)
c906108c 3420 printf_filtered ("keep and handle as signal %d\n",
c5aa993b 3421 exception_map[exception].sigmap);
c906108c
SS
3422 else
3423 printf_filtered ("keep and handle as unknown signal %d\n",
c5aa993b 3424 exception_map[exception].sigmap);
c906108c
SS
3425 else
3426 printf_filtered ("forward exception to inferior\n");
3427}
3428
3429void
fba45db2 3430exception_info (char *args, int from_tty)
c906108c
SS
3431{
3432 int exception;
3433
3434 if (!args)
3435 for (exception = 1; exception <= MAX_EXCEPTION; exception++)
3436 print_exception_info (exception);
3437 else
3438 {
3439 exception = atoi (args);
3440
3441 if (exception <= 0 || exception > MAX_EXCEPTION)
3442 error ("Invalid exception number, values from 1 to %d allowed",
3443 MAX_EXCEPTION);
3444 print_exception_info (exception);
3445 }
3446}
3447\f
3448/* Check for actions for mach exceptions.
3449 */
fba45db2 3450mach3_exception_actions (WAITTYPE *w, boolean_t force_print_only, char *who)
c906108c
SS
3451{
3452 boolean_t force_print = FALSE;
3453
c5aa993b 3454
c906108c
SS
3455 if (force_print_only ||
3456 exception_map[stop_exception].sigmap == SIG_UNKNOWN)
3457 force_print = TRUE;
3458 else
3459 WSETSTOP (*w, exception_map[stop_exception].sigmap);
3460
3461 if (exception_map[stop_exception].print || force_print)
3462 {
3463 target_terminal_ours ();
c5aa993b 3464
c906108c
SS
3465 printf_filtered ("\n%s received %s exception : ",
3466 who,
3467 exception_map[stop_exception].name);
c5aa993b 3468
c906108c
SS
3469 wrap_here (" ");
3470
c5aa993b
JM
3471 switch (stop_exception)
3472 {
3473 case EXC_BAD_ACCESS:
3474 printf_filtered ("referencing address 0x%x : %s\n",
3475 stop_subcode,
3476 mach_error_string (stop_code));
3477 break;
3478 case EXC_BAD_INSTRUCTION:
3479 printf_filtered
3480 ("illegal or undefined instruction. code %d subcode %d\n",
3481 stop_code, stop_subcode);
3482 break;
3483 case EXC_ARITHMETIC:
3484 printf_filtered ("code %d\n", stop_code);
3485 break;
3486 case EXC_EMULATION:
3487 printf_filtered ("code %d subcode %d\n", stop_code, stop_subcode);
3488 break;
3489 case EXC_SOFTWARE:
3490 printf_filtered ("%s specific, code 0x%x\n",
3491 stop_code < 0xffff ? "hardware" : "os emulation",
3492 stop_code);
3493 break;
3494 case EXC_BREAKPOINT:
3495 printf_filtered ("type %d (machine dependent)\n",
3496 stop_code);
3497 break;
3498 default:
8e65ff28
AC
3499 internal_error (__FILE__, __LINE__,
3500 "Unknown exception");
c5aa993b 3501 }
c906108c
SS
3502 }
3503}
3504\f
fba45db2 3505setup_notify_port (int create_new)
c906108c
SS
3506{
3507 kern_return_t ret;
3508
3509 if (MACH_PORT_VALID (our_notify_port))
3510 {
3511 ret = mach_port_destroy (mach_task_self (), our_notify_port);
3512 CHK ("Could not destroy our_notify_port", ret);
3513 }
3514
3515 our_notify_port = MACH_PORT_NULL;
c5aa993b 3516 notify_chain = (port_chain_t) NULL;
c906108c
SS
3517 port_chain_destroy (port_chain_obstack);
3518
3519 if (create_new)
3520 {
c5aa993b 3521 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
3522 MACH_PORT_RIGHT_RECEIVE,
3523 &our_notify_port);
3524 if (ret != KERN_SUCCESS)
8e65ff28
AC
3525 internal_error (__FILE__, __LINE__,
3526 "Creating notify port %s", mach_error_string (ret));
c5aa993b
JM
3527
3528 ret = mach_port_move_member (mach_task_self (),
3529 our_notify_port,
3530 inferior_wait_port_set);
c906108c 3531 if (ret != KERN_SUCCESS)
8e65ff28
AC
3532 internal_error (__FILE__, __LINE__,
3533 "initial move member %s", mach_error_string (ret));
c906108c
SS
3534 }
3535}
3536
3537/*
3538 * Register our message port to the net name server
3539 *
3540 * Currently used only by the external stop-gdb program
3541 * since ^C does not work if you would like to enter
3542 * gdb command level while debugging your program.
3543 *
3544 * NOTE: If the message port is sometimes used for other
3545 * purposes also, the NAME must not be a guessable one.
3546 * Then, there should be a way to change it.
3547 */
3548
c5aa993b 3549char registered_name[MAX_NAME_LEN];
c906108c
SS
3550
3551void
fba45db2 3552message_port_info (char *args, int from_tty)
c906108c
SS
3553{
3554 if (registered_name[0])
3555 printf_filtered ("gdb's message port name: '%s'\n",
3556 registered_name);
3557 else
3558 printf_filtered ("gdb's message port is not currently registered\n");
3559}
3560
3561void
fba45db2 3562gdb_register_port (char *name, mach_port_t port)
c906108c
SS
3563{
3564 kern_return_t ret;
3565 static int already_signed = 0;
3566 int len;
3567
c5aa993b 3568 if (!MACH_PORT_VALID (port) || !name || !*name)
c906108c
SS
3569 {
3570 warning ("Invalid registration request");
3571 return;
3572 }
3573
c5aa993b 3574 if (!already_signed)
c906108c
SS
3575 {
3576 ret = mach_port_insert_right (mach_task_self (),
3577 our_message_port,
3578 our_message_port,
3579 MACH_MSG_TYPE_MAKE_SEND);
3580 CHK ("Failed to create a signature to our_message_port", ret);
3581 already_signed = 1;
3582 }
3583 else if (already_signed > 1)
3584 {
3585 ret = netname_check_out (name_server_port,
3586 registered_name,
3587 our_message_port);
3588 CHK ("Failed to check out gdb's message port", ret);
3589 registered_name[0] = '\000';
3590 already_signed = 1;
3591 }
3592
3593 ret = netname_check_in (name_server_port, /* Name server port */
c5aa993b 3594 name, /* Name of service */
c906108c 3595 our_message_port, /* Signature */
c5aa993b
JM
3596 port); /* Creates a new send right */
3597 CHK ("Failed to check in the port", ret);
3598
c906108c 3599 len = 0;
c5aa993b 3600 while (len < MAX_NAME_LEN && *(name + len))
c906108c 3601 {
c5aa993b 3602 registered_name[len] = *(name + len);
c906108c
SS
3603 len++;
3604 }
3605 registered_name[len] = '\000';
3606 already_signed = 2;
c5aa993b 3607}
c906108c
SS
3608
3609struct cmd_list_element *cmd_thread_list;
3610struct cmd_list_element *cmd_task_list;
3611
c5aa993b 3612/*ARGSUSED */
c906108c 3613static void
fba45db2 3614thread_command (char *arg, int from_tty)
c906108c
SS
3615{
3616 printf_unfiltered ("\"thread\" must be followed by the name of a thread command.\n");
3617 help_list (cmd_thread_list, "thread ", -1, gdb_stdout);
3618}
3619
c5aa993b 3620/*ARGSUSED */
c906108c 3621static void
fba45db2 3622task_command (char *arg, int from_tty)
c906108c
SS
3623{
3624 printf_unfiltered ("\"task\" must be followed by the name of a task command.\n");
3625 help_list (cmd_task_list, "task ", -1, gdb_stdout);
3626}
3627
fba45db2 3628add_mach_specific_commands (void)
c906108c
SS
3629{
3630 /* Thread handling commands */
3631
3632 /* FIXME: Move our thread support into the generic thread.c stuff so we
3633 can share that code. */
3634 add_prefix_cmd ("mthread", class_stack, thread_command,
c5aa993b
JM
3635 "Generic command for handling Mach threads in the debugged task.",
3636 &cmd_thread_list, "thread ", 0, &cmdlist);
c906108c
SS
3637
3638 add_com_alias ("th", "mthread", class_stack, 1);
3639
c5aa993b 3640 add_cmd ("select", class_stack, thread_select_command,
c906108c
SS
3641 "Select and print MID of the selected thread",
3642 &cmd_thread_list);
c5aa993b 3643 add_cmd ("list", class_stack, thread_list_command,
c906108c
SS
3644 "List info of task's threads. Selected thread is marked with '*'",
3645 &cmd_thread_list);
3646 add_cmd ("suspend", class_run, thread_suspend_command,
3647 "Suspend one or all of the threads in the selected task.",
3648 &cmd_thread_list);
3649 add_cmd ("resume", class_run, thread_resume_command,
3650 "Resume one or all of the threads in the selected task.",
3651 &cmd_thread_list);
3652 add_cmd ("kill", class_run, thread_kill_command,
3653 "Kill the specified thread MID from inferior task.",
3654 &cmd_thread_list);
3655#if 0
3656 /* The rest of this support (condition_thread) was not merged. It probably
3657 should not be merged in this form, but instead added to the generic GDB
3658 thread support. */
3659 add_cmd ("break", class_breakpoint, condition_thread,
3660 "Breakpoint N will only be effective for thread MID or @SLOT\n\
3661 If MID/@SLOT is omitted allow all threads to break at breakpoint",
3662 &cmd_thread_list);
3663#endif
3664 /* Thread command shorthands (for backward compatibility) */
3665 add_alias_cmd ("ts", "mthread select", 0, 0, &cmdlist);
c5aa993b 3666 add_alias_cmd ("tl", "mthread list", 0, 0, &cmdlist);
c906108c
SS
3667
3668 /* task handling commands */
3669
3670 add_prefix_cmd ("task", class_stack, task_command,
c5aa993b
JM
3671 "Generic command for handling debugged task.",
3672 &cmd_task_list, "task ", 0, &cmdlist);
c906108c
SS
3673
3674 add_com_alias ("ta", "task", class_stack, 1);
3675
3676 add_cmd ("suspend", class_run, task_suspend_command,
3677 "Suspend the inferior task.",
3678 &cmd_task_list);
3679 add_cmd ("resume", class_run, task_resume_command,
3680 "Resume the inferior task.",
3681 &cmd_task_list);
3682 add_cmd ("info", no_class, task_info_command,
3683 "Print information about the specified task.",
3684 &cmd_task_list);
3685
3686 /* Print my message port name */
3687
3688 add_info ("message-port", message_port_info,
3689 "Returns the name of gdb's message port in the netnameserver");
3690
3691 /* Exception commands */
3692
3693 add_info ("exceptions", exception_info,
3694 "What debugger does when program gets various exceptions.\n\
3695Specify an exception number as argument to print info on that\n\
3696exception only.");
3697
3698 add_com ("exception", class_run, exception_command,
3699 "Specify how to handle an exception.\n\
3700Args are exception number followed by \"forward\" or \"keep\".\n\
3701`Forward' means forward the exception to the program's normal exception\n\
3702handler.\n\
3703`Keep' means reenter debugger if this exception happens, and GDB maps\n\
3704the exception to some signal (see info exception)\n\
3705Normally \"keep\" is used to return to GDB on exception.");
3706}
3707
3708kern_return_t
fba45db2 3709do_mach_notify_dead_name (mach_port_t notify, mach_port_t name)
c906108c
SS
3710{
3711 kern_return_t kr = KERN_SUCCESS;
3712
3713 /* Find the thing that notified */
3714 port_chain_t element = port_chain_member (notify_chain, name);
3715
3716 /* Take name of from unreceived dead name notification list */
3717 notify_chain = port_chain_delete (notify_chain, name);
3718
c5aa993b 3719 if (!element)
c906108c 3720 error ("Received a dead name notify from unchained port (0x%x)", name);
c906108c 3721
c5aa993b
JM
3722 switch (element->type)
3723 {
c906108c 3724
c5aa993b
JM
3725 case MACH_TYPE_THREAD:
3726 target_terminal_ours_for_output ();
3727 if (name == current_thread)
3728 {
3729 printf_filtered ("\nCurrent thread %d died", element->mid);
3730 current_thread = MACH_PORT_NULL;
3731 }
3732 else
3733 printf_filtered ("\nThread %d died", element->mid);
c906108c 3734
c5aa993b 3735 break;
c906108c 3736
c5aa993b
JM
3737 case MACH_TYPE_TASK:
3738 target_terminal_ours_for_output ();
3739 if (name != inferior_task)
3740 printf_filtered ("Task %d died, but it was not the selected task",
3741 element->mid);
3742 else
3743 {
3744 printf_filtered ("Current task %d died", element->mid);
c906108c 3745
c5aa993b
JM
3746 mach_port_destroy (mach_task_self (), name);
3747 inferior_task = MACH_PORT_NULL;
3748
3749 if (notify_chain)
3750 warning ("There were still unreceived dead_name_notifications???");
3751
3752 /* Destroy the old notifications */
3753 setup_notify_port (0);
3754
3755 }
3756 break;
3757
3758 default:
3759 error ("Unregistered dead_name 0x%x notification received. Type is %d, mid is 0x%x",
3760 name, element->type, element->mid);
3761 break;
3762 }
c906108c
SS
3763
3764 return KERN_SUCCESS;
3765}
3766
3767kern_return_t
fba45db2 3768do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t name)
c906108c
SS
3769{
3770 warning ("do_mach_notify_msg_accepted : notify %x, name %x",
3771 notify, name);
3772 return KERN_SUCCESS;
3773}
3774
3775kern_return_t
fba45db2 3776do_mach_notify_no_senders (mach_port_t notify, mach_port_mscount_t mscount)
c906108c
SS
3777{
3778 warning ("do_mach_notify_no_senders : notify %x, mscount %x",
3779 notify, mscount);
3780 return KERN_SUCCESS;
3781}
3782
3783kern_return_t
fba45db2 3784do_mach_notify_port_deleted (mach_port_t notify, mach_port_t name)
c906108c
SS
3785{
3786 warning ("do_mach_notify_port_deleted : notify %x, name %x",
3787 notify, name);
3788 return KERN_SUCCESS;
3789}
3790
3791kern_return_t
fba45db2 3792do_mach_notify_port_destroyed (mach_port_t notify, mach_port_t rights)
c906108c
SS
3793{
3794 warning ("do_mach_notify_port_destroyed : notify %x, rights %x",
3795 notify, rights);
3796 return KERN_SUCCESS;
3797}
3798
3799kern_return_t
fba45db2 3800do_mach_notify_send_once (mach_port_t notify)
c906108c
SS
3801{
3802#ifdef DUMP_SYSCALL
3803 /* MANY of these are generated. */
3804 warning ("do_mach_notify_send_once : notify %x",
3805 notify);
3806#endif
3807 return KERN_SUCCESS;
3808}
3809
3810/* Kills the inferior. It's gone when you call this */
3811static void
fba45db2 3812kill_inferior_fast (void)
c906108c
SS
3813{
3814 WAITTYPE w;
3815
3816 if (inferior_pid == 0 || inferior_pid == 1)
3817 return;
3818
3819 /* kill() it, since the Unix server does not otherwise notice when
3820 * killed with task_terminate().
3821 */
3822 if (inferior_pid > 0)
3823 kill (inferior_pid, SIGKILL);
3824
3825 /* It's propably terminate already */
3826 (void) task_terminate (inferior_task);
3827
c5aa993b 3828 inferior_task = MACH_PORT_NULL;
c906108c
SS
3829 current_thread = MACH_PORT_NULL;
3830
3831 wait3 (&w, WNOHANG, 0);
3832
3833 setup_notify_port (0);
3834}
3835
3836static void
fba45db2 3837m3_kill_inferior (void)
c906108c
SS
3838{
3839 kill_inferior_fast ();
3840 target_mourn_inferior ();
3841}
3842
3843/* Clean up after the inferior dies. */
3844
3845static void
fba45db2 3846m3_mourn_inferior (void)
c906108c
SS
3847{
3848 unpush_target (&m3_ops);
3849 generic_mourn_inferior ();
3850}
c906108c 3851\f
c5aa993b 3852
c906108c
SS
3853/* Fork an inferior process, and start debugging it. */
3854
3855static void
fba45db2 3856m3_create_inferior (char *exec_file, char *allargs, char **env)
c906108c
SS
3857{
3858 fork_inferior (exec_file, allargs, env, m3_trace_me, m3_trace_him, NULL, NULL);
3859 /* We are at the first instruction we care about. */
3860 /* Pedal to the metal... */
2acceee2 3861 proceed ((CORE_ADDR) -1, 0, 0);
c906108c
SS
3862}
3863
3864/* Mark our target-struct as eligible for stray "run" and "attach"
3865 commands. */
3866static int
fba45db2 3867m3_can_run (void)
c906108c
SS
3868{
3869 return 1;
3870}
3871\f
3872/* Mach 3.0 does not need ptrace for anything
3873 * Make sure nobody uses it on mach.
3874 */
fba45db2 3875ptrace (int a, int b, int c, int d)
c906108c
SS
3876{
3877 error ("Lose, Lose! Somebody called ptrace\n");
3878}
3879
3880/* Resume execution of the inferior process.
3881 If STEP is nonzero, single-step it.
3882 If SIGNAL is nonzero, give it that signal. */
3883
3884void
fba45db2 3885m3_resume (int pid, int step, enum target_signal signal)
c906108c 3886{
c5aa993b 3887 kern_return_t ret;
c906108c
SS
3888
3889 if (step)
3890 {
3891 thread_basic_info_data_t th_info;
c5aa993b
JM
3892 unsigned int infoCnt = THREAD_BASIC_INFO_COUNT;
3893
c906108c
SS
3894 /* There is no point in single stepping when current_thread
3895 * is dead.
3896 */
c5aa993b 3897 if (!MACH_PORT_VALID (current_thread))
c906108c 3898 error ("No thread selected; can not single step");
c5aa993b 3899
c906108c
SS
3900 /* If current_thread is suspended, tracing it would never return.
3901 */
3902 ret = thread_info (current_thread,
3903 THREAD_BASIC_INFO,
c5aa993b 3904 (thread_info_t) & th_info,
c906108c
SS
3905 &infoCnt);
3906 CHK ("child_resume: can't get thread info", ret);
c5aa993b 3907
c906108c
SS
3908 if (th_info.suspend_count)
3909 error ("Can't trace a suspended thread. Use \"thread resume\" command to resume it");
3910 }
3911
3912 vm_read_cache_valid = FALSE;
3913
c5aa993b 3914 if (signal && inferior_pid > 0) /* Do not signal, if attached by MID */
c906108c
SS
3915 kill (inferior_pid, target_signal_to_host (signal));
3916
3917 if (step)
3918 {
3919 suspend_all_threads (0);
3920
3921 setup_single_step (current_thread, TRUE);
c5aa993b 3922
c906108c
SS
3923 ret = thread_resume (current_thread);
3924 CHK ("thread_resume", ret);
3925 }
c5aa993b 3926
c906108c
SS
3927 ret = task_resume (inferior_task);
3928 if (ret == KERN_FAILURE)
3929 warning ("Task was not suspended");
3930 else
3931 CHK ("Resuming task", ret);
c5aa993b 3932
c906108c 3933 /* HACK HACK This is needed by the multiserver system HACK HACK */
c5aa993b
JM
3934 while ((ret = task_resume (inferior_task)) == KERN_SUCCESS)
3935 /* make sure it really runs */ ;
c906108c
SS
3936 /* HACK HACK This is needed by the multiserver system HACK HACK */
3937}
3938\f
3939#ifdef ATTACH_DETACH
3940
3941/* Start debugging the process with the given task */
3942void
fba45db2 3943task_attach (task_t tid)
c906108c
SS
3944{
3945 kern_return_t ret;
3946 inferior_task = tid;
3947
3948 ret = task_suspend (inferior_task);
c5aa993b 3949 CHK ("task_attach: task_suspend", ret);
c906108c
SS
3950
3951 must_suspend_thread = 0;
3952
3953 setup_notify_port (1);
3954
3955 request_notify (inferior_task, MACH_NOTIFY_DEAD_NAME, MACH_TYPE_TASK);
3956
3957 setup_exception_port ();
c5aa993b 3958
c906108c
SS
3959 emulator_present = have_emulator_p (inferior_task);
3960
3961 attach_flag = 1;
3962}
3963
3964/* Well, we can call error also here and leave the
3965 * target stack inconsistent. Sigh.
3966 * Fix this sometime (the only way to fail here is that
3967 * the task has no threads at all, which is rare, but
3968 * possible; or if the target task has died, which is also
3969 * possible, but unlikely, since it has been suspended.
3970 * (Someone must have killed it))
3971 */
3972void
fba45db2 3973attach_to_thread (void)
c906108c
SS
3974{
3975 if (select_thread (inferior_task, 0, 1) != KERN_SUCCESS)
3976 error ("Could not select any threads to attach to");
3977}
3978
fba45db2 3979mid_attach (int mid)
c906108c 3980{
c5aa993b 3981 kern_return_t ret;
c906108c 3982
c5aa993b
JM
3983 ret = machid_mach_port (mid_server, mid_auth, mid, &inferior_task);
3984 CHK ("mid_attach: machid_mach_port", ret);
c906108c 3985
c5aa993b 3986 task_attach (inferior_task);
c906108c 3987
c5aa993b 3988 return mid;
c906108c
SS
3989}
3990
3991/*
3992 * Start debugging the process whose unix process-id is PID.
3993 * A negative "pid" value is legal and signifies a mach_id not a unix pid.
3994 *
3995 * Prevent (possible unwanted) dangerous operations by enabled users
3996 * like "atta 0" or "atta foo" (equal to the previous :-) and
3997 * "atta pidself". Anyway, the latter is allowed by specifying a MID.
3998 */
3999static int
fba45db2 4000m3_do_attach (int pid)
c906108c
SS
4001{
4002 kern_return_t ret;
4003
4004 if (pid == 0)
c5aa993b 4005 error ("MID=0, Debugging the master unix server does not compute");
c906108c
SS
4006
4007 /* Foo. This assumes gdb has a unix pid */
c5aa993b 4008 if (pid == getpid ())
c906108c
SS
4009 error ("I will debug myself only by mid. (Gdb would suspend itself!)");
4010
4011 if (pid < 0)
4012 {
4013 mid_attach (-(pid));
4014
4015 /* inferior_pid will be NEGATIVE! */
4016 inferior_pid = pid;
4017
4018 return inferior_pid;
4019 }
4020
4021 inferior_task = task_by_pid (pid);
c5aa993b
JM
4022 if (!MACH_PORT_VALID (inferior_task))
4023 error ("Cannot map Unix pid %d to Mach task port", pid);
c906108c
SS
4024
4025 task_attach (inferior_task);
4026
4027 inferior_pid = pid;
4028
4029 return inferior_pid;
4030}
4031
4032/* Attach to process PID, then initialize for debugging it
4033 and wait for the trace-trap that results from attaching. */
4034
4035static void
fba45db2 4036m3_attach (char *args, int from_tty)
c906108c
SS
4037{
4038 char *exec_file;
4039 int pid;
4040
4041 if (!args)
4042 error_no_arg ("process-id to attach");
4043
4044 pid = atoi (args);
4045
c5aa993b 4046 if (pid == getpid ()) /* Trying to masturbate? */
c906108c
SS
4047 error ("I refuse to debug myself!");
4048
4049 if (from_tty)
4050 {
4051 exec_file = (char *) get_exec_file (0);
4052
4053 if (exec_file)
4054 printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
4055 else
4056 printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
4057
4058 gdb_flush (gdb_stdout);
4059 }
4060
4061 m3_do_attach (pid);
4062 inferior_pid = pid;
4063 push_target (&m3_ops);
4064}
4065\f
4066void
fba45db2 4067deallocate_inferior_ports (void)
c906108c 4068{
c5aa993b 4069 kern_return_t ret;
c906108c 4070 thread_array_t thread_list;
c5aa993b 4071 int thread_count, index;
c906108c
SS
4072
4073 if (!MACH_PORT_VALID (inferior_task))
4074 return;
4075
4076 ret = task_threads (inferior_task, &thread_list, &thread_count);
4077 if (ret != KERN_SUCCESS)
4078 {
4079 warning ("deallocate_inferior_ports: task_threads",
c5aa993b 4080 mach_error_string (ret));
c906108c
SS
4081 return;
4082 }
4083
4084 /* Get rid of send rights to task threads */
4085 for (index = 0; index < thread_count; index++)
4086 {
4087 int rights;
4088 ret = mach_port_get_refs (mach_task_self (),
4089 thread_list[index],
4090 MACH_PORT_RIGHT_SEND,
4091 &rights);
c5aa993b 4092 CHK ("deallocate_inferior_ports: get refs", ret);
c906108c
SS
4093
4094 if (rights > 0)
4095 {
4096 ret = mach_port_mod_refs (mach_task_self (),
4097 thread_list[index],
4098 MACH_PORT_RIGHT_SEND,
4099 -rights);
c5aa993b 4100 CHK ("deallocate_inferior_ports: mod refs", ret);
c906108c
SS
4101 }
4102 }
4103
4104 ret = mach_port_mod_refs (mach_task_self (),
4105 inferior_exception_port,
4106 MACH_PORT_RIGHT_RECEIVE,
4107 -1);
4108 CHK ("deallocate_inferior_ports: cannot get rid of exception port", ret);
4109
4110 ret = mach_port_deallocate (mach_task_self (),
4111 inferior_task);
4112 CHK ("deallocate_task_port: deallocating inferior_task", ret);
4113
4114 current_thread = MACH_PORT_NULL;
c5aa993b 4115 inferior_task = MACH_PORT_NULL;
c906108c
SS
4116}
4117
4118/* Stop debugging the process whose number is PID
4119 and continue it with signal number SIGNAL.
4120 SIGNAL = 0 means just continue it. */
4121
4122static void
fba45db2 4123m3_do_detach (int signal)
c906108c
SS
4124{
4125 kern_return_t ret;
4126
4127 MACH_ERROR_NO_INFERIOR;
4128
4129 if (current_thread != MACH_PORT_NULL)
4130 {
4131 /* Store the gdb's view of the thread we are deselecting
4132 * before we detach.
4133 * @@ I am really not sure if this is ever needeed.
4134 */
4135 target_prepare_to_store ();
4136 target_store_registers (-1);
4137 }
4138
4139 ret = task_set_special_port (inferior_task,
c5aa993b 4140 TASK_EXCEPTION_PORT,
c906108c
SS
4141 inferior_old_exception_port);
4142 CHK ("task_set_special_port", ret);
4143
4144 /* Discard all requested notifications */
4145 setup_notify_port (0);
4146
4147 if (remove_breakpoints ())
4148 warning ("Could not remove breakpoints when detaching");
c5aa993b 4149
c906108c
SS
4150 if (signal && inferior_pid > 0)
4151 kill (inferior_pid, signal);
c5aa993b 4152
c906108c
SS
4153 /* the task might be dead by now */
4154 (void) task_resume (inferior_task);
c5aa993b 4155
c906108c 4156 deallocate_inferior_ports ();
c5aa993b 4157
c906108c
SS
4158 attach_flag = 0;
4159}
4160
4161/* Take a program previously attached to and detaches it.
4162 The program resumes execution and will no longer stop
4163 on signals, etc. We'd better not have left any breakpoints
4164 in the program or it'll die when it hits one. For this
4165 to work, it may be necessary for the process to have been
4166 previously attached. It *might* work if the program was
4167 started via fork. */
4168
4169static void
fba45db2 4170m3_detach (char *args, int from_tty)
c906108c
SS
4171{
4172 int siggnal = 0;
4173
4174 if (from_tty)
4175 {
4176 char *exec_file = get_exec_file (0);
4177 if (exec_file == 0)
4178 exec_file = "";
4179 printf_unfiltered ("Detaching from program: %s %s\n",
c5aa993b 4180 exec_file, target_pid_to_str (inferior_pid));
c906108c
SS
4181 gdb_flush (gdb_stdout);
4182 }
4183 if (args)
4184 siggnal = atoi (args);
c5aa993b 4185
c906108c
SS
4186 m3_do_detach (siggnal);
4187 inferior_pid = 0;
c5aa993b 4188 unpush_target (&m3_ops); /* Pop out of handling an inferior */
c906108c
SS
4189}
4190#endif /* ATTACH_DETACH */
4191
4192/* Get ready to modify the registers array. On machines which store
4193 individual registers, this doesn't need to do anything. On machines
4194 which store all the registers in one fell swoop, this makes sure
4195 that registers contains all the registers from the program being
4196 debugged. */
4197
4198static void
fba45db2 4199m3_prepare_to_store (void)
c906108c
SS
4200{
4201#ifdef CHILD_PREPARE_TO_STORE
4202 CHILD_PREPARE_TO_STORE ();
4203#endif
4204}
4205
4206/* Print status information about what we're accessing. */
4207
4208static void
fba45db2 4209m3_files_info (struct target_ops *ignore)
c906108c
SS
4210{
4211 /* FIXME: should print MID and all that crap. */
4212 printf_unfiltered ("\tUsing the running image of %s %s.\n",
c5aa993b 4213 attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
c906108c
SS
4214}
4215
4216static void
fba45db2 4217m3_open (char *arg, int from_tty)
c906108c
SS
4218{
4219 error ("Use the \"run\" command to start a Unix child process.");
4220}
4221
4222#ifdef DUMP_SYSCALL
c906108c 4223#define STR(x) #x
c906108c 4224
c5aa993b
JM
4225char *bsd1_names[] =
4226{
c906108c
SS
4227 "execve",
4228 "fork",
4229 "take_signal",
4230 "sigreturn",
4231 "getrusage",
4232 "chdir",
4233 "chroot",
4234 "open",
4235 "creat",
4236 "mknod",
4237 "link",
4238 "symlink",
4239 "unlink",
4240 "access",
4241 "stat",
4242 "readlink",
4243 "chmod",
4244 "chown",
4245 "utimes",
4246 "truncate",
4247 "rename",
4248 "mkdir",
4249 "rmdir",
4250 "xutimes",
4251 "mount",
4252 "umount",
4253 "acct",
4254 "setquota",
4255 "write_short",
4256 "write_long",
4257 "send_short",
4258 "send_long",
4259 "sendto_short",
4260 "sendto_long",
4261 "select",
4262 "task_by_pid",
4263 "recvfrom_short",
4264 "recvfrom_long",
4265 "setgroups",
4266 "setrlimit",
4267 "sigvec",
4268 "sigstack",
4269 "settimeofday",
4270 "adjtime",
4271 "setitimer",
4272 "sethostname",
4273 "bind",
4274 "accept",
4275 "connect",
4276 "setsockopt",
4277 "getsockopt",
4278 "getsockname",
4279 "getpeername",
4280 "init_process",
4281 "table_set",
4282 "table_get",
4283 "pioctl",
4284 "emulator_error",
4285 "readwrite",
4286 "share_wakeup",
4287 0,
4288 "maprw_request_it",
4289 "maprw_release_it",
4290 "maprw_remap",
4291 "pid_by_task",
4292};
4293
c5aa993b 4294int bsd1_nnames = sizeof (bsd1_names) / sizeof (bsd1_names[0]);
c906108c 4295
c5aa993b 4296char *
fba45db2 4297name_str (int name, char *buf)
c906108c 4298{
c5aa993b
JM
4299 switch (name)
4300 {
4301 case MACH_MSG_TYPE_BOOLEAN:
4302 return "boolean";
4303 case MACH_MSG_TYPE_INTEGER_16:
4304 return "short";
4305 case MACH_MSG_TYPE_INTEGER_32:
4306 return "long";
4307 case MACH_MSG_TYPE_CHAR:
4308 return "char";
4309 case MACH_MSG_TYPE_BYTE:
4310 return "byte";
4311 case MACH_MSG_TYPE_REAL:
4312 return "real";
4313 case MACH_MSG_TYPE_STRING:
4314 return "string";
4315 default:
4316 sprintf (buf, "%d", name);
4317 return buf;
4318 }
c906108c
SS
4319}
4320
4321char *
fba45db2 4322id_str (int id, char *buf)
c906108c 4323{
c5aa993b
JM
4324 char *p;
4325 if (id >= 101000 && id < 101000 + bsd1_nnames)
4326 {
4327 if (p = bsd1_names[id - 101000])
4328 return p;
4329 }
c906108c
SS
4330 if (id == 102000)
4331 return "psignal_retry";
4332 if (id == 100000)
4333 return "syscall";
c5aa993b 4334 sprintf (buf, "%d", id);
c906108c
SS
4335 return buf;
4336}
4337
fba45db2 4338print_msg (mach_msg_header_t *mp)
c906108c 4339{
c5aa993b
JM
4340 char *fmt_x = "%20s : 0x%08x\n";
4341 char *fmt_d = "%20s : %10d\n";
4342 char *fmt_s = "%20s : %s\n";
4343 char buf[100];
c906108c
SS
4344
4345 puts_filtered ("\n");
4346#define pr(fmt,h,x) printf_filtered(fmt,STR(x),(h).x)
c5aa993b
JM
4347 pr (fmt_x, (*mp), msgh_bits);
4348 pr (fmt_d, (*mp), msgh_size);
4349 pr (fmt_x, (*mp), msgh_remote_port);
4350 pr (fmt_x, (*mp), msgh_local_port);
4351 pr (fmt_d, (*mp), msgh_kind);
4352 printf_filtered (fmt_s, STR (msgh_id), id_str (mp->msgh_id, buf));
4353
c906108c 4354 if (debug_level > 1)
c5aa993b
JM
4355 {
4356 char *p, *ep, *dp;
4357 int plen;
4358 p = (char *) mp;
4359 ep = p + mp->msgh_size;
4360 p += sizeof (*mp);
4361 for (; p < ep; p += plen)
4362 {
4363 mach_msg_type_t *tp;
4364 mach_msg_type_long_t *tlp;
4365 int name, size, number;
4366 tp = (mach_msg_type_t *) p;
4367 if (tp->msgt_longform)
4368 {
4369 tlp = (mach_msg_type_long_t *) tp;
4370 name = tlp->msgtl_name;
4371 size = tlp->msgtl_size;
4372 number = tlp->msgtl_number;
4373 plen = sizeof (*tlp);
4374 }
4375 else
4376 {
4377 name = tp->msgt_name;
4378 size = tp->msgt_size;
4379 number = tp->msgt_number;
4380 plen = sizeof (*tp);
4381 }
4382 printf_filtered ("name=%-16s size=%2d number=%7d inline=%d long=%d deal=%d\n",
4383 name_str (name, buf), size, number, tp->msgt_inline,
4384 tp->msgt_longform, tp->msgt_deallocate);
4385 dp = p + plen;
4386 if (tp->msgt_inline)
4387 {
4388 int l;
4389 l = size * number / 8;
4390 l = (l + sizeof (long) - 1) & ~((sizeof (long)) - 1);
4391 plen += l;
4392 print_data (dp, size, number);
4393 }
4394 else
4395 {
4396 plen += sizeof (int *);
4397 }
4398 printf_filtered ("plen=%d\n", plen);
4399 }
c906108c 4400 }
c906108c
SS
4401}
4402
fba45db2 4403print_data (char *p, int size, int number)
c906108c 4404{
c5aa993b
JM
4405 int *ip;
4406 short *sp;
4407 int i;
4408
4409 switch (size)
4410 {
4411 case 8:
4412 for (i = 0; i < number; i++)
4413 {
4414 printf_filtered (" %02x", p[i]);
4415 }
4416 break;
4417 case 16:
4418 sp = (short *) p;
4419 for (i = 0; i < number; i++)
4420 {
4421 printf_filtered (" %04x", sp[i]);
4422 }
4423 break;
4424 case 32:
4425 ip = (int *) p;
4426 for (i = 0; i < number; i++)
4427 {
4428 printf_filtered (" %08x", ip[i]);
4429 }
4430 break;
c906108c 4431 }
c5aa993b 4432 puts_filtered ("\n");
c906108c 4433}
c5aa993b 4434#endif /* DUMP_SYSCALL */
c906108c
SS
4435
4436static void
fba45db2 4437m3_stop (void)
c906108c
SS
4438{
4439 error ("to_stop target function not implemented");
4440}
4441
4442static char *
fba45db2 4443m3_pid_to_exec_file (int pid)
c906108c
SS
4444{
4445 error ("to_pid_to_exec_file target function not implemented");
c5aa993b 4446 return NULL; /* To keep all compilers happy. */
c906108c
SS
4447}
4448
4449static void
fba45db2 4450init_m3_ops (void)
c906108c
SS
4451{
4452 m3_ops.to_shortname = "mach";
4453 m3_ops.to_longname = "Mach child process";
4454 m3_ops.to_doc = "Mach child process (started by the \"run\" command).";
4455 m3_ops.to_open = m3_open;
4456 m3_ops.to_attach = m3_attach;
4457 m3_ops.to_detach = m3_detach;
4458 m3_ops.to_resume = m3_resume;
4459 m3_ops.to_wait = mach_really__wait;
4460 m3_ops.to_fetch_registers = fetch_inferior_registers;
4461 m3_ops.to_store_registers = store_inferior_registers;
4462 m3_ops.to_prepare_to_store = m3_prepare_to_store;
4463 m3_ops.to_xfer_memory = m3_xfer_memory;
4464 m3_ops.to_files_info = m3_files_info;
4465 m3_ops.to_insert_breakpoint = memory_insert_breakpoint;
4466 m3_ops.to_remove_breakpoint = memory_remove_breakpoint;
4467 m3_ops.to_terminal_init = terminal_init_inferior;
4468 m3_ops.to_terminal_inferior = terminal_inferior;
4469 m3_ops.to_terminal_ours_for_output = terminal_ours_for_output;
4470 m3_ops.to_terminal_ours = terminal_ours;
4471 m3_ops.to_terminal_info = child_terminal_info;
4472 m3_ops.to_kill = m3_kill_inferior;
4473 m3_ops.to_create_inferior = m3_create_inferior;
4474 m3_ops.to_mourn_inferior = m3_mourn_inferior;
4475 m3_ops.to_can_run = m3_can_run;
4476 m3_ops.to_stop = m3_stop;
4477 m3_ops.to_pid_to_exec_file = m3_pid_to_exec_file;
4478 m3_ops.to_stratum = process_stratum;
4479 m3_ops.to_has_all_memory = 1;
4480 m3_ops.to_has_memory = 1;
4481 m3_ops.to_has_stack = 1;
4482 m3_ops.to_has_registers = 1;
4483 m3_ops.to_has_execution = 1;
4484 m3_ops.to_magic = OPS_MAGIC;
4485}
4486
4487void
fba45db2 4488_initialize_m3_nat (void)
c906108c
SS
4489{
4490 kern_return_t ret;
4491
4492 init_m3_ops ();
4493 add_target (&m3_ops);
4494
c5aa993b
JM
4495 ret = mach_port_allocate (mach_task_self (),
4496 MACH_PORT_RIGHT_PORT_SET,
4497 &inferior_wait_port_set);
c906108c 4498 if (ret != KERN_SUCCESS)
8e65ff28
AC
4499 internal_error (__FILE__, __LINE__,
4500 "initial port set %s", mach_error_string (ret));
c906108c
SS
4501
4502 /* mach_really_wait now waits for this */
4503 currently_waiting_for = inferior_wait_port_set;
4504
c5aa993b 4505 ret = netname_look_up (name_server_port, hostname, "MachID", &mid_server);
c906108c
SS
4506 if (ret != KERN_SUCCESS)
4507 {
4508 mid_server = MACH_PORT_NULL;
c5aa993b 4509
c906108c 4510 warning ("initialize machid: netname_lookup_up(MachID) : %s",
c5aa993b 4511 mach_error_string (ret));
c906108c
SS
4512 warning ("Some (most?) features disabled...");
4513 }
c5aa993b
JM
4514
4515 mid_auth = mach_privileged_host_port ();
c906108c 4516 if (mid_auth == MACH_PORT_NULL)
c5aa993b
JM
4517 mid_auth = mach_task_self ();
4518
c906108c
SS
4519 obstack_init (port_chain_obstack);
4520
c5aa993b 4521 ret = mach_port_allocate (mach_task_self (),
c906108c
SS
4522 MACH_PORT_RIGHT_RECEIVE,
4523 &thread_exception_port);
4524 CHK ("Creating thread_exception_port for single stepping", ret);
c5aa993b 4525
c906108c
SS
4526 ret = mach_port_insert_right (mach_task_self (),
4527 thread_exception_port,
4528 thread_exception_port,
4529 MACH_MSG_TYPE_MAKE_SEND);
4530 CHK ("Inserting send right to thread_exception_port", ret);
4531
4532 /* Allocate message port */
4533 ret = mach_port_allocate (mach_task_self (),
4534 MACH_PORT_RIGHT_RECEIVE,
4535 &our_message_port);
4536 if (ret != KERN_SUCCESS)
4537 warning ("Creating message port %s", mach_error_string (ret));
4538 else
4539 {
c5aa993b
JM
4540 char buf[MAX_NAME_LEN];
4541 ret = mach_port_move_member (mach_task_self (),
4542 our_message_port,
4543 inferior_wait_port_set);
c906108c
SS
4544 if (ret != KERN_SUCCESS)
4545 warning ("message move member %s", mach_error_string (ret));
4546
4547
4548 /* @@@@ No way to change message port name currently */
4549 /* Foo. This assumes gdb has a unix pid */
4550 sprintf (buf, "gdb-%d", getpid ());
4551 gdb_register_port (buf, our_message_port);
4552 }
c5aa993b 4553
c906108c
SS
4554 /* Heap for thread commands */
4555 obstack_init (cproc_obstack);
4556
4557 add_mach_specific_commands ();
4558}
This page took 0.283981 seconds and 4 git commands to generate.