diff --git a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp index 1fa3bc09f4b..852536b8b11 100644 --- a/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp +++ b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp @@ -312,6 +312,7 @@ void AppleAcceleratorTable::ValueIterator::Next() { if (Data >= NumData || !AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) { NumData = 0; + DataOffset = 0; return; } Current.extract(*AccelTable, &DataOffset); @@ -849,8 +850,8 @@ void DWARFDebugNames::ValueIterator::next() { if (getEntryAtCurrentOffset()) return; - // If we're a local iterator, we're done. - if (IsLocal) { + // If we're a local iterator or we have reached the last Index, we're done. + if (IsLocal || CurrentIndex == &CurrentIndex->Section.NameIndices.back()) { setEnd(); return; } diff --git a/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s b/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s new file mode 100644 index 00000000000..799c9df0898 --- /dev/null +++ b/test/tools/llvm-dwarfdump/X86/debug-names-multi-find.s @@ -0,0 +1,92 @@ +# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj -o %t +# RUN: llvm-dwarfdump -find=foo - <%t | FileCheck %s + +# CHECK: 12: DW_TAG_subprogram +# CHECK-NEXT: DW_AT_name ("foo") +# CHECK-NEXT: DW_AT_external +# CHECK: 17: DW_TAG_subprogram +# CHECK-NEXT: DW_AT_name ("foo") +# CHECK-NEXT: DW_AT_external + + .section .debug_str,"MS",@progbits,1 +.Lstring_foo: + .asciz "foo" +.Lstring_producer: + .asciz "Hand-written dwarf" + + .section .debug_abbrev,"",@progbits +.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 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 .debug_info,"",@progbits +.Lcu_begin0: + .long .Lcu_end0-.Lcu_start0 # Length of Unit +.Lcu_start0: + .short 4 # DWARF version number + .long .Lsection_abbrev # Offset Into Abbrev. Section + .byte 8 # Address Size (in bytes) + .byte 1 # Abbrev [1] DW_TAG_compile_unit + .long .Lstring_producer # DW_AT_producer + .short 12 # DW_AT_language +.Ldie_foo: + .byte 2 # Abbrev [2] DW_TAG_subprogram + .long .Lstring_foo # DW_AT_name + # DW_AT_external +.Ldie_foo2: + .byte 2 # Abbrev [2] DW_TAG_subprogram + .long .Lstring_foo # DW_AT_name + # DW_AT_external + .byte 0 # End Of Children Mark +.Lcu_end0: + + .section .debug_names,"",@progbits + .long .Lnames_end0-.Lnames_start0 # Header: contribution length +.Lnames_start0: + .short 5 # Header: version + .short 0 # Header: padding + .long 1 # Header: compilation unit count + .long 0 # Header: local type unit count + .long 0 # Header: foreign type unit count + .long 0 # Header: bucket count + .long 1 # Header: name count + .long .Lnames_abbrev_end0-.Lnames_abbrev_start0 # Header: abbreviation table size + .long 0 # Header: augmentation length + .long .Lcu_begin0 # Compilation unit 0 + .long .Lstring_foo # String in Bucket 0: foo + .long .Lnames0-.Lnames_entries0 # Offset in Bucket 0 +.Lnames_abbrev_start0: + .byte 46 # Abbrev code + .byte 46 # DW_TAG_subprogram + .byte 3 # DW_IDX_die_offset + .byte 19 # DW_FORM_ref4 + .byte 0 # End of abbrev + .byte 0 # End of abbrev + .byte 0 # End of abbrev list +.Lnames_abbrev_end0: +.Lnames_entries0: +.Lnames0: + .byte 46 # Abbrev code + .long .Ldie_foo-.Lcu_begin0 # DW_IDX_die_offset + .byte 46 # Abbrev code + .long .Ldie_foo2-.Lcu_begin0 # DW_IDX_die_offset + .long 0 # End of list: foo + .p2align 2 +.Lnames_end0: diff --git a/test/tools/llvm-dwarfdump/X86/find.test b/test/tools/llvm-dwarfdump/X86/find.test index 0606c674f91..4174e51529d 100644 --- a/test/tools/llvm-dwarfdump/X86/find.test +++ b/test/tools/llvm-dwarfdump/X86/find.test @@ -5,8 +5,6 @@ EMPTY: {{^$}} RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \ RUN: | llvm-dwarfdump -find=main - | FileCheck %s -CHECK: .debug_info contents: -CHECK-NOT: {{:}} CHECK: : DW_TAG_subprogram CHECK-NOT: {{:}} CHECK: DW_AT_name ("main") @@ -15,13 +13,13 @@ CHECK-NOT: {{:}} RUN: llvm-dwarfdump %S/../../dsymutil/Inputs/libfat-test.a \ RUN: -find=x86_64h_var -find=i386_var \ RUN: | FileCheck %s --check-prefix=MULTI -MULTI: .debug_info contents: +MULTI: libfat-test.a(i386) MULTI-NOT: {{: DW}} MULTI: : DW_TAG_variable MULTI-NOT: {{: DW}} MULTI: DW_AT_name ("i386_var") +MULTI: libfat-test.a(x86_64h) MULTI-NOT: {{: DW}} -MULTI: .debug_info contents: MULTI: : DW_TAG_variable MULTI-NOT: {{: DW}} MULTI: DW_AT_name ("x86_64h_var") @@ -29,8 +27,6 @@ MULTI-NOT: {{: DW}} RUN: llvm-mc %S/brief.s -filetype obj -triple x86_64-apple-darwin -o - \ RUN: | llvm-dwarfdump -find=int - | FileCheck %s --check-prefix=TYPES -TYPES: .debug_info contents: -TYPES-NOT: {{:}} TYPES: : DW_TAG_base_type TYPES-NOT: {{:}} TYPES: DW_AT_name ("int") diff --git a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp index 300a00b01be..433c681a108 100644 --- a/tools/llvm-dwarfdump/llvm-dwarfdump.cpp +++ b/tools/llvm-dwarfdump/llvm-dwarfdump.cpp @@ -309,6 +309,33 @@ static void filterByName(const StringSet<> &Names, } +template +static void getDIEOffset(const AccelTable &Accel, StringRef Name, + SmallVectorImpl &Offsets) { + for (const auto &Entry : Accel.equal_range(Name)) + if (llvm::Optional Off = Entry.getDIESectionOffset()) + Offsets.push_back(*Off); +} + +/// Print only DIEs that have a certain name. +static void filterByAccelName(ArrayRef Names, DWARFContext &DICtx, + raw_ostream &OS) { + SmallVector Offsets; + for (const auto &Name : Names) { + getDIEOffset(DICtx.getAppleNames(), Name, Offsets); + getDIEOffset(DICtx.getAppleTypes(), Name, Offsets); + getDIEOffset(DICtx.getAppleNamespaces(), Name, Offsets); + getDIEOffset(DICtx.getDebugNames(), Name, Offsets); + } + llvm::sort(Offsets.begin(), Offsets.end()); + Offsets.erase(std::unique(Offsets.begin(), Offsets.end()), Offsets.end()); + + for (uint64_t Off: Offsets) { + DWARFDie Die = DICtx.getDIEForOffset(Off); + Die.dump(OS, 0, getDumpOpts()); + } +} + /// Handle the --lookup option and dump the DIEs and line info for the given /// address. static bool lookup(DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) { @@ -335,15 +362,6 @@ static bool lookup(DWARFContext &DICtx, uint64_t Address, raw_ostream &OS) { bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, raw_ostream &OS); -template -static llvm::Optional getDIEOffset(const AccelTable &Accel, - StringRef Name) { - for (const auto &Entry : Accel.equal_range(Name)) - if (llvm::Optional Off = Entry.getDIESectionOffset()) - return *Off; - return None; -} - static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, raw_ostream &OS) { logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(), @@ -369,22 +387,8 @@ static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx, Twine Filename, // Handle the --find option and lower it to --debug-info=. if (!Find.empty()) { - DumpOffsets[DIDT_ID_DebugInfo] = [&]() -> llvm::Optional { - for (auto Name : Find) { - if (auto Offset = getDIEOffset(DICtx.getAppleNames(), Name)) - return DumpOffsets[DIDT_ID_DebugInfo] = *Offset; - if (auto Offset = getDIEOffset(DICtx.getAppleTypes(), Name)) - return DumpOffsets[DIDT_ID_DebugInfo] = *Offset; - if (auto Offset = getDIEOffset(DICtx.getAppleNamespaces(), Name)) - return DumpOffsets[DIDT_ID_DebugInfo] = *Offset; - if (auto Offset = getDIEOffset(DICtx.getDebugNames(), Name)) - return DumpOffsets[DIDT_ID_DebugInfo] = *Offset; - } - return None; - }(); - // Early exit if --find was specified but the current file doesn't have it. - if (!DumpOffsets[DIDT_ID_DebugInfo]) - return true; + filterByAccelName(Find, DICtx, OS); + return true; } // Dump the complete DWARF structure.