Index: gdb/solib-svr4.c |
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c |
index 307e48392fe17ef3ca0d6dcf45df1b500ed99dbf..9538af602e213dc8d93c33f5bd49b8602a92f781 100644 |
--- a/gdb/solib-svr4.c |
+++ b/gdb/solib-svr4.c |
@@ -1,7 +1,6 @@ |
/* Handle SVR4 shared libraries for GDB, the GNU Debugger. |
- Copyright (C) 1990-1996, 1998-2001, 2003-2012 Free Software |
- Foundation, Inc. |
+ Copyright (C) 1990-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -46,10 +45,13 @@ |
#include "exec.h" |
#include "auxv.h" |
#include "exceptions.h" |
+#include "gdb_bfd.h" |
+#include "probe.h" |
static struct link_map_offsets *svr4_fetch_link_map_offsets (void); |
static int svr4_have_link_map_offsets (void); |
static void svr4_relocate_main_executable (void); |
+static void svr4_free_library_list (void *p_list); |
/* Link map info to include in an allocated so_list entry. */ |
@@ -106,6 +108,55 @@ static const char * const main_name_list[] = |
NULL |
}; |
+/* What to do when a probe stop occurs. */ |
+ |
+enum probe_action |
+{ |
+ /* Something went seriously wrong. Stop using probes and |
+ revert to using the older interface. */ |
+ PROBES_INTERFACE_FAILED, |
+ |
+ /* No action is required. The shared object list is still |
+ valid. */ |
+ DO_NOTHING, |
+ |
+ /* The shared object list should be reloaded entirely. */ |
+ FULL_RELOAD, |
+ |
+ /* Attempt to incrementally update the shared object list. If |
+ the update fails or is not possible, fall back to reloading |
+ the list in full. */ |
+ UPDATE_OR_RELOAD, |
+}; |
+ |
+/* A probe's name and its associated action. */ |
+ |
+struct probe_info |
+{ |
+ /* The name of the probe. */ |
+ const char *name; |
+ |
+ /* What to do when a probe stop occurs. */ |
+ enum probe_action action; |
+}; |
+ |
+/* A list of named probes and their associated actions. If all |
+ probes are present in the dynamic linker then the probes-based |
+ interface will be used. */ |
+ |
+static const struct probe_info probe_info[] = |
+{ |
+ { "init_start", DO_NOTHING }, |
+ { "init_complete", FULL_RELOAD }, |
+ { "map_start", DO_NOTHING }, |
+ { "map_failed", DO_NOTHING }, |
+ { "reloc_complete", UPDATE_OR_RELOAD }, |
+ { "unmap_start", DO_NOTHING }, |
+ { "unmap_complete", FULL_RELOAD }, |
+}; |
+ |
+#define NUM_PROBES ARRAY_SIZE (probe_info) |
+ |
/* Return non-zero if GDB_SO_NAME and INFERIOR_SO_NAME represent |
the same shared library. */ |
@@ -154,12 +205,12 @@ lm_info_read (CORE_ADDR lm_addr) |
if (target_read_memory (lm_addr, lm, lmo->link_map_size) != 0) |
{ |
warning (_("Error reading shared library list entry at %s"), |
- paddress (target_gdbarch, lm_addr)), |
+ paddress (target_gdbarch (), lm_addr)), |
lm_info = NULL; |
} |
else |
{ |
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; |
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; |
lm_info = xzalloc (sizeof (*lm_info)); |
lm_info->lm_addr = lm_addr; |
@@ -189,7 +240,7 @@ has_lm_dynamic_from_link_map (void) |
} |
static CORE_ADDR |
-lm_addr_check (struct so_list *so, bfd *abfd) |
+lm_addr_check (const struct so_list *so, bfd *abfd) |
{ |
if (!so->lm_info->l_addr_p) |
{ |
@@ -263,7 +314,7 @@ lm_addr_check (struct so_list *so, bfd *abfd) |
if (info_verbose) |
printf_unfiltered (_("Using PIC (Position Independent Code) " |
"prelink displacement %s for \"%s\".\n"), |
- paddress (target_gdbarch, l_addr), |
+ paddress (target_gdbarch (), l_addr), |
so->so_name); |
} |
else |
@@ -313,17 +364,54 @@ struct svr4_info |
CORE_ADDR interp_text_sect_high; |
CORE_ADDR interp_plt_sect_low; |
CORE_ADDR interp_plt_sect_high; |
+ |
+ /* Nonzero if the list of objects was last obtained from the target |
+ via qXfer:libraries-svr4:read. */ |
+ int using_xfer; |
+ |
+ /* Table of struct probe_and_action instances, used by the |
+ probes-based interface to map breakpoint addresses to probes |
+ and their associated actions. Lookup is performed using |
+ probe_and_action->probe->address. */ |
+ htab_t probes_table; |
+ |
+ /* List of objects loaded into the inferior, used by the probes- |
+ based interface. */ |
+ struct so_list *solib_list; |
}; |
/* Per-program-space data key. */ |
static const struct program_space_data *solib_svr4_pspace_data; |
+/* Free the probes table. */ |
+ |
+static void |
+free_probes_table (struct svr4_info *info) |
+{ |
+ if (info->probes_table == NULL) |
+ return; |
+ |
+ htab_delete (info->probes_table); |
+ info->probes_table = NULL; |
+} |
+ |
+/* Free the solib list. */ |
+ |
+static void |
+free_solib_list (struct svr4_info *info) |
+{ |
+ svr4_free_library_list (&info->solib_list); |
+ info->solib_list = NULL; |
+} |
+ |
static void |
svr4_pspace_data_cleanup (struct program_space *pspace, void *arg) |
{ |
- struct svr4_info *info; |
+ struct svr4_info *info = arg; |
+ |
+ free_probes_table (info); |
+ free_solib_list (info); |
- info = program_space_data (pspace, solib_svr4_pspace_data); |
xfree (info); |
} |
@@ -362,7 +450,7 @@ static int match_main (const char *); |
static gdb_byte * |
read_program_header (int type, int *p_sect_size, int *p_arch_size) |
{ |
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); |
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); |
CORE_ADDR at_phdr, at_phent, at_phnum, pt_phdr = 0; |
int arch_size, sect_size; |
CORE_ADDR sect_addr; |
@@ -496,7 +584,7 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) |
/* Return program interpreter string. */ |
-static gdb_byte * |
+static char * |
find_program_interpreter (void) |
{ |
gdb_byte *buf = NULL; |
@@ -521,7 +609,7 @@ find_program_interpreter (void) |
if (!buf) |
buf = read_program_header (PT_INTERP, NULL, NULL); |
- return buf; |
+ return (char *) buf; |
} |
@@ -611,7 +699,7 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) |
gdb_byte ptr_buf[8]; |
CORE_ADDR ptr_addr; |
- ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; |
+ ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; |
ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8; |
if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0) |
dyn_ptr = extract_typed_address (ptr_buf, ptr_type); |
@@ -631,7 +719,7 @@ scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr) |
static int |
scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr) |
{ |
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); |
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); |
int sect_size, arch_size, step; |
long dyn_tag; |
CORE_ADDR dyn_ptr; |
@@ -708,7 +796,7 @@ elf_locate_base (void) |
if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr) |
|| scan_dyntag_auxv (DT_MIPS_RLD_MAP, &dyn_ptr)) |
{ |
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; |
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; |
gdb_byte *pbuf; |
int pbuf_size = TYPE_LENGTH (ptr_type); |
@@ -786,7 +874,7 @@ static CORE_ADDR |
solib_svr4_r_map (struct svr4_info *info) |
{ |
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); |
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; |
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; |
CORE_ADDR addr = 0; |
volatile struct gdb_exception ex; |
@@ -805,7 +893,7 @@ static CORE_ADDR |
solib_svr4_r_brk (struct svr4_info *info) |
{ |
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); |
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; |
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; |
return read_memory_typed_address (info->debug_base + lmo->r_brk_offset, |
ptr_type); |
@@ -818,8 +906,8 @@ static CORE_ADDR |
solib_svr4_r_ldsomap (struct svr4_info *info) |
{ |
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); |
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; |
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); |
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; |
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); |
ULONGEST version; |
/* Check version, and return zero if `struct r_debug' doesn't have |
@@ -848,7 +936,6 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) |
CORE_ADDR ldsomap; |
struct so_list *new; |
struct cleanup *old_chain; |
- struct link_map_offsets *lmo; |
CORE_ADDR name_lm; |
info = get_svr4_info (); |
@@ -862,7 +949,6 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) |
if (!ldsomap) |
return 0; |
- lmo = svr4_fetch_link_map_offsets (); |
new = XZALLOC (struct so_list); |
old_chain = make_cleanup (xfree, new); |
new->lm_info = lm_info_read (ldsomap); |
@@ -888,7 +974,7 @@ open_symbol_file_object (void *from_ttyp) |
int errcode; |
int from_tty = *(int *)from_ttyp; |
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); |
- struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; |
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; |
int l_name_size = TYPE_LENGTH (ptr_type); |
gdb_byte *l_name_buf = xmalloc (l_name_size); |
struct cleanup *cleanups = make_cleanup (xfree, l_name_buf); |
@@ -968,6 +1054,15 @@ svr4_free_so (struct so_list *so) |
xfree (so->lm_info); |
} |
+/* Implement target_so_ops.clear_so. */ |
+ |
+static void |
+svr4_clear_so (struct so_list *so) |
+{ |
+ if (so->lm_info != NULL) |
+ so->lm_info->l_addr_p = 0; |
+} |
+ |
/* Free so_list built so far (called via cleanup). */ |
static void |
@@ -979,11 +1074,39 @@ svr4_free_library_list (void *p_list) |
{ |
struct so_list *next = list->next; |
- svr4_free_so (list); |
+ free_so (list); |
list = next; |
} |
} |
+/* Copy library list. */ |
+ |
+static struct so_list * |
+svr4_copy_library_list (struct so_list *src) |
+{ |
+ struct so_list *dst = NULL; |
+ struct so_list **link = &dst; |
+ |
+ while (src != NULL) |
+ { |
+ struct so_list *new; |
+ |
+ new = xmalloc (sizeof (struct so_list)); |
+ memcpy (new, src, sizeof (struct so_list)); |
+ |
+ new->lm_info = xmalloc (sizeof (struct lm_info)); |
+ memcpy (new->lm_info, src->lm_info, sizeof (struct lm_info)); |
+ |
+ new->next = NULL; |
+ *link = new; |
+ link = &new->next; |
+ |
+ src = src->next; |
+ } |
+ |
+ return dst; |
+} |
+ |
#ifdef HAVE_LIBEXPAT |
#include "xml-support.h" |
@@ -1099,23 +1222,30 @@ svr4_parse_libraries (const char *document, struct svr4_library_list *list) |
return 0; |
} |
-/* Attempt to get so_list from target via qXfer:libraries:read packet. |
+/* Attempt to get so_list from target via qXfer:libraries-svr4:read packet. |
Return 0 if packet not supported, *SO_LIST_RETURN is not modified in such |
case. Return 1 if *SO_LIST_RETURN contains the library list, it may be |
- empty, caller is responsible for freeing all its entries. */ |
+ empty, caller is responsible for freeing all its entries. |
+ |
+ Note that ANNEX must be NULL if the remote does not explicitly allow |
+ qXfer:libraries-svr4:read packets with non-empty annexes. Support for |
+ this can be checked using target_augmented_libraries_svr4_read (). */ |
static int |
-svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list) |
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list, |
+ const char *annex) |
{ |
char *svr4_library_document; |
int result; |
struct cleanup *back_to; |
+ gdb_assert (annex == NULL || target_augmented_libraries_svr4_read ()); |
+ |
/* Fetch the list of shared libraries. */ |
svr4_library_document = target_read_stralloc (¤t_target, |
TARGET_OBJECT_LIBRARIES_SVR4, |
- NULL); |
+ annex); |
if (svr4_library_document == NULL) |
return 0; |
@@ -1129,7 +1259,8 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list) |
#else |
static int |
-svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list) |
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list, |
+ const char *annex) |
{ |
return 0; |
} |
@@ -1163,19 +1294,23 @@ svr4_default_sos (void) |
return new; |
} |
-/* Read the whole inferior libraries chain starting at address LM. Add the |
- entries to the tail referenced by LINK_PTR_PTR. Ignore the first entry if |
- IGNORE_FIRST and set global MAIN_LM_ADDR according to it. */ |
+/* Read the whole inferior libraries chain starting at address LM. |
+ Expect the first entry in the chain's previous entry to be PREV_LM. |
+ Add the entries to the tail referenced by LINK_PTR_PTR. Ignore the |
+ first entry if IGNORE_FIRST and set global MAIN_LM_ADDR according |
+ to it. Returns nonzero upon success. If zero is returned the |
+ entries stored to LINK_PTR_PTR are still valid although they may |
+ represent only part of the inferior library list. */ |
-static void |
-svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, |
- int ignore_first) |
+static int |
+svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm, |
+ struct so_list ***link_ptr_ptr, int ignore_first) |
{ |
- CORE_ADDR prev_lm = 0, next_lm; |
+ struct so_list *first = NULL; |
+ CORE_ADDR next_lm; |
for (; lm != 0; prev_lm = lm, lm = next_lm) |
{ |
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); |
struct so_list *new; |
struct cleanup *old_chain; |
int errcode; |
@@ -1188,7 +1323,7 @@ svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, |
if (new->lm_info == NULL) |
{ |
do_cleanups (old_chain); |
- break; |
+ return 0; |
} |
next_lm = new->lm_info->l_next; |
@@ -1196,10 +1331,10 @@ svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, |
if (new->lm_info->l_prev != prev_lm) |
{ |
warning (_("Corrupted shared library list: %s != %s"), |
- paddress (target_gdbarch, prev_lm), |
- paddress (target_gdbarch, new->lm_info->l_prev)); |
+ paddress (target_gdbarch (), prev_lm), |
+ paddress (target_gdbarch (), new->lm_info->l_prev)); |
do_cleanups (old_chain); |
- break; |
+ return 0; |
} |
/* For SVR4 versions, the first entry in the link map is for the |
@@ -1211,6 +1346,7 @@ svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, |
{ |
struct svr4_info *info = get_svr4_info (); |
+ first = new; |
info->main_lm_addr = new->lm_info->lm_addr; |
do_cleanups (old_chain); |
continue; |
@@ -1221,8 +1357,14 @@ svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, |
SO_NAME_MAX_PATH_SIZE - 1, &errcode); |
if (errcode != 0) |
{ |
- warning (_("Can't read pathname for load map: %s."), |
- safe_strerror (errcode)); |
+ /* If this entry's l_name address matches that of the |
+ inferior executable, then this is not a normal shared |
+ object, but (most likely) a vDSO. In this case, silently |
+ skip it; otherwise emit a warning. */ |
+ if (first == NULL |
+ || new->lm_info->l_name != first->lm_info->l_name) |
+ warning (_("Can't read pathname for load map: %s."), |
+ safe_strerror (errcode)); |
do_cleanups (old_chain); |
continue; |
} |
@@ -1245,17 +1387,21 @@ svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, |
**link_ptr_ptr = new; |
*link_ptr_ptr = &new->next; |
} |
+ |
+ return 1; |
} |
-/* Implement the "current_sos" target_so_ops method. */ |
+/* Read the full list of currently loaded shared objects directly |
+ from the inferior, without referring to any libraries read and |
+ stored by the probes interface. Handle special cases relating |
+ to the first elements of the list. */ |
static struct so_list * |
-svr4_current_sos (void) |
+svr4_current_sos_direct (struct svr4_info *info) |
{ |
CORE_ADDR lm; |
struct so_list *head = NULL; |
struct so_list **link_ptr = &head; |
- struct svr4_info *info; |
struct cleanup *back_to; |
int ignore_first; |
struct svr4_library_list library_list; |
@@ -1268,19 +1414,16 @@ svr4_current_sos (void) |
Unfortunately statically linked inferiors will also fall back through this |
suboptimal code path. */ |
- if (svr4_current_sos_via_xfer_libraries (&library_list)) |
+ info->using_xfer = svr4_current_sos_via_xfer_libraries (&library_list, |
+ NULL); |
+ if (info->using_xfer) |
{ |
if (library_list.main_lm) |
- { |
- info = get_svr4_info (); |
- info->main_lm_addr = library_list.main_lm; |
- } |
+ info->main_lm_addr = library_list.main_lm; |
return library_list.head ? library_list.head : svr4_default_sos (); |
} |
- info = get_svr4_info (); |
- |
/* Always locate the debug struct, in case it has moved. */ |
info->debug_base = 0; |
locate_base (info); |
@@ -1303,7 +1446,7 @@ svr4_current_sos (void) |
`struct so_list' nodes. */ |
lm = solib_svr4_r_map (info); |
if (lm) |
- svr4_read_so_list (lm, &link_ptr, ignore_first); |
+ svr4_read_so_list (lm, 0, &link_ptr, ignore_first); |
/* On Solaris, the dynamic linker is not in the normal list of |
shared objects, so make sure we pick it up too. Having |
@@ -1311,7 +1454,7 @@ svr4_current_sos (void) |
for skipping dynamic linker resolver code. */ |
lm = solib_svr4_r_ldsomap (info); |
if (lm) |
- svr4_read_so_list (lm, &link_ptr, 0); |
+ svr4_read_so_list (lm, 0, &link_ptr, 0); |
discard_cleanups (back_to); |
@@ -1321,6 +1464,22 @@ svr4_current_sos (void) |
return head; |
} |
+/* Implement the "current_sos" target_so_ops method. */ |
+ |
+static struct so_list * |
+svr4_current_sos (void) |
+{ |
+ struct svr4_info *info = get_svr4_info (); |
+ |
+ /* If the solib list has been read and stored by the probes |
+ interface then we return a copy of the stored list. */ |
+ if (info->solib_list != NULL) |
+ return svr4_copy_library_list (info->solib_list); |
+ |
+ /* Otherwise obtain the solib list directly from the inferior. */ |
+ return svr4_current_sos_direct (info); |
+} |
+ |
/* Get the address of the link_map for a given OBJFILE. */ |
CORE_ADDR |
@@ -1377,7 +1536,7 @@ svr4_in_dynsym_resolve_code (CORE_ADDR pc) |
&& pc < info->interp_text_sect_high) |
|| (pc >= info->interp_plt_sect_low |
&& pc < info->interp_plt_sect_high) |
- || in_plt_section (pc, NULL) |
+ || in_plt_section (pc) |
|| in_gnu_ifunc_stub (pc)); |
} |
@@ -1387,6 +1546,8 @@ svr4_in_dynsym_resolve_code (CORE_ADDR pc) |
static CORE_ADDR |
exec_entry_point (struct bfd *abfd, struct target_ops *targ) |
{ |
+ CORE_ADDR addr; |
+ |
/* KevinB wrote ... for most targets, the address returned by |
bfd_get_start_address() is the entry point for the start |
function. But, for some targets, bfd_get_start_address() returns |
@@ -1395,9 +1556,494 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ) |
gdbarch_convert_from_func_ptr_addr(). The method |
gdbarch_convert_from_func_ptr_addr() is the merely the identify |
function for targets which don't use function descriptors. */ |
- return gdbarch_convert_from_func_ptr_addr (target_gdbarch, |
+ addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (), |
bfd_get_start_address (abfd), |
targ); |
+ return gdbarch_addr_bits_remove (target_gdbarch (), addr); |
+} |
+ |
+/* A probe and its associated action. */ |
+ |
+struct probe_and_action |
+{ |
+ /* The probe. */ |
+ struct probe *probe; |
+ |
+ /* The action. */ |
+ enum probe_action action; |
+}; |
+ |
+/* Returns a hash code for the probe_and_action referenced by p. */ |
+ |
+static hashval_t |
+hash_probe_and_action (const void *p) |
+{ |
+ const struct probe_and_action *pa = p; |
+ |
+ return (hashval_t) pa->probe->address; |
+} |
+ |
+/* Returns non-zero if the probe_and_actions referenced by p1 and p2 |
+ are equal. */ |
+ |
+static int |
+equal_probe_and_action (const void *p1, const void *p2) |
+{ |
+ const struct probe_and_action *pa1 = p1; |
+ const struct probe_and_action *pa2 = p2; |
+ |
+ return pa1->probe->address == pa2->probe->address; |
+} |
+ |
+/* Register a solib event probe and its associated action in the |
+ probes table. */ |
+ |
+static void |
+register_solib_event_probe (struct probe *probe, enum probe_action action) |
+{ |
+ struct svr4_info *info = get_svr4_info (); |
+ struct probe_and_action lookup, *pa; |
+ void **slot; |
+ |
+ /* Create the probes table, if necessary. */ |
+ if (info->probes_table == NULL) |
+ info->probes_table = htab_create_alloc (1, hash_probe_and_action, |
+ equal_probe_and_action, |
+ xfree, xcalloc, xfree); |
+ |
+ lookup.probe = probe; |
+ slot = htab_find_slot (info->probes_table, &lookup, INSERT); |
+ gdb_assert (*slot == HTAB_EMPTY_ENTRY); |
+ |
+ pa = XCNEW (struct probe_and_action); |
+ pa->probe = probe; |
+ pa->action = action; |
+ |
+ *slot = pa; |
+} |
+ |
+/* Get the solib event probe at the specified location, and the |
+ action associated with it. Returns NULL if no solib event probe |
+ was found. */ |
+ |
+static struct probe_and_action * |
+solib_event_probe_at (struct svr4_info *info, CORE_ADDR address) |
+{ |
+ struct probe lookup_probe; |
+ struct probe_and_action lookup; |
+ void **slot; |
+ |
+ lookup_probe.address = address; |
+ lookup.probe = &lookup_probe; |
+ slot = htab_find_slot (info->probes_table, &lookup, NO_INSERT); |
+ |
+ if (slot == NULL) |
+ return NULL; |
+ |
+ return (struct probe_and_action *) *slot; |
+} |
+ |
+/* Decide what action to take when the specified solib event probe is |
+ hit. */ |
+ |
+static enum probe_action |
+solib_event_probe_action (struct probe_and_action *pa) |
+{ |
+ enum probe_action action; |
+ unsigned probe_argc; |
+ |
+ action = pa->action; |
+ if (action == DO_NOTHING || action == PROBES_INTERFACE_FAILED) |
+ return action; |
+ |
+ gdb_assert (action == FULL_RELOAD || action == UPDATE_OR_RELOAD); |
+ |
+ /* Check that an appropriate number of arguments has been supplied. |
+ We expect: |
+ arg0: Lmid_t lmid (mandatory) |
+ arg1: struct r_debug *debug_base (mandatory) |
+ arg2: struct link_map *new (optional, for incremental updates) */ |
+ probe_argc = get_probe_argument_count (pa->probe); |
+ if (probe_argc == 2) |
+ action = FULL_RELOAD; |
+ else if (probe_argc < 2) |
+ action = PROBES_INTERFACE_FAILED; |
+ |
+ return action; |
+} |
+ |
+/* Populate the shared object list by reading the entire list of |
+ shared objects from the inferior. Handle special cases relating |
+ to the first elements of the list. Returns nonzero on success. */ |
+ |
+static int |
+solist_update_full (struct svr4_info *info) |
+{ |
+ free_solib_list (info); |
+ info->solib_list = svr4_current_sos_direct (info); |
+ |
+ return 1; |
+} |
+ |
+/* Update the shared object list starting from the link-map entry |
+ passed by the linker in the probe's third argument. Returns |
+ nonzero if the list was successfully updated, or zero to indicate |
+ failure. */ |
+ |
+static int |
+solist_update_incremental (struct svr4_info *info, CORE_ADDR lm) |
+{ |
+ struct so_list *tail; |
+ CORE_ADDR prev_lm; |
+ |
+ /* svr4_current_sos_direct contains logic to handle a number of |
+ special cases relating to the first elements of the list. To |
+ avoid duplicating this logic we defer to solist_update_full |
+ if the list is empty. */ |
+ if (info->solib_list == NULL) |
+ return 0; |
+ |
+ /* Fall back to a full update if we are using a remote target |
+ that does not support incremental transfers. */ |
+ if (info->using_xfer && !target_augmented_libraries_svr4_read ()) |
+ return 0; |
+ |
+ /* Walk to the end of the list. */ |
+ for (tail = info->solib_list; tail->next != NULL; tail = tail->next) |
+ /* Nothing. */; |
+ prev_lm = tail->lm_info->lm_addr; |
+ |
+ /* Read the new objects. */ |
+ if (info->using_xfer) |
+ { |
+ struct svr4_library_list library_list; |
+ char annex[64]; |
+ |
+ xsnprintf (annex, sizeof (annex), "start=%s;prev=%s", |
+ phex_nz (lm, sizeof (lm)), |
+ phex_nz (prev_lm, sizeof (prev_lm))); |
+ if (!svr4_current_sos_via_xfer_libraries (&library_list, annex)) |
+ return 0; |
+ |
+ tail->next = library_list.head; |
+ } |
+ else |
+ { |
+ struct so_list **link = &tail->next; |
+ |
+ /* IGNORE_FIRST may safely be set to zero here because the |
+ above check and deferral to solist_update_full ensures |
+ that this call to svr4_read_so_list will never see the |
+ first element. */ |
+ if (!svr4_read_so_list (lm, prev_lm, &link, 0)) |
+ return 0; |
+ } |
+ |
+ return 1; |
+} |
+ |
+/* Disable the probes-based linker interface and revert to the |
+ original interface. We don't reset the breakpoints as the |
+ ones set up for the probes-based interface are adequate. */ |
+ |
+static void |
+disable_probes_interface_cleanup (void *arg) |
+{ |
+ struct svr4_info *info = get_svr4_info (); |
+ |
+ warning (_("Probes-based dynamic linker interface failed.\n" |
+ "Reverting to original interface.\n")); |
+ |
+ free_probes_table (info); |
+ free_solib_list (info); |
+} |
+ |
+/* Update the solib list as appropriate when using the |
+ probes-based linker interface. Do nothing if using the |
+ standard interface. */ |
+ |
+static void |
+svr4_handle_solib_event (void) |
+{ |
+ struct svr4_info *info = get_svr4_info (); |
+ struct probe_and_action *pa; |
+ enum probe_action action; |
+ struct cleanup *old_chain, *usm_chain; |
+ struct value *val; |
+ CORE_ADDR pc, debug_base, lm = 0; |
+ int is_initial_ns; |
+ |
+ /* Do nothing if not using the probes interface. */ |
+ if (info->probes_table == NULL) |
+ return; |
+ |
+ /* If anything goes wrong we revert to the original linker |
+ interface. */ |
+ old_chain = make_cleanup (disable_probes_interface_cleanup, NULL); |
+ |
+ pc = regcache_read_pc (get_current_regcache ()); |
+ pa = solib_event_probe_at (info, pc); |
+ if (pa == NULL) |
+ { |
+ do_cleanups (old_chain); |
+ return; |
+ } |
+ |
+ action = solib_event_probe_action (pa); |
+ if (action == PROBES_INTERFACE_FAILED) |
+ { |
+ do_cleanups (old_chain); |
+ return; |
+ } |
+ |
+ if (action == DO_NOTHING) |
+ { |
+ discard_cleanups (old_chain); |
+ return; |
+ } |
+ |
+ /* evaluate_probe_argument looks up symbols in the dynamic linker |
+ using find_pc_section. find_pc_section is accelerated by a cache |
+ called the section map. The section map is invalidated every |
+ time a shared library is loaded or unloaded, and if the inferior |
+ is generating a lot of shared library events then the section map |
+ will be updated every time svr4_handle_solib_event is called. |
+ We called find_pc_section in svr4_create_solib_event_breakpoints, |
+ so we can guarantee that the dynamic linker's sections are in the |
+ section map. We can therefore inhibit section map updates across |
+ these calls to evaluate_probe_argument and save a lot of time. */ |
+ inhibit_section_map_updates (current_program_space); |
+ usm_chain = make_cleanup (resume_section_map_updates_cleanup, |
+ current_program_space); |
+ |
+ val = evaluate_probe_argument (pa->probe, 1); |
+ if (val == NULL) |
+ { |
+ do_cleanups (old_chain); |
+ return; |
+ } |
+ |
+ debug_base = value_as_address (val); |
+ if (debug_base == 0) |
+ { |
+ do_cleanups (old_chain); |
+ return; |
+ } |
+ |
+ /* Always locate the debug struct, in case it moved. */ |
+ info->debug_base = 0; |
+ if (locate_base (info) == 0) |
+ { |
+ do_cleanups (old_chain); |
+ return; |
+ } |
+ |
+ /* GDB does not currently support libraries loaded via dlmopen |
+ into namespaces other than the initial one. We must ignore |
+ any namespace other than the initial namespace here until |
+ support for this is added to GDB. */ |
+ if (debug_base != info->debug_base) |
+ action = DO_NOTHING; |
+ |
+ if (action == UPDATE_OR_RELOAD) |
+ { |
+ val = evaluate_probe_argument (pa->probe, 2); |
+ if (val != NULL) |
+ lm = value_as_address (val); |
+ |
+ if (lm == 0) |
+ action = FULL_RELOAD; |
+ } |
+ |
+ /* Resume section map updates. */ |
+ do_cleanups (usm_chain); |
+ |
+ if (action == UPDATE_OR_RELOAD) |
+ { |
+ if (!solist_update_incremental (info, lm)) |
+ action = FULL_RELOAD; |
+ } |
+ |
+ if (action == FULL_RELOAD) |
+ { |
+ if (!solist_update_full (info)) |
+ { |
+ do_cleanups (old_chain); |
+ return; |
+ } |
+ } |
+ |
+ discard_cleanups (old_chain); |
+} |
+ |
+/* Helper function for svr4_update_solib_event_breakpoints. */ |
+ |
+static int |
+svr4_update_solib_event_breakpoint (struct breakpoint *b, void *arg) |
+{ |
+ struct bp_location *loc; |
+ |
+ if (b->type != bp_shlib_event) |
+ { |
+ /* Continue iterating. */ |
+ return 0; |
+ } |
+ |
+ for (loc = b->loc; loc != NULL; loc = loc->next) |
+ { |
+ struct svr4_info *info; |
+ struct probe_and_action *pa; |
+ |
+ info = program_space_data (loc->pspace, solib_svr4_pspace_data); |
+ if (info == NULL || info->probes_table == NULL) |
+ continue; |
+ |
+ pa = solib_event_probe_at (info, loc->address); |
+ if (pa == NULL) |
+ continue; |
+ |
+ if (pa->action == DO_NOTHING) |
+ { |
+ if (b->enable_state == bp_disabled && stop_on_solib_events) |
+ enable_breakpoint (b); |
+ else if (b->enable_state == bp_enabled && !stop_on_solib_events) |
+ disable_breakpoint (b); |
+ } |
+ |
+ break; |
+ } |
+ |
+ /* Continue iterating. */ |
+ return 0; |
+} |
+ |
+/* Enable or disable optional solib event breakpoints as appropriate. |
+ Called whenever stop_on_solib_events is changed. */ |
+ |
+static void |
+svr4_update_solib_event_breakpoints (void) |
+{ |
+ iterate_over_breakpoints (svr4_update_solib_event_breakpoint, NULL); |
+} |
+ |
+/* Create and register solib event breakpoints. PROBES is an array |
+ of NUM_PROBES elements, each of which is vector of probes. A |
+ solib event breakpoint will be created and registered for each |
+ probe. */ |
+ |
+static void |
+svr4_create_probe_breakpoints (struct gdbarch *gdbarch, |
+ VEC (probe_p) **probes) |
+{ |
+ int i; |
+ |
+ for (i = 0; i < NUM_PROBES; i++) |
+ { |
+ enum probe_action action = probe_info[i].action; |
+ struct probe *probe; |
+ int ix; |
+ |
+ for (ix = 0; |
+ VEC_iterate (probe_p, probes[i], ix, probe); |
+ ++ix) |
+ { |
+ create_solib_event_breakpoint (gdbarch, probe->address); |
+ register_solib_event_probe (probe, action); |
+ } |
+ } |
+ |
+ svr4_update_solib_event_breakpoints (); |
+} |
+ |
+/* Both the SunOS and the SVR4 dynamic linkers call a marker function |
+ before and after mapping and unmapping shared libraries. The sole |
+ purpose of this method is to allow debuggers to set a breakpoint so |
+ they can track these changes. |
+ |
+ Some versions of the glibc dynamic linker contain named probes |
+ to allow more fine grained stopping. Given the address of the |
+ original marker function, this function attempts to find these |
+ probes, and if found, sets breakpoints on those instead. If the |
+ probes aren't found, a single breakpoint is set on the original |
+ marker function. */ |
+ |
+static void |
+svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch, |
+ CORE_ADDR address) |
+{ |
+ struct obj_section *os; |
+ |
+ os = find_pc_section (address); |
+ if (os != NULL) |
+ { |
+ int with_prefix; |
+ |
+ for (with_prefix = 0; with_prefix <= 1; with_prefix++) |
+ { |
+ VEC (probe_p) *probes[NUM_PROBES]; |
+ int all_probes_found = 1; |
+ int checked_can_use_probe_arguments = 0; |
+ int i; |
+ |
+ memset (probes, 0, sizeof (probes)); |
+ for (i = 0; i < NUM_PROBES; i++) |
+ { |
+ const char *name = probe_info[i].name; |
+ struct probe *p; |
+ char buf[32]; |
+ |
+ /* Fedora 17 and Red Hat Enterprise Linux 6.2-6.4 |
+ shipped with an early version of the probes code in |
+ which the probes' names were prefixed with "rtld_" |
+ and the "map_failed" probe did not exist. The |
+ locations of the probes are otherwise the same, so |
+ we check for probes with prefixed names if probes |
+ with unprefixed names are not present. */ |
+ if (with_prefix) |
+ { |
+ xsnprintf (buf, sizeof (buf), "rtld_%s", name); |
+ name = buf; |
+ } |
+ |
+ probes[i] = find_probes_in_objfile (os->objfile, "rtld", name); |
+ |
+ /* The "map_failed" probe did not exist in early |
+ versions of the probes code in which the probes' |
+ names were prefixed with "rtld_". */ |
+ if (strcmp (name, "rtld_map_failed") == 0) |
+ continue; |
+ |
+ if (VEC_empty (probe_p, probes[i])) |
+ { |
+ all_probes_found = 0; |
+ break; |
+ } |
+ |
+ /* Ensure probe arguments can be evaluated. */ |
+ if (!checked_can_use_probe_arguments) |
+ { |
+ p = VEC_index (probe_p, probes[i], 0); |
+ if (!can_evaluate_probe_arguments (p)) |
+ { |
+ all_probes_found = 0; |
+ break; |
+ } |
+ checked_can_use_probe_arguments = 1; |
+ } |
+ } |
+ |
+ if (all_probes_found) |
+ svr4_create_probe_breakpoints (gdbarch, probes); |
+ |
+ for (i = 0; i < NUM_PROBES; i++) |
+ VEC_free (probe_p, probes[i]); |
+ |
+ if (all_probes_found) |
+ return; |
+ } |
+ } |
+ |
+ create_solib_event_breakpoint (gdbarch, address); |
} |
/* Helper function for gdb_bfd_lookup_symbol. */ |
@@ -1446,7 +2092,7 @@ enable_break (struct svr4_info *info, int from_tty) |
struct minimal_symbol *msymbol; |
const char * const *bkpt_namep; |
asection *interp_sect; |
- gdb_byte *interp_name; |
+ char *interp_name; |
CORE_ADDR sym_addr; |
info->interp_text_sect_low = info->interp_text_sect_high = 0; |
@@ -1467,7 +2113,7 @@ enable_break (struct svr4_info *info, int from_tty) |
struct obj_section *os; |
sym_addr = gdbarch_addr_bits_remove |
- (target_gdbarch, gdbarch_convert_from_func_ptr_addr (target_gdbarch, |
+ (target_gdbarch (), gdbarch_convert_from_func_ptr_addr (target_gdbarch (), |
sym_addr, |
¤t_target)); |
@@ -1483,7 +2129,7 @@ enable_break (struct svr4_info *info, int from_tty) |
That knowledge is encoded in the address, if it's Thumb the low bit |
is 1. However, we've stripped that info above and it's not clear |
what all the consequences are of passing a non-addr_bits_remove'd |
- address to create_solib_event_breakpoint. The call to |
+ address to svr4_create_solib_event_breakpoints. The call to |
find_pc_section verifies we know about the address and have some |
hope of computing the right kind of breakpoint to use (via |
symbol info). It does mean that GDB needs to be pointed at a |
@@ -1500,7 +2146,7 @@ enable_break (struct svr4_info *info, int from_tty) |
tmp_bfd = os->objfile->obfd; |
load_addr = ANOFFSET (os->objfile->section_offsets, |
- os->objfile->sect_index_text); |
+ SECT_OFF_TEXT (os->objfile)); |
interp_sect = bfd_get_section_by_name (tmp_bfd, ".text"); |
if (interp_sect) |
@@ -1521,7 +2167,7 @@ enable_break (struct svr4_info *info, int from_tty) |
+ bfd_section_size (tmp_bfd, interp_sect); |
} |
- create_solib_event_breakpoint (target_gdbarch, sym_addr); |
+ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr); |
return 1; |
} |
} |
@@ -1558,9 +2204,11 @@ enable_break (struct svr4_info *info, int from_tty) |
goto bkpt_at_symbol; |
/* Now convert the TMP_BFD into a target. That way target, as |
- well as BFD operations can be used. Note that closing the |
- target will also close the underlying bfd. */ |
+ well as BFD operations can be used. */ |
tmp_bfd_target = target_bfd_reopen (tmp_bfd); |
+ /* target_bfd_reopen acquired its own reference, so we can |
+ release ours now. */ |
+ gdb_bfd_unref (tmp_bfd); |
/* On a running target, we can get the dynamic linker's base |
address from the shared library table. */ |
@@ -1582,7 +2230,7 @@ enable_break (struct svr4_info *info, int from_tty) |
if (!load_addr_found) |
if (target_auxv_search (¤t_target, AT_BASE, &load_addr) > 0) |
{ |
- int addr_bit = gdbarch_addr_bit (target_gdbarch); |
+ int addr_bit = gdbarch_addr_bit (target_gdbarch ()); |
/* Ensure LOAD_ADDR has proper sign in its possible upper bits so |
that `+ load_addr' will overflow CORE_ADDR width not creating |
@@ -1618,7 +2266,7 @@ enable_break (struct svr4_info *info, int from_tty) |
if (!load_addr_found) |
{ |
struct regcache *regcache |
- = get_thread_arch_regcache (inferior_ptid, target_gdbarch); |
+ = get_thread_arch_regcache (inferior_ptid, target_gdbarch ()); |
load_addr = (regcache_read_pc (regcache) |
- exec_entry_point (tmp_bfd, tmp_bfd_target)); |
@@ -1666,17 +2314,19 @@ enable_break (struct svr4_info *info, int from_tty) |
/* Convert 'sym_addr' from a function pointer to an address. |
Because we pass tmp_bfd_target instead of the current |
target, this will always produce an unrelocated value. */ |
- sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, |
+ sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (), |
sym_addr, |
tmp_bfd_target); |
- /* We're done with both the temporary bfd and target. Remember, |
- closing the target closes the underlying bfd. */ |
- target_close (tmp_bfd_target, 0); |
+ /* We're done with both the temporary bfd and target. Closing |
+ the target closes the underlying bfd, because it holds the |
+ only remaining reference. */ |
+ target_close (tmp_bfd_target); |
if (sym_addr != 0) |
{ |
- create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr); |
+ svr4_create_solib_event_breakpoints (target_gdbarch (), |
+ load_addr + sym_addr); |
xfree (interp_name); |
return 1; |
} |
@@ -1699,10 +2349,10 @@ enable_break (struct svr4_info *info, int from_tty) |
if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) |
{ |
sym_addr = SYMBOL_VALUE_ADDRESS (msymbol); |
- sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, |
+ sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (), |
sym_addr, |
¤t_target); |
- create_solib_event_breakpoint (target_gdbarch, sym_addr); |
+ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr); |
return 1; |
} |
} |
@@ -1715,10 +2365,10 @@ enable_break (struct svr4_info *info, int from_tty) |
if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0)) |
{ |
sym_addr = SYMBOL_VALUE_ADDRESS (msymbol); |
- sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, |
+ sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (), |
sym_addr, |
¤t_target); |
- create_solib_event_breakpoint (target_gdbarch, sym_addr); |
+ svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr); |
return 1; |
} |
} |
@@ -1859,7 +2509,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp) |
buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size); |
if (buf != NULL && buf2 != NULL) |
{ |
- enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); |
+ enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); |
/* We are dealing with three different addresses. EXEC_BFD |
represents current address in on-disk file. target memory content |
@@ -1954,6 +2604,28 @@ svr4_exec_displacement (CORE_ADDR *displacementp) |
if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0) |
continue; |
+ /* Strip modifies the flags and alignment of PT_GNU_RELRO. |
+ CentOS-5 has problems with filesz, memsz as well. |
+ See PR 11786. */ |
+ if (phdr2[i].p_type == PT_GNU_RELRO) |
+ { |
+ Elf32_External_Phdr tmp_phdr = *phdrp; |
+ Elf32_External_Phdr tmp_phdr2 = *phdr2p; |
+ |
+ memset (tmp_phdr.p_filesz, 0, 4); |
+ memset (tmp_phdr.p_memsz, 0, 4); |
+ memset (tmp_phdr.p_flags, 0, 4); |
+ memset (tmp_phdr.p_align, 0, 4); |
+ memset (tmp_phdr2.p_filesz, 0, 4); |
+ memset (tmp_phdr2.p_memsz, 0, 4); |
+ memset (tmp_phdr2.p_flags, 0, 4); |
+ memset (tmp_phdr2.p_align, 0, 4); |
+ |
+ if (memcmp (&tmp_phdr, &tmp_phdr2, sizeof (tmp_phdr)) |
+ == 0) |
+ continue; |
+ } |
+ |
/* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS. */ |
plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt"); |
if (plt2_asect) |
@@ -2063,6 +2735,28 @@ svr4_exec_displacement (CORE_ADDR *displacementp) |
if (memcmp (phdrp, phdr2p, sizeof (*phdrp)) == 0) |
continue; |
+ /* Strip modifies the flags and alignment of PT_GNU_RELRO. |
+ CentOS-5 has problems with filesz, memsz as well. |
+ See PR 11786. */ |
+ if (phdr2[i].p_type == PT_GNU_RELRO) |
+ { |
+ Elf64_External_Phdr tmp_phdr = *phdrp; |
+ Elf64_External_Phdr tmp_phdr2 = *phdr2p; |
+ |
+ memset (tmp_phdr.p_filesz, 0, 8); |
+ memset (tmp_phdr.p_memsz, 0, 8); |
+ memset (tmp_phdr.p_flags, 0, 4); |
+ memset (tmp_phdr.p_align, 0, 8); |
+ memset (tmp_phdr2.p_filesz, 0, 8); |
+ memset (tmp_phdr2.p_memsz, 0, 8); |
+ memset (tmp_phdr2.p_flags, 0, 4); |
+ memset (tmp_phdr2.p_align, 0, 8); |
+ |
+ if (memcmp (&tmp_phdr, &tmp_phdr2, sizeof (tmp_phdr)) |
+ == 0) |
+ continue; |
+ } |
+ |
/* prelink can convert .plt SHT_NOBITS to SHT_PROGBITS. */ |
plt2_asect = bfd_get_section_by_name (exec_bfd, ".plt"); |
if (plt2_asect) |
@@ -2114,7 +2808,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp) |
printf_unfiltered (_("Using PIE (Position Independent Executable) " |
"displacement %s for \"%s\".\n"), |
- paddress (target_gdbarch, displacement), |
+ paddress (target_gdbarch (), displacement), |
bfd_get_filename (exec_bfd)); |
} |
@@ -2205,29 +2899,19 @@ svr4_relocate_main_executable (void) |
This function is responsible for discovering those names and |
addresses, and saving sufficient information about them to allow |
- their symbols to be read at a later time. |
- |
- FIXME |
- |
- Between enable_break() and disable_break(), this code does not |
- properly handle hitting breakpoints which the user might have |
- set in the startup code or in the dynamic linker itself. Proper |
- handling will probably have to wait until the implementation is |
- changed to use the "breakpoint handler function" method. |
- |
- Also, what if child has exit()ed? Must exit loop somehow. */ |
+ their symbols to be read at a later time. */ |
static void |
svr4_solib_create_inferior_hook (int from_tty) |
{ |
-#if defined(_SCO_DS) |
- struct inferior *inf; |
- struct thread_info *tp; |
-#endif /* defined(_SCO_DS) */ |
struct svr4_info *info; |
info = get_svr4_info (); |
+ /* Clear the probes-based interface's state. */ |
+ free_probes_table (info); |
+ free_solib_list (info); |
+ |
/* Relocate the main executable if necessary. */ |
svr4_relocate_main_executable (); |
@@ -2241,31 +2925,6 @@ svr4_solib_create_inferior_hook (int from_tty) |
if (!enable_break (info, from_tty)) |
return; |
- |
-#if defined(_SCO_DS) |
- /* SCO needs the loop below, other systems should be using the |
- special shared library breakpoints and the shared library breakpoint |
- service routine. |
- |
- Now run the target. It will eventually hit the breakpoint, at |
- which point all of the libraries will have been mapped in and we |
- can go groveling around in the dynamic linker structures to find |
- out what we need to know about them. */ |
- |
- inf = current_inferior (); |
- tp = inferior_thread (); |
- |
- clear_proceed_status (); |
- inf->control.stop_soon = STOP_QUIETLY; |
- tp->suspend.stop_signal = GDB_SIGNAL_0; |
- do |
- { |
- target_resume (pid_to_ptid (-1), 0, tp->suspend.stop_signal); |
- wait_for_inferior (); |
- } |
- while (tp->suspend.stop_signal != GDB_SIGNAL_TRAP); |
- inf->control.stop_soon = NO_STOP_QUIETLY; |
-#endif /* defined(_SCO_DS) */ |
} |
static void |
@@ -2297,12 +2956,12 @@ svr4_clear_solib (void) |
static CORE_ADDR |
svr4_truncate_ptr (CORE_ADDR addr) |
{ |
- if (gdbarch_ptr_bit (target_gdbarch) == sizeof (CORE_ADDR) * 8) |
+ if (gdbarch_ptr_bit (target_gdbarch ()) == sizeof (CORE_ADDR) * 8) |
/* We don't need to truncate anything, and the bit twiddling below |
will fail due to overflow problems. */ |
return addr; |
else |
- return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch)) - 1); |
+ return addr & (((CORE_ADDR) 1 << gdbarch_ptr_bit (target_gdbarch ())) - 1); |
} |
@@ -2310,10 +2969,10 @@ static void |
svr4_relocate_section_addresses (struct so_list *so, |
struct target_section *sec) |
{ |
- sec->addr = svr4_truncate_ptr (sec->addr + lm_addr_check (so, |
- sec->bfd)); |
- sec->endaddr = svr4_truncate_ptr (sec->endaddr + lm_addr_check (so, |
- sec->bfd)); |
+ bfd *abfd = sec->the_bfd_section->owner; |
+ |
+ sec->addr = svr4_truncate_ptr (sec->addr + lm_addr_check (so, abfd)); |
+ sec->endaddr = svr4_truncate_ptr (sec->endaddr + lm_addr_check (so, abfd)); |
} |
@@ -2360,7 +3019,7 @@ set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch, |
static struct link_map_offsets * |
svr4_fetch_link_map_offsets (void) |
{ |
- struct solib_svr4_ops *ops = gdbarch_data (target_gdbarch, solib_svr4_data); |
+ struct solib_svr4_ops *ops = gdbarch_data (target_gdbarch (), solib_svr4_data); |
gdb_assert (ops->fetch_link_map_offsets); |
return ops->fetch_link_map_offsets (); |
@@ -2371,7 +3030,7 @@ svr4_fetch_link_map_offsets (void) |
static int |
svr4_have_link_map_offsets (void) |
{ |
- struct solib_svr4_ops *ops = gdbarch_data (target_gdbarch, solib_svr4_data); |
+ struct solib_svr4_ops *ops = gdbarch_data (target_gdbarch (), solib_svr4_data); |
return (ops->fetch_link_map_offsets != NULL); |
} |
@@ -2480,10 +3139,11 @@ _initialize_svr4_solib (void) |
{ |
solib_svr4_data = gdbarch_data_register_pre_init (solib_svr4_init); |
solib_svr4_pspace_data |
- = register_program_space_data_with_cleanup (svr4_pspace_data_cleanup); |
+ = register_program_space_data_with_cleanup (NULL, svr4_pspace_data_cleanup); |
svr4_so_ops.relocate_section_addresses = svr4_relocate_section_addresses; |
svr4_so_ops.free_so = svr4_free_so; |
+ svr4_so_ops.clear_so = svr4_clear_so; |
svr4_so_ops.clear_solib = svr4_clear_solib; |
svr4_so_ops.solib_create_inferior_hook = svr4_solib_create_inferior_hook; |
svr4_so_ops.special_symbol_handling = svr4_special_symbol_handling; |
@@ -2494,4 +3154,6 @@ _initialize_svr4_solib (void) |
svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; |
svr4_so_ops.same = svr4_same; |
svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; |
+ svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints; |
+ svr4_so_ops.handle_event = svr4_handle_solib_event; |
} |