From 13f614be23ab6ef1018ddf9c133175e806e68ed8 Mon Sep 17 00:00:00 2001 From: Claudiu Zissulescu Date: Fri, 28 Mar 2025 13:33:26 +0200 Subject: [PATCH] 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 --- 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(-) diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc index 9b40401138b..d399c3356cf 100644 --- a/gprofng/src/DwarfLib.cc +++ b/gprofng/src/DwarfLib.cc @@ -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 *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; diff --git a/gprofng/src/Elf.cc b/gprofng/src/Elf.cc index b9da2403bef..f0fd1215a04 100644 --- a/gprofng/src/Elf.cc +++ b/gprofng/src/Elf.cc @@ -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 * diff --git a/gprofng/src/Elf.h b/gprofng/src/Elf.h index 7c32dfe10b1..b324c394d16 100644 --- a/gprofng/src/Elf.h +++ b/gprofng/src/Elf.h @@ -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); diff --git a/gprofng/src/Stabs.cc b/gprofng/src/Stabs.cc index 908dcc4b7b4..2f64810b25f 100644 --- a/gprofng/src/Stabs.cc +++ b/gprofng/src/Stabs.cc @@ -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: diff --git a/gprofng/src/Stabs.h b/gprofng/src/Stabs.h index 88c2b8d64a5..a6a572d938c 100644 --- a/gprofng/src/Stabs.h +++ b/gprofng/src/Stabs.h @@ -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; -- 2.39.5