[llvm] dcff396 - [DWARF] Return Error from DWARFDebugArangeSet::extract().

Igor Kudrin via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 22 21:43:29 PST 2020


Author: Igor Kudrin
Date: 2020-01-23T12:41:05+07:00
New Revision: dcff3961c2d0872074e405d3fb06b28259bb652f

URL: https://github.com/llvm/llvm-project/commit/dcff3961c2d0872074e405d3fb06b28259bb652f
DIFF: https://github.com/llvm/llvm-project/commit/dcff3961c2d0872074e405d3fb06b28259bb652f.diff

LOG: [DWARF] Return Error from DWARFDebugArangeSet::extract().

This helps to detect and report parsing errors better.
The patch follows the ideas of LLDB's patches D59370 and D59381.

It adds tests for valid and some invalid cases. More checks and
tests to come. Note that the patch fixes validation of the Length
field because the value does not include the field itself.

The existing users are updated to show the error messages.

Differential Revision: https://reviews.llvm.org/D71875

Added: 
    llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s
    llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml
    llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp

Modified: 
    llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
    llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
    llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
    llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s
    llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml
    llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml
    llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml
    llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml
    llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml
    llvm/tools/obj2yaml/dwarf2yaml.cpp
    llvm/tools/obj2yaml/macho2yaml.cpp
    llvm/tools/obj2yaml/obj2yaml.cpp
    llvm/tools/obj2yaml/obj2yaml.h
    llvm/unittests/DebugInfo/DWARF/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
index ebe4ad6e24dd..d03c3414e737 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Error.h"
 #include <cstdint>
 #include <vector>
 
