From: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
This patch refactors a number of gprofng internal functions for using
more BFD data types and functions.
Stabs::readSymSec is a function which reads the symbols of an ELF file
mapping them into an internal structure. To use BFD asymbols, the
Elf::elf_getsym is changed from custom reading of the symbols from
.symtab and .dynsym section to BFD enable functions. A new function is
introduced which returns the number of either static or dynamic symbols,
named Elf::elf_getSymCount. Both Elf functions are used by
Stabs::readSymSec refactoring.
Also, this patch removes reading symbols, SUNW_ldnsym section as it is
only used by now defunct Studio compiler. However, it adds the reading
of both static and dynamic symbols, previously, only either one was
processed.
Signed-off-by: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
---
gprofng/src/DwarfLib.cc | 24 ++++----------
gprofng/src/Elf.cc | 69 +++++++++++++++++++++--------------------
gprofng/src/Elf.h | 3 +-
gprofng/src/Stabs.cc | 42 +++++++++----------------
gprofng/src/Stabs.h | 2 +-
5 files changed, 59 insertions(+), 81 deletions(-)
@@ -204,12 +204,6 @@ ElfReloc::dump_rela_debug_sec (int sec)
if (ScnSize == 0 || EntSize == 0)
return;
- Elf_Internal_Shdr *shdr_sym = elf->get_shdr (shdr->sh_link);
- if (shdr_sym == NULL)
- return;
- Elf_Data *data_sym = elf->elf_getdata (shdr->sh_link);
- Elf_Data *data_str = elf->elf_getdata (shdr_sym->sh_link);
- char *Strtab = data_str ? (char*) data_str->d_buf : NULL;
Elf_Internal_Rela rela;
int n, cnt = (int) (ScnSize / EntSize);
@@ -233,7 +227,8 @@ ElfReloc::dump_rela_debug_sec (int sec)
int ndx = (int) GELF_R_SYM (rela.r_info);
Elf_Internal_Shdr *secHdr;
Elf_Internal_Sym sym;
- elf->elf_getsym (data_sym, ndx, &sym);
+ asymbol *asym;
+ asym = elf->elf_getsym (ndx, &sym, false);
Dprintf (DUMP_RELA_SEC, NTXT ("%3d:%5d |%11lld |0x%016llx | %-15s|"),
n, (int) rela.r_addend,
(long long) rela.r_offset, (long long) rela.r_info,
@@ -243,12 +238,9 @@ ElfReloc::dump_rela_debug_sec (int sec)
case STT_FUNC:
case STT_OBJECT:
case STT_NOTYPE:
- secHdr = elf->get_shdr (sym.st_shndx);
- if (secHdr)
- Dprintf (DUMP_RELA_SEC, NTXT (" img_offset=0x%llx"),
- (long long) (sym.st_value + secHdr->sh_offset));
- if (Strtab && sym.st_name)
- Dprintf (DUMP_RELA_SEC, NTXT (" %s"), Strtab + sym.st_name);
+ Dprintf (DUMP_RELA_SEC, NTXT (" img_offset=0x%llx"),
+ (long long) (bfd_asymbol_value (asym)));
+ Dprintf (DUMP_RELA_SEC, NTXT (" %s"), bfd_asymbol_name (asym));
break;
case STT_SECTION:
secHdr = elf->get_shdr (sym.st_shndx);
@@ -311,10 +303,6 @@ ElfReloc::get_elf_reloc (Elf *elfp, char *sec_name, ElfReloc *rlc)
return rlc;
int cnt = (int) (data->d_size / shdr->sh_entsize);
- Elf_Internal_Shdr *shdr_sym = elfp->get_shdr (shdr->sh_link);
- if (shdr_sym == NULL)
- return rlc;
- Elf_Data *data_sym = elfp->elf_getdata (shdr->sh_link);
Vector<Sreloc *> *vp = NULL;
for (int n = 0; n < cnt; n++)
@@ -331,7 +319,7 @@ ElfReloc::get_elf_reloc (Elf *elfp, char *sec_name, ElfReloc *rlc)
}
int ndx = (int) GELF_R_SYM (rela.r_info);
Elf_Internal_Sym sym;
- elfp->elf_getsym (data_sym, ndx, &sym);
+ elfp->elf_getsym (ndx, &sym, false);
srlc = new Sreloc;
srlc->offset = rela.r_offset;
@@ -533,42 +533,43 @@ Elf::elf_strptr (unsigned int sec, uint64_t off)
return NULL;
}
-Elf_Internal_Sym *
-Elf::elf_getsym (Elf_Data *edta, unsigned int ndx, Elf_Internal_Sym *dst)
+long
+Elf::elf_getSymCount (bool is_dynamic)
{
- if (dst == NULL || edta == NULL)
- return NULL;
- if (elf_getclass () == ELFCLASS32)
- {
- if (edta->d_size <= ndx * sizeof (Elf32_Sym))
- return NULL;
- Elf32_Sym *hdr = (Elf32_Sym*) bind (edta->d_off + ndx * sizeof (Elf32_Sym), sizeof (Elf32_Sym));
- if (hdr == NULL)
- return NULL;
- dst->st_name = decode (hdr->st_name);
- dst->st_value = decode (hdr->st_value);
- dst->st_size = decode (hdr->st_size);
- dst->st_info = ELF64_ST_INFO (ELF32_ST_BIND (decode (hdr->st_info)),
- ELF32_ST_TYPE (decode (hdr->st_info)));
- dst->st_other = decode (hdr->st_other);
- dst->st_shndx = decode (hdr->st_shndx);
- }
+ if (bfd_dynsym == NULL && bfd_sym == NULL)
+ get_bfd_symbols ();
+ if (is_dynamic)
+ return bfd_dynsymcnt;
+ return bfd_symcnt;
+}
+
+/* Returns an ASYMBOL on index NDX if it exists. If DST is defined,
+ the internal elf symbol at intex NDX is copied into it. IS_DYNAMIC
+ selects the type of the symbol. */
+
+asymbol *
+Elf::elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic)
+{
+ asymbol *asym;
+
+ if (bfd_dynsym == NULL && bfd_sym == NULL)
+ get_bfd_symbols ();
+
+ if (is_dynamic)
+ if (ndx < bfd_dynsymcnt)
+ asym = bfd_dynsym[ndx];
+ else
+ return NULL;
else
- {
- if (edta->d_size <= ndx * sizeof (Elf64_Sym))
- return NULL;
- Elf64_Sym *hdr = (Elf64_Sym*) bind (edta->d_off + ndx * sizeof (Elf64_Sym),
- sizeof (Elf64_Sym));
- if (hdr == NULL)
- return NULL;
- dst->st_name = decode (hdr->st_name);
- dst->st_value = decode (hdr->st_value);
- dst->st_size = decode (hdr->st_size);
- dst->st_info = decode (hdr->st_info);
- dst->st_other = decode (hdr->st_other);
- dst->st_shndx = decode (hdr->st_shndx);
- }
- return dst;
+ if (ndx < bfd_symcnt)
+ asym = bfd_sym[ndx];
+ else
+ return NULL;
+
+ if (dst != NULL)
+ *dst = ((elf_symbol_type *) asym)->internal_elf_sym;
+
+ return asym;
}
Elf_Internal_Rela *
@@ -92,7 +92,8 @@ public:
int64_t elf_checksum ();
uint64_t get_baseAddr();
char *elf_strptr (unsigned int sec, uint64_t off);
- Elf_Internal_Sym *elf_getsym (Elf_Data *edta, unsigned int ndx, Elf_Internal_Sym *dst);
+ long elf_getSymCount (bool is_dynamic);
+ asymbol *elf_getsym (unsigned int ndx, Elf_Internal_Sym *dst, bool is_dynamic);
Elf_Internal_Rela *elf_getrel (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst);
Elf_Internal_Rela *elf_getrela (Elf_Data *edta, unsigned int ndx, Elf_Internal_Rela *dst);
Elf64_Ancillary *elf_getancillary (Elf_Data *edta, unsigned int ndx, Elf64_Ancillary *dst);
@@ -1702,43 +1702,31 @@ Stabs::check_Symtab ()
pltSym->flags |= SYM_PLT;
}
}
- if (elf->symtab)
- readSymSec (elf->symtab, elf);
- else
- {
- readSymSec (elf->SUNW_ldynsym, elf);
- readSymSec (elf->dynsym, elf);
- }
+
+ // Read first static symbols
+ readSymSec (elf, false);
+
+ // Read dynamic symbols
+ readSymSec (elf, true);
}
void
-Stabs::readSymSec (unsigned int sec, Elf *elf)
+Stabs::readSymSec (Elf *elf, bool is_dynamic)
{
Symbol *sitem;
Sp_lang_code local_lcode;
- if (sec == 0)
- return;
- // Get ELF data
- Elf_Data *data = elf->elf_getdata (sec);
- if (data == NULL)
- return;
- uint64_t SymtabSize = data->d_size;
- Elf_Internal_Shdr *shdr = elf->get_shdr (sec);
-
- if ((SymtabSize == 0) || (shdr->sh_entsize == 0))
- return;
- Elf_Data *data_str = elf->elf_getdata (shdr->sh_link);
- if (data_str == NULL)
- return;
- char *Strtab = (char *) data_str->d_buf;
+ unsigned int tot = elf->elf_getSymCount (is_dynamic);
// read func symbolic table
- for (unsigned int n = 0, tot = SymtabSize / shdr->sh_entsize; n < tot; n++)
+ for (unsigned int n = 0; n < tot; n++)
{
Elf_Internal_Sym Sym;
- elf->elf_getsym (data, n, &Sym);
- const char *st_name = Sym.st_name < data_str->d_size ?
- (Strtab + Sym.st_name) : NTXT ("no_name");
+ asymbol *asym;
+ asym = elf->elf_getsym (n, &Sym, is_dynamic);
+ // TBD: convert this check to an assert
+ if (asym == NULL)
+ break;
+ const char *st_name = bfd_asymbol_name (asym);
switch (GELF_ST_TYPE (Sym.st_info))
{
case STT_FUNC:
@@ -129,7 +129,7 @@ class Stabs {
// Interface with Elf Symbol Table
void check_Symtab();
- void readSymSec(unsigned int sec, Elf *elf);
+ void readSymSec (Elf *elf, bool is_dynamic);
void get_save_addr(bool need_swap_endian);
Symbol *map_PC_to_sym(uint64_t pc);
Symbol *pltSym;