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

Subversion Repositories openrisc_me

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 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, 2009, 2010
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 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
static void
135
hpux_thread_open (char *arg, int from_tty)
136
{
137
  deprecated_child_ops.to_open (arg, from_tty);
138
}
139
 
140
/* Attach to process PID, then initialize for debugging it
141
   and wait for the trace-trap that results from attaching.  */
142
 
143
static void
144
hpux_thread_attach (struct target_ops *ops, char *args, int from_tty)
145
{
146
  deprecated_child_ops.to_attach (&deprecated_child_ops, args, from_tty);
147
 
148
  /* XXX - might want to iterate over all the threads and register them. */
149
}
150
 
151
/* Take a program previously attached to and detaches it.
152
   The program resumes execution and will no longer stop
153
   on signals, etc.  We'd better not have left any breakpoints
154
   in the program or it'll die when it hits one.  For this
155
   to work, it may be necessary for the process to have been
156
   previously attached.  It *might* work if the program was
157
   started via the normal ptrace (PTRACE_TRACEME).  */
158
 
159
static void
160
hpux_thread_detach (struct target_ops *ops, char *args, int from_tty)
161
{
162
  deprecated_child_ops.to_detach (&deprecated_child_ops, args, from_tty);
163
}
164
 
165
/* Resume execution of process PID.  If STEP is nozero, then
166
   just single step it.  If SIGNAL is nonzero, restart it with that
167
   signal activated.  We may have to convert pid from a thread-id to an LWP id
168
   for procfs.  */
169
 
170
static void
171
hpux_thread_resume (struct target_ops *ops,
172
                    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
  deprecated_child_ops.to_resume (&deprecated_child_ops, ptid, step, signo);
182
 
183
  cached_thread = 0;
184
 
185
  do_cleanups (old_chain);
186
}
187
 
188
/* Wait for any threads to stop.  We may have to convert PID from a thread id
189
   to a LWP id, and vice versa on the way out.  */
190
 
191
static ptid_t
192
hpux_thread_wait (struct target_ops *ops,
193
                  ptid_t ptid, struct target_waitstatus *ourstatus, int options)
194
{
195
  ptid_t rtnval;
196
  struct cleanup *old_chain;
197
 
198
  old_chain = save_inferior_ptid ();
199
 
200
  inferior_ptid = main_ptid;
201
 
202
  if (!ptid_equal (ptid, minus_one_ptid))
203
    ptid = main_ptid;
204
 
205
  rtnval = deprecated_child_ops.to_wait (&deprecated_child_ops,
206
                                         ptid, ourstatus, options);
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 target_ops *ops,
243
                             struct regcache *regcache, int regno)
244
{
245
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
246
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
247
  cma__t_int_tcb tcb, *tcb_ptr;
248
  struct cleanup *old_chain;
249
  int i;
250
  int first_regno, last_regno;
251
 
252
  tcb_ptr = find_tcb (inferior_ptid);
253
 
254
  old_chain = save_inferior_ptid ();
255
 
256
  inferior_ptid = main_ptid;
257
 
258
  if (tcb_ptr->state == cma__c_state_running)
259
    {
260
      deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
261
                                               regcache, regno);
262
 
263
      do_cleanups (old_chain);
264
 
265
      return;
266
    }
267
 
268
  if (regno == -1)
269
    {
270
      first_regno = 0;
271
      last_regno = gdbarch_num_regs (gdbarch) - 1;
272
    }
273
  else
274
    {
275
      first_regno = regno;
276
      last_regno = regno;
277
    }
278
 
279
  for (regno = first_regno; regno <= last_regno; regno++)
280
    {
281
      if (regmap[regno] == -1)
282
        deprecated_child_ops.to_fetch_registers (&deprecated_child_ops,
283
                                                 regcache, regno);
284
      else
285
        {
286
          unsigned char buf[MAX_REGISTER_SIZE];
287
          CORE_ADDR sp;
288
 
289
          sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
290
 
291
          if (regno == HPPA_FLAGS_REGNUM)
292
            /* Flags must be 0 to avoid bogus value for SS_INSYSCALL */
293
            memset (buf, '\000', register_size (gdbarch, regno));
294
          else if (regno == HPPA_SP_REGNUM)
295
            store_unsigned_integer (buf, sizeof sp, byte_order, sp);
296
          else if (regno == HPPA_PCOQ_HEAD_REGNUM)
297
            read_memory (sp - 20, buf, register_size (gdbarch, regno));
298
          else
299
            read_memory (sp + regmap[regno], buf,
300
                         register_size (gdbarch, regno));
301
 
302
          regcache_raw_supply (regcache, regno, buf);
303
        }
304
    }
305
 
306
  do_cleanups (old_chain);
307
}
308
 
309
static void
310
hpux_thread_store_registers (struct target_ops *ops,
311
                             struct regcache *regcache, int regno)