@@ -57,7 +58,7 @@ class DWARFDebugArangeSet {
   DWARFDebugArangeSet() { clear(); }
 
   void clear();
-  bool extract(DataExtractor data, uint64_t *offset_ptr);
+  Error extract(DataExtractor data, uint64_t *offset_ptr);
   void dump(raw_ostream &OS) const;
 
   uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; }

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index aaa6d5250f23..01073aff5667 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -453,8 +453,13 @@ void DWARFContext::dump(
     uint64_t offset = 0;
     DataExtractor arangesData(DObj->getArangesSection(), isLittleEndian(), 0);
     DWARFDebugArangeSet set;
-    while (set.extract(arangesData, &offset))
+    while (arangesData.isValidOffset(offset)) {
+      if (Error E = set.extract(arangesData, &offset)) {
+        WithColor::error() << toString(std::move(E)) << '\n';
+        break;
+      }
       set.dump(OS);
+    }
   }
 
   auto DumpLineSection = [&](DWARFDebugLine::SectionParser Parser,

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
index b8478bdc48f9..c35297b1b818 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
@@ -29,73 +30,78 @@ void DWARFDebugArangeSet::clear() {
   ArangeDescriptors.clear();
 }
 
-bool
-DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) {
-  if (data.isValidOffset(*offset_ptr)) {
-    ArangeDescriptors.clear();
-    Offset = *offset_ptr;
-
-    // 7.20 Address Range Table
-    //
-    // Each set of entries in the table of address ranges contained in
-    // the .debug_aranges section begins with a header consisting of: a
-    // 4-byte length containing the length of the set of entries for this
-    // compilation unit, not including the length field itself; a 2-byte
-    // version identifier containing the value 2 for DWARF Version 2; a
-    // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
-    // containing the size in bytes of an address (or the offset portion of
-    // an address for segmented addressing) on the target system; and a
-    // 1-byte unsigned integer containing the size in bytes of a segment
-    // descriptor on the target system. This header is followed by a series
-    // of tuples. Each tuple consists of an address and a length, each in
-    // the size appropriate for an address on the target architecture.
-    HeaderData.Length = data.getU32(offset_ptr);
-    HeaderData.Version = data.getU16(offset_ptr);
-    HeaderData.CuOffset = data.getU32(offset_ptr);
-    HeaderData.AddrSize = data.getU8(offset_ptr);
-    HeaderData.SegSize = data.getU8(offset_ptr);
-
-    // Perform basic validation of the header fields.
-    if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length) ||
-        (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)) {
-      clear();
-      return false;
-    }
-
-    // The first tuple following the header in each set begins at an offset
-    // that is a multiple of the size of a single tuple (that is, twice the
-    // size of an address). The header is padded, if necessary, to the
-    // appropriate boundary.
-    const uint32_t header_size = *offset_ptr - Offset;
-    const uint32_t tuple_size = HeaderData.AddrSize * 2;
-    uint32_t first_tuple_offset = 0;
-    while (first_tuple_offset < header_size)
-      first_tuple_offset += tuple_size;
-
-    *offset_ptr = Offset + first_tuple_offset;
-
-    Descriptor arangeDescriptor;
-
-    static_assert(sizeof(arangeDescriptor.Address) ==
-                      sizeof(arangeDescriptor.Length),
-                  "Different datatypes for addresses and sizes!");
-    assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
-
-    while (data.isValidOffset(*offset_ptr)) {
-      arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
-      arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
-
-      // Each set of tuples is terminated by a 0 for the address and 0
-      // for the length.
-      if (arangeDescriptor.Address || arangeDescriptor.Length)
-        ArangeDescriptors.push_back(arangeDescriptor);
-      else
-        return true; // We are done if we get a zero address and length
-    }
-
-    return false; // No termination tuple is found.
+Error DWARFDebugArangeSet::extract(DataExtractor data, uint64_t *offset_ptr) {
+  assert(data.isValidOffset(*offset_ptr));
+  ArangeDescriptors.clear();
+  Offset = *offset_ptr;
+
+  // 7.20 Address Range Table
+  //
+  // Each set of entries in the table of address ranges contained in
+  // the .debug_aranges section begins with a header consisting of: a
+  // 4-byte length containing the length of the set of entries for this
+  // compilation unit, not including the length field itself; a 2-byte
+  // version identifier containing the value 2 for DWARF Version 2; a
+  // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
+  // containing the size in bytes of an address (or the offset portion of
+  // an address for segmented addressing) on the target system; and a
+  // 1-byte unsigned integer containing the size in bytes of a segment
+  // descriptor on the target system. This header is followed by a series
+  // of tuples. Each tuple consists of an address and a length, each in
+  // the size appropriate for an address on the target architecture.
+  HeaderData.Length = data.getU32(offset_ptr);
+  HeaderData.Version = data.getU16(offset_ptr);
+  HeaderData.CuOffset = data.getU32(offset_ptr);
+  HeaderData.AddrSize = data.getU8(offset_ptr);
+  HeaderData.SegSize = data.getU8(offset_ptr);
+
+  // Perform basic validation of the header fields.
+  if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length + 4))
+    return createStringError(errc::invalid_argument,
+                             "the length of address range table at offset "
+                             "0x%" PRIx64 " exceeds section size",
+                             Offset);
+  if (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)
+    return createStringError(errc::invalid_argument,
+                             "address range table at offset 0x%" PRIx64
+                             " has unsupported address size: %d "
+                             "(4 and 8 supported)",
+                             Offset, HeaderData.AddrSize);
+
+  // The first tuple following the header in each set begins at an offset
+  // that is a multiple of the size of a single tuple (that is, twice the
+  // size of an address). The header is padded, if necessary, to the
+  // appropriate boundary.
+  const uint32_t header_size = *offset_ptr - Offset;
+  const uint32_t tuple_size = HeaderData.AddrSize * 2;
+  uint32_t first_tuple_offset = 0;
+  while (first_tuple_offset < header_size)
+    first_tuple_offset += tuple_size;
+
+  *offset_ptr = Offset + first_tuple_offset;
+
+  Descriptor arangeDescriptor;
+
+  static_assert(sizeof(arangeDescriptor.Address) ==
+                    sizeof(arangeDescriptor.Length),
+                "Different datatypes for addresses and sizes!");
+  assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
+
+  while (data.isValidOffset(*offset_ptr)) {
+    arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
+    arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
+
+    // Each set of tuples is terminated by a 0 for the address and 0
+    // for the length.
+    if (arangeDescriptor.Address == 0 && arangeDescriptor.Length == 0)
+      return ErrorSuccess();
+    ArangeDescriptors.push_back(arangeDescriptor);
   }
