gprofng: Refactor readSymSec for using BFD's asymbol struct

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>
This commit is contained in:
Claudiu Zissulescu
2025-03-28 13:33:26 +02:00
committed by Vladimir Mezentsev
parent 91fd524499
commit 13f614be23
5 changed files with 59 additions and 81 deletions

View File

@@ -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;

View File

@@ -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 *

View File

@@ -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);

View File

@@ -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:

View File

@@ -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;