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,16 +149,24 @@ 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)) + if (!Sec || 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 (Obj.isELF()) { + uint8_t Type = ELFSymbolRef(Symbol).getELFType(); + // Functions defined in assembly are often STT_NONE. + 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 SymbolAddressOrErr = Symbol.getAddress(); if (!SymbolAddressOrErr) return SymbolAddressOrErr.takeError(); @@ -186,9 +194,11 @@ // 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; + + // DATA command symbolizes just ST_Data (ELF STT_OBJECT) symbols as an + // optimization. Treat everything else (ELF STT_NOTYPE, STT_FUNC and + // STT_GNU_IFUNC ) function symbols which can be symbolize addresses. + auto &M = SymbolType != SymbolRef::ST_Data ? Functions : Objects; SymbolDesc SD = { SymbolAddress, SymbolSize }; M.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,27 @@ +# 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,54 @@ +# 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