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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [hpux-thread.c] - Blame information for rev 294

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

Line No. Rev Author Line
1 24 jeremybenn
/* Low level interface for debugging HPUX/DCE threads for GDB, the GNU
2
   debugger.
3
 
4
   Copyright (C) 1996, 1998, 1999, 2000, 2001, 2004, 2007, 2008
5
   Free Software Foundation, Inc.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
 
22
/* This module implements a sort of half target that sits between the
23
   machine-independent parts of GDB and the ptrace interface (infptrace.c) to
24
   provide access to the HPUX user-mode thread implementation.
25
 
26
   HPUX threads are true user-mode threads, which are invoked via the cma_*
27
   and pthread_* (DCE and Posix respectivly) interfaces.  These are mostly
28
   implemented in user-space, with all thread context kept in various
29
   structures that live in the user's heap.  For the most part, the kernel has
30
   no knowlege of these threads.
31
 
32
 */
33
 
34
#include "defs.h"
35
 
36
#define _CMA_NOWRAPPERS_
37
 
38
#include <cma_tcb_defs.h>
39
#include <cma_deb_core.h>
40
#include "gdbthread.h"
41
#include "target.h"
42
#include "inferior.h"
43
#include "regcache.h"
44
#include <fcntl.h>
45
#include <string.h>
46
#include "gdb_stat.h"
47
#include "gdbcore.h"
48
#include "hppa-tdep.h"
49
#include "observer.h"
50
 
51
extern int child_suppress_run;
52
 
53
extern void _initialize_hpux_thread (void);
54
 
55
struct string_map
56
  {
57
    int num;
58
    char *str;
59
  };
60
 
61
static int hpux_thread_active = 0;
62
 
63
static ptid_t main_ptid;                /* Real process ID */
64
 
65
static CORE_ADDR P_cma__g_known_threads;
66
static CORE_ADDR P_cma__g_current_thread;
67
 
68
static void hpux_thread_resume (ptid_t ptid, int step,
69
                                enum target_signal signo);
70
 
71
static void init_hpux_thread_ops (void);
72
 
73
static struct target_ops hpux_thread_ops;
74
 
75
static ptid_t find_active_thread (void);
76
 
77
static int cached_thread;
78
static cma__t_int_tcb cached_tcb;
79
 
80
static ptid_t
81
find_active_thread (void)
82
{
83
  static cma__t_int_tcb tcb;
84
  CORE_ADDR tcb_ptr;
85
 
86
  read_memory ((CORE_ADDR) P_cma__g_current_thread,
87
               (char *) &tcb_ptr,
88
               sizeof tcb_ptr);
89
 
90
  read_memory (tcb_ptr, (char *) &tcb, sizeof tcb);
91
 
92
  return (ptid_build (PIDGET (main_ptid), 0,
93
                      cma_thread_get_unique (&tcb.prolog.client_thread)));
94
}
95
 
96
static cma__t_int_tcb *find_tcb (ptid_t ptid);
97
 
98
static cma__t_int_tcb *
99
find_tcb (ptid_t ptid)
100
{
101
  cma__t_known_object queue_header;
102
  cma__t_queue *queue_ptr;
103
  int thread = ptid_get_tid (ptid);
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)
124
          {
125
            cached_thread = thread;
126
            return &cached_tcb;
127
          }
128
    }
129
 
130
  error (_("Can't find TCB %d"), thread);
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
static void
138
hpux_thread_open (char *arg, int from_tty)
139
{
140
  deprecated_child_ops.to_open (arg, from_tty);
141
}
142
 
143
/* Attach to process PID, then initialize for debugging it
144
   and wait for the trace-trap that results from attaching.  */
145
 
146
static void
147
hpux_thread_attach (char *args, int from_tty)
148
{
149
  deprecated_child_ops.to_attach (args, from_tty);
150
 
151
  /* XXX - might want to iterate over all the threads and register them. */
152
}
153
 
154
/* Take a program previously attached to and detaches it.
155
   The program resumes execution and will no longer stop
156
   on signals, etc.  We'd better not have left any breakpoints
157
   in the program or it'll die when it hits one.  For this
158
   to work, it may be necessary for the process to have been
159
   previously attached.  It *might* work if the program was
160
   started via the normal ptrace (PTRACE_TRACEME).  */
