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
This commit is contained in:
parent
f961b61f88
commit
ff85dbdf6b
@ -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.
|
||||
@ -398,6 +406,8 @@ void splitAndWriteThinLTOBitcode(
|
||||
if (const auto *C = GV->getComdat())
|
||||
if (MergedMComdats.count(C))
|
||||
return false;
|
||||
if (MustEmitToMergedModule(GV))
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
|
19
llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll
Normal file
19
llvm/test/Transforms/ThinLTOBitcodeWriter/cfi-check.ll
Normal file
@ -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" }
|
Loading…
x
Reference in New Issue
Block a user