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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-7.1/] [gdb/] [bsd-uthread.c] - Blame information for rev 231

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

Line No. Rev Author Line
1 227 jeremybenn
/* BSD user-level threads support.
2
 
3
   Copyright (C) 2005, 2007, 2008, 2009, 2010 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
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
97
  ULONGEST magic = read_memory_unsigned_integer (addr, 4, byte_order);
98
 
99
  if (magic != BSD_UTHREAD_PTHREAD_MAGIC)
100
    error (_("Bad magic"));
101
}
102
 
103
/* Thread states.  */
104
#define BSD_UTHREAD_PS_RUNNING  0
105
#define BSD_UTHREAD_PS_DEAD     18
106
 
107
/* Address of the pointer to the the thread structure for the running
108
   thread.  */
109
static CORE_ADDR bsd_uthread_thread_run_addr;
110
 
111
/* Address of the list of all threads.  */
112
static CORE_ADDR bsd_uthread_thread_list_addr;
113
 
114
/* Offsets of various "interesting" bits in the thread structure.  */
115
static int bsd_uthread_thread_state_offset = -1;
116
static int bsd_uthread_thread_next_offset = -1;
117
static int bsd_uthread_thread_ctx_offset;
118
 
119
/* Name of shared threads library.  */
120
static const char *bsd_uthread_solib_name;
121
 
122
/* Non-zero if the thread startum implemented by this module is active.  */
123
static int bsd_uthread_active;
124
 
125
static CORE_ADDR
126
bsd_uthread_lookup_address (const char *name, struct objfile *objfile)
127
{
128
  struct minimal_symbol *sym;
129
 
130
  sym = lookup_minimal_symbol (name, NULL, objfile);
131
  if (sym)
132
    return SYMBOL_VALUE_ADDRESS (sym);
133
 
134
  return 0;
135
}
136
 
137
static int
138
bsd_uthread_lookup_offset (const char *name, struct objfile *objfile)
139
{
140
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
141
  CORE_ADDR addr;
142
 
143
  addr = bsd_uthread_lookup_address (name, objfile);
144
  if (addr == 0)
145
    return 0;
146
 
147
  return read_memory_unsigned_integer (addr, 4, byte_order);
148
}
149
 
150
static CORE_ADDR
151
bsd_uthread_read_memory_address (CORE_ADDR addr)
152
{
153
  struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr;
154
  return read_memory_typed_address (addr, ptr_type);
155
}
156
 
157
/* If OBJFILE contains the symbols corresponding to one of the
158
   supported user-level threads libraries, activate the thread stratum
159
   implemented by this module.  */
160
 
161
static int
162
bsd_uthread_activate (struct objfile *objfile)
163
{
164
  struct gdbarch *gdbarch = target_gdbarch;
165
  struct bsd_uthread_ops *ops = gdbarch_data (gdbarch, bsd_uthread_data);
166
 
167
  /* Skip if the thread stratum has already been activated.  */
168
  if (bsd_uthread_active)
169
    return 0;
170
 
171
  /* There's no point in enabling this module if no
172
     architecture-specific operations are provided.  */
173
  if (!ops->supply_uthread)
174
    return 0;
175
 
176
  bsd_uthread_thread_run_addr =
177
    bsd_uthread_lookup_address ("_thread_run", objfile);
178
  if (bsd_uthread_thread_run_addr == 0)
179
    return 0;
180
 
181
  bsd_uthread_thread_list_addr =
182
    bsd_uthread_lookup_address ("_thread_list", objfile);
183
  if (bsd_uthread_thread_list_addr == 0)
184
    return 0;
185
 
186
  bsd_uthread_thread_state_offset =
187
    bsd_uthread_lookup_offset ("_thread_state_offset", objfile);
188
  if (bsd_uthread_thread_state_offset == 0)
189
    return 0;
190
 
191
  bsd_uthread_thread_next_offset =
192
    bsd_uthread_lookup_offset ("_thread_next_offset", objfile);
193
  if (bsd_uthread_thread_next_offset == 0)
194
    return 0;
195
 
196
  bsd_uthread_thread_ctx_offset =
197
    bsd_uthread_lookup_offset ("_thread_ctx_offset", objfile);
198
 
199
  push_target (bsd_uthread_ops_hack);
200
  bsd_uthread_active = 1;
201
  return 1;
202
}
203
 
204
/* Cleanup due to deactivation.  */
205
 
