/* libthread_db assisted debugging support, generic parts.
- Copyright 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "target.h"
#include "regcache.h"
#include "solib-svr4.h"
+#include "gdbcore.h"
+#include "linux-nat.h"
#ifdef HAVE_GNU_LIBC_VERSION_H
#include <gnu/libc-version.h>
return err;
/* Set up the breakpoint. */
- (*bp) = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
- (CORE_ADDR) notify.u.bptaddr,
- ¤t_target);
+ gdb_assert (exec_bfd);
+ (*bp) = (gdbarch_convert_from_func_ptr_addr
+ (current_gdbarch,
+ /* Do proper sign extension for the target. */
+ (bfd_get_sign_extend_vma (exec_bfd) > 0
+ ? (CORE_ADDR) (intptr_t) notify.u.bptaddr
+ : (CORE_ADDR) (uintptr_t) notify.u.bptaddr),
+ ¤t_target));
create_thread_event_breakpoint ((*bp));
return TD_OK;
#endif
}
-static void
-thread_db_new_objfile (struct objfile *objfile)
+/* Check whether thread_db is usable. This function is called when
+ an inferior is created (or otherwise acquired, e.g. attached to)
+ and when new shared libraries are loaded into a running process. */
+
+void
+check_for_thread_db (void)
{
td_err_e err;
+ static int already_loaded;
/* 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. The real
- problem here is that libthread_db is loaded too early - it should
- only be loaded when there is a program to debug. */
- {
- static int dejavu;
- if (!dejavu)
- {
- Dl_info info;
- const char *library = NULL;
- /* Try dladdr. */
- if (dladdr ((*td_ta_new_p), &info) != 0)
- library = info.dli_fname;
- /* Try dlinfo? */
- if (library == NULL)
- /* Paranoid - don't let a NULL path slip through. */
- library = LIBTHREAD_DB_SO;
- printf_unfiltered (_("Using host libthread_db library \"%s\".\n"),
- library);
- dejavu = 1;
- }
- }
+ the interpreter and it's console haven't started. */
- /* Don't attempt to use thread_db on targets which can not run
- (core files). */
- if (objfile == NULL || !target_has_execution)
+ if (!already_loaded)
{
- /* All symbols have been discarded. If the thread_db target is
- active, deactivate it now. */
- if (using_thread_db)
- {
- gdb_assert (proc_handle.pid == 0);
- unpush_target (&thread_db_ops);
- using_thread_db = 0;
- }
+ Dl_info info;
+ const char *library = NULL;
+ if (dladdr ((*td_ta_new_p), &info) != 0)
+ library = info.dli_fname;
+
+ /* Try dlinfo? */
+
+ if (library == NULL)
+ /* Paranoid - don't let a NULL path slip through. */
+ library = LIBTHREAD_DB_SO;
- goto quit;
+ printf_unfiltered (_("Using host libthread_db library \"%s\".\n"),
+ library);
+ already_loaded = 1;
}
if (using_thread_db)
/* Nothing to do. The thread library was already detected and the
target vector was already activated. */
- goto quit;
+ return;
- /* Initialize the structure that identifies the child process. Note
- that at this point there is no guarantee that we actually have a
- child process. */
+ /* Don't attempt to use thread_db on targets which can not run
+ (executables not running yet, core files) for now. */
+ if (!target_has_execution)
+ return;
+
+ /* Initialize the structure that identifies the child process. */
proc_handle.pid = GET_PID (inferior_ptid);
/* Now attempt to open a connection to the thread library. */
thread_db_err_str (err));
break;
}
+}
+
+static void
+thread_db_new_objfile (struct objfile *objfile)
+{
+ if (objfile != NULL)
+ check_for_thread_db ();
-quit:
if (target_new_objfile_chain)
target_new_objfile_chain (objfile);
}
return ptid;
}
-static int
-thread_db_xfer_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len, int write,
- struct mem_attrib *attrib, struct target_ops *target)
+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 ();
- int xfer;
+ LONGEST xfer;
if (is_thread (inferior_ptid))
{
inferior_ptid = lwp_from_thread (inferior_ptid);
}
- xfer =
- target_beneath->deprecated_xfer_memory (memaddr, myaddr, len, write,
- attrib, target);
+ xfer = target_beneath->to_xfer_partial (ops, object, annex,
+ readbuf, writebuf, offset, len);
do_cleanups (old_chain);
return xfer;
if (regno != -1)
{
- char raw[MAX_REGISTER_SIZE];
+ gdb_byte raw[MAX_REGISTER_SIZE];
- deprecated_read_register_gen (regno, raw);
+ regcache_raw_collect (current_regcache, regno, raw);
thread_db_fetch_registers (-1);
regcache_raw_supply (current_regcache, regno, raw);
}
static void
thread_db_mourn_inferior (void)
{
- remove_thread_event_breakpoints ();
-
/* Forget about the child's process ID. We shouldn't need it
anymore. */
proc_handle.pid = 0;
target_beneath->to_mourn_inferior ();
+ /* Delete the old thread event breakpoints. Do this after mourning
+ the inferior, so that we don't try to uninsert them. */
+ remove_thread_event_breakpoints ();
+
/* Detach thread_db target ops. */
unpush_target (&thread_db_ops);
using_thread_db = 0;
(("%s")), thread_db_err_str (err));
/* Cast assuming host == target. Joy. */
- return (CORE_ADDR) address;
+ /* Do proper sign extension for the target. */
+ gdb_assert (exec_bfd);
+ return (bfd_get_sign_extend_vma (exec_bfd) > 0
+ ? (CORE_ADDR) (intptr_t) address
+ : (CORE_ADDR) (uintptr_t) address);
}
if (target_beneath->to_get_thread_local_address)
thread_db_ops.to_wait = thread_db_wait;
thread_db_ops.to_fetch_registers = thread_db_fetch_registers;
thread_db_ops.to_store_registers = thread_db_store_registers;
- thread_db_ops.deprecated_xfer_memory = thread_db_xfer_memory;
+ 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;