diff options
| author | Martin Storsjo <martin@martin.st> | 2019-09-25 11:03:48 +0000 |
|---|---|---|
| committer | Martin Storsjo <martin@martin.st> | 2019-09-25 11:03:48 +0000 |
| commit | 1d06d48bb3463632ed049284dacb3d1f6715d210 (patch) | |
| tree | f644e7b62b699a9805d00767996b4692113252da | |
| parent | 62aceecfafae042ba9c48b1028a61c467e992597 (diff) | |
| download | bcm5719-llvm-1d06d48bb3463632ed049284dacb3d1f6715d210.tar.gz bcm5719-llvm-1d06d48bb3463632ed049284dacb3d1f6715d210.zip | |
[LLD] [COFF] Resolve source locations for undefined references using dwarf
This fixes PR42407.
Differential Revision: https://reviews.llvm.org/D67053
llvm-svn: 372843
| -rw-r--r-- | lld/COFF/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | lld/COFF/Config.h | 8 | ||||
| -rw-r--r-- | lld/COFF/PDB.cpp | 4 | ||||
| -rw-r--r-- | lld/COFF/PDB.h | 4 | ||||
| -rw-r--r-- | lld/COFF/SymbolTable.cpp | 25 | ||||
| -rw-r--r-- | lld/test/COFF/undefined-symbol-dwarf.s | 100 |
6 files changed, 138 insertions, 4 deletions
diff --git a/lld/COFF/CMakeLists.txt b/lld/COFF/CMakeLists.txt index c7ef7c47fea..4a133835932 100644 --- a/lld/COFF/CMakeLists.txt +++ b/lld/COFF/CMakeLists.txt @@ -36,6 +36,7 @@ add_lld_library(lldCOFF Object Option Support + Symbolize WindowsManifest LINK_LIBS diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 309e1fbf99e..cd597ddca4f 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -18,6 +18,12 @@ #include <set> #include <string> +namespace llvm { +namespace symbolize { +class LLVMSymbolizer; +} +} // namespace llvm + namespace lld { namespace coff { @@ -226,6 +232,8 @@ struct Configuration { bool swaprunNet = false; bool thinLTOEmitImportsFiles; bool thinLTOIndexOnly; + + llvm::symbolize::LLVMSymbolizer *symbolizer = nullptr; }; extern Configuration *config; diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index 25952b59234..41d2c5a8001 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -1800,8 +1800,8 @@ static bool findLineTable(const SectionChunk *c, uint32_t addr, // Use CodeView line tables to resolve a file and line number for the given // offset into the given chunk and return them, or {"", 0} if a line table was // not found. -std::pair<StringRef, uint32_t> coff::getFileLine(const SectionChunk *c, - uint32_t addr) { +std::pair<StringRef, uint32_t> coff::getFileLineCodeView(const SectionChunk *c, + uint32_t addr) { ExitOnError exitOnErr; DebugStringTableSubsectionRef cVStrTab; diff --git a/lld/COFF/PDB.h b/lld/COFF/PDB.h index 3ac1adc85c5..4d8e3e2e5ea 100644 --- a/lld/COFF/PDB.h +++ b/lld/COFF/PDB.h @@ -29,8 +29,8 @@ void createPDB(SymbolTable *symtab, llvm::ArrayRef<uint8_t> sectionTable, llvm::codeview::DebugInfo *buildId); -std::pair<llvm::StringRef, uint32_t> getFileLine(const SectionChunk *c, - uint32_t addr); +std::pair<llvm::StringRef, uint32_t> getFileLineCodeView(const SectionChunk *c, + uint32_t addr); } } diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 4b75d667bd4..a4aa5d39820 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -15,6 +15,7 @@ #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "lld/Common/Timer.h" +#include "llvm/DebugInfo/Symbolize/Symbolize.h" #include "llvm/IR/LLVMContext.h" #include "llvm/Object/WindowsMachineFlag.h" #include "llvm/Support/Debug.h" @@ -107,6 +108,30 @@ static std::vector<std::string> getSymbolLocations(BitcodeFile *file) { return {res}; } +static std::pair<StringRef, uint32_t> getFileLineDwarf(const SectionChunk *c, + uint32_t addr) { + if (!config->symbolizer) + config->symbolizer = make<symbolize::LLVMSymbolizer>(); + Expected<DILineInfo> expectedLineInfo = config->symbolizer->symbolizeCode( + *c->file->getCOFFObj(), {addr, c->getSectionNumber() - 1}); + if (!expectedLineInfo) + return {"", 0}; + const DILineInfo &lineInfo = *expectedLineInfo; + if (lineInfo.FileName == DILineInfo::BadString) + return {"", 0}; + return {saver.save(lineInfo.FileName), lineInfo.Line}; +} + +static std::pair<StringRef, uint32_t> getFileLine(const SectionChunk *c, + uint32_t addr) { + // MinGW can optionally use codeview, even if the default is dwarf. + std::pair<StringRef, uint32_t> fileLine = getFileLineCodeView(c, addr); + // If codeview didn't yield any result, check dwarf in MinGW mode. + if (fileLine.first.empty() && config->mingw) + fileLine = getFileLineDwarf(c, addr); + return fileLine; +} + // Given a file and the index of a symbol in that file, returns a description // of all references to that symbol from that file. If no debug information is // available, returns just the name of the file, else one string per actual diff --git a/lld/test/COFF/undefined-symbol-dwarf.s b/lld/test/COFF/undefined-symbol-dwarf.s new file mode 100644 index 00000000000..c098c0fd688 --- /dev/null +++ b/lld/test/COFF/undefined-symbol-dwarf.s @@ -0,0 +1,100 @@ +# REQUIRES: x86 +# RUN: llvm-mc -triple=x86_64-windows-gnu -filetype=obj -o %t.o %s +# RUN: not lld-link /lldmingw /out:%t.exe %t.o /entry:entry 2>&1 | FileCheck %s + +# CHECK: error: undefined symbol: bar() +# CHECK-NEXT: >>> referenced by /path/to/src/undef.cpp:17 +# CHECK-NEXT: >>> {{.*}}.o:(entry) +# CHECK-EMPTY: +# CHECK-NEXT: error: undefined symbol: foo() +# CHECK-NEXT: >>> referenced by /path/to/src/undef.cpp:7 +# CHECK-NEXT: >>> {{.*}}.o:(A::afunc()) + + .text + .file "undef.cpp" + .file 1 "/path/to/src" "undef.cpp" + .globl entry # -- Begin function entry +entry: # @entry +.Lfunc_begin0: + .loc 1 14 0 # undef.cpp:14:0 + subq $40, %rsp +.Ltmp0: + leaq 32(%rsp), %rcx +.Ltmp1: + .loc 1 16 4 prologue_end # undef.cpp:16:4 + callq _ZN1A5afuncEv + .loc 1 17 2 # undef.cpp:17:2 + callq _Z3barv + .loc 1 18 1 # undef.cpp:18:1 + addq $40, %rsp + retq +.Ltmp2: +.Lfunc_end0: + + .def _ZN1A5afuncEv; + .scl 2; + .type 32; + .endef + .section .text$_ZN1A5afuncEv,"xr",discard,_ZN1A5afuncEv + .globl _ZN1A5afuncEv # -- Begin function _ZN1A5afuncEv + .p2align 1, 0x90 +_ZN1A5afuncEv: # @_ZN1A5afuncEv +.Lfunc_begin1: + .loc 1 6 0 # undef.cpp:6:0 + .loc 1 7 3 prologue_end # undef.cpp:7:3 + jmp _Z3foov # TAILCALL +.Ltmp3: +.Lfunc_end1: + + .section .debug_abbrev,"dr" +.Lsection_abbrev: + .byte 1 # Abbreviation Code + .byte 17 # DW_TAG_compile_unit + .byte 1 # DW_CHILDREN_yes + .byte 37 # DW_AT_producer + .byte 37 # DW_FORM_strx1 + .byte 19 # DW_AT_language + .byte 5 # DW_FORM_data2 + .byte 3 # DW_AT_name + .byte 37 # DW_FORM_strx1 + .byte 16 # DW_AT_stmt_list + .byte 23 # DW_FORM_sec_offset + .byte 27 # DW_AT_comp_dir + .byte 37 # DW_FORM_strx1 + .byte 17 # DW_AT_low_pc + .byte 1 # DW_FORM_addr + .byte 85 # DW_AT_ranges + .byte 23 # DW_FORM_sec_offset + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + .section .debug_info,"dr" +.Lsection_info: +.Lcu_begin0: + .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit +.Ldebug_info_start0: + .short 4 # DWARF version number + .secrel32 .Lsection_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] 0xb:0xb0 DW_TAG_compile_unit + .byte 0 # DW_AT_producer + .short 4 # DW_AT_language + .byte 0 # DW_AT_name + .secrel32 .Lline_table_start0 # DW_AT_stmt_list + .byte 0 # DW_AT_comp_dir + .quad 0 # DW_AT_low_pc + .secrel32 .Ldebug_ranges0 # DW_AT_ranges + .byte 0 # End Of Children Mark +.Ldebug_info_end0: + .section .debug_ranges,"dr" +.Ldebug_range: +.Ldebug_ranges0: + .quad .Lfunc_begin0 + .quad .Lfunc_end0 + .quad .Lfunc_begin1 + .quad .Lfunc_end1 + .quad 0 + .quad 0 + + .section .debug_line,"dr" +.Lline_table_start0: |