312
{
313
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
314
  cma__t_int_tcb tcb, *tcb_ptr;
315
  struct cleanup *old_chain;
316
  int i;
317
  int first_regno, last_regno;
318
 
319
  tcb_ptr = find_tcb (inferior_ptid);
320
 
321
  old_chain = save_inferior_ptid ();
322
 
323
  inferior_ptid = main_ptid;
324
 
325
  if (tcb_ptr->state == cma__c_state_running)
326
    {
327
      deprecated_child_ops.to_store_registers (&deprecated_child_ops,
328
                                               regcache, regno);
329
 
330
      do_cleanups (old_chain);
331
 
332
      return;
333
    }
334
 
335
  if (regno == -1)
336
    {
337
      first_regno = 0;
338
      last_regno = gdbarch_num_regs (gdbarch) - 1;
339
    }
340
  else
341
    {
342
      first_regno = regno;
343
      last_regno = regno;
344
    }
345
 
346
  for (regno = first_regno; regno <= last_regno; regno++)
347
    {
348
      if (regmap[regno] == -1)
349
        deprecated_child_ops.to_store_registers (regcache, regno);
350
      else
351
        {
352
          unsigned char buf[MAX_REGISTER_SIZE];
353
          CORE_ADDR sp;
354
 
355
          sp = (CORE_ADDR) tcb_ptr->static_ctx.sp - 160;
356
 
357
          if (regno == HPPA_FLAGS_REGNUM)
358
            {
359
              /* Let lower layer handle this... */
360
              deprecated_child_ops.to_store_registers
361
                (&deprecated_child_ops, regcache, regno);
362
            }
363
          else if (regno == HPPA_SP_REGNUM)
364
            {
365
              regcache_raw_collect (regcache, regno, buf);
366
              write_memory ((CORE_ADDR) &tcb_ptr->static_ctx.sp, buf,
367
                            register_size (gdbarch, regno));
368
              tcb_ptr->static_ctx.sp
369
                = (cma__t_hppa_regs *) ((CORE_ADDR) buf + 160);
370
            }
371
          else if (regno == HPPA_PCOQ_HEAD_REGNUM)
372
            {
373
              regcache_raw_collect (regcache, regno, buf);
374
              write_memory (sp - 20, buf,
375
                            register_size (gdbarch, regno));
376
            }
377
          else
378
            {
379
              regcache_raw_collect (regcache, regno, buf);
380
              write_memory (sp + regmap[regno], buf,
381
                            register_size (gdbarch, regno));
382
            }
383
        }
384
    }
385
 
386
  do_cleanups (old_chain);
387
}
388
 
389
/* Get ready to modify the registers array.  On machines which store
390
   individual registers, this doesn't need to do anything.  On machines
391
   which store all the registers in one fell swoop, this makes sure
392
   that registers contains all the registers from the program being
393
   debugged.  */
394
 
395
static void
396
hpux_thread_prepare_to_store (struct regcache *regcache)
397
{
398
  deprecated_child_ops.to_prepare_to_store (regcache);
399
}
400
 
401
static int
402
hpux_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
403
                         int dowrite, struct mem_attrib *attribs,
404
                         struct target_ops *target)
405
{
406
  int retval;
407
  struct cleanup *old_chain;
408
 
409
  old_chain = save_inferior_ptid ();
410
 
411
  inferior_ptid = main_ptid;
412
 
413
  retval =
414
    deprecated_child_ops.deprecated_xfer_memory (memaddr, myaddr, len, dowrite, attribs, target);
415
 
416
  do_cleanups (old_chain);
417
 
418
  return retval;
419
}
420
 
421
/* Print status information about what we're accessing.  */
422
 
423
static void
424
hpux_thread_files_info (struct target_ops *ignore)
425
{
426
  deprecated_child_ops.to_files_info (ignore);
427
}
428
 
429
static void
430
hpux_thread_kill_inferior (struct target_ops *ops)
431
{
432
  deprecated_child_ops.to_kill (&deprecated_child_ops);
433
}
434
 
435
static void
436
hpux_thread_notice_signals (ptid_t ptid)
437
{
438
  deprecated_child_ops.to_notice_signals (ptid);
439
}
440
 
441
/* Fork an inferior process, and start debugging it with /proc.  */
442
 
443
static void
444
hpux_thread_create_inferior (struct target_ops *ops, char *exec_file,
445
                             char *allargs, char **env, int from_tty)
446
{
447
  deprecated_child_ops.to_create_inferior (&deprecated_child_ops,
448
                                           exec_file, allargs, env, from_tty);
449
 
450
  if (hpux_thread_active)
451
    {
452
      main_ptid = inferior_ptid;
453
 
454
      push_target (&hpux_thread_ops);
455
 
456
      inferior_ptid = find_active_thread ();
457
 
458
      add_thread (inferior_ptid);
459
    }
460
}
461
 
462
/* This routine is called whenever a new symbol table is read in, or when all
463
   symbol tables are removed.  libthread_db can only be initialized when it
464
   finds the right variables in libthread.so.  Since it's a shared library,
465
   those variables don't show up until the library gets mapped and the symbol
466
   table is read in.  */
