https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/154859
Backport ff85dbdf6b399eac7bffa13e579f0f5e6edac3c0 Requested by: @efriedma-quic >From e887b28b9705a9a2b3c9af30ea0e5aba01f3b598 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <pe...@pcc.me.uk> Date: Thu, 21 Aug 2025 16:31:32 -0700 Subject: [PATCH] ThinLTOBitcodeWriter: Emit __cfi_check to full LTO part of bitcode file. The CrossDSOCFI pass runs on the full LTO module and fills in the body of __cfi_check. This function must have the correct attributes in order to be compatible with the rest of the program. For example, when building with -mbranch-protection=standard, the function must have the branch-target-enforcement attribute, which is normally added by Clang. When __cfi_check is missing, CrossDSOCFI will give it the default set of attributes, which are likely incorrect. Therefore, emit __cfi_check to the full LTO part, where CrossDSOCFI will see it. Reviewers: efriedma-quic, vitalybuka, fmayer Reviewed By: efriedma-quic Pull Request: https://github.com/llvm/llvm-project/pull/154833 (cherry picked from commit ff85dbdf6b399eac7bffa13e579f0f5e6edac3c0) --- .../Transforms/IPO/ThinLTOBitcodeWriter.cpp | 12 +++++++++++- .../ThinLTOBitcodeWriter/cfi-check.ll | 19 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll diff --git a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index e276376f21583..0d631734ca968 100644 --- a/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -350,12 +350,20 @@ void splitAndWriteThinLTOBitcode( }); } + auto MustEmitToMergedModule = [](const GlobalValue *GV) { + // The __cfi_check definition is filled in by the CrossDSOCFI pass which + // runs only in the merged module. + return GV->getName() == "__cfi_check"; + }; + ValueToValueMapTy VMap; std::unique_ptr<Module> MergedM( CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool { if (const auto *C = GV->getComdat()) if (MergedMComdats.count(C)) return true; + if (MustEmitToMergedModule(GV)) + return true; if (auto *F = dyn_cast<Function>(GV)) return EligibleVirtualFns.count(F); if (auto *GVar = @@ -372,7 +380,7 @@ void splitAndWriteThinLTOBitcode( cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ true); for (Function &F : *MergedM) - if (!F.isDeclaration()) { + if (!F.isDeclaration() && !MustEmitToMergedModule(&F)) { // Reset the linkage of all functions eligible for virtual constant // propagation. The canonical definitions live in the thin LTO module so // that they can be imported. @@ -394,6 +402,8 @@ void splitAndWriteThinLTOBitcode( if (const auto *C = GV->getComdat()) if (MergedMComdats.count(C)) return false; + if (MustEmitToMergedModule(GV)) + return false; return true; }); diff --git a/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll new file mode 100644 index 0000000000000..b927af6b92f7c --- /dev/null +++ b/llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll @@ -0,0 +1,19 @@ +; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s +; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s +; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s + +; Check that __cfi_check is emitted on the full LTO side with +; attributes preserved. + +; M0: define void @f() +define void @f() !type !{!"f1", i32 0} { + ret void +} + +; M1: define void @__cfi_check() #0 +define void @__cfi_check() #0 { + ret void +} + +; M1: attributes #0 = { "branch-target-enforcement" } +attributes #0 = { "branch-target-enforcement" } _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits