ReXGlue SDK
Loading...
Searching...
No Matches
exception_handler.h
Go to the documentation of this file.
1
12
13#pragma once
14
15#include <functional>
16#include <vector>
17
18#include <rex/assert.h>
19#include <rex/platform.h>
20#include <rex/types.h>
21
22#if !REX_PLATFORM_WIN32
23#include <signal.h>
24#endif
25
26namespace rex::platform {
27
28struct alignas(16) VectorRegister {
29 u8 bytes[16];
30};
31
33enum class ARM64Register : u8 {
34 kX0,
35 kX1,
36 kX2,
37 kX3,
38 kX4,
39 kX5,
40 kX6,
41 kX7,
42 kX8,
43 kX9,
44 kX10,
45 kX11,
46 kX12,
47 kX13,
48 kX14,
49 kX15,
50 kX16,
51 kX17,
52 kX18,
53 kX19,
54 kX20,
55 kX21,
56 kX22,
57 kX23,
58 kX24,
59 kX25,
60 kX26,
61 kX27,
62 kX28,
65 kSP,
66 kPC,
67 kPstate,
68 kFpsr,
69 kFpcr,
71 kV1,
72 kV2,
73 kV3,
74 kV4,
75 kV5,
76 kV6,
77 kV7,
78 kV8,
79 kV9,
80 kV10,
81 kV11,
82 kV12,
83 kV13,
84 kV14,
85 kV15,
86 kV16,
87 kV17,
88 kV18,
89 kV19,
90 kV20,
91 kV21,
92 kV22,
93 kV23,
94 kV24,
95 kV25,
96 kV26,
97 kV27,
98 kV28,
99 kV29,
100 kV30,
101 kV31,
102};
103
104#if REX_ARCH_AMD64
105
107enum class X64Register : u8 {
108 kRip,
109 kEflags,
110 kIntRegisterFirst,
111 kRax = kIntRegisterFirst,
112 kRcx,
113 kRdx,
114 kRbx,
115 kRsp,
116 kRbp,
117 kRsi,
118 kRdi,
119 kR8,
120 kR9,
121 kR10,
122 kR11,
123 kR12,
124 kR13,
125 kR14,
126 kR15,
127 kIntRegisterLast = kR15,
128 kXMM0,
129 kXMM1,
130 kXMM2,
131 kXMM3,
132 kXMM4,
133 kXMM5,
134 kXMM6,
135 kXMM7,
136 kXMM8,
137 kXMM9,
138 kXMM10,
139 kXMM11,
140 kXMM12,
141 kXMM13,
142 kXMM14,
143 kXMM15,
144};
145
146#endif // REX_ARCH_AMD64
147
148#if REX_ARCH_AMD64
149using HostRegister = X64Register;
150#elif REX_ARCH_ARM64
152#else
154enum class HostRegister {};
155#endif // REX_ARCH
156
159 public:
160#if REX_ARCH_AMD64
161 u64 rip;
162 u32 eflags;
163 union {
164 struct {
165 u64 rax;
166 u64 rcx;
167 u64 rdx;
168 u64 rbx;
169 u64 rsp;
170 u64 rbp;
171 u64 rsi;
172 u64 rdi;
173 u64 r8;
174 u64 r9;
175 u64 r10;
176 u64 r11;
177 u64 r12;
178 u64 r13;
179 u64 r14;
180 u64 r15;
181 };
182 u64 int_registers[16];
183 };
184 union {
185 struct {
186 VectorRegister xmm0;
187 VectorRegister xmm1;
188 VectorRegister xmm2;
189 VectorRegister xmm3;
190 VectorRegister xmm4;
191 VectorRegister xmm5;
192 VectorRegister xmm6;
193 VectorRegister xmm7;
194 VectorRegister xmm8;
195 VectorRegister xmm9;
196 VectorRegister xmm10;
197 VectorRegister xmm11;
198 VectorRegister xmm12;
199 VectorRegister xmm13;
200 VectorRegister xmm14;
201 VectorRegister xmm15;
202 };
203 VectorRegister xmm_registers[16];
204 };
205#elif REX_ARCH_ARM64
206 u64 x[31];
207 u64 sp;
208 u64 pc;
209 u64 pstate;
210 u32 fpsr;
211 u32 fpcr;
212 VectorRegister v[32];
213#endif // REX_ARCH
214};
215
216/*
217 * AArch64 load and store decoding based on VIXL.
218 * https://github.com/Linaro/vixl/blob/ae5957cd66517b3f31dbf37e9bf39db6594abfe3/src/aarch64/constants-aarch64.h
219 *
220 * Copyright 2015, VIXL authors
221 * All rights reserved.
222 *
223 * Redistribution and use in source and binary forms, with or without
224 * modification, are permitted provided that the following conditions are met:
225 *
226 * * Redistributions of source code must retain the above copyright notice,
227 * this list of conditions and the following disclaimer.
228 * * Redistributions in binary form must reproduce the above copyright notice,
229 * this list of conditions and the following disclaimer in the documentation
230 * and/or other materials provided with the distribution.
231 * * Neither the name of ARM Limited nor the names of its contributors may be
232 * used to endorse or promote products derived from this software without
233 * specific prior written permission.
234 *
235 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
236 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
237 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
238 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
239 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
240 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
241 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
242 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
243 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
244 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
245 */
246
248constexpr u32 kARM64LoadLiteralFMask = UINT32_C(0x3B000000);
249constexpr u32 kARM64LoadLiteralFixed = UINT32_C(0x18000000);
250
251constexpr u32 kARM64LoadStoreAnyFMask = UINT32_C(0x0A000000);
252constexpr u32 kARM64LoadStoreAnyFixed = UINT32_C(0x08000000);
253
254constexpr u32 kARM64LoadStorePairAnyFMask = UINT32_C(0x3A000000);
255constexpr u32 kARM64LoadStorePairAnyFixed = UINT32_C(0x28000000);
257constexpr u32 kARM64LoadStorePairLoadBit = UINT32_C(1) << 22;
258
260constexpr u32 kARM64LoadStoreMask = UINT32_C(0xC4C00000);
261
263enum class ARM64LoadStoreOp : u32 {
264 kSTRBW = UINT32_C(0x00000000),
265 kSTRHW = UINT32_C(0x40000000),
266 kSTRW = UINT32_C(0x80000000),
267 kSTRX = UINT32_C(0xC0000000),
268 kLDRBW = UINT32_C(0x00400000),
269 kLDRHW = UINT32_C(0x40400000),
270 kLDRW = UINT32_C(0x80400000),
271 kLDRX = UINT32_C(0xC0400000),
272 kLDRSBX = UINT32_C(0x00800000),
273 kLDRSHX = UINT32_C(0x40800000),
274 kLDRSWX = UINT32_C(0x80800000),
275 kLDRSBW = UINT32_C(0x00C00000),
276 kLDRSHW = UINT32_C(0x40C00000),
277 kSTRB = UINT32_C(0x04000000),
278 kSTRH = UINT32_C(0x44000000),
279 kSTRS = UINT32_C(0x84000000),
280 kSTRD = UINT32_C(0xC4000000),
281 kSTRQ = UINT32_C(0x04800000),
282 kLDRB = UINT32_C(0x04400000),
283 kLDRH = UINT32_C(0x44400000),
284 kLDRS = UINT32_C(0x84400000),
285 kLDRD = UINT32_C(0xC4400000),
286 kLDRQ = UINT32_C(0x04C00000),
287 kPRFM = UINT32_C(0xC0800000),
288};
289
291constexpr u32 kARM64LoadStoreOffsetFMask = UINT32_C(0x3B200C00);
292
295 kUnscaledOffset = UINT32_C(0x38000000),
296 kPostIndex = UINT32_C(0x38000400),
297 kPreIndex = UINT32_C(0x38000C00),
298 kRegisterOffset = UINT32_C(0x38200800),
299};
300
302constexpr u32 kARM64LoadStoreUnsignedOffsetFMask = UINT32_C(0x3B000000);
303constexpr u32 kARM64LoadStoreUnsignedOffsetFixed = UINT32_C(0x39000000);
304
312REX_API bool IsARM64LoadPrefetchStore(u32 instruction, bool& is_store_out);
313
316 public:
317 enum class Code : u8 {
318 kInvalidException = 0,
319 kAccessViolation,
320 kIllegalInstruction,
321 };
322
323 enum class AccessViolationOperation : u8 {
324 kUnknown,
325 kRead,
326 kWrite,
327 };
328
334 void InitializeAccessViolation(HostThreadContext* thread_context, u64 fault_address,
335 AccessViolationOperation operation) {
336 code_ = Code::kAccessViolation;
337 thread_context_ = thread_context;
338 fault_address_ = fault_address;
339 access_violation_operation_ = operation;
340 }
341
342 void InitializeIllegalInstruction(HostThreadContext* thread_context) {
343 code_ = Code::kIllegalInstruction;
344 thread_context_ = thread_context;
345 }
346
347 Code GetCode() const { return code_; }
348
353 HostThreadContext* GetThreadContext() const { return thread_context_; }
354
355 u64 GetPC() const {
356#if REX_ARCH_AMD64
357 return thread_context_->rip;
358#elif REX_ARCH_ARM64
359 return thread_context_->pc;
360#else
362 return 0;
363#endif // REX_ARCH
364 }
365
366 void SetResumePC(u64 pc) {
367#if REX_ARCH_AMD64
368 thread_context_->rip = pc;
369#elif REX_ARCH_ARM64
370 thread_context_->pc = pc;
371#else
373#endif // REX_ARCH
374 }
375
376#if REX_ARCH_AMD64
382 u64& ModifyIntRegister(u32 index) {
383 REX_ASSERT(index <= 15);
384 modified_int_registers_ |= UINT16_C(1) << index;
385 return thread_context_->int_registers[index];
386 }
387
389 u16 GetModifiedIntRegisters() const { return modified_int_registers_; }
390
396 VectorRegister& ModifyXMMRegister(u32 index) {
397 REX_ASSERT(index <= 15);
398 modified_xmm_registers_ |= UINT16_C(1) << index;
399 return thread_context_->xmm_registers[index];
400 }
401
405 u16 GetModifiedXMMRegisters() const { return modified_xmm_registers_; }
406#elif REX_ARCH_ARM64
412 u64& ModifyXRegister(u32 index) {
413 REX_ASSERT(index <= 30);
414 modified_x_registers_ |= UINT32_C(1) << index;
415 return thread_context_->x[index];
416 }
417
421 u32 GetModifiedXRegisters() const { return modified_x_registers_; }
422
428 VectorRegister& ModifyVRegister(u32 index) {
429 REX_ASSERT(index <= 31);
430 modified_v_registers_ |= UINT32_C(1) << index;
431 return thread_context_->v[index];
432 }
433
437 u32 GetModifiedVRegisters() const { return modified_v_registers_; }
438#endif // REX_ARCH
439
441 u64 GetFaultAddress() const { return fault_address_; }
442
443 AccessViolationOperation GetAccessViolationOperation() const {
444 return access_violation_operation_;
445 }
446
447 private:
449 HostThreadContext* thread_context_ = nullptr;
450#if REX_ARCH_AMD64
451 u16 modified_int_registers_ = 0;
452 u16 modified_xmm_registers_ = 0;
453#elif REX_ARCH_ARM64
454 u32 modified_x_registers_ = 0;
455 u32 modified_v_registers_ = 0;
456#endif // REX_ARCH
457 u64 fault_address_ = 0;
458 AccessViolationOperation access_violation_operation_ = AccessViolationOperation::kUnknown;
459};
460
463 public:
468 using Handler = bool (*)(Exception* ex, void* data);
469
471 static void Install(Handler fn, void* data);
472
478 static void Uninstall(Handler fn, void* data);
479};
480
481#if !REX_PLATFORM_WIN32
487REX_API u64 SignalPC(void* signal_context);
488
495REX_API void ReportFatalSignal(int signal_number, siginfo_t* info, void* signal_context);
496
503REX_API void ForwardSignal(struct sigaction& original, int signal_number, siginfo_t* info,
504 void* signal_context);
505
509[[noreturn]] REX_API void DieWithDefaultDisposition(int signal_number);
510#endif
511
512} // namespace rex::platform
#define REX_ASSERT_ALWAYS(...)
Definition assert.h:102
#define REX_ASSERT(cond,...)
Definition assert.h:84
Definition exception_handler.h:462
static void Uninstall(Handler fn, void *data)
bool(*)(Exception *ex, void *data) Handler
Definition exception_handler.h:468
static void Install(Handler fn, void *data)
Definition exception_handler.h:315
void InitializeAccessViolation(HostThreadContext *thread_context, u64 fault_address, AccessViolationOperation operation)
Definition exception_handler.h:334
u64 GetFaultAddress() const
Definition exception_handler.h:441
HostThreadContext * GetThreadContext() const
Definition exception_handler.h:353
Code
Definition exception_handler.h:317
@ kInvalidException
Definition exception_handler.h:318
Definition exception_handler.h:158
Definition platform.h:345
void ForwardSignal(struct sigaction &original, int signal_number, siginfo_t *info, void *signal_context)
constexpr u32 kARM64LoadStoreUnsignedOffsetFMask
Definition exception_handler.h:302
void DieWithDefaultDisposition(int signal_number)
constexpr u32 kARM64LoadStorePairLoadBit
Definition exception_handler.h:257
void ReportFatalSignal(int signal_number, siginfo_t *info, void *signal_context)
@ kRead
Definition socket.h:49
@ kWrite
Definition socket.h:50
constexpr u32 kARM64LoadStoreMask
Definition exception_handler.h:260
constexpr u32 kARM64LoadStoreOffsetFMask
Definition exception_handler.h:291
constexpr u32 kARM64LoadLiteralFMask
Definition exception_handler.h:248
ARM64LoadStoreOp
Definition exception_handler.h:263
@ kSTRS
Definition exception_handler.h:279
@ kLDRX
Definition exception_handler.h:271
@ kSTRHW
Definition exception_handler.h:265
@ kSTRBW
Definition exception_handler.h:264
@ kSTRW
Definition exception_handler.h:266
@ kLDRSBW
Definition exception_handler.h:275
@ kSTRD
Definition exception_handler.h:280
@ kLDRSHW
Definition exception_handler.h:276
@ kSTRQ
Definition exception_handler.h:281
@ kLDRBW
Definition exception_handler.h:268
@ kLDRB
Definition exception_handler.h:282
@ kLDRSHX
Definition exception_handler.h:273
@ kLDRSWX
Definition exception_handler.h:274
@ kSTRX
Definition exception_handler.h:267
@ kLDRHW
Definition exception_handler.h:269
@ kLDRQ
Definition exception_handler.h:286
@ kLDRW
Definition exception_handler.h:270
@ kSTRH
Definition exception_handler.h:278
@ kLDRSBX
Definition exception_handler.h:272
@ kPRFM
Definition exception_handler.h:287
@ kLDRS
Definition exception_handler.h:284
@ kSTRB
Definition exception_handler.h:277
@ kLDRH
Definition exception_handler.h:283
@ kLDRD
Definition exception_handler.h:285
u64 SignalPC(void *signal_context)
ARM64Register
Definition exception_handler.h:33
@ kX30
Definition exception_handler.h:64
@ kX29
Definition exception_handler.h:63
@ kV0
Definition exception_handler.h:70
ARM64LoadStoreOffsetFixed
Definition exception_handler.h:294
@ kPostIndex
Definition exception_handler.h:296
@ kUnscaledOffset
Definition exception_handler.h:295
@ kPreIndex
Definition exception_handler.h:297
bool IsARM64LoadPrefetchStore(u32 instruction, bool &is_store_out)
HostRegister
Definition exception_handler.h:154
Platform flags, packing macros and export markers.
#define REX_API
Definition platform.h:177
Definition exception_handler.h:28
Integer types, byte order wrappers and size literals.