[dsymutil] Do not crash on empty debug_range range.
authorFrederic Riss <friss@apple.com>
Mon, 31 Aug 2015 05:09:32 +0000 (05:09 +0000)
committerFrederic Riss <friss@apple.com>
Mon, 31 Aug 2015 05:09:32 +0000 (05:09 +0000)
The fix is trivial (The actual patch is 2 lines, but as it changes
indentation it looks like more).
clang does not produce this kind of (slightly bogus) debug info
anymore, thus I had to rely on a hand-crafted assembly test to trigger
that case.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246410 91177308-0d34-0410-b5e6-96231b3b80d8

test/tools/dsymutil/Inputs/empty_range/1.o [new file with mode: 0644]
test/tools/dsymutil/X86/empty_range.s [new file with mode: 0644]
test/tools/dsymutil/X86/lit.local.cfg
tools/dsymutil/DwarfLinker.cpp

diff --git a/test/tools/dsymutil/Inputs/empty_range/1.o b/test/tools/dsymutil/Inputs/empty_range/1.o
new file mode 100644 (file)
index 0000000..671bf4a
Binary files /dev/null and b/test/tools/dsymutil/Inputs/empty_range/1.o differ
diff --git a/test/tools/dsymutil/X86/empty_range.s b/test/tools/dsymutil/X86/empty_range.s
new file mode 100644 (file)
index 0000000..5c8ae6a
--- /dev/null
@@ -0,0 +1,57 @@
+# This test verifies that an empty range list in the .debug_ranges section
+# doesn't crash llvm-dsymutil. As clang does not produce this kind of debug
+# info anymore, we used this hand-crafted assembly file to produce a testcase
+# Compile with:
+#        llvm-mc -triple x86_64-apple-darwin -filetype=obj -o 1.o empty_range.o
+
+# RUN: llvm-dsymutil -f -y %p/dummy-debug-map.map -oso-prepend-path %p/../Inputs/empty_range -o - | llvm-dwarfdump -debug-dump=info - | FileCheck %s
+
+        .section       __TEXT,__text,regular,pure_instructions
+       .macosx_version_min 10, 11
+       .globl  __Z3foov
+       .align  4, 0x90
+__Z3foov:                               ## @_Z3foov
+Lfunc_begin0:
+       pushq   %rbp
+       movq    %rsp, %rbp
+       popq    %rbp
+       retq
+Lfunc_end0:
+       .section        __DWARF,__debug_abbrev,regular,debug
+Lsection_abbrev:
+       .byte   1                       ## Abbreviation Code
+       .byte   17                      ## DW_TAG_compile_unit
+       .byte   1                       ## DW_CHILDREN_yes
+       .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   0x55                    ## DW_AT_ranges
+        .byte   6                       ## DW_FORM_data4
+       .byte   0                       ## EOM(1)
+       .byte   0                       ## EOM(2)
+       .byte   0                       ## EOM(3)
+       .section        __DWARF,__debug_info,regular,debug
+Lsection_info:
+       .long   22                      ## Length of Unit
+       .short  2                       ## DWARF version number
+       .long   0                       ## Offset Into Abbrev. Section
+       .byte   8                       ## Address Size (in bytes)
+       .byte   1                       ## Abbrev [1]  DW_TAG_compile_unit
+       .byte   2                       ## Abbrev [2] DW_TAG_subprogram
+       .quad   Lfunc_begin0            ## DW_AT_low_pc
+        .long   0                       ## DW_AT_ranges (pointing at an empty entry)
+       .byte   0                       ## End Of Children Mark
+       .section        __DWARF,__debug_ranges,regular,debug
+Ldebug_range:
+        .long 0
+        .long 0
+
+# CHECK:  DW_TAG_compile_unit
+# CHECK:    DW_TAG_subprogram
+# CHECK-NEXT:      DW_AT_low_pc{{.*}}(0x0000000000010000)
+# CHECK-NEXT:      DW_AT_ranges{{.*}}(0x00000000)
+
index 7b8ecfecc2b031c63a72b34fc28d13ea99811908..ed9eba0b0d9f6038a1f910b76d6705b29f4ac414 100644 (file)
@@ -1,4 +1,4 @@
 if not 'X86' in config.root.targets:
     config.unsupported = True
 
-config.suffixes = ['.test', '.cpp']
+config.suffixes = ['.test', '.cpp', '.s']
index 6881eab9c3522edc972ed2f512ef2926e038d542..f3e48f5033e615549fcf41aa149a96fd4143ab76 100644 (file)
@@ -688,7 +688,7 @@ void DwarfStreamer::emitRangesEntries(
   MS->SwitchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
 
   // Offset each range by the right amount.
-  int64_t PcOffset = FuncRange.value() + UnitPcOffset;
+  int64_t PcOffset = Entries.empty() ? 0 : FuncRange.value() + UnitPcOffset;
   for (const auto &Range : Entries) {
     if (Range.isBaseAddressSelectionEntry(AddressSize)) {
       warn("unsupported base address selection operation",
@@ -2638,16 +2638,18 @@ void DwarfLinker::patchRangesForUnit(const CompileUnit &Unit,
     RangeAttribute.set(Streamer->getRangesSectionSize());
     RangeList.extract(RangeExtractor, &Offset);
     const auto &Entries = RangeList.getEntries();
-    const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
+    if (!Entries.empty()) {
+      const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
 
-    if (CurrRange == InvalidRange ||
-        First.StartAddress + OrigLowPc < CurrRange.start() ||
-        First.StartAddress + OrigLowPc >= CurrRange.stop()) {
-      CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc);
       if (CurrRange == InvalidRange ||
-          CurrRange.start() > First.StartAddress + OrigLowPc) {
-        reportWarning("no mapping for range.");
-        continue;
+          First.StartAddress + OrigLowPc < CurrRange.start() ||
+          First.StartAddress + OrigLowPc >= CurrRange.stop()) {
+        CurrRange = FunctionRanges.find(First.StartAddress + OrigLowPc);
+        if (CurrRange == InvalidRange ||
+            CurrRange.start() > First.StartAddress + OrigLowPc) {
+          reportWarning("no mapping for range.");
+          continue;
+        }
       }
     }