Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libunwind/src/Unwind-EHABI.cpp
35148 views
1
//===----------------------------------------------------------------------===//
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
// Implements ARM zero-cost C++ exceptions
9
//
10
//===----------------------------------------------------------------------===//
11
12
#include "Unwind-EHABI.h"
13
14
#if defined(_LIBUNWIND_ARM_EHABI)
15
16
#include <inttypes.h>
17
#include <stdbool.h>
18
#include <stdint.h>
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <string.h>
22
23
#include "config.h"
24
#include "libunwind.h"
25
#include "libunwind_ext.h"
26
#include "unwind.h"
27
28
namespace {
29
30
// Strange order: take words in order, but inside word, take from most to least
31
// signinficant byte.
32
uint8_t getByte(const uint32_t* data, size_t offset) {
33
const uint8_t* byteData = reinterpret_cast<const uint8_t*>(data);
34
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
35
return byteData[(offset & ~(size_t)0x03) + (3 - (offset & (size_t)0x03))];
36
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
37
return byteData[offset];
38
#else
39
#error "Unable to determine endianess"
40
#endif
41
}
42
43
const char* getNextWord(const char* data, uint32_t* out) {
44
*out = *reinterpret_cast<const uint32_t*>(data);
45
return data + 4;
46
}
47
48
const char* getNextNibble(const char* data, uint32_t* out) {
49
*out = *reinterpret_cast<const uint16_t*>(data);
50
return data + 2;
51
}
52
53
struct Descriptor {
54
// See # 9.2
55
typedef enum {
56
SU16 = 0, // Short descriptor, 16-bit entries
57
LU16 = 1, // Long descriptor, 16-bit entries
58
LU32 = 3, // Long descriptor, 32-bit entries
59
RESERVED0 = 4, RESERVED1 = 5, RESERVED2 = 6, RESERVED3 = 7,
60
RESERVED4 = 8, RESERVED5 = 9, RESERVED6 = 10, RESERVED7 = 11,
61
RESERVED8 = 12, RESERVED9 = 13, RESERVED10 = 14, RESERVED11 = 15
62
} Format;
63
64
// See # 9.2
65
typedef enum {
66
CLEANUP = 0x0,
67
FUNC = 0x1,
68
CATCH = 0x2,
69
INVALID = 0x4
70
} Kind;
71
};
72
73
_Unwind_Reason_Code ProcessDescriptors(
74
_Unwind_State state,
75
_Unwind_Control_Block* ucbp,
76
struct _Unwind_Context* context,
77
Descriptor::Format format,
78
const char* descriptorStart,
79
uint32_t flags) {
80
81
// EHT is inlined in the index using compact form. No descriptors. #5
82
if (flags & 0x1)
83
return _URC_CONTINUE_UNWIND;
84
85
// TODO: We should check the state here, and determine whether we need to
86
// perform phase1 or phase2 unwinding.
87
(void)state;
88
89
const char* descriptor = descriptorStart;
90
uint32_t descriptorWord;
91
getNextWord(descriptor, &descriptorWord);
92
while (descriptorWord) {
93
// Read descriptor based on # 9.2.
94
uint32_t length;
95
uint32_t offset;
96
switch (format) {
97
case Descriptor::LU32:
98
descriptor = getNextWord(descriptor, &length);
99
descriptor = getNextWord(descriptor, &offset);
100
break;
101
case Descriptor::LU16:
102
descriptor = getNextNibble(descriptor, &length);
103
descriptor = getNextNibble(descriptor, &offset);
104
break;
105
default:
106
assert(false);
107
return _URC_FAILURE;
108
}
109
110
// See # 9.2 table for decoding the kind of descriptor. It's a 2-bit value.
111
Descriptor::Kind kind =
112
static_cast<Descriptor::Kind>((length & 0x1) | ((offset & 0x1) << 1));
113
114
// Clear off flag from last bit.
115
length &= ~1u;
116
offset &= ~1u;
117
uintptr_t scopeStart = ucbp->pr_cache.fnstart + offset;
118
uintptr_t scopeEnd = scopeStart + length;
119
uintptr_t pc = _Unwind_GetIP(context);
120
bool isInScope = (scopeStart <= pc) && (pc < scopeEnd);
121
122
switch (kind) {
123
case Descriptor::CLEANUP: {
124
// TODO(ajwong): Handle cleanup descriptors.
125
break;
126
}
127
case Descriptor::FUNC: {
128
// TODO(ajwong): Handle function descriptors.
129
break;
130
}
131
case Descriptor::CATCH: {
132
// Catch descriptors require gobbling one more word.
133
uint32_t landing_pad;
134
descriptor = getNextWord(descriptor, &landing_pad);
135
136
if (isInScope) {
137
// TODO(ajwong): This is only phase1 compatible logic. Implement
138
// phase2.
139
landing_pad = signExtendPrel31(landing_pad & ~0x80000000);
140
if (landing_pad == 0xffffffff) {
141
return _URC_HANDLER_FOUND;
142
} else if (landing_pad == 0xfffffffe) {
143
return _URC_FAILURE;
144
} else {
145
/*
146
bool is_reference_type = landing_pad & 0x80000000;
147
void* matched_object;
148
if (__cxxabiv1::__cxa_type_match(
149
ucbp, reinterpret_cast<const std::type_info *>(landing_pad),
150
is_reference_type,
151
&matched_object) != __cxxabiv1::ctm_failed)
152
return _URC_HANDLER_FOUND;
153
*/
154
_LIBUNWIND_ABORT("Type matching not implemented");
155
}
156
}
157
break;
158
}
159
default:
160
_LIBUNWIND_ABORT("Invalid descriptor kind found.");
161
}
162
163
getNextWord(descriptor, &descriptorWord);
164
}
165
166
return _URC_CONTINUE_UNWIND;
167
}
168
169
static _Unwind_Reason_Code unwindOneFrame(_Unwind_State state,
170
_Unwind_Control_Block* ucbp,
171
struct _Unwind_Context* context) {
172
// Read the compact model EHT entry's header # 6.3
173
const uint32_t* unwindingData = ucbp->pr_cache.ehtp;
174
assert((*unwindingData & 0xf0000000) == 0x80000000 && "Must be a compact entry");
175
Descriptor::Format format =
176
static_cast<Descriptor::Format>((*unwindingData & 0x0f000000) >> 24);
177
178
const char *lsda =
179
reinterpret_cast<const char *>(_Unwind_GetLanguageSpecificData(context));
180
181
// Handle descriptors before unwinding so they are processed in the context
182
// of the correct stack frame.
183
_Unwind_Reason_Code result =
184
ProcessDescriptors(state, ucbp, context, format, lsda,
185
ucbp->pr_cache.additional);
186
187
if (result != _URC_CONTINUE_UNWIND)
188
return result;
189
190
switch (__unw_step(reinterpret_cast<unw_cursor_t *>(context))) {
191
case UNW_STEP_SUCCESS:
192
return _URC_CONTINUE_UNWIND;
193
case UNW_STEP_END:
194
return _URC_END_OF_STACK;
195
default:
196
return _URC_FAILURE;
197
}
198
}
199
200
// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_CORE /
201
// _UVRSD_UINT32.
202
uint32_t RegisterMask(uint8_t start, uint8_t count_minus_one) {
203
return ((1U << (count_minus_one + 1)) - 1) << start;
204
}
205
206
// Generates mask discriminator for _Unwind_VRS_Pop, e.g. for _UVRSC_VFP /
207
// _UVRSD_DOUBLE.
208
uint32_t RegisterRange(uint8_t start, uint8_t count_minus_one) {
209
return ((uint32_t)start << 16) | ((uint32_t)count_minus_one + 1);
210
}
211
212
} // end anonymous namespace
213
214
/**
215
* Decodes an EHT entry.
216
*
217
* @param data Pointer to EHT.
218
* @param[out] off Offset from return value (in bytes) to begin interpretation.
219
* @param[out] len Number of bytes in unwind code.
220
* @return Pointer to beginning of unwind code.
221
*/
222
extern "C" const uint32_t*
223
decode_eht_entry(const uint32_t* data, size_t* off, size_t* len) {
224
if ((*data & 0x80000000) == 0) {
225
// 6.2: Generic Model
226
//
227
// EHT entry is a prel31 pointing to the PR, followed by data understood
228
// only by the personality routine. Fortunately, all existing assembler
229
// implementations, including GNU assembler, LLVM integrated assembler,
230
// and ARM assembler, assume that the unwind opcodes come after the
231
// personality rountine address.
232
*off = 1; // First byte is size data.
233
*len = (((data[1] >> 24) & 0xff) + 1) * 4;
234
data++; // Skip the first word, which is the prel31 offset.
235
} else {
236
// 6.3: ARM Compact Model
237
//
238
// EHT entries here correspond to the __aeabi_unwind_cpp_pr[012] PRs indeed
239
// by format:
240
Descriptor::Format format =
241
static_cast<Descriptor::Format>((*data & 0x0f000000) >> 24);
242
switch (format) {
243
case Descriptor::SU16:
244
*len = 4;
245
*off = 1;
246
break;
247
case Descriptor::LU16:
248
case Descriptor::LU32:
249
*len = 4 + 4 * ((*data & 0x00ff0000) >> 16);
250
*off = 2;
251
break;
252
default:
253
return nullptr;
254
}
255
}
256
return data;
257
}
258
259
_LIBUNWIND_EXPORT _Unwind_Reason_Code
260
_Unwind_VRS_Interpret(_Unwind_Context *context, const uint32_t *data,
261
size_t offset, size_t len) {
262
bool wrotePC = false;
263
bool finish = false;
264
bool hasReturnAddrAuthCode = false;
265
while (offset < len && !finish) {
266
uint8_t byte = getByte(data, offset++);
267
if ((byte & 0x80) == 0) {
268
uint32_t sp;
269
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
270
if (byte & 0x40)
271
sp -= (((uint32_t)byte & 0x3f) << 2) + 4;
272
else
273
sp += ((uint32_t)byte << 2) + 4;
274
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
275
} else {
276
switch (byte & 0xf0) {
277
case 0x80: {
278
if (offset >= len)
279
return _URC_FAILURE;
280
uint32_t registers =
281
(((uint32_t)byte & 0x0f) << 12) |
282
(((uint32_t)getByte(data, offset++)) << 4);
283
if (!registers)
284
return _URC_FAILURE;
285
if (registers & (1 << 15))
286
wrotePC = true;
287
_Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
288
break;
289
}
290
case 0x90: {
291
uint8_t reg = byte & 0x0f;
292
if (reg == 13 || reg == 15)
293
return _URC_FAILURE;
294
uint32_t sp;
295
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_R0 + reg,
296
_UVRSD_UINT32, &sp);
297
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
298
&sp);
299
break;
300
}
301
case 0xa0: {
302
uint32_t registers = RegisterMask(4, byte & 0x07);
303
if (byte & 0x08)
304
registers |= 1 << 14;
305
_Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
306
break;
307
}
308
case 0xb0: {
309
switch (byte) {
310
case 0xb0:
311
finish = true;
312
break;
313
case 0xb1: {
314
if (offset >= len)
315
return _URC_FAILURE;
316
uint8_t registers = getByte(data, offset++);
317
if (registers & 0xf0 || !registers)
318
return _URC_FAILURE;
319
_Unwind_VRS_Pop(context, _UVRSC_CORE, registers, _UVRSD_UINT32);
320
break;
321
}
322
case 0xb2: {
323
uint32_t addend = 0;
324
uint32_t shift = 0;
325
// This decodes a uleb128 value.
326
while (true) {
327
if (offset >= len)
328
return _URC_FAILURE;
329
uint32_t v = getByte(data, offset++);
330
addend |= (v & 0x7f) << shift;
331
if ((v & 0x80) == 0)
332
break;
333
shift += 7;
334
}
335
uint32_t sp;
336
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
337
&sp);
338
sp += 0x204 + (addend << 2);
339
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
340
&sp);
341
break;
342
}
343
case 0xb3: {
344
uint8_t v = getByte(data, offset++);
345
_Unwind_VRS_Pop(context, _UVRSC_VFP,
346
RegisterRange(static_cast<uint8_t>(v >> 4),
347
v & 0x0f), _UVRSD_VFPX);
348
break;
349
}
350
case 0xb4:
351
hasReturnAddrAuthCode = true;
352
_Unwind_VRS_Pop(context, _UVRSC_PSEUDO,
353
0 /* Return Address Auth Code */, _UVRSD_UINT32);
354
break;
355
case 0xb5:
356
case 0xb6:
357
case 0xb7:
358
return _URC_FAILURE;
359
default:
360
_Unwind_VRS_Pop(context, _UVRSC_VFP,
361
RegisterRange(8, byte & 0x07), _UVRSD_VFPX);
362
break;
363
}
364
break;
365
}
366
case 0xc0: {
367
switch (byte) {
368
#if defined(__ARM_WMMX)
369
case 0xc0:
370
case 0xc1:
371
case 0xc2:
372
case 0xc3:
373
case 0xc4:
374
case 0xc5:
375
_Unwind_VRS_Pop(context, _UVRSC_WMMXD,
376
RegisterRange(10, byte & 0x7), _UVRSD_DOUBLE);
377
break;
378
case 0xc6: {
379
uint8_t v = getByte(data, offset++);
380
uint8_t start = static_cast<uint8_t>(v >> 4);
381
uint8_t count_minus_one = v & 0xf;
382
if (start + count_minus_one >= 16)
383
return _URC_FAILURE;
384
_Unwind_VRS_Pop(context, _UVRSC_WMMXD,
385
RegisterRange(start, count_minus_one),
386
_UVRSD_DOUBLE);
387
break;
388
}
389
case 0xc7: {
390
uint8_t v = getByte(data, offset++);
391
if (!v || v & 0xf0)
392
return _URC_FAILURE;
393
_Unwind_VRS_Pop(context, _UVRSC_WMMXC, v, _UVRSD_DOUBLE);
394
break;
395
}
396
#endif
397
case 0xc8:
398
case 0xc9: {
399
uint8_t v = getByte(data, offset++);
400
uint8_t start =
401
static_cast<uint8_t>(((byte == 0xc8) ? 16 : 0) + (v >> 4));
402
uint8_t count_minus_one = v & 0xf;
403
if (start + count_minus_one >= 32)
404
return _URC_FAILURE;
405
_Unwind_VRS_Pop(context, _UVRSC_VFP,
406
RegisterRange(start, count_minus_one),
407
_UVRSD_DOUBLE);
408
break;
409
}
410
default:
411
return _URC_FAILURE;
412
}
413
break;
414
}
415
case 0xd0: {
416
if (byte & 0x08)
417
return _URC_FAILURE;
418
_Unwind_VRS_Pop(context, _UVRSC_VFP, RegisterRange(8, byte & 0x7),
419
_UVRSD_DOUBLE);
420
break;
421
}
422
default:
423
return _URC_FAILURE;
424
}
425
}
426
}
427
if (!wrotePC) {
428
uint32_t lr;
429
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_LR, _UVRSD_UINT32, &lr);
430
#ifdef __ARM_FEATURE_PAUTH
431
if (hasReturnAddrAuthCode) {
432
uint32_t sp;
433
uint32_t pac;
434
_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
435
_Unwind_VRS_Get(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
436
__asm__ __volatile__("autg %0, %1, %2" : : "r"(pac), "r"(lr), "r"(sp) :);
437
}
438
#else
439
(void)hasReturnAddrAuthCode;
440
#endif
441
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_IP, _UVRSD_UINT32, &lr);
442
}
443
return _URC_CONTINUE_UNWIND;
444
}
445
446
extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
447
__aeabi_unwind_cpp_pr0(_Unwind_State state, _Unwind_Control_Block *ucbp,
448
_Unwind_Context *context) {
449
return unwindOneFrame(state, ucbp, context);
450
}
451
452
extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
453
__aeabi_unwind_cpp_pr1(_Unwind_State state, _Unwind_Control_Block *ucbp,
454
_Unwind_Context *context) {
455
return unwindOneFrame(state, ucbp, context);
456
}
457
458
extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
459
__aeabi_unwind_cpp_pr2(_Unwind_State state, _Unwind_Control_Block *ucbp,
460
_Unwind_Context *context) {
461
return unwindOneFrame(state, ucbp, context);
462
}
463
464
static _Unwind_Reason_Code
465
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
466
// EHABI #7.3 discusses preserving the VRS in a "temporary VRS" during
467
// phase 1 and then restoring it to the "primary VRS" for phase 2. The
468
// effect is phase 2 doesn't see any of the VRS manipulations from phase 1.
469
// In this implementation, the phases don't share the VRS backing store.
470
// Instead, they are passed the original |uc| and they create a new VRS
471
// from scratch thus achieving the same effect.
472
__unw_init_local(cursor, uc);
473
474
// Walk each frame looking for a place to stop.
475
for (bool handlerNotFound = true; handlerNotFound;) {
476
477
// See if frame has code to run (has personality routine).
478
unw_proc_info_t frameInfo;
479
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
480
_LIBUNWIND_TRACE_UNWINDING(
481
"unwind_phase1(ex_ojb=%p): __unw_get_proc_info "
482
"failed => _URC_FATAL_PHASE1_ERROR",
483
static_cast<void *>(exception_object));
484
return _URC_FATAL_PHASE1_ERROR;
485
}
486
487
#ifndef NDEBUG
488
// When tracing, print state information.
489
if (_LIBUNWIND_TRACING_UNWINDING) {
490
char functionBuf[512];
491
const char *functionName = functionBuf;
492
unw_word_t offset;
493
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
494
&offset) != UNW_ESUCCESS) ||
495
(frameInfo.start_ip + offset > frameInfo.end_ip))
496
functionName = ".anonymous.";
497
unw_word_t pc;
498
__unw_get_reg(cursor, UNW_REG_IP, &pc);
499
_LIBUNWIND_TRACE_UNWINDING(
500
"unwind_phase1(ex_ojb=%p): pc=0x%" PRIxPTR ", start_ip=0x%" PRIxPTR ", func=%s, "
501
"lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
502
static_cast<void *>(exception_object), pc,
503
frameInfo.start_ip, functionName,
504
frameInfo.lsda, frameInfo.handler);
505
}
506
#endif
507
508
// If there is a personality routine, ask it if it will want to stop at
509
// this frame.
510
if (frameInfo.handler != 0) {
511
_Unwind_Personality_Fn p =
512
(_Unwind_Personality_Fn)(long)(frameInfo.handler);
513
_LIBUNWIND_TRACE_UNWINDING(
514
"unwind_phase1(ex_ojb=%p): calling personality function %p",
515
static_cast<void *>(exception_object),
516
reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p)));
517
struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
518
exception_object->pr_cache.fnstart = frameInfo.start_ip;
519
exception_object->pr_cache.ehtp =
520
(_Unwind_EHT_Header *)frameInfo.unwind_info;
521
exception_object->pr_cache.additional = frameInfo.flags;
522
_Unwind_Reason_Code personalityResult =
523
(*p)(_US_VIRTUAL_UNWIND_FRAME, exception_object, context);
524
_LIBUNWIND_TRACE_UNWINDING(
525
"unwind_phase1(ex_ojb=%p): personality result %d start_ip %x ehtp %p "
526
"additional %x",
527
static_cast<void *>(exception_object), personalityResult,
528
exception_object->pr_cache.fnstart,
529
static_cast<void *>(exception_object->pr_cache.ehtp),
530
exception_object->pr_cache.additional);
531
switch (personalityResult) {
532
case _URC_HANDLER_FOUND:
533
// found a catch clause or locals that need destructing in this frame
534
// stop search and remember stack pointer at the frame
535
handlerNotFound = false;
536
// p should have initialized barrier_cache. EHABI #7.3.5
537
_LIBUNWIND_TRACE_UNWINDING(
538
"unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND",
539
static_cast<void *>(exception_object));
540
return _URC_NO_REASON;
541
542
case _URC_CONTINUE_UNWIND:
543
_LIBUNWIND_TRACE_UNWINDING(
544
"unwind_phase1(ex_ojb=%p): _URC_CONTINUE_UNWIND",
545
static_cast<void *>(exception_object));
546
// continue unwinding
547
break;
548
549
// EHABI #7.3.3
550
case _URC_FAILURE:
551
return _URC_FAILURE;
552
553
default:
554
// something went wrong
555
_LIBUNWIND_TRACE_UNWINDING(
556
"unwind_phase1(ex_ojb=%p): _URC_FATAL_PHASE1_ERROR",
557
static_cast<void *>(exception_object));
558
return _URC_FATAL_PHASE1_ERROR;
559
}
560
}
561
}
562
return _URC_NO_REASON;
563
}
564
565
static _Unwind_Reason_Code unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor,
566
_Unwind_Exception *exception_object,
567
bool resume) {
568
// See comment at the start of unwind_phase1 regarding VRS integrity.
569
__unw_init_local(cursor, uc);
570
571
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)",
572
static_cast<void *>(exception_object));
573
int frame_count = 0;
574
575
// Walk each frame until we reach where search phase said to stop.
576
while (true) {
577
// Ask libunwind to get next frame (skip over first which is
578
// _Unwind_RaiseException or _Unwind_Resume).
579
//
580
// Resume only ever makes sense for 1 frame.
581
_Unwind_State state =
582
resume ? _US_UNWIND_FRAME_RESUME : _US_UNWIND_FRAME_STARTING;
583
if (resume && frame_count == 1) {
584
// On a resume, first unwind the _Unwind_Resume() frame. The next frame
585
// is now the landing pad for the cleanup from a previous execution of
586
// phase2. To continue unwindingly correctly, replace VRS[15] with the
587
// IP of the frame that the previous run of phase2 installed the context
588
// for. After this, continue unwinding as if normal.
589
//
590
// See #7.4.6 for details.
591
__unw_set_reg(cursor, UNW_REG_IP,
592
exception_object->unwinder_cache.reserved2);
593
resume = false;
594
}
595
596
// Get info about this frame.
597
unw_word_t sp;
598
unw_proc_info_t frameInfo;
599
__unw_get_reg(cursor, UNW_REG_SP, &sp);
600
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
601
_LIBUNWIND_TRACE_UNWINDING(
602
"unwind_phase2(ex_ojb=%p): __unw_get_proc_info "
603
"failed => _URC_FATAL_PHASE2_ERROR",
604
static_cast<void *>(exception_object));
605
return _URC_FATAL_PHASE2_ERROR;
606
}
607
608
#ifndef NDEBUG
609
// When tracing, print state information.
610
if (_LIBUNWIND_TRACING_UNWINDING) {
611
char functionBuf[512];
612
const char *functionName = functionBuf;
613
unw_word_t offset;
614
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
615
&offset) != UNW_ESUCCESS) ||
616
(frameInfo.start_ip + offset > frameInfo.end_ip))
617
functionName = ".anonymous.";
618
_LIBUNWIND_TRACE_UNWINDING(
619
"unwind_phase2(ex_ojb=%p): start_ip=0x%" PRIxPTR ", func=%s, sp=0x%" PRIxPTR ", "
620
"lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR "",
621
static_cast<void *>(exception_object), frameInfo.start_ip,
622
functionName, sp, frameInfo.lsda,
623
frameInfo.handler);
624
}
625
#endif
626
627
// If there is a personality routine, tell it we are unwinding.
628
if (frameInfo.handler != 0) {
629
_Unwind_Personality_Fn p =
630
(_Unwind_Personality_Fn)(intptr_t)(frameInfo.handler);
631
struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
632
// EHABI #7.2
633
exception_object->pr_cache.fnstart = frameInfo.start_ip;
634
exception_object->pr_cache.ehtp =
635
(_Unwind_EHT_Header *)frameInfo.unwind_info;
636
exception_object->pr_cache.additional = frameInfo.flags;
637
_Unwind_Reason_Code personalityResult =
638
(*p)(state, exception_object, context);
639
switch (personalityResult) {
640
case _URC_CONTINUE_UNWIND:
641
// Continue unwinding
642
_LIBUNWIND_TRACE_UNWINDING(
643
"unwind_phase2(ex_ojb=%p): _URC_CONTINUE_UNWIND",
644
static_cast<void *>(exception_object));
645
// EHABI #7.2
646
if (sp == exception_object->barrier_cache.sp) {
647
// Phase 1 said we would stop at this frame, but we did not...
648
_LIBUNWIND_ABORT("during phase1 personality function said it would "
649
"stop here, but now in phase2 it did not stop here");
650
}
651
break;
652
case _URC_INSTALL_CONTEXT:
653
_LIBUNWIND_TRACE_UNWINDING(
654
"unwind_phase2(ex_ojb=%p): _URC_INSTALL_CONTEXT",
655
static_cast<void *>(exception_object));
656
// Personality routine says to transfer control to landing pad.
657
// We may get control back if landing pad calls _Unwind_Resume().
658
if (_LIBUNWIND_TRACING_UNWINDING) {
659
unw_word_t pc;
660
__unw_get_reg(cursor, UNW_REG_IP, &pc);
661
__unw_get_reg(cursor, UNW_REG_SP, &sp);
662
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
663
"user code with ip=0x%" PRIxPTR ", sp=0x%" PRIxPTR,
664
static_cast<void *>(exception_object),
665
pc, sp);
666
}
667
668
{
669
// EHABI #7.4.1 says we need to preserve pc for when _Unwind_Resume
670
// is called back, to find this same frame.
671
unw_word_t pc;
672
__unw_get_reg(cursor, UNW_REG_IP, &pc);
673
exception_object->unwinder_cache.reserved2 = (uint32_t)pc;
674
}
675
__unw_resume(cursor);
676
// __unw_resume() only returns if there was an error.
677
return _URC_FATAL_PHASE2_ERROR;
678
679
// # EHABI #7.4.3
680
case _URC_FAILURE:
681
abort();
682
683
default:
684
// Personality routine returned an unknown result code.
685
_LIBUNWIND_DEBUG_LOG("personality function returned unknown result %d",
686
personalityResult);
687
return _URC_FATAL_PHASE2_ERROR;
688
}
689
}
690
frame_count++;
691
}
692
693
// Clean up phase did not resume at the frame that the search phase
694
// said it would...
695
return _URC_FATAL_PHASE2_ERROR;
696
}
697
698
static _Unwind_Reason_Code
699
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
700
_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
701
void *stop_parameter) {
702
bool endOfStack = false;
703
// See comment at the start of unwind_phase1 regarding VRS integrity.
704
__unw_init_local(cursor, uc);
705
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_force(ex_ojb=%p)",
706
static_cast<void *>(exception_object));
707
// Walk each frame until we reach where search phase said to stop
708
while (!endOfStack) {
709
// Update info about this frame.
710
unw_proc_info_t frameInfo;
711
if (__unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
712
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): __unw_get_proc_info "
713
"failed => _URC_END_OF_STACK",
714
(void *)exception_object);
715
return _URC_FATAL_PHASE2_ERROR;
716
}
717
718
#ifndef NDEBUG
719
// When tracing, print state information.
720
if (_LIBUNWIND_TRACING_UNWINDING) {
721
char functionBuf[512];
722
const char *functionName = functionBuf;
723
unw_word_t offset;
724
if ((__unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
725
&offset) != UNW_ESUCCESS) ||
726
(frameInfo.start_ip + offset > frameInfo.end_ip))
727
functionName = ".anonymous.";
728
_LIBUNWIND_TRACE_UNWINDING(
729
"unwind_phase2_forced(ex_ojb=%p): start_ip=0x%" PRIxPTR
730
", func=%s, lsda=0x%" PRIxPTR ", personality=0x%" PRIxPTR,
731
(void *)exception_object, frameInfo.start_ip, functionName,
732
frameInfo.lsda, frameInfo.handler);
733
}
734
#endif
735
736
// Call stop function at each frame.
737
_Unwind_Action action =
738
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
739
_Unwind_Reason_Code stopResult =
740
(*stop)(1, action, exception_object->exception_class, exception_object,
741
(_Unwind_Context *)(cursor), stop_parameter);
742
_LIBUNWIND_TRACE_UNWINDING(
743
"unwind_phase2_forced(ex_ojb=%p): stop function returned %d",
744
(void *)exception_object, stopResult);
745
if (stopResult != _URC_NO_REASON) {
746
_LIBUNWIND_TRACE_UNWINDING(
747
"unwind_phase2_forced(ex_ojb=%p): stopped by stop function",
748
(void *)exception_object);
749
return _URC_FATAL_PHASE2_ERROR;
750
}
751
752
// If there is a personality routine, tell it we are unwinding.
753
if (frameInfo.handler != 0) {
754
_Unwind_Personality_Fn p =
755
(_Unwind_Personality_Fn)(uintptr_t)(frameInfo.handler);
756
struct _Unwind_Context *context = (struct _Unwind_Context *)(cursor);
757
// EHABI #7.2
758
exception_object->pr_cache.fnstart = frameInfo.start_ip;
759
exception_object->pr_cache.ehtp =
760
(_Unwind_EHT_Header *)frameInfo.unwind_info;
761
exception_object->pr_cache.additional = frameInfo.flags;
762
_Unwind_Reason_Code personalityResult =
763
(*p)(_US_FORCE_UNWIND | _US_UNWIND_FRAME_STARTING, exception_object,
764
context);
765
switch (personalityResult) {
766
case _URC_CONTINUE_UNWIND:
767
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
768
"personality returned "
769
"_URC_CONTINUE_UNWIND",
770
(void *)exception_object);
771
// Destructors called, continue unwinding
772
break;
773
case _URC_INSTALL_CONTEXT:
774
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
775
"personality returned "
776
"_URC_INSTALL_CONTEXT",
777
(void *)exception_object);
778
// We may get control back if landing pad calls _Unwind_Resume().
779
__unw_resume(cursor);
780
break;
781
case _URC_END_OF_STACK:
782
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
783
"personality returned "
784
"_URC_END_OF_STACK",
785
(void *)exception_object);
786
// Personalty routine did the step and it can't step forward.
787
endOfStack = true;
788
break;
789
default:
790
// Personality routine returned an unknown result code.
791
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
792
"personality returned %d, "
793
"_URC_FATAL_PHASE2_ERROR",
794
(void *)exception_object, personalityResult);
795
return _URC_FATAL_PHASE2_ERROR;
796
}
797
}
798
}
799
800
// Call stop function one last time and tell it we've reached the end
801
// of the stack.
802
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): calling stop "
803
"function with _UA_END_OF_STACK",
804
(void *)exception_object);
805
_Unwind_Action lastAction =
806
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
807
(*stop)(1, lastAction, exception_object->exception_class, exception_object,
808
(struct _Unwind_Context *)(cursor), stop_parameter);
809
810
// Clean up phase did not resume at the frame that the search phase said it
811
// would.
812
return _URC_FATAL_PHASE2_ERROR;
813
}
814
815
/// Called by __cxa_throw. Only returns if there is a fatal error.
816
_LIBUNWIND_EXPORT _Unwind_Reason_Code
817
_Unwind_RaiseException(_Unwind_Exception *exception_object) {
818
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)",
819
static_cast<void *>(exception_object));
820
unw_context_t uc;
821
unw_cursor_t cursor;
822
__unw_getcontext(&uc);
823
824
// This field for is for compatibility with GCC to say this isn't a forced
825
// unwind. EHABI #7.2
826
exception_object->unwinder_cache.reserved1 = 0;
827
828
// phase 1: the search phase
829
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
830
if (phase1 != _URC_NO_REASON)
831
return phase1;
832
833
// phase 2: the clean up phase
834
return unwind_phase2(&uc, &cursor, exception_object, false);
835
}
836
837
_LIBUNWIND_EXPORT void _Unwind_Complete(_Unwind_Exception* exception_object) {
838
// This is to be called when exception handling completes to give us a chance
839
// to perform any housekeeping. EHABI #7.2. But we have nothing to do here.
840
(void)exception_object;
841
}
842
843
/// When _Unwind_RaiseException() is in phase2, it hands control
844
/// to the personality function at each frame. The personality
845
/// may force a jump to a landing pad in that function, the landing
846
/// pad code may then call _Unwind_Resume() to continue with the
847
/// unwinding. Note: the call to _Unwind_Resume() is from compiler
848
/// generated user code. All other _Unwind_* routines are called
849
/// by the C++ runtime __cxa_* routines.
850
///
851
/// Note: re-throwing an exception (as opposed to continuing the unwind)
852
/// is implemented by having the code call __cxa_rethrow() which
853
/// in turn calls _Unwind_Resume_or_Rethrow().
854
_LIBUNWIND_EXPORT void
855
_Unwind_Resume(_Unwind_Exception *exception_object) {
856
_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)",
857
static_cast<void *>(exception_object));
858
unw_context_t uc;
859
unw_cursor_t cursor;
860
__unw_getcontext(&uc);
861
862
if (exception_object->unwinder_cache.reserved1)
863
unwind_phase2_forced(
864
&uc, &cursor, exception_object,
865
(_Unwind_Stop_Fn)exception_object->unwinder_cache.reserved1,
866
(void *)exception_object->unwinder_cache.reserved3);
867
else
868
unwind_phase2(&uc, &cursor, exception_object, true);
869
870
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
871
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
872
}
873
874
/// Called by personality handler during phase 2 to get LSDA for current frame.
875
_LIBUNWIND_EXPORT uintptr_t
876
_Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
877
unw_cursor_t *cursor = (unw_cursor_t *)context;
878
unw_proc_info_t frameInfo;
879
uintptr_t result = 0;
880
if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
881
result = (uintptr_t)frameInfo.lsda;
882
_LIBUNWIND_TRACE_API(
883
"_Unwind_GetLanguageSpecificData(context=%p) => 0x%llx",
884
static_cast<void *>(context), (long long)result);
885
return result;
886
}
887
888
// Only used in _LIBUNWIND_TRACE_API, which is a no-op when assertions are
889
// disabled.
890
[[gnu::unused]] static uint64_t
891
ValueAsBitPattern(_Unwind_VRS_DataRepresentation representation,
892
const void *valuep) {
893
uint64_t value = 0;
894
switch (representation) {
895
case _UVRSD_UINT32:
896
case _UVRSD_FLOAT:
897
memcpy(&value, valuep, sizeof(uint32_t));
898
break;
899
900
case _UVRSD_VFPX:
901
case _UVRSD_UINT64:
902
case _UVRSD_DOUBLE:
903
memcpy(&value, valuep, sizeof(uint64_t));
904
break;
905
}
906
return value;
907
}
908
909
_LIBUNWIND_EXPORT _Unwind_VRS_Result
910
_Unwind_VRS_Set(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
911
uint32_t regno, _Unwind_VRS_DataRepresentation representation,
912
void *valuep) {
913
_LIBUNWIND_TRACE_API("_Unwind_VRS_Set(context=%p, regclass=%d, reg=%d, "
914
"rep=%d, value=0x%llX)",
915
static_cast<void *>(context), regclass, regno,
916
representation,
917
ValueAsBitPattern(representation, valuep));
918
unw_cursor_t *cursor = (unw_cursor_t *)context;
919
switch (regclass) {
920
case _UVRSC_CORE:
921
if (representation != _UVRSD_UINT32 || regno > 15)
922
return _UVRSR_FAILED;
923
return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),
924
*(unw_word_t *)valuep) == UNW_ESUCCESS
925
? _UVRSR_OK
926
: _UVRSR_FAILED;
927
case _UVRSC_VFP:
928
if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
929
return _UVRSR_FAILED;
930
if (representation == _UVRSD_VFPX) {
931
// Can only touch d0-15 with FSTMFDX.
932
if (regno > 15)
933
return _UVRSR_FAILED;
934
__unw_save_vfp_as_X(cursor);
935
} else {
936
if (regno > 31)
937
return _UVRSR_FAILED;
938
}
939
return __unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),
940
*(unw_fpreg_t *)valuep) == UNW_ESUCCESS
941
? _UVRSR_OK
942
: _UVRSR_FAILED;
943
#if defined(__ARM_WMMX)
944
case _UVRSC_WMMXC:
945
if (representation != _UVRSD_UINT32 || regno > 3)
946
return _UVRSR_FAILED;
947
return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
948
*(unw_word_t *)valuep) == UNW_ESUCCESS
949
? _UVRSR_OK
950
: _UVRSR_FAILED;
951
case _UVRSC_WMMXD:
952
if (representation != _UVRSD_DOUBLE || regno > 31)
953
return _UVRSR_FAILED;
954
return __unw_set_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
955
*(unw_fpreg_t *)valuep) == UNW_ESUCCESS
956
? _UVRSR_OK
957
: _UVRSR_FAILED;
958
#else
959
case _UVRSC_WMMXC:
960
case _UVRSC_WMMXD:
961
break;
962
#endif
963
case _UVRSC_PSEUDO:
964
// There's only one pseudo-register, PAC, with regno == 0.
965
if (representation != _UVRSD_UINT32 || regno != 0)
966
return _UVRSR_FAILED;
967
return __unw_set_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE),
968
*(unw_word_t *)valuep) == UNW_ESUCCESS
969
? _UVRSR_OK
970
: _UVRSR_FAILED;
971
break;
972
}
973
_LIBUNWIND_ABORT("unsupported register class");
974
}
975
976
static _Unwind_VRS_Result
977
_Unwind_VRS_Get_Internal(_Unwind_Context *context,
978
_Unwind_VRS_RegClass regclass, uint32_t regno,
979
_Unwind_VRS_DataRepresentation representation,
980
void *valuep) {
981
unw_cursor_t *cursor = (unw_cursor_t *)context;
982
switch (regclass) {
983
case _UVRSC_CORE:
984
if (representation != _UVRSD_UINT32 || regno > 15)
985
return _UVRSR_FAILED;
986
return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_R0 + regno),
987
(unw_word_t *)valuep) == UNW_ESUCCESS
988
? _UVRSR_OK
989
: _UVRSR_FAILED;
990
case _UVRSC_VFP:
991
if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
992
return _UVRSR_FAILED;
993
if (representation == _UVRSD_VFPX) {
994
// Can only touch d0-15 with FSTMFDX.
995
if (regno > 15)
996
return _UVRSR_FAILED;
997
__unw_save_vfp_as_X(cursor);
998
} else {
999
if (regno > 31)
1000
return _UVRSR_FAILED;
1001
}
1002
return __unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_D0 + regno),
1003
(unw_fpreg_t *)valuep) == UNW_ESUCCESS
1004
? _UVRSR_OK
1005
: _UVRSR_FAILED;
1006
#if defined(__ARM_WMMX)
1007
case _UVRSC_WMMXC:
1008
if (representation != _UVRSD_UINT32 || regno > 3)
1009
return _UVRSR_FAILED;
1010
return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_WC0 + regno),
1011
(unw_word_t *)valuep) == UNW_ESUCCESS
1012
? _UVRSR_OK
1013
: _UVRSR_FAILED;
1014
case _UVRSC_WMMXD:
1015
if (representation != _UVRSD_DOUBLE || regno > 31)
1016
return _UVRSR_FAILED;
1017
return __unw_get_fpreg(cursor, (unw_regnum_t)(UNW_ARM_WR0 + regno),
1018
(unw_fpreg_t *)valuep) == UNW_ESUCCESS
1019
? _UVRSR_OK
1020
: _UVRSR_FAILED;
1021
#else
1022
case _UVRSC_WMMXC:
1023
case _UVRSC_WMMXD:
1024
break;
1025
#endif
1026
case _UVRSC_PSEUDO:
1027
// There's only one pseudo-register, PAC, with regno == 0.
1028
if (representation != _UVRSD_UINT32 || regno != 0)
1029
return _UVRSR_FAILED;
1030
return __unw_get_reg(cursor, (unw_regnum_t)(UNW_ARM_RA_AUTH_CODE),
1031
(unw_word_t *)valuep) == UNW_ESUCCESS
1032
? _UVRSR_OK
1033
: _UVRSR_FAILED;
1034
break;
1035
}
1036
_LIBUNWIND_ABORT("unsupported register class");
1037
}
1038
1039
_LIBUNWIND_EXPORT _Unwind_VRS_Result
1040
_Unwind_VRS_Get(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
1041
uint32_t regno, _Unwind_VRS_DataRepresentation representation,
1042
void *valuep) {
1043
_Unwind_VRS_Result result =
1044
_Unwind_VRS_Get_Internal(context, regclass, regno, representation,
1045
valuep);
1046
_LIBUNWIND_TRACE_API("_Unwind_VRS_Get(context=%p, regclass=%d, reg=%d, "
1047
"rep=%d, value=0x%llX, result = %d)",
1048
static_cast<void *>(context), regclass, regno,
1049
representation,
1050
ValueAsBitPattern(representation, valuep), result);
1051
return result;
1052
}
1053
1054
_Unwind_VRS_Result
1055
_Unwind_VRS_Pop(_Unwind_Context *context, _Unwind_VRS_RegClass regclass,
1056
uint32_t discriminator,
1057
_Unwind_VRS_DataRepresentation representation) {
1058
_LIBUNWIND_TRACE_API("_Unwind_VRS_Pop(context=%p, regclass=%d, "
1059
"discriminator=%d, representation=%d)",
1060
static_cast<void *>(context), regclass, discriminator,
1061
representation);
1062
switch (regclass) {
1063
case _UVRSC_WMMXC:
1064
#if !defined(__ARM_WMMX)
1065
break;
1066
#endif
1067
case _UVRSC_CORE: {
1068
if (representation != _UVRSD_UINT32)
1069
return _UVRSR_FAILED;
1070
// When popping SP from the stack, we don't want to override it from the
1071
// computed new stack location. See EHABI #7.5.4 table 3.
1072
bool poppedSP = false;
1073
uint32_t* sp;
1074
if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
1075
_UVRSD_UINT32, &sp) != _UVRSR_OK) {
1076
return _UVRSR_FAILED;
1077
}
1078
for (uint32_t i = 0; i < 16; ++i) {
1079
if (!(discriminator & static_cast<uint32_t>(1 << i)))
1080
continue;
1081
uint32_t value = *sp++;
1082
if (regclass == _UVRSC_CORE && i == 13)
1083
poppedSP = true;
1084
if (_Unwind_VRS_Set(context, regclass, i,
1085
_UVRSD_UINT32, &value) != _UVRSR_OK) {
1086
return _UVRSR_FAILED;
1087
}
1088
}
1089
if (!poppedSP) {
1090
return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP,
1091
_UVRSD_UINT32, &sp);
1092
}
1093
return _UVRSR_OK;
1094
}
1095
case _UVRSC_WMMXD:
1096
#if !defined(__ARM_WMMX)
1097
break;
1098
#endif
1099
case _UVRSC_VFP: {
1100
if (representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
1101
return _UVRSR_FAILED;
1102
uint32_t first = discriminator >> 16;
1103
uint32_t count = discriminator & 0xffff;
1104
uint32_t end = first+count;
1105
uint32_t* sp;
1106
if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP,
1107
_UVRSD_UINT32, &sp) != _UVRSR_OK) {
1108
return _UVRSR_FAILED;
1109
}
1110
// For _UVRSD_VFPX, we're assuming the data is stored in FSTMX "standard
1111
// format 1", which is equivalent to FSTMD + a padding word.
1112
for (uint32_t i = first; i < end; ++i) {
1113
// SP is only 32-bit aligned so don't copy 64-bit at a time.
1114
uint64_t w0 = *sp++;
1115
uint64_t w1 = *sp++;
1116
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
1117
uint64_t value = (w1 << 32) | w0;
1118
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
1119
uint64_t value = (w0 << 32) | w1;
1120
#else
1121
#error "Unable to determine endianess"
1122
#endif
1123
if (_Unwind_VRS_Set(context, regclass, i, representation, &value) !=
1124
_UVRSR_OK)
1125
return _UVRSR_FAILED;
1126
}
1127
if (representation == _UVRSD_VFPX)
1128
++sp;
1129
return _Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
1130
&sp);
1131
}
1132
case _UVRSC_PSEUDO: {
1133
if (representation != _UVRSD_UINT32 || discriminator != 0)
1134
return _UVRSR_FAILED;
1135
// Return Address Authentication code (PAC) - discriminator 0
1136
uint32_t *sp;
1137
if (_Unwind_VRS_Get(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32,
1138
&sp) != _UVRSR_OK) {
1139
return _UVRSR_FAILED;
1140
}
1141
uint32_t pac = *sp++;
1142
_Unwind_VRS_Set(context, _UVRSC_CORE, UNW_ARM_SP, _UVRSD_UINT32, &sp);
1143
return _Unwind_VRS_Set(context, _UVRSC_PSEUDO, 0, _UVRSD_UINT32, &pac);
1144
}
1145
}
1146
_LIBUNWIND_ABORT("unsupported register class");
1147
}
1148
1149
/// Not used by C++.
1150
/// Unwinds stack, calling "stop" function at each frame.
1151
/// Could be used to implement longjmp().
1152
_LIBUNWIND_EXPORT _Unwind_Reason_Code
1153
_Unwind_ForcedUnwind(_Unwind_Exception *exception_object, _Unwind_Stop_Fn stop,
1154
void *stop_parameter) {
1155
_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)",
1156
(void *)exception_object, (void *)(uintptr_t)stop);
1157
unw_context_t uc;
1158
unw_cursor_t cursor;
1159
__unw_getcontext(&uc);
1160
1161
// Mark that this is a forced unwind, so _Unwind_Resume() can do
1162
// the right thing.
1163
exception_object->unwinder_cache.reserved1 = (uintptr_t)stop;
1164
exception_object->unwinder_cache.reserved3 = (uintptr_t)stop_parameter;
1165
1166
return unwind_phase2_forced(&uc, &cursor, exception_object, stop,
1167
stop_parameter);
1168
}
1169
1170
/// Called by personality handler during phase 2 to find the start of the
1171
/// function.
1172
_LIBUNWIND_EXPORT uintptr_t
1173
_Unwind_GetRegionStart(struct _Unwind_Context *context) {
1174
unw_cursor_t *cursor = (unw_cursor_t *)context;
1175
unw_proc_info_t frameInfo;
1176
uintptr_t result = 0;
1177
if (__unw_get_proc_info(cursor, &frameInfo) == UNW_ESUCCESS)
1178
result = (uintptr_t)frameInfo.start_ip;
1179
_LIBUNWIND_TRACE_API("_Unwind_GetRegionStart(context=%p) => 0x%llX",
1180
static_cast<void *>(context), (long long)result);
1181
return result;
1182
}
1183
1184
1185
/// Called by personality handler during phase 2 if a foreign exception
1186
// is caught.
1187
_LIBUNWIND_EXPORT void
1188
_Unwind_DeleteException(_Unwind_Exception *exception_object) {
1189
_LIBUNWIND_TRACE_API("_Unwind_DeleteException(ex_obj=%p)",
1190
static_cast<void *>(exception_object));
1191
if (exception_object->exception_cleanup != NULL)
1192
(*exception_object->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT,
1193
exception_object);
1194
}
1195
1196
extern "C" _LIBUNWIND_EXPORT _Unwind_Reason_Code
1197
__gnu_unwind_frame(_Unwind_Exception *exception_object,
1198
struct _Unwind_Context *context) {
1199
(void)exception_object;
1200
unw_cursor_t *cursor = (unw_cursor_t *)context;
1201
switch (__unw_step(cursor)) {
1202
case UNW_STEP_SUCCESS:
1203
return _URC_OK;
1204
case UNW_STEP_END:
1205
return _URC_END_OF_STACK;
1206
default:
1207
return _URC_FAILURE;
1208
}
1209
}
1210
1211
#endif // defined(_LIBUNWIND_ARM_EHABI)
1212
1213