1132179Sdavidxu/* $FreeBSD$ */ 2132179Sdavidxu/* FreeBSD libthread_db assisted debugging support. 3132179Sdavidxu Copyright 1999, 2000, 2001 Free Software Foundation, Inc. 4132179Sdavidxu 5132179Sdavidxu This file is part of GDB. 6132179Sdavidxu 7132179Sdavidxu This program is free software; you can redistribute it and/or modify 8132179Sdavidxu it under the terms of the GNU General Public License as published by 9132179Sdavidxu the Free Software Foundation; either version 2 of the License, or 10132179Sdavidxu (at your option) any later version. 11132179Sdavidxu 12132179Sdavidxu This program is distributed in the hope that it will be useful, 13132179Sdavidxu but WITHOUT ANY WARRANTY; without even the implied warranty of 14132179Sdavidxu MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15132179Sdavidxu GNU General Public License for more details. 16132179Sdavidxu 17132179Sdavidxu You should have received a copy of the GNU General Public License 18132179Sdavidxu along with this program; if not, write to the Free Software 19132179Sdavidxu Foundation, Inc., 59 Temple Place - Suite 330, 20132179Sdavidxu Boston, MA 02111-1307, USA. */ 21132179Sdavidxu 22134147Sdavidxu#include <dlfcn.h> 23134147Sdavidxu#include <sys/types.h> 24134147Sdavidxu#include <sys/ptrace.h> 25155379Sdavidxu#include <signal.h> 26132179Sdavidxu 27132179Sdavidxu#include "proc_service.h" 28132179Sdavidxu#include "thread_db.h" 29132179Sdavidxu 30134147Sdavidxu#include "defs.h" 31132179Sdavidxu#include "bfd.h" 32134147Sdavidxu#include "elf-bfd.h" 33134147Sdavidxu#include "gdb_assert.h" 34134147Sdavidxu#include "gdbcore.h" 35132179Sdavidxu#include "gdbthread.h" 36132179Sdavidxu#include "inferior.h" 37134147Sdavidxu#include "objfiles.h" 38134147Sdavidxu#include "regcache.h" 39132179Sdavidxu#include "symfile.h" 40132179Sdavidxu#include "symtab.h" 41132179Sdavidxu#include "target.h" 42132179Sdavidxu#include "gdbcmd.h" 43133345Sdavidxu#include "solib-svr4.h" 44132179Sdavidxu 45218822Sdim#include "gregset.h" 46218822Sdim#ifdef PT_GETXMMREGS 47218822Sdim#include "i387-tdep.h" 48218822Sdim#endif 49132179Sdavidxu 50132179Sdavidxu#define LIBTHREAD_DB_SO "libthread_db.so" 51132179Sdavidxu 52132179Sdavidxustruct ps_prochandle 53132179Sdavidxu{ 54132179Sdavidxu pid_t pid; 55132179Sdavidxu}; 56132179Sdavidxu 57134147Sdavidxuextern int child_suppress_run; 58134147Sdavidxu 59132179Sdavidxuextern struct target_ops child_ops; 60132179Sdavidxu 61134152Sdavidxu/* This module's target vectors. */ 62134147Sdavidxustatic struct target_ops fbsd_thread_ops; 63134147Sdavidxustatic struct target_ops fbsd_core_ops; 64132179Sdavidxu 65134147Sdavidxu/* Saved copy of orignal core_ops. */ 66134147Sdavidxustatic struct target_ops orig_core_ops; 67134147Sdavidxuextern struct target_ops core_ops; 68134147Sdavidxu 69132179Sdavidxu/* Pointer to the next function on the objfile event chain. */ 70132179Sdavidxustatic void (*target_new_objfile_chain) (struct objfile *objfile); 71132179Sdavidxu 72134147Sdavidxu/* Non-zero if there is a thread module */ 73134147Sdavidxustatic int fbsd_thread_present; 74134147Sdavidxu 75132179Sdavidxu/* Non-zero if we're using this module's target vector. */ 76134147Sdavidxustatic int fbsd_thread_active; 77132179Sdavidxu 78134147Sdavidxu/* Non-zero if core_open is called */ 79134147Sdavidxustatic int fbsd_thread_core = 0; 80134147Sdavidxu 81132179Sdavidxu/* Non-zero if we have to keep this module's target vector active 82132179Sdavidxu across re-runs. */ 83132179Sdavidxustatic int keep_thread_db; 84132179Sdavidxu 85132179Sdavidxu/* Structure that identifies the child process for the 86132179Sdavidxu <proc_service.h> interface. */ 87132179Sdavidxustatic struct ps_prochandle proc_handle; 88132179Sdavidxu 89132179Sdavidxu/* Connection to the libthread_db library. */ 90132179Sdavidxustatic td_thragent_t *thread_agent; 91132179Sdavidxu 92132179Sdavidxu/* The last thread we are single stepping */ 93132179Sdavidxustatic ptid_t last_single_step_thread; 94132179Sdavidxu 95132179Sdavidxu/* Pointers to the libthread_db functions. */ 96132179Sdavidxu 97132179Sdavidxustatic td_err_e (*td_init_p) (void); 98132179Sdavidxu 99132179Sdavidxustatic td_err_e (*td_ta_new_p) (struct ps_prochandle *ps, td_thragent_t **ta); 100134147Sdavidxustatic td_err_e (*td_ta_delete_p) (td_thragent_t *); 101132179Sdavidxustatic td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, 102132179Sdavidxu td_thrhandle_t *__th); 103132179Sdavidxustatic td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, lwpid_t lwpid, 104132179Sdavidxu td_thrhandle_t *th); 105132179Sdavidxustatic td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, 106132179Sdavidxu td_thr_iter_f *callback, 107132179Sdavidxu void *cbdata_p, td_thr_state_e state, 108132179Sdavidxu int ti_pri, sigset_t *ti_sigmask_p, 109132179Sdavidxu unsigned int ti_user_flags); 110132179Sdavidxustatic td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, 111132179Sdavidxu td_event_e event, td_notify_t *ptr); 112132179Sdavidxustatic td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, 113132179Sdavidxu td_thr_events_t *event); 114132179Sdavidxustatic td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, 115132179Sdavidxu td_event_msg_t *msg); 116132179Sdavidxustatic td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, 117132179Sdavidxu td_thrinfo_t *infop); 118146818Sdfr#ifdef PT_GETXMMREGS 119146818Sdfrstatic td_err_e (*td_thr_getxmmregs_p) (const td_thrhandle_t *th, 120146818Sdfr char *regset); 121146818Sdfr#endif 122132179Sdavidxustatic td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, 123132179Sdavidxu prfpregset_t *regset); 124132179Sdavidxustatic td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, 125132179Sdavidxu prgregset_t gregs); 126146818Sdfr#ifdef PT_GETXMMREGS 127146818Sdfrstatic td_err_e (*td_thr_setxmmregs_p) (const td_thrhandle_t *th, 128146818Sdfr const char *fpregs); 129146818Sdfr#endif 130132179Sdavidxustatic td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, 131132179Sdavidxu const prfpregset_t *fpregs); 132132179Sdavidxustatic td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, 133132179Sdavidxu prgregset_t gregs); 134132179Sdavidxustatic td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, int event); 135132179Sdavidxu 136132179Sdavidxustatic td_err_e (*td_thr_sstep_p) (td_thrhandle_t *th, int step); 137132179Sdavidxu 138132179Sdavidxustatic td_err_e (*td_ta_tsd_iter_p) (const td_thragent_t *ta, 139132179Sdavidxu td_key_iter_f *func, void *data); 140133345Sdavidxustatic td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, 141133345Sdavidxu void *map_address, 142133345Sdavidxu size_t offset, void **address); 143132179Sdavidxustatic td_err_e (*td_thr_dbsuspend_p) (const td_thrhandle_t *); 144132179Sdavidxustatic td_err_e (*td_thr_dbresume_p) (const td_thrhandle_t *); 145132179Sdavidxu 146144923Sdavidxustatic CORE_ADDR td_create_bp_addr; 147144923Sdavidxu 148144923Sdavidxu/* Location of the thread death event breakpoint. */ 149144923Sdavidxustatic CORE_ADDR td_death_bp_addr; 150144923Sdavidxu 151132179Sdavidxu/* Prototypes for local functions. */ 152132179Sdavidxustatic void fbsd_thread_find_new_threads (void); 153133345Sdavidxustatic int fbsd_thread_alive (ptid_t ptid); 154144923Sdavidxustatic void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, 155144923Sdavidxu const td_thrinfo_t *ti_p, int verbose); 156144923Sdavidxustatic void fbsd_thread_detach (char *args, int from_tty); 157132179Sdavidxu 158132179Sdavidxu/* Building process ids. */ 159132179Sdavidxu 160132179Sdavidxu#define GET_PID(ptid) ptid_get_pid (ptid) 161132179Sdavidxu#define GET_LWP(ptid) ptid_get_lwp (ptid) 162132179Sdavidxu#define GET_THREAD(ptid) ptid_get_tid (ptid) 163132179Sdavidxu 164132179Sdavidxu#define IS_LWP(ptid) (GET_LWP (ptid) != 0) 165132179Sdavidxu#define IS_THREAD(ptid) (GET_THREAD (ptid) != 0) 166132179Sdavidxu 167132179Sdavidxu#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0) 168132179Sdavidxu#define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid) 169132179Sdavidxu 170132179Sdavidxustatic char * 171132179Sdavidxuthread_db_err_str (td_err_e err) 172132179Sdavidxu{ 173132179Sdavidxu static char buf[64]; 174132179Sdavidxu 175132179Sdavidxu switch (err) 176132179Sdavidxu { 177132179Sdavidxu case TD_OK: 178132179Sdavidxu return "generic 'call succeeded'"; 179132179Sdavidxu case TD_ERR: 180132179Sdavidxu return "generic error"; 181132179Sdavidxu case TD_NOTHR: 182132179Sdavidxu return "no thread to satisfy query"; 183132179Sdavidxu case TD_NOSV: 184132179Sdavidxu return "no sync handle to satisfy query"; 185132179Sdavidxu case TD_NOLWP: 186132179Sdavidxu return "no LWP to satisfy query"; 187132179Sdavidxu case TD_BADPH: 188132179Sdavidxu return "invalid process handle"; 189132179Sdavidxu case TD_BADTH: 190132179Sdavidxu return "invalid thread handle"; 191132179Sdavidxu case TD_BADSH: 192132179Sdavidxu return "invalid synchronization handle"; 193132179Sdavidxu case TD_BADTA: 194132179Sdavidxu return "invalid thread agent"; 195132179Sdavidxu case TD_BADKEY: 196132179Sdavidxu return "invalid key"; 197132179Sdavidxu case TD_NOMSG: 198132179Sdavidxu return "no event message for getmsg"; 199132179Sdavidxu case TD_NOFPREGS: 200132179Sdavidxu return "FPU register set not available"; 201132179Sdavidxu case TD_NOLIBTHREAD: 202132179Sdavidxu return "application not linked with libthread"; 203132179Sdavidxu case TD_NOEVENT: 204132179Sdavidxu return "requested event is not supported"; 205132179Sdavidxu case TD_NOCAPAB: 206132179Sdavidxu return "capability not available"; 207132179Sdavidxu case TD_DBERR: 208132179Sdavidxu return "debugger service failed"; 209132179Sdavidxu case TD_NOAPLIC: 210132179Sdavidxu return "operation not applicable to"; 211132179Sdavidxu case TD_NOTSD: 212132179Sdavidxu return "no thread-specific data for this thread"; 213132179Sdavidxu case TD_MALLOC: 214132179Sdavidxu return "malloc failed"; 215132179Sdavidxu case TD_PARTIALREG: 216132179Sdavidxu return "only part of register set was written/read"; 217132179Sdavidxu case TD_NOXREGS: 218132179Sdavidxu return "X register set not available for this thread"; 219132179Sdavidxu default: 220132179Sdavidxu snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err); 221132179Sdavidxu return buf; 222132179Sdavidxu } 223132179Sdavidxu} 224132179Sdavidxu 225132179Sdavidxustatic char * 226132179Sdavidxuthread_db_state_str (td_thr_state_e state) 227132179Sdavidxu{ 228132179Sdavidxu static char buf[64]; 229132179Sdavidxu 230132179Sdavidxu switch (state) 231132179Sdavidxu { 232132179Sdavidxu case TD_THR_STOPPED: 233132179Sdavidxu return "stopped by debugger"; 234132179Sdavidxu case TD_THR_RUN: 235132179Sdavidxu return "runnable"; 236132179Sdavidxu case TD_THR_ACTIVE: 237132179Sdavidxu return "active"; 238132179Sdavidxu case TD_THR_ZOMBIE: 239132179Sdavidxu return "zombie"; 240132179Sdavidxu case TD_THR_SLEEP: 241132179Sdavidxu return "sleeping"; 242132179Sdavidxu case TD_THR_STOPPED_ASLEEP: 243132179Sdavidxu return "stopped by debugger AND blocked"; 244132179Sdavidxu default: 245132179Sdavidxu snprintf (buf, sizeof (buf), "unknown thread_db state %d", state); 246132179Sdavidxu return buf; 247132179Sdavidxu } 248132179Sdavidxu} 249132179Sdavidxu 250132179Sdavidxu/* Convert LWP to user-level thread id. */ 251132179Sdavidxustatic ptid_t 252144923Sdavidxuthread_from_lwp (ptid_t ptid, td_thrhandle_t *th, td_thrinfo_t *ti) 253132179Sdavidxu{ 254132179Sdavidxu td_err_e err; 255132179Sdavidxu 256132179Sdavidxu gdb_assert (IS_LWP (ptid)); 257132179Sdavidxu 258134147Sdavidxu if (fbsd_thread_active) 259132179Sdavidxu { 260144923Sdavidxu err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), th); 261134147Sdavidxu if (err == TD_OK) 262134147Sdavidxu { 263144923Sdavidxu err = td_thr_get_info_p (th, ti); 264134147Sdavidxu if (err != TD_OK) 265134147Sdavidxu error ("Cannot get thread info: %s", thread_db_err_str (err)); 266144923Sdavidxu return BUILD_THREAD (ti->ti_tid, GET_PID (ptid)); 267134147Sdavidxu } 268132179Sdavidxu } 269132179Sdavidxu 270132179Sdavidxu /* the LWP is not mapped to user thread */ 271132179Sdavidxu return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid)); 272132179Sdavidxu} 273132179Sdavidxu 274134147Sdavidxustatic void 275134147Sdavidxufbsd_core_get_first_lwp (bfd *abfd, asection *asect, void *obj) 276134147Sdavidxu{ 277134147Sdavidxu if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) 278134147Sdavidxu return; 279134147Sdavidxu 280134147Sdavidxu if (*(lwpid_t *)obj != 0) 281134147Sdavidxu return; 282134147Sdavidxu 283134147Sdavidxu *(lwpid_t *)obj = atoi (bfd_section_name (abfd, asect) + 5); 284134147Sdavidxu} 285134147Sdavidxu 286132179Sdavidxustatic long 287132179Sdavidxuget_current_lwp (int pid) 288132179Sdavidxu{ 289132179Sdavidxu struct ptrace_lwpinfo pl; 290134147Sdavidxu lwpid_t lwpid; 291132179Sdavidxu 292134147Sdavidxu if (!target_has_execution) 293134147Sdavidxu { 294134147Sdavidxu lwpid = 0; 295134147Sdavidxu bfd_map_over_sections (core_bfd, fbsd_core_get_first_lwp, &lwpid); 296134147Sdavidxu return lwpid; 297134147Sdavidxu } 298132179Sdavidxu if (ptrace (PT_LWPINFO, pid, (caddr_t)&pl, sizeof(pl))) 299132179Sdavidxu perror_with_name("PT_LWPINFO"); 300132179Sdavidxu 301132179Sdavidxu return (long)pl.pl_lwpid; 302132179Sdavidxu} 303132179Sdavidxu 304132179Sdavidxustatic void 305132179Sdavidxuget_current_thread () 306132179Sdavidxu{ 307144923Sdavidxu td_thrhandle_t th; 308144923Sdavidxu td_thrinfo_t ti; 309132179Sdavidxu long lwp; 310132179Sdavidxu ptid_t tmp, ptid; 311132179Sdavidxu 312132179Sdavidxu lwp = get_current_lwp (proc_handle.pid); 313132179Sdavidxu tmp = BUILD_LWP (lwp, proc_handle.pid); 314144923Sdavidxu ptid = thread_from_lwp (tmp, &th, &ti); 315132179Sdavidxu if (!in_thread_list (ptid)) 316132179Sdavidxu { 317144923Sdavidxu attach_thread (ptid, &th, &ti, 1); 318132179Sdavidxu } 319137731Sdavidxu inferior_ptid = ptid; 320132179Sdavidxu} 321132179Sdavidxu 322144923Sdavidxustatic td_err_e 323144923Sdavidxuenable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp) 324144923Sdavidxu{ 325144923Sdavidxu td_notify_t notify; 326144923Sdavidxu td_err_e err; 327144923Sdavidxu 328144923Sdavidxu /* Get the breakpoint address for thread EVENT. */ 329144923Sdavidxu err = td_ta_event_addr_p (thread_agent, event, ¬ify); 330144923Sdavidxu if (err != TD_OK) 331144923Sdavidxu return err; 332144923Sdavidxu 333144923Sdavidxu /* Set up the breakpoint. */ 334144923Sdavidxu (*bp) = gdbarch_convert_from_func_ptr_addr (current_gdbarch, 335155379Sdavidxu extract_typed_address(¬ify.u.bptaddr, builtin_type_void_func_ptr), 336155379Sdavidxu ¤t_target); 337144923Sdavidxu create_thread_event_breakpoint ((*bp)); 338144923Sdavidxu 339144923Sdavidxu return TD_OK; 340144923Sdavidxu} 341144923Sdavidxu 342132179Sdavidxustatic void 343144923Sdavidxuenable_thread_event_reporting (void) 344144923Sdavidxu{ 345144923Sdavidxu td_thr_events_t events; 346144923Sdavidxu td_notify_t notify; 347144923Sdavidxu td_err_e err; 348144923Sdavidxu 349144923Sdavidxu /* We cannot use the thread event reporting facility if these 350144923Sdavidxu functions aren't available. */ 351144923Sdavidxu if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL 352144923Sdavidxu || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL) 353144923Sdavidxu return; 354144923Sdavidxu 355144923Sdavidxu /* Set the process wide mask saying which events we're interested in. */ 356144923Sdavidxu td_event_emptyset (&events); 357144923Sdavidxu td_event_addset (&events, TD_CREATE); 358144923Sdavidxu td_event_addset (&events, TD_DEATH); 359144923Sdavidxu 360144923Sdavidxu err = td_ta_set_event_p (thread_agent, &events); 361144923Sdavidxu if (err != TD_OK) 362144923Sdavidxu { 363144923Sdavidxu warning ("Unable to set global thread event mask: %s", 364144923Sdavidxu thread_db_err_str (err)); 365144923Sdavidxu return; 366144923Sdavidxu } 367144923Sdavidxu 368144923Sdavidxu /* Delete previous thread event breakpoints, if any. */ 369144923Sdavidxu remove_thread_event_breakpoints (); 370144923Sdavidxu td_create_bp_addr = 0; 371144923Sdavidxu td_death_bp_addr = 0; 372144923Sdavidxu 373144923Sdavidxu /* Set up the thread creation event. */ 374144923Sdavidxu err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr); 375144923Sdavidxu if (err != TD_OK) 376144923Sdavidxu { 377144923Sdavidxu warning ("Unable to get location for thread creation breakpoint: %s", 378144923Sdavidxu thread_db_err_str (err)); 379144923Sdavidxu return; 380144923Sdavidxu } 381144923Sdavidxu 382144923Sdavidxu /* Set up the thread death event. */ 383144923Sdavidxu err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr); 384144923Sdavidxu if (err != TD_OK) 385144923Sdavidxu { 386144923Sdavidxu warning ("Unable to get location for thread death breakpoint: %s", 387144923Sdavidxu thread_db_err_str (err)); 388144923Sdavidxu return; 389144923Sdavidxu } 390144923Sdavidxu} 391144923Sdavidxu 392144923Sdavidxustatic void 393144923Sdavidxudisable_thread_event_reporting (void) 394144923Sdavidxu{ 395144923Sdavidxu td_thr_events_t events; 396144923Sdavidxu 397144923Sdavidxu /* Set the process wide mask saying we aren't interested in any 398144923Sdavidxu events anymore. */ 399144923Sdavidxu td_event_emptyset (&events); 400144923Sdavidxu td_ta_set_event_p (thread_agent, &events); 401144923Sdavidxu 402144923Sdavidxu /* Delete thread event breakpoints, if any. */ 403144923Sdavidxu remove_thread_event_breakpoints (); 404144923Sdavidxu td_create_bp_addr = 0; 405144923Sdavidxu td_death_bp_addr = 0; 406144923Sdavidxu} 407144923Sdavidxu 408144923Sdavidxustatic void 409134147Sdavidxufbsd_thread_activate (void) 410134147Sdavidxu{ 411134147Sdavidxu fbsd_thread_active = 1; 412134147Sdavidxu init_thread_list(); 413144923Sdavidxu if (fbsd_thread_core == 0) 414144923Sdavidxu enable_thread_event_reporting (); 415134147Sdavidxu fbsd_thread_find_new_threads (); 416134147Sdavidxu get_current_thread (); 417134147Sdavidxu} 418134147Sdavidxu 419134147Sdavidxustatic void 420134147Sdavidxufbsd_thread_deactivate (void) 421134147Sdavidxu{ 422144923Sdavidxu if (fbsd_thread_core == 0) 423144923Sdavidxu disable_thread_event_reporting(); 424134147Sdavidxu td_ta_delete_p (thread_agent); 425134147Sdavidxu 426134147Sdavidxu inferior_ptid = pid_to_ptid (proc_handle.pid); 427134147Sdavidxu proc_handle.pid = 0; 428134147Sdavidxu fbsd_thread_active = 0; 429134147Sdavidxu fbsd_thread_present = 0; 430134147Sdavidxu init_thread_list (); 431134147Sdavidxu} 432134147Sdavidxu 433215679Sattiliostatic char * 434215679Sattiliofbsd_thread_get_name (lwpid_t lwpid) 435215679Sattilio{ 436215679Sattilio static char last_thr_name[MAXCOMLEN + 1]; 437215679Sattilio char section_name[32]; 438215679Sattilio struct ptrace_lwpinfo lwpinfo; 439215679Sattilio bfd_size_type size; 440215679Sattilio struct bfd_section *section; 441215679Sattilio 442215679Sattilio if (target_has_execution) 443215679Sattilio { 444215679Sattilio if (ptrace (PT_LWPINFO, lwpid, (caddr_t)&lwpinfo, sizeof (lwpinfo)) == -1) 445215679Sattilio goto fail; 446215679Sattilio strncpy (last_thr_name, lwpinfo.pl_tdname, sizeof (last_thr_name) - 1); 447215679Sattilio } 448215679Sattilio else 449215679Sattilio { 450215679Sattilio snprintf (section_name, sizeof (section_name), ".tname/%u", lwpid); 451215679Sattilio section = bfd_get_section_by_name (core_bfd, section_name); 452215679Sattilio if (! section) 453215679Sattilio goto fail; 454215679Sattilio 455215679Sattilio /* Section size fix-up. */ 456215679Sattilio size = bfd_section_size (core_bfd, section); 457215679Sattilio if (size > sizeof (last_thr_name)) 458215679Sattilio size = sizeof (last_thr_name); 459215679Sattilio 460215679Sattilio if (! bfd_get_section_contents (core_bfd, section, last_thr_name, 461215679Sattilio (file_ptr)0, size)) 462215679Sattilio goto fail; 463215679Sattilio if (last_thr_name[0] == '\0') 464215679Sattilio goto fail; 465215679Sattilio } 466215679Sattilio last_thr_name[sizeof (last_thr_name) - 1] = '\0'; 467215679Sattilio return last_thr_name; 468215679Sattiliofail: 469215679Sattilio strcpy (last_thr_name, "<unknown>"); 470215679Sattilio return last_thr_name; 471215679Sattilio} 472215679Sattilio 473134147Sdavidxustatic void 474132179Sdavidxufbsd_thread_new_objfile (struct objfile *objfile) 475132179Sdavidxu{ 476132179Sdavidxu td_err_e err; 477132179Sdavidxu 478134147Sdavidxu if (objfile == NULL) 479132179Sdavidxu { 480132179Sdavidxu /* All symbols have been discarded. If the thread_db target is 481132179Sdavidxu active, deactivate it now. */ 482134147Sdavidxu if (fbsd_thread_active) 483132179Sdavidxu { 484132179Sdavidxu gdb_assert (proc_handle.pid == 0); 485134147Sdavidxu fbsd_thread_active = 0; 486132179Sdavidxu } 487132179Sdavidxu 488132179Sdavidxu goto quit; 489132179Sdavidxu } 490132179Sdavidxu 491134147Sdavidxu if (!child_suppress_run) 492134147Sdavidxu goto quit; 493134147Sdavidxu 494134152Sdavidxu /* Nothing to do. The thread library was already detected and the 495134152Sdavidxu target vector was already activated. */ 496134147Sdavidxu if (fbsd_thread_active) 497132179Sdavidxu goto quit; 498132179Sdavidxu 499132179Sdavidxu /* Initialize the structure that identifies the child process. Note 500132179Sdavidxu that at this point there is no guarantee that we actually have a 501132179Sdavidxu child process. */ 502132179Sdavidxu proc_handle.pid = GET_PID (inferior_ptid); 503132179Sdavidxu 504132179Sdavidxu /* Now attempt to open a connection to the thread library. */ 505132179Sdavidxu err = td_ta_new_p (&proc_handle, &thread_agent); 506132179Sdavidxu switch (err) 507132179Sdavidxu { 508132179Sdavidxu case TD_NOLIBTHREAD: 509132179Sdavidxu /* No thread library was detected. */ 510132179Sdavidxu break; 511132179Sdavidxu 512132179Sdavidxu case TD_OK: 513132179Sdavidxu /* The thread library was detected. Activate the thread_db target. */ 514134147Sdavidxu fbsd_thread_present = 1; 515132179Sdavidxu 516132179Sdavidxu /* We can only poke around if there actually is a child process. 517132179Sdavidxu If there is no child process alive, postpone the steps below 518132179Sdavidxu until one has been created. */ 519134147Sdavidxu if (fbsd_thread_core == 0 && proc_handle.pid != 0) 520132179Sdavidxu { 521134147Sdavidxu push_target(&fbsd_thread_ops); 522134147Sdavidxu fbsd_thread_activate(); 523132179Sdavidxu } 524132179Sdavidxu else 525134147Sdavidxu { 526134147Sdavidxu td_ta_delete_p(thread_agent); 527134147Sdavidxu thread_agent = NULL; 528134147Sdavidxu } 529132179Sdavidxu break; 530132179Sdavidxu 531132179Sdavidxu default: 532132179Sdavidxu warning ("Cannot initialize thread debugging library: %s", 533132179Sdavidxu thread_db_err_str (err)); 534132179Sdavidxu break; 535132179Sdavidxu } 536132179Sdavidxu 537132179Sdavidxu quit: 538132179Sdavidxu if (target_new_objfile_chain) 539132179Sdavidxu target_new_objfile_chain (objfile); 540132179Sdavidxu} 541132179Sdavidxu 542132179Sdavidxustatic void 543132179Sdavidxufbsd_thread_attach (char *args, int from_tty) 544132179Sdavidxu{ 545134147Sdavidxu fbsd_thread_core = 0; 546134147Sdavidxu 547132179Sdavidxu child_ops.to_attach (args, from_tty); 548132179Sdavidxu 549134147Sdavidxu /* Must get symbols from solibs before libthread_db can run! */ 550134147Sdavidxu SOLIB_ADD ((char *) 0, from_tty, (struct target_ops *) 0, auto_solib_add); 551132179Sdavidxu 552134147Sdavidxu if (fbsd_thread_present && !fbsd_thread_active) 553134147Sdavidxu push_target(&fbsd_thread_ops); 554134147Sdavidxu} 555132179Sdavidxu 556134147Sdavidxustatic void 557134147Sdavidxufbsd_thread_post_attach (int pid) 558134147Sdavidxu{ 559134147Sdavidxu child_ops.to_post_attach (pid); 560134147Sdavidxu 561134147Sdavidxu if (fbsd_thread_present && !fbsd_thread_active) 562134147Sdavidxu { 563134147Sdavidxu proc_handle.pid = GET_PID (inferior_ptid); 564134147Sdavidxu fbsd_thread_activate (); 565134147Sdavidxu } 566132179Sdavidxu} 567132179Sdavidxu 568132179Sdavidxustatic void 569132179Sdavidxufbsd_thread_detach (char *args, int from_tty) 570132179Sdavidxu{ 571134147Sdavidxu fbsd_thread_deactivate (); 572134147Sdavidxu unpush_target (&fbsd_thread_ops); 573134147Sdavidxu 574134147Sdavidxu /* Clear gdb solib information and symbol file 575134147Sdavidxu cache, so that after detach and re-attach, new_objfile 576134147Sdavidxu hook will be called */ 577134147Sdavidxu 578134147Sdavidxu clear_solib(); 579134147Sdavidxu symbol_file_clear(0); 580132179Sdavidxu proc_handle.pid = 0; 581132179Sdavidxu child_ops.to_detach (args, from_tty); 582132179Sdavidxu} 583132179Sdavidxu 584132179Sdavidxustatic int 585132179Sdavidxususpend_thread_callback (const td_thrhandle_t *th_p, void *data) 586132179Sdavidxu{ 587133345Sdavidxu int err = td_thr_dbsuspend_p (th_p); 588133345Sdavidxu if (err != 0) 589134147Sdavidxu fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err)); 590133345Sdavidxu return (err); 591132179Sdavidxu} 592132179Sdavidxu 593132179Sdavidxustatic int 594132179Sdavidxuresume_thread_callback (const td_thrhandle_t *th_p, void *data) 595132179Sdavidxu{ 596133345Sdavidxu int err = td_thr_dbresume_p (th_p); 597133345Sdavidxu if (err != 0) 598134147Sdavidxu fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err)); 599133345Sdavidxu return (err); 600132179Sdavidxu} 601132179Sdavidxu 602132179Sdavidxustatic void 603132179Sdavidxufbsd_thread_resume (ptid_t ptid, int step, enum target_signal signo) 604132179Sdavidxu{ 605132179Sdavidxu td_thrhandle_t th; 606132179Sdavidxu td_thrinfo_t ti; 607132179Sdavidxu ptid_t work_ptid; 608132179Sdavidxu int resume_all, ret; 609132179Sdavidxu long lwp, thvalid = 0; 610132179Sdavidxu 611134147Sdavidxu if (!fbsd_thread_active) 612132179Sdavidxu { 613134147Sdavidxu child_ops.to_resume (ptid, step, signo); 614132179Sdavidxu return; 615132179Sdavidxu } 616132179Sdavidxu 617132179Sdavidxu if (GET_PID(ptid) != -1 && step != 0) 618132179Sdavidxu { 619132179Sdavidxu resume_all = 0; 620132179Sdavidxu work_ptid = ptid; 621132179Sdavidxu } 622132179Sdavidxu else 623132179Sdavidxu { 624132179Sdavidxu resume_all = 1; 625132179Sdavidxu work_ptid = inferior_ptid; 626132179Sdavidxu } 627132179Sdavidxu 628132179Sdavidxu lwp = GET_LWP (work_ptid); 629132179Sdavidxu if (lwp == 0) 630132179Sdavidxu { 631132179Sdavidxu /* check user thread */ 632132179Sdavidxu ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(work_ptid), &th); 633132179Sdavidxu if (ret) 634132179Sdavidxu error (thread_db_err_str (ret)); 635132179Sdavidxu 636134152Sdavidxu /* For M:N thread, we need to tell UTS to set/unset single step 637134152Sdavidxu flag at context switch time, the flag will be written into 638134152Sdavidxu thread mailbox. This becauses some architecture may not have 639134152Sdavidxu machine single step flag in ucontext, so we put the flag in mailbox, 640134152Sdavidxu when the thread switches back, kse_switchin restores the single step 641134152Sdavidxu state. */ 642132179Sdavidxu ret = td_thr_sstep_p (&th, step); 643132179Sdavidxu if (ret) 644132179Sdavidxu error (thread_db_err_str (ret)); 645132179Sdavidxu ret = td_thr_get_info_p (&th, &ti); 646132179Sdavidxu if (ret) 647132179Sdavidxu error (thread_db_err_str (ret)); 648132179Sdavidxu thvalid = 1; 649132179Sdavidxu lwp = ti.ti_lid; 650132179Sdavidxu } 651132179Sdavidxu 652132179Sdavidxu if (lwp) 653132179Sdavidxu { 654132179Sdavidxu int req = step ? PT_SETSTEP : PT_CLEARSTEP; 655132179Sdavidxu if (ptrace (req, (pid_t) lwp, (caddr_t) 1, target_signal_to_host(signo))) 656132179Sdavidxu perror_with_name ("PT_SETSTEP/PT_CLEARSTEP"); 657132179Sdavidxu } 658132179Sdavidxu 659132179Sdavidxu if (!ptid_equal (last_single_step_thread, null_ptid)) 660132179Sdavidxu { 661132179Sdavidxu ret = td_ta_thr_iter_p (thread_agent, resume_thread_callback, NULL, 662132179Sdavidxu TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 663132179Sdavidxu TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 664132179Sdavidxu if (ret != TD_OK) 665132179Sdavidxu error ("resume error: %s", thread_db_err_str (ret)); 666132179Sdavidxu } 667132179Sdavidxu 668132179Sdavidxu if (!resume_all) 669132179Sdavidxu { 670132179Sdavidxu ret = td_ta_thr_iter_p (thread_agent, suspend_thread_callback, NULL, 671132179Sdavidxu TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 672132179Sdavidxu TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 673132179Sdavidxu if (ret != TD_OK) 674132179Sdavidxu error ("suspend error: %s", thread_db_err_str (ret)); 675132179Sdavidxu last_single_step_thread = work_ptid; 676132179Sdavidxu } 677132179Sdavidxu else 678132179Sdavidxu last_single_step_thread = null_ptid; 679132179Sdavidxu 680132179Sdavidxu if (thvalid) 681132179Sdavidxu { 682132179Sdavidxu ret = td_thr_dbresume_p (&th); 683132179Sdavidxu if (ret != TD_OK) 684132179Sdavidxu error ("resume error: %s", thread_db_err_str (ret)); 685132179Sdavidxu } 686132179Sdavidxu else 687132179Sdavidxu { 688132179Sdavidxu /* it is not necessary, put it here for completness */ 689132179Sdavidxu ret = ptrace(PT_RESUME, lwp, 0, 0); 690132179Sdavidxu } 691132179Sdavidxu 692132179Sdavidxu /* now continue the process, suspended thread wont run */ 693132179Sdavidxu if (ptrace (PT_CONTINUE, proc_handle.pid , (caddr_t)1, 694132179Sdavidxu target_signal_to_host(signo))) 695132179Sdavidxu perror_with_name ("PT_CONTINUE"); 696132179Sdavidxu} 697132179Sdavidxu 698144923Sdavidxustatic void 699144923Sdavidxuattach_thread (ptid_t ptid, const td_thrhandle_t *th_p, 700144923Sdavidxu const td_thrinfo_t *ti_p, int verbose) 701144923Sdavidxu{ 702144923Sdavidxu td_err_e err; 703144923Sdavidxu 704144923Sdavidxu /* Add the thread to GDB's thread list. */ 705144923Sdavidxu if (!in_thread_list (ptid)) { 706144923Sdavidxu add_thread (ptid); 707144923Sdavidxu if (verbose) 708144923Sdavidxu printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid)); 709144923Sdavidxu } 710144923Sdavidxu 711144923Sdavidxu if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) 712144923Sdavidxu return; /* A zombie thread -- do not attach. */ 713144923Sdavidxu 714144923Sdavidxu if (! IS_THREAD(ptid)) 715144923Sdavidxu return; 716145960Sdavidxu if (fbsd_thread_core != 0) 717145960Sdavidxu return; 718144923Sdavidxu /* Enable thread event reporting for this thread. */ 719144923Sdavidxu err = td_thr_event_enable_p (th_p, 1); 720144923Sdavidxu if (err != TD_OK) 721144923Sdavidxu error ("Cannot enable thread event reporting for %s: %s", 722144923Sdavidxu target_pid_to_str (ptid), thread_db_err_str (err)); 723144923Sdavidxu} 724144923Sdavidxu 725144923Sdavidxustatic void 726144923Sdavidxudetach_thread (ptid_t ptid, int verbose) 727144923Sdavidxu{ 728144923Sdavidxu if (verbose) 729144923Sdavidxu printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid)); 730144923Sdavidxu} 731144923Sdavidxu 732144923Sdavidxustatic void 733144923Sdavidxucheck_event (ptid_t ptid) 734144923Sdavidxu{ 735144923Sdavidxu td_event_msg_t msg; 736144923Sdavidxu td_thrinfo_t ti; 737144923Sdavidxu td_err_e err; 738144923Sdavidxu CORE_ADDR stop_pc; 739144923Sdavidxu int loop = 0; 740144923Sdavidxu 741144923Sdavidxu /* Bail out early if we're not at a thread event breakpoint. */ 742144923Sdavidxu stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK; 743144923Sdavidxu if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) 744144923Sdavidxu return; 745144923Sdavidxu loop = 1; 746144923Sdavidxu 747144923Sdavidxu do 748144923Sdavidxu { 749144923Sdavidxu err = td_ta_event_getmsg_p (thread_agent, &msg); 750144923Sdavidxu if (err != TD_OK) 751144923Sdavidxu { 752144923Sdavidxu if (err == TD_NOMSG) 753144923Sdavidxu return; 754144923Sdavidxu error ("Cannot get thread event message: %s", 755144923Sdavidxu thread_db_err_str (err)); 756144923Sdavidxu } 757183023Smarcel err = td_thr_get_info_p ((void *)(uintptr_t)msg.th_p, &ti); 758144923Sdavidxu if (err != TD_OK) 759144923Sdavidxu error ("Cannot get thread info: %s", thread_db_err_str (err)); 760144923Sdavidxu ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); 761144923Sdavidxu switch (msg.event) 762144923Sdavidxu { 763144923Sdavidxu case TD_CREATE: 764144923Sdavidxu /* We may already know about this thread, for instance when the 765144923Sdavidxu user has issued the `info threads' command before the SIGTRAP 766144923Sdavidxu for hitting the thread creation breakpoint was reported. */ 767183023Smarcel attach_thread (ptid, (void *)(uintptr_t)msg.th_p, &ti, 1); 768144923Sdavidxu break; 769144923Sdavidxu case TD_DEATH: 770144923Sdavidxu if (!in_thread_list (ptid)) 771144923Sdavidxu error ("Spurious thread death event."); 772144923Sdavidxu detach_thread (ptid, 1); 773144923Sdavidxu break; 774144923Sdavidxu default: 775144923Sdavidxu error ("Spurious thread event."); 776144923Sdavidxu } 777144923Sdavidxu } 778144923Sdavidxu while (loop); 779144923Sdavidxu} 780144923Sdavidxu 781132179Sdavidxustatic ptid_t 782132179Sdavidxufbsd_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 783132179Sdavidxu{ 784132179Sdavidxu ptid_t ret; 785132179Sdavidxu long lwp; 786132179Sdavidxu CORE_ADDR stop_pc; 787144923Sdavidxu td_thrhandle_t th; 788144923Sdavidxu td_thrinfo_t ti; 789132179Sdavidxu 790132179Sdavidxu ret = child_ops.to_wait (ptid, ourstatus); 791132179Sdavidxu if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED) 792132179Sdavidxu { 793134147Sdavidxu lwp = get_current_lwp (GET_PID(ret)); 794144923Sdavidxu ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)), 795144923Sdavidxu &th, &ti); 796144923Sdavidxu if (!in_thread_list(ret)) { 797144923Sdavidxu /* 798144923Sdavidxu * We have to enable event reporting for initial thread 799144923Sdavidxu * which was not mapped before. 800144923Sdavidxu */ 801144923Sdavidxu attach_thread(ret, &th, &ti, 1); 802144923Sdavidxu } 803144923Sdavidxu if (ourstatus->value.sig == TARGET_SIGNAL_TRAP) 804144923Sdavidxu check_event(ret); 805133345Sdavidxu /* this is a hack, if an event won't cause gdb to stop, for example, 806133345Sdavidxu SIGARLM, gdb resumes the process immediatly without setting 807133345Sdavidxu inferior_ptid to the new thread returned here, this is a bug 808133345Sdavidxu because inferior_ptid may already not exist there, and passing 809133345Sdavidxu a none existing thread to fbsd_thread_resume causes error. */ 810133345Sdavidxu if (!fbsd_thread_alive (inferior_ptid)) 811133345Sdavidxu { 812133345Sdavidxu delete_thread (inferior_ptid); 813133345Sdavidxu inferior_ptid = ret; 814144923Sdavidxu } 815132179Sdavidxu } 816132179Sdavidxu 817132179Sdavidxu return (ret); 818132179Sdavidxu} 819132179Sdavidxu 820132179Sdavidxustatic int 821132179Sdavidxufbsd_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write, 822132179Sdavidxu struct mem_attrib *attrib, struct target_ops *target) 823132179Sdavidxu{ 824134147Sdavidxu int err; 825134147Sdavidxu 826134147Sdavidxu if (target_has_execution) 827134147Sdavidxu err = child_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib, 828134147Sdavidxu target); 829134147Sdavidxu else 830134147Sdavidxu err = orig_core_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib, 831134147Sdavidxu target); 832134147Sdavidxu 833134147Sdavidxu return (err); 834132179Sdavidxu} 835132179Sdavidxu 836132179Sdavidxustatic void 837132179Sdavidxufbsd_lwp_fetch_registers (int regno) 838132179Sdavidxu{ 839132179Sdavidxu gregset_t gregs; 840132179Sdavidxu fpregset_t fpregs; 841132179Sdavidxu lwpid_t lwp; 842146818Sdfr#ifdef PT_GETXMMREGS 843146818Sdfr char xmmregs[512]; 844146818Sdfr#endif 845132179Sdavidxu 846134147Sdavidxu if (!target_has_execution) 847134147Sdavidxu { 848134147Sdavidxu orig_core_ops.to_fetch_registers (-1); 849134147Sdavidxu return; 850134147Sdavidxu } 851134147Sdavidxu 852140071Speadar /* XXX: We've replaced the pid with the lwpid for GDB's benefit. */ 853140071Speadar lwp = GET_PID (inferior_ptid); 854132179Sdavidxu 855132179Sdavidxu if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) 856132179Sdavidxu error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); 857132179Sdavidxu supply_gregset (&gregs); 858132179Sdavidxu 859146818Sdfr#ifdef PT_GETXMMREGS 860146818Sdfr if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == 0) 861146818Sdfr { 862146818Sdfr i387_supply_fxsave (current_regcache, -1, xmmregs); 863146818Sdfr } 864146818Sdfr else 865146818Sdfr { 866146818Sdfr#endif 867146818Sdfr if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) 868146818Sdfr error ("Cannot get lwp %d registers: %s\n ", lwp, safe_strerror (errno)); 869146818Sdfr supply_fpregset (&fpregs); 870146818Sdfr#ifdef PT_GETXMMREGS 871146818Sdfr } 872146818Sdfr#endif 873132179Sdavidxu} 874132179Sdavidxu 875132179Sdavidxustatic void 876132179Sdavidxufbsd_thread_fetch_registers (int regno) 877132179Sdavidxu{ 878132179Sdavidxu prgregset_t gregset; 879132179Sdavidxu prfpregset_t fpregset; 880132179Sdavidxu td_thrhandle_t th; 881132179Sdavidxu td_err_e err; 882146818Sdfr#ifdef PT_GETXMMREGS 883146818Sdfr char xmmregs[512]; 884146818Sdfr#endif 885132179Sdavidxu 886132179Sdavidxu if (!IS_THREAD (inferior_ptid)) 887132179Sdavidxu { 888132179Sdavidxu fbsd_lwp_fetch_registers (regno); 889132179Sdavidxu return; 890132179Sdavidxu } 891132179Sdavidxu 892132179Sdavidxu err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); 893132179Sdavidxu if (err != TD_OK) 894132179Sdavidxu error ("Cannot find thread %d: Thread ID=%ld, %s", 895132179Sdavidxu pid_to_thread_id (inferior_ptid), 896132179Sdavidxu GET_THREAD (inferior_ptid), thread_db_err_str (err)); 897132179Sdavidxu 898132179Sdavidxu err = td_thr_getgregs_p (&th, gregset); 899132179Sdavidxu if (err != TD_OK) 900132179Sdavidxu error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%ld, %s", 901132179Sdavidxu pid_to_thread_id (inferior_ptid), 902132179Sdavidxu GET_THREAD (inferior_ptid), thread_db_err_str (err)); 903146818Sdfr#ifdef PT_GETXMMREGS 904146818Sdfr err = td_thr_getxmmregs_p (&th, xmmregs); 905146818Sdfr if (err == TD_OK) 906146818Sdfr { 907146818Sdfr i387_supply_fxsave (current_regcache, -1, xmmregs); 908146818Sdfr } 909146818Sdfr else 910146818Sdfr { 911146818Sdfr#endif 912146818Sdfr err = td_thr_getfpregs_p (&th, &fpregset); 913146818Sdfr if (err != TD_OK) 914146818Sdfr error ("Cannot get floating-point registers for thread %d: Thread ID=%ld, %s", 915146818Sdfr pid_to_thread_id (inferior_ptid), 916146818Sdfr GET_THREAD (inferior_ptid), thread_db_err_str (err)); 917146818Sdfr supply_fpregset (&fpregset); 918146818Sdfr#ifdef PT_GETXMMREGS 919146818Sdfr } 920146818Sdfr#endif 921132179Sdavidxu 922132179Sdavidxu supply_gregset (gregset); 923132179Sdavidxu} 924132179Sdavidxu 925132179Sdavidxustatic void 926132179Sdavidxufbsd_lwp_store_registers (int regno) 927132179Sdavidxu{ 928132179Sdavidxu gregset_t gregs; 929132179Sdavidxu fpregset_t fpregs; 930132179Sdavidxu lwpid_t lwp; 931146818Sdfr#ifdef PT_GETXMMREGS 932146818Sdfr char xmmregs[512]; 933146818Sdfr#endif 934132179Sdavidxu 935132179Sdavidxu /* FIXME, is it possible ? */ 936132179Sdavidxu if (!IS_LWP (inferior_ptid)) 937132179Sdavidxu { 938132179Sdavidxu child_ops.to_store_registers (regno); 939132179Sdavidxu return ; 940132179Sdavidxu } 941132179Sdavidxu 942132179Sdavidxu lwp = GET_LWP (inferior_ptid); 943132179Sdavidxu if (regno != -1) 944132179Sdavidxu if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1) 945132179Sdavidxu error ("Cannot get lwp %d registers: %s\n", lwp, safe_strerror (errno)); 946132179Sdavidxu 947132179Sdavidxu fill_gregset (&gregs, regno); 948132179Sdavidxu if (ptrace (PT_SETREGS, lwp, (caddr_t) &gregs, 0) == -1) 949132179Sdavidxu error ("Cannot set lwp %d registers: %s\n", lwp, safe_strerror (errno)); 950132179Sdavidxu 951146818Sdfr#ifdef PT_GETXMMREGS 952132179Sdavidxu if (regno != -1) 953146818Sdfr if (ptrace (PT_GETXMMREGS, lwp, xmmregs, 0) == -1) 954146818Sdfr goto noxmm; 955146818Sdfr 956146818Sdfr i387_fill_fxsave (xmmregs, regno); 957146818Sdfr if (ptrace (PT_SETXMMREGS, lwp, xmmregs, 0) == -1) 958146818Sdfr goto noxmm; 959146818Sdfr 960146818Sdfr return; 961146818Sdfr 962146818Sdfrnoxmm: 963146818Sdfr#endif 964146818Sdfr 965146818Sdfr if (regno != -1) 966132179Sdavidxu if (ptrace (PT_GETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) 967132179Sdavidxu error ("Cannot get lwp %d float registers: %s\n", lwp, 968132179Sdavidxu safe_strerror (errno)); 969132179Sdavidxu 970132179Sdavidxu fill_fpregset (&fpregs, regno); 971132179Sdavidxu if (ptrace (PT_SETFPREGS, lwp, (caddr_t) &fpregs, 0) == -1) 972132179Sdavidxu error ("Cannot set lwp %d float registers: %s\n", lwp, 973132179Sdavidxu safe_strerror (errno)); 974132179Sdavidxu} 975132179Sdavidxu 976132179Sdavidxustatic void 977132179Sdavidxufbsd_thread_store_registers (int regno) 978132179Sdavidxu{ 979132179Sdavidxu prgregset_t gregset; 980132179Sdavidxu prfpregset_t fpregset; 981132179Sdavidxu td_thrhandle_t th; 982132179Sdavidxu td_err_e err; 983146818Sdfr#ifdef PT_GETXMMREGS 984146818Sdfr char xmmregs[512]; 985146818Sdfr#endif 986132179Sdavidxu 987132179Sdavidxu if (!IS_THREAD (inferior_ptid)) 988132179Sdavidxu { 989132179Sdavidxu fbsd_lwp_store_registers (regno); 990132179Sdavidxu return; 991132179Sdavidxu } 992132179Sdavidxu 993132179Sdavidxu err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); 994132179Sdavidxu if (err != TD_OK) 995132179Sdavidxu error ("Cannot find thread %d: Thread ID=%ld, %s", 996132179Sdavidxu pid_to_thread_id (inferior_ptid), 997132179Sdavidxu GET_THREAD (inferior_ptid), 998132179Sdavidxu thread_db_err_str (err)); 999132179Sdavidxu 1000132179Sdavidxu if (regno != -1) 1001132179Sdavidxu { 1002132179Sdavidxu char old_value[MAX_REGISTER_SIZE]; 1003132179Sdavidxu 1004132179Sdavidxu regcache_collect (regno, old_value); 1005132179Sdavidxu err = td_thr_getgregs_p (&th, gregset); 1006132179Sdavidxu if (err != TD_OK) 1007132179Sdavidxu error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err)); 1008166851Semaste#ifdef PT_GETXMMREGS 1009166851Semaste err = td_thr_getxmmregs_p (&th, xmmregs); 1010132179Sdavidxu if (err != TD_OK) 1011166851Semaste { 1012166851Semaste#endif 1013166851Semaste err = td_thr_getfpregs_p (&th, &fpregset); 1014166851Semaste if (err != TD_OK) 1015166851Semaste error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err)); 1016166851Semaste#ifdef PT_GETXMMREGS 1017166851Semaste } 1018166851Semaste#endif 1019132179Sdavidxu supply_register (regno, old_value); 1020132179Sdavidxu } 1021132179Sdavidxu 1022132179Sdavidxu fill_gregset (gregset, regno); 1023132179Sdavidxu err = td_thr_setgregs_p (&th, gregset); 1024132179Sdavidxu if (err != TD_OK) 1025132179Sdavidxu error ("Cannot store general-purpose registers for thread %d: Thread ID=%d, %s", 1026132179Sdavidxu pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), 1027132179Sdavidxu thread_db_err_str (err)); 1028146818Sdfr 1029146818Sdfr#ifdef PT_GETXMMREGS 1030166851Semaste i387_fill_fxsave (xmmregs, regno); 1031146818Sdfr err = td_thr_setxmmregs_p (&th, xmmregs); 1032146818Sdfr if (err == TD_OK) 1033146818Sdfr return; 1034146818Sdfr#endif 1035146818Sdfr 1036166851Semaste fill_fpregset (&fpregset, regno); 1037132179Sdavidxu err = td_thr_setfpregs_p (&th, &fpregset); 1038132179Sdavidxu if (err != TD_OK) 1039132179Sdavidxu error ("Cannot store floating-point registers for thread %d: Thread ID=%d, %s", 1040132179Sdavidxu pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid), 1041132179Sdavidxu thread_db_err_str (err)); 1042132179Sdavidxu} 1043132179Sdavidxu 1044132179Sdavidxustatic void 1045132179Sdavidxufbsd_thread_kill (void) 1046132179Sdavidxu{ 1047132179Sdavidxu child_ops.to_kill(); 1048132179Sdavidxu} 1049132179Sdavidxu 1050134147Sdavidxustatic int 1051134147Sdavidxufbsd_thread_can_run (void) 1052134147Sdavidxu{ 1053134147Sdavidxu return child_suppress_run; 1054134147Sdavidxu} 1055134147Sdavidxu 1056132179Sdavidxustatic void 1057132179Sdavidxufbsd_thread_create_inferior (char *exec_file, char *allargs, char **env) 1058132179Sdavidxu{ 1059134147Sdavidxu if (fbsd_thread_present && !fbsd_thread_active) 1060134147Sdavidxu push_target(&fbsd_thread_ops); 1061132179Sdavidxu 1062132179Sdavidxu child_ops.to_create_inferior (exec_file, allargs, env); 1063132179Sdavidxu} 1064132179Sdavidxu 1065132179Sdavidxustatic void 1066132179Sdavidxufbsd_thread_post_startup_inferior (ptid_t ptid) 1067132179Sdavidxu{ 1068134147Sdavidxu if (fbsd_thread_present && !fbsd_thread_active) 1069132179Sdavidxu { 1070134152Sdavidxu /* The child process is now the actual multi-threaded 1071134152Sdavidxu program. Snatch its process ID... */ 1072132179Sdavidxu proc_handle.pid = GET_PID (ptid); 1073134147Sdavidxu td_ta_new_p (&proc_handle, &thread_agent); 1074134147Sdavidxu fbsd_thread_activate(); 1075132179Sdavidxu } 1076132179Sdavidxu} 1077132179Sdavidxu 1078132179Sdavidxustatic void 1079132179Sdavidxufbsd_thread_mourn_inferior (void) 1080132179Sdavidxu{ 1081134147Sdavidxu if (fbsd_thread_active) 1082134147Sdavidxu fbsd_thread_deactivate (); 1083132179Sdavidxu 1084134147Sdavidxu unpush_target (&fbsd_thread_ops); 1085134147Sdavidxu 1086132179Sdavidxu child_ops.to_mourn_inferior (); 1087132179Sdavidxu} 1088132179Sdavidxu 1089134147Sdavidxustatic void 1090134147Sdavidxufbsd_core_check_lwp (bfd *abfd, asection *asect, void *obj) 1091134147Sdavidxu{ 1092134147Sdavidxu lwpid_t lwp; 1093134147Sdavidxu 1094134147Sdavidxu if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0) 1095134147Sdavidxu return; 1096134147Sdavidxu 1097134147Sdavidxu /* already found */ 1098134147Sdavidxu if (*(lwpid_t *)obj == 0) 1099134147Sdavidxu return; 1100134147Sdavidxu 1101134147Sdavidxu lwp = atoi (bfd_section_name (abfd, asect) + 5); 1102134147Sdavidxu if (*(lwpid_t *)obj == lwp) 1103134147Sdavidxu *(lwpid_t *)obj = 0; 1104134147Sdavidxu} 1105134147Sdavidxu 1106132179Sdavidxustatic int 1107132179Sdavidxufbsd_thread_alive (ptid_t ptid) 1108132179Sdavidxu{ 1109132179Sdavidxu td_thrhandle_t th; 1110132179Sdavidxu td_thrinfo_t ti; 1111132179Sdavidxu td_err_e err; 1112132179Sdavidxu gregset_t gregs; 1113134147Sdavidxu lwpid_t lwp; 1114132179Sdavidxu 1115132179Sdavidxu if (IS_THREAD (ptid)) 1116132179Sdavidxu { 1117132179Sdavidxu err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); 1118132179Sdavidxu if (err != TD_OK) 1119132179Sdavidxu return 0; 1120132179Sdavidxu 1121132179Sdavidxu err = td_thr_get_info_p (&th, &ti); 1122132179Sdavidxu if (err != TD_OK) 1123132179Sdavidxu return 0; 1124132179Sdavidxu 1125132179Sdavidxu /* A zombie thread. */ 1126132179Sdavidxu if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) 1127132179Sdavidxu return 0; 1128132179Sdavidxu 1129132179Sdavidxu return 1; 1130132179Sdavidxu } 1131132179Sdavidxu else if (GET_LWP (ptid) == 0) 1132132179Sdavidxu { 1133132179Sdavidxu /* we sometimes are called with lwp == 0 */ 1134132179Sdavidxu return 1; 1135132179Sdavidxu } 1136132179Sdavidxu 1137134147Sdavidxu if (fbsd_thread_active) 1138134147Sdavidxu { 1139134147Sdavidxu err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); 1140132179Sdavidxu 1141134147Sdavidxu /* 1142134147Sdavidxu * if the lwp was already mapped to user thread, don't use it 1143134147Sdavidxu * directly, please use user thread id instead. 1144134147Sdavidxu */ 1145134147Sdavidxu if (err == TD_OK) 1146134147Sdavidxu return 0; 1147134147Sdavidxu } 1148132179Sdavidxu 1149134147Sdavidxu if (!target_has_execution) 1150134147Sdavidxu { 1151134147Sdavidxu lwp = GET_LWP (ptid); 1152134147Sdavidxu bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp); 1153134147Sdavidxu return (lwp == 0); 1154134147Sdavidxu } 1155134147Sdavidxu 1156132179Sdavidxu /* check lwp in kernel */ 1157132179Sdavidxu return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0; 1158132179Sdavidxu} 1159132179Sdavidxu 1160134147Sdavidxustatic void 1161134147Sdavidxufbsd_thread_files_info (struct target_ops *ignore) 1162134147Sdavidxu{ 1163134147Sdavidxu child_ops.to_files_info (ignore); 1164134147Sdavidxu} 1165134147Sdavidxu 1166132179Sdavidxustatic int 1167132179Sdavidxufind_new_threads_callback (const td_thrhandle_t *th_p, void *data) 1168132179Sdavidxu{ 1169132179Sdavidxu td_thrinfo_t ti; 1170132179Sdavidxu td_err_e err; 1171132179Sdavidxu ptid_t ptid; 1172132179Sdavidxu 1173132179Sdavidxu err = td_thr_get_info_p (th_p, &ti); 1174132179Sdavidxu if (err != TD_OK) 1175132179Sdavidxu error ("Cannot get thread info: %s", thread_db_err_str (err)); 1176132179Sdavidxu 1177132179Sdavidxu /* Ignore zombie */ 1178132179Sdavidxu if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE) 1179132179Sdavidxu return 0; 1180132179Sdavidxu 1181134147Sdavidxu ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid); 1182144923Sdavidxu attach_thread (ptid, th_p, &ti, 1); 1183132179Sdavidxu return 0; 1184132179Sdavidxu} 1185132179Sdavidxu 1186132179Sdavidxustatic void 1187132179Sdavidxufbsd_thread_find_new_threads (void) 1188132179Sdavidxu{ 1189132179Sdavidxu td_err_e err; 1190132179Sdavidxu 1191134147Sdavidxu if (!fbsd_thread_active) 1192134147Sdavidxu return; 1193134147Sdavidxu 1194132179Sdavidxu /* Iterate over all user-space threads to discover new threads. */ 1195132179Sdavidxu err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL, 1196132179Sdavidxu TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 1197132179Sdavidxu TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 1198132179Sdavidxu if (err != TD_OK) 1199132179Sdavidxu error ("Cannot find new threads: %s", thread_db_err_str (err)); 1200132179Sdavidxu} 1201132179Sdavidxu 1202132179Sdavidxustatic char * 1203132179Sdavidxufbsd_thread_pid_to_str (ptid_t ptid) 1204132179Sdavidxu{ 1205215679Sattilio static char buf[64 + MAXCOMLEN]; 1206132179Sdavidxu 1207132179Sdavidxu if (IS_THREAD (ptid)) 1208132179Sdavidxu { 1209132179Sdavidxu td_thrhandle_t th; 1210132179Sdavidxu td_thrinfo_t ti; 1211132179Sdavidxu td_err_e err; 1212132179Sdavidxu 1213132179Sdavidxu err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th); 1214132179Sdavidxu if (err != TD_OK) 1215132179Sdavidxu error ("Cannot find thread, Thread ID=%ld, %s", 1216132179Sdavidxu GET_THREAD (ptid), thread_db_err_str (err)); 1217132179Sdavidxu 1218132179Sdavidxu err = td_thr_get_info_p (&th, &ti); 1219132179Sdavidxu if (err != TD_OK) 1220132179Sdavidxu error ("Cannot get thread info, Thread ID=%ld, %s", 1221132179Sdavidxu GET_THREAD (ptid), thread_db_err_str (err)); 1222132179Sdavidxu 1223132179Sdavidxu if (ti.ti_lid != 0) 1224132179Sdavidxu { 1225215679Sattilio snprintf (buf, sizeof (buf), "Thread %llx (LWP %d/%s)", 1226215679Sattilio (unsigned long long)th.th_thread, ti.ti_lid, 1227215679Sattilio fbsd_thread_get_name (ti.ti_lid)); 1228132179Sdavidxu } 1229132179Sdavidxu else 1230132179Sdavidxu { 1231183023Smarcel snprintf (buf, sizeof (buf), "Thread %llx (%s)", 1232183023Smarcel (unsigned long long)th.th_thread, 1233183023Smarcel thread_db_state_str (ti.ti_state)); 1234132179Sdavidxu } 1235132179Sdavidxu 1236132179Sdavidxu return buf; 1237132179Sdavidxu } 1238132179Sdavidxu else if (IS_LWP (ptid)) 1239132179Sdavidxu { 1240132179Sdavidxu snprintf (buf, sizeof (buf), "LWP %d", (int) GET_LWP (ptid)); 1241132179Sdavidxu return buf; 1242132179Sdavidxu } 1243132179Sdavidxu return normal_pid_to_str (ptid); 1244132179Sdavidxu} 1245132179Sdavidxu 1246133345SdavidxuCORE_ADDR 1247133345Sdavidxufbsd_thread_get_local_address(ptid_t ptid, struct objfile *objfile, 1248133345Sdavidxu CORE_ADDR offset) 1249133345Sdavidxu{ 1250133345Sdavidxu td_thrhandle_t th; 1251133345Sdavidxu void *address; 1252133345Sdavidxu CORE_ADDR lm; 1253155379Sdavidxu void *lm2; 1254133345Sdavidxu int ret, is_library = (objfile->flags & OBJF_SHARED); 1255133345Sdavidxu 1256133345Sdavidxu if (IS_THREAD (ptid)) 1257133345Sdavidxu { 1258133345Sdavidxu if (!td_thr_tls_get_addr_p) 1259133345Sdavidxu error ("Cannot find thread-local interface in thread_db library."); 1260133345Sdavidxu 1261133345Sdavidxu /* Get the address of the link map for this objfile. */ 1262133345Sdavidxu lm = svr4_fetch_objfile_link_map (objfile); 1263133345Sdavidxu 1264133345Sdavidxu /* Couldn't find link map. Bail out. */ 1265133345Sdavidxu if (!lm) 1266133345Sdavidxu { 1267133345Sdavidxu if (is_library) 1268133345Sdavidxu error ("Cannot find shared library `%s' link_map in dynamic" 1269133345Sdavidxu " linker's module list", objfile->name); 1270133345Sdavidxu else 1271133345Sdavidxu error ("Cannot find executable file `%s' link_map in dynamic" 1272133345Sdavidxu " linker's module list", objfile->name); 1273133345Sdavidxu } 1274133345Sdavidxu 1275133345Sdavidxu ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th); 1276133345Sdavidxu 1277133345Sdavidxu /* get the address of the variable. */ 1278155379Sdavidxu store_typed_address(&lm2, builtin_type_void_data_ptr, lm); 1279155379Sdavidxu ret = td_thr_tls_get_addr_p (&th, lm2, offset, &address); 1280133345Sdavidxu 1281133345Sdavidxu if (ret != TD_OK) 1282133345Sdavidxu { 1283133345Sdavidxu if (is_library) 1284133345Sdavidxu error ("Cannot find thread-local storage for thread %ld, " 1285133345Sdavidxu "shared library %s:\n%s", 1286133345Sdavidxu (long) GET_THREAD (ptid), 1287133345Sdavidxu objfile->name, thread_db_err_str (ret)); 1288133345Sdavidxu else 1289133345Sdavidxu error ("Cannot find thread-local storage for thread %ld, " 1290133345Sdavidxu "executable file %s:\n%s", 1291133345Sdavidxu (long) GET_THREAD (ptid), 1292133345Sdavidxu objfile->name, thread_db_err_str (ret)); 1293133345Sdavidxu } 1294133345Sdavidxu 1295133345Sdavidxu /* Cast assuming host == target. */ 1296155379Sdavidxu return extract_typed_address(&address, builtin_type_void_data_ptr); 1297133345Sdavidxu } 1298133345Sdavidxu return (0); 1299133345Sdavidxu} 1300133345Sdavidxu 1301132179Sdavidxustatic int 1302132179Sdavidxutsd_cb (thread_key_t key, void (*destructor)(void *), void *ignore) 1303132179Sdavidxu{ 1304132179Sdavidxu struct minimal_symbol *ms; 1305132179Sdavidxu char *name; 1306132179Sdavidxu 1307155379Sdavidxu ms = lookup_minimal_symbol_by_pc ( 1308155379Sdavidxu extract_typed_address(&destructor, builtin_type_void_func_ptr)); 1309132179Sdavidxu if (!ms) 1310132179Sdavidxu name = "???"; 1311132179Sdavidxu else 1312132179Sdavidxu name = DEPRECATED_SYMBOL_NAME (ms); 1313132179Sdavidxu 1314235714Sdavidxu printf_filtered ("Key %d, destructor %p <%s>\n", key, destructor, name); 1315132179Sdavidxu return 0; 1316132179Sdavidxu} 1317132179Sdavidxu 1318132179Sdavidxustatic void 1319132179Sdavidxufbsd_thread_tsd_cmd (char *exp, int from_tty) 1320132179Sdavidxu{ 1321134147Sdavidxu if (fbsd_thread_active) 1322134147Sdavidxu td_ta_tsd_iter_p (thread_agent, tsd_cb, NULL); 1323132179Sdavidxu} 1324132179Sdavidxu 1325155379Sdavidxustatic void 1326155379Sdavidxufbsd_print_sigset (sigset_t *set) 1327155379Sdavidxu{ 1328155379Sdavidxu int i; 1329155379Sdavidxu 1330155379Sdavidxu for (i = 1; i <= _SIG_MAXSIG; ++i) { 1331155379Sdavidxu if (sigismember(set, i)) { 1332155379Sdavidxu if (i < sizeof(sys_signame)/sizeof(sys_signame[0])) 1333155379Sdavidxu printf_filtered("%s ", sys_signame[i]); 1334155379Sdavidxu else 1335155379Sdavidxu printf_filtered("sig%d ", i); 1336155379Sdavidxu } 1337155379Sdavidxu } 1338155379Sdavidxu printf_filtered("\n"); 1339155379Sdavidxu} 1340155379Sdavidxu 1341155379Sdavidxustatic void 1342155379Sdavidxufbsd_thread_signal_cmd (char *exp, int from_tty) 1343155379Sdavidxu{ 1344155379Sdavidxu td_thrhandle_t th; 1345155379Sdavidxu td_thrinfo_t ti; 1346155379Sdavidxu td_err_e err; 1347209690Skib const char *code; 1348155379Sdavidxu 1349155379Sdavidxu if (!fbsd_thread_active || !IS_THREAD(inferior_ptid)) 1350155379Sdavidxu return; 1351155379Sdavidxu 1352155379Sdavidxu err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th); 1353155379Sdavidxu if (err != TD_OK) 1354155379Sdavidxu return; 1355155379Sdavidxu 1356155379Sdavidxu err = td_thr_get_info_p (&th, &ti); 1357155379Sdavidxu if (err != TD_OK) 1358155379Sdavidxu return; 1359155379Sdavidxu 1360155379Sdavidxu printf_filtered("signal mask:\n"); 1361155379Sdavidxu fbsd_print_sigset(&ti.ti_sigmask); 1362155379Sdavidxu printf_filtered("signal pending:\n"); 1363155379Sdavidxu fbsd_print_sigset(&ti.ti_pending); 1364209690Skib if (ti.ti_siginfo.si_signo != 0) { 1365209690Skib printf_filtered("si_signo %d si_errno %d", ti.ti_siginfo.si_signo, 1366209690Skib ti.ti_siginfo.si_errno); 1367209690Skib if (ti.ti_siginfo.si_errno != 0) 1368209690Skib printf_filtered(" (%s)", strerror(ti.ti_siginfo.si_errno)); 1369209690Skib printf_filtered("\n"); 1370209690Skib switch (ti.ti_siginfo.si_code) { 1371209690Skib case SI_NOINFO: 1372209690Skib code = "NOINFO"; 1373209690Skib break; 1374209690Skib case SI_USER: 1375209690Skib code = "USER"; 1376209690Skib break; 1377209690Skib case SI_QUEUE: 1378209690Skib code = "QUEUE"; 1379209690Skib break; 1380209690Skib case SI_TIMER: 1381209690Skib code = "TIMER"; 1382209690Skib break; 1383209690Skib case SI_ASYNCIO: 1384209690Skib code = "ASYNCIO"; 1385209690Skib break; 1386209690Skib case SI_MESGQ: 1387209690Skib code = "MESGQ"; 1388209690Skib break; 1389209690Skib case SI_KERNEL: 1390209690Skib code = "KERNEL"; 1391209690Skib break; 1392209690Skib default: 1393209690Skib code = "UNKNOWN"; 1394209690Skib break; 1395209690Skib } 1396220043Skib printf_filtered("si_code %s (%d) si_pid %d si_uid %d si_status %x " 1397220043Skib "si_addr %p\n", 1398220043Skib code, ti.ti_siginfo.si_code, ti.ti_siginfo.si_pid, ti.ti_siginfo.si_uid, 1399220043Skib ti.ti_siginfo.si_status, ti.ti_siginfo.si_addr); 1400209690Skib } 1401155379Sdavidxu} 1402155379Sdavidxu 1403134147Sdavidxustatic int 1404134147Sdavidxuignore (CORE_ADDR addr, char *contents) 1405132179Sdavidxu{ 1406134147Sdavidxu return 0; 1407132179Sdavidxu} 1408132179Sdavidxu 1409134147Sdavidxustatic void 1410134147Sdavidxufbsd_core_open (char *filename, int from_tty) 1411132179Sdavidxu{ 1412134147Sdavidxu int err; 1413132179Sdavidxu 1414134147Sdavidxu fbsd_thread_core = 1; 1415132179Sdavidxu 1416134147Sdavidxu orig_core_ops.to_open (filename, from_tty); 1417132179Sdavidxu 1418134147Sdavidxu if (fbsd_thread_present) 1419134147Sdavidxu { 1420134147Sdavidxu err = td_ta_new_p (&proc_handle, &thread_agent); 1421134147Sdavidxu if (err == TD_OK) 1422134147Sdavidxu { 1423134147Sdavidxu proc_handle.pid = elf_tdata (core_bfd)->core_pid; 1424134147Sdavidxu fbsd_thread_activate (); 1425134147Sdavidxu } 1426134147Sdavidxu else 1427134149Sdavidxu error ("fbsd_core_open: td_ta_new: %s", thread_db_err_str (err)); 1428134147Sdavidxu } 1429134147Sdavidxu} 1430132179Sdavidxu 1431134147Sdavidxustatic void 1432134147Sdavidxufbsd_core_close (int quitting) 1433134147Sdavidxu{ 1434134147Sdavidxu orig_core_ops.to_close (quitting); 1435134147Sdavidxu} 1436132179Sdavidxu 1437134147Sdavidxustatic void 1438134147Sdavidxufbsd_core_detach (char *args, int from_tty) 1439134147Sdavidxu{ 1440134147Sdavidxu if (fbsd_thread_active) 1441134147Sdavidxu fbsd_thread_deactivate (); 1442134147Sdavidxu unpush_target (&fbsd_thread_ops); 1443134147Sdavidxu orig_core_ops.to_detach (args, from_tty); 1444134147Sdavidxu 1445134147Sdavidxu /* Clear gdb solib information and symbol file 1446134147Sdavidxu cache, so that after detach and re-attach, new_objfile 1447134147Sdavidxu hook will be called */ 1448134147Sdavidxu clear_solib(); 1449134147Sdavidxu symbol_file_clear(0); 1450134147Sdavidxu} 1451132179Sdavidxu 1452134147Sdavidxustatic void 1453134147Sdavidxufbsd_core_files_info (struct target_ops *ignore) 1454134147Sdavidxu{ 1455134147Sdavidxu orig_core_ops.to_files_info (ignore); 1456134147Sdavidxu} 1457132179Sdavidxu 1458134147Sdavidxustatic void 1459134147Sdavidxuinit_fbsd_core_ops (void) 1460134147Sdavidxu{ 1461134147Sdavidxu fbsd_core_ops.to_shortname = "FreeBSD-core"; 1462178666Sjhb fbsd_core_ops.to_longname = "FreeBSD multithreaded core dump file"; 1463178666Sjhb fbsd_core_ops.to_doc = 1464178666Sjhb "Use a core file as a target. Specify the filename of the core file."; 1465134147Sdavidxu fbsd_core_ops.to_open = fbsd_core_open; 1466134147Sdavidxu fbsd_core_ops.to_close = fbsd_core_close; 1467134147Sdavidxu fbsd_core_ops.to_attach = 0; 1468134147Sdavidxu fbsd_core_ops.to_post_attach = 0; 1469134147Sdavidxu fbsd_core_ops.to_detach = fbsd_core_detach; 1470134147Sdavidxu /* fbsd_core_ops.to_resume = 0; */ 1471134147Sdavidxu /* fbsd_core_ops.to_wait = 0; */ 1472134147Sdavidxu fbsd_core_ops.to_fetch_registers = fbsd_thread_fetch_registers; 1473134147Sdavidxu /* fbsd_core_ops.to_store_registers = 0; */ 1474134147Sdavidxu /* fbsd_core_ops.to_prepare_to_store = 0; */ 1475134147Sdavidxu fbsd_core_ops.to_xfer_memory = fbsd_thread_xfer_memory; 1476134147Sdavidxu fbsd_core_ops.to_files_info = fbsd_core_files_info; 1477134147Sdavidxu fbsd_core_ops.to_insert_breakpoint = ignore; 1478134147Sdavidxu fbsd_core_ops.to_remove_breakpoint = ignore; 1479134147Sdavidxu /* fbsd_core_ops.to_lookup_symbol = 0; */ 1480134147Sdavidxu fbsd_core_ops.to_create_inferior = fbsd_thread_create_inferior; 1481134147Sdavidxu fbsd_core_ops.to_stratum = core_stratum; 1482134147Sdavidxu fbsd_core_ops.to_has_all_memory = 0; 1483134147Sdavidxu fbsd_core_ops.to_has_memory = 1; 1484134147Sdavidxu fbsd_core_ops.to_has_stack = 1; 1485134147Sdavidxu fbsd_core_ops.to_has_registers = 1; 1486134147Sdavidxu fbsd_core_ops.to_has_execution = 0; 1487134147Sdavidxu fbsd_core_ops.to_has_thread_control = tc_none; 1488134147Sdavidxu fbsd_core_ops.to_thread_alive = fbsd_thread_alive; 1489134147Sdavidxu fbsd_core_ops.to_pid_to_str = fbsd_thread_pid_to_str; 1490134147Sdavidxu fbsd_core_ops.to_find_new_threads = fbsd_thread_find_new_threads; 1491134147Sdavidxu fbsd_core_ops.to_sections = 0; 1492134147Sdavidxu fbsd_core_ops.to_sections_end = 0; 1493134147Sdavidxu fbsd_core_ops.to_magic = OPS_MAGIC; 1494134147Sdavidxu} 1495132179Sdavidxu 1496134147Sdavidxustatic void 1497134147Sdavidxuinit_fbsd_thread_ops (void) 1498134147Sdavidxu{ 1499134147Sdavidxu fbsd_thread_ops.to_shortname = "freebsd-threads"; 1500134147Sdavidxu fbsd_thread_ops.to_longname = "FreeBSD multithreaded child process."; 1501134147Sdavidxu fbsd_thread_ops.to_doc = "FreeBSD threads support."; 1502134147Sdavidxu fbsd_thread_ops.to_attach = fbsd_thread_attach; 1503134147Sdavidxu fbsd_thread_ops.to_detach = fbsd_thread_detach; 1504134147Sdavidxu fbsd_thread_ops.to_post_attach = fbsd_thread_post_attach; 1505134147Sdavidxu fbsd_thread_ops.to_resume = fbsd_thread_resume; 1506134147Sdavidxu fbsd_thread_ops.to_wait = fbsd_thread_wait; 1507134147Sdavidxu fbsd_thread_ops.to_fetch_registers = fbsd_thread_fetch_registers; 1508134147Sdavidxu fbsd_thread_ops.to_store_registers = fbsd_thread_store_registers; 1509134147Sdavidxu fbsd_thread_ops.to_xfer_memory = fbsd_thread_xfer_memory; 1510134147Sdavidxu fbsd_thread_ops.to_files_info = fbsd_thread_files_info; 1511134147Sdavidxu fbsd_thread_ops.to_kill = fbsd_thread_kill; 1512134147Sdavidxu fbsd_thread_ops.to_create_inferior = fbsd_thread_create_inferior; 1513134147Sdavidxu fbsd_thread_ops.to_post_startup_inferior = fbsd_thread_post_startup_inferior; 1514134147Sdavidxu fbsd_thread_ops.to_mourn_inferior = fbsd_thread_mourn_inferior; 1515134147Sdavidxu fbsd_thread_ops.to_can_run = fbsd_thread_can_run; 1516134147Sdavidxu fbsd_thread_ops.to_thread_alive = fbsd_thread_alive; 1517134147Sdavidxu fbsd_thread_ops.to_find_new_threads = fbsd_thread_find_new_threads; 1518134147Sdavidxu fbsd_thread_ops.to_pid_to_str = fbsd_thread_pid_to_str; 1519134147Sdavidxu fbsd_thread_ops.to_stratum = thread_stratum; 1520134147Sdavidxu fbsd_thread_ops.to_has_thread_control = tc_none; 1521134147Sdavidxu fbsd_thread_ops.to_has_all_memory = 1; 1522134147Sdavidxu fbsd_thread_ops.to_has_memory = 1; 1523134147Sdavidxu fbsd_thread_ops.to_has_stack = 1; 1524134147Sdavidxu fbsd_thread_ops.to_has_registers = 1; 1525134147Sdavidxu fbsd_thread_ops.to_has_execution = 1; 1526134147Sdavidxu fbsd_thread_ops.to_insert_breakpoint = memory_insert_breakpoint; 1527134147Sdavidxu fbsd_thread_ops.to_remove_breakpoint = memory_remove_breakpoint; 1528134147Sdavidxu fbsd_thread_ops.to_get_thread_local_address = fbsd_thread_get_local_address; 1529134147Sdavidxu fbsd_thread_ops.to_magic = OPS_MAGIC; 1530134147Sdavidxu} 1531132179Sdavidxu 1532134147Sdavidxustatic int 1533134147Sdavidxuthread_db_load (void) 1534134147Sdavidxu{ 1535134147Sdavidxu void *handle; 1536134147Sdavidxu td_err_e err; 1537132179Sdavidxu 1538134147Sdavidxu handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW); 1539134147Sdavidxu if (handle == NULL) 1540134147Sdavidxu return 0; 1541132179Sdavidxu 1542134147Sdavidxu#define resolve(X) \ 1543134147Sdavidxu if (!(X##_p = dlsym (handle, #X))) \ 1544134147Sdavidxu return 0; 1545132179Sdavidxu 1546134147Sdavidxu resolve(td_init); 1547134147Sdavidxu resolve(td_ta_new); 1548134147Sdavidxu resolve(td_ta_delete); 1549134147Sdavidxu resolve(td_ta_map_id2thr); 1550134147Sdavidxu resolve(td_ta_map_lwp2thr); 1551134147Sdavidxu resolve(td_ta_thr_iter); 1552134147Sdavidxu resolve(td_thr_get_info); 1553146818Sdfr#ifdef PT_GETXMMREGS 1554146818Sdfr resolve(td_thr_getxmmregs); 1555146818Sdfr#endif 1556134147Sdavidxu resolve(td_thr_getfpregs); 1557134147Sdavidxu resolve(td_thr_getgregs); 1558146818Sdfr#ifdef PT_GETXMMREGS 1559146818Sdfr resolve(td_thr_setxmmregs); 1560146818Sdfr#endif 1561134147Sdavidxu resolve(td_thr_setfpregs); 1562134147Sdavidxu resolve(td_thr_setgregs); 1563134147Sdavidxu resolve(td_thr_sstep); 1564134147Sdavidxu resolve(td_ta_tsd_iter); 1565134147Sdavidxu resolve(td_thr_dbsuspend); 1566134147Sdavidxu resolve(td_thr_dbresume); 1567134147Sdavidxu resolve(td_thr_tls_get_addr); 1568132179Sdavidxu 1569132179Sdavidxu /* Initialize the library. */ 1570132179Sdavidxu err = td_init_p (); 1571132179Sdavidxu if (err != TD_OK) 1572132179Sdavidxu { 1573132179Sdavidxu warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err)); 1574132179Sdavidxu return 0; 1575132179Sdavidxu } 1576132179Sdavidxu 1577144923Sdavidxu /* These are not essential. */ 1578144923Sdavidxu td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); 1579144923Sdavidxu td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); 1580144923Sdavidxu td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); 1581144923Sdavidxu td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); 1582144923Sdavidxu td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); 1583144923Sdavidxu 1584132179Sdavidxu return 1; 1585132179Sdavidxu} 1586132179Sdavidxu 1587134147Sdavidxu/* we suppress the call to add_target of core_ops in corelow because 1588134147Sdavidxu if there are two targets in the stratum core_stratum, find_core_target 1589134147Sdavidxu won't know which one to return. see corelow.c for an additonal 1590134147Sdavidxu comment on coreops_suppress_target. */ 1591134147Sdavidxu 1592134147Sdavidxuint coreops_suppress_target = 1; 1593134147Sdavidxu 1594178666Sjhb/* similarly we allow this target to be completely skipped. This is used 1595178666Sjhb by kgdb which uses its own core target. */ 1596178666Sjhb 1597178666Sjhbint fbsdcoreops_suppress_target; 1598178666Sjhb 1599132179Sdavidxuvoid 1600132179Sdavidxu_initialize_thread_db (void) 1601132179Sdavidxu{ 1602178666Sjhb 1603178666Sjhb if (fbsdcoreops_suppress_target) 1604178666Sjhb return; 1605134147Sdavidxu init_fbsd_thread_ops (); 1606134147Sdavidxu init_fbsd_core_ops (); 1607134147Sdavidxu 1608132179Sdavidxu if (thread_db_load ()) 1609132179Sdavidxu { 1610134147Sdavidxu add_target (&fbsd_thread_ops); 1611132179Sdavidxu 1612132179Sdavidxu /* "thread tsd" command */ 1613132179Sdavidxu add_cmd ("tsd", class_run, fbsd_thread_tsd_cmd, 1614132179Sdavidxu "Show the thread-specific data keys and destructors " 1615132179Sdavidxu "for the process.\n", 1616132179Sdavidxu &thread_cmd_list); 1617132179Sdavidxu 1618155379Sdavidxu add_cmd ("signal", class_run, fbsd_thread_signal_cmd, 1619155379Sdavidxu "Show the thread signal info.\n", 1620155379Sdavidxu &thread_cmd_list); 1621155379Sdavidxu 1622134147Sdavidxu memcpy (&orig_core_ops, &core_ops, sizeof (struct target_ops)); 1623134147Sdavidxu memcpy (&core_ops, &fbsd_core_ops, sizeof (struct target_ops)); 1624134147Sdavidxu add_target (&core_ops); 1625134147Sdavidxu 1626132179Sdavidxu /* Add ourselves to objfile event chain. */ 1627132179Sdavidxu target_new_objfile_chain = target_new_objfile_hook; 1628132179Sdavidxu target_new_objfile_hook = fbsd_thread_new_objfile; 1629134147Sdavidxu 1630134147Sdavidxu child_suppress_run = 1; 1631132179Sdavidxu } 1632132179Sdavidxu else 1633132179Sdavidxu { 1634134147Sdavidxu fprintf_unfiltered (gdb_stderr, 1635134147Sdavidxu "[GDB will not be able to debug user-mode threads: %s]\n", dlerror()); 1636134147Sdavidxu 1637134147Sdavidxu /* allow the user to debug non-threaded core files */ 1638134147Sdavidxu add_target (&core_ops); 1639132179Sdavidxu } 1640132179Sdavidxu} 1641132179Sdavidxu 1642132179Sdavidxu/* proc service functions */ 1643132179Sdavidxuvoid 1644132179Sdavidxups_plog (const char *fmt, ...) 1645132179Sdavidxu{ 1646132179Sdavidxu va_list args; 1647132179Sdavidxu 1648132179Sdavidxu va_start (args, fmt); 1649132179Sdavidxu vfprintf_filtered (gdb_stderr, fmt, args); 1650132179Sdavidxu va_end (args); 1651132179Sdavidxu} 1652132179Sdavidxu 1653132179Sdavidxups_err_e 1654132179Sdavidxups_pglobal_lookup (struct ps_prochandle *ph, const char *obj, 1655132179Sdavidxu const char *name, psaddr_t *sym_addr) 1656132179Sdavidxu{ 1657132179Sdavidxu struct minimal_symbol *ms; 1658155379Sdavidxu CORE_ADDR addr; 1659132179Sdavidxu 1660132179Sdavidxu ms = lookup_minimal_symbol (name, NULL, NULL); 1661132179Sdavidxu if (ms == NULL) 1662132179Sdavidxu return PS_NOSYM; 1663132179Sdavidxu 1664155379Sdavidxu addr = SYMBOL_VALUE_ADDRESS (ms); 1665155379Sdavidxu store_typed_address(sym_addr, builtin_type_void_data_ptr, addr); 1666132179Sdavidxu return PS_OK; 1667132179Sdavidxu} 1668132179Sdavidxu 1669132179Sdavidxups_err_e 1670132300Smarcelps_pread (struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t len) 1671132179Sdavidxu{ 1672155379Sdavidxu int err = target_read_memory ( 1673155379Sdavidxu extract_typed_address(&addr, builtin_type_void_data_ptr), buf, len); 1674134147Sdavidxu return (err == 0 ? PS_OK : PS_ERR); 1675132179Sdavidxu} 1676132179Sdavidxu 1677132179Sdavidxups_err_e 1678132300Smarcelps_pwrite (struct ps_prochandle *ph, psaddr_t addr, const void *buf, 1679132179Sdavidxu size_t len) 1680132179Sdavidxu{ 1681155379Sdavidxu int err = target_write_memory ( 1682155379Sdavidxu extract_typed_address(&addr, builtin_type_void_data_ptr), (void *)buf, len); 1683134147Sdavidxu return (err == 0 ? PS_OK : PS_ERR); 1684132179Sdavidxu} 1685132179Sdavidxu 1686132179Sdavidxups_err_e 1687132179Sdavidxups_lgetregs (struct ps_prochandle *ph, lwpid_t lwpid, prgregset_t gregset) 1688132179Sdavidxu{ 1689132179Sdavidxu struct cleanup *old_chain; 1690132179Sdavidxu 1691132179Sdavidxu old_chain = save_inferior_ptid (); 1692140071Speadar 1693140071Speadar /* XXX: Target operation isn't lwp aware: replace pid with lwp */ 1694140071Speadar inferior_ptid = BUILD_LWP (0, lwpid); 1695140071Speadar 1696132179Sdavidxu target_fetch_registers (-1); 1697132179Sdavidxu fill_gregset (gregset, -1); 1698132179Sdavidxu do_cleanups (old_chain); 1699132179Sdavidxu return PS_OK; 1700132179Sdavidxu} 1701132179Sdavidxu 1702132179Sdavidxups_err_e 1703132179Sdavidxups_lsetregs (struct ps_prochandle *ph, lwpid_t lwpid, const prgregset_t gregset) 1704132179Sdavidxu{ 1705132179Sdavidxu struct cleanup *old_chain; 1706132179Sdavidxu 1707132179Sdavidxu old_chain = save_inferior_ptid (); 1708132179Sdavidxu inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); 1709218822Sdim supply_gregset ((gdb_gregset_t *) gregset); 1710132179Sdavidxu target_store_registers (-1); 1711132179Sdavidxu do_cleanups (old_chain); 1712132179Sdavidxu return PS_OK; 1713132179Sdavidxu} 1714132179Sdavidxu 1715132179Sdavidxups_err_e 1716132179Sdavidxups_lgetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, prfpregset_t *fpregset) 1717132179Sdavidxu{ 1718132179Sdavidxu struct cleanup *old_chain; 1719132179Sdavidxu 1720132179Sdavidxu old_chain = save_inferior_ptid (); 1721132179Sdavidxu inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); 1722132179Sdavidxu target_fetch_registers (-1); 1723132179Sdavidxu fill_fpregset (fpregset, -1); 1724132179Sdavidxu do_cleanups (old_chain); 1725132179Sdavidxu return PS_OK; 1726132179Sdavidxu} 1727132179Sdavidxu 1728132179Sdavidxups_err_e 1729132179Sdavidxups_lsetfpregs (struct ps_prochandle *ph, lwpid_t lwpid, 1730132179Sdavidxu const prfpregset_t *fpregset) 1731132179Sdavidxu{ 1732132179Sdavidxu struct cleanup *old_chain; 1733132179Sdavidxu 1734132179Sdavidxu old_chain = save_inferior_ptid (); 1735132179Sdavidxu inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); 1736218822Sdim supply_fpregset ((gdb_fpregset_t *) fpregset); 1737132179Sdavidxu target_store_registers (-1); 1738132179Sdavidxu do_cleanups (old_chain); 1739132179Sdavidxu return PS_OK; 1740132179Sdavidxu} 1741132179Sdavidxu 1742146818Sdfr#ifdef PT_GETXMMREGS 1743132179Sdavidxups_err_e 1744146818Sdfrps_lgetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, char *xmmregs) 1745146818Sdfr{ 1746146818Sdfr struct cleanup *old_chain; 1747146818Sdfr 1748146818Sdfr old_chain = save_inferior_ptid (); 1749146818Sdfr inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); 1750146818Sdfr target_fetch_registers (-1); 1751146818Sdfr i387_fill_fxsave (xmmregs, -1); 1752146818Sdfr do_cleanups (old_chain); 1753146818Sdfr return PS_OK; 1754146818Sdfr} 1755146818Sdfr 1756146818Sdfrps_err_e 1757146818Sdfrps_lsetxmmregs (struct ps_prochandle *ph, lwpid_t lwpid, 1758146818Sdfr const char *xmmregs) 1759146818Sdfr{ 1760146818Sdfr struct cleanup *old_chain; 1761146818Sdfr 1762146818Sdfr old_chain = save_inferior_ptid (); 1763146818Sdfr inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid)); 1764146818Sdfr i387_supply_fxsave (current_regcache, -1, xmmregs); 1765146818Sdfr target_store_registers (-1); 1766146818Sdfr do_cleanups (old_chain); 1767146818Sdfr return PS_OK; 1768146818Sdfr} 1769146818Sdfr#endif 1770146818Sdfr 1771146818Sdfrps_err_e 1772132179Sdavidxups_lstop(struct ps_prochandle *ph, lwpid_t lwpid) 1773132179Sdavidxu{ 1774132244Sdavidxu if (ptrace (PT_SUSPEND, lwpid, 0, 0) == -1) 1775132244Sdavidxu return PS_ERR; 1776132244Sdavidxu return PS_OK; 1777132179Sdavidxu} 1778132179Sdavidxu 1779132179Sdavidxups_err_e 1780132179Sdavidxups_lcontinue(struct ps_prochandle *ph, lwpid_t lwpid) 1781132179Sdavidxu{ 1782132244Sdavidxu if (ptrace (PT_RESUME, lwpid, 0, 0) == -1) 1783132244Sdavidxu return PS_ERR; 1784132244Sdavidxu return PS_OK; 1785132179Sdavidxu} 1786155412Sdavidxu 1787155412Sdavidxups_err_e 1788155412Sdavidxups_linfo(struct ps_prochandle *ph, lwpid_t lwpid, void *info) 1789155412Sdavidxu{ 1790155412Sdavidxu if (fbsd_thread_core) { 1791155412Sdavidxu /* XXX should verify lwpid and make a pseudo lwp info */ 1792155412Sdavidxu memset(info, 0, sizeof(struct ptrace_lwpinfo)); 1793155412Sdavidxu return PS_OK; 1794155412Sdavidxu } 1795155412Sdavidxu 1796155412Sdavidxu if (ptrace (PT_LWPINFO, lwpid, info, sizeof(struct ptrace_lwpinfo)) == -1) 1797155412Sdavidxu return PS_ERR; 1798155412Sdavidxu return PS_OK; 1799155412Sdavidxu} 1800