1 //===------ ExecutorAddress.h - Executing process address -------*- 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 // Represents an address in the executing program. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H 14 #define LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H 15 16 #include "llvm/ADT/DenseMapInfo.h" 17 #include "llvm/ADT/identity.h" 18 #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" 19 #include "llvm/Support/FormatVariadic.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 #include <cassert> 23 #if __has_feature(ptrauth_calls) 24 #include <ptrauth.h> 25 #endif 26 #include <type_traits> 27 28 namespace llvm { 29 namespace orc { 30 31 using ExecutorAddrDiff = uint64_t; 32 33 /// Represents an address in the executor process. 34 class ExecutorAddr { 35 public: 36 /// A wrap/unwrap function that leaves pointers unmodified. 37 template <typename T> using rawPtr = llvm::identity<T *>; 38 39 #if __has_feature(ptrauth_calls) 40 template <typename T> class PtrauthSignDefault { 41 public: operator()42 constexpr T *operator()(T *P) { 43 if (std::is_function_v<T>) 44 return ptrauth_sign_unauthenticated(P, ptrauth_key_function_pointer, 0); 45 else 46 return P; 47 } 48 }; 49 50 template <typename T> class PtrauthStripDefault { 51 public: operator()52 constexpr T *operator()(T *P) { 53 return ptrauth_strip(P, ptrauth_key_function_pointer); 54 } 55 }; 56 57 /// Default wrap function to use on this host. 58 template <typename T> using defaultWrap = PtrauthSignDefault<T>; 59 60 /// Default unwrap function to use on this host. 61 template <typename T> using defaultUnwrap = PtrauthStripDefault<T>; 62 63 #else 64 65 /// Default wrap function to use on this host. 66 template <typename T> using defaultWrap = rawPtr<T>; 67 68 /// Default unwrap function to use on this host. 69 template <typename T> using defaultUnwrap = rawPtr<T>; 70 71 #endif 72 73 /// Merges a tag into the raw address value: 74 /// P' = P | (TagValue << TagOffset). 75 class Tag { 76 public: Tag(uintptr_t TagValue,uintptr_t TagOffset)77 constexpr Tag(uintptr_t TagValue, uintptr_t TagOffset) 78 : TagMask(TagValue << TagOffset) {} 79 operator()80 template <typename T> constexpr T *operator()(T *P) { 81 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) | TagMask); 82 } 83 84 private: 85 uintptr_t TagMask; 86 }; 87 88 /// Strips a tag of the given length from the given offset within the pointer: 89 /// P' = P & ~(((1 << TagLen) -1) << TagOffset) 90 class Untag { 91 public: Untag(uintptr_t TagLen,uintptr_t TagOffset)92 constexpr Untag(uintptr_t TagLen, uintptr_t TagOffset) 93 : UntagMask(~(((uintptr_t(1) << TagLen) - 1) << TagOffset)) {} 94 operator()95 template <typename T> constexpr T *operator()(T *P) { 96 return reinterpret_cast<T *>(reinterpret_cast<uintptr_t>(P) & UntagMask); 97 } 98 99 private: 100 uintptr_t UntagMask; 101 }; 102 103 ExecutorAddr() = default; 104 105 /// Create an ExecutorAddr from the given value. ExecutorAddr(uint64_t Addr)106 explicit constexpr ExecutorAddr(uint64_t Addr) : Addr(Addr) {} 107 108 /// Create an ExecutorAddr from the given pointer. 109 /// Warning: This should only be used when JITing in-process. 110 template <typename T, typename UnwrapFn = defaultUnwrap<T>> 111 static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap = UnwrapFn()) { 112 return ExecutorAddr( 113 static_cast<uint64_t>(reinterpret_cast<uintptr_t>(Unwrap(Ptr)))); 114 } 115 116 /// Cast this ExecutorAddr to a pointer of the given type. 117 /// Warning: This should only be used when JITing in-process. 118 template <typename T, typename WrapFn = defaultWrap<std::remove_pointer_t<T>>> 119 std::enable_if_t<std::is_pointer<T>::value, T> 120 toPtr(WrapFn &&Wrap = WrapFn()) const { 121 uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 122 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 123 return Wrap(reinterpret_cast<T>(IntPtr)); 124 } 125 126 /// Cast this ExecutorAddr to a pointer of the given function type. 127 /// Warning: This should only be used when JITing in-process. 128 template <typename T, typename WrapFn = defaultWrap<T>> 129 std::enable_if_t<std::is_function<T>::value, T *> 130 toPtr(WrapFn &&Wrap = WrapFn()) const { 131 uintptr_t IntPtr = static_cast<uintptr_t>(Addr); 132 assert(IntPtr == Addr && "ExecutorAddr value out of range for uintptr_t"); 133 return Wrap(reinterpret_cast<T *>(IntPtr)); 134 } 135 getValue()136 uint64_t getValue() const { return Addr; } setValue(uint64_t Addr)137 void setValue(uint64_t Addr) { this->Addr = Addr; } isNull()138 bool isNull() const { return Addr == 0; } 139 140 explicit operator bool() const { return Addr != 0; } 141 142 friend bool operator==(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 143 return LHS.Addr == RHS.Addr; 144 } 145 146 friend bool operator!=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 147 return LHS.Addr != RHS.Addr; 148 } 149 150 friend bool operator<(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 151 return LHS.Addr < RHS.Addr; 152 } 153 154 friend bool operator<=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 155 return LHS.Addr <= RHS.Addr; 156 } 157 158 friend bool operator>(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 159 return LHS.Addr > RHS.Addr; 160 } 161 162 friend bool operator>=(const ExecutorAddr &LHS, const ExecutorAddr &RHS) { 163 return LHS.Addr >= RHS.Addr; 164 } 165 166 ExecutorAddr &operator++() { 167 ++Addr; 168 return *this; 169 } 170 ExecutorAddr &operator--() { 171 --Addr; 172 return *this; 173 } 174 ExecutorAddr operator++(int) { return ExecutorAddr(Addr++); } 175 ExecutorAddr operator--(int) { return ExecutorAddr(Addr--); } 176 177 ExecutorAddr &operator+=(const ExecutorAddrDiff &Delta) { 178 Addr += Delta; 179 return *this; 180 } 181 182 ExecutorAddr &operator-=(const ExecutorAddrDiff &Delta) { 183 Addr -= Delta; 184 return *this; 185 } 186 187 private: 188 uint64_t Addr = 0; 189 }; 190 191 /// Subtracting two addresses yields an offset. 192 inline ExecutorAddrDiff operator-(const ExecutorAddr &LHS, 193 const ExecutorAddr &RHS) { 194 return ExecutorAddrDiff(LHS.getValue() - RHS.getValue()); 195 } 196 197 /// Adding an offset and an address yields an address. 198 inline ExecutorAddr operator+(const ExecutorAddr &LHS, 199 const ExecutorAddrDiff &RHS) { 200 return ExecutorAddr(LHS.getValue() + RHS); 201 } 202 203 /// Adding an address and an offset yields an address. 204 inline ExecutorAddr operator+(const ExecutorAddrDiff &LHS, 205 const ExecutorAddr &RHS) { 206 return ExecutorAddr(LHS + RHS.getValue()); 207 } 208 209 /// Subtracting an offset from an address yields an address. 210 inline ExecutorAddr operator-(const ExecutorAddr &LHS, 211 const ExecutorAddrDiff &RHS) { 212 return ExecutorAddr(LHS.getValue() - RHS); 213 } 214 215 /// Taking the modulus of an address and a diff yields a diff. 216 inline ExecutorAddrDiff operator%(const ExecutorAddr &LHS, 217 const ExecutorAddrDiff &RHS) { 218 return ExecutorAddrDiff(LHS.getValue() % RHS); 219 } 220 221 /// Represents an address range in the exceutor process. 222 struct ExecutorAddrRange { 223 ExecutorAddrRange() = default; ExecutorAddrRangeExecutorAddrRange224 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddr End) 225 : Start(Start), End(End) {} ExecutorAddrRangeExecutorAddrRange226 ExecutorAddrRange(ExecutorAddr Start, ExecutorAddrDiff Size) 227 : Start(Start), End(Start + Size) {} 228 229 template <typename T, typename UnwrapFn = ExecutorAddr::defaultUnwrap<T>> 230 static ExecutorAddrRange fromPtrRange(T *Start, T *End, 231 UnwrapFn &&Unwrap = UnwrapFn()) { 232 return {ExecutorAddr::fromPtr(Start, Unwrap), 233 ExecutorAddr::fromPtr(End, Unwrap)}; 234 } 235 236 template <typename T, typename UnwrapFn = ExecutorAddr::defaultUnwrap<T>> 237 static ExecutorAddrRange fromPtrRange(T *Ptr, ExecutorAddrDiff Size, 238 UnwrapFn &&Unwrap = UnwrapFn()) { 239 return {ExecutorAddr::fromPtr(Ptr, std::forward<UnwrapFn>(Unwrap)), Size}; 240 } 241 emptyExecutorAddrRange242 bool empty() const { return Start == End; } sizeExecutorAddrRange243 ExecutorAddrDiff size() const { return End - Start; } 244 245 friend bool operator==(const ExecutorAddrRange &LHS, 246 const ExecutorAddrRange &RHS) { 247 return LHS.Start == RHS.Start && LHS.End == RHS.End; 248 } 249 friend bool operator!=(const ExecutorAddrRange &LHS, 250 const ExecutorAddrRange &RHS) { 251 return !(LHS == RHS); 252 } 253 friend bool operator<(const ExecutorAddrRange &LHS, 254 const ExecutorAddrRange &RHS) { 255 return LHS.Start < RHS.Start || 256 (LHS.Start == RHS.Start && LHS.End < RHS.End); 257 } 258 friend bool operator<=(const ExecutorAddrRange &LHS, 259 const ExecutorAddrRange &RHS) { 260 return LHS.Start < RHS.Start || 261 (LHS.Start == RHS.Start && LHS.End <= RHS.End); 262 } 263 friend bool operator>(const ExecutorAddrRange &LHS, 264 const ExecutorAddrRange &RHS) { 265 return LHS.Start > RHS.Start || 266 (LHS.Start == RHS.Start && LHS.End > RHS.End); 267 } 268 friend bool operator>=(const ExecutorAddrRange &LHS, 269 const ExecutorAddrRange &RHS) { 270 return LHS.Start > RHS.Start || 271 (LHS.Start == RHS.Start && LHS.End >= RHS.End); 272 } 273 containsExecutorAddrRange274 bool contains(ExecutorAddr Addr) const { return Start <= Addr && Addr < End; } overlapsExecutorAddrRange275 bool overlaps(const ExecutorAddrRange &Other) { 276 return !(Other.End <= Start || End <= Other.Start); 277 } 278 279 ExecutorAddr Start; 280 ExecutorAddr End; 281 }; 282 283 inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddr &A) { 284 return OS << formatv("{0:x}", A.getValue()); 285 } 286 287 inline raw_ostream &operator<<(raw_ostream &OS, const ExecutorAddrRange &R) { 288 return OS << formatv("{0:x} -- {1:x}", R.Start.getValue(), R.End.getValue()); 289 } 290 291 namespace shared { 292 293 class SPSExecutorAddr {}; 294 295 /// SPS serializatior for ExecutorAddr. 296 template <> class SPSSerializationTraits<SPSExecutorAddr, ExecutorAddr> { 297 public: size(const ExecutorAddr & EA)298 static size_t size(const ExecutorAddr &EA) { 299 return SPSArgList<uint64_t>::size(EA.getValue()); 300 } 301 serialize(SPSOutputBuffer & BOB,const ExecutorAddr & EA)302 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddr &EA) { 303 return SPSArgList<uint64_t>::serialize(BOB, EA.getValue()); 304 } 305 deserialize(SPSInputBuffer & BIB,ExecutorAddr & EA)306 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddr &EA) { 307 uint64_t Tmp; 308 if (!SPSArgList<uint64_t>::deserialize(BIB, Tmp)) 309 return false; 310 EA = ExecutorAddr(Tmp); 311 return true; 312 } 313 }; 314 315 using SPSExecutorAddrRange = SPSTuple<SPSExecutorAddr, SPSExecutorAddr>; 316 317 /// Serialization traits for address ranges. 318 template <> 319 class SPSSerializationTraits<SPSExecutorAddrRange, ExecutorAddrRange> { 320 public: size(const ExecutorAddrRange & Value)321 static size_t size(const ExecutorAddrRange &Value) { 322 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::size(Value.Start, 323 Value.End); 324 } 325 serialize(SPSOutputBuffer & BOB,const ExecutorAddrRange & Value)326 static bool serialize(SPSOutputBuffer &BOB, const ExecutorAddrRange &Value) { 327 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::serialize( 328 BOB, Value.Start, Value.End); 329 } 330 deserialize(SPSInputBuffer & BIB,ExecutorAddrRange & Value)331 static bool deserialize(SPSInputBuffer &BIB, ExecutorAddrRange &Value) { 332 return SPSArgList<SPSExecutorAddr, SPSExecutorAddr>::deserialize( 333 BIB, Value.Start, Value.End); 334 } 335 }; 336 337 using SPSExecutorAddrRangeSequence = SPSSequence<SPSExecutorAddrRange>; 338 339 } // End namespace shared. 340 } // End namespace orc. 341 342 // Provide DenseMapInfo for ExecutorAddrs. 343 template <> struct DenseMapInfo<orc::ExecutorAddr> { 344 static inline orc::ExecutorAddr getEmptyKey() { 345 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getEmptyKey()); 346 } 347 static inline orc::ExecutorAddr getTombstoneKey() { 348 return orc::ExecutorAddr(DenseMapInfo<uint64_t>::getTombstoneKey()); 349 } 350 351 static unsigned getHashValue(const orc::ExecutorAddr &Addr) { 352 return DenseMapInfo<uint64_t>::getHashValue(Addr.getValue()); 353 } 354 355 static bool isEqual(const orc::ExecutorAddr &LHS, 356 const orc::ExecutorAddr &RHS) { 357 return DenseMapInfo<uint64_t>::isEqual(LHS.getValue(), RHS.getValue()); 358 } 359 }; 360 361 } // End namespace llvm. 362 363 #endif // LLVM_EXECUTIONENGINE_ORC_SHARED_EXECUTORADDRESS_H 364