aboutsummaryrefslogtreecommitdiff
path: root/gprofng
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng')
-rw-r--r--gprofng/src/DwarfLib.cc24
-rw-r--r--gprofng/src/Elf.cc69
-rw-r--r--gprofng/src/Elf.h3
-rw-r--r--gprofng/src/Stabs.cc216
-rw-r--r--gprofng/src/Stabs.h6
-rw-r--r--gprofng/src/vec.h7
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);