gdb/solib: Refactor scan_dyntag
scan_dyntag is unnecessarily duplicated in solib-svr4.c and solib-dsbt.c. Move this function to solib.c and rename it to gdb_bfd_scan_elf_dyntag. Also add it to solib.h so it is included in both solib-svr4 and solib-dsbt.
This commit is contained in:
parent
76bed1fdbd
commit
8ddf46454a
4 changed files with 122 additions and 210 deletions
104
gdb/solib-dsbt.c
104
gdb/solib-dsbt.c
|
@ -396,106 +396,6 @@ fetch_loadmap (CORE_ADDR ldmaddr)
|
|||
static void dsbt_relocate_main_executable (void);
|
||||
static int enable_break (void);
|
||||
|
||||
/* Scan for DYNTAG in .dynamic section of ABFD. If DYNTAG is found 1 is
|
||||
returned and the corresponding PTR is set. */
|
||||
|
||||
static int
|
||||
scan_dyntag (int dyntag, bfd *abfd, CORE_ADDR *ptr)
|
||||
{
|
||||
int arch_size, step, sect_size;
|
||||
long dyn_tag;
|
||||
CORE_ADDR dyn_ptr, dyn_addr;
|
||||
gdb_byte *bufend, *bufstart, *buf;
|
||||
Elf32_External_Dyn *x_dynp_32;
|
||||
Elf64_External_Dyn *x_dynp_64;
|
||||
struct bfd_section *sect;
|
||||
|
||||
if (abfd == NULL)
|
||||
return 0;
|
||||
|
||||
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
|
||||
return 0;
|
||||
|
||||
arch_size = bfd_get_arch_size (abfd);
|
||||
if (arch_size == -1)
|
||||
return 0;
|
||||
|
||||
/* Find the start address of the .dynamic section. */
|
||||
sect = bfd_get_section_by_name (abfd, ".dynamic");
|
||||
if (sect == NULL)
|
||||
return 0;
|
||||
|
||||
bool found = false;
|
||||
for (const target_section &target_section
|
||||
: current_program_space->target_sections ())
|
||||
if (sect == target_section.the_bfd_section)
|
||||
{
|
||||
dyn_addr = target_section.addr;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
/* ABFD may come from OBJFILE acting only as a symbol file without being
|
||||
loaded into the target (see add_symbol_file_command). This case is
|
||||
such fallback to the file VMA address without the possibility of
|
||||
having the section relocated to its actual in-memory address. */
|
||||
|
||||
dyn_addr = bfd_section_vma (sect);
|
||||
}
|
||||
|
||||
/* Read in .dynamic from the BFD. We will get the actual value
|
||||
from memory later. */
|
||||
sect_size = bfd_section_size (sect);
|
||||
buf = bufstart = (gdb_byte *) alloca (sect_size);
|
||||
if (!bfd_get_section_contents (abfd, sect,
|
||||
buf, 0, sect_size))
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
dyn_ptr = bfd_h_get_64 (abfd, (bfd_byte *) x_dynp_64->d_un.d_ptr);
|
||||
}
|
||||
if (dyn_tag == DT_NULL)
|
||||
return 0;
|
||||
if (dyn_tag == dyntag)
|
||||
{
|
||||
/* If requested, try to read the runtime value of this .dynamic
|
||||
entry. */
|
||||
if (ptr)
|
||||
{
|
||||
struct type *ptr_type;
|
||||
gdb_byte ptr_buf[8];
|
||||
CORE_ADDR ptr_addr;
|
||||
|
||||
ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
|
||||
ptr_addr = dyn_addr + (buf - bufstart) + arch_size / 8;
|
||||
if (target_read_memory (ptr_addr, ptr_buf, arch_size / 8) == 0)
|
||||
dyn_ptr = extract_typed_address (ptr_buf, ptr_type);
|
||||
*ptr = dyn_ptr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See solist.h. */
|
||||
|
||||
static int
|
||||
|
@ -565,7 +465,9 @@ lm_base (void)
|
|||
"lm_base: get addr %x by _GLOBAL_OFFSET_TABLE_.\n",
|
||||
(unsigned int) addr);
|
||||
}
|
||||
else if (scan_dyntag (DT_PLTGOT, current_program_space->exec_bfd (), &addr))
|
||||
else if (gdb_bfd_scan_elf_dyntag (DT_PLTGOT,
|
||||
current_program_space->exec_bfd (),
|
||||
&addr, NULL))
|
||||
{
|
||||
struct int_elf32_dsbt_loadmap *ldm;
|
||||
|
||||
|
|
118
gdb/solib-svr4.c
118
gdb/solib-svr4.c
|
@ -582,109 +582,6 @@ find_program_interpreter (void)
|
|||
}
|
||||
|
||||
|
||||
/* 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 (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr,
|
||||
CORE_ADDR *ptr_addr)
|
||||
{
|
||||
int arch_size, step, sect_size;
|
||||
long current_dyntag;
|
||||
CORE_ADDR dyn_ptr, dyn_addr;
|
||||
gdb_byte *bufend, *bufstart, *buf;
|
||||
Elf32_External_Dyn *x_dynp_32;
|
||||
Elf64_External_Dyn *x_dynp_64;
|
||||
struct bfd_section *sect;
|
||||
|
||||
if (abfd == NULL)
|
||||
return 0;
|
||||
|
||||
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
|
||||
return 0;
|
||||
|
||||
arch_size = bfd_get_arch_size (abfd);
|
||||
if (arch_size == -1)
|
||||
return 0;
|
||||
|
||||
/* Find the start address of the .dynamic section. */
|
||||
sect = bfd_get_section_by_name (abfd, ".dynamic");
|
||||
if (sect == NULL)
|
||||
return 0;
|
||||
|
||||
bool found = false;
|
||||
for (const target_section &target_section
|
||||
: current_program_space->target_sections ())
|
||||
if (sect == target_section.the_bfd_section)
|
||||
{
|
||||
dyn_addr = target_section.addr;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
/* ABFD may come from OBJFILE acting only as a symbol file without being
|
||||
loaded into the target (see add_symbol_file_command). This case is
|
||||
such fallback to the file VMA address without the possibility of
|
||||
having the section relocated to its actual in-memory address. */
|
||||
|
||||
dyn_addr = bfd_section_vma (sect);
|
||||
}
|
||||
|
||||
/* Read in .dynamic from the BFD. We will get the actual value
|
||||
from memory later. */
|
||||
sect_size = bfd_section_size (sect);
|
||||
buf = bufstart = (gdb_byte *) alloca (sect_size);
|
||||
if (!bfd_get_section_contents (abfd, sect,
|
||||
buf, 0, sect_size))
|
||||
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)
|
||||
{
|
||||
if (arch_size == 32)
|
||||
{
|
||||
x_dynp_32 = (Elf32_External_Dyn *) buf;
|
||||
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;
|
||||
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 (current_dyntag == DT_NULL)
|
||||
return 0;
|
||||
if (current_dyntag == desired_dyntag)
|
||||
{
|
||||
/* If requested, try to read the runtime value of this .dynamic
|
||||
entry. */
|
||||
if (ptr)
|
||||
{
|
||||
struct type *ptr_type;
|
||||
gdb_byte ptr_buf[8];
|
||||
CORE_ADDR ptr_addr_1;
|
||||
|
||||
ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
|
||||
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 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. */
|
||||
|
@ -768,8 +665,9 @@ elf_locate_base (void)
|
|||
/* 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, current_program_space->exec_bfd (),
|
||||
&dyn_ptr, NULL)
|
||||
if (gdb_bfd_scan_elf_dyntag (DT_MIPS_RLD_MAP,
|
||||
current_program_space->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;
|
||||
|
@ -787,8 +685,9 @@ elf_locate_base (void)
|
|||
/* 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, current_program_space->exec_bfd (),
|
||||
&dyn_ptr, &dyn_ptr_addr)
|
||||
if (gdb_bfd_scan_elf_dyntag (DT_MIPS_RLD_MAP_REL,
|
||||
current_program_space->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;
|
||||
|
@ -804,7 +703,8 @@ elf_locate_base (void)
|
|||
}
|
||||
|
||||
/* Find DT_DEBUG. */
|
||||
if (scan_dyntag (DT_DEBUG, current_program_space->exec_bfd (), &dyn_ptr, NULL)
|
||||
if (gdb_bfd_scan_elf_dyntag (DT_DEBUG, current_program_space->exec_bfd (),
|
||||
&dyn_ptr, NULL)
|
||||
|| scan_dyntag_auxv (DT_DEBUG, &dyn_ptr, NULL))
|
||||
return dyn_ptr;
|
||||
|
||||
|
@ -3258,7 +3158,7 @@ svr4_iterate_over_objfiles_in_search_order
|
|||
abfd = current_objfile->obfd;
|
||||
|
||||
if (abfd != nullptr
|
||||
&& scan_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
|
||||
&& gdb_bfd_scan_elf_dyntag (DT_SYMBOLIC, abfd, nullptr, nullptr) == 1)
|
||||
{
|
||||
checked_current_objfile = true;
|
||||
if (cb (current_objfile, cb_data) != 0)
|
||||
|
|
104
gdb/solib.c
104
gdb/solib.c
|
@ -35,6 +35,8 @@
|
|||
#include "language.h"
|
||||
#include "gdbcmd.h"
|
||||
#include "completer.h"
|
||||
#include "elf/external.h"
|
||||
#include "elf/common.h"
|
||||
#include "filenames.h" /* for DOSish file names */
|
||||
#include "exec.h"
|
||||
#include "solist.h"
|
||||
|
@ -1481,6 +1483,108 @@ gdb_bfd_lookup_symbol_from_symtab (bfd *abfd,
|
|||
return symaddr;
|
||||
}
|
||||
|
||||
/* See solib.h. */
|
||||
|
||||
int
|
||||
gdb_bfd_scan_elf_dyntag (const int desired_dyntag, bfd *abfd, CORE_ADDR *ptr,
|
||||
CORE_ADDR *ptr_addr)
|
||||
{
|
||||
int arch_size, step, sect_size;
|
||||
long current_dyntag;
|
||||
CORE_ADDR dyn_ptr, dyn_addr;
|
||||
gdb_byte *bufend, *bufstart, *buf;
|
||||
Elf32_External_Dyn *x_dynp_32;
|
||||
Elf64_External_Dyn *x_dynp_64;
|
||||
struct bfd_section *sect;
|
||||
|
||||
if (abfd == NULL)
|
||||
return 0;
|
||||
|
||||
if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
|
||||
return 0;
|
||||
|
||||
arch_size = bfd_get_arch_size (abfd);
|
||||
if (arch_size == -1)
|
||||
return 0;
|
||||
|
||||
/* Find the start address of the .dynamic section. */
|
||||
sect = bfd_get_section_by_name (abfd, ".dynamic");
|
||||
if (sect == NULL)
|
||||
return 0;
|
||||
|
||||
bool found = false;
|
||||
for (const target_section &target_section
|
||||
: current_program_space->target_sections ())
|
||||
if (sect == target_section.the_bfd_section)
|
||||
{
|
||||
dyn_addr = target_section.addr;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
/* ABFD may come from OBJFILE acting only as a symbol file without being
|
||||
loaded into the target (see add_symbol_file_command). This case is
|
||||
such fallback to the file VMA address without the possibility of
|
||||
having the section relocated to its actual in-memory address. */
|
||||
|
||||
dyn_addr = bfd_section_vma (sect);
|
||||
}
|
||||
|
||||
/* Read in .dynamic from the BFD. We will get the actual value
|
||||
from memory later. */
|
||||
sect_size = bfd_section_size (sect);
|
||||
buf = bufstart = (gdb_byte *) alloca (sect_size);
|
||||
if (!bfd_get_section_contents (abfd, sect,
|
||||
buf, 0, sect_size))
|
||||
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)
|
||||
{
|
||||
if (arch_size == 32)
|
||||
{
|
||||
x_dynp_32 = (Elf32_External_Dyn *) buf;
|
||||
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;
|
||||
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 (current_dyntag == DT_NULL)
|
||||
return 0;
|
||||
if (current_dyntag == desired_dyntag)
|
||||
{
|
||||
/* If requested, try to read the runtime value of this .dynamic
|
||||
entry. */
|
||||
if (ptr)
|
||||
{
|
||||
struct type *ptr_type;
|
||||
gdb_byte ptr_buf[8];
|
||||
CORE_ADDR ptr_addr_1;
|
||||
|
||||
ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr;
|
||||
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;
|
||||
}
|
||||
|
||||
/* Lookup the value for a specific symbol from symbol table. Look up symbol
|
||||
from ABFD. MATCH_SYM is a callback function to determine whether to pick
|
||||
up a symbol. DATA is the input of this callback function. Return NULL
|
||||
|
|
|
@ -112,6 +112,12 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_from_symtab (bfd *abfd,
|
|||
const void *),
|
||||
const void *data);
|
||||
|
||||
/* Scan for DESIRED_DYNTAG in .dynamic section of ABFD. If DESIRED_DYNTAG is
|
||||
found, 1 is returned and the corresponding PTR and PTR_ADDR are set. */
|
||||
|
||||
extern int gdb_bfd_scan_elf_dyntag (const int desired_dyntag, bfd *abfd,
|
||||
CORE_ADDR *ptr, CORE_ADDR *ptr_addr);
|
||||
|
||||
/* Enable or disable optional solib event breakpoints as appropriate. */
|
||||
|
||||
extern void update_solib_breakpoints (void);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue