Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/unwind/src/UnwindCursor.hpp
12346 views
1
//===------------------------- UnwindCursor.hpp ---------------------------===//
2
//
3
// The LLVM Compiler Infrastructure
4
//
5
// This file is dual licensed under the MIT and the University of Illinois Open
6
// Source Licenses. See LICENSE.TXT for details.
7
//
8
//
9
// C++ interface to lower levels of libunwind
10
//===----------------------------------------------------------------------===//
11
12
#ifndef __UNWINDCURSOR_HPP__
13
#define __UNWINDCURSOR_HPP__
14
15
#include <algorithm>
16
#include <stdint.h>
17
#include <stdio.h>
18
#include <stdlib.h>
19
#include <unwind.h>
20
21
#ifdef _WIN32
22
#include <windows.h>
23
#include <ntverp.h>
24
#endif
25
#ifdef __APPLE__
26
#include <mach-o/dyld.h>
27
#endif
28
29
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
30
// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
31
// earlier) SDKs.
32
// MinGW-w64 has always provided this struct.
33
#if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
34
!defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
35
struct _DISPATCHER_CONTEXT {
36
ULONG64 ControlPc;
37
ULONG64 ImageBase;
38
PRUNTIME_FUNCTION FunctionEntry;
39
ULONG64 EstablisherFrame;
40
ULONG64 TargetIp;
41
PCONTEXT ContextRecord;
42
PEXCEPTION_ROUTINE LanguageHandler;
43
PVOID HandlerData;
44
PUNWIND_HISTORY_TABLE HistoryTable;
45
ULONG ScopeIndex;
46
ULONG Fill0;
47
};
48
#endif
49
50
struct UNWIND_INFO {
51
uint8_t Version : 3;
52
uint8_t Flags : 5;
53
uint8_t SizeOfProlog;
54
uint8_t CountOfCodes;
55
uint8_t FrameRegister : 4;
56
uint8_t FrameOffset : 4;
57
uint16_t UnwindCodes[2];
58
};
59
60
extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
61
int, _Unwind_Action, uint64_t, _Unwind_Exception *,
62
struct _Unwind_Context *);
63
64
#endif
65
66
#include "config.h"
67
68
#include "AddressSpace.hpp"
69
#include "CompactUnwinder.hpp"
70
#include "config.h"
71
#include "DwarfInstructions.hpp"
72
#include "EHHeaderParser.hpp"
73
#include "libunwind.h"
74
#include "Registers.hpp"
75
#include "RWMutex.hpp"
76
#include "Unwind-EHABI.h"
77
78
namespace libunwind {
79
80
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
81
/// Cache of recently found FDEs.
82
template <typename A>
83
class _LIBUNWIND_HIDDEN DwarfFDECache {
84
typedef typename A::pint_t pint_t;
85
public:
86
static pint_t findFDE(pint_t mh, pint_t pc);
87
static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
88
static void removeAllIn(pint_t mh);
89
static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
90
unw_word_t ip_end,
91
unw_word_t fde, unw_word_t mh));
92
93
private:
94
95
struct entry {
96
pint_t mh;
97
pint_t ip_start;
98
pint_t ip_end;
99
pint_t fde;
100
};
101
102
// These fields are all static to avoid needing an initializer.
103
// There is only one instance of this class per process.
104
static RWMutex _lock;
105
#ifdef __APPLE__
106
static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
107
static bool _registeredForDyldUnloads;
108
#endif
109
// Can't use std::vector<> here because this code is below libc++.
110
static entry *_buffer;
111
static entry *_bufferUsed;
112
static entry *_bufferEnd;
113
static entry _initialBuffer[64];
114
};
115
116
template <typename A>
117
typename DwarfFDECache<A>::entry *
118
DwarfFDECache<A>::_buffer = _initialBuffer;
119
120
template <typename A>
121
typename DwarfFDECache<A>::entry *
122
DwarfFDECache<A>::_bufferUsed = _initialBuffer;
123
124
template <typename A>
125
typename DwarfFDECache<A>::entry *
126
DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
127
128
template <typename A>
129
typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
130
131
template <typename A>
132
RWMutex DwarfFDECache<A>::_lock;
133
134
#ifdef __APPLE__
135
template <typename A>
136
bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
137
#endif
138
139
template <typename A>
140
typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
141
pint_t result = 0;
142
_LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
143
for (entry *p = _buffer; p < _bufferUsed; ++p) {
144
if ((mh == p->mh) || (mh == 0)) {
145
if ((p->ip_start <= pc) && (pc < p->ip_end)) {
146
result = p->fde;
147
break;
148
}
149
}
150
}
151
_LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared());
152
return result;
153
}
154
155
template <typename A>
156
void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
157
pint_t fde) {
158
#if !defined(_LIBUNWIND_NO_HEAP)
159
_LIBUNWIND_LOG_IF_FALSE(_lock.lock());
160
if (_bufferUsed >= _bufferEnd) {
161
size_t oldSize = (size_t)(_bufferEnd - _buffer);
162
size_t newSize = oldSize * 4;
163
// Can't use operator new (we are below it).
164
entry *newBuffer = (entry *)malloc(newSize * sizeof(entry));
165
memcpy(newBuffer, _buffer, oldSize * sizeof(entry));
166
if (_buffer != _initialBuffer)
167
free(_buffer);
168
_buffer = newBuffer;
169
_bufferUsed = &newBuffer[oldSize];
170
_bufferEnd = &newBuffer[newSize];
171
}
172
_bufferUsed->mh = mh;
173
_bufferUsed->ip_start = ip_start;
174
_bufferUsed->ip_end = ip_end;
175
_bufferUsed->fde = fde;
176
++_bufferUsed;
177
#ifdef __APPLE__
178
if (!_registeredForDyldUnloads) {
179
_dyld_register_func_for_remove_image(&dyldUnloadHook);
180
_registeredForDyldUnloads = true;
181
}
182
#endif
183
_LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
184
#endif
185
}
186
187
template <typename A>
188
void DwarfFDECache<A>::removeAllIn(pint_t mh) {
189
_LIBUNWIND_LOG_IF_FALSE(_lock.lock());
190
entry *d = _buffer;
191
for (const entry *s = _buffer; s < _bufferUsed; ++s) {
192
if (s->mh != mh) {
193
if (d != s)
194
*d = *s;
195
++d;
196
}
197
}
198
_bufferUsed = d;
199
_LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
200
}
201
202
#ifdef __APPLE__
203
template <typename A>
204
void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {
205
removeAllIn((pint_t) mh);
206
}
207
#endif
208
209
template <typename A>
210
void DwarfFDECache<A>::iterateCacheEntries(void (*func)(
211
unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
212
_LIBUNWIND_LOG_IF_FALSE(_lock.lock());
213
for (entry *p = _buffer; p < _bufferUsed; ++p) {
214
(*func)(p->ip_start, p->ip_end, p->fde, p->mh);
215
}
216
_LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
217
}
218
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
219
220
221
#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
222
223
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
224
template <typename A> class UnwindSectionHeader {
225
public:
226
UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)
227
: _addressSpace(addressSpace), _addr(addr) {}
228
229
uint32_t version() const {
230
return _addressSpace.get32(_addr +
231
offsetof(unwind_info_section_header, version));
232
}
233
uint32_t commonEncodingsArraySectionOffset() const {
234
return _addressSpace.get32(_addr +
235
offsetof(unwind_info_section_header,
236
commonEncodingsArraySectionOffset));
237
}
238
uint32_t commonEncodingsArrayCount() const {
239
return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
240
commonEncodingsArrayCount));
241
}
242
uint32_t personalityArraySectionOffset() const {
243
return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
244
personalityArraySectionOffset));
245
}
246
uint32_t personalityArrayCount() const {
247
return _addressSpace.get32(
248
_addr + offsetof(unwind_info_section_header, personalityArrayCount));
249
}
250
uint32_t indexSectionOffset() const {
251
return _addressSpace.get32(
252
_addr + offsetof(unwind_info_section_header, indexSectionOffset));
253
}
254
uint32_t indexCount() const {
255
return _addressSpace.get32(
256
_addr + offsetof(unwind_info_section_header, indexCount));
257
}
258
259
private:
260
A &_addressSpace;
261
typename A::pint_t _addr;
262
};
263
264
template <typename A> class UnwindSectionIndexArray {
265
public:
266
UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr)
267
: _addressSpace(addressSpace), _addr(addr) {}
268
269
uint32_t functionOffset(uint32_t index) const {
270
return _addressSpace.get32(
271
_addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
272
functionOffset));
273
}
274
uint32_t secondLevelPagesSectionOffset(uint32_t index) const {
275
return _addressSpace.get32(
276
_addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
277
secondLevelPagesSectionOffset));
278
}
279
uint32_t lsdaIndexArraySectionOffset(uint32_t index) const {
280
return _addressSpace.get32(
281
_addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
282
lsdaIndexArraySectionOffset));
283
}
284
285
private:
286
A &_addressSpace;
287
typename A::pint_t _addr;
288
};
289
290
template <typename A> class UnwindSectionRegularPageHeader {
291
public:
292
UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr)
293
: _addressSpace(addressSpace), _addr(addr) {}
294
295
uint32_t kind() const {
296
return _addressSpace.get32(
297
_addr + offsetof(unwind_info_regular_second_level_page_header, kind));
298
}
299
uint16_t entryPageOffset() const {
300
return _addressSpace.get16(
301
_addr + offsetof(unwind_info_regular_second_level_page_header,
302
entryPageOffset));
303
}
304
uint16_t entryCount() const {
305
return _addressSpace.get16(
306
_addr +
307
offsetof(unwind_info_regular_second_level_page_header, entryCount));
308
}
309
310
private:
311
A &_addressSpace;
312
typename A::pint_t _addr;
313
};
314
315
template <typename A> class UnwindSectionRegularArray {
316
public:
317
UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr)
318
: _addressSpace(addressSpace), _addr(addr) {}
319
320
uint32_t functionOffset(uint32_t index) const {
321
return _addressSpace.get32(
322
_addr + arrayoffsetof(unwind_info_regular_second_level_entry, index,
323
functionOffset));
324
}
325
uint32_t encoding(uint32_t index) const {
326
return _addressSpace.get32(
327
_addr +
328
arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding));
329
}
330
331
private:
332
A &_addressSpace;
333
typename A::pint_t _addr;
334
};
335
336
template <typename A> class UnwindSectionCompressedPageHeader {
337
public:
338
UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr)
339
: _addressSpace(addressSpace), _addr(addr) {}
340
341
uint32_t kind() const {
342
return _addressSpace.get32(
343
_addr +
344
offsetof(unwind_info_compressed_second_level_page_header, kind));
345
}
346
uint16_t entryPageOffset() const {
347
return _addressSpace.get16(
348
_addr + offsetof(unwind_info_compressed_second_level_page_header,
349
entryPageOffset));
350
}
351
uint16_t entryCount() const {
352
return _addressSpace.get16(
353
_addr +
354
offsetof(unwind_info_compressed_second_level_page_header, entryCount));
355
}
356
uint16_t encodingsPageOffset() const {
357
return _addressSpace.get16(
358
_addr + offsetof(unwind_info_compressed_second_level_page_header,
359
encodingsPageOffset));
360
}
361
uint16_t encodingsCount() const {
362
return _addressSpace.get16(
363
_addr + offsetof(unwind_info_compressed_second_level_page_header,
364
encodingsCount));
365
}
366
367
private:
368
A &_addressSpace;
369
typename A::pint_t _addr;
370
};
371
372
template <typename A> class UnwindSectionCompressedArray {
373
public:
374
UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr)
375
: _addressSpace(addressSpace), _addr(addr) {}
376
377
uint32_t functionOffset(uint32_t index) const {
378
return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
379
_addressSpace.get32(_addr + index * sizeof(uint32_t)));
380
}
381
uint16_t encodingIndex(uint32_t index) const {
382
return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
383
_addressSpace.get32(_addr + index * sizeof(uint32_t)));
384
}
385
386
private:
387
A &_addressSpace;
388
typename A::pint_t _addr;
389
};
390
391
template <typename A> class UnwindSectionLsdaArray {
392
public:
393
UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr)
394
: _addressSpace(addressSpace), _addr(addr) {}
395
396
uint32_t functionOffset(uint32_t index) const {
397
return _addressSpace.get32(
398
_addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
399
index, functionOffset));
400
}
401
uint32_t lsdaOffset(uint32_t index) const {
402
return _addressSpace.get32(
403
_addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
404
index, lsdaOffset));
405
}
406
407
private:
408
A &_addressSpace;
409
typename A::pint_t _addr;
410
};
411
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
412
413
class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
414
public:
415
// NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
416
// This avoids an unnecessary dependency to libc++abi.
417
void operator delete(void *, size_t) {}
418
419
virtual ~AbstractUnwindCursor() {}
420
virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
421
virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
422
virtual void setReg(int, unw_word_t) {
423
_LIBUNWIND_ABORT("setReg not implemented");
424
}
425
virtual bool validFloatReg(int) {
426
_LIBUNWIND_ABORT("validFloatReg not implemented");
427
}
428
virtual unw_fpreg_t getFloatReg(int) {
429
_LIBUNWIND_ABORT("getFloatReg not implemented");
430
}
431
virtual void setFloatReg(int, unw_fpreg_t) {
432
_LIBUNWIND_ABORT("setFloatReg not implemented");
433
}
434
virtual int step() { _LIBUNWIND_ABORT("step not implemented"); }
435
virtual void getInfo(unw_proc_info_t *) {
436
_LIBUNWIND_ABORT("getInfo not implemented");
437
}
438
virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
439
virtual bool isSignalFrame() {
440
_LIBUNWIND_ABORT("isSignalFrame not implemented");
441
}
442
virtual bool getFunctionName(char *, size_t, unw_word_t *) {
443
_LIBUNWIND_ABORT("getFunctionName not implemented");
444
}
445
virtual void setInfoBasedOnIPRegister(bool = false) {
446
_LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
447
}
448
virtual const char *getRegisterName(int) {
449
_LIBUNWIND_ABORT("getRegisterName not implemented");
450
}
451
#ifdef __arm__
452
virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
453
#endif
454
};
455
456
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
457
458
/// \c UnwindCursor contains all state (including all register values) during
459
/// an unwind. This is normally stack-allocated inside a unw_cursor_t.
460
template <typename A, typename R>
461
class UnwindCursor : public AbstractUnwindCursor {
462
typedef typename A::pint_t pint_t;
463
public:
464
UnwindCursor(unw_context_t *context, A &as);
465
UnwindCursor(CONTEXT *context, A &as);
466
UnwindCursor(A &as, void *threadArg);
467
virtual ~UnwindCursor() {}
468
virtual bool validReg(int);
469
virtual unw_word_t getReg(int);
470
virtual void setReg(int, unw_word_t);
471
virtual bool validFloatReg(int);
472
virtual unw_fpreg_t getFloatReg(int);
473
virtual void setFloatReg(int, unw_fpreg_t);
474
virtual int step();
475
virtual void getInfo(unw_proc_info_t *);
476
virtual void jumpto();
477
virtual bool isSignalFrame();
478
virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
479
virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
480
virtual const char *getRegisterName(int num);
481
#ifdef __arm__
482
virtual void saveVFPAsX();
483
#endif
484
485
DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
486
void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
487
488
private:
489
490
pint_t getLastPC() const { return _dispContext.ControlPc; }
491
void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
492
RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
493
_dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
494
&_dispContext.ImageBase,
495
_dispContext.HistoryTable);
496
*base = _dispContext.ImageBase;
497
return _dispContext.FunctionEntry;
498
}
499
bool getInfoFromSEH(pint_t pc);
500
int stepWithSEHData() {
501
_dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
502
_dispContext.ImageBase,
503
_dispContext.ControlPc,
504
_dispContext.FunctionEntry,
505
_dispContext.ContextRecord,
506
&_dispContext.HandlerData,
507
&_dispContext.EstablisherFrame,
508
NULL);
509
// Update some fields of the unwind info now, since we have them.
510
_info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
511
if (_dispContext.LanguageHandler) {
512
_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
513
} else
514
_info.handler = 0;
515
return UNW_STEP_SUCCESS;
516
}
517
518
A &_addressSpace;
519
unw_proc_info_t _info;
520
DISPATCHER_CONTEXT _dispContext;
521
CONTEXT _msContext;
522
UNWIND_HISTORY_TABLE _histTable;
523
bool _unwindInfoMissing;
524
};
525
526
527
template <typename A, typename R>
528
UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
529
: _addressSpace(as), _unwindInfoMissing(false) {
530
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
531
"UnwindCursor<> does not fit in unw_cursor_t");
532
memset(&_info, 0, sizeof(_info));
533
memset(&_histTable, 0, sizeof(_histTable));
534
_dispContext.ContextRecord = &_msContext;
535
_dispContext.HistoryTable = &_histTable;
536
// Initialize MS context from ours.
537
R r(context);
538
_msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
539
#if defined(_LIBUNWIND_TARGET_X86_64)
540
_msContext.Rax = r.getRegister(UNW_X86_64_RAX);
541
_msContext.Rcx = r.getRegister(UNW_X86_64_RCX);
542
_msContext.Rdx = r.getRegister(UNW_X86_64_RDX);
543
_msContext.Rbx = r.getRegister(UNW_X86_64_RBX);
544
_msContext.Rsp = r.getRegister(UNW_X86_64_RSP);
545
_msContext.Rbp = r.getRegister(UNW_X86_64_RBP);
546
_msContext.Rsi = r.getRegister(UNW_X86_64_RSI);
547
_msContext.Rdi = r.getRegister(UNW_X86_64_RDI);
548
_msContext.R8 = r.getRegister(UNW_X86_64_R8);
549
_msContext.R9 = r.getRegister(UNW_X86_64_R9);
550
_msContext.R10 = r.getRegister(UNW_X86_64_R10);
551
_msContext.R11 = r.getRegister(UNW_X86_64_R11);
552
_msContext.R12 = r.getRegister(UNW_X86_64_R12);
553
_msContext.R13 = r.getRegister(UNW_X86_64_R13);
554
_msContext.R14 = r.getRegister(UNW_X86_64_R14);
555
_msContext.R15 = r.getRegister(UNW_X86_64_R15);
556
_msContext.Rip = r.getRegister(UNW_REG_IP);
557
union {
558
v128 v;
559
M128A m;
560
} t;
561
t.v = r.getVectorRegister(UNW_X86_64_XMM0);
562
_msContext.Xmm0 = t.m;
563
t.v = r.getVectorRegister(UNW_X86_64_XMM1);
564
_msContext.Xmm1 = t.m;
565
t.v = r.getVectorRegister(UNW_X86_64_XMM2);
566
_msContext.Xmm2 = t.m;
567
t.v = r.getVectorRegister(UNW_X86_64_XMM3);
568
_msContext.Xmm3 = t.m;
569
t.v = r.getVectorRegister(UNW_X86_64_XMM4);
570
_msContext.Xmm4 = t.m;
571
t.v = r.getVectorRegister(UNW_X86_64_XMM5);
572
_msContext.Xmm5 = t.m;
573
t.v = r.getVectorRegister(UNW_X86_64_XMM6);
574
_msContext.Xmm6 = t.m;
575
t.v = r.getVectorRegister(UNW_X86_64_XMM7);
576
_msContext.Xmm7 = t.m;
577
t.v = r.getVectorRegister(UNW_X86_64_XMM8);
578
_msContext.Xmm8 = t.m;
579
t.v = r.getVectorRegister(UNW_X86_64_XMM9);
580
_msContext.Xmm9 = t.m;
581
t.v = r.getVectorRegister(UNW_X86_64_XMM10);
582
_msContext.Xmm10 = t.m;
583
t.v = r.getVectorRegister(UNW_X86_64_XMM11);
584
_msContext.Xmm11 = t.m;
585
t.v = r.getVectorRegister(UNW_X86_64_XMM12);
586
_msContext.Xmm12 = t.m;
587
t.v = r.getVectorRegister(UNW_X86_64_XMM13);
588
_msContext.Xmm13 = t.m;
589
t.v = r.getVectorRegister(UNW_X86_64_XMM14);
590
_msContext.Xmm14 = t.m;
591
t.v = r.getVectorRegister(UNW_X86_64_XMM15);
592
_msContext.Xmm15 = t.m;
593
#elif defined(_LIBUNWIND_TARGET_ARM)
594
_msContext.R0 = r.getRegister(UNW_ARM_R0);
595
_msContext.R1 = r.getRegister(UNW_ARM_R1);
596
_msContext.R2 = r.getRegister(UNW_ARM_R2);
597
_msContext.R3 = r.getRegister(UNW_ARM_R3);
598
_msContext.R4 = r.getRegister(UNW_ARM_R4);
599
_msContext.R5 = r.getRegister(UNW_ARM_R5);
600
_msContext.R6 = r.getRegister(UNW_ARM_R6);
601
_msContext.R7 = r.getRegister(UNW_ARM_R7);
602
_msContext.R8 = r.getRegister(UNW_ARM_R8);
603
_msContext.R9 = r.getRegister(UNW_ARM_R9);
604
_msContext.R10 = r.getRegister(UNW_ARM_R10);
605
_msContext.R11 = r.getRegister(UNW_ARM_R11);
606
_msContext.R12 = r.getRegister(UNW_ARM_R12);
607
_msContext.Sp = r.getRegister(UNW_ARM_SP);
608
_msContext.Lr = r.getRegister(UNW_ARM_LR);
609
_msContext.Pc = r.getRegister(UNW_ARM_IP);
610
for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {
611
union {
612
uint64_t w;
613
double d;
614
} d;
615
d.d = r.getFloatRegister(i);
616
_msContext.D[i - UNW_ARM_D0] = d.w;
617
}
618
#elif defined(_LIBUNWIND_TARGET_AARCH64)
619
for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i)
620
_msContext.X[i - UNW_ARM64_X0] = r.getRegister(i);
621
_msContext.Sp = r.getRegister(UNW_REG_SP);
622
_msContext.Pc = r.getRegister(UNW_REG_IP);
623
for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i)
624
_msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i);
625
#endif
626
}
627
628
template <typename A, typename R>
629
UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
630
: _addressSpace(as), _unwindInfoMissing(false) {
631
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
632
"UnwindCursor<> does not fit in unw_cursor_t");
633
memset(&_info, 0, sizeof(_info));
634
memset(&_histTable, 0, sizeof(_histTable));
635
_dispContext.ContextRecord = &_msContext;
636
_dispContext.HistoryTable = &_histTable;
637
_msContext = *context;
638
}
639
640
641
template <typename A, typename R>
642
bool UnwindCursor<A, R>::validReg(int regNum) {
643
if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
644
#if defined(_LIBUNWIND_TARGET_X86_64)
645
if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
646
#elif defined(_LIBUNWIND_TARGET_ARM)
647
if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true;
648
#elif defined(_LIBUNWIND_TARGET_AARCH64)
649
if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true;
650
#endif
651
return false;
652
}
653
654
template <typename A, typename R>
655
unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
656
switch (regNum) {
657
#if defined(_LIBUNWIND_TARGET_X86_64)
658
case UNW_REG_IP: return _msContext.Rip;
659
case UNW_X86_64_RAX: return _msContext.Rax;
660
case UNW_X86_64_RDX: return _msContext.Rdx;
661
case UNW_X86_64_RCX: return _msContext.Rcx;
662
case UNW_X86_64_RBX: return _msContext.Rbx;
663
case UNW_REG_SP:
664
case UNW_X86_64_RSP: return _msContext.Rsp;
665
case UNW_X86_64_RBP: return _msContext.Rbp;
666
case UNW_X86_64_RSI: return _msContext.Rsi;
667
case UNW_X86_64_RDI: return _msContext.Rdi;
668
case UNW_X86_64_R8: return _msContext.R8;
669
case UNW_X86_64_R9: return _msContext.R9;
670
case UNW_X86_64_R10: return _msContext.R10;
671
case UNW_X86_64_R11: return _msContext.R11;
672
case UNW_X86_64_R12: return _msContext.R12;
673
case UNW_X86_64_R13: return _msContext.R13;
674
case UNW_X86_64_R14: return _msContext.R14;
675
case UNW_X86_64_R15: return _msContext.R15;
676
#elif defined(_LIBUNWIND_TARGET_ARM)
677
case UNW_ARM_R0: return _msContext.R0;
678
case UNW_ARM_R1: return _msContext.R1;
679
case UNW_ARM_R2: return _msContext.R2;
680
case UNW_ARM_R3: return _msContext.R3;
681
case UNW_ARM_R4: return _msContext.R4;
682
case UNW_ARM_R5: return _msContext.R5;
683
case UNW_ARM_R6: return _msContext.R6;
684
case UNW_ARM_R7: return _msContext.R7;
685
case UNW_ARM_R8: return _msContext.R8;
686
case UNW_ARM_R9: return _msContext.R9;
687
case UNW_ARM_R10: return _msContext.R10;
688
case UNW_ARM_R11: return _msContext.R11;
689
case UNW_ARM_R12: return _msContext.R12;
690
case UNW_REG_SP:
691
case UNW_ARM_SP: return _msContext.Sp;
692
case UNW_ARM_LR: return _msContext.Lr;
693
case UNW_REG_IP:
694
case UNW_ARM_IP: return _msContext.Pc;
695
#elif defined(_LIBUNWIND_TARGET_AARCH64)
696
case UNW_REG_SP: return _msContext.Sp;
697
case UNW_REG_IP: return _msContext.Pc;
698
default: return _msContext.X[regNum - UNW_ARM64_X0];
699
#endif
700
}
701
_LIBUNWIND_ABORT("unsupported register");
702
}
703
704
template <typename A, typename R>
705
void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
706
switch (regNum) {
707
#if defined(_LIBUNWIND_TARGET_X86_64)
708
case UNW_REG_IP: _msContext.Rip = value; break;
709
case UNW_X86_64_RAX: _msContext.Rax = value; break;
710
case UNW_X86_64_RDX: _msContext.Rdx = value; break;
711
case UNW_X86_64_RCX: _msContext.Rcx = value; break;
712
case UNW_X86_64_RBX: _msContext.Rbx = value; break;
713
case UNW_REG_SP:
714
case UNW_X86_64_RSP: _msContext.Rsp = value; break;
715
case UNW_X86_64_RBP: _msContext.Rbp = value; break;
716
case UNW_X86_64_RSI: _msContext.Rsi = value; break;
717
case UNW_X86_64_RDI: _msContext.Rdi = value; break;
718
case UNW_X86_64_R8: _msContext.R8 = value; break;
719
case UNW_X86_64_R9: _msContext.R9 = value; break;
720
case UNW_X86_64_R10: _msContext.R10 = value; break;
721
case UNW_X86_64_R11: _msContext.R11 = value; break;
722
case UNW_X86_64_R12: _msContext.R12 = value; break;
723
case UNW_X86_64_R13: _msContext.R13 = value; break;
724
case UNW_X86_64_R14: _msContext.R14 = value; break;
725
case UNW_X86_64_R15: _msContext.R15 = value; break;
726
#elif defined(_LIBUNWIND_TARGET_ARM)
727
case UNW_ARM_R0: _msContext.R0 = value; break;
728
case UNW_ARM_R1: _msContext.R1 = value; break;
729
case UNW_ARM_R2: _msContext.R2 = value; break;
730
case UNW_ARM_R3: _msContext.R3 = value; break;
731
case UNW_ARM_R4: _msContext.R4 = value; break;
732
case UNW_ARM_R5: _msContext.R5 = value; break;
733
case UNW_ARM_R6: _msContext.R6 = value; break;
734
case UNW_ARM_R7: _msContext.R7 = value; break;
735
case UNW_ARM_R8: _msContext.R8 = value; break;
736
case UNW_ARM_R9: _msContext.R9 = value; break;
737
case UNW_ARM_R10: _msContext.R10 = value; break;
738
case UNW_ARM_R11: _msContext.R11 = value; break;
739
case UNW_ARM_R12: _msContext.R12 = value; break;
740
case UNW_REG_SP:
741
case UNW_ARM_SP: _msContext.Sp = value; break;
742
case UNW_ARM_LR: _msContext.Lr = value; break;
743
case UNW_REG_IP:
744
case UNW_ARM_IP: _msContext.Pc = value; break;
745
#elif defined(_LIBUNWIND_TARGET_AARCH64)
746
case UNW_REG_SP: _msContext.Sp = value; break;
747
case UNW_REG_IP: _msContext.Pc = value; break;
748
case UNW_ARM64_X0:
749
case UNW_ARM64_X1:
750
case UNW_ARM64_X2:
751
case UNW_ARM64_X3:
752
case UNW_ARM64_X4:
753
case UNW_ARM64_X5:
754
case UNW_ARM64_X6:
755
case UNW_ARM64_X7:
756
case UNW_ARM64_X8:
757
case UNW_ARM64_X9:
758
case UNW_ARM64_X10:
759
case UNW_ARM64_X11:
760
case UNW_ARM64_X12:
761
case UNW_ARM64_X13:
762
case UNW_ARM64_X14:
763
case UNW_ARM64_X15:
764
case UNW_ARM64_X16:
765
case UNW_ARM64_X17:
766
case UNW_ARM64_X18:
767
case UNW_ARM64_X19:
768
case UNW_ARM64_X20:
769
case UNW_ARM64_X21:
770
case UNW_ARM64_X22:
771
case UNW_ARM64_X23:
772
case UNW_ARM64_X24:
773
case UNW_ARM64_X25:
774
case UNW_ARM64_X26:
775
case UNW_ARM64_X27:
776
case UNW_ARM64_X28:
777
case UNW_ARM64_FP:
778
case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
779
#endif
780
default:
781
_LIBUNWIND_ABORT("unsupported register");
782
}
783
}
784
785
template <typename A, typename R>
786
bool UnwindCursor<A, R>::validFloatReg(int regNum) {
787
#if defined(_LIBUNWIND_TARGET_ARM)
788
if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
789
if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
790
#elif defined(_LIBUNWIND_TARGET_AARCH64)
791
if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true;
792
#endif
793
return false;
794
}
795
796
template <typename A, typename R>
797
unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
798
#if defined(_LIBUNWIND_TARGET_ARM)
799
if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
800
union {
801
uint32_t w;
802
float f;
803
} d;
804
d.w = _msContext.S[regNum - UNW_ARM_S0];
805
return d.f;
806
}
807
if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
808
union {
809
uint64_t w;
810
double d;
811
} d;
812
d.w = _msContext.D[regNum - UNW_ARM_D0];
813
return d.d;
814
}
815
_LIBUNWIND_ABORT("unsupported float register");
816
#elif defined(_LIBUNWIND_TARGET_AARCH64)
817
return _msContext.V[regNum - UNW_ARM64_D0].D[0];
818
#else
819
_LIBUNWIND_ABORT("float registers unimplemented");
820
#endif
821
}
822
823
template <typename A, typename R>
824
void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
825
#if defined(_LIBUNWIND_TARGET_ARM)
826
if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
827
union {
828
uint32_t w;
829
float f;
830
} d;
831
d.f = value;
832
_msContext.S[regNum - UNW_ARM_S0] = d.w;
833
}
834
if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
835
union {
836
uint64_t w;
837
double d;
838
} d;
839
d.d = value;
840
_msContext.D[regNum - UNW_ARM_D0] = d.w;
841
}
842
_LIBUNWIND_ABORT("unsupported float register");
843
#elif defined(_LIBUNWIND_TARGET_AARCH64)
844
_msContext.V[regNum - UNW_ARM64_D0].D[0] = value;
845
#else
846
_LIBUNWIND_ABORT("float registers unimplemented");
847
#endif
848
}
849
850
template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
851
RtlRestoreContext(&_msContext, nullptr);
852
}
853
854
#ifdef __arm__
855
template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}
856
#endif
857
858
template <typename A, typename R>
859
const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
860
return R::getRegisterName(regNum);
861
}
862
863
template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
864
return false;
865
}
866
867
#else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
868
869
/// UnwindCursor contains all state (including all register values) during
870
/// an unwind. This is normally stack allocated inside a unw_cursor_t.
871
template <typename A, typename R>
872
class UnwindCursor : public AbstractUnwindCursor{
873
typedef typename A::pint_t pint_t;
874
public:
875
UnwindCursor(unw_context_t *context, A &as);
876
UnwindCursor(A &as, void *threadArg);
877
virtual ~UnwindCursor() {}
878
virtual bool validReg(int);
879
virtual unw_word_t getReg(int);
880
virtual void setReg(int, unw_word_t);
881
virtual bool validFloatReg(int);
882
virtual unw_fpreg_t getFloatReg(int);
883
virtual void setFloatReg(int, unw_fpreg_t);
884
virtual int step();
885
virtual void getInfo(unw_proc_info_t *);
886
virtual void jumpto();
887
virtual bool isSignalFrame();
888
virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
889
virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
890
virtual const char *getRegisterName(int num);
891
#ifdef __arm__
892
virtual void saveVFPAsX();
893
#endif
894
895
private:
896
897
#if defined(_LIBUNWIND_ARM_EHABI)
898
bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
899
900
int stepWithEHABI() {
901
size_t len = 0;
902
size_t off = 0;
903
// FIXME: Calling decode_eht_entry() here is violating the libunwind
904
// abstraction layer.
905
const uint32_t *ehtp =
906
decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info),
907
&off, &len);
908
if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) !=
909
_URC_CONTINUE_UNWIND)
910
return UNW_STEP_END;
911
return UNW_STEP_SUCCESS;
912
}
913
#endif
914
915
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
916
bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
917
uint32_t fdeSectionOffsetHint=0);
918
int stepWithDwarfFDE() {
919
return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace,
920
(pint_t)this->getReg(UNW_REG_IP),
921
(pint_t)_info.unwind_info,
922
_registers);
923
}
924
#endif
925
926
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
927
bool getInfoFromCompactEncodingSection(pint_t pc,
928
const UnwindInfoSections &sects);
929
int stepWithCompactEncoding() {
930
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
931
if ( compactSaysUseDwarf() )
932
return stepWithDwarfFDE();
933
#endif
934
R dummy;
935
return stepWithCompactEncoding(dummy);
936
}
937
938
#if defined(_LIBUNWIND_TARGET_X86_64)
939
int stepWithCompactEncoding(Registers_x86_64 &) {
940
return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
941
_info.format, _info.start_ip, _addressSpace, _registers);
942
}
943
#endif
944
945
#if defined(_LIBUNWIND_TARGET_I386)
946
int stepWithCompactEncoding(Registers_x86 &) {
947
return CompactUnwinder_x86<A>::stepWithCompactEncoding(
948
_info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
949
}
950
#endif
951
952
#if defined(_LIBUNWIND_TARGET_PPC)
953
int stepWithCompactEncoding(Registers_ppc &) {
954
return UNW_EINVAL;
955
}
956
#endif
957
958
#if defined(_LIBUNWIND_TARGET_PPC64)
959
int stepWithCompactEncoding(Registers_ppc64 &) {
960
return UNW_EINVAL;
961
}
962
#endif
963
964
965
#if defined(_LIBUNWIND_TARGET_AARCH64)
966
int stepWithCompactEncoding(Registers_arm64 &) {
967
return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
968
_info.format, _info.start_ip, _addressSpace, _registers);
969
}
970
#endif
971
972
#if defined(_LIBUNWIND_TARGET_MIPS_O32)
973
int stepWithCompactEncoding(Registers_mips_o32 &) {
974
return UNW_EINVAL;
975
}
976
#endif
977
978
#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
979
int stepWithCompactEncoding(Registers_mips_newabi &) {
980
return UNW_EINVAL;
981
}
982
#endif
983
984
#if defined(_LIBUNWIND_TARGET_SPARC)
985
int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
986
#endif
987
988
bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
989
R dummy;
990
return compactSaysUseDwarf(dummy, offset);
991
}
992
993
#if defined(_LIBUNWIND_TARGET_X86_64)
994
bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
995
if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
996
if (offset)
997
*offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
998
return true;
999
}
1000
return false;
1001
}
1002
#endif
1003
1004
#if defined(_LIBUNWIND_TARGET_I386)
1005
bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
1006
if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
1007
if (offset)
1008
*offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);
1009
return true;
1010
}
1011
return false;
1012
}
1013
#endif
1014
1015
#if defined(_LIBUNWIND_TARGET_PPC)
1016
bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
1017
return true;
1018
}
1019
#endif
1020
1021
#if defined(_LIBUNWIND_TARGET_PPC64)
1022
bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {
1023
return true;
1024
}
1025
#endif
1026
1027
#if defined(_LIBUNWIND_TARGET_AARCH64)
1028
bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
1029
if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
1030
if (offset)
1031
*offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);
1032
return true;
1033
}
1034
return false;
1035
}
1036
#endif
1037
1038
#if defined(_LIBUNWIND_TARGET_MIPS_O32)
1039
bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const {
1040
return true;
1041
}
1042
#endif
1043
1044
#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1045
bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
1046
return true;
1047
}
1048
#endif
1049
1050
#if defined(_LIBUNWIND_TARGET_SPARC)
1051
bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
1052
#endif
1053
1054
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1055
1056
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1057
compact_unwind_encoding_t dwarfEncoding() const {
1058
R dummy;
1059
return dwarfEncoding(dummy);
1060
}
1061
1062
#if defined(_LIBUNWIND_TARGET_X86_64)
1063
compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
1064
return UNWIND_X86_64_MODE_DWARF;
1065
}
1066
#endif
1067
1068
#if defined(_LIBUNWIND_TARGET_I386)
1069
compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
1070
return UNWIND_X86_MODE_DWARF;
1071
}
1072
#endif
1073
1074
#if defined(_LIBUNWIND_TARGET_PPC)
1075
compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
1076
return 0;
1077
}
1078
#endif
1079
1080
#if defined(_LIBUNWIND_TARGET_PPC64)
1081
compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {
1082
return 0;
1083
}
1084
#endif
1085
1086
#if defined(_LIBUNWIND_TARGET_AARCH64)
1087
compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
1088
return UNWIND_ARM64_MODE_DWARF;
1089
}
1090
#endif
1091
1092
#if defined(_LIBUNWIND_TARGET_ARM)
1093
compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const {
1094
return 0;
1095
}
1096
#endif
1097
1098
#if defined (_LIBUNWIND_TARGET_OR1K)
1099
compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
1100
return 0;
1101
}
1102
#endif
1103
1104
#if defined (_LIBUNWIND_TARGET_MIPS_O32)
1105
compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const {
1106
return 0;
1107
}
1108
#endif
1109
1110
#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1111
compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
1112
return 0;
1113
}
1114
#endif
1115
1116
#if defined(_LIBUNWIND_TARGET_SPARC)
1117
compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
1118
#endif
1119
1120
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1121
1122
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1123
// For runtime environments using SEH unwind data without Windows runtime
1124
// support.
1125
pint_t getLastPC() const { /* FIXME: Implement */ return 0; }
1126
void setLastPC(pint_t pc) { /* FIXME: Implement */ }
1127
RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
1128
/* FIXME: Implement */
1129
*base = 0;
1130
return nullptr;
1131
}
1132
bool getInfoFromSEH(pint_t pc);
1133
int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1134
#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1135
1136
1137
A &_addressSpace;
1138
R _registers;
1139
unw_proc_info_t _info;
1140
bool _unwindInfoMissing;
1141
bool _isSignalFrame;
1142
};
1143
1144
1145
template <typename A, typename R>
1146
UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
1147
: _addressSpace(as), _registers(context), _unwindInfoMissing(false),
1148
_isSignalFrame(false) {
1149
static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
1150
"UnwindCursor<> does not fit in unw_cursor_t");
1151
memset(&_info, 0, sizeof(_info));
1152
}
1153
1154
template <typename A, typename R>
1155
UnwindCursor<A, R>::UnwindCursor(A &as, void *)
1156
: _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
1157
memset(&_info, 0, sizeof(_info));
1158
// FIXME
1159
// fill in _registers from thread arg
1160
}
1161
1162
1163
template <typename A, typename R>
1164
bool UnwindCursor<A, R>::validReg(int regNum) {
1165
return _registers.validRegister(regNum);
1166
}
1167
1168
template <typename A, typename R>
1169
unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
1170
return _registers.getRegister(regNum);
1171
}
1172
1173
template <typename A, typename R>
1174
void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
1175
_registers.setRegister(regNum, (typename A::pint_t)value);
1176
}
1177
1178
template <typename A, typename R>
1179
bool UnwindCursor<A, R>::validFloatReg(int regNum) {
1180
return _registers.validFloatRegister(regNum);
1181
}
1182
1183
template <typename A, typename R>
1184
unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
1185
return _registers.getFloatRegister(regNum);
1186
}
1187
1188
template <typename A, typename R>
1189
void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
1190
_registers.setFloatRegister(regNum, value);
1191
}
1192
1193
template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
1194
_registers.jumpto();
1195
}
1196
1197
#ifdef __arm__
1198
template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
1199
_registers.saveVFPAsX();
1200
}
1201
#endif
1202
1203
template <typename A, typename R>
1204
const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
1205
return _registers.getRegisterName(regNum);
1206
}
1207
1208
template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
1209
return _isSignalFrame;
1210
}
1211
1212
#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1213
1214
#if defined(_LIBUNWIND_ARM_EHABI)
1215
struct EHABIIndexEntry {
1216
uint32_t functionOffset;
1217
uint32_t data;
1218
};
1219
1220
template<typename A>
1221
struct EHABISectionIterator {
1222
typedef EHABISectionIterator _Self;
1223
1224
typedef std::random_access_iterator_tag iterator_category;
1225
typedef typename A::pint_t value_type;
1226
typedef typename A::pint_t* pointer;
1227
typedef typename A::pint_t& reference;
1228
typedef size_t size_type;
1229
typedef size_t difference_type;
1230
1231
static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {
1232
return _Self(addressSpace, sects, 0);
1233
}
1234
static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
1235
return _Self(addressSpace, sects,
1236
sects.arm_section_length / sizeof(EHABIIndexEntry));
1237
}
1238
1239
EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
1240
: _i(i), _addressSpace(&addressSpace), _sects(&sects) {}
1241
1242
_Self& operator++() { ++_i; return *this; }
1243
_Self& operator+=(size_t a) { _i += a; return *this; }
1244
_Self& operator--() { assert(_i > 0); --_i; return *this; }
1245
_Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; }
1246
1247
_Self operator+(size_t a) { _Self out = *this; out._i += a; return out; }
1248
_Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; }
1249
1250
size_t operator-(const _Self& other) { return _i - other._i; }
1251
1252
bool operator==(const _Self& other) const {
1253
assert(_addressSpace == other._addressSpace);
1254
assert(_sects == other._sects);
1255
return _i == other._i;
1256
}
1257
1258
typename A::pint_t operator*() const { return functionAddress(); }
1259
1260
typename A::pint_t functionAddress() const {
1261
typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1262
EHABIIndexEntry, _i, functionOffset);
1263
return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));
1264
}
1265
1266
typename A::pint_t dataAddress() {
1267
typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1268
EHABIIndexEntry, _i, data);
1269
return indexAddr;
1270
}
1271
1272
private:
1273
size_t _i;
1274
A* _addressSpace;
1275
const UnwindInfoSections* _sects;
1276
};
1277
1278
template <typename A, typename R>
1279
bool UnwindCursor<A, R>::getInfoFromEHABISection(
1280
pint_t pc,
1281
const UnwindInfoSections &sects) {
1282
EHABISectionIterator<A> begin =
1283
EHABISectionIterator<A>::begin(_addressSpace, sects);
1284
EHABISectionIterator<A> end =
1285
EHABISectionIterator<A>::end(_addressSpace, sects);
1286
if (begin == end)
1287
return false;
1288
1289
EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
1290
if (itNextPC == begin)
1291
return false;
1292
EHABISectionIterator<A> itThisPC = itNextPC - 1;
1293
1294
pint_t thisPC = itThisPC.functionAddress();
1295
// If an exception is thrown from a function, corresponding to the last entry
1296
// in the table, we don't really know the function extent and have to choose a
1297
// value for nextPC. Choosing max() will allow the range check during trace to
1298
// succeed.
1299
pint_t nextPC = (itNextPC == end) ? std::numeric_limits<pint_t>::max()
1300
: itNextPC.functionAddress();
1301
pint_t indexDataAddr = itThisPC.dataAddress();
1302
1303
if (indexDataAddr == 0)
1304
return false;
1305
1306
uint32_t indexData = _addressSpace.get32(indexDataAddr);
1307
if (indexData == UNW_EXIDX_CANTUNWIND)
1308
return false;
1309
1310
// If the high bit is set, the exception handling table entry is inline inside
1311
// the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1312
// the table points at an offset in the exception handling table (section 5 EHABI).
1313
pint_t exceptionTableAddr;
1314
uint32_t exceptionTableData;
1315
bool isSingleWordEHT;
1316
if (indexData & 0x80000000) {
1317
exceptionTableAddr = indexDataAddr;
1318
// TODO(ajwong): Should this data be 0?
1319
exceptionTableData = indexData;
1320
isSingleWordEHT = true;
1321
} else {
1322
exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);
1323
exceptionTableData = _addressSpace.get32(exceptionTableAddr);
1324
isSingleWordEHT = false;
1325
}
1326
1327
// Now we know the 3 things:
1328
// exceptionTableAddr -- exception handler table entry.
1329
// exceptionTableData -- the data inside the first word of the eht entry.
1330
// isSingleWordEHT -- whether the entry is in the index.
1331
unw_word_t personalityRoutine = 0xbadf00d;
1332
bool scope32 = false;
1333
uintptr_t lsda;
1334
1335
// If the high bit in the exception handling table entry is set, the entry is
1336
// in compact form (section 6.3 EHABI).
1337
if (exceptionTableData & 0x80000000) {
1338
// Grab the index of the personality routine from the compact form.
1339
uint32_t choice = (exceptionTableData & 0x0f000000) >> 24;
1340
uint32_t extraWords = 0;
1341
switch (choice) {
1342
case 0:
1343
personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;
1344
extraWords = 0;
1345
scope32 = false;
1346
lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4);
1347
break;
1348
case 1:
1349
personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;
1350
extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1351
scope32 = false;
1352
lsda = exceptionTableAddr + (extraWords + 1) * 4;
1353
break;
1354
case 2:
1355
personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;
1356
extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1357
scope32 = true;
1358
lsda = exceptionTableAddr + (extraWords + 1) * 4;
1359
break;
1360
default:
1361
_LIBUNWIND_ABORT("unknown personality routine");
1362
return false;
1363
}
1364
1365
if (isSingleWordEHT) {
1366
if (extraWords != 0) {
1367
_LIBUNWIND_ABORT("index inlined table detected but pr function "
1368
"requires extra words");
1369
return false;
1370
}
1371
}
1372
} else {
1373
pint_t personalityAddr =
1374
exceptionTableAddr + signExtendPrel31(exceptionTableData);
1375
personalityRoutine = personalityAddr;
1376
1377
// ARM EHABI # 6.2, # 9.2
1378
//
1379
// +---- ehtp
1380
// v
1381
// +--------------------------------------+
1382
// | +--------+--------+--------+-------+ |
1383
// | |0| prel31 to personalityRoutine | |
1384
// | +--------+--------+--------+-------+ |
1385
// | | N | unwind opcodes | | <-- UnwindData
1386
// | +--------+--------+--------+-------+ |
1387
// | | Word 2 unwind opcodes | |
1388
// | +--------+--------+--------+-------+ |
1389
// | ... |
1390
// | +--------+--------+--------+-------+ |
1391
// | | Word N unwind opcodes | |
1392
// | +--------+--------+--------+-------+ |
1393
// | | LSDA | | <-- lsda
1394
// | | ... | |
1395
// | +--------+--------+--------+-------+ |
1396
// +--------------------------------------+
1397
1398
uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;
1399
uint32_t FirstDataWord = *UnwindData;
1400
size_t N = ((FirstDataWord >> 24) & 0xff);
1401
size_t NDataWords = N + 1;
1402
lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);
1403
}
1404
1405
_info.start_ip = thisPC;
1406
_info.end_ip = nextPC;
1407
_info.handler = personalityRoutine;
1408
_info.unwind_info = exceptionTableAddr;
1409
_info.lsda = lsda;
1410
// flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1411
_info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum?
1412
1413
return true;
1414
}
1415
#endif
1416
1417
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1418
template <typename A, typename R>
1419
bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
1420
const UnwindInfoSections &sects,
1421
uint32_t fdeSectionOffsetHint) {
1422
typename CFI_Parser<A>::FDE_Info fdeInfo;
1423
typename CFI_Parser<A>::CIE_Info cieInfo;
1424
bool foundFDE = false;
1425
bool foundInCache = false;
1426
// If compact encoding table gave offset into dwarf section, go directly there
1427
if (fdeSectionOffsetHint != 0) {
1428
foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1429
(uint32_t)sects.dwarf_section_length,
1430
sects.dwarf_section + fdeSectionOffsetHint,
1431
&fdeInfo, &cieInfo);
1432
}
1433
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1434
if (!foundFDE && (sects.dwarf_index_section != 0)) {
1435
foundFDE = EHHeaderParser<A>::findFDE(
1436
_addressSpace, pc, sects.dwarf_index_section,
1437
(uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
1438
}
1439
#endif
1440
if (!foundFDE) {
1441
// otherwise, search cache of previously found FDEs.
1442
pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);
1443
if (cachedFDE != 0) {
1444
foundFDE =
1445
CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1446
(uint32_t)sects.dwarf_section_length,
1447
cachedFDE, &fdeInfo, &cieInfo);
1448
foundInCache = foundFDE;
1449
}
1450
}
1451
if (!foundFDE) {
1452
// Still not found, do full scan of __eh_frame section.
1453
foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1454
(uint32_t)sects.dwarf_section_length, 0,
1455
&fdeInfo, &cieInfo);
1456
}
1457
if (foundFDE) {
1458
typename CFI_Parser<A>::PrologInfo prolog;
1459
if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
1460
R::getArch(), &prolog)) {
1461
// Save off parsed FDE info
1462
_info.start_ip = fdeInfo.pcStart;
1463
_info.end_ip = fdeInfo.pcEnd;
1464
_info.lsda = fdeInfo.lsda;
1465
_info.handler = cieInfo.personality;
1466
_info.gp = prolog.spExtraArgSize;
1467
_info.flags = 0;
1468
_info.format = dwarfEncoding();
1469
_info.unwind_info = fdeInfo.fdeStart;
1470
_info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1471
_info.extra = (unw_word_t) sects.dso_base;
1472
1473
// Add to cache (to make next lookup faster) if we had no hint
1474
// and there was no index.
1475
if (!foundInCache && (fdeSectionOffsetHint == 0)) {
1476
#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1477
if (sects.dwarf_index_section == 0)
1478
#endif
1479
DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
1480
fdeInfo.fdeStart);
1481
}
1482
return true;
1483
}
1484
}
1485
//_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1486
return false;
1487
}
1488
#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1489
1490
1491
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1492
template <typename A, typename R>
1493
bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
1494
const UnwindInfoSections &sects) {
1495
const bool log = false;
1496
if (log)
1497
fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1498
(uint64_t)pc, (uint64_t)sects.dso_base);
1499
1500
const UnwindSectionHeader<A> sectionHeader(_addressSpace,
1501
sects.compact_unwind_section);
1502
if (sectionHeader.version() != UNWIND_SECTION_VERSION)
1503
return false;
1504
1505
// do a binary search of top level index to find page with unwind info
1506
pint_t targetFunctionOffset = pc - sects.dso_base;
1507
const UnwindSectionIndexArray<A> topIndex(_addressSpace,
1508
sects.compact_unwind_section
1509
+ sectionHeader.indexSectionOffset());
1510
uint32_t low = 0;
1511
uint32_t high = sectionHeader.indexCount();
1512
uint32_t last = high - 1;
1513
while (low < high) {
1514
uint32_t mid = (low + high) / 2;
1515
//if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1516
//mid, low, high, topIndex.functionOffset(mid));
1517
if (topIndex.functionOffset(mid) <= targetFunctionOffset) {
1518
if ((mid == last) ||
1519
(topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {
1520
low = mid;
1521
break;
1522
} else {
1523
low = mid + 1;
1524
}
1525
} else {
1526
high = mid;
1527
}
1528
}
1529
const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
1530
const uint32_t firstLevelNextPageFunctionOffset =
1531
topIndex.functionOffset(low + 1);
1532
const pint_t secondLevelAddr =
1533
sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);
1534
const pint_t lsdaArrayStartAddr =
1535
sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);
1536
const pint_t lsdaArrayEndAddr =
1537
sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);
1538
if (log)
1539
fprintf(stderr, "\tfirst level search for result index=%d "
1540
"to secondLevelAddr=0x%llX\n",
1541
low, (uint64_t) secondLevelAddr);
1542
// do a binary search of second level page index
1543
uint32_t encoding = 0;
1544
pint_t funcStart = 0;
1545
pint_t funcEnd = 0;
1546
pint_t lsda = 0;
1547
pint_t personality = 0;
1548
uint32_t pageKind = _addressSpace.get32(secondLevelAddr);
1549
if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {
1550
// regular page
1551
UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,
1552
secondLevelAddr);
1553
UnwindSectionRegularArray<A> pageIndex(
1554
_addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1555
// binary search looks for entry with e where index[e].offset <= pc <
1556
// index[e+1].offset
1557
if (log)
1558
fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "
1559
"regular page starting at secondLevelAddr=0x%llX\n",
1560
(uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);
1561
low = 0;
1562
high = pageHeader.entryCount();
1563
while (low < high) {
1564
uint32_t mid = (low + high) / 2;
1565
if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {
1566
if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {
1567
// at end of table
1568
low = mid;
1569
funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1570
break;
1571
} else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {
1572
// next is too big, so we found it
1573
low = mid;
1574
funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;
1575
break;
1576
} else {
1577
low = mid + 1;
1578
}
1579
} else {
1580
high = mid;
1581
}
1582
}
1583
encoding = pageIndex.encoding(low);
1584
funcStart = pageIndex.functionOffset(low) + sects.dso_base;
1585
if (pc < funcStart) {
1586
if (log)
1587
fprintf(
1588
stderr,
1589
"\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1590
(uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1591
return false;
1592
}
1593
if (pc > funcEnd) {
1594
if (log)
1595
fprintf(
1596
stderr,
1597
"\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1598
(uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1599
return false;
1600
}
1601
} else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {
1602
// compressed page
1603
UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,
1604
secondLevelAddr);
1605
UnwindSectionCompressedArray<A> pageIndex(
1606
_addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1607
const uint32_t targetFunctionPageOffset =
1608
(uint32_t)(targetFunctionOffset - firstLevelFunctionOffset);
1609
// binary search looks for entry with e where index[e].offset <= pc <
1610
// index[e+1].offset
1611
if (log)
1612
fprintf(stderr, "\tbinary search of compressed page starting at "
1613
"secondLevelAddr=0x%llX\n",
1614
(uint64_t) secondLevelAddr);
1615
low = 0;
1616
last = pageHeader.entryCount() - 1;
1617
high = pageHeader.entryCount();
1618
while (low < high) {
1619
uint32_t mid = (low + high) / 2;
1620
if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {
1621
if ((mid == last) ||
1622
(pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {
1623
low = mid;
1624
break;
1625
} else {
1626
low = mid + 1;
1627
}
1628
} else {
1629
high = mid;
1630
}
1631
}
1632
funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset
1633
+ sects.dso_base;
1634
if (low < last)
1635
funcEnd =
1636
pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset
1637
+ sects.dso_base;
1638
else
1639
funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1640
if (pc < funcStart) {
1641
_LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
1642
"level compressed unwind table. funcStart=0x%llX",
1643
(uint64_t) pc, (uint64_t) funcStart);
1644
return false;
1645
}
1646
if (pc > funcEnd) {
1647
_LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
1648
"level compressed unwind table. funcEnd=0x%llX",
1649
(uint64_t) pc, (uint64_t) funcEnd);
1650
return false;
1651
}
1652
uint16_t encodingIndex = pageIndex.encodingIndex(low);
1653
if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) {
1654
// encoding is in common table in section header
1655
encoding = _addressSpace.get32(
1656
sects.compact_unwind_section +
1657
sectionHeader.commonEncodingsArraySectionOffset() +
1658
encodingIndex * sizeof(uint32_t));
1659
} else {
1660
// encoding is in page specific table
1661
uint16_t pageEncodingIndex =
1662
encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount();
1663
encoding = _addressSpace.get32(secondLevelAddr +
1664
pageHeader.encodingsPageOffset() +
1665
pageEncodingIndex * sizeof(uint32_t));
1666
}
1667
} else {
1668
_LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second "
1669
"level page",
1670
(uint64_t) sects.compact_unwind_section);
1671
return false;
1672
}
1673
1674
// look up LSDA, if encoding says function has one
1675
if (encoding & UNWIND_HAS_LSDA) {
1676
UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);
1677
uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);
1678
low = 0;
1679
high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /
1680
sizeof(unwind_info_section_header_lsda_index_entry);
1681
// binary search looks for entry with exact match for functionOffset
1682
if (log)
1683
fprintf(stderr,
1684
"\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1685
funcStartOffset);
1686
while (low < high) {
1687
uint32_t mid = (low + high) / 2;
1688
if (lsdaIndex.functionOffset(mid) == funcStartOffset) {
1689
lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;
1690
break;
1691
} else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {
1692
low = mid + 1;
1693
} else {
1694
high = mid;
1695
}
1696
}
1697
if (lsda == 0) {
1698
_LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1699
"pc=0x%0llX, but lsda table has no entry",
1700
encoding, (uint64_t) pc);
1701
return false;
1702
}
1703
}
1704
1705
// extact personality routine, if encoding says function has one
1706
uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
1707
(__builtin_ctz(UNWIND_PERSONALITY_MASK));
1708
if (personalityIndex != 0) {
1709
--personalityIndex; // change 1-based to zero-based index
1710
if (personalityIndex > sectionHeader.personalityArrayCount()) {
1711
_LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
1712
"but personality table has only %d entires",
1713
encoding, personalityIndex,
1714
sectionHeader.personalityArrayCount());
1715
return false;
1716
}
1717
int32_t personalityDelta = (int32_t)_addressSpace.get32(
1718
sects.compact_unwind_section +
1719
sectionHeader.personalityArraySectionOffset() +
1720
personalityIndex * sizeof(uint32_t));
1721
pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
1722
personality = _addressSpace.getP(personalityPointer);
1723
if (log)
1724
fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1725
"personalityDelta=0x%08X, personality=0x%08llX\n",
1726
(uint64_t) pc, personalityDelta, (uint64_t) personality);
1727
}
1728
1729
if (log)
1730
fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1731
"encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1732
(uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart);
1733
_info.start_ip = funcStart;
1734
_info.end_ip = funcEnd;
1735
_info.lsda = lsda;
1736
_info.handler = personality;
1737
_info.gp = 0;
1738
_info.flags = 0;
1739
_info.format = encoding;
1740
_info.unwind_info = 0;
1741
_info.unwind_info_size = 0;
1742
_info.extra = sects.dso_base;
1743
return true;
1744
}
1745
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1746
1747
1748
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1749
template <typename A, typename R>
1750
bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
1751
pint_t base;
1752
RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);
1753
if (!unwindEntry) {
1754
_LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);
1755
return false;
1756
}
1757
_info.gp = 0;
1758
_info.flags = 0;
1759
_info.format = 0;
1760
_info.unwind_info_size = sizeof(RUNTIME_FUNCTION);
1761
_info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry);
1762
_info.extra = base;
1763
_info.start_ip = base + unwindEntry->BeginAddress;
1764
#ifdef _LIBUNWIND_TARGET_X86_64
1765
_info.end_ip = base + unwindEntry->EndAddress;
1766
// Only fill in the handler and LSDA if they're stale.
1767
if (pc != getLastPC()) {
1768
UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);
1769
if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {
1770
// The personality is given in the UNWIND_INFO itself. The LSDA immediately
1771
// follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
1772
// these structures.)
1773
// N.B. UNWIND_INFO structs are DWORD-aligned.
1774
uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
1775
const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
1776
_info.lsda = reinterpret_cast<unw_word_t>(handler+1);
1777
if (*handler) {
1778
_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
1779
} else
1780
_info.handler = 0;
1781
} else {
1782
_info.lsda = 0;
1783
_info.handler = 0;
1784
}
1785
}
1786
#elif defined(_LIBUNWIND_TARGET_ARM)
1787
_info.end_ip = _info.start_ip + unwindEntry->FunctionLength;
1788
_info.lsda = 0; // FIXME
1789
_info.handler = 0; // FIXME
1790
#endif
1791
setLastPC(pc);
1792
return true;
1793
}
1794
#endif
1795
1796
1797
template <typename A, typename R>
1798
void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
1799
pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
1800
#if defined(_LIBUNWIND_ARM_EHABI)
1801
// Remove the thumb bit so the IP represents the actual instruction address.
1802
// This matches the behaviour of _Unwind_GetIP on arm.
1803
pc &= (pint_t)~0x1;
1804
#endif
1805
1806
// If the last line of a function is a "throw" the compiler sometimes
1807
// emits no instructions after the call to __cxa_throw. This means
1808
// the return address is actually the start of the next function.
1809
// To disambiguate this, back up the pc when we know it is a return
1810
// address.
1811
if (isReturnAddress)
1812
--pc;
1813
1814
// Ask address space object to find unwind sections for this pc.
1815
UnwindInfoSections sects;
1816
if (_addressSpace.findUnwindSections(pc, sects)) {
1817
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1818
// If there is a compact unwind encoding table, look there first.
1819
if (sects.compact_unwind_section != 0) {
1820
if (this->getInfoFromCompactEncodingSection(pc, sects)) {
1821
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1822
// Found info in table, done unless encoding says to use dwarf.
1823
uint32_t dwarfOffset;
1824
if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
1825
if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {
1826
// found info in dwarf, done
1827
return;
1828
}
1829
}
1830
#endif
1831
// If unwind table has entry, but entry says there is no unwind info,
1832
// record that we have no unwind info.
1833
if (_info.format == 0)
1834
_unwindInfoMissing = true;
1835
return;
1836
}
1837
}
1838
#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1839
1840
#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1841
// If there is SEH unwind info, look there next.
1842
if (this->getInfoFromSEH(pc))
1843
return;
1844
#endif
1845
1846
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1847
// If there is dwarf unwind info, look there next.
1848
if (sects.dwarf_section != 0) {
1849
if (this->getInfoFromDwarfSection(pc, sects)) {
1850
// found info in dwarf, done
1851
return;
1852
}
1853
}
1854
#endif
1855
1856
#if defined(_LIBUNWIND_ARM_EHABI)
1857
// If there is ARM EHABI unwind info, look there next.
1858
if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
1859
return;
1860
#endif
1861
}
1862
1863
#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1864
// There is no static unwind info for this pc. Look to see if an FDE was
1865
// dynamically registered for it.
1866
pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
1867
if (cachedFDE != 0) {
1868
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1869
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1870
const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace,
1871
cachedFDE, &fdeInfo, &cieInfo);
1872
if (msg == NULL) {
1873
typename CFI_Parser<A>::PrologInfo prolog;
1874
if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
1875
pc, R::getArch(), &prolog)) {
1876
// save off parsed FDE info
1877
_info.start_ip = fdeInfo.pcStart;
1878
_info.end_ip = fdeInfo.pcEnd;
1879
_info.lsda = fdeInfo.lsda;
1880
_info.handler = cieInfo.personality;
1881
_info.gp = prolog.spExtraArgSize;
1882
// Some frameless functions need SP
1883
// altered when resuming in function.
1884
_info.flags = 0;
1885
_info.format = dwarfEncoding();
1886
_info.unwind_info = fdeInfo.fdeStart;
1887
_info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1888
_info.extra = 0;
1889
return;
1890
}
1891
}
1892
}
1893
1894
// Lastly, ask AddressSpace object about platform specific ways to locate
1895
// other FDEs.
1896
pint_t fde;
1897
if (_addressSpace.findOtherFDE(pc, fde)) {
1898
CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1899
CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1900
if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
1901
// Double check this FDE is for a function that includes the pc.
1902
if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
1903
typename CFI_Parser<A>::PrologInfo prolog;
1904
if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
1905
pc, R::getArch(), &prolog)) {
1906
// save off parsed FDE info
1907
_info.start_ip = fdeInfo.pcStart;
1908
_info.end_ip = fdeInfo.pcEnd;
1909
_info.lsda = fdeInfo.lsda;
1910
_info.handler = cieInfo.personality;
1911
_info.gp = prolog.spExtraArgSize;
1912
_info.flags = 0;
1913
_info.format = dwarfEncoding();
1914
_info.unwind_info = fdeInfo.fdeStart;
1915
_info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1916
_info.extra = 0;
1917
return;
1918
}
1919
}
1920
}
1921
}
1922
#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1923
1924
// no unwind info, flag that we can't reliably unwind
1925
_unwindInfoMissing = true;
1926
}
1927
1928
template <typename A, typename R>
1929
int UnwindCursor<A, R>::step() {
1930
// Bottom of stack is defined is when unwind info cannot be found.
1931
if (_unwindInfoMissing)
1932
return UNW_STEP_END;
1933
1934
// Use unwinding info to modify register set as if function returned.
1935
int result;
1936
#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1937
result = this->stepWithCompactEncoding();
1938
#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1939
result = this->stepWithSEHData();
1940
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1941
result = this->stepWithDwarfFDE();
1942
#elif defined(_LIBUNWIND_ARM_EHABI)
1943
result = this->stepWithEHABI();
1944
#else
1945
#error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
1946
_LIBUNWIND_SUPPORT_SEH_UNWIND or \
1947
_LIBUNWIND_SUPPORT_DWARF_UNWIND or \
1948
_LIBUNWIND_ARM_EHABI
1949
#endif
1950
1951
// update info based on new PC
1952
if (result == UNW_STEP_SUCCESS) {
1953
this->setInfoBasedOnIPRegister(true);
1954
if (_unwindInfoMissing)
1955
return UNW_STEP_END;
1956
}
1957
1958
return result;
1959
}
1960
1961
template <typename A, typename R>
1962
void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
1963
*info = _info;
1964
}
1965
1966
template <typename A, typename R>
1967
bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
1968
unw_word_t *offset) {
1969
return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),
1970
buf, bufLen, offset);
1971
}
1972
1973
} // namespace libunwind
1974
1975
#endif // __UNWINDCURSOR_HPP__
1976
1977