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