161
 
162
static void
163
hpux_thread_detach (char *args, int from_tty)
164
{
165
  deprecated_child_ops.to_detach (args, from_tty);
166
}
167
 
168
/* Resume execution of process PID.  If STEP is nozero, then
169
   just single step it.  If SIGNAL is nonzero, restart it with that
170
   signal activated.  We may have to convert pid from a thread-id to an LWP id
171
   for procfs.  */
172
 
173
static void
174
hpux_thread_resume (ptid_t ptid, int step, enum target_signal signo)
175
{
176
  struct cleanup *old_chain;
177
 
178
  old_chain = save_inferior_ptid ();
179
 
180
  ptid = main_ptid;
181
  inferior_ptid = main_ptid;
182
 
183
  deprecated_child_ops.to_resume (ptid, step, signo);
184
 
185
  cached_thread = 0;
186
 
187
  do_cleanups (old_chain);
188
}
189
 
190
/* Wait for any threads to stop.  We may have to convert PID from a thread id
191
   to a LWP id, and vice versa on the way out.  */
192
 
193
static ptid_t
194
hpux_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
195
{
196
  ptid_t rtnval;
197
  struct cleanup *old_chain;
198
 
199
  old_chain = save_inferior_ptid ();
200
 
201
  inferior_ptid = main_ptid;
202
 
203
  if (!ptid_equal (ptid, minus_one_ptid))
204
    ptid = main_ptid;
205
 
206
  rtnval = deprecated_child_ops.to_wait (ptid, ourstatus);
207
 
208
  rtnval = find_active_thread ();
209
 
210
  do_cleanups (old_chain);
211
 
212
  return rtnval;
213
}
214
 
215
static char regmap[] =
216
{
217
  -2, -1, -1, 0, 4, 8, 12, 16, 20, 24,   /* flags, r1 -> r9 */
218
  28, 32, 36, 40, 44, 48, 52, 56, 60, -1,       /* r10 -> r19 */
219
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,       /* r20 -> r29 */
220
 
221
  /* r30, r31, sar, pcoqh, pcsqh, pcoqt, pcsqt, eiem, iir, isr */
222
  -2, -1, -1, -2, -1, -1, -1, -1, -1, -1,
223
 
224
  /* ior, ipsw, goto, sr4, sr0, sr1, sr2, sr3, sr5, sr6 */
225
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226
 
227
  /* sr7, cr0, cr8, cr9, ccr, cr12, cr13, cr24, cr25, cr26 */
228
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
229
 
230
  -1, -1, -1, -1,               /* mpsfu_high, mpsfu_low, mpsfu_ovflo, pad */
231
  144, -1, -1, -1, -1, -1, -1, -1,      /* fpsr, fpe1 -> fpe7 */
232
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr4 -> fr7 */
233
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr8 -> fr11 */
234
  136, -1, 128, -1, 120, -1, 112, -1,   /* fr12 -> fr15 */
235
  104, -1, 96, -1, 88, -1, 80, -1,      /* fr16 -> fr19 */
236
  72, -1, 64, -1, -1, -1, -1, -1,       /* fr20 -> fr23 */
237
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr24 -> fr27 */
238
  -1, -1, -1, -1, -1, -1, -1, -1,       /* fr28 -> fr31 */
239
};
240
 