206
static void
207
bsd_uthread_close (int quitting)
208
{
209
  bsd_uthread_active = 0;
210
  bsd_uthread_thread_run_addr = 0;
211
  bsd_uthread_thread_list_addr = 0;
212
  bsd_uthread_thread_state_offset = 0;
213
  bsd_uthread_thread_next_offset = 0;
214
  bsd_uthread_thread_ctx_offset = 0;
215
  bsd_uthread_solib_name = NULL;
216
}
217
 
218
/* Deactivate the thread stratum implemented by this module.  */
219
 
220
static void
221
bsd_uthread_deactivate (void)
222
{
223
  /* Skip if the thread stratum has already been deactivated.  */
224
  if (!bsd_uthread_active)
225
    return;
226
 
227
  unpush_target (bsd_uthread_ops_hack);
228
}
229
 
230
static void
231
bsd_uthread_inferior_created (struct target_ops *ops, int from_tty)
232
{
233
  bsd_uthread_activate (NULL);
234
}
235
 
236
/* Likely candidates for the threads library.  */
237
static const char *bsd_uthread_solib_names[] =
238
{
239
  "/usr/lib/libc_r.so",         /* FreeBSD */
240
  "/usr/lib/libpthread.so",     /* OpenBSD */
241
  NULL
242
};
243
 
244
static void
245
bsd_uthread_solib_loaded (struct so_list *so)
246
{
247
  const char **names = bsd_uthread_solib_names;
248
 
249
  for (names = bsd_uthread_solib_names; *names; names++)
250
    {
251
      if (strncmp (so->so_original_name, *names, strlen (*names)) == 0)
252
        {
253
          solib_read_symbols (so, so->from_tty ? SYMFILE_VERBOSE : 0);
254
 
255
          if (bsd_uthread_activate (so->objfile))
256
            {
257
              bsd_uthread_solib_name = so->so_original_name;
258
              return;
259
            }
260
        }
261
    }
262
}
263
 
264
static void
265
bsd_uthread_solib_unloaded (struct so_list *so)
266
{
267
  if (!bsd_uthread_solib_name)
268
    return;
269
 
270
  if (strcmp (so->so_original_name, bsd_uthread_solib_name) == 0)
271
    bsd_uthread_deactivate ();
272
}
273
 
274
static void
275
bsd_uthread_mourn_inferior (struct target_ops *ops)
276
{
277
  struct target_ops *beneath = find_target_beneath (ops);
278
  beneath->to_mourn_inferior (beneath);
279
  bsd_uthread_deactivate ();
280
}
281
 
282
static void
283
bsd_uthread_fetch_registers (struct target_ops *ops,
284
                             struct regcache *regcache, int regnum)
285
{
286
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
287
  struct bsd_uthread_ops *uthread_ops = gdbarch_data (gdbarch, bsd_uthread_data);
288
  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
289
  struct target_ops *beneath = find_target_beneath (ops);
290
  CORE_ADDR active_addr;
291
 
292
  /* Always fetch the appropriate registers from the layer beneath.  */
293
  beneath->to_fetch_registers (beneath, regcache, regnum);
294
 
295
  /* FIXME: That might have gotten us more than we asked for.  Make
296
     sure we overwrite all relevant registers with values from the
297
     thread structure.  This can go once we fix the underlying target.  */
298
  regnum = -1;
299
 
300
  active_addr = bsd_uthread_read_memory_address (bsd_uthread_thread_run_addr);
301
  if (addr != 0 && addr != active_addr)
302
    {
303
      bsd_uthread_check_magic (addr);
304
      uthread_ops->supply_uthread (regcache, regnum,
305
                                   addr + bsd_uthread_thread_ctx_offset);
306
    }
307
}
308
 
309
static void
310
bsd_uthread_store_registers (struct target_ops *ops,
311
                             struct regcache *regcache, int regnum)
312
{
313
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
314
  struct bsd_uthread_ops *uthread_ops = gdbarch_data (gdbarch, bsd_uthread_data);
315
  struct target_ops *beneath = find_target_beneath (ops);
316
  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
317
  CORE_ADDR active_addr;
318
 
319
  active_addr = bsd_uthread_read_memory_address (bsd_uthread_thread_run_addr);
320
  if (addr != 0 && addr != active_addr)
321
    {
322
      bsd_uthread_check_magic (addr);
323
      uthread_ops->collect_uthread (regcache, regnum,
324
                                    addr + bsd_uthread_thread_ctx_offset);
325
    }
326
  else
327
    {
328
      /* Updating the thread that is currently running; pass the
329
         request to the layer beneath.  */
330
      beneath->to_store_registers (beneath, regcache, regnum);
331
    }
332
}
333
 
