diff --git a/lld/MachO/Dwarf.h b/lld/MachO/Dwarf.h --- a/lld/MachO/Dwarf.h +++ b/lld/MachO/Dwarf.h @@ -9,6 +9,8 @@ #ifndef LLD_MACHO_DWARF_H #define LLD_MACHO_DWARF_H +#include "Relocations.h" + #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DWARF/DWARFObject.h" @@ -17,6 +19,11 @@ class ObjFile; +class MachODWARFSection final : public llvm::DWARFSection { +public: + const InputSection *isec = nullptr; +}; + // Implements the interface between LLVM's DWARF-parsing utilities and LLD's // InputSection structures. class DwarfObject final : public llvm::DWARFObject { @@ -24,17 +31,23 @@ bool isLittleEndian() const override { return true; } llvm::Optional find(const llvm::DWARFSection &sec, - uint64_t pos) const override { - // TODO: implement this - return llvm::None; - } + uint64_t pos) const override; void forEachInfoSections( llvm::function_ref f) const override { f(infoSection); } + const llvm::DWARFSection &getLineSection() const override { + return lineSection; + } + + const llvm::DWARFSection &getAddrSection() const override { + return addrSection; + } + llvm::StringRef getAbbrevSection() const override { return abbrevSection; } + llvm::StringRef getLineStrSection() const override { return lineStrSection; } llvm::StringRef getStrSection() const override { return strSection; } // Returns an instance of DwarfObject if the given object file has the @@ -42,8 +55,12 @@ static std::unique_ptr create(ObjFile *); private: - llvm::DWARFSection infoSection; + MachODWARFSection addrSection; + MachODWARFSection infoSection; + MachODWARFSection lineSection; + llvm::StringRef abbrevSection; + llvm::StringRef lineStrSection; llvm::StringRef strSection; }; diff --git a/lld/MachO/Dwarf.cpp b/lld/MachO/Dwarf.cpp --- a/lld/MachO/Dwarf.cpp +++ b/lld/MachO/Dwarf.cpp @@ -10,6 +10,7 @@ #include "InputFiles.h" #include "InputSection.h" #include "OutputSegment.h" +#include "Symbols.h" #include @@ -27,12 +28,24 @@ // ourselves. for (const InputSection *isec : obj->debugSections) { if (StringRef *s = StringSwitch(isec->name) - .Case("__debug_info", &dObj->infoSection.Data) .Case("__debug_abbrev", &dObj->abbrevSection) + .Case("__debug_line_str", &dObj->lineStrSection) .Case("__debug_str", &dObj->strSection) .Default(nullptr)) { *s = toStringRef(isec->data); hasDwarfInfo = true; + continue; + } + + if (MachODWARFSection *m = StringSwitch(isec->name) + .Case("__debug_addr", &dObj->addrSection) + .Case("__debug_info", &dObj->infoSection) + .Case("__debug_line", &dObj->lineSection) + .Default(nullptr)) { + m->Data = toStringRef(isec->data); + m->isec = isec; + hasDwarfInfo = true; + continue; } } @@ -40,3 +53,42 @@ return dObj; return nullptr; } + +static uint64_t resolver(uint64_t Type, uint64_t Offset, uint64_t S, + uint64_t LocData, int64_t Addend) { + return S + Addend; +} + +llvm::Optional DwarfObject::find(const llvm::DWARFSection &sec, + uint64_t pos) const { + auto &msec = static_cast(sec); + if (msec.isec == nullptr) + return llvm::None; + + const Reloc *found = nullptr; + for (const auto &reloc : msec.isec->relocs) { + if (reloc.offset == pos) { + found = &reloc; + break; + } + } + if (!found) + return llvm::None; + + const Symbol *sym = found->referent.dyn_cast(); + if (!sym) + return llvm::None; + + uint32_t secIndex = sym->symtabIndex; + uint64_t val = 0; + if (const auto *def = dyn_cast(sym)) { + val = def->value; + } + + object::DataRefImpl d; + d.p = found->addend; + + return RelocAddrEntry{secIndex, object::RelocationRef(d, nullptr), + val, llvm::Optional(), + 0, resolver}; +} diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -173,15 +173,8 @@ isec->align = 1 << sec.align; isec->flags = sec.flags; - if (!(isDebugSection(isec->flags) && - isec->segname == segment_names::dwarf)) { - subsections.push_back({{0, isec}}); - } else { - // Instead of emitting DWARF sections, we emit STABS symbols to the - // object files that contain them. We filter them out early to avoid - // parsing their relocations unnecessarily. But we must still push an - // empty map to ensure the indices line up for the remaining sections. - subsections.push_back({}); + subsections.push_back({{0, isec}}); + if (isDebugSection(isec->flags) && isec->segname == segment_names::dwarf) { debugSections.push_back(isec); } } diff --git a/lld/test/MachO/undef.s b/lld/test/MachO/undef.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/undef.s @@ -0,0 +1,414 @@ +# REQUIRES: x86 +# RUN: rm -rf %t; split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %t/test.s -o %t/test.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %t/undef-debug.s -o %t/undef-debug.o + +# RUN: llvm-ar rc %t/undef-debug.a %t/undef-debug.o +# RUN: %lld %t/test.o %t/undef-debug.o -o %t/out1.out + +#--- test.s + .section __TEXT,__text,regular,pure_instructions + .build_version macos, 11, 0 sdk_version 11, 1 + .globl _main ## -- Begin function main + .p2align 4, 0x90 +_main: ## @main +Lfunc_begin0: +.quad foo +retq +Lfunc_end0: + ## -- End function + .section __DWARF,__debug_str,regular,debug +Linfo_string: + .asciz "Apple clang version 12.0.0 (clang-1200.0.32.29)" ## string offset=0 + .asciz "test.cc" ## string offset=48 + .asciz "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" ## string offset=56 + .asciz "MacOSX.sdk" ## string offset=108 + .asciz "/tmp" ## string offset=119 + .asciz "main" ## string offset=124 + .asciz "int" ## string offset=129 + .section __DWARF,__debug_abbrev,regular,debug +Lsection_abbrev: + .byte 1 ## Abbreviation Code + .byte 17 ## DW_TAG_compile_unit + .byte 1 ## DW_CHILDREN_yes + .byte 37 ## DW_AT_producer + .byte 14 ## DW_FORM_strp + .byte 19 ## DW_AT_language + .byte 5 ## DW_FORM_data2 + .byte 3 ## DW_AT_name + .byte 14 ## DW_FORM_strp + .ascii "\202|" ## DW_AT_LLVM_sysroot + .byte 14 ## DW_FORM_strp + .ascii "\357\177" ## DW_AT_APPLE_sdk + .byte 14 ## DW_FORM_strp + .byte 16 ## DW_AT_stmt_list + .byte 23 ## DW_FORM_sec_offset + .byte 27 ## DW_AT_comp_dir + .byte 14 ## DW_FORM_strp + .byte 17 ## DW_AT_low_pc + .byte 1 ## DW_FORM_addr + .byte 18 ## DW_AT_high_pc + .byte 6 ## DW_FORM_data4 + .byte 0 ## EOM(1) + .byte 0 ## EOM(2) + .byte 2 ## Abbreviation Code + .byte 46 ## DW_TAG_subprogram + .byte 0 ## DW_CHILDREN_no + .byte 17 ## DW_AT_low_pc + .byte 1 ## DW_FORM_addr + .byte 18 ## DW_AT_high_pc + .byte 6 ## DW_FORM_data4 + .byte 64 ## DW_AT_frame_base + .byte 24 ## DW_FORM_exprloc + .byte 3 ## DW_AT_name + .byte 14 ## DW_FORM_strp + .byte 58 ## DW_AT_decl_file + .byte 11 ## DW_FORM_data1 + .byte 59 ## DW_AT_decl_line + .byte 11 ## DW_FORM_data1 + .byte 73 ## DW_AT_type + .byte 19 ## DW_FORM_ref4 + .byte 63 ## DW_AT_external + .byte 25 ## DW_FORM_flag_present + .byte 0 ## EOM(1) + .byte 0 ## EOM(2) + .byte 3 ## Abbreviation Code + .byte 36 ## DW_TAG_base_type + .byte 0 ## DW_CHILDREN_no + .byte 3 ## DW_AT_name + .byte 14 ## DW_FORM_strp + .byte 62 ## DW_AT_encoding + .byte 11 ## DW_FORM_data1 + .byte 11 ## DW_AT_byte_size + .byte 11 ## DW_FORM_data1 + .byte 0 ## EOM(1) + .byte 0 ## EOM(2) + .byte 0 ## EOM(3) +.section __DWARF,__debug_info,regular,debug +Lsection_info: +Lcu_begin0: +.set Lset0, Ldebug_info_end0-Ldebug_info_start0 ## Length of Unit + .long Lset0 +Ldebug_info_start0: + .short 4 ## DWARF version number +.set Lset1, Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section + .long Lset1 + .byte 8 ## Address Size (in bytes) + .byte 1 ## Abbrev [1] 0xb:0x48 DW_TAG_compile_unit + .long 0 ## DW_AT_producer + .short 4 ## DW_AT_language + .long 48 ## DW_AT_name + .long 56 ## DW_AT_LLVM_sysroot + .long 108 ## DW_AT_APPLE_sdk + .long __debug_line ## DW_AT_stmt_list +.set Lset2, Lline_table_start0-Lsection_line ## DW_AT_stmt_list + .long Lset2 + .long 119 ## DW_AT_comp_dir + .quad Lfunc_begin0 ## DW_AT_low_pc +.set Lset3, Lfunc_end0-Lfunc_begin0 ## DW_AT_high_pc + .long Lset3 + .byte 2 ## Abbrev [2] 0x32:0x19 DW_TAG_subprogram + .quad Lfunc_begin0 ## DW_AT_low_pc +.set Lset4, Lfunc_end0-Lfunc_begin0 ## DW_AT_high_pc + .long Lset4 + .byte 1 ## DW_AT_frame_base + .byte 86 + .long 124 ## DW_AT_name + .byte 1 ## DW_AT_decl_file + .byte 3 ## DW_AT_decl_line + .long 75 ## DW_AT_type + ## DW_AT_external + .byte 3 ## Abbrev [3] 0x4b:0x7 DW_TAG_base_type + .long 129 ## DW_AT_name + .byte 5 ## DW_AT_encoding + .byte 4 ## DW_AT_byte_size + .byte 0 ## End Of Children Mark +Ldebug_info_end0: + +.section __DWARF,__apple_names,regular,debug +Lnames_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 1 ## Header Hash Count + .long 12 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 1 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .long 0 ## Bucket 0 + .long 2090499946 ## Hash in Bucket 0 +.set Lset5, LNames0-Lnames_begin ## Offset in Bucket 0 + .long Lset5 +LNames0: + .long 124 ## main + .long 1 ## Num DIEs + .long 50 + .long 0 + .section __DWARF,__apple_objc,regular,debug +Lobjc_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 0 ## Header Hash Count + .long 12 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 1 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .long -1 ## Bucket 0 + .section __DWARF,__apple_namespac,regular,debug +Lnamespac_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 0 ## Header Hash Count + .long 12 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 1 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .long -1 ## Bucket 0 + .section __DWARF,__apple_types,regular,debug +Ltypes_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 1 ## Header Hash Count + .long 20 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 3 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .short 3 ## DW_ATOM_die_tag + .short 5 ## DW_FORM_data2 + .short 4 ## DW_ATOM_type_flags + .short 11 ## DW_FORM_data1 + .long 0 ## Bucket 0 + .long 193495088 ## Hash in Bucket 0 +.set Lset6, Ltypes0-Ltypes_begin ## Offset in Bucket 0 + .long Lset6 +Ltypes0: + .long 129 ## int + .long 1 ## Num DIEs + .long 75 + .short 36 + .byte 0 + .long 0 +.subsections_via_symbols + .section __DWARF,__debug_line,regular,debug +Lsection_line: +Lline_table_start0: + +.section __DWARF,__debug_aranges,regular,debug +ltmp1: + .byte 0 + +#--- undef-debug.s + .section __TEXT,__text,regular,pure_instructions + .build_version macos, 11, 0 sdk_version 11, 1 + .p2align 4, 0x90 + +.text +.globl _usertwo +_usertwo: +Lfunc_begin0: + .quad bar + ret +Lfunc_end0: + +.section __DWARF,__debug_str,regular,debug +Linfo_string: + .asciz "Apple clang version 12.0.0 (clang-1200.0.32.29)" ## string offset=0 + .asciz "undef-debug.s" ## string offset=48 + .asciz "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk" ## string offset=56 + .asciz "MacOSX.sdk" ## string offset=108 + .asciz "/tmp" ## string offset=119 + .asciz "main" ## string offset=124 + .asciz "int" ## string offset=129 + .section __DWARF,__debug_abbrev,regular,debug +Lsection_abbrev: + .byte 1 ## Abbreviation Code + .byte 17 ## DW_TAG_compile_unit + .byte 1 ## DW_CHILDREN_yes + .byte 37 ## DW_AT_producer + .byte 14 ## DW_FORM_strp + .byte 19 ## DW_AT_language + .byte 5 ## DW_FORM_data2 + .byte 3 ## DW_AT_name + .byte 14 ## DW_FORM_strp + .ascii "\202|" ## DW_AT_LLVM_sysroot + .byte 14 ## DW_FORM_strp + .ascii "\357\177" ## DW_AT_APPLE_sdk + .byte 14 ## DW_FORM_strp + .byte 16 ## DW_AT_stmt_list + .byte 23 ## DW_FORM_sec_offset + .byte 27 ## DW_AT_comp_dir + .byte 14 ## DW_FORM_strp + .byte 17 ## DW_AT_low_pc + .byte 1 ## DW_FORM_addr + .byte 18 ## DW_AT_high_pc + .byte 6 ## DW_FORM_data4 + .byte 0 ## EOM(1) + .byte 0 ## EOM(2) + .byte 2 ## Abbreviation Code + .byte 46 ## DW_TAG_subprogram + .byte 0 ## DW_CHILDREN_no + .byte 17 ## DW_AT_low_pc + .byte 1 ## DW_FORM_addr + .byte 18 ## DW_AT_high_pc + .byte 6 ## DW_FORM_data4 + .byte 64 ## DW_AT_frame_base + .byte 24 ## DW_FORM_exprloc + .byte 3 ## DW_AT_name + .byte 14 ## DW_FORM_strp + .byte 58 ## DW_AT_decl_file + .byte 11 ## DW_FORM_data1 + .byte 59 ## DW_AT_decl_line + .byte 11 ## DW_FORM_data1 + .byte 73 ## DW_AT_type + .byte 19 ## DW_FORM_ref4 + .byte 63 ## DW_AT_external + .byte 25 ## DW_FORM_flag_present + .byte 0 ## EOM(1) + .byte 0 ## EOM(2) + .byte 3 ## Abbreviation Code + .byte 36 ## DW_TAG_base_type + .byte 0 ## DW_CHILDREN_no + .byte 3 ## DW_AT_name + .byte 14 ## DW_FORM_strp + .byte 62 ## DW_AT_encoding + .byte 11 ## DW_FORM_data1 + .byte 11 ## DW_AT_byte_size + .byte 11 ## DW_FORM_data1 + .byte 0 ## EOM(1) + .byte 0 ## EOM(2) + .byte 0 ## EOM(3) +.section __DWARF,__debug_info,regular,debug +Lsection_info: +Lcu_begin0: +.set Lset0, Ldebug_info_end0-Ldebug_info_start0 ## Length of Unit + .long Lset0 +Ldebug_info_start0: + .short 4 ## DWARF version number +.set Lset1, Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section + .long Lset1 + .byte 8 ## Address Size (in bytes) + .byte 1 ## Abbrev [1] 0xb:0x48 DW_TAG_compile_unit + .long 0 ## DW_AT_producer + .short 4 ## DW_AT_language + .long 48 ## DW_AT_name + .long 56 ## DW_AT_LLVM_sysroot + .long 108 ## DW_AT_APPLE_sdk + .long __debug_line ## DW_AT_stmt_list +.set Lset2, Lline_table_start0-Lsection_line ## DW_AT_stmt_list + .long Lset2 + .long 119 ## DW_AT_comp_dir + .quad Lfunc_begin0 ## DW_AT_low_pc +.set Lset3, Lfunc_end0-Lfunc_begin0 ## DW_AT_high_pc + .long Lset3 + .byte 2 ## Abbrev [2] 0x32:0x19 DW_TAG_subprogram + .quad Lfunc_begin0 ## DW_AT_low_pc +.set Lset4, Lfunc_end0-Lfunc_begin0 ## DW_AT_high_pc + .long Lset4 + .byte 1 ## DW_AT_frame_base + .byte 86 + .long 124 ## DW_AT_name + .byte 1 ## DW_AT_decl_file + .byte 3 ## DW_AT_decl_line + .long 75 ## DW_AT_type + ## DW_AT_external + .byte 3 ## Abbrev [3] 0x4b:0x7 DW_TAG_base_type + .long 129 ## DW_AT_name + .byte 5 ## DW_AT_encoding + .byte 4 ## DW_AT_byte_size + .byte 0 ## End Of Children Mark +Ldebug_info_end0: + +.section __DWARF,__apple_names,regular,debug +Lnames_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 1 ## Header Hash Count + .long 12 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 1 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .long 0 ## Bucket 0 + .long 2090499946 ## Hash in Bucket 0 +.set Lset5, LNames0-Lnames_begin ## Offset in Bucket 0 + .long Lset5 +LNames0: + .long 124 ## main + .long 1 ## Num DIEs + .long 50 + .long 0 + .section __DWARF,__apple_objc,regular,debug +Lobjc_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 0 ## Header Hash Count + .long 12 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 1 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .long -1 ## Bucket 0 + .section __DWARF,__apple_namespac,regular,debug +Lnamespac_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 0 ## Header Hash Count + .long 12 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 1 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .long -1 ## Bucket 0 + .section __DWARF,__apple_types,regular,debug +Ltypes_begin: + .long 1212240712 ## Header Magic + .short 1 ## Header Version + .short 0 ## Header Hash Function + .long 1 ## Header Bucket Count + .long 1 ## Header Hash Count + .long 20 ## Header Data Length + .long 0 ## HeaderData Die Offset Base + .long 3 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 6 ## DW_FORM_data4 + .short 3 ## DW_ATOM_die_tag + .short 5 ## DW_FORM_data2 + .short 4 ## DW_ATOM_type_flags + .short 11 ## DW_FORM_data1 + .long 0 ## Bucket 0 + .long 193495088 ## Hash in Bucket 0 +.set Lset6, Ltypes0-Ltypes_begin ## Offset in Bucket 0 + .long Lset6 +Ltypes0: + .long 129 ## int + .long 1 ## Num DIEs + .long 75 + .short 36 + .byte 0 + .long 0 +.subsections_via_symbols + .section __DWARF,__debug_line,regular,debug +Lsection_line: +Lline_table_start0: + +.section __DWARF,__debug_aranges,regular,debug +ltmp1: + .byte 0