diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 44906456f3371..3ec74ce0e46e1 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2028,7 +2028,8 @@ static void handleStandardNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &A) { } static void handleNoCfCheckAttr(Sema &S, Decl *D, const ParsedAttr &Attrs) { - if (!S.getLangOpts().CFProtectionBranch) + if (!S.getLangOpts().CFProtectionBranch && + !S.getLangOpts().Sanitize.has(SanitizerKind::KCFI)) S.Diag(Attrs.getLoc(), diag::warn_nocf_check_attribute_ignored); else handleSimpleAttribute(S, D, Attrs); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 0f655d7f684a5..12384aadc1cad 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -7936,7 +7936,8 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, } if (attr.getKind() == ParsedAttr::AT_AnyX86NoCfCheck) { - if (!S.getLangOpts().CFProtectionBranch) { + if (!S.getLangOpts().CFProtectionBranch && + !S.getLangOpts().Sanitize.has(SanitizerKind::KCFI)) { S.Diag(attr.getLoc(), diag::warn_nocf_check_attribute_ignored); attr.setInvalid(); return true; diff --git a/clang/test/Sema/attr-nocf_check.c b/clang/test/Sema/attr-nocf_check.c index 59ec85ed2629b..1262b87928089 100644 --- a/clang/test/Sema/attr-nocf_check.c +++ b/clang/test/Sema/attr-nocf_check.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -triple=x86_64-unknown-unknown -verify -fcf-protection=branch -fsyntax-only %s +// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -verify -fsanitize=kcfi -fsyntax-only %s // Function pointer definition. typedef void (*FuncPointerWithNoCfCheck)(void) __attribute__((nocf_check)); // no-warning diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index ff22ee8c86fac..486bf3986cf5a 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -170,8 +170,9 @@ void X86AsmPrinter::emitKCFITypeId(const MachineFunction &MF) { Type = mdconst::extract(MD->getOperand(0)); // If we don't have a type to emit, just emit padding if needed to maintain - // the same alignment for all functions. - if (!Type) { + // the same alignment for all functions. Also skip `nocf_check` functions as + // they are not indirectly callable due to a missing ENDBR. + if (!Type || F.doesNoCfCheck()) { EmitKCFITypePadding(MF, /*HasType=*/false); return; } diff --git a/llvm/test/CodeGen/X86/kcfi-nocf-check.ll b/llvm/test/CodeGen/X86/kcfi-nocf-check.ll new file mode 100644 index 0000000000000..1ce886c1587f8 --- /dev/null +++ b/llvm/test/CodeGen/X86/kcfi-nocf-check.ll @@ -0,0 +1,39 @@ +; RUN: llc -mtriple=x86_64-unknown-unknown -x86-indirect-branch-tracking < %s | FileCheck %s + +; CHECK-LABEL: __cfi_cf_check_func: +; CHECK: movl $12345678, %eax +define void @cf_check_func() !kcfi_type !2 { +; CHECK-LABEL: cf_check_func: +; CHECK: endbr64 +; CHECK: retq +entry: + ret void +} + +; CHECK-NOT: __cfi_notype_cf_check_func: +; CHECK-NOT: movl +define void @notype_cf_check_func() { +; CHECK-LABEL: notype_cf_check_func: +; CHECK: endbr64 +; CHECK: retq +entry: + ret void +} + +; CHECK-NOT: __cfi_nocf_check_func: +; CHECK-NOT: movl +define void @nocf_check_func() #0 !kcfi_type !2 { +; CHECK-LABEL: nocf_check_func: +; CHECK-NOT: endbr64 +; CHECK: retq +entry: + ret void +} + +attributes #0 = { nocf_check } + +!llvm.module.flags = !{!0, !1} + +!0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 4, !"kcfi", i32 1} +!2 = !{i32 12345678}