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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [gdb/] [gdbserver/] [thread-db.c] - Blame information for rev 25

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 25 jlechner
/* Thread management interface, for the remote server for GDB.
2
   Copyright (C) 2002, 2004, 2005, 2006, 2007, 2008
3
   Free Software Foundation, Inc.
4
 
5
   Contributed by MontaVista Software.
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
#include "server.h"
23
 
24
#include "linux-low.h"
25
 
26
extern int debug_threads;
27
 
28
static int thread_db_use_events;
29
 
30
#ifdef HAVE_THREAD_DB_H
31
#include <thread_db.h>
32
#endif
33
 
34
#include "gdb_proc_service.h"
35
 
36
#include <stdint.h>
37
 
38
/* Structure that identifies the child process for the
39
   <proc_service.h> interface.  */
40
static struct ps_prochandle proc_handle;
41
 
42
/* Connection to the libthread_db library.  */
43
static td_thragent_t *thread_agent;
44
 
45
static int find_one_thread (int);
46
static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
47
 
48
static char *
49
thread_db_err_str (td_err_e err)
50
{
51
  static char buf[64];
52
 
53
  switch (err)
54
    {
55
    case TD_OK:
56
      return "generic 'call succeeded'";
57
    case TD_ERR:
58
      return "generic error";
59
    case TD_NOTHR:
60
      return "no thread to satisfy query";
61
    case TD_NOSV:
62
      return "no sync handle to satisfy query";
63
    case TD_NOLWP:
64
      return "no LWP to satisfy query";
65
    case TD_BADPH:
66
      return "invalid process handle";
67
    case TD_BADTH:
68
      return "invalid thread handle";
69
    case TD_BADSH:
70
      return "invalid synchronization handle";
71
    case TD_BADTA:
72
      return "invalid thread agent";
73
    case TD_BADKEY:
74
      return "invalid key";
75
    case TD_NOMSG:
76
      return "no event message for getmsg";
77
    case TD_NOFPREGS:
78
      return "FPU register set not available";
79
    case TD_NOLIBTHREAD:
80
      return "application not linked with libthread";
81
    case TD_NOEVENT:
82
      return "requested event is not supported";
83
    case TD_NOCAPAB:
84
      return "capability not available";
85
    case TD_DBERR:
86
      return "debugger service failed";
87
    case TD_NOAPLIC:
88
      return "operation not applicable to";
89
    case TD_NOTSD:
90
      return "no thread-specific data for this thread";
91
    case TD_MALLOC:
92
      return "malloc failed";
93
    case TD_PARTIALREG:
94
      return "only part of register set was written/read";
95
    case TD_NOXREGS:
96
      return "X register set not available for this thread";
97
#ifdef HAVE_TD_VERSION
98
    case TD_VERSION:
99
      return "version mismatch between libthread_db and libpthread";
100
#endif
101
    default:
102
      snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err);
103
      return buf;
104
    }
105
}
106
 
107
#if 0
108
static char *
109
thread_db_state_str (td_thr_state_e state)
110
{
111
  static char buf[64];
112
 
113
  switch (state)
114
    {
115
    case TD_THR_STOPPED:
116
      return "stopped by debugger";
117
    case TD_THR_RUN:
118
      return "runnable";
119
    case TD_THR_ACTIVE:
120
      return "active";
121
    case TD_THR_ZOMBIE:
122
      return "zombie";
123
    case TD_THR_SLEEP:
124
      return "sleeping";
125
    case TD_THR_STOPPED_ASLEEP:
126
      return "stopped by debugger AND blocked";
127
    default:
128
      snprintf (buf, sizeof (buf), "unknown thread_db state %d", state);
129
      return buf;
130
    }
131
}
132
#endif
133
 
134
static int
135
thread_db_create_event (CORE_ADDR where)
136
{
137
  td_event_msg_t msg;
138
  td_err_e err;
139
  struct process_info *process;
140
 
141
  if (debug_threads)
142
    fprintf (stderr, "Thread creation event.\n");
143
 
144
  /* FIXME: This assumes we don't get another event.
145
     In the LinuxThreads implementation, this is safe,
146
     because all events come from the manager thread
147
     (except for its own creation, of course).  */
148
  err = td_ta_event_getmsg (thread_agent, &msg);
149
  if (err != TD_OK)
150
    fprintf (stderr, "thread getmsg err: %s\n",
151
             thread_db_err_str (err));
152
 
153
  /* If we do not know about the main thread yet, this would be a good time to
154
     find it.  We need to do this to pick up the main thread before any newly
155
     created threads.  */
156
  process = get_thread_process (current_inferior);
157
  if (process->thread_known == 0)
158
    find_one_thread (process->lwpid);
159
 
160
  /* msg.event == TD_EVENT_CREATE */
161
 
162
  find_new_threads_callback (msg.th_p, NULL);
163
 
164
  return 0;
165
}
166
 