334
/* FIXME: This function is only there because otherwise GDB tries to
335
   invoke deprecate_xfer_memory.  */
336
 
337
static LONGEST
338
bsd_uthread_xfer_partial (struct target_ops *ops, enum target_object object,
339
                          const char *annex, gdb_byte *readbuf,
340
                          const gdb_byte *writebuf,
341
                          ULONGEST offset, LONGEST len)
342
{
343
  gdb_assert (ops->beneath->to_xfer_partial);
344
  return ops->beneath->to_xfer_partial (ops->beneath, object, annex, readbuf,
345
                                        writebuf, offset, len);
346
}
347
 
348
static ptid_t
349
bsd_uthread_wait (struct target_ops *ops,
350
                  ptid_t ptid, struct target_waitstatus *status, int options)
351
{
352
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
353
  CORE_ADDR addr;
354
  struct target_ops *beneath = find_target_beneath (ops);
355
 
356
  /* Pass the request to the layer beneath.  */
357
  ptid = beneath->to_wait (beneath, ptid, status, options);
358
 
359
  /* If the process is no longer alive, there's no point in figuring
360
     out the thread ID.  It will fail anyway.  */
361
  if (status->kind == TARGET_WAITKIND_SIGNALLED
362
      || status->kind == TARGET_WAITKIND_EXITED)
363
    return ptid;
364
 
365
  /* Fetch the corresponding thread ID, and augment the returned
366
     process ID with it.  */
367
  addr = bsd_uthread_read_memory_address (bsd_uthread_thread_run_addr);
368
  if (addr != 0)
369
    {
370
      gdb_byte buf[4];
371
 
372
      /* FIXME: For executables linked statically with the threads
373
         library, we end up here before the program has actually been
374
         executed.  In that case ADDR will be garbage since it has
375
         been read from the wrong virtual memory image.  */
376
      if (target_read_memory (addr, buf, 4) == 0)
377
        {
378
          ULONGEST magic = extract_unsigned_integer (buf, 4, byte_order);
379
          if (magic == BSD_UTHREAD_PTHREAD_MAGIC)
380
            ptid = ptid_build (ptid_get_pid (ptid), 0, addr);
381
        }
382
    }
383
 
384
  /* If INFERIOR_PTID doesn't have a tid member yet, and we now have a
385
     ptid with tid set, then ptid is still the initial thread of
386
     the process.  Notify GDB core about it.  */
387
  if (ptid_get_tid (inferior_ptid) == 0
388
      && ptid_get_tid (ptid) != 0 && !in_thread_list (ptid))
389
    thread_change_ptid (inferior_ptid, ptid);
390
 
391
  /* Don't let the core see a ptid without a corresponding thread.  */
392
  if (!in_thread_list (ptid) || is_exited (ptid))
393
    add_thread (ptid);
394
 
395
  return ptid;
396
}
397
 
398
static void
399
bsd_uthread_resume (struct target_ops *ops,
400
                    ptid_t ptid, int step, enum target_signal sig)
401
{
402
  /* Pass the request to the layer beneath.  */
403
  struct target_ops *beneath = find_target_beneath (ops);
404
  beneath->to_resume (beneath, ptid, step, sig);
405
}
406
 
407
static int
408
bsd_uthread_thread_alive (struct target_ops *ops, ptid_t ptid)
409
{
410
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
411
  struct target_ops *beneath = find_target_beneath (ops);
412
  CORE_ADDR addr = ptid_get_tid (inferior_ptid);
413
 
414
  if (addr != 0)
415
    {
416
      int offset = bsd_uthread_thread_state_offset;
417
      ULONGEST state;
418
 
419
      bsd_uthread_check_magic (addr);
420
 
421
      state = read_memory_unsigned_integer (addr + offset, 4, byte_order);
422
      if (state == BSD_UTHREAD_PS_DEAD)
423
        return 0;
424
    }
425
 
426
  return beneath->to_thread_alive (beneath, ptid);
427
}
428
 