-  return false;
+
+  return createStringError(errc::invalid_argument,
+                           "address range table at offset 0x%" PRIx64
+                           " is not terminated by null entry",
+                           Offset);
 }
 
 void DWARFDebugArangeSet::dump(raw_ostream &OS) const {

diff  --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
index fa157e868851..9ca9021e205e 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
@@ -26,7 +26,11 @@ void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
   uint64_t Offset = 0;
   DWARFDebugArangeSet Set;
 
-  while (Set.extract(DebugArangesData, &Offset)) {
+  while (DebugArangesData.isValidOffset(Offset)) {
+    if (Error E = Set.extract(DebugArangesData, &Offset)) {
+      WithColor::error() << toString(std::move(E)) << '\n';
+      return;
+    }
     uint64_t CUOffset = Set.getCompileUnitDIEOffset();
     for (const auto &Desc : Set.descriptors()) {
       uint64_t LowPC = Desc.Address;

diff  --git a/llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s b/llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s
index 0ee166da4c22..359543baa6d0 100644
--- a/llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s
+++ b/llvm/test/DebugInfo/X86/dwarfdump-debug-aranges.s
@@ -5,7 +5,7 @@
     .section .debug_aranges,"", at progbits
 # CHECK: .debug_aranges contents:
 
-## Check that an empty set of ranges is supported.
+## Case 1: Check that an empty set of ranges is supported.
     .long   .L1end - .L1version     # Length
 # CHECK: Address Range Header: length = 0x00000014,
 .L1version:
@@ -22,3 +22,44 @@
     .long   0, 0                    # Termination tuple
 # CHECK-NOT: [0x
 .L1end:
+
+## Case 2: Check that the address size of 4 is supported.
+    .long   .L2end - .L2version     # Length
+# CHECK: Address Range Header: length = 0x0000001c,
+.L2version:
+    .short  2                       # Version
+    .long   0x11223344              # Debug Info Offset
+    .byte   4                       # Address Size
+    .byte   0                       # Segment Selector Size
+# CHECK-SAME: version = 0x0002,
+# CHECK-SAME: cu_offset = 0x11223344,
+# CHECK-SAME: addr_size = 0x04,
+# CHECK-SAME: seg_size = 0x00
+    .space  4                       # Padding
+.L2tuples:
+    .long   0x11223344, 0x01020304  # Address and length
+# CHECK-NEXT: [0x11223344,  0x12243648)
+    .long   0, 0                    # Termination tuple
+# CHECK-NOT: [0x
+.L2end:
+
+## Case 3: Check that the address size of 8 is also supported.
+    .long   .L3end - .L3version     # Length
+# CHECK: Address Range Header: length = 0x0000002c,
+.L3version:
+    .short  2                       # Version
+    .long   0x22334455              # Debug Info Offset
+    .byte   8                       # Address Size
+    .byte   0                       # Segment Selector Size
+# CHECK-SAME: version = 0x0002,
+# CHECK-SAME: cu_offset = 0x22334455,
+# CHECK-SAME: addr_size = 0x08,
+# CHECK-SAME: seg_size = 0x00
+    .space  4                       # Padding
+.L3tuples:
+    .quad   0x1122334455667788      # Address
+    .quad   0x0102030405060708      # Length
+# CHECK-NEXT: [0x1122334455667788,  0x122436485a6c7e90)
+    .quad   0, 0                    # Termination tuple
+# CHECK-NOT: [0x
+.L3end:

diff  --git a/llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml b/llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml
index 07365148bb82..8301aa69172a 100644
--- a/llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml
+++ b/llvm/test/ObjectYAML/MachO/DWARF-debug_abbrev.yaml
@@ -189,18 +189,6 @@ LoadCommands:
         reserved1:       0x00000000
         reserved2:       0x00000000
         reserved3:       0x00000000
-      - sectname:        __debug_aranges
-        segname:         __DWARF
-        addr:            0x0000000100003083
-        size:            48
-        offset:          0x00002083
-        align:           0
-        reloff:          0x00000000
-        nreloc:          0
-        flags:           0x00000000
-        reserved1:       0x00000000
-        reserved2:       0x00000000
-        reserved3:       0x00000000
       - sectname:        __debug_info
         segname:         __DWARF
         addr:            0x00000001000030B3

diff  --git a/llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml b/llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml
index 84c5e22d2554..40890349f5c6 100644
--- a/llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml
+++ b/llvm/test/ObjectYAML/MachO/DWARF-debug_str.yaml
@@ -126,18 +126,6 @@ LoadCommands:
         reserved1:       0x00000000
         reserved2:       0x00000000
         reserved3:       0x00000000
-      - sectname:        __debug_aranges
-        segname:         __DWARF
-        addr:            0x0000000100002084
-        size:            48
-        offset:          0x00002084
-        align:           0
-        reloff:          0x00000000
-        nreloc:          0
-        flags:           0x00000000
-        reserved1:       0x00000000
-        reserved2:       0x00000000
-        reserved3:       0x00000000
       - sectname:        __debug_info
         segname:         __DWARF
         addr:            0x00000001000020B4

diff  --git a/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml b/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml
index a3c05ca5b358..f2eadd20d8a7 100644
--- a/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml
+++ b/llvm/test/ObjectYAML/MachO/DWARF-pubsections.yaml
@@ -189,18 +189,6 @@ LoadCommands:
         reserved1:       0x00000000
         reserved2:       0x00000000
         reserved3:       0x00000000
-      - sectname:        __debug_aranges
-        segname:         __DWARF
-        addr:            0x0000000100003083
-        size:            48
-        offset:          0x00002083
-        align:           0
-        reloff:          0x00000000
-        nreloc:          0
-        flags:           0x00000000
-        reserved1:       0x00000000
-        reserved2:       0x00000000
-        reserved3:       0x00000000
       - sectname:        __debug_info
         segname:         __DWARF
         addr:            0x00000001000030B3

diff  --git a/llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml b/llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml
index a7aa4e205d2b..8e30d4953271 100644
--- a/llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml
+++ b/llvm/test/ObjectYAML/MachO/DWARF2-AddrSize8-FormValues.yaml
@@ -189,18 +189,6 @@ LoadCommands:
         reserved1:       0x00000000
         reserved2:       0x00000000
         reserved3:       0x00000000
-      - sectname:        __debug_aranges
-        segname:         __DWARF
-        addr:            0x0000000100003083
-        size:            48
-        offset:          0x00002083
-        align:           0
-        reloff:          0x00000000
-        nreloc:          0
-        flags:           0x00000000
-        reserved1:       0x00000000
-        reserved2:       0x00000000
-        reserved3:       0x00000000
       - sectname:        __debug_info
         segname:         __DWARF
         addr:            0x00000001000030B3

diff  --git a/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml b/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml
index 047ee749d674..817830d35420 100644
--- a/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml
+++ b/llvm/test/ObjectYAML/MachO/DWARF5-abbrevValues.yaml
@@ -189,18 +189,6 @@ LoadCommands:
         reserved1:       0x00000000
         reserved2:       0x00000000
         reserved3:       0x00000000
-      - sectname:        __debug_aranges
-        segname:         __DWARF
-        addr:            0x0000000100003083
-        size:            48
-        offset:          0x00002083
-        align:           0
-        reloff:          0x00000000
-        nreloc:          0
-        flags:           0x00000000
-        reserved1:       0x00000000
-        reserved2:       0x00000000
-        reserved3:       0x00000000
       - sectname:        __debug_info
         segname:         __DWARF
         addr:            0x00000001000030B3

diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s b/llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s
new file mode 100644
index 000000000000..7c44810a21ae
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/debug_aranges-error.s
@@ -0,0 +1,21 @@
+# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o
+# RUN: llvm-dwarfdump -debug-aranges %t.o 2>&1 | FileCheck %s
+# RUN: llvm-dwarfdump -lookup 10 %t.o 2>&1 | FileCheck %s
+
+## This checks that llvm-dwarfdump shows parsing errors in .debug_aranges.
+## For more error cases see unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp.
+
+# CHECK: the length of address range table at offset 0x0 exceeds section size
+
+    .section .debug_aranges,"", at progbits
+    .long   .Lend - .Lversion + 1   # The length exceeds the section boundaries
+.Lversion:
+    .short  2                       # Version
+    .long   0                       # Debug Info Offset
+    .byte   4                       # Address Size
+    .byte   0                       # Segment Selector Size
+    .space  4                       # Padding
+.Ltuples:
+    .long   0, 1                    # Address and length
+    .long   0, 0                    # Termination tuple
+.Lend:

diff  --git a/llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml b/llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml
new file mode 100644
index 000000000000..680b7c6e80a6
--- /dev/null
+++ b/llvm/test/tools/obj2yaml/macho-DWARF-debug_aranges-error.yaml
@@ -0,0 +1,301 @@
+# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
+
+--- !mach-o
+FileHeader:      
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x00000003
+  filetype:        0x0000000A
+  ncmds:           5
+  sizeofcmds:      1800
+  flags:           0x00000000
+  reserved:        0x00000000
+LoadCommands:    
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __PAGEZERO
+    vmaddr:          0
+    vmsize:          4294967296
+    fileoff:         0
+    filesize:        0
+    maxprot:         0
+    initprot:        0
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         472
+    segname:         __TEXT
+    vmaddr:          4294967296
+    vmsize:          4096
+    fileoff:         0
+    filesize:        0
+    maxprot:         7
+    initprot:        5
+    nsects:          5
+    flags:           0
+    Sections:        
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0000000100000F50
+        size:            52
+        offset:          0x00000000
+        align:           4
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __stubs
+        segname:         __TEXT
+        addr:            0x0000000100000F84
+        size:            6
+        offset:          0x00000000
+        align:           1
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000408
+        reserved1:       0x00000000
+        reserved2:       0x00000006
+        reserved3:       0x00000000
+      - sectname:        __stub_helper
+        segname:         __TEXT
+        addr:            0x0000000100000F8C
+        size:            26
+        offset:          0x00000000
+        align:           2
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __cstring
+        segname:         __TEXT
+        addr:            0x0000000100000FA6
+        size:            14
+        offset:          0x00000000
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000002
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __unwind_info
+        segname:         __TEXT
+        addr:            0x0000000100000FB4
+        size:            72
+        offset:          0x00000000
+        align:           2
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         232
+    segname:         __DATA
+    vmaddr:          4294971392
+    vmsize:          4096
+    fileoff:         0
+    filesize:        0
+    maxprot:         7
+    initprot:        3
+    nsects:          2
+    flags:           0
+    Sections:        
+      - sectname:        __nl_symbol_ptr
+        segname:         __DATA
+        addr:            0x0000000100001000
+        size:            16
+        offset:          0x00000000
+        align:           3
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000006
+        reserved1:       0x00000001
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __la_symbol_ptr
+        segname:         __DATA
+        addr:            0x0000000100001010
+        size:            8
+        offset:          0x00000000
+        align:           3
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000007
+        reserved1:       0x00000003
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         72
+    segname:         __LINKEDIT
+    vmaddr:          4294975488
+    vmsize:          4096
+    fileoff:         4096
+    filesize:        60
+    maxprot:         7
+    initprot:        1
+    nsects:          0
+    flags:           0
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         952
+    segname:         __DWARF
+    vmaddr:          4294979584
+    vmsize:          4096
+    fileoff:         8192
+    filesize:        764
+    maxprot:         7
+    initprot:        3
+    nsects:          11
+    flags:           0
+    Sections:        
+      - sectname:        __debug_line
+        segname:         __DWARF
+        addr:            0x0000000100003000
+        size:            69
+        offset:          0x00002000
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __debug_pubnames
+        segname:         __DWARF
+        addr:            0x0000000100003045
+        size:            27
+        offset:          0x00002045
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __debug_pubtypes
+        segname:         __DWARF
+        addr:            0x0000000100003060
+        size:            35
+        offset:          0x00002060
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __debug_aranges
+        segname:         __DWARF
+        addr:            0x0000000100003083
+        size:            48
+        offset:          0x00002083
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __debug_info
+        segname:         __DWARF
+        addr:            0x00000001000030B3
+        size:            121
+        offset:          0x000020B3
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __debug_abbrev
+        segname:         __DWARF
+        addr:            0x000000010000312C
+        size:            76
+        offset:          0x0000212C
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __debug_str
+        segname:         __DWARF
+        addr:            0x0000000100003178
+        size:            142
+        offset:          0x00002178
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __apple_names
+        segname:         __DWARF
+        addr:            0x0000000100003206
+        size:            60
+        offset:          0x00002206
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __apple_namespac
+        segname:         __DWARF
+        addr:            0x0000000100003242
+        size:            36
+        offset:          0x00002242
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __apple_types
+        segname:         __DWARF
+        addr:            0x0000000100003266
+        size:            114
+        offset:          0x00002266
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+      - sectname:        __apple_objc
+        segname:         __DWARF
+        addr:            0x00000001000032D8
+        size:            36
+        offset:          0x000022D8
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+DWARF:
+  debug_aranges:
+    - Length:
+        TotalLength:     45
+      Version:         2
+      CuOffset:        0
+      AddrSize:        8
+      SegSize:         0
+      Descriptors:
+        - Address:         0x0000000100000F50
+          Length:          52
+...
+
+#CHECK: the length of address range table at offset 0x0 exceeds section size

diff  --git a/llvm/tools/obj2yaml/dwarf2yaml.cpp b/llvm/tools/obj2yaml/dwarf2yaml.cpp
index f684b4655047..524f43e71bd5 100644
--- a/llvm/tools/obj2yaml/dwarf2yaml.cpp
+++ b/llvm/tools/obj2yaml/dwarf2yaml.cpp
@@ -56,13 +56,15 @@ void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) {
   }
 }
 
-void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
+Error dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
   DataExtractor ArangesData(DCtx.getDWARFObj().getArangesSection(),
                             DCtx.isLittleEndian(), 0);
   uint64_t Offset = 0;
   DWARFDebugArangeSet Set;
 
-  while (Set.extract(ArangesData, &Offset)) {
+  while (ArangesData.isValidOffset(Offset)) {
+    if (Error E = Set.extract(ArangesData, &Offset))
+      return E;
     DWARFYAML::ARange Range;
     Range.Length.setLength(Set.getHeader().Length);
     Range.Version = Set.getHeader().Version;
@@ -77,6 +79,7 @@ void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
     }
     Y.ARanges.push_back(Range);
   }
+  return ErrorSuccess();
 }
 
 void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y,
@@ -346,12 +349,13 @@ void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
   }
 }
 
