xref: /llvm-project/clang/include/clang/Basic/PointerAuthOptions.h (revision 41cde465acfddb44d400b0a53bb57960762312a2)
1 //===--- PointerAuthOptions.h -----------------------------------*- 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 //  This file defines options for configuring pointer-auth technologies
10 //  like ARMv8.3.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
15 #define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H
16 
17 #include "clang/Basic/LLVM.h"
18 #include "clang/Basic/LangOptions.h"
19 #include "llvm/ADT/STLForwardCompat.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Target/TargetOptions.h"
22 #include <optional>
23 
24 namespace clang {
25 
26 /// Constant discriminator to be used with function pointers in .init_array and
27 /// .fini_array. The value is ptrauth_string_discriminator("init_fini")
28 constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4;
29 
30 constexpr unsigned PointerAuthKeyNone = -1;
31 
32 /// Constant discriminator for std::type_info vtable pointers: 0xB1EA/45546
33 /// The value is ptrauth_string_discriminator("_ZTVSt9type_info"), i.e.,
34 /// the vtable type discriminator for classes derived from std::type_info.
35 constexpr uint16_t StdTypeInfoVTablePointerConstantDiscrimination = 0xB1EA;
36 
37 class PointerAuthSchema {
38 public:
39   enum class Kind : unsigned {
40     None,
41     ARM8_3,
42   };
43 
44   /// Hardware pointer-signing keys in ARM8.3.
45   ///
46   /// These values are the same used in ptrauth.h.
47   enum class ARM8_3Key : unsigned {
48     ASIA = 0,
49     ASIB = 1,
50     ASDA = 2,
51     ASDB = 3
52   };
53 
54   /// Forms of extra discrimination.
55   enum class Discrimination : unsigned {
56     /// No additional discrimination.
57     None,
58 
59     /// Include a hash of the entity's type.
60     Type,
61 
62     /// Include a hash of the entity's identity.
63     Decl,
64 
65     /// Discriminate using a constant value.
66     Constant,
67   };
68 
69 private:
70   Kind TheKind : 2;
71   unsigned IsAddressDiscriminated : 1;
72   unsigned IsIsaPointer : 1;
73   unsigned AuthenticatesNullValues : 1;
74   PointerAuthenticationMode SelectedAuthenticationMode : 2;
75   Discrimination DiscriminationKind : 2;
76   unsigned Key : 2;
77   unsigned ConstantDiscriminator : 16;
78 
79 public:
80   PointerAuthSchema() : TheKind(Kind::None) {}
81 
82   PointerAuthSchema(
83       ARM8_3Key Key, bool IsAddressDiscriminated,
84       PointerAuthenticationMode AuthenticationMode,
85       Discrimination OtherDiscrimination,
86       std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
87       bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
88       : TheKind(Kind::ARM8_3), IsAddressDiscriminated(IsAddressDiscriminated),
89         IsIsaPointer(IsIsaPointer),
90         AuthenticatesNullValues(AuthenticatesNullValues),
91         SelectedAuthenticationMode(AuthenticationMode),
92         DiscriminationKind(OtherDiscrimination), Key(llvm::to_underlying(Key)) {
93     assert((getOtherDiscrimination() != Discrimination::Constant ||
94             ConstantDiscriminatorOrNone) &&
95            "constant discrimination requires a constant!");
96     if (ConstantDiscriminatorOrNone)
97       ConstantDiscriminator = *ConstantDiscriminatorOrNone;
98   }
99 
100   PointerAuthSchema(
101       ARM8_3Key Key, bool IsAddressDiscriminated,
102       Discrimination OtherDiscrimination,
103       std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt,
104       bool IsIsaPointer = false, bool AuthenticatesNullValues = false)
105       : PointerAuthSchema(Key, IsAddressDiscriminated,
106                           PointerAuthenticationMode::SignAndAuth,
107                           OtherDiscrimination, ConstantDiscriminatorOrNone,
108                           IsIsaPointer, AuthenticatesNullValues) {}
109 
110   Kind getKind() const { return TheKind; }
111 
112   explicit operator bool() const { return isEnabled(); }
113 
114   bool isEnabled() const { return getKind() != Kind::None; }
115 
116   bool isAddressDiscriminated() const {
117     assert(getKind() != Kind::None);
118     return IsAddressDiscriminated;
119   }
120 
121   bool isIsaPointer() const {
122     assert(getKind() != Kind::None);
123     return IsIsaPointer;
124   }
125 
126   bool authenticatesNullValues() const {
127     assert(getKind() != Kind::None);
128     return AuthenticatesNullValues;
129   }
130 
131   bool hasOtherDiscrimination() const {
132     return getOtherDiscrimination() != Discrimination::None;
133   }
134 
135   Discrimination getOtherDiscrimination() const {
136     assert(getKind() != Kind::None);
137     return DiscriminationKind;
138   }
139 
140   uint16_t getConstantDiscrimination() const {
141     assert(getOtherDiscrimination() == Discrimination::Constant);
142     return ConstantDiscriminator;
143   }
144 
145   unsigned getKey() const {
146     switch (getKind()) {
147     case Kind::None:
148       llvm_unreachable("calling getKey() on disabled schema");
149     case Kind::ARM8_3:
150       return llvm::to_underlying(getARM8_3Key());
151     }
152     llvm_unreachable("bad key kind");
153   }
154 
155   PointerAuthenticationMode getAuthenticationMode() const {
156     return SelectedAuthenticationMode;
157   }
158 
159   ARM8_3Key getARM8_3Key() const {
160     assert(getKind() == Kind::ARM8_3);
161     return ARM8_3Key(Key);
162   }
163 };
164 
165 struct PointerAuthOptions {
166   /// Should return addresses be authenticated?
167   bool ReturnAddresses = false;
168 
169   /// Do authentication failures cause a trap?
170   bool AuthTraps = false;
171 
172   /// Do indirect goto label addresses need to be authenticated?
173   bool IndirectGotos = false;
174 
175   /// Use hardened lowering for jump-table dispatch?
176   bool AArch64JumpTableHardening = false;
177 
178   /// The ABI for C function pointers.
179   PointerAuthSchema FunctionPointers;
180 
181   /// The ABI for C++ virtual table pointers (the pointer to the table
182   /// itself) as installed in an actual class instance.
183   PointerAuthSchema CXXVTablePointers;
184 
185   /// TypeInfo has external ABI requirements and is emitted without
186   /// actually having parsed the libcxx definition, so we can't simply
187   /// perform a look up. The settings for this should match the exact
188   /// specification in type_info.h
189   PointerAuthSchema CXXTypeInfoVTablePointer;
190 
191   /// The ABI for C++ virtual table pointers as installed in a VTT.
192   PointerAuthSchema CXXVTTVTablePointers;
193 
194   /// The ABI for most C++ virtual function pointers, i.e. v-table entries.
195   PointerAuthSchema CXXVirtualFunctionPointers;
196 
197   /// The ABI for variadic C++ virtual function pointers.
198   PointerAuthSchema CXXVirtualVariadicFunctionPointers;
199 
200   /// The ABI for C++ member function pointers.
201   PointerAuthSchema CXXMemberFunctionPointers;
202 
203   /// The ABI for function addresses in .init_array and .fini_array
204   PointerAuthSchema InitFiniPointers;
205 };
206 
207 } // end namespace clang
208 
209 #endif
210