diff options
| -rw-r--r-- | llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h | 41 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 58 | ||||
| -rw-r--r-- | llvm/test/DebugInfo/X86/dwarfdump-header.s | 8 | 
3 files changed, 67 insertions, 40 deletions
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index a829510a219..54636773a48 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -14,6 +14,7 @@  #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"  #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"  #include "llvm/DebugInfo/DWARF/DWARFDie.h" +#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"  #include <cstdint>  #include <map> @@ -113,20 +114,20 @@ private:    /// \returns The number of errors that occurred during verification.    unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev); -  /// Verifies the header of a unit in the .debug_info section. +  /// Verifies the header of a unit in a .debug_info or .debug_types section.    ///    /// This function currently checks for:    /// - Unit is in 32-bit DWARF format. The function can be modified to    /// support 64-bit format.    /// - The DWARF version is valid    /// - The unit type is valid (if unit is in version >=5) -  /// - The unit doesn't extend beyond .debug_info section +  /// - The unit doesn't extend beyond the containing section    /// - The address size is valid    /// - The offset in the .debug_abbrev section is valid    /// -  /// \param DebugInfoData The .debug_info section data +  /// \param DebugInfoData The section data    /// \param Offset A reference to the offset start of the unit. The offset will -  /// be updated to point to the next unit in .debug_info +  /// be updated to point to the next unit in the section    /// \param UnitIndex The index of the unit to be verified    /// \param UnitType A reference to the type of the unit    /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is @@ -137,7 +138,7 @@ private:                          uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType,                          bool &isUnitDWARF64); -  /// Verifies the header of a unit in the .debug_info section. +  /// Verifies the header of a unit in a .debug_info or .debug_types section.    ///    /// This function currently verifies:    ///  - The debug info attributes. @@ -147,12 +148,22 @@ private:    ///  - If a unit type is provided, that the unit DIE matches the unit type.    ///  - The DIE ranges.    /// -  /// \param Unit      The DWARF Unit to verifiy. +  /// \param Unit      The DWARF Unit to verify.    /// \param UnitType  An optional unit type which will be used to verify the    ///                  type of the unit DIE.    /// -  /// \returns true if the content is verified successfully, false otherwise. -  bool verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType = 0); +  /// \returns The number of errors that occurred during verification. +  unsigned verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType = 0); + +  /// Verifies the unit headers and contents in a .debug_info or .debug_types +  /// section. +  /// +  /// \param S           The DWARF Section to verify. +  /// \param SectionKind The object-file section kind that S comes from. +  /// +  /// \returns The number of errors that occurred during verification. +  unsigned verifyUnitSection(const DWARFSection &S, +                             DWARFSectionKind SectionKind);    /// Verify that all Die ranges are valid.    /// @@ -172,7 +183,7 @@ private:    /// \param AttrValue    The DWARF attribute value to check    ///    /// \returns NumErrors The number of errors occurred during verification of -  /// attributes' values in a .debug_info section unit +  /// attributes' values in a unit    unsigned verifyDebugInfoAttribute(const DWARFDie &Die,                                      DWARFAttribute &AttrValue); @@ -180,14 +191,14 @@ private:    ///    /// This function currently checks for:    /// - All DW_FORM_ref values that are CU relative have valid CU offsets -  /// - All DW_FORM_ref_addr values have valid .debug_info offsets +  /// - All DW_FORM_ref_addr values have valid section offsets    /// - All DW_FORM_strp values have valid .debug_str offsets    ///    /// \param Die          The DWARF DIE that owns the attribute value    /// \param AttrValue    The DWARF attribute value to check    ///    /// \returns NumErrors The number of errors occurred during verification of -  /// attributes' forms in a .debug_info section unit +  /// attributes' forms in a unit    unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue);    /// Verifies the all valid references that were found when iterating through @@ -199,7 +210,7 @@ private:    /// CU relative and absolute references.    ///    /// \returns NumErrors The number of errors occurred during verification of -  /// references for the .debug_info section +  /// references for the .debug_info and .debug_types sections    unsigned verifyDebugInfoReferences();    /// Verify the DW_AT_stmt_list encoding and value and ensure that no @@ -280,12 +291,12 @@ public:    /// false otherwise.    bool handleDebugAbbrev(); -  /// Verify the information in the .debug_info section. +  /// Verify the information in the .debug_info and .debug_types sections.    /// -  /// Any errors are reported to the stream that was this object was +  /// Any errors are reported to the stream that this object was    /// constructed with.    /// -  /// \returns true if the .debug_info verifies successfully, false otherwise. +  /// \returns true if all sections verify successfully, false otherwise.    bool handleDebugInfo();    /// Verify the information in the .debug_line section. diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index 85dd84b5417..b8b876879e9 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -171,8 +171,8 @@ bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,    return Success;  } -bool DWARFVerifier::verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType) { -  uint32_t NumUnitErrors = 0; +unsigned DWARFVerifier::verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType) { +  unsigned NumUnitErrors = 0;    unsigned NumDies = Unit.getNumDIEs();    for (unsigned I = 0; I < NumDies; ++I) {      auto Die = Unit.getDIEAtIndex(I); @@ -188,7 +188,7 @@ bool DWARFVerifier::verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType) {    if (!Die) {      error() << "Compilation unit without DIE.\n";      NumUnitErrors++; -    return NumUnitErrors == 0; +    return NumUnitErrors;    }    if (!dwarf::isUnitType(Die.getTag())) { @@ -208,7 +208,7 @@ bool DWARFVerifier::verifyUnitContents(DWARFUnit &Unit, uint8_t UnitType) {    DieRangeInfo RI;    NumUnitErrors += verifyDieRanges(Die, RI); -  return NumUnitErrors == 0; +  return NumUnitErrors;  }  unsigned DWARFVerifier::verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev) { @@ -252,13 +252,11 @@ bool DWARFVerifier::handleDebugAbbrev() {    return NumErrors == 0;  } -bool DWARFVerifier::handleDebugInfo() { -  OS << "Verifying .debug_info Unit Header Chain...\n"; - +unsigned DWARFVerifier::verifyUnitSection(const DWARFSection &S, +                                          DWARFSectionKind SectionKind) {    const DWARFObject &DObj = DCtx.getDWARFObj(); -  DWARFDataExtractor DebugInfoData(DObj, DObj.getInfoSection(), -                                   DCtx.isLittleEndian(), 0); -  uint32_t NumDebugInfoErrors = 0; +  DWARFDataExtractor DebugInfoData(DObj, S, DCtx.isLittleEndian(), 0); +  unsigned NumDebugInfoErrors = 0;    uint32_t OffsetStart = 0, Offset = 0, UnitIdx = 0;    uint8_t UnitType = 0;    bool isUnitDWARF64 = false; @@ -274,16 +272,16 @@ bool DWARFVerifier::handleDebugInfo() {          break;      } else {        DWARFUnitHeader Header; -      Header.extract(DCtx, DebugInfoData, &OffsetStart); +      Header.extract(DCtx, DebugInfoData, &OffsetStart, SectionKind);        std::unique_ptr<DWARFUnit> Unit;        switch (UnitType) {        case dwarf::DW_UT_type:        case dwarf::DW_UT_split_type: {          Unit.reset(new DWARFTypeUnit( -            DCtx, DObj.getInfoSection(), Header, DCtx.getDebugAbbrev(), -            &DObj.getRangeSection(), DObj.getStringSection(), -            DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), -            DObj.getLineSection(), DCtx.isLittleEndian(), false, UnitVector)); +            DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), +            DObj.getStringSection(), DObj.getStringOffsetSection(), +            &DObj.getAppleObjCSection(), DObj.getLineSection(), +            DCtx.isLittleEndian(), false, UnitVector));          break;        }        case dwarf::DW_UT_skeleton: @@ -294,26 +292,40 @@ bool DWARFVerifier::handleDebugInfo() {        // verifying a compile unit in DWARF v4.        case 0: {          Unit.reset(new DWARFCompileUnit( -            DCtx, DObj.getInfoSection(), Header, DCtx.getDebugAbbrev(), -            &DObj.getRangeSection(), DObj.getStringSection(), -            DObj.getStringOffsetSection(), &DObj.getAppleObjCSection(), -            DObj.getLineSection(), DCtx.isLittleEndian(), false, UnitVector)); +            DCtx, S, Header, DCtx.getDebugAbbrev(), &DObj.getRangeSection(), +            DObj.getStringSection(), DObj.getStringOffsetSection(), +            &DObj.getAppleObjCSection(), DObj.getLineSection(), +            DCtx.isLittleEndian(), false, UnitVector));          break;        }        default: { llvm_unreachable("Invalid UnitType."); }        } -      if (!verifyUnitContents(*Unit, UnitType)) -        ++NumDebugInfoErrors; +      NumDebugInfoErrors += verifyUnitContents(*Unit, UnitType);      }      hasDIE = DebugInfoData.isValidOffset(Offset);      ++UnitIdx;    }    if (UnitIdx == 0 && !hasDIE) { -    warn() << ".debug_info is empty.\n"; +    warn() << "Section is empty.\n";      isHeaderChainValid = true;    } +  if (!isHeaderChainValid) +    ++NumDebugInfoErrors;    NumDebugInfoErrors += verifyDebugInfoReferences(); -  return (isHeaderChainValid && NumDebugInfoErrors == 0); +  return NumDebugInfoErrors; +} + +bool DWARFVerifier::handleDebugInfo() { +  const DWARFObject &DObj = DCtx.getDWARFObj(); + +  OS << "Verifying .debug_info Unit Header Chain...\n"; +  unsigned result = verifyUnitSection(DObj.getInfoSection(), DW_SECT_INFO); + +  OS << "Verifying .debug_types Unit Header Chain...\n"; +  DObj.forEachTypesSections([&](const DWARFSection &S) { +    result += verifyUnitSection(S, DW_SECT_TYPES); +  }); +  return result == 0;  }  unsigned DWARFVerifier::verifyDieRanges(const DWARFDie &Die, diff --git a/llvm/test/DebugInfo/X86/dwarfdump-header.s b/llvm/test/DebugInfo/X86/dwarfdump-header.s index a65bf72deb7..7daba5f6961 100644 --- a/llvm/test/DebugInfo/X86/dwarfdump-header.s +++ b/llvm/test/DebugInfo/X86/dwarfdump-header.s @@ -2,8 +2,9 @@  # We have a representative set of units: v4 CU, v5 CU, v4 TU, v5 split TU.  # We have v4 and v5 line-table headers.  # -# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o - | \ -# RUN: llvm-dwarfdump -v - | FileCheck %s +# RUN: llvm-mc -triple x86_64-unknown-linux %s -filetype=obj -o %t.o +# RUN: llvm-dwarfdump -v %t.o | FileCheck %s +# RUN: llvm-dwarfdump -verify %t.o | FileCheck %s --check-prefix=VERIFY          .section .debug_str,"MS",@progbits,1  str_producer: @@ -435,3 +436,6 @@ dwo_LH_5_end:  # CHECK-NEXT: mod_time: 0x00000035  # CHECK-NEXT: length: 0x00000045  # CHECK-NOT: file_names + +# VERIFY: Verifying .debug_types +# VERIFY: No errors.  | 

