https://github.com/ojhunt updated https://github.com/llvm/llvm-project/pull/98276
>From 4b92c4af87a1a381dad09b243db4d3ec71d64738 Mon Sep 17 00:00:00 2001 From: John McCall <rjmcc...@apple.com> Date: Wed, 18 Sep 2019 02:21:37 -0400 Subject: [PATCH 1/5] Sign function pointers passed to atexit and __cxa_atexit. Patch by Akira Hatanaka. --- clang/lib/CodeGen/CGDeclCXX.cpp | 9 +++++-- clang/lib/CodeGen/CodeGenFunction.h | 2 +- clang/lib/CodeGen/ItaniumCXXABI.cpp | 10 ++++++- .../CodeGenCXX/ptrauth-static-destructors.cpp | 26 +++++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGenCXX/ptrauth-static-destructors.cpp diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 05dd7ddb86fa6..36248a9c75188 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -232,7 +232,7 @@ void CodeGenFunction::EmitCXXGlobalVarDeclInit(const VarDecl &D, /// Create a stub function, suitable for being passed to atexit, /// which passes the given address to the given destructor function. -llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD, +llvm::Constant *CodeGenFunction::createAtExitStub(const VarDecl &VD, llvm::FunctionCallee dtor, llvm::Constant *addr) { // Get the destructor function type, void(*)(void). @@ -264,7 +264,12 @@ llvm::Function *CodeGenFunction::createAtExitStub(const VarDecl &VD, CGF.FinishFunction(); - return fn; + // Get a proper function pointer. + FunctionProtoType::ExtProtoInfo EPI(getContext().getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/false)); + QualType fnType = getContext().getFunctionType(getContext().VoidTy, + {getContext().VoidPtrTy}, EPI); + return CGM.getFunctionPointer(fn, fnType); } /// Create a stub function, suitable for being passed to __pt_atexit_np, diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 13f12b5d878a6..e33267c4787fd 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4862,7 +4862,7 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitCXXGlobalVarDeclInit(const VarDecl &D, llvm::GlobalVariable *GV, bool PerformInit); - llvm::Function *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, + llvm::Constant *createAtExitStub(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr); llvm::Function *createTLSAtExitStub(const VarDecl &VD, diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index e1d056765a866..1924c07c1529d 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -2699,6 +2699,14 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee())) fn->setDoesNotThrow(); + auto &Context = CGF.CGM.getContext(); + FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( + /*IsVariadic=*/false, /*IsCXXMethod=*/false)); + QualType fnType = + Context.getFunctionType(Context.VoidTy, {Context.VoidPtrTy}, EPI); + llvm::Constant *dtorCallee = cast<llvm::Constant>(dtor.getCallee()); + dtorCallee = CGF.CGM.getFunctionPointer(dtorCallee, fnType); + if (!addr) // addr is null when we are trying to register a dtor annotated with // __attribute__((destructor)) in a constructor function. Using null here is @@ -2706,7 +2714,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, // function. addr = llvm::Constant::getNullValue(CGF.Int8PtrTy); - llvm::Value *args[] = {dtor.getCallee(), addr, handle}; + llvm::Value *args[] = {dtorCallee, addr, handle}; CGF.EmitNounwindRuntimeCall(atexit, args); } diff --git a/clang/test/CodeGenCXX/ptrauth-static-destructors.cpp b/clang/test/CodeGenCXX/ptrauth-static-destructors.cpp new file mode 100644 index 0000000000000..6c8d0c560681a --- /dev/null +++ b/clang/test/CodeGenCXX/ptrauth-static-destructors.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -emit-llvm -std=c++11 %s -o - \ +// RUN: | FileCheck %s --check-prefix=CXAATEXIT + +// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -emit-llvm -std=c++11 %s -o - \ +// RUN: -fno-use-cxa-atexit \ +// RUN: | FileCheck %s --check-prefix=ATEXIT + +class Foo { + public: + ~Foo() { + } +}; + +Foo global; + +// 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 +// CXAATEXIT: define internal void @__cxx_global_var_init() +// 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) + + +// 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 +// ATEXIT: define internal void @__cxx_global_var_init() +// ATEXIT: %{{.*}} = call i32 @atexit(void ()* bitcast ({ i8*, i32, i64, i64 }* @__dtor_global.ptrauth to void ()*)) + +// ATEXIT: define internal void @__dtor_global() {{.*}} section "__TEXT,__StaticInit,regular,pure_instructions" { +// ATEXIT: %{{.*}} = call %class.Foo* @_ZN3FooD1Ev(%class.Foo* @global) >From b00d0b2f361a5537efaba68fbac7cfa8f682581e Mon Sep 17 00:00:00 2001 From: Oliver Hunt <oli...@apple.com> Date: Tue, 9 Jul 2024 23:22:07 -0700 Subject: [PATCH 2/5] Fix build and tests for upstream --- clang/lib/CodeGen/CGDeclCXX.cpp | 3 ++- clang/lib/CodeGen/ItaniumCXXABI.cpp | 3 ++- clang/test/CodeGenCXX/ptrauth-static-destructors.cpp | 8 +++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 36248a9c75188..2f56355cff90e 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -338,7 +338,8 @@ void CodeGenFunction::registerGlobalDtorWithLLVM(const VarDecl &VD, llvm::FunctionCallee Dtor, llvm::Constant *Addr) { // Create a function which calls the destructor. - llvm::Function *dtorStub = createAtExitStub(VD, Dtor, Addr); + llvm::Function *dtorStub = + cast<llvm::Function>(createAtExitStub(VD, Dtor, Addr)); CGM.AddGlobalDtor(dtorStub); } diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 1924c07c1529d..21023f60e19de 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -4915,7 +4915,8 @@ void XLCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D, } // Create __dtor function for the var decl. - llvm::Function *DtorStub = CGF.createAtExitStub(D, Dtor, Addr); + llvm::Function *DtorStub = + cast<llvm::Function>(CGF.createAtExitStub(D, Dtor, Addr)); // Register above __dtor with atexit(). CGF.registerGlobalDtorWithAtExit(DtorStub); diff --git a/clang/test/CodeGenCXX/ptrauth-static-destructors.cpp b/clang/test/CodeGenCXX/ptrauth-static-destructors.cpp index 6c8d0c560681a..cad43dc0746df 100644 --- a/clang/test/CodeGenCXX/ptrauth-static-destructors.cpp +++ b/clang/test/CodeGenCXX/ptrauth-static-destructors.cpp @@ -13,14 +13,12 @@ class Foo { Foo global; -// 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 // CXAATEXIT: define internal void @__cxx_global_var_init() -// 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) +// CXAATEXIT: call i32 @__cxa_atexit(ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0), ptr @global, ptr @__dso_handle) -// 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 // ATEXIT: define internal void @__cxx_global_var_init() -// ATEXIT: %{{.*}} = call i32 @atexit(void ()* bitcast ({ i8*, i32, i64, i64 }* @__dtor_global.ptrauth to void ()*)) +// ATEXIT: %{{.*}} = call i32 @atexit(ptr ptrauth (ptr @__dtor_global, i32 0)) // ATEXIT: define internal void @__dtor_global() {{.*}} section "__TEXT,__StaticInit,regular,pure_instructions" { -// ATEXIT: %{{.*}} = call %class.Foo* @_ZN3FooD1Ev(%class.Foo* @global) +// ATEXIT: %{{.*}} = call ptr @_ZN3FooD1Ev(ptr @global) >From b0d4bda0956e3baf23e3c0bc9db0f14dfb5c7156 Mon Sep 17 00:00:00 2001 From: Ahmed Bougacha <ah...@bougacha.org> Date: Mon, 27 Sep 2021 08:00:00 -0700 Subject: [PATCH 3/5] [clang] Sign the dtor passed to __cxa_throw as a void(*)(void*) fptr. __cxa_throw is declared to take its destructor as void (*)(void *). We must match that if function pointers can be authenticated with a discriminator based on their type. --- clang/lib/CodeGen/ItaniumCXXABI.cpp | 8 ++++++++ clang/test/CodeGenCXX/ptrauth-throw.cpp | 20 ++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 clang/test/CodeGenCXX/ptrauth-throw.cpp diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 21023f60e19de..489051e95953e 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1321,8 +1321,16 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); if (!Record->hasTrivialDestructor()) { + // __cxa_throw is declared to take its destructor as void (*)(void *). We + // must match that if function pointers can be authenticated with a + // discriminator based on their type. + ASTContext &Ctx = getContext(); + QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy}, + FunctionProtoType::ExtProtoInfo()); + CXXDestructorDecl *DtorD = Record->getDestructor(); Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete)); + Dtor = CGM.getFunctionPointer(Dtor, DtorTy); } } if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy); diff --git a/clang/test/CodeGenCXX/ptrauth-throw.cpp b/clang/test/CodeGenCXX/ptrauth-throw.cpp new file mode 100644 index 0000000000000..0e143433ee5a3 --- /dev/null +++ b/clang/test/CodeGenCXX/ptrauth-throw.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s + +class Foo { + public: + ~Foo() { + } +}; + +// CHECK-LABEL: define void @_Z1fv() +// CHECK: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTI3Foo, ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0)) +void f() { + throw Foo(); +} + +// __cxa_throw is defined to take its destructor as "void (*)(void *)" in the ABI. +// CHECK-LABEL: define void @__cxa_throw({{.*}}) +// CHECK: call void {{%.*}}(ptr noundef {{%.*}}) [ "ptrauth"(i32 0, i64 0) ] +extern "C" void __cxa_throw(void *exception, void *, void (*dtor)(void *)) { + dtor(exception); +} >From f116be80e35b6e82938a1dae994542d17b768ccf Mon Sep 17 00:00:00 2001 From: Oliver Hunt <oli...@apple.com> Date: Sun, 14 Jul 2024 15:20:22 -0700 Subject: [PATCH 4/5] Update test to include test for type discriminated function pointers --- clang/test/CodeGenCXX/ptrauth-throw.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGenCXX/ptrauth-throw.cpp b/clang/test/CodeGenCXX/ptrauth-throw.cpp index 0e143433ee5a3..cea7226547e5a 100644 --- a/clang/test/CodeGenCXX/ptrauth-throw.cpp +++ b/clang/test/CodeGenCXX/ptrauth-throw.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios -fptrauth-calls -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK +// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECKDISC class Foo { public: @@ -8,13 +9,21 @@ class Foo { // CHECK-LABEL: define void @_Z1fv() // CHECK: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTI3Foo, ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0)) + +// CHECKDISC-LABEL: define void @_Z1fv() +// CHECKDISC: call void @__cxa_throw(ptr %{{.*}}, ptr @_ZTI3Foo, ptr ptrauth (ptr @_ZN3FooD1Ev, i32 0, i64 10942)) + void f() { throw Foo(); } // __cxa_throw is defined to take its destructor as "void (*)(void *)" in the ABI. // CHECK-LABEL: define void @__cxa_throw({{.*}}) -// CHECK: call void {{%.*}}(ptr noundef {{%.*}}) [ "ptrauth"(i32 0, i64 0) ] +// CHECK: call void {{%.*}}(ptr noundef {{%.*}}) [ "ptrauth"(i32 0, i64 0) ] + +// CHECKDISC-LABEL: define void @__cxa_throw({{.*}}) +// CHECKDISC: call void {{%.*}}(ptr noundef {{%.*}}) [ "ptrauth"(i32 0, i64 10942) ] + extern "C" void __cxa_throw(void *exception, void *, void (*dtor)(void *)) { dtor(exception); } >From e9219d6397567eb19e67b61e86e17f852592a9b8 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <oli...@apple.com> Date: Tue, 16 Jul 2024 15:21:33 -0700 Subject: [PATCH 5/5] Address style comments --- clang/lib/CodeGen/ItaniumCXXABI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 489051e95953e..37b436a21fbc0 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1324,7 +1324,7 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { // __cxa_throw is declared to take its destructor as void (*)(void *). We // must match that if function pointers can be authenticated with a // discriminator based on their type. - ASTContext &Ctx = getContext(); + const ASTContext &Ctx = getContext(); QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy}, FunctionProtoType::ExtProtoInfo()); @@ -2707,7 +2707,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF, if (llvm::Function *fn = dyn_cast<llvm::Function>(atexit.getCallee())) fn->setDoesNotThrow(); - auto &Context = CGF.CGM.getContext(); + const auto &Context = CGF.CGM.getContext(); FunctionProtoType::ExtProtoInfo EPI(Context.getDefaultCallingConvention( /*IsVariadic=*/false, /*IsCXXMethod=*/false)); QualType fnType = _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits