| 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;
|
| }
|
|
|