<div dir="ltr">This included some unused variables :)<div><br></div><div>I've gone ahead and removed them in r307987</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Jul 13, 2017 at 4:25 PM Spyridoula Gravani via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: sgravani<br>
Date: Thu Jul 13 16:25:24 2017<br>
New Revision: 307975<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=307975&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=307975&view=rev</a><br>
Log:<br>
[DWARF] Introduce verification for the unit header chain in .debug_info section to llvm-dwarfdump.<br>
<br>
This patch adds verification checks for the unit header chain in the .debug_info section.<br>
Specifically, for each unit in the .debug_info section, the verifier checks that:<br>
<br>
The unit length is valid (i.e. the unit can actually fit in the .debug_info section)<br>
The dwarf version of the unit is valid<br>
The address size is valid (4 or 8)<br>
The unit type (if the unit is in dwarf5) is valid<br>
The debug_abbrev_offset is valid<br>
<br>
Added:<br>
    llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s<br>
Modified:<br>
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h<br>
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h<br>
    llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp<br>
    llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFUnit.h Thu Jul 13 16:25:24 2017<br>
@@ -238,6 +238,34 @@ public:<br>
<br>
   uint8_t getUnitType() const { return UnitType; }<br>
<br>
+  static bool isValidUnitType(uint8_t UnitType) {<br>
+    return UnitType == dwarf::DW_UT_compile || UnitType == dwarf::DW_UT_type ||<br>
+           UnitType == dwarf::DW_UT_partial ||<br>
+           UnitType == dwarf::DW_UT_skeleton ||<br>
+           UnitType == dwarf::DW_UT_split_compile ||<br>
+           UnitType == dwarf::DW_UT_split_type;<br>
+  }<br>
+<br>
+  /// \brief Return the number of bytes for the header of a unit of<br>
+  /// UnitType type.<br>
+  ///<br>
+  /// This function must be called with a valid unit type which in<br>
+  /// DWARF5 is defined as one of the following six types.<br>
+  static uint32_t getDWARF5HeaderSize(uint8_t UnitType) {<br>
+    switch (UnitType) {<br>
+    case dwarf::DW_UT_compile:<br>
+    case dwarf::DW_UT_partial:<br>
+      return 12;<br>
+    case dwarf::DW_UT_skeleton:<br>
+    case dwarf::DW_UT_split_compile:<br>
+      return 20;<br>
+    case dwarf::DW_UT_type:<br>
+    case dwarf::DW_UT_split_type:<br>
+      return 24;<br>
+    }<br>
+    llvm_unreachable("Invalid UnitType.");<br>
+  }<br>
+<br>
   uint64_t getBaseAddress() const { return BaseAddr; }<br>
