1 //===------------------------- UnwindCursor.hpp ---------------------------===//
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
8 // C++ interface to lower levels of libunwind
9 //===----------------------------------------------------------------------===//
11 #ifndef __UNWINDCURSOR_HPP__
12 #define __UNWINDCURSOR_HPP__
24 #include <mach-o/dyld.h>
27 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
28 // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
30 // MinGW-w64 has always provided this struct.
31 #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
32 !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
33 struct _DISPATCHER_CONTEXT
{
36 PRUNTIME_FUNCTION FunctionEntry
;
37 ULONG64 EstablisherFrame
;
39 PCONTEXT ContextRecord
;
40 PEXCEPTION_ROUTINE LanguageHandler
;
42 PUNWIND_HISTORY_TABLE HistoryTable
;
53 uint8_t FrameRegister
: 4;
54 uint8_t FrameOffset
: 4;
55 uint16_t UnwindCodes
[2];
58 extern "C" _Unwind_Reason_Code
__libunwind_seh_personality(
59 int, _Unwind_Action
, uint64_t, _Unwind_Exception
*,
60 struct _Unwind_Context
*);
66 #include "AddressSpace.hpp"
67 #include "CompactUnwinder.hpp"
69 #include "DwarfInstructions.hpp"
70 #include "EHHeaderParser.hpp"
71 #include "libunwind.h"
72 #include "Registers.hpp"
73 #include "RWMutex.hpp"
74 #include "Unwind-EHABI.h"
78 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
79 /// Cache of recently found FDEs.
81 class _LIBUNWIND_HIDDEN DwarfFDECache
{
82 typedef typename
A::pint_t pint_t
;
84 static constexpr pint_t kSearchAll
= static_cast<pint_t
>(-1);
85 static pint_t
findFDE(pint_t mh
, pint_t pc
);
86 static void add(pint_t mh
, pint_t ip_start
, pint_t ip_end
, pint_t fde
);
87 static void removeAllIn(pint_t mh
);
88 static void iterateCacheEntries(void (*func
)(unw_word_t ip_start
,
90 unw_word_t fde
, unw_word_t mh
));
101 // These fields are all static to avoid needing an initializer.
102 // There is only one instance of this class per process.
103 static RWMutex _lock
;
105 static void dyldUnloadHook(const struct mach_header
*mh
, intptr_t slide
);
106 static bool _registeredForDyldUnloads
;
108 static entry
*_buffer
;
109 static entry
*_bufferUsed
;
110 static entry
*_bufferEnd
;
111 static entry _initialBuffer
[64];
114 template <typename A
>
115 typename DwarfFDECache
<A
>::entry
*
116 DwarfFDECache
<A
>::_buffer
= _initialBuffer
;
118 template <typename A
>
119 typename DwarfFDECache
<A
>::entry
*
120 DwarfFDECache
<A
>::_bufferUsed
= _initialBuffer
;
122 template <typename A
>
123 typename DwarfFDECache
<A
>::entry
*
124 DwarfFDECache
<A
>::_bufferEnd
= &_initialBuffer
[64];
126 template <typename A
>
127 typename DwarfFDECache
<A
>::entry DwarfFDECache
<A
>::_initialBuffer
[64];
129 template <typename A
>
130 RWMutex DwarfFDECache
<A
>::_lock
;
133 template <typename A
>
134 bool DwarfFDECache
<A
>::_registeredForDyldUnloads
= false;
137 template <typename A
>
138 typename
A::pint_t DwarfFDECache
<A
>::findFDE(pint_t mh
, pint_t pc
) {
140 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock_shared());
141 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
142 if ((mh
== p
->mh
) || (mh
== kSearchAll
)) {
143 if ((p
->ip_start
<= pc
) && (pc
< p
->ip_end
)) {
149 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock_shared());
153 template <typename A
>
154 void DwarfFDECache
<A
>::add(pint_t mh
, pint_t ip_start
, pint_t ip_end
,
156 #if !defined(_LIBUNWIND_NO_HEAP)
157 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
158 if (_bufferUsed
>= _bufferEnd
) {
159 size_t oldSize
= (size_t)(_bufferEnd
- _buffer
);
160 size_t newSize
= oldSize
* 4;
161 // Can't use operator new (we are below it).
162 entry
*newBuffer
= (entry
*)malloc(newSize
* sizeof(entry
));
163 memcpy(newBuffer
, _buffer
, oldSize
* sizeof(entry
));
164 if (_buffer
!= _initialBuffer
)
167 _bufferUsed
= &newBuffer
[oldSize
];
168 _bufferEnd
= &newBuffer
[newSize
];
170 _bufferUsed
->mh
= mh
;
171 _bufferUsed
->ip_start
= ip_start
;
172 _bufferUsed
->ip_end
= ip_end
;
173 _bufferUsed
->fde
= fde
;
176 if (!_registeredForDyldUnloads
) {
177 _dyld_register_func_for_remove_image(&dyldUnloadHook
);
178 _registeredForDyldUnloads
= true;
181 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
185 template <typename A
>
186 void DwarfFDECache
<A
>::removeAllIn(pint_t mh
) {
187 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
189 for (const entry
*s
= _buffer
; s
< _bufferUsed
; ++s
) {
197 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
201 template <typename A
>
202 void DwarfFDECache
<A
>::dyldUnloadHook(const struct mach_header
*mh
, intptr_t ) {
203 removeAllIn((pint_t
) mh
);
207 template <typename A
>
208 void DwarfFDECache
<A
>::iterateCacheEntries(void (*func
)(
209 unw_word_t ip_start
, unw_word_t ip_end
, unw_word_t fde
, unw_word_t mh
)) {
210 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
211 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
212 (*func
)(p
->ip_start
, p
->ip_end
, p
->fde
, p
->mh
);
214 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
216 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
219 #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
221 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
222 template <typename A
> class UnwindSectionHeader
{
224 UnwindSectionHeader(A
&addressSpace
, typename
A::pint_t addr
)
225 : _addressSpace(addressSpace
), _addr(addr
) {}
227 uint32_t version() const {
228 return _addressSpace
.get32(_addr
+
229 offsetof(unwind_info_section_header
, version
));
231 uint32_t commonEncodingsArraySectionOffset() const {
232 return _addressSpace
.get32(_addr
+
233 offsetof(unwind_info_section_header
,
234 commonEncodingsArraySectionOffset
));
236 uint32_t commonEncodingsArrayCount() const {
237 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
238 commonEncodingsArrayCount
));
240 uint32_t personalityArraySectionOffset() const {
241 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
242 personalityArraySectionOffset
));
244 uint32_t personalityArrayCount() const {
245 return _addressSpace
.get32(
246 _addr
+ offsetof(unwind_info_section_header
, personalityArrayCount
));
248 uint32_t indexSectionOffset() const {
249 return _addressSpace
.get32(
250 _addr
+ offsetof(unwind_info_section_header
, indexSectionOffset
));
252 uint32_t indexCount() const {
253 return _addressSpace
.get32(
254 _addr
+ offsetof(unwind_info_section_header
, indexCount
));
259 typename
A::pint_t _addr
;
262 template <typename A
> class UnwindSectionIndexArray
{
264 UnwindSectionIndexArray(A
&addressSpace
, typename
A::pint_t addr
)
265 : _addressSpace(addressSpace
), _addr(addr
) {}
267 uint32_t functionOffset(uint32_t index
) const {
268 return _addressSpace
.get32(
269 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
272 uint32_t secondLevelPagesSectionOffset(uint32_t index
) const {
273 return _addressSpace
.get32(
274 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
275 secondLevelPagesSectionOffset
));
277 uint32_t lsdaIndexArraySectionOffset(uint32_t index
) const {
278 return _addressSpace
.get32(
279 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
280 lsdaIndexArraySectionOffset
));
285 typename
A::pint_t _addr
;
288 template <typename A
> class UnwindSectionRegularPageHeader
{
290 UnwindSectionRegularPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
291 : _addressSpace(addressSpace
), _addr(addr
) {}
293 uint32_t kind() const {
294 return _addressSpace
.get32(
295 _addr
+ offsetof(unwind_info_regular_second_level_page_header
, kind
));
297 uint16_t entryPageOffset() const {
298 return _addressSpace
.get16(
299 _addr
+ offsetof(unwind_info_regular_second_level_page_header
,
302 uint16_t entryCount() const {
303 return _addressSpace
.get16(
305 offsetof(unwind_info_regular_second_level_page_header
, entryCount
));
310 typename
A::pint_t _addr
;
313 template <typename A
> class UnwindSectionRegularArray
{
315 UnwindSectionRegularArray(A
&addressSpace
, typename
A::pint_t addr
)
316 : _addressSpace(addressSpace
), _addr(addr
) {}
318 uint32_t functionOffset(uint32_t index
) const {
319 return _addressSpace
.get32(
320 _addr
+ arrayoffsetof(unwind_info_regular_second_level_entry
, index
,
323 uint32_t encoding(uint32_t index
) const {
324 return _addressSpace
.get32(
326 arrayoffsetof(unwind_info_regular_second_level_entry
, index
, encoding
));
331 typename
A::pint_t _addr
;
334 template <typename A
> class UnwindSectionCompressedPageHeader
{
336 UnwindSectionCompressedPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
337 : _addressSpace(addressSpace
), _addr(addr
) {}
339 uint32_t kind() const {
340 return _addressSpace
.get32(
342 offsetof(unwind_info_compressed_second_level_page_header
, kind
));
344 uint16_t entryPageOffset() const {
345 return _addressSpace
.get16(
346 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
349 uint16_t entryCount() const {
350 return _addressSpace
.get16(
352 offsetof(unwind_info_compressed_second_level_page_header
, entryCount
));
354 uint16_t encodingsPageOffset() const {
355 return _addressSpace
.get16(
356 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
357 encodingsPageOffset
));
359 uint16_t encodingsCount() const {
360 return _addressSpace
.get16(
361 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
367 typename
A::pint_t _addr
;
370 template <typename A
> class UnwindSectionCompressedArray
{
372 UnwindSectionCompressedArray(A
&addressSpace
, typename
A::pint_t addr
)
373 : _addressSpace(addressSpace
), _addr(addr
) {}
375 uint32_t functionOffset(uint32_t index
) const {
376 return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
377 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
379 uint16_t encodingIndex(uint32_t index
) const {
380 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
381 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
386 typename
A::pint_t _addr
;
389 template <typename A
> class UnwindSectionLsdaArray
{
391 UnwindSectionLsdaArray(A
&addressSpace
, typename
A::pint_t addr
)
392 : _addressSpace(addressSpace
), _addr(addr
) {}
394 uint32_t functionOffset(uint32_t index
) const {
395 return _addressSpace
.get32(
396 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
397 index
, functionOffset
));
399 uint32_t lsdaOffset(uint32_t index
) const {
400 return _addressSpace
.get32(
401 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
407 typename
A::pint_t _addr
;
409 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
411 class _LIBUNWIND_HIDDEN AbstractUnwindCursor
{
413 // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
414 // This avoids an unnecessary dependency to libc++abi.
415 void operator delete(void *, size_t) {}
417 virtual ~AbstractUnwindCursor() {}
418 virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
419 virtual unw_word_t
getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
420 virtual void setReg(int, unw_word_t
) {
421 _LIBUNWIND_ABORT("setReg not implemented");
423 virtual bool validFloatReg(int) {
424 _LIBUNWIND_ABORT("validFloatReg not implemented");
426 virtual unw_fpreg_t
getFloatReg(int) {
427 _LIBUNWIND_ABORT("getFloatReg not implemented");
429 virtual void setFloatReg(int, unw_fpreg_t
) {
430 _LIBUNWIND_ABORT("setFloatReg not implemented");
432 virtual int step() { _LIBUNWIND_ABORT("step not implemented"); }
433 virtual void getInfo(unw_proc_info_t
*) {
434 _LIBUNWIND_ABORT("getInfo not implemented");
436 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
437 virtual bool isSignalFrame() {
438 _LIBUNWIND_ABORT("isSignalFrame not implemented");
440 virtual bool getFunctionName(char *, size_t, unw_word_t
*) {
441 _LIBUNWIND_ABORT("getFunctionName not implemented");
443 virtual void setInfoBasedOnIPRegister(bool = false) {
444 _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
446 virtual const char *getRegisterName(int) {
447 _LIBUNWIND_ABORT("getRegisterName not implemented");
450 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
454 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
456 /// \c UnwindCursor contains all state (including all register values) during
457 /// an unwind. This is normally stack-allocated inside a unw_cursor_t.
458 template <typename A
, typename R
>
459 class UnwindCursor
: public AbstractUnwindCursor
{
460 typedef typename
A::pint_t pint_t
;
462 UnwindCursor(unw_context_t
*context
, A
&as
);
463 UnwindCursor(CONTEXT
*context
, A
&as
);
464 UnwindCursor(A
&as
, void *threadArg
);
465 virtual ~UnwindCursor() {}
466 virtual bool validReg(int);
467 virtual unw_word_t
getReg(int);
468 virtual void setReg(int, unw_word_t
);
469 virtual bool validFloatReg(int);
470 virtual unw_fpreg_t
getFloatReg(int);
471 virtual void setFloatReg(int, unw_fpreg_t
);
473 virtual void getInfo(unw_proc_info_t
*);
474 virtual void jumpto();
475 virtual bool isSignalFrame();
476 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
477 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
478 virtual const char *getRegisterName(int num
);
480 virtual void saveVFPAsX();
483 DISPATCHER_CONTEXT
*getDispatcherContext() { return &_dispContext
; }
484 void setDispatcherContext(DISPATCHER_CONTEXT
*disp
) { _dispContext
= *disp
; }
486 // libunwind does not and should not depend on C++ library which means that we
487 // need our own defition of inline placement new.
488 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
492 pint_t
getLastPC() const { return _dispContext
.ControlPc
; }
493 void setLastPC(pint_t pc
) { _dispContext
.ControlPc
= pc
; }
494 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
495 _dispContext
.FunctionEntry
= RtlLookupFunctionEntry(pc
,
496 &_dispContext
.ImageBase
,
497 _dispContext
.HistoryTable
);
498 *base
= _dispContext
.ImageBase
;
499 return _dispContext
.FunctionEntry
;
501 bool getInfoFromSEH(pint_t pc
);
502 int stepWithSEHData() {
503 _dispContext
.LanguageHandler
= RtlVirtualUnwind(UNW_FLAG_UHANDLER
,
504 _dispContext
.ImageBase
,
505 _dispContext
.ControlPc
,
506 _dispContext
.FunctionEntry
,
507 _dispContext
.ContextRecord
,
508 &_dispContext
.HandlerData
,
509 &_dispContext
.EstablisherFrame
,
511 // Update some fields of the unwind info now, since we have them.
512 _info
.lsda
= reinterpret_cast<unw_word_t
>(_dispContext
.HandlerData
);
513 if (_dispContext
.LanguageHandler
) {
514 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
517 return UNW_STEP_SUCCESS
;
521 unw_proc_info_t _info
;
522 DISPATCHER_CONTEXT _dispContext
;
524 UNWIND_HISTORY_TABLE _histTable
;
525 bool _unwindInfoMissing
;
529 template <typename A
, typename R
>
530 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
531 : _addressSpace(as
), _unwindInfoMissing(false) {
532 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
533 "UnwindCursor<> does not fit in unw_cursor_t");
534 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
535 "UnwindCursor<> requires more alignment than unw_cursor_t");
536 memset(&_info
, 0, sizeof(_info
));
537 memset(&_histTable
, 0, sizeof(_histTable
));
538 _dispContext
.ContextRecord
= &_msContext
;
539 _dispContext
.HistoryTable
= &_histTable
;
540 // Initialize MS context from ours.
542 _msContext
.ContextFlags
= CONTEXT_CONTROL
|CONTEXT_INTEGER
|CONTEXT_FLOATING_POINT
;
543 #if defined(_LIBUNWIND_TARGET_X86_64)
544 _msContext
.Rax
= r
.getRegister(UNW_X86_64_RAX
);
545 _msContext
.Rcx
= r
.getRegister(UNW_X86_64_RCX
);
546 _msContext
.Rdx
= r
.getRegister(UNW_X86_64_RDX
);
547 _msContext
.Rbx
= r
.getRegister(UNW_X86_64_RBX
);
548 _msContext
.Rsp
= r
.getRegister(UNW_X86_64_RSP
);
549 _msContext
.Rbp
= r
.getRegister(UNW_X86_64_RBP
);
550 _msContext
.Rsi
= r
.getRegister(UNW_X86_64_RSI
);
551 _msContext
.Rdi
= r
.getRegister(UNW_X86_64_RDI
);
552 _msContext
.R8
= r
.getRegister(UNW_X86_64_R8
);
553 _msContext
.R9
= r
.getRegister(UNW_X86_64_R9
);
554 _msContext
.R10
= r
.getRegister(UNW_X86_64_R10
);
555 _msContext
.R11
= r
.getRegister(UNW_X86_64_R11
);
556 _msContext
.R12
= r
.getRegister(UNW_X86_64_R12
);
557 _msContext
.R13
= r
.getRegister(UNW_X86_64_R13
);
558 _msContext
.R14
= r
.getRegister(UNW_X86_64_R14
);
559 _msContext
.R15
= r
.getRegister(UNW_X86_64_R15
);
560 _msContext
.Rip
= r
.getRegister(UNW_REG_IP
);
565 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM0
);
566 _msContext
.Xmm0
= t
.m
;
567 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM1
);
568 _msContext
.Xmm1
= t
.m
;
569 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM2
);
570 _msContext
.Xmm2
= t
.m
;
571 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM3
);
572 _msContext
.Xmm3
= t
.m
;
573 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM4
);
574 _msContext
.Xmm4
= t
.m
;
575 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM5
);
576 _msContext
.Xmm5
= t
.m
;
577 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM6
);
578 _msContext
.Xmm6
= t
.m
;
579 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM7
);
580 _msContext
.Xmm7
= t
.m
;
581 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM8
);
582 _msContext
.Xmm8
= t
.m
;
583 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM9
);
584 _msContext
.Xmm9
= t
.m
;
585 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM10
);
586 _msContext
.Xmm10
= t
.m
;
587 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM11
);
588 _msContext
.Xmm11
= t
.m
;
589 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM12
);
590 _msContext
.Xmm12
= t
.m
;
591 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM13
);
592 _msContext
.Xmm13
= t
.m
;
593 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM14
);
594 _msContext
.Xmm14
= t
.m
;
595 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM15
);
596 _msContext
.Xmm15
= t
.m
;
597 #elif defined(_LIBUNWIND_TARGET_ARM)
598 _msContext
.R0
= r
.getRegister(UNW_ARM_R0
);
599 _msContext
.R1
= r
.getRegister(UNW_ARM_R1
);
600 _msContext
.R2
= r
.getRegister(UNW_ARM_R2
);
601 _msContext
.R3
= r
.getRegister(UNW_ARM_R3
);
602 _msContext
.R4
= r
.getRegister(UNW_ARM_R4
);
603 _msContext
.R5
= r
.getRegister(UNW_ARM_R5
);
604 _msContext
.R6
= r
.getRegister(UNW_ARM_R6
);
605 _msContext
.R7
= r
.getRegister(UNW_ARM_R7
);
606 _msContext
.R8
= r
.getRegister(UNW_ARM_R8
);
607 _msContext
.R9
= r
.getRegister(UNW_ARM_R9
);
608 _msContext
.R10
= r
.getRegister(UNW_ARM_R10
);
609 _msContext
.R11
= r
.getRegister(UNW_ARM_R11
);
610 _msContext
.R12
= r
.getRegister(UNW_ARM_R12
);
611 _msContext
.Sp
= r
.getRegister(UNW_ARM_SP
);
612 _msContext
.Lr
= r
.getRegister(UNW_ARM_LR
);
613 _msContext
.Pc
= r
.getRegister(UNW_ARM_IP
);
614 for (int i
= UNW_ARM_D0
; i
<= UNW_ARM_D31
; ++i
) {
619 d
.d
= r
.getFloatRegister(i
);
620 _msContext
.D
[i
- UNW_ARM_D0
] = d
.w
;
622 #elif defined(_LIBUNWIND_TARGET_AARCH64)
623 for (int i
= UNW_ARM64_X0
; i
<= UNW_ARM64_X30
; ++i
)
624 _msContext
.X
[i
- UNW_ARM64_X0
] = r
.getRegister(i
);
625 _msContext
.Sp
= r
.getRegister(UNW_REG_SP
);
626 _msContext
.Pc
= r
.getRegister(UNW_REG_IP
);
627 for (int i
= UNW_ARM64_D0
; i
<= UNW_ARM64_D31
; ++i
)
628 _msContext
.V
[i
- UNW_ARM64_D0
].D
[0] = r
.getFloatRegister(i
);
632 template <typename A
, typename R
>
633 UnwindCursor
<A
, R
>::UnwindCursor(CONTEXT
*context
, A
&as
)
634 : _addressSpace(as
), _unwindInfoMissing(false) {
635 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
636 "UnwindCursor<> does not fit in unw_cursor_t");
637 memset(&_info
, 0, sizeof(_info
));
638 memset(&_histTable
, 0, sizeof(_histTable
));
639 _dispContext
.ContextRecord
= &_msContext
;
640 _dispContext
.HistoryTable
= &_histTable
;
641 _msContext
= *context
;
645 template <typename A
, typename R
>
646 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
647 if (regNum
== UNW_REG_IP
|| regNum
== UNW_REG_SP
) return true;
648 #if defined(_LIBUNWIND_TARGET_X86_64)
649 if (regNum
>= UNW_X86_64_RAX
&& regNum
<= UNW_X86_64_R15
) return true;
650 #elif defined(_LIBUNWIND_TARGET_ARM)
651 if (regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R15
) return true;
652 #elif defined(_LIBUNWIND_TARGET_AARCH64)
653 if (regNum
>= UNW_ARM64_X0
&& regNum
<= UNW_ARM64_X30
) return true;
658 template <typename A
, typename R
>
659 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
661 #if defined(_LIBUNWIND_TARGET_X86_64)
662 case UNW_REG_IP
: return _msContext
.Rip
;
663 case UNW_X86_64_RAX
: return _msContext
.Rax
;
664 case UNW_X86_64_RDX
: return _msContext
.Rdx
;
665 case UNW_X86_64_RCX
: return _msContext
.Rcx
;
666 case UNW_X86_64_RBX
: return _msContext
.Rbx
;
668 case UNW_X86_64_RSP
: return _msContext
.Rsp
;
669 case UNW_X86_64_RBP
: return _msContext
.Rbp
;
670 case UNW_X86_64_RSI
: return _msContext
.Rsi
;
671 case UNW_X86_64_RDI
: return _msContext
.Rdi
;
672 case UNW_X86_64_R8
: return _msContext
.R8
;
673 case UNW_X86_64_R9
: return _msContext
.R9
;
674 case UNW_X86_64_R10
: return _msContext
.R10
;
675 case UNW_X86_64_R11
: return _msContext
.R11
;
676 case UNW_X86_64_R12
: return _msContext
.R12
;
677 case UNW_X86_64_R13
: return _msContext
.R13
;
678 case UNW_X86_64_R14
: return _msContext
.R14
;
679 case UNW_X86_64_R15
: return _msContext
.R15
;
680 #elif defined(_LIBUNWIND_TARGET_ARM)
681 case UNW_ARM_R0
: return _msContext
.R0
;
682 case UNW_ARM_R1
: return _msContext
.R1
;
683 case UNW_ARM_R2
: return _msContext
.R2
;
684 case UNW_ARM_R3
: return _msContext
.R3
;
685 case UNW_ARM_R4
: return _msContext
.R4
;
686 case UNW_ARM_R5
: return _msContext
.R5
;
687 case UNW_ARM_R6
: return _msContext
.R6
;
688 case UNW_ARM_R7
: return _msContext
.R7
;
689 case UNW_ARM_R8
: return _msContext
.R8
;
690 case UNW_ARM_R9
: return _msContext
.R9
;
691 case UNW_ARM_R10
: return _msContext
.R10
;
692 case UNW_ARM_R11
: return _msContext
.R11
;
693 case UNW_ARM_R12
: return _msContext
.R12
;
695 case UNW_ARM_SP
: return _msContext
.Sp
;
696 case UNW_ARM_LR
: return _msContext
.Lr
;
698 case UNW_ARM_IP
: return _msContext
.Pc
;
699 #elif defined(_LIBUNWIND_TARGET_AARCH64)
700 case UNW_REG_SP
: return _msContext
.Sp
;
701 case UNW_REG_IP
: return _msContext
.Pc
;
702 default: return _msContext
.X
[regNum
- UNW_ARM64_X0
];
705 _LIBUNWIND_ABORT("unsupported register");
708 template <typename A
, typename R
>
709 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
711 #if defined(_LIBUNWIND_TARGET_X86_64)
712 case UNW_REG_IP
: _msContext
.Rip
= value
; break;
713 case UNW_X86_64_RAX
: _msContext
.Rax
= value
; break;
714 case UNW_X86_64_RDX
: _msContext
.Rdx
= value
; break;
715 case UNW_X86_64_RCX
: _msContext
.Rcx
= value
; break;
716 case UNW_X86_64_RBX
: _msContext
.Rbx
= value
; break;
718 case UNW_X86_64_RSP
: _msContext
.Rsp
= value
; break;
719 case UNW_X86_64_RBP
: _msContext
.Rbp
= value
; break;
720 case UNW_X86_64_RSI
: _msContext
.Rsi
= value
; break;
721 case UNW_X86_64_RDI
: _msContext
.Rdi
= value
; break;
722 case UNW_X86_64_R8
: _msContext
.R8
= value
; break;
723 case UNW_X86_64_R9
: _msContext
.R9
= value
; break;
724 case UNW_X86_64_R10
: _msContext
.R10
= value
; break;
725 case UNW_X86_64_R11
: _msContext
.R11
= value
; break;
726 case UNW_X86_64_R12
: _msContext
.R12
= value
; break;
727 case UNW_X86_64_R13
: _msContext
.R13
= value
; break;
728 case UNW_X86_64_R14
: _msContext
.R14
= value
; break;
729 case UNW_X86_64_R15
: _msContext
.R15
= value
; break;
730 #elif defined(_LIBUNWIND_TARGET_ARM)
731 case UNW_ARM_R0
: _msContext
.R0
= value
; break;
732 case UNW_ARM_R1
: _msContext
.R1
= value
; break;
733 case UNW_ARM_R2
: _msContext
.R2
= value
; break;
734 case UNW_ARM_R3
: _msContext
.R3
= value
; break;
735 case UNW_ARM_R4
: _msContext
.R4
= value
; break;
736 case UNW_ARM_R5
: _msContext
.R5
= value
; break;
737 case UNW_ARM_R6
: _msContext
.R6
= value
; break;
738 case UNW_ARM_R7
: _msContext
.R7
= value
; break;
739 case UNW_ARM_R8
: _msContext
.R8
= value
; break;
740 case UNW_ARM_R9
: _msContext
.R9
= value
; break;
741 case UNW_ARM_R10
: _msContext
.R10
= value
; break;
742 case UNW_ARM_R11
: _msContext
.R11
= value
; break;
743 case UNW_ARM_R12
: _msContext
.R12
= value
; break;
745 case UNW_ARM_SP
: _msContext
.Sp
= value
; break;
746 case UNW_ARM_LR
: _msContext
.Lr
= value
; break;
748 case UNW_ARM_IP
: _msContext
.Pc
= value
; break;
749 #elif defined(_LIBUNWIND_TARGET_AARCH64)
750 case UNW_REG_SP
: _msContext
.Sp
= value
; break;
751 case UNW_REG_IP
: _msContext
.Pc
= value
; break;
782 case UNW_ARM64_LR
: _msContext
.X
[regNum
- UNW_ARM64_X0
] = value
; break;
785 _LIBUNWIND_ABORT("unsupported register");
789 template <typename A
, typename R
>
790 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
791 #if defined(_LIBUNWIND_TARGET_ARM)
792 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) return true;
793 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) return true;
794 #elif defined(_LIBUNWIND_TARGET_AARCH64)
795 if (regNum
>= UNW_ARM64_D0
&& regNum
<= UNW_ARM64_D31
) return true;
802 template <typename A
, typename R
>
803 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
804 #if defined(_LIBUNWIND_TARGET_ARM)
805 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
810 d
.w
= _msContext
.S
[regNum
- UNW_ARM_S0
];
813 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
818 d
.w
= _msContext
.D
[regNum
- UNW_ARM_D0
];
821 _LIBUNWIND_ABORT("unsupported float register");
822 #elif defined(_LIBUNWIND_TARGET_AARCH64)
823 return _msContext
.V
[regNum
- UNW_ARM64_D0
].D
[0];
826 _LIBUNWIND_ABORT("float registers unimplemented");
830 template <typename A
, typename R
>
831 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
832 #if defined(_LIBUNWIND_TARGET_ARM)
833 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
839 _msContext
.S
[regNum
- UNW_ARM_S0
] = d
.w
;
841 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
847 _msContext
.D
[regNum
- UNW_ARM_D0
] = d
.w
;
849 _LIBUNWIND_ABORT("unsupported float register");
850 #elif defined(_LIBUNWIND_TARGET_AARCH64)
851 _msContext
.V
[regNum
- UNW_ARM64_D0
].D
[0] = value
;
855 _LIBUNWIND_ABORT("float registers unimplemented");
859 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
860 RtlRestoreContext(&_msContext
, nullptr);
864 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {}
867 template <typename A
, typename R
>
868 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
869 return R::getRegisterName(regNum
);
872 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
876 #else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
878 /// UnwindCursor contains all state (including all register values) during
879 /// an unwind. This is normally stack allocated inside a unw_cursor_t.
880 template <typename A
, typename R
>
881 class UnwindCursor
: public AbstractUnwindCursor
{
882 typedef typename
A::pint_t pint_t
;
884 UnwindCursor(unw_context_t
*context
, A
&as
);
885 UnwindCursor(A
&as
, void *threadArg
);
886 virtual ~UnwindCursor() {}
887 virtual bool validReg(int);
888 virtual unw_word_t
getReg(int);
889 virtual void setReg(int, unw_word_t
);
890 virtual bool validFloatReg(int);
891 virtual unw_fpreg_t
getFloatReg(int);
892 virtual void setFloatReg(int, unw_fpreg_t
);
894 virtual void getInfo(unw_proc_info_t
*);
895 virtual void jumpto();
896 virtual bool isSignalFrame();
897 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
898 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
899 virtual const char *getRegisterName(int num
);
901 virtual void saveVFPAsX();
904 // libunwind does not and should not depend on C++ library which means that we
905 // need our own defition of inline placement new.
906 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
910 #if defined(_LIBUNWIND_ARM_EHABI)
911 bool getInfoFromEHABISection(pint_t pc
, const UnwindInfoSections
§s
);
913 int stepWithEHABI() {
916 // FIXME: Calling decode_eht_entry() here is violating the libunwind
917 // abstraction layer.
918 const uint32_t *ehtp
=
919 decode_eht_entry(reinterpret_cast<const uint32_t *>(_info
.unwind_info
),
921 if (_Unwind_VRS_Interpret((_Unwind_Context
*)this, ehtp
, off
, len
) !=
922 _URC_CONTINUE_UNWIND
)
924 return UNW_STEP_SUCCESS
;
928 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
929 bool getInfoFromFdeCie(const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
930 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
,
931 pint_t pc
, uintptr_t dso_base
);
932 bool getInfoFromDwarfSection(pint_t pc
, const UnwindInfoSections
§s
,
933 uint32_t fdeSectionOffsetHint
=0);
934 int stepWithDwarfFDE() {
935 return DwarfInstructions
<A
, R
>::stepWithDwarf(_addressSpace
,
936 (pint_t
)this->getReg(UNW_REG_IP
),
937 (pint_t
)_info
.unwind_info
,
938 _registers
, _isSignalFrame
);
942 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
943 bool getInfoFromCompactEncodingSection(pint_t pc
,
944 const UnwindInfoSections
§s
);
945 int stepWithCompactEncoding() {
946 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
947 if ( compactSaysUseDwarf() )
948 return stepWithDwarfFDE();
951 return stepWithCompactEncoding(dummy
);
954 #if defined(_LIBUNWIND_TARGET_X86_64)
955 int stepWithCompactEncoding(Registers_x86_64
&) {
956 return CompactUnwinder_x86_64
<A
>::stepWithCompactEncoding(
957 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
961 #if defined(_LIBUNWIND_TARGET_I386)
962 int stepWithCompactEncoding(Registers_x86
&) {
963 return CompactUnwinder_x86
<A
>::stepWithCompactEncoding(
964 _info
.format
, (uint32_t)_info
.start_ip
, _addressSpace
, _registers
);
968 #if defined(_LIBUNWIND_TARGET_PPC)
969 int stepWithCompactEncoding(Registers_ppc
&) {
974 #if defined(_LIBUNWIND_TARGET_PPC64)
975 int stepWithCompactEncoding(Registers_ppc64
&) {
981 #if defined(_LIBUNWIND_TARGET_AARCH64)
982 int stepWithCompactEncoding(Registers_arm64
&) {
983 return CompactUnwinder_arm64
<A
>::stepWithCompactEncoding(
984 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
988 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
989 int stepWithCompactEncoding(Registers_mips_o32
&) {
994 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
995 int stepWithCompactEncoding(Registers_mips_newabi
&) {
1000 #if defined(_LIBUNWIND_TARGET_SPARC)
1001 int stepWithCompactEncoding(Registers_sparc
&) { return UNW_EINVAL
; }
1004 #if defined (_LIBUNWIND_TARGET_RISCV)
1005 int stepWithCompactEncoding(Registers_riscv
&) {
1010 bool compactSaysUseDwarf(uint32_t *offset
=NULL
) const {
1012 return compactSaysUseDwarf(dummy
, offset
);
1015 #if defined(_LIBUNWIND_TARGET_X86_64)
1016 bool compactSaysUseDwarf(Registers_x86_64
&, uint32_t *offset
) const {
1017 if ((_info
.format
& UNWIND_X86_64_MODE_MASK
) == UNWIND_X86_64_MODE_DWARF
) {
1019 *offset
= (_info
.format
& UNWIND_X86_64_DWARF_SECTION_OFFSET
);
1026 #if defined(_LIBUNWIND_TARGET_I386)
1027 bool compactSaysUseDwarf(Registers_x86
&, uint32_t *offset
) const {
1028 if ((_info
.format
& UNWIND_X86_MODE_MASK
) == UNWIND_X86_MODE_DWARF
) {
1030 *offset
= (_info
.format
& UNWIND_X86_DWARF_SECTION_OFFSET
);
1037 #if defined(_LIBUNWIND_TARGET_PPC)
1038 bool compactSaysUseDwarf(Registers_ppc
&, uint32_t *) const {
1043 #if defined(_LIBUNWIND_TARGET_PPC64)
1044 bool compactSaysUseDwarf(Registers_ppc64
&, uint32_t *) const {
1049 #if defined(_LIBUNWIND_TARGET_AARCH64)
1050 bool compactSaysUseDwarf(Registers_arm64
&, uint32_t *offset
) const {
1051 if ((_info
.format
& UNWIND_ARM64_MODE_MASK
) == UNWIND_ARM64_MODE_DWARF
) {
1053 *offset
= (_info
.format
& UNWIND_ARM64_DWARF_SECTION_OFFSET
);
1060 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
1061 bool compactSaysUseDwarf(Registers_mips_o32
&, uint32_t *) const {
1066 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1067 bool compactSaysUseDwarf(Registers_mips_newabi
&, uint32_t *) const {
1072 #if defined(_LIBUNWIND_TARGET_SPARC)
1073 bool compactSaysUseDwarf(Registers_sparc
&, uint32_t *) const { return true; }
1076 #if defined (_LIBUNWIND_TARGET_RISCV)
1077 bool compactSaysUseDwarf(Registers_riscv
&, uint32_t *) const {
1082 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1084 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1085 compact_unwind_encoding_t
dwarfEncoding() const {
1087 return dwarfEncoding(dummy
);
1090 #if defined(_LIBUNWIND_TARGET_X86_64)
1091 compact_unwind_encoding_t
dwarfEncoding(Registers_x86_64
&) const {
1092 return UNWIND_X86_64_MODE_DWARF
;
1096 #if defined(_LIBUNWIND_TARGET_I386)
1097 compact_unwind_encoding_t
dwarfEncoding(Registers_x86
&) const {
1098 return UNWIND_X86_MODE_DWARF
;
1102 #if defined(_LIBUNWIND_TARGET_PPC)
1103 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc
&) const {
1108 #if defined(_LIBUNWIND_TARGET_PPC64)
1109 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc64
&) const {
1114 #if defined(_LIBUNWIND_TARGET_AARCH64)
1115 compact_unwind_encoding_t
dwarfEncoding(Registers_arm64
&) const {
1116 return UNWIND_ARM64_MODE_DWARF
;
1120 #if defined(_LIBUNWIND_TARGET_ARM)
1121 compact_unwind_encoding_t
dwarfEncoding(Registers_arm
&) const {
1126 #if defined (_LIBUNWIND_TARGET_OR1K)
1127 compact_unwind_encoding_t
dwarfEncoding(Registers_or1k
&) const {
1132 #if defined (_LIBUNWIND_TARGET_HEXAGON)
1133 compact_unwind_encoding_t
dwarfEncoding(Registers_hexagon
&) const {
1138 #if defined (_LIBUNWIND_TARGET_MIPS_O32)
1139 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_o32
&) const {
1144 #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1145 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_newabi
&) const {
1150 #if defined(_LIBUNWIND_TARGET_SPARC)
1151 compact_unwind_encoding_t
dwarfEncoding(Registers_sparc
&) const { return 0; }
1154 #if defined (_LIBUNWIND_TARGET_RISCV)
1155 compact_unwind_encoding_t
dwarfEncoding(Registers_riscv
&) const {
1160 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1162 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1163 // For runtime environments using SEH unwind data without Windows runtime
1165 pint_t
getLastPC() const { /* FIXME: Implement */ return 0; }
1166 void setLastPC(pint_t pc
) { /* FIXME: Implement */ }
1167 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
1168 /* FIXME: Implement */
1172 bool getInfoFromSEH(pint_t pc
);
1173 int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1174 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1179 unw_proc_info_t _info
;
1180 bool _unwindInfoMissing
;
1181 bool _isSignalFrame
;
1185 template <typename A
, typename R
>
1186 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
1187 : _addressSpace(as
), _registers(context
), _unwindInfoMissing(false),
1188 _isSignalFrame(false) {
1189 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
1190 "UnwindCursor<> does not fit in unw_cursor_t");
1191 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
1192 "UnwindCursor<> requires more alignment than unw_cursor_t");
1193 memset(&_info
, 0, sizeof(_info
));
1196 template <typename A
, typename R
>
1197 UnwindCursor
<A
, R
>::UnwindCursor(A
&as
, void *)
1198 : _addressSpace(as
), _unwindInfoMissing(false), _isSignalFrame(false) {
1199 memset(&_info
, 0, sizeof(_info
));
1201 // fill in _registers from thread arg
1205 template <typename A
, typename R
>
1206 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
1207 return _registers
.validRegister(regNum
);
1210 template <typename A
, typename R
>
1211 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
1212 return _registers
.getRegister(regNum
);
1215 template <typename A
, typename R
>
1216 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
1217 _registers
.setRegister(regNum
, (typename
A::pint_t
)value
);
1220 template <typename A
, typename R
>
1221 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
1222 return _registers
.validFloatRegister(regNum
);
1225 template <typename A
, typename R
>
1226 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
1227 return _registers
.getFloatRegister(regNum
);
1230 template <typename A
, typename R
>
1231 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
1232 _registers
.setFloatRegister(regNum
, value
);
1235 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
1236 _registers
.jumpto();
1240 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {
1241 _registers
.saveVFPAsX();
1245 template <typename A
, typename R
>
1246 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
1247 return _registers
.getRegisterName(regNum
);
1250 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
1251 return _isSignalFrame
;
1254 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1256 #if defined(_LIBUNWIND_ARM_EHABI)
1257 template<typename A
>
1258 struct EHABISectionIterator
{
1259 typedef EHABISectionIterator _Self
;
1261 typedef typename
A::pint_t value_type
;
1262 typedef typename
A::pint_t
* pointer
;
1263 typedef typename
A::pint_t
& reference
;
1264 typedef size_t size_type
;
1265 typedef size_t difference_type
;
1267 static _Self
begin(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1268 return _Self(addressSpace
, sects
, 0);
1270 static _Self
end(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1271 return _Self(addressSpace
, sects
,
1272 sects
.arm_section_length
/ sizeof(EHABIIndexEntry
));
1275 EHABISectionIterator(A
& addressSpace
, const UnwindInfoSections
& sects
, size_t i
)
1276 : _i(i
), _addressSpace(&addressSpace
), _sects(§s
) {}
1278 _Self
& operator++() { ++_i
; return *this; }
1279 _Self
& operator+=(size_t a
) { _i
+= a
; return *this; }
1280 _Self
& operator--() { assert(_i
> 0); --_i
; return *this; }
1281 _Self
& operator-=(size_t a
) { assert(_i
>= a
); _i
-= a
; return *this; }
1283 _Self
operator+(size_t a
) { _Self out
= *this; out
._i
+= a
; return out
; }
1284 _Self
operator-(size_t a
) { assert(_i
>= a
); _Self out
= *this; out
._i
-= a
; return out
; }
1286 size_t operator-(const _Self
& other
) const { return _i
- other
._i
; }
1288 bool operator==(const _Self
& other
) const {
1289 assert(_addressSpace
== other
._addressSpace
);
1290 assert(_sects
== other
._sects
);
1291 return _i
== other
._i
;
1294 bool operator!=(const _Self
& other
) const {
1295 assert(_addressSpace
== other
._addressSpace
);
1296 assert(_sects
== other
._sects
);
1297 return _i
!= other
._i
;
1300 typename
A::pint_t
operator*() const { return functionAddress(); }
1302 typename
A::pint_t
functionAddress() const {
1303 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1304 EHABIIndexEntry
, _i
, functionOffset
);
1305 return indexAddr
+ signExtendPrel31(_addressSpace
->get32(indexAddr
));
1308 typename
A::pint_t
dataAddress() {
1309 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1310 EHABIIndexEntry
, _i
, data
);
1317 const UnwindInfoSections
* _sects
;
1322 template <typename A
>
1323 EHABISectionIterator
<A
> EHABISectionUpperBound(
1324 EHABISectionIterator
<A
> first
,
1325 EHABISectionIterator
<A
> last
,
1326 typename
A::pint_t value
) {
1327 size_t len
= last
- first
;
1329 size_t l2
= len
/ 2;
1330 EHABISectionIterator
<A
> m
= first
+ l2
;
1343 template <typename A
, typename R
>
1344 bool UnwindCursor
<A
, R
>::getInfoFromEHABISection(
1346 const UnwindInfoSections
§s
) {
1347 EHABISectionIterator
<A
> begin
=
1348 EHABISectionIterator
<A
>::begin(_addressSpace
, sects
);
1349 EHABISectionIterator
<A
> end
=
1350 EHABISectionIterator
<A
>::end(_addressSpace
, sects
);
1354 EHABISectionIterator
<A
> itNextPC
= EHABISectionUpperBound(begin
, end
, pc
);
1355 if (itNextPC
== begin
)
1357 EHABISectionIterator
<A
> itThisPC
= itNextPC
- 1;
1359 pint_t thisPC
= itThisPC
.functionAddress();
1360 // If an exception is thrown from a function, corresponding to the last entry
1361 // in the table, we don't really know the function extent and have to choose a
1362 // value for nextPC. Choosing max() will allow the range check during trace to
1364 pint_t nextPC
= (itNextPC
== end
) ? UINTPTR_MAX
: itNextPC
.functionAddress();
1365 pint_t indexDataAddr
= itThisPC
.dataAddress();
1367 if (indexDataAddr
== 0)
1370 uint32_t indexData
= _addressSpace
.get32(indexDataAddr
);
1371 if (indexData
== UNW_EXIDX_CANTUNWIND
)
1374 // If the high bit is set, the exception handling table entry is inline inside
1375 // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1376 // the table points at an offset in the exception handling table (section 5
1378 pint_t exceptionTableAddr
;
1379 uint32_t exceptionTableData
;
1380 bool isSingleWordEHT
;
1381 if (indexData
& 0x80000000) {
1382 exceptionTableAddr
= indexDataAddr
;
1383 // TODO(ajwong): Should this data be 0?
1384 exceptionTableData
= indexData
;
1385 isSingleWordEHT
= true;
1387 exceptionTableAddr
= indexDataAddr
+ signExtendPrel31(indexData
);
1388 exceptionTableData
= _addressSpace
.get32(exceptionTableAddr
);
1389 isSingleWordEHT
= false;
1392 // Now we know the 3 things:
1393 // exceptionTableAddr -- exception handler table entry.
1394 // exceptionTableData -- the data inside the first word of the eht entry.
1395 // isSingleWordEHT -- whether the entry is in the index.
1396 unw_word_t personalityRoutine
= 0xbadf00d;
1397 bool scope32
= false;
1400 // If the high bit in the exception handling table entry is set, the entry is
1401 // in compact form (section 6.3 EHABI).
1402 if (exceptionTableData
& 0x80000000) {
1403 // Grab the index of the personality routine from the compact form.
1404 uint32_t choice
= (exceptionTableData
& 0x0f000000) >> 24;
1405 uint32_t extraWords
= 0;
1408 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr0
;
1411 lsda
= isSingleWordEHT
? 0 : (exceptionTableAddr
+ 4);
1414 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr1
;
1415 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1417 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1420 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr2
;
1421 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1423 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1426 _LIBUNWIND_ABORT("unknown personality routine");
1430 if (isSingleWordEHT
) {
1431 if (extraWords
!= 0) {
1432 _LIBUNWIND_ABORT("index inlined table detected but pr function "
1433 "requires extra words");
1438 pint_t personalityAddr
=
1439 exceptionTableAddr
+ signExtendPrel31(exceptionTableData
);
1440 personalityRoutine
= personalityAddr
;
1442 // ARM EHABI # 6.2, # 9.2
1446 // +--------------------------------------+
1447 // | +--------+--------+--------+-------+ |
1448 // | |0| prel31 to personalityRoutine | |
1449 // | +--------+--------+--------+-------+ |
1450 // | | N | unwind opcodes | | <-- UnwindData
1451 // | +--------+--------+--------+-------+ |
1452 // | | Word 2 unwind opcodes | |
1453 // | +--------+--------+--------+-------+ |
1455 // | +--------+--------+--------+-------+ |
1456 // | | Word N unwind opcodes | |
1457 // | +--------+--------+--------+-------+ |
1458 // | | LSDA | | <-- lsda
1460 // | +--------+--------+--------+-------+ |
1461 // +--------------------------------------+
1463 uint32_t *UnwindData
= reinterpret_cast<uint32_t*>(exceptionTableAddr
) + 1;
1464 uint32_t FirstDataWord
= *UnwindData
;
1465 size_t N
= ((FirstDataWord
>> 24) & 0xff);
1466 size_t NDataWords
= N
+ 1;
1467 lsda
= reinterpret_cast<uintptr_t>(UnwindData
+ NDataWords
);
1470 _info
.start_ip
= thisPC
;
1471 _info
.end_ip
= nextPC
;
1472 _info
.handler
= personalityRoutine
;
1473 _info
.unwind_info
= exceptionTableAddr
;
1475 // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1476 _info
.flags
= (isSingleWordEHT
? 1 : 0) | (scope32
? 0x2 : 0); // Use enum?
1482 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1483 template <typename A
, typename R
>
1484 bool UnwindCursor
<A
, R
>::getInfoFromFdeCie(
1485 const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
1486 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
, pint_t pc
,
1487 uintptr_t dso_base
) {
1488 typename CFI_Parser
<A
>::PrologInfo prolog
;
1489 if (CFI_Parser
<A
>::parseFDEInstructions(_addressSpace
, fdeInfo
, cieInfo
, pc
,
1490 R::getArch(), &prolog
)) {
1491 // Save off parsed FDE info
1492 _info
.start_ip
= fdeInfo
.pcStart
;
1493 _info
.end_ip
= fdeInfo
.pcEnd
;
1494 _info
.lsda
= fdeInfo
.lsda
;
1495 _info
.handler
= cieInfo
.personality
;
1496 // Some frameless functions need SP altered when resuming in function, so
1497 // propagate spExtraArgSize.
1498 _info
.gp
= prolog
.spExtraArgSize
;
1500 _info
.format
= dwarfEncoding();
1501 _info
.unwind_info
= fdeInfo
.fdeStart
;
1502 _info
.unwind_info_size
= static_cast<uint32_t>(fdeInfo
.fdeLength
);
1503 _info
.extra
= static_cast<unw_word_t
>(dso_base
);
1509 template <typename A
, typename R
>
1510 bool UnwindCursor
<A
, R
>::getInfoFromDwarfSection(pint_t pc
,
1511 const UnwindInfoSections
§s
,
1512 uint32_t fdeSectionOffsetHint
) {
1513 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
1514 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
1515 bool foundFDE
= false;
1516 bool foundInCache
= false;
1517 // If compact encoding table gave offset into dwarf section, go directly there
1518 if (fdeSectionOffsetHint
!= 0) {
1519 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1520 sects
.dwarf_section_length
,
1521 sects
.dwarf_section
+ fdeSectionOffsetHint
,
1522 &fdeInfo
, &cieInfo
);
1524 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1525 if (!foundFDE
&& (sects
.dwarf_index_section
!= 0)) {
1526 foundFDE
= EHHeaderParser
<A
>::findFDE(
1527 _addressSpace
, pc
, sects
.dwarf_index_section
,
1528 (uint32_t)sects
.dwarf_index_section_length
, &fdeInfo
, &cieInfo
);
1532 // otherwise, search cache of previously found FDEs.
1533 pint_t cachedFDE
= DwarfFDECache
<A
>::findFDE(sects
.dso_base
, pc
);
1534 if (cachedFDE
!= 0) {
1536 CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1537 sects
.dwarf_section_length
,
1538 cachedFDE
, &fdeInfo
, &cieInfo
);
1539 foundInCache
= foundFDE
;
1543 // Still not found, do full scan of __eh_frame section.
1544 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1545 sects
.dwarf_section_length
, 0,
1546 &fdeInfo
, &cieInfo
);
1549 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, sects
.dso_base
)) {
1550 // Add to cache (to make next lookup faster) if we had no hint
1551 // and there was no index.
1552 if (!foundInCache
&& (fdeSectionOffsetHint
== 0)) {
1553 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1554 if (sects
.dwarf_index_section
== 0)
1556 DwarfFDECache
<A
>::add(sects
.dso_base
, fdeInfo
.pcStart
, fdeInfo
.pcEnd
,
1562 //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1565 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1568 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1569 template <typename A
, typename R
>
1570 bool UnwindCursor
<A
, R
>::getInfoFromCompactEncodingSection(pint_t pc
,
1571 const UnwindInfoSections
§s
) {
1572 const bool log
= false;
1574 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1575 (uint64_t)pc
, (uint64_t)sects
.dso_base
);
1577 const UnwindSectionHeader
<A
> sectionHeader(_addressSpace
,
1578 sects
.compact_unwind_section
);
1579 if (sectionHeader
.version() != UNWIND_SECTION_VERSION
)
1582 // do a binary search of top level index to find page with unwind info
1583 pint_t targetFunctionOffset
= pc
- sects
.dso_base
;
1584 const UnwindSectionIndexArray
<A
> topIndex(_addressSpace
,
1585 sects
.compact_unwind_section
1586 + sectionHeader
.indexSectionOffset());
1588 uint32_t high
= sectionHeader
.indexCount();
1589 uint32_t last
= high
- 1;
1590 while (low
< high
) {
1591 uint32_t mid
= (low
+ high
) / 2;
1592 //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1593 //mid, low, high, topIndex.functionOffset(mid));
1594 if (topIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1595 if ((mid
== last
) ||
1596 (topIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
)) {
1606 const uint32_t firstLevelFunctionOffset
= topIndex
.functionOffset(low
);
1607 const uint32_t firstLevelNextPageFunctionOffset
=
1608 topIndex
.functionOffset(low
+ 1);
1609 const pint_t secondLevelAddr
=
1610 sects
.compact_unwind_section
+ topIndex
.secondLevelPagesSectionOffset(low
);
1611 const pint_t lsdaArrayStartAddr
=
1612 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
);
1613 const pint_t lsdaArrayEndAddr
=
1614 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
+1);
1616 fprintf(stderr
, "\tfirst level search for result index=%d "
1617 "to secondLevelAddr=0x%llX\n",
1618 low
, (uint64_t) secondLevelAddr
);
1619 // do a binary search of second level page index
1620 uint32_t encoding
= 0;
1621 pint_t funcStart
= 0;
1624 pint_t personality
= 0;
1625 uint32_t pageKind
= _addressSpace
.get32(secondLevelAddr
);
1626 if (pageKind
== UNWIND_SECOND_LEVEL_REGULAR
) {
1628 UnwindSectionRegularPageHeader
<A
> pageHeader(_addressSpace
,
1630 UnwindSectionRegularArray
<A
> pageIndex(
1631 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1632 // binary search looks for entry with e where index[e].offset <= pc <
1633 // index[e+1].offset
1635 fprintf(stderr
, "\tbinary search for targetFunctionOffset=0x%08llX in "
1636 "regular page starting at secondLevelAddr=0x%llX\n",
1637 (uint64_t) targetFunctionOffset
, (uint64_t) secondLevelAddr
);
1639 high
= pageHeader
.entryCount();
1640 while (low
< high
) {
1641 uint32_t mid
= (low
+ high
) / 2;
1642 if (pageIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1643 if (mid
== (uint32_t)(pageHeader
.entryCount() - 1)) {
1646 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1648 } else if (pageIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
) {
1649 // next is too big, so we found it
1651 funcEnd
= pageIndex
.functionOffset(low
+ 1) + sects
.dso_base
;
1660 encoding
= pageIndex
.encoding(low
);
1661 funcStart
= pageIndex
.functionOffset(low
) + sects
.dso_base
;
1662 if (pc
< funcStart
) {
1666 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1667 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1674 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1675 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1678 } else if (pageKind
== UNWIND_SECOND_LEVEL_COMPRESSED
) {
1680 UnwindSectionCompressedPageHeader
<A
> pageHeader(_addressSpace
,
1682 UnwindSectionCompressedArray
<A
> pageIndex(
1683 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1684 const uint32_t targetFunctionPageOffset
=
1685 (uint32_t)(targetFunctionOffset
- firstLevelFunctionOffset
);
1686 // binary search looks for entry with e where index[e].offset <= pc <
1687 // index[e+1].offset
1689 fprintf(stderr
, "\tbinary search of compressed page starting at "
1690 "secondLevelAddr=0x%llX\n",
1691 (uint64_t) secondLevelAddr
);
1693 last
= pageHeader
.entryCount() - 1;
1694 high
= pageHeader
.entryCount();
1695 while (low
< high
) {
1696 uint32_t mid
= (low
+ high
) / 2;
1697 if (pageIndex
.functionOffset(mid
) <= targetFunctionPageOffset
) {
1698 if ((mid
== last
) ||
1699 (pageIndex
.functionOffset(mid
+ 1) > targetFunctionPageOffset
)) {
1709 funcStart
= pageIndex
.functionOffset(low
) + firstLevelFunctionOffset
1713 pageIndex
.functionOffset(low
+ 1) + firstLevelFunctionOffset
1716 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1717 if (pc
< funcStart
) {
1718 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
1719 "level compressed unwind table. funcStart=0x%llX",
1720 (uint64_t) pc
, (uint64_t) funcStart
);
1724 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second "
1725 "level compressed unwind table. funcEnd=0x%llX",
1726 (uint64_t) pc
, (uint64_t) funcEnd
);
1729 uint16_t encodingIndex
= pageIndex
.encodingIndex(low
);
1730 if (encodingIndex
< sectionHeader
.commonEncodingsArrayCount()) {
1731 // encoding is in common table in section header
1732 encoding
= _addressSpace
.get32(
1733 sects
.compact_unwind_section
+
1734 sectionHeader
.commonEncodingsArraySectionOffset() +
1735 encodingIndex
* sizeof(uint32_t));
1737 // encoding is in page specific table
1738 uint16_t pageEncodingIndex
=
1739 encodingIndex
- (uint16_t)sectionHeader
.commonEncodingsArrayCount();
1740 encoding
= _addressSpace
.get32(secondLevelAddr
+
1741 pageHeader
.encodingsPageOffset() +
1742 pageEncodingIndex
* sizeof(uint32_t));
1745 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second "
1747 (uint64_t) sects
.compact_unwind_section
);
1751 // look up LSDA, if encoding says function has one
1752 if (encoding
& UNWIND_HAS_LSDA
) {
1753 UnwindSectionLsdaArray
<A
> lsdaIndex(_addressSpace
, lsdaArrayStartAddr
);
1754 uint32_t funcStartOffset
= (uint32_t)(funcStart
- sects
.dso_base
);
1756 high
= (uint32_t)(lsdaArrayEndAddr
- lsdaArrayStartAddr
) /
1757 sizeof(unwind_info_section_header_lsda_index_entry
);
1758 // binary search looks for entry with exact match for functionOffset
1761 "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1763 while (low
< high
) {
1764 uint32_t mid
= (low
+ high
) / 2;
1765 if (lsdaIndex
.functionOffset(mid
) == funcStartOffset
) {
1766 lsda
= lsdaIndex
.lsdaOffset(mid
) + sects
.dso_base
;
1768 } else if (lsdaIndex
.functionOffset(mid
) < funcStartOffset
) {
1775 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1776 "pc=0x%0llX, but lsda table has no entry",
1777 encoding
, (uint64_t) pc
);
1782 // extract personality routine, if encoding says function has one
1783 uint32_t personalityIndex
= (encoding
& UNWIND_PERSONALITY_MASK
) >>
1784 (__builtin_ctz(UNWIND_PERSONALITY_MASK
));
1785 if (personalityIndex
!= 0) {
1786 --personalityIndex
; // change 1-based to zero-based index
1787 if (personalityIndex
>= sectionHeader
.personalityArrayCount()) {
1788 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
1789 "but personality table has only %d entries",
1790 encoding
, personalityIndex
,
1791 sectionHeader
.personalityArrayCount());
1794 int32_t personalityDelta
= (int32_t)_addressSpace
.get32(
1795 sects
.compact_unwind_section
+
1796 sectionHeader
.personalityArraySectionOffset() +
1797 personalityIndex
* sizeof(uint32_t));
1798 pint_t personalityPointer
= sects
.dso_base
+ (pint_t
)personalityDelta
;
1799 personality
= _addressSpace
.getP(personalityPointer
);
1801 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1802 "personalityDelta=0x%08X, personality=0x%08llX\n",
1803 (uint64_t) pc
, personalityDelta
, (uint64_t) personality
);
1807 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1808 "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1809 (uint64_t) pc
, encoding
, (uint64_t) lsda
, (uint64_t) funcStart
);
1810 _info
.start_ip
= funcStart
;
1811 _info
.end_ip
= funcEnd
;
1813 _info
.handler
= personality
;
1816 _info
.format
= encoding
;
1817 _info
.unwind_info
= 0;
1818 _info
.unwind_info_size
= 0;
1819 _info
.extra
= sects
.dso_base
;
1822 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1825 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1826 template <typename A
, typename R
>
1827 bool UnwindCursor
<A
, R
>::getInfoFromSEH(pint_t pc
) {
1829 RUNTIME_FUNCTION
*unwindEntry
= lookUpSEHUnwindInfo(pc
, &base
);
1831 _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc
);
1837 _info
.unwind_info_size
= sizeof(RUNTIME_FUNCTION
);
1838 _info
.unwind_info
= reinterpret_cast<unw_word_t
>(unwindEntry
);
1840 _info
.start_ip
= base
+ unwindEntry
->BeginAddress
;
1841 #ifdef _LIBUNWIND_TARGET_X86_64
1842 _info
.end_ip
= base
+ unwindEntry
->EndAddress
;
1843 // Only fill in the handler and LSDA if they're stale.
1844 if (pc
!= getLastPC()) {
1845 UNWIND_INFO
*xdata
= reinterpret_cast<UNWIND_INFO
*>(base
+ unwindEntry
->UnwindData
);
1846 if (xdata
->Flags
& (UNW_FLAG_EHANDLER
|UNW_FLAG_UHANDLER
)) {
1847 // The personality is given in the UNWIND_INFO itself. The LSDA immediately
1848 // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
1849 // these structures.)
1850 // N.B. UNWIND_INFO structs are DWORD-aligned.
1851 uint32_t lastcode
= (xdata
->CountOfCodes
+ 1) & ~1;
1852 const uint32_t *handler
= reinterpret_cast<uint32_t *>(&xdata
->UnwindCodes
[lastcode
]);
1853 _info
.lsda
= reinterpret_cast<unw_word_t
>(handler
+1);
1855 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
1863 #elif defined(_LIBUNWIND_TARGET_ARM)
1864 _info
.end_ip
= _info
.start_ip
+ unwindEntry
->FunctionLength
;
1865 _info
.lsda
= 0; // FIXME
1866 _info
.handler
= 0; // FIXME
1874 template <typename A
, typename R
>
1875 void UnwindCursor
<A
, R
>::setInfoBasedOnIPRegister(bool isReturnAddress
) {
1876 pint_t pc
= (pint_t
)this->getReg(UNW_REG_IP
);
1877 #if defined(_LIBUNWIND_ARM_EHABI)
1878 // Remove the thumb bit so the IP represents the actual instruction address.
1879 // This matches the behaviour of _Unwind_GetIP on arm.
1883 // Exit early if at the top of the stack.
1885 _unwindInfoMissing
= true;
1889 // If the last line of a function is a "throw" the compiler sometimes
1890 // emits no instructions after the call to __cxa_throw. This means
1891 // the return address is actually the start of the next function.
1892 // To disambiguate this, back up the pc when we know it is a return
1894 if (isReturnAddress
)
1897 // Ask address space object to find unwind sections for this pc.
1898 UnwindInfoSections sects
;
1899 if (_addressSpace
.findUnwindSections(pc
, sects
)) {
1900 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1901 // If there is a compact unwind encoding table, look there first.
1902 if (sects
.compact_unwind_section
!= 0) {
1903 if (this->getInfoFromCompactEncodingSection(pc
, sects
)) {
1904 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1905 // Found info in table, done unless encoding says to use dwarf.
1906 uint32_t dwarfOffset
;
1907 if ((sects
.dwarf_section
!= 0) && compactSaysUseDwarf(&dwarfOffset
)) {
1908 if (this->getInfoFromDwarfSection(pc
, sects
, dwarfOffset
)) {
1909 // found info in dwarf, done
1914 // If unwind table has entry, but entry says there is no unwind info,
1915 // record that we have no unwind info.
1916 if (_info
.format
== 0)
1917 _unwindInfoMissing
= true;
1921 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1923 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1924 // If there is SEH unwind info, look there next.
1925 if (this->getInfoFromSEH(pc
))
1929 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1930 // If there is dwarf unwind info, look there next.
1931 if (sects
.dwarf_section
!= 0) {
1932 if (this->getInfoFromDwarfSection(pc
, sects
)) {
1933 // found info in dwarf, done
1939 #if defined(_LIBUNWIND_ARM_EHABI)
1940 // If there is ARM EHABI unwind info, look there next.
1941 if (sects
.arm_section
!= 0 && this->getInfoFromEHABISection(pc
, sects
))
1946 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1947 // There is no static unwind info for this pc. Look to see if an FDE was
1948 // dynamically registered for it.
1949 pint_t cachedFDE
= DwarfFDECache
<A
>::findFDE(DwarfFDECache
<A
>::kSearchAll
,
1951 if (cachedFDE
!= 0) {
1952 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
1953 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
1954 if (!CFI_Parser
<A
>::decodeFDE(_addressSpace
, cachedFDE
, &fdeInfo
, &cieInfo
))
1955 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, 0))
1959 // Lastly, ask AddressSpace object about platform specific ways to locate
1962 if (_addressSpace
.findOtherFDE(pc
, fde
)) {
1963 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
1964 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
1965 if (!CFI_Parser
<A
>::decodeFDE(_addressSpace
, fde
, &fdeInfo
, &cieInfo
)) {
1966 // Double check this FDE is for a function that includes the pc.
1967 if ((fdeInfo
.pcStart
<= pc
) && (pc
< fdeInfo
.pcEnd
))
1968 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, 0))
1972 #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1974 // no unwind info, flag that we can't reliably unwind
1975 _unwindInfoMissing
= true;
1978 template <typename A
, typename R
>
1979 int UnwindCursor
<A
, R
>::step() {
1980 // Bottom of stack is defined is when unwind info cannot be found.
1981 if (_unwindInfoMissing
)
1982 return UNW_STEP_END
;
1984 // Use unwinding info to modify register set as if function returned.
1986 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1987 result
= this->stepWithCompactEncoding();
1988 #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1989 result
= this->stepWithSEHData();
1990 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1991 result
= this->stepWithDwarfFDE();
1992 #elif defined(_LIBUNWIND_ARM_EHABI)
1993 result
= this->stepWithEHABI();
1995 #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
1996 _LIBUNWIND_SUPPORT_SEH_UNWIND or \
1997 _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
1998 _LIBUNWIND_ARM_EHABI
2001 // update info based on new PC
2002 if (result
== UNW_STEP_SUCCESS
) {
2003 this->setInfoBasedOnIPRegister(true);
2004 if (_unwindInfoMissing
)
2005 return UNW_STEP_END
;
2011 template <typename A
, typename R
>
2012 void UnwindCursor
<A
, R
>::getInfo(unw_proc_info_t
*info
) {
2013 if (_unwindInfoMissing
)
2014 memset(info
, 0, sizeof(*info
));
2019 template <typename A
, typename R
>
2020 bool UnwindCursor
<A
, R
>::getFunctionName(char *buf
, size_t bufLen
,
2021 unw_word_t
*offset
) {
2022 return _addressSpace
.findFunctionName((pint_t
)this->getReg(UNW_REG_IP
),
2023 buf
, bufLen
, offset
);
2026 } // namespace libunwind
2028 #endif // __UNWINDCURSOR_HPP__