diff options
author | Aaron Merey <amerey@redhat.com> | 2021-08-10 22:05:44 -0400 |
---|---|---|
committer | Aaron Merey <amerey@redhat.com> | 2021-08-18 22:24:18 -0400 |
commit | 8ddf46454aa981246f9611b1897f41fabd2a108d (patch) | |
tree | 17b1d9632a2f2e5d8627b7d50585d13690630b10 /gdb/solib.c | |
parent | 76bed1fdbd7256228847962770bdc5832c53172c (diff) | |
download | gdb-8ddf46454aa981246f9611b1897f41fabd2a108d.zip gdb-8ddf46454aa981246f9611b1897f41fabd2a108d.tar.gz gdb-8ddf46454aa981246f9611b1897f41fabd2a108d.tar.bz2 |
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.
Diffstat (limited to 'gdb/solib.c')
-rw-r--r-- | gdb/solib.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/gdb/solib.c b/gdb/solib.c index 317f7eb..e30affb 100644 --- a/gdb/solib.c +++ b/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 |