diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -121,6 +121,8 @@ bool hasFileAtIndex(uint64_t FileIndex) const; + uint32_t getLastValidFileIndex() const; + bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir, DILineInfoSpecifier::FileLineInfoKind Kind, @@ -251,6 +253,10 @@ return Prologue.hasFileAtIndex(FileIndex); } + uint32_t getLastValidFileIndex() const { + return Prologue.getLastValidFileIndex(); + } + /// Extracts filename by its index in filename table in prologue. /// In Dwarf 4, the files are 1-indexed and the current compilation file /// name is not represented in the list. In DWARF v5, the files are diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -79,6 +79,16 @@ return FileIndex != 0 && FileIndex <= FileNames.size(); } +uint32_t DWARFDebugLine::Prologue::getLastValidFileIndex() const { + uint16_t DwarfVersion = getVersion(); + assert(DwarfVersion != 0 && + "line table prologue has no dwarf version information"); + // In DWARF v5 the file names are 0-indexed. + if (DwarfVersion >= 5) + return FileNames.size() - 1; + return FileNames.size(); +} + const llvm::DWARFDebugLine::FileNameEntry & DWARFDebugLine::Prologue::getFileNameEntry(uint64_t Index) const { uint16_t DwarfVersion = getVersion(); 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 @@ -538,6 +538,32 @@ } break; } + case DW_AT_call_file: + case DW_AT_decl_file: { + if (auto FileIdx = AttrValue.Value.getAsUnsignedConstant()) { + DWARFUnit *U = Die.getDwarfUnit(); + const auto *LT = U->getContext().getLineTableForUnit(U); + if (LT) { + if (!LT->hasFileAtIndex(*FileIdx)) { + bool isDWARF5 = LT->Prologue.getVersion() >= 5; + uint32_t LastFileIdx = LT->getLastValidFileIndex(); + ReportError("DIE has " + AttributeString(Attr) + + " with an invalid file index " + + llvm::formatv("{0}", *FileIdx) + " (valid values are [" + + (isDWARF5 ? "0-" : "1-") + + llvm::formatv("{0}", LastFileIdx) + "])"); + } + } else { + ReportError("DIE has " + AttributeString(Attr) + + " that references a file by index " + + llvm::formatv("{0}", *FileIdx) + + " and the compile unit has no line table."); + } + } else { + ReportError("DIE has " + AttributeString(Attr) + + " with invalid encoding."); + } + } break; default: break; } diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_attr_file_indexes.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_attr_file_indexes.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_attr_file_indexes.yaml @@ -0,0 +1,218 @@ + +# RUN: yaml2obj %s | not llvm-dwarfdump --verify - | FileCheck %s --implicit-check-not=error: + +# CHECK: error: DIE has DW_AT_decl_file with an invalid file index 2 (valid values are [1-1]){{[[:space:]]}} +# CHECK-NEXT: 0x0000001e: DW_TAG_subprogram +# CHECK-NEXT: DW_AT_name ("main") +# CHECK-NEXT: DW_AT_low_pc (0x0000000000001000) +# CHECK-NEXT: DW_AT_high_pc (0x0000000000002000) +# CHECK-NEXT: DW_AT_decl_file (0x02) +# CHECK-NEXT: DW_AT_call_line (5){{[[:space:]]}} +# CHECK-NEXT: error: DIE has DW_AT_call_file with an invalid file index 3 (valid values are [1-1]){{[[:space:]]}} +# CHECK-NEXT: 0x00000035: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_AT_name ("inline1") +# CHECK-NEXT: DW_AT_low_pc (0x0000000000001100) +# CHECK-NEXT: DW_AT_high_pc (0x0000000000001200) +# CHECK-NEXT: DW_AT_call_file (0x03) +# CHECK-NEXT: DW_AT_call_line (10){{[[:space:]]}} + +# CHECK: Errors detected. +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 4 + sizeofcmds: 464 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 392 + segname: '' + vmaddr: 0 + vmsize: 188 + fileoff: 528 + filesize: 188 + maxprot: 7 + initprot: 7 + nsects: 4 + flags: 0 + Sections: + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x0000000000000000 + size: 44 + offset: 0x00000210 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 011101030E1305110110170000022E01030E110112013A0B590B0000031D00030E11011206580B590B000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x000000000000002C + size: 74 + offset: 0x0000023C + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 460000000400000000000801010000000200000000000000000000000000020D0000000010000000000000002000000000000001050312000000003000000000000000010000010A0000 + - sectname: __debug_line + segname: __DWARF + addr: 0x0000000000000076 + size: 44 + offset: 0x00000286 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 280000000200220000000101FB0E0D0001010101000000010000012F746D7000006D61696E2E630001000000 + - sectname: __debug_str + segname: __DWARF + addr: 0x00000000000000A2 + size: 26 + offset: 0x000002B2 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 002F746D702F6D61696E2E63006D61696E00696E6C696E653100 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 0 + nsyms: 0 + stroff: 720 + strsize: 8 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 659200 + sdk: 659204 + ntools: 1 + Tools: + - tool: 3 + version: 36439552 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 720 + datasize: 0 +LinkEditData: + StringTable: + - ' ' + - '' + - '' + - '' + - '' + - '' + - '' +DWARF: + debug_str: + - '' + - '/tmp/main.c' + - main + - inline1 + debug_abbrev: + - Code: 0x0000000000000001 + 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_data2 + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Code: 0x0000000000000002 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + 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_addr + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_call_line + Form: DW_FORM_data1 + - Code: 0x0000000000000003 + Tag: DW_TAG_inlined_subroutine + 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 + - Attribute: DW_AT_call_file + Form: DW_FORM_data1 + - Attribute: DW_AT_call_line + Form: DW_FORM_data1 + debug_info: + - Length: 0x0000000000000046 + Version: 4 + AbbrOffset: 0x0000000000000000 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000001 + - Value: 0x0000000000000002 + - Value: 0x0000000000000000 + - Value: 0x0000000000000000 + - AbbrCode: 0x00000002 + Values: + - Value: 0x000000000000000D + - Value: 0x0000000000001000 + - Value: 0x0000000000002000 + - Value: 0x0000000000000002 + - Value: 0x0000000000000005 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000012 + - Value: 0x0000000000001100 + - Value: 0x0000000000000100 + - Value: 0x0000000000000003 + - Value: 0x000000000000000A + - AbbrCode: 0x00000000 + Values: [] + - AbbrCode: 0x00000000 + Values: [] + debug_line: + - Length: 40 + Version: 2 + PrologueLength: 34 + MinInstLength: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: + - '/tmp' + Files: + - Name: main.c + DirIdx: 1 + ModTime: 0 + Length: 0 + Opcodes: [] +... diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_info.s b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_info.s --- a/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_info.s +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_debug_info.s @@ -11,6 +11,17 @@ # CHECK-NEXT: DW_AT_comp_dir [DW_FORM_strp] ( .debug_str[0x0000003f] = "/Users/sgravani/Development/tests") # CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) # CHECK-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000016){{[[:space:]]}} +# CHECK-NEXT: error: DIE has DW_AT_decl_file that references a file by index 1 and the compile unit has no line table.{{[[:space:]]}} +# CHECK-NEXT: 0x0000002b: DW_TAG_subprogram [2] * +# CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +# CHECK-NEXT: DW_AT_high_pc [DW_FORM_data4] (0x00000016) +# CHECK-NEXT: DW_AT_frame_base [DW_FORM_exprloc] (DW_OP_reg6) +# CHECK-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[0x00000061] = "main") +# CHECK-NEXT: DW_AT_decl_file [DW_FORM_data1] (0x01) +# CHECK-NEXT: DW_AT_decl_line [DW_FORM_data1] (1) +# CHECK-NEXT: DW_AT_prototyped [DW_FORM_flag_present] (true) +# CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0052 => {0x00000052} "") +# CHECK-NEXT: DW_AT_external [DW_FORM_flag_present] (true){{[[:space:]]}} # CHECK-NEXT: error: DIE has DW_AT_type with incompatible tag DW_TAG_null{{[[:space:]]}} # CHECK-NEXT: 0x0000002b: DW_TAG_subprogram [2] * # CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) @@ -22,6 +33,13 @@ # CHECK-NEXT: DW_AT_prototyped [DW_FORM_flag_present] (true) # CHECK-NEXT: DW_AT_type [DW_FORM_ref4] (cu + 0x0052 => {0x00000052} "") # CHECK-NEXT: DW_AT_external [DW_FORM_flag_present] (true){{[[:space:]]}} +# CHECK-NEXT: error: DIE has DW_AT_decl_file that references a file by index 1 and the compile unit has no line table.{{[[:space:]]}} +# CHECK-NEXT: 0x00000044: DW_TAG_variable [3] +# CHECK-NEXT: DW_AT_location [DW_FORM_exprloc] (DW_OP_fbreg -8) +# CHECK-NEXT: DW_AT_name [DW_FORM_strp] ( .debug_str[0x0000006a] = "a") +# CHECK-NEXT: DW_AT_decl_file [DW_FORM_data1] (0x01) +# CHECK-NEXT: DW_AT_decl_line [DW_FORM_data1] (2) +# CHECK-NEXT: DW_AT_use_location [DW_FORM_ref4] (cu + 0x0053 => {0x00000053}){{[[:space:]]}} # CHECK-NEXT: error: Compilation unit root DIE is not a unit DIE: DW_TAG_null. # CHECK-NEXT: error: Compilation unit type (DW_UT_compile) and root DIE (DW_TAG_null) do not match. # CHECK-NEXT: error: Units[2] - start offset: 0x00000068 diff --git a/llvm/test/tools/llvm-dwarfdump/X86/verify_file_encoding.yaml b/llvm/test/tools/llvm-dwarfdump/X86/verify_file_encoding.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-dwarfdump/X86/verify_file_encoding.yaml @@ -0,0 +1,183 @@ +# RUN: yaml2obj %s | not llvm-dwarfdump --verify - | FileCheck %s --implicit-check-not=error: + +# CHECK: error: DIE has DW_AT_decl_file with invalid encoding.{{[[:space:]]}} +# CHECK-NEXT: 0x0000001a: DW_TAG_subprogram +# CHECK-NEXT: DW_AT_name ("main") +# CHECK-NEXT: DW_AT_low_pc (0x0000000000001000) +# CHECK-NEXT: DW_AT_high_pc (0x0000000000002000) +# CHECK-NEXT: DW_AT_decl_file ("") +# CHECK-NEXT: DW_AT_call_line (5){{[[:space:]]}} +# CHECK-NEXT: error: DIE has DW_AT_call_file with invalid encoding.{{[[:space:]]}} +# CHECK-NEXT: 0x00000034: DW_TAG_inlined_subroutine +# CHECK-NEXT: DW_AT_name ("inline1") +# CHECK-NEXT: DW_AT_low_pc (0x0000000000001100) +# CHECK-NEXT: DW_AT_high_pc (0x0000000000001200) +# CHECK-NEXT: DW_AT_call_file ("") +# CHECK-NEXT: DW_AT_call_line (10){{[[:space:]]}} + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 4 + sizeofcmds: 384 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 312 + segname: '' + vmaddr: 0 + vmsize: 145 + fileoff: 448 + filesize: 145 + maxprot: 7 + initprot: 7 + nsects: 3 + flags: 0 + Sections: + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x0000000000000000 + size: 42 + offset: 0x000001C0 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 011101030E130511010000022E01030E110112013A0E590B0000031D00030E11011206580E590B000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x000000000000002A + size: 76 + offset: 0x000001EA + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 4800000004000000000008010100000002000000000000000000020D0000000010000000000000002000000000000012000000050313000000001100000000000000010000120000000A0000 + - sectname: __debug_str + segname: __DWARF + addr: 0x0000000000000076 + size: 27 + offset: 0x00000236 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: 002F746D702F6D61696E2E63006D61696E0000696E6C696E653100 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 0 + nsyms: 0 + stroff: 600 + strsize: 8 + - cmd: LC_BUILD_VERSION + cmdsize: 32 + platform: 1 + minos: 659200 + sdk: 659204 + ntools: 1 + Tools: + - tool: 3 + version: 36439552 + - cmd: LC_DATA_IN_CODE + cmdsize: 16 + dataoff: 600 + datasize: 0 +LinkEditData: + StringTable: + - ' ' + - '' + - '' + - '' + - '' + - '' + - '' +DWARF: + debug_str: + - '' + - '/tmp/main.c' + - main + - '' + - inline1 + debug_abbrev: + - Code: 0x0000000000000001 + 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_data2 + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Code: 0x0000000000000002 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_yes + 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_addr + - Attribute: DW_AT_decl_file + Form: DW_FORM_strp + - Attribute: DW_AT_call_line + Form: DW_FORM_data1 + - Code: 0x0000000000000003 + Tag: DW_TAG_inlined_subroutine + 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 + - Attribute: DW_AT_call_file + Form: DW_FORM_strp + - Attribute: DW_AT_call_line + Form: DW_FORM_data1 + debug_info: + - Length: 0x0000000000000048 + Version: 4 + AbbrOffset: 0x0000000000000000 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000001 + - Value: 0x0000000000000002 + - Value: 0x0000000000000000 + - AbbrCode: 0x00000002 + Values: + - Value: 0x000000000000000D + - Value: 0x0000000000001000 + - Value: 0x0000000000002000 + - Value: 0x0000000000000012 + - Value: 0x0000000000000005 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000013 + - Value: 0x0000000000001100 + - Value: 0x0000000000000100 + - Value: 0x0000000000000012 + - Value: 0x000000000000000A + - AbbrCode: 0x00000000 + Values: [] + - AbbrCode: 0x00000000 + Values: [] +...