1 | /* |
2 | * Copyright (C) 2018-2019 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * 1. Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. |
9 | * 2. Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. |
12 | * |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 | */ |
25 | |
26 | #pragma once |
27 | |
28 | #include <wtf/Assertions.h> |
29 | #include <wtf/DataLog.h> |
30 | |
31 | namespace WTF { |
32 | |
33 | #define FOR_EACH_BASE_WTF_PTRTAG(v) \ |
34 | v(NoPtrTag) \ |
35 | v(CFunctionPtrTag) \ |
36 | |
37 | #define FOR_EACH_ADDITIONAL_WTF_PTRTAG(v) \ |
38 | v(FreeSpacePtrTag) \ |
39 | v(HandleMemoryPtrTag) \ |
40 | v(PlatformRegistersLRPtrTag) \ |
41 | v(PlatformRegistersPCPtrTag) \ |
42 | |
43 | #define FOR_EACH_WTF_PTRTAG(v) \ |
44 | FOR_EACH_BASE_WTF_PTRTAG(v) \ |
45 | FOR_EACH_ADDITIONAL_WTF_PTRTAG(v) \ |
46 | |
47 | enum PtrTag : uintptr_t { |
48 | NoPtrTag, |
49 | CFunctionPtrTag, |
50 | }; |
51 | |
52 | #if CPU(ARM64E) |
53 | #define WTF_PTRTAG_HASH(tag) ptrauth_string_discriminator(#tag) |
54 | |
55 | #else // not CPU(ARM64E) |
56 | |
57 | template<size_t N> |
58 | constexpr uintptr_t makePtrTagHash(const char (&str)[N]) |
59 | { |
60 | uintptr_t result = 134775813; |
61 | for (size_t i = 0; i < N; ++i) |
62 | result += ((result * str[i]) ^ (result >> 16)); |
63 | return result & 0xffff; |
64 | } |
65 | |
66 | #define WTF_PTRTAG_HASH(tag) WTF::makePtrTagHash(#tag) |
67 | #endif // not CPU(ARM64E) |
68 | |
69 | #define WTF_DECLARE_PTRTAG(tag) \ |
70 | constexpr PtrTag tag = static_cast<PtrTag>(WTF_PTRTAG_HASH(#tag)); \ |
71 | static_assert(tag != NoPtrTag && tag != CFunctionPtrTag, ""); |
72 | |
73 | static_assert(static_cast<uintptr_t>(NoPtrTag) == static_cast<uintptr_t>(0), "" ); |
74 | static_assert(static_cast<uintptr_t>(CFunctionPtrTag) == static_cast<uintptr_t>(1), "" ); |
75 | |
76 | #if COMPILER(MSVC) |
77 | #pragma warning(push) |
78 | #pragma warning(disable:4307) |
79 | #endif |
80 | |
81 | FOR_EACH_ADDITIONAL_WTF_PTRTAG(WTF_DECLARE_PTRTAG) |
82 | |
83 | #if COMPILER(MSVC) |
84 | #pragma warning(pop) |
85 | #endif |
86 | |
87 | struct PtrTagLookup { |
88 | const char* (*tagForPtr)(const void*); |
89 | const char* (*ptrTagName)(PtrTag); |
90 | PtrTagLookup* next { nullptr }; |
91 | }; |
92 | |
93 | #if CPU(ARM64E) |
94 | |
95 | enum class PtrTagAction { |
96 | ReleaseAssert, |
97 | DebugAssert, |
98 | NoAssert, |
99 | }; |
100 | |
101 | constexpr PtrTag AnyPtrTag = static_cast<PtrTag>(-1); // Only used for assertion messages. |
102 | |
103 | WTF_EXPORT_PRIVATE void registerPtrTagLookup(PtrTagLookup*); |
104 | WTF_EXPORT_PRIVATE void reportBadTag(const void*, PtrTag expectedTag); |
105 | |
106 | #if ASSERT_DISABLED |
107 | constexpr bool enablePtrTagDebugAssert = false; |
108 | #else |
109 | constexpr bool enablePtrTagDebugAssert = true; |
110 | #endif |
111 | |
112 | #define WTF_PTRTAG_ASSERT(action, ptr, expectedTag, assertion) \ |
113 | do { \ |
114 | if (action == PtrTagAction::ReleaseAssert \ |
115 | || (WTF::enablePtrTagDebugAssert && action == PtrTagAction::DebugAssert)) { \ |
116 | bool passed = (assertion); \ |
117 | if (UNLIKELY(!passed)) { \ |
118 | reportBadTag(reinterpret_cast<const void*>(ptr), expectedTag); \ |
119 | } \ |
120 | RELEASE_ASSERT(passed && #assertion); \ |
121 | } \ |
122 | } while (false) |
123 | |
124 | |
125 | template<typename T> |
126 | inline T* tagArrayPtr(std::nullptr_t ptr, size_t length) |
127 | { |
128 | ASSERT(!length); |
129 | return ptrauth_sign_unauthenticated(static_cast<T*>(ptr), ptrauth_key_process_dependent_data, length); |
130 | } |
131 | |
132 | |
133 | template<typename T> |
134 | inline T* tagArrayPtr(T* ptr, size_t length) |
135 | { |
136 | return ptrauth_sign_unauthenticated(ptr, ptrauth_key_process_dependent_data, length); |
137 | } |
138 | |
139 | template<typename T> |
140 | inline T* untagArrayPtr(T* ptr, size_t length) |
141 | { |
142 | return ptrauth_auth_data(ptr, ptrauth_key_process_dependent_data, length); |
143 | } |
144 | |
145 | template<typename T> |
146 | inline T* removeArrayPtrTag(T* ptr) |
147 | { |
148 | return ptrauth_strip(ptr, ptrauth_key_process_dependent_data); |
149 | } |
150 | |
151 | template<typename T> |
152 | inline T* retagArrayPtr(T* ptr, size_t oldLength, size_t newLength) |
153 | { |
154 | return ptrauth_auth_and_resign(ptr, ptrauth_key_process_dependent_data, oldLength, ptrauth_key_process_dependent_data, newLength); |
155 | } |
156 | |
157 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
158 | inline constexpr T removeCodePtrTag(PtrType ptr) |
159 | { |
160 | return bitwise_cast<T>(ptrauth_strip(ptr, ptrauth_key_process_dependent_code)); |
161 | } |
162 | |
163 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
164 | inline constexpr PtrType removeCodePtrTag(PtrType ptr) |
165 | { |
166 | return ptrauth_strip(ptr, ptrauth_key_process_dependent_code); |
167 | } |
168 | |
169 | template<PtrTagAction tagAction, typename PtrType> |
170 | inline PtrType tagCodePtrImpl(PtrType ptr, PtrTag tag) |
171 | { |
172 | if (!ptr) |
173 | return nullptr; |
174 | WTF_PTRTAG_ASSERT(tagAction, ptr, NoPtrTag, removeCodePtrTag(ptr) == ptr); |
175 | if (tag == NoPtrTag) |
176 | return ptr; |
177 | if (tag == CFunctionPtrTag) |
178 | return ptrauth_sign_unauthenticated(ptr, ptrauth_key_function_pointer, 0); |
179 | return ptrauth_sign_unauthenticated(ptr, ptrauth_key_process_dependent_code, tag); |
180 | } |
181 | |
182 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
183 | inline T tagCodePtr(PtrType ptr, PtrTag tag) |
184 | { |
185 | return bitwise_cast<T>(tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag)); |
186 | } |
187 | |
188 | template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
189 | inline T tagCodePtr(PtrType ptr) |
190 | { |
191 | return bitwise_cast<T>(tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag)); |
192 | } |
193 | |
194 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
195 | inline PtrType tagCodePtr(PtrType ptr, PtrTag tag) |
196 | { |
197 | return tagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, tag); |
198 | } |
199 | |
200 | template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
201 | inline PtrType tagCodePtr(PtrType ptr) { return tagCodePtr(ptr, tag); } |
202 | |
203 | template<typename PtrType> |
204 | inline PtrType untagCodePtrImplHelper(PtrType ptr, PtrTag tag) |
205 | { |
206 | if (tag == NoPtrTag) |
207 | return ptr; |
208 | if (tag == CFunctionPtrTag) |
209 | return __builtin_ptrauth_auth(ptr, ptrauth_key_function_pointer, 0); |
210 | return __builtin_ptrauth_auth(ptr, ptrauth_key_process_dependent_code, tag); |
211 | } |
212 | |
213 | template<PtrTagAction tagAction, typename PtrType> |
214 | inline PtrType untagCodePtrImpl(PtrType ptr, PtrTag tag) |
215 | { |
216 | if (!ptr) |
217 | return nullptr; |
218 | PtrType result = untagCodePtrImplHelper(ptr, tag); |
219 | WTF_PTRTAG_ASSERT(tagAction, ptr, tag, removeCodePtrTag(ptr) == result); |
220 | return result; |
221 | } |
222 | |
223 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
224 | inline T untagCodePtr(PtrType ptr, PtrTag tag) |
225 | { |
226 | return bitwise_cast<T>(untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag)); |
227 | } |
228 | |
229 | template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
230 | inline T untagCodePtr(PtrType ptr) |
231 | { |
232 | return bitwise_cast<T>(untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag)); |
233 | } |
234 | |
235 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
236 | inline PtrType untagCodePtr(PtrType ptr, PtrTag tag) |
237 | { |
238 | return untagCodePtrImpl<PtrTagAction::ReleaseAssert>(ptr, tag); |
239 | } |
240 | |
241 | template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
242 | inline PtrType untagCodePtr(PtrType ptr) { return untagCodePtr(ptr, tag); } |
243 | |
244 | template<PtrTagAction tagAction, typename PtrType> |
245 | inline PtrType retagCodePtrImplHelper(PtrType ptr, PtrTag oldTag, PtrTag newTag) |
246 | { |
247 | if (oldTag == newTag || (oldTag == NoPtrTag && newTag == NoPtrTag)) |
248 | return ptr; |
249 | if (newTag == NoPtrTag) |
250 | return untagCodePtrImpl<tagAction>(ptr, oldTag); |
251 | if (oldTag == NoPtrTag) |
252 | return tagCodePtrImpl<tagAction>(ptr, newTag); |
253 | if (oldTag == CFunctionPtrTag) |
254 | return ptrauth_auth_and_resign(ptr, ptrauth_key_function_pointer, 0, ptrauth_key_process_dependent_code, newTag); |
255 | if (newTag == CFunctionPtrTag) |
256 | return ptrauth_auth_and_resign(ptr, ptrauth_key_process_dependent_code, oldTag, ptrauth_key_function_pointer, 0); |
257 | return ptrauth_auth_and_resign(ptr, ptrauth_key_process_dependent_code, oldTag, ptrauth_key_process_dependent_code, newTag); |
258 | } |
259 | |
260 | template<PtrTagAction tagAction, typename PtrType> |
261 | inline PtrType retagCodePtrImpl(PtrType ptr, PtrTag oldTag, PtrTag newTag) |
262 | { |
263 | if (!ptr) |
264 | return nullptr; |
265 | PtrTagAction untagAction = (tagAction == PtrTagAction::NoAssert) ? PtrTagAction::NoAssert : PtrTagAction::ReleaseAssert; |
266 | WTF_PTRTAG_ASSERT(untagAction, ptr, oldTag, removeCodePtrTag(ptr) == untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, oldTag)); |
267 | PtrType result = retagCodePtrImplHelper<tagAction>(ptr, oldTag, newTag); |
268 | WTF_PTRTAG_ASSERT(tagAction, ptr, newTag, result == tagCodePtrImpl<PtrTagAction::NoAssert>(removeCodePtrTag(ptr), newTag)); |
269 | return result; |
270 | } |
271 | |
272 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
273 | inline T retagCodePtr(PtrType ptr, PtrTag oldTag, PtrTag newTag) |
274 | { |
275 | return bitwise_cast<T>(retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag)); |
276 | } |
277 | |
278 | template<typename T, PtrTag oldTag, PtrTag newTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
279 | inline T retagCodePtr(PtrType ptr) |
280 | { |
281 | return bitwise_cast<T>(retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag)); |
282 | } |
283 | |
284 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
285 | inline PtrType retagCodePtr(PtrType ptr, PtrTag oldTag, PtrTag newTag) |
286 | { |
287 | return retagCodePtrImpl<PtrTagAction::DebugAssert>(ptr, oldTag, newTag); |
288 | } |
289 | |
290 | template<PtrTag oldTag, PtrTag newTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
291 | inline PtrType retagCodePtr(PtrType ptr) { return retagCodePtr(ptr, oldTag, newTag); } |
292 | |
293 | template<PtrTagAction tagAction, typename PtrType> |
294 | inline PtrType tagCFunctionPtrImpl(PtrType ptr, PtrTag tag) |
295 | { |
296 | if (!ptr) |
297 | return nullptr; |
298 | WTF_PTRTAG_ASSERT(tagAction, ptr, CFunctionPtrTag, removeCodePtrTag(ptr) == untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, CFunctionPtrTag)); |
299 | return retagCodePtrImpl<tagAction>(ptr, CFunctionPtrTag, tag); |
300 | } |
301 | |
302 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
303 | inline T tagCFunctionPtr(PtrType ptr, PtrTag tag) |
304 | { |
305 | return bitwise_cast<T>(tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag)); |
306 | } |
307 | |
308 | template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
309 | inline T tagCFunctionPtr(PtrType ptr) |
310 | { |
311 | return bitwise_cast<T>(tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag)); |
312 | } |
313 | |
314 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
315 | inline PtrType tagCFunctionPtr(PtrType ptr, PtrTag tag) |
316 | { |
317 | return tagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag); |
318 | } |
319 | |
320 | template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
321 | inline PtrType tagCFunctionPtr(PtrType ptr) { return tagCFunctionPtr(ptr, tag); } |
322 | |
323 | template<PtrTagAction tagAction, typename PtrType> |
324 | inline PtrType untagCFunctionPtrImpl(PtrType ptr, PtrTag tag) |
325 | { |
326 | if (!ptr) |
327 | return nullptr; |
328 | WTF_PTRTAG_ASSERT(tagAction, ptr, tag, removeCodePtrTag(ptr) == untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, tag)); |
329 | return retagCodePtrImpl<tagAction>(ptr, tag, CFunctionPtrTag); |
330 | } |
331 | |
332 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
333 | inline T untagCFunctionPtr(PtrType ptr, PtrTag tag) |
334 | { |
335 | return bitwise_cast<T>(untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag)); |
336 | } |
337 | |
338 | template<typename T, PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
339 | inline T untagCFunctionPtr(PtrType ptr) |
340 | { |
341 | return bitwise_cast<T>(untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag)); |
342 | } |
343 | |
344 | template<typename T, PtrTag tag, PtrTagAction tagAction, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
345 | inline T untagCFunctionPtr(PtrType ptr) |
346 | { |
347 | return bitwise_cast<T>(untagCFunctionPtrImpl<tagAction>(ptr, tag)); |
348 | } |
349 | |
350 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
351 | inline PtrType untagCFunctionPtr(PtrType ptr, PtrTag tag) |
352 | { |
353 | return untagCFunctionPtrImpl<PtrTagAction::DebugAssert>(ptr, tag); |
354 | } |
355 | |
356 | template<PtrTag tag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
357 | inline PtrType untagCFunctionPtr(PtrType ptr) { return untagCFunctionPtr(ptr, tag); } |
358 | |
359 | template <typename IntType> |
360 | inline IntType tagInt(IntType ptrInt, PtrTag tag) |
361 | { |
362 | static_assert(sizeof(IntType) == sizeof(uintptr_t), "" ); |
363 | return bitwise_cast<IntType>(ptrauth_sign_unauthenticated(bitwise_cast<void*>(ptrInt), ptrauth_key_process_dependent_data, tag)); |
364 | } |
365 | |
366 | template<typename PtrType> |
367 | void assertIsCFunctionPtr(PtrType value) |
368 | { |
369 | void* ptr = bitwise_cast<void*>(value); |
370 | WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, CFunctionPtrTag, untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, CFunctionPtrTag) == removeCodePtrTag(ptr)); |
371 | } |
372 | |
373 | template<typename PtrType> |
374 | void assertIsNullOrCFunctionPtr(PtrType ptr) |
375 | { |
376 | if (ptr) |
377 | assertIsCFunctionPtr(ptr); |
378 | } |
379 | |
380 | template<typename PtrType> |
381 | void assertIsNotTagged(PtrType value) |
382 | { |
383 | void* ptr = bitwise_cast<void*>(value); |
384 | WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, NoPtrTag, ptr == removeCodePtrTag(ptr)); |
385 | } |
386 | |
387 | template<typename PtrType> |
388 | void assertIsTagged(PtrType value) |
389 | { |
390 | void* ptr = bitwise_cast<void*>(value); |
391 | WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, ptr, AnyPtrTag, ptr != removeCodePtrTag(ptr)); |
392 | } |
393 | |
394 | template<typename PtrType> |
395 | void assertIsNullOrTagged(PtrType ptr) |
396 | { |
397 | if (ptr) |
398 | assertIsTagged(ptr); |
399 | } |
400 | |
401 | template<typename PtrType> |
402 | bool isTaggedWith(PtrType value, PtrTag tag) |
403 | { |
404 | void* ptr = bitwise_cast<void*>(value); |
405 | if (tag == NoPtrTag) |
406 | return ptr == removeCodePtrTag(ptr); |
407 | return untagCodePtrImpl<PtrTagAction::NoAssert>(ptr, tag) == removeCodePtrTag(ptr); |
408 | } |
409 | |
410 | template<typename PtrType> |
411 | void assertIsTaggedWith(PtrType value, PtrTag tag) |
412 | { |
413 | WTF_PTRTAG_ASSERT(PtrTagAction::ReleaseAssert, value, tag, isTaggedWith(value, tag)); |
414 | } |
415 | |
416 | template<typename PtrType> |
417 | void assertIsNullOrTaggedWith(PtrType ptr, PtrTag tag) |
418 | { |
419 | if (ptr) |
420 | assertIsTaggedWith(ptr, tag); |
421 | } |
422 | |
423 | inline bool usesPointerTagging() { return true; } |
424 | |
425 | #else // not CPU(ARM64E) |
426 | |
427 | inline void registerPtrTagLookup(PtrTagLookup*) { } |
428 | inline void reportBadTag(const void*, PtrTag) { } |
429 | |
430 | template<typename T> |
431 | inline T* tagArrayPtr(std::nullptr_t, size_t size) |
432 | { |
433 | ASSERT_UNUSED(size, !size); |
434 | return nullptr; |
435 | } |
436 | |
437 | template<typename T> |
438 | inline T* tagArrayPtr(T* ptr, size_t) |
439 | { |
440 | return ptr; |
441 | } |
442 | |
443 | template<typename T> |
444 | inline T* untagArrayPtr(T* ptr, size_t) |
445 | { |
446 | return ptr; |
447 | } |
448 | |
449 | template<typename T> |
450 | inline T* removeArrayPtrTag(T* ptr) |
451 | { |
452 | return ptr; |
453 | } |
454 | |
455 | template<typename T> |
456 | inline T* retagArrayPtr(T* ptr, size_t, size_t) |
457 | { |
458 | return ptr; |
459 | } |
460 | |
461 | |
462 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
463 | constexpr T tagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); } |
464 | |
465 | template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
466 | inline T tagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); } |
467 | |
468 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
469 | constexpr PtrType tagCodePtr(PtrType ptr, PtrTag) { return ptr; } |
470 | |
471 | template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
472 | inline PtrType tagCodePtr(PtrType ptr) { return ptr; } |
473 | |
474 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
475 | constexpr T untagCodePtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); } |
476 | |
477 | template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
478 | inline T untagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); } |
479 | |
480 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
481 | constexpr PtrType untagCodePtr(PtrType ptr, PtrTag) { return ptr; } |
482 | |
483 | template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
484 | inline PtrType untagCodePtr(PtrType ptr) { return ptr; } |
485 | |
486 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
487 | constexpr T retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return bitwise_cast<T>(ptr); } |
488 | |
489 | template<typename T, PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
490 | inline T retagCodePtr(PtrType ptr) { return bitwise_cast<T>(ptr); } |
491 | |
492 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
493 | constexpr PtrType retagCodePtr(PtrType ptr, PtrTag, PtrTag) { return ptr; } |
494 | |
495 | template<PtrTag, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
496 | inline PtrType retagCodePtr(PtrType ptr) { return ptr; } |
497 | |
498 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
499 | constexpr T removeCodePtrTag(PtrType ptr) { return bitwise_cast<T>(ptr); } |
500 | |
501 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
502 | constexpr PtrType removeCodePtrTag(PtrType ptr) { return ptr; } |
503 | |
504 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
505 | inline T tagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); } |
506 | |
507 | template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
508 | inline T tagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); } |
509 | |
510 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
511 | inline PtrType tagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; } |
512 | |
513 | template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
514 | inline PtrType tagCFunctionPtr(PtrType ptr) { return ptr; } |
515 | |
516 | template<typename T, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_same<T, PtrType>::value>> |
517 | inline T untagCFunctionPtr(PtrType ptr, PtrTag) { return bitwise_cast<T>(ptr); } |
518 | |
519 | template<typename T, PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
520 | inline T untagCFunctionPtr(PtrType ptr) { return bitwise_cast<T>(ptr); } |
521 | |
522 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
523 | inline PtrType untagCFunctionPtr(PtrType ptr, PtrTag) { return ptr; } |
524 | |
525 | template<PtrTag, typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value>> |
526 | inline PtrType untagCFunctionPtr(PtrType ptr) { return ptr; } |
527 | |
528 | template <typename IntType> |
529 | inline IntType tagInt(IntType ptrInt, PtrTag) |
530 | { |
531 | static_assert(sizeof(IntType) == sizeof(uintptr_t), "" ); |
532 | return ptrInt; |
533 | } |
534 | |
535 | template<typename PtrType> void assertIsCFunctionPtr(PtrType) { } |
536 | template<typename PtrType> void assertIsNullOrCFunctionPtr(PtrType) { } |
537 | |
538 | template<typename PtrType> void assertIsNotTagged(PtrType) { } |
539 | template<typename PtrType> void assertIsTagged(PtrType) { } |
540 | template<typename PtrType> void assertIsNullOrTagged(PtrType) { } |
541 | |
542 | template<typename PtrType> bool isTaggedWith(PtrType, PtrTag) { return false; } |
543 | |
544 | template<typename PtrType> void assertIsTaggedWith(PtrType, PtrTag) { } |
545 | template<typename PtrType> void assertIsNullOrTaggedWith(PtrType, PtrTag) { } |
546 | |
547 | inline bool usesPointerTagging() { return false; } |
548 | |
549 | #endif // CPU(ARM64E) |
550 | |
551 | } // namespace WTF |
552 | |
553 | using WTF::CFunctionPtrTag; |
554 | using WTF::NoPtrTag; |
555 | using WTF::PlatformRegistersLRPtrTag; |
556 | using WTF::PlatformRegistersPCPtrTag; |
557 | using WTF::PtrTag; |
558 | |
559 | using WTF::reportBadTag; |
560 | |
561 | using WTF::tagArrayPtr; |
562 | using WTF::untagArrayPtr; |
563 | using WTF::retagArrayPtr; |
564 | using WTF::removeArrayPtrTag; |
565 | |
566 | using WTF::tagCodePtr; |
567 | using WTF::untagCodePtr; |
568 | using WTF::retagCodePtr; |
569 | using WTF::removeCodePtrTag; |
570 | using WTF::tagCFunctionPtr; |
571 | using WTF::untagCFunctionPtr; |
572 | using WTF::tagInt; |
573 | |
574 | using WTF::assertIsCFunctionPtr; |
575 | using WTF::assertIsNullOrCFunctionPtr; |
576 | using WTF::assertIsNotTagged; |
577 | using WTF::assertIsTagged; |
578 | using WTF::assertIsNullOrTagged; |
579 | using WTF::isTaggedWith; |
580 | using WTF::assertIsTaggedWith; |
581 | using WTF::assertIsNullOrTaggedWith; |
582 | using WTF::usesPointerTagging; |
583 | |