Skip to content

Commit 62f16ef

Browse files
ahmedbougachadtapuska
authored andcommitted
Implement SoftPointerAuth prototype. (deprecated)
1 parent 1fac945 commit 62f16ef

File tree

16 files changed

+1080
-6
lines changed

16 files changed

+1080
-6
lines changed

clang/include/clang/Basic/LangOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ VALUE_LANGOPT(PointerAuthABIVersion, 32, 0, "pointer authentication ABI version"
188188
LANGOPT(PointerAuthKernelABIVersion, 1, 0, "controls whether the pointer auth abi version represents a kernel ABI")
189189
LANGOPT(PointerAuthABIVersionEncoded, 1, 0, "controls whether the pointer auth abi version should be encoded in the IR")
190190

191+
LANGOPT(SoftPointerAuth , 1, 0, "software emulation of pointer authentication")
192+
191193
LANGOPT(DoubleSquareBracketAttributes, 1, 0, "'[[]]' attributes extension for all language standard modes")
192194
LANGOPT(ExperimentalLateParseAttributes, 1, 0, "experimental late parsing of attributes")
193195

clang/include/clang/Basic/PointerAuthOptions.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,25 @@ class PointerAuthSchema {
5454
public:
5555
enum class Kind : unsigned {
5656
None,
57+
Soft,
5758
ARM8_3,
5859
};
5960

61+
/// Software pointer-signing "keys". If you add a new key, make sure this->Key
62+
/// has a large enough bit-width.
63+
enum class SoftKey : unsigned {
64+
FunctionPointers = 0,
65+
BlockInvocationFunctionPointers = 1,
66+
BlockHelperFunctionPointers = 2,
67+
ObjCMethodListFunctionPointers = 3,
68+
CXXVTablePointers = 4,
69+
CXXVirtualFunctionPointers = 5,
70+
CXXMemberFunctionPointers = 6,
71+
ObjCMethodListPointer = 7,
72+
ObjCIsaPointer = 8,
73+
BlockDescriptorPointers = 9,
74+
};
75+
6076
/// Hardware pointer-signing keys in ARM8.3.
6177
///
6278
/// These values are the same used in ptrauth.h.
@@ -113,6 +129,24 @@ class PointerAuthSchema {
113129
ConstantDiscriminator = *ConstantDiscriminatorOrNone;
114130
}
115131

132+
PointerAuthSchema(
133+
SoftKey Key, bool IsAddressDiscriminated,
134+
PointerAuthenticationMode AuthenticationMode,
135+
Discrimination OtherDiscrimination,
136+
std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
137+
bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
138+
: TheKind(Kind::Soft), IsAddressDiscriminated(IsAddressDiscriminated),
139+
IsIsaPointer(IsIsaPointer),
140+
AuthenticatesNullValues(AuthenticatesNullValues),
141+
SelectedAuthenticationMode(AuthenticationMode),
142+
DiscriminationKind(OtherDiscrimination), Key(unsigned(Key)) {
143+
assert((getOtherDiscrimination() != Discrimination::Constant ||
144+
ConstantDiscriminatorOrNone) &&
145+
"constant discrimination requires a constant!");
146+
if (ConstantDiscriminatorOrNone)
147+
ConstantDiscriminator = *ConstantDiscriminatorOrNone;
148+
}
149+
116150
PointerAuthSchema(
117151
ARM8_3Key Key, bool IsAddressDiscriminated,
118152
Discrimination OtherDiscrimination,
@@ -123,6 +157,16 @@ class PointerAuthSchema {
123157
OtherDiscrimination, ConstantDiscriminatorOrNone,
124158
IsIsaPointer, AuthenticatesNullValues) {}
125159

160+
PointerAuthSchema(
161+
SoftKey Key, bool IsAddressDiscriminated,
162+
Discrimination OtherDiscrimination,
163+
std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
164+
bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
165+
: PointerAuthSchema(Key, IsAddressDiscriminated,
166+
PointerAuthenticationMode::SignAndAuth,
167+
OtherDiscrimination, ConstantDiscriminatorOrNone,
168+
IsIsaPointer, AuthenticatesNullValues) {}
169+
126170
Kind getKind() const { return TheKind; }
127171

128172
explicit operator bool() const { return isEnabled(); }
@@ -162,6 +206,8 @@ class PointerAuthSchema {
162206
switch (getKind()) {
163207
case Kind::None:
164208
llvm_unreachable("calling getKey() on disabled schema");
209+
case Kind::Soft:
210+
return unsigned(getSoftKey());
165211
case Kind::ARM8_3:
166212
return llvm::to_underlying(getARM8_3Key());
167213
}
@@ -172,6 +218,11 @@ class PointerAuthSchema {
172218
return SelectedAuthenticationMode;
173219
}
174220

221+
SoftKey getSoftKey() const {
222+
assert(getKind() == Kind::Soft);
223+
return SoftKey(Key);
224+
}
225+
175226
ARM8_3Key getARM8_3Key() const {
176227
assert(getKind() == Kind::ARM8_3);
177228
return ARM8_3Key(Key);

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4403,6 +4403,11 @@ let Group = f_Group in {
44034403
HelpText<"Enable Pointer Authentication kernel ABI version">;
44044404
def fno_ptrauth_kernel_abi_version : Flag<["-"], "fno-ptrauth-kernel-abi-version">,
44054405
HelpText<"Disable Pointer Authentication kernel ABI versioning">;
4406+
4407+
def fptrauth_soft : Flag<["-"], "fptrauth-soft">,
4408+
Visibility<[ClangOption, CC1Option, CC1AsOption]>,
4409+
HelpText<"Enable software lowering of pointer authentication">;
4410+
def fno_ptrauth_soft : Flag<["-"], "fno-ptrauth-soft">;
44064411
}
44074412

44084413
def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "llvm/Transforms/Instrumentation/RealtimeSanitizer.h"
7878
#include "llvm/Transforms/Instrumentation/SanitizerBinaryMetadata.h"
7979
#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h"
80+
#include "llvm/Transforms/Instrumentation/SoftPointerAuth.h"
8081
#include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
8182
#include "llvm/Transforms/Instrumentation/TypeSanitizer.h"
8283
#include "llvm/Transforms/ObjCARC.h"
@@ -1074,6 +1075,11 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
10741075
addKCFIPass(TargetTriple, LangOpts, PB);
10751076
}
10761077

1078+
if (LangOpts.SoftPointerAuth)
1079+
PB.registerOptimizerLastEPCallback(
1080+
[](ModulePassManager &MPM, OptimizationLevel Level,
1081+
ThinOrFullLTOPhase) { MPM.addPass(SoftPointerAuthPass()); });
1082+
10771083
if (std::optional<GCOVOptions> Options =
10781084
getGCOVOptions(CodeGenOpts, LangOpts))
10791085
PB.registerPipelineStartEPCallback(

clang/lib/CodeGen/CGPointerAuth.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -714,12 +714,16 @@ CodeGenModule::computeVTPointerAuthentication(const CXXRecordDecl *ThisClass) {
714714
return std::nullopt;
715715

716716
if (ExplicitKey != VTablePointerAuthenticationAttr::DefaultKey) {
717-
if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
718-
Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA;
719-
else {
720-
assert(ExplicitKey ==
721-
VTablePointerAuthenticationAttr::ProcessDependent);
722-
Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB;
717+
if (Context.getLangOpts().SoftPointerAuth) {
718+
Key = (unsigned)PointerAuthSchema::SoftKey::CXXVirtualFunctionPointers;
719+
} else {
720+
if (ExplicitKey == VTablePointerAuthenticationAttr::ProcessIndependent)
721+
Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDA;
722+
else {
723+
assert(ExplicitKey ==
724+
VTablePointerAuthenticationAttr::ProcessDependent);
725+
Key = (unsigned)PointerAuthSchema::ARM8_3Key::ASDB;
726+
}
723727
}
724728
}
725729

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7571,6 +7571,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
75717571
// -fno-common is the default, set -fcommon only when that flag is set.
75727572
Args.addOptInFlag(CmdArgs, options::OPT_fcommon, options::OPT_fno_common);
75737573

7574+
if (Args.hasFlag(options::OPT_fptrauth_soft,
7575+
options::OPT_fno_ptrauth_soft, false))
7576+
CmdArgs.push_back("-fptrauth-soft");
7577+
75747578
// -fsigned-bitfields is default, and clang doesn't yet support
75757579
// -funsigned-bitfields.
75767580
if (!Args.hasFlag(options::OPT_fsigned_bitfields,

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1524,6 +1524,66 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts,
15241524
void CompilerInvocation::setDefaultPointerAuthOptions(
15251525
PointerAuthOptions &Opts, const LangOptions &LangOpts,
15261526
const llvm::Triple &Triple) {
1527+
1528+
if (LangOpts.SoftPointerAuth) {
1529+
if (LangOpts.PointerAuthCalls) {
1530+
using Key = PointerAuthSchema::SoftKey;
1531+
using Discrimination = PointerAuthSchema::Discrimination;
1532+
Opts.FunctionPointers =
1533+
PointerAuthSchema(Key::FunctionPointers, false,
1534+
LangOpts.PointerAuthFunctionTypeDiscrimination
1535+
? Discrimination::Type
1536+
: Discrimination::None);
1537+
1538+
Opts.CXXVTablePointers = PointerAuthSchema(
1539+
Key::CXXVTablePointers,
1540+
LangOpts.PointerAuthVTPtrAddressDiscrimination,
1541+
LangOpts.PointerAuthVTPtrTypeDiscrimination ? Discrimination::Type
1542+
: Discrimination::None);
1543+
Opts.CXXTypeInfoVTablePointer = PointerAuthSchema(
1544+
Key::CXXVTablePointers, false, Discrimination::None);
1545+
Opts.CXXVTTVTablePointers = PointerAuthSchema(
1546+
Key::CXXVTablePointers, false, Discrimination::None);
1547+
Opts.CXXVirtualFunctionPointers =
1548+
Opts.CXXVirtualVariadicFunctionPointers = PointerAuthSchema(
1549+
Key::CXXVirtualFunctionPointers, true, Discrimination::Decl);
1550+
Opts.CXXMemberFunctionPointers = PointerAuthSchema(
1551+
Key::CXXMemberFunctionPointers, false, Discrimination::Type);
1552+
1553+
Opts.BlockInvocationFunctionPointers = PointerAuthSchema(
1554+
Key::BlockInvocationFunctionPointers, true, Discrimination::None);
1555+
Opts.BlockHelperFunctionPointers = PointerAuthSchema(
1556+
Key::BlockHelperFunctionPointers, true, Discrimination::None);
1557+
Opts.BlockByrefHelperFunctionPointers = PointerAuthSchema(
1558+
Key::BlockHelperFunctionPointers, true, Discrimination::None);
1559+
if (LangOpts.PointerAuthBlockDescriptorPointers)
1560+
Opts.BlockDescriptorPointers = PointerAuthSchema(
1561+
Key::BlockDescriptorPointers, true, Discrimination::Constant,
1562+
BlockDescriptorConstantDiscriminator);
1563+
1564+
Opts.ObjCMethodListFunctionPointers = PointerAuthSchema(
1565+
Key::ObjCMethodListFunctionPointers, true, Discrimination::None);
1566+
Opts.ObjCMethodListPointer = PointerAuthSchema(
1567+
Key::ObjCMethodListPointer, true, Discrimination::Constant,
1568+
MethodListPointerConstantDiscriminator);
1569+
1570+
auto IsaAuthenticationMode =
1571+
LangOpts.getPointerAuthObjcIsaAuthentication();
1572+
if (IsaAuthenticationMode != PointerAuthenticationMode::None) {
1573+
Opts.ObjCIsaPointers = PointerAuthSchema(
1574+
Key::ObjCIsaPointer, true, IsaAuthenticationMode,
1575+
Discrimination::Constant, IsaPointerConstantDiscriminator, true);
1576+
Opts.ObjCSuperPointers = PointerAuthSchema(
1577+
Key::ObjCIsaPointer, true, IsaAuthenticationMode,
1578+
Discrimination::Constant, SuperPointerConstantDiscriminator);
1579+
}
1580+
}
1581+
Opts.ReturnAddresses = LangOpts.PointerAuthReturns;
1582+
Opts.IndirectGotos = LangOpts.PointerAuthIndirectGotos;
1583+
Opts.AuthTraps = LangOpts.PointerAuthAuthTraps;
1584+
return;
1585+
}
1586+
15271587
assert(Triple.getArch() == llvm::Triple::aarch64);
15281588
if (LangOpts.PointerAuthCalls) {
15291589
using Key = PointerAuthSchema::ARM8_3Key;
@@ -3558,6 +3618,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
35583618
GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination);
35593619
if (Opts.PointerAuthFunctionTypeDiscrimination)
35603620
GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination);
3621+
if (Opts.SoftPointerAuth)
3622+
GenerateArg(Consumer, OPT_fptrauth_soft);
35613623
if (Opts.PointerAuthBlockDescriptorPointers)
35623624
GenerateArg(Consumer, OPT_fptrauth_block_descriptor_pointers);
35633625

@@ -3650,6 +3712,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
36503712
Opts.PointerAuthABIVersion =
36513713
getLastArgIntValue(Args, OPT_fptrauth_abi_version_EQ, 0, Diags);
36523714
Opts.PointerAuthKernelABIVersion = Args.hasArg(OPT_fptrauth_kernel_abi_version);
3715+
3716+
Opts.SoftPointerAuth = Args.hasArg(OPT_fptrauth_soft);
36533717
}
36543718

36553719
/// Check if input file kind and language standard are compatible.

clang/test/Driver/arch-arm64e.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// NONE-NOT: "-fptrauth-indirect-gotos"
99
// NONE-NOT: "-fptrauth-auth-traps"
1010
// NONE-NOT: "-mbranch-target-enforce"
11+
// NONE-NOT: "-fptrauth-soft"
1112

1213
// RUN: %clang -target arm64-apple-ios15 -fptrauth-calls -c %s -### 2>&1 | FileCheck %s --check-prefix CALL
1314
// CALL: "-cc1"{{.*}} {{.*}} "-fptrauth-calls"
@@ -27,6 +28,9 @@
2728
// RUN: %clang -target arm64-apple-ios15 -fbranch-target-identification -c %s -### 2>&1 | FileCheck %s --check-prefix BTI
2829
// BTI: "-cc1"{{.*}} {{.*}} "-mbranch-target-enforce"
2930

31+
// RUN: %clang -target arm64-apple-ios -fptrauth-soft -c %s -### 2>&1 | FileCheck %s --check-prefix SOFT
32+
// SOFT: "-cc1"{{.*}} {{.*}} "-fptrauth-soft"
33+
3034

3135
// Check the arm64e defaults.
3236
// isa signing depends on the target OS and is tested elsewhere.

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ void initializeSingleLoopExtractorPass(PassRegistry &);
287287
void initializeSinkingLegacyPassPass(PassRegistry &);
288288
void initializeSjLjEHPreparePass(PassRegistry &);
289289
void initializeSlotIndexesWrapperPassPass(PassRegistry &);
290+
void initializeSoftPointerAuthLegacyPassPass(PassRegistry&);
290291
void initializeSpeculativeExecutionLegacyPassPass(PassRegistry &);
291292
void initializeSpillPlacementWrapperLegacyPass(PassRegistry &);
292293
void initializeStackColoringLegacyPass(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)