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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [gdb/] [hpux-thread.c] - Blame information for rev 578

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

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

powered by: WebSVN 2.1.0

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