Skip to content

Commit 562605c

Browse files
pcctru
authored andcommitted
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: #154833 (cherry picked from commit ff85dbd)
1 parent 33e18ac commit 562605c

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,12 +350,20 @@ void splitAndWriteThinLTOBitcode(
350350
});
351351
}
352352

353+
auto MustEmitToMergedModule = [](const GlobalValue *GV) {
354+
// The __cfi_check definition is filled in by the CrossDSOCFI pass which
355+
// runs only in the merged module.
356+
return GV->getName() == "__cfi_check";
357+
};
358+
353359
ValueToValueMapTy VMap;
354360
std::unique_ptr<Module> MergedM(
355361
CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool {
356362
if (const auto *C = GV->getComdat())
357363
if (MergedMComdats.count(C))
358364
return true;
365+
if (MustEmitToMergedModule(GV))
366+
return true;
359367
if (auto *F = dyn_cast<Function>(GV))
360368
return EligibleVirtualFns.count(F);
361369
if (auto *GVar =
@@ -372,7 +380,7 @@ void splitAndWriteThinLTOBitcode(
372380
cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ true);
373381

374382
for (Function &F : *MergedM)
375-
if (!F.isDeclaration()) {
383+
if (!F.isDeclaration() && !MustEmitToMergedModule(&F)) {
376384
// Reset the linkage of all functions eligible for virtual constant
377385
// propagation. The canonical definitions live in the thin LTO module so
378386
// that they can be imported.
@@ -394,6 +402,8 @@ void splitAndWriteThinLTOBitcode(
394402
if (const auto *C = GV->getComdat())
395403
if (MergedMComdats.count(C))
396404
return false;
405+
if (MustEmitToMergedModule(GV))
406+
return false;
397407
return true;
398408
});
399409

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
2+
; RUN: llvm-modextract -b -n 0 -o - %t | llvm-dis | FileCheck --check-prefix=M0 %s
3+
; RUN: llvm-modextract -b -n 1 -o - %t | llvm-dis | FileCheck --check-prefix=M1 %s
4+
5+
; Check that __cfi_check is emitted on the full LTO side with
6+
; attributes preserved.
7+
8+
; M0: define void @f()
9+
define void @f() !type !{!"f1", i32 0} {
10+
ret void
11+
}
12+
13+
; M1: define void @__cfi_check() #0
14+
define void @__cfi_check() #0 {
15+
ret void
16+
}
17+
18+
; M1: attributes #0 = { "branch-target-enforcement" }
19+
attributes #0 = { "branch-target-enforcement" }

0 commit comments

Comments
 (0)