198944Sobrien/* libthread_db assisted debugging support, generic parts. 298944Sobrien 3130803Smarcel Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc. 4130803Smarcel 598944Sobrien This file is part of GDB. 698944Sobrien 798944Sobrien This program is free software; you can redistribute it and/or modify 898944Sobrien it under the terms of the GNU General Public License as published by 998944Sobrien the Free Software Foundation; either version 2 of the License, or 1098944Sobrien (at your option) any later version. 1198944Sobrien 1298944Sobrien This program is distributed in the hope that it will be useful, 1398944Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1498944Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1598944Sobrien GNU General Public License for more details. 1698944Sobrien 1798944Sobrien You should have received a copy of the GNU General Public License 1898944Sobrien along with this program; if not, write to the Free Software 1998944Sobrien Foundation, Inc., 59 Temple Place - Suite 330, 2098944Sobrien Boston, MA 02111-1307, USA. */ 2198944Sobrien 2298944Sobrien#include "defs.h" 2398944Sobrien 2498944Sobrien#include "gdb_assert.h" 2598944Sobrien#include <dlfcn.h> 2698944Sobrien#include "gdb_proc_service.h" 2798944Sobrien#include "gdb_thread_db.h" 2898944Sobrien 2998944Sobrien#include "bfd.h" 3098944Sobrien#include "gdbthread.h" 3198944Sobrien#include "inferior.h" 3298944Sobrien#include "symfile.h" 3398944Sobrien#include "objfiles.h" 3498944Sobrien#include "target.h" 3598944Sobrien#include "regcache.h" 36130803Smarcel#include "solib-svr4.h" 3798944Sobrien 3898944Sobrien#ifndef LIBTHREAD_DB_SO 3998944Sobrien#define LIBTHREAD_DB_SO "libthread_db.so.1" 4098944Sobrien#endif 4198944Sobrien 4298944Sobrien/* If we're running on GNU/Linux, we must explicitly attach to any new 4398944Sobrien threads. */ 4498944Sobrien 4598944Sobrien/* FIXME: There is certainly some room for improvements: 4698944Sobrien - Cache LWP ids. 4798944Sobrien - Bypass libthread_db when fetching or storing registers for 4898944Sobrien threads bound to a LWP. */ 4998944Sobrien 5098944Sobrien/* This module's target vector. */ 5198944Sobrienstatic struct target_ops thread_db_ops; 5298944Sobrien 5398944Sobrien/* The target vector that we call for things this module can't handle. */ 5498944Sobrienstatic struct target_ops *target_beneath; 5598944Sobrien 5698944Sobrien/* Pointer to the next function on the objfile event chain. */ 57130803Smarcelstatic void (*target_new_objfile_chain) (struct objfile * objfile); 5898944Sobrien 5998944Sobrien/* Non-zero if we're using this module's target vector. */ 6098944Sobrienstatic int using_thread_db; 6198944Sobrien 6298944Sobrien/* Non-zero if we have to keep this module's target vector active 6398944Sobrien across re-runs. */ 6498944Sobrienstatic int keep_thread_db; 6598944Sobrien 6698944Sobrien/* Non-zero if we have determined the signals used by the threads 6798944Sobrien library. */ 6898944Sobrienstatic int thread_signals; 6998944Sobrienstatic sigset_t thread_stop_set; 7098944Sobrienstatic sigset_t thread_print_set; 7198944Sobrien 7298944Sobrien/* Structure that identifies the child process for the 7398944Sobrien <proc_service.h> interface. */ 7498944Sobrienstatic struct ps_prochandle proc_handle; 7598944Sobrien 7698944Sobrien/* Connection to the libthread_db library. */ 7798944Sobrienstatic td_thragent_t *thread_agent; 7898944Sobrien 7998944Sobrien/* Pointers to the libthread_db functions. */ 8098944Sobrien 8198944Sobrienstatic td_err_e (*td_init_p) (void); 8298944Sobrien 83130803Smarcelstatic td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, 84130803Smarcel td_thragent_t **ta); 8598944Sobrienstatic td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, 8698944Sobrien td_thrhandle_t *__th); 87130803Smarcelstatic td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, 88130803Smarcel lwpid_t lwpid, td_thrhandle_t *th); 8998944Sobrienstatic td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, 90130803Smarcel td_thr_iter_f *callback, void *cbdata_p, 91130803Smarcel td_thr_state_e state, int ti_pri, 92130803Smarcel sigset_t *ti_sigmask_p, 9398944Sobrien unsigned int ti_user_flags); 9498944Sobrienstatic td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, 9598944Sobrien td_event_e event, td_notify_t *ptr); 9698944Sobrienstatic td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, 9798944Sobrien td_thr_events_t *event); 9898944Sobrienstatic td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, 9998944Sobrien td_event_msg_t *msg); 10098944Sobrien 10198944Sobrienstatic td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th); 10298944Sobrienstatic td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, 10398944Sobrien td_thrinfo_t *infop); 10498944Sobrienstatic td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, 10598944Sobrien gdb_prfpregset_t *regset); 10698944Sobrienstatic td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, 10798944Sobrien prgregset_t gregs); 10898944Sobrienstatic td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, 10998944Sobrien const gdb_prfpregset_t *fpregs); 11098944Sobrienstatic td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, 11198944Sobrien prgregset_t gregs); 112130803Smarcelstatic td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, 113130803Smarcel int event); 11498944Sobrien 115130803Smarcelstatic td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, 116130803Smarcel void *map_address, 117130803Smarcel size_t offset, void **address); 118130803Smarcel 11998944Sobrien/* Location of the thread creation event breakpoint. The code at this 12098944Sobrien location in the child process will be called by the pthread library 12198944Sobrien whenever a new thread is created. By setting a special breakpoint 12298944Sobrien at this location, GDB can detect when a new thread is created. We 12398944Sobrien obtain this location via the td_ta_event_addr call. */ 12498944Sobrienstatic CORE_ADDR td_create_bp_addr; 12598944Sobrien 12698944Sobrien/* Location of the thread death event breakpoint. */ 12798944Sobrienstatic CORE_ADDR td_death_bp_addr; 12898944Sobrien 12998944Sobrien/* Prototypes for local functions. */ 13098944Sobrienstatic void thread_db_find_new_threads (void); 131130803Smarcelstatic void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, 132130803Smarcel const td_thrinfo_t *ti_p, int verbose); 13398944Sobrien 13498944Sobrien 13598944Sobrien/* Building process ids. */ 13698944Sobrien 13798944Sobrien#define GET_PID(ptid) ptid_get_pid (ptid) 13898944Sobrien#define GET_LWP(ptid) ptid_get_lwp (ptid) 13998944Sobrien#define GET_THREAD(ptid) ptid_get_tid (ptid) 14098944Sobrien 14198944Sobrien#define is_lwp(ptid) (GET_LWP (ptid) != 0) 14298944Sobrien#define is_thread(ptid) (GET_THREAD (ptid) != 0) 14398944Sobrien 14498944Sobrien#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0) 14598944Sobrien#define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid) 14698944Sobrien 14798944Sobrien 148130803Smarcel/* Use "struct private_thread_info" to cache thread state. This is 149130803Smarcel a substantial optimization. */ 150130803Smarcel 15198944Sobrienstruct private_thread_info 15298944Sobrien{ 153130803Smarcel /* Cached thread state. */ 154130803Smarcel unsigned int th_valid:1; 155130803Smarcel unsigned int ti_valid:1; 156130803Smarcel 157130803Smarcel td_thrhandle_t th; 158130803Smarcel td_thrinfo_t ti; 15998944Sobrien}; 16098944Sobrien 16198944Sobrien 16298944Sobrienstatic char * 16398944Sobrienthread_db_err_str (td_err_e err) 16498944Sobrien{ 16598944Sobrien static char buf[64]; 16698944Sobrien 16798944Sobrien switch (err) 16898944Sobrien { 16998944Sobrien case TD_OK: 17098944Sobrien return "generic 'call succeeded'"; 17198944Sobrien case TD_ERR: 17298944Sobrien return "generic error"; 17398944Sobrien case TD_NOTHR: 17498944Sobrien return "no thread to satisfy query"; 17598944Sobrien case TD_NOSV: 17698944Sobrien return "no sync handle to satisfy query"; 17798944Sobrien case TD_NOLWP: 17898944Sobrien return "no LWP to satisfy query"; 17998944Sobrien case TD_BADPH: 18098944Sobrien return "invalid process handle"; 18198944Sobrien case TD_BADTH: 18298944Sobrien return "invalid thread handle"; 18398944Sobrien case TD_BADSH: 18498944Sobrien return "invalid synchronization handle"; 18598944Sobrien case TD_BADTA: 18698944Sobrien return "invalid thread agent"; 18798944Sobrien case TD_BADKEY: 18898944Sobrien return "invalid key"; 18998944Sobrien case TD_NOMSG: 19098944Sobrien return "no event message for getmsg"; 19198944Sobrien case TD_NOFPREGS: 19298944Sobrien return "FPU register set not available"; 19398944Sobrien case TD_NOLIBTHREAD: 19498944Sobrien return "application not linked with libthread"; 19598944Sobrien case TD_NOEVENT: 19698944Sobrien return "requested event is not supported"; 19798944Sobrien case TD_NOCAPAB: 19898944Sobrien return "capability not available"; 19998944Sobrien case TD_DBERR: 20098944Sobrien return "debugger service failed"; 20198944Sobrien case TD_NOAPLIC: 20298944Sobrien return "operation not applicable to"; 20398944Sobrien case TD_NOTSD: 20498944Sobrien return "no thread-specific data for this thread"; 20598944Sobrien case TD_MALLOC: 20698944Sobrien return "malloc failed"; 20798944Sobrien case TD_PARTIALREG: 20898944Sobrien return "only part of register set was written/read"; 20998944Sobrien case TD_NOXREGS: 21098944Sobrien return "X register set not available for this thread"; 21198944Sobrien default: 21298944Sobrien snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err); 21398944Sobrien return buf; 21498944Sobrien } 21598944Sobrien} 21698944Sobrien 21798944Sobrienstatic char * 21898944Sobrienthread_db_state_str (td_thr_state_e state) 21998944Sobrien{ 22098944Sobrien static char buf[64]; 22198944Sobrien 22298944Sobrien switch (state) 22398944Sobrien { 22498944Sobrien case TD_THR_STOPPED: 22598944Sobrien return "stopped by debugger"; 22698944Sobrien case TD_THR_RUN: 22798944Sobrien return "runnable"; 22898944Sobrien case TD_THR_ACTIVE: 22998944Sobrien return "active"; 23098944Sobrien case TD_THR_ZOMBIE: 23198944Sobrien return "zombie"; 23298944Sobrien case TD_THR_SLEEP: 23398944Sobrien return "sleeping"; 23498944Sobrien case TD_THR_STOPPED_ASLEEP: 23598944Sobrien return "stopped by debugger AND blocked"; 23698944Sobrien default: 23798944Sobrien snprintf (buf, sizeof (buf), "unknown thread_db state %d", state); 23898944Sobrien return buf; 23998944Sobrien } 24098944Sobrien} 24198944Sobrien 242130803Smarcel/* A callback function for td_ta_thr_iter, which we use to map all 243130803Smarcel threads to LWPs. 24498944Sobrien 245130803Smarcel THP is a handle to the current thread; if INFOP is not NULL, the 246130803Smarcel struct thread_info associated with this thread is returned in 247130803Smarcel *INFOP. */ 248130803Smarcel 249130803Smarcelstatic int 250130803Smarcelthread_get_info_callback (const td_thrhandle_t *thp, void *infop) 251130803Smarcel{ 252130803Smarcel td_thrinfo_t ti; 253130803Smarcel td_err_e err; 254130803Smarcel struct thread_info *thread_info; 255130803Smarcel ptid_t thread_ptid; 256130803Smarcel 257130803Smarcel err = td_thr_get_info_p (thp, &ti); 258130803Smarcel if (err != TD_OK) 259130803Smarcel error ("thread_get_info_callback: cannot get thread info: %s", 260130803Smarcel thread_db_err_str (err)); 261130803Smarcel 262130803Smarcel /* Fill the cache. */ 263130803Smarcel thread_ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid)); 264130803Smarcel thread_info = find_thread_pid (thread_ptid); 265130803Smarcel 266130803Smarcel if (thread_info == NULL) 267130803Smarcel { 268130803Smarcel /* New thread. Attach to it now (why wait?). */ 269130803Smarcel attach_thread (thread_ptid, thp, &ti, 1); 270130803Smarcel thread_info = find_thread_pid (thread_ptid); 271130803Smarcel gdb_assert (thread_info != NULL); 272130803Smarcel } 273130803Smarcel 274130803Smarcel memcpy (&thread_info->private->th, thp, sizeof (*thp)); 275130803Smarcel thread_info->private->th_valid = 1; 276130803Smarcel memcpy (&thread_info->private->ti, &ti, sizeof (ti)); 277130803Smarcel thread_info->private->ti_valid = 1; 278130803Smarcel 279130803Smarcel if (infop != NULL) 280130803Smarcel *(struct thread_info **) infop = thread_info; 281130803Smarcel 282130803Smarcel return 0; 283130803Smarcel} 284130803Smarcel 285130803Smarcel/* Accessor functions for the thread_db information, with caching. */ 286130803Smarcel 287130803Smarcelstatic void 288130803Smarcelthread_db_map_id2thr (struct thread_info *thread_info, int fatal) 289130803Smarcel{ 290130803Smarcel td_err_e err; 291130803Smarcel 292130803Smarcel if (thread_info->private->th_valid) 293130803Smarcel return; 294130803Smarcel 295130803Smarcel err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid), 296130803Smarcel &thread_info->private->th); 297130803Smarcel if (err != TD_OK) 298130803Smarcel { 299130803Smarcel if (fatal) 300130803Smarcel error ("Cannot find thread %ld: %s", 301130803Smarcel (long) GET_THREAD (thread_info->ptid), 302130803Smarcel thread_db_err_str (err)); 303130803Smarcel } 304130803Smarcel else 305130803Smarcel thread_info->private->th_valid = 1; 306130803Smarcel} 307130803Smarcel 308130803Smarcelstatic td_thrinfo_t * 309130803Smarcelthread_db_get_info (struct thread_info *thread_info) 310130803Smarcel{ 311130803Smarcel td_err_e err; 312130803Smarcel 313130803Smarcel if (thread_info->private->ti_valid) 314130803Smarcel return &thread_info->private->ti; 315130803Smarcel 316130803Smarcel if (!thread_info->private->th_valid) 317130803Smarcel thread_db_map_id2thr (thread_info, 1); 318130803Smarcel 319130803Smarcel err = 320130803Smarcel td_thr_get_info_p (&thread_info->private->th, &thread_info->private->ti); 321130803Smarcel if (err != TD_OK) 322130803Smarcel error ("thread_db_get_info: cannot get thread info: %s", 323130803Smarcel thread_db_err_str (err)); 324130803Smarcel 325130803Smarcel thread_info->private->ti_valid = 1; 326130803Smarcel return &thread_info->private->ti; 327130803Smarcel} 328130803Smarcel 32998944Sobrien/* Convert between user-level thread ids and LWP ids. */ 33098944Sobrien 33198944Sobrienstatic ptid_t 33298944Sobrienthread_from_lwp (ptid_t ptid) 33398944Sobrien{ 33498944Sobrien td_thrhandle_t th; 33598944Sobrien td_err_e err; 336130803Smarcel struct thread_info *thread_info; 337130803Smarcel ptid_t thread_ptid; 33898944Sobrien 33998944Sobrien if (GET_LWP (ptid) == 0) 34098944Sobrien ptid = BUILD_LWP (GET_PID (ptid), GET_PID (ptid)); 34198944Sobrien 34298944Sobrien gdb_assert (is_lwp (ptid)); 34398944Sobrien 34498944Sobrien err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); 34598944Sobrien if (err != TD_OK) 346130803Smarcel error ("Cannot find user-level thread for LWP %ld: %s", 34798944Sobrien GET_LWP (ptid), thread_db_err_str (err)); 34898944Sobrien 349130803Smarcel thread_info = NULL; 350130803Smarcel thread_get_info_callback (&th, &thread_info); 351130803Smarcel gdb_assert (thread_info && thread_info->private->ti_valid); 35298944Sobrien 353130803Smarcel return BUILD_THREAD (thread_info->private->ti.ti_tid, GET_PID (ptid)); 35498944Sobrien} 35598944Sobrien 35698944Sobrienstatic ptid_t 35798944Sobrienlwp_from_thread (ptid_t ptid) 35898944Sobrien{ 359130803Smarcel struct thread_info *thread_info; 360130803Smarcel ptid_t thread_ptid; 36198944Sobrien 36298944Sobrien if (!is_thread (ptid)) 36398944Sobrien return ptid; 36498944Sobrien 365130803Smarcel thread_info = find_thread_pid (ptid); 366130803Smarcel thread_db_get_info (thread_info); 36798944Sobrien 368130803Smarcel return BUILD_LWP (thread_info->private->ti.ti_lid, GET_PID (ptid)); 36998944Sobrien} 37098944Sobrien 37198944Sobrien 37298944Sobrienvoid 37398944Sobrienthread_db_init (struct target_ops *target) 37498944Sobrien{ 37598944Sobrien target_beneath = target; 37698944Sobrien} 37798944Sobrien 378130803Smarcelstatic void * 379130803Smarcelverbose_dlsym (void *handle, const char *name) 380130803Smarcel{ 381130803Smarcel void *sym = dlsym (handle, name); 382130803Smarcel if (sym == NULL) 383130803Smarcel warning ("Symbol \"%s\" not found in libthread_db: %s", name, dlerror ()); 384130803Smarcel return sym; 385130803Smarcel} 386130803Smarcel 38798944Sobrienstatic int 38898944Sobrienthread_db_load (void) 38998944Sobrien{ 39098944Sobrien void *handle; 39198944Sobrien td_err_e err; 39298944Sobrien 39398944Sobrien handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW); 39498944Sobrien if (handle == NULL) 395130803Smarcel { 396130803Smarcel fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n", 397130803Smarcel LIBTHREAD_DB_SO, dlerror ()); 398130803Smarcel fprintf_filtered (gdb_stderr, 399130803Smarcel "GDB will not be able to debug pthreads.\n\n"); 400130803Smarcel return 0; 401130803Smarcel } 40298944Sobrien 40398944Sobrien /* Initialize pointers to the dynamic library functions we will use. 40498944Sobrien Essential functions first. */ 40598944Sobrien 406130803Smarcel td_init_p = verbose_dlsym (handle, "td_init"); 40798944Sobrien if (td_init_p == NULL) 40898944Sobrien return 0; 40998944Sobrien 410130803Smarcel td_ta_new_p = verbose_dlsym (handle, "td_ta_new"); 41198944Sobrien if (td_ta_new_p == NULL) 41298944Sobrien return 0; 41398944Sobrien 414130803Smarcel td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr"); 41598944Sobrien if (td_ta_map_id2thr_p == NULL) 41698944Sobrien return 0; 41798944Sobrien 418130803Smarcel td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr"); 41998944Sobrien if (td_ta_map_lwp2thr_p == NULL) 42098944Sobrien return 0; 42198944Sobrien 422130803Smarcel td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter"); 42398944Sobrien if (td_ta_thr_iter_p == NULL) 42498944Sobrien return 0; 42598944Sobrien 426130803Smarcel td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate"); 42798944Sobrien if (td_thr_validate_p == NULL) 42898944Sobrien return 0; 42998944Sobrien 430130803Smarcel td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info"); 43198944Sobrien if (td_thr_get_info_p == NULL) 43298944Sobrien return 0; 43398944Sobrien 434130803Smarcel td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs"); 43598944Sobrien if (td_thr_getfpregs_p == NULL) 43698944Sobrien return 0; 43798944Sobrien 438130803Smarcel td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs"); 43998944Sobrien if (td_thr_getgregs_p == NULL) 44098944Sobrien return 0; 44198944Sobrien 442130803Smarcel td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs"); 44398944Sobrien if (td_thr_setfpregs_p == NULL) 44498944Sobrien return 0; 44598944Sobrien 446130803Smarcel td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs"); 44798944Sobrien if (td_thr_setgregs_p == NULL) 44898944Sobrien return 0; 44998944Sobrien 45098944Sobrien /* Initialize the library. */ 45198944Sobrien err = td_init_p (); 45298944Sobrien if (err != TD_OK) 45398944Sobrien { 45498944Sobrien warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err)); 45598944Sobrien return 0; 45698944Sobrien } 45798944Sobrien 45898944Sobrien /* These are not essential. */ 45998944Sobrien td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); 46098944Sobrien td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); 46198944Sobrien td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); 46298944Sobrien td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); 463130803Smarcel td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); 46498944Sobrien 46598944Sobrien return 1; 46698944Sobrien} 46798944Sobrien 468130803Smarcelstatic td_err_e 469130803Smarcelenable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp) 470130803Smarcel{ 471130803Smarcel td_notify_t notify; 472130803Smarcel td_err_e err; 473130803Smarcel 474130803Smarcel /* Get the breakpoint address for thread EVENT. */ 475130803Smarcel err = td_ta_event_addr_p (thread_agent, event, ¬ify); 476130803Smarcel if (err != TD_OK) 477130803Smarcel return err; 478130803Smarcel 479130803Smarcel /* Set up the breakpoint. */ 480130803Smarcel (*bp) = gdbarch_convert_from_func_ptr_addr (current_gdbarch, 481130803Smarcel (CORE_ADDR) notify.u.bptaddr, 482130803Smarcel ¤t_target); 483130803Smarcel create_thread_event_breakpoint ((*bp)); 484130803Smarcel 485130803Smarcel return TD_OK; 486130803Smarcel} 487130803Smarcel 48898944Sobrienstatic void 48998944Sobrienenable_thread_event_reporting (void) 49098944Sobrien{ 49198944Sobrien td_thr_events_t events; 49298944Sobrien td_notify_t notify; 49398944Sobrien td_err_e err; 49498944Sobrien 49598944Sobrien /* We cannot use the thread event reporting facility if these 49698944Sobrien functions aren't available. */ 49798944Sobrien if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL 49898944Sobrien || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL) 49998944Sobrien return; 50098944Sobrien 50198944Sobrien /* Set the process wide mask saying which events we're interested in. */ 50298944Sobrien td_event_emptyset (&events); 50398944Sobrien td_event_addset (&events, TD_CREATE); 50498944Sobrien#if 0 50598944Sobrien /* FIXME: kettenis/2000-04-23: The event reporting facility is 50698944Sobrien broken for TD_DEATH events in glibc 2.1.3, so don't enable it for 50798944Sobrien now. */ 50898944Sobrien td_event_addset (&events, TD_DEATH); 50998944Sobrien#endif 51098944Sobrien 51198944Sobrien err = td_ta_set_event_p (thread_agent, &events); 51298944Sobrien if (err != TD_OK) 51398944Sobrien { 51498944Sobrien warning ("Unable to set global thread event mask: %s", 51598944Sobrien thread_db_err_str (err)); 51698944Sobrien return; 51798944Sobrien } 51898944Sobrien 51998944Sobrien /* Delete previous thread event breakpoints, if any. */ 52098944Sobrien remove_thread_event_breakpoints (); 521130803Smarcel td_create_bp_addr = 0; 522130803Smarcel td_death_bp_addr = 0; 52398944Sobrien 524130803Smarcel /* Set up the thread creation event. */ 525130803Smarcel err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr); 52698944Sobrien if (err != TD_OK) 52798944Sobrien { 52898944Sobrien warning ("Unable to get location for thread creation breakpoint: %s", 52998944Sobrien thread_db_err_str (err)); 53098944Sobrien return; 53198944Sobrien } 53298944Sobrien 533130803Smarcel /* Set up the thread death event. */ 534130803Smarcel err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr); 53598944Sobrien if (err != TD_OK) 53698944Sobrien { 53798944Sobrien warning ("Unable to get location for thread death breakpoint: %s", 53898944Sobrien thread_db_err_str (err)); 53998944Sobrien return; 54098944Sobrien } 54198944Sobrien} 54298944Sobrien 54398944Sobrienstatic void 54498944Sobriendisable_thread_event_reporting (void) 54598944Sobrien{ 54698944Sobrien td_thr_events_t events; 54798944Sobrien 54898944Sobrien /* Set the process wide mask saying we aren't interested in any 54998944Sobrien events anymore. */ 55098944Sobrien td_event_emptyset (&events); 55198944Sobrien td_ta_set_event_p (thread_agent, &events); 55298944Sobrien 55398944Sobrien /* Delete thread event breakpoints, if any. */ 55498944Sobrien remove_thread_event_breakpoints (); 55598944Sobrien td_create_bp_addr = 0; 55698944Sobrien td_death_bp_addr = 0; 55798944Sobrien} 55898944Sobrien 55998944Sobrienstatic void 56098944Sobriencheck_thread_signals (void) 56198944Sobrien{ 56298944Sobrien#ifdef GET_THREAD_SIGNALS 56398944Sobrien if (!thread_signals) 56498944Sobrien { 56598944Sobrien sigset_t mask; 56698944Sobrien int i; 56798944Sobrien 56898944Sobrien GET_THREAD_SIGNALS (&mask); 56998944Sobrien sigemptyset (&thread_stop_set); 57098944Sobrien sigemptyset (&thread_print_set); 57198944Sobrien 57298944Sobrien for (i = 1; i < NSIG; i++) 57398944Sobrien { 57498944Sobrien if (sigismember (&mask, i)) 57598944Sobrien { 57698944Sobrien if (signal_stop_update (target_signal_from_host (i), 0)) 57798944Sobrien sigaddset (&thread_stop_set, i); 57898944Sobrien if (signal_print_update (target_signal_from_host (i), 0)) 57998944Sobrien sigaddset (&thread_print_set, i); 58098944Sobrien thread_signals = 1; 58198944Sobrien } 58298944Sobrien } 58398944Sobrien } 58498944Sobrien#endif 58598944Sobrien} 58698944Sobrien 58798944Sobrienstatic void 58898944Sobrienthread_db_new_objfile (struct objfile *objfile) 58998944Sobrien{ 59098944Sobrien td_err_e err; 59198944Sobrien 592130803Smarcel /* First time through, report that libthread_db was successfuly 593130803Smarcel loaded. Can't print this in in thread_db_load as, at that stage, 594130803Smarcel the interpreter and it's console haven't started. The real 595130803Smarcel problem here is that libthread_db is loaded too early - it should 596130803Smarcel only be loaded when there is a program to debug. */ 597130803Smarcel { 598130803Smarcel static int dejavu; 599130803Smarcel if (!dejavu) 600130803Smarcel { 601130803Smarcel Dl_info info; 602130803Smarcel const char *library = NULL; 603130803Smarcel /* Try dladdr. */ 604130803Smarcel if (dladdr ((*td_ta_new_p), &info) != 0) 605130803Smarcel library = info.dli_fname; 606130803Smarcel /* Try dlinfo? */ 607130803Smarcel if (library == NULL) 608130803Smarcel /* Paranoid - don't let a NULL path slip through. */ 609130803Smarcel library = LIBTHREAD_DB_SO; 610130803Smarcel printf_unfiltered ("Using host libthread_db library \"%s\".\n", 611130803Smarcel library); 612130803Smarcel dejavu = 1; 613130803Smarcel } 614130803Smarcel } 615130803Smarcel 61698944Sobrien /* Don't attempt to use thread_db on targets which can not run 61798944Sobrien (core files). */ 61898944Sobrien if (objfile == NULL || !target_has_execution) 61998944Sobrien { 62098944Sobrien /* All symbols have been discarded. If the thread_db target is 62198944Sobrien active, deactivate it now. */ 62298944Sobrien if (using_thread_db) 62398944Sobrien { 62498944Sobrien gdb_assert (proc_handle.pid == 0); 62598944Sobrien unpush_target (&thread_db_ops); 62698944Sobrien using_thread_db = 0; 62798944Sobrien } 62898944Sobrien 62998944Sobrien keep_thread_db = 0; 63098944Sobrien 63198944Sobrien goto quit; 63298944Sobrien } 63398944Sobrien 63498944Sobrien if (using_thread_db) 63598944Sobrien /* Nothing to do. The thread library was already detected and the 63698944Sobrien target vector was already activated. */ 63798944Sobrien goto quit; 63898944Sobrien 63998944Sobrien /* Initialize the structure that identifies the child process. Note 64098944Sobrien that at this point there is no guarantee that we actually have a 64198944Sobrien child process. */ 64298944Sobrien proc_handle.pid = GET_PID (inferior_ptid); 64398944Sobrien 64498944Sobrien /* Now attempt to open a connection to the thread library. */ 64598944Sobrien err = td_ta_new_p (&proc_handle, &thread_agent); 64698944Sobrien switch (err) 64798944Sobrien { 64898944Sobrien case TD_NOLIBTHREAD: 64998944Sobrien /* No thread library was detected. */ 65098944Sobrien break; 65198944Sobrien 65298944Sobrien case TD_OK: 653130803Smarcel printf_unfiltered ("[Thread debugging using libthread_db enabled]\n"); 654130803Smarcel 65598944Sobrien /* The thread library was detected. Activate the thread_db target. */ 65698944Sobrien push_target (&thread_db_ops); 65798944Sobrien using_thread_db = 1; 65898944Sobrien 65998944Sobrien /* If the thread library was detected in the main symbol file 66098944Sobrien itself, we assume that the program was statically linked 66198944Sobrien against the thread library and well have to keep this 66298944Sobrien module's target vector activated until forever... Well, at 66398944Sobrien least until all symbols have been discarded anyway (see 66498944Sobrien above). */ 66598944Sobrien if (objfile == symfile_objfile) 66698944Sobrien { 66798944Sobrien gdb_assert (proc_handle.pid == 0); 66898944Sobrien keep_thread_db = 1; 66998944Sobrien } 67098944Sobrien 67198944Sobrien /* We can only poke around if there actually is a child process. 67298944Sobrien If there is no child process alive, postpone the steps below 67398944Sobrien until one has been created. */ 67498944Sobrien if (proc_handle.pid != 0) 67598944Sobrien { 67698944Sobrien enable_thread_event_reporting (); 67798944Sobrien thread_db_find_new_threads (); 67898944Sobrien } 67998944Sobrien break; 68098944Sobrien 68198944Sobrien default: 68298944Sobrien warning ("Cannot initialize thread debugging library: %s", 68398944Sobrien thread_db_err_str (err)); 68498944Sobrien break; 68598944Sobrien } 68698944Sobrien 687130803Smarcelquit: 68898944Sobrien if (target_new_objfile_chain) 68998944Sobrien target_new_objfile_chain (objfile); 69098944Sobrien} 69198944Sobrien 69298944Sobrienstatic void 69398944Sobrienattach_thread (ptid_t ptid, const td_thrhandle_t *th_p, 69498944Sobrien const td_thrinfo_t *ti_p, int verbose) 69598944Sobrien{ 69698944Sobrien struct thread_info *tp; 69798944Sobrien td_err_e err; 69898944Sobrien 69998944Sobrien check_thread_signals (); 70098944Sobrien 70198944Sobrien /* Add the thread to GDB's thread list. */ 70298944Sobrien tp = add_thread (ptid); 70398944Sobrien tp->private = xmalloc (sizeof (struct private_thread_info)); 704130803Smarcel memset (tp->private, 0, sizeof (struct private_thread_info)); 70598944Sobrien 706130803Smarcel if (verbose) 707130803Smarcel printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid)); 708130803Smarcel 70998944Sobrien if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) 71098944Sobrien return; /* A zombie thread -- do not attach. */ 71198944Sobrien 71298944Sobrien /* Under GNU/Linux, we have to attach to each and every thread. */ 71398944Sobrien#ifdef ATTACH_LWP 71498944Sobrien ATTACH_LWP (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)), 0); 71598944Sobrien#endif 71698944Sobrien 71798944Sobrien /* Enable thread event reporting for this thread. */ 71898944Sobrien err = td_thr_event_enable_p (th_p, 1); 71998944Sobrien if (err != TD_OK) 72098944Sobrien error ("Cannot enable thread event reporting for %s: %s", 72198944Sobrien target_pid_to_str (ptid), thread_db_err_str (err)); 72298944Sobrien} 72398944Sobrien 72498944Sobrienstatic void 72598944Sobrienthread_db_attach (char *args, int from_tty) 72698944Sobrien{ 72798944Sobrien target_beneath->to_attach (args, from_tty); 72898944Sobrien 72998944Sobrien /* Destroy thread info; it's no longer valid. */ 73098944Sobrien init_thread_list (); 73198944Sobrien 73298944Sobrien /* The child process is now the actual multi-threaded 73398944Sobrien program. Snatch its process ID... */ 73498944Sobrien proc_handle.pid = GET_PID (inferior_ptid); 73598944Sobrien 73698944Sobrien /* ...and perform the remaining initialization steps. */ 73798944Sobrien enable_thread_event_reporting (); 738130803Smarcel thread_db_find_new_threads (); 73998944Sobrien} 74098944Sobrien 74198944Sobrienstatic void 74298944Sobriendetach_thread (ptid_t ptid, int verbose) 74398944Sobrien{ 74498944Sobrien if (verbose) 74598944Sobrien printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid)); 74698944Sobrien} 74798944Sobrien 74898944Sobrienstatic void 74998944Sobrienthread_db_detach (char *args, int from_tty) 75098944Sobrien{ 75198944Sobrien disable_thread_event_reporting (); 75298944Sobrien 75398944Sobrien /* There's no need to save & restore inferior_ptid here, since the 75498944Sobrien inferior is supposed to be survive this function call. */ 75598944Sobrien inferior_ptid = lwp_from_thread (inferior_ptid); 75698944Sobrien 75798944Sobrien /* Forget about the child's process ID. We shouldn't need it 75898944Sobrien anymore. */ 75998944Sobrien proc_handle.pid = 0; 76098944Sobrien 76198944Sobrien target_beneath->to_detach (args, from_tty); 76298944Sobrien} 76398944Sobrien 764130803Smarcelstatic int 765130803Smarcelclear_lwpid_callback (struct thread_info *thread, void *dummy) 766130803Smarcel{ 767130803Smarcel /* If we know that our thread implementation is 1-to-1, we could save 768130803Smarcel a certain amount of information; it's not clear how much, so we 769130803Smarcel are always conservative. */ 770130803Smarcel 771130803Smarcel thread->private->th_valid = 0; 772130803Smarcel thread->private->ti_valid = 0; 773130803Smarcel 774130803Smarcel return 0; 775130803Smarcel} 776130803Smarcel 77798944Sobrienstatic void 77898944Sobrienthread_db_resume (ptid_t ptid, int step, enum target_signal signo) 77998944Sobrien{ 78098944Sobrien struct cleanup *old_chain = save_inferior_ptid (); 78198944Sobrien 78298944Sobrien if (GET_PID (ptid) == -1) 78398944Sobrien inferior_ptid = lwp_from_thread (inferior_ptid); 78498944Sobrien else if (is_thread (ptid)) 78598944Sobrien ptid = lwp_from_thread (ptid); 78698944Sobrien 787130803Smarcel /* Clear cached data which may not be valid after the resume. */ 788130803Smarcel iterate_over_threads (clear_lwpid_callback, NULL); 789130803Smarcel 79098944Sobrien target_beneath->to_resume (ptid, step, signo); 79198944Sobrien 79298944Sobrien do_cleanups (old_chain); 79398944Sobrien} 79498944Sobrien 79598944Sobrien/* Check if PID is currently stopped at the location of a thread event 79698944Sobrien breakpoint location. If it is, read the event message and act upon 79798944Sobrien the event. */ 79898944Sobrien 79998944Sobrienstatic void 80098944Sobriencheck_event (ptid_t ptid) 80198944Sobrien{ 80298944Sobrien td_event_msg_t msg; 80398944Sobrien td_thrinfo_t ti; 80498944Sobrien td_err_e err; 80598944Sobrien CORE_ADDR stop_pc; 806130803Smarcel int loop = 0; 80798944Sobrien 80898944Sobrien /* Bail out early if we're not at a thread event breakpoint. */ 80998944Sobrien stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK; 81098944Sobrien if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) 81198944Sobrien return; 81298944Sobrien 813130803Smarcel /* If we are at a create breakpoint, we do not know what new lwp 814130803Smarcel was created and cannot specifically locate the event message for it. 815130803Smarcel We have to call td_ta_event_getmsg() to get 816130803Smarcel the latest message. Since we have no way of correlating whether 817130803Smarcel the event message we get back corresponds to our breakpoint, we must 818130803Smarcel loop and read all event messages, processing them appropriately. 819130803Smarcel This guarantees we will process the correct message before continuing 820130803Smarcel from the breakpoint. 821130803Smarcel 822130803Smarcel Currently, death events are not enabled. If they are enabled, 823130803Smarcel the death event can use the td_thr_event_getmsg() interface to 824130803Smarcel get the message specifically for that lwp and avoid looping 825130803Smarcel below. */ 826130803Smarcel 827130803Smarcel loop = 1; 828130803Smarcel 829130803Smarcel do 83098944Sobrien { 831130803Smarcel err = td_ta_event_getmsg_p (thread_agent, &msg); 832130803Smarcel if (err != TD_OK) 833130803Smarcel { 834130803Smarcel if (err == TD_NOMSG) 835130803Smarcel return; 83698944Sobrien 837130803Smarcel error ("Cannot get thread event message: %s", 838130803Smarcel thread_db_err_str (err)); 839130803Smarcel } 84098944Sobrien 841130803Smarcel err = td_thr_get_info_p (msg.th_p, &ti); 842130803Smarcel if (err != TD_OK) 843130803Smarcel error ("Cannot get thread info: %s", thread_db_err_str (err)); 84498944Sobrien 845130803Smarcel ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); 84698944Sobrien 847130803Smarcel switch (msg.event) 848130803Smarcel { 849130803Smarcel case TD_CREATE: 85098944Sobrien 851130803Smarcel /* We may already know about this thread, for instance when the 852130803Smarcel user has issued the `info threads' command before the SIGTRAP 853130803Smarcel for hitting the thread creation breakpoint was reported. */ 854130803Smarcel if (!in_thread_list (ptid)) 855130803Smarcel attach_thread (ptid, msg.th_p, &ti, 1); 85698944Sobrien 857130803Smarcel break; 85898944Sobrien 859130803Smarcel case TD_DEATH: 86098944Sobrien 861130803Smarcel if (!in_thread_list (ptid)) 862130803Smarcel error ("Spurious thread death event."); 86398944Sobrien 864130803Smarcel detach_thread (ptid, 1); 86598944Sobrien 866130803Smarcel break; 86798944Sobrien 868130803Smarcel default: 869130803Smarcel error ("Spurious thread event."); 870130803Smarcel } 87198944Sobrien } 872130803Smarcel while (loop); 87398944Sobrien} 87498944Sobrien 87598944Sobrienstatic ptid_t 87698944Sobrienthread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 87798944Sobrien{ 87898944Sobrien extern ptid_t trap_ptid; 87998944Sobrien 88098944Sobrien if (GET_PID (ptid) != -1 && is_thread (ptid)) 88198944Sobrien ptid = lwp_from_thread (ptid); 88298944Sobrien 88398944Sobrien ptid = target_beneath->to_wait (ptid, ourstatus); 88498944Sobrien 88598944Sobrien if (proc_handle.pid == 0) 88698944Sobrien /* The current child process isn't the actual multi-threaded 88798944Sobrien program yet, so don't try to do any special thread-specific 88898944Sobrien post-processing and bail out early. */ 88998944Sobrien return ptid; 89098944Sobrien 89198944Sobrien if (ourstatus->kind == TARGET_WAITKIND_EXITED) 89298944Sobrien return pid_to_ptid (-1); 89398944Sobrien 89498944Sobrien if (ourstatus->kind == TARGET_WAITKIND_STOPPED 89598944Sobrien && ourstatus->value.sig == TARGET_SIGNAL_TRAP) 89698944Sobrien /* Check for a thread event. */ 89798944Sobrien check_event (ptid); 89898944Sobrien 89998944Sobrien if (!ptid_equal (trap_ptid, null_ptid)) 90098944Sobrien trap_ptid = thread_from_lwp (trap_ptid); 90198944Sobrien 90298944Sobrien return thread_from_lwp (ptid); 90398944Sobrien} 90498944Sobrien 90598944Sobrienstatic int 90698944Sobrienthread_db_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, 907130803Smarcel struct mem_attrib *attrib, struct target_ops *target) 90898944Sobrien{ 90998944Sobrien struct cleanup *old_chain = save_inferior_ptid (); 91098944Sobrien int xfer; 91198944Sobrien 91298944Sobrien if (is_thread (inferior_ptid)) 91398944Sobrien { 91498944Sobrien /* FIXME: This seems to be necessary to make sure breakpoints 91598944Sobrien are removed. */ 91698944Sobrien if (!target_thread_alive (inferior_ptid)) 91798944Sobrien inferior_ptid = pid_to_ptid (GET_PID (inferior_ptid)); 91898944Sobrien else 91998944Sobrien inferior_ptid = lwp_from_thread (inferior_ptid); 92098944Sobrien } 92198944Sobrien 922130803Smarcel xfer = 923130803Smarcel target_beneath->to_xfer_memory (memaddr, myaddr, len, write, attrib, 924130803Smarcel target); 92598944Sobrien 92698944Sobrien do_cleanups (old_chain); 92798944Sobrien return xfer; 92898944Sobrien} 92998944Sobrien 93098944Sobrienstatic void 93198944Sobrienthread_db_fetch_registers (int regno) 93298944Sobrien{ 933130803Smarcel struct thread_info *thread_info; 93498944Sobrien prgregset_t gregset; 93598944Sobrien gdb_prfpregset_t fpregset; 93698944Sobrien td_err_e err; 93798944Sobrien 93898944Sobrien if (!is_thread (inferior_ptid)) 93998944Sobrien { 94098944Sobrien /* Pass the request to the target beneath us. */ 94198944Sobrien target_beneath->to_fetch_registers (regno); 94298944Sobrien return; 94398944Sobrien } 94498944Sobrien 945130803Smarcel thread_info = find_thread_pid (inferior_ptid); 946130803Smarcel thread_db_map_id2thr (thread_info, 1); 94798944Sobrien 948130803Smarcel err = td_thr_getgregs_p (&thread_info->private->th, gregset); 94998944Sobrien if (err != TD_OK) 95098944Sobrien error ("Cannot fetch general-purpose registers for thread %ld: %s", 95198944Sobrien (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); 95298944Sobrien 953130803Smarcel err = td_thr_getfpregs_p (&thread_info->private->th, &fpregset); 95498944Sobrien if (err != TD_OK) 95598944Sobrien error ("Cannot get floating-point registers for thread %ld: %s", 95698944Sobrien (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); 95798944Sobrien 95898944Sobrien /* Note that we must call supply_gregset after calling the thread_db 95998944Sobrien routines because the thread_db routines call ps_lgetgregs and 96098944Sobrien friends which clobber GDB's register cache. */ 96198944Sobrien supply_gregset ((gdb_gregset_t *) gregset); 96298944Sobrien supply_fpregset (&fpregset); 96398944Sobrien} 96498944Sobrien 96598944Sobrienstatic void 96698944Sobrienthread_db_store_registers (int regno) 96798944Sobrien{ 96898944Sobrien prgregset_t gregset; 96998944Sobrien gdb_prfpregset_t fpregset; 97098944Sobrien td_err_e err; 971130803Smarcel struct thread_info *thread_info; 97298944Sobrien 97398944Sobrien if (!is_thread (inferior_ptid)) 97498944Sobrien { 97598944Sobrien /* Pass the request to the target beneath us. */ 97698944Sobrien target_beneath->to_store_registers (regno); 97798944Sobrien return; 97898944Sobrien } 97998944Sobrien 980130803Smarcel thread_info = find_thread_pid (inferior_ptid); 981130803Smarcel thread_db_map_id2thr (thread_info, 1); 98298944Sobrien 98398944Sobrien if (regno != -1) 98498944Sobrien { 985130803Smarcel char raw[MAX_REGISTER_SIZE]; 98698944Sobrien 987130803Smarcel deprecated_read_register_gen (regno, raw); 98898944Sobrien thread_db_fetch_registers (-1); 98998944Sobrien supply_register (regno, raw); 99098944Sobrien } 99198944Sobrien 99298944Sobrien fill_gregset ((gdb_gregset_t *) gregset, -1); 99398944Sobrien fill_fpregset (&fpregset, -1); 99498944Sobrien 995130803Smarcel err = td_thr_setgregs_p (&thread_info->private->th, gregset); 99698944Sobrien if (err != TD_OK) 99798944Sobrien error ("Cannot store general-purpose registers for thread %ld: %s", 99898944Sobrien (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); 999130803Smarcel err = td_thr_setfpregs_p (&thread_info->private->th, &fpregset); 100098944Sobrien if (err != TD_OK) 100198944Sobrien error ("Cannot store floating-point registers for thread %ld: %s", 100298944Sobrien (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); 100398944Sobrien} 100498944Sobrien 100598944Sobrienstatic void 100698944Sobrienthread_db_kill (void) 100798944Sobrien{ 100898944Sobrien /* There's no need to save & restore inferior_ptid here, since the 100998944Sobrien inferior isn't supposed to survive this function call. */ 101098944Sobrien inferior_ptid = lwp_from_thread (inferior_ptid); 101198944Sobrien target_beneath->to_kill (); 101298944Sobrien} 101398944Sobrien 101498944Sobrienstatic void 101598944Sobrienthread_db_create_inferior (char *exec_file, char *allargs, char **env) 101698944Sobrien{ 101798944Sobrien if (!keep_thread_db) 101898944Sobrien { 101998944Sobrien unpush_target (&thread_db_ops); 102098944Sobrien using_thread_db = 0; 102198944Sobrien } 102298944Sobrien 102398944Sobrien target_beneath->to_create_inferior (exec_file, allargs, env); 102498944Sobrien} 102598944Sobrien 102698944Sobrienstatic void 102798944Sobrienthread_db_post_startup_inferior (ptid_t ptid) 102898944Sobrien{ 102998944Sobrien if (proc_handle.pid == 0) 103098944Sobrien { 103198944Sobrien /* The child process is now the actual multi-threaded 103298944Sobrien program. Snatch its process ID... */ 103398944Sobrien proc_handle.pid = GET_PID (ptid); 103498944Sobrien 103598944Sobrien /* ...and perform the remaining initialization steps. */ 103698944Sobrien enable_thread_event_reporting (); 103798944Sobrien thread_db_find_new_threads (); 103898944Sobrien } 103998944Sobrien} 104098944Sobrien 104198944Sobrienstatic void 104298944Sobrienthread_db_mourn_inferior (void) 104398944Sobrien{ 104498944Sobrien remove_thread_event_breakpoints (); 104598944Sobrien 104698944Sobrien /* Forget about the child's process ID. We shouldn't need it 104798944Sobrien anymore. */ 104898944Sobrien proc_handle.pid = 0; 104998944Sobrien 105098944Sobrien target_beneath->to_mourn_inferior (); 1051130803Smarcel 1052130803Smarcel /* Detach thread_db target ops if not dealing with a statically 1053130803Smarcel linked threaded program. This allows a corefile to be debugged 1054130803Smarcel after finishing debugging of a threaded program. At present, 1055130803Smarcel debugging a statically-linked threaded program is broken, but 1056130803Smarcel the check is added below in the event that it is fixed in the 1057130803Smarcel future. */ 1058130803Smarcel if (!keep_thread_db) 1059130803Smarcel { 1060130803Smarcel unpush_target (&thread_db_ops); 1061130803Smarcel using_thread_db = 0; 1062130803Smarcel } 106398944Sobrien} 106498944Sobrien 106598944Sobrienstatic int 106698944Sobrienthread_db_thread_alive (ptid_t ptid) 106798944Sobrien{ 106898944Sobrien td_thrhandle_t th; 106998944Sobrien td_err_e err; 107098944Sobrien 107198944Sobrien if (is_thread (ptid)) 107298944Sobrien { 1073130803Smarcel struct thread_info *thread_info; 1074130803Smarcel thread_info = find_thread_pid (ptid); 107598944Sobrien 1076130803Smarcel thread_db_map_id2thr (thread_info, 0); 1077130803Smarcel if (!thread_info->private->th_valid) 107898944Sobrien return 0; 107998944Sobrien 1080130803Smarcel err = td_thr_validate_p (&thread_info->private->th); 108198944Sobrien if (err != TD_OK) 108298944Sobrien return 0; 108398944Sobrien 1084130803Smarcel if (!thread_info->private->ti_valid) 1085130803Smarcel { 1086130803Smarcel err = 1087130803Smarcel td_thr_get_info_p (&thread_info->private->th, 1088130803Smarcel &thread_info->private->ti); 1089130803Smarcel if (err != TD_OK) 1090130803Smarcel return 0; 1091130803Smarcel thread_info->private->ti_valid = 1; 1092130803Smarcel } 1093130803Smarcel 1094130803Smarcel if (thread_info->private->ti.ti_state == TD_THR_UNKNOWN 1095130803Smarcel || thread_info->private->ti.ti_state == TD_THR_ZOMBIE) 109698944Sobrien return 0; /* A zombie thread. */ 109798944Sobrien 109898944Sobrien return 1; 109998944Sobrien } 110098944Sobrien 110198944Sobrien if (target_beneath->to_thread_alive) 110298944Sobrien return target_beneath->to_thread_alive (ptid); 110398944Sobrien 110498944Sobrien return 0; 110598944Sobrien} 110698944Sobrien 110798944Sobrienstatic int 110898944Sobrienfind_new_threads_callback (const td_thrhandle_t *th_p, void *data) 110998944Sobrien{ 111098944Sobrien td_thrinfo_t ti; 111198944Sobrien td_err_e err; 111298944Sobrien ptid_t ptid; 111398944Sobrien 111498944Sobrien err = td_thr_get_info_p (th_p, &ti); 111598944Sobrien if (err != TD_OK) 1116130803Smarcel error ("find_new_threads_callback: cannot get thread info: %s", 1117130803Smarcel thread_db_err_str (err)); 111898944Sobrien 111998944Sobrien if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) 112098944Sobrien return 0; /* A zombie -- ignore. */ 112198944Sobrien 112298944Sobrien ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid)); 112398944Sobrien 112498944Sobrien if (!in_thread_list (ptid)) 112598944Sobrien attach_thread (ptid, th_p, &ti, 1); 112698944Sobrien 112798944Sobrien return 0; 112898944Sobrien} 112998944Sobrien 113098944Sobrienstatic void 113198944Sobrienthread_db_find_new_threads (void) 113298944Sobrien{ 113398944Sobrien td_err_e err; 113498944Sobrien 113598944Sobrien /* Iterate over all user-space threads to discover new threads. */ 113698944Sobrien err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL, 113798944Sobrien TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 113898944Sobrien TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 113998944Sobrien if (err != TD_OK) 114098944Sobrien error ("Cannot find new threads: %s", thread_db_err_str (err)); 114198944Sobrien} 114298944Sobrien 114398944Sobrienstatic char * 114498944Sobrienthread_db_pid_to_str (ptid_t ptid) 114598944Sobrien{ 114698944Sobrien if (is_thread (ptid)) 114798944Sobrien { 114898944Sobrien static char buf[64]; 1149130803Smarcel td_thrinfo_t *ti_p; 115098944Sobrien td_err_e err; 1151130803Smarcel struct thread_info *thread_info; 115298944Sobrien 1153130803Smarcel thread_info = find_thread_pid (ptid); 1154130803Smarcel thread_db_map_id2thr (thread_info, 0); 1155130803Smarcel if (!thread_info->private->th_valid) 1156130803Smarcel { 1157130803Smarcel snprintf (buf, sizeof (buf), "Thread %ld (Missing)", 1158130803Smarcel GET_THREAD (ptid)); 1159130803Smarcel return buf; 1160130803Smarcel } 116198944Sobrien 1162130803Smarcel ti_p = thread_db_get_info (thread_info); 116398944Sobrien 1164130803Smarcel if (ti_p->ti_state == TD_THR_ACTIVE && ti_p->ti_lid != 0) 116598944Sobrien { 116698944Sobrien snprintf (buf, sizeof (buf), "Thread %ld (LWP %d)", 1167130803Smarcel (long) ti_p->ti_tid, ti_p->ti_lid); 116898944Sobrien } 116998944Sobrien else 117098944Sobrien { 117198944Sobrien snprintf (buf, sizeof (buf), "Thread %ld (%s)", 1172130803Smarcel (long) ti_p->ti_tid, 1173130803Smarcel thread_db_state_str (ti_p->ti_state)); 117498944Sobrien } 117598944Sobrien 117698944Sobrien return buf; 117798944Sobrien } 117898944Sobrien 117998944Sobrien if (target_beneath->to_pid_to_str (ptid)) 118098944Sobrien return target_beneath->to_pid_to_str (ptid); 118198944Sobrien 118298944Sobrien return normal_pid_to_str (ptid); 118398944Sobrien} 118498944Sobrien 1185130803Smarcel/* Get the address of the thread local variable in OBJFILE which is 1186130803Smarcel stored at OFFSET within the thread local storage for thread PTID. */ 1187130803Smarcel 1188130803Smarcelstatic CORE_ADDR 1189130803Smarcelthread_db_get_thread_local_address (ptid_t ptid, struct objfile *objfile, 1190130803Smarcel CORE_ADDR offset) 1191130803Smarcel{ 1192130803Smarcel if (is_thread (ptid)) 1193130803Smarcel { 1194130803Smarcel int objfile_is_library = (objfile->flags & OBJF_SHARED); 1195130803Smarcel td_err_e err; 1196130803Smarcel void *address; 1197130803Smarcel CORE_ADDR lm; 1198130803Smarcel struct thread_info *thread_info; 1199130803Smarcel 1200130803Smarcel /* glibc doesn't provide the needed interface. */ 1201130803Smarcel if (!td_thr_tls_get_addr_p) 1202130803Smarcel error ("Cannot find thread-local variables in this thread library."); 1203130803Smarcel 1204130803Smarcel /* Get the address of the link map for this objfile. */ 1205130803Smarcel lm = svr4_fetch_objfile_link_map (objfile); 1206130803Smarcel 1207130803Smarcel /* Whoops, we couldn't find one. Bail out. */ 1208130803Smarcel if (!lm) 1209130803Smarcel { 1210130803Smarcel if (objfile_is_library) 1211130803Smarcel error ("Cannot find shared library `%s' link_map in dynamic" 1212130803Smarcel " linker's module list", objfile->name); 1213130803Smarcel else 1214130803Smarcel error ("Cannot find executable file `%s' link_map in dynamic" 1215130803Smarcel " linker's module list", objfile->name); 1216130803Smarcel } 1217130803Smarcel 1218130803Smarcel /* Get info about the thread. */ 1219130803Smarcel thread_info = find_thread_pid (ptid); 1220130803Smarcel thread_db_map_id2thr (thread_info, 1); 1221130803Smarcel 1222130803Smarcel /* Finally, get the address of the variable. */ 1223130803Smarcel err = td_thr_tls_get_addr_p (&thread_info->private->th, (void *) lm, 1224130803Smarcel offset, &address); 1225130803Smarcel 1226130803Smarcel#ifdef THREAD_DB_HAS_TD_NOTALLOC 1227130803Smarcel /* The memory hasn't been allocated, yet. */ 1228130803Smarcel if (err == TD_NOTALLOC) 1229130803Smarcel { 1230130803Smarcel /* Now, if libthread_db provided the initialization image's 1231130803Smarcel address, we *could* try to build a non-lvalue value from 1232130803Smarcel the initialization image. */ 1233130803Smarcel if (objfile_is_library) 1234130803Smarcel error ("The inferior has not yet allocated storage for" 1235130803Smarcel " thread-local variables in\n" 1236130803Smarcel "the shared library `%s'\n" 1237130803Smarcel "for the thread %ld", 1238130803Smarcel objfile->name, (long) GET_THREAD (ptid)); 1239130803Smarcel else 1240130803Smarcel error ("The inferior has not yet allocated storage for" 1241130803Smarcel " thread-local variables in\n" 1242130803Smarcel "the executable `%s'\n" 1243130803Smarcel "for the thread %ld", 1244130803Smarcel objfile->name, (long) GET_THREAD (ptid)); 1245130803Smarcel } 1246130803Smarcel#endif 1247130803Smarcel 1248130803Smarcel /* Something else went wrong. */ 1249130803Smarcel if (err != TD_OK) 1250130803Smarcel { 1251130803Smarcel if (objfile_is_library) 1252130803Smarcel error ("Cannot find thread-local storage for thread %ld, " 1253130803Smarcel "shared library %s:\n%s", 1254130803Smarcel (long) GET_THREAD (ptid), 1255130803Smarcel objfile->name, thread_db_err_str (err)); 1256130803Smarcel else 1257130803Smarcel error ("Cannot find thread-local storage for thread %ld, " 1258130803Smarcel "executable file %s:\n%s", 1259130803Smarcel (long) GET_THREAD (ptid), 1260130803Smarcel objfile->name, thread_db_err_str (err)); 1261130803Smarcel } 1262130803Smarcel 1263130803Smarcel /* Cast assuming host == target. Joy. */ 1264130803Smarcel return (CORE_ADDR) address; 1265130803Smarcel } 1266130803Smarcel 1267130803Smarcel if (target_beneath->to_get_thread_local_address) 1268130803Smarcel return target_beneath->to_get_thread_local_address (ptid, objfile, 1269130803Smarcel offset); 1270130803Smarcel 1271130803Smarcel error ("Cannot find thread-local values on this target."); 1272130803Smarcel} 1273130803Smarcel 127498944Sobrienstatic void 127598944Sobrieninit_thread_db_ops (void) 127698944Sobrien{ 127798944Sobrien thread_db_ops.to_shortname = "multi-thread"; 127898944Sobrien thread_db_ops.to_longname = "multi-threaded child process."; 127998944Sobrien thread_db_ops.to_doc = "Threads and pthreads support."; 128098944Sobrien thread_db_ops.to_attach = thread_db_attach; 128198944Sobrien thread_db_ops.to_detach = thread_db_detach; 128298944Sobrien thread_db_ops.to_resume = thread_db_resume; 128398944Sobrien thread_db_ops.to_wait = thread_db_wait; 128498944Sobrien thread_db_ops.to_fetch_registers = thread_db_fetch_registers; 128598944Sobrien thread_db_ops.to_store_registers = thread_db_store_registers; 128698944Sobrien thread_db_ops.to_xfer_memory = thread_db_xfer_memory; 128798944Sobrien thread_db_ops.to_kill = thread_db_kill; 128898944Sobrien thread_db_ops.to_create_inferior = thread_db_create_inferior; 128998944Sobrien thread_db_ops.to_post_startup_inferior = thread_db_post_startup_inferior; 129098944Sobrien thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior; 129198944Sobrien thread_db_ops.to_thread_alive = thread_db_thread_alive; 129298944Sobrien thread_db_ops.to_find_new_threads = thread_db_find_new_threads; 129398944Sobrien thread_db_ops.to_pid_to_str = thread_db_pid_to_str; 129498944Sobrien thread_db_ops.to_stratum = thread_stratum; 129598944Sobrien thread_db_ops.to_has_thread_control = tc_schedlock; 1296130803Smarcel thread_db_ops.to_get_thread_local_address 1297130803Smarcel = thread_db_get_thread_local_address; 129898944Sobrien thread_db_ops.to_magic = OPS_MAGIC; 129998944Sobrien} 130098944Sobrien 130198944Sobrienvoid 130298944Sobrien_initialize_thread_db (void) 130398944Sobrien{ 130498944Sobrien /* Only initialize the module if we can load libthread_db. */ 130598944Sobrien if (thread_db_load ()) 130698944Sobrien { 130798944Sobrien init_thread_db_ops (); 130898944Sobrien add_target (&thread_db_ops); 130998944Sobrien 131098944Sobrien /* Add ourselves to objfile event chain. */ 131198944Sobrien target_new_objfile_chain = target_new_objfile_hook; 131298944Sobrien target_new_objfile_hook = thread_db_new_objfile; 131398944Sobrien } 131498944Sobrien} 1315