diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -283,6 +283,15 @@ unsigned verifyDebugNames(const DWARFSection &AccelSection, const DataExtractor &StrData); + /// Verify that the .debug_aranges table is valid. + /// + /// This function currently checks that: + /// - Any DW_TAG_compile_unit DIEs that have a DW_AT_ranges attribute has a + /// matching entry in the .debug_aranges + /// + /// \returns The number of errors occurred during verification + unsigned verifyDebugAranges(); + public: DWARFVerifier(raw_ostream &S, DWARFContext &D, DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE()); diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -6,6 +6,7 @@ // //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/DWARF/DWARFVerifier.h" +#include "llvm/ADT/AddressRanges.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/SmallSet.h" #include "llvm/BinaryFormat/Dwarf.h" @@ -15,6 +16,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" @@ -965,6 +967,180 @@ return NumDebugLineErrors == 0; } + +static bool DWARFAddressIsInvalid(uint64_t Addr, unsigned AddrSize) { + // Catch any addresses that have been zeroed out, or if they have been set to + // -1 or -2 (max PC) + if (AddrSize == 4) + return Addr == 0 || Addr == UINT32_MAX || Addr == UINT32_MAX-1; + else + return Addr == 0 || Addr == UINT64_MAX || Addr == UINT64_MAX-1; +} + +static size_t AppendDieRanges(DWARFDie Die, unsigned AddrSize, + AddressRanges &Ranges) { + Expected DWARFRanges = Die.getAddressRanges(); + if (!DWARFRanges) { + consumeError(DWARFRanges.takeError()); + return 0; + } + for (const auto &DWARFRange: DWARFRanges.get()) { + // Skip invalid addresses + if (DWARFAddressIsInvalid(DWARFRange.LowPC, AddrSize)) + continue; + if (DWARFRange.LowPC < DWARFRange.HighPC) + Ranges.insert(AddressRange(DWARFRange.LowPC, DWARFRange.HighPC)); + } + return DWARFRanges.get().size(); +} + + +unsigned DWARFVerifier::verifyDebugAranges() { + OS << "Verifying .debug_aranges...\n"; + unsigned NumErrors = 0; + const DWARFObject &D = DCtx.getDWARFObj(); + uint64_t Offset = 0; + DWARFDataExtractor arangesData(D.getArangesSection(), DCtx.isLittleEndian(), 0); + DWARFDebugArangeSet ArangeSet; + while (arangesData.isValidOffset(Offset)) { + const uint64_t SetOffset = Offset; + if (Error E = ArangeSet.extract(arangesData, &Offset, + DumpOpts.WarningHandler)) { + ++NumErrors; + error() << "Failed to exrtact DWARFDebugArangeSet from offset " << + format_hex(SetOffset, 10) << ":\n "; + error() << toString(std::move(E)) << '\n'; + return NumErrors; + } + const DWARFDebugArangeSet::Header &SetHdr = ArangeSet.getHeader(); + auto errorHeader = [SetOffset](raw_ostream &OS) { + OS << ".debug_aranges[" << format_hex(SetOffset, 10) << "]"; + }; + arangesData.setAddressSize(SetHdr.AddrSize); + DWARFCompileUnit *CU = DCtx.getCompileUnitForOffset(SetHdr.CuOffset); + if (CU) { + DWARFDie CUDie = CU->getUnitDIE(); + AddressRanges SortedCURanges; + AddressRanges SortedAranges; + bool CURangesFromSubprograms = false; + // Get all valid compile unit ranges by first trying to get it from the + // compile unit DIE, and if that fails grab all function ranges manually. + if (!AppendDieRanges(CUDie, SetHdr.AddrSize, SortedCURanges)) { + // No DW_AT_ranges or DW_AT_low_pc/DW_AT_high_pc on this compile unit, + // fetch address ranges from all DW_TAG_subprogram DIEs manually. + CURangesFromSubprograms = true; + const unsigned NumDies = CU->getNumDIEs(); + // Note we skip the compile unit DIE by starting at index 1 since we + // already checked that die above. + for (unsigned I = 1; I < NumDies; ++I) { + DWARFDie Die = CU->getDIEAtIndex(I); + if (Die.getTag() == DW_TAG_subprogram) + AppendDieRanges(Die, SetHdr.AddrSize, SortedCURanges); + } + } + const uint32_t AddrPrintSize = 2 + SetHdr.AddrSize * 2; + + // Make sure all .debug_aranges descriptor ranges are found in the + // compile unit's ranges. + uint32_t DescIdx = 0; + for (const auto &Descriptor: ArangeSet.descriptors()) { + if (DWARFAddressIsInvalid(Descriptor.Address, SetHdr.AddrSize)) { + ++DescIdx; + continue; + } + if (Descriptor.Length == 0) { + errorHeader(error()); + OS << "[" << DescIdx << "] has length zero for address " + << format_hex(SetOffset, AddrPrintSize) << ".\n"; + ++NumErrors; + } else { + AddressRange DescRange(Descriptor.Address, + Descriptor.getEndAddress()); + SortedAranges.insert(DescRange); + if (!SortedCURanges.contains(DescRange)) { + errorHeader(error()); + OS << "[" << DescIdx << "] range [" + << format_hex(DescRange.start(), AddrPrintSize) + << " - " << format_hex(DescRange.end(), AddrPrintSize) + << ") not in compile unit @ " + << format_hex(SetHdr.CuOffset, 10); + + if (CURangesFromSubprograms) + OS << " subprogram ranges.\n"; + else + OS << " ranges.\n"; + ++NumErrors; + } + } + ++DescIdx; + } + + // Now make sure that all CU ranges are in the .debug_aranges set. + for (const auto &Range: SortedCURanges) { + if (!SortedAranges.contains(Range)) { + errorHeader(error()); + OS << " compile unit range [" + << format_hex(Range.start(), AddrPrintSize) + << " - " << format_hex(Range.end(), AddrPrintSize) + << ") not in .debug_aranges.\n"; + ++NumErrors; + } + } + + // Now verify that all line table entries in the line tables, whose + // sequences start with a valid address, are found in the .debug_aranges + // for this compile unit. + const DWARFDebugLine::LineTable *LT = DCtx.getLineTableForUnit(CU); + if (LT) { + for (const auto &Sequence: LT->Sequences) { + // If the first address in a sequence is invalid, don't verify it as + // it should have been dead stripped. + const DWARFDebugLine::Row &Row = LT->Rows[Sequence.FirstRowIndex]; + if (DWARFAddressIsInvalid(Row.Address.Address, SetHdr.AddrSize)) + continue; + for (auto I = Sequence.FirstRowIndex; I < Sequence.LastRowIndex; ++I) { + const auto Addr = LT->Rows[I].Address.Address; + // Rows with EndSequence set to true will not be in our ranges, so + // we need to decrement by 1. + const auto EndAdjust = LT->Rows[I].EndSequence ? 1 : 0; + bool InAranges = SortedAranges.contains(Addr - EndAdjust); + bool InCURanges = SortedCURanges.contains(Addr - EndAdjust); + if (!InAranges || !InCURanges) { + errorHeader(error()); + OS << " compile unit @ " << format_hex(SetHdr.CuOffset, 10) + << " line table sequence [" + << Sequence.FirstRowIndex << "-" << Sequence.LastRowIndex + << ") has row[" << I << "] with address " + << format_hex(Addr, AddrPrintSize); + if (!InAranges) + OS << " that is not in .debug_aranges"; + if (!InCURanges) { + if (!InAranges) + OS << " nor"; + OS << " in compile unit"; + if (CURangesFromSubprograms) + OS << " subprogram ranges"; + else + OS << " ranges"; + } + OS << ".\n"; + ++NumErrors; + // Skip the rest of the sequence to avoid too many errors. + break; + } + } + } + } + + } else { + error() << "Failed to find compile unit for unit offset " << + format_hex(SetHdr.CuOffset, 10) << ".\n"; + ++NumErrors; + } + } + return NumErrors; +} + unsigned DWARFVerifier::verifyAppleAccelTable(const DWARFSection *AccelSection, DataExtractor *StrData, const char *SectionName) { @@ -1624,6 +1800,10 @@ if (!D.getNamesSection().Data.empty()) NumErrors += verifyDebugNames(D.getNamesSection(), StrData); + + if (!D.getArangesSection().empty()) + NumErrors += verifyDebugAranges(); + return NumErrors == 0; } diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_cu_range_missing.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_cu_range_missing.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_cu_range_missing.yaml @@ -0,0 +1,144 @@ +# Test a file that has a compile unit that has DW_AT_ranges like: +# DW_AT_ranges [DW_FORM_sec_offset] (0x00000000 +# [0x0000000000001000, 0x0000000000002000) +# [0x0000000000010000, 0x0000000000002000)) +# But the .debug_aranges doesn't have the range: +# [0x0000000000001000, 0x0000000000002000) +# that we get the expected error reported. +# +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-dwarfdump -verify %t.o | FileCheck %s +# CHECK: Verifying .debug_aranges... +# CHECK-NEXT: error: .debug_aranges[0x00000000] compile unit range [0x0000000000001000 - 0x0000000000002000) not in .debug_aranges. + + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x00000000004003E0 +DWARF: + debug_str: + - '' + - './src/main.cpp' + - foo + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_ranges + Form: DW_FORM_sec_offset + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + debug_aranges: + - Length: 0x2C + Version: 4 + CuOffset: 0x0 + AddressSize: 0x8 + Descriptors: + - Address: 0x10000 + Length: 0x1000 + debug_ranges: + - Offset: 0x0 + AddrSize: 0x8 + Entries: + - LowOffset: 0x0 + HighOffset: 0x1000 + - LowOffset: 0xf000 + HighOffset: 0x10000 + debug_info: + - Length: 0x2F + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0x1000 + - Value: 0x0 + - Value: 0x0 + - AbbrCode: 0x2 + Values: + - Value: 0x10 + - Value: 0x1000 + - Value: 0x1000 + - AbbrCode: 0x0 + debug_line: + - Length: 78 + Version: 2 + PrologueLength: 37 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - './src' + Files: + - Name: main.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4096 + - Opcode: DW_LNS_advance_line + SData: 9 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 4048 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges.yaml @@ -0,0 +1,147 @@ +# Test a file that has a compile unit that has the following DWARF: +# +# 0x0000000b: DW_TAG_compile_unit +# DW_AT_name ("./src/main.cpp") +# DW_AT_language (DW_LANG_C) +# DW_AT_low_pc (0x0000000000001000) +# DW_AT_ranges (0x00000000 +# [0x0000000000001000, 0x0000000000002010)) +# DW_AT_stmt_list (0x00000000) +# +# 0x00000021: DW_TAG_subprogram +# DW_AT_name ("foo") +# DW_AT_low_pc (0x0000000000001000) +# DW_AT_high_pc (0x0000000000002010) +# +# 0x00000032: NULL +# +# And the .debug_aranges contains contains: +# Address Range Header: length = 0x0000002c, format = DWARF32, version = 0x0004, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 +# [0x0000000000001000, 0x0000000000002000) + +# With a line table that looks like: +# Address Line Column File ISA Discriminator Flags +# ------------------ ------ ------ ------ --- ------------- ------------- +# 0x0000000000001000 10 0 1 0 0 is_stmt +# 0x0000000000002010 13 0 1 0 0 is_stmt end_sequence +# +# This line table has an address that isn't in the .debug_aranges, so we need to +# verify the error. +# +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-dwarfdump -verify %t.o | FileCheck %s +# CHECK: Verifying .debug_aranges... +# CHECK-NEXT: .debug_aranges[0x00000000] compile unit range [0x0000000000001000 - 0x0000000000002010) not in .debug_aranges. +# CHECK-NEXT: .debug_aranges[0x00000000] compile unit @ 0x00000000 line table sequence [0-2) has row[1] with address 0x0000000000002010 that is not in .debug_aranges. + + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x00000000004003E0 +DWARF: + debug_str: + - '' + - './src/main.cpp' + - foo + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_ranges + Form: DW_FORM_sec_offset + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + debug_aranges: + - Length: 0x2C + Version: 4 + CuOffset: 0x0 + AddressSize: 0x8 + Descriptors: + - Address: 0x1000 + Length: 0x1000 + debug_ranges: + - Offset: 0x0 + AddrSize: 0x8 + Entries: + - LowOffset: 0x0 + HighOffset: 0x1010 + debug_info: + - Length: 0x2F + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0x1000 + - Value: 0x0 + - Value: 0x0 + - AbbrCode: 0x2 + Values: + - Value: 0x10 + - Value: 0x1000 + - Value: 0x1010 + - AbbrCode: 0x0 + debug_line: + - Length: 65 + Version: 2 + PrologueLength: 37 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - './src' + Files: + - Name: main.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4096 + - Opcode: DW_LNS_advance_line + SData: 9 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 4112 + - Opcode: DW_LNS_advance_line + SData: 3 + Data: 0 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges_or_cu_ranges.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges_or_cu_ranges.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges_or_cu_ranges.yaml @@ -0,0 +1,146 @@ +# Test a file that has a compile unit that has the following DWARF: +# +# 0x0000000b: DW_TAG_compile_unit +# DW_AT_name ("./src/main.cpp") +# DW_AT_language (DW_LANG_C) +# DW_AT_low_pc (0x0000000000001000) +# DW_AT_ranges (0x00000000 +# [0x0000000000001000, 0x0000000000002000)) +# DW_AT_stmt_list (0x00000000) +# +# 0x00000021: DW_TAG_subprogram +# DW_AT_name ("foo") +# DW_AT_low_pc (0x0000000000001000) +# DW_AT_high_pc (0x0000000000002000) +# +# 0x00000032: NULL +# +# And the .debug_aranges contains contains: +# Address Range Header: length = 0x0000002c, format = DWARF32, version = 0x0004, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 +# [0x0000000000001000, 0x0000000000002000) +# +# With a line table that looks like: +# Address Line Column File ISA Discriminator Flags +# ------------------ ------ ------ ------ --- ------------- ------------- +# 0x0000000000001000 10 0 1 0 0 is_stmt +# 0x0000000000002010 13 0 1 0 0 is_stmt end_sequence +# +# This line table has an address that isn't in the .debug_aranges or in the +# compile unit DW_AT_ranges, so we need to verify the error. +# +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-dwarfdump -verify %t.o | FileCheck %s +# CHECK: Verifying .debug_aranges... +# CHECK-NEXT: .debug_aranges[0x00000000] compile unit @ 0x00000000 line table sequence [0-2) has row[1] with address 0x0000000000002010 that is not in .debug_aranges nor in compile unit ranges. + + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x00000000004003E0 +DWARF: + debug_str: + - '' + - './src/main.cpp' + - foo + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_ranges + Form: DW_FORM_sec_offset + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + debug_aranges: + - Length: 0x2C + Version: 4 + CuOffset: 0x0 + AddressSize: 0x8 + Descriptors: + - Address: 0x1000 + Length: 0x1000 + debug_ranges: + - Offset: 0x0 + AddrSize: 0x8 + Entries: + - LowOffset: 0x0 + HighOffset: 0x1000 + debug_info: + - Length: 0x2F + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0x1000 + - Value: 0x0 + - Value: 0x0 + - AbbrCode: 0x2 + Values: + - Value: 0x10 + - Value: 0x1000 + - Value: 0x1000 + - AbbrCode: 0x0 + debug_line: + - Length: 65 + Version: 2 + PrologueLength: 37 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - './src' + Files: + - Name: main.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4096 + - Opcode: DW_LNS_advance_line + SData: 9 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 4112 + - Opcode: DW_LNS_advance_line + SData: 3 + Data: 0 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges_or_cu_subprogram.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges_or_cu_subprogram.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_line_row_not_in_aranges_or_cu_subprogram.yaml @@ -0,0 +1,131 @@ +# Test a file that has a compile unit that has the following DWARF: +# +# 0x0000000b: DW_TAG_compile_unit +# DW_AT_name ("./src/main.cpp") +# DW_AT_language (DW_LANG_C) +# DW_AT_stmt_list (0x00000000) +# +# 0x00000015: DW_TAG_subprogram +# DW_AT_name ("foo") +# DW_AT_low_pc (0x0000000000001000) +# DW_AT_high_pc (0x0000000000002000) +# +# 0x00000026: NULL +# +# And the .debug_aranges contains contains: +# Address Range Header: length = 0x0000002c, format = DWARF32, version = 0x0004, cu_offset = 0x00000000, addr_size = 0x08, seg_size = 0x00 +# [0x0000000000001000, 0x0000000000002000) + +# With a line table that looks like: +# Address Line Column File ISA Discriminator Flags +# ------------------ ------ ------ ------ --- ------------- ------------- +# 0x0000000000001000 10 0 1 0 0 is_stmt +# 0x0000000000002010 13 0 1 0 0 is_stmt end_sequence +# +# This line table has an address that isn't in the .debug_aranges or in any +# compile unit DW_TAG_subprogram ranges, so we need to verify the error. +# +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-dwarfdump -verify %t.o | FileCheck %s +# CHECK: Verifying .debug_aranges... +# CHECK-NEXT: .debug_aranges[0x00000000] compile unit @ 0x00000000 line table sequence [0-2) has row[1] with address 0x0000000000002010 that is not in .debug_aranges nor in compile unit subprogram ranges. + + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x00000000004003E0 +DWARF: + debug_str: + - '' + - './src/main.cpp' + - foo + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + debug_aranges: + - Length: 0x2C + Version: 4 + CuOffset: 0x0 + AddressSize: 0x8 + Descriptors: + - Address: 0x1000 + Length: 0x1000 + debug_info: + - Length: 0x23 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0x0 + - AbbrCode: 0x2 + Values: + - Value: 0x10 + - Value: 0x1000 + - Value: 0x1000 + - AbbrCode: 0x0 + debug_line: + - Length: 65 + Version: 2 + PrologueLength: 37 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - './src' + Files: + - Name: main.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4096 + - Opcode: DW_LNS_advance_line + SData: 9 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 4112 + - Opcode: DW_LNS_advance_line + SData: 3 + Data: 0 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_missing_cu_range.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_missing_cu_range.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_missing_cu_range.yaml @@ -0,0 +1,145 @@ +# Test a file that has a compile unit that has DW_AT_ranges like: +# DW_AT_ranges [DW_FORM_sec_offset] (0x00000000 +# [0x0000000000001000, 0x0000000000002000) +# And the .debug_aranges contains the following ranges: +# [0x0000000000001000, 0x0000000000002000) +# [0x0000000000010000, 0x0000000000011000) +# that we get the expected error reported stating that one of the .debug_aranges +# is not in the compile units ranges. +# +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-dwarfdump -verify %t.o | FileCheck %s +# CHECK: Verifying .debug_aranges... +# CHECK-NEXT: error: .debug_aranges[0x00000000][1] range [0x0000000000010000 - 0x0000000000011000) not in compile unit @ 0x00000000 ranges. + + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x00000000004003E0 +DWARF: + debug_str: + - '' + - './src/main.cpp' + - foo + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_ranges + Form: DW_FORM_sec_offset + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + debug_aranges: + - Length: 0x3C + Version: 4 + CuOffset: 0x0 + AddressSize: 0x8 + Descriptors: + - Address: 0x1000 + Length: 0x1000 + - Address: 0x10000 + Length: 0x1000 + debug_ranges: + - Offset: 0x0 + AddrSize: 0x8 + Entries: + - LowOffset: 0x0 + HighOffset: 0x1000 + debug_info: + - Length: 0x2F + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0x1000 + - Value: 0x0 + - Value: 0x0 + - AbbrCode: 0x2 + Values: + - Value: 0x10 + - Value: 0x1000 + - Value: 0x1000 + - AbbrCode: 0x0 + debug_line: + - Length: 78 + Version: 2 + PrologueLength: 37 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - './src' + Files: + - Name: main.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4096 + - Opcode: DW_LNS_advance_line + SData: 9 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 4048 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0 +... diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_missing_cu_subprogram.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_missing_cu_subprogram.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_aranges_missing_cu_subprogram.yaml @@ -0,0 +1,132 @@ +# Test a file that has a compile unit that has DW_AT_ranges like: +# DW_AT_ranges [DW_FORM_sec_offset] (0x00000000 +# [0x0000000000001000, 0x0000000000002000) +# And the .debug_aranges contains the following ranges: +# [0x0000000000001000, 0x0000000000002000) +# [0x0000000000010000, 0x0000000000011000) +# that we get the expected error reported stating that one of the .debug_aranges +# is not in the compile units ranges. +# +# RUN: yaml2obj %s -o %t.o +# RUN: not llvm-dwarfdump -verify %t.o | FileCheck %s +# CHECK: Verifying .debug_aranges... +# CHECK-NEXT: error: .debug_aranges[0x00000000][1] range [0x0000000000010000 - 0x0000000000011000) not in compile unit @ 0x00000000 subprogram ranges. + + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 + Entry: 0x00000000004003E0 +DWARF: + debug_str: + - '' + - './src/main.cpp' + - foo + debug_abbrev: + - ID: 0 + Table: + - Code: 0x1 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_udata + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x2 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + debug_aranges: + - Length: 0x3C + Version: 4 + CuOffset: 0x0 + AddressSize: 0x8 + Descriptors: + - Address: 0x1000 + Length: 0x1000 + - Address: 0x10000 + Length: 0x1000 + debug_info: + - Length: 0x23 + Version: 4 + AbbrevTableID: 0 + AbbrOffset: 0x0 + AddrSize: 8 + Entries: + - AbbrCode: 0x1 + Values: + - Value: 0x1 + - Value: 0x2 + - Value: 0x0 + - AbbrCode: 0x2 + Values: + - Value: 0x10 + - Value: 0x1000 + - Value: 0x1000 + - AbbrCode: 0x0 + debug_line: + - Length: 78 + Version: 2 + PrologueLength: 37 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - './src' + Files: + - Name: main.cpp + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 4096 + - Opcode: DW_LNS_advance_line + SData: 9 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 16 + - Opcode: DW_LNS_advance_line + SData: 1 + Data: 0 + - Opcode: DW_LNS_copy + Data: 0 + - Opcode: DW_LNS_advance_pc + Data: 4048 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 0