241
static void
242
hpux_thread_fetch_registers (struct regcache *regcache, int regno)
243
{
244
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
245
  cma__t_int_tcb tcb, *tcb_ptr;
246
  struct cleanup *old_chain;
247
  int i;
248
  int first_regno, last_regno;
249
 
250
  tcb_ptr = find_tcb (inferior_ptid);
251
 
252
  old_chain = save_inferior_ptid ();
253
 
254
  inferior_ptid = main_ptid;
255
 
256
  if (tcb_ptr->state == cma__c_state_running)
257
    {
258
      deprecated_child_ops.to_fetch_registers (regcache, regno);
259
 
260
      do_cleanups (old_chain);
261
 
262
      return;
263
    }
264
 
265
  if (regno == -1)
266
    {
267
      first_regno = 0;
268
      last_regno = gdbarch_num_regs (gdbarch) - 1;
269
    }
270
  else
271
    {
272
      first_regno = regno;
273
      last_regno = regno;
274
    }
275
 
276
  for (regno = first_regno; regno <= last_regno; regno++)
277
    {
278
      if (regmap[regno] == -1)
279
        deprecated_child_ops.to_fetch_registers (regcache, regno);
280
      else
281
        {
282
          unsigned char buf[MAX_REGISTER_SIZE];
283
          CORE_ADDR sp;
284
 
285
          sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
286
 
287
          if (regno == HPPA_FLAGS_REGNUM)
288
            /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
289
            memset (buf, '\000', register_size (gdbarch, regno));
290
          else if (regno == HPPA_SP_REGNUM)
291
            store_unsigned_integer (buf, sizeof sp, sp);
292
          else if (regno == HPPA_PCOQ_HEAD_REGNUM)
293
            read_memory (sp - 20, buf, register_size (gdbarch, regno));
294
          else
295
            read_memory (sp + regmap[regno], buf,
296
                         register_size (gdbarch, regno));
297
 
298
          regcache_raw_supply (regcache, regno, buf);
299
        }
300
    }
301
 
302
  do_cleanups (old_chain);
303
}
304
 