-std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) {
+llvm::Error dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) {
   dumpDebugAbbrev(DCtx, Y);
   dumpDebugStrings(DCtx, Y);
-  dumpDebugARanges(DCtx, Y);
+  if (Error E = dumpDebugARanges(DCtx, Y))
+    return E;
   dumpDebugPubSections(DCtx, Y);
   dumpDebugInfo(DCtx, Y);
   dumpDebugLines(DCtx, Y);
-  return obj2yaml_error::success;
+  return ErrorSuccess();
 }

diff  --git a/llvm/tools/obj2yaml/macho2yaml.cpp b/llvm/tools/obj2yaml/macho2yaml.cpp
index 517e7f196ee0..0ee8814d35ab 100644
--- a/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -198,7 +198,7 @@ Expected<std::unique_ptr<MachOYAML::Object>> MachODumper::dump() {
 
   std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(Obj);
   if (auto Err = dwarf2yaml(*DICtx, Y->DWARF))
-    return errorCodeToError(Err);
+    return std::move(Err);
   return std::move(Y);
 }
 
@@ -543,20 +543,20 @@ Error macho2yaml(raw_ostream &Out, const object::MachOUniversalBinary &Obj) {
   return Error::success();
 }
 
-std::error_code macho2yaml(raw_ostream &Out, const object::Binary &Binary) {
+Error macho2yaml(raw_ostream &Out, const object::Binary &Binary) {
   if (const auto *MachOObj = dyn_cast<object::MachOUniversalBinary>(&Binary)) {
     if (auto Err = macho2yaml(Out, *MachOObj)) {
-      return errorToErrorCode(std::move(Err));
+      return Err;
     }
-    return obj2yaml_error::success;
+    return Error::success();
   }
 
   if (const auto *MachOObj = dyn_cast<object::MachOObjectFile>(&Binary)) {
     if (auto Err = macho2yaml(Out, *MachOObj)) {
-      return errorToErrorCode(std::move(Err));
+      return Err;
     }
-    return obj2yaml_error::success;
+    return Error::success();
   }
 
-  return obj2yaml_error::unsupported_obj_file_format;
+  return errorCodeToError(obj2yaml_error::unsupported_obj_file_format);
 }

diff  --git a/llvm/tools/obj2yaml/obj2yaml.cpp b/llvm/tools/obj2yaml/obj2yaml.cpp
index f03b1ef4bade..67ba0e416e68 100644
--- a/llvm/tools/obj2yaml/obj2yaml.cpp
+++ b/llvm/tools/obj2yaml/obj2yaml.cpp
@@ -42,7 +42,7 @@ static Error dumpInput(StringRef File) {
   // Universal MachO is not a subclass of ObjectFile, so it needs to be handled
   // here with the other binary types.
   if (Binary.isMachO() || Binary.isMachOUniversalBinary())
-    return errorCodeToError(macho2yaml(outs(), Binary));
+    return macho2yaml(outs(), Binary);
   // TODO: If this is an archive, then burst it and dump each entry
   if (ObjectFile *Obj = dyn_cast<ObjectFile>(&Binary))
     return dumpObject(*Obj);

diff  --git a/llvm/tools/obj2yaml/obj2yaml.h b/llvm/tools/obj2yaml/obj2yaml.h
index 4f4a5330429f..b538ff87ac2b 100644
--- a/llvm/tools/obj2yaml/obj2yaml.h
+++ b/llvm/tools/obj2yaml/obj2yaml.h
@@ -23,7 +23,7 @@ std::error_code coff2yaml(llvm::raw_ostream &Out,
                           const llvm::object::COFFObjectFile &Obj);
 llvm::Error elf2yaml(llvm::raw_ostream &Out,
                          const llvm::object::ObjectFile &Obj);
-std::error_code macho2yaml(llvm::raw_ostream &Out,
+llvm::Error macho2yaml(llvm::raw_ostream &Out,
                            const llvm::object::Binary &Obj);
 llvm::Error minidump2yaml(llvm::raw_ostream &Out,
                           const llvm::object::MinidumpFile &Obj);
@@ -40,6 +40,6 @@ struct Data;
 }
 }
 
-std::error_code dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y);
+llvm::Error dwarf2yaml(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y);
 
 #endif

