diff options
Diffstat (limited to 'gprofng')
-rw-r--r-- | gprofng/src/DwarfLib.cc | 24 | ||||
-rw-r--r-- | gprofng/src/Elf.cc | 69 | ||||
-rw-r--r-- | gprofng/src/Elf.h | 3 | ||||
-rw-r--r-- | gprofng/src/Stabs.cc | 216 | ||||
-rw-r--r-- | gprofng/src/Stabs.h | 6 | ||||
-rw-r--r-- | gprofng/src/vec.h | 7 |
6 files changed, 104 insertions, 221 deletions
diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc index 9b40401..d399c33 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<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; diff --git a/gprofng/src/Elf.cc b/gprofng/src/Elf.cc index b9da240..f0fd121 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 7c32dfe..b324c39 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 2120319..b98ac28 100644 --- a/gprofng/src/Stabs.cc +++ b/gprofng/src/Stabs.cc @@ -241,6 +241,40 @@ RelValueCmp (const void *a, const void *b) (item1->value == item2->value) ? 0 : -1; } +/* Remove all duplicate symbols which can be in SymLst. The + duplication is due to processing of both static and dynamic + symbols. This function is called before computing symbol + aliases. */ + +void +Stabs::removeDupSyms () +{ + long ind, i, last; + Symbol *symA, *symB; + SymLst->sort (SymImgOffsetCmp); + dump (); + + last = 0; + ind = SymLst->size (); + for (i = 0; i < ind; i++) + { + symA = SymLst->fetch (i); + if (symA->img_offset == 0) // Ignore this bad symbol + continue; + + SymLst->put (last++, symA); + for (long k = i + 1; k < ind; k++, i++) + { + symB = SymLst->fetch (k); + if (symA->img_offset != symB->img_offset) + break; + if (strcmp (symA->name, symB->name) != 0) + break; + } + } + SymLst->truncate (last); +} + Stabs * Stabs::NewStabs (char *_path, char *lo_name) { @@ -272,7 +306,7 @@ Stabs::Stabs (char *_path, char *_lo_name) stabsModules = NULL; textsz = 0; wsize = Wnone; - st_check_symtab = st_check_relocs = false; + st_check_symtab = false; status = DBGD_ERR_NONE; if (openElf (false) == NULL) @@ -412,7 +446,6 @@ Stabs::read_symbols (Vector<Function*> *functions) if (openElf (true) == NULL) return false; check_Symtab (); - check_Relocs (); if (functions) { Function *fp; @@ -1703,43 +1736,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: @@ -1814,6 +1835,7 @@ Stabs::readSymSec (unsigned int sec, Elf *elf) } } } + removeDupSyms (); fixSymtabAlias (); SymLst->sort (SymValueCmp); get_save_addr (elf->need_swap_endian); @@ -1821,142 +1843,6 @@ Stabs::readSymSec (unsigned int sec, Elf *elf) }//check_Symtab void -Stabs::check_Relocs () -{ - // We may have many relocation tables to process: .rela.text%foo, - // rela.text%bar, etc. On Intel, compilers generate .rel.text sections - // which have to be processed as well. A lot of rework is needed here. - Symbol *sptr = NULL; - if (st_check_relocs) - return; - st_check_relocs = true; - - Elf *elf = openElf (false); - if (elf == NULL) - return; - for (unsigned int sec = 1; sec < elf->elf_getehdr ()->e_shnum; sec++) - { - bool use_rela, use_PLT; - char *name = elf->get_sec_name (sec); - if (name == NULL) - continue; - if (strncmp (name, NTXT (".rela.text"), 10) == 0) - { - use_rela = true; - use_PLT = false; - } - else if (streq (name, NTXT (".rela.plt"))) - { - use_rela = true; - use_PLT = true; - } - else if (strncmp (name, NTXT (".rel.text"), 9) == 0) - { - use_rela = false; - use_PLT = false; - } - else if (streq (name, NTXT (".rel.plt"))) - { - use_rela = false; - use_PLT = true; - } - else - continue; - - Elf_Internal_Shdr *shdr = elf->get_shdr (sec); - if (shdr == NULL) - continue; - - // Get ELF data - Elf_Data *data = elf->elf_getdata (sec); - if (data == NULL) - continue; - uint64_t ScnSize = data->d_size; - uint64_t EntSize = shdr->sh_entsize; - if ((ScnSize == 0) || (EntSize == 0)) - continue; - int tot = (int) (ScnSize / EntSize); - - // Get corresponding text section - Elf_Internal_Shdr *shdr_txt = elf->get_shdr (shdr->sh_info); - if (shdr_txt == NULL) - continue; - if (!(shdr_txt->sh_flags & SHF_EXECINSTR)) - continue; - - // Get corresponding symbol table section - Elf_Internal_Shdr *shdr_sym = elf->get_shdr (shdr->sh_link); - if (shdr_sym == NULL) - continue; - Elf_Data *data_sym = elf->elf_getdata (shdr->sh_link); - - // Get corresponding string table section - Elf_Data *data_str = elf->elf_getdata (shdr_sym->sh_link); - if (data_str == NULL) - continue; - char *Strtab = (char*) data_str->d_buf; - for (int n = 0; n < tot; n++) - { - Elf_Internal_Sym sym; - Elf_Internal_Rela rela; - char *symName; - if (use_rela) - elf->elf_getrela (data, n, &rela); - else - { - // GElf_Rela is extended GElf_Rel - elf->elf_getrel (data, n, &rela); - rela.r_addend = 0; - } - - int ndx = (int) GELF_R_SYM (rela.r_info); - elf->elf_getsym (data_sym, ndx, &sym); - switch (GELF_ST_TYPE (sym.st_info)) - { - case STT_FUNC: - case STT_OBJECT: - case STT_NOTYPE: - if (sym.st_name == 0 || sym.st_name >= data_str->d_size) - continue; - symName = Strtab + sym.st_name; - break; - case STT_SECTION: - { - Elf_Internal_Shdr *secHdr = elf->get_shdr (sym.st_shndx); - if (secHdr == NULL) - continue; - if (sptr == NULL) - sptr = new Symbol; - sptr->value = secHdr->sh_offset + rela.r_addend; - long index = SymLst->bisearch (0, -1, &sptr, SymFindCmp); - if (index == -1) - continue; - Symbol *sp = SymLst->fetch (index); - if (sptr->value != sp->value) - continue; - symName = sp->name; - break; - } - default: - continue; - } - Reloc *reloc = new Reloc; - reloc->name = dbe_strdup (symName); - reloc->type = GELF_R_TYPE (rela.r_info); - reloc->value = use_PLT ? rela.r_offset - : rela.r_offset + shdr_txt->sh_offset; - reloc->addend = rela.r_addend; - if (use_PLT) - RelPLTLst->append (reloc); - else - RelLst->append (reloc); - } - } - delete sptr; - RelLst->sort (RelValueCmp); -} //check_Relocs - -void Stabs::get_save_addr (bool need_swap_endian) { if (elfDis->is_Intel ()) diff --git a/gprofng/src/Stabs.h b/gprofng/src/Stabs.h index 42aa6fb..d34741f 100644 --- a/gprofng/src/Stabs.h +++ b/gprofng/src/Stabs.h @@ -129,8 +129,7 @@ class Stabs { // Interface with Elf Symbol Table void check_Symtab(); - void readSymSec(unsigned int sec, Elf *elf); - void check_Relocs(); + 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; @@ -146,9 +145,10 @@ class Stabs { Map<const char*, Symbol*> *get_elf_symbols(); Dwarf *dwarf; - bool st_check_symtab, st_check_relocs; + bool st_check_symtab; Function *createFunction(LoadObject *lo, Module *module, Symbol *sym); void fixSymtabAlias(); + void removeDupSyms (); // Interface with dwarf Dwarf *openDwarf(); diff --git a/gprofng/src/vec.h b/gprofng/src/vec.h index 04cce4e..a768a02 100644 --- a/gprofng/src/vec.h +++ b/gprofng/src/vec.h @@ -112,6 +112,13 @@ public: return data[index]; } + void + truncate (long ncount) + { + if (count > ncount && ncount >= 0) + count = ncount; + } + // Return the first index in "this" that equals "item". // Return -1 if "item" is not found. long find (const ITEM item); |