diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h @@ -387,9 +387,12 @@ function_ref getWarningHandler() { return WarningHandler; } + enum class ProcessDebugRelocations { Process, Ignore }; + static std::unique_ptr - create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr, - std::string DWPName = "", + create(const object::ObjectFile &Obj, + ProcessDebugRelocations RelocAction = ProcessDebugRelocations::Process, + const LoadedObjectInfo *L = nullptr, std::string DWPName = "", std::function RecoverableErrorHandler = WithColor::defaultErrorHandler, std::function WarningHandler = diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -1411,7 +1411,7 @@ auto S = std::make_shared(); S->File = std::move(Obj.get()); - S->Context = DWARFContext::create(*S->File.getBinary()); + S->Context = DWARFContext::create(*S->File.getBinary(), ProcessDebugRelocations::Ignore); *Entry = S; auto *Ctxt = S->Context.get(); return std::shared_ptr(std::move(S), Ctxt); @@ -1652,7 +1652,9 @@ } } DWARFObjInMemory(const object::ObjectFile &Obj, const LoadedObjectInfo *L, - function_ref HandleError, function_ref HandleWarning ) + function_ref HandleError, + function_ref HandleWarning, + DWARFContext::ProcessDebugRelocations RelocAction) : IsLittleEndian(Obj.isLittleEndian()), AddressSize(Obj.getBytesInAddress()), FileName(Obj.getFileName()), Obj(&Obj) { @@ -1735,7 +1737,11 @@ S.Data = Data; } - if (RelocatedSection == Obj.section_end()) + if (RelocatedSection != Obj.section_end() && Name.contains(".dwo")) + HandleWarning(createError("Unexpected relocations for dwo section " + Name)); + + if (RelocatedSection == Obj.section_end() || + (RelocAction == DWARFContext::ProcessDebugRelocations::Ignore)) continue; StringRef RelSecName; @@ -1772,18 +1778,10 @@ if (RelSecName == "debug_info") Map = &static_cast(InfoSections[*RelocatedSection]) .Relocs; - else if (RelSecName == "debug_info.dwo") - Map = &static_cast( - InfoDWOSections[*RelocatedSection]) - .Relocs; else if (RelSecName == "debug_types") Map = &static_cast(TypesSections[*RelocatedSection]) .Relocs; - else if (RelSecName == "debug_types.dwo") - Map = &static_cast( - TypesDWOSections[*RelocatedSection]) - .Relocs; else continue; } @@ -1966,12 +1964,12 @@ } // namespace std::unique_ptr -DWARFContext::create(const object::ObjectFile &Obj, const LoadedObjectInfo *L, - std::string DWPName, +DWARFContext::create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction, + const LoadedObjectInfo *L, std::string DWPName, std::function RecoverableErrorHandler, std::function WarningHandler) { - auto DObj = - std::make_unique(Obj, L, RecoverableErrorHandler, WarningHandler); + auto DObj = std::make_unique( + Obj, L, RecoverableErrorHandler, WarningHandler, RelocAction); return std::make_unique(std::move(DObj), std::move(DWPName), RecoverableErrorHandler, WarningHandler); diff --git a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp --- a/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ b/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -600,7 +600,9 @@ } } if (!Context) - Context = DWARFContext::create(*Objects.second, nullptr, Opts.DWPName); + Context = DWARFContext::create(*Objects.second, + DWARFContext::ProcessDebugRelocations::Process, + nullptr, Opts.DWPName); return createModuleInfo(Objects.first, std::move(Context), ModuleName); } diff --git a/llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s b/llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/X86/dwarfdump-rela-dwo.s @@ -0,0 +1,283 @@ +# Test objective to verify warning is printed if DWO secton has relocations. +# +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o +# RUN: llvm-dwarfdump --debug-info %t.o | FileCheck %s +# RUN: llvm-dwarfdump --debug-info %t.o 2> %t.txt +# RUN: cat %t.txt | FileCheck %s --check-prefix=PART2 + + .section .debug_str,"MS",@progbits,1 +str_producer: + .asciz "Handmade DWARF producer" +str_CU_4: + .asciz "V4_compile_unit" +str_CU_5: + .asciz "V5_compile_unit" +str_TU_4: + .asciz "V4_type_unit" +str_LT_5a: + .asciz "Directory5a" +str_LT_5b: + .asciz "Directory5b" + + .section .debug_str.dwo,"MSe",@progbits,1 +.dwo_TU_5: + .asciz "V5_split_type_unit" +.dwo_producer: + .asciz "Handmade DWO producer" +.dwo_CU_5: + .asciz "V5_dwo_compile_unit" +.dwo_LT_5a: + .asciz "DWODirectory5a" +.dwo_LT_5b: + .asciz "DWODirectory5b" + + .section .debug_str_offsets.dwo,"e",@progbits + .long Lstr_offsets_end-Lstr_offsets_start # Length of String Offsets Set + Lstr_offsets_start: + .short 5 + .short 0 + .long .dwo_TU_5-.debug_str.dwo + .long .dwo_producer-.debug_str.dwo + .long .dwo_CU_5-.debug_str.dwo + .long .dwo_LT_5a-.debug_str.dwo + .long .dwo_LT_5b-.debug_str.dwo + Lstr_offsets_end: + +# All CUs/TUs use the same abbrev section for simplicity. + .section .debug_abbrev,"",@progbits + .byte 0x01 # Abbrev code + .byte 0x11 # DW_TAG_compile_unit + .byte 0x00 # DW_CHILDREN_no + .byte 0x25 # DW_AT_producer + .byte 0x0e # DW_FORM_strp + .byte 0x03 # DW_AT_name + .byte 0x0e # DW_FORM_strp + .byte 0x10 # DW_AT_stmt_list + .byte 0x17 # DW_FORM_sec_offset + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x02 # Abbrev code + .byte 0x41 # DW_TAG_type_unit + .byte 0x01 # DW_CHILDREN_yes + .byte 0x03 # DW_AT_name + .byte 0x0e # DW_FORM_strp + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x03 # Abbrev code + .byte 0x13 # DW_TAG_structure_type + .byte 0x00 # DW_CHILDREN_no (no members) + .byte 0x03 # DW_AT_name + .byte 0x0e # DW_FORM_strp + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x04 # Abbrev code + .byte 0x3c # DW_TAG_partial_unit + .byte 0x00 # DW_CHILDREN_no + .byte 0x03 # DW_AT_name + .byte 0x0e # DW_FORM_strp + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x00 # EOM(3) + +# And a .dwo copy for the .dwo sections. + .section .debug_abbrev.dwo,"e",@progbits + .byte 0x01 # Abbrev code + .byte 0x11 # DW_TAG_compile_unit + .byte 0x00 # DW_CHILDREN_no + .byte 0x25 # DW_AT_producer + .byte 0x25 # DW_FORM_strx1 + .byte 0x03 # DW_AT_name + .byte 0x25 # DW_FORM_strx1 + .byte 0x10 # DW_AT_stmt_list + .byte 0x17 # DW_FORM_sec_offset + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x02 # Abbrev code + .byte 0x41 # DW_TAG_type_unit + .byte 0x01 # DW_CHILDREN_yes + .byte 0x03 # DW_AT_name + .byte 0x25 # DW_FORM_strx1 + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x03 # Abbrev code + .byte 0x13 # DW_TAG_structure_type + .byte 0x00 # DW_CHILDREN_no (no members) + .byte 0x03 # DW_AT_name + .byte 0x25 # DW_FORM_strx1 + .byte 0x00 # EOM(1) + .byte 0x00 # EOM(2) + .byte 0x00 # EOM(3) + + .section .debug_info,"",@progbits +# CHECK-LABEL: .debug_info contents: + + +# DWARF v5 normal CU header. + .long CU_5_end-CU_5_version # Length of Unit +CU_5_version: + .short 5 # DWARF version number + .byte 1 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long .debug_abbrev # Offset Into Abbrev. Section +# The compile-unit DIE, with DW_AT_producer, DW_AT_name, DW_AT_stmt_list. + .byte 1 + .long str_producer + .long str_CU_5 + .long LH_5_start + .byte 0 # NULL +CU_5_end: + +# CHECK: 0x00000000: Compile Unit: length = 0x00000016, format = DWARF32, version = 0x0005, unit_type = DW_UT_compile, abbr_offset = 0x0000, addr_size = 0x08 (next unit at 0x0000001a) +# CHECK: 0x0000000c: DW_TAG_compile_unit + + + .section .debug_info.dwo,"e",@progbits +# CHECK-LABEL: .debug_info.dwo + +# DWARF v5 split CU header. + .long CU_split_5_end-CU_split_5_version # Length of Unit +CU_split_5_version: + .short 5 # DWARF version number + .byte 5 # DWARF Unit Type + .byte 8 # Address Size (in bytes) + .long 0 # Offset Into Abbrev. Section + .quad 0x5a # DWO ID +# The split compile-unit DIE, with DW_AT_producer, DW_AT_name, DW_AT_stmt_list. + .byte 1 + .byte 1 + .byte 2 + .long dwo_LH_5_start + .byte 0 # NULL +CU_split_5_end: + +# CHECK: 0x00000000: Compile Unit: length = 0x00000018, format = DWARF32, version = 0x0005, unit_type = DW_UT_split_compile, abbr_offset = 0x0000, addr_size = 0x08, DWO_id = 0x000000000000005a (next unit at 0x0000001c) +# CHECK: 0x00000014: DW_TAG_compile_unit +# CHECK-NEXT: DW_AT_producer ("Handmade DWO producer") +# CHECK-NEXT: DW_AT_name ("V5_dwo_compile_unit") +# PART2: warning: Relocation rela.debug_info.dwo exists + + .section .debug_types,"",@progbits + + .section .debug_line,"",@progbits +# DWARF v5 line-table header. +LH_5_start: + .long LH_5_end-LH_5_version # Length of Unit +LH_5_version: + .short 5 # DWARF version number + .byte 8 # Address Size + .byte 0 # Segment Selector Size + .long LH_5_header_end-LH_5_params # Length of Prologue +LH_5_params: + .byte 1 # Minimum Instruction Length + .byte 1 # Maximum Operations per Instruction + .byte 1 # Default is_stmt + .byte -5 # Line Base + .byte 14 # Line Range + .byte 13 # Opcode Base + .byte 0 # Standard Opcode Lengths + .byte 1 + .byte 1 + .byte 1 + .byte 1 + .byte 0 + .byte 0 + .byte 0 + .byte 1 + .byte 0 + .byte 0 + .byte 1 + # Directory table format + .byte 1 # One element per directory entry + .byte 1 # DW_LNCT_path + .byte 0x0e # DW_FORM_strp (-> .debug_str) + # Directory table entries + .byte 2 # Two directories + .long str_LT_5a + .long str_LT_5b + # File table format + .byte 3 # Three elements per file entry + .byte 1 # DW_LNCT_path + .byte 0x1f # DW_FORM_line_strp (-> .debug_line_str) + .byte 2 # DW_LNCT_directory_index + .byte 0x0b # DW_FORM_data1 + .byte 5 # DW_LNCT_MD5 + .byte 0x1e # DW_FORM_data16 + # File table entries + .byte 2 # Two files + .long lstr_LT_5a + .byte 0 + .quad 0x7766554433221100 + .quad 0xffeeddccbbaa9988 + .long lstr_LT_5b + .byte 1 + .quad 0x8899aabbccddeeff + .quad 0x0011223344556677 +LH_5_header_end: + # Line number program, which is empty. +LH_5_end: + + .section .debug_line_str,"MS",@progbits,1 +lstr_LT_5a: + .asciz "File5a" +lstr_LT_5b: + .asciz "File5b" + + .section .debug_line.dwo,"e",@progbits +# DWARF v5 DWO line-table header. +dwo_LH_5_start: + .long dwo_LH_5_end-dwo_LH_5_version # Length of Unit +dwo_LH_5_version: + .short 5 # DWARF version number + .byte 8 # Address Size + .byte 0 # Segment Selector Size + .long dwo_LH_5_header_end-dwo_LH_5_params # Length of Prologue +dwo_LH_5_params: + .byte 1 # Minimum Instruction Length + .byte 1 # Maximum Operations per Instruction + .byte 1 # Default is_stmt + .byte -5 # Line Base + .byte 14 # Line Range + .byte 13 # Opcode Base + .byte 0 # Standard Opcode Lengths + .byte 1 + .byte 1 + .byte 1 + .byte 1 + .byte 0 + .byte 0 + .byte 0 + .byte 1 + .byte 0 + .byte 0 + .byte 1 + # Directory table format + .byte 1 # One element per directory entry + .byte 1 # DW_LNCT_path + .byte 0x25 # DW_FORM_strx1 (-> .debug_str.dwo) + # Directory table entries + .byte 2 # Two directories + .byte 3 + .byte 4 + # File table format + .byte 4 # Four elements per file entry + .byte 1 # DW_LNCT_path + .byte 0x08 # DW_FORM_string + .byte 2 # DW_LNCT_directory_index + .byte 0x0b # DW_FORM_data1 + .byte 3 # DW_LNCT_timestamp + .byte 0x0f # DW_FORM_udata + .byte 4 # DW_LNCT_size + .byte 0x0f # DW_FORM_udata + # File table entries + .byte 2 # Two files + .asciz "DWOFile5a" + .byte 0 + .byte 0x15 + .byte 0x25 + .asciz "DWOFile5b" + .byte 1 + .byte 0x35 + .byte 0x45 +dwo_LH_5_header_end: + # Line number program, which is empty. +dwo_LH_5_end: diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp --- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -537,7 +537,8 @@ if (auto *Obj = dyn_cast(BinOrErr->get())) { if (filterArch(*Obj)) { std::unique_ptr DICtx = - DWARFContext::create(*Obj, nullptr, "", RecoverableErrorHandler); + DWARFContext::create(*Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, + "", RecoverableErrorHandler); if (!HandleObj(*Obj, *DICtx, Filename, OS)) Result = false; } @@ -549,7 +550,8 @@ auto &Obj = **MachOOrErr; if (filterArch(Obj)) { std::unique_ptr DICtx = - DWARFContext::create(Obj, nullptr, "", RecoverableErrorHandler); + DWARFContext::create(Obj, DWARFContext::ProcessDebugRelocations::Process, + nullptr, "", RecoverableErrorHandler); if (!HandleObj(Obj, *DICtx, ObjName, OS)) Result = false; } diff --git a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h --- a/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h +++ b/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h @@ -185,7 +185,8 @@ reportError(DataOrErr.takeError(), ObjF.getFileName()); // Construct DWARFDataExtractor to handle relocations ("PC Begin" fields). - std::unique_ptr DICtx = DWARFContext::create(ObjF, nullptr); + std::unique_ptr DICtx = DWARFContext::create( + ObjF, DWARFContext::ProcessDebugRelocations::Process, nullptr); DWARFDataExtractor DE(DICtx->getDWARFObj(), DICtx->getDWARFObj().getEHFrameSection(), ELFT::TargetEndianness == support::endianness::little, diff --git a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp --- a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -413,8 +413,8 @@ } } - std::unique_ptr Context = - DWARFContext::create(*SymbolObj, LoadedObjInfo.get()); + std::unique_ptr Context = DWARFContext::create( + *SymbolObj, DWARFContext::ProcessDebugRelocations::Process, LoadedObjInfo.get()); std::vector> SymAddr = object::computeSymbolSizes(*SymbolObj); diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp --- a/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp @@ -2519,8 +2519,8 @@ // DWARFContext parses whole file and finds the two errors we expect. int Errors = 0; - std::unique_ptr Ctx1 = - DWARFContext::create(**Obj, nullptr, "", [&](Error E) { + std::unique_ptr Ctx1 = DWARFContext::create( + **Obj, DWARFContext::ContextType::MONOLITHIC, nullptr, "", [&](Error E) { ++Errors; consumeError(std::move(E)); });