167
#if 0
168
static int
169
thread_db_death_event (CORE_ADDR where)
170
{
171
  if (debug_threads)
172
    fprintf (stderr, "Thread death event.\n");
173
 
174
  return 0;
175
}
176
#endif
177
 
178
static int
179
thread_db_enable_reporting ()
180
{
181
  td_thr_events_t events;
182
  td_notify_t notify;
183
  td_err_e err;
184
 
185
  /* Set the process wide mask saying which events we're interested in.  */
186
  td_event_emptyset (&events);
187
  td_event_addset (&events, TD_CREATE);
188
 
189
#if 0
190
  /* This is reported to be broken in glibc 2.1.3.  A different approach
191
     will be necessary to support that.  */
192
  td_event_addset (&events, TD_DEATH);
193
#endif
194
 
195
  err = td_ta_set_event (thread_agent, &events);
196
  if (err != TD_OK)
197
    {
198
      warning ("Unable to set global thread event mask: %s",
199
               thread_db_err_str (err));
200
      return 0;
201
    }
202
 
203
  /* Get address for thread creation breakpoint.  */
204
  err = td_ta_event_addr (thread_agent, TD_CREATE, &notify);
205
  if (err != TD_OK)
206
    {
207
      warning ("Unable to get location for thread creation breakpoint: %s",
208
               thread_db_err_str (err));
209
      return 0;
210
    }
211
  set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
212
                     thread_db_create_event);
213
 
214
#if 0
215
  /* Don't concern ourselves with reported thread deaths, only
216
     with actual thread deaths (via wait).  */
217
 
218
  /* Get address for thread death breakpoint.  */
219
  err = td_ta_event_addr (thread_agent, TD_DEATH, &notify);
220
  if (err != TD_OK)
221
    {
222
      warning ("Unable to get location for thread death breakpoint: %s",
223
               thread_db_err_str (err));
224
      return;
225
    }
226
  set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
227
                     thread_db_death_event);
228
#endif
229
 
230
  return 1;
231
}
232
 
233
static int
234
find_one_thread (int lwpid)
235
{
236
  td_thrhandle_t th;
237
  td_thrinfo_t ti;
238
  td_err_e err;
239
  struct thread_info *inferior;
240
  struct process_info *process;
241
 
242
  inferior = (struct thread_info *) find_inferior_id (&all_threads, lwpid);
243
  process = get_thread_process (inferior);
244
  if (process->thread_known)
245
    return 1;
246
 
247
  /* Get information about this thread.  */
248
  err = td_ta_map_lwp2thr (thread_agent, process->lwpid, &th);
249
  if (err != TD_OK)
250
    error ("Cannot get thread handle for LWP %d: %s",
251
           lwpid, thread_db_err_str (err));
252
 
253
  err = td_thr_get_info (&th, &ti);
254
  if (err != TD_OK)
255
    error ("Cannot get thread info for LWP %d: %s",
256
           lwpid, thread_db_err_str (err));
257
 
258
  if (debug_threads)
259
    fprintf (stderr, "Found thread %ld (LWP %d)\n",
260
             ti.ti_tid, ti.ti_lid);
261
 
262
  if (process->lwpid != ti.ti_lid)
263
    {
264
      warning ("PID mismatch!  Expected %ld, got %ld",
265
               (long) process->lwpid, (long) ti.ti_lid);
266
      return 0;
267
    }
268
 
269
  if (thread_db_use_events)
270
    {
271
      err = td_thr_event_enable (&th, 1);
272
      if (err != TD_OK)
273
        error ("Cannot enable thread event reporting for %d: %s",
274
               ti.ti_lid, thread_db_err_str (err));
275
    }
276
 
277
  /* If the new thread ID is zero, a final thread ID will be available
278
     later.  Do not enable thread debugging yet.  */
279
  if (ti.ti_tid == 0)
280
    return 0;
281
 
282
  process->thread_known = 1;
283
  process->tid = ti.ti_tid;
284
  process->th = th;
285
 
286
  return 1;
287
}
288
 
289
static void
290
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
291
{
292
  td_err_e err;
293
  struct thread_info *inferior;
294
  struct process_info *process;
295
 
296
  inferior = (struct thread_info *) find_inferior_id (&all_threads,
297
                                                      ti_p->ti_lid);
298
  if (inferior != NULL)
299
    return;
300
 
301
  if (debug_threads)
302
    fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
303
             ti_p->ti_tid, ti_p->ti_lid);
304
  linux_attach_lwp (ti_p->ti_lid);
305
  inferior = (struct thread_info *) find_inferior_id (&all_threads,
306
                                                      ti_p->ti_lid);
307
  if (inferior == NULL)
308
    {
309
      warning ("Could not attach to thread %ld (LWP %d)\n",
310
               ti_p->ti_tid, ti_p->ti_lid);
311
      return;
312
    }
