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