ElfFile::Symbol ElfFile::getDefinitionByAddress(uintptr_t address) const {
Symbol foundSymbol {nullptr, nullptr};
- auto find = [&] (const ElfW(Shdr)& section) {
- enforce(section.sh_entsize == sizeof(ElfW(Sym)),
- "invalid entry size in symbol table");
-
- const ElfW(Sym)* sym = &at<ElfW(Sym)>(section.sh_offset);
- const ElfW(Sym)* end = &at<ElfW(Sym)>(section.sh_offset + section.sh_size);
- for (; sym != end; ++sym) {
- // st_info has the same representation on 32- and 64-bit platforms
- auto type = ELF32_ST_TYPE(sym->st_info);
-
- // TODO(tudorb): Handle STT_TLS, but then we'd have to understand
- // thread-local relocations. If all we're looking up is functions
- // (instruction pointers), it doesn't matter, though.
- if (type != STT_OBJECT && type != STT_FUNC) {
- continue;
+ auto findSection = [&](const ElfW(Shdr)& section) {
+ auto findSymbols = [&](const ElfW(Sym)& sym) {
+ if (sym.st_shndx == SHN_UNDEF) {
+ return false; // not a definition
}
- if (sym->st_shndx == SHN_UNDEF) {
- continue; // not a definition
- }
- if (address >= sym->st_value && address < sym->st_value + sym->st_size) {
+ if (address >= sym.st_value && address < sym.st_value + sym.st_size) {
foundSymbol.first = §ion;
- foundSymbol.second = sym;
+ foundSymbol.second = &sym;
return true;
}
+
+ return false;
+ };
+
+ return iterateSymbolsWithType(section, STT_OBJECT, findSymbols) ||
+ iterateSymbolsWithType(section, STT_FUNC, findSymbols);
+ };
+
+ // Try the .dynsym section first if it exists, it's smaller.
+ (iterateSectionsWithType(SHT_DYNSYM, findSection) ||
+ iterateSectionsWithType(SHT_SYMTAB, findSection));
+
+ return foundSymbol;
+}
+
+ElfFile::Symbol ElfFile::getSymbolByName(const char* name) const {
+ Symbol foundSymbol{nullptr, nullptr};
+
+ auto findSection = [&](const ElfW(Shdr)& section) -> bool {
+ // This section has no string table associated w/ its symbols; hence we
+ // can't get names for them
+ if (section.sh_link == SHN_UNDEF) {
+ return false;
}
- return false;
+ auto findSymbols = [&](const ElfW(Sym)& sym) -> bool {
+ if (sym.st_shndx == SHN_UNDEF) {
+ return false; // not a definition
+ }
+ if (sym.st_name == 0) {
+ return false; // no name for this symbol
+ }
+ const char* sym_name = getString(
+ *getSectionByIndex(section.sh_link), sym.st_name);
+ if (strcmp(sym_name, name) == 0) {
+ foundSymbol.first = §ion;
+ foundSymbol.second = &sym;
+ return true;
+ }
+
+ return false;
+ };
+
+ return iterateSymbolsWithType(section, STT_OBJECT, findSymbols) ||
+ iterateSymbolsWithType(section, STT_FUNC, findSymbols);
};
// Try the .dynsym section first if it exists, it's smaller.
- (iterateSectionsWithType(SHT_DYNSYM, find) ||
- iterateSectionsWithType(SHT_SYMTAB, find));
+ iterateSectionsWithType(SHT_DYNSYM, findSection) ||
+ iterateSectionsWithType(SHT_SYMTAB, findSection);
return foundSymbol;
}
+const ElfW(Shdr)* ElfFile::getSectionContainingAddress(ElfW(Addr) addr) const {
+ return iterateSections([&](const ElfW(Shdr)& sh) -> bool {
+ return (addr >= sh.sh_addr) && (addr < (sh.sh_addr + sh.sh_size));
+ });
+}
+
const char* ElfFile::getSymbolName(Symbol symbol) const {
if (!symbol.first || !symbol.second) {
return nullptr;