#include "regcache.h"
#include "solib-svr4.h"
#include "gdbcore.h"
+#include "observer.h"
#include "linux-nat.h"
#include <signal.h>
/* If we're running on GNU/Linux, we must explicitly attach to any new
threads. */
-/* FIXME: There is certainly some room for improvements:
- - Cache LWP ids.
- - Bypass libthread_db when fetching or storing registers for
- threads bound to a LWP. */
-
/* This module's target vector. */
static struct target_ops thread_db_ops;
/* The target vector that we call for things this module can't handle. */
static struct target_ops *target_beneath;
-/* Pointer to the next function on the objfile event chain. */
-static void (*target_new_objfile_chain) (struct objfile * objfile);
-
/* Non-zero if we're using this module's target vector. */
static int using_thread_db;
td_event_addset (&events, TD_CREATE);
#ifdef HAVE_GNU_LIBC_VERSION_H
- /* FIXME: kettenis/2000-04-23: The event reporting facility is
- broken for TD_DEATH events in glibc 2.1.3, so don't enable it for
- now. */
+ /* The event reporting facility is broken for TD_DEATH events in
+ glibc 2.1.3, so don't enable it if we have glibc but a lower
+ version. */
libc_version = gnu_get_libc_version ();
if (sscanf (libc_version, "%d.%d", &libc_major, &libc_minor) == 2
&& (libc_major > 2 || (libc_major == 2 && libc_minor > 1)))
td_err_e err;
static int already_loaded;
+ /* Do nothing if we couldn't load libthread_db.so.1. */
+ if (td_ta_new_p == NULL)
+ return;
+
/* First time through, report that libthread_db was successfuly
loaded. Can't print this in in thread_db_load as, at that stage,
the interpreter and it's console haven't started. */
{
if (objfile != NULL)
check_for_thread_db ();
-
- if (target_new_objfile_chain)
- target_new_objfile_chain (objfile);
}
/* Attach to a new thread. This function is called when we receive a
int loop = 0;
/* Bail out early if we're not at a thread event breakpoint. */
- stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK;
+ stop_pc = read_pc_pid (ptid) - gdbarch_decr_pc_after_break (current_gdbarch);
if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
return;
return ptid;
}
-static LONGEST
-thread_db_xfer_partial (struct target_ops *ops, enum target_object object,
- const char *annex, gdb_byte *readbuf,
- const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
-{
- struct cleanup *old_chain = save_inferior_ptid ();
- LONGEST xfer;
-
- if (is_thread (inferior_ptid))
- {
- /* FIXME: This seems to be necessary to make sure breakpoints
- are removed. */
- if (!target_thread_alive (inferior_ptid))
- inferior_ptid = pid_to_ptid (GET_PID (inferior_ptid));
- else
- inferior_ptid = lwp_from_thread (inferior_ptid);
- }
-
- xfer = target_beneath->to_xfer_partial (ops, object, annex,
- readbuf, writebuf, offset, len);
-
- do_cleanups (old_chain);
- return xfer;
-}
-
static void
thread_db_kill (void)
{
thread_info = find_thread_pid (ptid);
if (thread_info == NULL)
- snprintf (buf, sizeof (buf), "Thread %ld (LWP %ld) (Missing)",
+ snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld) (Missing)",
GET_THREAD (ptid), GET_LWP (ptid));
else
- snprintf (buf, sizeof (buf), "Thread %ld (LWP %ld)",
+ snprintf (buf, sizeof (buf), "Thread 0x%lx (LWP %ld)",
GET_THREAD (ptid), GET_LWP (ptid));
return buf;
thread_db_ops.to_detach = thread_db_detach;
thread_db_ops.to_resume = thread_db_resume;
thread_db_ops.to_wait = thread_db_wait;
- thread_db_ops.to_xfer_partial = thread_db_xfer_partial;
thread_db_ops.to_kill = thread_db_kill;
thread_db_ops.to_create_inferior = thread_db_create_inferior;
thread_db_ops.to_post_startup_inferior = thread_db_post_startup_inferior;
add_target (&thread_db_ops);
/* Add ourselves to objfile event chain. */
- target_new_objfile_chain = deprecated_target_new_objfile_hook;
- deprecated_target_new_objfile_hook = thread_db_new_objfile;
+ observer_attach_new_objfile (thread_db_new_objfile);
}
}