diff --git a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp --- a/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp +++ b/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp @@ -149,15 +149,9 @@ DataExtractor *OpdExtractor, uint64_t OpdAddress) { // Avoid adding symbols from an unknown/undefined section. - const ObjectFile *Obj = Symbol.getObject(); + const ObjectFile &Obj = *Symbol.getObject(); Expected Sec = Symbol.getSection(); - if (!Sec || (Obj && Obj->section_end() == *Sec)) - return Error::success(); - Expected SymbolTypeOrErr = Symbol.getType(); - if (!SymbolTypeOrErr) - return SymbolTypeOrErr.takeError(); - SymbolRef::Type SymbolType = *SymbolTypeOrErr; - if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data) + if (!Sec || Obj.section_end() == *Sec) return Error::success(); Expected SymbolAddressOrErr = Symbol.getAddress(); if (!SymbolAddressOrErr) @@ -186,11 +180,20 @@ // 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); + + Expected SymbolTypeOrErr = Symbol.getType(); + if (!SymbolTypeOrErr) + return SymbolTypeOrErr.takeError(); + SymbolRef::Type SymbolType = *SymbolTypeOrErr; + 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) function symbols which can be symbolize addresses. + if (SymbolType == SymbolRef::ST_Data) + Objects.emplace_back(SD, SymbolName); + else + Functions.emplace_back(SD, SymbolName); return Error::success(); } diff --git a/llvm/test/DebugInfo/Symbolize/ELF/symtab-file.yaml b/llvm/test/DebugInfo/Symbolize/ELF/symtab-file.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Symbolize/ELF/symtab-file.yaml @@ -0,0 +1,43 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-symbolizer --obj=%t 0 1 2 | FileCheck %s + +## TODO Find the preceding STT_FILE symbol as the filename of a local symbol. +# CHECK: local1 +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK-NEXT: local2 +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK-NEXT: local3 +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_DYN + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + Size: 3 +Symbols: + - Name: 1.c + Type: STT_FILE + Index: SHN_ABS + - Name: local1 + Section: .text + - Name: 2.c + Type: STT_FILE + Index: SHN_ABS + - Name: local2 + Section: .text + Value: 1 + - Name: 3.c + Type: STT_FILE + Index: SHN_ABS + - Name: local3 + Section: .text + Value: 2 diff --git a/llvm/test/DebugInfo/Symbolize/ELF/symtab-ifunc.s b/llvm/test/DebugInfo/Symbolize/ELF/symtab-ifunc.s new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Symbolize/ELF/symtab-ifunc.s @@ -0,0 +1,28 @@ +## Test we can symbolize STT_GNU_IFUNC symbols. +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t +# RUN: llvm-symbolizer --obj=%t 0 1 + +# CHECK: g_ifunc +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK-NEXT: l_ifunc +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: + +## TODO Find the preceding STT_FILE symbol as the filename of l_ifunc. +.file "symtab-ifunc.s" + +.Lg_resolver: + ret +.size .Lg_resolver, 1 + +.globl g_ifunc +.set g_ifunc, .Lg_resolver +.type g_ifunc, @gnu_indirect_function + +.Ll_resolver: + ret +.size .Ll_resolver, 1 + +.set l_ifunc, .Ll_resolver +.type l_ifunc, @gnu_indirect_function diff --git a/llvm/test/DebugInfo/Symbolize/ELF/symtab-notype.s b/llvm/test/DebugInfo/Symbolize/ELF/symtab-notype.s new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Symbolize/ELF/symtab-notype.s @@ -0,0 +1,55 @@ +## STT_NOTYPE symbols are common in assembly files. Test we can symbolize them. +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t +# RUN: llvm-symbolizer --obj=%t --inlines 0 1 2 3 4 5 6 7 | FileCheck %s +# RUN: llvm-symbolizer --obj=%t --no-inlines 0 1 2 3 4 5 6 7 | FileCheck %s + +# CHECK: _start +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK-NEXT: g_notype +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK-NEXT: g_notype +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: + +## This is a gap. +# CHECK-NEXT: ?? +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: + +# CHECK-NEXT: l_notype +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: + +## TODO addr2line does not symbolize the last two out-of-bounds addresses. +# CHECK-NEXT: l_notype_nosize +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK-NEXT: l_notype_nosize +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: +# CHECK-NEXT: l_notype_nosize +# CHECK-NEXT: ??:0:0 +# CHECK-EMPTY: + +## TODO Find the preceding STT_FILE symbol as the filename of a local symbol. +.file "symtab-notype.s" + +.globl _start, g_notype +_start: + retq + +g_notype: + nop + nop +.size g_notype, . - g_notype + + nop + +l_notype: + retq +.size l_notype, . - l_notype + +l_notype_nosize: + nop