aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp')
-rw-r--r--llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp143
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;
}