305
static void
306
hpux_thread_store_registers (struct regcache *regcache, int regno)
307
{
308
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
309
  cma__t_int_tcb tcb, *tcb_ptr;
310
  struct cleanup *old_chain;
311
  int i;
312
  int first_regno, last_regno;
313
 
314
  tcb_ptr = find_tcb (inferior_ptid);
315
 
316
  old_chain = save_inferior_ptid ();
317
 
318
  inferior_ptid = main_ptid;
319
 
320
  if (tcb_ptr->state == cma__c_state_running)
321
    {
322
      deprecated_child_ops.to_store_registers (regcache, regno);
323
 
324
      do_cleanups (old_chain);
325
 
326
      return;
327
    }
328
 
329
  if (regno == -1)
330
    {
331
      first_regno = 0;
332
      last_regno = gdbarch_num_regs (gdbarch) - 1;
333
    }
334
  else
335
    {
336
      first_regno = regno;
337
      last_regno = regno;
338
    }
339
 
340
  for (regno = first_regno; regno <= last_regno; regno++)
341
    {
342
      if (regmap[regno] == -1)
343
        deprecated_child_ops.to_store_registers (regcache, regno);
344
      else
345
        {
346
          unsigned char buf[MAX_REGISTER_SIZE];
347
          CORE_ADDR sp;
348
 
349
          sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
350
 
351
          if (regno == HPPA_FLAGS_REGNUM)
352
            deprecated_child_ops.to_store_registers (regcache, regno);  /* Let lower layer handle this... */
353
          else if (regno == HPPA_SP_REGNUM)
354
            {
355
              regcache_raw_collect (regcache, regno, buf);
356
              write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
357
                            register_size (gdbarch, regno));
358
              tcb_ptr->static_ctx.sp
359
                = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
360
            }
361
          else if (regno == HPPA_PCOQ_HEAD_REGNUM)
362
            {
363
              regcache_raw_collect (regcache, regno, buf);
364
              write_memory (sp - 20, buf,
365
                            register_size (gdbarch, regno));
366
            }
367
          else
368
            {
369
              regcache_raw_collect (regcache, regno, buf);
370
              write_memory (sp + regmap[regno], buf,
371
                            register_size (gdbarch, regno));
372
            }
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 (struct regcache *regcache)
387
{
388
  deprecated_child_ops.to_prepare_to_store (regcache);
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
    deprecated_child_ops.deprecated_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
  deprecated_child_ops.to_files_info (ignore);
417
}
418
 
419
static void
420
hpux_thread_kill_inferior (void)
421
{
422
  deprecated_child_ops.to_kill ();
423
}
424
 
425
static void
426
hpux_thread_notice_signals (ptid_t ptid)
427
{
428
  deprecated_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
                             int from_tty)
436
{
437
  deprecated_child_ops.to_create_inferior (exec_file, allargs, env, from_tty);
438
 
439
  if (hpux_thread_active)
440
    {
441
      main_ptid = inferior_ptid;
442
 
443
      push_target (&hpux_thread_ops);
444
 
445
      inferior_ptid = find_active_thread ();
446
 
447
      add_thread (inferior_ptid);
448
    }
449
}
450
 
451
/* This routine is called whenever a new symbol table is read in, or when all
452
   symbol tables are removed.  libthread_db can only be initialized when it
453
   finds the right variables in libthread.so.  Since it's a shared library,
454
   those variables don't show up until the library gets mapped and the symbol
455
   table is read in.  */
456
 
457
static void
458
hpux_thread_new_objfile (struct objfile *objfile)
459
{
460
  struct minimal_symbol *ms;
461
 
462
  if (!objfile)
463
    {
464
      hpux_thread_active = 0;
465
      return;
466
    }
467
 
468
  ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
469
 
470
  if (!ms)
471
    return;
472
 
473
  P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
474
 
475
  ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
476
 
477
  if (!ms)
478
    return;
479
 
480
  P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
481
 
482
  hpux_thread_active = 1;
483
}
484
 
485
/* Clean up after the inferior dies.  */
486
 
487
static void
488
hpux_thread_mourn_inferior (void)
489
{
490
  deprecated_child_ops.to_mourn_inferior ();
491
}
492
 
493
/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
494
 
495
static int
496
hpux_thread_can_run (void)
497
{
498
  return child_suppress_run;
499
}
500
 
501
static int
502
hpux_thread_alive (ptid_t ptid)
503
{
504
  return 1;
505
}
506
 
507
static void
508
hpux_thread_stop (void)
509
{
510
  deprecated_child_ops.to_stop ();
511
}
512
 
513
/* Convert a pid to printable form. */
514
 
515
char *
516
hpux_pid_to_str (ptid_t ptid)
517
{
518
  static char buf[100];
519
  int pid = PIDGET (ptid);
520
 
521
  sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
522
 
523
  return buf;
524
}
525
 
526
static void
527
init_hpux_thread_ops (void)
528
{
529
  hpux_thread_ops.to_shortname = "hpux-threads";
530
  hpux_thread_ops.to_longname = "HPUX threads and pthread.";
531
  hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
532
  hpux_thread_ops.to_open = hpux_thread_open;
533
  hpux_thread_ops.to_attach = hpux_thread_attach;
534
  hpux_thread_ops.to_detach = hpux_thread_detach;
535
  hpux_thread_ops.to_resume = hpux_thread_resume;
536
  hpux_thread_ops.to_wait = hpux_thread_wait;
537
  hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
538
  hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
539
  hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
540
  hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
541
  hpux_thread_ops.to_files_info = hpux_thread_files_info;
542
  hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
543
  hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
544
  hpux_thread_ops.to_terminal_init = terminal_init_inferior;
545
  hpux_thread_ops.to_terminal_inferior = terminal_inferior;
546
  hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
547
  hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
548
  hpux_thread_ops.to_terminal_ours = terminal_ours;
549
  hpux_thread_ops.to_terminal_info = child_terminal_info;
550
  hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
551
  hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
552
  hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
553
  hpux_thread_ops.to_can_run = hpux_thread_can_run;
554
  hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
555
  hpux_thread_ops.to_thread_alive = hpux_thread_alive;
556
  hpux_thread_ops.to_stop = hpux_thread_stop;
557
  hpux_thread_ops.to_stratum = process_stratum;
558
  hpux_thread_ops.to_has_all_memory = 1;
559
  hpux_thread_ops.to_has_memory = 1;
560
  hpux_thread_ops.to_has_stack = 1;
561
  hpux_thread_ops.to_has_registers = 1;
562
  hpux_thread_ops.to_has_execution = 1;
563
  hpux_thread_ops.to_magic = OPS_MAGIC;
564
}
565
 
566
void
567
_initialize_hpux_thread (void)
568
{
569
  init_hpux_thread_ops ();
570
  add_target (&hpux_thread_ops);
571
 
572
  child_suppress_run = 1;
573
  /* Hook into new_objfile notification.  */
574
  observer_attach_new_objfile (hpux_thread_new_objfile);
575
}

powered by: WebSVN 2.1.0

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