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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [bsd-uthread.c] - Blame information for rev 24

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

Line No. Rev Author Line
1 24 jeremybenn
/* BSD user-level threads support.
2
 
3
   Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
#include "defs.h"
21
#include "gdbcore.h"
22
#include "gdbthread.h"
23
#include "inferior.h"
24
#include "objfiles.h"
25
#include "observer.h"
26
#include "regcache.h"
27
#include "solib.h"
28
#include "solist.h"
29
#include "symfile.h"
30
#include "target.h"
31
 
32
#include "gdb_assert.h"
33
#include "gdb_obstack.h"
34
 
35
#include "bsd-uthread.h"
36
 
37
/* HACK: Save the bsd_uthreads ops returned by bsd_uthread_target.  */
38
static struct target_ops *bsd_uthread_ops_hack;
39
 
40
 
41
/* Architecture-specific operations.  */
42
 
43
/* Per-architecture data key.  */
44
static struct gdbarch_data *bsd_uthread_data;
45
 
46
struct bsd_uthread_ops
47
{
48
  /* Supply registers for an inactive thread to a register cache.  */
49
  void (*supply_uthread)(struct regcache *, int, CORE_ADDR);
50
 
51
  /* Collect registers for an inactive thread from a register cache.  */
52
  void (*collect_uthread)(const struct regcache *, int, CORE_ADDR);
53
};
54
 
55
static void *
56
bsd_uthread_init (struct obstack *obstack)
57
{
58
  struct bsd_uthread_ops *ops;
59
 
60
  ops = OBSTACK_ZALLOC (obstack, struct bsd_uthread_ops);
61
  return ops;
62
}
63
 
64
/* Set the function that supplies registers from an inactive thread
65
   for architecture GDBARCH to SUPPLY_UTHREAD.  */
66
 
67
void
68
bsd_uthread_set_supply_uthread (struct gdbarch *gdbarch,
69
                                void (*supply_uthread) (struct regcache *,
70
                                                        int, CORE_ADDR))
71
{
72
  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
73
  ops->supply_uthread = supply_uthread;
74
}
75
 
76
/* Set the function that collects registers for an inactive thread for
77
   architecture GDBARCH to SUPPLY_UTHREAD.  */
78
 
79
void
80
bsd_uthread_set_collect_uthread (struct gdbarch *gdbarch,
81
                         void (*collect_uthread) (const struct regcache *,
82
                                                  int, CORE_ADDR))
83
{
84
  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
85
  ops->collect_uthread = collect_uthread;
86
}
87
 
88
/* Magic number to help recognize a valid thread structure.  */
89
#define BSD_UTHREAD_PTHREAD_MAGIC       0xd09ba115
90
 
91
/* Check whether the thread structure at ADDR is valid.  */
92
 
93
static void
94
bsd_uthread_check_magic (CORE_ADDR addr)
95
{
96
  ULONGEST magic = read_memory_unsigned_integer (addr, 4);
97
 
98
  if (magic != BSD_UTHREAD_PTHREAD_MAGIC)
99
    error (_("Bad magic"));
100
}
101
 
102
/* Thread states.  */
103
#define BSD_UTHREAD_PS_RUNNING  0
104
#define BSD_UTHREAD_PS_DEAD     18
105
 
106
/* Address of the pointer to the the thread structure for the running
107
   thread.  */
108
static CORE_ADDR bsd_uthread_thread_run_addr;
109
 
110
/* Address of the list of all threads.  */
111
static CORE_ADDR bsd_uthread_thread_list_addr;
112
 
113
/* Offsets of various "interesting" bits in the thread structure.  */
114
static int bsd_uthread_thread_state_offset = -1;
115
static int bsd_uthread_thread_next_offset = -1;
116
static int bsd_uthread_thread_ctx_offset;
117
 
118
/* Name of shared threads library.  */
119
static const char *bsd_uthread_solib_name;
120
 
121
/* Non-zero if the thread startum implemented by this module is active.  */
122
static int bsd_uthread_active;
123
 
124
static CORE_ADDR
125
bsd_uthread_lookup_address (const char *name, struct objfile *objfile)
126
{
127
  struct minimal_symbol *sym;
128
 
129
  sym = lookup_minimal_symbol (name, NULL, objfile);
130
  if (sym)
131
    return SYMBOL_VALUE_ADDRESS (sym);
132
 
133
  return 0;
134
}
135
 
136
static int
137
bsd_uthread_lookup_offset (const char *name, struct objfile *objfile)
138
{
139
  CORE_ADDR addr;
140
 
141
  addr = bsd_uthread_lookup_address (name, objfile);
142
  if (addr == 0)
143
    return 0;
144
 
145
  return read_memory_unsigned_integer (addr, 4);
146
}
147
 
