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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [hpux-thread.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 104 markom
/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU debugger.
2
   Copyright 1996, 1999 Free Software Foundation, Inc.
3
 
4
   This file is part of GDB.
5
 
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 2 of the License, or
9
   (at your option) any later version.
10
 
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
 
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 59 Temple Place - Suite 330,
19
   Boston, MA 02111-1307, USA.  */
20
 
21
/* This module implements a sort of half target that sits between the
22
   machine-independent parts of GDB and the ptrace interface (infptrace.c) to
23
   provide access to the HPUX user-mode thread implementation.
24
 
25
   HPUX threads are true user-mode threads, which are invoked via the cma_*
26
   and pthread_* (DCE and Posix respectivly) interfaces.  These are mostly
27
   implemented in user-space, with all thread context kept in various
28
   structures that live in the user's heap.  For the most part, the kernel has
29
   no knowlege of these threads.
30
 
31
 */
32
 
33
#include "defs.h"
34
 
35
#define _CMA_NOWRAPPERS_
36
 
37
#include <cma_tcb_defs.h>
38
#include <cma_deb_core.h>
39
#include "gdbthread.h"
40
#include "target.h"
41
#include "inferior.h"
42
#include <fcntl.h>
43
#include <sys/stat.h>
44
#include "gdbcore.h"
45
 
46
extern int child_suppress_run;
47
extern struct target_ops child_ops;     /* target vector for inftarg.c */
48
 
49
extern void _initialize_hpux_thread PARAMS ((void));
50
 
51
struct string_map
52
  {
53
    int num;
54
    char *str;
55
  };
56
 
57
static int hpux_thread_active = 0;
58
 
59
static int main_pid;            /* Real process ID */
60
 
61
static CORE_ADDR P_cma__g_known_threads;
62
static CORE_ADDR P_cma__g_current_thread;
63
 
64
static struct cleanup *save_inferior_pid PARAMS ((void));
65
 
66
static void restore_inferior_pid PARAMS ((int pid));
67
 
68
static void hpux_thread_resume PARAMS ((int pid, int step,
69
                                        enum target_signal signo));
70
 
71
static void init_hpux_thread_ops PARAMS ((void));
72
 
73
static struct target_ops hpux_thread_ops;
74
 
75
/*
76
 
77
   LOCAL FUNCTION
78
 
79
   save_inferior_pid - Save inferior_pid on the cleanup list
80
   restore_inferior_pid - Restore inferior_pid from the cleanup list
81
 
82
   SYNOPSIS
83
 
84
   struct cleanup *save_inferior_pid ()
85
   void restore_inferior_pid (int pid)
86
 
87
   DESCRIPTION
88
 
89
   These two functions act in unison to restore inferior_pid in
90
   case of an error.
91
 
92
   NOTES
93
 
94
   inferior_pid is a global variable that needs to be changed by many of
95
   these routines before calling functions in procfs.c.  In order to
96
   guarantee that inferior_pid gets restored (in case of errors), you
97
   need to call save_inferior_pid before changing it.  At the end of the
98
   function, you should invoke do_cleanups to restore it.
99
 
100
 */
101
 
102
 
103
static struct cleanup *
104
save_inferior_pid ()
105
{
106
  return make_cleanup (restore_inferior_pid, inferior_pid);
107
}
108
 
109
static void
110
restore_inferior_pid (pid)
111
     int pid;
112
{
113
  inferior_pid = pid;
114
}
115
 
116
static int find_active_thread PARAMS ((void));
117
 
118
static int cached_thread;
119
static int cached_active_thread;
120
static cma__t_int_tcb cached_tcb;
121
 
122
static int
123
find_active_thread ()
124
{
125
  static cma__t_int_tcb tcb;
126
  CORE_ADDR tcb_ptr;
127
 
128
  if (cached_active_thread != 0)
129
    return cached_active_thread;
130
 
131
  read_memory ((CORE_ADDR) P_cma__g_current_thread,
132
               (char *) &tcb_ptr,
133
               sizeof tcb_ptr);
134
 
135
  read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
136
 
137
  return (cma_thread_get_unique (&tcb.prolog.client_thread) << 16) | main_pid;
138
}
139
 
140
static cma__t_int_tcb *find_tcb PARAMS ((int thread));
141
 
142
static cma__t_int_tcb *
143
find_tcb (thread)
144
     int thread;
145
{
146
  cma__t_known_object queue_header;
147
  cma__t_queue *queue_ptr;
148
 
149
  if (thread == cached_thread)
150
    return &cached_tcb;
151
 
152
  read_memory ((CORE_ADDR) P_cma__g_known_threads,
153
               (char *) &queue_header,
154
               sizeof queue_header);
155
 
156
  for (queue_ptr = queue_header.queue.flink;
157
       queue_ptr != (cma__t_queue *) P_cma__g_known_threads;
158
       queue_ptr = cached_tcb.threads.flink)
159
    {
160
      cma__t_int_tcb *tcb_ptr;
161
 
162
      tcb_ptr = cma__base (queue_ptr, threads, cma__t_int_tcb);
163
 
164
      read_memory ((CORE_ADDR) tcb_ptr, (char *) &cached_tcb, sizeof cached_tcb);
165
 
166
      if (cached_tcb.header.type == cma__c_obj_tcb)
167
        if (cma_thread_get_unique (&cached_tcb.prolog.client_thread) == thread >> 16)
168
          {
169
            cached_thread = thread;
170
            return &cached_tcb;
171
          }
172
    }
173
 
174
  error ("Can't find TCB %d,%d", thread >> 16, thread & 0xffff);
175
  return NULL;
176
}
177
 
178
/* Most target vector functions from here on actually just pass through to
179
   inftarg.c, as they don't need to do anything specific for threads.  */
180
 
181
/* ARGSUSED */
182
static void
183
hpux_thread_open (arg, from_tty)
184
     char *arg;
185
     int from_tty;
186
{
187
  child_ops.to_open (arg, from_tty);
188
}
189
 
190
/* Attach to process PID, then initialize for debugging it
191
   and wait for the trace-trap that results from attaching.  */
192
 
193
static void
194
hpux_thread_attach (args, from_tty)
195
     char *args;
196
     int from_tty;
197
{
198
  child_ops.to_attach (args, from_tty);
199
 
200
  /* XXX - might want to iterate over all the threads and register them. */
201
}
202
 
203
/* Take a program previously attached to and detaches it.
204
   The program resumes execution and will no longer stop
205
   on signals, etc.  We'd better not have left any breakpoints
206
   in the program or it'll die when it hits one.  For this
207
   to work, it may be necessary for the process to have been
208
   previously attached.  It *might* work if the program was
209
   started via the normal ptrace (PTRACE_TRACEME).  */
210
 
211
static void
212
hpux_thread_detach (args, from_tty)
213
     char *args;
214
     int from_tty;
215
{
216
  child_ops.to_detach (args, from_tty);
217
}
218
 
219
/* Resume execution of process PID.  If STEP is nozero, then
220
   just single step it.  If SIGNAL is nonzero, restart it with that
221
   signal activated.  We may have to convert pid from a thread-id to an LWP id
222
   for procfs.  */
223
 
224
static void
225
hpux_thread_resume (pid, step, signo)
226
     int pid;
227
     int step;
228
     enum target_signal signo;
229
{
230
  struct cleanup *old_chain;
231
 
232
  old_chain = save_inferior_pid ();
233
 
234
  pid = inferior_pid = main_pid;
235
 
236
#if 0
237
  if (pid != -1)
238
    {
239
      pid = thread_to_lwp (pid, -2);
240
      if (pid == -2)            /* Inactive thread */
241
        error ("This version of Solaris can't start inactive threads.");
242
    }
243
#endif
244
 
245
  child_ops.to_resume (pid, step, signo);
246
 
247
  cached_thread = 0;
248
  cached_active_thread = 0;
249
 
250
  do_cleanups (old_chain);
251
}
252
 
253
/* Wait for any threads to stop.  We may have to convert PID from a thread id
254
   to a LWP id, and vice versa on the way out.  */
255
 
256
static int
257
hpux_thread_wait (pid, ourstatus)
258
     int pid;
259
     struct target_waitstatus *ourstatus;
260
{
261
  int rtnval;
262
  struct cleanup *old_chain;
263
 
264
  old_chain = save_inferior_pid ();
265
 
266
  inferior_pid = main_pid;
267
 
268
  if (pid != -1)
269
    pid = main_pid;
270
 
271
  rtnval = child_ops.to_wait (pid, ourstatus);
272
 
273
  rtnval = find_active_thread ();
274
 
275
  do_cleanups (old_chain);
276
 
277
  return rtnval;
278
}
279
 
280
static char regmap[NUM_REGS] =
281
{
282
  -2, -1, -1, 0, 4, 8, 12, 16, 20, 24,   /* flags, r1 -> r9 */
283
  28, 32, 36, 40, 44, 48, 52, 56, 60, -1,       /* r10 -> r19 */
284
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       /* r20 -> r29 */
285
 
286
  /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
287
  -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
288
 
289
  /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
290
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
291
 
292
  /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
293
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
294
 
295
  -1, -1, -1, -1,               /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
296
  144, -1, -1, -1, -1, -1, -1, -1,      /* fpsr, fpe1 -> fpe7 */
297
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr4 -> fr7 */
298
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr8 -> fr11 */
299
  136, -1, 128, -1, 120, -1, 112, -1,   /* fr12 -> fr15 */
300
  104, -1, 96, -1, 88, -1, 80, -1,      /* fr16 -> fr19 */
301
  72, -1, 64, -1, -1, -1, -1, -1,       /* fr20 -> fr23 */
302
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr24 -> fr27 */
303
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr28 -> fr31 */
304
};
305
 
306
static void
307
hpux_thread_fetch_registers (regno)
308
     int regno;
309
{
310
  cma__t_int_tcb tcb, *tcb_ptr;
311
  struct cleanup *old_chain;
312
  int i;
313
  int first_regno, last_regno;
314
 
315
  tcb_ptr = find_tcb (inferior_pid);
316
 
317
  old_chain = save_inferior_pid ();
318
 
319
  inferior_pid = main_pid;
320
 
321
  if (tcb_ptr->state == cma__c_state_running)
322
    {
323
      child_ops.to_fetch_registers (regno);
324
 
325
      do_cleanups (old_chain);
326
 
327
      return;
328
    }
329
 
330
  if (regno == -1)
331
    {
332
      first_regno = 0;
333
      last_regno = NUM_REGS - 1;
334
    }
335
  else
336
    {
337
      first_regno = regno;
338
      last_regno = regno;
339
    }
340
 
341
  for (regno = first_regno; regno <= last_regno; regno++)
342
    {
343
      if (regmap[regno] == -1)
344
        child_ops.to_fetch_registers (regno);
345
      else
346
        {
347
          unsigned char buf[MAX_REGISTER_RAW_SIZE];
348
          CORE_ADDR sp;
349
 
350
          sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
351
 
352
          if (regno == FLAGS_REGNUM)
353
            /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
354
            memset (buf, '\000', REGISTER_RAW_SIZE (regno));
355
          else if (regno == SP_REGNUM)
356
            store_address (buf, sizeof sp, sp);
357
          else if (regno == PC_REGNUM)
358
            read_memory (sp - 20, buf, REGISTER_RAW_SIZE (regno));
359
          else
360
            read_memory (sp + regmap[regno], buf, REGISTER_RAW_SIZE (regno));
361
 
362
          supply_register (regno, buf);
363
        }
364
    }
365
 
366
  do_cleanups (old_chain);
367
}
368
 
369
static void
370
hpux_thread_store_registers (regno)
371
     int regno;
372
{
373
  cma__t_int_tcb tcb, *tcb_ptr;
374
  struct cleanup *old_chain;
375
  int i;
376
  int first_regno, last_regno;
377
 
378
  tcb_ptr = find_tcb (inferior_pid);
379
 
380
  old_chain = save_inferior_pid ();
381
 
382
  inferior_pid = main_pid;
383
 
384
  if (tcb_ptr->state == cma__c_state_running)
385
    {
386
      child_ops.to_store_registers (regno);
387
 
388
      do_cleanups (old_chain);
389
 
390
      return;
391
    }
392
 
393
  if (regno == -1)
394
    {
395
      first_regno = 0;
396
      last_regno = NUM_REGS - 1;
397
    }
398
  else
399
    {
400
      first_regno = regno;
401
      last_regno = regno;
402
    }
403
 
404
  for (regno = first_regno; regno <= last_regno; regno++)
405
    {
406
      if (regmap[regno] == -1)
407
        child_ops.to_store_registers (regno);
408
      else
409
        {
410
          unsigned char buf[MAX_REGISTER_RAW_SIZE];
411
          CORE_ADDR sp;
412
 
413
          sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
414
 
415
          if (regno == FLAGS_REGNUM)
416
            child_ops.to_store_registers (regno);       /* Let lower layer handle this... */
417
          else if (regno == SP_REGNUM)
418
            {
419
              write_memory ((CORE_ADDR) & tcb_ptr->static_ctx.sp,
420
                            registers + REGISTER_BYTE (regno),
421
                            REGISTER_RAW_SIZE (regno));
422
              tcb_ptr->static_ctx.sp = (cma__t_hppa_regs *)
423
                (extract_address (registers + REGISTER_BYTE (regno), REGISTER_RAW_SIZE (regno)) + 160);
424
            }
425
          else if (regno == PC_REGNUM)
426
            write_memory (sp - 20,
427
                          registers + REGISTER_BYTE (regno),
428
                          REGISTER_RAW_SIZE (regno));
429
          else
430
            write_memory (sp + regmap[regno],
431
                          registers + REGISTER_BYTE (regno),
432
                          REGISTER_RAW_SIZE (regno));
433
        }
434
    }
435
 
436
  do_cleanups (old_chain);
437
}
438
 
439
/* Get ready to modify the registers array.  On machines which store
440
   individual registers, this doesn't need to do anything.  On machines
441
   which store all the registers in one fell swoop, this makes sure
442
   that registers contains all the registers from the program being
443
   debugged.  */
444
 
445
static void
446
hpux_thread_prepare_to_store ()
447
{
448
  child_ops.to_prepare_to_store ();
449
}
450
 
451
static int
452
hpux_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
453
     CORE_ADDR memaddr;
454
     char *myaddr;
455
     int len;
456
     int dowrite;
457
     struct target_ops *target; /* ignored */
458
{
459
  int retval;
460
  struct cleanup *old_chain;
461
 
462
  old_chain = save_inferior_pid ();
463
 
464
  inferior_pid = main_pid;
465
 
466
  retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
467
 
468
  do_cleanups (old_chain);
469
 
470
  return retval;
471
}
472
 
473
/* Print status information about what we're accessing.  */
474
 
475
static void
476
hpux_thread_files_info (ignore)
477
     struct target_ops *ignore;
478
{
479
  child_ops.to_files_info (ignore);
480
}
481
 
482
static void
483
hpux_thread_kill_inferior ()
484
{
485
  child_ops.to_kill ();
486
}
487
 
488
static void
489
hpux_thread_notice_signals (pid)
490
     int pid;
491
{
492
  child_ops.to_notice_signals (pid);
493
}
494
 
495
/* Fork an inferior process, and start debugging it with /proc.  */
496
 
497
static void
498
hpux_thread_create_inferior (exec_file, allargs, env)
499
     char *exec_file;
500
     char *allargs;
501
     char **env;
502
{
503
  child_ops.to_create_inferior (exec_file, allargs, env);
504
 
505
  if (hpux_thread_active)
506
    {
507
      main_pid = inferior_pid;
508
 
509
      push_target (&hpux_thread_ops);
510
 
511
      inferior_pid = find_active_thread ();
512
 
513
      add_thread (inferior_pid);
514
    }
515
}
516
 
517
/* This routine is called whenever a new symbol table is read in, or when all
518
   symbol tables are removed.  libthread_db can only be initialized when it
519
   finds the right variables in libthread.so.  Since it's a shared library,
520
   those variables don't show up until the library gets mapped and the symbol
521
   table is read in.  */
522
 
523
/* This new_objfile event is now managed by a chained function pointer.
524
 * It is the callee's responsability to call the next client on the chain.
525
 */
526
 
527
/* Saved pointer to previous owner of the new_objfile event. */
528
static void (*target_new_objfile_chain) PARAMS ((struct objfile *));
529
 
530
void
531
hpux_thread_new_objfile (objfile)
532
     struct objfile *objfile;
533
{
534
  struct minimal_symbol *ms;
535
 
536
  if (!objfile)
537
    {
538
      hpux_thread_active = 0;
539
      goto quit;
540
    }
541
 
542
  ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
543
 
544
  if (!ms)
545
    goto quit;
546
 
547
  P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
548
 
549
  ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
550
 
551
  if (!ms)
552
    goto quit;
553
 
554
  P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
555
 
556
  hpux_thread_active = 1;
557
quit:
558
  /* Call predecessor on chain, if any. */
559
  if (target_new_objfile_chain)
560
    target_new_objfile_chain (objfile);
561
}
562
 
563
/* Clean up after the inferior dies.  */
564
 
565
static void
566
hpux_thread_mourn_inferior ()
567
{
568
  child_ops.to_mourn_inferior ();
569
}
570
 
571
/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
572
 
573
static int
574
hpux_thread_can_run ()
575
{
576
  return child_suppress_run;
577
}
578
 
579
static int
580
hpux_thread_alive (pid)
581
     int pid;
582
{
583
  return 1;
584
}
585
 
586
static void
587
hpux_thread_stop ()
588
{
589
  child_ops.to_stop ();
590
}
591
 
592
/* Convert a pid to printable form. */
593
 
594
char *
595
hpux_pid_to_str (pid)
596
     int pid;
597
{
598
  static char buf[100];
599
 
600
  sprintf (buf, "Thread %d", pid >> 16);
601
 
602
  return buf;
603
}
604
 
605
static void
606
init_hpux_thread_ops ()
607
{
608
  hpux_thread_ops.to_shortname = "hpux-threads";
609
  hpux_thread_ops.to_longname = "HPUX threads and pthread.";
610
  hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
611
  hpux_thread_ops.to_open = hpux_thread_open;
612
  hpux_thread_ops.to_attach = hpux_thread_attach;
613
  hpux_thread_ops.to_detach = hpux_thread_detach;
614
  hpux_thread_ops.to_resume = hpux_thread_resume;
615
  hpux_thread_ops.to_wait = hpux_thread_wait;
616
  hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
617
  hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
618
  hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
619
  hpux_thread_ops.to_xfer_memory = hpux_thread_xfer_memory;
620
  hpux_thread_ops.to_files_info = hpux_thread_files_info;
621
  hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
622
  hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
623
  hpux_thread_ops.to_terminal_init = terminal_init_inferior;
624
  hpux_thread_ops.to_terminal_inferior = terminal_inferior;
625
  hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
626
  hpux_thread_ops.to_terminal_ours = terminal_ours;
627
  hpux_thread_ops.to_terminal_info = child_terminal_info;
628
  hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
629
  hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
630
  hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
631
  hpux_thread_ops.to_can_run = hpux_thread_can_run;
632
  hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
633
  hpux_thread_ops.to_thread_alive = hpux_thread_alive;
634
  hpux_thread_ops.to_stop = hpux_thread_stop;
635
  hpux_thread_ops.to_stratum = process_stratum;
636
  hpux_thread_ops.to_has_all_memory = 1;
637
  hpux_thread_ops.to_has_memory = 1;
638
  hpux_thread_ops.to_has_stack = 1;
639
  hpux_thread_ops.to_has_registers = 1;
640
  hpux_thread_ops.to_has_execution = 1;
641
  hpux_thread_ops.to_magic = OPS_MAGIC;
642
}
643
 
644
void
645
_initialize_hpux_thread ()
646
{
647
  init_hpux_thread_ops ();
648
  add_target (&hpux_thread_ops);
649
 
650
  child_suppress_run = 1;
651
  /* Hook into new_objfile notification. */
652
  target_new_objfile_chain = target_new_objfile_hook;
653
  target_new_objfile_hook  = hpux_thread_new_objfile;
654
}

powered by: WebSVN 2.1.0

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