Skip to content

Commit 6133884

Browse files
committed
Implement SoftPointerAuth prototype.
1 parent 2d562c9 commit 6133884

File tree

17 files changed

+1059
-7
lines changed

17 files changed

+1059
-7
lines changed

clang/include/clang/Basic/LangOptions.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ LANGOPT(PointerAuthReturns, 1, 0, "return pointer authentication")
166166
LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps")
167167
LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated vtable pointers")
168168
LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, "incorporate type discrimination in authenticated vtable pointers")
169+
LANGOPT(SoftPointerAuth , 1, 0, "software emulation of pointer authentication")
169170
LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, "enable signed block descriptors")
170171
VALUE_LANGOPT(PointerAuthABIVersion, 32, 0, "pointer authentication ABI version")
171172
LANGOPT(PointerAuthKernelABIVersion, 1, 0, "controls whether the pointer auth abi version represents a kernel ABI")

clang/include/clang/Basic/PointerAuthOptions.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,24 @@ class PointerAuthSchema {
3939
public:
4040
enum class Kind : unsigned {
4141
None,
42+
Soft,
4243
ARM8_3,
4344
};
4445

46+
/// Software pointer-signing "keys". If you add a new key, make sure this->Key
47+
/// has a large enough bit-width.
48+
enum class SoftKey : unsigned {
49+
FunctionPointers = 0,
50+
BlockInvocationFunctionPointers = 1,
51+
BlockHelperFunctionPointers = 2,
52+
ObjCMethodListFunctionPointers = 3,
53+
CXXVTablePointers = 4,
54+
CXXVirtualFunctionPointers = 5,
55+
CXXMemberFunctionPointers = 6,
56+
ObjCMethodListPointer = 7,
57+
BlockDescriptorPointers = 8,
58+
};
59+
4560
/// Hardware pointer-signing keys in ARM8.3.
4661
///
4762
/// These values are the same used in ptrauth.h.
@@ -79,6 +94,22 @@ class PointerAuthSchema {
7994
public:
8095
PointerAuthSchema() : TheKind(Kind::None) {}
8196

97+
PointerAuthSchema(SoftKey key, bool isAddressDiscriminated,
98+
PointerAuthenticationMode authenticationMode,
99+
Discrimination otherDiscrimination,
100+
std::optional<uint16_t> constantDiscriminator = std::nullopt,
101+
bool authenticatesNullValues = false)
102+
: TheKind(Kind::Soft), IsAddressDiscriminated(isAddressDiscriminated),
103+
AuthenticatesNullValues(authenticatesNullValues),
104+
SelectedAuthenticationMode(authenticationMode),
105+
DiscriminationKind(otherDiscrimination), Key(unsigned(key)) {
106+
assert((getOtherDiscrimination() != Discrimination::Constant ||
107+
constantDiscriminator) &&
108+
"constant discrimination requires a constant!");
109+
if (constantDiscriminator)
110+
ConstantDiscriminator = *constantDiscriminator;
111+
}
112+
82113
PointerAuthSchema(ARM8_3Key key, bool isAddressDiscriminated,
83114
PointerAuthenticationMode authenticationMode,
84115
Discrimination otherDiscrimination,
@@ -95,6 +126,16 @@ class PointerAuthSchema {
95126
ConstantDiscriminator = *constantDiscriminator;
96127
}
97128

129+
PointerAuthSchema(SoftKey key, bool isAddressDiscriminated,
130+
Discrimination otherDiscrimination,
131+
std::optional<uint16_t> constantDiscriminator = std::nullopt,
132+
bool isIsaPointer = false,
133+
bool authenticatesNullValues = false)
134+
: PointerAuthSchema(key, isAddressDiscriminated,
135+
PointerAuthenticationMode::SignAndAuth,
136+
otherDiscrimination, constantDiscriminator,
137+
authenticatesNullValues) {}
138+
98139
PointerAuthSchema(ARM8_3Key key, bool isAddressDiscriminated,
99140
Discrimination otherDiscrimination,
100141
std::optional<uint16_t> constantDiscriminator = std::nullopt,
@@ -138,6 +179,8 @@ class PointerAuthSchema {
138179
switch (getKind()) {
139180
case Kind::None:
140181
llvm_unreachable("calling getKey() on disabled schema");
182+
case Kind::Soft:
183+
return unsigned(getSoftKey());
141184
case Kind::ARM8_3:
142185
return unsigned(getARM8_3Key());
143186
}
@@ -148,6 +191,11 @@ class PointerAuthSchema {
148191
return SelectedAuthenticationMode;
149192
}
150193

194+
SoftKey getSoftKey() const {
195+
assert(getKind() == Kind::Soft);
196+
return SoftKey(Key);
197+
}
198+
151199
ARM8_3Key getARM8_3Key() const {
152200
assert(getKind() == Kind::ARM8_3);
153201
return ARM8_3Key(Key);

clang/include/clang/Driver/Options.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3887,6 +3887,8 @@ let Group = f_Group in {
38873887
HelpText<"Enable address discrimination of vtable pointers">;
38883888
def fptrauth_vtable_pointer_type_discrimination : Flag<["-"], "fptrauth-vtable-pointer-type-discrimination">,
38893889
HelpText<"Enable type discrimination of vtable pointers">;
3890+
def fptrauth_soft : Flag<["-"], "fptrauth-soft">,
3891+
HelpText<"Enable software lowering of pointer authentication">;
38903892
def fptrauth_block_descriptor_pointers : Flag<["-"], "fptrauth-block-descriptor-pointers">,
38913893
HelpText<"enable signing block descriptors">;
38923894
def fptrauth_function_pointer_type_discrimination : Flag<["-"], "fptrauth-function-pointer-type-discrimination">,
@@ -3898,6 +3900,7 @@ let Group = f_Group in {
38983900
def fno_ptrauth_auth_traps : Flag<["-"], "fno-ptrauth-auth-traps">;
38993901
def fno_ptrauth_vtable_pointer_address_discrimination : Flag<["-"], "fno-ptrauth-vtable-pointer-address-discrimination">;
39003902
def fno_ptrauth_vtable_pointer_type_discrimination : Flag<["-"], "fno-ptrauth-vtable-pointer-type-discrimination">;
3903+
def fno_ptrauth_soft : Flag<["-"], "fno-ptrauth-soft">;
39013904
def fno_ptrauth_block_descriptor_pointers : Flag<["-"], "fno-ptrauth-block-descriptor-pointers">;
39023905
def fno_ptrauth_function_pointer_type_discrimination : Flag<["-"], "fno-ptrauth-function-pointer-type-discrimination">;
39033906
}

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
7373
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
7474
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
75+
#include "llvm/Transforms/Instrumentation/SoftPointerAuth.h"
7576
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
7677
#include "llvm/Transforms/ObjCARC.h"
7778
#include "llvm/Transforms/Scalar/EarlyCSE.h"
@@ -995,6 +996,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
995996
addKCFIPass(TargetTriple, LangOpts, PB);
996997
}
997998

999+
if (LangOpts.SoftPointerAuth)
1000+
PB.registerOptimizerLastEPCallback(
1001+
[](ModulePassManager &MPM, OptimizationLevel Level) {
1002+
MPM.addPass(SoftPointerAuthPass());
1003+
});
1004+
9981005
if (std::optional<GCOVOptions> Options =
9991006
getGCOVOptions(CodeGenOpts, LangOpts))
10001007
PB.registerPipelineStartEPCallback(

clang/lib/CodeGen/CGPointerAuth.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -731,12 +731,16 @@ CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *thisClass) {
731731
return std::nullopt;
732732
}
733733
if (explicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
734-
if (explicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
735-
key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA;
736-
else {
737-
assert(explicitKey ==
738-
VTablePointerAuthenticationAttr::ProcessDependent);
739-
key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB;
734+
if (Context.getLangOpts().SoftPointerAuth) {
735+
key = (unsigned)PointerAuthSchema::SoftKey::CXXVirtualFunctionPointers;
736+
} else {
737+
if (explicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
738+
key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA;
739+
else {
740+
assert(explicitKey ==
741+
VTablePointerAuthenticationAttr::ProcessDependent);
742+
key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB;
743+
}
740744
}
741745
}
742746

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7006,6 +7006,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
70067006
false))
70077007
CmdArgs.push_back("-fptrauth-vtable-pointer-type-discrimination");
70087008

7009+
if (Args.hasFlag(options::OPT_fptrauth_soft,
7010+
options::OPT_fno_ptrauth_soft, false))
7011+
CmdArgs.push_back("-fptrauth-soft");
7012+
70097013
if (Args.hasFlag(options::OPT_fptrauth_block_descriptor_pointers,
70107014
options::OPT_fno_ptrauth_block_descriptor_pointers, false))
70117015
CmdArgs.push_back("-fptrauth-block-descriptor-pointers");

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,6 +1442,51 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts,
14421442
bool CompilerInvocation::setDefaultPointerAuthOptions(
14431443
PointerAuthOptions &Opts, const LangOptions &LangOpts,
14441444
const llvm::Triple &Triple) {
1445+
if (LangOpts.SoftPointerAuth) {
1446+
if (LangOpts.PointerAuthCalls) {
1447+
using Key = PointerAuthSchema::SoftKey;
1448+
using Discrimination = PointerAuthSchema::Discrimination;
1449+
Opts.FunctionPointers =
1450+
PointerAuthSchema(Key::FunctionPointers, false,
1451+
LangOpts.FunctionPointerTypeDiscrimination
1452+
? Discrimination::Type
1453+
: Discrimination::None);
1454+
Opts.BlockInvocationFunctionPointers = PointerAuthSchema(
1455+
Key::BlockInvocationFunctionPointers, true, Discrimination::None);
1456+
Opts.BlockHelperFunctionPointers = PointerAuthSchema(
1457+
Key::BlockHelperFunctionPointers, true, Discrimination::None);
1458+
Opts.BlockByrefHelperFunctionPointers = PointerAuthSchema(
1459+
Key::BlockHelperFunctionPointers, true, Discrimination::None);
1460+
if (LangOpts.PointerAuthBlockDescriptorPointers) {
1461+
Opts.BlockDescriptorPointers = PointerAuthSchema(
1462+
Key::BlockDescriptorPointers, true, Discrimination::Constant,
1463+
BlockDescriptorConstantDiscriminator);
1464+
}
1465+
Opts.ObjCMethodListFunctionPointers = PointerAuthSchema(
1466+
Key::ObjCMethodListFunctionPointers, true, Discrimination::None);
1467+
Opts.ObjCMethodListPointer = PointerAuthSchema(
1468+
Key::ObjCMethodListPointer, true, Discrimination::Constant,
1469+
MethodListPointerConstantDiscriminator);
1470+
Opts.CXXVTablePointers = PointerAuthSchema(
1471+
Key::CXXVTablePointers,
1472+
LangOpts.PointerAuthVTPtrAddressDiscrimination,
1473+
LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
1474+
: Discrimination::None);
1475+
Opts.CXXTypeInfoVTablePointer = PointerAuthSchema(
1476+
Key::CXXVTablePointers, false, Discrimination::None);
1477+
Opts.CXXVTTVTablePointers = PointerAuthSchema(
1478+
Key::CXXVTablePointers, false, Discrimination::None);
1479+
Opts.CXXVirtualFunctionPointers =
1480+
Opts.CXXVirtualVariadicFunctionPointers = PointerAuthSchema(
1481+
Key::CXXVirtualFunctionPointers, true, Discrimination::Decl);
1482+
Opts.CXXMemberFunctionPointers = PointerAuthSchema(
1483+
Key::CXXMemberFunctionPointers, false, Discrimination::Type);
1484+
}
1485+
Opts.ReturnAddresses = LangOpts.PointerAuthReturns;
1486+
Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;
1487+
return true;
1488+
}
1489+
14451490
if (Triple.getArch() == llvm::Triple::aarch64) {
14461491
if (LangOpts.PointerAuthCalls) {
14471492
using Key = PointerAuthSchema::ARM8_3Key;
@@ -3346,6 +3391,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
33463391
GenerateArg(Consumer, OPT_fptrauth_vtable_pointer_type_discrimination);
33473392
if (Opts.FunctionPointerTypeDiscrimination)
33483393
GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
3394+
if (Opts.SoftPointerAuth)
3395+
GenerateArg(Consumer, OPT_fptrauth_soft);
33493396
if (Opts.PointerAuthBlockDescriptorPointers)
33503397
GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
33513398

@@ -3367,6 +3414,7 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
33673414
Args.hasArg(OPT_fptrauth_vtable_pointer_address_discrimination);
33683415
Opts.PointerAuthVTPtrTypeDiscrimination =
33693416
Args.hasArg(OPT_fptrauth_vtable_pointer_type_discrimination);
3417+
Opts.SoftPointerAuth = Args.hasArg(OPT_fptrauth_soft);
33703418
Opts.PointerAuthBlockDescriptorPointers =
33713419
Args.hasArg(OPT_fptrauth_block_descriptor_pointers);
33723420

clang/test/Driver/arch-arm64e.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
// NONE-NOT: "-fptrauth-calls"
77
// NONE-NOT: "-fptrauth-returns"
88
// NONE-NOT: "-fptrauth-auth-traps"
9+
// NONE-NOT: "-fptrauth-soft"
910

1011
// RUN: %clang -target arm64-apple-ios -fptrauth-calls -c %s -### 2>&1 | FileCheck %s --check-prefix CALL
1112
// CALL: "-cc1"{{.*}} {{.*}} "-fptrauth-calls"
@@ -19,6 +20,9 @@
1920
// RUN: %clang -target arm64-apple-ios -fptrauth-auth-traps -c %s -### 2>&1 | FileCheck %s --check-prefix TRAPS
2021
// TRAPS: "-cc1"{{.*}} {{.*}} "-fptrauth-auth-traps"
2122

23+
// RUN: %clang -target arm64-apple-ios -fptrauth-soft -c %s -### 2>&1 | FileCheck %s --check-prefix SOFT
24+
// SOFT: "-cc1"{{.*}} {{.*}} "-fptrauth-soft"
25+
2226

2327
// Check the arm64e defaults.
2428

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ void initializeSingleLoopExtractorPass(PassRegistry&);
305305
void initializeSinkingLegacyPassPass(PassRegistry&);
306306
void initializeSjLjEHPreparePass(PassRegistry&);
307307
void initializeSlotIndexesPass(PassRegistry&);
308+
void initializeSoftPointerAuthLegacyPassPass(PassRegistry&);
308309
void initializeSpeculativeExecutionLegacyPassPass(PassRegistry&);
309310
void initializeSpillPlacementPass(PassRegistry&);
310311
void initializeStackColoringPass(PassRegistry&);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//===- SoftPointerAuth.h - Software lowering of ptrauth intrins -*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_SOFTPOINTERAUTH_H
10+
#define LLVM_TRANSFORMS_INSTRUMENTATION_SOFTPOINTERAUTH_H
11+
12+
#include "llvm/IR/PassManager.h"
13+
14+
namespace llvm {
15+
16+
struct SoftPointerAuthPass : public PassInfoMixin<SoftPointerAuthPass> {
17+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
18+
};
19+
20+
} // end namespace llvm
21+
22+
#endif // LLVM_TRANSFORMS_INSTRUMENTATION_SOFTPOINTERAUTH_H

0 commit comments

Comments
 (0)