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>
40 #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
43 #include "AddressSpace.hpp"
44 #include "CompactUnwinder.hpp"
46 #include "DwarfInstructions.hpp"
47 #include "EHHeaderParser.hpp"
48 #include "libunwind.h"
49 #include "libunwind_ext.h"
50 #include "Registers.hpp"
51 #include "RWMutex.hpp"
52 #include "Unwind-EHABI.h"
54 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
55 // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
57 // MinGW-w64 has always provided this struct.
58 #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
59 !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
60 struct _DISPATCHER_CONTEXT
{
63 PRUNTIME_FUNCTION FunctionEntry
;
64 ULONG64 EstablisherFrame
;
66 PCONTEXT ContextRecord
;
67 PEXCEPTION_ROUTINE LanguageHandler
;
69 PUNWIND_HISTORY_TABLE HistoryTable
;
80 uint8_t FrameRegister
: 4;
81 uint8_t FrameOffset
: 4;
82 uint16_t UnwindCodes
[2];
85 extern "C" _Unwind_Reason_Code
__libunwind_seh_personality(
86 int, _Unwind_Action
, uint64_t, _Unwind_Exception
*,
87 struct _Unwind_Context
*);
93 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
94 /// Cache of recently found FDEs.
96 class _LIBUNWIND_HIDDEN DwarfFDECache
{
97 typedef typename
A::pint_t pint_t
;
99 static constexpr pint_t kSearchAll
= static_cast<pint_t
>(-1);
100 static pint_t
findFDE(pint_t mh
, pint_t pc
);
101 static void add(pint_t mh
, pint_t ip_start
, pint_t ip_end
, pint_t fde
);
102 static void removeAllIn(pint_t mh
);
103 static void iterateCacheEntries(void (*func
)(unw_word_t ip_start
,
105 unw_word_t fde
, unw_word_t mh
));
116 // These fields are all static to avoid needing an initializer.
117 // There is only one instance of this class per process.
118 static RWMutex _lock
;
120 static void dyldUnloadHook(const struct mach_header
*mh
, intptr_t slide
);
121 static bool _registeredForDyldUnloads
;
123 static entry
*_buffer
;
124 static entry
*_bufferUsed
;
125 static entry
*_bufferEnd
;
126 static entry _initialBuffer
[64];
129 template <typename A
>
130 typename DwarfFDECache
<A
>::entry
*
131 DwarfFDECache
<A
>::_buffer
= _initialBuffer
;
133 template <typename A
>
134 typename DwarfFDECache
<A
>::entry
*
135 DwarfFDECache
<A
>::_bufferUsed
= _initialBuffer
;
137 template <typename A
>
138 typename DwarfFDECache
<A
>::entry
*
139 DwarfFDECache
<A
>::_bufferEnd
= &_initialBuffer
[64];
141 template <typename A
>
142 typename DwarfFDECache
<A
>::entry DwarfFDECache
<A
>::_initialBuffer
[64];
144 template <typename A
>
145 RWMutex DwarfFDECache
<A
>::_lock
;
148 template <typename A
>
149 bool DwarfFDECache
<A
>::_registeredForDyldUnloads
= false;
152 template <typename A
>
153 typename
A::pint_t DwarfFDECache
<A
>::findFDE(pint_t mh
, pint_t pc
) {
155 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock_shared());
156 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
157 if ((mh
== p
->mh
) || (mh
== kSearchAll
)) {
158 if ((p
->ip_start
<= pc
) && (pc
< p
->ip_end
)) {
164 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock_shared());
168 template <typename A
>
169 void DwarfFDECache
<A
>::add(pint_t mh
, pint_t ip_start
, pint_t ip_end
,
171 #if !defined(_LIBUNWIND_NO_HEAP)
172 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
173 if (_bufferUsed
>= _bufferEnd
) {
174 size_t oldSize
= (size_t)(_bufferEnd
- _buffer
);
175 size_t newSize
= oldSize
* 4;
176 // Can't use operator new (we are below it).
177 entry
*newBuffer
= (entry
*)malloc(newSize
* sizeof(entry
));
178 memcpy(newBuffer
, _buffer
, oldSize
* sizeof(entry
));
179 if (_buffer
!= _initialBuffer
)
182 _bufferUsed
= &newBuffer
[oldSize
];
183 _bufferEnd
= &newBuffer
[newSize
];
185 _bufferUsed
->mh
= mh
;
186 _bufferUsed
->ip_start
= ip_start
;
187 _bufferUsed
->ip_end
= ip_end
;
188 _bufferUsed
->fde
= fde
;
191 if (!_registeredForDyldUnloads
) {
192 _dyld_register_func_for_remove_image(&dyldUnloadHook
);
193 _registeredForDyldUnloads
= true;
196 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
200 template <typename A
>
201 void DwarfFDECache
<A
>::removeAllIn(pint_t mh
) {
202 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
204 for (const entry
*s
= _buffer
; s
< _bufferUsed
; ++s
) {
212 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
216 template <typename A
>
217 void DwarfFDECache
<A
>::dyldUnloadHook(const struct mach_header
*mh
, intptr_t ) {
218 removeAllIn((pint_t
) mh
);
222 template <typename A
>
223 void DwarfFDECache
<A
>::iterateCacheEntries(void (*func
)(
224 unw_word_t ip_start
, unw_word_t ip_end
, unw_word_t fde
, unw_word_t mh
)) {
225 _LIBUNWIND_LOG_IF_FALSE(_lock
.lock());
226 for (entry
*p
= _buffer
; p
< _bufferUsed
; ++p
) {
227 (*func
)(p
->ip_start
, p
->ip_end
, p
->fde
, p
->mh
);
229 _LIBUNWIND_LOG_IF_FALSE(_lock
.unlock());
231 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
233 #define arrayoffsetof(type, index, field) \
234 (sizeof(type) * (index) + offsetof(type, field))
236 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
237 template <typename A
> class UnwindSectionHeader
{
239 UnwindSectionHeader(A
&addressSpace
, typename
A::pint_t addr
)
240 : _addressSpace(addressSpace
), _addr(addr
) {}
242 uint32_t version() const {
243 return _addressSpace
.get32(_addr
+
244 offsetof(unwind_info_section_header
, version
));
246 uint32_t commonEncodingsArraySectionOffset() const {
247 return _addressSpace
.get32(_addr
+
248 offsetof(unwind_info_section_header
,
249 commonEncodingsArraySectionOffset
));
251 uint32_t commonEncodingsArrayCount() const {
252 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
253 commonEncodingsArrayCount
));
255 uint32_t personalityArraySectionOffset() const {
256 return _addressSpace
.get32(_addr
+ offsetof(unwind_info_section_header
,
257 personalityArraySectionOffset
));
259 uint32_t personalityArrayCount() const {
260 return _addressSpace
.get32(
261 _addr
+ offsetof(unwind_info_section_header
, personalityArrayCount
));
263 uint32_t indexSectionOffset() const {
264 return _addressSpace
.get32(
265 _addr
+ offsetof(unwind_info_section_header
, indexSectionOffset
));
267 uint32_t indexCount() const {
268 return _addressSpace
.get32(
269 _addr
+ offsetof(unwind_info_section_header
, indexCount
));
274 typename
A::pint_t _addr
;
277 template <typename A
> class UnwindSectionIndexArray
{
279 UnwindSectionIndexArray(A
&addressSpace
, typename
A::pint_t addr
)
280 : _addressSpace(addressSpace
), _addr(addr
) {}
282 uint32_t functionOffset(uint32_t index
) const {
283 return _addressSpace
.get32(
284 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
287 uint32_t secondLevelPagesSectionOffset(uint32_t index
) const {
288 return _addressSpace
.get32(
289 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
290 secondLevelPagesSectionOffset
));
292 uint32_t lsdaIndexArraySectionOffset(uint32_t index
) const {
293 return _addressSpace
.get32(
294 _addr
+ arrayoffsetof(unwind_info_section_header_index_entry
, index
,
295 lsdaIndexArraySectionOffset
));
300 typename
A::pint_t _addr
;
303 template <typename A
> class UnwindSectionRegularPageHeader
{
305 UnwindSectionRegularPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
306 : _addressSpace(addressSpace
), _addr(addr
) {}
308 uint32_t kind() const {
309 return _addressSpace
.get32(
310 _addr
+ offsetof(unwind_info_regular_second_level_page_header
, kind
));
312 uint16_t entryPageOffset() const {
313 return _addressSpace
.get16(
314 _addr
+ offsetof(unwind_info_regular_second_level_page_header
,
317 uint16_t entryCount() const {
318 return _addressSpace
.get16(
320 offsetof(unwind_info_regular_second_level_page_header
, entryCount
));
325 typename
A::pint_t _addr
;
328 template <typename A
> class UnwindSectionRegularArray
{
330 UnwindSectionRegularArray(A
&addressSpace
, typename
A::pint_t addr
)
331 : _addressSpace(addressSpace
), _addr(addr
) {}
333 uint32_t functionOffset(uint32_t index
) const {
334 return _addressSpace
.get32(
335 _addr
+ arrayoffsetof(unwind_info_regular_second_level_entry
, index
,
338 uint32_t encoding(uint32_t index
) const {
339 return _addressSpace
.get32(
341 arrayoffsetof(unwind_info_regular_second_level_entry
, index
, encoding
));
346 typename
A::pint_t _addr
;
349 template <typename A
> class UnwindSectionCompressedPageHeader
{
351 UnwindSectionCompressedPageHeader(A
&addressSpace
, typename
A::pint_t addr
)
352 : _addressSpace(addressSpace
), _addr(addr
) {}
354 uint32_t kind() const {
355 return _addressSpace
.get32(
357 offsetof(unwind_info_compressed_second_level_page_header
, kind
));
359 uint16_t entryPageOffset() const {
360 return _addressSpace
.get16(
361 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
364 uint16_t entryCount() const {
365 return _addressSpace
.get16(
367 offsetof(unwind_info_compressed_second_level_page_header
, entryCount
));
369 uint16_t encodingsPageOffset() const {
370 return _addressSpace
.get16(
371 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
372 encodingsPageOffset
));
374 uint16_t encodingsCount() const {
375 return _addressSpace
.get16(
376 _addr
+ offsetof(unwind_info_compressed_second_level_page_header
,
382 typename
A::pint_t _addr
;
385 template <typename A
> class UnwindSectionCompressedArray
{
387 UnwindSectionCompressedArray(A
&addressSpace
, typename
A::pint_t addr
)
388 : _addressSpace(addressSpace
), _addr(addr
) {}
390 uint32_t functionOffset(uint32_t index
) const {
391 return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
392 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
394 uint16_t encodingIndex(uint32_t index
) const {
395 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
396 _addressSpace
.get32(_addr
+ index
* sizeof(uint32_t)));
401 typename
A::pint_t _addr
;
404 template <typename A
> class UnwindSectionLsdaArray
{
406 UnwindSectionLsdaArray(A
&addressSpace
, typename
A::pint_t addr
)
407 : _addressSpace(addressSpace
), _addr(addr
) {}
409 uint32_t functionOffset(uint32_t index
) const {
410 return _addressSpace
.get32(
411 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
412 index
, functionOffset
));
414 uint32_t lsdaOffset(uint32_t index
) const {
415 return _addressSpace
.get32(
416 _addr
+ arrayoffsetof(unwind_info_section_header_lsda_index_entry
,
422 typename
A::pint_t _addr
;
424 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
426 class _LIBUNWIND_HIDDEN AbstractUnwindCursor
{
428 // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
429 // This avoids an unnecessary dependency to libc++abi.
430 void operator delete(void *, size_t) {}
432 virtual ~AbstractUnwindCursor() {}
433 virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
434 virtual unw_word_t
getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
435 virtual void setReg(int, unw_word_t
) {
436 _LIBUNWIND_ABORT("setReg not implemented");
438 virtual bool validFloatReg(int) {
439 _LIBUNWIND_ABORT("validFloatReg not implemented");
441 virtual unw_fpreg_t
getFloatReg(int) {
442 _LIBUNWIND_ABORT("getFloatReg not implemented");
444 virtual void setFloatReg(int, unw_fpreg_t
) {
445 _LIBUNWIND_ABORT("setFloatReg not implemented");
447 virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); }
448 virtual void getInfo(unw_proc_info_t
*) {
449 _LIBUNWIND_ABORT("getInfo not implemented");
451 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
452 virtual bool isSignalFrame() {
453 _LIBUNWIND_ABORT("isSignalFrame not implemented");
455 virtual bool getFunctionName(char *, size_t, unw_word_t
*) {
456 _LIBUNWIND_ABORT("getFunctionName not implemented");
458 virtual void setInfoBasedOnIPRegister(bool = false) {
459 _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
461 virtual const char *getRegisterName(int) {
462 _LIBUNWIND_ABORT("getRegisterName not implemented");
465 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
469 virtual uintptr_t getDataRelBase() {
470 _LIBUNWIND_ABORT("getDataRelBase not implemented");
474 #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
475 virtual void *get_registers() {
476 _LIBUNWIND_ABORT("get_registers not implemented");
481 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
483 /// \c UnwindCursor contains all state (including all register values) during
484 /// an unwind. This is normally stack-allocated inside a unw_cursor_t.
485 template <typename A
, typename R
>
486 class UnwindCursor
: public AbstractUnwindCursor
{
487 typedef typename
A::pint_t pint_t
;
489 UnwindCursor(unw_context_t
*context
, A
&as
);
490 UnwindCursor(CONTEXT
*context
, A
&as
);
491 UnwindCursor(A
&as
, void *threadArg
);
492 virtual ~UnwindCursor() {}
493 virtual bool validReg(int);
494 virtual unw_word_t
getReg(int);
495 virtual void setReg(int, unw_word_t
);
496 virtual bool validFloatReg(int);
497 virtual unw_fpreg_t
getFloatReg(int);
498 virtual void setFloatReg(int, unw_fpreg_t
);
499 virtual int step(bool = false);
500 virtual void getInfo(unw_proc_info_t
*);
501 virtual void jumpto();
502 virtual bool isSignalFrame();
503 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
504 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
505 virtual const char *getRegisterName(int num
);
507 virtual void saveVFPAsX();
510 DISPATCHER_CONTEXT
*getDispatcherContext() { return &_dispContext
; }
511 void setDispatcherContext(DISPATCHER_CONTEXT
*disp
) {
512 _dispContext
= *disp
;
513 _info
.lsda
= reinterpret_cast<unw_word_t
>(_dispContext
.HandlerData
);
514 if (_dispContext
.LanguageHandler
) {
515 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
520 // libunwind does not and should not depend on C++ library which means that we
521 // need our own definition of inline placement new.
522 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
526 pint_t
getLastPC() const { return _dispContext
.ControlPc
; }
527 void setLastPC(pint_t pc
) { _dispContext
.ControlPc
= pc
; }
528 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
530 // Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.
533 // If pc points exactly at the end of the range, we might resolve the
534 // next function instead. Decrement pc by 1 to fit inside the current
537 _dispContext
.FunctionEntry
= RtlLookupFunctionEntry(pc
,
538 &_dispContext
.ImageBase
,
539 _dispContext
.HistoryTable
);
540 *base
= _dispContext
.ImageBase
;
541 return _dispContext
.FunctionEntry
;
543 bool getInfoFromSEH(pint_t pc
);
544 int stepWithSEHData() {
545 _dispContext
.LanguageHandler
= RtlVirtualUnwind(UNW_FLAG_UHANDLER
,
546 _dispContext
.ImageBase
,
547 _dispContext
.ControlPc
,
548 _dispContext
.FunctionEntry
,
549 _dispContext
.ContextRecord
,
550 &_dispContext
.HandlerData
,
551 &_dispContext
.EstablisherFrame
,
553 // Update some fields of the unwind info now, since we have them.
554 _info
.lsda
= reinterpret_cast<unw_word_t
>(_dispContext
.HandlerData
);
555 if (_dispContext
.LanguageHandler
) {
556 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
559 return UNW_STEP_SUCCESS
;
563 unw_proc_info_t _info
;
564 DISPATCHER_CONTEXT _dispContext
;
566 UNWIND_HISTORY_TABLE _histTable
;
567 bool _unwindInfoMissing
;
571 template <typename A
, typename R
>
572 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
573 : _addressSpace(as
), _unwindInfoMissing(false) {
574 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
575 "UnwindCursor<> does not fit in unw_cursor_t");
576 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
577 "UnwindCursor<> requires more alignment than unw_cursor_t");
578 memset(&_info
, 0, sizeof(_info
));
579 memset(&_histTable
, 0, sizeof(_histTable
));
580 memset(&_dispContext
, 0, sizeof(_dispContext
));
581 _dispContext
.ContextRecord
= &_msContext
;
582 _dispContext
.HistoryTable
= &_histTable
;
583 // Initialize MS context from ours.
585 RtlCaptureContext(&_msContext
);
586 _msContext
.ContextFlags
= CONTEXT_CONTROL
|CONTEXT_INTEGER
|CONTEXT_FLOATING_POINT
;
587 #if defined(_LIBUNWIND_TARGET_X86_64)
588 _msContext
.Rax
= r
.getRegister(UNW_X86_64_RAX
);
589 _msContext
.Rcx
= r
.getRegister(UNW_X86_64_RCX
);
590 _msContext
.Rdx
= r
.getRegister(UNW_X86_64_RDX
);
591 _msContext
.Rbx
= r
.getRegister(UNW_X86_64_RBX
);
592 _msContext
.Rsp
= r
.getRegister(UNW_X86_64_RSP
);
593 _msContext
.Rbp
= r
.getRegister(UNW_X86_64_RBP
);
594 _msContext
.Rsi
= r
.getRegister(UNW_X86_64_RSI
);
595 _msContext
.Rdi
= r
.getRegister(UNW_X86_64_RDI
);
596 _msContext
.R8
= r
.getRegister(UNW_X86_64_R8
);
597 _msContext
.R9
= r
.getRegister(UNW_X86_64_R9
);
598 _msContext
.R10
= r
.getRegister(UNW_X86_64_R10
);
599 _msContext
.R11
= r
.getRegister(UNW_X86_64_R11
);
600 _msContext
.R12
= r
.getRegister(UNW_X86_64_R12
);
601 _msContext
.R13
= r
.getRegister(UNW_X86_64_R13
);
602 _msContext
.R14
= r
.getRegister(UNW_X86_64_R14
);
603 _msContext
.R15
= r
.getRegister(UNW_X86_64_R15
);
604 _msContext
.Rip
= r
.getRegister(UNW_REG_IP
);
609 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM0
);
610 _msContext
.Xmm0
= t
.m
;
611 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM1
);
612 _msContext
.Xmm1
= t
.m
;
613 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM2
);
614 _msContext
.Xmm2
= t
.m
;
615 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM3
);
616 _msContext
.Xmm3
= t
.m
;
617 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM4
);
618 _msContext
.Xmm4
= t
.m
;
619 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM5
);
620 _msContext
.Xmm5
= t
.m
;
621 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM6
);
622 _msContext
.Xmm6
= t
.m
;
623 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM7
);
624 _msContext
.Xmm7
= t
.m
;
625 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM8
);
626 _msContext
.Xmm8
= t
.m
;
627 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM9
);
628 _msContext
.Xmm9
= t
.m
;
629 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM10
);
630 _msContext
.Xmm10
= t
.m
;
631 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM11
);
632 _msContext
.Xmm11
= t
.m
;
633 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM12
);
634 _msContext
.Xmm12
= t
.m
;
635 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM13
);
636 _msContext
.Xmm13
= t
.m
;
637 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM14
);
638 _msContext
.Xmm14
= t
.m
;
639 t
.v
= r
.getVectorRegister(UNW_X86_64_XMM15
);
640 _msContext
.Xmm15
= t
.m
;
641 #elif defined(_LIBUNWIND_TARGET_ARM)
642 _msContext
.R0
= r
.getRegister(UNW_ARM_R0
);
643 _msContext
.R1
= r
.getRegister(UNW_ARM_R1
);
644 _msContext
.R2
= r
.getRegister(UNW_ARM_R2
);
645 _msContext
.R3
= r
.getRegister(UNW_ARM_R3
);
646 _msContext
.R4
= r
.getRegister(UNW_ARM_R4
);
647 _msContext
.R5
= r
.getRegister(UNW_ARM_R5
);
648 _msContext
.R6
= r
.getRegister(UNW_ARM_R6
);
649 _msContext
.R7
= r
.getRegister(UNW_ARM_R7
);
650 _msContext
.R8
= r
.getRegister(UNW_ARM_R8
);
651 _msContext
.R9
= r
.getRegister(UNW_ARM_R9
);
652 _msContext
.R10
= r
.getRegister(UNW_ARM_R10
);
653 _msContext
.R11
= r
.getRegister(UNW_ARM_R11
);
654 _msContext
.R12
= r
.getRegister(UNW_ARM_R12
);
655 _msContext
.Sp
= r
.getRegister(UNW_ARM_SP
);
656 _msContext
.Lr
= r
.getRegister(UNW_ARM_LR
);
657 _msContext
.Pc
= r
.getRegister(UNW_ARM_IP
);
658 for (int i
= UNW_ARM_D0
; i
<= UNW_ARM_D31
; ++i
) {
663 d
.d
= r
.getFloatRegister(i
);
664 _msContext
.D
[i
- UNW_ARM_D0
] = d
.w
;
666 #elif defined(_LIBUNWIND_TARGET_AARCH64)
667 for (int i
= UNW_AARCH64_X0
; i
<= UNW_ARM64_X30
; ++i
)
668 _msContext
.X
[i
- UNW_AARCH64_X0
] = r
.getRegister(i
);
669 _msContext
.Sp
= r
.getRegister(UNW_REG_SP
);
670 _msContext
.Pc
= r
.getRegister(UNW_REG_IP
);
671 for (int i
= UNW_AARCH64_V0
; i
<= UNW_ARM64_D31
; ++i
)
672 _msContext
.V
[i
- UNW_AARCH64_V0
].D
[0] = r
.getFloatRegister(i
);
676 template <typename A
, typename R
>
677 UnwindCursor
<A
, R
>::UnwindCursor(CONTEXT
*context
, A
&as
)
678 : _addressSpace(as
), _unwindInfoMissing(false) {
679 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
680 "UnwindCursor<> does not fit in unw_cursor_t");
681 memset(&_info
, 0, sizeof(_info
));
682 memset(&_histTable
, 0, sizeof(_histTable
));
683 memset(&_dispContext
, 0, sizeof(_dispContext
));
684 _dispContext
.ContextRecord
= &_msContext
;
685 _dispContext
.HistoryTable
= &_histTable
;
686 _msContext
= *context
;
690 template <typename A
, typename R
>
691 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
692 if (regNum
== UNW_REG_IP
|| regNum
== UNW_REG_SP
) return true;
693 #if defined(_LIBUNWIND_TARGET_X86_64)
694 if (regNum
>= UNW_X86_64_RAX
&& regNum
<= UNW_X86_64_RIP
) return true;
695 #elif defined(_LIBUNWIND_TARGET_ARM)
696 if ((regNum
>= UNW_ARM_R0
&& regNum
<= UNW_ARM_R15
) ||
697 regNum
== UNW_ARM_RA_AUTH_CODE
)
699 #elif defined(_LIBUNWIND_TARGET_AARCH64)
700 if (regNum
>= UNW_AARCH64_X0
&& regNum
<= UNW_ARM64_X30
) return true;
705 template <typename A
, typename R
>
706 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
708 #if defined(_LIBUNWIND_TARGET_X86_64)
710 case UNW_REG_IP
: return _msContext
.Rip
;
711 case UNW_X86_64_RAX
: return _msContext
.Rax
;
712 case UNW_X86_64_RDX
: return _msContext
.Rdx
;
713 case UNW_X86_64_RCX
: return _msContext
.Rcx
;
714 case UNW_X86_64_RBX
: return _msContext
.Rbx
;
716 case UNW_X86_64_RSP
: return _msContext
.Rsp
;
717 case UNW_X86_64_RBP
: return _msContext
.Rbp
;
718 case UNW_X86_64_RSI
: return _msContext
.Rsi
;
719 case UNW_X86_64_RDI
: return _msContext
.Rdi
;
720 case UNW_X86_64_R8
: return _msContext
.R8
;
721 case UNW_X86_64_R9
: return _msContext
.R9
;
722 case UNW_X86_64_R10
: return _msContext
.R10
;
723 case UNW_X86_64_R11
: return _msContext
.R11
;
724 case UNW_X86_64_R12
: return _msContext
.R12
;
725 case UNW_X86_64_R13
: return _msContext
.R13
;
726 case UNW_X86_64_R14
: return _msContext
.R14
;
727 case UNW_X86_64_R15
: return _msContext
.R15
;
728 #elif defined(_LIBUNWIND_TARGET_ARM)
729 case UNW_ARM_R0
: return _msContext
.R0
;
730 case UNW_ARM_R1
: return _msContext
.R1
;
731 case UNW_ARM_R2
: return _msContext
.R2
;
732 case UNW_ARM_R3
: return _msContext
.R3
;
733 case UNW_ARM_R4
: return _msContext
.R4
;
734 case UNW_ARM_R5
: return _msContext
.R5
;
735 case UNW_ARM_R6
: return _msContext
.R6
;
736 case UNW_ARM_R7
: return _msContext
.R7
;
737 case UNW_ARM_R8
: return _msContext
.R8
;
738 case UNW_ARM_R9
: return _msContext
.R9
;
739 case UNW_ARM_R10
: return _msContext
.R10
;
740 case UNW_ARM_R11
: return _msContext
.R11
;
741 case UNW_ARM_R12
: return _msContext
.R12
;
743 case UNW_ARM_SP
: return _msContext
.Sp
;
744 case UNW_ARM_LR
: return _msContext
.Lr
;
746 case UNW_ARM_IP
: return _msContext
.Pc
;
747 #elif defined(_LIBUNWIND_TARGET_AARCH64)
748 case UNW_REG_SP
: return _msContext
.Sp
;
749 case UNW_REG_IP
: return _msContext
.Pc
;
750 default: return _msContext
.X
[regNum
- UNW_AARCH64_X0
];
753 _LIBUNWIND_ABORT("unsupported register");
756 template <typename A
, typename R
>
757 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
759 #if defined(_LIBUNWIND_TARGET_X86_64)
761 case UNW_REG_IP
: _msContext
.Rip
= value
; break;
762 case UNW_X86_64_RAX
: _msContext
.Rax
= value
; break;
763 case UNW_X86_64_RDX
: _msContext
.Rdx
= value
; break;
764 case UNW_X86_64_RCX
: _msContext
.Rcx
= value
; break;
765 case UNW_X86_64_RBX
: _msContext
.Rbx
= value
; break;
767 case UNW_X86_64_RSP
: _msContext
.Rsp
= value
; break;
768 case UNW_X86_64_RBP
: _msContext
.Rbp
= value
; break;
769 case UNW_X86_64_RSI
: _msContext
.Rsi
= value
; break;
770 case UNW_X86_64_RDI
: _msContext
.Rdi
= value
; break;
771 case UNW_X86_64_R8
: _msContext
.R8
= value
; break;
772 case UNW_X86_64_R9
: _msContext
.R9
= value
; break;
773 case UNW_X86_64_R10
: _msContext
.R10
= value
; break;
774 case UNW_X86_64_R11
: _msContext
.R11
= value
; break;
775 case UNW_X86_64_R12
: _msContext
.R12
= value
; break;
776 case UNW_X86_64_R13
: _msContext
.R13
= value
; break;
777 case UNW_X86_64_R14
: _msContext
.R14
= value
; break;
778 case UNW_X86_64_R15
: _msContext
.R15
= value
; break;
779 #elif defined(_LIBUNWIND_TARGET_ARM)
780 case UNW_ARM_R0
: _msContext
.R0
= value
; break;
781 case UNW_ARM_R1
: _msContext
.R1
= value
; break;
782 case UNW_ARM_R2
: _msContext
.R2
= value
; break;
783 case UNW_ARM_R3
: _msContext
.R3
= value
; break;
784 case UNW_ARM_R4
: _msContext
.R4
= value
; break;
785 case UNW_ARM_R5
: _msContext
.R5
= value
; break;
786 case UNW_ARM_R6
: _msContext
.R6
= value
; break;
787 case UNW_ARM_R7
: _msContext
.R7
= value
; break;
788 case UNW_ARM_R8
: _msContext
.R8
= value
; break;
789 case UNW_ARM_R9
: _msContext
.R9
= value
; break;
790 case UNW_ARM_R10
: _msContext
.R10
= value
; break;
791 case UNW_ARM_R11
: _msContext
.R11
= value
; break;
792 case UNW_ARM_R12
: _msContext
.R12
= value
; break;
794 case UNW_ARM_SP
: _msContext
.Sp
= value
; break;
795 case UNW_ARM_LR
: _msContext
.Lr
= value
; break;
797 case UNW_ARM_IP
: _msContext
.Pc
= value
; break;
798 #elif defined(_LIBUNWIND_TARGET_AARCH64)
799 case UNW_REG_SP
: _msContext
.Sp
= value
; break;
800 case UNW_REG_IP
: _msContext
.Pc
= value
; break;
811 case UNW_AARCH64_X10
:
812 case UNW_AARCH64_X11
:
813 case UNW_AARCH64_X12
:
814 case UNW_AARCH64_X13
:
815 case UNW_AARCH64_X14
:
816 case UNW_AARCH64_X15
:
817 case UNW_AARCH64_X16
:
818 case UNW_AARCH64_X17
:
819 case UNW_AARCH64_X18
:
820 case UNW_AARCH64_X19
:
821 case UNW_AARCH64_X20
:
822 case UNW_AARCH64_X21
:
823 case UNW_AARCH64_X22
:
824 case UNW_AARCH64_X23
:
825 case UNW_AARCH64_X24
:
826 case UNW_AARCH64_X25
:
827 case UNW_AARCH64_X26
:
828 case UNW_AARCH64_X27
:
829 case UNW_AARCH64_X28
:
831 case UNW_AARCH64_LR
: _msContext
.X
[regNum
- UNW_ARM64_X0
] = value
; break;
834 _LIBUNWIND_ABORT("unsupported register");
838 template <typename A
, typename R
>
839 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
840 #if defined(_LIBUNWIND_TARGET_ARM)
841 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) return true;
842 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) return true;
843 #elif defined(_LIBUNWIND_TARGET_AARCH64)
844 if (regNum
>= UNW_AARCH64_V0
&& regNum
<= UNW_ARM64_D31
) return true;
851 template <typename A
, typename R
>
852 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
853 #if defined(_LIBUNWIND_TARGET_ARM)
854 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
859 d
.w
= _msContext
.S
[regNum
- UNW_ARM_S0
];
862 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
867 d
.w
= _msContext
.D
[regNum
- UNW_ARM_D0
];
870 _LIBUNWIND_ABORT("unsupported float register");
871 #elif defined(_LIBUNWIND_TARGET_AARCH64)
872 return _msContext
.V
[regNum
- UNW_AARCH64_V0
].D
[0];
875 _LIBUNWIND_ABORT("float registers unimplemented");
879 template <typename A
, typename R
>
880 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
881 #if defined(_LIBUNWIND_TARGET_ARM)
882 if (regNum
>= UNW_ARM_S0
&& regNum
<= UNW_ARM_S31
) {
888 _msContext
.S
[regNum
- UNW_ARM_S0
] = d
.w
;
890 if (regNum
>= UNW_ARM_D0
&& regNum
<= UNW_ARM_D31
) {
896 _msContext
.D
[regNum
- UNW_ARM_D0
] = d
.w
;
898 _LIBUNWIND_ABORT("unsupported float register");
899 #elif defined(_LIBUNWIND_TARGET_AARCH64)
900 _msContext
.V
[regNum
- UNW_AARCH64_V0
].D
[0] = value
;
904 _LIBUNWIND_ABORT("float registers unimplemented");
908 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
909 RtlRestoreContext(&_msContext
, nullptr);
913 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {}
916 template <typename A
, typename R
>
917 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
918 return R::getRegisterName(regNum
);
921 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
925 #else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
927 /// UnwindCursor contains all state (including all register values) during
928 /// an unwind. This is normally stack allocated inside a unw_cursor_t.
929 template <typename A
, typename R
>
930 class UnwindCursor
: public AbstractUnwindCursor
{
931 typedef typename
A::pint_t pint_t
;
933 UnwindCursor(unw_context_t
*context
, A
&as
);
934 UnwindCursor(A
&as
, void *threadArg
);
935 virtual ~UnwindCursor() {}
936 virtual bool validReg(int);
937 virtual unw_word_t
getReg(int);
938 virtual void setReg(int, unw_word_t
);
939 virtual bool validFloatReg(int);
940 virtual unw_fpreg_t
getFloatReg(int);
941 virtual void setFloatReg(int, unw_fpreg_t
);
942 virtual int step(bool stage2
= false);
943 virtual void getInfo(unw_proc_info_t
*);
944 virtual void jumpto();
945 virtual bool isSignalFrame();
946 virtual bool getFunctionName(char *buf
, size_t len
, unw_word_t
*off
);
947 virtual void setInfoBasedOnIPRegister(bool isReturnAddress
= false);
948 virtual const char *getRegisterName(int num
);
950 virtual void saveVFPAsX();
954 virtual uintptr_t getDataRelBase();
957 #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
958 virtual void *get_registers() { return &_registers
; }
961 // libunwind does not and should not depend on C++ library which means that we
962 // need our own definition of inline placement new.
963 static void *operator new(size_t, UnwindCursor
<A
, R
> *p
) { return p
; }
967 #if defined(_LIBUNWIND_ARM_EHABI)
968 bool getInfoFromEHABISection(pint_t pc
, const UnwindInfoSections
§s
);
970 int stepWithEHABI() {
973 // FIXME: Calling decode_eht_entry() here is violating the libunwind
974 // abstraction layer.
975 const uint32_t *ehtp
=
976 decode_eht_entry(reinterpret_cast<const uint32_t *>(_info
.unwind_info
),
978 if (_Unwind_VRS_Interpret((_Unwind_Context
*)this, ehtp
, off
, len
) !=
979 _URC_CONTINUE_UNWIND
)
981 return UNW_STEP_SUCCESS
;
985 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
986 bool setInfoForSigReturn() {
988 return setInfoForSigReturn(dummy
);
990 int stepThroughSigReturn() {
992 return stepThroughSigReturn(dummy
);
994 bool isReadableAddr(const pint_t addr
) const;
995 #if defined(_LIBUNWIND_TARGET_AARCH64)
996 bool setInfoForSigReturn(Registers_arm64
&);
997 int stepThroughSigReturn(Registers_arm64
&);
999 #if defined(_LIBUNWIND_TARGET_RISCV)
1000 bool setInfoForSigReturn(Registers_riscv
&);
1001 int stepThroughSigReturn(Registers_riscv
&);
1003 #if defined(_LIBUNWIND_TARGET_S390X)
1004 bool setInfoForSigReturn(Registers_s390x
&);
1005 int stepThroughSigReturn(Registers_s390x
&);
1007 template <typename Registers
> bool setInfoForSigReturn(Registers
&) {
1010 template <typename Registers
> int stepThroughSigReturn(Registers
&) {
1011 return UNW_STEP_END
;
1015 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1016 bool getInfoFromFdeCie(const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
1017 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
,
1018 pint_t pc
, uintptr_t dso_base
);
1019 bool getInfoFromDwarfSection(pint_t pc
, const UnwindInfoSections
§s
,
1020 uint32_t fdeSectionOffsetHint
=0);
1021 int stepWithDwarfFDE(bool stage2
) {
1022 return DwarfInstructions
<A
, R
>::stepWithDwarf(
1023 _addressSpace
, (pint_t
)this->getReg(UNW_REG_IP
),
1024 (pint_t
)_info
.unwind_info
, _registers
, _isSignalFrame
, stage2
);
1028 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1029 bool getInfoFromCompactEncodingSection(pint_t pc
,
1030 const UnwindInfoSections
§s
);
1031 int stepWithCompactEncoding(bool stage2
= false) {
1032 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1033 if ( compactSaysUseDwarf() )
1034 return stepWithDwarfFDE(stage2
);
1037 return stepWithCompactEncoding(dummy
);
1040 #if defined(_LIBUNWIND_TARGET_X86_64)
1041 int stepWithCompactEncoding(Registers_x86_64
&) {
1042 return CompactUnwinder_x86_64
<A
>::stepWithCompactEncoding(
1043 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
1047 #if defined(_LIBUNWIND_TARGET_I386)
1048 int stepWithCompactEncoding(Registers_x86
&) {
1049 return CompactUnwinder_x86
<A
>::stepWithCompactEncoding(
1050 _info
.format
, (uint32_t)_info
.start_ip
, _addressSpace
, _registers
);
1054 #if defined(_LIBUNWIND_TARGET_PPC)
1055 int stepWithCompactEncoding(Registers_ppc
&) {
1060 #if defined(_LIBUNWIND_TARGET_PPC64)
1061 int stepWithCompactEncoding(Registers_ppc64
&) {
1067 #if defined(_LIBUNWIND_TARGET_AARCH64)
1068 int stepWithCompactEncoding(Registers_arm64
&) {
1069 return CompactUnwinder_arm64
<A
>::stepWithCompactEncoding(
1070 _info
.format
, _info
.start_ip
, _addressSpace
, _registers
);
1074 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
1075 int stepWithCompactEncoding(Registers_mips_o32
&) {
1080 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1081 int stepWithCompactEncoding(Registers_mips_newabi
&) {
1086 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1087 int stepWithCompactEncoding(Registers_loongarch
&) { return UNW_EINVAL
; }
1090 #if defined(_LIBUNWIND_TARGET_SPARC)
1091 int stepWithCompactEncoding(Registers_sparc
&) { return UNW_EINVAL
; }
1094 #if defined(_LIBUNWIND_TARGET_SPARC64)
1095 int stepWithCompactEncoding(Registers_sparc64
&) { return UNW_EINVAL
; }
1098 #if defined (_LIBUNWIND_TARGET_RISCV)
1099 int stepWithCompactEncoding(Registers_riscv
&) {
1104 bool compactSaysUseDwarf(uint32_t *offset
=NULL
) const {
1106 return compactSaysUseDwarf(dummy
, offset
);
1109 #if defined(_LIBUNWIND_TARGET_X86_64)
1110 bool compactSaysUseDwarf(Registers_x86_64
&, uint32_t *offset
) const {
1111 if ((_info
.format
& UNWIND_X86_64_MODE_MASK
) == UNWIND_X86_64_MODE_DWARF
) {
1113 *offset
= (_info
.format
& UNWIND_X86_64_DWARF_SECTION_OFFSET
);
1120 #if defined(_LIBUNWIND_TARGET_I386)
1121 bool compactSaysUseDwarf(Registers_x86
&, uint32_t *offset
) const {
1122 if ((_info
.format
& UNWIND_X86_MODE_MASK
) == UNWIND_X86_MODE_DWARF
) {
1124 *offset
= (_info
.format
& UNWIND_X86_DWARF_SECTION_OFFSET
);
1131 #if defined(_LIBUNWIND_TARGET_PPC)
1132 bool compactSaysUseDwarf(Registers_ppc
&, uint32_t *) const {
1137 #if defined(_LIBUNWIND_TARGET_PPC64)
1138 bool compactSaysUseDwarf(Registers_ppc64
&, uint32_t *) const {
1143 #if defined(_LIBUNWIND_TARGET_AARCH64)
1144 bool compactSaysUseDwarf(Registers_arm64
&, uint32_t *offset
) const {
1145 if ((_info
.format
& UNWIND_ARM64_MODE_MASK
) == UNWIND_ARM64_MODE_DWARF
) {
1147 *offset
= (_info
.format
& UNWIND_ARM64_DWARF_SECTION_OFFSET
);
1154 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
1155 bool compactSaysUseDwarf(Registers_mips_o32
&, uint32_t *) const {
1160 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1161 bool compactSaysUseDwarf(Registers_mips_newabi
&, uint32_t *) const {
1166 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1167 bool compactSaysUseDwarf(Registers_loongarch
&, uint32_t *) const {
1172 #if defined(_LIBUNWIND_TARGET_SPARC)
1173 bool compactSaysUseDwarf(Registers_sparc
&, uint32_t *) const { return true; }
1176 #if defined(_LIBUNWIND_TARGET_SPARC64)
1177 bool compactSaysUseDwarf(Registers_sparc64
&, uint32_t *) const {
1182 #if defined (_LIBUNWIND_TARGET_RISCV)
1183 bool compactSaysUseDwarf(Registers_riscv
&, uint32_t *) const {
1188 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1190 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1191 compact_unwind_encoding_t
dwarfEncoding() const {
1193 return dwarfEncoding(dummy
);
1196 #if defined(_LIBUNWIND_TARGET_X86_64)
1197 compact_unwind_encoding_t
dwarfEncoding(Registers_x86_64
&) const {
1198 return UNWIND_X86_64_MODE_DWARF
;
1202 #if defined(_LIBUNWIND_TARGET_I386)
1203 compact_unwind_encoding_t
dwarfEncoding(Registers_x86
&) const {
1204 return UNWIND_X86_MODE_DWARF
;
1208 #if defined(_LIBUNWIND_TARGET_PPC)
1209 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc
&) const {
1214 #if defined(_LIBUNWIND_TARGET_PPC64)
1215 compact_unwind_encoding_t
dwarfEncoding(Registers_ppc64
&) const {
1220 #if defined(_LIBUNWIND_TARGET_AARCH64)
1221 compact_unwind_encoding_t
dwarfEncoding(Registers_arm64
&) const {
1222 return UNWIND_ARM64_MODE_DWARF
;
1226 #if defined(_LIBUNWIND_TARGET_ARM)
1227 compact_unwind_encoding_t
dwarfEncoding(Registers_arm
&) const {
1232 #if defined (_LIBUNWIND_TARGET_OR1K)
1233 compact_unwind_encoding_t
dwarfEncoding(Registers_or1k
&) const {
1238 #if defined (_LIBUNWIND_TARGET_HEXAGON)
1239 compact_unwind_encoding_t
dwarfEncoding(Registers_hexagon
&) const {
1244 #if defined (_LIBUNWIND_TARGET_MIPS_O32)
1245 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_o32
&) const {
1250 #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1251 compact_unwind_encoding_t
dwarfEncoding(Registers_mips_newabi
&) const {
1256 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1257 compact_unwind_encoding_t
dwarfEncoding(Registers_loongarch
&) const {
1262 #if defined(_LIBUNWIND_TARGET_SPARC)
1263 compact_unwind_encoding_t
dwarfEncoding(Registers_sparc
&) const { return 0; }
1266 #if defined(_LIBUNWIND_TARGET_SPARC64)
1267 compact_unwind_encoding_t
dwarfEncoding(Registers_sparc64
&) const {
1272 #if defined (_LIBUNWIND_TARGET_RISCV)
1273 compact_unwind_encoding_t
dwarfEncoding(Registers_riscv
&) const {
1278 #if defined (_LIBUNWIND_TARGET_S390X)
1279 compact_unwind_encoding_t
dwarfEncoding(Registers_s390x
&) const {
1284 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1286 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1287 // For runtime environments using SEH unwind data without Windows runtime
1289 pint_t
getLastPC() const { /* FIXME: Implement */ return 0; }
1290 void setLastPC(pint_t pc
) { /* FIXME: Implement */ }
1291 RUNTIME_FUNCTION
*lookUpSEHUnwindInfo(pint_t pc
, pint_t
*base
) {
1292 /* FIXME: Implement */
1296 bool getInfoFromSEH(pint_t pc
);
1297 int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1298 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1300 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1301 bool getInfoFromTBTable(pint_t pc
, R
®isters
);
1302 int stepWithTBTable(pint_t pc
, tbtable
*TBTable
, R
®isters
,
1303 bool &isSignalFrame
);
1304 int stepWithTBTableData() {
1305 return stepWithTBTable(reinterpret_cast<pint_t
>(this->getReg(UNW_REG_IP
)),
1306 reinterpret_cast<tbtable
*>(_info
.unwind_info
),
1307 _registers
, _isSignalFrame
);
1309 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1313 unw_proc_info_t _info
;
1314 bool _unwindInfoMissing
;
1315 bool _isSignalFrame
;
1316 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1317 bool _isSigReturn
= false;
1322 template <typename A
, typename R
>
1323 UnwindCursor
<A
, R
>::UnwindCursor(unw_context_t
*context
, A
&as
)
1324 : _addressSpace(as
), _registers(context
), _unwindInfoMissing(false),
1325 _isSignalFrame(false) {
1326 static_assert((check_fit
<UnwindCursor
<A
, R
>, unw_cursor_t
>::does_fit
),
1327 "UnwindCursor<> does not fit in unw_cursor_t");
1328 static_assert((alignof(UnwindCursor
<A
, R
>) <= alignof(unw_cursor_t
)),
1329 "UnwindCursor<> requires more alignment than unw_cursor_t");
1330 memset(&_info
, 0, sizeof(_info
));
1333 template <typename A
, typename R
>
1334 UnwindCursor
<A
, R
>::UnwindCursor(A
&as
, void *)
1335 : _addressSpace(as
), _unwindInfoMissing(false), _isSignalFrame(false) {
1336 memset(&_info
, 0, sizeof(_info
));
1338 // fill in _registers from thread arg
1342 template <typename A
, typename R
>
1343 bool UnwindCursor
<A
, R
>::validReg(int regNum
) {
1344 return _registers
.validRegister(regNum
);
1347 template <typename A
, typename R
>
1348 unw_word_t UnwindCursor
<A
, R
>::getReg(int regNum
) {
1349 return _registers
.getRegister(regNum
);
1352 template <typename A
, typename R
>
1353 void UnwindCursor
<A
, R
>::setReg(int regNum
, unw_word_t value
) {
1354 _registers
.setRegister(regNum
, (typename
A::pint_t
)value
);
1357 template <typename A
, typename R
>
1358 bool UnwindCursor
<A
, R
>::validFloatReg(int regNum
) {
1359 return _registers
.validFloatRegister(regNum
);
1362 template <typename A
, typename R
>
1363 unw_fpreg_t UnwindCursor
<A
, R
>::getFloatReg(int regNum
) {
1364 return _registers
.getFloatRegister(regNum
);
1367 template <typename A
, typename R
>
1368 void UnwindCursor
<A
, R
>::setFloatReg(int regNum
, unw_fpreg_t value
) {
1369 _registers
.setFloatRegister(regNum
, value
);
1372 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::jumpto() {
1373 _registers
.jumpto();
1377 template <typename A
, typename R
> void UnwindCursor
<A
, R
>::saveVFPAsX() {
1378 _registers
.saveVFPAsX();
1383 template <typename A
, typename R
>
1384 uintptr_t UnwindCursor
<A
, R
>::getDataRelBase() {
1385 return reinterpret_cast<uintptr_t>(_info
.extra
);
1389 template <typename A
, typename R
>
1390 const char *UnwindCursor
<A
, R
>::getRegisterName(int regNum
) {
1391 return _registers
.getRegisterName(regNum
);
1394 template <typename A
, typename R
> bool UnwindCursor
<A
, R
>::isSignalFrame() {
1395 return _isSignalFrame
;
1398 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1400 #if defined(_LIBUNWIND_ARM_EHABI)
1401 template<typename A
>
1402 struct EHABISectionIterator
{
1403 typedef EHABISectionIterator _Self
;
1405 typedef typename
A::pint_t value_type
;
1406 typedef typename
A::pint_t
* pointer
;
1407 typedef typename
A::pint_t
& reference
;
1408 typedef size_t size_type
;
1409 typedef size_t difference_type
;
1411 static _Self
begin(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1412 return _Self(addressSpace
, sects
, 0);
1414 static _Self
end(A
& addressSpace
, const UnwindInfoSections
& sects
) {
1415 return _Self(addressSpace
, sects
,
1416 sects
.arm_section_length
/ sizeof(EHABIIndexEntry
));
1419 EHABISectionIterator(A
& addressSpace
, const UnwindInfoSections
& sects
, size_t i
)
1420 : _i(i
), _addressSpace(&addressSpace
), _sects(§s
) {}
1422 _Self
& operator++() { ++_i
; return *this; }
1423 _Self
& operator+=(size_t a
) { _i
+= a
; return *this; }
1424 _Self
& operator--() { assert(_i
> 0); --_i
; return *this; }
1425 _Self
& operator-=(size_t a
) { assert(_i
>= a
); _i
-= a
; return *this; }
1427 _Self
operator+(size_t a
) { _Self out
= *this; out
._i
+= a
; return out
; }
1428 _Self
operator-(size_t a
) { assert(_i
>= a
); _Self out
= *this; out
._i
-= a
; return out
; }
1430 size_t operator-(const _Self
& other
) const { return _i
- other
._i
; }
1432 bool operator==(const _Self
& other
) const {
1433 assert(_addressSpace
== other
._addressSpace
);
1434 assert(_sects
== other
._sects
);
1435 return _i
== other
._i
;
1438 bool operator!=(const _Self
& other
) const {
1439 assert(_addressSpace
== other
._addressSpace
);
1440 assert(_sects
== other
._sects
);
1441 return _i
!= other
._i
;
1444 typename
A::pint_t
operator*() const { return functionAddress(); }
1446 typename
A::pint_t
functionAddress() const {
1447 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1448 EHABIIndexEntry
, _i
, functionOffset
);
1449 return indexAddr
+ signExtendPrel31(_addressSpace
->get32(indexAddr
));
1452 typename
A::pint_t
dataAddress() {
1453 typename
A::pint_t indexAddr
= _sects
->arm_section
+ arrayoffsetof(
1454 EHABIIndexEntry
, _i
, data
);
1461 const UnwindInfoSections
* _sects
;
1466 template <typename A
>
1467 EHABISectionIterator
<A
> EHABISectionUpperBound(
1468 EHABISectionIterator
<A
> first
,
1469 EHABISectionIterator
<A
> last
,
1470 typename
A::pint_t value
) {
1471 size_t len
= last
- first
;
1473 size_t l2
= len
/ 2;
1474 EHABISectionIterator
<A
> m
= first
+ l2
;
1487 template <typename A
, typename R
>
1488 bool UnwindCursor
<A
, R
>::getInfoFromEHABISection(
1490 const UnwindInfoSections
§s
) {
1491 EHABISectionIterator
<A
> begin
=
1492 EHABISectionIterator
<A
>::begin(_addressSpace
, sects
);
1493 EHABISectionIterator
<A
> end
=
1494 EHABISectionIterator
<A
>::end(_addressSpace
, sects
);
1498 EHABISectionIterator
<A
> itNextPC
= EHABISectionUpperBound(begin
, end
, pc
);
1499 if (itNextPC
== begin
)
1501 EHABISectionIterator
<A
> itThisPC
= itNextPC
- 1;
1503 pint_t thisPC
= itThisPC
.functionAddress();
1504 // If an exception is thrown from a function, corresponding to the last entry
1505 // in the table, we don't really know the function extent and have to choose a
1506 // value for nextPC. Choosing max() will allow the range check during trace to
1508 pint_t nextPC
= (itNextPC
== end
) ? UINTPTR_MAX
: itNextPC
.functionAddress();
1509 pint_t indexDataAddr
= itThisPC
.dataAddress();
1511 if (indexDataAddr
== 0)
1514 uint32_t indexData
= _addressSpace
.get32(indexDataAddr
);
1515 if (indexData
== UNW_EXIDX_CANTUNWIND
)
1518 // If the high bit is set, the exception handling table entry is inline inside
1519 // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1520 // the table points at an offset in the exception handling table (section 5
1522 pint_t exceptionTableAddr
;
1523 uint32_t exceptionTableData
;
1524 bool isSingleWordEHT
;
1525 if (indexData
& 0x80000000) {
1526 exceptionTableAddr
= indexDataAddr
;
1527 // TODO(ajwong): Should this data be 0?
1528 exceptionTableData
= indexData
;
1529 isSingleWordEHT
= true;
1531 exceptionTableAddr
= indexDataAddr
+ signExtendPrel31(indexData
);
1532 exceptionTableData
= _addressSpace
.get32(exceptionTableAddr
);
1533 isSingleWordEHT
= false;
1536 // Now we know the 3 things:
1537 // exceptionTableAddr -- exception handler table entry.
1538 // exceptionTableData -- the data inside the first word of the eht entry.
1539 // isSingleWordEHT -- whether the entry is in the index.
1540 unw_word_t personalityRoutine
= 0xbadf00d;
1541 bool scope32
= false;
1544 // If the high bit in the exception handling table entry is set, the entry is
1545 // in compact form (section 6.3 EHABI).
1546 if (exceptionTableData
& 0x80000000) {
1547 // Grab the index of the personality routine from the compact form.
1548 uint32_t choice
= (exceptionTableData
& 0x0f000000) >> 24;
1549 uint32_t extraWords
= 0;
1552 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr0
;
1555 lsda
= isSingleWordEHT
? 0 : (exceptionTableAddr
+ 4);
1558 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr1
;
1559 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1561 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1564 personalityRoutine
= (unw_word_t
) &__aeabi_unwind_cpp_pr2
;
1565 extraWords
= (exceptionTableData
& 0x00ff0000) >> 16;
1567 lsda
= exceptionTableAddr
+ (extraWords
+ 1) * 4;
1570 _LIBUNWIND_ABORT("unknown personality routine");
1574 if (isSingleWordEHT
) {
1575 if (extraWords
!= 0) {
1576 _LIBUNWIND_ABORT("index inlined table detected but pr function "
1577 "requires extra words");
1582 pint_t personalityAddr
=
1583 exceptionTableAddr
+ signExtendPrel31(exceptionTableData
);
1584 personalityRoutine
= personalityAddr
;
1586 // ARM EHABI # 6.2, # 9.2
1590 // +--------------------------------------+
1591 // | +--------+--------+--------+-------+ |
1592 // | |0| prel31 to personalityRoutine | |
1593 // | +--------+--------+--------+-------+ |
1594 // | | N | unwind opcodes | | <-- UnwindData
1595 // | +--------+--------+--------+-------+ |
1596 // | | Word 2 unwind opcodes | |
1597 // | +--------+--------+--------+-------+ |
1599 // | +--------+--------+--------+-------+ |
1600 // | | Word N unwind opcodes | |
1601 // | +--------+--------+--------+-------+ |
1602 // | | LSDA | | <-- lsda
1604 // | +--------+--------+--------+-------+ |
1605 // +--------------------------------------+
1607 uint32_t *UnwindData
= reinterpret_cast<uint32_t*>(exceptionTableAddr
) + 1;
1608 uint32_t FirstDataWord
= *UnwindData
;
1609 size_t N
= ((FirstDataWord
>> 24) & 0xff);
1610 size_t NDataWords
= N
+ 1;
1611 lsda
= reinterpret_cast<uintptr_t>(UnwindData
+ NDataWords
);
1614 _info
.start_ip
= thisPC
;
1615 _info
.end_ip
= nextPC
;
1616 _info
.handler
= personalityRoutine
;
1617 _info
.unwind_info
= exceptionTableAddr
;
1619 // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1620 _info
.flags
= (isSingleWordEHT
? 1 : 0) | (scope32
? 0x2 : 0); // Use enum?
1626 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1627 template <typename A
, typename R
>
1628 bool UnwindCursor
<A
, R
>::getInfoFromFdeCie(
1629 const typename CFI_Parser
<A
>::FDE_Info
&fdeInfo
,
1630 const typename CFI_Parser
<A
>::CIE_Info
&cieInfo
, pint_t pc
,
1631 uintptr_t dso_base
) {
1632 typename CFI_Parser
<A
>::PrologInfo prolog
;
1633 if (CFI_Parser
<A
>::parseFDEInstructions(_addressSpace
, fdeInfo
, cieInfo
, pc
,
1634 R::getArch(), &prolog
)) {
1635 // Save off parsed FDE info
1636 _info
.start_ip
= fdeInfo
.pcStart
;
1637 _info
.end_ip
= fdeInfo
.pcEnd
;
1638 _info
.lsda
= fdeInfo
.lsda
;
1639 _info
.handler
= cieInfo
.personality
;
1640 // Some frameless functions need SP altered when resuming in function, so
1641 // propagate spExtraArgSize.
1642 _info
.gp
= prolog
.spExtraArgSize
;
1644 _info
.format
= dwarfEncoding();
1645 _info
.unwind_info
= fdeInfo
.fdeStart
;
1646 _info
.unwind_info_size
= static_cast<uint32_t>(fdeInfo
.fdeLength
);
1647 _info
.extra
= static_cast<unw_word_t
>(dso_base
);
1653 template <typename A
, typename R
>
1654 bool UnwindCursor
<A
, R
>::getInfoFromDwarfSection(pint_t pc
,
1655 const UnwindInfoSections
§s
,
1656 uint32_t fdeSectionOffsetHint
) {
1657 typename CFI_Parser
<A
>::FDE_Info fdeInfo
;
1658 typename CFI_Parser
<A
>::CIE_Info cieInfo
;
1659 bool foundFDE
= false;
1660 bool foundInCache
= false;
1661 // If compact encoding table gave offset into dwarf section, go directly there
1662 if (fdeSectionOffsetHint
!= 0) {
1663 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1664 sects
.dwarf_section_length
,
1665 sects
.dwarf_section
+ fdeSectionOffsetHint
,
1666 &fdeInfo
, &cieInfo
);
1668 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1669 if (!foundFDE
&& (sects
.dwarf_index_section
!= 0)) {
1670 foundFDE
= EHHeaderParser
<A
>::findFDE(
1671 _addressSpace
, pc
, sects
.dwarf_index_section
,
1672 (uint32_t)sects
.dwarf_index_section_length
, &fdeInfo
, &cieInfo
);
1676 // otherwise, search cache of previously found FDEs.
1677 pint_t cachedFDE
= DwarfFDECache
<A
>::findFDE(sects
.dso_base
, pc
);
1678 if (cachedFDE
!= 0) {
1680 CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1681 sects
.dwarf_section_length
,
1682 cachedFDE
, &fdeInfo
, &cieInfo
);
1683 foundInCache
= foundFDE
;
1687 // Still not found, do full scan of __eh_frame section.
1688 foundFDE
= CFI_Parser
<A
>::findFDE(_addressSpace
, pc
, sects
.dwarf_section
,
1689 sects
.dwarf_section_length
, 0,
1690 &fdeInfo
, &cieInfo
);
1693 if (getInfoFromFdeCie(fdeInfo
, cieInfo
, pc
, sects
.dso_base
)) {
1694 // Add to cache (to make next lookup faster) if we had no hint
1695 // and there was no index.
1696 if (!foundInCache
&& (fdeSectionOffsetHint
== 0)) {
1697 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1698 if (sects
.dwarf_index_section
== 0)
1700 DwarfFDECache
<A
>::add(sects
.dso_base
, fdeInfo
.pcStart
, fdeInfo
.pcEnd
,
1706 //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1709 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1712 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1713 template <typename A
, typename R
>
1714 bool UnwindCursor
<A
, R
>::getInfoFromCompactEncodingSection(pint_t pc
,
1715 const UnwindInfoSections
§s
) {
1716 const bool log
= false;
1718 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1719 (uint64_t)pc
, (uint64_t)sects
.dso_base
);
1721 const UnwindSectionHeader
<A
> sectionHeader(_addressSpace
,
1722 sects
.compact_unwind_section
);
1723 if (sectionHeader
.version() != UNWIND_SECTION_VERSION
)
1726 // do a binary search of top level index to find page with unwind info
1727 pint_t targetFunctionOffset
= pc
- sects
.dso_base
;
1728 const UnwindSectionIndexArray
<A
> topIndex(_addressSpace
,
1729 sects
.compact_unwind_section
1730 + sectionHeader
.indexSectionOffset());
1732 uint32_t high
= sectionHeader
.indexCount();
1733 uint32_t last
= high
- 1;
1734 while (low
< high
) {
1735 uint32_t mid
= (low
+ high
) / 2;
1736 //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1737 //mid, low, high, topIndex.functionOffset(mid));
1738 if (topIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1739 if ((mid
== last
) ||
1740 (topIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
)) {
1750 const uint32_t firstLevelFunctionOffset
= topIndex
.functionOffset(low
);
1751 const uint32_t firstLevelNextPageFunctionOffset
=
1752 topIndex
.functionOffset(low
+ 1);
1753 const pint_t secondLevelAddr
=
1754 sects
.compact_unwind_section
+ topIndex
.secondLevelPagesSectionOffset(low
);
1755 const pint_t lsdaArrayStartAddr
=
1756 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
);
1757 const pint_t lsdaArrayEndAddr
=
1758 sects
.compact_unwind_section
+ topIndex
.lsdaIndexArraySectionOffset(low
+1);
1760 fprintf(stderr
, "\tfirst level search for result index=%d "
1761 "to secondLevelAddr=0x%llX\n",
1762 low
, (uint64_t) secondLevelAddr
);
1763 // do a binary search of second level page index
1764 uint32_t encoding
= 0;
1765 pint_t funcStart
= 0;
1768 pint_t personality
= 0;
1769 uint32_t pageKind
= _addressSpace
.get32(secondLevelAddr
);
1770 if (pageKind
== UNWIND_SECOND_LEVEL_REGULAR
) {
1772 UnwindSectionRegularPageHeader
<A
> pageHeader(_addressSpace
,
1774 UnwindSectionRegularArray
<A
> pageIndex(
1775 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1776 // binary search looks for entry with e where index[e].offset <= pc <
1777 // index[e+1].offset
1779 fprintf(stderr
, "\tbinary search for targetFunctionOffset=0x%08llX in "
1780 "regular page starting at secondLevelAddr=0x%llX\n",
1781 (uint64_t) targetFunctionOffset
, (uint64_t) secondLevelAddr
);
1783 high
= pageHeader
.entryCount();
1784 while (low
< high
) {
1785 uint32_t mid
= (low
+ high
) / 2;
1786 if (pageIndex
.functionOffset(mid
) <= targetFunctionOffset
) {
1787 if (mid
== (uint32_t)(pageHeader
.entryCount() - 1)) {
1790 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1792 } else if (pageIndex
.functionOffset(mid
+ 1) > targetFunctionOffset
) {
1793 // next is too big, so we found it
1795 funcEnd
= pageIndex
.functionOffset(low
+ 1) + sects
.dso_base
;
1804 encoding
= pageIndex
.encoding(low
);
1805 funcStart
= pageIndex
.functionOffset(low
) + sects
.dso_base
;
1806 if (pc
< funcStart
) {
1810 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1811 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1818 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1819 (uint64_t) pc
, (uint64_t) funcStart
, (uint64_t) funcEnd
);
1822 } else if (pageKind
== UNWIND_SECOND_LEVEL_COMPRESSED
) {
1824 UnwindSectionCompressedPageHeader
<A
> pageHeader(_addressSpace
,
1826 UnwindSectionCompressedArray
<A
> pageIndex(
1827 _addressSpace
, secondLevelAddr
+ pageHeader
.entryPageOffset());
1828 const uint32_t targetFunctionPageOffset
=
1829 (uint32_t)(targetFunctionOffset
- firstLevelFunctionOffset
);
1830 // binary search looks for entry with e where index[e].offset <= pc <
1831 // index[e+1].offset
1833 fprintf(stderr
, "\tbinary search of compressed page starting at "
1834 "secondLevelAddr=0x%llX\n",
1835 (uint64_t) secondLevelAddr
);
1837 last
= pageHeader
.entryCount() - 1;
1838 high
= pageHeader
.entryCount();
1839 while (low
< high
) {
1840 uint32_t mid
= (low
+ high
) / 2;
1841 if (pageIndex
.functionOffset(mid
) <= targetFunctionPageOffset
) {
1842 if ((mid
== last
) ||
1843 (pageIndex
.functionOffset(mid
+ 1) > targetFunctionPageOffset
)) {
1853 funcStart
= pageIndex
.functionOffset(low
) + firstLevelFunctionOffset
1857 pageIndex
.functionOffset(low
+ 1) + firstLevelFunctionOffset
1860 funcEnd
= firstLevelNextPageFunctionOffset
+ sects
.dso_base
;
1861 if (pc
< funcStart
) {
1862 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1863 "not in second level compressed unwind table. "
1865 (uint64_t) pc
, (uint64_t) funcStart
);
1869 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1870 "not in second level compressed unwind table. "
1872 (uint64_t) pc
, (uint64_t) funcEnd
);
1875 uint16_t encodingIndex
= pageIndex
.encodingIndex(low
);
1876 if (encodingIndex
< sectionHeader
.commonEncodingsArrayCount()) {
1877 // encoding is in common table in section header
1878 encoding
= _addressSpace
.get32(
1879 sects
.compact_unwind_section
+
1880 sectionHeader
.commonEncodingsArraySectionOffset() +
1881 encodingIndex
* sizeof(uint32_t));
1883 // encoding is in page specific table
1884 uint16_t pageEncodingIndex
=
1885 encodingIndex
- (uint16_t)sectionHeader
.commonEncodingsArrayCount();
1886 encoding
= _addressSpace
.get32(secondLevelAddr
+
1887 pageHeader
.encodingsPageOffset() +
1888 pageEncodingIndex
* sizeof(uint32_t));
1891 _LIBUNWIND_DEBUG_LOG(
1892 "malformed __unwind_info at 0x%0llX bad second level page",
1893 (uint64_t)sects
.compact_unwind_section
);
1897 // look up LSDA, if encoding says function has one
1898 if (encoding
& UNWIND_HAS_LSDA
) {
1899 UnwindSectionLsdaArray
<A
> lsdaIndex(_addressSpace
, lsdaArrayStartAddr
);
1900 uint32_t funcStartOffset
= (uint32_t)(funcStart
- sects
.dso_base
);
1902 high
= (uint32_t)(lsdaArrayEndAddr
- lsdaArrayStartAddr
) /
1903 sizeof(unwind_info_section_header_lsda_index_entry
);
1904 // binary search looks for entry with exact match for functionOffset
1907 "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1909 while (low
< high
) {
1910 uint32_t mid
= (low
+ high
) / 2;
1911 if (lsdaIndex
.functionOffset(mid
) == funcStartOffset
) {
1912 lsda
= lsdaIndex
.lsdaOffset(mid
) + sects
.dso_base
;
1914 } else if (lsdaIndex
.functionOffset(mid
) < funcStartOffset
) {
1921 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1922 "pc=0x%0llX, but lsda table has no entry",
1923 encoding
, (uint64_t) pc
);
1928 // extract personality routine, if encoding says function has one
1929 uint32_t personalityIndex
= (encoding
& UNWIND_PERSONALITY_MASK
) >>
1930 (__builtin_ctz(UNWIND_PERSONALITY_MASK
));
1931 if (personalityIndex
!= 0) {
1932 --personalityIndex
; // change 1-based to zero-based index
1933 if (personalityIndex
>= sectionHeader
.personalityArrayCount()) {
1934 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
1935 "but personality table has only %d entries",
1936 encoding
, personalityIndex
,
1937 sectionHeader
.personalityArrayCount());
1940 int32_t personalityDelta
= (int32_t)_addressSpace
.get32(
1941 sects
.compact_unwind_section
+
1942 sectionHeader
.personalityArraySectionOffset() +
1943 personalityIndex
* sizeof(uint32_t));
1944 pint_t personalityPointer
= sects
.dso_base
+ (pint_t
)personalityDelta
;
1945 personality
= _addressSpace
.getP(personalityPointer
);
1947 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1948 "personalityDelta=0x%08X, personality=0x%08llX\n",
1949 (uint64_t) pc
, personalityDelta
, (uint64_t) personality
);
1953 fprintf(stderr
, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1954 "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1955 (uint64_t) pc
, encoding
, (uint64_t) lsda
, (uint64_t) funcStart
);
1956 _info
.start_ip
= funcStart
;
1957 _info
.end_ip
= funcEnd
;
1959 _info
.handler
= personality
;
1962 _info
.format
= encoding
;
1963 _info
.unwind_info
= 0;
1964 _info
.unwind_info_size
= 0;
1965 _info
.extra
= sects
.dso_base
;
1968 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1971 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1972 template <typename A
, typename R
>
1973 bool UnwindCursor
<A
, R
>::getInfoFromSEH(pint_t pc
) {
1975 RUNTIME_FUNCTION
*unwindEntry
= lookUpSEHUnwindInfo(pc
, &base
);
1977 _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc
);
1983 _info
.unwind_info_size
= sizeof(RUNTIME_FUNCTION
);
1984 _info
.unwind_info
= reinterpret_cast<unw_word_t
>(unwindEntry
);
1986 _info
.start_ip
= base
+ unwindEntry
->BeginAddress
;
1987 #ifdef _LIBUNWIND_TARGET_X86_64
1988 _info
.end_ip
= base
+ unwindEntry
->EndAddress
;
1989 // Only fill in the handler and LSDA if they're stale.
1990 if (pc
!= getLastPC()) {
1991 UNWIND_INFO
*xdata
= reinterpret_cast<UNWIND_INFO
*>(base
+ unwindEntry
->UnwindData
);
1992 if (xdata
->Flags
& (UNW_FLAG_EHANDLER
|UNW_FLAG_UHANDLER
)) {
1993 // The personality is given in the UNWIND_INFO itself. The LSDA immediately
1994 // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
1995 // these structures.)
1996 // N.B. UNWIND_INFO structs are DWORD-aligned.
1997 uint32_t lastcode
= (xdata
->CountOfCodes
+ 1) & ~1;
1998 const uint32_t *handler
= reinterpret_cast<uint32_t *>(&xdata
->UnwindCodes
[lastcode
]);
1999 _info
.lsda
= reinterpret_cast<unw_word_t
>(handler
+1);
2000 _dispContext
.HandlerData
= reinterpret_cast<void *>(_info
.lsda
);
2001 _dispContext
.LanguageHandler
=
2002 reinterpret_cast<EXCEPTION_ROUTINE
*>(base
+ *handler
);
2004 _info
.handler
= reinterpret_cast<unw_word_t
>(__libunwind_seh_personality
);
2018 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2019 // Masks for traceback table field xtbtable.
2020 enum xTBTableMask
: uint8_t {
2021 reservedBit
= 0x02, // The traceback table was incorrectly generated if set
2022 // (see comments in function getInfoFromTBTable().
2023 ehInfoBit
= 0x08 // Exception handling info is present if set
2026 enum frameType
: unw_word_t
{
2027 frameWithXLEHStateTable
= 0,
2032 typedef _Unwind_Reason_Code
__xlcxx_personality_v0_t(int, _Unwind_Action
,
2034 _Unwind_Exception
*,
2035 struct _Unwind_Context
*);
2038 static __xlcxx_personality_v0_t
*xlcPersonalityV0
;
2039 static RWMutex xlcPersonalityV0InitLock
;
2041 template <typename A
, typename R
>
2042 bool UnwindCursor
<A
, R
>::getInfoFromTBTable(pint_t pc
, R
®isters
) {
2043 uint32_t *p
= reinterpret_cast<uint32_t *>(pc
);
2045 // Keep looking forward until a word of 0 is found. The traceback
2046 // table starts at the following word.
2049 tbtable
*TBTable
= reinterpret_cast<tbtable
*>(p
+ 1);
2051 if (_LIBUNWIND_TRACING_UNWINDING
) {
2052 char functionBuf
[512];
2053 const char *functionName
= functionBuf
;
2055 if (!getFunctionName(functionBuf
, sizeof(functionBuf
), &offset
)) {
2056 functionName
= ".anonymous.";
2058 _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
2059 __func__
, functionName
,
2060 reinterpret_cast<void *>(TBTable
));
2063 // If the traceback table does not contain necessary info, bypass this frame.
2064 if (!TBTable
->tb
.has_tboff
)
2067 // Structure tbtable_ext contains important data we are looking for.
2068 p
= reinterpret_cast<uint32_t *>(&TBTable
->tb_ext
);
2070 // Skip field parminfo if it exists.
2071 if (TBTable
->tb
.fixedparms
|| TBTable
->tb
.floatparms
)
2074 // p now points to tb_offset, the offset from start of function to TB table.
2075 unw_word_t start_ip
=
2076 reinterpret_cast<unw_word_t
>(TBTable
) - *p
- sizeof(uint32_t);
2077 unw_word_t end_ip
= reinterpret_cast<unw_word_t
>(TBTable
);
2080 _LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",
2081 reinterpret_cast<void *>(start_ip
),
2082 reinterpret_cast<void *>(end_ip
));
2084 // Skip field hand_mask if it exists.
2085 if (TBTable
->tb
.int_hndl
)
2088 unw_word_t lsda
= 0;
2089 unw_word_t handler
= 0;
2090 unw_word_t flags
= frameType::frameWithXLEHStateTable
;
2092 if (TBTable
->tb
.lang
== TB_CPLUSPLUS
&& TBTable
->tb
.has_ctl
) {
2093 // State table info is available. The ctl_info field indicates the
2094 // number of CTL anchors. There should be only one entry for the C++
2096 assert(*p
== 1 && "libunwind: there must be only one ctl_info entry");
2098 // p points to the offset of the state table into the stack.
2099 pint_t stateTableOffset
= *p
++;
2101 int framePointerReg
;
2103 // Skip fields name_len and name if exist.
2104 if (TBTable
->tb
.name_present
) {
2105 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(p
));
2106 p
= reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p
) + name_len
+
2110 if (TBTable
->tb
.uses_alloca
)
2111 framePointerReg
= *(reinterpret_cast<char *>(p
));
2113 framePointerReg
= 1; // default frame pointer == SP
2115 _LIBUNWIND_TRACE_UNWINDING(
2116 "framePointerReg=%d, framePointer=%p, "
2117 "stateTableOffset=%#lx\n",
2119 reinterpret_cast<void *>(_registers
.getRegister(framePointerReg
)),
2121 lsda
= _registers
.getRegister(framePointerReg
) + stateTableOffset
;
2123 // Since the traceback table generated by the legacy XLC++ does not
2124 // provide the location of the personality for the state table,
2125 // function __xlcxx_personality_v0(), which is the personality for the state
2126 // table and is exported from libc++abi, is directly assigned as the
2127 // handler here. When a legacy XLC++ frame is encountered, the symbol
2128 // is resolved dynamically using dlopen() to avoid a hard dependency of
2129 // libunwind on libc++abi in cases such as non-C++ applications.
2131 // Resolve the function pointer to the state table personality if it has
2132 // not already been done.
2133 if (xlcPersonalityV0
== NULL
) {
2134 xlcPersonalityV0InitLock
.lock();
2135 if (xlcPersonalityV0
== NULL
) {
2136 // Resolve __xlcxx_personality_v0 using dlopen().
2137 const char *libcxxabi
= "libc++abi.a(libc++abi.so.1)";
2139 // The AIX dlopen() sets errno to 0 when it is successful, which
2140 // clobbers the value of errno from the user code. This is an AIX
2141 // bug because according to POSIX it should not set errno to 0. To
2142 // workaround before AIX fixes the bug, errno is saved and restored.
2143 int saveErrno
= errno
;
2144 libHandle
= dlopen(libcxxabi
, RTLD_MEMBER
| RTLD_NOW
);
2145 if (libHandle
== NULL
) {
2146 _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno
);
2147 assert(0 && "dlopen() failed");
2149 xlcPersonalityV0
= reinterpret_cast<__xlcxx_personality_v0_t
*>(
2150 dlsym(libHandle
, "__xlcxx_personality_v0"));
2151 if (xlcPersonalityV0
== NULL
) {
2152 _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno
);
2154 assert(0 && "dlsym() failed");
2158 xlcPersonalityV0InitLock
.unlock();
2160 handler
= reinterpret_cast<unw_word_t
>(xlcPersonalityV0
);
2161 _LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",
2162 reinterpret_cast<void *>(lsda
),
2163 reinterpret_cast<void *>(handler
));
2164 } else if (TBTable
->tb
.longtbtable
) {
2165 // This frame has the traceback table extension. Possible cases are
2166 // 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that
2167 // is not EH aware; or, 3) a frame of other languages. We need to figure out
2168 // if the traceback table extension contains the 'eh_info' structure.
2170 // We also need to deal with the complexity arising from some XL compiler
2171 // versions use the wrong ordering of 'longtbtable' and 'has_vec' bits
2172 // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice
2173 // versa. For frames of code generated by those compilers, the 'longtbtable'
2174 // bit may be set but there isn't really a traceback table extension.
2176 // In </usr/include/sys/debug.h>, there is the following definition of
2177 // 'struct tbtable_ext'. It is not really a structure but a dummy to
2178 // collect the description of optional parts of the traceback table.
2180 // struct tbtable_ext {
2182 // char alloca_reg; /* Register for alloca automatic storage */
2183 // struct vec_ext vec_ext; /* Vector extension (if has_vec is set) */
2184 // unsigned char xtbtable; /* More tbtable fields, if longtbtable is set*/
2187 // Depending on how the 'has_vec'/'longtbtable' bit is interpreted, the data
2188 // following 'alloca_reg' can be treated either as 'struct vec_ext' or
2189 // 'unsigned char xtbtable'. 'xtbtable' bits are defined in
2190 // </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently
2191 // unused and should not be set. 'struct vec_ext' is defined in
2192 // </usr/include/sys/debug.h> as follows:
2195 // unsigned vr_saved:6; /* Number of non-volatile vector regs saved
2197 // /* first register saved is assumed to be */
2198 // /* 32 - vr_saved */
2199 // unsigned saves_vrsave:1; /* Set if vrsave is saved on the stack */
2200 // unsigned has_varargs:1;
2204 // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it
2205 // is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',
2206 // we checks if the 7th bit is set or not because 'xtbtable' should
2207 // never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved
2208 // in the future to make sure the mitigation works. This mitigation
2209 // is not 100% bullet proof because 'struct vec_ext' may not always have
2210 // 'saves_vrsave' bit set.
2212 // 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for
2213 // checking the 7th bit.
2215 // p points to field name len.
2216 uint8_t *charPtr
= reinterpret_cast<uint8_t *>(p
);
2218 // Skip fields name_len and name if they exist.
2219 if (TBTable
->tb
.name_present
) {
2220 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(charPtr
));
2221 charPtr
= charPtr
+ name_len
+ sizeof(uint16_t);
2224 // Skip field alloc_reg if it exists.
2225 if (TBTable
->tb
.uses_alloca
)
2228 // Check traceback table bit has_vec. Skip struct vec_ext if it exists.
2229 if (TBTable
->tb
.has_vec
)
2230 // Note struct vec_ext does exist at this point because whether the
2231 // ordering of longtbtable and has_vec bits is correct or not, both
2233 charPtr
+= sizeof(struct vec_ext
);
2235 // charPtr points to field 'xtbtable'. Check if the EH info is available.
2236 // Also check if the reserved bit of the extended traceback table field
2237 // 'xtbtable' is set. If it is, the traceback table was incorrectly
2238 // generated by an XL compiler that uses the wrong ordering of 'longtbtable'
2239 // and 'has_vec' bits and this is in fact 'struct vec_ext'. So skip the
2241 if ((*charPtr
& xTBTableMask::ehInfoBit
) &&
2242 !(*charPtr
& xTBTableMask::reservedBit
)) {
2243 // Mark this frame has the new EH info.
2244 flags
= frameType::frameWithEHInfo
;
2246 // eh_info is available.
2248 // The pointer is 4-byte aligned.
2249 if (reinterpret_cast<uintptr_t>(charPtr
) % 4)
2250 charPtr
+= 4 - reinterpret_cast<uintptr_t>(charPtr
) % 4;
2252 reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(
2253 registers
.getRegister(2) +
2254 *(reinterpret_cast<uintptr_t *>(charPtr
)))));
2256 // ehInfo points to structure en_info. The first member is version.
2257 // Only version 0 is currently supported.
2258 assert(*(reinterpret_cast<uint32_t *>(ehInfo
)) == 0 &&
2259 "libunwind: ehInfo version other than 0 is not supported");
2261 // Increment ehInfo to point to member lsda.
2265 // enInfo now points to member personality.
2268 _LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",
2273 _info
.start_ip
= start_ip
;
2274 _info
.end_ip
= end_ip
;
2276 _info
.handler
= handler
;
2278 _info
.flags
= flags
;
2280 _info
.unwind_info
= reinterpret_cast<unw_word_t
>(TBTable
);
2281 _info
.unwind_info_size
= 0;
2282 _info
.extra
= registers
.getRegister(2);
2287 // Step back up the stack following the frame back link.
2288 template <typename A
, typename R
>
2289 int UnwindCursor
<A
, R
>::stepWithTBTable(pint_t pc
, tbtable
*TBTable
,
2290 R
®isters
, bool &isSignalFrame
) {
2291 if (_LIBUNWIND_TRACING_UNWINDING
) {
2292 char functionBuf
[512];
2293 const char *functionName
= functionBuf
;
2295 if (!getFunctionName(functionBuf
, sizeof(functionBuf
), &offset
)) {
2296 functionName
= ".anonymous.";
2298 _LIBUNWIND_TRACE_UNWINDING(
2299 "%s: Look up traceback table of func=%s at %p, pc=%p, "
2300 "SP=%p, saves_lr=%d, stores_bc=%d",
2301 __func__
, functionName
, reinterpret_cast<void *>(TBTable
),
2302 reinterpret_cast<void *>(pc
),
2303 reinterpret_cast<void *>(registers
.getSP()), TBTable
->tb
.saves_lr
,
2304 TBTable
->tb
.stores_bc
);
2307 #if defined(__powerpc64__)
2308 // Instruction to reload TOC register "ld r2,40(r1)"
2309 const uint32_t loadTOCRegInst
= 0xe8410028;
2310 const int32_t unwPPCF0Index
= UNW_PPC64_F0
;
2311 const int32_t unwPPCV0Index
= UNW_PPC64_V0
;
2313 // Instruction to reload TOC register "lwz r2,20(r1)"
2314 const uint32_t loadTOCRegInst
= 0x80410014;
2315 const int32_t unwPPCF0Index
= UNW_PPC_F0
;
2316 const int32_t unwPPCV0Index
= UNW_PPC_V0
;
2319 // lastStack points to the stack frame of the next routine up.
2320 pint_t curStack
= static_cast<pint_t
>(registers
.getSP());
2321 pint_t lastStack
= *reinterpret_cast<pint_t
*>(curStack
);
2324 return UNW_STEP_END
;
2326 R newRegisters
= registers
;
2328 // If backchain is not stored, use the current stack frame.
2329 if (!TBTable
->tb
.stores_bc
)
2330 lastStack
= curStack
;
2332 // Return address is the address after call site instruction.
2333 pint_t returnAddress
;
2335 if (isSignalFrame
) {
2336 _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
2337 reinterpret_cast<void *>(lastStack
));
2339 sigcontext
*sigContext
= reinterpret_cast<sigcontext
*>(
2340 reinterpret_cast<char *>(lastStack
) + STKMINALIGN
);
2341 returnAddress
= sigContext
->sc_jmpbuf
.jmp_context
.iar
;
2343 bool useSTKMIN
= false;
2344 if (returnAddress
< 0x10000000) {
2345 // Try again using STKMIN.
2346 sigContext
= reinterpret_cast<sigcontext
*>(
2347 reinterpret_cast<char *>(lastStack
) + STKMIN
);
2348 returnAddress
= sigContext
->sc_jmpbuf
.jmp_context
.iar
;
2349 if (returnAddress
< 0x10000000) {
2350 _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
2351 reinterpret_cast<void *>(returnAddress
),
2352 reinterpret_cast<void *>(sigContext
));
2353 return UNW_EBADFRAME
;
2357 _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
2358 "sigContext=%p, returnAddress=%p. "
2359 "Seems to be a valid address",
2360 useSTKMIN
? "STKMIN" : "STKMINALIGN",
2361 reinterpret_cast<void *>(sigContext
),
2362 reinterpret_cast<void *>(returnAddress
));
2364 // Restore the condition register from sigcontext.
2365 newRegisters
.setCR(sigContext
->sc_jmpbuf
.jmp_context
.cr
);
2367 // Save the LR in sigcontext for stepping up when the function that
2368 // raised the signal is a leaf function. This LR has the return address
2369 // to the caller of the leaf function.
2370 newRegisters
.setLR(sigContext
->sc_jmpbuf
.jmp_context
.lr
);
2371 _LIBUNWIND_TRACE_UNWINDING(
2372 "Save LR=%p from sigcontext",
2373 reinterpret_cast<void *>(sigContext
->sc_jmpbuf
.jmp_context
.lr
));
2375 // Restore GPRs from sigcontext.
2376 for (int i
= 0; i
< 32; ++i
)
2377 newRegisters
.setRegister(i
, sigContext
->sc_jmpbuf
.jmp_context
.gpr
[i
]);
2379 // Restore FPRs from sigcontext.
2380 for (int i
= 0; i
< 32; ++i
)
2381 newRegisters
.setFloatRegister(i
+ unwPPCF0Index
,
2382 sigContext
->sc_jmpbuf
.jmp_context
.fpr
[i
]);
2384 // Restore vector registers if there is an associated extended context
2386 if (sigContext
->sc_jmpbuf
.jmp_context
.msr
& __EXTCTX
) {
2387 ucontext_t
*uContext
= reinterpret_cast<ucontext_t
*>(sigContext
);
2388 if (uContext
->__extctx
->__extctx_magic
== __EXTCTX_MAGIC
) {
2389 for (int i
= 0; i
< 32; ++i
)
2390 newRegisters
.setVectorRegister(
2391 i
+ unwPPCV0Index
, *(reinterpret_cast<v128
*>(
2392 &(uContext
->__extctx
->__vmx
.__vr
[i
]))));
2396 // Step up a normal frame.
2398 if (!TBTable
->tb
.saves_lr
&& registers
.getLR()) {
2399 // This case should only occur if we were called from a signal handler
2400 // and the signal occurred in a function that doesn't save the LR.
2401 returnAddress
= static_cast<pint_t
>(registers
.getLR());
2402 _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
2403 reinterpret_cast<void *>(returnAddress
));
2405 // Otherwise, use the LR value in the stack link area.
2406 returnAddress
= reinterpret_cast<pint_t
*>(lastStack
)[2];
2409 // Reset LR in the current context.
2410 newRegisters
.setLR(static_cast<uintptr_t>(NULL
));
2412 _LIBUNWIND_TRACE_UNWINDING(
2413 "Extract info from lastStack=%p, returnAddress=%p",
2414 reinterpret_cast<void *>(lastStack
),
2415 reinterpret_cast<void *>(returnAddress
));
2416 _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
2417 TBTable
->tb
.fpr_saved
, TBTable
->tb
.gpr_saved
,
2418 TBTable
->tb
.saves_cr
);
2420 // Restore FP registers.
2421 char *ptrToRegs
= reinterpret_cast<char *>(lastStack
);
2422 double *FPRegs
= reinterpret_cast<double *>(
2423 ptrToRegs
- (TBTable
->tb
.fpr_saved
* sizeof(double)));
2424 for (int i
= 0; i
< TBTable
->tb
.fpr_saved
; ++i
)
2425 newRegisters
.setFloatRegister(
2426 32 - TBTable
->tb
.fpr_saved
+ i
+ unwPPCF0Index
, FPRegs
[i
]);
2428 // Restore GP registers.
2429 ptrToRegs
= reinterpret_cast<char *>(FPRegs
);
2430 uintptr_t *GPRegs
= reinterpret_cast<uintptr_t *>(
2431 ptrToRegs
- (TBTable
->tb
.gpr_saved
* sizeof(uintptr_t)));
2432 for (int i
= 0; i
< TBTable
->tb
.gpr_saved
; ++i
)
2433 newRegisters
.setRegister(32 - TBTable
->tb
.gpr_saved
+ i
, GPRegs
[i
]);
2435 // Restore Vector registers.
2436 ptrToRegs
= reinterpret_cast<char *>(GPRegs
);
2438 // Restore vector registers only if this is a Clang frame. Also
2439 // check if traceback table bit has_vec is set. If it is, structure
2440 // vec_ext is available.
2441 if (_info
.flags
== frameType::frameWithEHInfo
&& TBTable
->tb
.has_vec
) {
2443 // Get to the vec_ext structure to check if vector registers are saved.
2444 uint32_t *p
= reinterpret_cast<uint32_t *>(&TBTable
->tb_ext
);
2446 // Skip field parminfo if exists.
2447 if (TBTable
->tb
.fixedparms
|| TBTable
->tb
.floatparms
)
2450 // Skip field tb_offset if exists.
2451 if (TBTable
->tb
.has_tboff
)
2454 // Skip field hand_mask if exists.
2455 if (TBTable
->tb
.int_hndl
)
2458 // Skip fields ctl_info and ctl_info_disp if exist.
2459 if (TBTable
->tb
.has_ctl
) {
2460 // Skip field ctl_info.
2462 // Skip field ctl_info_disp.
2466 // Skip fields name_len and name if exist.
2467 // p is supposed to point to field name_len now.
2468 uint8_t *charPtr
= reinterpret_cast<uint8_t *>(p
);
2469 if (TBTable
->tb
.name_present
) {
2470 const uint16_t name_len
= *(reinterpret_cast<uint16_t *>(charPtr
));
2471 charPtr
= charPtr
+ name_len
+ sizeof(uint16_t);
2474 // Skip field alloc_reg if it exists.
2475 if (TBTable
->tb
.uses_alloca
)
2478 struct vec_ext
*vec_ext
= reinterpret_cast<struct vec_ext
*>(charPtr
);
2480 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext
->vr_saved
);
2482 // Restore vector register(s) if saved on the stack.
2483 if (vec_ext
->vr_saved
) {
2484 // Saved vector registers are 16-byte aligned.
2485 if (reinterpret_cast<uintptr_t>(ptrToRegs
) % 16)
2486 ptrToRegs
-= reinterpret_cast<uintptr_t>(ptrToRegs
) % 16;
2487 v128
*VecRegs
= reinterpret_cast<v128
*>(ptrToRegs
- vec_ext
->vr_saved
*
2489 for (int i
= 0; i
< vec_ext
->vr_saved
; ++i
) {
2490 newRegisters
.setVectorRegister(
2491 32 - vec_ext
->vr_saved
+ i
+ unwPPCV0Index
, VecRegs
[i
]);
2495 if (TBTable
->tb
.saves_cr
) {
2496 // Get the saved condition register. The condition register is only
2499 *(reinterpret_cast<uint32_t *>(lastStack
+ sizeof(uintptr_t))));
2503 newRegisters
.setSP(lastStack
);
2505 // The first instruction after return.
2506 uint32_t firstInstruction
= *(reinterpret_cast<uint32_t *>(returnAddress
));
2508 // Do we need to set the TOC register?
2509 _LIBUNWIND_TRACE_UNWINDING(
2511 reinterpret_cast<void *>(newRegisters
.getRegister(2)));
2512 if (firstInstruction
== loadTOCRegInst
) {
2513 _LIBUNWIND_TRACE_UNWINDING(
2514 "Set gpr2=%p from frame",
2515 reinterpret_cast<void *>(reinterpret_cast<pint_t
*>(lastStack
)[5]));
2516 newRegisters
.setRegister(2, reinterpret_cast<pint_t
*>(lastStack
)[5]);
2519 _LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",
2520 reinterpret_cast<void *>(lastStack
),
2521 reinterpret_cast<void *>(returnAddress
),
2522 reinterpret_cast<void *>(pc
));
2524 // The return address is the address after call site instruction, so
2525 // setting IP to that simulates a return.
2526 newRegisters
.setIP(reinterpret_cast<uintptr_t>(returnAddress
));
2528 // Simulate the step by replacing the register set with the new ones.
2529 registers
= newRegisters
;
2531 // Check if the next frame is a signal frame.
2532 pint_t nextStack
= *(reinterpret_cast<pint_t
*>(registers
.getSP()));
2534 // Return address is the address after call site instruction.
2535 pint_t nextReturnAddress
= reinterpret_cast<pint_t
*>(nextStack
)[2];
2537 if (nextReturnAddress
> 0x01 && nextReturnAddress
< 0x10000) {
2538 _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
2539 "nextStack=%p, next return address=%p\n",
2540 reinterpret_cast<void *>(nextStack
),
2541 reinterpret_cast<void *>(nextReturnAddress
));
2542 isSignalFrame
= true;
2544 isSignalFrame
= false;
2546 return UNW_STEP_SUCCESS
;
2548 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2550 template <typename A
, typename R
>
2551 void UnwindCursor
<A
, R
>::setInfoBasedOnIPRegister(bool isReturnAddress
) {
2552 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
2553 _isSigReturn
= false;
2556 pint_t pc
= static_cast<pint_t
>(this->getReg(UNW_REG_IP
));
2557 #if defined(_LIBUNWIND_ARM_EHABI)
2558 // Remove the thumb bit so the IP represents the actual instruction address.
2559 // This matches the behaviour of _Unwind_GetIP on arm.
2563 // Exit early if at the top of the stack.
2565 _unwindInfoMissing
= true;
2569 // If the last line of a function is a "throw" the compiler sometimes
2570 // emits no instructions after the call to __cxa_throw. This means
2571 // the return address is actually the start of the next function.
2572 // To disambiguate this, back up the pc when we know it is a return
2574 if (isReturnAddress
)
2576 // PC needs to be a 4-byte aligned address to be able to look for a
2577 // word of 0 that indicates the start of the traceback table at the end
2578 // of a function on AIX.
2584 #if !(defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)) && \
2585 !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2586 // In case of this is frame of signal handler, the IP saved in the signal
2587 // handler points to first non-executed instruction, while FDE/CIE expects IP
2588 // to be after the first non-executed instruction.
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) || defined(_LIBUNWIND_USE_GCS)
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__