/* Handle SVR4 shared libraries for GDB, the GNU Debugger.
- Copyright (C) 1990-2014 Free Software Foundation, Inc.
+ Copyright (C) 1990-2016 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbcore.h"
#include "target.h"
#include "inferior.h"
+#include "infrun.h"
#include "regcache.h"
#include "gdbthread.h"
#include "observer.h"
-#include "gdb_assert.h"
-
#include "solist.h"
#include "solib.h"
#include "solib-svr4.h"
#include "elf-bfd.h"
#include "exec.h"
#include "auxv.h"
-#include "exceptions.h"
#include "gdb_bfd.h"
#include "probe.h"
struct lm_info *lm_info;
struct cleanup *back_to;
- lm = xmalloc (lmo->link_map_size);
+ lm = (gdb_byte *) xmalloc (lmo->link_map_size);
back_to = make_cleanup (xfree, lm);
if (target_read_memory (lm_addr, lm, lmo->link_map_size) != 0)
{
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
- lm_info = xzalloc (sizeof (*lm_info));
+ lm_info = XCNEW (struct lm_info);
lm_info->lm_addr = lm_addr;
lm_info->l_addr_inferior = extract_typed_address (&lm[lmo->l_addr_offset],
static void
svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
{
- struct svr4_info *info = arg;
+ struct svr4_info *info = (struct svr4_info *) arg;
free_probes_table (info);
free_solib_list (info);
{
struct svr4_info *info;
- info = program_space_data (current_program_space, solib_svr4_pspace_data);
+ info = (struct svr4_info *) program_space_data (current_program_space,
+ solib_svr4_pspace_data);
if (info != NULL)
return info;
Return a pointer to allocated memory holding the program header contents,
or NULL on failure. If sucessful, and unless P_SECT_SIZE is NULL, the
size of those contents is returned to P_SECT_SIZE. Likewise, the target
- architecture size (32-bit or 64-bit) is returned to P_ARCH_SIZE. */
+ architecture size (32-bit or 64-bit) is returned to P_ARCH_SIZE and
+ the base address of the section is returned in BASE_ADDR. */
static gdb_byte *
-read_program_header (int type, int *p_sect_size, int *p_arch_size)
+read_program_header (int type, int *p_sect_size, int *p_arch_size,
+ CORE_ADDR *base_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
CORE_ADDR at_phdr, at_phent, at_phnum, pt_phdr = 0;
}
/* Read in requested program header. */
- buf = xmalloc (sect_size);
+ buf = (gdb_byte *) xmalloc (sect_size);
if (target_read_memory (sect_addr, buf, sect_size))
{
xfree (buf);
*p_arch_size = arch_size;
if (p_sect_size)
*p_sect_size = sect_size;
+ if (base_addr)
+ *base_addr = sect_addr;
return buf;
}
{
int sect_size = bfd_section_size (exec_bfd, interp_sect);
- buf = xmalloc (sect_size);
+ buf = (gdb_byte *) xmalloc (sect_size);
bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, sect_size);
}
}
/* If we didn't find it, use the target auxillary vector. */
if (!buf)
- buf = read_program_header (PT_INTERP, NULL, NULL);
+ buf = read_program_header (PT_INTERP, NULL, NULL, NULL);
return (char *) buf;
}
-/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is
- returned and the corresponding PTR is set. */
+/* Scan for DESIRED_DYNTAG in .dynamic section of ABFD. If DESIRED_DYNTAG is
+ found, 1 is returned and the corresponding PTR is set. */
static int
-scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
+scan_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr,
+ CORE_ADDR *ptr_addr)
{
int arch_size, step, sect_size;
- long dyn_tag;
+ long current_dyntag;
CORE_ADDR dyn_ptr, dyn_addr;
gdb_byte *bufend, *bufstart, *buf;
Elf32_External_Dyn *x_dynp_32;
/* Read in .dynamic from the BFD. We will get the actual value
from memory later. */
sect_size = bfd_section_size (abfd, sect);
- buf = bufstart = alloca (sect_size);
+ buf = bufstart = (gdb_byte *) alloca (sect_size);
if (!bfd_get_section_contents (abfd, sect,
buf, 0, sect_size))
return 0;
if (arch_size == 32)
{
x_dynp_32 = (Elf32_External_Dyn *) buf;
- dyn_tag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
+ current_dyntag = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_tag);
dyn_ptr = bfd_h_get_32 (abfd, (bfd_byte *) x_dynp_32->d_un.d_ptr);
}
else
{
x_dynp_64 = (Elf64_External_Dyn *) buf;
- dyn_tag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
+ current_dyntag = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_tag);
dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
}
- if (dyn_tag == DT_NULL)
+ if (current_dyntag == DT_NULL)
return 0;
- if (dyn_tag == dyntag)
+ if (current_dyntag == desired_dyntag)
{
/* If requested, try to read the runtime value of this .dynamic
entry. */
{
struct type *ptr_type;
gdb_byte ptr_buf[8];
- CORE_ADDR ptr_addr;
+ CORE_ADDR ptr_addr_1;
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)
+ ptr_addr_1 = dyn_addr + (buf - bufstart) + arch_size / 8;
+ if (target_read_memory (ptr_addr_1, ptr_buf, arch_size / 8) == 0)
dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
*ptr = dyn_ptr;
+ if (ptr_addr)
+ *ptr_addr = dyn_addr + (buf - bufstart);
}
return 1;
}
return 0;
}
-/* Scan for DYNTAG in .dynamic section of the target's main executable,
- found by consulting the OS auxillary vector. If DYNTAG is found 1 is
- returned and the corresponding PTR is set. */
+/* Scan for DESIRED_DYNTAG in .dynamic section of the target's main executable,
+ found by consulting the OS auxillary vector. If DESIRED_DYNTAG is found, 1
+ is returned and the corresponding PTR is set. */
static int
-scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr)
+scan_dyntag_auxv (const int desired_dyntag, CORE_ADDR *ptr,
+ CORE_ADDR *ptr_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
int sect_size, arch_size, step;
- long dyn_tag;
+ long current_dyntag;
CORE_ADDR dyn_ptr;
+ CORE_ADDR base_addr;
gdb_byte *bufend, *bufstart, *buf;
/* Read in .dynamic section. */
- buf = bufstart = read_program_header (PT_DYNAMIC, §_size, &arch_size);
+ buf = bufstart = read_program_header (PT_DYNAMIC, §_size, &arch_size,
+ &base_addr);
if (!buf)
return 0;
{
Elf32_External_Dyn *dynp = (Elf32_External_Dyn *) buf;
- dyn_tag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag,
+ current_dyntag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag,
4, byte_order);
dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr,
4, byte_order);
{
Elf64_External_Dyn *dynp = (Elf64_External_Dyn *) buf;
- dyn_tag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag,
+ current_dyntag = extract_unsigned_integer ((gdb_byte *) dynp->d_tag,
8, byte_order);
dyn_ptr = extract_unsigned_integer ((gdb_byte *) dynp->d_un.d_ptr,
8, byte_order);
}
- if (dyn_tag == DT_NULL)
+ if (current_dyntag == DT_NULL)
break;
- if (dyn_tag == dyntag)
+ if (current_dyntag == desired_dyntag)
{
if (ptr)
*ptr = dyn_ptr;
+ if (ptr_addr)
+ *ptr_addr = base_addr + buf - bufstart;
+
xfree (bufstart);
return 1;
}
elf_locate_base (void)
{
struct bound_minimal_symbol msymbol;
- CORE_ADDR dyn_ptr;
+ CORE_ADDR dyn_ptr, dyn_ptr_addr;
/* Look for DT_MIPS_RLD_MAP first. MIPS executables use this
instead of DT_DEBUG, although they sometimes contain an unused
DT_DEBUG. */
- if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr)
- || scan_dyntag_auxv (DT_MIPS_RLD_MAP, &dyn_ptr))
+ if (scan_dyntag (DT_MIPS_RLD_MAP, exec_bfd, &dyn_ptr, NULL)
+ || scan_dyntag_auxv (DT_MIPS_RLD_MAP, &dyn_ptr, NULL))
{
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
gdb_byte *pbuf;
int pbuf_size = TYPE_LENGTH (ptr_type);
- pbuf = alloca (pbuf_size);
+ pbuf = (gdb_byte *) alloca (pbuf_size);
/* DT_MIPS_RLD_MAP contains a pointer to the address
of the dynamic link structure. */
if (target_read_memory (dyn_ptr, pbuf, pbuf_size))
return extract_typed_address (pbuf, ptr_type);
}
+ /* Then check DT_MIPS_RLD_MAP_REL. MIPS executables now use this form
+ because of needing to support PIE. DT_MIPS_RLD_MAP will also exist
+ in non-PIE. */
+ if (scan_dyntag (DT_MIPS_RLD_MAP_REL, exec_bfd, &dyn_ptr, &dyn_ptr_addr)
+ || scan_dyntag_auxv (DT_MIPS_RLD_MAP_REL, &dyn_ptr, &dyn_ptr_addr))
+ {
+ struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
+ gdb_byte *pbuf;
+ int pbuf_size = TYPE_LENGTH (ptr_type);
+
+ pbuf = (gdb_byte *) alloca (pbuf_size);
+ /* DT_MIPS_RLD_MAP_REL contains an offset from the address of the
+ DT slot to the address of the dynamic link structure. */
+ if (target_read_memory (dyn_ptr + dyn_ptr_addr, pbuf, pbuf_size))
+ return 0;
+ return extract_typed_address (pbuf, ptr_type);
+ }
+
/* Find DT_DEBUG. */
- if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr)
- || scan_dyntag_auxv (DT_DEBUG, &dyn_ptr))
+ if (scan_dyntag (DT_DEBUG, exec_bfd, &dyn_ptr, NULL)
+ || scan_dyntag_auxv (DT_DEBUG, &dyn_ptr, NULL))
return dyn_ptr;
/* This may be a static executable. Look for the symbol
conventionally named _r_debug, as a last resort. */
msymbol = lookup_minimal_symbol ("_r_debug", NULL, symfile_objfile);
if (msymbol.minsym != NULL)
- return MSYMBOL_VALUE_ADDRESS (msymbol.minsym);
+ return BMSYMBOL_VALUE_ADDRESS (msymbol);
/* DT_DEBUG entry not found. */
return 0;
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
CORE_ADDR addr = 0;
- volatile struct gdb_exception ex;
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
addr = read_memory_typed_address (info->debug_base + lmo->r_map_offset,
ptr_type);
}
- exception_print (gdb_stderr, ex);
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ }
+ END_CATCH
+
return addr;
}
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 ());
- ULONGEST version;
+ ULONGEST version = 0;
+
+ TRY
+ {
+ /* Check version, and return zero if `struct r_debug' doesn't have
+ the r_ldsomap member. */
+ version
+ = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
+ lmo->r_version_size, byte_order);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ }
+ END_CATCH
- /* Check version, and return zero if `struct r_debug' doesn't have
- the r_ldsomap member. */
- version
- = read_memory_unsigned_integer (info->debug_base + lmo->r_version_offset,
- lmo->r_version_size, byte_order);
if (version < 2 || lmo->r_ldsomap_offset == -1)
return 0;
{
struct svr4_info *info;
CORE_ADDR ldsomap;
- struct so_list *new;
+ struct so_list *newobj;
struct cleanup *old_chain;
CORE_ADDR name_lm;
if (!ldsomap)
return 0;
- new = XCNEW (struct so_list);
- old_chain = make_cleanup (xfree, new);
- new->lm_info = lm_info_read (ldsomap);
- make_cleanup (xfree, new->lm_info);
- name_lm = new->lm_info ? new->lm_info->l_name : 0;
+ newobj = XCNEW (struct so_list);
+ old_chain = make_cleanup (xfree, newobj);
+ newobj->lm_info = lm_info_read (ldsomap);
+ make_cleanup (xfree, newobj->lm_info);
+ name_lm = newobj->lm_info ? newobj->lm_info->l_name : 0;
do_cleanups (old_chain);
return (name_lm >= vaddr && name_lm < vaddr + size);
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
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);
+ gdb_byte *l_name_buf = (gdb_byte *) xmalloc (l_name_size);
struct cleanup *cleanups = make_cleanup (xfree, l_name_buf);
struct svr4_info *info = get_svr4_info ();
while (src != NULL)
{
- struct so_list *new;
+ struct so_list *newobj;
- new = xmalloc (sizeof (struct so_list));
- memcpy (new, src, sizeof (struct so_list));
+ newobj = XNEW (struct so_list);
+ memcpy (newobj, src, sizeof (struct so_list));
- new->lm_info = xmalloc (sizeof (struct lm_info));
- memcpy (new->lm_info, src->lm_info, sizeof (struct lm_info));
+ newobj->lm_info = XNEW (struct lm_info);
+ memcpy (newobj->lm_info, src->lm_info, sizeof (struct lm_info));
- new->next = NULL;
- *link = new;
- link = &new->next;
+ newobj->next = NULL;
+ *link = newobj;
+ link = &newobj->next;
src = src->next;
}
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 svr4_library_list *list = (struct svr4_library_list *) user_data;
+ const char *name
+ = (const char *) xml_find_attribute (attributes, "name")->value;
+ ULONGEST *lmp
+ = (ULONGEST *) xml_find_attribute (attributes, "lm")->value;
+ ULONGEST *l_addrp
+ = (ULONGEST *) xml_find_attribute (attributes, "l_addr")->value;
+ ULONGEST *l_ldp
+ = (ULONGEST *) xml_find_attribute (attributes, "l_ld")->value;
struct so_list *new_elem;
new_elem = XCNEW (struct so_list);
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 svr4_library_list *list = (struct svr4_library_list *) user_data;
+ const char *version
+ = (const char *) xml_find_attribute (attributes, "version")->value;
struct gdb_xml_value *main_lm = xml_find_attribute (attributes, "main-lm");
if (strcmp (version, "1.0") != 0)
memset (list, 0, sizeof (*list));
list->tailp = &list->head;
- if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd",
+ if (gdb_xml_parse_quick (_("target library list"), "library-list-svr4.dtd",
svr4_library_list_elements, document, list) == 0)
{
/* Parsed successfully, keep the result. */
svr4_default_sos (void)
{
struct svr4_info *info = get_svr4_info ();
- struct so_list *new;
+ struct so_list *newobj;
if (!info->debug_loader_offset_p)
return NULL;
- new = XCNEW (struct so_list);
+ newobj = XCNEW (struct so_list);
- new->lm_info = xzalloc (sizeof (struct lm_info));
+ newobj->lm_info = XCNEW (struct lm_info);
/* Nothing will ever check the other fields if we set l_addr_p. */
- new->lm_info->l_addr = info->debug_loader_offset;
- new->lm_info->l_addr_p = 1;
+ newobj->lm_info->l_addr = info->debug_loader_offset;
+ newobj->lm_info->l_addr_p = 1;
- strncpy (new->so_name, info->debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1);
- new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
- strcpy (new->so_original_name, new->so_name);
+ strncpy (newobj->so_name, info->debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1);
+ newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strcpy (newobj->so_original_name, newobj->so_name);
- return new;
+ return newobj;
}
/* Read the whole inferior libraries chain starting at address LM.
svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
struct so_list ***link_ptr_ptr, int ignore_first)
{
- struct so_list *first = NULL;
+ CORE_ADDR first_l_name = 0;
CORE_ADDR next_lm;
for (; lm != 0; prev_lm = lm, lm = next_lm)
{
- struct so_list *new;
+ struct so_list *newobj;
struct cleanup *old_chain;
int errcode;
char *buffer;
- new = XCNEW (struct so_list);
- old_chain = make_cleanup_free_so (new);
+ newobj = XCNEW (struct so_list);
+ old_chain = make_cleanup_free_so (newobj);
- new->lm_info = lm_info_read (lm);
- if (new->lm_info == NULL)
+ newobj->lm_info = lm_info_read (lm);
+ if (newobj->lm_info == NULL)
{
do_cleanups (old_chain);
return 0;
}
- next_lm = new->lm_info->l_next;
+ next_lm = newobj->lm_info->l_next;
- if (new->lm_info->l_prev != prev_lm)
+ if (newobj->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 (), newobj->lm_info->l_prev));
do_cleanups (old_chain);
return 0;
}
SVR4, it has no name. For others (Solaris 2.3 for example), it
does have a name, so we can no longer use a missing name to
decide when to ignore it. */
- if (ignore_first && new->lm_info->l_prev == 0)
+ if (ignore_first && newobj->lm_info->l_prev == 0)
{
struct svr4_info *info = get_svr4_info ();
- first = new;
- info->main_lm_addr = new->lm_info->lm_addr;
+ first_l_name = newobj->lm_info->l_name;
+ info->main_lm_addr = newobj->lm_info->lm_addr;
do_cleanups (old_chain);
continue;
}
/* Extract this shared object's name. */
- target_read_string (new->lm_info->l_name, &buffer,
+ target_read_string (newobj->lm_info->l_name, &buffer,
SO_NAME_MAX_PATH_SIZE - 1, &errcode);
if (errcode != 0)
{
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)
+ if (first_l_name == 0 || newobj->lm_info->l_name != first_l_name)
warning (_("Can't read pathname for load map: %s."),
safe_strerror (errcode));
do_cleanups (old_chain);
continue;
}
- strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
- new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
- strcpy (new->so_original_name, new->so_name);
+ strncpy (newobj->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1);
+ newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strcpy (newobj->so_original_name, newobj->so_name);
xfree (buffer);
/* If this entry has no name, or its name matches the name
for the main executable, don't include it in the list. */
- if (! new->so_name[0] || match_main (new->so_name))
+ if (! newobj->so_name[0] || match_main (newobj->so_name))
{
do_cleanups (old_chain);
continue;
}
discard_cleanups (old_chain);
- new->next = 0;
- **link_ptr_ptr = new;
- *link_ptr_ptr = &new->next;
+ newobj->next = 0;
+ **link_ptr_ptr = newobj;
+ *link_ptr_ptr = &newobj->next;
}
return 1;
return head;
}
-/* Implement the "current_sos" target_so_ops method. */
+/* Implement the main part of the "current_sos" target_so_ops
+ method. */
static struct so_list *
-svr4_current_sos (void)
+svr4_current_sos_1 (void)
{
struct svr4_info *info = get_svr4_info ();
return svr4_current_sos_direct (info);
}
+/* Implement the "current_sos" target_so_ops method. */
+
+static struct so_list *
+svr4_current_sos (void)
+{
+ struct so_list *so_head = svr4_current_sos_1 ();
+ struct mem_range vsyscall_range;
+
+ /* Filter out the vDSO module, if present. Its symbol file would
+ not be found on disk. The vDSO/vsyscall's OBJFILE is instead
+ managed by symfile-mem.c:add_vsyscall_page. */
+ if (gdbarch_vsyscall_range (target_gdbarch (), &vsyscall_range)
+ && vsyscall_range.length != 0)
+ {
+ struct so_list **sop;
+
+ sop = &so_head;
+ while (*sop != NULL)
+ {
+ struct so_list *so = *sop;
+
+ /* We can't simply match the vDSO by starting address alone,
+ because lm_info->l_addr_inferior (and also l_addr) do not
+ necessarily represent the real starting address of the
+ ELF if the vDSO's ELF itself is "prelinked". The l_ld
+ field (the ".dynamic" section of the shared object)
+ always points at the absolute/resolved address though.
+ So check whether that address is inside the vDSO's
+ mapping instead.
+
+ E.g., on Linux 3.16 (x86_64) the vDSO is a regular
+ 0-based ELF, and we see:
+
+ (gdb) info auxv
+ 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffb000
+ (gdb) p/x *_r_debug.r_map.l_next
+ $1 = {l_addr = 0x7ffff7ffb000, ..., l_ld = 0x7ffff7ffb318, ...}
+
+ And on Linux 2.6.32 (x86_64) we see:
+
+ (gdb) info auxv
+ 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffe000
+ (gdb) p/x *_r_debug.r_map.l_next
+ $5 = {l_addr = 0x7ffff88fe000, ..., l_ld = 0x7ffff7ffe580, ... }
+
+ Dumping that vDSO shows:
+
+ (gdb) info proc mappings
+ 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0 [vdso]
+ (gdb) dump memory vdso.bin 0x7ffff7ffe000 0x7ffff7fff000
+ # readelf -Wa vdso.bin
+ [...]
+ Entry point address: 0xffffffffff700700
+ [...]
+ Section Headers:
+ [Nr] Name Type Address Off Size
+ [ 0] NULL 0000000000000000 000000 000000
+ [ 1] .hash HASH ffffffffff700120 000120 000038
+ [ 2] .dynsym DYNSYM ffffffffff700158 000158 0000d8
+ [...]
+ [ 9] .dynamic DYNAMIC ffffffffff700580 000580 0000f0
+ */
+ if (address_in_mem_range (so->lm_info->l_ld, &vsyscall_range))
+ {
+ *sop = so->next;
+ free_so (so);
+ break;
+ }
+
+ sop = &so->next;
+ }
+ }
+
+ return so_head;
+}
+
/* Get the address of the link_map for a given OBJFILE. */
CORE_ADDR
/* The probe. */
struct probe *probe;
+ /* The relocated address of the probe. */
+ CORE_ADDR address;
+
/* The action. */
enum probe_action action;
};
static hashval_t
hash_probe_and_action (const void *p)
{
- const struct probe_and_action *pa = p;
+ const struct probe_and_action *pa = (const struct probe_and_action *) p;
- return (hashval_t) pa->probe->address;
+ return (hashval_t) pa->address;
}
/* Returns non-zero if the probe_and_actions referenced by p1 and p2
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;
+ const struct probe_and_action *pa1 = (const struct probe_and_action *) p1;
+ const struct probe_and_action *pa2 = (const struct probe_and_action *) p2;
- return pa1->probe->address == pa2->probe->address;
+ return pa1->address == pa2->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)
+register_solib_event_probe (struct probe *probe, CORE_ADDR address,
+ enum probe_action action)
{
struct svr4_info *info = get_svr4_info ();
struct probe_and_action lookup, *pa;
xfree, xcalloc, xfree);
lookup.probe = probe;
+ lookup.address = address;
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->address = address;
pa->action = action;
*slot = pa;
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;
+ lookup.address = address;
slot = htab_find_slot (info->probes_table, &lookup, NO_INSERT);
if (slot == NULL)
solib_event_probe_action (struct probe_and_action *pa)
{
enum probe_action action;
- unsigned probe_argc;
+ unsigned probe_argc = 0;
struct frame_info *frame = get_current_frame ();
action = pa->action;
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, frame);
+ TRY
+ {
+ probe_argc = get_probe_argument_count (pa->probe, frame);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ probe_argc = 0;
+ }
+ END_CATCH
+
+ /* If get_probe_argument_count throws an exception, probe_argc will
+ be set to zero. However, if pa->probe does not have arguments,
+ then get_probe_argument_count will succeed but probe_argc will
+ also be zero. Both cases happen because of different things, but
+ they are treated equally here: action will be set to
+ PROBES_INTERFACE_FAILED. */
if (probe_argc == 2)
action = FULL_RELOAD;
else if (probe_argc < 2)
struct probe_and_action *pa;
enum probe_action action;
struct cleanup *old_chain, *usm_chain;
- struct value *val;
+ struct value *val = NULL;
CORE_ADDR pc, debug_base, lm = 0;
- int is_initial_ns;
struct frame_info *frame = get_current_frame ();
/* Do nothing if not using the probes interface. */
usm_chain = make_cleanup (resume_section_map_updates_cleanup,
current_program_space);
- val = evaluate_probe_argument (pa->probe, 1, frame);
+ TRY
+ {
+ val = evaluate_probe_argument (pa->probe, 1, frame);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ val = NULL;
+ }
+ END_CATCH
+
if (val == NULL)
{
do_cleanups (old_chain);
if (action == UPDATE_OR_RELOAD)
{
- val = evaluate_probe_argument (pa->probe, 2, frame);
+ TRY
+ {
+ val = evaluate_probe_argument (pa->probe, 2, frame);
+ }
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ exception_print (gdb_stderr, ex);
+ do_cleanups (old_chain);
+ return;
+ }
+ END_CATCH
+
if (val != NULL)
lm = value_as_address (val);
struct svr4_info *info;
struct probe_and_action *pa;
- info = program_space_data (loc->pspace, solib_svr4_pspace_data);
+ info = ((struct svr4_info *)
+ program_space_data (loc->pspace, solib_svr4_pspace_data));
if (info == NULL || info->probes_table == NULL)
continue;
static void
svr4_create_probe_breakpoints (struct gdbarch *gdbarch,
- VEC (probe_p) **probes)
+ VEC (probe_p) **probes,
+ struct objfile *objfile)
{
int i;
VEC_iterate (probe_p, probes[i], ix, probe);
++ix)
{
- create_solib_event_breakpoint (gdbarch, probe->address);
- register_solib_event_probe (probe, action);
+ CORE_ADDR address = get_probe_address (probe, objfile);
+
+ create_solib_event_breakpoint (gdbarch, address);
+ register_solib_event_probe (probe, address, action);
}
}
}
if (all_probes_found)
- svr4_create_probe_breakpoints (gdbarch, probes);
+ svr4_create_probe_breakpoints (gdbarch, probes, os->objfile);
for (i = 0; i < NUM_PROBES; i++)
VEC_free (probe_p, probes[i]);
/* Helper function for gdb_bfd_lookup_symbol. */
static int
-cmp_name_and_sec_flags (asymbol *sym, void *data)
+cmp_name_and_sec_flags (const asymbol *sym, const void *data)
{
return (strcmp (sym->name, (const char *) data) == 0
&& (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0);
struct so_list *so;
bfd *tmp_bfd = NULL;
struct target_ops *tmp_bfd_target;
- volatile struct gdb_exception ex;
sym_addr = 0;
be trivial on GNU/Linux). Therefore, we have to try an alternate
mechanism to find the dynamic linker's base address. */
- TRY_CATCH (ex, RETURN_MASK_ALL)
+ TRY
{
tmp_bfd = solib_bfd_open (interp_name);
}
+ CATCH (ex, RETURN_MASK_ALL)
+ {
+ }
+ END_CATCH
+
if (tmp_bfd == NULL)
goto bkpt_at_symbol;
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
{
sym_addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name_and_sec_flags,
- (void *) *bkpt_namep);
+ *bkpt_namep);
if (sym_addr != 0)
break;
}
{
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
if ((msymbol.minsym != NULL)
- && (MSYMBOL_VALUE_ADDRESS (msymbol.minsym) != 0))
+ && (BMSYMBOL_VALUE_ADDRESS (msymbol) != 0))
{
- sym_addr = MSYMBOL_VALUE_ADDRESS (msymbol.minsym);
+ sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
sym_addr,
¤t_target);
{
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
if ((msymbol.minsym != NULL)
- && (MSYMBOL_VALUE_ADDRESS (msymbol.minsym) != 0))
+ && (BMSYMBOL_VALUE_ADDRESS (msymbol) != 0))
{
- sym_addr = MSYMBOL_VALUE_ADDRESS (msymbol.minsym);
+ sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
sym_addr,
¤t_target);
return 0;
}
-/* Implement the "special_symbol_handling" target_so_ops method. */
-
-static void
-svr4_special_symbol_handling (void)
-{
- /* Nothing to do. */
-}
-
/* Read the ELF program headers from ABFD. Return the contents and
set *PHDRS_SIZE to the size of the program headers. */
if (*phdrs_size == 0)
return NULL;
- buf = xmalloc (*phdrs_size);
+ buf = (gdb_byte *) xmalloc (*phdrs_size);
if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
|| bfd_bread (buf, *phdrs_size, abfd) != *phdrs_size)
{
{
/* ENTRY_POINT is a possible function descriptor - before
a call to gdbarch_convert_from_func_ptr_addr. */
- CORE_ADDR entry_point, displacement;
+ CORE_ADDR entry_point, exec_displacement;
if (exec_bfd == NULL)
return 0;
if (target_auxv_search (¤t_target, AT_ENTRY, &entry_point) <= 0)
return 0;
- displacement = entry_point - bfd_get_start_address (exec_bfd);
+ exec_displacement = entry_point - bfd_get_start_address (exec_bfd);
- /* Verify the DISPLACEMENT candidate complies with the required page
+ /* Verify the EXEC_DISPLACEMENT candidate complies with the required page
alignment. It is cheaper than the program headers comparison below. */
if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
p_offset % p_align == p_vaddr % p_align
Kernel is free to load the executable with lower alignment. */
- if ((displacement & (elf->minpagesize - 1)) != 0)
+ if ((exec_displacement & (elf->minpagesize - 1)) != 0)
return 0;
}
gdb_byte *buf, *buf2;
int arch_size;
- buf = read_program_header (-1, &phdrs_size, &arch_size);
+ buf = read_program_header (-1, &phdrs_size, &arch_size, NULL);
buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
if (buf != NULL && buf2 != NULL)
{
printf_unfiltered (_("Using PIE (Position Independent Executable) "
"displacement %s for \"%s\".\n"),
- paddress (target_gdbarch (), displacement),
+ paddress (target_gdbarch (), exec_displacement),
bfd_get_filename (exec_bfd));
}
- *displacementp = displacement;
+ *displacementp = exec_displacement;
return 1;
}
struct section_offsets *new_offsets;
int i;
- new_offsets = alloca (symfile_objfile->num_sections
- * sizeof (*new_offsets));
+ new_offsets = XALLOCAVEC (struct section_offsets,
+ symfile_objfile->num_sections);
for (i = 0; i < symfile_objfile->num_sections; i++)
new_offsets->offsets[i] = displacement;
set_solib_svr4_fetch_link_map_offsets (struct gdbarch *gdbarch,
struct link_map_offsets *(*flmo) (void))
{
- struct solib_svr4_ops *ops = gdbarch_data (gdbarch, solib_svr4_data);
+ struct solib_svr4_ops *ops
+ = (struct solib_svr4_ops *) gdbarch_data (gdbarch, solib_svr4_data);
ops->fetch_link_map_offsets = flmo;
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
+ = (struct solib_svr4_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
+ = (struct solib_svr4_ops *) gdbarch_data (target_gdbarch (),
+ solib_svr4_data);
return (ops->fetch_link_map_offsets != NULL);
}
different rule for symbol lookup. The lookup begins here in the DSO, not in
the main executable. */
-static struct symbol *
-elf_lookup_lib_symbol (const struct objfile *objfile,
+static struct block_symbol
+elf_lookup_lib_symbol (struct objfile *objfile,
const char *name,
const domain_enum domain)
{
abfd = objfile->obfd;
}
- if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL) != 1)
- return NULL;
+ if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL, NULL) != 1)
+ return (struct block_symbol) {NULL, NULL};
return lookup_global_symbol_from_objfile (objfile, name, domain);
}
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;
svr4_so_ops.current_sos = svr4_current_sos;
svr4_so_ops.open_symbol_file_object = open_symbol_file_object;
svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;