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