Skip to content

Commit 329c38e

Browse files
committed
[clang] Sign function pointers passed to atexit and __cxa_atexit.
1 parent 302135e commit 329c38e

File tree

4 files changed

+43
-4
lines changed

4 files changed

+43
-4
lines changed

clang/lib/CodeGen/CGDeclCXX.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D,
232232

233233
/// Create a stub function, suitable for being passed to atexit,
234234
/// which passes the given address to the given destructor function.
235-
llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD,
235+
llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD,
236236
llvm::FunctionCallee dtor,
237237
llvm::Constant *addr) {
238238
// Get the destructor function type, void(*)(void).
@@ -264,7 +264,12 @@ llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD,
264264

265265
CGF.FinishFunction();
266266

267-
return fn;
267+
// Get a proper function pointer.
268+
FunctionProtoType::ExtProtoInfo EPI(getContext().getDefaultCallingConvention(
269+
/*IsVariadic=*/false, /*IsCXXMethod=*/false));
270+
QualType fnType = getContext().getFunctionType(getContext().VoidTy,
271+
{getContext().VoidPtrTy}, EPI);
272+
return CGM.getFunctionPointer(fn, fnType);
268273
}
269274

270275
/// Create a stub function, suitable for being passed to __pt_atexit_np,

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4685,7 +4685,7 @@ class CodeGenFunction : public CodeGenTypeCache {
46854685
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV,
46864686
bool PerformInit);
46874687

4688-
llvm::Function *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor,
4688+
llvm::Constant *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor,
46894689
llvm::Constant *Addr);
46904690

46914691
llvm::Function *createTLSAtExitStub(const VarDecl &VD,

clang/lib/CodeGen/ItaniumCXXABI.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2845,14 +2845,22 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
28452845
if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
28462846
fn->setDoesNotThrow();
28472847

2848+
auto &Context = CGF.CGM.getContext();
2849+
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
2850+
/*IsVariadic=*/false, /*IsCXXMethod=*/false));
2851+
QualType fnType =
2852+
Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI);
2853+
llvm::Constant *dtorCallee = cast<llvm::Constant>(dtor.getCallee());
2854+
dtorCallee = CGF.CGM.getFunctionPointer(dtorCallee, fnType);
2855+
28482856
if (!addr)
28492857
// addr is null when we are trying to register a dtor annotated with
28502858
// __attribute__((destructor)) in a constructor function. Using null here is
28512859
// okay because this argument is just passed back to the destructor
28522860
// function.
28532861
addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
28542862

2855-
llvm::Value *args[] = {dtor.getCallee(), addr, handle};
2863+
llvm::Value *args[] = {dtorCallee, addr, handle};
28562864
CGF.EmitNounwindRuntimeCall(atexit, args);
28572865
}
28582866

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -emit-llvm -std=c++11 %s -o - \
2+
// RUN: | FileCheck %s --check-prefix=CXAATEXIT
3+
4+
// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -emit-llvm -std=c++11 %s -o - \
5+
// RUN: -fno-use-cxa-atexit \
6+
// RUN: | FileCheck %s --check-prefix=ATEXIT
7+
8+
class Foo {
9+
public:
10+
~Foo() {
11+
}
12+
};
13+
14+
Foo global;
15+
16+
// CXAATEXIT: @_ZN3FooD1Ev.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @_ZN3FooD1Ev, i32 0, i64 0, i64 10942 }, section "llvm.ptrauth", align 8
17+
// CXAATEXIT: define internal void @__cxx_global_var_init()
18+
// CXAATEXIT: call i32 @__cxa_atexit(ptr @_ZN3FooD1Ev.ptrauth, ptr @global, ptr @__dso_handle)
19+
20+
21+
// ATEXIT: @__dtor_global.ptrauth = private constant { ptr, i32, i64, i64 } { ptr @__dtor_global, i32 0, i64 0, i64 10942 }, section "llvm.ptrauth", align 8
22+
// ATEXIT: define internal void @__cxx_global_var_init()
23+
// ATEXIT: %{{.*}} = call i32 @atexit(ptr @__dtor_global.ptrauth)
24+
25+
// ATEXIT: define internal void @__dtor_global() {{.*}} section "__TEXT,__StaticInit,regular,pure_instructions" {
26+
// ATEXIT: %{{.*}} = call ptr @_ZN3FooD1Ev(ptr @global)

0 commit comments

Comments
 (0)