467
 
468
static void
469
hpux_thread_new_objfile (struct objfile *objfile)
470
{
471
  struct minimal_symbol *ms;
472
 
473
  if (!objfile)
474
    {
475
      hpux_thread_active = 0;
476
      return;
477
    }
478
 
479
  ms = lookup_minimal_symbol ("cma__g_known_threads", NULL, objfile);
480
 
481
  if (!ms)
482
    return;
483
 
484
  P_cma__g_known_threads = SYMBOL_VALUE_ADDRESS (ms);
485
 
486
  ms = lookup_minimal_symbol ("cma__g_current_thread", NULL, objfile);
487
 
488
  if (!ms)
489
    return;
490
 
491
  P_cma__g_current_thread = SYMBOL_VALUE_ADDRESS (ms);
492
 
493
  hpux_thread_active = 1;
494
}
495
 
496
/* Clean up after the inferior dies.  */
497
 
498
static void
499
hpux_thread_mourn_inferior (void)
500
{
501
  deprecated_child_ops.to_mourn_inferior (&deprecated_child_ops);
502
}
503
 
504
/* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
505
 
506
static int
507
hpux_thread_can_run (void)
508
{
509
  return child_suppress_run;
510
}
511
 
512
static int
513
hpux_thread_alive (struct target_ops *ops, ptid_t ptid)
514
{
515
  return 1;
516
}
517
 
518
static void
519
hpux_thread_stop (ptid_t ptid)
520
{
521
  deprecated_child_ops.to_stop (ptid);
522
}
523
 
524
/* Convert a pid to printable form. */
525
 
526
char *
527
hpux_pid_to_str (ptid_t ptid)
528
{
529
  static char buf[100];
530
  int pid = PIDGET (ptid);
531
 
532
  sprintf (buf, "Thread %ld", ptid_get_tid (ptid));
533
 
534
  return buf;
535
}
536
 
537
static void
538
init_hpux_thread_ops (void)
539
{
540
  hpux_thread_ops.to_shortname = "hpux-threads";
541
  hpux_thread_ops.to_longname = "HPUX threads and pthread.";
542
  hpux_thread_ops.to_doc = "HPUX threads and pthread support.";
543
  hpux_thread_ops.to_open = hpux_thread_open;
544
  hpux_thread_ops.to_attach = hpux_thread_attach;
545
  hpux_thread_ops.to_detach = hpux_thread_detach;
546
  hpux_thread_ops.to_resume = hpux_thread_resume;
547
  hpux_thread_ops.to_wait = hpux_thread_wait;
548
  hpux_thread_ops.to_fetch_registers = hpux_thread_fetch_registers;
549
  hpux_thread_ops.to_store_registers = hpux_thread_store_registers;
550
  hpux_thread_ops.to_prepare_to_store = hpux_thread_prepare_to_store;
551
  hpux_thread_ops.deprecated_xfer_memory = hpux_thread_xfer_memory;
552
  hpux_thread_ops.to_files_info = hpux_thread_files_info;
553
  hpux_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
554
  hpux_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
555
  hpux_thread_ops.to_terminal_init = terminal_init_inferior;
556
  hpux_thread_ops.to_terminal_inferior = terminal_inferior;
557
  hpux_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
558
  hpux_thread_ops.to_terminal_save_ours = terminal_save_ours;
559
  hpux_thread_ops.to_terminal_ours = terminal_ours;
560
  hpux_thread_ops.to_terminal_info = child_terminal_info;
561
  hpux_thread_ops.to_kill = hpux_thread_kill_inferior;
562
  hpux_thread_ops.to_create_inferior = hpux_thread_create_inferior;
563
  hpux_thread_ops.to_mourn_inferior = hpux_thread_mourn_inferior;
564
  hpux_thread_ops.to_can_run = hpux_thread_can_run;
565
  hpux_thread_ops.to_notice_signals = hpux_thread_notice_signals;
566
  hpux_thread_ops.to_thread_alive = hpux_thread_alive;
567
  hpux_thread_ops.to_stop = hpux_thread_stop;
568
  hpux_thread_ops.to_stratum = process_stratum;
569
  hpux_thread_ops.to_has_all_memory = default_child_has_all_memory;
570
  hpux_thread_ops.to_has_memory = default_child_has_memory;
571
  hpux_thread_ops.to_has_stack = default_child_has_stack;
572
  hpux_thread_ops.to_has_registers = default_child_has_registers;
573
  hpux_thread_ops.to_has_execution = default_child_has_execution;
574
  hpux_thread_ops.to_magic = OPS_MAGIC;
575
}
576
 
577
void
578
_initialize_hpux_thread (void)
579
{
580
  init_hpux_thread_ops ();
581
  add_target (&hpux_thread_ops);
582
 
583
  child_suppress_run = 1;
584
  /* Hook into new_objfile notification.  */
585
  observer_attach_new_objfile (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.