Skip to content

Commit

Permalink
Handle hits in PLT
Browse files Browse the repository at this point in the history
  • Loading branch information
ostash committed Apr 4, 2013
1 parent f89c1d7 commit ab01a43
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 9 deletions.
86 changes: 81 additions & 5 deletions AddressResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ enum Section {
DebugInfo,
DebugLink,
PrelinkUndo,
PLT,
RelPLT,
SectionCount
};

Expand Down Expand Up @@ -118,6 +120,7 @@ void ElfHolder::loadInfo()
Elf_Scn* scn = elf_getscn(elf_, i);
GElf_Shdr shdr;
gelf_getshdr(scn, &shdr);
const char* sectionName;

switch (shdr.sh_type)
{
Expand All @@ -130,7 +133,7 @@ void ElfHolder::loadInfo()
needToFind--;
break;
case SHT_PROGBITS:
const char* sectionName = elf_strptr(elf_, ehdr.e_shstrndx, shdr.sh_name);
sectionName = elf_strptr(elf_, ehdr.e_shstrndx, shdr.sh_name);
if (strcmp(sectionName, ".debug_info") == 0)
{
sections_[DebugInfo] = scn;
Expand All @@ -146,23 +149,39 @@ void ElfHolder::loadInfo()
sections_[PrelinkUndo] = scn;
needToFind--;
}
else if (strcmp(sectionName, ".plt") == 0)
{
sections_[PLT] = scn;
needToFind--;
}
break;
case SHT_REL:
case SHT_RELA:
sectionName = elf_strptr(elf_, ehdr.e_shstrndx, shdr.sh_name);
if (strcmp(sectionName, ".rel.plt") == 0 || strcmp(sectionName, "rela.plt"))
{
sections_[RelPLT] = scn;
needToFind--;
}
break;
}
}
}

struct ARSymbolData
{
enum { MiscPLT = 255 };
explicit ARSymbolData(const GElf_Sym& elfSymbol)
: size(elfSymbol.st_size)
, binding(GELF_ST_BIND(elfSymbol.st_info))
, misc(GELF_ST_BIND(elfSymbol.st_info))
{}
explicit ARSymbolData(uint64_t _size)
: size(_size)
{}
ARSymbolData() {}
uint64_t size;
std::string name;
unsigned char binding;
unsigned char misc;
};

typedef std::map<Range, ARSymbolData> ARSymbolStorage;
Expand All @@ -173,11 +192,13 @@ struct AddressResolverPrivate
AddressResolverPrivate()
: baseAddress(0)
, origBaseAddress(0)
, pltEndAddress(0)
, dwfl(0)
, dwMod(0)
, dwBias(0)
{}

void loadPLTSymbols(Elf* elf, Elf_Scn* pltSection, Elf_Scn* relPltSection, Elf_Scn *dynsymSection);
void loadSymbolsFromSection(Elf* elf, Elf_Scn* section);
const char* getDebugLink(Elf_Scn* section);
void setOriginalBaseAddress(Elf* elf, Elf_Scn* section);
Expand All @@ -186,6 +207,7 @@ struct AddressResolverPrivate

uint64_t baseAddress;
uint64_t origBaseAddress;
uint64_t pltEndAddress;

Dwfl* dwfl;
Dwfl_Module* dwMod;
Expand All @@ -209,6 +231,9 @@ AddressResolver::AddressResolver(Profile::DetailLevel details, const char *fileN
ElfHolder elfh(fileName);
d->origBaseAddress = d->baseAddress = elfh.getBaseAddress();

if (details != Profile::Objects && elfh.getSection(PLT) && elfh.getSection(RelPLT) && elfh.getSection(DynSym))
d->loadPLTSymbols(elfh.get(), elfh.getSection(PLT), elfh.getSection(RelPLT), elfh.getSection(DynSym));

// Don't load symbols if not requested
bool symTabLoaded = (details == Profile::Objects);
// Try to load .symtab from main file
Expand Down Expand Up @@ -305,6 +330,9 @@ bool AddressResolver::resolve(Address value, Address loadBase, Range& symbolRang
}
else
symbolName = maybeSymbolName;

if (arSymIt->second.misc == ARSymbolData::MiscPLT)
symbolName.append("@plt");
}

return true;
Expand All @@ -326,9 +354,57 @@ std::pair<const char*, size_t> AddressResolver::getSourcePosition(Address value,
return std::make_pair(static_cast<const char*>(0), 0);
}

void AddressResolverPrivate::loadPLTSymbols(Elf* elf, Elf_Scn *pltSection, Elf_Scn *relPltSection, Elf_Scn *dynsymSection)
{
GElf_Shdr header;

gelf_getshdr(pltSection, &header);
Address symStart = header.sh_addr;
Count symSize = header.sh_entsize;

gelf_getshdr(relPltSection, &header);
bool isRela = header.sh_type == SHT_RELA;
size_t relPltCount = header.sh_size / header.sh_entsize;

gelf_getshdr(dynsymSection, &header);
int strtabIdx = header.sh_link;

Elf_Data* relPltData = elf_getdata(relPltSection, 0);
Elf_Data* dynsymData = elf_getdata(dynsymSection, 0);

for (size_t relPltIdx = 0; relPltIdx < relPltCount; relPltIdx++)
{
size_t symIdx;
if (isRela)
{
GElf_Rela rela;
gelf_getrela(relPltData, relPltIdx, &rela);
symIdx = GELF_R_SYM(rela.r_info);
}
else
{
GElf_Rel rel;
gelf_getrel(relPltData, relPltIdx, &rel);
symIdx = GELF_R_SYM(rel.r_info);
}

GElf_Sym elfSymbol;
gelf_getsym(dynsymData, symIdx, &elfSymbol);


ARSymbolData& symbolData = symbols[Range(symStart, symStart + symSize)];
symbolData.name = elf_strptr(elf, strtabIdx, elfSymbol.st_name);
symbolData.misc = ARSymbolData::MiscPLT;

symStart += symSize;
}

pltEndAddress = symStart;
}

void AddressResolverPrivate::loadSymbolsFromSection(Elf* elf, Elf_Scn *section)
{
symbols.clear();
symbols.erase(symbols.lower_bound(Range(pltEndAddress)), symbols.end());

GElf_Shdr sectionHeader;
gelf_getshdr(section, &sectionHeader);
Expand Down Expand Up @@ -356,7 +432,7 @@ void AddressResolverPrivate::loadSymbolsFromSection(Elf* elf, Elf_Scn *section)
{
const ARSymbolData& oldSymbolData = insResult.first->second;
// Sized functions better that asm labels and higer binding is also better
if ((oldSymbolData.size == 0 && symbolData.size != 0) || (oldSymbolData.binding < symbolData.binding))
if ((oldSymbolData.size == 0 && symbolData.size != 0) || (oldSymbolData.misc < symbolData.misc))
{
symbols.erase(insResult.first);
symbolData.name = elf_strptr(elf, sectionHeader.sh_link, elfSymbol.st_name);
Expand Down
4 changes: 3 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
perfgrind 0.3
* Allow to set arbitrary frequency in pgcollect via -F argument

* Allow to set arbitrary frequency in pgcollect via -F argument.
* Handling of hits in PLT added.

perfgrind 0.2

Expand Down
3 changes: 0 additions & 3 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ Short and incomplete TODO list:

- use debug link section in ELF for finding separate debug info.

- handle hits in PLT. At the moment they are usually reported as hits in
_init@object function.

- detect correct call from addresses. Currently we put cumulative count to
instruction next after call.

Expand Down

0 comments on commit ab01a43

Please sign in to comment.