Skip to content

Commit 1a8030e

Browse files
committed
[cfi] Emit __cfi_check stub in the frontend.
Previously __cfi_check was created in LTO optimization pipeline, which means LLD has no way of knowing about the existence of this symbol without rescanning the LTO output object. As a result, LLD fails to export __cfi_check, even when given --export-dynamic-symbol flag. llvm-svn: 299806
1 parent 349adba commit 1a8030e

File tree

4 files changed

+29
-1
lines changed

4 files changed

+29
-1
lines changed

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,6 +2783,24 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
27832783
EmitBlock(Cont);
27842784
}
27852785

2786+
// Emit a stub for __cfi_check function so that the linker knows about this
2787+
// symbol in LTO mode.
2788+
void CodeGenFunction::EmitCfiCheckStub() {
2789+
llvm::Module *M = &CGM.getModule();
2790+
auto &Ctx = M->getContext();
2791+
llvm::Function *F = llvm::Function::Create(
2792+
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false),
2793+
llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M);
2794+
llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F);
2795+
// FIXME: consider emitting an intrinsic call like
2796+
// call void @llvm.cfi_check(i64 %0, i8* %1, i8* %2)
2797+
// which can be lowered in CrossDSOCFI pass to the actual contents of
2798+
// __cfi_check. This would allow inlining of __cfi_check calls.
2799+
llvm::CallInst::Create(
2800+
llvm::Intrinsic::getDeclaration(M, llvm::Intrinsic::trap), "", BB);
2801+
llvm::ReturnInst::Create(Ctx, nullptr, BB);
2802+
}
2803+
27862804
// This function is basically a switch over the CFI failure kind, which is
27872805
// extracted from CFICheckFailData (1st function argument). Each case is either
27882806
// llvm.trap or a call to one of the two runtime handlers, based on

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3524,6 +3524,9 @@ class CodeGenFunction : public CodeGenTypeCache {
35243524
/// "trap-func-name" if specified.
35253525
llvm::CallInst *EmitTrapCall(llvm::Intrinsic::ID IntrID);
35263526

3527+
/// \brief Emit a stub for the cross-DSO CFI check function.
3528+
void EmitCfiCheckStub();
3529+
35273530
/// \brief Emit a cross-DSO CFI failure handling function.
35283531
void EmitCfiCheckFail();
35293532

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,10 @@ void CodeGenModule::Release() {
406406
EmitDeferredUnusedCoverageMappings();
407407
if (CoverageMapping)
408408
CoverageMapping->emit();
409-
if (CodeGenOpts.SanitizeCfiCrossDso)
409+
if (CodeGenOpts.SanitizeCfiCrossDso) {
410410
CodeGenFunction(*this).EmitCfiCheckFail();
411+
CodeGenFunction(*this).EmitCfiCheckStub();
412+
}
411413
emitAtAvailableLinkGuard();
412414
emitLLVMUsed();
413415
if (SanStats)

clang/test/CodeGen/cfi-check-fail.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,8 @@ void caller(void (*f)()) {
7272

7373
// CHECK: [[CONT5]]:
7474
// CHECK: ret void
75+
76+
// CHECK: define weak void @__cfi_check(i64, i8*, i8*)
77+
// CHECK-NOT: }
78+
// CHECK: call void @llvm.trap()
79+
// CHECK-NEXT: ret void

0 commit comments

Comments
 (0)