1 | /* |
2 | * Copyright (C) 2009-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 "ExecutableAllocator.h" |
29 | #include "JSCPtrTag.h" |
30 | #include <wtf/DataLog.h> |
31 | #include <wtf/PrintStream.h> |
32 | #include <wtf/RefPtr.h> |
33 | #include <wtf/text/CString.h> |
34 | |
35 | // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid |
36 | // instruction address on the platform (for example, check any alignment requirements). |
37 | #if CPU(ARM_THUMB2) && ENABLE(JIT) |
38 | // ARM instructions must be 16-bit aligned. Thumb2 code pointers to be loaded into |
39 | // into the processor are decorated with the bottom bit set, while traditional ARM has |
40 | // the lower bit clear. Since we don't know what kind of pointer, we check for both |
41 | // decorated and undecorated null. |
42 | #define ASSERT_NULL_OR_VALID_CODE_POINTER(ptr) \ |
43 | ASSERT(!ptr || reinterpret_cast<intptr_t>(ptr) & ~1) |
44 | #define ASSERT_VALID_CODE_POINTER(ptr) \ |
45 | ASSERT(reinterpret_cast<intptr_t>(ptr) & ~1) |
46 | #define ASSERT_VALID_CODE_OFFSET(offset) \ |
47 | ASSERT(!(offset & 1)) // Must be multiple of 2. |
48 | #else |
49 | #define ASSERT_NULL_OR_VALID_CODE_POINTER(ptr) // Anything goes! |
50 | #define ASSERT_VALID_CODE_POINTER(ptr) \ |
51 | ASSERT(ptr) |
52 | #define ASSERT_VALID_CODE_OFFSET(offset) // Anything goes! |
53 | #endif |
54 | |
55 | namespace JSC { |
56 | |
57 | template<PtrTag> class MacroAssemblerCodePtr; |
58 | |
59 | enum OpcodeID : unsigned; |
60 | |
61 | // FunctionPtr: |
62 | // |
63 | // FunctionPtr should be used to wrap pointers to C/C++ functions in JSC |
64 | // (particularly, the stub functions). |
65 | template<PtrTag tag = CFunctionPtrTag> |
66 | class FunctionPtr { |
67 | public: |
68 | FunctionPtr() { } |
69 | FunctionPtr(std::nullptr_t) { } |
70 | |
71 | template<typename ReturnType, typename... Arguments> |
72 | FunctionPtr(ReturnType(*value)(Arguments...)) |
73 | : m_value(tagCFunctionPtr<void*, tag>(value)) |
74 | { |
75 | assertIsNullOrCFunctionPtr(value); |
76 | ASSERT_NULL_OR_VALID_CODE_POINTER(m_value); |
77 | } |
78 | |
79 | // MSVC doesn't seem to treat functions with different calling conventions as |
80 | // different types; these methods already defined for fastcall, below. |
81 | #if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS) |
82 | |
83 | template<typename ReturnType, typename... Arguments> |
84 | FunctionPtr(ReturnType(CDECL *value)(Arguments...)) |
85 | : m_value(tagCFunctionPtr<void*, tag>(value)) |
86 | { |
87 | assertIsNullOrCFunctionPtr(value); |
88 | ASSERT_NULL_OR_VALID_CODE_POINTER(m_value); |
89 | } |
90 | |
91 | #endif // CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS) |
92 | |
93 | #if COMPILER_SUPPORTS(FASTCALL_CALLING_CONVENTION) |
94 | |
95 | template<typename ReturnType, typename... Arguments> |
96 | FunctionPtr(ReturnType(FASTCALL *value)(Arguments...)) |
97 | : m_value(tagCFunctionPtr<void*, tag>(value)) |
98 | { |
99 | assertIsNullOrCFunctionPtr(value); |
100 | ASSERT_NULL_OR_VALID_CODE_POINTER(m_value); |
101 | } |
102 | |
103 | #endif // COMPILER_SUPPORTS(FASTCALL_CALLING_CONVENTION) |
104 | |
105 | template<typename PtrType, typename = std::enable_if_t<std::is_pointer<PtrType>::value && !std::is_function<typename std::remove_pointer<PtrType>::type>::value>> |
106 | explicit FunctionPtr(PtrType value) |
107 | // Using a C-ctyle cast here to avoid compiler error on RVTC: |
108 | // Error: #694: reinterpret_cast cannot cast away const or other type qualifiers |
109 | // (I guess on RVTC function pointers have a different constness to GCC/MSVC?) |
110 | : m_value(tagCFunctionPtr<void*, tag>(value)) |
111 | { |
112 | assertIsNullOrCFunctionPtr(value); |
113 | ASSERT_NULL_OR_VALID_CODE_POINTER(m_value); |
114 | } |
115 | |
116 | explicit FunctionPtr(MacroAssemblerCodePtr<tag>); |
117 | |
118 | template<PtrTag otherTag> |
119 | FunctionPtr<otherTag> retagged() const |
120 | { |
121 | if (!m_value) |
122 | return FunctionPtr<otherTag>(); |
123 | return FunctionPtr<otherTag>(*this); |
124 | } |
125 | |
126 | void* executableAddress() const |
127 | { |
128 | return m_value; |
129 | } |
130 | |
131 | template<PtrTag newTag> |
132 | void* retaggedExecutableAddress() const |
133 | { |
134 | return retagCodePtr<tag, newTag>(m_value); |
135 | } |
136 | |
137 | explicit operator bool() const { return !!m_value; } |
138 | bool operator!() const { return !m_value; } |
139 | |
140 | bool operator==(const FunctionPtr& other) const { return m_value == other.m_value; } |
141 | bool operator!=(const FunctionPtr& other) const { return m_value != other.m_value; } |
142 | |
143 | private: |
144 | template<PtrTag otherTag> |
145 | explicit FunctionPtr(const FunctionPtr<otherTag>& other) |
146 | : m_value(retagCodePtr<otherTag, tag>(other.executableAddress())) |
147 | { |
148 | ASSERT_NULL_OR_VALID_CODE_POINTER(m_value); |
149 | } |
150 | |
151 | void* m_value { nullptr }; |
152 | |
153 | template<PtrTag> friend class FunctionPtr; |
154 | }; |
155 | |
156 | static_assert(sizeof(FunctionPtr<CFunctionPtrTag>) == sizeof(void*), "" ); |
157 | #if COMPILER_SUPPORTS(BUILTIN_IS_TRIVIALLY_COPYABLE) |
158 | static_assert(__is_trivially_copyable(FunctionPtr<CFunctionPtrTag>), "" ); |
159 | #endif |
160 | |
161 | // ReturnAddressPtr: |
162 | // |
163 | // ReturnAddressPtr should be used to wrap return addresses generated by processor |
164 | // 'call' instructions exectued in JIT code. We use return addresses to look up |
165 | // exception and optimization information, and to repatch the call instruction |
166 | // that is the source of the return address. |
167 | class ReturnAddressPtr { |
168 | public: |
169 | ReturnAddressPtr() { } |
170 | |
171 | explicit ReturnAddressPtr(const void* value) |
172 | : m_value(value) |
173 | { |
174 | ASSERT_VALID_CODE_POINTER(m_value); |
175 | } |
176 | |
177 | template<PtrTag tag> |
178 | explicit ReturnAddressPtr(FunctionPtr<tag> function) |
179 | : m_value(untagCodePtr<tag>(function.executableAddress())) |
180 | { |
181 | ASSERT_VALID_CODE_POINTER(m_value); |
182 | } |
183 | |
184 | const void* value() const |
185 | { |
186 | return m_value; |
187 | } |
188 | |
189 | void dump(PrintStream& out) const |
190 | { |
191 | out.print(RawPointer(m_value)); |
192 | } |
193 | |
194 | private: |
195 | const void* m_value { nullptr }; |
196 | }; |
197 | |
198 | // MacroAssemblerCodePtr: |
199 | // |
200 | // MacroAssemblerCodePtr should be used to wrap pointers to JIT generated code. |
201 | class MacroAssemblerCodePtrBase { |
202 | protected: |
203 | static void dumpWithName(void* executableAddress, void* dataLocation, const char* name, PrintStream& out); |
204 | }; |
205 | |
206 | // FIXME: Make JSC MacroAssemblerCodePtr injerit from MetaAllocatorPtr. |
207 | // https://bugs.webkit.org/show_bug.cgi?id=185145 |
208 | template<PtrTag tag> |
209 | class MacroAssemblerCodePtr : private MacroAssemblerCodePtrBase { |
210 | public: |
211 | MacroAssemblerCodePtr() = default; |
212 | MacroAssemblerCodePtr(std::nullptr_t) : m_value(nullptr) { } |
213 | |
214 | explicit MacroAssemblerCodePtr(const void* value) |
215 | #if CPU(ARM_THUMB2) |
216 | // Decorate the pointer as a thumb code pointer. |
217 | : m_value(reinterpret_cast<const char*>(value) + 1) |
218 | #else |
219 | : m_value(value) |
220 | #endif |
221 | { |
222 | assertIsTaggedWith(value, tag); |
223 | ASSERT(value); |
224 | #if CPU(ARM_THUMB2) |
225 | ASSERT(!(reinterpret_cast<uintptr_t>(value) & 1)); |
226 | #endif |
227 | ASSERT_VALID_CODE_POINTER(m_value); |
228 | } |
229 | |
230 | static MacroAssemblerCodePtr createFromExecutableAddress(const void* value) |
231 | { |
232 | ASSERT(value); |
233 | ASSERT_VALID_CODE_POINTER(value); |
234 | assertIsTaggedWith(value, tag); |
235 | MacroAssemblerCodePtr result; |
236 | result.m_value = value; |
237 | return result; |
238 | } |
239 | |
240 | explicit MacroAssemblerCodePtr(ReturnAddressPtr ra) |
241 | : m_value(tagCodePtr<tag>(ra.value())) |
242 | { |
243 | assertIsNotTagged(ra.value()); |
244 | ASSERT(ra.value()); |
245 | ASSERT_VALID_CODE_POINTER(m_value); |
246 | } |
247 | |
248 | template<PtrTag newTag> |
249 | MacroAssemblerCodePtr<newTag> retagged() const |
250 | { |
251 | if (!m_value) |
252 | return MacroAssemblerCodePtr<newTag>(); |
253 | return MacroAssemblerCodePtr<newTag>::createFromExecutableAddress(retaggedExecutableAddress<newTag>()); |
254 | } |
255 | |
256 | template<typename T = void*> |
257 | T executableAddress() const |
258 | { |
259 | return bitwise_cast<T>(m_value); |
260 | } |
261 | |
262 | template<typename T = void*> |
263 | T untaggedExecutableAddress() const |
264 | { |
265 | return untagCodePtr<T, tag>(m_value); |
266 | } |
267 | |
268 | template<PtrTag newTag, typename T = void*> |
269 | T retaggedExecutableAddress() const |
270 | { |
271 | return retagCodePtr<T, tag, newTag>(m_value); |
272 | } |
273 | |
274 | #if CPU(ARM_THUMB2) |
275 | // To use this pointer as a data address remove the decoration. |
276 | template<typename T = void*> |
277 | T dataLocation() const |
278 | { |
279 | ASSERT_VALID_CODE_POINTER(m_value); |
280 | return bitwise_cast<T>(m_value ? bitwise_cast<char*>(m_value) - 1 : nullptr); |
281 | } |
282 | #else |
283 | template<typename T = void*> |
284 | T dataLocation() const |
285 | { |
286 | ASSERT_VALID_CODE_POINTER(m_value); |
287 | return untagCodePtr<T, tag>(m_value); |
288 | } |
289 | #endif |
290 | |
291 | bool operator!() const |
292 | { |
293 | return !m_value; |
294 | } |
295 | explicit operator bool() const { return !(!*this); } |
296 | |
297 | bool operator==(const MacroAssemblerCodePtr& other) const |
298 | { |
299 | return m_value == other.m_value; |
300 | } |
301 | |
302 | // Disallow any casting operations (except for booleans). Instead, the client |
303 | // should be asking executableAddress() explicitly. |
304 | template<typename T, typename = std::enable_if_t<!std::is_same<T, bool>::value>> |
305 | operator T() = delete; |
306 | |
307 | void dumpWithName(const char* name, PrintStream& out) const |
308 | { |
309 | MacroAssemblerCodePtrBase::dumpWithName(executableAddress(), dataLocation(), name, out); |
310 | } |
311 | |
312 | void dump(PrintStream& out) const { dumpWithName("CodePtr" , out); } |
313 | |
314 | enum EmptyValueTag { EmptyValue }; |
315 | enum DeletedValueTag { DeletedValue }; |
316 | |
317 | MacroAssemblerCodePtr(EmptyValueTag) |
318 | : m_value(emptyValue()) |
319 | { } |
320 | |
321 | MacroAssemblerCodePtr(DeletedValueTag) |
322 | : m_value(deletedValue()) |
323 | { } |
324 | |
325 | bool isEmptyValue() const { return m_value == emptyValue(); } |
326 | bool isDeletedValue() const { return m_value == deletedValue(); } |
327 | |
328 | unsigned hash() const { return PtrHash<const void*>::hash(m_value); } |
329 | |
330 | static void initialize(); |
331 | |
332 | private: |
333 | static const void* emptyValue() { return bitwise_cast<void*>(static_cast<intptr_t>(1)); } |
334 | static const void* deletedValue() { return bitwise_cast<void*>(static_cast<intptr_t>(2)); } |
335 | |
336 | const void* m_value { nullptr }; |
337 | }; |
338 | |
339 | template<PtrTag tag> |
340 | struct MacroAssemblerCodePtrHash { |
341 | static unsigned hash(const MacroAssemblerCodePtr<tag>& ptr) { return ptr.hash(); } |
342 | static bool equal(const MacroAssemblerCodePtr<tag>& a, const MacroAssemblerCodePtr<tag>& b) |
343 | { |
344 | return a == b; |
345 | } |
346 | static const bool safeToCompareToEmptyOrDeleted = true; |
347 | }; |
348 | |
349 | // MacroAssemblerCodeRef: |
350 | // |
351 | // A reference to a section of JIT generated code. A CodeRef consists of a |
352 | // pointer to the code, and a ref pointer to the pool from within which it |
353 | // was allocated. |
354 | class MacroAssemblerCodeRefBase { |
355 | protected: |
356 | static bool tryToDisassemble(MacroAssemblerCodePtr<DisassemblyPtrTag>, size_t, const char* prefix, PrintStream& out); |
357 | static bool tryToDisassemble(MacroAssemblerCodePtr<DisassemblyPtrTag>, size_t, const char* prefix); |
358 | JS_EXPORT_PRIVATE static CString disassembly(MacroAssemblerCodePtr<DisassemblyPtrTag>, size_t); |
359 | }; |
360 | |
361 | template<PtrTag tag> |
362 | class MacroAssemblerCodeRef : private MacroAssemblerCodeRefBase { |
363 | private: |
364 | // This is private because it's dangerous enough that we want uses of it |
365 | // to be easy to find - hence the static create method below. |
366 | explicit MacroAssemblerCodeRef(MacroAssemblerCodePtr<tag> codePtr) |
367 | : m_codePtr(codePtr) |
368 | { |
369 | ASSERT(m_codePtr); |
370 | } |
371 | |
372 | public: |
373 | MacroAssemblerCodeRef() = default; |
374 | |
375 | MacroAssemblerCodeRef(Ref<ExecutableMemoryHandle>&& executableMemory) |
376 | : m_codePtr(executableMemory->start().retaggedPtr<tag>()) |
377 | , m_executableMemory(WTFMove(executableMemory)) |
378 | { |
379 | ASSERT(m_executableMemory->isManaged()); |
380 | ASSERT(m_executableMemory->start()); |
381 | ASSERT(m_codePtr); |
382 | } |
383 | |
384 | template<PtrTag otherTag> |
385 | MacroAssemblerCodeRef& operator=(const MacroAssemblerCodeRef<otherTag>& otherCodeRef) |
386 | { |
387 | m_codePtr = MacroAssemblerCodePtr<tag>::createFromExecutableAddress(otherCodeRef.code().template retaggedExecutableAddress<tag>()); |
388 | m_executableMemory = otherCodeRef.m_executableMemory; |
389 | return *this; |
390 | } |
391 | |
392 | // Use this only when you know that the codePtr refers to code that is |
393 | // already being kept alive through some other means. Typically this means |
394 | // that codePtr is immortal. |
395 | static MacroAssemblerCodeRef createSelfManagedCodeRef(MacroAssemblerCodePtr<tag> codePtr) |
396 | { |
397 | return MacroAssemblerCodeRef(codePtr); |
398 | } |
399 | |
400 | ExecutableMemoryHandle* executableMemory() const |
401 | { |
402 | return m_executableMemory.get(); |
403 | } |
404 | |
405 | MacroAssemblerCodePtr<tag> code() const |
406 | { |
407 | return m_codePtr; |
408 | } |
409 | |
410 | template<PtrTag newTag> |
411 | MacroAssemblerCodePtr<newTag> retaggedCode() const |
412 | { |
413 | return m_codePtr.template retagged<newTag>(); |
414 | } |
415 | |
416 | template<PtrTag newTag> |
417 | MacroAssemblerCodeRef<newTag> retagged() const |
418 | { |
419 | return MacroAssemblerCodeRef<newTag>(*this); |
420 | } |
421 | |
422 | size_t size() const |
423 | { |
424 | if (!m_executableMemory) |
425 | return 0; |
426 | return m_executableMemory->sizeInBytes(); |
427 | } |
428 | |
429 | bool tryToDisassemble(PrintStream& out, const char* prefix = "" ) const |
430 | { |
431 | return tryToDisassemble(retaggedCode<DisassemblyPtrTag>(), size(), prefix, out); |
432 | } |
433 | |
434 | bool tryToDisassemble(const char* prefix = "" ) const |
435 | { |
436 | return tryToDisassemble(retaggedCode<DisassemblyPtrTag>(), size(), prefix); |
437 | } |
438 | |
439 | CString disassembly() const |
440 | { |
441 | return MacroAssemblerCodeRefBase::disassembly(retaggedCode<DisassemblyPtrTag>(), size()); |
442 | } |
443 | |
444 | explicit operator bool() const { return !!m_codePtr; } |
445 | |
446 | void dump(PrintStream& out) const |
447 | { |
448 | m_codePtr.dumpWithName("CodeRef" , out); |
449 | } |
450 | |
451 | private: |
452 | template<PtrTag otherTag> |
453 | MacroAssemblerCodeRef(const MacroAssemblerCodeRef<otherTag>& otherCodeRef) |
454 | { |
455 | *this = otherCodeRef; |
456 | } |
457 | |
458 | MacroAssemblerCodePtr<tag> m_codePtr; |
459 | RefPtr<ExecutableMemoryHandle> m_executableMemory; |
460 | |
461 | template<PtrTag> friend class MacroAssemblerCodeRef; |
462 | }; |
463 | |
464 | template<PtrTag tag> |
465 | inline FunctionPtr<tag>::FunctionPtr(MacroAssemblerCodePtr<tag> ptr) |
466 | : m_value(ptr.executableAddress()) |
467 | { |
468 | } |
469 | |
470 | } // namespace JSC |
471 | |
472 | namespace WTF { |
473 | |
474 | template<typename T> struct DefaultHash; |
475 | template<JSC::PtrTag tag> struct DefaultHash<JSC::MacroAssemblerCodePtr<tag>> { |
476 | typedef JSC::MacroAssemblerCodePtrHash<tag> Hash; |
477 | }; |
478 | |
479 | template<typename T> struct HashTraits; |
480 | template<JSC::PtrTag tag> struct HashTraits<JSC::MacroAssemblerCodePtr<tag>> : public CustomHashTraits<JSC::MacroAssemblerCodePtr<tag>> { }; |
481 | |
482 | } // namespace WTF |
483 | |