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