148
/* If OBJFILE contains the symbols corresponding to one of the
149
   supported user-level threads libraries, activate the thread stratum
150
   implemented by this module.  */
151
 
152
static int
153
bsd_uthread_activate (struct objfile *objfile)
154
{
155
  struct gdbarch *gdbarch = current_gdbarch;
156
  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
157
 
158
  /* Skip if the thread stratum has already been activated.  */
159
  if (bsd_uthread_active)
160
    return 0;
161
 
162
  /* There's no point in enabling this module if no
163
     architecture-specific operations are provided.  */
164
  if (!ops->supply_uthread)
165
    return 0;
166
 
167
  bsd_uthread_thread_run_addr =
168
    bsd_uthread_lookup_address ("_thread_run", objfile);
169
  if (bsd_uthread_thread_run_addr == 0)
170
    return 0;
171
 
172
  bsd_uthread_thread_list_addr =
173
    bsd_uthread_lookup_address ("_thread_list", objfile);
174
  if (bsd_uthread_thread_list_addr == 0)
175
    return 0;
176
 
177
  bsd_uthread_thread_state_offset =
178
    bsd_uthread_lookup_offset ("_thread_state_offset", objfile);
179
  if (bsd_uthread_thread_state_offset == 0)
180
    return 0;
181
 
182
  bsd_uthread_thread_next_offset =
183
    bsd_uthread_lookup_offset ("_thread_next_offset", objfile);
184
  if (bsd_uthread_thread_next_offset == 0)
185
    return 0;
186
 
187
  bsd_uthread_thread_ctx_offset =
188
    bsd_uthread_lookup_offset ("_thread_ctx_offset", objfile);
189
 
190
  push_target (bsd_uthread_ops_hack);
191
  bsd_uthread_active = 1;
192
  return 1;
193
}
194
 
195
/* Deactivate the thread stratum implemented by this module.  */
196
 
197
static void
198
bsd_uthread_deactivate (void)
199
{
200
  /* Skip if the thread stratum has already been deactivated.  */
201
  if (!bsd_uthread_active)
202
    return;
203
 
204
  bsd_uthread_active = 0;
205
  unpush_target (bsd_uthread_ops_hack);
206
 
207
  bsd_uthread_thread_run_addr = 0;
208
  bsd_uthread_thread_list_addr = 0;
209
  bsd_uthread_thread_state_offset = 0;
210
  bsd_uthread_thread_next_offset = 0;
211
  bsd_uthread_thread_ctx_offset = 0;
212
  bsd_uthread_solib_name = NULL;
213
}
214
 
215
void
216
bsd_uthread_inferior_created (struct target_ops *ops, int from_tty)
217
{
218
  bsd_uthread_activate (NULL);
219
}
220
 
221
/* Likely candidates for the threads library.  */
222
static const char *bsd_uthread_solib_names[] =
223
{
224
  "/usr/lib/libc_r.so",         /* FreeBSD */
225
  "/usr/lib/libpthread.so",     /* OpenBSD */
226
  NULL
227
};
228
 
229
void
230
bsd_uthread_solib_loaded (struct so_list *so)
231
{
232
  const char **names = bsd_uthread_solib_names;
233
 
234
  for (names = bsd_uthread_solib_names; *names; names++)
235
    {
236
      if (strncmp (so->so_original_name, *names, strlen (*names)) == 0)
237
        {
238
          solib_read_symbols (so, so->from_tty);
239
 
240
          if (bsd_uthread_activate (so->objfile))
241
            {
242
              bsd_uthread_solib_name == so->so_original_name;
243
              return;
244
            }
245
        }
246
    }
247
}
248
 
249
void
250
bsd_uthread_solib_unloaded (struct so_list *so)
251
{
252
  if (!bsd_uthread_solib_name)
253
    return;
254
 
255
  if (strcmp (so->so_original_name, bsd_uthread_solib_name) == 0)
256
    bsd_uthread_deactivate ();
257
}
258
 
259
static void
260
bsd_uthread_mourn_inferior (void)
261
{
262
  find_target_beneath (bsd_uthread_ops_hack)->to_mourn_inferior ();
263
  bsd_uthread_deactivate ();
264
}
265
 
