aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2021-02-08 12:29:11 -0800
committerFangrui Song <i@maskray.me>2021-02-08 12:29:11 -0800
commit6d766c8bf9df3c22590a78c77879080736ad55ae (patch)
tree3497efed448025cab2d24c8d092b621c07ec0716 /llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
parent4c9adbb287e7e6cfea866b3c3254b50f21e5ce1f (diff)
downloadllvm-6d766c8bf9df3c22590a78c77879080736ad55ae.zip
llvm-6d766c8bf9df3c22590a78c77879080736ad55ae.tar.gz
llvm-6d766c8bf9df3c22590a78c77879080736ad55ae.tar.bz2
DebugInfo/Symbolize: Allow STT_NOTYPE/STT_GNU_IFUNC symbols for .symtab symbolization
In assembly files, omitting `.type foo,@function` is common. Such functions have type `STT_NOTYPE` and llvm-symbolizer reports `??` for them. An ifunc symbol usually has an associated resolver symbol which is defined at the same address. Returning either one is fine for symbolization. The resolver symbol may not end up in the symbol table if (object file) `.L` is used (linked image) .symtab is stripped while .dynsym is retained. This patch allows ELF STT_NOTYPE/STT_GNU_IFUNC symbols for .symtab symbolization. I have left TODO in the test files for an unimplemented STT_FILE heuristic. Differential Revision: https://reviews.llvm.org/D95916
Diffstat (limited to 'llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp')
-rw-r--r--llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp33
1 files changed, 25 insertions, 8 deletions
diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
index 93d05e4..b260cd9d 100644
--- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
+++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
@@ -149,16 +149,27 @@ 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<section_iterator> Sec = Symbol.getSection();
- if (!Sec || (Obj && Obj->section_end() == *Sec))
+ if (!Sec || Obj.section_end() == *Sec)
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();
+ } else if (SymbolType != SymbolRef::ST_Function &&
+ SymbolType != SymbolRef::ST_Data) {
return Error::success();
+ }
+
Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
if (!SymbolAddressOrErr)
return SymbolAddressOrErr.takeError();
@@ -186,11 +197,17 @@ Error SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
// 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);
+
+ SymbolDesc SD = {SymbolAddress, SymbolSize};
+
+ // DATA command symbolizes just ST_Data (ELF STT_OBJECT) symbols as an
+ // optimization. Treat everything else (e.g. ELF STT_NOTYPE, STT_FUNC and
+ // STT_GNU_IFUNC) as function symbols which can be used to symbolize
+ // addresses.
+ if (SymbolType == SymbolRef::ST_Data)
+ Objects.emplace_back(SD, SymbolName);
+ else
+ Functions.emplace_back(SD, SymbolName);
return Error::success();
}