429
static void
430
bsd_uthread_find_new_threads (struct target_ops *ops)
431
{
432
  pid_t pid = ptid_get_pid (inferior_ptid);
433
  int offset = bsd_uthread_thread_next_offset;
434
  CORE_ADDR addr;
435
 
436
  addr = bsd_uthread_read_memory_address (bsd_uthread_thread_list_addr);
437
  while (addr != 0)
438
    {
439
      ptid_t ptid = ptid_build (pid, 0, addr);
440
 
441
      if (!in_thread_list (ptid) || is_exited (ptid))
442
        {
443
          /* If INFERIOR_PTID doesn't have a tid member yet, then ptid
444
             is still the initial thread of the process.  Notify GDB
445
             core about it.  */
446
          if (ptid_get_tid (inferior_ptid) == 0)
447
            thread_change_ptid (inferior_ptid, ptid);
448
          else
449
            add_thread (ptid);
450
        }
451
 
452
      addr = bsd_uthread_read_memory_address (addr + offset);
453
    }
454
}
455
 
456
/* Possible states a thread can be in.  */
457
static char *bsd_uthread_state[] =
458
{
459
  "RUNNING",
460
  "SIGTHREAD",
461
  "MUTEX_WAIT",
462
  "COND_WAIT",
463
  "FDLR_WAIT",
464
  "FDLW_WAIT",
465
  "FDR_WAIT",
466
  "FDW_WAIT",
467
  "FILE_WAIT",
468
  "POLL_WAIT",
469
  "SELECT_WAIT",
470
  "SLEEP_WAIT",
471
  "WAIT_WAIT",
472
  "SIGSUSPEND",
473
  "SIGWAIT",
474
  "SPINBLOCK",
475
  "JOIN",
476
  "SUSPENDED",
477
  "DEAD",
478
  "DEADLOCK"
479
};
480
 
481
/* Return a string describing th state of the thread specified by
482
   INFO.  */
483
 
484
static char *
485
bsd_uthread_extra_thread_info (struct thread_info *info)
486
{
487
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);
488
  CORE_ADDR addr = ptid_get_tid (info->ptid);
489
 
490
  if (addr != 0)
491
    {
492
      int offset = bsd_uthread_thread_state_offset;
493
      ULONGEST state;
494
 
495
      state = read_memory_unsigned_integer (addr + offset, 4, byte_order);
496
      if (state < ARRAY_SIZE (bsd_uthread_state))
497
        return bsd_uthread_state[state];
498
    }
499
 
500
  return NULL;
501
}
502
 
503
static char *
504
bsd_uthread_pid_to_str (struct target_ops *ops, ptid_t ptid)
505
{
506
  if (ptid_get_tid (ptid) != 0)
507
    {
508
      static char buf[64];
509
 
510
      xsnprintf (buf, sizeof buf, "process %d, thread 0x%lx",
511
                 ptid_get_pid (ptid), ptid_get_tid (ptid));
512
      return buf;
513
    }
514
 
515
  return normal_pid_to_str (ptid);
516
}
517
 
518
static struct target_ops *
519
bsd_uthread_target (void)
520
{
521
  struct target_ops *t = XZALLOC (struct target_ops);
522
 
523
  t->to_shortname = "bsd-uthreads";
524
  t->to_longname = "BSD user-level threads";
525
  t->to_doc = "BSD user-level threads";
526
  t->to_close = bsd_uthread_close;
527
  t->to_mourn_inferior = bsd_uthread_mourn_inferior;
528
  t->to_fetch_registers = bsd_uthread_fetch_registers;
529
  t->to_store_registers = bsd_uthread_store_registers;
530
  t->to_xfer_partial = bsd_uthread_xfer_partial;
531
  t->to_wait = bsd_uthread_wait;
532
  t->to_resume = bsd_uthread_resume;
533
  t->to_thread_alive = bsd_uthread_thread_alive;
534
  t->to_find_new_threads = bsd_uthread_find_new_threads;
535
  t->to_extra_thread_info = bsd_uthread_extra_thread_info;
536
  t->to_pid_to_str = bsd_uthread_pid_to_str;
537
  t->to_stratum = thread_stratum;
538
  t->to_magic = OPS_MAGIC;
539
  bsd_uthread_ops_hack = t;
540
 
541
  return t;
542
}
543
 
544
/* Provide a prototype to silence -Wmissing-prototypes.  */
545
extern initialize_file_ftype _initialize_bsd_uthread;
546
 
547
void
548
_initialize_bsd_uthread (void)
549
{
550
  add_target (bsd_uthread_target ());
551
 
552
  bsd_uthread_data = gdbarch_data_register_pre_init (bsd_uthread_init);
553
 
554
  observer_attach_inferior_created (bsd_uthread_inferior_created);
555
  observer_attach_solib_loaded (bsd_uthread_solib_loaded);
556
  observer_attach_solib_unloaded (bsd_uthread_solib_unloaded);
557
}

powered by: WebSVN 2.1.0

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