<br>
   void setBaseAddress(uint64_t base_addr) {<br>
<br>
Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h (original)<br>
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFVerifier.h Thu Jul 13 16:25:24 2017<br>
@@ -21,6 +21,7 @@ class DWARFContext;<br>
 class DWARFDie;<br>
 class DWARFUnit;<br>
 class DWARFAcceleratorTable;<br>
+class DWARFDataExtractor;<br>
<br>
 /// A class that verifies DWARF debug information given a DWARF Context.<br>
 class DWARFVerifier {<br>
@@ -34,6 +35,29 @@ class DWARFVerifier {<br>
   uint32_t NumDebugLineErrors = 0;<br>
   uint32_t NumAppleNamesErrors = 0;<br>
<br>
+  /// Verifies the header of a unit in the .debug_info section.<br>
+  ///<br>
+  /// This function currently checks for:<br>
+  /// - Unit is in 32-bit DWARF format. The function can be modified to<br>
+  /// support 64-bit format.<br>
+  /// - The DWARF version is valid<br>
+  /// - The unit type is valid (if unit is in version >=5)<br>
+  /// - The unit doesn't extend beyond .debug_info section<br>
+  /// - The address size is valid<br>
+  /// - The offset in the .debug_abbrev section is valid<br>
+  ///<br>
+  /// \param DebugInfoData The .debug_info section data<br>
+  /// \param Offset A reference to the offset start of the unit. The offset will<br>
+  /// be updated to point to the next unit in .debug_info<br>
+  /// \param UnitIndex The index of the unit to be verified<br>
+  /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is<br>
+  /// in 64-bit format.<br>
+  ///<br>
+  /// \returns true if the header is verified successfully, false otherwise.<br>
+  bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,<br>
+                        uint32_t *Offset, unsigned UnitIndex,<br>
+                        bool &isUnitDWARF64);<br>
+<br>
   /// Verifies the attribute's DWARF attribute and its value.<br>
   ///<br>
   /// This function currently checks for:<br>
@@ -78,6 +102,14 @@ class DWARFVerifier {<br>
 public:<br>
   DWARFVerifier(raw_ostream &S, DWARFContext &D)<br>
       : OS(S), DCtx(D) {}<br>
+  /// Verify the unit header chain in the .debug_info section.<br>
+  ///<br>
+  /// Any errors are reported to the stream that this object was<br>
+  /// constructed with.<br>
+  ///<br>
+  /// \returns true if the unit header chain verifies successfully, false<br>
+  /// otherwise.<br>
+  bool handleDebugInfoUnitHeaderChain();<br>
   /// Verify the information in the .debug_info section.<br>
   ///<br>
   /// Any errors are reported to the stream that was this object was<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Thu Jul 13 16:25:24 2017<br>
@@ -414,6 +414,8 @@ DWARFDie DWARFContext::getDIEForOffset(u<br>
 bool DWARFContext::verify(raw_ostream &OS, DIDumpType DumpType) {<br>
   bool Success = true;<br>
   DWARFVerifier verifier(OS, *this);<br>
+  if (!verifier.handleDebugInfoUnitHeaderChain())<br>
+    Success = false;<br>
   if (DumpType == DIDT_All || DumpType == DIDT_Info) {<br>
     if (!verifier.handleDebugInfo())<br>
       Success = false;<br>
<br>
Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=307975&r1=307974&r2=307975&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp?rev=307975&r1=307974&r2=307975&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp (original)<br>
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFVerifier.cpp Thu Jul 13 16:25:24 2017<br>
@@ -24,6 +24,98 @@ using namespace llvm;<br>
 using namespace dwarf;<br>
 using namespace object;<br>
<br>
+bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,<br>
+                               uint32_t *Offset, unsigned UnitIndex,<br>
+                               bool &isUnitDWARF64) {<br>
+  uint32_t AbbrOffset, Length;<br>
+  uint8_t AddrSize = 0, UnitType = 0;<br>
+  uint16_t Version;<br>
+  bool Success = true;<br>
+  uint32_t HeaderSize =<br>
+      11; // means that we have only compile units in .debug_info<br>
+<br>
+  bool ValidLength = false;<br>
+  bool ValidVersion = false;<br>
+  bool ValidAddrSize = false;<br>
+  bool ValidType = true;<br>
+  bool ValidAbbrevOffset = true;<br>
+<br>
+  uint32_t OffsetStart = *Offset;<br>
+  Length = DebugInfoData.getU32(Offset);<br>
+  if (Length == UINT32_MAX) {<br>
+    isUnitDWARF64 = true;<br>
+    OS << format(<br>
+        "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",<br>
+        UnitIndex);<br>
+    return false;<br>
+  }<br>
+  Version = DebugInfoData.getU16(Offset);<br>
+<br>
+  if (Version >= 5) {<br>
+    UnitType = DebugInfoData.getU8(Offset);<br>
+    AddrSize = DebugInfoData.getU8(Offset);<br>
+    AbbrOffset = DebugInfoData.getU32(Offset);<br>
+    ValidType = DWARFUnit::isValidUnitType(UnitType);<br>
+    if (ValidType)<br>
+      HeaderSize = DWARFUnit::getDWARF5HeaderSize(UnitType);<br>
+  } else {<br>
+    AbbrOffset = DebugInfoData.getU32(Offset);<br>
+    AddrSize = DebugInfoData.getU8(Offset);<br>
+  }<br>
+<br>
+  if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))<br>
+    ValidAbbrevOffset = false;<br>
+<br>
+  ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);<br>
+  ValidVersion = DWARFContext::isSupportedVersion(Version);<br>
+  ValidAddrSize = AddrSize == 4 || AddrSize == 8;<br>
+  if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||<br>
+      !ValidType) {<br>
+    Success = false;<br>
+    OS << format("Units[%d] - start offset: 0x%08x \n", UnitIndex, OffsetStart);<br>
+    if (!ValidLength)<br>
+      OS << "\tError: The length for this unit is too "<br>
+            "large for the .debug_info provided.\n";<br>
+    if (!ValidVersion)<br>
+      OS << "\tError: The 16 bit unit header version is not valid.\n";<br>
+    if (!ValidType)<br>
+      OS << "\tError: The unit type encoding is not valid.\n";<br>
+    if (!ValidAbbrevOffset)<br>
+      OS << "\tError: The offset into the .debug_abbrev section is "<br>
+            "not valid.\n";<br>
+    if (!ValidAddrSize)<br>
+      OS << "\tError: The address size is unsupported.\n";<br>
+  }<br>
+  *Offset = OffsetStart + Length + 4;<br>
+  return Success;<br>
+}<br>
+<br>
+bool DWARFVerifier::handleDebugInfoUnitHeaderChain() {<br>
+  OS << "Verifying .debug_info Unit Header Chain...\n";<br>
+<br>
+  DWARFDataExtractor DebugInfoData(DCtx.getInfoSection(), DCtx.isLittleEndian(),<br>
+                                   0);<br>
+  uint32_t OffsetStart, Offset = 0, UnitIdx = 0;<br>
+  bool isUnitDWARF64 = false;<br>
+  bool Success = true;<br>
+  bool hasDIE = DebugInfoData.isValidOffset(Offset);<br>
+  while (hasDIE) {<br>
+    OffsetStart = Offset;<br>
+    if (!verifyUnitHeader(DebugInfoData, &Offset, UnitIdx, isUnitDWARF64)) {<br>
+      Success = false;<br>
+      if (isUnitDWARF64)<br>
+        break;<br>
+    }<br>
+    hasDIE = DebugInfoData.isValidOffset(Offset);<br>
+    ++UnitIdx;<br>
+  }<br>
+  if (UnitIdx == 0 && !hasDIE) {<br>
+    OS << "Warning: .debug_info is empty.\n";<br>
+    Success = true;<br>
+  }<br>
+  return Success;<br>
+}<br>
+<br>
 void DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,<br>
                                              DWARFAttribute &AttrValue) {<br>
   const auto Attr = AttrValue.Attr;<br>
<br>
Added: llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s?rev=307975&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s?rev=307975&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s (added)<br>
+++ llvm/trunk/test/tools/llvm-dwarfdump/X86/verify_unit_header_chain.s Thu Jul 13 16:25:24 2017<br>
@@ -0,0 +1,81 @@<br>
+# RUN: llvm-mc %s -filetype obj -triple x86_64-apple-darwin -o - \<br>
+# RUN: | not llvm-dwarfdump -verify - \<br>
+# RUN: | FileCheck %s<br>
+<br>
+# CHECK: Verifying .debug_info Unit Header Chain...<br>
+# CHECK-NEXT: Units[1] - start offset: 0x0000000d<br>
+# CHECK-NEXT:  Error: The unit type encoding is not valid.<br>
+# CHECK-NEXT:  Error: The address size is unsupported.<br>
+# CHECK-NEXT: Units[2] - start offset: 0x00000026<br>
+# CHECK-NEXT:  Error: The 16 bit unit header version is not valid.<br>
+# CHECK-NEXT:  Error: The offset into the .debug_abbrev section is not valid.<br>
+# CHECK-NEXT: Units[4] - start offset: 0x00000041<br>
+# CHECK-NEXT:  Error: The length for this unit is too large for the .debug_info provided.<br>
+<br>
+       .section        __TEXT,__text,regular,pure_instructions<br>
+       .file   1 "basic.c"<br>
+       .comm   _i,4,2                  ## @i<br>
+       .comm   _j,4,2                  ## @j<br>
+       .section        __DWARF,__debug_str,regular,debug<br>
+Linfo_string:<br>
+       .asciz  "clang version 5.0.0 (trunk 307232) (llvm/trunk 307042)" ## string offset=0<br>
+       .asciz  "basic.c"               ## string offset=55<br>
+       .asciz  "/Users/sgravani/Development/tests" ## string offset=63<br>
+       .asciz  "i"                     ## string offset=97<br>
+       .asciz  "int"                   ## string offset=99<br>
+       .asciz  "j"                     ## string offset=103<br>
+       .section        __DWARF,__debug_abbrev,regular,debug<br>
+Lsection_abbrev:<br>
+       .byte   1                       ## Abbreviation Code<br>
+       .byte   17                      ## DW_TAG_compile_unit<br>
+       .byte   0                       ## EOM(1)<br>
+       .byte   0                       ## EOM(2)<br>
+       .byte   0                       ## EOM(3)<br>
+       .section        __DWARF,__debug_info,regular,debug<br>
+Lsection_info:<br>
+Lcu_begin0:<br>
+       .long   9                      ## Length of Unit<br>
+       .short  4                       ## DWARF version number<br>
+Lset0 = Lsection_abbrev-Lsection_abbrev ## Offset Into Abbrev. Section<br>
+       .long   Lset0<br>
+       .byte   4                       ## Address Size (in bytes)<br>
+       .byte   1                       ## Abbrev [1] 0xc:0x45 DW_TAG_compile_unit<br>
+       .byte   0                       ## End Of Children Mark<br>
+Ltu_begin0:<br>
+       .long   21                      ## Length of Unit<br>
+       .short  5                       ## DWARF version number<br>
+       .byte   0                       ## DWARF Unit Type -- Error: The unit type encoding is not valid.<br>
+       .byte   3                       ## Address Size (in bytes) -- Error: The address size is unsupported.<br>
+       .long   0<br>
+       .quad   0<br>
+       .long   0<br>
+       .byte   0<br>
+Lcu_begin1:<br>
+       .long   10                      ## Length of Unit<br>
+       .short  6                       ## DWARF version number -- Error: The 16 bit unit header version is not valid.<br>
+       .byte   1                       ## DWARF Unit Type<br>
+       .byte   4                       ## Address Size (in bytes) -- The offset into the .debug_abbrev section is not valid.<br>
+       .long   Lline_table_start0<br>
+       .byte   1                       ## Abbrev [1] 0xc:0x45 DW_TAG_compile_unit<br>
+       .byte   0                       ## End Of Children Mark<br>
+Lcu_begin2:<br>
+       .long   9                      ## Length of Unit<br>
+       .short  5                       ## DWARF version number<br>
+       .byte   1                       ## DWARF Unit Type<br>
+       .byte   4                       ## Address Size (in bytes)<br>
+       .long   0                                               ## Abbrev offset<br>
+       .byte   0<br>
+Ltu_begin1:<br>
+       .long   26                      ## Length of Unit -- Error: The length for this unit is too large for the .debug_info provided.<br>
+       .short  5                       ## DWARF version number<br>
+       .byte   2                       ## DWARF Unit Type<br>
+       .byte   4                       ## Address Size (in bytes)<br>
+       .long   0<br>
+       .quad   0<br>
+       .long   0<br>
+       .byte   0<br>
+<br>
+.subsections_via_symbols<br>
+       .section        __DWARF,__debug_line,regular,debug<br>
+Lsection_line:<br>
+Lline_table_start0:<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>