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))
38 #include <sys/syscall.h>
41 #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
44 #include "AddressSpace.hpp"
45 #include "CompactUnwinder.hpp"
47 #include "DwarfInstructions.hpp"
48 #include "EHHeaderParser.hpp"
49 #include "libunwind.h"
50 #include "libunwind_ext.h"
51 #include "Registers.hpp"
52 #include "RWMutex.hpp"
53 #include "Unwind-EHABI.h"
55 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
56 // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
58 // MinGW-w64 has always provided this struct.
59 #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
60 !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
61 struct _DISPATCHER_CONTEXT
{
64 PRUNTIME_FUNCTION FunctionEntry
;
65 ULONG64 EstablisherFrame
;
67 PCONTEXT ContextRecord
;
68 PEXCEPTION_ROUTINE LanguageHandler
;
70 PUNWIND_HISTORY_TABLE HistoryTable
;
81 uint8_t FrameRegister
: 4;
82 uint8_t FrameOffset
: 4;
83 uint16_t UnwindCodes
[2];
86 extern "C" _Unwind_Reason_Code
__libunwind_seh_personality(
87 int, _Unwind_Action
, uint64_t, _Unwind_Exception
*,
88 struct _Unwind_Context
*);
94 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
95 /// Cache of recently found FDEs.
97 class _LIBUNWIND_HIDDEN DwarfFDECache
{
98 typedef typename
A::pint_t pint_t
;
100 static constexpr pint_t kSearchAll
= static_cast<pint_t
>(-1);
101 static pint_t
findFDE(pint_t mh
, pint_t pc
);
102 static void add(pint_t mh
, pint_t ip_start
, pint_t ip_end
, pint_t fde
);
103 static void removeAllIn(pint_t mh
);
104 static void iterateCacheEntries(void (*func
)(unw_word_t ip_start
,
106 unw_word_t fde
, unw_word_t mh
));
117 // These fields are all static to avoid needing an initializer.
118 // There is only one instance of this class per process.
119 static RWMutex _lock
;
121 static void dyldUnloadHook(const struct mach_header
*mh
, intptr_t slide
);
122 static bool _registeredForDyldUnloads
;
124 static entry
*_buffer
;
125 static entry
*_bufferUsed
;
126 static entry
*_bufferEnd
;
127 static entry _initialBuffer
[64];
130 template <typename A
>
131 typename DwarfFDECache
<A
>::entry
*
132 DwarfFDECache
<A
>::_buffer
= _initialBuffer
;
134 template <typename A
>
135 typename DwarfFDECache
<A
>::entry
*
136 DwarfFDECache
<A
>::_bufferUsed
= _initialBuffer
;
138 template <typename A
>
139 typename DwarfFDECache
<A
>::entry
*
140 DwarfFDECache
<A
>::_bufferEnd
= &_initialBuffer
[64];
142 template <typename A
>
143 typename DwarfFDECache
<A
>::entry DwarfFDECache
<A
>::_initialBuffer
[64];
145 template <typename A
>
146 RWMutex DwarfFDECache
<A
>::_lock
;
149 template <typename A
>
150 bool DwarfFDECache
<A
>::_registeredForDyldUnloads
= false;
153 template <typename A
>
154 typename
A::pint_t DwarfFDECache
<A
>::findFDE(pint_t mh
, pint_t pc
) {
156 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock_shared());
157 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
158 if ((mh
== p
->mh
) || (mh
== kSearchAll
)) {
159 if ((p
->ip_start
<= pc
) && (pc
< p
->ip_end
)) {
165 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock_shared());
169 template <typename A
>
170 void DwarfFDECache
<A
>::add(pint_t mh
, pint_t ip_start
, pint_t ip_end
,
172 #if !defined(_LIBUNWIND_NO_HEAP)
173 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
174 if (_bufferUsed
>= _bufferEnd
) {
175 size_t oldSize
= (size_t)(_bufferEnd
- _buffer
);
176 size_t newSize
= oldSize
* 4;
177 // Can't use operator new (we are below it).
178 entry
*newBuffer
= (entry
*)malloc(newSize
* sizeof(entry
));
179 memcpy(newBuffer
, _buffer
, oldSize
* sizeof(entry
));
180 if (_buffer
!= _initialBuffer
)
183 _bufferUsed
= &newBuffer
[oldSize
];
184 _bufferEnd
= &newBuffer
[newSize
];
186 _bufferUsed
->mh
= mh
;
187 _bufferUsed
->ip_start
= ip_start
;
188 _bufferUsed
->ip_end
= ip_end
;
189 _bufferUsed
->fde
= fde
;
192 if (!_registeredForDyldUnloads
) {
193 _dyld_register_func_for_remove_image(&dyldUnloadHook
);
194 _registeredForDyldUnloads
= true;
197 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
201 template <typename A
>
202 void DwarfFDECache
<A
>::removeAllIn(pint_t mh
) {
203 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
205 for (const entry
*s
= _buffer
; s
< _bufferUsed
; ++s
) {
213 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
217 template <typename A
>
218 void DwarfFDECache
<A
>::dyldUnloadHook(const struct mach_header
*mh
, intptr_t ) {
219 removeAllIn((pint_t
) mh
);
223 template <typename A
>
224 void DwarfFDECache
<A
>::iterateCacheEntries(void (*func
)(
225 unw_word_t ip_start
, unw_word_t ip_end
, unw_word_t fde
, unw_word_t mh
)) {
226 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
227 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
228 (*func
)(p
->ip_start
, p
->ip_end
, p
->fde
, p
->mh
);
230 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
232 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
235 #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
237 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
238 template <typename A
> class UnwindSectionHeader
{
240 UnwindSectionHeader(A
&addressSpace
, typename
A::pint_t addr
)
241 : _addressSpace(addressSpace
), _addr(addr
) {}
243 uint32_t version() const {
244 return _addressSpace
.get32(_addr
+
245 offsetof(unwind_info_section_header
, version
));
247 uint32_t commonEncodingsArraySectionOffset() const {
248 return _addressSpace
.get32(_addr
+
249 offsetof(unwind_info_section_header
,
250 commonEncodingsArraySectionOffset
));
252 uint32_t commonEncodingsArrayCount() const {
253 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
254 commonEncodingsArrayCount
));
256 uint32_t personalityArraySectionOffset() const {
257 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
258 personalityArraySectionOffset
));
260 uint32_t personalityArrayCount() const {
261 return _addressSpace
.get32(
262 _addr
+ offsetof(unwind_info_section_header
, personalityArrayCount
));
264 uint32_t indexSectionOffset() const {
265 return _addressSpace
.get32(
266 _addr
+ offsetof(unwind_info_section_header
, indexSectionOffset
));
268 uint32_t indexCount() const {
269 return _addressSpace
.get32(
270 _addr
+ offsetof(unwind_info_section_header
, indexCount
));
275 typename
A::pint_t _addr
;
278 template <typename A
> class UnwindSectionIndexArray
{
280 UnwindSectionIndexArray(A
&addressSpace
, typename
A::pint_t addr
)
281 : _addressSpace(addressSpace
), _addr(addr
) {}
283 uint32_t functionOffset(uint32_t index
) const {
284 return _addressSpace
.get32(
285 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
288 uint32_t secondLevelPagesSectionOffset(uint32_t index
) const {
289 return _addressSpace
.get32(
290 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
291 secondLevelPagesSectionOffset
));
293 uint32_t lsdaIndexArraySectionOffset(uint32_t index
) const {
294 return _addressSpace
.get32(
295 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
296 lsdaIndexArraySectionOffset
));
301 typename
A::pint_t _addr
;
304 template <typename A
> class UnwindSectionRegularPageHeader
{
306 UnwindSectionRegularPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
307 : _addressSpace(addressSpace
), _addr(addr
) {}
309 uint32_t kind() const {
310 return _addressSpace
.get32(
311 _addr
+ offsetof(unwind_info_regular_second_level_page_header
, kind
));
313 uint16_t entryPageOffset() const {
314 return _addressSpace
.get16(
315 _addr
+ offsetof(unwind_info_regular_second_level_page_header
,
318 uint16_t entryCount() const {
319 return _addressSpace
.get16(
321 offsetof(unwind_info_regular_second_level_page_header
, entryCount
));
326 typename
A::pint_t _addr
;
329 template <typename A
> class UnwindSectionRegularArray
{
331 UnwindSectionRegularArray(A
&addressSpace
, typename
A::pint_t addr
)
332 : _addressSpace(addressSpace
), _addr(addr
) {}
334 uint32_t functionOffset(uint32_t index
) const {
335 return _addressSpace
.get32(
336 _addr
+ arrayoffsetof(unwind_info_regular_second_level_entry
, index
,
339 uint32_t encoding(uint32_t index
) const {
340 return _addressSpace
.get32(
342 arrayoffsetof(unwind_info_regular_second_level_entry
, index
, encoding
));
347 typename
A::pint_t _addr
;
350 template <typename A
> class UnwindSectionCompressedPageHeader
{
352 UnwindSectionCompressedPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
353 : _addressSpace(addressSpace
), _addr(addr
) {}
355 uint32_t kind() const {
356 return _addressSpace
.get32(
358 offsetof(unwind_info_compressed_second_level_page_header
, kind
));
360 uint16_t entryPageOffset() const {
361 return _addressSpace
.get16(
362 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
365 uint16_t entryCount() const {
366 return _addressSpace
.get16(
368 offsetof(unwind_info_compressed_second_level_page_header
, entryCount
));
370 uint16_t encodingsPageOffset() const {
371 return _addressSpace
.get16(
372 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
373 encodingsPageOffset
));
375 uint16_t encodingsCount() const {
376 return _addressSpace
.get16(
377 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
383 typename
A::pint_t _addr
;
386 template <typename A
> class UnwindSectionCompressedArray
{
388 UnwindSectionCompressedArray(A
&addressSpace
, typename
A::pint_t addr
)
389 : _addressSpace(addressSpace
), _addr(addr
) {}
391 uint32_t functionOffset(uint32_t index
) const {
392 return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
393 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
395 uint16_t encodingIndex(uint32_t index
) const {
396 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
397 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
402 typename
A::pint_t _addr
;
405 template <typename A
> class UnwindSectionLsdaArray
{
407 UnwindSectionLsdaArray(A
&addressSpace
, typename
A::pint_t addr
)
408 : _addressSpace(addressSpace
), _addr(addr
) {}
410 uint32_t functionOffset(uint32_t index
) const {
411 return _addressSpace
.get32(
412 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
413 index
, functionOffset
));
415 uint32_t lsdaOffset(uint32_t index
) const {
416 return _addressSpace
.get32(
417 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
423 typename
A::pint_t _addr
;
425 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
427 class _LIBUNWIND_HIDDEN AbstractUnwindCursor
{
429 // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
430 // This avoids an unnecessary dependency to libc++abi.
431 void operator delete(void *, size_t) {}
433 virtual ~AbstractUnwindCursor() {}
434 virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
435 virtual unw_word_t
getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
436 virtual void setReg(int, unw_word_t
) {
437 _LIBUNWIND_ABORT("setReg not implemented");
439 virtual bool validFloatReg(int) {
440 _LIBUNWIND_ABORT("validFloatReg not implemented");
442 virtual unw_fpreg_t
getFloatReg(int) {
443 _LIBUNWIND_ABORT("getFloatReg not implemented");
445 virtual void setFloatReg(int, unw_fpreg_t
) {
446 _LIBUNWIND_ABORT("setFloatReg not implemented");
448 virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); }
449 virtual void getInfo(unw_proc_info_t
*) {
450 _LIBUNWIND_ABORT("getInfo not implemented");
452 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
453 virtual bool isSignalFrame() {
454 _LIBUNWIND_ABORT("isSignalFrame not implemented");
456 virtual bool getFunctionName(char *, size_t, unw_word_t
*) {
457 _LIBUNWIND_ABORT("getFunctionName not implemented");
459 virtual void setInfoBasedOnIPRegister(bool = false) {
460 _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
462 virtual const char *getRegisterName(int) {
463 _LIBUNWIND_ABORT("getRegisterName not implemented");
466 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
470 virtual uintptr_t getDataRelBase() {
471 _LIBUNWIND_ABORT("getDataRelBase not implemented");
475 #if defined(_LIBUNWIND_USE_CET)
476 virtual void *get_registers() {
477 _LIBUNWIND_ABORT("get_registers not implemented");
482 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
484 /// \c UnwindCursor contains all state (including all register values) during
485 /// an unwind. This is normally stack-allocated inside a unw_cursor_t.
486 template <typename A
, typename R
>
487 class UnwindCursor
: public AbstractUnwindCursor
{
488 typedef typename
A::pint_t pint_t
;
490 UnwindCursor(unw_context_t
*context
, A
&as
);
491 UnwindCursor(CONTEXT
*context
, A
&as
);
492 UnwindCursor(A
&as
, void *threadArg
);
493 virtual ~UnwindCursor() {}
494 virtual bool validReg(int);
495 virtual unw_word_t
getReg(int);
496 virtual void setReg(int, unw_word_t
);
497 virtual bool validFloatReg(int);
498 virtual unw_fpreg_t
getFloatReg(int);
499 virtual void setFloatReg(int, unw_fpreg_t
);
500 virtual int step(bool = false);
501 virtual void getInfo(unw_proc_info_t
*);
502 virtual void jumpto();
503 virtual bool isSignalFrame();
504 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
505 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
506 virtual const char *getRegisterName(int num
);
508 virtual void saveVFPAsX();
511 DISPATCHER_CONTEXT
*getDispatcherContext() { return &_dispContext
; }
512 void setDispatcherContext(DISPATCHER_CONTEXT
*disp
) {
513 _dispContext
= *disp
;
514 _info
.lsda
= reinterpret_cast<unw_word_t
>(_dispContext
.HandlerData
);
515 if (_dispContext
.LanguageHandler
) {
516 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
521 // libunwind does not and should not depend on C++ library which means that we
522 // need our own definition of inline placement new.
523 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
527 pint_t
getLastPC() const { return _dispContext
.ControlPc
; }
528 void setLastPC(pint_t pc
) { _dispContext
.ControlPc
= pc
; }
529 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
531 // Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.
534 // If pc points exactly at the end of the range, we might resolve the
535 // next function instead. Decrement pc by 1 to fit inside the current
538 _dispContext
.FunctionEntry
= RtlLookupFunctionEntry(pc
,
539 &_dispContext
.ImageBase
,
540 _dispContext
.HistoryTable
);
541 *base
= _dispContext
.ImageBase
;
542 return _dispContext
.FunctionEntry
;
544 bool getInfoFromSEH(pint_t pc
);
545 int stepWithSEHData() {
546 _dispContext
.LanguageHandler
= RtlVirtualUnwind(UNW_FLAG_UHANDLER
,
547 _dispContext
.ImageBase
,
548 _dispContext
.ControlPc
,
549 _dispContext
.FunctionEntry
,
550 _dispContext
.ContextRecord
,
551 &_dispContext
.HandlerData
,
552 &_dispContext
.EstablisherFrame
,
554 // Update some fields of the unwind info now, since we have them.
555 _info
.lsda
= reinterpret_cast<unw_word_t
>(_dispContext
.HandlerData
);
556 if (_dispContext
.LanguageHandler
) {
557 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
560 return UNW_STEP_SUCCESS
;
564 unw_proc_info_t _info
;
565 DISPATCHER_CONTEXT _dispContext
;
567 UNWIND_HISTORY_TABLE _histTable
;
568 bool _unwindInfoMissing
;
572 template <typename A
, typename R
>
573 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
574 : _addressSpace(as
), _unwindInfoMissing(false) {
575 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
576 "UnwindCursor<> does not fit in unw_cursor_t");
577 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
578 "UnwindCursor<> requires more alignment than unw_cursor_t");
579 memset(&_info
, 0, sizeof(_info
));
580 memset(&_histTable
, 0, sizeof(_histTable
));
581 memset(&_dispContext
, 0, sizeof(_dispContext
));
582 _dispContext
.ContextRecord
= &_msContext
;
583 _dispContext
.HistoryTable
= &_histTable
;
584 // Initialize MS context from ours.
586 RtlCaptureContext(&_msContext
);
587 _msContext
.ContextFlags
= CONTEXT_CONTROL
|CONTEXT_INTEGER
|CONTEXT_FLOATING_POINT
;
588 #if defined(_LIBUNWIND_TARGET_X86_64)
589 _msContext
.Rax
= r
.getRegister(UNW_X86_64_RAX
);
590 _msContext
.Rcx
= r
.getRegister(UNW_X86_64_RCX
);
591 _msContext
.Rdx
= r
.getRegister(UNW_X86_64_RDX
);
592 _msContext
.Rbx
= r
.getRegister(UNW_X86_64_RBX
);
593 _msContext
.Rsp
= r
.getRegister(UNW_X86_64_RSP
);
594 _msContext
.Rbp
= r
.getRegister(UNW_X86_64_RBP
);
595 _msContext
.Rsi
= r
.getRegister(UNW_X86_64_RSI
);
596 _msContext
.Rdi
= r
.getRegister(UNW_X86_64_RDI
);
597 _msContext
.R8
= r
.getRegister(UNW_X86_64_R8
);
598 _msContext
.R9
= r
.getRegister(UNW_X86_64_R9
);
599 _msContext
.R10
= r
.getRegister(UNW_X86_64_R10
);
600 _msContext
.R11
= r
.getRegister(UNW_X86_64_R11
);
601 _msContext
.R12
= r
.getRegister(UNW_X86_64_R12
);
602 _msContext
.R13
= r
.getRegister(UNW_X86_64_R13
);
603 _msContext
.R14
= r
.getRegister(UNW_X86_64_R14
);
604 _msContext
.R15
= r
.getRegister(UNW_X86_64_R15
);
605 _msContext
.Rip
= r
.getRegister(UNW_REG_IP
);
610 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM0
);
611 _msContext
.Xmm0
= t
.m
;
612 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM1
);
613 _msContext
.Xmm1
= t
.m
;
614 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM2
);
615 _msContext
.Xmm2
= t
.m
;
616 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM3
);
617 _msContext
.Xmm3
= t
.m
;
618 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM4
);
619 _msContext
.Xmm4
= t
.m
;
620 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM5
);
621 _msContext
.Xmm5
= t
.m
;
622 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM6
);
623 _msContext
.Xmm6
= t
.m
;
624 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM7
);
625 _msContext
.Xmm7
= t
.m
;
626 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM8
);
627 _msContext
.Xmm8
= t
.m
;
628 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM9
);
629 _msContext
.Xmm9
= t
.m
;
630 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM10
);
631 _msContext
.Xmm10
= t
.m
;
632 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM11
);
633 _msContext
.Xmm11
= t
.m
;
634 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM12
);
635 _msContext
.Xmm12
= t
.m
;
636 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM13
);
637 _msContext
.Xmm13
= t
.m
;
638 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM14
);
639 _msContext
.Xmm14
= t
.m
;
640 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM15
);
641 _msContext
.Xmm15
= t
.m
;
642 #elif defined(_LIBUNWIND_TARGET_ARM)
643 _msContext
.R0
= r
.getRegister(UNW_ARM_R0
);
644 _msContext
.R1
= r
.getRegister(UNW_ARM_R1
);
645 _msContext
.R2
= r
.getRegister(UNW_ARM_R2
);
646 _msContext
.R3
= r
.getRegister(UNW_ARM_R3
);
647 _msContext
.R4
= r
.getRegister(UNW_ARM_R4
);
648 _msContext
.R5
= r
.getRegister(UNW_ARM_R5
);
649 _msContext
.R6
= r
.getRegister(UNW_ARM_R6
);
650 _msContext
.R7
= r
.getRegister(UNW_ARM_R7
);
651 _msContext
.R8
= r
.getRegister(UNW_ARM_R8
);
652 _msContext
.R9
= r
.getRegister(UNW_ARM_R9
);
653 _msContext
.R10
= r
.getRegister(UNW_ARM_R10
);
654 _msContext
.R11
= r
.getRegister(UNW_ARM_R11
);
655 _msContext
.R12
= r
.getRegister(UNW_ARM_R12
);
656 _msContext
.Sp
= r
.getRegister(UNW_ARM_SP
);
657 _msContext
.Lr
= r
.getRegister(UNW_ARM_LR
);
658 _msContext
.Pc
= r
.getRegister(UNW_ARM_IP
);
659 for (int i
= UNW_ARM_D0
; i
<= UNW_ARM_D31
; ++i
) {
664 d
.d
= r
.getFloatRegister(i
);
665 _msContext
.D
[i
- UNW_ARM_D0
] = d
.w
;
667 #elif defined(_LIBUNWIND_TARGET_AARCH64)
668 for (int i
= UNW_AARCH64_X0
; i
<= UNW_ARM64_X30
; ++i
)
669 _msContext
.X
[i
- UNW_AARCH64_X0
] = r
.getRegister(i
);
670 _msContext
.Sp
= r
.getRegister(UNW_REG_SP
);
671 _msContext
.Pc
= r
.getRegister(UNW_REG_IP
);
672 for (int i
= UNW_AARCH64_V0
; i
<= UNW_ARM64_D31
; ++i
)
673 _msContext
.V
[i
- UNW_AARCH64_V0
].D
[0] = r
.getFloatRegister(i
);
677 template <typename A
, typename R
>
678 UnwindCursor
<A
, R
>::UnwindCursor(CONTEXT
*context
, A
&as
)
679 : _addressSpace(as
), _unwindInfoMissing(false) {
680 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
681 "UnwindCursor<> does not fit in unw_cursor_t");
682 memset(&_info
, 0, sizeof(_info
));
683 memset(&_histTable
, 0, sizeof(_histTable
));
684 memset(&_dispContext
, 0, sizeof(_dispContext
));
685 _dispContext
.ContextRecord
= &_msContext
;
686 _dispContext
.HistoryTable
= &_histTable
;
687 _msContext
= *context
;
691 template <typename A
, typename R
>
692 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
693 if (regNum
== UNW_REG_IP
|| regNum
== UNW_REG_SP
) return true;
694 #if defined(_LIBUNWIND_TARGET_X86_64)
695 if (regNum
>= UNW_X86_64_RAX
&& regNum
<= UNW_X86_64_RIP
) return true;
696 #elif defined(_LIBUNWIND_TARGET_ARM)
697 if ((regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R15
) ||
698 regNum
== UNW_ARM_RA_AUTH_CODE
)
700 #elif defined(_LIBUNWIND_TARGET_AARCH64)
701 if (regNum
>= UNW_AARCH64_X0
&& regNum
<= UNW_ARM64_X30
) return true;
706 template <typename A
, typename R
>
707 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
709 #if defined(_LIBUNWIND_TARGET_X86_64)
711 case UNW_REG_IP
: return _msContext
.Rip
;
712 case UNW_X86_64_RAX
: return _msContext
.Rax
;
713 case UNW_X86_64_RDX
: return _msContext
.Rdx
;
714 case UNW_X86_64_RCX
: return _msContext
.Rcx
;
715 case UNW_X86_64_RBX
: return _msContext
.Rbx
;
717 case UNW_X86_64_RSP
: return _msContext
.Rsp
;
718 case UNW_X86_64_RBP
: return _msContext
.Rbp
;
719 case UNW_X86_64_RSI
: return _msContext
.Rsi
;
720 case UNW_X86_64_RDI
: return _msContext
.Rdi
;
721 case UNW_X86_64_R8
: return _msContext
.R8
;
722 case UNW_X86_64_R9
: return _msContext
.R9
;
723 case UNW_X86_64_R10
: return _msContext
.R10
;
724 case UNW_X86_64_R11
: return _msContext
.R11
;
725 case UNW_X86_64_R12
: return _msContext
.R12
;
726 case UNW_X86_64_R13
: return _msContext
.R13
;
727 case UNW_X86_64_R14
: return _msContext
.R14
;
728 case UNW_X86_64_R15
: return _msContext
.R15
;
729 #elif defined(_LIBUNWIND_TARGET_ARM)
730 case UNW_ARM_R0
: return _msContext
.R0
;
731 case UNW_ARM_R1
: return _msContext
.R1
;
732 case UNW_ARM_R2
: return _msContext
.R2
;
733 case UNW_ARM_R3
: return _msContext
.R3
;
734 case UNW_ARM_R4
: return _msContext
.R4
;
735 case UNW_ARM_R5
: return _msContext
.R5
;
736 case UNW_ARM_R6
: return _msContext
.R6
;
737 case UNW_ARM_R7
: return _msContext
.R7
;
738 case UNW_ARM_R8
: return _msContext
.R8
;
739 case UNW_ARM_R9
: return _msContext
.R9
;
740 case UNW_ARM_R10
: return _msContext
.R10
;
741 case UNW_ARM_R11
: return _msContext
.R11
;
742 case UNW_ARM_R12
: return _msContext
.R12
;
744 case UNW_ARM_SP
: return _msContext
.Sp
;
745 case UNW_ARM_LR
: return _msContext
.Lr
;
747 case UNW_ARM_IP
: return _msContext
.Pc
;
748 #elif defined(_LIBUNWIND_TARGET_AARCH64)
749 case UNW_REG_SP
: return _msContext
.Sp
;
750 case UNW_REG_IP
: return _msContext
.Pc
;
751 default: return _msContext
.X
[regNum
- UNW_AARCH64_X0
];
754 _LIBUNWIND_ABORT("unsupported register");
757 template <typename A
, typename R
>
758 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
760 #if defined(_LIBUNWIND_TARGET_X86_64)
762 case UNW_REG_IP
: _msContext
.Rip
= value
; break;
763 case UNW_X86_64_RAX
: _msContext
.Rax
= value
; break;
764 case UNW_X86_64_RDX
: _msContext
.Rdx
= value
; break;
765 case UNW_X86_64_RCX
: _msContext
.Rcx
= value
; break;
766 case UNW_X86_64_RBX
: _msContext
.Rbx
= value
; break;
768 case UNW_X86_64_RSP
: _msContext
.Rsp
= value
; break;
769 case UNW_X86_64_RBP
: _msContext
.Rbp
= value
; break;
770 case UNW_X86_64_RSI
: _msContext
.Rsi
= value
; break;
771 case UNW_X86_64_RDI
: _msContext
.Rdi
= value
; break;
772 case UNW_X86_64_R8
: _msContext
.R8
= value
; break;
773 case UNW_X86_64_R9
: _msContext
.R9
= value
; break;
774 case UNW_X86_64_R10
: _msContext
.R10
= value
; break;
775 case UNW_X86_64_R11
: _msContext
.R11
= value
; break;
776 case UNW_X86_64_R12
: _msContext
.R12
= value
; break;
777 case UNW_X86_64_R13
: _msContext
.R13
= value
; break;
778 case UNW_X86_64_R14
: _msContext
.R14
= value
; break;
779 case UNW_X86_64_R15
: _msContext
.R15
= value
; break;
780 #elif defined(_LIBUNWIND_TARGET_ARM)
781 case UNW_ARM_R0
: _msContext
.R0
= value
; break;
782 case UNW_ARM_R1
: _msContext
.R1
= value
; break;
783 case UNW_ARM_R2
: _msContext
.R2
= value
; break;
784 case UNW_ARM_R3
: _msContext
.R3
= value
; break;
785 case UNW_ARM_R4
: _msContext
.R4
= value
; break;
786 case UNW_ARM_R5
: _msContext
.R5
= value
; break;
787 case UNW_ARM_R6
: _msContext
.R6
= value
; break;
788 case UNW_ARM_R7
: _msContext
.R7
= value
; break;
789 case UNW_ARM_R8
: _msContext
.R8
= value
; break;
790 case UNW_ARM_R9
: _msContext
.R9
= value
; break;
791 case UNW_ARM_R10
: _msContext
.R10
= value
; break;
792 case UNW_ARM_R11
: _msContext
.R11
= value
; break;
793 case UNW_ARM_R12
: _msContext
.R12
= value
; break;
795 case UNW_ARM_SP
: _msContext
.Sp
= value
; break;
796 case UNW_ARM_LR
: _msContext
.Lr
= value
; break;
798 case UNW_ARM_IP
: _msContext
.Pc
= value
; break;
799 #elif defined(_LIBUNWIND_TARGET_AARCH64)
800 case UNW_REG_SP
: _msContext
.Sp
= value
; break;
801 case UNW_REG_IP
: _msContext
.Pc
= value
; break;
812 case UNW_AARCH64_X10
:
813 case UNW_AARCH64_X11
:
814 case UNW_AARCH64_X12
:
815 case UNW_AARCH64_X13
:
816 case UNW_AARCH64_X14
:
817 case UNW_AARCH64_X15
:
818 case UNW_AARCH64_X16
:
819 case UNW_AARCH64_X17
:
820 case UNW_AARCH64_X18
:
821 case UNW_AARCH64_X19
:
822 case UNW_AARCH64_X20
:
823 case UNW_AARCH64_X21
:
824 case UNW_AARCH64_X22
:
825 case UNW_AARCH64_X23
:
826 case UNW_AARCH64_X24
:
827 case UNW_AARCH64_X25
:
828 case UNW_AARCH64_X26
:
829 case UNW_AARCH64_X27
:
830 case UNW_AARCH64_X28
:
832 case UNW_AARCH64_LR
: _msContext
.X
[regNum
- UNW_ARM64_X0
] = value
; break;
835 _LIBUNWIND_ABORT("unsupported register");
839 template <typename A
, typename R
>
840 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
841 #if defined(_LIBUNWIND_TARGET_ARM)
842 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) return true;
843 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) return true;
844 #elif defined(_LIBUNWIND_TARGET_AARCH64)
845 if (regNum
>= UNW_AARCH64_V0
&& regNum
<= UNW_ARM64_D31
) return true;
852 template <typename A
, typename R
>
853 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
854 #if defined(_LIBUNWIND_TARGET_ARM)
855 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
860 d
.w
= _msContext
.S
[regNum
- UNW_ARM_S0
];
863 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
868 d
.w
= _msContext
.D
[regNum
- UNW_ARM_D0
];
871 _LIBUNWIND_ABORT("unsupported float register");
872 #elif defined(_LIBUNWIND_TARGET_AARCH64)
873 return _msContext
.V
[regNum
- UNW_AARCH64_V0
].D
[0];
876 _LIBUNWIND_ABORT("float registers unimplemented");
880 template <typename A
, typename R
>
881 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
882 #if defined(_LIBUNWIND_TARGET_ARM)
883 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
889 _msContext
.S
[regNum
- UNW_ARM_S0
] = d
.w
;
891 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
897 _msContext
.D
[regNum
- UNW_ARM_D0
] = d
.w
;
899 _LIBUNWIND_ABORT("unsupported float register");
900 #elif defined(_LIBUNWIND_TARGET_AARCH64)
901 _msContext
.V
[regNum
- UNW_AARCH64_V0
].D
[0] = value
;
905 _LIBUNWIND_ABORT("float registers unimplemented");
909 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
910 RtlRestoreContext(&_msContext
, nullptr);
914 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {}
917 template <typename A
, typename R
>
918 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
919 return R::getRegisterName(regNum
);
922 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
926 #else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
928 /// UnwindCursor contains all state (including all register values) during
929 /// an unwind. This is normally stack allocated inside a unw_cursor_t.
930 template <typename A
, typename R
>
931 class UnwindCursor
: public AbstractUnwindCursor
{
932 typedef typename
A::pint_t pint_t
;
934 UnwindCursor(unw_context_t
*context
, A
&as
);
935 UnwindCursor(A
&as
, void *threadArg
);
936 virtual ~UnwindCursor() {}
937 virtual bool validReg(int);
938 virtual unw_word_t
getReg(int);
939 virtual void setReg(int, unw_word_t
);
940 virtual bool validFloatReg(int);
941 virtual unw_fpreg_t
getFloatReg(int);
942 virtual void setFloatReg(int, unw_fpreg_t
);
943 virtual int step(bool stage2
= false);
944 virtual void getInfo(unw_proc_info_t
*);
945 virtual void jumpto();
946 virtual bool isSignalFrame();
947 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
948 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
949 virtual const char *getRegisterName(int num
);
951 virtual void saveVFPAsX();
955 virtual uintptr_t getDataRelBase();
958 #if defined(_LIBUNWIND_USE_CET)
959 virtual void *get_registers() { return &_registers
; }
962 // libunwind does not and should not depend on C++ library which means that we
963 // need our own definition of inline placement new.
964 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
968 #if defined(_LIBUNWIND_ARM_EHABI)
969 bool getInfoFromEHABISection(pint_t pc
, const UnwindInfoSections
§s
);
971 int stepWithEHABI() {
974 // FIXME: Calling decode_eht_entry() here is violating the libunwind
975 // abstraction layer.
976 const uint32_t *ehtp
=
977 decode_eht_entry(reinterpret_cast<const uint32_t *>(_info
.unwind_info
),
979 if (_Unwind_VRS_Interpret((_Unwind_Context
*)this, ehtp
, off
, len
) !=
980 _URC_CONTINUE_UNWIND
)
982 return UNW_STEP_SUCCESS
;
986 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
987 bool setInfoForSigReturn() {
989 return setInfoForSigReturn(dummy
);
991 int stepThroughSigReturn() {
993 return stepThroughSigReturn(dummy
);
995 bool isReadableAddr(const pint_t addr
) const;
996 #if defined(_LIBUNWIND_TARGET_AARCH64)
997 bool setInfoForSigReturn(Registers_arm64
&);
998 int stepThroughSigReturn(Registers_arm64
&);
1000 #if defined(_LIBUNWIND_TARGET_RISCV)
1001 bool setInfoForSigReturn(Registers_riscv
&);
1002 int stepThroughSigReturn(Registers_riscv
&);
1004 #if defined(_LIBUNWIND_TARGET_S390X)
1005 bool setInfoForSigReturn(Registers_s390x
&);
1006 int stepThroughSigReturn(Registers_s390x
&);
1008 template <typename Registers
> bool setInfoForSigReturn(Registers
&) {
1011 template <typename Registers
> int stepThroughSigReturn(Registers
&) {
1012 return UNW_STEP_END
;
1016 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1017 bool getInfoFromFdeCie(const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
1018 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
,
1019 pint_t pc
, uintptr_t dso_base
);
1020 bool getInfoFromDwarfSection(pint_t pc
, const UnwindInfoSections
§s
,
1021 uint32_t fdeSectionOffsetHint
=0);
1022 int stepWithDwarfFDE(bool stage2
) {
1023 return DwarfInstructions
<A
, R
>::stepWithDwarf(
1024 _addressSpace
, (pint_t
)this->getReg(UNW_REG_IP
),
1025 (pint_t
)_info
.unwind_info
, _registers
, _isSignalFrame
, stage2
);
1029 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1030 bool getInfoFromCompactEncodingSection(pint_t pc
,
1031 const UnwindInfoSections
§s
);
1032 int stepWithCompactEncoding(bool stage2
= false) {
1033 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1034 if ( compactSaysUseDwarf() )
1035 return stepWithDwarfFDE(stage2
);
1038 return stepWithCompactEncoding(dummy
);
1041 #if defined(_LIBUNWIND_TARGET_X86_64)
1042 int stepWithCompactEncoding(Registers_x86_64
&) {
1043 return CompactUnwinder_x86_64
<A
>::stepWithCompactEncoding(
1044 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
1048 #if defined(_LIBUNWIND_TARGET_I386)
1049 int stepWithCompactEncoding(Registers_x86
&) {
1050 return CompactUnwinder_x86
<A
>::stepWithCompactEncoding(
1051 _info
.format
, (uint32_t)_info
.start_ip
, _addressSpace
, _registers
);
1055 #if defined(_LIBUNWIND_TARGET_PPC)
1056 int stepWithCompactEncoding(Registers_ppc
&) {
1061 #if defined(_LIBUNWIND_TARGET_PPC64)
1062 int stepWithCompactEncoding(Registers_ppc64
&) {
1068 #if defined(_LIBUNWIND_TARGET_AARCH64)
1069 int stepWithCompactEncoding(Registers_arm64
&) {
1070 return CompactUnwinder_arm64
<A
>::stepWithCompactEncoding(
1071 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
1075 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
1076 int stepWithCompactEncoding(Registers_mips_o32
&) {
1081 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1082 int stepWithCompactEncoding(Registers_mips_newabi
&) {
1087 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1088 int stepWithCompactEncoding(Registers_loongarch
&) { return UNW_EINVAL
; }
1091 #if defined(_LIBUNWIND_TARGET_SPARC)
1092 int stepWithCompactEncoding(Registers_sparc
&) { return UNW_EINVAL
; }
1095 #if defined(_LIBUNWIND_TARGET_SPARC64)
1096 int stepWithCompactEncoding(Registers_sparc64
&) { return UNW_EINVAL
; }
1099 #if defined (_LIBUNWIND_TARGET_RISCV)
1100 int stepWithCompactEncoding(Registers_riscv
&) {
1105 bool compactSaysUseDwarf(uint32_t *offset
=NULL
) const {
1107 return compactSaysUseDwarf(dummy
, offset
);
1110 #if defined(_LIBUNWIND_TARGET_X86_64)
1111 bool compactSaysUseDwarf(Registers_x86_64
&, uint32_t *offset
) const {
1112 if ((_info
.format
& UNWIND_X86_64_MODE_MASK
) == UNWIND_X86_64_MODE_DWARF
) {
1114 *offset
= (_info
.format
& UNWIND_X86_64_DWARF_SECTION_OFFSET
);
1121 #if defined(_LIBUNWIND_TARGET_I386)
1122 bool compactSaysUseDwarf(Registers_x86
&, uint32_t *offset
) const {
1123 if ((_info
.format
& UNWIND_X86_MODE_MASK
) == UNWIND_X86_MODE_DWARF
) {
1125 *offset
= (_info
.format
& UNWIND_X86_DWARF_SECTION_OFFSET
);
1132 #if defined(_LIBUNWIND_TARGET_PPC)
1133 bool compactSaysUseDwarf(Registers_ppc
&, uint32_t *) const {
1138 #if defined(_LIBUNWIND_TARGET_PPC64)
1139 bool compactSaysUseDwarf(Registers_ppc64
&, uint32_t *) const {
1144 #if defined(_LIBUNWIND_TARGET_AARCH64)
1145 bool compactSaysUseDwarf(Registers_arm64
&, uint32_t *offset
) const {
1146 if ((_info
.format
& UNWIND_ARM64_MODE_MASK
) == UNWIND_ARM64_MODE_DWARF
) {
1148 *offset
= (_info
.format
& UNWIND_ARM64_DWARF_SECTION_OFFSET
);
1155 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
1156 bool compactSaysUseDwarf(Registers_mips_o32
&, uint32_t *) const {
1161 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1162 bool compactSaysUseDwarf(Registers_mips_newabi
&, uint32_t *) const {
1167 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1168 bool compactSaysUseDwarf(Registers_loongarch
&, uint32_t *) const {
1173 #if defined(_LIBUNWIND_TARGET_SPARC)
1174 bool compactSaysUseDwarf(Registers_sparc
&, uint32_t *) const { return true; }
1177 #if defined(_LIBUNWIND_TARGET_SPARC64)
1178 bool compactSaysUseDwarf(Registers_sparc64
&, uint32_t *) const {
1183 #if defined (_LIBUNWIND_TARGET_RISCV)
1184 bool compactSaysUseDwarf(Registers_riscv
&, uint32_t *) const {
1189 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1191 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1192 compact_unwind_encoding_t
dwarfEncoding() const {
1194 return dwarfEncoding(dummy
);
1197 #if defined(_LIBUNWIND_TARGET_X86_64)
1198 compact_unwind_encoding_t
dwarfEncoding(Registers_x86_64
&) const {
1199 return UNWIND_X86_64_MODE_DWARF
;
1203 #if defined(_LIBUNWIND_TARGET_I386)
1204 compact_unwind_encoding_t
dwarfEncoding(Registers_x86
&) const {
1205 return UNWIND_X86_MODE_DWARF
;
1209 #if defined(_LIBUNWIND_TARGET_PPC)
1210 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc
&) const {
1215 #if defined(_LIBUNWIND_TARGET_PPC64)
1216 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc64
&) const {
1221 #if defined(_LIBUNWIND_TARGET_AARCH64)
1222 compact_unwind_encoding_t
dwarfEncoding(Registers_arm64
&) const {
1223 return UNWIND_ARM64_MODE_DWARF
;
1227 #if defined(_LIBUNWIND_TARGET_ARM)
1228 compact_unwind_encoding_t
dwarfEncoding(Registers_arm
&) const {
1233 #if defined (_LIBUNWIND_TARGET_OR1K)
1234 compact_unwind_encoding_t
dwarfEncoding(Registers_or1k
&) const {
1239 #if defined (_LIBUNWIND_TARGET_HEXAGON)
1240 compact_unwind_encoding_t
dwarfEncoding(Registers_hexagon
&) const {
1245 #if defined (_LIBUNWIND_TARGET_MIPS_O32)
1246 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_o32
&) const {
1251 #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1252 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_newabi
&) const {
1257 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1258 compact_unwind_encoding_t
dwarfEncoding(Registers_loongarch
&) const {
1263 #if defined(_LIBUNWIND_TARGET_SPARC)
1264 compact_unwind_encoding_t
dwarfEncoding(Registers_sparc
&) const { return 0; }
1267 #if defined(_LIBUNWIND_TARGET_SPARC64)
1268 compact_unwind_encoding_t
dwarfEncoding(Registers_sparc64
&) const {
1273 #if defined (_LIBUNWIND_TARGET_RISCV)
1274 compact_unwind_encoding_t
dwarfEncoding(Registers_riscv
&) const {
1279 #if defined (_LIBUNWIND_TARGET_S390X)
1280 compact_unwind_encoding_t
dwarfEncoding(Registers_s390x
&) const {
1285 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1287 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1288 // For runtime environments using SEH unwind data without Windows runtime
1290 pint_t
getLastPC() const { /* FIXME: Implement */ return 0; }
1291 void setLastPC(pint_t pc
) { /* FIXME: Implement */ }
1292 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
1293 /* FIXME: Implement */
1297 bool getInfoFromSEH(pint_t pc
);
1298 int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1299 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1301 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1302 bool getInfoFromTBTable(pint_t pc
, R
®isters
);
1303 int stepWithTBTable(pint_t pc
, tbtable
*TBTable
, R
®isters
,
1304 bool &isSignalFrame
);
1305 int stepWithTBTableData() {
1306 return stepWithTBTable(reinterpret_cast<pint_t
>(this->getReg(UNW_REG_IP
)),
1307 reinterpret_cast<tbtable
*>(_info
.unwind_info
),
1308 _registers
, _isSignalFrame
);
1310 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1314 unw_proc_info_t _info
;
1315 bool _unwindInfoMissing
;
1316 bool _isSignalFrame
;
1317 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1318 bool _isSigReturn
= false;
1323 template <typename A
, typename R
>
1324 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
1325 : _addressSpace(as
), _registers(context
), _unwindInfoMissing(false),
1326 _isSignalFrame(false) {
1327 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
1328 "UnwindCursor<> does not fit in unw_cursor_t");
1329 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
1330 "UnwindCursor<> requires more alignment than unw_cursor_t");
1331 memset(&_info
, 0, sizeof(_info
));
1334 template <typename A
, typename R
>
1335 UnwindCursor
<A
, R
>::UnwindCursor(A
&as
, void *)
1336 : _addressSpace(as
), _unwindInfoMissing(false), _isSignalFrame(false) {
1337 memset(&_info
, 0, sizeof(_info
));
1339 // fill in _registers from thread arg
1343 template <typename A
, typename R
>
1344 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
1345 return _registers
.validRegister(regNum
);
1348 template <typename A
, typename R
>
1349 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
1350 return _registers
.getRegister(regNum
);
1353 template <typename A
, typename R
>
1354 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
1355 _registers
.setRegister(regNum
, (typename
A::pint_t
)value
);
1358 template <typename A
, typename R
>
1359 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
1360 return _registers
.validFloatRegister(regNum
);
1363 template <typename A
, typename R
>
1364 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
1365 return _registers
.getFloatRegister(regNum
);
1368 template <typename A
, typename R
>
1369 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
1370 _registers
.setFloatRegister(regNum
, value
);
1373 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
1374 _registers
.jumpto();
1378 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {
1379 _registers
.saveVFPAsX();
1384 template <typename A
, typename R
>
1385 uintptr_t UnwindCursor
<A
, R
>::getDataRelBase() {
1386 return reinterpret_cast<uintptr_t>(_info
.extra
);
1390 template <typename A
, typename R
>
1391 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
1392 return _registers
.getRegisterName(regNum
);
1395 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
1396 return _isSignalFrame
;
1399 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1401 #if defined(_LIBUNWIND_ARM_EHABI)
1402 template<typename A
>
1403 struct EHABISectionIterator
{
1404 typedef EHABISectionIterator _Self
;
1406 typedef typename
A::pint_t value_type
;
1407 typedef typename
A::pint_t
* pointer
;
1408 typedef typename
A::pint_t
& reference
;
1409 typedef size_t size_type
;
1410 typedef size_t difference_type
;
1412 static _Self
begin(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1413 return _Self(addressSpace
, sects
, 0);
1415 static _Self
end(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1416 return _Self(addressSpace
, sects
,
1417 sects
.arm_section_length
/ sizeof(EHABIIndexEntry
));
1420 EHABISectionIterator(A
& addressSpace
, const UnwindInfoSections
& sects
, size_t i
)
1421 : _i(i
), _addressSpace(&addressSpace
), _sects(§s
) {}
1423 _Self
& operator++() { ++_i
; return *this; }
1424 _Self
& operator+=(size_t a
) { _i
+= a
; return *this; }
1425 _Self
& operator--() { assert(_i
> 0); --_i
; return *this; }
1426 _Self
& operator-=(size_t a
) { assert(_i
>= a
); _i
-= a
; return *this; }
1428 _Self
operator+(size_t a
) { _Self out
= *this; out
._i
+= a
; return out
; }
1429 _Self
operator-(size_t a
) { assert(_i
>= a
); _Self out
= *this; out
._i
-= a
; return out
; }
1431 size_t operator-(const _Self
& other
) const { return _i
- other
._i
; }
1433 bool operator==(const _Self
& other
) const {
1434 assert(_addressSpace
== other
._addressSpace
);
1435 assert(_sects
== other
._sects
);
1436 return _i
== other
._i
;
1439 bool operator!=(const _Self
& other
) const {
1440 assert(_addressSpace
== other
._addressSpace
);
1441 assert(_sects
== other
._sects
);
1442 return _i
!= other
._i
;
1445 typename
A::pint_t
operator*() const { return functionAddress(); }
1447 typename
A::pint_t
functionAddress() const {
1448 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1449 EHABIIndexEntry
, _i
, functionOffset
);
1450 return indexAddr
+ signExtendPrel31(_addressSpace
->get32(indexAddr
));
1453 typename
A::pint_t
dataAddress() {
1454 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1455 EHABIIndexEntry
, _i
, data
);
1462 const UnwindInfoSections
* _sects
;
1467 template <typename A
>
1468 EHABISectionIterator
<A
> EHABISectionUpperBound(
1469 EHABISectionIterator
<A
> first
,
1470 EHABISectionIterator
<A
> last
,
1471 typename
A::pint_t value
) {
1472 size_t len
= last
- first
;
1474 size_t l2
= len
/ 2;
1475 EHABISectionIterator
<A
> m
= first
+ l2
;
1488 template <typename A
, typename R
>
1489 bool UnwindCursor
<A
, R
>::getInfoFromEHABISection(
1491 const UnwindInfoSections
§s
) {
1492 EHABISectionIterator
<A
> begin
=
1493 EHABISectionIterator
<A
>::begin(_addressSpace
, sects
);
1494 EHABISectionIterator
<A
> end
=
1495 EHABISectionIterator
<A
>::end(_addressSpace
, sects
);
1499 EHABISectionIterator
<A
> itNextPC
= EHABISectionUpperBound(begin
, end
, pc
);
1500 if (itNextPC
== begin
)
1502 EHABISectionIterator
<A
> itThisPC
= itNextPC
- 1;
1504 pint_t thisPC
= itThisPC
.functionAddress();
1505 // If an exception is thrown from a function, corresponding to the last entry
1506 // in the table, we don't really know the function extent and have to choose a
1507 // value for nextPC. Choosing max() will allow the range check during trace to
1509 pint_t nextPC
= (itNextPC
== end
) ? UINTPTR_MAX
: itNextPC
.functionAddress();
1510 pint_t indexDataAddr
= itThisPC
.dataAddress();
1512 if (indexDataAddr
== 0)
1515 uint32_t indexData
= _addressSpace
.get32(indexDataAddr
);
1516 if (indexData
== UNW_EXIDX_CANTUNWIND
)
1519 // If the high bit is set, the exception handling table entry is inline inside
1520 // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1521 // the table points at an offset in the exception handling table (section 5
1523 pint_t exceptionTableAddr
;
1524 uint32_t exceptionTableData
;
1525 bool isSingleWordEHT
;
1526 if (indexData
& 0x80000000) {
1527 exceptionTableAddr
= indexDataAddr
;
1528 // TODO(ajwong): Should this data be 0?
1529 exceptionTableData
= indexData
;
1530 isSingleWordEHT
= true;
1532 exceptionTableAddr
= indexDataAddr
+ signExtendPrel31(indexData
);
1533 exceptionTableData
= _addressSpace
.get32(exceptionTableAddr
);
1534 isSingleWordEHT
= false;
1537 // Now we know the 3 things:
1538 // exceptionTableAddr -- exception handler table entry.
1539 // exceptionTableData -- the data inside the first word of the eht entry.
1540 // isSingleWordEHT -- whether the entry is in the index.
1541 unw_word_t personalityRoutine
= 0xbadf00d;
1542 bool scope32
= false;
1545 // If the high bit in the exception handling table entry is set, the entry is
1546 // in compact form (section 6.3 EHABI).
1547 if (exceptionTableData
& 0x80000000) {
1548 // Grab the index of the personality routine from the compact form.
1549 uint32_t choice
= (exceptionTableData
& 0x0f000000) >> 24;
1550 uint32_t extraWords
= 0;
1553 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr0
;
1556 lsda
= isSingleWordEHT
? 0 : (exceptionTableAddr
+ 4);
1559 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr1
;
1560 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1562 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1565 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr2
;
1566 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1568 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1571 _LIBUNWIND_ABORT("unknown personality routine");
1575 if (isSingleWordEHT
) {
1576 if (extraWords
!= 0) {
1577 _LIBUNWIND_ABORT("index inlined table detected but pr function "
1578 "requires extra words");
1583 pint_t personalityAddr
=
1584 exceptionTableAddr
+ signExtendPrel31(exceptionTableData
);
1585 personalityRoutine
= personalityAddr
;
1587 // ARM EHABI # 6.2, # 9.2
1591 // +--------------------------------------+
1592 // | +--------+--------+--------+-------+ |
1593 // | |0| prel31 to personalityRoutine | |
1594 // | +--------+--------+--------+-------+ |
1595 // | | N | unwind opcodes | | <-- UnwindData
1596 // | +--------+--------+--------+-------+ |
1597 // | | Word 2 unwind opcodes | |
1598 // | +--------+--------+--------+-------+ |
1600 // | +--------+--------+--------+-------+ |
1601 // | | Word N unwind opcodes | |
1602 // | +--------+--------+--------+-------+ |
1603 // | | LSDA | | <-- lsda
1605 // | +--------+--------+--------+-------+ |
1606 // +--------------------------------------+
1608 uint32_t *UnwindData
= reinterpret_cast<uint32_t*>(exceptionTableAddr
) + 1;
1609 uint32_t FirstDataWord
= *UnwindData
;
1610 size_t N
= ((FirstDataWord
>> 24) & 0xff);
1611 size_t NDataWords
= N
+ 1;
1612 lsda
= reinterpret_cast<uintptr_t>(UnwindData
+ NDataWords
);
1615 _info
.start_ip
= thisPC
;
1616 _info
.end_ip
= nextPC
;
1617 _info
.handler
= personalityRoutine
;
1618 _info
.unwind_info
= exceptionTableAddr
;
1620 // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1621 _info
.flags
= (isSingleWordEHT
? 1 : 0) | (scope32
? 0x2 : 0); // Use enum?
1627 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1628 template <typename A
, typename R
>
1629 bool UnwindCursor
<A
, R
>::getInfoFromFdeCie(
1630 const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
1631 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
, pint_t pc
,
1632 uintptr_t dso_base
) {
1633 typename CFI_Parser
<A
>::PrologInfo prolog
;
1634 if (CFI_Parser
<A
>::parseFDEInstructions(_addressSpace
, fdeInfo
, cieInfo
, pc
,
1635 R::getArch(), &prolog
)) {
1636 // Save off parsed FDE info
1637 _info
.start_ip
= fdeInfo
.pcStart
;
1638 _info
.end_ip
= fdeInfo
.pcEnd
;
1639 _info
.lsda
= fdeInfo
.lsda
;
1640 _info
.handler
= cieInfo
.personality
;
1641 // Some frameless functions need SP altered when resuming in function, so
1642 // propagate spExtraArgSize.
1643 _info
.gp
= prolog
.spExtraArgSize
;
1645 _info
.format
= dwarfEncoding();
1646 _info
.unwind_info
= fdeInfo
.fdeStart
;
1647 _info
.unwind_info_size
= static_cast<uint32_t>(fdeInfo
.fdeLength
);
1648 _info
.extra
= static_cast<unw_word_t
>(dso_base
);
1654 template <typename A
, typename R
>
1655 bool UnwindCursor
<A
, R
>::getInfoFromDwarfSection(pint_t pc
,
1656 const UnwindInfoSections
§s
,
1657 uint32_t fdeSectionOffsetHint
) {
1658 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
1659 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
1660 bool foundFDE
= false;
1661 bool foundInCache
= false;
1662 // If compact encoding table gave offset into dwarf section, go directly there
1663 if (fdeSectionOffsetHint
!= 0) {
1664 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1665 sects
.dwarf_section_length
,
1666 sects
.dwarf_section
+ fdeSectionOffsetHint
,
1667 &fdeInfo
, &cieInfo
);
1669 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1670 if (!foundFDE
&& (sects
.dwarf_index_section
!= 0)) {
1671 foundFDE
= EHHeaderParser
<A
>::findFDE(
1672 _addressSpace
, pc
, sects
.dwarf_index_section
,
1673 (uint32_t)sects
.dwarf_index_section_length
, &fdeInfo
, &cieInfo
);
1677 // otherwise, search cache of previously found FDEs.
1678 pint_t cachedFDE
= DwarfFDECache
<A
>::findFDE(sects
.dso_base
, pc
);
1679 if (cachedFDE
!= 0) {
1681 CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1682 sects
.dwarf_section_length
,
1683 cachedFDE
, &fdeInfo
, &cieInfo
);
1684 foundInCache
= foundFDE
;
1688 // Still not found, do full scan of __eh_frame section.
1689 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1690 sects
.dwarf_section_length
, 0,
1691 &fdeInfo
, &cieInfo
);
1694 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, sects
.dso_base
)) {
1695 // Add to cache (to make next lookup faster) if we had no hint
1696 // and there was no index.
1697 if (!foundInCache
&& (fdeSectionOffsetHint
== 0)) {
1698 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1699 if (sects
.dwarf_index_section
== 0)
1701 DwarfFDECache
<A
>::add(sects
.dso_base
, fdeInfo
.pcStart
, fdeInfo
.pcEnd
,
1707 //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1710 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1713 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1714 template <typename A
, typename R
>
1715 bool UnwindCursor
<A
, R
>::getInfoFromCompactEncodingSection(pint_t pc
,
1716 const UnwindInfoSections
§s
) {
1717 const bool log
= false;
1719 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1720 (uint64_t)pc
, (uint64_t)sects
.dso_base
);
1722 const UnwindSectionHeader
<A
> sectionHeader(_addressSpace
,
1723 sects
.compact_unwind_section
);
1724 if (sectionHeader
.version() != UNWIND_SECTION_VERSION
)
1727 // do a binary search of top level index to find page with unwind info
1728 pint_t targetFunctionOffset
= pc
- sects
.dso_base
;
1729 const UnwindSectionIndexArray
<A
> topIndex(_addressSpace
,
1730 sects
.compact_unwind_section
1731 + sectionHeader
.indexSectionOffset());
1733 uint32_t high
= sectionHeader
.indexCount();
1734 uint32_t last
= high
- 1;
1735 while (low
< high
) {
1736 uint32_t mid
= (low
+ high
) / 2;
1737 //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1738 //mid, low, high, topIndex.functionOffset(mid));
1739 if (topIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1740 if ((mid
== last
) ||
1741 (topIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
)) {
1751 const uint32_t firstLevelFunctionOffset
= topIndex
.functionOffset(low
);
1752 const uint32_t firstLevelNextPageFunctionOffset
=
1753 topIndex
.functionOffset(low
+ 1);
1754 const pint_t secondLevelAddr
=
1755 sects
.compact_unwind_section
+ topIndex
.secondLevelPagesSectionOffset(low
);
1756 const pint_t lsdaArrayStartAddr
=
1757 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
);
1758 const pint_t lsdaArrayEndAddr
=
1759 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
+1);
1761 fprintf(stderr
, "\tfirst level search for result index=%d "
1762 "to secondLevelAddr=0x%llX\n",
1763 low
, (uint64_t) secondLevelAddr
);
1764 // do a binary search of second level page index
1765 uint32_t encoding
= 0;
1766 pint_t funcStart
= 0;
1769 pint_t personality
= 0;
1770 uint32_t pageKind
= _addressSpace
.get32(secondLevelAddr
);
1771 if (pageKind
== UNWIND_SECOND_LEVEL_REGULAR
) {
1773 UnwindSectionRegularPageHeader
<A
> pageHeader(_addressSpace
,
1775 UnwindSectionRegularArray
<A
> pageIndex(
1776 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1777 // binary search looks for entry with e where index[e].offset <= pc <
1778 // index[e+1].offset
1780 fprintf(stderr
, "\tbinary search for targetFunctionOffset=0x%08llX in "
1781 "regular page starting at secondLevelAddr=0x%llX\n",
1782 (uint64_t) targetFunctionOffset
, (uint64_t) secondLevelAddr
);
1784 high
= pageHeader
.entryCount();
1785 while (low
< high
) {
1786 uint32_t mid
= (low
+ high
) / 2;
1787 if (pageIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1788 if (mid
== (uint32_t)(pageHeader
.entryCount() - 1)) {
1791 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1793 } else if (pageIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
) {
1794 // next is too big, so we found it
1796 funcEnd
= pageIndex
.functionOffset(low
+ 1) + sects
.dso_base
;
1805 encoding
= pageIndex
.encoding(low
);
1806 funcStart
= pageIndex
.functionOffset(low
) + sects
.dso_base
;
1807 if (pc
< funcStart
) {
1811 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1812 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1819 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1820 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1823 } else if (pageKind
== UNWIND_SECOND_LEVEL_COMPRESSED
) {
1825 UnwindSectionCompressedPageHeader
<A
> pageHeader(_addressSpace
,
1827 UnwindSectionCompressedArray
<A
> pageIndex(
1828 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1829 const uint32_t targetFunctionPageOffset
=
1830 (uint32_t)(targetFunctionOffset
- firstLevelFunctionOffset
);
1831 // binary search looks for entry with e where index[e].offset <= pc <
1832 // index[e+1].offset
1834 fprintf(stderr
, "\tbinary search of compressed page starting at "
1835 "secondLevelAddr=0x%llX\n",
1836 (uint64_t) secondLevelAddr
);
1838 last
= pageHeader
.entryCount() - 1;
1839 high
= pageHeader
.entryCount();
1840 while (low
< high
) {
1841 uint32_t mid
= (low
+ high
) / 2;
1842 if (pageIndex
.functionOffset(mid
) <= targetFunctionPageOffset
) {
1843 if ((mid
== last
) ||
1844 (pageIndex
.functionOffset(mid
+ 1) > targetFunctionPageOffset
)) {
1854 funcStart
= pageIndex
.functionOffset(low
) + firstLevelFunctionOffset
1858 pageIndex
.functionOffset(low
+ 1) + firstLevelFunctionOffset
1861 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1862 if (pc
< funcStart
) {
1863 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1864 "not in second level compressed unwind table. "
1866 (uint64_t) pc
, (uint64_t) funcStart
);
1870 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1871 "not in second level compressed unwind table. "
1873 (uint64_t) pc
, (uint64_t) funcEnd
);
1876 uint16_t encodingIndex
= pageIndex
.encodingIndex(low
);
1877 if (encodingIndex
< sectionHeader
.commonEncodingsArrayCount()) {
1878 // encoding is in common table in section header
1879 encoding
= _addressSpace
.get32(
1880 sects
.compact_unwind_section
+
1881 sectionHeader
.commonEncodingsArraySectionOffset() +
1882 encodingIndex
* sizeof(uint32_t));
1884 // encoding is in page specific table
1885 uint16_t pageEncodingIndex
=
1886 encodingIndex
- (uint16_t)sectionHeader
.commonEncodingsArrayCount();
1887 encoding
= _addressSpace
.get32(secondLevelAddr
+
1888 pageHeader
.encodingsPageOffset() +
1889 pageEncodingIndex
* sizeof(uint32_t));
1892 _LIBUNWIND_DEBUG_LOG(
1893 "malformed __unwind_info at 0x%0llX bad second level page",
1894 (uint64_t)sects
.compact_unwind_section
);
1898 // look up LSDA, if encoding says function has one
1899 if (encoding
& UNWIND_HAS_LSDA
) {
1900 UnwindSectionLsdaArray
<A
> lsdaIndex(_addressSpace
, lsdaArrayStartAddr
);
1901 uint32_t funcStartOffset
= (uint32_t)(funcStart
- sects
.dso_base
);
1903 high
= (uint32_t)(lsdaArrayEndAddr
- lsdaArrayStartAddr
) /
1904 sizeof(unwind_info_section_header_lsda_index_entry
);
1905 // binary search looks for entry with exact match for functionOffset
1908 "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1910 while (low
< high
) {
1911 uint32_t mid
= (low
+ high
) / 2;
1912 if (lsdaIndex
.functionOffset(mid
) == funcStartOffset
) {
1913 lsda
= lsdaIndex
.lsdaOffset(mid
) + sects
.dso_base
;
1915 } else if (lsdaIndex
.functionOffset(mid
) < funcStartOffset
) {
1922 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1923 "pc=0x%0llX, but lsda table has no entry",
1924 encoding
, (uint64_t) pc
);
1929 // extract personality routine, if encoding says function has one
1930 uint32_t personalityIndex
= (encoding
& UNWIND_PERSONALITY_MASK
) >>
1931 (__builtin_ctz(UNWIND_PERSONALITY_MASK
));
1932 if (personalityIndex
!= 0) {
1933 --personalityIndex
; // change 1-based to zero-based index
1934 if (personalityIndex
>= sectionHeader
.personalityArrayCount()) {
1935 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
1936 "but personality table has only %d entries",
1937 encoding
, personalityIndex
,
1938 sectionHeader
.personalityArrayCount());
1941 int32_t personalityDelta
= (int32_t)_addressSpace
.get32(
1942 sects
.compact_unwind_section
+
1943 sectionHeader
.personalityArraySectionOffset() +
1944 personalityIndex
* sizeof(uint32_t));
1945 pint_t personalityPointer
= sects
.dso_base
+ (pint_t
)personalityDelta
;
1946 personality
= _addressSpace
.getP(personalityPointer
);
1948 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1949 "personalityDelta=0x%08X, personality=0x%08llX\n",
1950 (uint64_t) pc
, personalityDelta
, (uint64_t) personality
);
1954 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1955 "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1956 (uint64_t) pc
, encoding
, (uint64_t) lsda
, (uint64_t) funcStart
);
1957 _info
.start_ip
= funcStart
;
1958 _info
.end_ip
= funcEnd
;
1960 _info
.handler
= personality
;
1963 _info
.format
= encoding
;
1964 _info
.unwind_info
= 0;
1965 _info
.unwind_info_size
= 0;
1966 _info
.extra
= sects
.dso_base
;
1969 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1972 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1973 template <typename A
, typename R
>
1974 bool UnwindCursor
<A
, R
>::getInfoFromSEH(pint_t pc
) {
1976 RUNTIME_FUNCTION
*unwindEntry
= lookUpSEHUnwindInfo(pc
, &base
);
1978 _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc
);
1984 _info
.unwind_info_size
= sizeof(RUNTIME_FUNCTION
);
1985 _info
.unwind_info
= reinterpret_cast<unw_word_t
>(unwindEntry
);
1987 _info
.start_ip
= base
+ unwindEntry
->BeginAddress
;
1988 #ifdef _LIBUNWIND_TARGET_X86_64
1989 _info
.end_ip
= base
+ unwindEntry
->EndAddress
;
1990 // Only fill in the handler and LSDA if they're stale.
1991 if (pc
!= getLastPC()) {
1992 UNWIND_INFO
*xdata
= reinterpret_cast<UNWIND_INFO
*>(base
+ unwindEntry
->UnwindData
);
1993 if (xdata
->Flags
& (UNW_FLAG_EHANDLER
|UNW_FLAG_UHANDLER
)) {
1994 // The personality is given in the UNWIND_INFO itself. The LSDA immediately
1995 // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
1996 // these structures.)
1997 // N.B. UNWIND_INFO structs are DWORD-aligned.
1998 uint32_t lastcode
= (xdata
->CountOfCodes
+ 1) & ~1;
1999 const uint32_t *handler
= reinterpret_cast<uint32_t *>(&xdata
->UnwindCodes
[lastcode
]);
2000 _info
.lsda
= reinterpret_cast<unw_word_t
>(handler
+1);
2001 _dispContext
.HandlerData
= reinterpret_cast<void *>(_info
.lsda
);
2002 _dispContext
.LanguageHandler
=
2003 reinterpret_cast<EXCEPTION_ROUTINE
*>(base
+ *handler
);
2005 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
2019 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2020 // Masks for traceback table field xtbtable.
2021 enum xTBTableMask
: uint8_t {
2022 reservedBit
= 0x02, // The traceback table was incorrectly generated if set
2023 // (see comments in function getInfoFromTBTable().
2024 ehInfoBit
= 0x08 // Exception handling info is present if set
2027 enum frameType
: unw_word_t
{
2028 frameWithXLEHStateTable
= 0,
2033 typedef _Unwind_Reason_Code
__xlcxx_personality_v0_t(int, _Unwind_Action
,
2035 _Unwind_Exception
*,
2036 struct _Unwind_Context
*);
2037 __attribute__((__weak__
)) __xlcxx_personality_v0_t __xlcxx_personality_v0
;
2040 static __xlcxx_personality_v0_t
*xlcPersonalityV0
;
2041 static RWMutex xlcPersonalityV0InitLock
;
2043 template <typename A
, typename R
>
2044 bool UnwindCursor
<A
, R
>::getInfoFromTBTable(pint_t pc
, R
®isters
) {
2045 uint32_t *p
= reinterpret_cast<uint32_t *>(pc
);
2047 // Keep looking forward until a word of 0 is found. The traceback
2048 // table starts at the following word.
2051 tbtable
*TBTable
= reinterpret_cast<tbtable
*>(p
+ 1);
2053 if (_LIBUNWIND_TRACING_UNWINDING
) {
2054 char functionBuf
[512];
2055 const char *functionName
= functionBuf
;
2057 if (!getFunctionName(functionBuf
, sizeof(functionBuf
), &offset
)) {
2058 functionName
= ".anonymous.";
2060 _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
2061 __func__
, functionName
,
2062 reinterpret_cast<void *>(TBTable
));
2065 // If the traceback table does not contain necessary info, bypass this frame.
2066 if (!TBTable
->tb
.has_tboff
)
2069 // Structure tbtable_ext contains important data we are looking for.
2070 p
= reinterpret_cast<uint32_t *>(&TBTable
->tb_ext
);
2072 // Skip field parminfo if it exists.
2073 if (TBTable
->tb
.fixedparms
|| TBTable
->tb
.floatparms
)
2076 // p now points to tb_offset, the offset from start of function to TB table.
2077 unw_word_t start_ip
=
2078 reinterpret_cast<unw_word_t
>(TBTable
) - *p
- sizeof(uint32_t);
2079 unw_word_t end_ip
= reinterpret_cast<unw_word_t
>(TBTable
);
2082 _LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",
2083 reinterpret_cast<void *>(start_ip
),
2084 reinterpret_cast<void *>(end_ip
));
2086 // Skip field hand_mask if it exists.
2087 if (TBTable
->tb
.int_hndl
)
2090 unw_word_t lsda
= 0;
2091 unw_word_t handler
= 0;
2092 unw_word_t flags
= frameType::frameWithXLEHStateTable
;
2094 if (TBTable
->tb
.lang
== TB_CPLUSPLUS
&& TBTable
->tb
.has_ctl
) {
2095 // State table info is available. The ctl_info field indicates the
2096 // number of CTL anchors. There should be only one entry for the C++
2098 assert(*p
== 1 && "libunwind: there must be only one ctl_info entry");
2100 // p points to the offset of the state table into the stack.
2101 pint_t stateTableOffset
= *p
++;
2103 int framePointerReg
;
2105 // Skip fields name_len and name if exist.
2106 if (TBTable
->tb
.name_present
) {
2107 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(p
));
2108 p
= reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p
) + name_len
+
2112 if (TBTable
->tb
.uses_alloca
)
2113 framePointerReg
= *(reinterpret_cast<char *>(p
));
2115 framePointerReg
= 1; // default frame pointer == SP
2117 _LIBUNWIND_TRACE_UNWINDING(
2118 "framePointerReg=%d, framePointer=%p, "
2119 "stateTableOffset=%#lx\n",
2121 reinterpret_cast<void *>(_registers
.getRegister(framePointerReg
)),
2123 lsda
= _registers
.getRegister(framePointerReg
) + stateTableOffset
;
2125 // Since the traceback table generated by the legacy XLC++ does not
2126 // provide the location of the personality for the state table,
2127 // function __xlcxx_personality_v0(), which is the personality for the state
2128 // table and is exported from libc++abi, is directly assigned as the
2129 // handler here. When a legacy XLC++ frame is encountered, the symbol
2130 // is resolved dynamically using dlopen() to avoid hard dependency from
2131 // libunwind on libc++abi.
2133 // Resolve the function pointer to the state table personality if it has
2135 if (xlcPersonalityV0
== NULL
) {
2136 xlcPersonalityV0InitLock
.lock();
2137 if (xlcPersonalityV0
== NULL
) {
2138 // If libc++abi is statically linked in, symbol __xlcxx_personality_v0
2139 // has been resolved at the link time.
2140 xlcPersonalityV0
= &__xlcxx_personality_v0
;
2141 if (xlcPersonalityV0
== NULL
) {
2142 // libc++abi is dynamically linked. Resolve __xlcxx_personality_v0
2144 const char libcxxabi
[] = "libc++abi.a(libc++abi.so.1)";
2146 // The AIX dlopen() sets errno to 0 when it is successful, which
2147 // clobbers the value of errno from the user code. This is an AIX
2148 // bug because according to POSIX it should not set errno to 0. To
2149 // workaround before AIX fixes the bug, errno is saved and restored.
2150 int saveErrno
= errno
;
2151 libHandle
= dlopen(libcxxabi
, RTLD_MEMBER
| RTLD_NOW
);
2152 if (libHandle
== NULL
) {
2153 _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n",
2155 assert(0 && "dlopen() failed");
2157 xlcPersonalityV0
= reinterpret_cast<__xlcxx_personality_v0_t
*>(
2158 dlsym(libHandle
, "__xlcxx_personality_v0"));
2159 if (xlcPersonalityV0
== NULL
) {
2160 _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno
);
2161 assert(0 && "dlsym() failed");
2167 xlcPersonalityV0InitLock
.unlock();
2169 handler
= reinterpret_cast<unw_word_t
>(xlcPersonalityV0
);
2170 _LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",
2171 reinterpret_cast<void *>(lsda
),
2172 reinterpret_cast<void *>(handler
));
2173 } else if (TBTable
->tb
.longtbtable
) {
2174 // This frame has the traceback table extension. Possible cases are
2175 // 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that
2176 // is not EH aware; or, 3) a frame of other languages. We need to figure out
2177 // if the traceback table extension contains the 'eh_info' structure.
2179 // We also need to deal with the complexity arising from some XL compiler
2180 // versions use the wrong ordering of 'longtbtable' and 'has_vec' bits
2181 // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice
2182 // versa. For frames of code generated by those compilers, the 'longtbtable'
2183 // bit may be set but there isn't really a traceback table extension.
2185 // In </usr/include/sys/debug.h>, there is the following definition of
2186 // 'struct tbtable_ext'. It is not really a structure but a dummy to
2187 // collect the description of optional parts of the traceback table.
2189 // struct tbtable_ext {
2191 // char alloca_reg; /* Register for alloca automatic storage */
2192 // struct vec_ext vec_ext; /* Vector extension (if has_vec is set) */
2193 // unsigned char xtbtable; /* More tbtable fields, if longtbtable is set*/
2196 // Depending on how the 'has_vec'/'longtbtable' bit is interpreted, the data
2197 // following 'alloca_reg' can be treated either as 'struct vec_ext' or
2198 // 'unsigned char xtbtable'. 'xtbtable' bits are defined in
2199 // </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently
2200 // unused and should not be set. 'struct vec_ext' is defined in
2201 // </usr/include/sys/debug.h> as follows:
2204 // unsigned vr_saved:6; /* Number of non-volatile vector regs saved
2206 // /* first register saved is assumed to be */
2207 // /* 32 - vr_saved */
2208 // unsigned saves_vrsave:1; /* Set if vrsave is saved on the stack */
2209 // unsigned has_varargs:1;
2213 // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it
2214 // is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',
2215 // we checks if the 7th bit is set or not because 'xtbtable' should
2216 // never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved
2217 // in the future to make sure the mitigation works. This mitigation
2218 // is not 100% bullet proof because 'struct vec_ext' may not always have
2219 // 'saves_vrsave' bit set.
2221 // 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for
2222 // checking the 7th bit.
2224 // p points to field name len.
2225 uint8_t *charPtr
= reinterpret_cast<uint8_t *>(p
);
2227 // Skip fields name_len and name if they exist.
2228 if (TBTable
->tb
.name_present
) {
2229 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(charPtr
));
2230 charPtr
= charPtr
+ name_len
+ sizeof(uint16_t);
2233 // Skip field alloc_reg if it exists.
2234 if (TBTable
->tb
.uses_alloca
)
2237 // Check traceback table bit has_vec. Skip struct vec_ext if it exists.
2238 if (TBTable
->tb
.has_vec
)
2239 // Note struct vec_ext does exist at this point because whether the
2240 // ordering of longtbtable and has_vec bits is correct or not, both
2242 charPtr
+= sizeof(struct vec_ext
);
2244 // charPtr points to field 'xtbtable'. Check if the EH info is available.
2245 // Also check if the reserved bit of the extended traceback table field
2246 // 'xtbtable' is set. If it is, the traceback table was incorrectly
2247 // generated by an XL compiler that uses the wrong ordering of 'longtbtable'
2248 // and 'has_vec' bits and this is in fact 'struct vec_ext'. So skip the
2250 if ((*charPtr
& xTBTableMask::ehInfoBit
) &&
2251 !(*charPtr
& xTBTableMask::reservedBit
)) {
2252 // Mark this frame has the new EH info.
2253 flags
= frameType::frameWithEHInfo
;
2255 // eh_info is available.
2257 // The pointer is 4-byte aligned.
2258 if (reinterpret_cast<uintptr_t>(charPtr
) % 4)
2259 charPtr
+= 4 - reinterpret_cast<uintptr_t>(charPtr
) % 4;
2261 reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(
2262 registers
.getRegister(2) +
2263 *(reinterpret_cast<uintptr_t *>(charPtr
)))));
2265 // ehInfo points to structure en_info. The first member is version.
2266 // Only version 0 is currently supported.
2267 assert(*(reinterpret_cast<uint32_t *>(ehInfo
)) == 0 &&
2268 "libunwind: ehInfo version other than 0 is not supported");
2270 // Increment ehInfo to point to member lsda.
2274 // enInfo now points to member personality.
2277 _LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",
2282 _info
.start_ip
= start_ip
;
2283 _info
.end_ip
= end_ip
;
2285 _info
.handler
= handler
;
2287 _info
.flags
= flags
;
2289 _info
.unwind_info
= reinterpret_cast<unw_word_t
>(TBTable
);
2290 _info
.unwind_info_size
= 0;
2291 _info
.extra
= registers
.getRegister(2);
2296 // Step back up the stack following the frame back link.
2297 template <typename A
, typename R
>
2298 int UnwindCursor
<A
, R
>::stepWithTBTable(pint_t pc
, tbtable
*TBTable
,
2299 R
®isters
, bool &isSignalFrame
) {
2300 if (_LIBUNWIND_TRACING_UNWINDING
) {
2301 char functionBuf
[512];
2302 const char *functionName
= functionBuf
;
2304 if (!getFunctionName(functionBuf
, sizeof(functionBuf
), &offset
)) {
2305 functionName
= ".anonymous.";
2307 _LIBUNWIND_TRACE_UNWINDING(
2308 "%s: Look up traceback table of func=%s at %p, pc=%p, "
2309 "SP=%p, saves_lr=%d, stores_bc=%d",
2310 __func__
, functionName
, reinterpret_cast<void *>(TBTable
),
2311 reinterpret_cast<void *>(pc
),
2312 reinterpret_cast<void *>(registers
.getSP()), TBTable
->tb
.saves_lr
,
2313 TBTable
->tb
.stores_bc
);
2316 #if defined(__powerpc64__)
2317 // Instruction to reload TOC register "ld r2,40(r1)"
2318 const uint32_t loadTOCRegInst
= 0xe8410028;
2319 const int32_t unwPPCF0Index
= UNW_PPC64_F0
;
2320 const int32_t unwPPCV0Index
= UNW_PPC64_V0
;
2322 // Instruction to reload TOC register "lwz r2,20(r1)"
2323 const uint32_t loadTOCRegInst
= 0x80410014;
2324 const int32_t unwPPCF0Index
= UNW_PPC_F0
;
2325 const int32_t unwPPCV0Index
= UNW_PPC_V0
;
2328 // lastStack points to the stack frame of the next routine up.
2329 pint_t curStack
= static_cast<pint_t
>(registers
.getSP());
2330 pint_t lastStack
= *reinterpret_cast<pint_t
*>(curStack
);
2333 return UNW_STEP_END
;
2335 R newRegisters
= registers
;
2337 // If backchain is not stored, use the current stack frame.
2338 if (!TBTable
->tb
.stores_bc
)
2339 lastStack
= curStack
;
2341 // Return address is the address after call site instruction.
2342 pint_t returnAddress
;
2344 if (isSignalFrame
) {
2345 _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
2346 reinterpret_cast<void *>(lastStack
));
2348 sigcontext
*sigContext
= reinterpret_cast<sigcontext
*>(
2349 reinterpret_cast<char *>(lastStack
) + STKMINALIGN
);
2350 returnAddress
= sigContext
->sc_jmpbuf
.jmp_context
.iar
;
2352 bool useSTKMIN
= false;
2353 if (returnAddress
< 0x10000000) {
2354 // Try again using STKMIN.
2355 sigContext
= reinterpret_cast<sigcontext
*>(
2356 reinterpret_cast<char *>(lastStack
) + STKMIN
);
2357 returnAddress
= sigContext
->sc_jmpbuf
.jmp_context
.iar
;
2358 if (returnAddress
< 0x10000000) {
2359 _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
2360 reinterpret_cast<void *>(returnAddress
),
2361 reinterpret_cast<void *>(sigContext
));
2362 return UNW_EBADFRAME
;
2366 _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
2367 "sigContext=%p, returnAddress=%p. "
2368 "Seems to be a valid address",
2369 useSTKMIN
? "STKMIN" : "STKMINALIGN",
2370 reinterpret_cast<void *>(sigContext
),
2371 reinterpret_cast<void *>(returnAddress
));
2373 // Restore the condition register from sigcontext.
2374 newRegisters
.setCR(sigContext
->sc_jmpbuf
.jmp_context
.cr
);
2376 // Save the LR in sigcontext for stepping up when the function that
2377 // raised the signal is a leaf function. This LR has the return address
2378 // to the caller of the leaf function.
2379 newRegisters
.setLR(sigContext
->sc_jmpbuf
.jmp_context
.lr
);
2380 _LIBUNWIND_TRACE_UNWINDING(
2381 "Save LR=%p from sigcontext",
2382 reinterpret_cast<void *>(sigContext
->sc_jmpbuf
.jmp_context
.lr
));
2384 // Restore GPRs from sigcontext.
2385 for (int i
= 0; i
< 32; ++i
)
2386 newRegisters
.setRegister(i
, sigContext
->sc_jmpbuf
.jmp_context
.gpr
[i
]);
2388 // Restore FPRs from sigcontext.
2389 for (int i
= 0; i
< 32; ++i
)
2390 newRegisters
.setFloatRegister(i
+ unwPPCF0Index
,
2391 sigContext
->sc_jmpbuf
.jmp_context
.fpr
[i
]);
2393 // Restore vector registers if there is an associated extended context
2395 if (sigContext
->sc_jmpbuf
.jmp_context
.msr
& __EXTCTX
) {
2396 ucontext_t
*uContext
= reinterpret_cast<ucontext_t
*>(sigContext
);
2397 if (uContext
->__extctx
->__extctx_magic
== __EXTCTX_MAGIC
) {
2398 for (int i
= 0; i
< 32; ++i
)
2399 newRegisters
.setVectorRegister(
2400 i
+ unwPPCV0Index
, *(reinterpret_cast<v128
*>(
2401 &(uContext
->__extctx
->__vmx
.__vr
[i
]))));
2405 // Step up a normal frame.
2407 if (!TBTable
->tb
.saves_lr
&& registers
.getLR()) {
2408 // This case should only occur if we were called from a signal handler
2409 // and the signal occurred in a function that doesn't save the LR.
2410 returnAddress
= static_cast<pint_t
>(registers
.getLR());
2411 _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
2412 reinterpret_cast<void *>(returnAddress
));
2414 // Otherwise, use the LR value in the stack link area.
2415 returnAddress
= reinterpret_cast<pint_t
*>(lastStack
)[2];
2418 // Reset LR in the current context.
2419 newRegisters
.setLR(NULL
);
2421 _LIBUNWIND_TRACE_UNWINDING(
2422 "Extract info from lastStack=%p, returnAddress=%p",
2423 reinterpret_cast<void *>(lastStack
),
2424 reinterpret_cast<void *>(returnAddress
));
2425 _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
2426 TBTable
->tb
.fpr_saved
, TBTable
->tb
.gpr_saved
,
2427 TBTable
->tb
.saves_cr
);
2429 // Restore FP registers.
2430 char *ptrToRegs
= reinterpret_cast<char *>(lastStack
);
2431 double *FPRegs
= reinterpret_cast<double *>(
2432 ptrToRegs
- (TBTable
->tb
.fpr_saved
* sizeof(double)));
2433 for (int i
= 0; i
< TBTable
->tb
.fpr_saved
; ++i
)
2434 newRegisters
.setFloatRegister(
2435 32 - TBTable
->tb
.fpr_saved
+ i
+ unwPPCF0Index
, FPRegs
[i
]);
2437 // Restore GP registers.
2438 ptrToRegs
= reinterpret_cast<char *>(FPRegs
);
2439 uintptr_t *GPRegs
= reinterpret_cast<uintptr_t *>(
2440 ptrToRegs
- (TBTable
->tb
.gpr_saved
* sizeof(uintptr_t)));
2441 for (int i
= 0; i
< TBTable
->tb
.gpr_saved
; ++i
)
2442 newRegisters
.setRegister(32 - TBTable
->tb
.gpr_saved
+ i
, GPRegs
[i
]);
2444 // Restore Vector registers.
2445 ptrToRegs
= reinterpret_cast<char *>(GPRegs
);
2447 // Restore vector registers only if this is a Clang frame. Also
2448 // check if traceback table bit has_vec is set. If it is, structure
2449 // vec_ext is available.
2450 if (_info
.flags
== frameType::frameWithEHInfo
&& TBTable
->tb
.has_vec
) {
2452 // Get to the vec_ext structure to check if vector registers are saved.
2453 uint32_t *p
= reinterpret_cast<uint32_t *>(&TBTable
->tb_ext
);
2455 // Skip field parminfo if exists.
2456 if (TBTable
->tb
.fixedparms
|| TBTable
->tb
.floatparms
)
2459 // Skip field tb_offset if exists.
2460 if (TBTable
->tb
.has_tboff
)
2463 // Skip field hand_mask if exists.
2464 if (TBTable
->tb
.int_hndl
)
2467 // Skip fields ctl_info and ctl_info_disp if exist.
2468 if (TBTable
->tb
.has_ctl
) {
2469 // Skip field ctl_info.
2471 // Skip field ctl_info_disp.
2475 // Skip fields name_len and name if exist.
2476 // p is supposed to point to field name_len now.
2477 uint8_t *charPtr
= reinterpret_cast<uint8_t *>(p
);
2478 if (TBTable
->tb
.name_present
) {
2479 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(charPtr
));
2480 charPtr
= charPtr
+ name_len
+ sizeof(uint16_t);
2483 // Skip field alloc_reg if it exists.
2484 if (TBTable
->tb
.uses_alloca
)
2487 struct vec_ext
*vec_ext
= reinterpret_cast<struct vec_ext
*>(charPtr
);
2489 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext
->vr_saved
);
2491 // Restore vector register(s) if saved on the stack.
2492 if (vec_ext
->vr_saved
) {
2493 // Saved vector registers are 16-byte aligned.
2494 if (reinterpret_cast<uintptr_t>(ptrToRegs
) % 16)
2495 ptrToRegs
-= reinterpret_cast<uintptr_t>(ptrToRegs
) % 16;
2496 v128
*VecRegs
= reinterpret_cast<v128
*>(ptrToRegs
- vec_ext
->vr_saved
*
2498 for (int i
= 0; i
< vec_ext
->vr_saved
; ++i
) {
2499 newRegisters
.setVectorRegister(
2500 32 - vec_ext
->vr_saved
+ i
+ unwPPCV0Index
, VecRegs
[i
]);
2504 if (TBTable
->tb
.saves_cr
) {
2505 // Get the saved condition register. The condition register is only
2508 *(reinterpret_cast<uint32_t *>(lastStack
+ sizeof(uintptr_t))));
2512 newRegisters
.setSP(lastStack
);
2514 // The first instruction after return.
2515 uint32_t firstInstruction
= *(reinterpret_cast<uint32_t *>(returnAddress
));
2517 // Do we need to set the TOC register?
2518 _LIBUNWIND_TRACE_UNWINDING(
2520 reinterpret_cast<void *>(newRegisters
.getRegister(2)));
2521 if (firstInstruction
== loadTOCRegInst
) {
2522 _LIBUNWIND_TRACE_UNWINDING(
2523 "Set gpr2=%p from frame",
2524 reinterpret_cast<void *>(reinterpret_cast<pint_t
*>(lastStack
)[5]));
2525 newRegisters
.setRegister(2, reinterpret_cast<pint_t
*>(lastStack
)[5]);
2528 _LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",
2529 reinterpret_cast<void *>(lastStack
),
2530 reinterpret_cast<void *>(returnAddress
),
2531 reinterpret_cast<void *>(pc
));
2533 // The return address is the address after call site instruction, so
2534 // setting IP to that simulates a return.
2535 newRegisters
.setIP(reinterpret_cast<uintptr_t>(returnAddress
));
2537 // Simulate the step by replacing the register set with the new ones.
2538 registers
= newRegisters
;
2540 // Check if the next frame is a signal frame.
2541 pint_t nextStack
= *(reinterpret_cast<pint_t
*>(registers
.getSP()));
2543 // Return address is the address after call site instruction.
2544 pint_t nextReturnAddress
= reinterpret_cast<pint_t
*>(nextStack
)[2];
2546 if (nextReturnAddress
> 0x01 && nextReturnAddress
< 0x10000) {
2547 _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
2548 "nextStack=%p, next return address=%p\n",
2549 reinterpret_cast<void *>(nextStack
),
2550 reinterpret_cast<void *>(nextReturnAddress
));
2551 isSignalFrame
= true;
2553 isSignalFrame
= false;
2555 return UNW_STEP_SUCCESS
;
2557 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2559 template <typename A
, typename R
>
2560 void UnwindCursor
<A
, R
>::setInfoBasedOnIPRegister(bool isReturnAddress
) {
2561 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2562 _isSigReturn
= false;
2565 pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2566 #if defined(_LIBUNWIND_ARM_EHABI)
2567 // Remove the thumb bit so the IP represents the actual instruction address.
2568 // This matches the behaviour of _Unwind_GetIP on arm.
2572 // Exit early if at the top of the stack.
2574 _unwindInfoMissing
= true;
2578 // If the last line of a function is a "throw" the compiler sometimes
2579 // emits no instructions after the call to __cxa_throw. This means
2580 // the return address is actually the start of the next function.
2581 // To disambiguate this, back up the pc when we know it is a return
2583 if (isReturnAddress
)
2585 // PC needs to be a 4-byte aligned address to be able to look for a
2586 // word of 0 that indicates the start of the traceback table at the end
2587 // of a function on AIX.
2593 // Ask address space object to find unwind sections for this pc.
2594 UnwindInfoSections sects
;
2595 if (_addressSpace
.findUnwindSections(pc
, sects
)) {
2596 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2597 // If there is a compact unwind encoding table, look there first.
2598 if (sects
.compact_unwind_section
!= 0) {
2599 if (this->getInfoFromCompactEncodingSection(pc
, sects
)) {
2600 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2601 // Found info in table, done unless encoding says to use dwarf.
2602 uint32_t dwarfOffset
;
2603 if ((sects
.dwarf_section
!= 0) && compactSaysUseDwarf(&dwarfOffset
)) {
2604 if (this->getInfoFromDwarfSection(pc
, sects
, dwarfOffset
)) {
2605 // found info in dwarf, done
2610 // If unwind table has entry, but entry says there is no unwind info,
2611 // record that we have no unwind info.
2612 if (_info
.format
== 0)
2613 _unwindInfoMissing
= true;
2617 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2619 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2620 // If there is SEH unwind info, look there next.
2621 if (this->getInfoFromSEH(pc
))
2625 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2626 // If there is unwind info in the traceback table, look there next.
2627 if (this->getInfoFromTBTable(pc
, _registers
))
2631 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2632 // If there is dwarf unwind info, look there next.
2633 if (sects
.dwarf_section
!= 0) {
2634 if (this->getInfoFromDwarfSection(pc
, sects
)) {
2635 // found info in dwarf, done
2641 #if defined(_LIBUNWIND_ARM_EHABI)
2642 // If there is ARM EHABI unwind info, look there next.
2643 if (sects
.arm_section
!= 0 && this->getInfoFromEHABISection(pc
, sects
))
2648 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2649 // There is no static unwind info for this pc. Look to see if an FDE was
2650 // dynamically registered for it.
2651 pint_t cachedFDE
= DwarfFDECache
<A
>::findFDE(DwarfFDECache
<A
>::kSearchAll
,
2653 if (cachedFDE
!= 0) {
2654 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
2655 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
2656 if (!CFI_Parser
<A
>::decodeFDE(_addressSpace
, cachedFDE
, &fdeInfo
, &cieInfo
))
2657 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, 0))
2661 // Lastly, ask AddressSpace object about platform specific ways to locate
2664 if (_addressSpace
.findOtherFDE(pc
, fde
)) {
2665 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
2666 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
2667 if (!CFI_Parser
<A
>::decodeFDE(_addressSpace
, fde
, &fdeInfo
, &cieInfo
)) {
2668 // Double check this FDE is for a function that includes the pc.
2669 if ((fdeInfo
.pcStart
<= pc
) && (pc
< fdeInfo
.pcEnd
))
2670 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, 0))
2674 #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2676 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2677 if (setInfoForSigReturn())
2681 // no unwind info, flag that we can't reliably unwind
2682 _unwindInfoMissing
= true;
2685 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2686 defined(_LIBUNWIND_TARGET_AARCH64)
2687 template <typename A
, typename R
>
2688 bool UnwindCursor
<A
, R
>::setInfoForSigReturn(Registers_arm64
&) {
2689 // Look for the sigreturn trampoline. The trampoline's body is two
2690 // specific instructions (see below). Typically the trampoline comes from the
2691 // vDSO[1] (i.e. the __kernel_rt_sigreturn function). A libc might provide its
2692 // own restorer function, though, or user-mode QEMU might write a trampoline
2695 // This special code path is a fallback that is only used if the trampoline
2696 // lacks proper (e.g. DWARF) unwind info. On AArch64, a new DWARF register
2697 // constant for the PC needs to be defined before DWARF can handle a signal
2698 // trampoline. This code may segfault if the target PC is unreadable, e.g.:
2699 // - The PC points at a function compiled without unwind info, and which is
2700 // part of an execute-only mapping (e.g. using -Wl,--execute-only).
2701 // - The PC is invalid and happens to point to unreadable or unmapped memory.
2703 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
2704 const pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2705 // The PC might contain an invalid address if the unwind info is bad, so
2706 // directly accessing it could cause a SIGSEGV.
2707 if (!isReadableAddr(pc
))
2709 auto *instructions
= reinterpret_cast<const uint32_t *>(pc
);
2710 // Look for instructions: mov x8, #0x8b; svc #0x0
2711 if (instructions
[0] != 0xd2801168 || instructions
[1] != 0xd4000001)
2715 _info
.start_ip
= pc
;
2716 _info
.end_ip
= pc
+ 4;
2717 _isSigReturn
= true;
2721 template <typename A
, typename R
>
2722 int UnwindCursor
<A
, R
>::stepThroughSigReturn(Registers_arm64
&) {
2723 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2724 // - 128-byte siginfo struct
2725 // - ucontext struct:
2726 // - 8-byte long (uc_flags)
2727 // - 8-byte pointer (uc_link)
2728 // - 24-byte stack_t
2729 // - 128-byte signal set
2730 // - 8 bytes of padding because sigcontext has 16-byte alignment
2731 // - sigcontext/mcontext_t
2732 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c
2733 const pint_t kOffsetSpToSigcontext
= (128 + 8 + 8 + 24 + 128 + 8); // 304
2735 // Offsets from sigcontext to each register.
2736 const pint_t kOffsetGprs
= 8; // offset to "__u64 regs[31]" field
2737 const pint_t kOffsetSp
= 256; // offset to "__u64 sp" field
2738 const pint_t kOffsetPc
= 264; // offset to "__u64 pc" field
2740 pint_t sigctx
= _registers
.getSP() + kOffsetSpToSigcontext
;
2742 for (int i
= 0; i
<= 30; ++i
) {
2743 uint64_t value
= _addressSpace
.get64(sigctx
+ kOffsetGprs
+
2744 static_cast<pint_t
>(i
* 8));
2745 _registers
.setRegister(UNW_AARCH64_X0
+ i
, value
);
2747 _registers
.setSP(_addressSpace
.get64(sigctx
+ kOffsetSp
));
2748 _registers
.setIP(_addressSpace
.get64(sigctx
+ kOffsetPc
));
2749 _isSignalFrame
= true;
2750 return UNW_STEP_SUCCESS
;
2752 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2753 // defined(_LIBUNWIND_TARGET_AARCH64)
2755 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2756 defined(_LIBUNWIND_TARGET_RISCV)
2757 template <typename A
, typename R
>
2758 bool UnwindCursor
<A
, R
>::setInfoForSigReturn(Registers_riscv
&) {
2759 const pint_t pc
= static_cast<pint_t
>(getReg(UNW_REG_IP
));
2760 // The PC might contain an invalid address if the unwind info is bad, so
2761 // directly accessing it could cause a SIGSEGV.
2762 if (!isReadableAddr(pc
))
2764 const auto *instructions
= reinterpret_cast<const uint32_t *>(pc
);
2765 // Look for the two instructions used in the sigreturn trampoline
2766 // __vdso_rt_sigreturn:
2768 // 0x08b00893 li a7,0x8b
2770 if (instructions
[0] != 0x08b00893 || instructions
[1] != 0x00000073)
2774 _info
.start_ip
= pc
;
2775 _info
.end_ip
= pc
+ 4;
2776 _isSigReturn
= true;
2780 template <typename A
, typename R
>
2781 int UnwindCursor
<A
, R
>::stepThroughSigReturn(Registers_riscv
&) {
2782 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2783 // - 128-byte siginfo struct
2784 // - ucontext_t struct:
2785 // - 8-byte long (__uc_flags)
2786 // - 8-byte pointer (*uc_link)
2787 // - 24-byte uc_stack
2788 // - 8-byte uc_sigmask
2789 // - 120-byte of padding to allow sigset_t to be expanded in the future
2790 // - 8 bytes of padding because sigcontext has 16-byte alignment
2791 // - struct sigcontext uc_mcontext
2793 // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
2794 const pint_t kOffsetSpToSigcontext
= 128 + 8 + 8 + 24 + 8 + 128;
2796 const pint_t sigctx
= _registers
.getSP() + kOffsetSpToSigcontext
;
2797 _registers
.setIP(_addressSpace
.get64(sigctx
));
2798 for (int i
= UNW_RISCV_X1
; i
<= UNW_RISCV_X31
; ++i
) {
2799 uint64_t value
= _addressSpace
.get64(sigctx
+ static_cast<pint_t
>(i
* 8));
2800 _registers
.setRegister(i
, value
);
2802 _isSignalFrame
= true;
2803 return UNW_STEP_SUCCESS
;
2805 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2806 // defined(_LIBUNWIND_TARGET_RISCV)
2808 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
2809 defined(_LIBUNWIND_TARGET_S390X)
2810 template <typename A
, typename R
>
2811 bool UnwindCursor
<A
, R
>::setInfoForSigReturn(Registers_s390x
&) {
2812 // Look for the sigreturn trampoline. The trampoline's body is a
2813 // specific instruction (see below). Typically the trampoline comes from the
2814 // vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its
2815 // own restorer function, though, or user-mode QEMU might write a trampoline
2817 const pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2818 // The PC might contain an invalid address if the unwind info is bad, so
2819 // directly accessing it could cause a SIGSEGV.
2820 if (!isReadableAddr(pc
))
2822 const auto inst
= *reinterpret_cast<const uint16_t *>(pc
);
2823 if (inst
== 0x0a77 || inst
== 0x0aad) {
2825 _info
.start_ip
= pc
;
2826 _info
.end_ip
= pc
+ 2;
2827 _isSigReturn
= true;
2833 template <typename A
, typename R
>
2834 int UnwindCursor
<A
, R
>::stepThroughSigReturn(Registers_s390x
&) {
2835 // Determine current SP.
2836 const pint_t sp
= static_cast<pint_t
>(this->getReg(UNW_REG_SP
));
2837 // According to the s390x ABI, the CFA is at (incoming) SP + 160.
2838 const pint_t cfa
= sp
+ 160;
2840 // Determine current PC and instruction there (this must be either
2841 // a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn").
2842 const pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2843 const uint16_t inst
= _addressSpace
.get16(pc
);
2845 // Find the addresses of the signo and sigcontext in the frame.
2849 // "svc __NR_sigreturn" uses a non-RT signal trampoline frame.
2850 if (inst
== 0x0a77) {
2851 // Layout of a non-RT signal trampoline frame, starting at the CFA:
2852 // - 8-byte signal mask
2853 // - 8-byte pointer to sigcontext, followed by signo
2855 pSigctx
= _addressSpace
.get64(cfa
+ 8);
2856 pSigno
= pSigctx
+ 344;
2859 // "svc __NR_rt_sigreturn" uses a RT signal trampoline frame.
2860 if (inst
== 0x0aad) {
2861 // Layout of a RT signal trampoline frame, starting at the CFA:
2862 // - 8-byte retcode (+ alignment)
2863 // - 128-byte siginfo struct (starts with signo)
2864 // - ucontext struct:
2865 // - 8-byte long (uc_flags)
2866 // - 8-byte pointer (uc_link)
2867 // - 24-byte stack_t
2868 // - 8 bytes of padding because sigcontext has 16-byte alignment
2869 // - sigcontext/mcontext_t
2870 pSigctx
= cfa
+ 8 + 128 + 8 + 8 + 24 + 8;
2874 assert(pSigctx
!= 0);
2875 assert(pSigno
!= 0);
2877 // Offsets from sigcontext to each register.
2878 const pint_t kOffsetPc
= 8;
2879 const pint_t kOffsetGprs
= 16;
2880 const pint_t kOffsetFprs
= 216;
2882 // Restore all registers.
2883 for (int i
= 0; i
< 16; ++i
) {
2884 uint64_t value
= _addressSpace
.get64(pSigctx
+ kOffsetGprs
+
2885 static_cast<pint_t
>(i
* 8));
2886 _registers
.setRegister(UNW_S390X_R0
+ i
, value
);
2888 for (int i
= 0; i
< 16; ++i
) {
2889 static const int fpr
[16] = {
2890 UNW_S390X_F0
, UNW_S390X_F1
, UNW_S390X_F2
, UNW_S390X_F3
,
2891 UNW_S390X_F4
, UNW_S390X_F5
, UNW_S390X_F6
, UNW_S390X_F7
,
2892 UNW_S390X_F8
, UNW_S390X_F9
, UNW_S390X_F10
, UNW_S390X_F11
,
2893 UNW_S390X_F12
, UNW_S390X_F13
, UNW_S390X_F14
, UNW_S390X_F15
2895 double value
= _addressSpace
.getDouble(pSigctx
+ kOffsetFprs
+
2896 static_cast<pint_t
>(i
* 8));
2897 _registers
.setFloatRegister(fpr
[i
], value
);
2899 _registers
.setIP(_addressSpace
.get64(pSigctx
+ kOffsetPc
));
2901 // SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
2902 // after the faulting instruction rather than before it.
2903 // Do not set _isSignalFrame in that case.
2904 uint32_t signo
= _addressSpace
.get32(pSigno
);
2905 _isSignalFrame
= (signo
!= 4 && signo
!= 5 && signo
!= 8);
2907 return UNW_STEP_SUCCESS
;
2909 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2910 // defined(_LIBUNWIND_TARGET_S390X)
2912 template <typename A
, typename R
> int UnwindCursor
<A
, R
>::step(bool stage2
) {
2914 // Bottom of stack is defined is when unwind info cannot be found.
2915 if (_unwindInfoMissing
)
2916 return UNW_STEP_END
;
2918 // Use unwinding info to modify register set as if function returned.
2920 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2922 result
= this->stepThroughSigReturn();
2926 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2927 result
= this->stepWithCompactEncoding(stage2
);
2928 #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2929 result
= this->stepWithSEHData();
2930 #elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2931 result
= this->stepWithTBTableData();
2932 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2933 result
= this->stepWithDwarfFDE(stage2
);
2934 #elif defined(_LIBUNWIND_ARM_EHABI)
2935 result
= this->stepWithEHABI();
2937 #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
2938 _LIBUNWIND_SUPPORT_SEH_UNWIND or \
2939 _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
2940 _LIBUNWIND_ARM_EHABI
2944 // update info based on new PC
2945 if (result
== UNW_STEP_SUCCESS
) {
2946 this->setInfoBasedOnIPRegister(true);
2947 if (_unwindInfoMissing
)
2948 return UNW_STEP_END
;
2954 template <typename A
, typename R
>
2955 void UnwindCursor
<A
, R
>::getInfo(unw_proc_info_t
*info
) {
2956 if (_unwindInfoMissing
)
2957 memset(info
, 0, sizeof(*info
));
2962 template <typename A
, typename R
>
2963 bool UnwindCursor
<A
, R
>::getFunctionName(char *buf
, size_t bufLen
,
2964 unw_word_t
*offset
) {
2965 return _addressSpace
.findFunctionName((pint_t
)this->getReg(UNW_REG_IP
),
2966 buf
, bufLen
, offset
);
2969 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2970 template <typename A
, typename R
>
2971 bool UnwindCursor
<A
, R
>::isReadableAddr(const pint_t addr
) const {
2972 // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable.
2974 const auto sigsetAddr
= reinterpret_cast<sigset_t
*>(addr
);
2975 // We have to check that addr is nullptr because sigprocmask allows that
2976 // as an argument without failure.
2979 const auto saveErrno
= errno
;
2980 // We MUST use a raw syscall here, as wrappers may try to access
2981 // sigsetAddr which may cause a SIGSEGV. A raw syscall however is
2982 // safe. Additionally, we need to pass the kernel_sigset_size, which is
2983 // different from libc sizeof(sigset_t). For the majority of architectures,
2984 // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
2985 const auto kernelSigsetSize
= NSIG
/ 8;
2986 [[maybe_unused
]] const int Result
= syscall(
2987 SYS_rt_sigprocmask
, /*how=*/~0, sigsetAddr
, nullptr, kernelSigsetSize
);
2988 // Because our "how" is invalid, this syscall should always fail, and our
2989 // errno should always be EINVAL or an EFAULT. This relies on the Linux
2990 // kernel to check copy_from_user before checking if the "how" argument is
2992 assert(Result
== -1);
2993 assert(errno
== EFAULT
|| errno
== EINVAL
);
2994 const auto readable
= errno
!= EFAULT
;
3000 #if defined(_LIBUNWIND_USE_CET)
3001 extern "C" void *__libunwind_cet_get_registers(unw_cursor_t
*cursor
) {
3002 AbstractUnwindCursor
*co
= (AbstractUnwindCursor
*)cursor
;
3003 return co
->get_registers();
3006 } // namespace libunwind
3008 #endif // __UNWINDCURSOR_HPP__