From 508b081514b4fe2ab856ac1958fdd227a173e862 Mon Sep 17 00:00:00 2001 From: Paul Robinson Date: Wed, 8 Aug 2018 23:50:22 +0000 Subject: [PATCH] [DWARF] Verifier now handles .debug_types sections. Differential Revision: https://reviews.llvm.org/D50466 llvm-svn: 339302 --- llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h | 41 ++++++++++------ llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp | 58 ++++++++++++++--------- 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 a829510..5463677 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 #include @@ -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 85dd84b..b8b8768 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 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 a65bf72..7daba5f 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. -- 2.7.4