266
static void
267
bsd_uthread_fetch_registers (struct regcache *regcache, int regnum)
268
{
269
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
270
  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
271
  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
272
  CORE_ADDR active_addr;
273
 
274
  /* Always fetch the appropriate registers from the layer beneath.  */
275
  find_target_beneath (bsd_uthread_ops_hack)->to_fetch_registers (regcache, regnum);
276
 
277
  /* FIXME: That might have gotten us more than we asked for.  Make
278
     sure we overwrite all relevant registers with values from the
279
     thread structure.  This can go once we fix the underlying target.  */
280
  regnum = -1;
281
 
282
  active_addr = read_memory_typed_address (bsd_uthread_thread_run_addr,
283
                                           builtin_type_void_data_ptr);
284
  if (addr != 0 && addr != active_addr)
285
    {
286
      bsd_uthread_check_magic (addr);
287
      ops->supply_uthread (regcache, regnum,
288
                           addr + bsd_uthread_thread_ctx_offset);
289
    }
290
}
291
 
292
static void
293
bsd_uthread_store_registers (struct regcache *regcache, int regnum)
294
{
295
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
296
  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
297
  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
298
  CORE_ADDR active_addr;
299
 
300
  active_addr = read_memory_typed_address (bsd_uthread_thread_run_addr,
301
                                           builtin_type_void_data_ptr);
302
  if (addr != 0 && addr != active_addr)
303
    {
304
      bsd_uthread_check_magic (addr);
305
      ops->collect_uthread (regcache, regnum,
306
                            addr + bsd_uthread_thread_ctx_offset);
307
    }
308
  else
309
    {
310
      /* Updating the thread that is currently running; pass the
311
         request to the layer beneath.  */
312
      find_target_beneath (bsd_uthread_ops_hack)->to_store_registers (regcache, regnum);
313
    }
314
}
315
 
316
/* FIXME: This function is only there because otherwise GDB tries to
317
   invoke deprecate_xfer_memory.  */
318
 
319
static LONGEST
320
bsd_uthread_xfer_partial (struct target_ops *ops, enum target_object object,
321
                          const char *annex, gdb_byte *readbuf,
322
                          const gdb_byte *writebuf,
323
                          ULONGEST offset, LONGEST len)
324
{
325
  gdb_assert (ops->beneath->to_xfer_partial);
326
  return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf,
327
                                        writebuf, offset, len);
328
}
329
 
330
static ptid_t
331
bsd_uthread_wait (ptid_t ptid, struct target_waitstatus *status)
332
{
333
  CORE_ADDR addr;
334
 
335
  /* Pass the request to the layer beneath.  */
336
  ptid = find_target_beneath (bsd_uthread_ops_hack)->to_wait (ptid, status);
337
 
338
  /* If the process is no longer alive, there's no point in figuring
339
     out the thread ID.  It will fail anyway.  */
340
  if (status->kind == TARGET_WAITKIND_SIGNALLED
341
      || status->kind == TARGET_WAITKIND_EXITED)
342
    return ptid;
343
 
344
  /* Fetch the corresponding thread ID, and augment the returned
345
     process ID with it.  */
346
  addr = read_memory_typed_address (bsd_uthread_thread_run_addr,
347
                                    builtin_type_void_data_ptr);
348
  if (addr != 0)
349
    {
350
      gdb_byte buf[4];
351
 
352
      /* FIXME: For executables linked statically with the threads
353
         library, we end up here before the program has actually been
354
         executed.  In that case ADDR will be garbage since it has
355
         been read from the wrong virtual memory image.  */
356
      if (target_read_memory (addr, buf, 4) == 0)
357
        {
358
          ULONGEST magic = extract_unsigned_integer (buf, 4);
359
          if (magic == BSD_UTHREAD_PTHREAD_MAGIC)
360
            ptid = ptid_build (ptid_get_pid (ptid), 0, addr);
361
        }
362
    }
363
 
364
  /* HACK: Twiddle INFERIOR_PTID such that the initial thread of a
365
     process isn't recognized as a new thread.  */
366
  if (ptid_get_tid (ptid) != 0 && !in_thread_list (ptid)
367
      && ptid_get_tid (inferior_ptid) == 0)
368
    {
369
      add_thread_silent (ptid);
370
      inferior_ptid = ptid;
371
    }
372
 
373
  return ptid;
374
}
375
 
376
static void
377
bsd_uthread_resume (ptid_t ptid, int step, enum target_signal sig)
378
{
379
  /* Pass the request to the layer beneath.  */
380
  find_target_beneath (bsd_uthread_ops_hack)->to_resume (ptid, step, sig);
381
}
382
 
383
static int
384
bsd_uthread_thread_alive (ptid_t ptid)
385
{
386
  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
387
 
388
  if (addr != 0)
389
    {
390
      int offset = bsd_uthread_thread_state_offset;
391
      ULONGEST state;
392
 
393
      bsd_uthread_check_magic (addr);
394
 
395
      state = read_memory_unsigned_integer (addr + offset, 4);
396
      if (state == BSD_UTHREAD_PS_DEAD)
397
        return 0;
398
    }
399
 
400
  return find_target_beneath (bsd_uthread_ops_hack)->to_thread_alive (ptid);
401
}
402
 
