/* Handle SVR4 shared libraries for GDB, the GNU Debugger.
- Copyright (C) 1990-2013 Free Software Foundation, Inc.
+ Copyright (C) 1990-2019 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 "observable.h"
#include "solist.h"
#include "solib.h"
#include "elf-bfd.h"
#include "exec.h"
#include "auxv.h"
-#include "exceptions.h"
#include "gdb_bfd.h"
#include "probe.h"
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. */
-
-struct lm_info
- {
- /* Amount by which addresses in the binary should be relocated to
- match the inferior. The direct inferior value is L_ADDR_INFERIOR.
- When prelinking is involved and the prelink base address changes,
- we may need a different offset - the recomputed offset is in L_ADDR.
- It is commonly the same value. It is cached as we want to warn about
- the difference and compute it only once. L_ADDR is valid
- iff L_ADDR_P. */
- CORE_ADDR l_addr, l_addr_inferior;
- unsigned int l_addr_p : 1;
-
- /* The target location of lm. */
- CORE_ADDR lm_addr;
-
- /* Values read in from inferior's fields of the same name. */
- CORE_ADDR l_ld, l_next, l_prev, l_name;
- };
+static void probes_table_remove_objfile_probes (struct objfile *objfile);
/* On SVR4 systems, a list of symbols in the dynamic linker where
GDB can try to place a breakpoint to monitor shared library
&& strcmp (inferior_so_name, "/lib/ld.so.1") == 0)
return 1;
- /* Similarly, we observed the same issue with sparc64, but with
+ /* Similarly, we observed the same issue with amd64 and sparcv9, but with
different locations. */
+ if (strcmp (gdb_so_name, "/usr/lib/amd64/ld.so.1") == 0
+ && strcmp (inferior_so_name, "/lib/amd64/ld.so.1") == 0)
+ return 1;
+
if (strcmp (gdb_so_name, "/usr/lib/sparcv9/ld.so.1") == 0
&& strcmp (inferior_so_name, "/lib/sparcv9/ld.so.1") == 0)
return 1;
return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name));
}
-static struct lm_info *
+static std::unique_ptr<lm_info_svr4>
lm_info_read (CORE_ADDR lm_addr)
{
struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
- gdb_byte *lm;
- struct lm_info *lm_info;
- struct cleanup *back_to;
+ std::unique_ptr<lm_info_svr4> lm_info;
- lm = xmalloc (lmo->link_map_size);
- back_to = make_cleanup (xfree, lm);
+ gdb::byte_vector lm (lmo->link_map_size);
- 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)),
- lm_info = NULL;
- }
+ if (target_read_memory (lm_addr, lm.data (), lmo->link_map_size) != 0)
+ warning (_("Error reading shared library list entry at %s"),
+ paddress (target_gdbarch (), lm_addr));
else
{
struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
- lm_info = xzalloc (sizeof (*lm_info));
+ lm_info.reset (new lm_info_svr4);
lm_info->lm_addr = lm_addr;
lm_info->l_addr_inferior = extract_typed_address (&lm[lmo->l_addr_offset],
ptr_type);
}
- do_cleanups (back_to);
-
return lm_info;
}
static CORE_ADDR
lm_addr_check (const struct so_list *so, bfd *abfd)
{
- if (!so->lm_info->l_addr_p)
+ lm_info_svr4 *li = (lm_info_svr4 *) so->lm_info;
+
+ if (!li->l_addr_p)
{
struct bfd_section *dyninfo_sect;
CORE_ADDR l_addr, l_dynaddr, dynaddr;
- l_addr = so->lm_info->l_addr_inferior;
+ l_addr = li->l_addr_inferior;
if (! abfd || ! has_lm_dynamic_from_link_map ())
goto set_addr;
- l_dynaddr = so->lm_info->l_ld;
+ l_dynaddr = li->l_ld;
dyninfo_sect = bfd_get_section_by_name (abfd, ".dynamic");
if (dyninfo_sect == NULL)
}
set_addr:
- so->lm_info->l_addr = l_addr;
- so->lm_info->l_addr_p = 1;
+ li->l_addr = l_addr;
+ li->l_addr_p = 1;
}
- return so->lm_info->l_addr;
+ return li->l_addr;
}
/* Per pspace SVR4 specific data. */
struct svr4_info
{
- CORE_ADDR debug_base; /* Base of dynamic linker structures. */
+ svr4_info () = default;
+ ~svr4_info ();
+
+ /* Base of dynamic linker structures. */
+ CORE_ADDR debug_base = 0;
/* Validity flag for debug_loader_offset. */
- int debug_loader_offset_p;
+ int debug_loader_offset_p = 0;
/* Load address for the dynamic linker, inferred. */
- CORE_ADDR debug_loader_offset;
+ CORE_ADDR debug_loader_offset = 0;
/* Name of the dynamic linker, valid if debug_loader_offset_p. */
- char *debug_loader_name;
+ char *debug_loader_name = nullptr;
/* Load map address for the main executable. */
- CORE_ADDR main_lm_addr;
+ CORE_ADDR main_lm_addr = 0;
- CORE_ADDR interp_text_sect_low;
- CORE_ADDR interp_text_sect_high;
- CORE_ADDR interp_plt_sect_low;
- CORE_ADDR interp_plt_sect_high;
+ CORE_ADDR interp_text_sect_low = 0;
+ CORE_ADDR interp_text_sect_high = 0;
+ CORE_ADDR interp_plt_sect_low = 0;
+ CORE_ADDR interp_plt_sect_high = 0;
/* Nonzero if the list of objects was last obtained from the target
via qXfer:libraries-svr4:read. */
- int using_xfer;
+ int using_xfer = 0;
/* 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;
+ probe_and_action->prob->address. */
+ htab_up probes_table;
/* List of objects loaded into the inferior, used by the probes-
based interface. */
- struct so_list *solib_list;
+ struct so_list *solib_list = nullptr;
};
/* Per-program-space data key. */
-static const struct program_space_data *solib_svr4_pspace_data;
+static const struct program_space_key<svr4_info> 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;
+ info->probes_table.reset (nullptr);
}
/* Free the solib list. */
info->solib_list = NULL;
}
-static void
-svr4_pspace_data_cleanup (struct program_space *pspace, void *arg)
+svr4_info::~svr4_info ()
{
- struct svr4_info *info;
-
- info = program_space_data (pspace, solib_svr4_pspace_data);
- if (info == NULL)
- return;
-
- free_probes_table (info);
- free_solib_list (info);
-
- xfree (info);
+ free_solib_list (this);
}
-/* Get the current svr4 data. If none is found yet, add it now. This
- function always returns a valid object. */
+/* Get the svr4 data for program space PSPACE. If none is found yet, add it now.
+ This function always returns a valid object. */
static struct svr4_info *
-get_svr4_info (void)
+get_svr4_info (program_space *pspace)
{
- struct svr4_info *info;
+ struct svr4_info *info = solib_svr4_pspace_data.get (pspace);
- info = program_space_data (current_program_space, solib_svr4_pspace_data);
- if (info != NULL)
- return info;
+ if (info == NULL)
+ info = solib_svr4_pspace_data.emplace (pspace);
- info = XZALLOC (struct svr4_info);
- set_program_space_data (current_program_space, solib_svr4_pspace_data, info);
return info;
}
static int match_main (const char *);
/* Read program header TYPE from inferior memory. The header is found
- by scanning the OS auxillary vector.
+ by scanning the OS auxiliary vector.
If TYPE == -1, return the program headers instead of the contents of
one program header.
- 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. */
+ Return vector of bytes holding the program header contents, or an empty
+ optional on failure. If successful and P_ARCH_SIZE is non-NULL, the target
+ architecture size (32-bit or 64-bit) is returned to *P_ARCH_SIZE. Likewise,
+ 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)
+static gdb::optional<gdb::byte_vector>
+read_program_header (int type, 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;
int arch_size, sect_size;
CORE_ADDR sect_addr;
- gdb_byte *buf;
int pt_phdr_p = 0;
/* Get required auxv elements from target. */
- if (target_auxv_search (¤t_target, AT_PHDR, &at_phdr) <= 0)
- return 0;
- if (target_auxv_search (¤t_target, AT_PHENT, &at_phent) <= 0)
- return 0;
- if (target_auxv_search (¤t_target, AT_PHNUM, &at_phnum) <= 0)
- return 0;
+ if (target_auxv_search (current_top_target (), AT_PHDR, &at_phdr) <= 0)
+ return {};
+ if (target_auxv_search (current_top_target (), AT_PHENT, &at_phent) <= 0)
+ return {};
+ if (target_auxv_search (current_top_target (), AT_PHNUM, &at_phnum) <= 0)
+ return {};
if (!at_phdr || !at_phnum)
- return 0;
+ return {};
/* Determine ELF architecture type. */
if (at_phent == sizeof (Elf32_External_Phdr))
else if (at_phent == sizeof (Elf64_External_Phdr))
arch_size = 64;
else
- return 0;
+ return {};
/* Find the requested segment. */
if (type == -1)
if (target_read_memory (at_phdr + i * sizeof (phdr),
(gdb_byte *)&phdr, sizeof (phdr)))
- return 0;
+ return {};
p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type,
4, byte_order);
}
if (i == at_phnum)
- return 0;
+ return {};
/* Retrieve address and size. */
sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr,
if (target_read_memory (at_phdr + i * sizeof (phdr),
(gdb_byte *)&phdr, sizeof (phdr)))
- return 0;
+ return {};
p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type,
4, byte_order);
}
if (i == at_phnum)
- return 0;
+ return {};
/* Retrieve address and size. */
sect_addr = extract_unsigned_integer ((gdb_byte *)phdr.p_vaddr,
}
/* Read in requested program header. */
- buf = xmalloc (sect_size);
- if (target_read_memory (sect_addr, buf, sect_size))
- {
- xfree (buf);
- return NULL;
- }
+ gdb::byte_vector buf (sect_size);
+ if (target_read_memory (sect_addr, buf.data (), sect_size))
+ return {};
if (p_arch_size)
*p_arch_size = arch_size;
- if (p_sect_size)
- *p_sect_size = sect_size;
+ if (base_addr)
+ *base_addr = sect_addr;
return buf;
}
/* Return program interpreter string. */
-static char *
+static gdb::optional<gdb::byte_vector>
find_program_interpreter (void)
{
- gdb_byte *buf = NULL;
-
/* If we have an exec_bfd, use its section table. */
if (exec_bfd
&& bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
{
int sect_size = bfd_section_size (exec_bfd, interp_sect);
- buf = xmalloc (sect_size);
- bfd_get_section_contents (exec_bfd, interp_sect, buf, 0, sect_size);
+ gdb::byte_vector buf (sect_size);
+ bfd_get_section_contents (exec_bfd, interp_sect, buf.data (), 0,
+ sect_size);
+ return buf;
}
}
- /* If we didn't find it, use the target auxillary vector. */
- if (!buf)
- buf = read_program_header (PT_INTERP, NULL, NULL);
-
- return (char *) buf;
+ /* If we didn't find it, use the target auxiliary vector. */
+ return read_program_header (PT_INTERP, NULL, NULL);
}
-/* 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;
+ int arch_size, step;
+ long current_dyntag;
CORE_ADDR dyn_ptr;
- gdb_byte *bufend, *bufstart, *buf;
+ CORE_ADDR base_addr;
/* Read in .dynamic section. */
- buf = bufstart = read_program_header (PT_DYNAMIC, §_size, &arch_size);
- if (!buf)
+ gdb::optional<gdb::byte_vector> ph_data
+ = read_program_header (PT_DYNAMIC, &arch_size, &base_addr);
+ if (!ph_data)
return 0;
/* Iterate over BUF and scan for DYNTAG. If found, set PTR and return. */
step = (arch_size == 32) ? sizeof (Elf32_External_Dyn)
: sizeof (Elf64_External_Dyn);
- for (bufend = buf + sect_size;
- buf < bufend;
- buf += step)
+ for (gdb_byte *buf = ph_data->data (), *bufend = buf + ph_data->size ();
+ buf < bufend; buf += step)
{
if (arch_size == 32)
{
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;
- xfree (bufstart);
+ if (ptr_addr)
+ *ptr_addr = base_addr + buf - ph_data->data ();
+
return 1;
}
}
- xfree (bufstart);
return 0;
}
static CORE_ADDR
elf_locate_base (void)
{
- struct minimal_symbol *msymbol;
- CORE_ADDR dyn_ptr;
+ struct bound_minimal_symbol msymbol;
+ 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 != NULL)
- return SYMBOL_VALUE_ADDRESS (msymbol);
+ if (msymbol.minsym != NULL)
+ 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 (const gdb_exception_error &ex)
+ {
+ exception_print (gdb_stderr, ex);
+ }
+
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 (const gdb_exception_error &ex)
+ {
+ exception_print (gdb_stderr, ex);
+ }
- /* 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 cleanup *old_chain;
CORE_ADDR name_lm;
- info = get_svr4_info ();
+ info = get_svr4_info (current_program_space);
info->debug_base = 0;
locate_base (info);
if (!ldsomap)
return 0;
- new = XZALLOC (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;
- do_cleanups (old_chain);
+ std::unique_ptr<lm_info_svr4> li = lm_info_read (ldsomap);
+ name_lm = li != NULL ? li->l_name : 0;
return (name_lm >= vaddr && name_lm < vaddr + size);
}
-/* Implement the "open_symbol_file_object" target_so_ops method.
-
- If no open symbol file, attempt to locate and open the main symbol
- file. On SVR4 systems, this is the first link map entry. If its
- name is here, we can open it. Useful when attaching to a process
- without first loading its symbol file. */
+/* See solist.h. */
static int
-open_symbol_file_object (void *from_ttyp)
+open_symbol_file_object (int from_tty)
{
CORE_ADDR lm, l_name;
- char *filename;
+ gdb::unique_xmalloc_ptr<char> filename;
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;
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);
- struct svr4_info *info = get_svr4_info ();
+ gdb::byte_vector l_name_buf (l_name_size);
+ struct svr4_info *info = get_svr4_info (current_program_space);
+ symfile_add_flags add_flags = 0;
+
+ if (from_tty)
+ add_flags |= SYMFILE_VERBOSE;
if (symfile_objfile)
if (!query (_("Attempt to reload symbols from process? ")))
- {
- do_cleanups (cleanups);
- return 0;
- }
+ return 0;
/* Always locate the debug struct, in case it has moved. */
info->debug_base = 0;
if (locate_base (info) == 0)
- {
- do_cleanups (cleanups);
- return 0; /* failed somehow... */
- }
+ return 0; /* failed somehow... */
/* First link map member should be the executable. */
lm = solib_svr4_r_map (info);
if (lm == 0)
- {
- do_cleanups (cleanups);
- return 0; /* failed somehow... */
- }
+ return 0; /* failed somehow... */
/* Read address of name from target memory to GDB. */
- read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size);
+ read_memory (lm + lmo->l_name_offset, l_name_buf.data (), l_name_size);
/* Convert the address to host format. */
- l_name = extract_typed_address (l_name_buf, ptr_type);
+ l_name = extract_typed_address (l_name_buf.data (), ptr_type);
if (l_name == 0)
- {
- do_cleanups (cleanups);
- return 0; /* No filename. */
- }
+ return 0; /* No filename. */
/* Now fetch the filename from target memory. */
target_read_string (l_name, &filename, SO_NAME_MAX_PATH_SIZE - 1, &errcode);
- make_cleanup (xfree, filename);
if (errcode)
{
warning (_("failed to read exec filename from attached file: %s"),
safe_strerror (errcode));
- do_cleanups (cleanups);
return 0;
}
/* Have a pathname: read the symbol file. */
- symbol_file_add_main (filename, from_tty);
+ symbol_file_add_main (filename.get (), add_flags);
- do_cleanups (cleanups);
return 1;
}
CORE_ADDR main_lm;
};
+/* This module's 'free_objfile' observer. */
+
+static void
+svr4_free_objfile_observer (struct objfile *objfile)
+{
+ probes_table_remove_objfile_probes (objfile);
+}
+
/* Implementation for target_so_ops.free_so. */
static void
svr4_free_so (struct so_list *so)
{
- xfree (so->lm_info);
+ lm_info_svr4 *li = (lm_info_svr4 *) so->lm_info;
+
+ delete li;
}
/* 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;
+ lm_info_svr4 *li = (lm_info_svr4 *) so->lm_info;
+
+ if (li != NULL)
+ li->l_addr_p = 0;
}
/* Free so_list built so far (called via cleanup). */
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));
+ lm_info_svr4 *src_li = (lm_info_svr4 *) src->lm_info;
+ newobj->lm_info = new lm_info_svr4 (*src_li);
- new->next = NULL;
- *link = new;
- link = &new->next;
+ newobj->next = NULL;
+ *link = newobj;
+ link = &newobj->next;
src = src->next;
}
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;
+ void *user_data,
+ std::vector<gdb_xml_value> &attributes)
+{
+ struct svr4_library_list *list = (struct svr4_library_list *) user_data;
+ const char *name
+ = (const char *) xml_find_attribute (attributes, "name")->value.get ();
+ ULONGEST *lmp
+ = (ULONGEST *) xml_find_attribute (attributes, "lm")->value.get ();
+ ULONGEST *l_addrp
+ = (ULONGEST *) xml_find_attribute (attributes, "l_addr")->value.get ();
+ ULONGEST *l_ldp
+ = (ULONGEST *) xml_find_attribute (attributes, "l_ld")->value.get ();
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;
+ new_elem = XCNEW (struct so_list);
+ lm_info_svr4 *li = new lm_info_svr4;
+ new_elem->lm_info = li;
+ li->lm_addr = *lmp;
+ li->l_addr_inferior = *l_addrp;
+ li->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;
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)
+ void *user_data,
+ std::vector<gdb_xml_value> &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.get ();
struct gdb_xml_value *main_lm = xml_find_attribute (attributes, "main-lm");
if (strcmp (version, "1.0") != 0)
version);
if (main_lm)
- list->main_lm = *(ULONGEST *) main_lm->value;
+ list->main_lm = *(ULONGEST *) main_lm->value.get ();
}
/* The allowed elements and attributes for an XML library list.
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);
+ auto cleanup = make_scope_exit ([&] ()
+ {
+ 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",
+ if (gdb_xml_parse_quick (_("target library list"), "library-list-svr4.dtd",
svr4_library_list_elements, document, list) == 0)
{
/* Parsed successfully, keep the result. */
- discard_cleanups (back_to);
+ cleanup.release ();
return 1;
}
- do_cleanups (back_to);
return 0;
}
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,
- annex);
- if (svr4_library_document == NULL)
+ gdb::optional<gdb::char_vector> svr4_library_document
+ = target_read_stralloc (current_top_target (), TARGET_OBJECT_LIBRARIES_SVR4,
+ annex);
+ if (!svr4_library_document)
return 0;
- back_to = make_cleanup (xfree, svr4_library_document);
- result = svr4_parse_libraries (svr4_library_document, list);
- do_cleanups (back_to);
-
- return result;
+ return svr4_parse_libraries (svr4_library_document->data (), list);
}
#else
linker, build a fallback list from other sources. */
static struct so_list *
-svr4_default_sos (void)
+svr4_default_sos (svr4_info *info)
{
- struct svr4_info *info = get_svr4_info ();
- struct so_list *new;
+ struct so_list *newobj;
if (!info->debug_loader_offset_p)
return NULL;
- new = XZALLOC (struct so_list);
-
- new->lm_info = xzalloc (sizeof (struct lm_info));
+ newobj = XCNEW (struct so_list);
+ lm_info_svr4 *li = new lm_info_svr4;
+ newobj->lm_info = li;
/* 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;
+ li->l_addr = info->debug_loader_offset;
+ li->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.
represent only part of the inferior library list. */
static int
-svr4_read_so_list (CORE_ADDR lm, CORE_ADDR prev_lm,
+svr4_read_so_list (svr4_info *info, CORE_ADDR lm, CORE_ADDR prev_lm,
struct so_list ***link_ptr_ptr, int ignore_first)
{
+ CORE_ADDR first_l_name = 0;
CORE_ADDR next_lm;
for (; lm != 0; prev_lm = lm, lm = next_lm)
{
- struct so_list *new;
- struct cleanup *old_chain;
int errcode;
- char *buffer;
+ gdb::unique_xmalloc_ptr<char> buffer;
- new = XZALLOC (struct so_list);
- old_chain = make_cleanup_free_so (new);
+ so_list_up newobj (XCNEW (struct so_list));
- new->lm_info = lm_info_read (lm);
- if (new->lm_info == NULL)
- {
- do_cleanups (old_chain);
- return 0;
- }
+ lm_info_svr4 *li = lm_info_read (lm).release ();
+ newobj->lm_info = li;
+ if (li == NULL)
+ return 0;
- next_lm = new->lm_info->l_next;
+ next_lm = li->l_next;
- if (new->lm_info->l_prev != prev_lm)
+ if (li->l_prev != prev_lm)
{
warning (_("Corrupted shared library list: %s != %s"),
paddress (target_gdbarch (), prev_lm),
- paddress (target_gdbarch (), new->lm_info->l_prev));
- do_cleanups (old_chain);
+ paddress (target_gdbarch (), li->l_prev));
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 && li->l_prev == 0)
{
- struct svr4_info *info = get_svr4_info ();
-
- info->main_lm_addr = new->lm_info->lm_addr;
- do_cleanups (old_chain);
+ first_l_name = li->l_name;
+ info->main_lm_addr = li->lm_addr;
continue;
}
/* Extract this shared object's name. */
- target_read_string (new->lm_info->l_name, &buffer,
- SO_NAME_MAX_PATH_SIZE - 1, &errcode);
+ target_read_string (li->l_name, &buffer, SO_NAME_MAX_PATH_SIZE - 1,
+ &errcode);
if (errcode != 0)
{
- warning (_("Can't read pathname for load map: %s."),
- safe_strerror (errcode));
- do_cleanups (old_chain);
+ /* 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_l_name == 0 || li->l_name != first_l_name)
+ warning (_("Can't read pathname for load map: %s."),
+ safe_strerror (errcode));
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);
- xfree (buffer);
+ strncpy (newobj->so_name, buffer.get (), SO_NAME_MAX_PATH_SIZE - 1);
+ newobj->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+ strcpy (newobj->so_original_name, newobj->so_name);
/* 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))
- {
- do_cleanups (old_chain);
- continue;
- }
+ if (! newobj->so_name[0] || match_main (newobj->so_name))
+ continue;
- discard_cleanups (old_chain);
- new->next = 0;
- **link_ptr_ptr = new;
- *link_ptr_ptr = &new->next;
+ newobj->next = 0;
+ /* Don't free it now. */
+ **link_ptr_ptr = newobj.release ();
+ *link_ptr_ptr = &(**link_ptr_ptr)->next;
}
return 1;
CORE_ADDR lm;
struct so_list *head = NULL;
struct so_list **link_ptr = &head;
- struct cleanup *back_to;
int ignore_first;
struct svr4_library_list library_list;
if (library_list.main_lm)
info->main_lm_addr = library_list.main_lm;
- return library_list.head ? library_list.head : svr4_default_sos ();
+ return library_list.head ? library_list.head : svr4_default_sos (info);
}
/* Always locate the debug struct, in case it has moved. */
/* If we can't find the dynamic linker's base structure, this
must not be a dynamically linked executable. Hmm. */
if (! info->debug_base)
- return svr4_default_sos ();
+ return svr4_default_sos (info);
/* Assume that everything is a library if the dynamic loader was loaded
late by a static executable. */
else
ignore_first = 1;
- back_to = make_cleanup (svr4_free_library_list, &head);
+ auto cleanup = make_scope_exit ([&] ()
+ {
+ svr4_free_library_list (&head);
+ });
/* Walk the inferior's link map list, and build our list of
`struct so_list' nodes. */
lm = solib_svr4_r_map (info);
if (lm)
- svr4_read_so_list (lm, 0, &link_ptr, ignore_first);
+ svr4_read_so_list (info, 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
for skipping dynamic linker resolver code. */
lm = solib_svr4_r_ldsomap (info);
if (lm)
- svr4_read_so_list (lm, 0, &link_ptr, 0);
+ svr4_read_so_list (info, lm, 0, &link_ptr, 0);
- discard_cleanups (back_to);
+ cleanup.release ();
if (head == NULL)
- return svr4_default_sos ();
+ return svr4_default_sos (info);
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 (svr4_info *info)
{
- 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_current_sos_direct (info);
}
+/* Implement the "current_sos" target_so_ops method. */
+
+static struct so_list *
+svr4_current_sos (void)
+{
+ svr4_info *info = get_svr4_info (current_program_space);
+ struct so_list *so_head = svr4_current_sos_1 (info);
+ 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
+ */
+
+ lm_info_svr4 *li = (lm_info_svr4 *) so->lm_info;
+
+ if (address_in_mem_range (li->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
svr4_fetch_objfile_link_map (struct objfile *objfile)
{
struct so_list *so;
- struct svr4_info *info = get_svr4_info ();
+ struct svr4_info *info = get_svr4_info (objfile->pspace);
/* Cause svr4_current_sos() to be run if it hasn't been already. */
if (info->main_lm_addr == 0)
- solib_add (NULL, 0, ¤t_target, auto_solib_add);
+ solib_add (NULL, 0, auto_solib_add);
/* svr4_current_sos() will set main_lm_addr for the main executable. */
if (objfile == symfile_objfile)
return info->main_lm_addr;
+ /* If OBJFILE is a separate debug object file, look for the
+ original object file. */
+ if (objfile->separate_debug_objfile_backlink != NULL)
+ objfile = objfile->separate_debug_objfile_backlink;
+
/* The other link map addresses may be found by examining the list
of shared libraries. */
for (so = master_so_list (); so; so = so->next)
if (so->objfile == objfile)
- return so->lm_info->lm_addr;
+ {
+ lm_info_svr4 *li = (lm_info_svr4 *) so->lm_info;
+
+ return li->lm_addr;
+ }
/* Not found! */
return 0;
int
svr4_in_dynsym_resolve_code (CORE_ADDR pc)
{
- struct svr4_info *info = get_svr4_info ();
+ struct svr4_info *info = get_svr4_info (current_program_space);
return ((pc >= info->interp_text_sect_low
&& pc < info->interp_text_sect_high)
struct probe_and_action
{
/* The probe. */
- struct probe *probe;
+ probe *prob;
+
+ /* The relocated address of the probe. */
+ CORE_ADDR address;
/* The action. */
enum probe_action action;
+
+ /* The objfile where this probe was found. */
+ struct objfile *objfile;
};
/* 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;
+ 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->address == pa2->address;
+}
+
+/* Traversal function for probes_table_remove_objfile_probes. */
+
+static int
+probes_table_htab_remove_objfile_probes (void **slot, void *info)
+{
+ probe_and_action *pa = (probe_and_action *) *slot;
+ struct objfile *objfile = (struct objfile *) info;
+
+ if (pa->objfile == objfile)
+ htab_clear_slot (get_svr4_info (objfile->pspace)->probes_table.get (),
+ slot);
+
+ return 1;
+}
- return pa1->probe->address == pa2->probe->address;
+/* Remove all probes that belong to OBJFILE from the probes table. */
+
+static void
+probes_table_remove_objfile_probes (struct objfile *objfile)
+{
+ svr4_info *info = get_svr4_info (objfile->pspace);
+ if (info->probes_table != nullptr)
+ htab_traverse_noresize (info->probes_table.get (),
+ probes_table_htab_remove_objfile_probes, objfile);
}
/* 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 (svr4_info *info, struct objfile *objfile,
+ probe *prob, CORE_ADDR address,
+ 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);
+ info->probes_table.reset (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);
+ lookup.address = address;
+ slot = htab_find_slot (info->probes_table.get (), &lookup, INSERT);
gdb_assert (*slot == HTAB_EMPTY_ENTRY);
pa = XCNEW (struct probe_and_action);
- pa->probe = probe;
+ pa->prob = prob;
+ pa->address = address;
pa->action = action;
+ pa->objfile = objfile;
*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;
- slot = htab_find_slot (info->probes_table, &lookup, NO_INSERT);
+ lookup.address = address;
+ slot = htab_find_slot (info->probes_table.get (), &lookup, NO_INSERT);
if (slot == NULL)
return 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;
if (action == DO_NOTHING || action == PROBES_INTERFACE_FAILED)
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);
+ try
+ {
+ probe_argc = pa->prob->get_argument_count (frame);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ exception_print (gdb_stderr, ex);
+ probe_argc = 0;
+ }
+
+ /* If get_argument_count throws an exception, probe_argc will be set
+ to zero. However, if pa->prob does not have arguments, then
+ get_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)
/* 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;
+
+ lm_info_svr4 *li = (lm_info_svr4 *) tail->lm_info;
+ prev_lm = li->lm_addr;
/* Read the new objects. */
if (info->using_xfer)
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))
+ if (!svr4_read_so_list (info, lm, prev_lm, &link, 0))
return 0;
}
ones set up for the probes-based interface are adequate. */
static void
-disable_probes_interface_cleanup (void *arg)
+disable_probes_interface (svr4_info *info)
{
- struct svr4_info *info = get_svr4_info ();
-
warning (_("Probes-based dynamic linker interface failed.\n"
- "Reverting to original interface.\n"));
+ "Reverting to original interface."));
free_probes_table (info);
free_solib_list (info);
static void
svr4_handle_solib_event (void)
{
- struct svr4_info *info = get_svr4_info ();
+ struct svr4_info *info = get_svr4_info (current_program_space);
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. */
if (info->probes_table == NULL)
/* If anything goes wrong we revert to the original linker
interface. */
- old_chain = make_cleanup (disable_probes_interface_cleanup, NULL);
+ auto cleanup = make_scope_exit ([info] ()
+ {
+ disable_probes_interface (info);
+ });
pc = regcache_read_pc (get_current_regcache ());
pa = solib_event_probe_at (info, pc);
if (pa == NULL)
- {
- do_cleanups (old_chain);
- return;
- }
+ return;
action = solib_event_probe_action (pa);
if (action == PROBES_INTERFACE_FAILED)
- {
- do_cleanups (old_chain);
- return;
- }
+ return;
if (action == DO_NOTHING)
{
- discard_cleanups (old_chain);
+ cleanup.release ();
return;
}
- /* evaluate_probe_argument looks up symbols in the dynamic linker
+ /* evaluate_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
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);
+ these calls to evaluate_argument and save a lot of time. */
+ {
+ scoped_restore inhibit_updates
+ = inhibit_section_map_updates (current_program_space);
- val = evaluate_probe_argument (pa->probe, 1);
- if (val == NULL)
- {
- do_cleanups (old_chain);
+ try
+ {
+ val = pa->prob->evaluate_argument (1, frame);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ exception_print (gdb_stderr, ex);
+ val = NULL;
+ }
+
+ if (val == NULL)
return;
- }
- debug_base = value_as_address (val);
- if (debug_base == 0)
- {
- do_cleanups (old_chain);
+ debug_base = value_as_address (val);
+ if (debug_base == 0)
return;
- }
- /* Always locate the debug struct, in case it moved. */
- info->debug_base = 0;
- if (locate_base (info) == 0)
- {
- do_cleanups (old_chain);
+ /* Always locate the debug struct, in case it moved. */
+ info->debug_base = 0;
+ if (locate_base (info) == 0)
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;
+ /* 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 (action == UPDATE_OR_RELOAD)
+ {
+ try
+ {
+ val = pa->prob->evaluate_argument (2, frame);
+ }
+ catch (const gdb_exception_error &ex)
+ {
+ exception_print (gdb_stderr, ex);
+ return;
+ }
- if (lm == 0)
- action = FULL_RELOAD;
- }
+ if (val != NULL)
+ lm = value_as_address (val);
+
+ if (lm == 0)
+ action = FULL_RELOAD;
+ }
- /* Resume section map updates. */
- do_cleanups (usm_chain);
+ /* Resume section map updates. Closing the scope is
+ sufficient. */
+ }
if (action == UPDATE_OR_RELOAD)
{
if (action == FULL_RELOAD)
{
if (!solist_update_full (info))
- {
- do_cleanups (old_chain);
- return;
- }
+ return;
}
- discard_cleanups (old_chain);
+ cleanup.release ();
}
/* Helper function for svr4_update_solib_event_breakpoints. */
struct svr4_info *info;
struct probe_and_action *pa;
- info = program_space_data (loc->pspace, solib_svr4_pspace_data);
+ info = solib_svr4_pspace_data.get (loc->pspace);
if (info == NULL || info->probes_table == NULL)
continue;
probe. */
static void
-svr4_create_probe_breakpoints (struct gdbarch *gdbarch,
- VEC (probe_p) **probes)
+svr4_create_probe_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
+ const std::vector<probe *> *probes,
+ struct objfile *objfile)
{
- int i;
-
- for (i = 0; i < NUM_PROBES; i++)
+ for (int 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)
+ for (probe *p : probes[i])
{
- create_solib_event_breakpoint (gdbarch, probe->address);
- register_solib_event_probe (probe, action);
+ CORE_ADDR address = p->get_relocated_address (objfile);
+
+ create_solib_event_breakpoint (gdbarch, address);
+ register_solib_event_probe (info, objfile, p, address, action);
}
}
marker function. */
static void
-svr4_create_solib_event_breakpoints (struct gdbarch *gdbarch,
+svr4_create_solib_event_breakpoints (svr4_info *info, struct gdbarch *gdbarch,
CORE_ADDR address)
{
struct obj_section *os;
for (with_prefix = 0; with_prefix <= 1; with_prefix++)
{
- VEC (probe_p) *probes[NUM_PROBES];
+ std::vector<probe *> probes[NUM_PROBES];
int all_probes_found = 1;
- int i;
+ int checked_can_use_probe_arguments = 0;
- memset (probes, 0, sizeof (probes));
- for (i = 0; i < NUM_PROBES; i++)
+ for (int i = 0; i < NUM_PROBES; i++)
{
const char *name = probe_info[i].name;
+ probe *p;
char buf[32];
/* Fedora 17 and Red Hat Enterprise Linux 6.2-6.4
if (strcmp (name, "rtld_map_failed") == 0)
continue;
- if (VEC_empty (probe_p, probes[i]))
+ if (probes[i].empty ())
{
all_probes_found = 0;
break;
}
+
+ /* Ensure probe arguments can be evaluated. */
+ if (!checked_can_use_probe_arguments)
+ {
+ p = probes[i][0];
+ if (!p->can_evaluate_arguments ())
+ {
+ 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]);
+ svr4_create_probe_breakpoints (info, gdbarch, probes, os->objfile);
if (all_probes_found)
return;
/* 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);
static int
enable_break (struct svr4_info *info, int from_tty)
{
- struct minimal_symbol *msymbol;
+ struct bound_minimal_symbol msymbol;
const char * const *bkpt_namep;
asection *interp_sect;
- char *interp_name;
CORE_ADDR sym_addr;
info->interp_text_sect_low = info->interp_text_sect_high = 0;
mean r_brk has already been relocated. Assume the dynamic linker
is the object containing r_brk. */
- solib_add (NULL, from_tty, ¤t_target, auto_solib_add);
+ solib_add (NULL, from_tty, auto_solib_add);
sym_addr = 0;
if (info->debug_base && solib_svr4_r_map (info) != 0)
sym_addr = solib_svr4_r_brk (info);
struct obj_section *os;
sym_addr = gdbarch_addr_bits_remove
- (target_gdbarch (), gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
- sym_addr,
- ¤t_target));
+ (target_gdbarch (),
+ gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
+ sym_addr,
+ current_top_target ()));
/* On at least some versions of Solaris there's a dynamic relocation
on _r_debug.r_brk and SYM_ADDR may not be relocated yet, e.g., if
+ bfd_section_size (tmp_bfd, interp_sect);
}
- svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+ svr4_create_solib_event_breakpoints (info, target_gdbarch (), sym_addr);
return 1;
}
}
/* Find the program interpreter; if not found, warn the user and drop
into the old breakpoint at symbol code. */
- interp_name = find_program_interpreter ();
- if (interp_name)
+ gdb::optional<gdb::byte_vector> interp_name_holder
+ = find_program_interpreter ();
+ if (interp_name_holder)
{
+ const char *interp_name = (const char *) interp_name_holder->data ();
CORE_ADDR load_addr = 0;
int load_addr_found = 0;
int loader_found_in_list = 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)
+ gdb_bfd_ref_ptr tmp_bfd;
+ try
{
tmp_bfd = solib_bfd_open (interp_name);
}
+ catch (const gdb_exception &ex)
+ {
+ }
+
if (tmp_bfd == NULL)
goto bkpt_at_symbol;
/* Now convert the TMP_BFD into a target. That way target, as
- 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);
+ well as BFD operations can be used. target_bfd_reopen
+ acquires its own reference. */
+ tmp_bfd_target = target_bfd_reopen (tmp_bfd.get ());
/* On a running target, we can get the dynamic linker's base
address from the shared library table. */
{
load_addr_found = 1;
loader_found_in_list = 1;
- load_addr = lm_addr_check (so, tmp_bfd);
+ load_addr = lm_addr_check (so, tmp_bfd.get ());
break;
}
so = so->next;
/* If we were not able to find the base address of the loader
from our so_list, then try using the AT_BASE auxilliary entry. */
if (!load_addr_found)
- if (target_auxv_search (¤t_target, AT_BASE, &load_addr) > 0)
+ if (target_auxv_search (current_top_target (), AT_BASE, &load_addr) > 0)
{
int addr_bit = gdbarch_addr_bit (target_gdbarch ());
if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
{
CORE_ADDR space_size = (CORE_ADDR) 1 << addr_bit;
- CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd,
+ CORE_ADDR tmp_entry_point = exec_entry_point (tmp_bfd.get (),
tmp_bfd_target);
gdb_assert (load_addr < space_size);
= get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
load_addr = (regcache_read_pc (regcache)
- - exec_entry_point (tmp_bfd, tmp_bfd_target));
+ - exec_entry_point (tmp_bfd.get (), tmp_bfd_target));
}
if (!loader_found_in_list)
info->debug_loader_name = xstrdup (interp_name);
info->debug_loader_offset_p = 1;
info->debug_loader_offset = load_addr;
- solib_add (NULL, from_tty, ¤t_target, auto_solib_add);
+ solib_add (NULL, from_tty, auto_solib_add);
}
/* Record the relocated start and end address of the dynamic linker
text and plt section for svr4_in_dynsym_resolve_code. */
- interp_sect = bfd_get_section_by_name (tmp_bfd, ".text");
+ interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".text");
if (interp_sect)
{
info->interp_text_sect_low =
- bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+ bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
info->interp_text_sect_high =
info->interp_text_sect_low
- + bfd_section_size (tmp_bfd, interp_sect);
+ + bfd_section_size (tmp_bfd.get (), interp_sect);
}
- interp_sect = bfd_get_section_by_name (tmp_bfd, ".plt");
+ interp_sect = bfd_get_section_by_name (tmp_bfd.get (), ".plt");
if (interp_sect)
{
info->interp_plt_sect_low =
- bfd_section_vma (tmp_bfd, interp_sect) + load_addr;
+ bfd_section_vma (tmp_bfd.get (), interp_sect) + load_addr;
info->interp_plt_sect_high =
info->interp_plt_sect_low
- + bfd_section_size (tmp_bfd, interp_sect);
+ + bfd_section_size (tmp_bfd.get (), interp_sect);
}
/* Now try to set a breakpoint in the dynamic linker. */
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);
+ sym_addr = gdb_bfd_lookup_symbol (tmp_bfd.get (),
+ cmp_name_and_sec_flags,
+ *bkpt_namep);
if (sym_addr != 0)
break;
}
if (sym_addr != 0)
{
- svr4_create_solib_event_breakpoints (target_gdbarch (),
+ svr4_create_solib_event_breakpoints (info, target_gdbarch (),
load_addr + sym_addr);
- xfree (interp_name);
return 1;
}
/* For whatever reason we couldn't set a breakpoint in the dynamic
linker. Warn and drop into the old code. */
bkpt_at_symbol:
- xfree (interp_name);
warning (_("Unable to find dynamic linker breakpoint function.\n"
"GDB will be unable to debug shared library initializers\n"
"and track explicitly loaded dynamic code."));
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
{
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
- if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ if ((msymbol.minsym != NULL)
+ && (BMSYMBOL_VALUE_ADDRESS (msymbol) != 0))
{
- sym_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
sym_addr,
- ¤t_target);
- svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+ current_top_target ());
+ svr4_create_solib_event_breakpoints (info, target_gdbarch (),
+ sym_addr);
return 1;
}
}
- if (interp_name != NULL && !current_inferior ()->attach_flag)
+ if (interp_name_holder && !current_inferior ()->attach_flag)
{
for (bkpt_namep = bkpt_names; *bkpt_namep != NULL; bkpt_namep++)
{
msymbol = lookup_minimal_symbol (*bkpt_namep, NULL, symfile_objfile);
- if ((msymbol != NULL) && (SYMBOL_VALUE_ADDRESS (msymbol) != 0))
+ if ((msymbol.minsym != NULL)
+ && (BMSYMBOL_VALUE_ADDRESS (msymbol) != 0))
{
- sym_addr = SYMBOL_VALUE_ADDRESS (msymbol);
+ sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
sym_addr,
- ¤t_target);
- svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
+ current_top_target ());
+ svr4_create_solib_event_breakpoints (info, target_gdbarch (),
+ sym_addr);
return 1;
}
}
return 0;
}
-/* Implement the "special_symbol_handling" target_so_ops method. */
+/* Read the ELF program headers from ABFD. */
-static void
-svr4_special_symbol_handling (void)
+static gdb::optional<gdb::byte_vector>
+read_program_headers_from_bfd (bfd *abfd)
{
- /* Nothing to do. */
-}
-
-/* Read the ELF program headers from ABFD. Return the contents and
- set *PHDRS_SIZE to the size of the program headers. */
+ Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
+ int phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
+ if (phdrs_size == 0)
+ return {};
-static gdb_byte *
-read_program_headers_from_bfd (bfd *abfd, int *phdrs_size)
-{
- Elf_Internal_Ehdr *ehdr;
- gdb_byte *buf;
-
- ehdr = elf_elfheader (abfd);
-
- *phdrs_size = ehdr->e_phnum * ehdr->e_phentsize;
- if (*phdrs_size == 0)
- return NULL;
-
- buf = xmalloc (*phdrs_size);
+ gdb::byte_vector buf (phdrs_size);
if (bfd_seek (abfd, ehdr->e_phoff, SEEK_SET) != 0
- || bfd_bread (buf, *phdrs_size, abfd) != *phdrs_size)
- {
- xfree (buf);
- return NULL;
- }
+ || bfd_bread (buf.data (), phdrs_size, abfd) != phdrs_size)
+ return {};
return buf;
}
{
/* 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 ((bfd_get_file_flags (exec_bfd) & DYNAMIC) == 0)
return 0;
- if (target_auxv_search (¤t_target, AT_ENTRY, &entry_point) <= 0)
+ if (target_auxv_search (current_top_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;
}
if (bfd_get_flavour (exec_bfd) == bfd_target_elf_flavour)
{
- /* Be optimistic and clear OK only if GDB was able to verify the headers
+ /* Be optimistic and return 0 only if GDB was able to verify the headers
really do not match. */
- int phdrs_size, phdrs2_size, ok = 1;
- gdb_byte *buf, *buf2;
int arch_size;
- buf = read_program_header (-1, &phdrs_size, &arch_size);
- buf2 = read_program_headers_from_bfd (exec_bfd, &phdrs2_size);
- if (buf != NULL && buf2 != NULL)
+ gdb::optional<gdb::byte_vector> phdrs_target
+ = read_program_header (-1, &arch_size, NULL);
+ gdb::optional<gdb::byte_vector> phdrs_binary
+ = read_program_headers_from_bfd (exec_bfd);
+ if (phdrs_target && phdrs_binary)
{
enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
relocate BUF and BUF2 just by the EXEC_BFD vs. target memory
content offset for the verification purpose. */
- if (phdrs_size != phdrs2_size
+ if (phdrs_target->size () != phdrs_binary->size ()
|| bfd_get_arch_size (exec_bfd) != arch_size)
- ok = 0;
+ return 0;
else if (arch_size == 32
- && phdrs_size >= sizeof (Elf32_External_Phdr)
- && phdrs_size % sizeof (Elf32_External_Phdr) == 0)
+ && phdrs_target->size () >= sizeof (Elf32_External_Phdr)
+ && phdrs_target->size () % sizeof (Elf32_External_Phdr) == 0)
{
Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
CORE_ADDR displacement_vaddr = 0;
CORE_ADDR displacement_paddr = 0;
- phdrp = &((Elf32_External_Phdr *) buf)[i];
+ phdrp = &((Elf32_External_Phdr *) phdrs_target->data ())[i];
buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
break;
}
- /* Now compare BUF and BUF2 with optional DISPLACEMENT. */
+ /* Now compare program headers from the target and the binary
+ with optional DISPLACEMENT. */
- for (i = 0; i < phdrs_size / sizeof (Elf32_External_Phdr); i++)
+ for (i = 0;
+ i < phdrs_target->size () / sizeof (Elf32_External_Phdr);
+ i++)
{
Elf32_External_Phdr *phdrp;
Elf32_External_Phdr *phdr2p;
CORE_ADDR vaddr, paddr;
asection *plt2_asect;
- phdrp = &((Elf32_External_Phdr *) buf)[i];
+ phdrp = &((Elf32_External_Phdr *) phdrs_target->data ())[i];
buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
- phdr2p = &((Elf32_External_Phdr *) buf2)[i];
+ phdr2p = &((Elf32_External_Phdr *) phdrs_binary->data ())[i];
/* PT_GNU_STACK is an exception by being never relocated by
prelink as its addresses are always zero. */
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.
+ Strip also modifies memsz of PT_TLS.
+ See PR 11786. */
+ if (phdr2[i].p_type == PT_GNU_RELRO
+ || phdr2[i].p_type == PT_TLS)
+ {
+ 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)
continue;
}
- ok = 0;
- break;
+ return 0;
}
}
else if (arch_size == 64
- && phdrs_size >= sizeof (Elf64_External_Phdr)
- && phdrs_size % sizeof (Elf64_External_Phdr) == 0)
+ && phdrs_target->size () >= sizeof (Elf64_External_Phdr)
+ && phdrs_target->size () % sizeof (Elf64_External_Phdr) == 0)
{
Elf_Internal_Ehdr *ehdr2 = elf_tdata (exec_bfd)->elf_header;
Elf_Internal_Phdr *phdr2 = elf_tdata (exec_bfd)->phdr;
CORE_ADDR displacement_vaddr = 0;
CORE_ADDR displacement_paddr = 0;
- phdrp = &((Elf64_External_Phdr *) buf)[i];
+ phdrp = &((Elf64_External_Phdr *) phdrs_target->data ())[i];
buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
/* Now compare BUF and BUF2 with optional DISPLACEMENT. */
- for (i = 0; i < phdrs_size / sizeof (Elf64_External_Phdr); i++)
+ for (i = 0;
+ i < phdrs_target->size () / sizeof (Elf64_External_Phdr);
+ i++)
{
Elf64_External_Phdr *phdrp;
Elf64_External_Phdr *phdr2p;
CORE_ADDR vaddr, paddr;
asection *plt2_asect;
- phdrp = &((Elf64_External_Phdr *) buf)[i];
+ phdrp = &((Elf64_External_Phdr *) phdrs_target->data ())[i];
buf_vaddr_p = (gdb_byte *) &phdrp->p_vaddr;
buf_paddr_p = (gdb_byte *) &phdrp->p_paddr;
- phdr2p = &((Elf64_External_Phdr *) buf2)[i];
+ phdr2p = &((Elf64_External_Phdr *) phdrs_binary->data ())[i];
/* PT_GNU_STACK is an exception by being never relocated by
prelink as its addresses are always zero. */
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.
+ Strip also modifies memsz of PT_TLS.
+ See PR 11786. */
+ if (phdr2[i].p_type == PT_GNU_RELRO
+ || phdr2[i].p_type == PT_TLS)
+ {
+ 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)
continue;
}
- ok = 0;
- break;
+ return 0;
}
}
else
- ok = 0;
+ return 0;
}
-
- xfree (buf);
- xfree (buf2);
-
- if (!ok)
- return 0;
}
if (info_verbose)
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;
{
struct svr4_info *info;
- info = get_svr4_info ();
+ info = get_svr4_info (current_program_space);
/* Clear the probes-based interface's state. */
free_probes_table (info);
{
struct svr4_info *info;
- info = get_svr4_info ();
+ info = get_svr4_info (current_program_space);
info->debug_base = 0;
info->debug_loader_offset_p = 0;
info->debug_loader_offset = 0;
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));
}
\f
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 {};
return lookup_global_symbol_from_objfile (objfile, name, domain);
}
-extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
-
void
_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 (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;
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;
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;
+
+ gdb::observers::free_objfile.attach (svr4_free_objfile_observer);
}