summaryrefslogtreecommitdiffstats
path: root/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'gnu')
-rw-r--r--gnu/usr.bin/gdb/libgdb/fbsd-threads.c544
1 files changed, 367 insertions, 177 deletions
diff --git a/gnu/usr.bin/gdb/libgdb/fbsd-threads.c b/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
index c2e6c5f..765700a 100644
--- a/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
+++ b/gnu/usr.bin/gdb/libgdb/fbsd-threads.c
@@ -19,25 +19,28 @@
Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#include "defs.h"
-
-#include "gdb_assert.h"
#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/ptrace.h>
+
#include "proc_service.h"
#include "thread_db.h"
+#include "defs.h"
#include "bfd.h"
+#include "elf-bfd.h"
+#include "gdb_assert.h"
+#include "gdbcore.h"
#include "gdbthread.h"
#include "inferior.h"
+#include "objfiles.h"
+#include "regcache.h"
#include "symfile.h"
#include "symtab.h"
-#include "objfiles.h"
#include "target.h"
-#include "regcache.h"
#include "gdbcmd.h"
#include "solib-svr4.h"
-#include <sys/ptrace.h>
#define LIBTHREAD_DB_SO "libthread_db.so"
@@ -46,18 +49,29 @@ struct ps_prochandle
pid_t pid;
};
+extern int child_suppress_run;
+
extern struct target_ops child_ops;
/* This module's target vector. */
-static struct target_ops thread_db_ops;
+static struct target_ops fbsd_thread_ops;
+static struct target_ops fbsd_core_ops;
+
+/* Saved copy of orignal core_ops. */
+static struct target_ops orig_core_ops;
+extern struct target_ops core_ops;
-static struct target_ops base_ops;
-
/* Pointer to the next function on the objfile event chain. */
static void (*target_new_objfile_chain) (struct objfile *objfile);
+/* Non-zero if there is a thread module */
+static int fbsd_thread_present;
+
/* Non-zero if we're using this module's target vector. */
-static int using_thread_db;
+static int fbsd_thread_active;
+
+/* Non-zero if core_open is called */
+static int fbsd_thread_core = 0;
/* Non-zero if we have to keep this module's target vector active
across re-runs. */
@@ -78,6 +92,7 @@ static ptid_t last_single_step_thread;
static td_err_e (*td_init_p) (void);
static td_err_e (*td_ta_new_p) (struct ps_prochandle *ps, td_thragent_t **ta);
+static td_err_e (*td_ta_delete_p) (td_thragent_t *);
static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
td_thrhandle_t *__th);
static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, lwpid_t lwpid,
@@ -93,7 +108,6 @@ static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
td_thr_events_t *event);
static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
td_event_msg_t *msg);
-static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
td_thrinfo_t *infop);
static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
@@ -222,24 +236,46 @@ thread_from_lwp (ptid_t ptid)
gdb_assert (IS_LWP (ptid));
- err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
- if (err == TD_OK)
+ if (fbsd_thread_active)
{
- err = td_thr_get_info_p (&th, &ti);
- if (err != TD_OK)
- error ("Cannot get thread info: %s", thread_db_err_str (err));
- return BUILD_THREAD (ti.ti_tid, GET_PID (ptid));
+ err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+ if (err == TD_OK)
+ {
+ err = td_thr_get_info_p (&th, &ti);
+ if (err != TD_OK)
+ error ("Cannot get thread info: %s", thread_db_err_str (err));
+ return BUILD_THREAD (ti.ti_tid, GET_PID (ptid));
+ }
}
/* the LWP is not mapped to user thread */
return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid));
}
+static void
+fbsd_core_get_first_lwp (bfd *abfd, asection *asect, void *obj)
+{
+ if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
+ return;
+
+ if (*(lwpid_t *)obj != 0)
+ return;
+
+ *(lwpid_t *)obj = atoi (bfd_section_name (abfd, asect) + 5);
+}
+
static long
get_current_lwp (int pid)
{
struct ptrace_lwpinfo pl;
+ lwpid_t lwpid;
+ if (!target_has_execution)
+ {
+ lwpid = 0;
+ bfd_map_over_sections (core_bfd, fbsd_core_get_first_lwp, &lwpid);
+ return lwpid;
+ }
if (ptrace (PT_LWPINFO, pid, (caddr_t)&pl, sizeof(pl)))
perror_with_name("PT_LWPINFO");
@@ -263,29 +299,50 @@ get_current_thread ()
}
static void
+fbsd_thread_activate (void)
+{
+ fbsd_thread_active = 1;
+ init_thread_list();
+ fbsd_thread_find_new_threads ();
+ get_current_thread ();
+}
+
+static void
+fbsd_thread_deactivate (void)
+{
+ td_ta_delete_p (thread_agent);
+
+ inferior_ptid = pid_to_ptid (proc_handle.pid);
+ proc_handle.pid = 0;
+ fbsd_thread_active = 0;
+ fbsd_thread_present = 0;
+ init_thread_list ();
+}
+
+static void
fbsd_thread_new_objfile (struct objfile *objfile)
{
td_err_e err;
/* Don't attempt to use thread_db on targets which can not run
(core files). */
- if (objfile == NULL || !target_has_execution)
+ if (objfile == NULL)
{
/* All symbols have been discarded. If the thread_db target is
active, deactivate it now. */
- if (using_thread_db)
+ if (fbsd_thread_active)
{
gdb_assert (proc_handle.pid == 0);
- unpush_target (&thread_db_ops);
- using_thread_db = 0;
+ fbsd_thread_active = 0;
}
- keep_thread_db = 0;
-
goto quit;
}
- if (using_thread_db)
+ if (!child_suppress_run)
+ goto quit;
+
+ if (fbsd_thread_active)
/* Nothing to do. The thread library was already detected and the
target vector was already activated. */
goto quit;
@@ -305,32 +362,21 @@ fbsd_thread_new_objfile (struct objfile *objfile)
case TD_OK:
/* The thread library was detected. Activate the thread_db target. */
- base_ops = current_target;
- push_target (&thread_db_ops);
- using_thread_db = 1;
-
- /* If the thread library was detected in the main symbol file
- itself, we assume that the program was statically linked
- against the thread library and well have to keep this
- module's target vector activated until forever... Well, at
- least until all symbols have been discarded anyway (see
- above). */
- if (objfile == symfile_objfile)
- {
- gdb_assert (proc_handle.pid == 0);
- keep_thread_db = 1;
- }
+ fbsd_thread_present = 1;
/* We can only poke around if there actually is a child process.
If there is no child process alive, postpone the steps below
until one has been created. */
- if (proc_handle.pid != 0)
+ if (fbsd_thread_core == 0 && proc_handle.pid != 0)
{
- fbsd_thread_find_new_threads ();
- get_current_thread ();
+ push_target(&fbsd_thread_ops);
+ fbsd_thread_activate();
}
else
- printf_filtered("%s postpone processing\n", __func__);
+ {
+ td_ta_delete_p(thread_agent);
+ thread_agent = NULL;
+ }
break;
default:
@@ -347,23 +393,41 @@ fbsd_thread_new_objfile (struct objfile *objfile)
static void
fbsd_thread_attach (char *args, int from_tty)
{
+ fbsd_thread_core = 0;
+
child_ops.to_attach (args, from_tty);
- /* Destroy thread info; it's no longer valid. */
- init_thread_list ();
+ /* Must get symbols from solibs before libthread_db can run! */
+ SOLIB_ADD ((char *) 0, from_tty, (struct target_ops *) 0, auto_solib_add);
- /* The child process is now the actual multi-threaded
- program. Snatch its process ID... */
- proc_handle.pid = GET_PID (inferior_ptid);
+ if (fbsd_thread_present && !fbsd_thread_active)
+ push_target(&fbsd_thread_ops);
+}
- /* ...and perform the remaining initialization steps. */
- fbsd_thread_find_new_threads();
- get_current_thread ();
+static void
+fbsd_thread_post_attach (int pid)
+{
+ child_ops.to_post_attach (pid);
+
+ if (fbsd_thread_present && !fbsd_thread_active)
+ {
+ proc_handle.pid = GET_PID (inferior_ptid);
+ fbsd_thread_activate ();
+ }
}
static void
fbsd_thread_detach (char *args, int from_tty)
{
+ fbsd_thread_deactivate ();
+ unpush_target (&fbsd_thread_ops);
+
+ /* Clear gdb solib information and symbol file
+ cache, so that after detach and re-attach, new_objfile
+ hook will be called */
+
+ clear_solib();
+ symbol_file_clear(0);
proc_handle.pid = 0;
child_ops.to_detach (args, from_tty);
}
@@ -373,7 +437,7 @@ suspend_thread_callback (const td_thrhandle_t *th_p, void *data)
{
int err = td_thr_dbsuspend_p (th_p);
if (err != 0)
- printf_filtered("%s %s\n", __func__, thread_db_err_str (err));
+ fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err));
return (err);
}
@@ -382,7 +446,7 @@ resume_thread_callback (const td_thrhandle_t *th_p, void *data)
{
int err = td_thr_dbresume_p (th_p);
if (err != 0)
- printf_filtered("%s %s\n", __func__, thread_db_err_str (err));
+ fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err));
return (err);
}
@@ -395,17 +459,9 @@ fbsd_thread_resume (ptid_t ptid, int step, enum target_signal signo)
int resume_all, ret;
long lwp, thvalid = 0;
-#if 0
- printf_filtered("%s ptid=%ld.%ld.%ld step=%d\n", __func__,
- GET_PID(ptid), GET_LWP(ptid), GET_THREAD(ptid), step);
- printf_filtered("%s inferior_ptid=%ld.%ld.%ld\n", __func__,
- GET_PID(inferior_ptid), GET_LWP(inferior_ptid),
- GET_THREAD(inferior_ptid));
-#endif
-
- if (proc_handle.pid == 0)
+ if (!fbsd_thread_active)
{
- base_ops.to_resume (ptid, step, signo);
+ child_ops.to_resume (ptid, step, signo);
return;
}
@@ -502,7 +558,7 @@ fbsd_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
ret = child_ops.to_wait (ptid, ourstatus);
if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED)
{
- lwp = get_current_lwp (proc_handle.pid);
+ lwp = get_current_lwp (GET_PID(ret));
ret = thread_from_lwp (BUILD_LWP (lwp, GET_PID (ret)));
if (!in_thread_list (ret))
add_thread (ret);
@@ -525,8 +581,16 @@ static int
fbsd_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
struct mem_attrib *attrib, struct target_ops *target)
{
- return base_ops.to_xfer_memory (memaddr, myaddr, len, write,
- attrib, target);
+ int err;
+
+ if (target_has_execution)
+ err = child_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib,
+ target);
+ else
+ err = orig_core_ops.to_xfer_memory (memaddr, myaddr, len, write, attrib,
+ target);
+
+ return (err);
}
static void
@@ -536,7 +600,12 @@ fbsd_lwp_fetch_registers (int regno)
fpregset_t fpregs;
lwpid_t lwp;
- /* FIXME, use base_ops to fetch lwp registers! */
+ if (!target_has_execution)
+ {
+ orig_core_ops.to_fetch_registers (-1);
+ return;
+ }
+
lwp = GET_LWP (inferior_ptid);
if (ptrace (PT_GETREGS, lwp, (caddr_t) &gregs, 0) == -1)
@@ -675,14 +744,17 @@ fbsd_thread_kill (void)
child_ops.to_kill();
}
+static int
+fbsd_thread_can_run (void)
+{
+ return child_suppress_run;
+}
+
static void
fbsd_thread_create_inferior (char *exec_file, char *allargs, char **env)
{
- if (!keep_thread_db)
- {
- unpush_target (&thread_db_ops);
- using_thread_db = 0;
- }
+ if (fbsd_thread_present && !fbsd_thread_active)
+ push_target(&fbsd_thread_ops);
child_ops.to_create_inferior (exec_file, allargs, env);
}
@@ -690,16 +762,15 @@ fbsd_thread_create_inferior (char *exec_file, char *allargs, char **env)
static void
fbsd_thread_post_startup_inferior (ptid_t ptid)
{
- if (proc_handle.pid == 0)
+ if (fbsd_thread_present && !fbsd_thread_active)
{
/*
* The child process is now the actual multi-threaded
* program. Snatch its process ID...
*/
proc_handle.pid = GET_PID (ptid);
-
- fbsd_thread_find_new_threads ();
- get_current_thread ();
+ td_ta_new_p (&proc_handle, &thread_agent);
+ fbsd_thread_activate();
}
}
@@ -710,11 +781,31 @@ fbsd_thread_mourn_inferior (void)
* Forget about the child's process ID. We shouldn't need it
* anymore.
*/
- proc_handle.pid = 0;
+ if (fbsd_thread_active)
+ fbsd_thread_deactivate ();
+
+ unpush_target (&fbsd_thread_ops);
child_ops.to_mourn_inferior ();
}
+static void
+fbsd_core_check_lwp (bfd *abfd, asection *asect, void *obj)
+{
+ lwpid_t lwp;
+
+ if (strncmp (bfd_section_name (abfd, asect), ".reg/", 5) != 0)
+ return;
+
+ /* already found */
+ if (*(lwpid_t *)obj == 0)
+ return;
+
+ lwp = atoi (bfd_section_name (abfd, asect) + 5);
+ if (*(lwpid_t *)obj == lwp)
+ *(lwpid_t *)obj = 0;
+}
+
static int
fbsd_thread_alive (ptid_t ptid)
{
@@ -722,6 +813,7 @@ fbsd_thread_alive (ptid_t ptid)
td_thrinfo_t ti;
td_err_e err;
gregset_t gregs;
+ lwpid_t lwp;
if (IS_THREAD (ptid))
{
@@ -745,19 +837,35 @@ fbsd_thread_alive (ptid_t ptid)
return 1;
}
- err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+ if (fbsd_thread_active)
+ {
+ err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
- /*
- * if the lwp was already mapped to user thread, don't use it
- * directly, please use user thread id instead.
- */
- if (err == TD_OK)
- return 0;
+ /*
+ * if the lwp was already mapped to user thread, don't use it
+ * directly, please use user thread id instead.
+ */
+ if (err == TD_OK)
+ return 0;
+ }
+
+ if (!target_has_execution)
+ {
+ lwp = GET_LWP (ptid);
+ bfd_map_over_sections (core_bfd, fbsd_core_check_lwp, &lwp);
+ return (lwp == 0);
+ }
/* check lwp in kernel */
return ptrace (PT_GETREGS, GET_LWP (ptid), (caddr_t)&gregs, 0) == 0;
}
+static void
+fbsd_thread_files_info (struct target_ops *ignore)
+{
+ child_ops.to_files_info (ignore);
+}
+
static int
find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
{
@@ -773,11 +881,10 @@ find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
return 0;
- ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid));
+ ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid);
if (!in_thread_list (ptid))
add_thread (ptid);
-
return 0;
}
@@ -786,6 +893,9 @@ fbsd_thread_find_new_threads (void)
{
td_err_e err;
+ if (!fbsd_thread_active)
+ return;
+
/* Iterate over all user-space threads to discover new threads. */
err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
@@ -908,108 +1018,168 @@ tsd_cb (thread_key_t key, void (*destructor)(void *), void *ignore)
static void
fbsd_thread_tsd_cmd (char *exp, int from_tty)
{
- td_ta_tsd_iter_p (thread_agent, tsd_cb, NULL);
+ if (fbsd_thread_active)
+ td_ta_tsd_iter_p (thread_agent, tsd_cb, NULL);
}
-static void
-init_thread_db_ops (void)
+static int
+ignore (CORE_ADDR addr, char *contents)
{
- thread_db_ops.to_shortname = "multi-thread";
- thread_db_ops.to_longname = "multi-threaded child process.";
- thread_db_ops.to_doc = "Threads and pthreads support.";
- thread_db_ops.to_attach = fbsd_thread_attach;
- thread_db_ops.to_detach = fbsd_thread_detach;
- thread_db_ops.to_resume = fbsd_thread_resume;
- thread_db_ops.to_wait = fbsd_thread_wait;
- thread_db_ops.to_fetch_registers = fbsd_thread_fetch_registers;
- thread_db_ops.to_store_registers = fbsd_thread_store_registers;
- thread_db_ops.to_xfer_memory = fbsd_thread_xfer_memory;
- thread_db_ops.to_kill = fbsd_thread_kill;
- thread_db_ops.to_create_inferior = fbsd_thread_create_inferior;
- thread_db_ops.to_post_startup_inferior = fbsd_thread_post_startup_inferior;
- thread_db_ops.to_mourn_inferior = fbsd_thread_mourn_inferior;
- thread_db_ops.to_thread_alive = fbsd_thread_alive;
- thread_db_ops.to_find_new_threads = fbsd_thread_find_new_threads;
- thread_db_ops.to_pid_to_str = fbsd_thread_pid_to_str;
- thread_db_ops.to_stratum = thread_stratum;
- thread_db_ops.to_has_thread_control = tc_none;
- thread_db_ops.to_insert_breakpoint = memory_insert_breakpoint;
- thread_db_ops.to_remove_breakpoint = memory_remove_breakpoint;
- thread_db_ops.to_get_thread_local_address = fbsd_thread_get_local_address;
- thread_db_ops.to_magic = OPS_MAGIC;
+ return 0;
}
-static int
-thread_db_load (void)
+static void
+fbsd_core_open (char *filename, int from_tty)
{
- void *handle;
- td_err_e err;
+ int err;
- handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
- if (handle == NULL)
- return 0;
+ fbsd_thread_core = 1;
- td_init_p = dlsym (handle, "td_init");
- if (td_init_p == NULL)
- return 0;
+ orig_core_ops.to_open (filename, from_tty);
- td_ta_new_p = dlsym (handle, "td_ta_new");
- if (td_ta_new_p == NULL)
- return 0;
-
- td_ta_map_id2thr_p = dlsym (handle, "td_ta_map_id2thr");
- if (td_ta_map_id2thr_p == NULL)
- return 0;
-
- td_ta_map_lwp2thr_p = dlsym (handle, "td_ta_map_lwp2thr");
- if (td_ta_map_lwp2thr_p == NULL)
- return 0;
-
- td_ta_thr_iter_p = dlsym (handle, "td_ta_thr_iter");
- if (td_ta_thr_iter_p == NULL)
- return 0;
-
- td_thr_validate_p = dlsym (handle, "td_thr_validate");
- if (td_thr_validate_p == NULL)
- return 0;
-
- td_thr_get_info_p = dlsym (handle, "td_thr_get_info");
- if (td_thr_get_info_p == NULL)
- return 0;
-
- td_thr_getfpregs_p = dlsym (handle, "td_thr_getfpregs");
- if (td_thr_getfpregs_p == NULL)
- return 0;
+ if (fbsd_thread_present)
+ {
+ err = td_ta_new_p (&proc_handle, &thread_agent);
+ if (err == TD_OK)
+ {
+ proc_handle.pid = elf_tdata (core_bfd)->core_pid;
+ fbsd_thread_activate ();
+ }
+ else
+ error ("fbsd_core_open: td_open: %s", thread_db_err_str (err));
+ }
+}
- td_thr_getgregs_p = dlsym (handle, "td_thr_getgregs");
- if (td_thr_getgregs_p == NULL)
- return 0;
+static void
+fbsd_core_close (int quitting)
+{
+ orig_core_ops.to_close (quitting);
+}
- td_thr_setfpregs_p = dlsym (handle, "td_thr_setfpregs");
- if (td_thr_setfpregs_p == NULL)
- return 0;
+static void
+fbsd_core_detach (char *args, int from_tty)
+{
+ if (fbsd_thread_active)
+ fbsd_thread_deactivate ();
+ unpush_target (&fbsd_thread_ops);
+ orig_core_ops.to_detach (args, from_tty);
+
+ /* Clear gdb solib information and symbol file
+ cache, so that after detach and re-attach, new_objfile
+ hook will be called */
+ clear_solib();
+ symbol_file_clear(0);
+}
- td_thr_setgregs_p = dlsym (handle, "td_thr_setgregs");
- if (td_thr_setgregs_p == NULL)
- return 0;
+static void
+fbsd_core_files_info (struct target_ops *ignore)
+{
+ orig_core_ops.to_files_info (ignore);
+}
- td_thr_sstep_p = dlsym(handle, "td_thr_sstep");
- if (td_thr_sstep_p == NULL)
- return 0;
+static void
+init_fbsd_core_ops (void)
+{
+ fbsd_core_ops.to_shortname = "FreeBSD-core";
+ fbsd_core_ops.to_longname = "FreeBSD core thread.";
+ fbsd_core_ops.to_doc = "FreeBSD thread support for core files.";
+ fbsd_core_ops.to_open = fbsd_core_open;
+ fbsd_core_ops.to_close = fbsd_core_close;
+ fbsd_core_ops.to_attach = 0;
+ fbsd_core_ops.to_post_attach = 0;
+ fbsd_core_ops.to_detach = fbsd_core_detach;
+ /* fbsd_core_ops.to_resume = 0; */
+ /* fbsd_core_ops.to_wait = 0; */
+ fbsd_core_ops.to_fetch_registers = fbsd_thread_fetch_registers;
+ /* fbsd_core_ops.to_store_registers = 0; */
+ /* fbsd_core_ops.to_prepare_to_store = 0; */
+ fbsd_core_ops.to_xfer_memory = fbsd_thread_xfer_memory;
+ fbsd_core_ops.to_files_info = fbsd_core_files_info;
+ fbsd_core_ops.to_insert_breakpoint = ignore;
+ fbsd_core_ops.to_remove_breakpoint = ignore;
+ /* fbsd_core_ops.to_lookup_symbol = 0; */
+ fbsd_core_ops.to_create_inferior = fbsd_thread_create_inferior;
+ fbsd_core_ops.to_stratum = core_stratum;
+ fbsd_core_ops.to_has_all_memory = 0;
+ fbsd_core_ops.to_has_memory = 1;
+ fbsd_core_ops.to_has_stack = 1;
+ fbsd_core_ops.to_has_registers = 1;
+ fbsd_core_ops.to_has_execution = 0;
+ fbsd_core_ops.to_has_thread_control = tc_none;
+ fbsd_core_ops.to_thread_alive = fbsd_thread_alive;
+ fbsd_core_ops.to_pid_to_str = fbsd_thread_pid_to_str;
+ fbsd_core_ops.to_find_new_threads = fbsd_thread_find_new_threads;
+ fbsd_core_ops.to_sections = 0;
+ fbsd_core_ops.to_sections_end = 0;
+ fbsd_core_ops.to_magic = OPS_MAGIC;
+}
- td_ta_tsd_iter_p = dlsym (handle, "td_ta_tsd_iter");
- if (td_ta_tsd_iter_p == NULL)
- return 0;
+static void
+init_fbsd_thread_ops (void)
+{
+ fbsd_thread_ops.to_shortname = "freebsd-threads";
+ fbsd_thread_ops.to_longname = "FreeBSD multithreaded child process.";
+ fbsd_thread_ops.to_doc = "FreeBSD threads support.";
+ fbsd_thread_ops.to_attach = fbsd_thread_attach;
+ fbsd_thread_ops.to_detach = fbsd_thread_detach;
+ fbsd_thread_ops.to_post_attach = fbsd_thread_post_attach;
+ fbsd_thread_ops.to_resume = fbsd_thread_resume;
+ fbsd_thread_ops.to_wait = fbsd_thread_wait;
+ fbsd_thread_ops.to_fetch_registers = fbsd_thread_fetch_registers;
+ fbsd_thread_ops.to_store_registers = fbsd_thread_store_registers;
+ fbsd_thread_ops.to_xfer_memory = fbsd_thread_xfer_memory;
+ fbsd_thread_ops.to_files_info = fbsd_thread_files_info;
+ fbsd_thread_ops.to_kill = fbsd_thread_kill;
+ fbsd_thread_ops.to_create_inferior = fbsd_thread_create_inferior;
+ fbsd_thread_ops.to_post_startup_inferior = fbsd_thread_post_startup_inferior;
+ fbsd_thread_ops.to_mourn_inferior = fbsd_thread_mourn_inferior;
+ fbsd_thread_ops.to_can_run = fbsd_thread_can_run;
+ fbsd_thread_ops.to_thread_alive = fbsd_thread_alive;
+ fbsd_thread_ops.to_find_new_threads = fbsd_thread_find_new_threads;
+ fbsd_thread_ops.to_pid_to_str = fbsd_thread_pid_to_str;
+ fbsd_thread_ops.to_stratum = thread_stratum;
+ fbsd_thread_ops.to_has_thread_control = tc_none;
+ fbsd_thread_ops.to_has_all_memory = 1;
+ fbsd_thread_ops.to_has_memory = 1;
+ fbsd_thread_ops.to_has_stack = 1;
+ fbsd_thread_ops.to_has_registers = 1;
+ fbsd_thread_ops.to_has_execution = 1;
+ fbsd_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
+ fbsd_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
+ fbsd_thread_ops.to_get_thread_local_address = fbsd_thread_get_local_address;
+ fbsd_thread_ops.to_magic = OPS_MAGIC;
+}
- td_thr_dbsuspend_p = dlsym (handle, "td_thr_dbsuspend");
- if (td_thr_dbsuspend_p == NULL)
- return 0;
+static int
+thread_db_load (void)
+{
+ void *handle;
+ td_err_e err;
- td_thr_dbresume_p = dlsym (handle, "td_thr_dbresume");
- if (td_thr_dbresume_p == NULL)
- return 0;
+ handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
+ if (handle == NULL)
+ return 0;
- td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
+#define resolve(X) \
+ if (!(X##_p = dlsym (handle, #X))) \
+ return 0;
+
+ resolve(td_init);
+ resolve(td_ta_new);
+ resolve(td_ta_delete);
+ resolve(td_ta_map_id2thr);
+ resolve(td_ta_map_lwp2thr);
+ resolve(td_ta_thr_iter);
+ resolve(td_thr_get_info);
+ resolve(td_thr_getfpregs);
+ resolve(td_thr_getgregs);
+ resolve(td_thr_setfpregs);
+ resolve(td_thr_setgregs);
+ resolve(td_thr_sstep);
+ resolve(td_ta_tsd_iter);
+ resolve(td_thr_dbsuspend);
+ resolve(td_thr_dbresume);
+ resolve(td_thr_tls_get_addr);
/* Initialize the library. */
err = td_init_p ();
@@ -1022,14 +1192,22 @@ thread_db_load (void)
return 1;
}
+/* we suppress the call to add_target of core_ops in corelow because
+ if there are two targets in the stratum core_stratum, find_core_target
+ won't know which one to return. see corelow.c for an additonal
+ comment on coreops_suppress_target. */
+
+int coreops_suppress_target = 1;
+
void
_initialize_thread_db (void)
{
- /* Only initialize the module if we can load libthread_db. */
+ init_fbsd_thread_ops ();
+ init_fbsd_core_ops ();
+
if (thread_db_load ())
{
- init_thread_db_ops ();
- add_target (&thread_db_ops);
+ add_target (&fbsd_thread_ops);
/* "thread tsd" command */
add_cmd ("tsd", class_run, fbsd_thread_tsd_cmd,
@@ -1037,13 +1215,23 @@ _initialize_thread_db (void)
"for the process.\n",
&thread_cmd_list);
+ memcpy (&orig_core_ops, &core_ops, sizeof (struct target_ops));
+ memcpy (&core_ops, &fbsd_core_ops, sizeof (struct target_ops));
+ add_target (&core_ops);
+
/* Add ourselves to objfile event chain. */
target_new_objfile_chain = target_new_objfile_hook;
target_new_objfile_hook = fbsd_thread_new_objfile;
+
+ child_suppress_run = 1;
}
else
{
- printf_filtered("%s: can not load %s.\n", __func__, LIBTHREAD_DB_SO);
+ fprintf_unfiltered (gdb_stderr,
+ "[GDB will not be able to debug user-mode threads: %s]\n", dlerror());
+
+ /* allow the user to debug non-threaded core files */
+ add_target (&core_ops);
}
}
@@ -1075,14 +1263,16 @@ ps_pglobal_lookup (struct ps_prochandle *ph, const char *obj,
ps_err_e
ps_pread (struct ps_prochandle *ph, psaddr_t addr, void *buf, size_t len)
{
- return target_read_memory ((CORE_ADDR) addr, buf, len);
+ int err = target_read_memory ((CORE_ADDR) addr, buf, len);
+ return (err == 0 ? PS_OK : PS_ERR);
}
ps_err_e
ps_pwrite (struct ps_prochandle *ph, psaddr_t addr, const void *buf,
size_t len)
{
- return target_write_memory ((CORE_ADDR) addr, (void *)buf, len);
+ int err = target_write_memory ((CORE_ADDR) addr, (void *)buf, len);
+ return (err == 0 ? PS_OK : PS_ERR);
}
ps_err_e
OpenPOWER on IntegriCloud