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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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