403
static void
404
bsd_uthread_find_new_threads (void)
405
{
406
  pid_t pid = ptid_get_pid (inferior_ptid);
407
  int offset = bsd_uthread_thread_next_offset;
408
  CORE_ADDR addr;
409
 
410
  addr = read_memory_typed_address (bsd_uthread_thread_list_addr,
411
                                    builtin_type_void_data_ptr);
412
  while (addr != 0)
413
    {
414
      ptid_t ptid = ptid_build (pid, 0, addr);
415
 
416
      if (!in_thread_list (ptid))
417
        add_thread (ptid);
418
 
419
      addr = read_memory_typed_address (addr + offset,
420
                                        builtin_type_void_data_ptr);
421
    }
422
}
423
 
424
/* Possible states a thread can be in.  */
425
static char *bsd_uthread_state[] =
426
{
427
  "RUNNING",
428
  "SIGTHREAD",
429
  "MUTEX_WAIT",
430
  "COND_WAIT",
431
  "FDLR_WAIT",
432
  "FDLW_WAIT",
433
  "FDR_WAIT",
434
  "FDW_WAIT",
435
  "FILE_WAIT",
436
  "POLL_WAIT",
437
  "SELECT_WAIT",
438
  "SLEEP_WAIT",
439
  "WAIT_WAIT",
440
  "SIGSUSPEND",
441
  "SIGWAIT",
442
  "SPINBLOCK",
443
  "JOIN",
444
  "SUSPENDED",
445
  "DEAD",
446
  "DEADLOCK"
447
};
448
 
449
/* Return a string describing th state of the thread specified by
450
   INFO.  */
451
 
452
static char *
453
bsd_uthread_extra_thread_info (struct thread_info *info)
454
{
455
  CORE_ADDR addr = ptid_get_tid (info->ptid);
456
 
457
  if (addr != 0)
458
    {
459
      int offset = bsd_uthread_thread_state_offset;
460
      ULONGEST state;
461
 
462
      state = read_memory_unsigned_integer (addr + offset, 4);
463
      if (state < ARRAY_SIZE (bsd_uthread_state))
464
        return bsd_uthread_state[state];
465
    }
466
 
467
  return NULL;
468
}
469
 
470
static char *
471
bsd_uthread_pid_to_str (ptid_t ptid)
472
{
473
  if (ptid_get_tid (ptid) != 0)
474
    {
475
      static char buf[64];
476
 
477
      xsnprintf (buf, sizeof buf, "process %d, thread 0x%lx",
478
                 ptid_get_pid (ptid), ptid_get_tid (ptid));
479
      return buf;
480
    }
481
 
482
  return normal_pid_to_str (ptid);
483
}
484
 
485
struct target_ops *
486
bsd_uthread_target (void)
487
{
488
  struct target_ops *t = XZALLOC (struct target_ops);
489
 
490
  t->to_shortname = "bsd-uthreads";
491
  t->to_longname = "BSD user-level threads";
492
  t->to_doc = "BSD user-level threads";
493
  t->to_mourn_inferior = bsd_uthread_mourn_inferior;
494
  t->to_fetch_registers = bsd_uthread_fetch_registers;
495
  t->to_store_registers = bsd_uthread_store_registers;
496
  t->to_xfer_partial = bsd_uthread_xfer_partial;
497
  t->to_wait = bsd_uthread_wait;
498
  t->to_resume = bsd_uthread_resume;
499
  t->to_thread_alive = bsd_uthread_thread_alive;
500
  t->to_find_new_threads = bsd_uthread_find_new_threads;
501
  t->to_extra_thread_info = bsd_uthread_extra_thread_info;
502
  t->to_pid_to_str = bsd_uthread_pid_to_str;
503
  t->to_stratum = thread_stratum;
504
  t->to_magic = OPS_MAGIC;
505
  bsd_uthread_ops_hack = t;
506
 
507
  return t;
508
}
509
 
510
void
511
_initialize_bsd_uthread (void)
512
{
513
  add_target (bsd_uthread_target ());
514
 
515
  bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init);
516
 
517
  observer_attach_inferior_created (bsd_uthread_inferior_created);
518
  observer_attach_solib_loaded (bsd_uthread_solib_loaded);
519
  observer_attach_solib_unloaded (bsd_uthread_solib_unloaded);
520
}

powered by: WebSVN 2.1.0

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