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