mirror of
https://github.com/RPCS3/llvm.git
synced 2026-07-01 21:04:04 -04:00
[DWARF] Verifier now handles .debug_types sections.
Differential Revision: https://reviews.llvm.org/D50466 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@339302 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user