Index: llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp =================================================================== --- llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -175,11 +175,24 @@ unsigned NumDies = Unit.getNumDIEs(); for (unsigned I = 0; I < NumDies; ++I) { auto Die = Unit.getDIEAtIndex(I); + if (Die.getTag() == DW_TAG_null) continue; + + bool HasTypeAttr = false; for (auto AttrValue : Die.attributes()) { NumUnitErrors += verifyDebugInfoAttribute(Die, AttrValue); NumUnitErrors += verifyDebugInfoForm(Die, AttrValue); + HasTypeAttr |= (AttrValue.Attr == DW_AT_type); + } + + if (!HasTypeAttr && (Die.getTag() == DW_TAG_formal_parameter || + Die.getTag() == DW_TAG_variable || + Die.getTag() == DW_TAG_array_type)) { + error() << "DIE with tag " << TagString(Die.getTag()) + << " is missing type attribute:\n"; + dump(Die) << '\n'; + NumUnitErrors++; } } @@ -465,6 +478,18 @@ TagString(RefTag)); } } + case DW_AT_type: { + DWARFDie TypeDie = Die.getAttributeValueAsReferencedDie(DW_AT_type); + if (!TypeDie) { + ReportError("DIE has invalid type attribute"); + break; + } + if (!isType(TypeDie.getTag())) { + ReportError("DIE has " + AttributeString(Attr) + + " with incompatible tag " + TagString(TypeDie.getTag())); + break; + } + } default: break; } Index: llvm/test/tools/llvm-dwarfdump/X86/verify_debug_info.s =================================================================== --- llvm/test/tools/llvm-dwarfdump/X86/verify_debug_info.s +++ llvm/test/tools/llvm-dwarfdump/X86/verify_debug_info.s @@ -11,6 +11,24 @@ # 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_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) +# 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 with tag DW_TAG_variable is missing type attribute:{{[[: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 @@ -107,7 +125,7 @@ .byte 11 ## DW_FORM_data1 .byte 59 ## DW_AT_decl_line .byte 11 ## DW_FORM_data1 - .byte 73 ## DW_AT_type + .byte 74 ## DW_AT_type .byte 19 ## DW_FORM_ref4 .byte 0 ## EOM(1) .byte 0 ## EOM(2) @@ -152,7 +170,7 @@ .byte 1 ## DW_AT_decl_file .byte 1 ## DW_AT_decl_line ## DW_AT_prototyped - .long 83 ## DW_AT_type + .long 82 ## DW_AT_type ## DW_AT_external .byte 3 ## Abbrev [3] 0x44:0xe DW_TAG_variable .byte 2 ## DW_AT_location