diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -298,6 +298,13 @@ std::vector getGroups(); + // Returns the function symbol index for the given address. Matches the + // symbol's section with FunctionSec when specified. + // Returns None if no function symbol can be found for the address or in case + // it is not defined in the specified section. + Optional + getSymbolIndexForFunctionAddress(uint64_t SymValue, + Optional FunctionSec); bool printFunctionStackSize(uint64_t SymValue, Optional FunctionSec, const Elf_Shdr &StackSizeSec, DataExtractor Data, @@ -353,6 +360,7 @@ const Elf_Shdr *DotAddrsigSec = nullptr; DenseMap> ShndxTables; Optional SONameOffset; + Optional>> SymbolValueToIndexMap; const Elf_Shdr *SymbolVersionSection = nullptr; // .gnu.version const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r @@ -5701,64 +5709,83 @@ } template -bool ELFDumper::printFunctionStackSize( - uint64_t SymValue, Optional FunctionSec, - const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) { - uint32_t FuncSymIndex = 0; - if (this->DotSymtabSec) { - if (Expected SymsOrError = Obj.symbols(this->DotSymtabSec)) { - uint32_t Index = (uint32_t)-1; - for (const Elf_Sym &Sym : *SymsOrError) { - ++Index; - - if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC) - continue; - - if (Expected SymAddrOrErr = - ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress()) { - if (SymValue != *SymAddrOrErr) +Optional ELFDumper::getSymbolIndexForFunctionAddress( + uint64_t SymValue, Optional FunctionSec) { + if (!this->SymbolValueToIndexMap.hasValue()) { + // Populate the address to index map upon the first invocation of this + // function. + this->SymbolValueToIndexMap.emplace(); + if (this->DotSymtabSec) { + if (Expected SymsOrError = + Obj.symbols(this->DotSymtabSec)) { + uint32_t Index = (uint32_t)-1; + for (const Elf_Sym &Sym : *SymsOrError) { + (void)Sym; + ++Index; + + if (Sym.st_shndx == ELF::SHN_UNDEF || Sym.getType() != ELF::STT_FUNC) continue; - } else { - std::string Name = this->getStaticSymbolName(Index); - reportUniqueWarning("unable to get address of symbol '" + Name + - "': " + toString(SymAddrOrErr.takeError())); - break; - } - // Check if the symbol is in the right section. FunctionSec == None - // means "any section". - if (FunctionSec) { - if (Expected SecOrErr = - Obj.getSection(Sym, this->DotSymtabSec, - this->getShndxTable(this->DotSymtabSec))) { - if (*FunctionSec != *SecOrErr) - continue; - } else { + Expected SymAddrOrErr = + ObjF.toSymbolRef(this->DotSymtabSec, Index).getAddress(); + if (!SymAddrOrErr) { std::string Name = this->getStaticSymbolName(Index); - // Note: it is impossible to trigger this error currently, it is - // untested. - reportUniqueWarning("unable to get section of symbol '" + Name + - "': " + toString(SecOrErr.takeError())); - break; + reportUniqueWarning("unable to get address of symbol '" + Name + + "': " + toString(SymAddrOrErr.takeError())); + return None; } + + (*this->SymbolValueToIndexMap)[*SymAddrOrErr].push_back(Index); } + } else { + reportUniqueWarning("unable to read the symbol table: " + + toString(SymsOrError.takeError())); + } + } + } - FuncSymIndex = Index; - break; + auto Symbols = this->SymbolValueToIndexMap->find(SymValue); + if (Symbols == this->SymbolValueToIndexMap->end()) + return None; + + for (uint32_t Index : Symbols->second) { + // Check if the symbol is in the right section. FunctionSec == None + // means "any section". + if (FunctionSec) { + const Elf_Sym &Sym = *cantFail(Obj.getSymbol(this->DotSymtabSec, Index)); + if (Expected SecOrErr = + Obj.getSection(Sym, this->DotSymtabSec, + this->getShndxTable(this->DotSymtabSec))) { + if (*FunctionSec != *SecOrErr) + continue; + } else { + std::string Name = this->getStaticSymbolName(Index); + // Note: it is impossible to trigger this error currently, it is + // untested. + reportUniqueWarning("unable to get section of symbol '" + Name + + "': " + toString(SecOrErr.takeError())); + return None; } - } else { - reportUniqueWarning("unable to read the symbol table: " + - toString(SymsOrError.takeError())); } + + return Index; } + return None; +} +template +bool ELFDumper::printFunctionStackSize( + uint64_t SymValue, Optional FunctionSec, + const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) { + Optional FuncSymIndex = + this->getSymbolIndexForFunctionAddress(SymValue, FunctionSec); std::string FuncName = "?"; if (!FuncSymIndex) reportUniqueWarning( "could not identify function symbol for stack size entry in " + describe(StackSizeSec)); else - FuncName = this->getStaticSymbolName(FuncSymIndex); + FuncName = this->getStaticSymbolName(*FuncSymIndex); // Extract the size. The expectation is that Offset is pointing to the right // place, i.e. past the function address.