313
 
314
  process = inferior_target_data (inferior);
315
 
316
  process->tid = ti_p->ti_tid;
317
  process->thread_known = 1;
318
  process->th = *th_p;
319
 
320
  if (thread_db_use_events)
321
    {
322
      err = td_thr_event_enable (th_p, 1);
323
      if (err != TD_OK)
324
        error ("Cannot enable thread event reporting for %d: %s",
325
               ti_p->ti_lid, thread_db_err_str (err));
326
    }
327
}
328
 
329
static int
330
find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
331
{
332
  td_thrinfo_t ti;
333
  td_err_e err;
334
 
335
  err = td_thr_get_info (th_p, &ti);
336
  if (err != TD_OK)
337
    error ("Cannot get thread info: %s", thread_db_err_str (err));
338
 
339
  /* Check for zombies.  */
340
  if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
341
    return 0;
342
 
343
  maybe_attach_thread (th_p, &ti);
344
 
345
  return 0;
346
}
347
 
348
static void
349
thread_db_find_new_threads (void)
350
{
351
  td_err_e err;
352
 
353
  /* This function is only called when we first initialize thread_db.
354
     First locate the initial thread.  If it is not ready for
355
     debugging yet, then stop.  */
356
  if (find_one_thread (all_threads.head->id) == 0)
357
    return;
358
 
359
  /* Iterate over all user-space threads to discover new threads.  */
360
  err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
361
                        TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
362
                        TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
363
  if (err != TD_OK)
364
    error ("Cannot find new threads: %s", thread_db_err_str (err));
365
}
366
 
367
/* Cache all future symbols that thread_db might request.  We can not
368
   request symbols at arbitrary states in the remote protocol, only
369
   when the client tells us that new symbols are available.  So when
370
   we load the thread library, make sure to check the entire list.  */
371
 
372
static void
373
thread_db_look_up_symbols (void)
374
{
375
  const char **sym_list = td_symbol_list ();
376
  CORE_ADDR unused;
377
 
378
  for (sym_list = td_symbol_list (); *sym_list; sym_list++)
379
    look_up_one_symbol (*sym_list, &unused);
380
}
381
 
382
int
383
thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
384
                           CORE_ADDR load_module, CORE_ADDR *address)
385
{
386
#if HAVE_TD_THR_TLS_GET_ADDR
387
  psaddr_t addr;
388
  td_err_e err;
389
  struct process_info *process;
390
 
391
  process = get_thread_process (thread);
392
  if (!process->thread_known)
393
    find_one_thread (process->lwpid);
394
  if (!process->thread_known)
395
    return TD_NOTHR;
396
 
397
  /* Note the cast through uintptr_t: this interface only works if
398
     a target address fits in a psaddr_t, which is a host pointer.
399
     So a 32-bit debugger can not access 64-bit TLS through this.  */
400
  err = td_thr_tls_get_addr (&process->th, (psaddr_t) (uintptr_t) load_module,
401
                             offset, &addr);
402
  if (err == TD_OK)
403
    {
404
      *address = (CORE_ADDR) (uintptr_t) addr;
405
      return 0;
406
    }
407
  else
408
    return err;
409
#else
410
  return -1;
411
#endif
412
}
413
 
414
int
415
thread_db_init (int use_events)
416
{
417
  int err;
418
 
419
  /* FIXME drow/2004-10-16: This is the "overall process ID", which
420
     GNU/Linux calls tgid, "thread group ID".  When we support
421
     attaching to threads, the original thread may not be the correct
422
     thread.  We would have to get the process ID from /proc for NPTL.
423
     For LinuxThreads we could do something similar: follow the chain
424
     of parent processes until we find the highest one we're attached
425
     to, and use its tgid.
426
 
427
     This isn't the only place in gdbserver that assumes that the first
428
     process in the list is the thread group leader.  */
429
  proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
430
 
431
  /* Allow new symbol lookups.  */
432
  all_symbols_looked_up = 0;
433
 
434
  thread_db_use_events = use_events;
435
 
436
  err = td_ta_new (&proc_handle, &thread_agent);
437
  switch (err)
438
    {
439
    case TD_NOLIBTHREAD:
440
      /* No thread library was detected.  */
441
      return 0;
442
 
443
    case TD_OK:
444
      /* The thread library was detected.  */
445
 
446
      if (use_events && thread_db_enable_reporting () == 0)
447
        return 0;
448
      thread_db_find_new_threads ();
449
      thread_db_look_up_symbols ();
450
      all_symbols_looked_up = 1;
451
      return 1;
452
 
453
    default:
454
      warning ("error initializing thread_db library: %s",
455
               thread_db_err_str (err));
456
    }
457
 
458
  return 0;
459
}

powered by: WebSVN 2.1.0

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