diff options
Diffstat (limited to 'llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp')
-rw-r--r-- | llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp | 143 |
1 files changed, 90 insertions, 53 deletions
diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp index 93d05e4e27bf..a9c78830fa59 100644 --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -16,6 +16,7 @@ #include "llvm/BinaryFormat/COFF.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/Object/COFF.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolSize.h" #include "llvm/Support/Casting.h" @@ -69,24 +70,19 @@ SymbolizableObjectFile::create(const object::ObjectFile *Obj, return std::move(E); } - std::vector<std::pair<SymbolDesc, StringRef>> &Fs = res->Functions, - &Os = res->Objects; - auto Uniquify = [](std::vector<std::pair<SymbolDesc, StringRef>> &S) { - // Sort by (Addr,Size,Name). If several SymbolDescs share the same Addr, - // pick the one with the largest Size. This helps us avoid symbols with no - // size information (Size=0). - llvm::sort(S); - auto I = S.begin(), E = S.end(), J = S.begin(); - while (I != E) { - auto OI = I; - while (++I != E && OI->first.Addr == I->first.Addr) { - } - *J++ = I[-1]; + std::vector<SymbolDesc> &SS = res->Symbols; + // Sort by (Addr,Size,Name). If several SymbolDescs share the same Addr, + // pick the one with the largest Size. This helps us avoid symbols with no + // size information (Size=0). + llvm::stable_sort(SS); + auto I = SS.begin(), E = SS.end(), J = SS.begin(); + while (I != E) { + auto OI = I; + while (++I != E && OI->Addr == I->Addr) { } - S.erase(J, S.end()); - }; - Uniquify(Fs); - Uniquify(Os); + *J++ = I[-1]; + } + SS.erase(J, SS.end()); return std::move(res); } @@ -138,8 +134,7 @@ Error SymbolizableObjectFile::addCoffExportSymbols( uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1; uint64_t SymbolStart = ImageBase + Export.Offset; uint64_t SymbolSize = NextOffset - Export.Offset; - SymbolDesc SD = {SymbolStart, SymbolSize}; - Functions.emplace_back(SD, Export.Name); + Symbols.push_back({SymbolStart, SymbolSize, Export.Name, 0}); } return Error::success(); } @@ -149,16 +144,46 @@ Error SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, DataExtractor *OpdExtractor, uint64_t OpdAddress) { // Avoid adding symbols from an unknown/undefined section. - const ObjectFile *Obj = Symbol.getObject(); + const ObjectFile &Obj = *Symbol.getObject(); + Expected<StringRef> SymbolNameOrErr = Symbol.getName(); + if (!SymbolNameOrErr) + return SymbolNameOrErr.takeError(); + StringRef SymbolName = *SymbolNameOrErr; + + uint32_t ELFSymIdx = + Obj.isELF() ? ELFSymbolRef(Symbol).getRawDataRefImpl().d.b : 0; Expected<section_iterator> Sec = Symbol.getSection(); - if (!Sec || (Obj && Obj->section_end() == *Sec)) + if (!Sec || Obj.section_end() == *Sec) { + if (Obj.isELF()) { + // Store the (index, filename) pair for a file symbol. + ELFSymbolRef ESym(Symbol); + if (ESym.getELFType() == ELF::STT_FILE) + FileSymbols.emplace_back(ELFSymIdx, SymbolName); + } return Error::success(); + } + Expected<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType(); if (!SymbolTypeOrErr) return SymbolTypeOrErr.takeError(); SymbolRef::Type SymbolType = *SymbolTypeOrErr; - if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data) + if (Obj.isELF()) { + // Allow function and data symbols. Additionally allow STT_NONE, which are + // common for functions defined in assembly. + uint8_t Type = ELFSymbolRef(Symbol).getELFType(); + if (Type != ELF::STT_NOTYPE && Type != ELF::STT_FUNC && + Type != ELF::STT_OBJECT && Type != ELF::STT_GNU_IFUNC) + return Error::success(); + // Some STT_NOTYPE symbols are not desired. This excludes STT_SECTION and + // ARM mapping symbols. + uint32_t Flags = cantFail(Symbol.getFlags()); + if (Flags & SymbolRef::SF_FormatSpecific) + return Error::success(); + } else if (SymbolType != SymbolRef::ST_Function && + SymbolType != SymbolRef::ST_Data) { return Error::success(); + } + Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress(); if (!SymbolAddressOrErr) return SymbolAddressOrErr.takeError(); @@ -179,18 +204,13 @@ Error SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, if (OpdExtractor->isValidOffsetForAddress(OpdOffset)) SymbolAddress = OpdExtractor->getAddress(&OpdOffset); } - Expected<StringRef> SymbolNameOrErr = Symbol.getName(); - if (!SymbolNameOrErr) - return SymbolNameOrErr.takeError(); - StringRef SymbolName = *SymbolNameOrErr; // Mach-O symbol table names have leading underscore, skip it. if (Module->isMachO() && !SymbolName.empty() && SymbolName[0] == '_') SymbolName = SymbolName.drop_front(); - // FIXME: If a function has alias, there are two entries in symbol table - // with same address size. Make sure we choose the correct one. - auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects; - SymbolDesc SD = { SymbolAddress, SymbolSize }; - M.emplace_back(SD, SymbolName); + + if (Obj.isELF() && ELFSymbolRef(Symbol).getBinding() != ELF::STB_LOCAL) + ELFSymIdx = 0; + Symbols.push_back({SymbolAddress, SymbolSize, SymbolName, ELFSymIdx}); return Error::success(); } @@ -206,23 +226,32 @@ uint64_t SymbolizableObjectFile::getModulePreferredBase() const { return 0; } -bool SymbolizableObjectFile::getNameFromSymbolTable(SymbolRef::Type Type, - uint64_t Address, - std::string &Name, - uint64_t &Addr, - uint64_t &Size) const { - const auto &Symbols = Type == SymbolRef::ST_Function ? Functions : Objects; - std::pair<SymbolDesc, StringRef> SD{{Address, UINT64_C(-1)}, StringRef()}; +bool SymbolizableObjectFile::getNameFromSymbolTable( + uint64_t Address, std::string &Name, uint64_t &Addr, uint64_t &Size, + std::string &FileName) const { + SymbolDesc SD{Address, UINT64_C(-1), StringRef(), 0}; auto SymbolIterator = llvm::upper_bound(Symbols, SD); if (SymbolIterator == Symbols.begin()) return false; --SymbolIterator; - if (SymbolIterator->first.Size != 0 && - SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address) + if (SymbolIterator->Size != 0 && + SymbolIterator->Addr + SymbolIterator->Size <= Address) return false; - Name = SymbolIterator->second.str(); - Addr = SymbolIterator->first.Addr; - Size = SymbolIterator->first.Size; + Name = SymbolIterator->Name.str(); + Addr = SymbolIterator->Addr; + Size = SymbolIterator->Size; + + if (SymbolIterator->ELFLocalSymIdx != 0) { + // If this is an ELF local symbol, find the STT_FILE symbol preceding + // SymbolIterator to get the filename. The ELF spec requires the STT_FILE + // symbol (if present) precedes the other STB_LOCAL symbols for the file. + assert(Module->isELF()); + auto It = llvm::upper_bound( + FileSymbols, + std::make_pair(SymbolIterator->ELFLocalSymIdx, StringRef())); + if (It != FileSymbols.begin()) + FileName = It[-1].second.str(); + } return true; } @@ -248,11 +277,14 @@ SymbolizableObjectFile::symbolizeCode(object::SectionedAddress ModuleOffset, // Override function name from symbol table if necessary. if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) { - std::string FunctionName; + std::string FunctionName, FileName; uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, - FunctionName, Start, Size)) { + if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size, + FileName)) { LineInfo.FunctionName = FunctionName; + LineInfo.StartAddress = Start; + if (LineInfo.FileName == DILineInfo::BadString && !FileName.empty()) + LineInfo.FileName = FileName; } } return LineInfo; @@ -273,12 +305,16 @@ DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( // Override the function name in lower frame with name from symbol table. if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) { - std::string FunctionName; + std::string FunctionName, FileName; uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, - FunctionName, Start, Size)) { - InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1) - ->FunctionName = FunctionName; + if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size, + FileName)) { + DILineInfo *LI = InlinedContext.getMutableFrame( + InlinedContext.getNumberOfFrames() - 1); + LI->FunctionName = FunctionName; + LI->StartAddress = Start; + if (LI->FileName == DILineInfo::BadString && !FileName.empty()) + LI->FileName = FileName; } } @@ -288,8 +324,9 @@ DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( DIGlobal SymbolizableObjectFile::symbolizeData( object::SectionedAddress ModuleOffset) const { DIGlobal Res; - getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset.Address, Res.Name, - Res.Start, Res.Size); + std::string FileName; + getNameFromSymbolTable(ModuleOffset.Address, Res.Name, Res.Start, Res.Size, + FileName); return Res; } |