Skip to content

Commit 4b92c4a

Browse files
rjmccallojhunt
authored andcommitted
Sign function pointers passed to atexit and __cxa_atexit.
Patch by Akira Hatanaka.
1 parent ac299ed commit 4b92c4a

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
@@ -4862,7 +4862,7 @@ class CodeGenFunction : public CodeGenTypeCache {
48624862
void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV,
48634863
bool PerformInit);
48644864

4865-
llvm::Function *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor,
4865+
llvm::Constant *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor,
48664866
llvm::Constant *Addr);
48674867

48684868
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
@@ -2699,14 +2699,22 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
26992699
if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee()))
27002700
fn->setDoesNotThrow();
27012701

2702+
auto &Context = CGF.CGM.getContext();
2703+
FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention(
2704+
/*IsVariadic=*/false, /*IsCXXMethod=*/false));
2705+
QualType fnType =
2706+
Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI);
2707+
llvm::Constant *dtorCallee = cast<llvm::Constant>(dtor.getCallee());
2708+
dtorCallee = CGF.CGM.getFunctionPointer(dtorCallee, fnType);
2709+
27022710
if (!addr)
27032711
// addr is null when we are trying to register a dtor annotated with
27042712
// __attribute__((destructor)) in a constructor function. Using null here is
27052713
// okay because this argument is just passed back to the destructor
27062714
// function.
27072715
addr = llvm::Constant::getNullValue(CGF.Int8PtrTy);
27082716

2709-
llvm::Value *args[] = {dtor.getCallee(), addr, handle};
2717+
llvm::Value *args[] = {dtorCallee, addr, handle};
27102718
CGF.EmitNounwindRuntimeCall(atexit, args);
27112719
}
27122720

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %clang_cc1 -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 -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 { i8*, i32, i64, i64 } { i8* bitcast (%class.Foo* (%class.Foo*)* @_ZN3FooD1Ev to i8*), i32 0, i64 0, i64 0 }, section "llvm.ptrauth", align 8
17+
// CXAATEXIT: define internal void @__cxx_global_var_init()
18+
// CXAATEXIT: call i32 @__cxa_atexit(void (i8*)* bitcast ({ i8*, i32, i64, i64 }* @_ZN3FooD1Ev.ptrauth to void (i8*)*), i8* getelementptr inbounds (%class.Foo, %class.Foo* @global, i32 0, i32 0), i8* @__dso_handle)
19+
20+
21+
// ATEXIT: @__dtor_global.ptrauth = private constant { i8*, i32, i64, i64 } { i8* bitcast (void ()* @__dtor_global to i8*), i32 0, i64 0, i64 0 }, section "llvm.ptrauth", align 8
22+
// ATEXIT: define internal void @__cxx_global_var_init()
23+
// ATEXIT: %{{.*}} = call i32 @atexit(void ()* bitcast ({ i8*, i32, i64, i64 }* @__dtor_global.ptrauth to void ()*))
24+
25+
// ATEXIT: define internal void @__dtor_global() {{.*}} section "__TEXT,__StaticInit,regular,pure_instructions" {
26+
// ATEXIT: %{{.*}} = call %class.Foo* @_ZN3FooD1Ev(%class.Foo* @global)

0 commit comments

Comments
 (0)