[DebugInfo][IR] Verifier checks for the extraData (#167971)

LLVM IR verifier checks for `extraData` in debug info metadata. 

This is a follow-up PR based on discussions in #165023
This commit is contained in:
Laxman Sole 2025-11-18 11:33:40 -08:00 committed by GitHub
parent ac6e48de40
commit 58b8e6e424
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 80 additions and 0 deletions

View File

@ -1158,6 +1158,7 @@ void Verifier::visitMetadataAsValue(const MetadataAsValue &MDV, Function *F) {
static bool isType(const Metadata *MD) { return !MD || isa<DIType>(MD); }
static bool isScope(const Metadata *MD) { return !MD || isa<DIScope>(MD); }
static bool isDINode(const Metadata *MD) { return !MD || isa<DINode>(MD); }
static bool isMDTuple(const Metadata *MD) { return !MD || isa<MDTuple>(MD); }
void Verifier::visitDILocation(const DILocation &N) {
CheckDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),
@ -1320,6 +1321,30 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) {
if (N.getTag() == dwarf::DW_TAG_ptr_to_member_type) {
CheckDI(isType(N.getRawExtraData()), "invalid pointer to member type", &N,
N.getRawExtraData());
} else if (N.getTag() == dwarf::DW_TAG_template_alias) {
CheckDI(isMDTuple(N.getRawExtraData()), "invalid template parameters", &N,
N.getRawExtraData());
} else if (N.getTag() == dwarf::DW_TAG_inheritance ||
N.getTag() == dwarf::DW_TAG_member ||
N.getTag() == dwarf::DW_TAG_variable) {
auto *ExtraData = N.getRawExtraData();
auto IsValidExtraData = [&]() {
if (ExtraData == nullptr)
return true;
if (isa<ConstantAsMetadata>(ExtraData) || isa<MDString>(ExtraData) ||
isa<DIObjCProperty>(ExtraData))
return true;
if (auto *Tuple = dyn_cast<MDTuple>(ExtraData)) {
if (Tuple->getNumOperands() != 1)
return false;
return isa_and_nonnull<ConstantAsMetadata>(Tuple->getOperand(0).get());
}
return false;
};
CheckDI(IsValidExtraData(),
"extraData must be ConstantAsMetadata, MDString, DIObjCProperty, "
"or MDTuple with single ConstantAsMetadata operand",
&N, ExtraData);
}
if (N.getTag() == dwarf::DW_TAG_set_type) {

View File

@ -0,0 +1,55 @@
; RUN: not opt -S < %s 2>&1 | FileCheck %s
;; Test that extraData with MDTuple is only allowed for specific DWARF tags:
;; DW_TAG_inheritance, DW_TAG_member, and DW_TAG_variable
!llvm.module.flags = !{!0}
!0 = !{i32 2, !"Debug Info Version", i32 3}
!1 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
; Keep all metadata nodes alive so verifier can check them
!named = !{!1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16}
!2 = !{i32 0}
; Valid: DW_TAG_inheritance with tuple extraData should be accepted
!3 = !DIDerivedType(tag: DW_TAG_inheritance, baseType: !1, size: 32, extraData: !2)
; Valid: DW_TAG_member with tuple extraData should be accepted
!4 = !DIDerivedType(tag: DW_TAG_member, name: "field", baseType: !1, size: 32, extraData: !2)
; Valid: DW_TAG_variable (static member) with tuple extraData should be accepted
!5 = !DIDerivedType(tag: DW_TAG_variable, name: "var", baseType: !1, extraData: !2, flags: DIFlagStaticMember)
; Invalid: Empty tuple should be rejected
!6 = !{}
; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
!7 = !DIDerivedType(tag: DW_TAG_member, name: "field2", baseType: !1, extraData: !6)
; Invalid: Tuple with multiple operands should be rejected
!8 = !{i32 0, i32 1}
; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
!9 = !DIDerivedType(tag: DW_TAG_member, name: "field3", baseType: !1, extraData: !8)
; Invalid: Tuple with non-ConstantAsMetadata operand should be rejected
!10 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float)
!11 = !{!10}
; CHECK: extraData must be ConstantAsMetadata, MDString, DIObjCProperty, or MDTuple with single ConstantAsMetadata operand
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_member
!12 = !DIDerivedType(tag: DW_TAG_member, name: "field4", baseType: !1, extraData: !11)
; Valid: DW_TAG_template_alias with proper template parameters tuple
; Template aliases are handled specially and accept any MDTuple for template parameters
!13 = !DITemplateTypeParameter(name: "T", type: !1)
!14 = !{!13}
!15 = !DIDerivedType(tag: DW_TAG_template_alias, name: "MyAlias", baseType: !1, extraData: !14)
; Invalid: DW_TAG_template_alias with non-tuple extraData should fail
; CHECK: invalid template parameters
; CHECK-NEXT: !{{[0-9]+}} = !DIDerivedType(tag: DW_TAG_template_alias
!16 = !DIDerivedType(tag: DW_TAG_template_alias, name: "FailingAlias", baseType: !1, extraData: i32 42)
; CHECK: warning: ignoring invalid debug info