/* Handle SVR4 shared libraries for GDB, the GNU Debugger.
- Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000,
- 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 1990-1996, 1998-2001, 2003-2012 Free Software
+ Foundation, Inc.
This file is part of GDB.
#include "exec.h"
#include "auxv.h"
#include "exceptions.h"
+#include "gdb_bfd.h"
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
static int svr4_have_link_map_offsets (void);
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;
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
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;
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);
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;
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);
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;
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);
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
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);
return 1;
}
+/* Data exchange structure for the XML parser as returned by
+ svr4_current_sos_via_xfer_libraries. */
+
+struct svr4_library_list
+{
+ struct so_list *head, **tailp;
+
+ /* Inferior address of struct link_map used for the main executable. It is
+ NULL if not known. */
+ CORE_ADDR main_lm;
+};
+
/* Implementation for target_so_ops.free_so. */
static void
{
struct so_list *next = list->next;
- svr4_free_so (list);
+ free_so (list);
list = next;
}
}
+#ifdef HAVE_LIBEXPAT
+
+#include "xml-support.h"
+
+/* Handle the start of a <library> element. Note: new elements are added
+ at the tail of the list, keeping the list in order. */
+
+static void
+library_list_start_library (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct svr4_library_list *list = user_data;
+ const char *name = xml_find_attribute (attributes, "name")->value;
+ ULONGEST *lmp = xml_find_attribute (attributes, "lm")->value;
+ ULONGEST *l_addrp = xml_find_attribute (attributes, "l_addr")->value;
+ ULONGEST *l_ldp = xml_find_attribute (attributes, "l_ld")->value;
+ struct so_list *new_elem;
+
+ new_elem = XZALLOC (struct so_list);
+ new_elem->lm_info = XZALLOC (struct lm_info);
+ new_elem->lm_info->lm_addr = *lmp;
+ new_elem->lm_info->l_addr_inferior = *l_addrp;
+ new_elem->lm_info->l_ld = *l_ldp;
+
+ strncpy (new_elem->so_name, name, sizeof (new_elem->so_name) - 1);
+ new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0;
+ strcpy (new_elem->so_original_name, new_elem->so_name);
+
+ *list->tailp = new_elem;
+ list->tailp = &new_elem->next;
+}
+
+/* Handle the start of a <library-list-svr4> element. */
+
+static void
+svr4_library_list_start_list (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct svr4_library_list *list = user_data;
+ const char *version = xml_find_attribute (attributes, "version")->value;
+ struct gdb_xml_value *main_lm = xml_find_attribute (attributes, "main-lm");
+
+ if (strcmp (version, "1.0") != 0)
+ gdb_xml_error (parser,
+ _("SVR4 Library list has unsupported version \"%s\""),
+ version);
+
+ if (main_lm)
+ list->main_lm = *(ULONGEST *) main_lm->value;
+}
+
+/* The allowed elements and attributes for an XML library list.
+ The root element is a <library-list>. */
+
+static const struct gdb_xml_attribute svr4_library_attributes[] =
+{
+ { "name", GDB_XML_AF_NONE, NULL, NULL },
+ { "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element svr4_library_list_children[] =
+{
+ {
+ "library", svr4_library_attributes, NULL,
+ GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+ library_list_start_library, NULL
+ },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_attribute svr4_library_list_attributes[] =
+{
+ { "version", GDB_XML_AF_NONE, NULL, NULL },
+ { "main-lm", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+static const struct gdb_xml_element svr4_library_list_elements[] =
+{
+ { "library-list-svr4", svr4_library_list_attributes, svr4_library_list_children,
+ GDB_XML_EF_NONE, svr4_library_list_start_list, NULL },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* Parse qXfer:libraries:read packet into *SO_LIST_RETURN. Return 1 if
+
+ 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. */
+
+static int
+svr4_parse_libraries (const char *document, struct svr4_library_list *list)
+{
+ struct cleanup *back_to = make_cleanup (svr4_free_library_list,
+ &list->head);
+
+ memset (list, 0, sizeof (*list));
+ list->tailp = &list->head;
+ if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
+ svr4_library_list_elements, document, list) == 0)
+ {
+ /* Parsed successfully, keep the result. */
+ discard_cleanups (back_to);
+ return 1;
+ }
+
+ do_cleanups (back_to);
+ return 0;
+}
+
+/* Attempt to get so_list from target via qXfer:libraries: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. */
+
+static int
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list)
+{
+ char *svr4_library_document;
+ int result;
+ struct cleanup *back_to;
+
+ /* Fetch the list of shared libraries. */
+ svr4_library_document = target_read_stralloc (¤t_target,
+ TARGET_OBJECT_LIBRARIES_SVR4,
+ NULL);
+ if (svr4_library_document == NULL)
+ return 0;
+
+ back_to = make_cleanup (xfree, svr4_library_document);
+ result = svr4_parse_libraries (svr4_library_document, list);
+ do_cleanups (back_to);
+
+ return result;
+}
+
+#else
+
+static int
+svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list)
+{
+ return 0;
+}
+
+#endif
+
/* If no shared library information is available from the dynamic
linker, build a fallback list from other sources. */
if (new->lm_info->l_prev != prev_lm)
{
- warning (_("Corrupted shared library list"));
+ warning (_("Corrupted shared library list: %s != %s"),
+ paddress (target_gdbarch (), prev_lm),
+ paddress (target_gdbarch (), new->lm_info->l_prev));
do_cleanups (old_chain);
break;
}
struct svr4_info *info;
struct cleanup *back_to;
int ignore_first;
+ struct svr4_library_list library_list;
+
+ /* Fall back to manual examination of the target if the packet is not
+ supported or gdbserver failed to find DT_DEBUG. gdb.server/solib-list.exp
+ tests a case where gdbserver cannot find the shared libraries list while
+ GDB itself is able to find it via SYMFILE_OBJFILE.
+
+ Unfortunately statically linked inferiors will also fall back through this
+ suboptimal code path. */
+
+ if (svr4_current_sos_via_xfer_libraries (&library_list))
+ {
+ if (library_list.main_lm)
+ {
+ info = get_svr4_info ();
+ info->main_lm_addr = library_list.main_lm;
+ }
+
+ return library_list.head ? library_list.head : svr4_default_sos ();
+ }
info = get_svr4_info ();
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,
+ return gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
bfd_get_start_address (abfd),
targ);
}
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));
+ bfd_section_size (tmp_bfd, interp_sect);
}
- create_solib_event_breakpoint (target_gdbarch, sym_addr);
+ create_solib_event_breakpoint (target_gdbarch (), sym_addr);
return 1;
}
}
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. */
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
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));
/* 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. */
+ /* 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, 0);
if (sym_addr != 0)
{
- create_solib_event_breakpoint (target_gdbarch, load_addr + sym_addr);
+ create_solib_event_breakpoint (target_gdbarch (), load_addr + sym_addr);
xfree (interp_name);
return 1;
}
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);
+ create_solib_event_breakpoint (target_gdbarch (), sym_addr);
return 1;
}
}
- if (!current_inferior ()->attach_flag)
+ if (interp_name != NULL && !current_inferior ()->attach_flag)
{
for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
{
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);
+ create_solib_event_breakpoint (target_gdbarch (), sym_addr);
return 1;
}
}
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
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));
}
clear_proceed_status ();
inf->control.stop_soon = STOP_QUIETLY;
- tp->suspend.stop_signal = TARGET_SIGNAL_0;
+ 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 != TARGET_SIGNAL_TRAP);
+ while (tp->suspend.stop_signal != GDB_SIGNAL_TRAP);
inf->control.stop_soon = NO_STOP_QUIETLY;
#endif /* defined(_SCO_DS) */
}
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);
}
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 ();
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);
}
{
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;