Index: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h +++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h @@ -56,10 +56,11 @@ /// in this Accelerator Entry. virtual Optional getCUOffset() const = 0; - /// Returns the Offset of the Debug Info Entry associated with this + /// Returns the Section Offset of the Debug Info Entry associated with this /// Accelerator Entry or None if the DIE offset is not recorded in this - /// Accelerator Entry. - virtual Optional getDIEOffset() const = 0; + /// Accelerator Entry. The returned offset is relative to the start of the + /// Section containing the DIE. + virtual Optional getDIESectionOffset() const = 0; /// Returns the Tag of the Debug Info Entry associated with this /// Accelerator Entry or None if the Tag is not recorded in this @@ -104,6 +105,8 @@ uint32_t DIEOffsetBase; SmallVector, 3> Atoms; + + Optional extractOffset(Optional Value) const; }; struct Header Hdr; @@ -127,7 +130,7 @@ public: Optional getCUOffset() const override; - Optional getDIEOffset() const override; + Optional getDIESectionOffset() const override; Optional getTag() const override; /// Returns the value of the Atom in this Accelerator Entry, if the Entry @@ -284,18 +287,24 @@ /// Index or None if this Accelerator Entry does not have an associated /// Compilation Unit. It is up to the user to verify that the returned Index /// is valid in the owning NameIndex (or use getCUOffset(), which will - /// handle that check itself). + /// handle that check itself). Note that entries in NameIndexes which index + /// just a single Compilation Unit are implicitly associated with that unit, + /// so this function will return 0 even without an explicit + /// DW_IDX_compile_unit attribute. Optional getCUIndex() const; public: Optional getCUOffset() const override; - Optional getDIEOffset() const override; + Optional getDIESectionOffset() const override; Optional getTag() const override { return tag(); } /// .debug_names-specific getter, which always succeeds (DWARF v5 index /// entries always have a tag). dwarf::Tag tag() const { return Abbr->Tag; } + /// Returns the Offset of the DIE within the containing CU or TU. + Optional getDIEUnitOffset() const; + /// Return the Abbreviation that can be used to interpret the raw values of /// this Accelerator Entry. const Abbrev &getAbbrev() const { return *Abbr; } Index: llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ llvm/trunk/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -159,6 +159,23 @@ W.printNumber("HeaderData length", HeaderDataLength); } +Optional AppleAcceleratorTable::HeaderData::extractOffset( + Optional Value) const { + if (!Value) + return None; + + switch (Value->getForm()) { + case dwarf::DW_FORM_ref1: + case dwarf::DW_FORM_ref2: + case dwarf::DW_FORM_ref4: + case dwarf::DW_FORM_ref8: + case dwarf::DW_FORM_ref_udata: + return Value->getRawUValue() + DIEOffsetBase; + default: + return Value->getAsSectionOffset(); + } +} + bool AppleAcceleratorTable::dumpName(ScopedPrinter &W, SmallVectorImpl &AtomForms, uint32_t *DataOffset) const { @@ -276,16 +293,12 @@ return None; } -Optional AppleAcceleratorTable::Entry::getDIEOffset() const { - if (Optional Off = lookup(dwarf::DW_ATOM_die_offset)) - return Off->getAsSectionOffset(); - return None; +Optional AppleAcceleratorTable::Entry::getDIESectionOffset() const { + return HdrData->extractOffset(lookup(dwarf::DW_ATOM_die_offset)); } Optional AppleAcceleratorTable::Entry::getCUOffset() const { - if (Optional Off = lookup(dwarf::DW_ATOM_cu_offset)) - return Off->getAsSectionOffset(); - return None; + return HdrData->extractOffset(lookup(dwarf::DW_ATOM_cu_offset)); } Optional AppleAcceleratorTable::Entry::getTag() const { @@ -537,7 +550,7 @@ return None; } -Optional DWARFDebugNames::Entry::getDIEOffset() const { +Optional DWARFDebugNames::Entry::getDIEUnitOffset() const { if (Optional Off = lookup(dwarf::DW_IDX_die_offset)) return Off->getAsSectionOffset(); return None; @@ -546,6 +559,10 @@ Optional DWARFDebugNames::Entry::getCUIndex() const { if (Optional Off = lookup(dwarf::DW_IDX_compile_unit)) return Off->getAsUnsignedConstant(); + // In a per-CU index, the entries without a DW_IDX_compile_unit attribute + // implicitly refer to the single CU. + if (NameIdx->getCUCount() == 1) + return 0; return None; } @@ -556,6 +573,14 @@ return NameIdx->getCUOffset(*Index); } +Optional DWARFDebugNames::Entry::getDIESectionOffset() const { + Optional CUOff = getCUOffset(); + Optional DIEOff = getDIEUnitOffset(); + if (CUOff && DIEOff) + return *CUOff + *DIEOff; + return None; +} + void DWARFDebugNames::Entry::dump(ScopedPrinter &W) const { W.printHex("Abbrev", Abbr->Code); W.startLine() << "Tag: " << formatTag(Abbr->Tag) << "\n"; Index: llvm/trunk/test/tools/llvm-dwarfdump/X86/apple-names-die-offset-data.s =================================================================== --- llvm/trunk/test/tools/llvm-dwarfdump/X86/apple-names-die-offset-data.s +++ llvm/trunk/test/tools/llvm-dwarfdump/X86/apple-names-die-offset-data.s @@ -0,0 +1,75 @@ +# This test sets non-zero Die Offset Base field in the accelerator table header, +# and makes sure it is *not* added to the DW_FORM_data*** forms. + +# RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o %t +# RUN: llvm-dwarfdump -find=main %t | FileCheck %s + +# CHECK: DW_TAG_subprogram +# CHECK-NEXT: DW_AT_name ("main") +# CHECK-NEXT: DW_AT_external + + .section __DWARF,__debug_str,regular,debug +Ldebug_str: +Lstring_producer: + .asciz "Hand-written dwarf" +Lstring_main: + .asciz "main" + + .section __DWARF,__debug_abbrev,regular,debug + .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 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section __DWARF,__debug_info,regular,debug +Ldebug_info: + .long Lcu_end0-Lcu_start0 # Length of Unit +Lcu_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .long Lstring_producer-Ldebug_str # DW_AT_producer + .short 12 # DW_AT_language +Ldie_main: + .byte 2 # Abbrev [2] DW_TAG_subprogram + .long Lstring_main-Ldebug_str # DW_AT_name + # DW_AT_external + .byte 0 # End Of Children Mark +Lcu_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 1 ## 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 + .long LNames0-Lnames_begin ## Offset in Bucket 0 +LNames0: + .long Lstring_main-Ldebug_str ## main + .long 1 ## Num DIEs + .long Ldie_main-Ldebug_info + .long 0 Index: llvm/trunk/test/tools/llvm-dwarfdump/X86/apple-names-die-offset-ref.s =================================================================== --- llvm/trunk/test/tools/llvm-dwarfdump/X86/apple-names-die-offset-ref.s +++ llvm/trunk/test/tools/llvm-dwarfdump/X86/apple-names-die-offset-ref.s @@ -0,0 +1,75 @@ +# This test sets non-zero Die Offset Base field in the accelerator table header, +# and makes sure it is added to the DW_FORM_ref*** forms. + +# RUN: llvm-mc -triple x86_64-apple-darwin %s -filetype=obj -o %t +# RUN: llvm-dwarfdump -find=main %t | FileCheck %s + +# CHECK: DW_TAG_subprogram +# CHECK-NEXT: DW_AT_name ("main") +# CHECK-NEXT: DW_AT_external + + .section __DWARF,__debug_str,regular,debug +Ldebug_str: +Lstring_producer: + .asciz "Hand-written dwarf" +Lstring_main: + .asciz "main" + + .section __DWARF,__debug_abbrev,regular,debug + .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 0 # EOM(1) + .byte 0 # EOM(2) + .byte 2 # Abbreviation Code + .byte 46 # DW_TAG_subprogram + .byte 0 # DW_CHILDREN_no + .byte 3 # DW_AT_name + .byte 14 # DW_FORM_strp + .byte 63 # DW_AT_external + .byte 25 # DW_FORM_flag_present + .byte 0 # EOM(1) + .byte 0 # EOM(2) + .byte 0 # EOM(3) + + .section __DWARF,__debug_info,regular,debug +Ldebug_info: + .long Lcu_end0-Lcu_start0 # Length of Unit +Lcu_start0: + .short 4 # DWARF version number + .long 0 # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .long Lstring_producer-Ldebug_str # DW_AT_producer + .short 12 # DW_AT_language +Ldie_main: + .byte 2 # Abbrev [2] DW_TAG_subprogram + .long Lstring_main-Ldebug_str # DW_AT_name + # DW_AT_external + .byte 0 # End Of Children Mark +Lcu_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 1 ## HeaderData Die Offset Base + .long 1 ## HeaderData Atom Count + .short 1 ## DW_ATOM_die_offset + .short 0x13 ## DW_FORM_ref4 + .long 0 ## Bucket 0 + .long 2090499946 ## Hash in Bucket 0 + .long LNames0-Lnames_begin ## Offset in Bucket 0 +LNames0: + .long Lstring_main-Ldebug_str ## main + .long 1 ## Num DIEs + .long Ldie_main-Ldebug_info-1 + .long 0 Index: llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s =================================================================== --- llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s +++ llvm/trunk/test/tools/llvm-dwarfdump/X86/debug-names-find.s @@ -129,15 +129,15 @@ .Lnames_entries0: .Lnames0: .byte 46 # Abbrev code - .long .Ldie_bar # DW_IDX_die_offset + .long .Ldie_bar-.Lcu_begin0 # DW_IDX_die_offset .long 0 # End of list: bar .Lnames1: .byte 46 # Abbrev code - .long .Ldie_foo # DW_IDX_die_offset + .long .Ldie_foo-.Lcu_begin0 # DW_IDX_die_offset .long 0 # End of list: foo .Lnames2: .byte 46 # Abbrev code - .long .Ldie_foo # DW_IDX_die_offset + .long .Ldie_foo-.Lcu_begin0 # DW_IDX_die_offset .long 0 # End of list: _Z3foov .p2align 2 .Lnames_end0: @@ -171,12 +171,12 @@ .Lnames_entries1: .Lnames3: .byte 46 # Abbrev code - .long .Ldie_baz # DW_IDX_die_offset + .long .Ldie_baz-.Lcu_begin1 # DW_IDX_die_offset .long 0 # End of list: baz .p2align 2 .Lnames4: .byte 46 # Abbrev code - .long .Ldie_bazz # DW_IDX_die_offset + .long .Ldie_bazz-.Lcu_begin1 # DW_IDX_die_offset .long 0 # End of list: baz .p2align 2 .Lnames_end1: Index: llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp =================================================================== --- llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ llvm/trunk/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -340,7 +340,7 @@ static llvm::Optional getDIEOffset(const AccelTable &Accel, StringRef Name) { for (const auto &Entry : Accel.equal_range(Name)) - if (llvm::Optional Off = Entry.getDIEOffset()) + if (llvm::Optional Off = Entry.getDIESectionOffset()) return *Off; return None; }