diff options
Diffstat (limited to 'lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp')
-rw-r--r-- | lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp | 124 |
1 files changed, 88 insertions, 36 deletions
diff --git a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp index 08be524ab464..2765bf44d504 100644 --- a/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ b/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -1,9 +1,8 @@ //===- SymbolizableObjectFile.cpp -----------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -43,8 +42,9 @@ getDILineInfoSpecifier(FunctionNameKind FNKind) { } ErrorOr<std::unique_ptr<SymbolizableObjectFile>> -SymbolizableObjectFile::create(object::ObjectFile *Obj, +SymbolizableObjectFile::create(const object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx) { + assert(DICtx); std::unique_ptr<SymbolizableObjectFile> res( new SymbolizableObjectFile(Obj, std::move(DICtx))); std::unique_ptr<DataExtractor> OpdExtractor; @@ -54,13 +54,13 @@ SymbolizableObjectFile::create(object::ObjectFile *Obj, if (Obj->getArch() == Triple::ppc64) { for (section_iterator Section : Obj->sections()) { StringRef Name; - StringRef Data; if (auto EC = Section->getName(Name)) return EC; if (Name == ".opd") { - if (auto EC = Section->getContents(Data)) - return EC; - OpdExtractor.reset(new DataExtractor(Data, Obj->isLittleEndian(), + Expected<StringRef> E = Section->getContents(); + if (!E) + return errorToErrorCode(E.takeError()); + OpdExtractor.reset(new DataExtractor(*E, Obj->isLittleEndian(), Obj->getBytesInAddress())); OpdAddress = Section->getAddress(); break; @@ -79,10 +79,30 @@ SymbolizableObjectFile::create(object::ObjectFile *Obj, if (auto EC = res->addCoffExportSymbols(CoffObj)) return EC; } + + 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]; + } + S.erase(J, S.end()); + }; + Uniquify(Fs); + Uniquify(Os); + return std::move(res); } -SymbolizableObjectFile::SymbolizableObjectFile(ObjectFile *Obj, +SymbolizableObjectFile::SymbolizableObjectFile(const ObjectFile *Obj, std::unique_ptr<DIContext> DICtx) : Module(Obj), DebugInfoContext(std::move(DICtx)) {} @@ -128,7 +148,7 @@ std::error_code SymbolizableObjectFile::addCoffExportSymbols( uint64_t SymbolStart = ImageBase + Export.Offset; uint64_t SymbolSize = NextOffset - Export.Offset; SymbolDesc SD = {SymbolStart, SymbolSize}; - Functions.insert(std::make_pair(SD, Export.Name)); + Functions.emplace_back(SD, Export.Name); } return std::error_code(); } @@ -137,6 +157,11 @@ std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, uint64_t SymbolSize, DataExtractor *OpdExtractor, uint64_t OpdAddress) { + // Avoid adding symbols from an unknown/undefined section. + const ObjectFile *Obj = Symbol.getObject(); + Expected<section_iterator> Sec = Symbol.getSection(); + if (!Sec || (Obj && Obj->section_end() == *Sec)) + return std::error_code(); Expected<SymbolRef::Type> SymbolTypeOrErr = Symbol.getType(); if (!SymbolTypeOrErr) return errorToErrorCode(SymbolTypeOrErr.takeError()); @@ -170,7 +195,7 @@ std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol, // with same address size. Make sure we choose the correct one. auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects; SymbolDesc SD = { SymbolAddress, SymbolSize }; - M.insert(std::make_pair(SD, SymbolName)); + M.emplace_back(SD, SymbolName); return std::error_code(); } @@ -191,12 +216,10 @@ bool SymbolizableObjectFile::getNameFromSymbolTable(SymbolRef::Type Type, std::string &Name, uint64_t &Addr, uint64_t &Size) const { - const auto &SymbolMap = Type == SymbolRef::ST_Function ? Functions : Objects; - if (SymbolMap.empty()) - return false; - SymbolDesc SD = { Address, Address }; - auto SymbolIterator = SymbolMap.upper_bound(SD); - if (SymbolIterator == SymbolMap.begin()) + const auto &Symbols = Type == SymbolRef::ST_Function ? Functions : Objects; + std::pair<SymbolDesc, StringRef> SD{{Address, UINT64_C(-1)}, StringRef()}; + auto SymbolIterator = llvm::upper_bound(Symbols, SD); + if (SymbolIterator == Symbols.begin()) return false; --SymbolIterator; if (SymbolIterator->first.Size != 0 && @@ -218,19 +241,21 @@ bool SymbolizableObjectFile::shouldOverrideWithSymbolTable( isa<DWARFContext>(DebugInfoContext.get()); } -DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset, - FunctionNameKind FNKind, - bool UseSymbolTable) const { - DILineInfo LineInfo; - if (DebugInfoContext) { - LineInfo = DebugInfoContext->getLineInfoForAddress( - ModuleOffset, getDILineInfoSpecifier(FNKind)); - } +DILineInfo +SymbolizableObjectFile::symbolizeCode(object::SectionedAddress ModuleOffset, + FunctionNameKind FNKind, + bool UseSymbolTable) const { + if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) + ModuleOffset.SectionIndex = + getModuleSectionIndexForAddress(ModuleOffset.Address); + DILineInfo LineInfo = DebugInfoContext->getLineInfoForAddress( + ModuleOffset, getDILineInfoSpecifier(FNKind)); + // Override function name from symbol table if necessary. if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { std::string FunctionName; uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, + if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, FunctionName, Start, Size)) { LineInfo.FunctionName = FunctionName; } @@ -239,12 +264,14 @@ DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset, } DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( - uint64_t ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const { - DIInliningInfo InlinedContext; + object::SectionedAddress ModuleOffset, FunctionNameKind FNKind, + bool UseSymbolTable) const { + if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) + ModuleOffset.SectionIndex = + getModuleSectionIndexForAddress(ModuleOffset.Address); + DIInliningInfo InlinedContext = DebugInfoContext->getInliningInfoForAddress( + ModuleOffset, getDILineInfoSpecifier(FNKind)); - if (DebugInfoContext) - InlinedContext = DebugInfoContext->getInliningInfoForAddress( - ModuleOffset, getDILineInfoSpecifier(FNKind)); // Make sure there is at least one frame in context. if (InlinedContext.getNumberOfFrames() == 0) InlinedContext.addFrame(DILineInfo()); @@ -253,7 +280,7 @@ DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) { std::string FunctionName; uint64_t Start, Size; - if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset, + if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset.Address, FunctionName, Start, Size)) { InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1) ->FunctionName = FunctionName; @@ -263,9 +290,34 @@ DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode( return InlinedContext; } -DIGlobal SymbolizableObjectFile::symbolizeData(uint64_t ModuleOffset) const { +DIGlobal SymbolizableObjectFile::symbolizeData( + object::SectionedAddress ModuleOffset) const { DIGlobal Res; - getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Res.Name, Res.Start, - Res.Size); + getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset.Address, Res.Name, + Res.Start, Res.Size); return Res; } + +std::vector<DILocal> SymbolizableObjectFile::symbolizeFrame( + object::SectionedAddress ModuleOffset) const { + if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection) + ModuleOffset.SectionIndex = + getModuleSectionIndexForAddress(ModuleOffset.Address); + return DebugInfoContext->getLocalsForAddress(ModuleOffset); +} + +/// Search for the first occurence of specified Address in ObjectFile. +uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress( + uint64_t Address) const { + + for (SectionRef Sec : Module->sections()) { + if (!Sec.isText() || Sec.isVirtual()) + continue; + + if (Address >= Sec.getAddress() && + Address < Sec.getAddress() + Sec.getSize()) + return Sec.getIndex(); + } + + return object::SectionedAddress::UndefSection; +} |