1 //===----------------------------------------------------------------------===//
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__
14 #include "cet_unwind.h"
25 #include <mach-o/dyld.h>
29 #include <sys/debug.h>
33 #if defined(_LIBUNWIND_TARGET_LINUX) && \
34 (defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_RISCV) || \
35 defined(_LIBUNWIND_TARGET_S390X))
36 #include <sys/syscall.h>
39 #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
42 #include "AddressSpace.hpp"
43 #include "CompactUnwinder.hpp"
45 #include "DwarfInstructions.hpp"
46 #include "EHHeaderParser.hpp"
47 #include "libunwind.h"
48 #include "libunwind_ext.h"
49 #include "Registers.hpp"
50 #include "RWMutex.hpp"
51 #include "Unwind-EHABI.h"
53 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
54 // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
56 // MinGW-w64 has always provided this struct.
57 #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
58 !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
59 struct _DISPATCHER_CONTEXT
{
62 PRUNTIME_FUNCTION FunctionEntry
;
63 ULONG64 EstablisherFrame
;
65 PCONTEXT ContextRecord
;
66 PEXCEPTION_ROUTINE LanguageHandler
;
68 PUNWIND_HISTORY_TABLE HistoryTable
;
79 uint8_t FrameRegister
: 4;
80 uint8_t FrameOffset
: 4;
81 uint16_t UnwindCodes
[2];
84 extern "C" _Unwind_Reason_Code
__libunwind_seh_personality(
85 int, _Unwind_Action
, uint64_t, _Unwind_Exception
*,
86 struct _Unwind_Context
*);
92 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
93 /// Cache of recently found FDEs.
95 class _LIBUNWIND_HIDDEN DwarfFDECache
{
96 typedef typename
A::pint_t pint_t
;
98 static constexpr pint_t kSearchAll
= static_cast<pint_t
>(-1);
99 static pint_t
findFDE(pint_t mh
, pint_t pc
);
100 static void add(pint_t mh
, pint_t ip_start
, pint_t ip_end
, pint_t fde
);
101 static void removeAllIn(pint_t mh
);
102 static void iterateCacheEntries(void (*func
)(unw_word_t ip_start
,
104 unw_word_t fde
, unw_word_t mh
));
115 // These fields are all static to avoid needing an initializer.
116 // There is only one instance of this class per process.
117 static RWMutex _lock
;
119 static void dyldUnloadHook(const struct mach_header
*mh
, intptr_t slide
);
120 static bool _registeredForDyldUnloads
;
122 static entry
*_buffer
;
123 static entry
*_bufferUsed
;
124 static entry
*_bufferEnd
;
125 static entry _initialBuffer
[64];
128 template <typename A
>
129 typename DwarfFDECache
<A
>::entry
*
130 DwarfFDECache
<A
>::_buffer
= _initialBuffer
;
132 template <typename A
>
133 typename DwarfFDECache
<A
>::entry
*
134 DwarfFDECache
<A
>::_bufferUsed
= _initialBuffer
;
136 template <typename A
>
137 typename DwarfFDECache
<A
>::entry
*
138 DwarfFDECache
<A
>::_bufferEnd
= &_initialBuffer
[64];
140 template <typename A
>
141 typename DwarfFDECache
<A
>::entry DwarfFDECache
<A
>::_initialBuffer
[64];
143 template <typename A
>
144 RWMutex DwarfFDECache
<A
>::_lock
;
147 template <typename A
>
148 bool DwarfFDECache
<A
>::_registeredForDyldUnloads
= false;
151 template <typename A
>
152 typename
A::pint_t DwarfFDECache
<A
>::findFDE(pint_t mh
, pint_t pc
) {
154 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock_shared());
155 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
156 if ((mh
== p
->mh
) || (mh
== kSearchAll
)) {
157 if ((p
->ip_start
<= pc
) && (pc
< p
->ip_end
)) {
163 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock_shared());
167 template <typename A
>
168 void DwarfFDECache
<A
>::add(pint_t mh
, pint_t ip_start
, pint_t ip_end
,
170 #if !defined(_LIBUNWIND_NO_HEAP)
171 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
172 if (_bufferUsed
>= _bufferEnd
) {
173 size_t oldSize
= (size_t)(_bufferEnd
- _buffer
);
174 size_t newSize
= oldSize
* 4;
175 // Can't use operator new (we are below it).
176 entry
*newBuffer
= (entry
*)malloc(newSize
* sizeof(entry
));
177 memcpy(newBuffer
, _buffer
, oldSize
* sizeof(entry
));
178 if (_buffer
!= _initialBuffer
)
181 _bufferUsed
= &newBuffer
[oldSize
];
182 _bufferEnd
= &newBuffer
[newSize
];
184 _bufferUsed
->mh
= mh
;
185 _bufferUsed
->ip_start
= ip_start
;
186 _bufferUsed
->ip_end
= ip_end
;
187 _bufferUsed
->fde
= fde
;
190 if (!_registeredForDyldUnloads
) {
191 _dyld_register_func_for_remove_image(&dyldUnloadHook
);
192 _registeredForDyldUnloads
= true;
195 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
199 template <typename A
>
200 void DwarfFDECache
<A
>::removeAllIn(pint_t mh
) {
201 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
203 for (const entry
*s
= _buffer
; s
< _bufferUsed
; ++s
) {
211 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
215 template <typename A
>
216 void DwarfFDECache
<A
>::dyldUnloadHook(const struct mach_header
*mh
, intptr_t ) {
217 removeAllIn((pint_t
) mh
);
221 template <typename A
>
222 void DwarfFDECache
<A
>::iterateCacheEntries(void (*func
)(
223 unw_word_t ip_start
, unw_word_t ip_end
, unw_word_t fde
, unw_word_t mh
)) {
224 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
225 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
226 (*func
)(p
->ip_start
, p
->ip_end
, p
->fde
, p
->mh
);
228 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
230 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
233 #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
235 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
236 template <typename A
> class UnwindSectionHeader
{
238 UnwindSectionHeader(A
&addressSpace
, typename
A::pint_t addr
)
239 : _addressSpace(addressSpace
), _addr(addr
) {}
241 uint32_t version() const {
242 return _addressSpace
.get32(_addr
+
243 offsetof(unwind_info_section_header
, version
));
245 uint32_t commonEncodingsArraySectionOffset() const {
246 return _addressSpace
.get32(_addr
+
247 offsetof(unwind_info_section_header
,
248 commonEncodingsArraySectionOffset
));
250 uint32_t commonEncodingsArrayCount() const {
251 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
252 commonEncodingsArrayCount
));
254 uint32_t personalityArraySectionOffset() const {
255 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
256 personalityArraySectionOffset
));
258 uint32_t personalityArrayCount() const {
259 return _addressSpace
.get32(
260 _addr
+ offsetof(unwind_info_section_header
, personalityArrayCount
));
262 uint32_t indexSectionOffset() const {
263 return _addressSpace
.get32(
264 _addr
+ offsetof(unwind_info_section_header
, indexSectionOffset
));
266 uint32_t indexCount() const {
267 return _addressSpace
.get32(
268 _addr
+ offsetof(unwind_info_section_header
, indexCount
));
273 typename
A::pint_t _addr
;
276 template <typename A
> class UnwindSectionIndexArray
{
278 UnwindSectionIndexArray(A
&addressSpace
, typename
A::pint_t addr
)
279 : _addressSpace(addressSpace
), _addr(addr
) {}
281 uint32_t functionOffset(uint32_t index
) const {
282 return _addressSpace
.get32(
283 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
286 uint32_t secondLevelPagesSectionOffset(uint32_t index
) const {
287 return _addressSpace
.get32(
288 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
289 secondLevelPagesSectionOffset
));
291 uint32_t lsdaIndexArraySectionOffset(uint32_t index
) const {
292 return _addressSpace
.get32(
293 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
294 lsdaIndexArraySectionOffset
));
299 typename
A::pint_t _addr
;
302 template <typename A
> class UnwindSectionRegularPageHeader
{
304 UnwindSectionRegularPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
305 : _addressSpace(addressSpace
), _addr(addr
) {}
307 uint32_t kind() const {
308 return _addressSpace
.get32(
309 _addr
+ offsetof(unwind_info_regular_second_level_page_header
, kind
));
311 uint16_t entryPageOffset() const {
312 return _addressSpace
.get16(
313 _addr
+ offsetof(unwind_info_regular_second_level_page_header
,
316 uint16_t entryCount() const {
317 return _addressSpace
.get16(
319 offsetof(unwind_info_regular_second_level_page_header
, entryCount
));
324 typename
A::pint_t _addr
;
327 template <typename A
> class UnwindSectionRegularArray
{
329 UnwindSectionRegularArray(A
&addressSpace
, typename
A::pint_t addr
)
330 : _addressSpace(addressSpace
), _addr(addr
) {}
332 uint32_t functionOffset(uint32_t index
) const {
333 return _addressSpace
.get32(
334 _addr
+ arrayoffsetof(unwind_info_regular_second_level_entry
, index
,
337 uint32_t encoding(uint32_t index
) const {
338 return _addressSpace
.get32(
340 arrayoffsetof(unwind_info_regular_second_level_entry
, index
, encoding
));
345 typename
A::pint_t _addr
;
348 template <typename A
> class UnwindSectionCompressedPageHeader
{
350 UnwindSectionCompressedPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
351 : _addressSpace(addressSpace
), _addr(addr
) {}
353 uint32_t kind() const {
354 return _addressSpace
.get32(
356 offsetof(unwind_info_compressed_second_level_page_header
, kind
));
358 uint16_t entryPageOffset() const {
359 return _addressSpace
.get16(
360 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
363 uint16_t entryCount() const {
364 return _addressSpace
.get16(
366 offsetof(unwind_info_compressed_second_level_page_header
, entryCount
));
368 uint16_t encodingsPageOffset() const {
369 return _addressSpace
.get16(
370 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
371 encodingsPageOffset
));
373 uint16_t encodingsCount() const {
374 return _addressSpace
.get16(
375 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
381 typename
A::pint_t _addr
;
384 template <typename A
> class UnwindSectionCompressedArray
{
386 UnwindSectionCompressedArray(A
&addressSpace
, typename
A::pint_t addr
)
387 : _addressSpace(addressSpace
), _addr(addr
) {}
389 uint32_t functionOffset(uint32_t index
) const {
390 return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
391 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
393 uint16_t encodingIndex(uint32_t index
) const {
394 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
395 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
400 typename
A::pint_t _addr
;
403 template <typename A
> class UnwindSectionLsdaArray
{
405 UnwindSectionLsdaArray(A
&addressSpace
, typename
A::pint_t addr
)
406 : _addressSpace(addressSpace
), _addr(addr
) {}
408 uint32_t functionOffset(uint32_t index
) const {
409 return _addressSpace
.get32(
410 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
411 index
, functionOffset
));
413 uint32_t lsdaOffset(uint32_t index
) const {
414 return _addressSpace
.get32(
415 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
421 typename
A::pint_t _addr
;
423 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
425 class _LIBUNWIND_HIDDEN AbstractUnwindCursor
{
427 // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
428 // This avoids an unnecessary dependency to libc++abi.
429 void operator delete(void *, size_t) {}
431 virtual ~AbstractUnwindCursor() {}
432 virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
433 virtual unw_word_t
getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
434 virtual void setReg(int, unw_word_t
) {
435 _LIBUNWIND_ABORT("setReg not implemented");
437 virtual bool validFloatReg(int) {
438 _LIBUNWIND_ABORT("validFloatReg not implemented");
440 virtual unw_fpreg_t
getFloatReg(int) {
441 _LIBUNWIND_ABORT("getFloatReg not implemented");
443 virtual void setFloatReg(int, unw_fpreg_t
) {
444 _LIBUNWIND_ABORT("setFloatReg not implemented");
446 virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); }
447 virtual void getInfo(unw_proc_info_t
*) {
448 _LIBUNWIND_ABORT("getInfo not implemented");
450 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
451 virtual bool isSignalFrame() {
452 _LIBUNWIND_ABORT("isSignalFrame not implemented");
454 virtual bool getFunctionName(char *, size_t, unw_word_t
*) {
455 _LIBUNWIND_ABORT("getFunctionName not implemented");
457 virtual void setInfoBasedOnIPRegister(bool = false) {
458 _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
460 virtual const char *getRegisterName(int) {
461 _LIBUNWIND_ABORT("getRegisterName not implemented");
464 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
468 virtual uintptr_t getDataRelBase() {
469 _LIBUNWIND_ABORT("getDataRelBase not implemented");
473 #if defined(_LIBUNWIND_USE_CET)
474 virtual void *get_registers() {
475 _LIBUNWIND_ABORT("get_registers not implemented");
480 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
482 /// \c UnwindCursor contains all state (including all register values) during
483 /// an unwind. This is normally stack-allocated inside a unw_cursor_t.
484 template <typename A
, typename R
>
485 class UnwindCursor
: public AbstractUnwindCursor
{
486 typedef typename
A::pint_t pint_t
;
488 UnwindCursor(unw_context_t
*context
, A
&as
);
489 UnwindCursor(CONTEXT
*context
, A
&as
);
490 UnwindCursor(A
&as
, void *threadArg
);
491 virtual ~UnwindCursor() {}
492 virtual bool validReg(int);
493 virtual unw_word_t
getReg(int);
494 virtual void setReg(int, unw_word_t
);
495 virtual bool validFloatReg(int);
496 virtual unw_fpreg_t
getFloatReg(int);
497 virtual void setFloatReg(int, unw_fpreg_t
);
498 virtual int step(bool = false);
499 virtual void getInfo(unw_proc_info_t
*);
500 virtual void jumpto();
501 virtual bool isSignalFrame();
502 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
503 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
504 virtual const char *getRegisterName(int num
);
506 virtual void saveVFPAsX();
509 DISPATCHER_CONTEXT
*getDispatcherContext() { return &_dispContext
; }
510 void setDispatcherContext(DISPATCHER_CONTEXT
*disp
) {
511 _dispContext
= *disp
;
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
);
519 // libunwind does not and should not depend on C++ library which means that we
520 // need our own definition of inline placement new.
521 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
525 pint_t
getLastPC() const { return _dispContext
.ControlPc
; }
526 void setLastPC(pint_t pc
) { _dispContext
.ControlPc
= pc
; }
527 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
529 // Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.
532 // If pc points exactly at the end of the range, we might resolve the
533 // next function instead. Decrement pc by 1 to fit inside the current
536 _dispContext
.FunctionEntry
= RtlLookupFunctionEntry(pc
,
537 &_dispContext
.ImageBase
,
538 _dispContext
.HistoryTable
);
539 *base
= _dispContext
.ImageBase
;
540 return _dispContext
.FunctionEntry
;
542 bool getInfoFromSEH(pint_t pc
);
543 int stepWithSEHData() {
544 _dispContext
.LanguageHandler
= RtlVirtualUnwind(UNW_FLAG_UHANDLER
,
545 _dispContext
.ImageBase
,
546 _dispContext
.ControlPc
,
547 _dispContext
.FunctionEntry
,
548 _dispContext
.ContextRecord
,
549 &_dispContext
.HandlerData
,
550 &_dispContext
.EstablisherFrame
,
552 // Update some fields of the unwind info now, since we have them.
553 _info
.lsda
= reinterpret_cast<unw_word_t
>(_dispContext
.HandlerData
);
554 if (_dispContext
.LanguageHandler
) {
555 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
558 return UNW_STEP_SUCCESS
;
562 unw_proc_info_t _info
;
563 DISPATCHER_CONTEXT _dispContext
;
565 UNWIND_HISTORY_TABLE _histTable
;
566 bool _unwindInfoMissing
;
570 template <typename A
, typename R
>
571 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
572 : _addressSpace(as
), _unwindInfoMissing(false) {
573 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
574 "UnwindCursor<> does not fit in unw_cursor_t");
575 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
576 "UnwindCursor<> requires more alignment than unw_cursor_t");
577 memset(&_info
, 0, sizeof(_info
));
578 memset(&_histTable
, 0, sizeof(_histTable
));
579 memset(&_dispContext
, 0, sizeof(_dispContext
));
580 _dispContext
.ContextRecord
= &_msContext
;
581 _dispContext
.HistoryTable
= &_histTable
;
582 // Initialize MS context from ours.
584 RtlCaptureContext(&_msContext
);
585 _msContext
.ContextFlags
= CONTEXT_CONTROL
|CONTEXT_INTEGER
|CONTEXT_FLOATING_POINT
;
586 #if defined(_LIBUNWIND_TARGET_X86_64)
587 _msContext
.Rax
= r
.getRegister(UNW_X86_64_RAX
);
588 _msContext
.Rcx
= r
.getRegister(UNW_X86_64_RCX
);
589 _msContext
.Rdx
= r
.getRegister(UNW_X86_64_RDX
);
590 _msContext
.Rbx
= r
.getRegister(UNW_X86_64_RBX
);
591 _msContext
.Rsp
= r
.getRegister(UNW_X86_64_RSP
);
592 _msContext
.Rbp
= r
.getRegister(UNW_X86_64_RBP
);
593 _msContext
.Rsi
= r
.getRegister(UNW_X86_64_RSI
);
594 _msContext
.Rdi
= r
.getRegister(UNW_X86_64_RDI
);
595 _msContext
.R8
= r
.getRegister(UNW_X86_64_R8
);
596 _msContext
.R9
= r
.getRegister(UNW_X86_64_R9
);
597 _msContext
.R10
= r
.getRegister(UNW_X86_64_R10
);
598 _msContext
.R11
= r
.getRegister(UNW_X86_64_R11
);
599 _msContext
.R12
= r
.getRegister(UNW_X86_64_R12
);
600 _msContext
.R13
= r
.getRegister(UNW_X86_64_R13
);
601 _msContext
.R14
= r
.getRegister(UNW_X86_64_R14
);
602 _msContext
.R15
= r
.getRegister(UNW_X86_64_R15
);
603 _msContext
.Rip
= r
.getRegister(UNW_REG_IP
);
608 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM0
);
609 _msContext
.Xmm0
= t
.m
;
610 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM1
);
611 _msContext
.Xmm1
= t
.m
;
612 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM2
);
613 _msContext
.Xmm2
= t
.m
;
614 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM3
);
615 _msContext
.Xmm3
= t
.m
;
616 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM4
);
617 _msContext
.Xmm4
= t
.m
;
618 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM5
);
619 _msContext
.Xmm5
= t
.m
;
620 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM6
);
621 _msContext
.Xmm6
= t
.m
;
622 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM7
);
623 _msContext
.Xmm7
= t
.m
;
624 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM8
);
625 _msContext
.Xmm8
= t
.m
;
626 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM9
);
627 _msContext
.Xmm9
= t
.m
;
628 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM10
);
629 _msContext
.Xmm10
= t
.m
;
630 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM11
);
631 _msContext
.Xmm11
= t
.m
;
632 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM12
);
633 _msContext
.Xmm12
= t
.m
;
634 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM13
);
635 _msContext
.Xmm13
= t
.m
;
636 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM14
);
637 _msContext
.Xmm14
= t
.m
;
638 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM15
);
639 _msContext
.Xmm15
= t
.m
;
640 #elif defined(_LIBUNWIND_TARGET_ARM)
641 _msContext
.R0
= r
.getRegister(UNW_ARM_R0
);
642 _msContext
.R1
= r
.getRegister(UNW_ARM_R1
);
643 _msContext
.R2
= r
.getRegister(UNW_ARM_R2
);
644 _msContext
.R3
= r
.getRegister(UNW_ARM_R3
);
645 _msContext
.R4
= r
.getRegister(UNW_ARM_R4
);
646 _msContext
.R5
= r
.getRegister(UNW_ARM_R5
);
647 _msContext
.R6
= r
.getRegister(UNW_ARM_R6
);
648 _msContext
.R7
= r
.getRegister(UNW_ARM_R7
);
649 _msContext
.R8
= r
.getRegister(UNW_ARM_R8
);
650 _msContext
.R9
= r
.getRegister(UNW_ARM_R9
);
651 _msContext
.R10
= r
.getRegister(UNW_ARM_R10
);
652 _msContext
.R11
= r
.getRegister(UNW_ARM_R11
);
653 _msContext
.R12
= r
.getRegister(UNW_ARM_R12
);
654 _msContext
.Sp
= r
.getRegister(UNW_ARM_SP
);
655 _msContext
.Lr
= r
.getRegister(UNW_ARM_LR
);
656 _msContext
.Pc
= r
.getRegister(UNW_ARM_IP
);
657 for (int i
= UNW_ARM_D0
; i
<= UNW_ARM_D31
; ++i
) {
662 d
.d
= r
.getFloatRegister(i
);
663 _msContext
.D
[i
- UNW_ARM_D0
] = d
.w
;
665 #elif defined(_LIBUNWIND_TARGET_AARCH64)
666 for (int i
= UNW_AARCH64_X0
; i
<= UNW_ARM64_X30
; ++i
)
667 _msContext
.X
[i
- UNW_AARCH64_X0
] = r
.getRegister(i
);
668 _msContext
.Sp
= r
.getRegister(UNW_REG_SP
);
669 _msContext
.Pc
= r
.getRegister(UNW_REG_IP
);
670 for (int i
= UNW_AARCH64_V0
; i
<= UNW_ARM64_D31
; ++i
)
671 _msContext
.V
[i
- UNW_AARCH64_V0
].D
[0] = r
.getFloatRegister(i
);
675 template <typename A
, typename R
>
676 UnwindCursor
<A
, R
>::UnwindCursor(CONTEXT
*context
, A
&as
)
677 : _addressSpace(as
), _unwindInfoMissing(false) {
678 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
679 "UnwindCursor<> does not fit in unw_cursor_t");
680 memset(&_info
, 0, sizeof(_info
));
681 memset(&_histTable
, 0, sizeof(_histTable
));
682 memset(&_dispContext
, 0, sizeof(_dispContext
));
683 _dispContext
.ContextRecord
= &_msContext
;
684 _dispContext
.HistoryTable
= &_histTable
;
685 _msContext
= *context
;
689 template <typename A
, typename R
>
690 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
691 if (regNum
== UNW_REG_IP
|| regNum
== UNW_REG_SP
) return true;
692 #if defined(_LIBUNWIND_TARGET_X86_64)
693 if (regNum
>= UNW_X86_64_RAX
&& regNum
<= UNW_X86_64_RIP
) return true;
694 #elif defined(_LIBUNWIND_TARGET_ARM)
695 if ((regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R15
) ||
696 regNum
== UNW_ARM_RA_AUTH_CODE
)
698 #elif defined(_LIBUNWIND_TARGET_AARCH64)
699 if (regNum
>= UNW_AARCH64_X0
&& regNum
<= UNW_ARM64_X30
) return true;
704 template <typename A
, typename R
>
705 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
707 #if defined(_LIBUNWIND_TARGET_X86_64)
709 case UNW_REG_IP
: return _msContext
.Rip
;
710 case UNW_X86_64_RAX
: return _msContext
.Rax
;
711 case UNW_X86_64_RDX
: return _msContext
.Rdx
;
712 case UNW_X86_64_RCX
: return _msContext
.Rcx
;
713 case UNW_X86_64_RBX
: return _msContext
.Rbx
;
715 case UNW_X86_64_RSP
: return _msContext
.Rsp
;
716 case UNW_X86_64_RBP
: return _msContext
.Rbp
;
717 case UNW_X86_64_RSI
: return _msContext
.Rsi
;
718 case UNW_X86_64_RDI
: return _msContext
.Rdi
;
719 case UNW_X86_64_R8
: return _msContext
.R8
;
720 case UNW_X86_64_R9
: return _msContext
.R9
;
721 case UNW_X86_64_R10
: return _msContext
.R10
;
722 case UNW_X86_64_R11
: return _msContext
.R11
;
723 case UNW_X86_64_R12
: return _msContext
.R12
;
724 case UNW_X86_64_R13
: return _msContext
.R13
;
725 case UNW_X86_64_R14
: return _msContext
.R14
;
726 case UNW_X86_64_R15
: return _msContext
.R15
;
727 #elif defined(_LIBUNWIND_TARGET_ARM)
728 case UNW_ARM_R0
: return _msContext
.R0
;
729 case UNW_ARM_R1
: return _msContext
.R1
;
730 case UNW_ARM_R2
: return _msContext
.R2
;
731 case UNW_ARM_R3
: return _msContext
.R3
;
732 case UNW_ARM_R4
: return _msContext
.R4
;
733 case UNW_ARM_R5
: return _msContext
.R5
;
734 case UNW_ARM_R6
: return _msContext
.R6
;
735 case UNW_ARM_R7
: return _msContext
.R7
;
736 case UNW_ARM_R8
: return _msContext
.R8
;
737 case UNW_ARM_R9
: return _msContext
.R9
;
738 case UNW_ARM_R10
: return _msContext
.R10
;
739 case UNW_ARM_R11
: return _msContext
.R11
;
740 case UNW_ARM_R12
: return _msContext
.R12
;
742 case UNW_ARM_SP
: return _msContext
.Sp
;
743 case UNW_ARM_LR
: return _msContext
.Lr
;
745 case UNW_ARM_IP
: return _msContext
.Pc
;
746 #elif defined(_LIBUNWIND_TARGET_AARCH64)
747 case UNW_REG_SP
: return _msContext
.Sp
;
748 case UNW_REG_IP
: return _msContext
.Pc
;
749 default: return _msContext
.X
[regNum
- UNW_AARCH64_X0
];
752 _LIBUNWIND_ABORT("unsupported register");
755 template <typename A
, typename R
>
756 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
758 #if defined(_LIBUNWIND_TARGET_X86_64)
760 case UNW_REG_IP
: _msContext
.Rip
= value
; break;
761 case UNW_X86_64_RAX
: _msContext
.Rax
= value
; break;
762 case UNW_X86_64_RDX
: _msContext
.Rdx
= value
; break;
763 case UNW_X86_64_RCX
: _msContext
.Rcx
= value
; break;
764 case UNW_X86_64_RBX
: _msContext
.Rbx
= value
; break;
766 case UNW_X86_64_RSP
: _msContext
.Rsp
= value
; break;
767 case UNW_X86_64_RBP
: _msContext
.Rbp
= value
; break;
768 case UNW_X86_64_RSI
: _msContext
.Rsi
= value
; break;
769 case UNW_X86_64_RDI
: _msContext
.Rdi
= value
; break;
770 case UNW_X86_64_R8
: _msContext
.R8
= value
; break;
771 case UNW_X86_64_R9
: _msContext
.R9
= value
; break;
772 case UNW_X86_64_R10
: _msContext
.R10
= value
; break;
773 case UNW_X86_64_R11
: _msContext
.R11
= value
; break;
774 case UNW_X86_64_R12
: _msContext
.R12
= value
; break;
775 case UNW_X86_64_R13
: _msContext
.R13
= value
; break;
776 case UNW_X86_64_R14
: _msContext
.R14
= value
; break;
777 case UNW_X86_64_R15
: _msContext
.R15
= value
; break;
778 #elif defined(_LIBUNWIND_TARGET_ARM)
779 case UNW_ARM_R0
: _msContext
.R0
= value
; break;
780 case UNW_ARM_R1
: _msContext
.R1
= value
; break;
781 case UNW_ARM_R2
: _msContext
.R2
= value
; break;
782 case UNW_ARM_R3
: _msContext
.R3
= value
; break;
783 case UNW_ARM_R4
: _msContext
.R4
= value
; break;
784 case UNW_ARM_R5
: _msContext
.R5
= value
; break;
785 case UNW_ARM_R6
: _msContext
.R6
= value
; break;
786 case UNW_ARM_R7
: _msContext
.R7
= value
; break;
787 case UNW_ARM_R8
: _msContext
.R8
= value
; break;
788 case UNW_ARM_R9
: _msContext
.R9
= value
; break;
789 case UNW_ARM_R10
: _msContext
.R10
= value
; break;
790 case UNW_ARM_R11
: _msContext
.R11
= value
; break;
791 case UNW_ARM_R12
: _msContext
.R12
= value
; break;
793 case UNW_ARM_SP
: _msContext
.Sp
= value
; break;
794 case UNW_ARM_LR
: _msContext
.Lr
= value
; break;
796 case UNW_ARM_IP
: _msContext
.Pc
= value
; break;
797 #elif defined(_LIBUNWIND_TARGET_AARCH64)
798 case UNW_REG_SP
: _msContext
.Sp
= value
; break;
799 case UNW_REG_IP
: _msContext
.Pc
= value
; break;
810 case UNW_AARCH64_X10
:
811 case UNW_AARCH64_X11
:
812 case UNW_AARCH64_X12
:
813 case UNW_AARCH64_X13
:
814 case UNW_AARCH64_X14
:
815 case UNW_AARCH64_X15
:
816 case UNW_AARCH64_X16
:
817 case UNW_AARCH64_X17
:
818 case UNW_AARCH64_X18
:
819 case UNW_AARCH64_X19
:
820 case UNW_AARCH64_X20
:
821 case UNW_AARCH64_X21
:
822 case UNW_AARCH64_X22
:
823 case UNW_AARCH64_X23
:
824 case UNW_AARCH64_X24
:
825 case UNW_AARCH64_X25
:
826 case UNW_AARCH64_X26
:
827 case UNW_AARCH64_X27
:
828 case UNW_AARCH64_X28
:
830 case UNW_AARCH64_LR
: _msContext
.X
[regNum
- UNW_ARM64_X0
] = value
; break;
833 _LIBUNWIND_ABORT("unsupported register");
837 template <typename A
, typename R
>
838 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
839 #if defined(_LIBUNWIND_TARGET_ARM)
840 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) return true;
841 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) return true;
842 #elif defined(_LIBUNWIND_TARGET_AARCH64)
843 if (regNum
>= UNW_AARCH64_V0
&& regNum
<= UNW_ARM64_D31
) return true;
850 template <typename A
, typename R
>
851 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
852 #if defined(_LIBUNWIND_TARGET_ARM)
853 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
858 d
.w
= _msContext
.S
[regNum
- UNW_ARM_S0
];
861 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
866 d
.w
= _msContext
.D
[regNum
- UNW_ARM_D0
];
869 _LIBUNWIND_ABORT("unsupported float register");
870 #elif defined(_LIBUNWIND_TARGET_AARCH64)
871 return _msContext
.V
[regNum
- UNW_AARCH64_V0
].D
[0];
874 _LIBUNWIND_ABORT("float registers unimplemented");
878 template <typename A
, typename R
>
879 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
880 #if defined(_LIBUNWIND_TARGET_ARM)
881 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
887 _msContext
.S
[regNum
- UNW_ARM_S0
] = d
.w
;
889 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
895 _msContext
.D
[regNum
- UNW_ARM_D0
] = d
.w
;
897 _LIBUNWIND_ABORT("unsupported float register");
898 #elif defined(_LIBUNWIND_TARGET_AARCH64)
899 _msContext
.V
[regNum
- UNW_AARCH64_V0
].D
[0] = value
;
903 _LIBUNWIND_ABORT("float registers unimplemented");
907 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
908 RtlRestoreContext(&_msContext
, nullptr);
912 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {}
915 template <typename A
, typename R
>
916 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
917 return R::getRegisterName(regNum
);
920 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
924 #else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
926 /// UnwindCursor contains all state (including all register values) during
927 /// an unwind. This is normally stack allocated inside a unw_cursor_t.
928 template <typename A
, typename R
>
929 class UnwindCursor
: public AbstractUnwindCursor
{
930 typedef typename
A::pint_t pint_t
;
932 UnwindCursor(unw_context_t
*context
, A
&as
);
933 UnwindCursor(A
&as
, void *threadArg
);
934 virtual ~UnwindCursor() {}
935 virtual bool validReg(int);
936 virtual unw_word_t
getReg(int);
937 virtual void setReg(int, unw_word_t
);
938 virtual bool validFloatReg(int);
939 virtual unw_fpreg_t
getFloatReg(int);
940 virtual void setFloatReg(int, unw_fpreg_t
);
941 virtual int step(bool stage2
= false);
942 virtual void getInfo(unw_proc_info_t
*);
943 virtual void jumpto();
944 virtual bool isSignalFrame();
945 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
946 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
947 virtual const char *getRegisterName(int num
);
949 virtual void saveVFPAsX();
953 virtual uintptr_t getDataRelBase();
956 #if defined(_LIBUNWIND_USE_CET)
957 virtual void *get_registers() { return &_registers
; }
960 // libunwind does not and should not depend on C++ library which means that we
961 // need our own definition of inline placement new.
962 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
966 #if defined(_LIBUNWIND_ARM_EHABI)
967 bool getInfoFromEHABISection(pint_t pc
, const UnwindInfoSections
§s
);
969 int stepWithEHABI() {
972 // FIXME: Calling decode_eht_entry() here is violating the libunwind
973 // abstraction layer.
974 const uint32_t *ehtp
=
975 decode_eht_entry(reinterpret_cast<const uint32_t *>(_info
.unwind_info
),
977 if (_Unwind_VRS_Interpret((_Unwind_Context
*)this, ehtp
, off
, len
) !=
978 _URC_CONTINUE_UNWIND
)
980 return UNW_STEP_SUCCESS
;
984 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
985 bool setInfoForSigReturn() {
987 return setInfoForSigReturn(dummy
);
989 int stepThroughSigReturn() {
991 return stepThroughSigReturn(dummy
);
993 #if defined(_LIBUNWIND_TARGET_AARCH64)
994 bool setInfoForSigReturn(Registers_arm64
&);
995 int stepThroughSigReturn(Registers_arm64
&);
997 #if defined(_LIBUNWIND_TARGET_RISCV)
998 bool setInfoForSigReturn(Registers_riscv
&);
999 int stepThroughSigReturn(Registers_riscv
&);
1001 #if defined(_LIBUNWIND_TARGET_S390X)
1002 bool setInfoForSigReturn(Registers_s390x
&);
1003 int stepThroughSigReturn(Registers_s390x
&);
1005 template <typename Registers
> bool setInfoForSigReturn(Registers
&) {
1008 template <typename Registers
> int stepThroughSigReturn(Registers
&) {
1009 return UNW_STEP_END
;
1013 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1014 bool getInfoFromFdeCie(const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
1015 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
,
1016 pint_t pc
, uintptr_t dso_base
);
1017 bool getInfoFromDwarfSection(pint_t pc
, const UnwindInfoSections
§s
,
1018 uint32_t fdeSectionOffsetHint
=0);
1019 int stepWithDwarfFDE(bool stage2
) {
1020 return DwarfInstructions
<A
, R
>::stepWithDwarf(
1021 _addressSpace
, (pint_t
)this->getReg(UNW_REG_IP
),
1022 (pint_t
)_info
.unwind_info
, _registers
, _isSignalFrame
, stage2
);
1026 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1027 bool getInfoFromCompactEncodingSection(pint_t pc
,
1028 const UnwindInfoSections
§s
);
1029 int stepWithCompactEncoding(bool stage2
= false) {
1030 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1031 if ( compactSaysUseDwarf() )
1032 return stepWithDwarfFDE(stage2
);
1035 return stepWithCompactEncoding(dummy
);
1038 #if defined(_LIBUNWIND_TARGET_X86_64)
1039 int stepWithCompactEncoding(Registers_x86_64
&) {
1040 return CompactUnwinder_x86_64
<A
>::stepWithCompactEncoding(
1041 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
1045 #if defined(_LIBUNWIND_TARGET_I386)
1046 int stepWithCompactEncoding(Registers_x86
&) {
1047 return CompactUnwinder_x86
<A
>::stepWithCompactEncoding(
1048 _info
.format
, (uint32_t)_info
.start_ip
, _addressSpace
, _registers
);
1052 #if defined(_LIBUNWIND_TARGET_PPC)
1053 int stepWithCompactEncoding(Registers_ppc
&) {
1058 #if defined(_LIBUNWIND_TARGET_PPC64)
1059 int stepWithCompactEncoding(Registers_ppc64
&) {
1065 #if defined(_LIBUNWIND_TARGET_AARCH64)
1066 int stepWithCompactEncoding(Registers_arm64
&) {
1067 return CompactUnwinder_arm64
<A
>::stepWithCompactEncoding(
1068 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
1072 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
1073 int stepWithCompactEncoding(Registers_mips_o32
&) {
1078 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1079 int stepWithCompactEncoding(Registers_mips_newabi
&) {
1084 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1085 int stepWithCompactEncoding(Registers_loongarch
&) { return UNW_EINVAL
; }
1088 #if defined(_LIBUNWIND_TARGET_SPARC)
1089 int stepWithCompactEncoding(Registers_sparc
&) { return UNW_EINVAL
; }
1092 #if defined(_LIBUNWIND_TARGET_SPARC64)
1093 int stepWithCompactEncoding(Registers_sparc64
&) { return UNW_EINVAL
; }
1096 #if defined (_LIBUNWIND_TARGET_RISCV)
1097 int stepWithCompactEncoding(Registers_riscv
&) {
1102 bool compactSaysUseDwarf(uint32_t *offset
=NULL
) const {
1104 return compactSaysUseDwarf(dummy
, offset
);
1107 #if defined(_LIBUNWIND_TARGET_X86_64)
1108 bool compactSaysUseDwarf(Registers_x86_64
&, uint32_t *offset
) const {
1109 if ((_info
.format
& UNWIND_X86_64_MODE_MASK
) == UNWIND_X86_64_MODE_DWARF
) {
1111 *offset
= (_info
.format
& UNWIND_X86_64_DWARF_SECTION_OFFSET
);
1118 #if defined(_LIBUNWIND_TARGET_I386)
1119 bool compactSaysUseDwarf(Registers_x86
&, uint32_t *offset
) const {
1120 if ((_info
.format
& UNWIND_X86_MODE_MASK
) == UNWIND_X86_MODE_DWARF
) {
1122 *offset
= (_info
.format
& UNWIND_X86_DWARF_SECTION_OFFSET
);
1129 #if defined(_LIBUNWIND_TARGET_PPC)
1130 bool compactSaysUseDwarf(Registers_ppc
&, uint32_t *) const {
1135 #if defined(_LIBUNWIND_TARGET_PPC64)
1136 bool compactSaysUseDwarf(Registers_ppc64
&, uint32_t *) const {
1141 #if defined(_LIBUNWIND_TARGET_AARCH64)
1142 bool compactSaysUseDwarf(Registers_arm64
&, uint32_t *offset
) const {
1143 if ((_info
.format
& UNWIND_ARM64_MODE_MASK
) == UNWIND_ARM64_MODE_DWARF
) {
1145 *offset
= (_info
.format
& UNWIND_ARM64_DWARF_SECTION_OFFSET
);
1152 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
1153 bool compactSaysUseDwarf(Registers_mips_o32
&, uint32_t *) const {
1158 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1159 bool compactSaysUseDwarf(Registers_mips_newabi
&, uint32_t *) const {
1164 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1165 bool compactSaysUseDwarf(Registers_loongarch
&, uint32_t *) const {
1170 #if defined(_LIBUNWIND_TARGET_SPARC)
1171 bool compactSaysUseDwarf(Registers_sparc
&, uint32_t *) const { return true; }
1174 #if defined(_LIBUNWIND_TARGET_SPARC64)
1175 bool compactSaysUseDwarf(Registers_sparc64
&, uint32_t *) const {
1180 #if defined (_LIBUNWIND_TARGET_RISCV)
1181 bool compactSaysUseDwarf(Registers_riscv
&, uint32_t *) const {
1186 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1188 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1189 compact_unwind_encoding_t
dwarfEncoding() const {
1191 return dwarfEncoding(dummy
);
1194 #if defined(_LIBUNWIND_TARGET_X86_64)
1195 compact_unwind_encoding_t
dwarfEncoding(Registers_x86_64
&) const {
1196 return UNWIND_X86_64_MODE_DWARF
;
1200 #if defined(_LIBUNWIND_TARGET_I386)
1201 compact_unwind_encoding_t
dwarfEncoding(Registers_x86
&) const {
1202 return UNWIND_X86_MODE_DWARF
;
1206 #if defined(_LIBUNWIND_TARGET_PPC)
1207 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc
&) const {
1212 #if defined(_LIBUNWIND_TARGET_PPC64)
1213 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc64
&) const {
1218 #if defined(_LIBUNWIND_TARGET_AARCH64)
1219 compact_unwind_encoding_t
dwarfEncoding(Registers_arm64
&) const {
1220 return UNWIND_ARM64_MODE_DWARF
;
1224 #if defined(_LIBUNWIND_TARGET_ARM)
1225 compact_unwind_encoding_t
dwarfEncoding(Registers_arm
&) const {
1230 #if defined (_LIBUNWIND_TARGET_OR1K)
1231 compact_unwind_encoding_t
dwarfEncoding(Registers_or1k
&) const {
1236 #if defined (_LIBUNWIND_TARGET_HEXAGON)
1237 compact_unwind_encoding_t
dwarfEncoding(Registers_hexagon
&) const {
1242 #if defined (_LIBUNWIND_TARGET_MIPS_O32)
1243 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_o32
&) const {
1248 #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1249 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_newabi
&) const {
1254 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1255 compact_unwind_encoding_t
dwarfEncoding(Registers_loongarch
&) const {
1260 #if defined(_LIBUNWIND_TARGET_SPARC)
1261 compact_unwind_encoding_t
dwarfEncoding(Registers_sparc
&) const { return 0; }
1264 #if defined(_LIBUNWIND_TARGET_SPARC64)
1265 compact_unwind_encoding_t
dwarfEncoding(Registers_sparc64
&) const {
1270 #if defined (_LIBUNWIND_TARGET_RISCV)
1271 compact_unwind_encoding_t
dwarfEncoding(Registers_riscv
&) const {
1276 #if defined (_LIBUNWIND_TARGET_S390X)
1277 compact_unwind_encoding_t
dwarfEncoding(Registers_s390x
&) const {
1282 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1284 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1285 // For runtime environments using SEH unwind data without Windows runtime
1287 pint_t
getLastPC() const { /* FIXME: Implement */ return 0; }
1288 void setLastPC(pint_t pc
) { /* FIXME: Implement */ }
1289 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
1290 /* FIXME: Implement */
1294 bool getInfoFromSEH(pint_t pc
);
1295 int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1296 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1298 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1299 bool getInfoFromTBTable(pint_t pc
, R
®isters
);
1300 int stepWithTBTable(pint_t pc
, tbtable
*TBTable
, R
®isters
,
1301 bool &isSignalFrame
);
1302 int stepWithTBTableData() {
1303 return stepWithTBTable(reinterpret_cast<pint_t
>(this->getReg(UNW_REG_IP
)),
1304 reinterpret_cast<tbtable
*>(_info
.unwind_info
),
1305 _registers
, _isSignalFrame
);
1307 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1311 unw_proc_info_t _info
;
1312 bool _unwindInfoMissing
;
1313 bool _isSignalFrame
;
1314 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1315 bool _isSigReturn
= false;
1320 template <typename A
, typename R
>
1321 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
1322 : _addressSpace(as
), _registers(context
), _unwindInfoMissing(false),
1323 _isSignalFrame(false) {
1324 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
1325 "UnwindCursor<> does not fit in unw_cursor_t");
1326 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
1327 "UnwindCursor<> requires more alignment than unw_cursor_t");
1328 memset(&_info
, 0, sizeof(_info
));
1331 template <typename A
, typename R
>
1332 UnwindCursor
<A
, R
>::UnwindCursor(A
&as
, void *)
1333 : _addressSpace(as
), _unwindInfoMissing(false), _isSignalFrame(false) {
1334 memset(&_info
, 0, sizeof(_info
));
1336 // fill in _registers from thread arg
1340 template <typename A
, typename R
>
1341 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
1342 return _registers
.validRegister(regNum
);
1345 template <typename A
, typename R
>
1346 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
1347 return _registers
.getRegister(regNum
);
1350 template <typename A
, typename R
>
1351 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
1352 _registers
.setRegister(regNum
, (typename
A::pint_t
)value
);
1355 template <typename A
, typename R
>
1356 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
1357 return _registers
.validFloatRegister(regNum
);
1360 template <typename A
, typename R
>
1361 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
1362 return _registers
.getFloatRegister(regNum
);
1365 template <typename A
, typename R
>
1366 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
1367 _registers
.setFloatRegister(regNum
, value
);
1370 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
1371 _registers
.jumpto();
1375 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {
1376 _registers
.saveVFPAsX();
1381 template <typename A
, typename R
>
1382 uintptr_t UnwindCursor
<A
, R
>::getDataRelBase() {
1383 return reinterpret_cast<uintptr_t>(_info
.extra
);
1387 template <typename A
, typename R
>
1388 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
1389 return _registers
.getRegisterName(regNum
);
1392 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
1393 return _isSignalFrame
;
1396 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1398 #if defined(_LIBUNWIND_ARM_EHABI)
1399 template<typename A
>
1400 struct EHABISectionIterator
{
1401 typedef EHABISectionIterator _Self
;
1403 typedef typename
A::pint_t value_type
;
1404 typedef typename
A::pint_t
* pointer
;
1405 typedef typename
A::pint_t
& reference
;
1406 typedef size_t size_type
;
1407 typedef size_t difference_type
;
1409 static _Self
begin(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1410 return _Self(addressSpace
, sects
, 0);
1412 static _Self
end(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1413 return _Self(addressSpace
, sects
,
1414 sects
.arm_section_length
/ sizeof(EHABIIndexEntry
));
1417 EHABISectionIterator(A
& addressSpace
, const UnwindInfoSections
& sects
, size_t i
)
1418 : _i(i
), _addressSpace(&addressSpace
), _sects(§s
) {}
1420 _Self
& operator++() { ++_i
; return *this; }
1421 _Self
& operator+=(size_t a
) { _i
+= a
; return *this; }
1422 _Self
& operator--() { assert(_i
> 0); --_i
; return *this; }
1423 _Self
& operator-=(size_t a
) { assert(_i
>= a
); _i
-= a
; return *this; }
1425 _Self
operator+(size_t a
) { _Self out
= *this; out
._i
+= a
; return out
; }
1426 _Self
operator-(size_t a
) { assert(_i
>= a
); _Self out
= *this; out
._i
-= a
; return out
; }
1428 size_t operator-(const _Self
& other
) const { return _i
- other
._i
; }
1430 bool operator==(const _Self
& other
) const {
1431 assert(_addressSpace
== other
._addressSpace
);
1432 assert(_sects
== other
._sects
);
1433 return _i
== other
._i
;
1436 bool operator!=(const _Self
& other
) const {
1437 assert(_addressSpace
== other
._addressSpace
);
1438 assert(_sects
== other
._sects
);
1439 return _i
!= other
._i
;
1442 typename
A::pint_t
operator*() const { return functionAddress(); }
1444 typename
A::pint_t
functionAddress() const {
1445 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1446 EHABIIndexEntry
, _i
, functionOffset
);
1447 return indexAddr
+ signExtendPrel31(_addressSpace
->get32(indexAddr
));
1450 typename
A::pint_t
dataAddress() {
1451 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1452 EHABIIndexEntry
, _i
, data
);
1459 const UnwindInfoSections
* _sects
;
1464 template <typename A
>
1465 EHABISectionIterator
<A
> EHABISectionUpperBound(
1466 EHABISectionIterator
<A
> first
,
1467 EHABISectionIterator
<A
> last
,
1468 typename
A::pint_t value
) {
1469 size_t len
= last
- first
;
1471 size_t l2
= len
/ 2;
1472 EHABISectionIterator
<A
> m
= first
+ l2
;
1485 template <typename A
, typename R
>
1486 bool UnwindCursor
<A
, R
>::getInfoFromEHABISection(
1488 const UnwindInfoSections
§s
) {
1489 EHABISectionIterator
<A
> begin
=
1490 EHABISectionIterator
<A
>::begin(_addressSpace
, sects
);
1491 EHABISectionIterator
<A
> end
=
1492 EHABISectionIterator
<A
>::end(_addressSpace
, sects
);
1496 EHABISectionIterator
<A
> itNextPC
= EHABISectionUpperBound(begin
, end
, pc
);
1497 if (itNextPC
== begin
)
1499 EHABISectionIterator
<A
> itThisPC
= itNextPC
- 1;
1501 pint_t thisPC
= itThisPC
.functionAddress();
1502 // If an exception is thrown from a function, corresponding to the last entry
1503 // in the table, we don't really know the function extent and have to choose a
1504 // value for nextPC. Choosing max() will allow the range check during trace to
1506 pint_t nextPC
= (itNextPC
== end
) ? UINTPTR_MAX
: itNextPC
.functionAddress();
1507 pint_t indexDataAddr
= itThisPC
.dataAddress();
1509 if (indexDataAddr
== 0)
1512 uint32_t indexData
= _addressSpace
.get32(indexDataAddr
);
1513 if (indexData
== UNW_EXIDX_CANTUNWIND
)
1516 // If the high bit is set, the exception handling table entry is inline inside
1517 // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1518 // the table points at an offset in the exception handling table (section 5
1520 pint_t exceptionTableAddr
;
1521 uint32_t exceptionTableData
;
1522 bool isSingleWordEHT
;
1523 if (indexData
& 0x80000000) {
1524 exceptionTableAddr
= indexDataAddr
;
1525 // TODO(ajwong): Should this data be 0?
1526 exceptionTableData
= indexData
;
1527 isSingleWordEHT
= true;
1529 exceptionTableAddr
= indexDataAddr
+ signExtendPrel31(indexData
);
1530 exceptionTableData
= _addressSpace
.get32(exceptionTableAddr
);
1531 isSingleWordEHT
= false;
1534 // Now we know the 3 things:
1535 // exceptionTableAddr -- exception handler table entry.
1536 // exceptionTableData -- the data inside the first word of the eht entry.
1537 // isSingleWordEHT -- whether the entry is in the index.
1538 unw_word_t personalityRoutine
= 0xbadf00d;
1539 bool scope32
= false;
1542 // If the high bit in the exception handling table entry is set, the entry is
1543 // in compact form (section 6.3 EHABI).
1544 if (exceptionTableData
& 0x80000000) {
1545 // Grab the index of the personality routine from the compact form.
1546 uint32_t choice
= (exceptionTableData
& 0x0f000000) >> 24;
1547 uint32_t extraWords
= 0;
1550 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr0
;
1553 lsda
= isSingleWordEHT
? 0 : (exceptionTableAddr
+ 4);
1556 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr1
;
1557 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1559 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1562 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr2
;
1563 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1565 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1568 _LIBUNWIND_ABORT("unknown personality routine");
1572 if (isSingleWordEHT
) {
1573 if (extraWords
!= 0) {
1574 _LIBUNWIND_ABORT("index inlined table detected but pr function "
1575 "requires extra words");
1580 pint_t personalityAddr
=
1581 exceptionTableAddr
+ signExtendPrel31(exceptionTableData
);
1582 personalityRoutine
= personalityAddr
;
1584 // ARM EHABI # 6.2, # 9.2
1588 // +--------------------------------------+
1589 // | +--------+--------+--------+-------+ |
1590 // | |0| prel31 to personalityRoutine | |
1591 // | +--------+--------+--------+-------+ |
1592 // | | N | unwind opcodes | | <-- UnwindData
1593 // | +--------+--------+--------+-------+ |
1594 // | | Word 2 unwind opcodes | |
1595 // | +--------+--------+--------+-------+ |
1597 // | +--------+--------+--------+-------+ |
1598 // | | Word N unwind opcodes | |
1599 // | +--------+--------+--------+-------+ |
1600 // | | LSDA | | <-- lsda
1602 // | +--------+--------+--------+-------+ |
1603 // +--------------------------------------+
1605 uint32_t *UnwindData
= reinterpret_cast<uint32_t*>(exceptionTableAddr
) + 1;
1606 uint32_t FirstDataWord
= *UnwindData
;
1607 size_t N
= ((FirstDataWord
>> 24) & 0xff);
1608 size_t NDataWords
= N
+ 1;
1609 lsda
= reinterpret_cast<uintptr_t>(UnwindData
+ NDataWords
);
1612 _info
.start_ip
= thisPC
;
1613 _info
.end_ip
= nextPC
;
1614 _info
.handler
= personalityRoutine
;
1615 _info
.unwind_info
= exceptionTableAddr
;
1617 // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1618 _info
.flags
= (isSingleWordEHT
? 1 : 0) | (scope32
? 0x2 : 0); // Use enum?
1624 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1625 template <typename A
, typename R
>
1626 bool UnwindCursor
<A
, R
>::getInfoFromFdeCie(
1627 const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
1628 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
, pint_t pc
,
1629 uintptr_t dso_base
) {
1630 typename CFI_Parser
<A
>::PrologInfo prolog
;
1631 if (CFI_Parser
<A
>::parseFDEInstructions(_addressSpace
, fdeInfo
, cieInfo
, pc
,
1632 R::getArch(), &prolog
)) {
1633 // Save off parsed FDE info
1634 _info
.start_ip
= fdeInfo
.pcStart
;
1635 _info
.end_ip
= fdeInfo
.pcEnd
;
1636 _info
.lsda
= fdeInfo
.lsda
;
1637 _info
.handler
= cieInfo
.personality
;
1638 // Some frameless functions need SP altered when resuming in function, so
1639 // propagate spExtraArgSize.
1640 _info
.gp
= prolog
.spExtraArgSize
;
1642 _info
.format
= dwarfEncoding();
1643 _info
.unwind_info
= fdeInfo
.fdeStart
;
1644 _info
.unwind_info_size
= static_cast<uint32_t>(fdeInfo
.fdeLength
);
1645 _info
.extra
= static_cast<unw_word_t
>(dso_base
);
1651 template <typename A
, typename R
>
1652 bool UnwindCursor
<A
, R
>::getInfoFromDwarfSection(pint_t pc
,
1653 const UnwindInfoSections
§s
,
1654 uint32_t fdeSectionOffsetHint
) {
1655 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
1656 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
1657 bool foundFDE
= false;
1658 bool foundInCache
= false;
1659 // If compact encoding table gave offset into dwarf section, go directly there
1660 if (fdeSectionOffsetHint
!= 0) {
1661 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1662 sects
.dwarf_section_length
,
1663 sects
.dwarf_section
+ fdeSectionOffsetHint
,
1664 &fdeInfo
, &cieInfo
);
1666 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1667 if (!foundFDE
&& (sects
.dwarf_index_section
!= 0)) {
1668 foundFDE
= EHHeaderParser
<A
>::findFDE(
1669 _addressSpace
, pc
, sects
.dwarf_index_section
,
1670 (uint32_t)sects
.dwarf_index_section_length
, &fdeInfo
, &cieInfo
);
1674 // otherwise, search cache of previously found FDEs.
1675 pint_t cachedFDE
= DwarfFDECache
<A
>::findFDE(sects
.dso_base
, pc
);
1676 if (cachedFDE
!= 0) {
1678 CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1679 sects
.dwarf_section_length
,
1680 cachedFDE
, &fdeInfo
, &cieInfo
);
1681 foundInCache
= foundFDE
;
1685 // Still not found, do full scan of __eh_frame section.
1686 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1687 sects
.dwarf_section_length
, 0,
1688 &fdeInfo
, &cieInfo
);
1691 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, sects
.dso_base
)) {
1692 // Add to cache (to make next lookup faster) if we had no hint
1693 // and there was no index.
1694 if (!foundInCache
&& (fdeSectionOffsetHint
== 0)) {
1695 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1696 if (sects
.dwarf_index_section
== 0)
1698 DwarfFDECache
<A
>::add(sects
.dso_base
, fdeInfo
.pcStart
, fdeInfo
.pcEnd
,
1704 //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1707 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1710 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1711 template <typename A
, typename R
>
1712 bool UnwindCursor
<A
, R
>::getInfoFromCompactEncodingSection(pint_t pc
,
1713 const UnwindInfoSections
§s
) {
1714 const bool log
= false;
1716 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1717 (uint64_t)pc
, (uint64_t)sects
.dso_base
);
1719 const UnwindSectionHeader
<A
> sectionHeader(_addressSpace
,
1720 sects
.compact_unwind_section
);
1721 if (sectionHeader
.version() != UNWIND_SECTION_VERSION
)
1724 // do a binary search of top level index to find page with unwind info
1725 pint_t targetFunctionOffset
= pc
- sects
.dso_base
;
1726 const UnwindSectionIndexArray
<A
> topIndex(_addressSpace
,
1727 sects
.compact_unwind_section
1728 + sectionHeader
.indexSectionOffset());
1730 uint32_t high
= sectionHeader
.indexCount();
1731 uint32_t last
= high
- 1;
1732 while (low
< high
) {
1733 uint32_t mid
= (low
+ high
) / 2;
1734 //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1735 //mid, low, high, topIndex.functionOffset(mid));
1736 if (topIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1737 if ((mid
== last
) ||
1738 (topIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
)) {
1748 const uint32_t firstLevelFunctionOffset
= topIndex
.functionOffset(low
);
1749 const uint32_t firstLevelNextPageFunctionOffset
=
1750 topIndex
.functionOffset(low
+ 1);
1751 const pint_t secondLevelAddr
=
1752 sects
.compact_unwind_section
+ topIndex
.secondLevelPagesSectionOffset(low
);
1753 const pint_t lsdaArrayStartAddr
=
1754 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
);
1755 const pint_t lsdaArrayEndAddr
=
1756 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
+1);
1758 fprintf(stderr
, "\tfirst level search for result index=%d "
1759 "to secondLevelAddr=0x%llX\n",
1760 low
, (uint64_t) secondLevelAddr
);
1761 // do a binary search of second level page index
1762 uint32_t encoding
= 0;
1763 pint_t funcStart
= 0;
1766 pint_t personality
= 0;
1767 uint32_t pageKind
= _addressSpace
.get32(secondLevelAddr
);
1768 if (pageKind
== UNWIND_SECOND_LEVEL_REGULAR
) {
1770 UnwindSectionRegularPageHeader
<A
> pageHeader(_addressSpace
,
1772 UnwindSectionRegularArray
<A
> pageIndex(
1773 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1774 // binary search looks for entry with e where index[e].offset <= pc <
1775 // index[e+1].offset
1777 fprintf(stderr
, "\tbinary search for targetFunctionOffset=0x%08llX in "
1778 "regular page starting at secondLevelAddr=0x%llX\n",
1779 (uint64_t) targetFunctionOffset
, (uint64_t) secondLevelAddr
);
1781 high
= pageHeader
.entryCount();
1782 while (low
< high
) {
1783 uint32_t mid
= (low
+ high
) / 2;
1784 if (pageIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1785 if (mid
== (uint32_t)(pageHeader
.entryCount() - 1)) {
1788 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1790 } else if (pageIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
) {
1791 // next is too big, so we found it
1793 funcEnd
= pageIndex
.functionOffset(low
+ 1) + sects
.dso_base
;
1802 encoding
= pageIndex
.encoding(low
);
1803 funcStart
= pageIndex
.functionOffset(low
) + sects
.dso_base
;
1804 if (pc
< funcStart
) {
1808 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1809 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1816 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1817 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1820 } else if (pageKind
== UNWIND_SECOND_LEVEL_COMPRESSED
) {
1822 UnwindSectionCompressedPageHeader
<A
> pageHeader(_addressSpace
,
1824 UnwindSectionCompressedArray
<A
> pageIndex(
1825 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1826 const uint32_t targetFunctionPageOffset
=
1827 (uint32_t)(targetFunctionOffset
- firstLevelFunctionOffset
);
1828 // binary search looks for entry with e where index[e].offset <= pc <
1829 // index[e+1].offset
1831 fprintf(stderr
, "\tbinary search of compressed page starting at "
1832 "secondLevelAddr=0x%llX\n",
1833 (uint64_t) secondLevelAddr
);
1835 last
= pageHeader
.entryCount() - 1;
1836 high
= pageHeader
.entryCount();
1837 while (low
< high
) {
1838 uint32_t mid
= (low
+ high
) / 2;
1839 if (pageIndex
.functionOffset(mid
) <= targetFunctionPageOffset
) {
1840 if ((mid
== last
) ||
1841 (pageIndex
.functionOffset(mid
+ 1) > targetFunctionPageOffset
)) {
1851 funcStart
= pageIndex
.functionOffset(low
) + firstLevelFunctionOffset
1855 pageIndex
.functionOffset(low
+ 1) + firstLevelFunctionOffset
1858 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1859 if (pc
< funcStart
) {
1860 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1861 "not in second level compressed unwind table. "
1863 (uint64_t) pc
, (uint64_t) funcStart
);
1867 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1868 "not in second level compressed unwind table. "
1870 (uint64_t) pc
, (uint64_t) funcEnd
);
1873 uint16_t encodingIndex
= pageIndex
.encodingIndex(low
);
1874 if (encodingIndex
< sectionHeader
.commonEncodingsArrayCount()) {
1875 // encoding is in common table in section header
1876 encoding
= _addressSpace
.get32(
1877 sects
.compact_unwind_section
+
1878 sectionHeader
.commonEncodingsArraySectionOffset() +
1879 encodingIndex
* sizeof(uint32_t));
1881 // encoding is in page specific table
1882 uint16_t pageEncodingIndex
=
1883 encodingIndex
- (uint16_t)sectionHeader
.commonEncodingsArrayCount();
1884 encoding
= _addressSpace
.get32(secondLevelAddr
+
1885 pageHeader
.encodingsPageOffset() +
1886 pageEncodingIndex
* sizeof(uint32_t));
1889 _LIBUNWIND_DEBUG_LOG(
1890 "malformed __unwind_info at 0x%0llX bad second level page",
1891 (uint64_t)sects
.compact_unwind_section
);
1895 // look up LSDA, if encoding says function has one
1896 if (encoding
& UNWIND_HAS_LSDA
) {
1897 UnwindSectionLsdaArray
<A
> lsdaIndex(_addressSpace
, lsdaArrayStartAddr
);
1898 uint32_t funcStartOffset
= (uint32_t)(funcStart
- sects
.dso_base
);
1900 high
= (uint32_t)(lsdaArrayEndAddr
- lsdaArrayStartAddr
) /
1901 sizeof(unwind_info_section_header_lsda_index_entry
);
1902 // binary search looks for entry with exact match for functionOffset
1905 "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1907 while (low
< high
) {
1908 uint32_t mid
= (low
+ high
) / 2;
1909 if (lsdaIndex
.functionOffset(mid
) == funcStartOffset
) {
1910 lsda
= lsdaIndex
.lsdaOffset(mid
) + sects
.dso_base
;
1912 } else if (lsdaIndex
.functionOffset(mid
) < funcStartOffset
) {
1919 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1920 "pc=0x%0llX, but lsda table has no entry",
1921 encoding
, (uint64_t) pc
);
1926 // extract personality routine, if encoding says function has one
1927 uint32_t personalityIndex
= (encoding
& UNWIND_PERSONALITY_MASK
) >>
1928 (__builtin_ctz(UNWIND_PERSONALITY_MASK
));
1929 if (personalityIndex
!= 0) {
1930 --personalityIndex
; // change 1-based to zero-based index
1931 if (personalityIndex
>= sectionHeader
.personalityArrayCount()) {
1932 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
1933 "but personality table has only %d entries",
1934 encoding
, personalityIndex
,
1935 sectionHeader
.personalityArrayCount());
1938 int32_t personalityDelta
= (int32_t)_addressSpace
.get32(
1939 sects
.compact_unwind_section
+
1940 sectionHeader
.personalityArraySectionOffset() +
1941 personalityIndex
* sizeof(uint32_t));
1942 pint_t personalityPointer
= sects
.dso_base
+ (pint_t
)personalityDelta
;
1943 personality
= _addressSpace
.getP(personalityPointer
);
1945 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1946 "personalityDelta=0x%08X, personality=0x%08llX\n",
1947 (uint64_t) pc
, personalityDelta
, (uint64_t) personality
);
1951 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1952 "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1953 (uint64_t) pc
, encoding
, (uint64_t) lsda
, (uint64_t) funcStart
);
1954 _info
.start_ip
= funcStart
;
1955 _info
.end_ip
= funcEnd
;
1957 _info
.handler
= personality
;
1960 _info
.format
= encoding
;
1961 _info
.unwind_info
= 0;
1962 _info
.unwind_info_size
= 0;
1963 _info
.extra
= sects
.dso_base
;
1966 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1969 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1970 template <typename A
, typename R
>
1971 bool UnwindCursor
<A
, R
>::getInfoFromSEH(pint_t pc
) {
1973 RUNTIME_FUNCTION
*unwindEntry
= lookUpSEHUnwindInfo(pc
, &base
);
1975 _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc
);
1981 _info
.unwind_info_size
= sizeof(RUNTIME_FUNCTION
);
1982 _info
.unwind_info
= reinterpret_cast<unw_word_t
>(unwindEntry
);
1984 _info
.start_ip
= base
+ unwindEntry
->BeginAddress
;
1985 #ifdef _LIBUNWIND_TARGET_X86_64
1986 _info
.end_ip
= base
+ unwindEntry
->EndAddress
;
1987 // Only fill in the handler and LSDA if they're stale.
1988 if (pc
!= getLastPC()) {
1989 UNWIND_INFO
*xdata
= reinterpret_cast<UNWIND_INFO
*>(base
+ unwindEntry
->UnwindData
);
1990 if (xdata
->Flags
& (UNW_FLAG_EHANDLER
|UNW_FLAG_UHANDLER
)) {
1991 // The personality is given in the UNWIND_INFO itself. The LSDA immediately
1992 // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
1993 // these structures.)
1994 // N.B. UNWIND_INFO structs are DWORD-aligned.
1995 uint32_t lastcode
= (xdata
->CountOfCodes
+ 1) & ~1;
1996 const uint32_t *handler
= reinterpret_cast<uint32_t *>(&xdata
->UnwindCodes
[lastcode
]);
1997 _info
.lsda
= reinterpret_cast<unw_word_t
>(handler
+1);
1998 _dispContext
.HandlerData
= reinterpret_cast<void *>(_info
.lsda
);
1999 _dispContext
.LanguageHandler
=
2000 reinterpret_cast<EXCEPTION_ROUTINE
*>(base
+ *handler
);
2002 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
2016 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2017 // Masks for traceback table field xtbtable.
2018 enum xTBTableMask
: uint8_t {
2019 reservedBit
= 0x02, // The traceback table was incorrectly generated if set
2020 // (see comments in function getInfoFromTBTable().
2021 ehInfoBit
= 0x08 // Exception handling info is present if set
2024 enum frameType
: unw_word_t
{
2025 frameWithXLEHStateTable
= 0,
2030 typedef _Unwind_Reason_Code
__xlcxx_personality_v0_t(int, _Unwind_Action
,
2032 _Unwind_Exception
*,
2033 struct _Unwind_Context
*);
2034 __attribute__((__weak__
)) __xlcxx_personality_v0_t __xlcxx_personality_v0
;
2037 static __xlcxx_personality_v0_t
*xlcPersonalityV0
;
2038 static RWMutex xlcPersonalityV0InitLock
;
2040 template <typename A
, typename R
>
2041 bool UnwindCursor
<A
, R
>::getInfoFromTBTable(pint_t pc
, R
®isters
) {
2042 uint32_t *p
= reinterpret_cast<uint32_t *>(pc
);
2044 // Keep looking forward until a word of 0 is found. The traceback
2045 // table starts at the following word.
2048 tbtable
*TBTable
= reinterpret_cast<tbtable
*>(p
+ 1);
2050 if (_LIBUNWIND_TRACING_UNWINDING
) {
2051 char functionBuf
[512];
2052 const char *functionName
= functionBuf
;
2054 if (!getFunctionName(functionBuf
, sizeof(functionBuf
), &offset
)) {
2055 functionName
= ".anonymous.";
2057 _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
2058 __func__
, functionName
,
2059 reinterpret_cast<void *>(TBTable
));
2062 // If the traceback table does not contain necessary info, bypass this frame.
2063 if (!TBTable
->tb
.has_tboff
)
2066 // Structure tbtable_ext contains important data we are looking for.
2067 p
= reinterpret_cast<uint32_t *>(&TBTable
->tb_ext
);
2069 // Skip field parminfo if it exists.
2070 if (TBTable
->tb
.fixedparms
|| TBTable
->tb
.floatparms
)
2073 // p now points to tb_offset, the offset from start of function to TB table.
2074 unw_word_t start_ip
=
2075 reinterpret_cast<unw_word_t
>(TBTable
) - *p
- sizeof(uint32_t);
2076 unw_word_t end_ip
= reinterpret_cast<unw_word_t
>(TBTable
);
2079 _LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",
2080 reinterpret_cast<void *>(start_ip
),
2081 reinterpret_cast<void *>(end_ip
));
2083 // Skip field hand_mask if it exists.
2084 if (TBTable
->tb
.int_hndl
)
2087 unw_word_t lsda
= 0;
2088 unw_word_t handler
= 0;
2089 unw_word_t flags
= frameType::frameWithXLEHStateTable
;
2091 if (TBTable
->tb
.lang
== TB_CPLUSPLUS
&& TBTable
->tb
.has_ctl
) {
2092 // State table info is available. The ctl_info field indicates the
2093 // number of CTL anchors. There should be only one entry for the C++
2095 assert(*p
== 1 && "libunwind: there must be only one ctl_info entry");
2097 // p points to the offset of the state table into the stack.
2098 pint_t stateTableOffset
= *p
++;
2100 int framePointerReg
;
2102 // Skip fields name_len and name if exist.
2103 if (TBTable
->tb
.name_present
) {
2104 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(p
));
2105 p
= reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p
) + name_len
+
2109 if (TBTable
->tb
.uses_alloca
)
2110 framePointerReg
= *(reinterpret_cast<char *>(p
));
2112 framePointerReg
= 1; // default frame pointer == SP
2114 _LIBUNWIND_TRACE_UNWINDING(
2115 "framePointerReg=%d, framePointer=%p, "
2116 "stateTableOffset=%#lx\n",
2118 reinterpret_cast<void *>(_registers
.getRegister(framePointerReg
)),
2120 lsda
= _registers
.getRegister(framePointerReg
) + stateTableOffset
;
2122 // Since the traceback table generated by the legacy XLC++ does not
2123 // provide the location of the personality for the state table,
2124 // function __xlcxx_personality_v0(), which is the personality for the state
2125 // table and is exported from libc++abi, is directly assigned as the
2126 // handler here. When a legacy XLC++ frame is encountered, the symbol
2127 // is resolved dynamically using dlopen() to avoid hard dependency from
2128 // libunwind on libc++abi.
2130 // Resolve the function pointer to the state table personality if it has
2132 if (xlcPersonalityV0
== NULL
) {
2133 xlcPersonalityV0InitLock
.lock();
2134 if (xlcPersonalityV0
== NULL
) {
2135 // If libc++abi is statically linked in, symbol __xlcxx_personality_v0
2136 // has been resolved at the link time.
2137 xlcPersonalityV0
= &__xlcxx_personality_v0
;
2138 if (xlcPersonalityV0
== NULL
) {
2139 // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0
2141 const char libcxxabi
[] = "libc++abi.a(libc++abi.so.1)";
2143 // The AIX dlopen() sets errno to 0 when it is successful, which
2144 // clobbers the value of errno from the user code. This is an AIX
2145 // bug because according to POSIX it should not set errno to 0. To
2146 // workaround before AIX fixes the bug, errno is saved and restored.
2147 int saveErrno
= errno
;
2148 libHandle
= dlopen(libcxxabi
, RTLD_MEMBER
| RTLD_NOW
);
2149 if (libHandle
== NULL
) {
2150 _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
2152 assert(0 && "dlopen() failed");
2154 xlcPersonalityV0
= reinterpret_cast<__xlcxx_personality_v0_t
*>(
2155 dlsym(libHandle
, "__xlcxx_personality_v0"));
2156 if (xlcPersonalityV0
== NULL
) {
2157 _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno
);
2158 assert(0 && "dlsym() failed");
2164 xlcPersonalityV0InitLock
.unlock();
2166 handler
= reinterpret_cast<unw_word_t
>(xlcPersonalityV0
);
2167 _LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",
2168 reinterpret_cast<void *>(lsda
),
2169 reinterpret_cast<void *>(handler
));
2170 } else if (TBTable
->tb
.longtbtable
) {
2171 // This frame has the traceback table extension. Possible cases are
2172 // 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that
2173 // is not EH aware; or, 3) a frame of other languages. We need to figure out
2174 // if the traceback table extension contains the 'eh_info' structure.
2176 // We also need to deal with the complexity arising from some XL compiler
2177 // versions use the wrong ordering of 'longtbtable' and 'has_vec' bits
2178 // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice
2179 // versa. For frames of code generated by those compilers, the 'longtbtable'
2180 // bit may be set but there isn't really a traceback table extension.
2182 // In </usr/include/sys/debug.h>, there is the following definition of
2183 // 'struct tbtable_ext'. It is not really a structure but a dummy to
2184 // collect the description of optional parts of the traceback table.
2186 // struct tbtable_ext {
2188 // char alloca_reg; /* Register for alloca automatic storage */
2189 // struct vec_ext vec_ext; /* Vector extension (if has_vec is set) */
2190 // unsigned char xtbtable; /* More tbtable fields, if longtbtable is set*/
2193 // Depending on how the 'has_vec'/'longtbtable' bit is interpreted, the data
2194 // following 'alloca_reg' can be treated either as 'struct vec_ext' or
2195 // 'unsigned char xtbtable'. 'xtbtable' bits are defined in
2196 // </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently
2197 // unused and should not be set. 'struct vec_ext' is defined in
2198 // </usr/include/sys/debug.h> as follows:
2201 // unsigned vr_saved:6; /* Number of non-volatile vector regs saved
2203 // /* first register saved is assumed to be */
2204 // /* 32 - vr_saved */
2205 // unsigned saves_vrsave:1; /* Set if vrsave is saved on the stack */
2206 // unsigned has_varargs:1;
2210 // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it
2211 // is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',
2212 // we checks if the 7th bit is set or not because 'xtbtable' should
2213 // never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved
2214 // in the future to make sure the mitigation works. This mitigation
2215 // is not 100% bullet proof because 'struct vec_ext' may not always have
2216 // 'saves_vrsave' bit set.
2218 // 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for
2219 // checking the 7th bit.
2221 // p points to field name len.
2222 uint8_t *charPtr
= reinterpret_cast<uint8_t *>(p
);
2224 // Skip fields name_len and name if they exist.
2225 if (TBTable
->tb
.name_present
) {
2226 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(charPtr
));
2227 charPtr
= charPtr
+ name_len
+ sizeof(uint16_t);
2230 // Skip field alloc_reg if it exists.
2231 if (TBTable
->tb
.uses_alloca
)
2234 // Check traceback table bit has_vec. Skip struct vec_ext if it exists.
2235 if (TBTable
->tb
.has_vec
)
2236 // Note struct vec_ext does exist at this point because whether the
2237 // ordering of longtbtable and has_vec bits is correct or not, both
2239 charPtr
+= sizeof(struct vec_ext
);
2241 // charPtr points to field 'xtbtable'. Check if the EH info is available.
2242 // Also check if the reserved bit of the extended traceback table field
2243 // 'xtbtable' is set. If it is, the traceback table was incorrectly
2244 // generated by an XL compiler that uses the wrong ordering of 'longtbtable'
2245 // and 'has_vec' bits and this is in fact 'struct vec_ext'. So skip the
2247 if ((*charPtr
& xTBTableMask::ehInfoBit
) &&
2248 !(*charPtr
& xTBTableMask::reservedBit
)) {
2249 // Mark this frame has the new EH info.
2250 flags
= frameType::frameWithEHInfo
;
2252 // eh_info is available.
2254 // The pointer is 4-byte aligned.
2255 if (reinterpret_cast<uintptr_t>(charPtr
) % 4)
2256 charPtr
+= 4 - reinterpret_cast<uintptr_t>(charPtr
) % 4;
2258 reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(
2259 registers
.getRegister(2) +
2260 *(reinterpret_cast<uintptr_t *>(charPtr
)))));
2262 // ehInfo points to structure en_info. The first member is version.
2263 // Only version 0 is currently supported.
2264 assert(*(reinterpret_cast<uint32_t *>(ehInfo
)) == 0 &&
2265 "libunwind: ehInfo version other than 0 is not supported");
2267 // Increment ehInfo to point to member lsda.
2271 // enInfo now points to member personality.
2274 _LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",
2279 _info
.start_ip
= start_ip
;
2280 _info
.end_ip
= end_ip
;
2282 _info
.handler
= handler
;
2284 _info
.flags
= flags
;
2286 _info
.unwind_info
= reinterpret_cast<unw_word_t
>(TBTable
);
2287 _info
.unwind_info_size
= 0;
2288 _info
.extra
= registers
.getRegister(2);
2293 // Step back up the stack following the frame back link.
2294 template <typename A
, typename R
>
2295 int UnwindCursor
<A
, R
>::stepWithTBTable(pint_t pc
, tbtable
*TBTable
,
2296 R
®isters
, bool &isSignalFrame
) {
2297 if (_LIBUNWIND_TRACING_UNWINDING
) {
2298 char functionBuf
[512];
2299 const char *functionName
= functionBuf
;
2301 if (!getFunctionName(functionBuf
, sizeof(functionBuf
), &offset
)) {
2302 functionName
= ".anonymous.";
2304 _LIBUNWIND_TRACE_UNWINDING(
2305 "%s: Look up traceback table of func=%s at %p, pc=%p, "
2306 "SP=%p, saves_lr=%d, stores_bc=%d",
2307 __func__
, functionName
, reinterpret_cast<void *>(TBTable
),
2308 reinterpret_cast<void *>(pc
),
2309 reinterpret_cast<void *>(registers
.getSP()), TBTable
->tb
.saves_lr
,
2310 TBTable
->tb
.stores_bc
);
2313 #if defined(__powerpc64__)
2314 // Instruction to reload TOC register "ld r2,40(r1)"
2315 const uint32_t loadTOCRegInst
= 0xe8410028;
2316 const int32_t unwPPCF0Index
= UNW_PPC64_F0
;
2317 const int32_t unwPPCV0Index
= UNW_PPC64_V0
;
2319 // Instruction to reload TOC register "lwz r2,20(r1)"
2320 const uint32_t loadTOCRegInst
= 0x80410014;
2321 const int32_t unwPPCF0Index
= UNW_PPC_F0
;
2322 const int32_t unwPPCV0Index
= UNW_PPC_V0
;
2325 // lastStack points to the stack frame of the next routine up.
2326 pint_t curStack
= static_cast<pint_t
>(registers
.getSP());
2327 pint_t lastStack
= *reinterpret_cast<pint_t
*>(curStack
);
2330 return UNW_STEP_END
;
2332 R newRegisters
= registers
;
2334 // If backchain is not stored, use the current stack frame.
2335 if (!TBTable
->tb
.stores_bc
)
2336 lastStack
= curStack
;
2338 // Return address is the address after call site instruction.
2339 pint_t returnAddress
;
2341 if (isSignalFrame
) {
2342 _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
2343 reinterpret_cast<void *>(lastStack
));
2345 sigcontext
*sigContext
= reinterpret_cast<sigcontext
*>(
2346 reinterpret_cast<char *>(lastStack
) + STKMINALIGN
);
2347 returnAddress
= sigContext
->sc_jmpbuf
.jmp_context
.iar
;
2349 bool useSTKMIN
= false;
2350 if (returnAddress
< 0x10000000) {
2351 // Try again using STKMIN.
2352 sigContext
= reinterpret_cast<sigcontext
*>(
2353 reinterpret_cast<char *>(lastStack
) + STKMIN
);
2354 returnAddress
= sigContext
->sc_jmpbuf
.jmp_context
.iar
;
2355 if (returnAddress
< 0x10000000) {
2356 _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
2357 reinterpret_cast<void *>(returnAddress
),
2358 reinterpret_cast<void *>(sigContext
));
2359 return UNW_EBADFRAME
;
2363 _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
2364 "sigContext=%p, returnAddress=%p. "
2365 "Seems to be a valid address",
2366 useSTKMIN
? "STKMIN" : "STKMINALIGN",
2367 reinterpret_cast<void *>(sigContext
),
2368 reinterpret_cast<void *>(returnAddress
));
2370 // Restore the condition register from sigcontext.
2371 newRegisters
.setCR(sigContext
->sc_jmpbuf
.jmp_context
.cr
);
2373 // Save the LR in sigcontext for stepping up when the function that
2374 // raised the signal is a leaf function. This LR has the return address
2375 // to the caller of the leaf function.
2376 newRegisters
.setLR(sigContext
->sc_jmpbuf
.jmp_context
.lr
);
2377 _LIBUNWIND_TRACE_UNWINDING(
2378 "Save LR=%p from sigcontext",
2379 reinterpret_cast<void *>(sigContext
->sc_jmpbuf
.jmp_context
.lr
));
2381 // Restore GPRs from sigcontext.
2382 for (int i
= 0; i
< 32; ++i
)
2383 newRegisters
.setRegister(i
, sigContext
->sc_jmpbuf
.jmp_context
.gpr
[i
]);
2385 // Restore FPRs from sigcontext.
2386 for (int i
= 0; i
< 32; ++i
)
2387 newRegisters
.setFloatRegister(i
+ unwPPCF0Index
,
2388 sigContext
->sc_jmpbuf
.jmp_context
.fpr
[i
]);
2390 // Restore vector registers if there is an associated extended context
2392 if (sigContext
->sc_jmpbuf
.jmp_context
.msr
& __EXTCTX
) {
2393 ucontext_t
*uContext
= reinterpret_cast<ucontext_t
*>(sigContext
);
2394 if (uContext
->__extctx
->__extctx_magic
== __EXTCTX_MAGIC
) {
2395 for (int i
= 0; i
< 32; ++i
)
2396 newRegisters
.setVectorRegister(
2397 i
+ unwPPCV0Index
, *(reinterpret_cast<v128
*>(
2398 &(uContext
->__extctx
->__vmx
.__vr
[i
]))));
2402 // Step up a normal frame.
2404 if (!TBTable
->tb
.saves_lr
&& registers
.getLR()) {
2405 // This case should only occur if we were called from a signal handler
2406 // and the signal occurred in a function that doesn't save the LR.
2407 returnAddress
= static_cast<pint_t
>(registers
.getLR());
2408 _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
2409 reinterpret_cast<void *>(returnAddress
));
2411 // Otherwise, use the LR value in the stack link area.
2412 returnAddress
= reinterpret_cast<pint_t
*>(lastStack
)[2];
2415 // Reset LR in the current context.
2416 newRegisters
.setLR(NULL
);
2418 _LIBUNWIND_TRACE_UNWINDING(
2419 "Extract info from lastStack=%p, returnAddress=%p",
2420 reinterpret_cast<void *>(lastStack
),
2421 reinterpret_cast<void *>(returnAddress
));
2422 _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
2423 TBTable
->tb
.fpr_saved
, TBTable
->tb
.gpr_saved
,
2424 TBTable
->tb
.saves_cr
);
2426 // Restore FP registers.
2427 char *ptrToRegs
= reinterpret_cast<char *>(lastStack
);
2428 double *FPRegs
= reinterpret_cast<double *>(
2429 ptrToRegs
- (TBTable
->tb
.fpr_saved
* sizeof(double)));
2430 for (int i
= 0; i
< TBTable
->tb
.fpr_saved
; ++i
)
2431 newRegisters
.setFloatRegister(
2432 32 - TBTable
->tb
.fpr_saved
+ i
+ unwPPCF0Index
, FPRegs
[i
]);
2434 // Restore GP registers.
2435 ptrToRegs
= reinterpret_cast<char *>(FPRegs
);
2436 uintptr_t *GPRegs
= reinterpret_cast<uintptr_t *>(
2437 ptrToRegs
- (TBTable
->tb
.gpr_saved
* sizeof(uintptr_t)));
2438 for (int i
= 0; i
< TBTable
->tb
.gpr_saved
; ++i
)
2439 newRegisters
.setRegister(32 - TBTable
->tb
.gpr_saved
+ i
, GPRegs
[i
]);
2441 // Restore Vector registers.
2442 ptrToRegs
= reinterpret_cast<char *>(GPRegs
);
2444 // Restore vector registers only if this is a Clang frame. Also
2445 // check if traceback table bit has_vec is set. If it is, structure
2446 // vec_ext is available.
2447 if (_info
.flags
== frameType::frameWithEHInfo
&& TBTable
->tb
.has_vec
) {
2449 // Get to the vec_ext structure to check if vector registers are saved.
2450 uint32_t *p
= reinterpret_cast<uint32_t *>(&TBTable
->tb_ext
);
2452 // Skip field parminfo if exists.
2453 if (TBTable
->tb
.fixedparms
|| TBTable
->tb
.floatparms
)
2456 // Skip field tb_offset if exists.
2457 if (TBTable
->tb
.has_tboff
)
2460 // Skip field hand_mask if exists.
2461 if (TBTable
->tb
.int_hndl
)
2464 // Skip fields ctl_info and ctl_info_disp if exist.
2465 if (TBTable
->tb
.has_ctl
) {
2466 // Skip field ctl_info.
2468 // Skip field ctl_info_disp.
2472 // Skip fields name_len and name if exist.
2473 // p is supposed to point to field name_len now.
2474 uint8_t *charPtr
= reinterpret_cast<uint8_t *>(p
);
2475 if (TBTable
->tb
.name_present
) {
2476 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(charPtr
));
2477 charPtr
= charPtr
+ name_len
+ sizeof(uint16_t);
2480 // Skip field alloc_reg if it exists.
2481 if (TBTable
->tb
.uses_alloca
)
2484 struct vec_ext
*vec_ext
= reinterpret_cast<struct vec_ext
*>(charPtr
);
2486 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext
->vr_saved
);
2488 // Restore vector register(s) if saved on the stack.
2489 if (vec_ext
->vr_saved
) {
2490 // Saved vector registers are 16-byte aligned.
2491 if (reinterpret_cast<uintptr_t>(ptrToRegs
) % 16)
2492 ptrToRegs
-= reinterpret_cast<uintptr_t>(ptrToRegs
) % 16;
2493 v128
*VecRegs
= reinterpret_cast<v128
*>(ptrToRegs
- vec_ext
->vr_saved
*
2495 for (int i
= 0; i
< vec_ext
->vr_saved
; ++i
) {
2496 newRegisters
.setVectorRegister(
2497 32 - vec_ext
->vr_saved
+ i
+ unwPPCV0Index
, VecRegs
[i
]);
2501 if (TBTable
->tb
.saves_cr
) {
2502 // Get the saved condition register. The condition register is only
2505 *(reinterpret_cast<uint32_t *>(lastStack
+ sizeof(uintptr_t))));
2509 newRegisters
.setSP(lastStack
);
2511 // The first instruction after return.
2512 uint32_t firstInstruction
= *(reinterpret_cast<uint32_t *>(returnAddress
));
2514 // Do we need to set the TOC register?
2515 _LIBUNWIND_TRACE_UNWINDING(
2517 reinterpret_cast<void *>(newRegisters
.getRegister(2)));
2518 if (firstInstruction
== loadTOCRegInst
) {
2519 _LIBUNWIND_TRACE_UNWINDING(
2520 "Set gpr2=%p from frame",
2521 reinterpret_cast<void *>(reinterpret_cast<pint_t
*>(lastStack
)[5]));
2522 newRegisters
.setRegister(2, reinterpret_cast<pint_t
*>(lastStack
)[5]);
2525 _LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",
2526 reinterpret_cast<void *>(lastStack
),
2527 reinterpret_cast<void *>(returnAddress
),
2528 reinterpret_cast<void *>(pc
));
2530 // The return address is the address after call site instruction, so
2531 // setting IP to that simulates a return.
2532 newRegisters
.setIP(reinterpret_cast<uintptr_t>(returnAddress
));
2534 // Simulate the step by replacing the register set with the new ones.
2535 registers
= newRegisters
;
2537 // Check if the next frame is a signal frame.
2538 pint_t nextStack
= *(reinterpret_cast<pint_t
*>(registers
.getSP()));
2540 // Return address is the address after call site instruction.
2541 pint_t nextReturnAddress
= reinterpret_cast<pint_t
*>(nextStack
)[2];
2543 if (nextReturnAddress
> 0x01 && nextReturnAddress
< 0x10000) {
2544 _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
2545 "nextStack=%p, next return address=%p\n",
2546 reinterpret_cast<void *>(nextStack
),
2547 reinterpret_cast<void *>(nextReturnAddress
));
2548 isSignalFrame
= true;
2550 isSignalFrame
= false;
2552 return UNW_STEP_SUCCESS
;
2554 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2556 template <typename A
, typename R
>
2557 void UnwindCursor
<A
, R
>::setInfoBasedOnIPRegister(bool isReturnAddress
) {
2558 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2559 _isSigReturn
= false;
2562 pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2563 #if defined(_LIBUNWIND_ARM_EHABI)
2564 // Remove the thumb bit so the IP represents the actual instruction address.
2565 // This matches the behaviour of _Unwind_GetIP on arm.
2569 // Exit early if at the top of the stack.
2571 _unwindInfoMissing
= true;
2575 // If the last line of a function is a "throw" the compiler sometimes
2576 // emits no instructions after the call to __cxa_throw. This means
2577 // the return address is actually the start of the next function.
2578 // To disambiguate this, back up the pc when we know it is a return
2580 if (isReturnAddress
)
2582 // PC needs to be a 4-byte aligned address to be able to look for a
2583 // word of 0 that indicates the start of the traceback table at the end
2584 // of a function on AIX.
2590 // Ask address space object to find unwind sections for this pc.
2591 UnwindInfoSections sects
;
2592 if (_addressSpace
.findUnwindSections(pc
, sects
)) {
2593 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2594 // If there is a compact unwind encoding table, look there first.
2595 if (sects
.compact_unwind_section
!= 0) {
2596 if (this->getInfoFromCompactEncodingSection(pc
, sects
)) {
2597 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2598 // Found info in table, done unless encoding says to use dwarf.
2599 uint32_t dwarfOffset
;
2600 if ((sects
.dwarf_section
!= 0) && compactSaysUseDwarf(&dwarfOffset
)) {
2601 if (this->getInfoFromDwarfSection(pc
, sects
, dwarfOffset
)) {
2602 // found info in dwarf, done
2607 // If unwind table has entry, but entry says there is no unwind info,
2608 // record that we have no unwind info.
2609 if (_info
.format
== 0)
2610 _unwindInfoMissing
= true;
2614 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2616 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2617 // If there is SEH unwind info, look there next.
2618 if (this->getInfoFromSEH(pc
))
2622 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2623 // If there is unwind info in the traceback table, look there next.
2624 if (this->getInfoFromTBTable(pc
, _registers
))
2628 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2629 // If there is dwarf unwind info, look there next.
2630 if (sects
.dwarf_section
!= 0) {
2631 if (this->getInfoFromDwarfSection(pc
, sects
)) {
2632 // found info in dwarf, done
2638 #if defined(_LIBUNWIND_ARM_EHABI)
2639 // If there is ARM EHABI unwind info, look there next.
2640 if (sects
.arm_section
!= 0 && this->getInfoFromEHABISection(pc
, sects
))
2645 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2646 // There is no static unwind info for this pc. Look to see if an FDE was
2647 // dynamically registered for it.
2648 pint_t cachedFDE
= DwarfFDECache
<A
>::findFDE(DwarfFDECache
<A
>::kSearchAll
,
2650 if (cachedFDE
!= 0) {
2651 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
2652 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
2653 if (!CFI_Parser
<A
>::decodeFDE(_addressSpace
, cachedFDE
, &fdeInfo
, &cieInfo
))
2654 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, 0))
2658 // Lastly, ask AddressSpace object about platform specific ways to locate
2661 if (_addressSpace
.findOtherFDE(pc
, fde
)) {
2662 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
2663 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
2664 if (!CFI_Parser
<A
>::decodeFDE(_addressSpace
, fde
, &fdeInfo
, &cieInfo
)) {
2665 // Double check this FDE is for a function that includes the pc.
2666 if ((fdeInfo
.pcStart
<= pc
) && (pc
< fdeInfo
.pcEnd
))
2667 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, 0))
2671 #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2673 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2674 if (setInfoForSigReturn())
2678 // no unwind info, flag that we can't reliably unwind
2679 _unwindInfoMissing
= true;
2682 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2683 defined(_LIBUNWIND_TARGET_AARCH64)
2684 template <typename A
, typename R
>
2685 bool UnwindCursor
<A
, R
>::setInfoForSigReturn(Registers_arm64
&) {
2686 // Look for the sigreturn trampoline. The trampoline's body is two
2687 // specific instructions (see below). Typically the trampoline comes from the
2688 // vDSO[1] (i.e. the __kernel_rt_sigreturn function). A libc might provide its
2689 // own restorer function, though, or user-mode QEMU might write a trampoline
2692 // This special code path is a fallback that is only used if the trampoline
2693 // lacks proper (e.g. DWARF) unwind info. On AArch64, a new DWARF register
2694 // constant for the PC needs to be defined before DWARF can handle a signal
2695 // trampoline. This code may segfault if the target PC is unreadable, e.g.:
2696 // - The PC points at a function compiled without unwind info, and which is
2697 // part of an execute-only mapping (e.g. using -Wl,--execute-only).
2698 // - The PC is invalid and happens to point to unreadable or unmapped memory.
2700 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
2701 const pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2702 // The PC might contain an invalid address if the unwind info is bad, so
2703 // directly accessing it could cause a segfault. Use process_vm_readv to read
2704 // the memory safely instead. process_vm_readv was added in Linux 3.2, and
2705 // AArch64 supported was added in Linux 3.7, so the syscall is guaranteed to
2706 // be present. Unfortunately, there are Linux AArch64 environments where the
2707 // libc wrapper for the syscall might not be present (e.g. Android 5), so call
2708 // the syscall directly instead.
2709 uint32_t instructions
[2];
2710 struct iovec local_iov
= {&instructions
, sizeof instructions
};
2711 struct iovec remote_iov
= {reinterpret_cast<void *>(pc
), sizeof instructions
};
2713 syscall(SYS_process_vm_readv
, getpid(), &local_iov
, 1, &remote_iov
, 1, 0);
2714 // Look for instructions: mov x8, #0x8b; svc #0x0
2715 if (bytesRead
!= sizeof instructions
|| instructions
[0] != 0xd2801168 ||
2716 instructions
[1] != 0xd4000001)
2720 _info
.start_ip
= pc
;
2721 _info
.end_ip
= pc
+ 4;
2722 _isSigReturn
= true;
2726 template <typename A
, typename R
>
2727 int UnwindCursor
<A
, R
>::stepThroughSigReturn(Registers_arm64
&) {
2728 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2729 // - 128-byte siginfo struct
2730 // - ucontext struct:
2731 // - 8-byte long (uc_flags)
2732 // - 8-byte pointer (uc_link)
2733 // - 24-byte stack_t
2734 // - 128-byte signal set
2735 // - 8 bytes of padding because sigcontext has 16-byte alignment
2736 // - sigcontext/mcontext_t
2737 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c
2738 const pint_t kOffsetSpToSigcontext
= (128 + 8 + 8 + 24 + 128 + 8); // 304
2740 // Offsets from sigcontext to each register.
2741 const pint_t kOffsetGprs
= 8; // offset to "__u64 regs[31]" field
2742 const pint_t kOffsetSp
= 256; // offset to "__u64 sp" field
2743 const pint_t kOffsetPc
= 264; // offset to "__u64 pc" field
2745 pint_t sigctx
= _registers
.getSP() + kOffsetSpToSigcontext
;
2747 for (int i
= 0; i
<= 30; ++i
) {
2748 uint64_t value
= _addressSpace
.get64(sigctx
+ kOffsetGprs
+
2749 static_cast<pint_t
>(i
* 8));
2750 _registers
.setRegister(UNW_AARCH64_X0
+ i
, value
);
2752 _registers
.setSP(_addressSpace
.get64(sigctx
+ kOffsetSp
));
2753 _registers
.setIP(_addressSpace
.get64(sigctx
+ kOffsetPc
));
2754 _isSignalFrame
= true;
2755 return UNW_STEP_SUCCESS
;
2757 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2758 // defined(_LIBUNWIND_TARGET_AARCH64)
2760 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2761 defined(_LIBUNWIND_TARGET_RISCV)
2762 template <typename A
, typename R
>
2763 bool UnwindCursor
<A
, R
>::setInfoForSigReturn(Registers_riscv
&) {
2764 const pint_t pc
= static_cast<pint_t
>(getReg(UNW_REG_IP
));
2765 uint32_t instructions
[2];
2766 struct iovec local_iov
= {&instructions
, sizeof instructions
};
2767 struct iovec remote_iov
= {reinterpret_cast<void *>(pc
), sizeof instructions
};
2769 syscall(SYS_process_vm_readv
, getpid(), &local_iov
, 1, &remote_iov
, 1, 0);
2770 // Look for the two instructions used in the sigreturn trampoline
2771 // __vdso_rt_sigreturn:
2773 // 0x08b00893 li a7,0x8b
2775 if (bytesRead
!= sizeof instructions
|| instructions
[0] != 0x08b00893 ||
2776 instructions
[1] != 0x00000073)
2780 _info
.start_ip
= pc
;
2781 _info
.end_ip
= pc
+ 4;
2782 _isSigReturn
= true;
2786 template <typename A
, typename R
>
2787 int UnwindCursor
<A
, R
>::stepThroughSigReturn(Registers_riscv
&) {
2788 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2789 // - 128-byte siginfo struct
2790 // - ucontext_t struct:
2791 // - 8-byte long (__uc_flags)
2792 // - 8-byte pointer (*uc_link)
2793 // - 24-byte uc_stack
2794 // - 8-byte uc_sigmask
2795 // - 120-byte of padding to allow sigset_t to be expanded in the future
2796 // - 8 bytes of padding because sigcontext has 16-byte alignment
2797 // - struct sigcontext uc_mcontext
2799 // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
2800 const pint_t kOffsetSpToSigcontext
= 128 + 8 + 8 + 24 + 8 + 128;
2802 const pint_t sigctx
= _registers
.getSP() + kOffsetSpToSigcontext
;
2803 _registers
.setIP(_addressSpace
.get64(sigctx
));
2804 for (int i
= UNW_RISCV_X1
; i
<= UNW_RISCV_X31
; ++i
) {
2805 uint64_t value
= _addressSpace
.get64(sigctx
+ static_cast<pint_t
>(i
* 8));
2806 _registers
.setRegister(i
, value
);
2808 _isSignalFrame
= true;
2809 return UNW_STEP_SUCCESS
;
2811 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2812 // defined(_LIBUNWIND_TARGET_RISCV)
2814 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2815 defined(_LIBUNWIND_TARGET_S390X)
2816 template <typename A
, typename R
>
2817 bool UnwindCursor
<A
, R
>::setInfoForSigReturn(Registers_s390x
&) {
2818 // Look for the sigreturn trampoline. The trampoline's body is a
2819 // specific instruction (see below). Typically the trampoline comes from the
2820 // vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its
2821 // own restorer function, though, or user-mode QEMU might write a trampoline
2823 const pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2824 // The PC might contain an invalid address if the unwind info is bad, so
2825 // directly accessing it could cause a segfault. Use process_vm_readv to
2826 // read the memory safely instead.
2828 struct iovec local_iov
= {&inst
, sizeof inst
};
2829 struct iovec remote_iov
= {reinterpret_cast<void *>(pc
), sizeof inst
};
2830 long bytesRead
= process_vm_readv(getpid(), &local_iov
, 1, &remote_iov
, 1, 0);
2831 if (bytesRead
== sizeof inst
&& (inst
== 0x0a77 || inst
== 0x0aad)) {
2833 _info
.start_ip
= pc
;
2834 _info
.end_ip
= pc
+ 2;
2835 _isSigReturn
= true;
2841 template <typename A
, typename R
>
2842 int UnwindCursor
<A
, R
>::stepThroughSigReturn(Registers_s390x
&) {
2843 // Determine current SP.
2844 const pint_t sp
= static_cast<pint_t
>(this->getReg(UNW_REG_SP
));
2845 // According to the s390x ABI, the CFA is at (incoming) SP + 160.
2846 const pint_t cfa
= sp
+ 160;
2848 // Determine current PC and instruction there (this must be either
2849 // a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn").
2850 const pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2851 const uint16_t inst
= _addressSpace
.get16(pc
);
2853 // Find the addresses of the signo and sigcontext in the frame.
2857 // "svc __NR_sigreturn" uses a non-RT signal trampoline frame.
2858 if (inst
== 0x0a77) {
2859 // Layout of a non-RT signal trampoline frame, starting at the CFA:
2860 // - 8-byte signal mask
2861 // - 8-byte pointer to sigcontext, followed by signo
2863 pSigctx
= _addressSpace
.get64(cfa
+ 8);
2864 pSigno
= pSigctx
+ 344;
2867 // "svc __NR_rt_sigreturn" uses a RT signal trampoline frame.
2868 if (inst
== 0x0aad) {
2869 // Layout of a RT signal trampoline frame, starting at the CFA:
2870 // - 8-byte retcode (+ alignment)
2871 // - 128-byte siginfo struct (starts with signo)
2872 // - ucontext struct:
2873 // - 8-byte long (uc_flags)
2874 // - 8-byte pointer (uc_link)
2875 // - 24-byte stack_t
2876 // - 8 bytes of padding because sigcontext has 16-byte alignment
2877 // - sigcontext/mcontext_t
2878 pSigctx
= cfa
+ 8 + 128 + 8 + 8 + 24 + 8;
2882 assert(pSigctx
!= 0);
2883 assert(pSigno
!= 0);
2885 // Offsets from sigcontext to each register.
2886 const pint_t kOffsetPc
= 8;
2887 const pint_t kOffsetGprs
= 16;
2888 const pint_t kOffsetFprs
= 216;
2890 // Restore all registers.
2891 for (int i
= 0; i
< 16; ++i
) {
2892 uint64_t value
= _addressSpace
.get64(pSigctx
+ kOffsetGprs
+
2893 static_cast<pint_t
>(i
* 8));
2894 _registers
.setRegister(UNW_S390X_R0
+ i
, value
);
2896 for (int i
= 0; i
< 16; ++i
) {
2897 static const int fpr
[16] = {
2898 UNW_S390X_F0
, UNW_S390X_F1
, UNW_S390X_F2
, UNW_S390X_F3
,
2899 UNW_S390X_F4
, UNW_S390X_F5
, UNW_S390X_F6
, UNW_S390X_F7
,
2900 UNW_S390X_F8
, UNW_S390X_F9
, UNW_S390X_F10
, UNW_S390X_F11
,
2901 UNW_S390X_F12
, UNW_S390X_F13
, UNW_S390X_F14
, UNW_S390X_F15
2903 double value
= _addressSpace
.getDouble(pSigctx
+ kOffsetFprs
+
2904 static_cast<pint_t
>(i
* 8));
2905 _registers
.setFloatRegister(fpr
[i
], value
);
2907 _registers
.setIP(_addressSpace
.get64(pSigctx
+ kOffsetPc
));
2909 // SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
2910 // after the faulting instruction rather than before it.
2911 // Do not set _isSignalFrame in that case.
2912 uint32_t signo
= _addressSpace
.get32(pSigno
);
2913 _isSignalFrame
= (signo
!= 4 && signo
!= 5 && signo
!= 8);
2915 return UNW_STEP_SUCCESS
;
2917 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2918 // defined(_LIBUNWIND_TARGET_S390X)
2920 template <typename A
, typename R
> int UnwindCursor
<A
, R
>::step(bool stage2
) {
2922 // Bottom of stack is defined is when unwind info cannot be found.
2923 if (_unwindInfoMissing
)
2924 return UNW_STEP_END
;
2926 // Use unwinding info to modify register set as if function returned.
2928 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2930 result
= this->stepThroughSigReturn();
2934 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2935 result
= this->stepWithCompactEncoding(stage2
);
2936 #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2937 result
= this->stepWithSEHData();
2938 #elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2939 result
= this->stepWithTBTableData();
2940 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2941 result
= this->stepWithDwarfFDE(stage2
);
2942 #elif defined(_LIBUNWIND_ARM_EHABI)
2943 result
= this->stepWithEHABI();
2945 #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
2946 _LIBUNWIND_SUPPORT_SEH_UNWIND or \
2947 _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
2948 _LIBUNWIND_ARM_EHABI
2952 // update info based on new PC
2953 if (result
== UNW_STEP_SUCCESS
) {
2954 this->setInfoBasedOnIPRegister(true);
2955 if (_unwindInfoMissing
)
2956 return UNW_STEP_END
;
2962 template <typename A
, typename R
>
2963 void UnwindCursor
<A
, R
>::getInfo(unw_proc_info_t
*info
) {
2964 if (_unwindInfoMissing
)
2965 memset(info
, 0, sizeof(*info
));
2970 template <typename A
, typename R
>
2971 bool UnwindCursor
<A
, R
>::getFunctionName(char *buf
, size_t bufLen
,
2972 unw_word_t
*offset
) {
2973 return _addressSpace
.findFunctionName((pint_t
)this->getReg(UNW_REG_IP
),
2974 buf
, bufLen
, offset
);
2977 #if defined(_LIBUNWIND_USE_CET)
2978 extern "C" void *__libunwind_cet_get_registers(unw_cursor_t
*cursor
) {
2979 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
2980 return co
->get_registers();
2983 } // namespace libunwind
2985 #endif // __UNWINDCURSOR_HPP__