1 | /* |
2 | * Copyright (C) 2017 Yusuke Suzuki <[email protected]>. |
3 | * Copyright (C) 2018 Apple Inc. All rights reserved. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * |
14 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
15 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
16 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
17 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
18 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
19 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
20 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
21 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
22 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
23 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
24 | * THE POSSIBILITY OF SUCH DAMAGE. |
25 | */ |
26 | |
27 | #pragma once |
28 | |
29 | #include "GPRInfo.h" |
30 | #include "LLIntPCRanges.h" |
31 | #include "MacroAssemblerCodeRef.h" |
32 | #include <wtf/Optional.h> |
33 | #include <wtf/PlatformRegisters.h> |
34 | #include <wtf/PointerPreparations.h> |
35 | #include <wtf/StdLibExtras.h> |
36 | |
37 | namespace JSC { |
38 | namespace MachineContext { |
39 | |
40 | template<typename T = void*> T stackPointer(const PlatformRegisters&); |
41 | |
42 | #if OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
43 | template<typename T = void*> void setStackPointer(PlatformRegisters&, T); |
44 | template<typename T = void*> T framePointer(const PlatformRegisters&); |
45 | template<typename T = void*> void setFramePointer(PlatformRegisters&, T); |
46 | inline MacroAssemblerCodePtr<PlatformRegistersLRPtrTag> linkRegister(const PlatformRegisters&); |
47 | inline void setLinkRegister(PlatformRegisters&, MacroAssemblerCodePtr<CFunctionPtrTag>); |
48 | inline Optional<MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>> instructionPointer(const PlatformRegisters&); |
49 | inline void setInstructionPointer(PlatformRegisters&, MacroAssemblerCodePtr<CFunctionPtrTag>); |
50 | |
51 | template<size_t N> void*& argumentPointer(PlatformRegisters&); |
52 | template<size_t N> void* argumentPointer(const PlatformRegisters&); |
53 | #if !ENABLE(C_LOOP) |
54 | void*& llintInstructionPointer(PlatformRegisters&); |
55 | void* llintInstructionPointer(const PlatformRegisters&); |
56 | #endif // !ENABLE(C_LOOP) |
57 | |
58 | #if HAVE(MACHINE_CONTEXT) |
59 | |
60 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
61 | static inline void*& stackPointerImpl(mcontext_t&); |
62 | static inline void*& framePointerImpl(mcontext_t&); |
63 | static inline void*& instructionPointerImpl(mcontext_t&); |
64 | #endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
65 | |
66 | template<typename T = void*> T stackPointer(const mcontext_t&); |
67 | template<typename T = void*> void setStackPointer(mcontext_t&, T); |
68 | template<typename T = void*> T framePointer(const mcontext_t&); |
69 | template<typename T = void*> void setFramePointer(mcontext_t&, T); |
70 | inline MacroAssemblerCodePtr<PlatformRegistersPCPtrTag> instructionPointer(const mcontext_t&); |
71 | inline void setInstructionPointer(mcontext_t&, MacroAssemblerCodePtr<CFunctionPtrTag>); |
72 | |
73 | template<size_t N> void*& argumentPointer(mcontext_t&); |
74 | template<size_t N> void* argumentPointer(const mcontext_t&); |
75 | #if !ENABLE(C_LOOP) |
76 | void*& llintInstructionPointer(mcontext_t&); |
77 | void* llintInstructionPointer(const mcontext_t&); |
78 | #endif // !ENABLE(C_LOOP) |
79 | #endif // HAVE(MACHINE_CONTEXT) |
80 | #endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
81 | |
82 | #if OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
83 | |
84 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
85 | static inline void*& stackPointerImpl(PlatformRegisters& regs) |
86 | { |
87 | #if OS(DARWIN) |
88 | #if __DARWIN_UNIX03 |
89 | |
90 | #if CPU(X86) |
91 | return reinterpret_cast<void*&>(regs.__esp); |
92 | #elif CPU(X86_64) |
93 | return reinterpret_cast<void*&>(regs.__rsp); |
94 | #elif CPU(PPC) || CPU(PPC64) |
95 | return reinterpret_cast<void*&>(regs.__r1); |
96 | #elif CPU(ARM_THUMB2) || CPU(ARM) || CPU(ARM64) |
97 | return reinterpret_cast<void*&>(regs.__sp); |
98 | #else |
99 | #error Unknown Architecture |
100 | #endif |
101 | |
102 | #else // !__DARWIN_UNIX03 |
103 | |
104 | #if CPU(X86) |
105 | return reinterpret_cast<void*&>(regs.esp); |
106 | #elif CPU(X86_64) |
107 | return reinterpret_cast<void*&>(regs.rsp); |
108 | #elif CPU(PPC) || CPU(PPC64) |
109 | return reinterpret_cast<void*&>(regs.r1); |
110 | #else |
111 | #error Unknown Architecture |
112 | #endif |
113 | |
114 | #endif // __DARWIN_UNIX03 |
115 | |
116 | #elif OS(WINDOWS) |
117 | |
118 | #if CPU(ARM) |
119 | return reinterpret_cast<void*&>((uintptr_t&) regs.Sp); |
120 | #elif CPU(MIPS) |
121 | return reinterpret_cast<void*&>((uintptr_t&) regs.IntSp); |
122 | #elif CPU(X86) |
123 | return reinterpret_cast<void*&>((uintptr_t&) regs.Esp); |
124 | #elif CPU(X86_64) |
125 | return reinterpret_cast<void*&>((uintptr_t&) regs.Rsp); |
126 | #else |
127 | #error Unknown Architecture |
128 | #endif |
129 | |
130 | #elif HAVE(MACHINE_CONTEXT) |
131 | return stackPointerImpl(regs.machineContext); |
132 | #endif |
133 | } |
134 | #endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
135 | |
136 | template<typename T> |
137 | inline T stackPointer(const PlatformRegisters& regs) |
138 | { |
139 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
140 | void* value = WTF_READ_PLATFORM_REGISTERS_SP_WITH_PROFILE(regs); |
141 | assertIsNotTagged(value); |
142 | return bitwise_cast<T>(value); |
143 | #else |
144 | return bitwise_cast<T>(stackPointerImpl(const_cast<PlatformRegisters&>(regs))); |
145 | #endif |
146 | } |
147 | |
148 | template<typename T> |
149 | inline void setStackPointer(PlatformRegisters& regs, T value) |
150 | { |
151 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
152 | assertIsNotTagged(bitwise_cast<void*>(value)); |
153 | WTF_WRITE_PLATFORM_REGISTERS_SP_WITH_PROFILE(regs, bitwise_cast<void*>(value)); |
154 | #else |
155 | stackPointerImpl(regs) = bitwise_cast<void*>(value); |
156 | #endif |
157 | } |
158 | |
159 | #else // not OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
160 | |
161 | template<typename T> |
162 | inline T stackPointer(const PlatformRegisters& regs) |
163 | { |
164 | return bitwise_cast<T>(regs.stackPointer); |
165 | } |
166 | #endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
167 | |
168 | #if HAVE(MACHINE_CONTEXT) |
169 | |
170 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
171 | static inline void*& stackPointerImpl(mcontext_t& machineContext) |
172 | { |
173 | #if OS(DARWIN) |
174 | return stackPointerImpl(machineContext->__ss); |
175 | #elif OS(FREEBSD) |
176 | |
177 | #if CPU(X86) |
178 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_esp); |
179 | #elif CPU(X86_64) |
180 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rsp); |
181 | #elif CPU(ARM) |
182 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_SP]); |
183 | #elif CPU(ARM64) |
184 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_sp); |
185 | #elif CPU(MIPS) |
186 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[29]); |
187 | #else |
188 | #error Unknown Architecture |
189 | #endif |
190 | |
191 | #elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__) |
192 | |
193 | #if CPU(X86) |
194 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_ESP]); |
195 | #elif CPU(X86_64) |
196 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RSP]); |
197 | #elif CPU(ARM) |
198 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_sp); |
199 | #elif CPU(ARM64) |
200 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.sp); |
201 | #elif CPU(MIPS) |
202 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[29]); |
203 | #else |
204 | #error Unknown Architecture |
205 | #endif |
206 | #endif |
207 | } |
208 | #endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
209 | |
210 | template<typename T> |
211 | inline T stackPointer(const mcontext_t& machineContext) |
212 | { |
213 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
214 | void* value = WTF_READ_MACHINE_CONTEXT_SP_WITH_PROFILE(machineContext); |
215 | assertIsNotTagged(value); |
216 | return bitwise_cast<T>(value); |
217 | #else |
218 | return bitwise_cast<T>(stackPointerImpl(const_cast<mcontext_t&>(machineContext))); |
219 | #endif |
220 | } |
221 | |
222 | template<typename T> |
223 | inline void setStackPointer(mcontext_t& machineContext, T value) |
224 | { |
225 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
226 | assertIsNotTagged(bitwise_cast<void*>(value)); |
227 | WTF_WRITE_MACHINE_CONTEXT_SP_WITH_PROFILE(machineContext, bitwise_cast<void*>(value)); |
228 | #else |
229 | stackPointerImpl(machineContext) = bitwise_cast<void*>(value); |
230 | #endif |
231 | } |
232 | #endif // HAVE(MACHINE_CONTEXT) |
233 | |
234 | |
235 | #if OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
236 | |
237 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
238 | static inline void*& framePointerImpl(PlatformRegisters& regs) |
239 | { |
240 | #if OS(DARWIN) |
241 | |
242 | #if __DARWIN_UNIX03 |
243 | |
244 | #if CPU(X86) |
245 | return reinterpret_cast<void*&>(regs.__ebp); |
246 | #elif CPU(X86_64) |
247 | return reinterpret_cast<void*&>(regs.__rbp); |
248 | #elif CPU(ARM_THUMB2) |
249 | return reinterpret_cast<void*&>(regs.__r[7]); |
250 | #elif CPU(ARM) |
251 | return reinterpret_cast<void*&>(regs.__r[11]); |
252 | #elif CPU(ARM64) |
253 | return reinterpret_cast<void*&>(regs.__x[29]); |
254 | #else |
255 | #error Unknown Architecture |
256 | #endif |
257 | |
258 | #else // !__DARWIN_UNIX03 |
259 | |
260 | #if CPU(X86) |
261 | return reinterpret_cast<void*&>(regs.esp); |
262 | #elif CPU(X86_64) |
263 | return reinterpret_cast<void*&>(regs.rsp); |
264 | #else |
265 | #error Unknown Architecture |
266 | #endif |
267 | |
268 | #endif // __DARWIN_UNIX03 |
269 | |
270 | #elif OS(WINDOWS) |
271 | |
272 | #if CPU(ARM) |
273 | return reinterpret_cast<void*&>((uintptr_t&) regs.R11); |
274 | #elif CPU(MIPS) |
275 | #error Dont know what to do with mips. Do we even need this? |
276 | #elif CPU(X86) |
277 | return reinterpret_cast<void*&>((uintptr_t&) regs.Ebp); |
278 | #elif CPU(X86_64) |
279 | return reinterpret_cast<void*&>((uintptr_t&) regs.Rbp); |
280 | #else |
281 | #error Unknown Architecture |
282 | #endif |
283 | |
284 | #elif HAVE(MACHINE_CONTEXT) |
285 | return framePointerImpl(regs.machineContext); |
286 | #endif |
287 | } |
288 | #endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
289 | |
290 | template<typename T> |
291 | inline T framePointer(const PlatformRegisters& regs) |
292 | { |
293 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
294 | void* value = WTF_READ_PLATFORM_REGISTERS_FP_WITH_PROFILE(regs); |
295 | assertIsNotTagged(value); |
296 | return bitwise_cast<T>(value); |
297 | #else |
298 | return bitwise_cast<T>(framePointerImpl(const_cast<PlatformRegisters&>(regs))); |
299 | #endif |
300 | } |
301 | |
302 | template<typename T> |
303 | inline void setFramePointer(PlatformRegisters& regs, T value) |
304 | { |
305 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
306 | assertIsNotTagged(bitwise_cast<void*>(value)); |
307 | WTF_WRITE_PLATFORM_REGISTERS_FP_WITH_PROFILE(regs, bitwise_cast<void*>(value)); |
308 | #else |
309 | framePointerImpl(regs) = bitwise_cast<void*>(value); |
310 | #endif |
311 | } |
312 | #endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
313 | |
314 | |
315 | #if HAVE(MACHINE_CONTEXT) |
316 | |
317 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
318 | static inline void*& framePointerImpl(mcontext_t& machineContext) |
319 | { |
320 | #if OS(DARWIN) |
321 | return framePointerImpl(machineContext->__ss); |
322 | #elif OS(FREEBSD) |
323 | |
324 | #if CPU(X86) |
325 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_ebp); |
326 | #elif CPU(X86_64) |
327 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rbp); |
328 | #elif CPU(ARM) |
329 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_FP]); |
330 | #elif CPU(ARM64) |
331 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_x[29]); |
332 | #elif CPU(MIPS) |
333 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[30]); |
334 | #else |
335 | #error Unknown Architecture |
336 | #endif |
337 | |
338 | #elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__) |
339 | |
340 | // The following sequence depends on glibc's sys/ucontext.h. |
341 | #if CPU(X86) |
342 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_EBP]); |
343 | #elif CPU(X86_64) |
344 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RBP]); |
345 | #elif CPU(ARM) |
346 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_fp); |
347 | #elif CPU(ARM64) |
348 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.regs[29]); |
349 | #elif CPU(MIPS) |
350 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[30]); |
351 | #else |
352 | #error Unknown Architecture |
353 | #endif |
354 | |
355 | #else |
356 | #error Need a way to get the frame pointer for another thread on this platform |
357 | #endif |
358 | } |
359 | #endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
360 | |
361 | template<typename T> |
362 | inline T framePointer(const mcontext_t& machineContext) |
363 | { |
364 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
365 | void* value = WTF_READ_MACHINE_CONTEXT_FP_WITH_PROFILE(machineContext); |
366 | assertIsNotTagged(value); |
367 | return bitwise_cast<T>(value); |
368 | #else |
369 | return bitwise_cast<T>(framePointerImpl(const_cast<mcontext_t&>(machineContext))); |
370 | #endif |
371 | } |
372 | |
373 | template<typename T> |
374 | inline void setFramePointer(mcontext_t& machineContext, T value) |
375 | { |
376 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
377 | assertIsNotTagged(bitwise_cast<void*>(value)); |
378 | WTF_WRITE_MACHINE_CONTEXT_FP_WITH_PROFILE(machineContext, bitwise_cast<void*>(value)); |
379 | #else |
380 | framePointerImpl(machineContext) = bitwise_cast<void*>(value); |
381 | #endif |
382 | } |
383 | #endif // HAVE(MACHINE_CONTEXT) |
384 | |
385 | |
386 | #if OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
387 | |
388 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
389 | static inline void*& instructionPointerImpl(PlatformRegisters& regs) |
390 | { |
391 | #if OS(DARWIN) |
392 | #if __DARWIN_UNIX03 |
393 | |
394 | #if CPU(X86) |
395 | return reinterpret_cast<void*&>(regs.__eip); |
396 | #elif CPU(X86_64) |
397 | return reinterpret_cast<void*&>(regs.__rip); |
398 | #elif CPU(ARM_THUMB2) || CPU(ARM) || CPU(ARM64) |
399 | return reinterpret_cast<void*&>(regs.__pc); |
400 | #else |
401 | #error Unknown Architecture |
402 | #endif |
403 | |
404 | #else // !__DARWIN_UNIX03 |
405 | #if CPU(X86) |
406 | return reinterpret_cast<void*&>(regs.eip); |
407 | #elif CPU(X86_64) |
408 | return reinterpret_cast<void*&>(regs.rip); |
409 | #else |
410 | #error Unknown Architecture |
411 | #endif |
412 | |
413 | #endif // __DARWIN_UNIX03 |
414 | |
415 | #elif OS(WINDOWS) |
416 | |
417 | #if CPU(ARM) |
418 | return reinterpret_cast<void*&>((uintptr_t&) regs.Pc); |
419 | #elif CPU(MIPS) |
420 | #error Dont know what to do with mips. Do we even need this? |
421 | #elif CPU(X86) |
422 | return reinterpret_cast<void*&>((uintptr_t&) regs.Eip); |
423 | #elif CPU(X86_64) |
424 | return reinterpret_cast<void*&>((uintptr_t&) regs.Rip); |
425 | #else |
426 | #error Unknown Architecture |
427 | #endif |
428 | |
429 | #elif HAVE(MACHINE_CONTEXT) |
430 | return instructionPointerImpl(regs.machineContext); |
431 | #endif |
432 | } |
433 | #endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
434 | |
435 | inline Optional<MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>> instructionPointer(const PlatformRegisters& regs) |
436 | { |
437 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
438 | void* value = WTF_READ_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs); |
439 | #else |
440 | void* value = instructionPointerImpl(const_cast<PlatformRegisters&>(regs)); |
441 | #endif |
442 | if (!value) |
443 | return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(nullptr); |
444 | if (!usesPointerTagging()) |
445 | return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(value); |
446 | if (isTaggedWith(value, PlatformRegistersPCPtrTag)) |
447 | return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(value); |
448 | return WTF::nullopt; |
449 | } |
450 | |
451 | inline void setInstructionPointer(PlatformRegisters& regs, MacroAssemblerCodePtr<CFunctionPtrTag> value) |
452 | { |
453 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
454 | WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, value.executableAddress()); |
455 | #else |
456 | instructionPointerImpl(regs) = value.executableAddress(); |
457 | #endif |
458 | } |
459 | #endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
460 | |
461 | |
462 | #if HAVE(MACHINE_CONTEXT) |
463 | |
464 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
465 | static inline void*& instructionPointerImpl(mcontext_t& machineContext) |
466 | { |
467 | #if OS(DARWIN) |
468 | return instructionPointerImpl(machineContext->__ss); |
469 | #elif OS(FREEBSD) |
470 | |
471 | #if CPU(X86) |
472 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_eip); |
473 | #elif CPU(X86_64) |
474 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rip); |
475 | #elif CPU(ARM) |
476 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_PC]); |
477 | #elif CPU(ARM64) |
478 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_elr); |
479 | #elif CPU(MIPS) |
480 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_pc); |
481 | #else |
482 | #error Unknown Architecture |
483 | #endif |
484 | |
485 | #elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__) |
486 | |
487 | // The following sequence depends on glibc's sys/ucontext.h. |
488 | #if CPU(X86) |
489 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_EIP]); |
490 | #elif CPU(X86_64) |
491 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RIP]); |
492 | #elif CPU(ARM) |
493 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_pc); |
494 | #elif CPU(ARM64) |
495 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.pc); |
496 | #elif CPU(MIPS) |
497 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.pc); |
498 | #else |
499 | #error Unknown Architecture |
500 | #endif |
501 | |
502 | #else |
503 | #error Need a way to get the instruction pointer for another thread on this platform |
504 | #endif |
505 | } |
506 | #endif // !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
507 | |
508 | inline MacroAssemblerCodePtr<PlatformRegistersPCPtrTag> instructionPointer(const mcontext_t& machineContext) |
509 | { |
510 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
511 | void* value = WTF_READ_MACHINE_CONTEXT_PC_WITH_PROFILE(machineContext); |
512 | #else |
513 | void* value = instructionPointerImpl(const_cast<mcontext_t&>(machineContext)); |
514 | #endif |
515 | return MacroAssemblerCodePtr<PlatformRegistersPCPtrTag>(value); |
516 | } |
517 | |
518 | inline void setInstructionPointer(mcontext_t& machineContext, MacroAssemblerCodePtr<CFunctionPtrTag> value) |
519 | { |
520 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
521 | WTF_WRITE_MACHINE_CONTEXT_PC_WITH_PROFILE(machineContext, value.executableAddress()); |
522 | #else |
523 | instructionPointerImpl(machineContext) = value.executableAddress(); |
524 | #endif |
525 | } |
526 | #endif // HAVE(MACHINE_CONTEXT) |
527 | |
528 | |
529 | #if OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
530 | |
531 | #if OS(DARWIN) && __DARWIN_UNIX03 && CPU(ARM64) |
532 | #if !USE(PLATFORM_REGISTERS_WITH_PROFILE) |
533 | inline void*& linkRegisterImpl(PlatformRegisters& regs) |
534 | { |
535 | return reinterpret_cast<void*&>(regs.__lr); |
536 | } |
537 | #endif // USE(PLATFORM_REGISTERS_WITH_PROFILE) |
538 | |
539 | |
540 | inline MacroAssemblerCodePtr<PlatformRegistersLRPtrTag> linkRegister(const PlatformRegisters& regs) |
541 | { |
542 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
543 | void* value = WTF_READ_PLATFORM_REGISTERS_LR_WITH_PROFILE(regs); |
544 | #else |
545 | void* value = linkRegisterImpl(const_cast<PlatformRegisters&>(regs)); |
546 | #endif |
547 | return MacroAssemblerCodePtr<PlatformRegistersLRPtrTag>(value); |
548 | } |
549 | |
550 | inline void setLinkRegister(PlatformRegisters& regs, MacroAssemblerCodePtr<CFunctionPtrTag> value) |
551 | { |
552 | #if USE(PLATFORM_REGISTERS_WITH_PROFILE) |
553 | WTF_WRITE_PLATFORM_REGISTERS_PC_WITH_PROFILE(regs, value.executableAddress()); |
554 | #else |
555 | linkRegisterImpl(regs) = value.executableAddress(); |
556 | #endif |
557 | } |
558 | #endif // OS(DARWIN) && __DARWIN_UNIX03 && CPU(ARM64) |
559 | |
560 | #if HAVE(MACHINE_CONTEXT) |
561 | template<> void*& argumentPointer<1>(mcontext_t&); |
562 | #endif |
563 | |
564 | template<> |
565 | inline void*& argumentPointer<1>(PlatformRegisters& regs) |
566 | { |
567 | #if OS(DARWIN) |
568 | #if __DARWIN_UNIX03 |
569 | |
570 | #if CPU(X86) |
571 | return reinterpret_cast<void*&>(regs.__edx); |
572 | #elif CPU(X86_64) |
573 | return reinterpret_cast<void*&>(regs.__rsi); |
574 | #elif CPU(ARM_THUMB2) || CPU(ARM) |
575 | return reinterpret_cast<void*&>(regs.__r[1]); |
576 | #elif CPU(ARM64) |
577 | return reinterpret_cast<void*&>(regs.__x[1]); |
578 | #else |
579 | #error Unknown Architecture |
580 | #endif |
581 | |
582 | #else // !__DARWIN_UNIX03 |
583 | |
584 | #if CPU(X86) |
585 | return reinterpret_cast<void*&>(regs.edx); |
586 | #elif CPU(X86_64) |
587 | return reinterpret_cast<void*&>(regs.rsi); |
588 | #else |
589 | #error Unknown Architecture |
590 | #endif |
591 | |
592 | #endif // __DARWIN_UNIX03 |
593 | |
594 | #elif OS(WINDOWS) |
595 | |
596 | #if CPU(ARM) |
597 | return reinterpret_cast<void*&>((uintptr_t&) regs.R1); |
598 | #elif CPU(MIPS) |
599 | #error Dont know what to do with mips. Do we even need this? |
600 | #elif CPU(X86) |
601 | return reinterpret_cast<void*&>((uintptr_t&) regs.Edx); |
602 | #elif CPU(X86_64) |
603 | return reinterpret_cast<void*&>((uintptr_t&) regs.Rdx); |
604 | #else |
605 | #error Unknown Architecture |
606 | #endif |
607 | |
608 | #elif HAVE(MACHINE_CONTEXT) |
609 | return argumentPointer<1>(regs.machineContext); |
610 | #endif |
611 | } |
612 | |
613 | template<size_t N> |
614 | inline void* argumentPointer(const PlatformRegisters& regs) |
615 | { |
616 | return argumentPointer<N>(const_cast<PlatformRegisters&>(regs)); |
617 | } |
618 | #endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
619 | |
620 | #if HAVE(MACHINE_CONTEXT) |
621 | template<> |
622 | inline void*& argumentPointer<1>(mcontext_t& machineContext) |
623 | { |
624 | #if OS(DARWIN) |
625 | return argumentPointer<1>(machineContext->__ss); |
626 | #elif OS(FREEBSD) |
627 | |
628 | #if CPU(X86) |
629 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_edx); |
630 | #elif CPU(X86_64) |
631 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_rsi); |
632 | #elif CPU(ARM) |
633 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_R1]); |
634 | #elif CPU(ARM64) |
635 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_x[1]); |
636 | #elif CPU(MIPS) |
637 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[5]); |
638 | #else |
639 | #error Unknown Architecture |
640 | #endif |
641 | |
642 | #elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__) |
643 | |
644 | // The following sequence depends on glibc's sys/ucontext.h. |
645 | #if CPU(X86) |
646 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_EDX]); |
647 | #elif CPU(X86_64) |
648 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_RSI]); |
649 | #elif CPU(ARM) |
650 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_r1); |
651 | #elif CPU(ARM64) |
652 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.regs[1]); |
653 | #elif CPU(MIPS) |
654 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[5]); |
655 | #else |
656 | #error Unknown Architecture |
657 | #endif |
658 | |
659 | #else |
660 | #error Need a way to get the frame pointer for another thread on this platform |
661 | #endif |
662 | } |
663 | |
664 | template<unsigned N> |
665 | inline void* argumentPointer(const mcontext_t& machineContext) |
666 | { |
667 | return argumentPointer<N>(const_cast<mcontext_t&>(machineContext)); |
668 | } |
669 | #endif // HAVE(MACHINE_CONTEXT) |
670 | |
671 | #if !ENABLE(C_LOOP) |
672 | #if OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
673 | inline void*& llintInstructionPointer(PlatformRegisters& regs) |
674 | { |
675 | // LLInt uses regT4 as PC. |
676 | #if OS(DARWIN) |
677 | #if __DARWIN_UNIX03 |
678 | |
679 | #if CPU(X86) |
680 | static_assert(LLInt::LLIntPC == X86Registers::esi, "Wrong LLInt PC." ); |
681 | return reinterpret_cast<void*&>(regs.__esi); |
682 | #elif CPU(X86_64) |
683 | static_assert(LLInt::LLIntPC == X86Registers::r8, "Wrong LLInt PC." ); |
684 | return reinterpret_cast<void*&>(regs.__r8); |
685 | #elif CPU(ARM) |
686 | static_assert(LLInt::LLIntPC == ARMRegisters::r8, "Wrong LLInt PC." ); |
687 | return reinterpret_cast<void*&>(regs.__r[8]); |
688 | #elif CPU(ARM64) |
689 | static_assert(LLInt::LLIntPC == ARM64Registers::x4, "Wrong LLInt PC." ); |
690 | return reinterpret_cast<void*&>(regs.__x[4]); |
691 | #else |
692 | #error Unknown Architecture |
693 | #endif |
694 | |
695 | #else // !__DARWIN_UNIX03 |
696 | #if CPU(X86) |
697 | static_assert(LLInt::LLIntPC == X86Registers::esi, "Wrong LLInt PC." ); |
698 | return reinterpret_cast<void*&>(regs.esi); |
699 | #elif CPU(X86_64) |
700 | static_assert(LLInt::LLIntPC == X86Registers::r8, "Wrong LLInt PC." ); |
701 | return reinterpret_cast<void*&>(regs.r8); |
702 | #else |
703 | #error Unknown Architecture |
704 | #endif |
705 | |
706 | #endif // __DARWIN_UNIX03 |
707 | |
708 | #elif OS(WINDOWS) |
709 | |
710 | #if CPU(ARM) |
711 | static_assert(LLInt::LLIntPC == ARMRegisters::r8, "Wrong LLInt PC." ); |
712 | return reinterpret_cast<void*&>((uintptr_t&) regs.R8); |
713 | #elif CPU(MIPS) |
714 | #error Dont know what to do with mips. Do we even need this? |
715 | #elif CPU(X86) |
716 | static_assert(LLInt::LLIntPC == X86Registers::esi, "Wrong LLInt PC." ); |
717 | return reinterpret_cast<void*&>((uintptr_t&) regs.Esi); |
718 | #elif CPU(X86_64) |
719 | static_assert(LLInt::LLIntPC == X86Registers::r10, "Wrong LLInt PC." ); |
720 | return reinterpret_cast<void*&>((uintptr_t&) regs.R10); |
721 | #else |
722 | #error Unknown Architecture |
723 | #endif |
724 | |
725 | #elif HAVE(MACHINE_CONTEXT) |
726 | return llintInstructionPointer(regs.machineContext); |
727 | #endif |
728 | } |
729 | |
730 | inline void* llintInstructionPointer(const PlatformRegisters& regs) |
731 | { |
732 | return llintInstructionPointer(const_cast<PlatformRegisters&>(regs)); |
733 | } |
734 | #endif // OS(WINDOWS) || HAVE(MACHINE_CONTEXT) |
735 | |
736 | |
737 | #if HAVE(MACHINE_CONTEXT) |
738 | inline void*& llintInstructionPointer(mcontext_t& machineContext) |
739 | { |
740 | // LLInt uses regT4 as PC. |
741 | #if OS(DARWIN) |
742 | return llintInstructionPointer(machineContext->__ss); |
743 | #elif OS(FREEBSD) |
744 | |
745 | #if CPU(X86) |
746 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_esi); |
747 | #elif CPU(X86_64) |
748 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_r8); |
749 | #elif CPU(ARM) |
750 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.__gregs[_REG_R8]); |
751 | #elif CPU(ARM64) |
752 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_gpregs.gp_x[4]); |
753 | #elif CPU(MIPS) |
754 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.mc_regs[12]); |
755 | #else |
756 | #error Unknown Architecture |
757 | #endif |
758 | |
759 | #elif OS(FUCHSIA) || defined(__GLIBC__) || defined(__BIONIC__) |
760 | |
761 | // The following sequence depends on glibc's sys/ucontext.h. |
762 | #if CPU(X86) |
763 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_ESI]); |
764 | #elif CPU(X86_64) |
765 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[REG_R8]); |
766 | #elif CPU(ARM) |
767 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.arm_r8); |
768 | #elif CPU(ARM64) |
769 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.regs[4]); |
770 | #elif CPU(MIPS) |
771 | return reinterpret_cast<void*&>((uintptr_t&) machineContext.gregs[12]); |
772 | #else |
773 | #error Unknown Architecture |
774 | #endif |
775 | |
776 | #else |
777 | #error Need a way to get the LLIntPC for another thread on this platform |
778 | #endif |
779 | } |
780 | |
781 | inline void* llintInstructionPointer(const mcontext_t& machineContext) |
782 | { |
783 | return llintInstructionPointer(const_cast<mcontext_t&>(machineContext)); |
784 | } |
785 | #endif // HAVE(MACHINE_CONTEXT) |
786 | #endif // !ENABLE(C_LOOP) |
787 | |
788 | } |
789 | } |
790 | |