OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [m3-nat.c] - Blame information for rev 104

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.