diff  --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
index 4fb79b2a96e9..611621dbd379 100644
--- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
@@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS
 add_llvm_unittest(DebugInfoDWARFTests
   DwarfGenerator.cpp
   DwarfUtils.cpp
+  DWARFDebugArangeSetTest.cpp
   DWARFDebugInfoTest.cpp
   DWARFDebugLineTest.cpp
   DWARFDieTest.cpp

diff  --git a/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
new file mode 100644
index 000000000000..61937c54c636
--- /dev/null
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFDebugArangeSetTest.cpp
@@ -0,0 +1,75 @@
+//===- llvm/unittest/DebugInfo/DWARFDebugArangeSetTest.cpp-----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+template <size_t SecSize>
+void ExpectExtractError(const char (&SecDataRaw)[SecSize],
+                        const char *ErrorMessage) {
+  DataExtractor Extractor(StringRef(SecDataRaw, SecSize - 1),
+                          /* IsLittleEndian = */ true,
+                          /* AddressSize = */ 4);
+  DWARFDebugArangeSet Set;
+  uint64_t Offset = 0;
+  Error E = Set.extract(Extractor, &Offset);
+  ASSERT_TRUE(E.operator bool());
+  EXPECT_STREQ(ErrorMessage, toString(std::move(E)).c_str());
+}
+
+TEST(DWARFDebugArangeSet, LengthExceedsSectionSize) {
+  static const char DebugArangesSecRaw[] =
+      "\x15\x00\x00\x00" // The length exceeds the section boundaries
+      "\x02\x00"         // Version
+      "\x00\x00\x00\x00" // Debug Info Offset
+      "\x04"             // Address Size
+      "\x00"             // Segment Selector Size
+      "\x00\x00\x00\x00" // Padding
+      "\x00\x00\x00\x00" // Termination tuple
+      "\x00\x00\x00\x00";
+  ExpectExtractError(
+      DebugArangesSecRaw,
+      "the length of address range table at offset 0x0 exceeds section size");
+}
+
+TEST(DWARFDebugArangeSet, UnsupportedAddressSize) {
+  static const char DebugArangesSecRaw[] =
+      "\x0c\x00\x00\x00"  // Length
+      "\x02\x00"          // Version
+      "\x00\x00\x00\x00"  // Debug Info Offset
+      "\x02"              // Address Size (not supported)
+      "\x00"              // Segment Selector Size
+                          // No padding
+      "\x00\x00\x00\x00"; // Termination tuple
+  ExpectExtractError(
+      DebugArangesSecRaw,
+      "address range table at offset 0x0 has unsupported address size: 2 "
+      "(4 and 8 supported)");
+}
+
+TEST(DWARFDebugArangeSet, NoTerminationEntry) {
+  static const char DebugArangesSecRaw[] =
+      "\x14\x00\x00\x00" // Length
+      "\x02\x00"         // Version
+      "\x00\x00\x00\x00" // Debug Info Offset
+      "\x04"             // Address Size
+      "\x00"             // Segment Selector Size
+      "\x00\x00\x00\x00" // Padding
+      "\x00\x00\x00\x00" // Entry: Address
+      "\x01\x00\x00\x00" //        Length
+      ;                  // No termination tuple
+  ExpectExtractError(
+      DebugArangesSecRaw,
+      "address range table at offset 0x0 is not terminated by null entry");
+}
+
+} // end anonymous namespace


        


More information about the llvm-commits mailing list