1//===----------------------------------------------------------------------===//
2//
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
6//
7//
8// C++ interface to lower levels of libunwind
9//===----------------------------------------------------------------------===//
10
11#ifndef __UNWINDCURSOR_HPP__
12#define __UNWINDCURSOR_HPP__
13
14#include "shadow_stack_unwind.h"
15#include <stdint.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <unwind.h>
19
20#ifdef _WIN32
21 #include <windows.h>
22 #include <ntverp.h>
23#endif
24#ifdef __APPLE__
25 #include <mach-o/dyld.h>
26#endif
27#ifdef _AIX
28#include <dlfcn.h>
29#include <sys/debug.h>
30#include <sys/pseg.h>
31#endif
32
33#if defined(_LIBUNWIND_TARGET_LINUX) && \
34 (defined(_LIBUNWIND_TARGET_AARCH64) || \
35 defined(_LIBUNWIND_TARGET_LOONGARCH) || \
36 defined(_LIBUNWIND_TARGET_RISCV) || defined(_LIBUNWIND_TARGET_S390X))
37#include <errno.h>
38#include <signal.h>
39#include <sys/syscall.h>
40#include <unistd.h>
41#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
42#endif
43
44#if defined(_LIBUNWIND_TARGET_HAIKU) && \
45 (defined(_LIBUNWIND_TARGET_I386) || defined(_LIBUNWIND_TARGET_X86_64))
46#include <OS.h>
47#include <signal.h>
48#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1
49#endif
50
51#include "AddressSpace.hpp"
52#include "CompactUnwinder.hpp"
53#include "config.h"
54#include "DwarfInstructions.hpp"
55#include "EHHeaderParser.hpp"
56#include "libunwind.h"
57#include "libunwind_ext.h"
58#include "Registers.hpp"
59#include "RWMutex.hpp"
60#include "Unwind-EHABI.h"
61
62#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
63// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
64// earlier) SDKs.
65// MinGW-w64 has always provided this struct.
66 #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
67 !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
68struct _DISPATCHER_CONTEXT {
69 ULONG64 ControlPc;
70 ULONG64 ImageBase;
71 PRUNTIME_FUNCTION FunctionEntry;
72 ULONG64 EstablisherFrame;
73 ULONG64 TargetIp;
74 PCONTEXT ContextRecord;
75 PEXCEPTION_ROUTINE LanguageHandler;
76 PVOID HandlerData;
77 PUNWIND_HISTORY_TABLE HistoryTable;
78 ULONG ScopeIndex;
79 ULONG Fill0;
80};
81 #endif
82
83struct UNWIND_INFO {
84 uint8_t Version : 3;
85 uint8_t Flags : 5;
86 uint8_t SizeOfProlog;
87 uint8_t CountOfCodes;
88 uint8_t FrameRegister : 4;
89 uint8_t FrameOffset : 4;
90 uint16_t UnwindCodes[2];
91};
92
93#pragma clang diagnostic push
94#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
95union UNWIND_INFO_ARM {
96 DWORD HeaderData;
97 struct {
98 DWORD FunctionLength : 18;
99 DWORD Version : 2;
100 DWORD ExceptionDataPresent : 1;
101 DWORD EpilogInHeader : 1;
102 DWORD FunctionFragment : 1;
103 DWORD EpilogCount : 5;
104 DWORD CodeWords : 4;
105 };
106};
107#pragma clang diagnostic pop
108
109extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
110 int, _Unwind_Action, uint64_t, _Unwind_Exception *,
111 struct _Unwind_Context *);
112
113#endif
114
115namespace libunwind {
116
117#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
118/// Cache of recently found FDEs.
119template <typename A>
120class _LIBUNWIND_HIDDEN DwarfFDECache {
121 typedef typename A::pint_t pint_t;
122public:
123 static constexpr pint_t kSearchAll = static_cast<pint_t>(-1);
124 template <typename R>
125 static pint_t findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc);
126
127 static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
128 static void removeAllIn(pint_t mh);
129 static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
130 unw_word_t ip_end,
131 unw_word_t fde, unw_word_t mh));
132
133private:
134
135 struct entry {
136 pint_t mh;
137 pint_t ip_start;
138 pint_t ip_end;
139 pint_t fde;
140 };
141
142 // These fields are all static to avoid needing an initializer.
143 // There is only one instance of this class per process.
144 static RWMutex _lock;
145#ifdef __APPLE__
146 static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
147 static bool _registeredForDyldUnloads;
148#endif
149 static entry *_buffer;
150 static entry *_bufferUsed;
151 static entry *_bufferEnd;
152 static entry _initialBuffer[64];
153};
154
155template <typename A>
156typename DwarfFDECache<A>::entry *
157DwarfFDECache<A>::_buffer = _initialBuffer;
158
159template <typename A>
160typename DwarfFDECache<A>::entry *
161DwarfFDECache<A>::_bufferUsed = _initialBuffer;
162
163template <typename A>
164typename DwarfFDECache<A>::entry *
165DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
166
167template <typename A>
168typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
169
170template <typename A>
171RWMutex DwarfFDECache<A>::_lock;
172
173#ifdef __APPLE__
174template <typename A>
175bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
176#endif
177
178template <typename A>
179template <typename R>
180typename DwarfFDECache<A>::pint_t
181DwarfFDECache<A>::findFDE(pint_t mh, typename R::link_hardened_reg_arg_t pc) {
182 pint_t result = 0;
183 _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
184 for (entry *p = _buffer; p < _bufferUsed; ++p) {
185 if ((mh == p->mh) || (mh == kSearchAll)) {
186 if ((p->ip_start <= pc) && (pc < p->ip_end)) {
187 result = p->fde;
188 break;
189 }
190 }
191 }
192 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared());
193 return result;
194}
195
196template <typename A>
197void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
198 pint_t fde) {
199#if !defined(_LIBUNWIND_NO_HEAP)
200 _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
201 if (_bufferUsed >= _bufferEnd) {
202 size_t oldSize = (size_t)(_bufferEnd - _buffer);
203 size_t newSize = oldSize * 4;
204 // Can't use operator new (we are below it).
205 entry *newBuffer = (entry *)malloc(size: newSize * sizeof(entry));
206 memcpy(newBuffer, _buffer, oldSize * sizeof(entry));
207 if (_buffer != _initialBuffer)
208 free(_buffer);
209 _buffer = newBuffer;
210 _bufferUsed = &newBuffer[oldSize];
211 _bufferEnd = &newBuffer[newSize];
212 }
213 _bufferUsed->mh = mh;
214 _bufferUsed->ip_start = ip_start;
215 _bufferUsed->ip_end = ip_end;
216 _bufferUsed->fde = fde;
217 ++_bufferUsed;
218#ifdef __APPLE__
219 if (!_registeredForDyldUnloads) {
220 _dyld_register_func_for_remove_image(&dyldUnloadHook);
221 _registeredForDyldUnloads = true;
222 }
223#endif
224 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
225#endif
226}
227
228template <typename A>
229void DwarfFDECache<A>::removeAllIn(pint_t mh) {
230 _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
231 entry *d = _buffer;
232 for (const entry *s = _buffer; s < _bufferUsed; ++s) {
233 if (s->mh != mh) {
234 if (d != s)
235 *d = *s;
236 ++d;
237 }
238 }
239 _bufferUsed = d;
240 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
241}
242
243#ifdef __APPLE__
244template <typename A>
245void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {
246 removeAllIn((pint_t) mh);
247}
248#endif
249
250template <typename A>
251void DwarfFDECache<A>::iterateCacheEntries(void (*func)(
252 unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
253 _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
254 for (entry *p = _buffer; p < _bufferUsed; ++p) {
255 (*func)(p->ip_start, p->ip_end, p->fde, p->mh);
256 }
257 _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
258}
259#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
260
261#define arrayoffsetof(type, index, field) \
262 (sizeof(type) * (index) + offsetof(type, field))
263
264#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
265template <typename A> class UnwindSectionHeader {
266public:
267 UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)
268 : _addressSpace(addressSpace), _addr(addr) {}
269
270 uint32_t version() const {
271 return _addressSpace.get32(_addr +
272 offsetof(unwind_info_section_header, version));
273 }
274 uint32_t commonEncodingsArraySectionOffset() const {
275 return _addressSpace.get32(_addr +
276 offsetof(unwind_info_section_header,
277 commonEncodingsArraySectionOffset));
278 }
279 uint32_t commonEncodingsArrayCount() const {
280 return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
281 commonEncodingsArrayCount));
282 }
283 uint32_t personalityArraySectionOffset() const {
284 return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
285 personalityArraySectionOffset));
286 }
287 uint32_t personalityArrayCount() const {
288 return _addressSpace.get32(
289 _addr + offsetof(unwind_info_section_header, personalityArrayCount));
290 }
291 uint32_t indexSectionOffset() const {
292 return _addressSpace.get32(
293 _addr + offsetof(unwind_info_section_header, indexSectionOffset));
294 }
295 uint32_t indexCount() const {
296 return _addressSpace.get32(
297 _addr + offsetof(unwind_info_section_header, indexCount));
298 }
299
300private:
301 A &_addressSpace;
302 typename A::pint_t _addr;
303};
304
305template <typename A> class UnwindSectionIndexArray {
306public:
307 UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr)
308 : _addressSpace(addressSpace), _addr(addr) {}
309
310 uint32_t functionOffset(uint32_t index) const {
311 return _addressSpace.get32(
312 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
313 functionOffset));
314 }
315 uint32_t secondLevelPagesSectionOffset(uint32_t index) const {
316 return _addressSpace.get32(
317 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
318 secondLevelPagesSectionOffset));
319 }
320 uint32_t lsdaIndexArraySectionOffset(uint32_t index) const {
321 return _addressSpace.get32(
322 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
323 lsdaIndexArraySectionOffset));
324 }
325
326private:
327 A &_addressSpace;
328 typename A::pint_t _addr;
329};
330
331template <typename A> class UnwindSectionRegularPageHeader {
332public:
333 UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr)
334 : _addressSpace(addressSpace), _addr(addr) {}
335
336 uint32_t kind() const {
337 return _addressSpace.get32(
338 _addr + offsetof(unwind_info_regular_second_level_page_header, kind));
339 }
340 uint16_t entryPageOffset() const {
341 return _addressSpace.get16(
342 _addr + offsetof(unwind_info_regular_second_level_page_header,
343 entryPageOffset));
344 }
345 uint16_t entryCount() const {
346 return _addressSpace.get16(
347 _addr +
348 offsetof(unwind_info_regular_second_level_page_header, entryCount));
349 }
350
351private:
352 A &_addressSpace;
353 typename A::pint_t _addr;
354};
355
356template <typename A> class UnwindSectionRegularArray {
357public:
358 UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr)
359 : _addressSpace(addressSpace), _addr(addr) {}
360
361 uint32_t functionOffset(uint32_t index) const {
362 return _addressSpace.get32(
363 _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index,
364 functionOffset));
365 }
366 uint32_t encoding(uint32_t index) const {
367 return _addressSpace.get32(
368 _addr +
369 arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding));
370 }
371
372private:
373 A &_addressSpace;
374 typename A::pint_t _addr;
375};
376
377template <typename A> class UnwindSectionCompressedPageHeader {
378public:
379 UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr)
380 : _addressSpace(addressSpace), _addr(addr) {}
381
382 uint32_t kind() const {
383 return _addressSpace.get32(
384 _addr +
385 offsetof(unwind_info_compressed_second_level_page_header, kind));
386 }
387 uint16_t entryPageOffset() const {
388 return _addressSpace.get16(
389 _addr + offsetof(unwind_info_compressed_second_level_page_header,
390 entryPageOffset));
391 }
392 uint16_t entryCount() const {
393 return _addressSpace.get16(
394 _addr +
395 offsetof(unwind_info_compressed_second_level_page_header, entryCount));
396 }
397 uint16_t encodingsPageOffset() const {
398 return _addressSpace.get16(
399 _addr + offsetof(unwind_info_compressed_second_level_page_header,
400 encodingsPageOffset));
401 }
402 uint16_t encodingsCount() const {
403 return _addressSpace.get16(
404 _addr + offsetof(unwind_info_compressed_second_level_page_header,
405 encodingsCount));
406 }
407
408private:
409 A &_addressSpace;
410 typename A::pint_t _addr;
411};
412
413template <typename A> class UnwindSectionCompressedArray {
414public:
415 UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr)
416 : _addressSpace(addressSpace), _addr(addr) {}
417
418 uint32_t functionOffset(uint32_t index) const {
419 return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
420 _addressSpace.get32(_addr + index * sizeof(uint32_t)));
421 }
422 uint16_t encodingIndex(uint32_t index) const {
423 return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
424 _addressSpace.get32(_addr + index * sizeof(uint32_t)));
425 }
426
427private:
428 A &_addressSpace;
429 typename A::pint_t _addr;
430};
431
432template <typename A> class UnwindSectionLsdaArray {
433public:
434 UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr)
435 : _addressSpace(addressSpace), _addr(addr) {}
436
437 uint32_t functionOffset(uint32_t index) const {
438 return _addressSpace.get32(
439 _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
440 index, functionOffset));
441 }
442 uint32_t lsdaOffset(uint32_t index) const {
443 return _addressSpace.get32(
444 _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
445 index, lsdaOffset));
446 }
447
448private:
449 A &_addressSpace;
450 typename A::pint_t _addr;
451};
452#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
453
454class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
455public:
456 // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
457 // This avoids an unnecessary dependency to libc++abi.
458 void operator delete(void *, size_t) {}
459
460 virtual ~AbstractUnwindCursor() {}
461 virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
462 virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
463 virtual void setReg(int, unw_word_t) {
464 _LIBUNWIND_ABORT("setReg not implemented");
465 }
466 virtual bool validFloatReg(int) {
467 _LIBUNWIND_ABORT("validFloatReg not implemented");
468 }
469 virtual unw_fpreg_t getFloatReg(int) {
470 _LIBUNWIND_ABORT("getFloatReg not implemented");
471 }
472 virtual void setFloatReg(int, unw_fpreg_t) {
473 _LIBUNWIND_ABORT("setFloatReg not implemented");
474 }
475 virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); }
476 virtual void getInfo(unw_proc_info_t *) {
477 _LIBUNWIND_ABORT("getInfo not implemented");
478 }
479 _LIBUNWIND_TRACE_NO_INLINE virtual void jumpto() {
480 _LIBUNWIND_ABORT("jumpto not implemented");
481 }
482 virtual bool isSignalFrame() {
483 _LIBUNWIND_ABORT("isSignalFrame not implemented");
484 }
485 virtual bool getFunctionName(char *, size_t, unw_word_t *) {
486 _LIBUNWIND_ABORT("getFunctionName not implemented");
487 }
488 virtual void setInfoBasedOnIPRegister(bool = false) {
489 _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
490 }
491 virtual const char *getRegisterName(int) {
492 _LIBUNWIND_ABORT("getRegisterName not implemented");
493 }
494#ifdef __arm__
495 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
496#endif
497
498#ifdef _LIBUNWIND_TRACE_RET_INJECT
499 virtual void setWalkedFrames(unsigned) {
500 _LIBUNWIND_ABORT("setWalkedFrames not implemented");
501 }
502#endif
503
504#ifdef _AIX
505 virtual uintptr_t getDataRelBase() {
506 _LIBUNWIND_ABORT("getDataRelBase not implemented");
507 }
508#endif
509
510#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
511 virtual void *get_registers() {
512 _LIBUNWIND_ABORT("get_registers not implemented");
513 }
514#endif
515};
516
517#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
518
519/// \c UnwindCursor contains all state (including all register values) during
520/// an unwind. This is normally stack-allocated inside a unw_cursor_t.
521template <typename A, typename R>
522class UnwindCursor : public AbstractUnwindCursor {
523 typedef typename A::pint_t pint_t;
524public:
525 UnwindCursor(unw_context_t *context, A &as);
526 UnwindCursor(CONTEXT *context, A &as);
527 UnwindCursor(A &as, void *threadArg);
528 virtual ~UnwindCursor() {}
529 virtual bool validReg(int);
530 virtual unw_word_t getReg(int);
531 virtual void setReg(int, unw_word_t);
532 virtual bool validFloatReg(int);
533 virtual unw_fpreg_t getFloatReg(int);
534 virtual void setFloatReg(int, unw_fpreg_t);
535 virtual int step(bool = false);
536 virtual void getInfo(unw_proc_info_t *);
537 virtual void jumpto();
538 virtual bool isSignalFrame();
539 virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
540 virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
541 virtual const char *getRegisterName(int num);
542#ifdef __arm__
543 virtual void saveVFPAsX();
544#endif
545
546 DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
547 void setDispatcherContext(DISPATCHER_CONTEXT *disp) {
548 _dispContext = *disp;
549 _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
550 if (_dispContext.LanguageHandler) {
551 _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
552 } else
553 _info.handler = 0;
554 }
555
556 // libunwind does not and should not depend on C++ library which means that we
557 // need our own definition of inline placement new.
558 static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
559
560private:
561
562 pint_t getLastPC() const { return _dispContext.ControlPc; }
563 void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
564 RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
565#ifdef __arm__
566 // Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.
567 pc &= ~1U;
568#endif
569 // If pc points exactly at the end of the range, we might resolve the
570 // next function instead. Decrement pc by 1 to fit inside the current
571 // function.
572 pc -= 1;
573 _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
574 &_dispContext.ImageBase,
575 _dispContext.HistoryTable);
576 *base = _dispContext.ImageBase;
577 return _dispContext.FunctionEntry;
578 }
579 bool getInfoFromSEH(pint_t pc);
580 int stepWithSEHData() {
581 _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
582 _dispContext.ImageBase,
583 _dispContext.ControlPc,
584 _dispContext.FunctionEntry,
585 _dispContext.ContextRecord,
586 &_dispContext.HandlerData,
587 &_dispContext.EstablisherFrame,
588 NULL);
589 // Update some fields of the unwind info now, since we have them.
590 _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
591 if (_dispContext.LanguageHandler) {
592 _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
593 } else
594 _info.handler = 0;
595 return UNW_STEP_SUCCESS;
596 }
597
598 A &_addressSpace;
599 unw_proc_info_t _info;
600 DISPATCHER_CONTEXT _dispContext;
601 CONTEXT _msContext;
602 UNWIND_HISTORY_TABLE _histTable;
603 bool _unwindInfoMissing;
604};
605
606
607template <typename A, typename R>
608UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
609 : _addressSpace(as), _unwindInfoMissing(false) {
610 static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
611 "UnwindCursor<> does not fit in unw_cursor_t");
612 static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
613 "UnwindCursor<> requires more alignment than unw_cursor_t");
614 memset(&_info, 0, sizeof(_info));
615 memset(&_histTable, 0, sizeof(_histTable));
616 memset(&_dispContext, 0, sizeof(_dispContext));
617 _dispContext.ContextRecord = &_msContext;
618 _dispContext.HistoryTable = &_histTable;
619 // Initialize MS context from ours.
620 R r(context);
621 RtlCaptureContext(&_msContext);
622 _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
623#if defined(_LIBUNWIND_TARGET_X86_64)
624 _msContext.Rax = r.getRegister(UNW_X86_64_RAX);
625 _msContext.Rcx = r.getRegister(UNW_X86_64_RCX);
626 _msContext.Rdx = r.getRegister(UNW_X86_64_RDX);
627 _msContext.Rbx = r.getRegister(UNW_X86_64_RBX);
628 _msContext.Rsp = r.getRegister(UNW_X86_64_RSP);
629 _msContext.Rbp = r.getRegister(UNW_X86_64_RBP);
630 _msContext.Rsi = r.getRegister(UNW_X86_64_RSI);
631 _msContext.Rdi = r.getRegister(UNW_X86_64_RDI);
632 _msContext.R8 = r.getRegister(UNW_X86_64_R8);
633 _msContext.R9 = r.getRegister(UNW_X86_64_R9);
634 _msContext.R10 = r.getRegister(UNW_X86_64_R10);
635 _msContext.R11 = r.getRegister(UNW_X86_64_R11);
636 _msContext.R12 = r.getRegister(UNW_X86_64_R12);
637 _msContext.R13 = r.getRegister(UNW_X86_64_R13);
638 _msContext.R14 = r.getRegister(UNW_X86_64_R14);
639 _msContext.R15 = r.getRegister(UNW_X86_64_R15);
640 _msContext.Rip = r.getRegister(UNW_REG_IP);
641 union {
642 v128 v;
643 M128A m;
644 } t;
645 t.v = r.getVectorRegister(UNW_X86_64_XMM0);
646 _msContext.Xmm0 = t.m;
647 t.v = r.getVectorRegister(UNW_X86_64_XMM1);
648 _msContext.Xmm1 = t.m;
649 t.v = r.getVectorRegister(UNW_X86_64_XMM2);
650 _msContext.Xmm2 = t.m;
651 t.v = r.getVectorRegister(UNW_X86_64_XMM3);
652 _msContext.Xmm3 = t.m;
653 t.v = r.getVectorRegister(UNW_X86_64_XMM4);
654 _msContext.Xmm4 = t.m;
655 t.v = r.getVectorRegister(UNW_X86_64_XMM5);
656 _msContext.Xmm5 = t.m;
657 t.v = r.getVectorRegister(UNW_X86_64_XMM6);
658 _msContext.Xmm6 = t.m;
659 t.v = r.getVectorRegister(UNW_X86_64_XMM7);
660 _msContext.Xmm7 = t.m;
661 t.v = r.getVectorRegister(UNW_X86_64_XMM8);
662 _msContext.Xmm8 = t.m;
663 t.v = r.getVectorRegister(UNW_X86_64_XMM9);
664 _msContext.Xmm9 = t.m;
665 t.v = r.getVectorRegister(UNW_X86_64_XMM10);
666 _msContext.Xmm10 = t.m;
667 t.v = r.getVectorRegister(UNW_X86_64_XMM11);
668 _msContext.Xmm11 = t.m;
669 t.v = r.getVectorRegister(UNW_X86_64_XMM12);
670 _msContext.Xmm12 = t.m;
671 t.v = r.getVectorRegister(UNW_X86_64_XMM13);
672 _msContext.Xmm13 = t.m;
673 t.v = r.getVectorRegister(UNW_X86_64_XMM14);
674 _msContext.Xmm14 = t.m;
675 t.v = r.getVectorRegister(UNW_X86_64_XMM15);
676 _msContext.Xmm15 = t.m;
677#elif defined(_LIBUNWIND_TARGET_ARM)
678 _msContext.R0 = r.getRegister(UNW_ARM_R0);
679 _msContext.R1 = r.getRegister(UNW_ARM_R1);
680 _msContext.R2 = r.getRegister(UNW_ARM_R2);
681 _msContext.R3 = r.getRegister(UNW_ARM_R3);
682 _msContext.R4 = r.getRegister(UNW_ARM_R4);
683 _msContext.R5 = r.getRegister(UNW_ARM_R5);
684 _msContext.R6 = r.getRegister(UNW_ARM_R6);
685 _msContext.R7 = r.getRegister(UNW_ARM_R7);
686 _msContext.R8 = r.getRegister(UNW_ARM_R8);
687 _msContext.R9 = r.getRegister(UNW_ARM_R9);
688 _msContext.R10 = r.getRegister(UNW_ARM_R10);
689 _msContext.R11 = r.getRegister(UNW_ARM_R11);
690 _msContext.R12 = r.getRegister(UNW_ARM_R12);
691 _msContext.Sp = r.getRegister(UNW_ARM_SP);
692 _msContext.Lr = r.getRegister(UNW_ARM_LR);
693 _msContext.Pc = r.getRegister(UNW_ARM_IP);
694 for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {
695 union {
696 uint64_t w;
697 double d;
698 } d;
699 d.d = r.getFloatRegister(i);
700 _msContext.D[i - UNW_ARM_D0] = d.w;
701 }
702#elif defined(_LIBUNWIND_TARGET_AARCH64)
703 for (int i = UNW_AARCH64_X0; i <= UNW_ARM64_X30; ++i)
704 _msContext.X[i - UNW_AARCH64_X0] = r.getRegister(i);
705 _msContext.Sp = r.getRegister(UNW_REG_SP);
706 _msContext.Pc = r.getRegister(UNW_REG_IP);
707 for (int i = UNW_AARCH64_V0; i <= UNW_ARM64_D31; ++i)
708 _msContext.V[i - UNW_AARCH64_V0].D[0] = r.getFloatRegister(i);
709#endif
710}
711
712template <typename A, typename R>
713UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
714 : _addressSpace(as), _unwindInfoMissing(false) {
715 static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
716 "UnwindCursor<> does not fit in unw_cursor_t");
717 memset(&_info, 0, sizeof(_info));
718 memset(&_histTable, 0, sizeof(_histTable));
719 memset(&_dispContext, 0, sizeof(_dispContext));
720 _dispContext.ContextRecord = &_msContext;
721 _dispContext.HistoryTable = &_histTable;
722 _msContext = *context;
723}
724
725
726template <typename A, typename R>
727bool UnwindCursor<A, R>::validReg(int regNum) {
728 if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
729#if defined(_LIBUNWIND_TARGET_X86_64)
730 if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP) return true;
731#elif defined(_LIBUNWIND_TARGET_ARM)
732 if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) ||
733 regNum == UNW_ARM_RA_AUTH_CODE)
734 return true;
735#elif defined(_LIBUNWIND_TARGET_AARCH64)
736 if (regNum >= UNW_AARCH64_X0 && regNum <= UNW_ARM64_X30) return true;
737#endif
738 return false;
739}
740
741template <typename A, typename R>
742unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
743 switch (regNum) {
744#if defined(_LIBUNWIND_TARGET_X86_64)
745 case UNW_X86_64_RIP:
746 case UNW_REG_IP: return _msContext.Rip;
747 case UNW_X86_64_RAX: return _msContext.Rax;
748 case UNW_X86_64_RDX: return _msContext.Rdx;
749 case UNW_X86_64_RCX: return _msContext.Rcx;
750 case UNW_X86_64_RBX: return _msContext.Rbx;
751 case UNW_REG_SP:
752 case UNW_X86_64_RSP: return _msContext.Rsp;
753 case UNW_X86_64_RBP: return _msContext.Rbp;
754 case UNW_X86_64_RSI: return _msContext.Rsi;
755 case UNW_X86_64_RDI: return _msContext.Rdi;
756 case UNW_X86_64_R8: return _msContext.R8;
757 case UNW_X86_64_R9: return _msContext.R9;
758 case UNW_X86_64_R10: return _msContext.R10;
759 case UNW_X86_64_R11: return _msContext.R11;
760 case UNW_X86_64_R12: return _msContext.R12;
761 case UNW_X86_64_R13: return _msContext.R13;
762 case UNW_X86_64_R14: return _msContext.R14;
763 case UNW_X86_64_R15: return _msContext.R15;
764#elif defined(_LIBUNWIND_TARGET_ARM)
765 case UNW_ARM_R0: return _msContext.R0;
766 case UNW_ARM_R1: return _msContext.R1;
767 case UNW_ARM_R2: return _msContext.R2;
768 case UNW_ARM_R3: return _msContext.R3;
769 case UNW_ARM_R4: return _msContext.R4;
770 case UNW_ARM_R5: return _msContext.R5;
771 case UNW_ARM_R6: return _msContext.R6;
772 case UNW_ARM_R7: return _msContext.R7;
773 case UNW_ARM_R8: return _msContext.R8;
774 case UNW_ARM_R9: return _msContext.R9;
775 case UNW_ARM_R10: return _msContext.R10;
776 case UNW_ARM_R11: return _msContext.R11;
777 case UNW_ARM_R12: return _msContext.R12;
778 case UNW_REG_SP:
779 case UNW_ARM_SP: return _msContext.Sp;
780 case UNW_ARM_LR: return _msContext.Lr;
781 case UNW_REG_IP:
782 case UNW_ARM_IP: return _msContext.Pc;
783#elif defined(_LIBUNWIND_TARGET_AARCH64)
784 case UNW_REG_SP: return _msContext.Sp;
785 case UNW_REG_IP: return _msContext.Pc;
786 default: return _msContext.X[regNum - UNW_AARCH64_X0];
787#endif
788 }
789 _LIBUNWIND_ABORT("unsupported register");
790}
791
792template <typename A, typename R>
793void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
794 switch (regNum) {
795#if defined(_LIBUNWIND_TARGET_X86_64)
796 case UNW_X86_64_RIP:
797 case UNW_REG_IP: _msContext.Rip = value; break;
798 case UNW_X86_64_RAX: _msContext.Rax = value; break;
799 case UNW_X86_64_RDX: _msContext.Rdx = value; break;
800 case UNW_X86_64_RCX: _msContext.Rcx = value; break;
801 case UNW_X86_64_RBX: _msContext.Rbx = value; break;
802 case UNW_REG_SP:
803 case UNW_X86_64_RSP: _msContext.Rsp = value; break;
804 case UNW_X86_64_RBP: _msContext.Rbp = value; break;
805 case UNW_X86_64_RSI: _msContext.Rsi = value; break;
806 case UNW_X86_64_RDI: _msContext.Rdi = value; break;
807 case UNW_X86_64_R8: _msContext.R8 = value; break;
808 case UNW_X86_64_R9: _msContext.R9 = value; break;
809 case UNW_X86_64_R10: _msContext.R10 = value; break;
810 case UNW_X86_64_R11: _msContext.R11 = value; break;
811 case UNW_X86_64_R12: _msContext.R12 = value; break;
812 case UNW_X86_64_R13: _msContext.R13 = value; break;
813 case UNW_X86_64_R14: _msContext.R14 = value; break;
814 case UNW_X86_64_R15: _msContext.R15 = value; break;
815#elif defined(_LIBUNWIND_TARGET_ARM)
816 case UNW_ARM_R0: _msContext.R0 = value; break;
817 case UNW_ARM_R1: _msContext.R1 = value; break;
818 case UNW_ARM_R2: _msContext.R2 = value; break;
819 case UNW_ARM_R3: _msContext.R3 = value; break;
820 case UNW_ARM_R4: _msContext.R4 = value; break;
821 case UNW_ARM_R5: _msContext.R5 = value; break;
822 case UNW_ARM_R6: _msContext.R6 = value; break;
823 case UNW_ARM_R7: _msContext.R7 = value; break;
824 case UNW_ARM_R8: _msContext.R8 = value; break;
825 case UNW_ARM_R9: _msContext.R9 = value; break;
826 case UNW_ARM_R10: _msContext.R10 = value; break;
827 case UNW_ARM_R11: _msContext.R11 = value; break;
828 case UNW_ARM_R12: _msContext.R12 = value; break;
829 case UNW_REG_SP:
830 case UNW_ARM_SP: _msContext.Sp = value; break;
831 case UNW_ARM_LR: _msContext.Lr = value; break;
832 case UNW_REG_IP:
833 case UNW_ARM_IP: _msContext.Pc = value; break;
834#elif defined(_LIBUNWIND_TARGET_AARCH64)
835 case UNW_REG_SP: _msContext.Sp = value; break;
836 case UNW_REG_IP: _msContext.Pc = value; break;
837 case UNW_AARCH64_X0:
838 case UNW_AARCH64_X1:
839 case UNW_AARCH64_X2:
840 case UNW_AARCH64_X3:
841 case UNW_AARCH64_X4:
842 case UNW_AARCH64_X5:
843 case UNW_AARCH64_X6:
844 case UNW_AARCH64_X7:
845 case UNW_AARCH64_X8:
846 case UNW_AARCH64_X9:
847 case UNW_AARCH64_X10:
848 case UNW_AARCH64_X11:
849 case UNW_AARCH64_X12:
850 case UNW_AARCH64_X13:
851 case UNW_AARCH64_X14:
852 case UNW_AARCH64_X15:
853 case UNW_AARCH64_X16:
854 case UNW_AARCH64_X17:
855 case UNW_AARCH64_X18:
856 case UNW_AARCH64_X19:
857 case UNW_AARCH64_X20:
858 case UNW_AARCH64_X21:
859 case UNW_AARCH64_X22:
860 case UNW_AARCH64_X23:
861 case UNW_AARCH64_X24:
862 case UNW_AARCH64_X25:
863 case UNW_AARCH64_X26:
864 case UNW_AARCH64_X27:
865 case UNW_AARCH64_X28:
866 case UNW_AARCH64_FP:
867 case UNW_AARCH64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
868#endif
869 default:
870 _LIBUNWIND_ABORT("unsupported register");
871 }
872}
873
874template <typename A, typename R>
875bool UnwindCursor<A, R>::validFloatReg(int regNum) {
876#if defined(_LIBUNWIND_TARGET_ARM)
877 if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
878 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
879#elif defined(_LIBUNWIND_TARGET_AARCH64)
880 if (regNum >= UNW_AARCH64_V0 && regNum <= UNW_ARM64_D31) return true;
881#else
882 (void)regNum;
883#endif
884 return false;
885}
886
887template <typename A, typename R>
888unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
889#if defined(_LIBUNWIND_TARGET_ARM)
890 if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
891 union {
892 uint32_t w;
893 float f;
894 } d;
895 d.w = _msContext.S[regNum - UNW_ARM_S0];
896 return d.f;
897 }
898 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
899 union {
900 uint64_t w;
901 double d;
902 } d;
903 d.w = _msContext.D[regNum - UNW_ARM_D0];
904 return d.d;
905 }
906 _LIBUNWIND_ABORT("unsupported float register");
907#elif defined(_LIBUNWIND_TARGET_AARCH64)
908 return _msContext.V[regNum - UNW_AARCH64_V0].D[0];
909#else
910 (void)regNum;
911 _LIBUNWIND_ABORT("float registers unimplemented");
912#endif
913}
914
915template <typename A, typename R>
916void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
917#if defined(_LIBUNWIND_TARGET_ARM)
918 if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
919 union {
920 uint32_t w;
921 float f;
922 } d;
923 d.f = (float)value;
924 _msContext.S[regNum - UNW_ARM_S0] = d.w;
925 }
926 if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
927 union {
928 uint64_t w;
929 double d;
930 } d;
931 d.d = value;
932 _msContext.D[regNum - UNW_ARM_D0] = d.w;
933 }
934 _LIBUNWIND_ABORT("unsupported float register");
935#elif defined(_LIBUNWIND_TARGET_AARCH64)
936 _msContext.V[regNum - UNW_AARCH64_V0].D[0] = value;
937#else
938 (void)regNum;
939 (void)value;
940 _LIBUNWIND_ABORT("float registers unimplemented");
941#endif
942}
943
944template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
945 RtlRestoreContext(&_msContext, nullptr);
946}
947
948#ifdef __arm__
949template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}
950#endif
951
952template <typename A, typename R>
953const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
954 return R::getRegisterName(regNum);
955}
956
957template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
958 return false;
959}
960
961#else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
962
963/// UnwindCursor contains all state (including all register values) during
964/// an unwind. This is normally stack allocated inside a unw_cursor_t.
965template <typename A, typename R>
966class UnwindCursor : public AbstractUnwindCursor {
967 typedef typename A::pint_t pint_t;
968public:
969 UnwindCursor(unw_context_t *context, A &as);
970 UnwindCursor(A &as, void *threadArg);
971 virtual ~UnwindCursor() {}
972 virtual bool validReg(int);
973 virtual unw_word_t getReg(int);
974 virtual void setReg(int, unw_word_t);
975 virtual bool validFloatReg(int);
976 virtual unw_fpreg_t getFloatReg(int);
977 virtual void setFloatReg(int, unw_fpreg_t);
978 virtual int step(bool stage2 = false);
979 virtual void getInfo(unw_proc_info_t *);
980 _LIBUNWIND_TRACE_NO_INLINE
981 virtual void jumpto();
982 virtual bool isSignalFrame();
983 virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);
984 virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);
985 virtual const char *getRegisterName(int num);
986#ifdef __arm__
987 virtual void saveVFPAsX();
988#endif
989
990#ifdef _LIBUNWIND_TRACE_RET_INJECT
991 virtual void setWalkedFrames(unsigned);
992#endif
993
994#ifdef _AIX
995 virtual uintptr_t getDataRelBase();
996#endif
997
998#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
999 virtual void *get_registers() { return &_registers; }
1000#endif
1001
1002 // libunwind does not and should not depend on C++ library which means that we
1003 // need our own definition of inline placement new.
1004 static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
1005
1006private:
1007
1008#if defined(_LIBUNWIND_ARM_EHABI)
1009 bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
1010
1011 int stepWithEHABI() {
1012 size_t len = 0;
1013 size_t off = 0;
1014 // FIXME: Calling decode_eht_entry() here is violating the libunwind
1015 // abstraction layer.
1016 const uint32_t *ehtp =
1017 decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info),
1018 &off, &len);
1019 if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) !=
1020 _URC_CONTINUE_UNWIND)
1021 return UNW_STEP_END;
1022 return UNW_STEP_SUCCESS;
1023 }
1024#endif
1025
1026#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
1027 bool setInfoForSigReturn() {
1028 R dummy;
1029 return setInfoForSigReturn(dummy);
1030 }
1031 int stepThroughSigReturn() {
1032 R dummy;
1033 return stepThroughSigReturn(dummy);
1034 }
1035 bool isReadableAddr(const pint_t addr) const;
1036#if defined(_LIBUNWIND_TARGET_AARCH64)
1037 bool setInfoForSigReturn(Registers_arm64 &);
1038 int stepThroughSigReturn(Registers_arm64 &);
1039#endif
1040#if defined(_LIBUNWIND_TARGET_LOONGARCH)
1041 bool setInfoForSigReturn(Registers_loongarch &);
1042 int stepThroughSigReturn(Registers_loongarch &);
1043#endif
1044#if defined(_LIBUNWIND_TARGET_RISCV)
1045 bool setInfoForSigReturn(Registers_riscv &);
1046 int stepThroughSigReturn(Registers_riscv &);
1047#endif
1048#if defined(_LIBUNWIND_TARGET_S390X)
1049 bool setInfoForSigReturn(Registers_s390x &);
1050 int stepThroughSigReturn(Registers_s390x &);
1051#endif
1052 template <typename Registers> bool setInfoForSigReturn(Registers &) {
1053 return false;
1054 }
1055 template <typename Registers> int stepThroughSigReturn(Registers &) {
1056 return UNW_STEP_END;
1057 }
1058#elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
1059 bool setInfoForSigReturn();
1060 int stepThroughSigReturn();
1061#endif
1062
1063#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1064 bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,
1065 const typename CFI_Parser<A>::CIE_Info &cieInfo,
1066 typename R::link_hardened_reg_arg_t pc,
1067 uintptr_t dso_base);
1068 bool getInfoFromDwarfSection(typename R::link_hardened_reg_arg_t pc,
1069 const UnwindInfoSections &sects,
1070 uint32_t fdeSectionOffsetHint = 0);
1071 int stepWithDwarfFDE(bool stage2) {
1072#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
1073 typename R::reg_t rawPC = this->getReg(UNW_REG_IP);
1074 typename R::link_reg_t pc;
1075 _registers.loadAndAuthenticateLinkRegister(rawPC, &pc);
1076#else
1077 typename R::link_reg_t pc = this->getReg(UNW_REG_IP);
1078#endif
1079 return DwarfInstructions<A, R>::stepWithDwarf(
1080 _addressSpace, pc, (pint_t)_info.unwind_info, _registers,
1081 _isSignalFrame, stage2);
1082 }
1083#endif
1084
1085#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1086 bool getInfoFromCompactEncodingSection(typename R::link_hardened_reg_arg_t pc,
1087 const UnwindInfoSections &sects);
1088 int stepWithCompactEncoding(bool stage2 = false) {
1089#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1090 if ( compactSaysUseDwarf() )
1091 return stepWithDwarfFDE(stage2);
1092#endif
1093 R dummy;
1094 return stepWithCompactEncoding(dummy);
1095 }
1096
1097#if defined(_LIBUNWIND_TARGET_X86_64)
1098 int stepWithCompactEncoding(Registers_x86_64 &) {
1099 return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
1100 _info.format, _info.start_ip, _addressSpace, _registers);
1101 }
1102#endif
1103
1104#if defined(_LIBUNWIND_TARGET_I386)
1105 int stepWithCompactEncoding(Registers_x86 &) {
1106 return CompactUnwinder_x86<A>::stepWithCompactEncoding(
1107 _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
1108 }
1109#endif
1110
1111#if defined(_LIBUNWIND_TARGET_PPC)
1112 int stepWithCompactEncoding(Registers_ppc &) {
1113 return UNW_EINVAL;
1114 }
1115#endif
1116
1117#if defined(_LIBUNWIND_TARGET_PPC64)
1118 int stepWithCompactEncoding(Registers_ppc64 &) {
1119 return UNW_EINVAL;
1120 }
1121#endif
1122
1123
1124#if defined(_LIBUNWIND_TARGET_AARCH64)
1125 int stepWithCompactEncoding(Registers_arm64 &) {
1126 return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
1127 _info.format, _info.start_ip, _addressSpace, _registers);
1128 }
1129#endif
1130
1131#if defined(_LIBUNWIND_TARGET_MIPS_O32)
1132 int stepWithCompactEncoding(Registers_mips_o32 &) {
1133 return UNW_EINVAL;
1134 }
1135#endif
1136
1137#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1138 int stepWithCompactEncoding(Registers_mips_newabi &) {
1139 return UNW_EINVAL;
1140 }
1141#endif
1142
1143#if defined(_LIBUNWIND_TARGET_LOONGARCH)
1144 int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; }
1145#endif
1146
1147#if defined(_LIBUNWIND_TARGET_SPARC)
1148 int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
1149#endif
1150
1151#if defined(_LIBUNWIND_TARGET_SPARC64)
1152 int stepWithCompactEncoding(Registers_sparc64 &) { return UNW_EINVAL; }
1153#endif
1154
1155#if defined (_LIBUNWIND_TARGET_RISCV)
1156 int stepWithCompactEncoding(Registers_riscv &) {
1157 return UNW_EINVAL;
1158 }
1159#endif
1160
1161 bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
1162 R dummy;
1163 return compactSaysUseDwarf(dummy, offset);
1164 }
1165
1166#if defined(_LIBUNWIND_TARGET_X86_64)
1167 bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
1168 if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
1169 if (offset)
1170 *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
1171 return true;
1172 }
1173 return false;
1174 }
1175#endif
1176
1177#if defined(_LIBUNWIND_TARGET_I386)
1178 bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
1179 if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
1180 if (offset)
1181 *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);
1182 return true;
1183 }
1184 return false;
1185 }
1186#endif
1187
1188#if defined(_LIBUNWIND_TARGET_PPC)
1189 bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
1190 return true;
1191 }
1192#endif
1193
1194#if defined(_LIBUNWIND_TARGET_PPC64)
1195 bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {
1196 return true;
1197 }
1198#endif
1199
1200#if defined(_LIBUNWIND_TARGET_AARCH64)
1201 bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
1202 if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
1203 if (offset)
1204 *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);
1205 return true;
1206 }
1207 return false;
1208 }
1209#endif
1210
1211#if defined(_LIBUNWIND_TARGET_MIPS_O32)
1212 bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const {
1213 return true;
1214 }
1215#endif
1216
1217#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1218 bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
1219 return true;
1220 }
1221#endif
1222
1223#if defined(_LIBUNWIND_TARGET_LOONGARCH)
1224 bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const {
1225 return true;
1226 }
1227#endif
1228
1229#if defined(_LIBUNWIND_TARGET_SPARC)
1230 bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
1231#endif
1232
1233#if defined(_LIBUNWIND_TARGET_SPARC64)
1234 bool compactSaysUseDwarf(Registers_sparc64 &, uint32_t *) const {
1235 return true;
1236 }
1237#endif
1238
1239#if defined (_LIBUNWIND_TARGET_RISCV)
1240 bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const {
1241 return true;
1242 }
1243#endif
1244
1245#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1246
1247#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1248 compact_unwind_encoding_t dwarfEncoding() const {
1249 R dummy;
1250 return dwarfEncoding(dummy);
1251 }
1252
1253#if defined(_LIBUNWIND_TARGET_X86_64)
1254 compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
1255 return UNWIND_X86_64_MODE_DWARF;
1256 }
1257#endif
1258
1259#if defined(_LIBUNWIND_TARGET_I386)
1260 compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
1261 return UNWIND_X86_MODE_DWARF;
1262 }
1263#endif
1264
1265#if defined(_LIBUNWIND_TARGET_PPC)
1266 compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
1267 return 0;
1268 }
1269#endif
1270
1271#if defined(_LIBUNWIND_TARGET_PPC64)
1272 compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {
1273 return 0;
1274 }
1275#endif
1276
1277#if defined(_LIBUNWIND_TARGET_AARCH64)
1278 compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
1279 return UNWIND_ARM64_MODE_DWARF;
1280 }
1281#endif
1282
1283#if defined(_LIBUNWIND_TARGET_ARM)
1284 compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const {
1285 return 0;
1286 }
1287#endif
1288
1289#if defined (_LIBUNWIND_TARGET_OR1K)
1290 compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
1291 return 0;
1292 }
1293#endif
1294
1295#if defined (_LIBUNWIND_TARGET_HEXAGON)
1296 compact_unwind_encoding_t dwarfEncoding(Registers_hexagon &) const {
1297 return 0;
1298 }
1299#endif
1300
1301#if defined (_LIBUNWIND_TARGET_MIPS_O32)
1302 compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const {
1303 return 0;
1304 }
1305#endif
1306
1307#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1308 compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
1309 return 0;
1310 }
1311#endif
1312
1313#if defined(_LIBUNWIND_TARGET_LOONGARCH)
1314 compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const {
1315 return 0;
1316 }
1317#endif
1318
1319#if defined(_LIBUNWIND_TARGET_SPARC)
1320 compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
1321#endif
1322
1323#if defined(_LIBUNWIND_TARGET_SPARC64)
1324 compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const {
1325 return 0;
1326 }
1327#endif
1328
1329#if defined (_LIBUNWIND_TARGET_RISCV)
1330 compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const {
1331 return 0;
1332 }
1333#endif
1334
1335#if defined (_LIBUNWIND_TARGET_S390X)
1336 compact_unwind_encoding_t dwarfEncoding(Registers_s390x &) const {
1337 return 0;
1338 }
1339#endif
1340
1341#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1342
1343#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1344 // For runtime environments using SEH unwind data without Windows runtime
1345 // support.
1346 pint_t getLastPC() const { /* FIXME: Implement */ return 0; }
1347 void setLastPC(pint_t pc) { /* FIXME: Implement */ }
1348 RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
1349 /* FIXME: Implement */
1350 *base = 0;
1351 return nullptr;
1352 }
1353 bool getInfoFromSEH(pint_t pc);
1354 int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1355#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1356
1357#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1358 bool getInfoFromTBTable(pint_t pc, R &registers);
1359 int stepWithTBTable(pint_t pc, tbtable *TBTable, R &registers,
1360 bool &isSignalFrame);
1361 int stepWithTBTableData() {
1362 return stepWithTBTable(reinterpret_cast<pint_t>(this->getReg(UNW_REG_IP)),
1363 reinterpret_cast<tbtable *>(_info.unwind_info),
1364 _registers, _isSignalFrame);
1365 }
1366 bool isKnownVapiNotActive() const { return _isKnownVapiNotActive; }
1367 void setIsKnownVapiNotActive(bool val) { _isKnownVapiNotActive = val; }
1368 static pint_t getVAPILR();
1369
1370#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1371
1372 A &_addressSpace;
1373 R _registers;
1374 unw_proc_info_t _info;
1375 bool _unwindInfoMissing;
1376 bool _isSignalFrame;
1377#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
1378 defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
1379 bool _isSigReturn = false;
1380#endif
1381#ifdef _LIBUNWIND_TRACE_RET_INJECT
1382 uint32_t _walkedFrames;
1383#endif
1384#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1385 // TODO: this will need to be recorded in the unw_context_t by unw_getcontext
1386 // to support cases where the cursor is retrieved prior to invocation of the
1387 // Virtual API.
1388 bool _isKnownVapiNotActive;
1389#endif
1390};
1391
1392template <typename A, typename R>
1393UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
1394 : _addressSpace(as), _registers(context), _unwindInfoMissing(false),
1395 _isSignalFrame(false)
1396#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1397 ,
1398 _isKnownVapiNotActive(false)
1399#endif
1400{
1401 static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
1402 "UnwindCursor<> does not fit in unw_cursor_t");
1403 static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
1404 "UnwindCursor<> requires more alignment than unw_cursor_t");
1405 memset(s: static_cast<void *>(&_info), c: 0, n: sizeof(_info));
1406}
1407
1408template <typename A, typename R>
1409UnwindCursor<A, R>::UnwindCursor(A &as, void *)
1410 : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false)
1411#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1412 ,
1413 _isKnownVapiNotActive(false)
1414#endif
1415{
1416 memset(s: static_cast<void *>(&_info), c: 0, n: sizeof(_info));
1417 // FIXME
1418 // fill in _registers from thread arg
1419}
1420
1421template <typename A, typename R>
1422bool UnwindCursor<A, R>::validReg(int regNum) {
1423 return _registers.validRegister(regNum);
1424}
1425
1426template <typename A, typename R>
1427unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
1428 return _registers.getRegister(regNum);
1429}
1430
1431template <typename A, typename R>
1432void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
1433 _registers.setRegister(regNum, (typename A::pint_t)value);
1434}
1435
1436template <typename A, typename R>
1437bool UnwindCursor<A, R>::validFloatReg(int regNum) {
1438 return _registers.validFloatRegister(regNum);
1439}
1440
1441template <typename A, typename R>
1442unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
1443 return _registers.getFloatRegister(regNum);
1444}
1445
1446template <typename A, typename R>
1447void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
1448 _registers.setFloatRegister(regNum, value);
1449}
1450
1451template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
1452#ifdef _LIBUNWIND_TRACE_RET_INJECT
1453 /*
1454
1455 The value of `_walkedFrames` is computed in `unwind_phase2` and represents the
1456 number of frames walked starting `unwind_phase2` to get to the landing pad.
1457
1458 ```
1459 // uc is initialized by __unw_getcontext in the parent frame.
1460 // The first stack frame walked is unwind_phase2.
1461 unsigned framesWalked = 1;
1462 ```
1463
1464 To that, we need to add the number of function calls in libunwind between
1465 `unwind_phase2` & `__libunwind_Registers_arm64_jumpto` which performs the long
1466 jump, to rebalance the execution flow.
1467
1468 ```
1469 frame #0: libunwind.1.dylib`__libunwind_Registers_arm64_jumpto at UnwindRegistersRestore.S:646
1470 frame #1: libunwind.1.dylib`libunwind::Registers_arm64::returnto at Registers.hpp:2291:3
1471 frame #2: libunwind.1.dylib`libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_arm64>::jumpto at UnwindCursor.hpp:1474:14
1472 frame #3: libunwind.1.dylib`__unw_resume at libunwind.cpp:375:7
1473 frame #4: libunwind.1.dylib`__unw_resume_with_frames_walked at libunwind.cpp:363:10
1474 frame #5: libunwind.1.dylib`unwind_phase2 at UnwindLevel1.c:328:9
1475 frame #6: libunwind.1.dylib`_Unwind_RaiseException at UnwindLevel1.c:480:10
1476 frame #7: libc++abi.dylib`__cxa_throw at cxa_exception.cpp:295:5
1477 ...
1478 ```
1479
1480 If we look at the backtrace from `__libunwind_Registers_arm64_jumpto`, we see
1481 there are 5 frames on the stack to reach `unwind_phase2`. However, only 4 of
1482 them will never return, since `__libunwind_Registers_arm64_jumpto` returns
1483 back to the landing pad, so we need to subtract 1 to the number of
1484 `_EXTRA_LIBUNWIND_FRAMES_WALKED`.
1485 */
1486
1487 static constexpr size_t _EXTRA_LIBUNWIND_FRAMES_WALKED = 5 - 1;
1488 _registers.returnto(_walkedFrames + _EXTRA_LIBUNWIND_FRAMES_WALKED);
1489#else
1490#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1491 if (isKnownVapiNotActive()) {
1492 // If the current frame is known VAPI not active, execute the VAPI return
1493 // glue to clear the VAPI control block. The VAPI return glue is used by
1494 // AIX longjmp based on the VAPI active status recorded by setjmp in the
1495 // jmp_buf, which means that the VAPI return glue can be called solely on
1496 // the basis of the VAPI active status of the target context.
1497
1498 // VAPI return glue address is the VAPI glue address - 4.
1499#ifdef __64BIT__
1500 constexpr pint_t VAPIReturnGlue = 0x8e40 - 4;
1501#else
1502 constexpr pint_t VAPIReturnGlue = 0x8c40 - 4;
1503#endif
1504
1505 _LIBUNWIND_TRACE_UNWINDING("VAPI: executing return glue %p\n",
1506 reinterpret_cast<void *>(VAPIReturnGlue));
1507 register auto *registers __asm__("r30") = &_registers;
1508 __asm__ __volatile__("bla %[retglue]"
1509 : "+r"(registers)
1510 : [retglue] "i"(VAPIReturnGlue));
1511 registers->jumpto();
1512 }
1513#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1514 _registers.jumpto();
1515#endif
1516}
1517
1518#ifdef __arm__
1519template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
1520 _registers.saveVFPAsX();
1521}
1522#endif
1523
1524#ifdef _LIBUNWIND_TRACE_RET_INJECT
1525template <typename A, typename R>
1526void UnwindCursor<A, R>::setWalkedFrames(unsigned walkedFrames) {
1527 _walkedFrames = walkedFrames;
1528}
1529#endif
1530
1531#ifdef _AIX
1532template <typename A, typename R>
1533uintptr_t UnwindCursor<A, R>::getDataRelBase() {
1534 return reinterpret_cast<uintptr_t>(_info.extra);
1535}
1536#endif
1537
1538template <typename A, typename R>
1539const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
1540 return _registers.getRegisterName(regNum);
1541}
1542
1543template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
1544 return _isSignalFrame;
1545}
1546
1547#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1548
1549#if defined(_LIBUNWIND_ARM_EHABI)
1550template<typename A>
1551struct EHABISectionIterator {
1552 typedef EHABISectionIterator _Self;
1553
1554 typedef typename A::pint_t value_type;
1555 typedef typename A::pint_t* pointer;
1556 typedef typename A::pint_t& reference;
1557 typedef size_t size_type;
1558 typedef size_t difference_type;
1559
1560 static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {
1561 return _Self(addressSpace, sects, 0);
1562 }
1563 static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
1564 return _Self(addressSpace, sects,
1565 sects.arm_section_length / sizeof(EHABIIndexEntry));
1566 }
1567
1568 EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
1569 : _i(i), _addressSpace(&addressSpace), _sects(&sects) {}
1570
1571 _Self& operator++() { ++_i; return *this; }
1572 _Self& operator+=(size_t a) { _i += a; return *this; }
1573 _Self& operator--() { assert(_i > 0); --_i; return *this; }
1574 _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; }
1575
1576 _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; }
1577 _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; }
1578
1579 size_t operator-(const _Self& other) const { return _i - other._i; }
1580
1581 bool operator==(const _Self& other) const {
1582 assert(_addressSpace == other._addressSpace);
1583 assert(_sects == other._sects);
1584 return _i == other._i;
1585 }
1586
1587 bool operator!=(const _Self& other) const {
1588 assert(_addressSpace == other._addressSpace);
1589 assert(_sects == other._sects);
1590 return _i != other._i;
1591 }
1592
1593 typename A::pint_t operator*() const { return functionAddress(); }
1594
1595 typename A::pint_t functionAddress() const {
1596 typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1597 EHABIIndexEntry, _i, functionOffset);
1598 return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));
1599 }
1600
1601 typename A::pint_t dataAddress() {
1602 typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1603 EHABIIndexEntry, _i, data);
1604 return indexAddr;
1605 }
1606
1607 private:
1608 size_t _i;
1609 A* _addressSpace;
1610 const UnwindInfoSections* _sects;
1611};
1612
1613namespace {
1614
1615template <typename A>
1616EHABISectionIterator<A> EHABISectionUpperBound(
1617 EHABISectionIterator<A> first,
1618 EHABISectionIterator<A> last,
1619 typename A::pint_t value) {
1620 size_t len = last - first;
1621 while (len > 0) {
1622 size_t l2 = len / 2;
1623 EHABISectionIterator<A> m = first + l2;
1624 if (value < *m) {
1625 len = l2;
1626 } else {
1627 first = ++m;
1628 len -= l2 + 1;
1629 }
1630 }
1631 return first;
1632}
1633
1634}
1635
1636template <typename A, typename R>
1637bool UnwindCursor<A, R>::getInfoFromEHABISection(
1638 pint_t pc,
1639 const UnwindInfoSections &sects) {
1640 EHABISectionIterator<A> begin =
1641 EHABISectionIterator<A>::begin(_addressSpace, sects);
1642 EHABISectionIterator<A> end =
1643 EHABISectionIterator<A>::end(_addressSpace, sects);
1644 if (begin == end)
1645 return false;
1646
1647 EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc);
1648 if (itNextPC == begin)
1649 return false;
1650 EHABISectionIterator<A> itThisPC = itNextPC - 1;
1651
1652 pint_t thisPC = itThisPC.functionAddress();
1653 // If an exception is thrown from a function, corresponding to the last entry
1654 // in the table, we don't really know the function extent and have to choose a
1655 // value for nextPC. Choosing max() will allow the range check during trace to
1656 // succeed.
1657 pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress();
1658 pint_t indexDataAddr = itThisPC.dataAddress();
1659
1660 if (indexDataAddr == 0)
1661 return false;
1662
1663 uint32_t indexData = _addressSpace.get32(indexDataAddr);
1664 if (indexData == UNW_EXIDX_CANTUNWIND)
1665 return false;
1666
1667 // If the high bit is set, the exception handling table entry is inline inside
1668 // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1669 // the table points at an offset in the exception handling table (section 5
1670 // EHABI).
1671 pint_t exceptionTableAddr;
1672 uint32_t exceptionTableData;
1673 bool isSingleWordEHT;
1674 if (indexData & 0x80000000) {
1675 exceptionTableAddr = indexDataAddr;
1676 // TODO(ajwong): Should this data be 0?
1677 exceptionTableData = indexData;
1678 isSingleWordEHT = true;
1679 } else {
1680 exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);
1681 exceptionTableData = _addressSpace.get32(exceptionTableAddr);
1682 isSingleWordEHT = false;
1683 }
1684
1685 // Now we know the 3 things:
1686 // exceptionTableAddr -- exception handler table entry.
1687 // exceptionTableData -- the data inside the first word of the eht entry.
1688 // isSingleWordEHT -- whether the entry is in the index.
1689 unw_word_t personalityRoutine = 0xbadf00d;
1690 bool scope32 = false;
1691 uintptr_t lsda;
1692
1693 // If the high bit in the exception handling table entry is set, the entry is
1694 // in compact form (section 6.3 EHABI).
1695 if (exceptionTableData & 0x80000000) {
1696 // Grab the index of the personality routine from the compact form.
1697 uint32_t choice = (exceptionTableData & 0x0f000000) >> 24;
1698 uint32_t extraWords = 0;
1699 switch (choice) {
1700 case 0:
1701 personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;
1702 extraWords = 0;
1703 scope32 = false;
1704 lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4);
1705 break;
1706 case 1:
1707 personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;
1708 extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1709 scope32 = false;
1710 lsda = exceptionTableAddr + (extraWords + 1) * 4;
1711 break;
1712 case 2:
1713 personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;
1714 extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1715 scope32 = true;
1716 lsda = exceptionTableAddr + (extraWords + 1) * 4;
1717 break;
1718 default:
1719 _LIBUNWIND_ABORT("unknown personality routine");
1720 return false;
1721 }
1722
1723 if (isSingleWordEHT) {
1724 if (extraWords != 0) {
1725 _LIBUNWIND_ABORT("index inlined table detected but pr function "
1726 "requires extra words");
1727 return false;
1728 }
1729 }
1730 } else {
1731 pint_t personalityAddr =
1732 exceptionTableAddr + signExtendPrel31(exceptionTableData);
1733 personalityRoutine = personalityAddr;
1734
1735 // ARM EHABI # 6.2, # 9.2
1736 //
1737 // +---- ehtp
1738 // v
1739 // +--------------------------------------+
1740 // | +--------+--------+--------+-------+ |
1741 // | |0| prel31 to personalityRoutine | |
1742 // | +--------+--------+--------+-------+ |
1743 // | | N | unwind opcodes | | <-- UnwindData
1744 // | +--------+--------+--------+-------+ |
1745 // | | Word 2 unwind opcodes | |
1746 // | +--------+--------+--------+-------+ |
1747 // | ... |
1748 // | +--------+--------+--------+-------+ |
1749 // | | Word N unwind opcodes | |
1750 // | +--------+--------+--------+-------+ |
1751 // | | LSDA | | <-- lsda
1752 // | | ... | |
1753 // | +--------+--------+--------+-------+ |
1754 // +--------------------------------------+
1755
1756 uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;
1757 uint32_t FirstDataWord = *UnwindData;
1758 size_t N = ((FirstDataWord >> 24) & 0xff);
1759 size_t NDataWords = N + 1;
1760 lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);
1761 }
1762
1763 _info.start_ip = thisPC;
1764 _info.end_ip = nextPC;
1765 _info.handler = personalityRoutine;
1766 _info.unwind_info = exceptionTableAddr;
1767 _info.lsda = lsda;
1768 // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1769 _info.flags = (isSingleWordEHT ? 1 : 0) | (scope32 ? 0x2 : 0); // Use enum?
1770
1771 return true;
1772}
1773#endif
1774
1775#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1776template <typename A, typename R>
1777bool UnwindCursor<A, R>::getInfoFromFdeCie(
1778 const typename CFI_Parser<A>::FDE_Info &fdeInfo,
1779 const typename CFI_Parser<A>::CIE_Info &cieInfo,
1780 typename R::link_hardened_reg_arg_t pc, uintptr_t dso_base) {
1781 typename CFI_Parser<A>::PrologInfo prolog;
1782 if (CFI_Parser<A>::template parseFDEInstructions<R>(
1783 _addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) {
1784 // Save off parsed FDE info
1785 _info.start_ip = fdeInfo.pcStart;
1786 _info.end_ip = fdeInfo.pcEnd;
1787 _info.lsda = fdeInfo.lsda;
1788 _info.handler = cieInfo.personality;
1789 // Some frameless functions need SP altered when resuming in function, so
1790 // propagate spExtraArgSize.
1791 _info.gp = prolog.spExtraArgSize;
1792 _info.flags = 0;
1793 _info.format = dwarfEncoding();
1794 _info.unwind_info = fdeInfo.fdeStart;
1795 _info.unwind_info_size = static_cast<uint32_t>(fdeInfo.fdeLength);
1796 _info.extra = static_cast<unw_word_t>(dso_base);
1797 return true;
1798 }
1799 return false;
1800}
1801
1802template <typename A, typename R>
1803bool UnwindCursor<A, R>::getInfoFromDwarfSection(
1804 typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects,
1805 uint32_t fdeSectionOffsetHint) {
1806 typename CFI_Parser<A>::FDE_Info fdeInfo;
1807 typename CFI_Parser<A>::CIE_Info cieInfo;
1808 bool foundFDE = false;
1809 bool foundInCache = false;
1810 // If compact encoding table gave offset into dwarf section, go directly there
1811 if (fdeSectionOffsetHint != 0) {
1812 foundFDE = CFI_Parser<A>::template findFDE<R>(
1813 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length,
1814 sects.dwarf_section + fdeSectionOffsetHint, &fdeInfo, &cieInfo);
1815 }
1816#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1817 if (!foundFDE && (sects.dwarf_index_section != 0)) {
1818 foundFDE = EHHeaderParser<A>::template findFDE<R>(
1819 _addressSpace, pc, sects.dwarf_index_section,
1820 (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
1821 }
1822#endif
1823 if (!foundFDE) {
1824 // otherwise, search cache of previously found FDEs.
1825 pint_t cachedFDE =
1826 DwarfFDECache<A>::template findFDE<R>(sects.dso_base, pc);
1827 if (cachedFDE != 0) {
1828 foundFDE = CFI_Parser<A>::template findFDE<R>(
1829 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length,
1830 cachedFDE, &fdeInfo, &cieInfo);
1831 foundInCache = foundFDE;
1832 }
1833 }
1834 if (!foundFDE) {
1835 // Still not found, do full scan of __eh_frame section.
1836 foundFDE = CFI_Parser<A>::template findFDE<R>(
1837 _addressSpace, pc, sects.dwarf_section, sects.dwarf_section_length, 0,
1838 &fdeInfo, &cieInfo);
1839 }
1840 if (foundFDE) {
1841 if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, dso_base: sects.dso_base)) {
1842 // Add to cache (to make next lookup faster) if we had no hint
1843 // and there was no index.
1844 if (!foundInCache && (fdeSectionOffsetHint == 0)) {
1845 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1846 if (sects.dwarf_index_section == 0)
1847 #endif
1848 DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
1849 fdeInfo.fdeStart);
1850 }
1851 return true;
1852 }
1853 }
1854 //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1855 return false;
1856}
1857#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1858
1859
1860#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1861template <typename A, typename R>
1862bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(
1863 typename R::link_hardened_reg_arg_t pc, const UnwindInfoSections &sects) {
1864 const bool log = false;
1865 if (log)
1866 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1867 (uint64_t)pc, (uint64_t)sects.dso_base);
1868
1869 const UnwindSectionHeader<A> sectionHeader(_addressSpace,
1870 sects.compact_unwind_section);
1871 if (sectionHeader.version() != UNWIND_SECTION_VERSION)
1872 return false;
1873
1874 // do a binary search of top level index to find page with unwind info
1875 pint_t targetFunctionOffset = pc - sects.dso_base;
1876 const UnwindSectionIndexArray<A> topIndex(_addressSpace,
1877 sects.compact_unwind_section
1878 + sectionHeader.indexSectionOffset());
1879 uint32_t low = 0;
1880 uint32_t high = sectionHeader.indexCount();
1881 uint32_t last = high - 1;
1882 while (low < high) {
1883 uint32_t mid = (low + high) / 2;
1884 //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1885 //mid, low, high, topIndex.functionOffset(mid));
1886 if (topIndex.functionOffset(mid) <= targetFunctionOffset) {
1887 if ((mid == last) ||
1888 (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {
1889 low = mid;
1890 break;
1891 } else {
1892 low = mid + 1;
1893 }
1894 } else {
1895 high = mid;
1896 }
1897 }
1898 const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
1899 const uint32_t firstLevelNextPageFunctionOffset =
1900 topIndex.functionOffset(low + 1);
1901 const pint_t secondLevelAddr =
1902 sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);
1903 const pint_t lsdaArrayStartAddr =
1904 sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);
1905 const pint_t lsdaArrayEndAddr =
1906 sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);
1907 if (log)
1908 fprintf(stderr, "\tfirst level search for result index=%d "
1909 "to secondLevelAddr=0x%llX\n",
1910 low, (uint64_t) secondLevelAddr);
1911 // do a binary search of second level page index
1912 uint32_t encoding = 0;
1913 pint_t funcStart = 0;
1914 pint_t rangeStart = 0;
1915 pint_t funcEnd = 0;
1916 pint_t lsda = 0;
1917 pint_t personality = 0;
1918 uint32_t pageKind = _addressSpace.get32(secondLevelAddr);
1919 if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {
1920 // regular page
1921 UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,
1922 secondLevelAddr);
1923 UnwindSectionRegularArray<A> pageIndex(
1924 _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1925 // binary search looks for entry with e where index[e].offset <= pc <
1926 // index[e+1].offset
1927 if (log)
1928 fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "
1929 "regular page starting at secondLevelAddr=0x%llX\n",
1930 (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);
1931 low = 0;
1932 high = pageHeader.entryCount();
1933 while (low < high) {
1934 uint32_t mid = (low + high) / 2;
1935 if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {
1936 if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {
1937 // at end of table
1938 low = mid;
1939 funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1940 break;
1941 } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {
1942 // next is too big, so we found it
1943 low = mid;
1944 funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;
1945 break;
1946 } else {
1947 low = mid + 1;
1948 }
1949 } else {
1950 high = mid;
1951 }
1952 }
1953 encoding = pageIndex.encoding(low);
1954 rangeStart = pageIndex.functionOffset(low) + sects.dso_base;
1955
1956 // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual
1957 // function start.
1958 funcStart = rangeStart;
1959 if (encoding & UNWIND_IS_NOT_FUNCTION_START) {
1960 assert(low != 0 &&
1961 "UNWIND_IS_NOT_FUNCTION_START comact unwind must be preceded by a "
1962 "~UNWIND_IS_NOT_FUNCTION_START entry for the same function");
1963 uint32_t backIndex = low;
1964 do {
1965 --backIndex;
1966 } while (backIndex > 0 &&
1967 (pageIndex.encoding(backIndex) & UNWIND_IS_NOT_FUNCTION_START));
1968 funcStart = pageIndex.functionOffset(backIndex) + sects.dso_base;
1969 }
1970
1971 if (pc < funcStart) {
1972 if (log)
1973 fprintf(stderr,
1974 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, "
1975 "rangeStart=0x%llX, funcEnd=0x%llX\n",
1976 (uint64_t)pc, (uint64_t)funcStart, (uint64_t)rangeStart,
1977 (uint64_t)funcEnd);
1978 return false;
1979 }
1980 if (pc > funcEnd) {
1981 if (log)
1982 fprintf(stderr,
1983 "\tpc not in table, pc=0x%llX, funcStart=0x%llX, "
1984 "rangeStart=0x%llX, funcEnd=0x%llX\n",
1985 (uint64_t)pc, (uint64_t)funcStart, (uint64_t)rangeStart,
1986 (uint64_t)funcEnd);
1987 return false;
1988 }
1989 } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {
1990 // compressed page
1991 UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,
1992 secondLevelAddr);
1993 UnwindSectionCompressedArray<A> pageIndex(
1994 _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1995 const uint32_t targetFunctionPageOffset =
1996 (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset);
1997 // binary search looks for entry with e where index[e].offset <= pc <
1998 // index[e+1].offset
1999 if (log)
2000 fprintf(stderr, "\tbinary search of compressed page starting at "
2001 "secondLevelAddr=0x%llX\n",
2002 (uint64_t) secondLevelAddr);
2003 low = 0;
2004 last = pageHeader.entryCount() - 1;
2005 high = pageHeader.entryCount();
2006 while (low < high) {
2007 uint32_t mid = (low + high) / 2;
2008 if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {
2009 if ((mid == last) ||
2010 (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {
2011 low = mid;
2012 break;
2013 } else {
2014 low = mid + 1;
2015 }
2016 } else {
2017 high = mid;
2018 }
2019 }
2020 rangeStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset +
2021 sects.dso_base;
2022 if (low < last)
2023 funcEnd =
2024 pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset
2025 + sects.dso_base;
2026 else
2027 funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
2028
2029 auto encodingAtIndex = [&](uint32_t idx) -> uint32_t {
2030 uint16_t encIdx = pageIndex.encodingIndex(idx);
2031 if (encIdx < sectionHeader.commonEncodingsArrayCount()) {
2032 return _addressSpace.get32(
2033 sects.compact_unwind_section +
2034 sectionHeader.commonEncodingsArraySectionOffset() +
2035 encIdx * sizeof(uint32_t));
2036 } else {
2037 uint16_t pageEncIdx =
2038 encIdx - (uint16_t)sectionHeader.commonEncodingsArrayCount();
2039 return _addressSpace.get32(secondLevelAddr +
2040 pageHeader.encodingsPageOffset() +
2041 pageEncIdx * sizeof(uint32_t));
2042 }
2043 };
2044
2045 encoding = encodingAtIndex(low);
2046
2047 // If UNWIND_IS_NOT_FUNCTION_START is set, walk backwards to find the actual
2048 // function start.
2049 funcStart = rangeStart;
2050 if (encoding & UNWIND_IS_NOT_FUNCTION_START) {
2051 assert(low != 0 &&
2052 "UNWIND_IS_NOT_FUNCTION_START comact unwind must be preceded by a "
2053 "~UNWIND_IS_NOT_FUNCTION_START entry for the same function.");
2054 uint32_t backIndex = low;
2055 do {
2056 --backIndex;
2057 } while (backIndex > 0 &&
2058 (encodingAtIndex(backIndex) & UNWIND_IS_NOT_FUNCTION_START));
2059 funcStart = pageIndex.functionOffset(backIndex) +
2060 firstLevelFunctionOffset + sects.dso_base;
2061 }
2062
2063 if (pc < funcStart) {
2064 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
2065 "not in second level compressed unwind table. "
2066 "funcStart=0x%llX, rangeStart=0x%llX",
2067 (uint64_t)pc, (uint64_t)funcStart,
2068 (uint64_t)rangeStart);
2069 return false;
2070 }
2071 if (pc > funcEnd) {
2072 _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
2073 "not in second level compressed unwind table. "
2074 "funcEnd=0x%llX",
2075 (uint64_t) pc, (uint64_t) funcEnd);
2076 return false;
2077 }
2078 } else {
2079 _LIBUNWIND_DEBUG_LOG(
2080 "malformed __unwind_info at 0x%0llX bad second level page",
2081 (uint64_t)sects.compact_unwind_section);
2082 return false;
2083 }
2084
2085 // look up LSDA, if encoding says function has one
2086 if (encoding & UNWIND_HAS_LSDA) {
2087 UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);
2088 uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);
2089 low = 0;
2090 high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /
2091 sizeof(unwind_info_section_header_lsda_index_entry);
2092 // binary search looks for entry with exact match for functionOffset
2093 if (log)
2094 fprintf(stderr,
2095 "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
2096 funcStartOffset);
2097 while (low < high) {
2098 uint32_t mid = (low + high) / 2;
2099 if (lsdaIndex.functionOffset(mid) == funcStartOffset) {
2100 lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;
2101 break;
2102 } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {
2103 low = mid + 1;
2104 } else {
2105 high = mid;
2106 }
2107 }
2108 if (lsda == 0) {
2109 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
2110 "pc=0x%0llX, but lsda table has no entry",
2111 encoding, (uint64_t) pc);
2112 return false;
2113 }
2114 }
2115
2116 // extract personality routine, if encoding says function has one
2117 uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
2118 (__builtin_ctz(UNWIND_PERSONALITY_MASK));
2119 if (personalityIndex != 0) {
2120 --personalityIndex; // change 1-based to zero-based index
2121 if (personalityIndex >= sectionHeader.personalityArrayCount()) {
2122 _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "
2123 "but personality table has only %d entries",
2124 encoding, personalityIndex,
2125 sectionHeader.personalityArrayCount());
2126 return false;
2127 }
2128 int32_t personalityDelta = (int32_t)_addressSpace.get32(
2129 sects.compact_unwind_section +
2130 sectionHeader.personalityArraySectionOffset() +
2131 personalityIndex * sizeof(uint32_t));
2132 pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
2133 personality = _addressSpace.getP(personalityPointer);
2134#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
2135 // The GOT for the personality function was signed address authenticated.
2136 // Resign it as a regular function pointer.
2137 const auto discriminator = ptrauth_blend_discriminator(
2138 &_info.handler, __ptrauth_unwind_upi_handler_disc);
2139 void *signedPtr = ptrauth_auth_and_resign(
2140 (void *)personality, ptrauth_key_function_pointer, personalityPointer,
2141 ptrauth_key_function_pointer, discriminator);
2142 personality = (__typeof(personality))signedPtr;
2143#endif
2144 if (log)
2145 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
2146 "personalityDelta=0x%08X, personality=0x%08llX\n",
2147 (uint64_t) pc, personalityDelta, (uint64_t) personality);
2148 }
2149
2150 if (log)
2151 fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
2152 "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
2153 (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart);
2154
2155 // For ARM64 PAuth_LR frames, start_ip should be the pacibsppc address
2156 // (rangeStart). For all other cases, start_ip should be the function start.
2157#if defined(_LIBUNWIND_TARGET_AARCH64)
2158 if ((encoding & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_FRAME_PAUTH_LR) {
2159 _info.start_ip = rangeStart;
2160 } else {
2161 _info.start_ip = funcStart;
2162 }
2163#else
2164 _info.start_ip = funcStart;
2165#endif
2166 _info.end_ip = funcEnd;
2167 _info.lsda = lsda;
2168 // We use memmove to copy the personality function as we have already manually
2169 // re-signed the pointer, and assigning directly will attempt to incorrectly
2170 // sign the already signed value.
2171 memmove(reinterpret_cast<void *>(&_info.handler),
2172 reinterpret_cast<void *>(&personality), sizeof(personality));
2173 _info.gp = 0;
2174 _info.flags = 0;
2175 _info.format = encoding;
2176 _info.unwind_info = 0;
2177 _info.unwind_info_size = 0;
2178 _info.extra = sects.dso_base;
2179 return true;
2180}
2181#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2182
2183
2184#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2185template <typename A, typename R>
2186bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
2187 pint_t base;
2188 RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);
2189 if (!unwindEntry) {
2190 _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);
2191 return false;
2192 }
2193 _info.gp = 0;
2194 _info.flags = 0;
2195 _info.format = 0;
2196 _info.unwind_info_size = sizeof(RUNTIME_FUNCTION);
2197 _info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry);
2198 _info.extra = base;
2199 _info.start_ip = base + unwindEntry->BeginAddress;
2200#ifdef _LIBUNWIND_TARGET_X86_64
2201 _info.end_ip = base + unwindEntry->EndAddress;
2202 // Only fill in the handler and LSDA if they're stale.
2203 if (pc != getLastPC()) {
2204 UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);
2205 if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {
2206 // The personality is given in the UNWIND_INFO itself. The LSDA immediately
2207 // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
2208 // these structures.)
2209 // N.B. UNWIND_INFO structs are DWORD-aligned.
2210 uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
2211 const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
2212 _info.lsda = reinterpret_cast<unw_word_t>(handler+1);
2213 _dispContext.HandlerData = reinterpret_cast<void *>(_info.lsda);
2214 _dispContext.LanguageHandler =
2215 reinterpret_cast<EXCEPTION_ROUTINE *>(base + *handler);
2216 if (*handler) {
2217 _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
2218 } else
2219 _info.handler = 0;
2220 } else {
2221 _info.lsda = 0;
2222 _info.handler = 0;
2223 }
2224 }
2225#elif defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_ARM)
2226
2227#if defined(_LIBUNWIND_TARGET_AARCH64)
2228#define FUNC_LENGTH_UNIT 4
2229#define XDATA_TYPE IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA
2230#else
2231#define FUNC_LENGTH_UNIT 2
2232#define XDATA_TYPE UNWIND_INFO_ARM
2233#endif
2234 if (unwindEntry->Flag != 0) { // Packed unwind info
2235 _info.end_ip =
2236 _info.start_ip + unwindEntry->FunctionLength * FUNC_LENGTH_UNIT;
2237 // Only fill in the handler and LSDA if they're stale.
2238 if (pc != getLastPC()) {
2239 // Packed unwind info doesn't have an exception handler.
2240 _info.lsda = 0;
2241 _info.handler = 0;
2242 }
2243 } else {
2244 XDATA_TYPE *xdata =
2245 reinterpret_cast<XDATA_TYPE *>(base + unwindEntry->UnwindData);
2246 _info.end_ip = _info.start_ip + xdata->FunctionLength * FUNC_LENGTH_UNIT;
2247 // Only fill in the handler and LSDA if they're stale.
2248 if (pc != getLastPC()) {
2249 if (xdata->ExceptionDataPresent) {
2250 uint32_t offset = 1; // The main xdata
2251 uint32_t codeWords = xdata->CodeWords;
2252 uint32_t epilogScopes = xdata->EpilogCount;
2253 if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) {
2254 // The extension word has got the same layout for both ARM and ARM64
2255 uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
2256 codeWords = (extensionWord >> 16) & 0xff;
2257 epilogScopes = extensionWord & 0xffff;
2258 offset++;
2259 }
2260 if (!xdata->EpilogInHeader)
2261 offset += epilogScopes;
2262 offset += codeWords;
2263 uint32_t *exceptionHandlerInfo =
2264 reinterpret_cast<uint32_t *>(xdata) + offset;
2265 _dispContext.HandlerData = &exceptionHandlerInfo[1];
2266 _dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>(
2267 base + exceptionHandlerInfo[0]);
2268 _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
2269 if (exceptionHandlerInfo[0])
2270 _info.handler =
2271 reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
2272 else
2273 _info.handler = 0;
2274 } else {
2275 _info.lsda = 0;
2276 _info.handler = 0;
2277 }
2278 }
2279 }
2280#endif
2281 setLastPC(pc);
2282 return true;
2283}
2284#endif
2285
2286#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2287// Masks for traceback table field xtbtable.
2288enum xTBTableMask : uint8_t {
2289 reservedBit = 0x02, // The traceback table was incorrectly generated if set
2290 // (see comments in function getInfoFromTBTable().
2291 ehInfoBit = 0x08 // Exception handling info is present if set
2292};
2293
2294enum frameType : unw_word_t {
2295 frameWithXLEHStateTable = 0,
2296 frameWithEHInfo = 1
2297};
2298
2299extern "C" {
2300typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,
2301 uint64_t,
2302 _Unwind_Exception *,
2303 struct _Unwind_Context *);
2304}
2305
2306static __xlcxx_personality_v0_t *xlcPersonalityV0;
2307static RWMutex xlcPersonalityV0InitLock;
2308
2309template <typename A, typename R>
2310bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
2311 uint32_t *p = reinterpret_cast<uint32_t *>(pc);
2312
2313 // Keep looking forward until a word of 0 is found. The traceback
2314 // table starts at the following word.
2315 while (*p)
2316 ++p;
2317 tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
2318
2319 if (_LIBUNWIND_TRACING_UNWINDING) {
2320 char functionBuf[512];
2321 const char *functionName = functionBuf;
2322 unw_word_t offset;
2323 if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
2324 functionName = ".anonymous.";
2325 }
2326 _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
2327 __func__, functionName,
2328 reinterpret_cast<void *>(TBTable));
2329 }
2330
2331 // If the traceback table does not contain necessary info, bypass this frame.
2332 if (!TBTable->tb.has_tboff)
2333 return false;
2334
2335 // Structure tbtable_ext contains important data we are looking for.
2336 p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
2337
2338 // Skip field parminfo if it exists.
2339 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
2340 ++p;
2341
2342 // p now points to tb_offset, the offset from start of function to TB table.
2343 unw_word_t start_ip =
2344 reinterpret_cast<unw_word_t>(TBTable) - *p - sizeof(uint32_t);
2345 unw_word_t end_ip = reinterpret_cast<unw_word_t>(TBTable);
2346 ++p;
2347
2348 _LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",
2349 reinterpret_cast<void *>(start_ip),
2350 reinterpret_cast<void *>(end_ip));
2351
2352 // Skip field hand_mask if it exists.
2353 if (TBTable->tb.int_hndl)
2354 ++p;
2355
2356 unw_word_t lsda = 0;
2357 unw_word_t handler = 0;
2358 unw_word_t flags = frameType::frameWithXLEHStateTable;
2359
2360 if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl) {
2361 // State table info is available. The ctl_info field indicates the
2362 // number of CTL anchors. There should be only one entry for the C++
2363 // state table.
2364 assert(*p == 1 && "libunwind: there must be only one ctl_info entry");
2365 ++p;
2366 // p points to the offset of the state table into the stack.
2367 pint_t stateTableOffset = *p++;
2368
2369 int framePointerReg;
2370
2371 // Skip fields name_len and name if exist.
2372 if (TBTable->tb.name_present) {
2373 const uint16_t name_len = *(reinterpret_cast<uint16_t *>(p));
2374 p = reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p) + name_len +
2375 sizeof(uint16_t));
2376 }
2377
2378 if (TBTable->tb.uses_alloca)
2379 framePointerReg = *(reinterpret_cast<char *>(p));
2380 else
2381 framePointerReg = 1; // default frame pointer == SP
2382
2383 _LIBUNWIND_TRACE_UNWINDING(
2384 "framePointerReg=%d, framePointer=%p, "
2385 "stateTableOffset=%#lx\n",
2386 framePointerReg,
2387 reinterpret_cast<void *>(_registers.getRegister(framePointerReg)),
2388 stateTableOffset);
2389 lsda = _registers.getRegister(framePointerReg) + stateTableOffset;
2390
2391 // Since the traceback table generated by the legacy XLC++ does not
2392 // provide the location of the personality for the state table,
2393 // function __xlcxx_personality_v0(), which is the personality for the state
2394 // table and is exported from libc++abi, is directly assigned as the
2395 // handler here. When a legacy XLC++ frame is encountered, the symbol
2396 // is resolved dynamically using dlopen() to avoid a hard dependency of
2397 // libunwind on libc++abi in cases such as non-C++ applications.
2398
2399 // Resolve the function pointer to the state table personality if it has
2400 // not already been done.
2401 if (xlcPersonalityV0 == NULL) {
2402 xlcPersonalityV0InitLock.lock();
2403 if (xlcPersonalityV0 == NULL) {
2404 // Resolve __xlcxx_personality_v0 using dlopen().
2405 const char *libcxxabi = "libc++abi.a(libc++abi.so.1)";
2406 void *libHandle;
2407 // The AIX dlopen() sets errno to 0 when it is successful, which
2408 // clobbers the value of errno from the user code. This is an AIX
2409 // bug because according to POSIX it should not set errno to 0. To
2410 // workaround before AIX fixes the bug, errno is saved and restored.
2411 int saveErrno = errno;
2412 libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
2413 if (libHandle == NULL) {
2414 _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno);
2415 assert(0 && "dlopen() failed");
2416 }
2417 xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
2418 dlsym(libHandle, "__xlcxx_personality_v0"));
2419 if (xlcPersonalityV0 == NULL) {
2420 _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
2421 dlclose(libHandle);
2422 assert(0 && "dlsym() failed");
2423 }
2424 errno = saveErrno;
2425 }
2426 xlcPersonalityV0InitLock.unlock();
2427 }
2428 handler = reinterpret_cast<unw_word_t>(xlcPersonalityV0);
2429 _LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",
2430 reinterpret_cast<void *>(lsda),
2431 reinterpret_cast<void *>(handler));
2432 } else if (TBTable->tb.longtbtable) {
2433 // This frame has the traceback table extension. Possible cases are
2434 // 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that
2435 // is not EH aware; or, 3) a frame of other languages. We need to figure out
2436 // if the traceback table extension contains the 'eh_info' structure.
2437 //
2438 // We also need to deal with the complexity arising from some XL compiler
2439 // versions use the wrong ordering of 'longtbtable' and 'has_vec' bits
2440 // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice
2441 // versa. For frames of code generated by those compilers, the 'longtbtable'
2442 // bit may be set but there isn't really a traceback table extension.
2443 //
2444 // In </usr/include/sys/debug.h>, there is the following definition of
2445 // 'struct tbtable_ext'. It is not really a structure but a dummy to
2446 // collect the description of optional parts of the traceback table.
2447 //
2448 // struct tbtable_ext {
2449 // ...
2450 // char alloca_reg; /* Register for alloca automatic storage */
2451 // struct vec_ext vec_ext; /* Vector extension (if has_vec is set) */
2452 // unsigned char xtbtable; /* More tbtable fields, if longtbtable is set*/
2453 // };
2454 //
2455 // Depending on how the 'has_vec'/'longtbtable' bit is interpreted, the data
2456 // following 'alloca_reg' can be treated either as 'struct vec_ext' or
2457 // 'unsigned char xtbtable'. 'xtbtable' bits are defined in
2458 // </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently
2459 // unused and should not be set. 'struct vec_ext' is defined in
2460 // </usr/include/sys/debug.h> as follows:
2461 //
2462 // struct vec_ext {
2463 // unsigned vr_saved:6; /* Number of non-volatile vector regs saved
2464 // */
2465 // /* first register saved is assumed to be */
2466 // /* 32 - vr_saved */
2467 // unsigned saves_vrsave:1; /* Set if vrsave is saved on the stack */
2468 // unsigned has_varargs:1;
2469 // ...
2470 // };
2471 //
2472 // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it
2473 // is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',
2474 // we checks if the 7th bit is set or not because 'xtbtable' should
2475 // never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved
2476 // in the future to make sure the mitigation works. This mitigation
2477 // is not 100% bullet proof because 'struct vec_ext' may not always have
2478 // 'saves_vrsave' bit set.
2479 //
2480 // 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for
2481 // checking the 7th bit.
2482
2483 // p points to field name len.
2484 uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
2485
2486 // Skip fields name_len and name if they exist.
2487 if (TBTable->tb.name_present) {
2488 const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
2489 charPtr = charPtr + name_len + sizeof(uint16_t);
2490 }
2491
2492 // Skip field alloc_reg if it exists.
2493 if (TBTable->tb.uses_alloca)
2494 ++charPtr;
2495
2496 // Check traceback table bit has_vec. Skip struct vec_ext if it exists.
2497 if (TBTable->tb.has_vec)
2498 // Note struct vec_ext does exist at this point because whether the
2499 // ordering of longtbtable and has_vec bits is correct or not, both
2500 // are set.
2501 charPtr += sizeof(struct vec_ext);
2502
2503 // charPtr points to field 'xtbtable'. Check if the EH info is available.
2504 // Also check if the reserved bit of the extended traceback table field
2505 // 'xtbtable' is set. If it is, the traceback table was incorrectly
2506 // generated by an XL compiler that uses the wrong ordering of 'longtbtable'
2507 // and 'has_vec' bits and this is in fact 'struct vec_ext'. So skip the
2508 // frame.
2509 if ((*charPtr & xTBTableMask::ehInfoBit) &&
2510 !(*charPtr & xTBTableMask::reservedBit)) {
2511 // Mark this frame has the new EH info.
2512 flags = frameType::frameWithEHInfo;
2513
2514 // eh_info is available.
2515 charPtr++;
2516 // The pointer is 4-byte aligned.
2517 if (reinterpret_cast<uintptr_t>(charPtr) % 4)
2518 charPtr += 4 - reinterpret_cast<uintptr_t>(charPtr) % 4;
2519 uintptr_t *ehInfo =
2520 reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(
2521 registers.getRegister(2) +
2522 *(reinterpret_cast<uintptr_t *>(charPtr)))));
2523
2524 // ehInfo points to structure en_info. The first member is version.
2525 // Only version 0 is currently supported.
2526 assert(*(reinterpret_cast<uint32_t *>(ehInfo)) == 0 &&
2527 "libunwind: ehInfo version other than 0 is not supported");
2528
2529 // Increment ehInfo to point to member lsda.
2530 ++ehInfo;
2531 lsda = *ehInfo++;
2532
2533 // enInfo now points to member personality.
2534 handler = *ehInfo;
2535
2536 _LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",
2537 lsda, handler);
2538 }
2539 }
2540
2541 _info.start_ip = start_ip;
2542 _info.end_ip = end_ip;
2543 _info.lsda = lsda;
2544 _info.handler = handler;
2545 _info.gp = 0;
2546 _info.flags = flags;
2547 _info.format = 0;
2548 _info.unwind_info = reinterpret_cast<unw_word_t>(TBTable);
2549 _info.unwind_info_size = 0;
2550 _info.extra = registers.getRegister(2);
2551
2552 return true;
2553}
2554
2555// VAPI glue addresses
2556constexpr uintptr_t vapi_glue_addr_ext_32 = 0x8b80;
2557constexpr uintptr_t vapi_addr_64 = 0x8e00;
2558constexpr size_t vapi_size_64 = 0x0200;
2559constexpr uintptr_t vapi_glue_addr_begin =
2560 vapi_glue_addr_ext_32; // Start address in 32-bit
2561constexpr uintptr_t vapi_glue_addr_end =
2562 vapi_addr_64 + vapi_size_64; // End address in 64-bit
2563
2564#ifdef __64BIT__
2565constexpr size_t VAPI_CB_SIZE = 256;
2566constexpr ptrdiff_t TLS_POINTER_OFFSET = 30 * 1024;
2567constexpr size_t TLSCB_BASE_SIZE = 256;
2568
2569static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
2570 char *result;
2571 __asm__("mr %0, 13" : "=r"(result));
2572 return result;
2573}
2574#else // 32-bit
2575constexpr size_t VAPI_CB_SIZE = 128;
2576constexpr ptrdiff_t TLS_POINTER_OFFSET = 31 * 1024;
2577constexpr size_t TLSCB_BASE_SIZE = 128;
2578
2579static __inline__ __attribute__((__always_inline__)) char *tptr(void) {
2580 char *result;
2581 __asm__("mfspr %0, 259" : "=r"(result));
2582 return result;
2583}
2584#endif
2585
2586constexpr ptrdiff_t VAPI_CB_OFFSET =
2587 TLS_POINTER_OFFSET + VAPI_CB_SIZE + TLSCB_BASE_SIZE;
2588
2589template <typename A, typename R>
2590typename UnwindCursor<A, R>::pint_t UnwindCursor<A, R>::getVAPILR() {
2591 return *reinterpret_cast<pint_t *>(tptr() - VAPI_CB_OFFSET + 8);
2592}
2593
2594// Step back up the stack following the frame back link.
2595template <typename A, typename R>
2596int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2597 R &registers, bool &isSignalFrame) {
2598 if (_LIBUNWIND_TRACING_UNWINDING) {
2599 char functionBuf[512];
2600 const char *functionName = functionBuf;
2601 unw_word_t offset;
2602 if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
2603 functionName = ".anonymous.";
2604 }
2605 _LIBUNWIND_TRACE_UNWINDING(
2606 "%s: Look up traceback table of func=%s at %p, pc=%p, "
2607 "SP=%p, saves_lr=%d, stores_bc=%d",
2608 __func__, functionName, reinterpret_cast<void *>(TBTable),
2609 reinterpret_cast<void *>(pc),
2610 reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr,
2611 TBTable->tb.stores_bc);
2612 }
2613
2614#if defined(__powerpc64__)
2615 // Instruction to reload TOC register "ld r2,40(r1)"
2616 const uint32_t loadTOCRegInst = 0xe8410028;
2617 const int32_t unwPPCF0Index = UNW_PPC64_F0;
2618 const int32_t unwPPCV0Index = UNW_PPC64_V0;
2619#else
2620 // Instruction to reload TOC register "lwz r2,20(r1)"
2621 const uint32_t loadTOCRegInst = 0x80410014;
2622 const int32_t unwPPCF0Index = UNW_PPC_F0;
2623 const int32_t unwPPCV0Index = UNW_PPC_V0;
2624#endif
2625
2626 // lastStack points to the stack frame of the next routine up.
2627 pint_t curStack = static_cast<pint_t>(registers.getSP());
2628 pint_t lastStack = *reinterpret_cast<pint_t *>(curStack);
2629
2630 if (lastStack == 0)
2631 return UNW_STEP_END;
2632
2633 R newRegisters = registers;
2634
2635 // If backchain is not stored, use the current stack frame.
2636 if (!TBTable->tb.stores_bc)
2637 lastStack = curStack;
2638
2639 // Return address is the address after call site instruction.
2640 pint_t returnAddress;
2641
2642 if (isSignalFrame) {
2643 _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
2644 reinterpret_cast<void *>(lastStack));
2645
2646 pint_t returnAddressInStack = reinterpret_cast<pint_t *>(lastStack)[2];
2647 if (vapi_glue_addr_begin <= returnAddressInStack &&
2648 returnAddressInStack < vapi_glue_addr_end) {
2649 _LIBUNWIND_TRACE_UNWINDING(
2650 "The return address in stack %p is within the range of VAPI address;"
2651 " set isKnownVapiNotActive to true\n",
2652 reinterpret_cast<void *>(returnAddressInStack));
2653 setIsKnownVapiNotActive(true);
2654 }
2655
2656 sigcontext *sigContext = reinterpret_cast<sigcontext *>(
2657 reinterpret_cast<char *>(lastStack) + STKMINALIGN);
2658 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
2659
2660 bool useSTKMIN = false;
2661 if (returnAddress < 0x10000000) {
2662 // Try again using STKMIN.
2663 sigContext = reinterpret_cast<sigcontext *>(
2664 reinterpret_cast<char *>(lastStack) + STKMIN);
2665 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
2666 if (returnAddress < 0x10000000) {
2667 _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
2668 reinterpret_cast<void *>(returnAddress),
2669 reinterpret_cast<void *>(sigContext));
2670 return UNW_EBADFRAME;
2671 }
2672 useSTKMIN = true;
2673 }
2674 _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
2675 "sigContext=%p, returnAddress=%p. "
2676 "Seems to be a valid address",
2677 useSTKMIN ? "STKMIN" : "STKMINALIGN",
2678 reinterpret_cast<void *>(sigContext),
2679 reinterpret_cast<void *>(returnAddress));
2680
2681 // Restore the condition register from sigcontext.
2682 newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);
2683
2684 // Save the LR in sigcontext for stepping up when the function that
2685 // raised the signal is a leaf function. This LR has the return address
2686 // to the caller of the leaf function.
2687 newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr);
2688 _LIBUNWIND_TRACE_UNWINDING(
2689 "Save LR=%p from sigcontext",
2690 reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr));
2691
2692 // Restore GPRs from sigcontext.
2693 for (int i = 0; i < 32; ++i)
2694 newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);
2695
2696 // Restore FPRs from sigcontext.
2697 for (int i = 0; i < 32; ++i)
2698 newRegisters.setFloatRegister(i + unwPPCF0Index,
2699 sigContext->sc_jmpbuf.jmp_context.fpr[i]);
2700
2701 // Restore vector registers if there is an associated extended context
2702 // structure.
2703 if (sigContext->sc_jmpbuf.jmp_context.msr & __EXTCTX) {
2704 ucontext_t *uContext = reinterpret_cast<ucontext_t *>(sigContext);
2705 if (uContext->__extctx->__extctx_magic == __EXTCTX_MAGIC) {
2706 for (int i = 0; i < 32; ++i)
2707 newRegisters.setVectorRegister(
2708 i + unwPPCV0Index, *(reinterpret_cast<v128 *>(
2709 &(uContext->__extctx->__vmx.__vr[i]))));
2710 }
2711 }
2712 } else {
2713 // Step up a normal frame.
2714
2715 if (!TBTable->tb.saves_lr && registers.getLR()) {
2716 // This case should only occur if we were called from a signal handler
2717 // and the signal occurred in a function that doesn't save the LR.
2718 returnAddress = static_cast<pint_t>(registers.getLR());
2719 _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
2720 reinterpret_cast<void *>(returnAddress));
2721 } else {
2722 // Otherwise, use the LR value in the stack link area.
2723 returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
2724
2725 if (vapi_glue_addr_begin <= returnAddress &&
2726 returnAddress < vapi_glue_addr_end) {
2727 _LIBUNWIND_TRACE_UNWINDING(
2728 "The return address=%p is within the range of VAPI address;",
2729 reinterpret_cast<void *>(returnAddress));
2730 setIsKnownVapiNotActive(true);
2731 returnAddress = getVAPILR();
2732 _LIBUNWIND_TRACE_UNWINDING("return address=%p from VAPI\n",
2733 reinterpret_cast<void *>(returnAddress));
2734 }
2735 }
2736
2737 // Reset LR in the current context.
2738 newRegisters.setLR(static_cast<uintptr_t>(NULL));
2739
2740 _LIBUNWIND_TRACE_UNWINDING(
2741 "Extract info from lastStack=%p, returnAddress=%p",
2742 reinterpret_cast<void *>(lastStack),
2743 reinterpret_cast<void *>(returnAddress));
2744 _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
2745 TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,
2746 TBTable->tb.saves_cr);
2747
2748 // Restore FP registers.
2749 char *ptrToRegs = reinterpret_cast<char *>(lastStack);
2750 double *FPRegs = reinterpret_cast<double *>(
2751 ptrToRegs - (TBTable->tb.fpr_saved * sizeof(double)));
2752 for (int i = 0; i < TBTable->tb.fpr_saved; ++i)
2753 newRegisters.setFloatRegister(
2754 32 - TBTable->tb.fpr_saved + i + unwPPCF0Index, FPRegs[i]);
2755
2756 // Restore GP registers.
2757 ptrToRegs = reinterpret_cast<char *>(FPRegs);
2758 uintptr_t *GPRegs = reinterpret_cast<uintptr_t *>(
2759 ptrToRegs - (TBTable->tb.gpr_saved * sizeof(uintptr_t)));
2760 for (int i = 0; i < TBTable->tb.gpr_saved; ++i)
2761 newRegisters.setRegister(32 - TBTable->tb.gpr_saved + i, GPRegs[i]);
2762
2763 // Restore Vector registers.
2764 ptrToRegs = reinterpret_cast<char *>(GPRegs);
2765
2766 // Restore vector registers only if this is a Clang frame. Also
2767 // check if traceback table bit has_vec is set. If it is, structure
2768 // vec_ext is available.
2769 if (_info.flags == frameType::frameWithEHInfo && TBTable->tb.has_vec) {
2770
2771 // Get to the vec_ext structure to check if vector registers are saved.
2772 uint32_t *p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
2773
2774 // Skip field parminfo if exists.
2775 if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
2776 ++p;
2777
2778 // Skip field tb_offset if exists.
2779 if (TBTable->tb.has_tboff)
2780 ++p;
2781
2782 // Skip field hand_mask if exists.
2783 if (TBTable->tb.int_hndl)
2784 ++p;
2785
2786 // Skip fields ctl_info and ctl_info_disp if exist.
2787 if (TBTable->tb.has_ctl) {
2788 // Skip field ctl_info.
2789 ++p;
2790 // Skip field ctl_info_disp.
2791 ++p;
2792 }
2793
2794 // Skip fields name_len and name if exist.
2795 // p is supposed to point to field name_len now.
2796 uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
2797 if (TBTable->tb.name_present) {
2798 const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
2799 charPtr = charPtr + name_len + sizeof(uint16_t);
2800 }
2801
2802 // Skip field alloc_reg if it exists.
2803 if (TBTable->tb.uses_alloca)
2804 ++charPtr;
2805
2806 struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);
2807
2808 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved);
2809
2810 // Restore vector register(s) if saved on the stack.
2811 if (vec_ext->vr_saved) {
2812 // Saved vector registers are 16-byte aligned.
2813 if (reinterpret_cast<uintptr_t>(ptrToRegs) % 16)
2814 ptrToRegs -= reinterpret_cast<uintptr_t>(ptrToRegs) % 16;
2815 v128 *VecRegs = reinterpret_cast<v128 *>(ptrToRegs - vec_ext->vr_saved *
2816 sizeof(v128));
2817 for (int i = 0; i < vec_ext->vr_saved; ++i) {
2818 newRegisters.setVectorRegister(
2819 32 - vec_ext->vr_saved + i + unwPPCV0Index, VecRegs[i]);
2820 }
2821 }
2822 }
2823 if (TBTable->tb.saves_cr) {
2824 // Get the saved condition register. The condition register is only
2825 // a single word.
2826 newRegisters.setCR(
2827 *(reinterpret_cast<uint32_t *>(lastStack + sizeof(uintptr_t))));
2828 }
2829
2830 // Restore the SP.
2831 newRegisters.setSP(lastStack);
2832
2833 // The first instruction after return.
2834 uint32_t firstInstruction = *(reinterpret_cast<uint32_t *>(returnAddress));
2835
2836 // Do we need to set the TOC register?
2837 _LIBUNWIND_TRACE_UNWINDING(
2838 "Current gpr2=%p",
2839 reinterpret_cast<void *>(newRegisters.getRegister(2)));
2840 if (firstInstruction == loadTOCRegInst) {
2841 _LIBUNWIND_TRACE_UNWINDING(
2842 "Set gpr2=%p from frame",
2843 reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));
2844 newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);
2845 }
2846 }
2847 _LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",
2848 reinterpret_cast<void *>(lastStack),
2849 reinterpret_cast<void *>(returnAddress),
2850 reinterpret_cast<void *>(pc));
2851
2852 // The return address is the address after call site instruction, so
2853 // setting IP to that simulates a return.
2854 newRegisters.setIP(reinterpret_cast<uintptr_t>(returnAddress));
2855
2856 // Simulate the step by replacing the register set with the new ones.
2857 registers = newRegisters;
2858
2859 // Check if the next frame is a signal frame.
2860 pint_t nextStack = *(reinterpret_cast<pint_t *>(registers.getSP()));
2861
2862 // Return address is the address after call site instruction.
2863 pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2];
2864
2865 if (vapi_glue_addr_begin <= nextReturnAddress &&
2866 nextReturnAddress < vapi_glue_addr_end) {
2867 _LIBUNWIND_TRACE_UNWINDING(
2868 "The next return address=%p is within the range of VAPI address;",
2869 reinterpret_cast<void *>(nextReturnAddress));
2870 nextReturnAddress = getVAPILR();
2871 _LIBUNWIND_TRACE_UNWINDING("the next return address=%p from VAPI\n",
2872 reinterpret_cast<void *>(nextReturnAddress));
2873 }
2874
2875 if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) {
2876 _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
2877 "nextStack=%p, next return address=%p\n",
2878 reinterpret_cast<void *>(nextStack),
2879 reinterpret_cast<void *>(nextReturnAddress));
2880 isSignalFrame = true;
2881 } else {
2882 isSignalFrame = false;
2883 }
2884 return UNW_STEP_SUCCESS;
2885}
2886#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2887
2888template <typename A, typename R>
2889void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2890#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
2891 defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
2892 _isSigReturn = false;
2893#endif
2894
2895 typename R::reg_t rawPC = this->getReg(regNum: UNW_REG_IP);
2896
2897#if defined(_LIBUNWIND_ARM_EHABI)
2898 // Remove the thumb bit so the IP represents the actual instruction address.
2899 // This matches the behaviour of _Unwind_GetIP on arm.
2900 rawPC &= (pint_t)~0x1;
2901#endif
2902
2903 typename R::link_reg_t pc;
2904#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
2905 _registers.loadAndAuthenticateLinkRegister(rawPC, &pc);
2906#else
2907 pc = rawPC;
2908#endif
2909
2910 // Exit early if at the top of the stack.
2911 if (pc == 0) {
2912 _unwindInfoMissing = true;
2913 return;
2914 }
2915
2916 // If the last line of a function is a "throw" the compiler sometimes
2917 // emits no instructions after the call to __cxa_throw. This means
2918 // the return address is actually the start of the next function.
2919 // To disambiguate this, back up the pc when we know it is a return
2920 // address.
2921 if (isReturnAddress)
2922#if defined(_AIX)
2923 // PC needs to be a 4-byte aligned address to be able to look for a
2924 // word of 0 that indicates the start of the traceback table at the end
2925 // of a function on AIX.
2926 pc -= 4;
2927#else
2928 --pc;
2929#endif
2930
2931#if !(defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)) && \
2932 !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2933 // In case of this is frame of signal handler, the IP saved in the signal
2934 // handler points to first non-executed instruction, while FDE/CIE expects IP
2935 // to be after the first non-executed instruction.
2936 if (_isSignalFrame)
2937 ++pc;
2938#endif
2939
2940 // Ask address space object to find unwind sections for this pc.
2941 UnwindInfoSections sects;
2942 if (_addressSpace.template findUnwindSections<R>(pc, sects)) {
2943#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2944 // If there is a compact unwind encoding table, look there first.
2945 if (sects.compact_unwind_section != 0) {
2946 if (this->getInfoFromCompactEncodingSection(pc, sects)) {
2947 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2948 // Found info in table, done unless encoding says to use dwarf.
2949 uint32_t dwarfOffset;
2950 if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
2951 if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {
2952 // found info in dwarf, done
2953 return;
2954 }
2955 }
2956 #endif
2957 // If unwind table has entry, but entry says there is no unwind info,
2958 // record that we have no unwind info.
2959 if (_info.format == 0)
2960 _unwindInfoMissing = true;
2961 return;
2962 }
2963 }
2964#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2965
2966#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2967 // If there is SEH unwind info, look there next.
2968 if (this->getInfoFromSEH(pc))
2969 return;
2970#endif
2971
2972#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2973 // If there is unwind info in the traceback table, look there next.
2974 if (this->getInfoFromTBTable(pc, _registers))
2975 return;
2976#endif
2977
2978#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2979 // If there is dwarf unwind info, look there next.
2980 if (sects.dwarf_section != 0) {
2981 if (this->getInfoFromDwarfSection(pc, sects)) {
2982 // found info in dwarf, done
2983 return;
2984 }
2985 }
2986#endif
2987
2988#if defined(_LIBUNWIND_ARM_EHABI)
2989 // If there is ARM EHABI unwind info, look there next.
2990 if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
2991 return;
2992#endif
2993 }
2994
2995#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2996 // There is no static unwind info for this pc. Look to see if an FDE was
2997 // dynamically registered for it.
2998 pint_t cachedFDE =
2999 DwarfFDECache<A>::template findFDE<R>(DwarfFDECache<A>::kSearchAll, pc);
3000 if (cachedFDE != 0) {
3001 typename CFI_Parser<A>::FDE_Info fdeInfo;
3002 typename CFI_Parser<A>::CIE_Info cieInfo;
3003 if (!CFI_Parser<A>::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo))
3004 if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, dso_base: 0))
3005 return;
3006 }
3007
3008 // Lastly, ask AddressSpace object about platform specific ways to locate
3009 // other FDEs.
3010 pint_t fde;
3011 if (_addressSpace.template findOtherFDE<R>(pc, fde)) {
3012 typename CFI_Parser<A>::FDE_Info fdeInfo;
3013 typename CFI_Parser<A>::CIE_Info cieInfo;
3014 if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
3015 // Double check this FDE is for a function that includes the pc.
3016 if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd))
3017 if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, dso_base: 0))
3018 return;
3019 }
3020 }
3021#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
3022
3023#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
3024 defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3025 if (setInfoForSigReturn())
3026 return;
3027#endif
3028
3029 // no unwind info, flag that we can't reliably unwind
3030 _unwindInfoMissing = true;
3031}
3032
3033#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
3034 defined(_LIBUNWIND_TARGET_AARCH64)
3035
3036/*
3037 * The linux sigreturn restorer stub will always have the form:
3038 *
3039 * d2801168 movz x8, #0x8b
3040 * d4000001 svc #0x0
3041 */
3042#if defined(__AARCH64EB__)
3043#define MOVZ_X8_8B 0x681180d2
3044#define SVC_0 0x010000d4
3045#else
3046#define MOVZ_X8_8B 0xd2801168
3047#define SVC_0 0xd4000001
3048#endif
3049
3050template <typename A, typename R>
3051bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
3052 // Look for the sigreturn trampoline. The trampoline's body is two
3053 // specific instructions (see below). Typically the trampoline comes from the
3054 // vDSO[1] (i.e. the __kernel_rt_sigreturn function). A libc might provide its
3055 // own restorer function, though, or user-mode QEMU might write a trampoline
3056 // onto the stack.
3057 //
3058 // This special code path is a fallback that is only used if the trampoline
3059 // lacks proper (e.g. DWARF) unwind info. On AArch64, a new DWARF register
3060 // constant for the PC needs to be defined before DWARF can handle a signal
3061 // trampoline. This code may segfault if the target PC is unreadable, e.g.:
3062 // - The PC points at a function compiled without unwind info, and which is
3063 // part of an execute-only mapping (e.g. using -Wl,--execute-only).
3064 // - The PC is invalid and happens to point to unreadable or unmapped memory.
3065 //
3066 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
3067 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
3068 // The PC might contain an invalid address if the unwind info is bad, so
3069 // directly accessing it could cause a SIGSEGV.
3070 if (!isReadableAddr(pc))
3071 return false;
3072 auto *instructions = reinterpret_cast<const uint32_t *>(pc);
3073 // Look for instructions: mov x8, #0x8b; svc #0x0
3074 if (instructions[0] != MOVZ_X8_8B || instructions[1] != SVC_0)
3075 return false;
3076
3077 _info = {};
3078 _info.start_ip = pc;
3079 _info.end_ip = pc + 4;
3080 _isSigReturn = true;
3081 return true;
3082}
3083
3084template <typename A, typename R>
3085int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
3086 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
3087 // - 128-byte siginfo struct
3088 // - ucontext struct:
3089 // - 8-byte long (uc_flags)
3090 // - 8-byte pointer (uc_link)
3091 // - 24-byte stack_t
3092 // - 128-byte signal set
3093 // - 8 bytes of padding because sigcontext has 16-byte alignment
3094 // - sigcontext/mcontext_t
3095 // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c
3096 const pint_t kOffsetSpToSigcontext = (128 + 8 + 8 + 24 + 128 + 8); // 304
3097
3098 // Offsets from sigcontext to each register.
3099 const pint_t kOffsetGprs = 8; // offset to "__u64 regs[31]" field
3100 const pint_t kOffsetSp = 256; // offset to "__u64 sp" field
3101 const pint_t kOffsetPc = 264; // offset to "__u64 pc" field
3102
3103 pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
3104
3105 for (int i = 0; i <= 30; ++i) {
3106 uint64_t value = _addressSpace.get64(sigctx + kOffsetGprs +
3107 static_cast<pint_t>(i * 8));
3108 _registers.setRegister(UNW_AARCH64_X0 + i, value);
3109 }
3110 _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp));
3111 _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc));
3112 _isSignalFrame = true;
3113 return UNW_STEP_SUCCESS;
3114}
3115#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
3116 // defined(_LIBUNWIND_TARGET_AARCH64)
3117
3118#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
3119 defined(_LIBUNWIND_TARGET_LOONGARCH)
3120template <typename A, typename R>
3121bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_loongarch &) {
3122 const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
3123 // The PC might contain an invalid address if the unwind info is bad, so
3124 // directly accessing it could cause a SIGSEGV.
3125 if (!isReadableAddr(pc))
3126 return false;
3127 const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
3128 // Look for the two instructions used in the sigreturn trampoline
3129 // __vdso_rt_sigreturn:
3130 //
3131 // 0x03822c0b li a7,0x8b
3132 // 0x002b0000 syscall 0
3133 if (instructions[0] != 0x03822c0b || instructions[1] != 0x002b0000)
3134 return false;
3135
3136 _info = {};
3137 _info.start_ip = pc;
3138 _info.end_ip = pc + 4;
3139 _isSigReturn = true;
3140 return true;
3141}
3142
3143template <typename A, typename R>
3144int UnwindCursor<A, R>::stepThroughSigReturn(Registers_loongarch &) {
3145 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
3146 // - 128-byte siginfo struct
3147 // - ucontext_t struct:
3148 // - 8-byte long (__uc_flags)
3149 // - 8-byte pointer (*uc_link)
3150 // - 24-byte uc_stack
3151 // - 8-byte uc_sigmask
3152 // - 120-byte of padding to allow sigset_t to be expanded in the future
3153 // - 8 bytes of padding because sigcontext has 16-byte alignment
3154 // - struct sigcontext uc_mcontext
3155 // [1]
3156 // https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c
3157 const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
3158
3159 const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
3160 _registers.setIP(_addressSpace.get64(sigctx));
3161 for (int i = UNW_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) {
3162 // skip R0
3163 uint64_t value =
3164 _addressSpace.get64(sigctx + static_cast<pint_t>((i + 1) * 8));
3165 _registers.setRegister(i, value);
3166 }
3167 _isSignalFrame = true;
3168 return UNW_STEP_SUCCESS;
3169}
3170#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
3171 // defined(_LIBUNWIND_TARGET_LOONGARCH)
3172
3173#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
3174 defined(_LIBUNWIND_TARGET_RISCV)
3175template <typename A, typename R>
3176bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
3177 const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
3178 // The PC might contain an invalid address if the unwind info is bad, so
3179 // directly accessing it could cause a SIGSEGV.
3180 if (!isReadableAddr(pc))
3181 return false;
3182 const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
3183 // Look for the two instructions used in the sigreturn trampoline
3184 // __vdso_rt_sigreturn:
3185 //
3186 // 0x08b00893 li a7,0x8b
3187 // 0x00000073 ecall
3188 if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073)
3189 return false;
3190
3191 _info = {};
3192 _info.start_ip = pc;
3193 _info.end_ip = pc + 4;
3194 _isSigReturn = true;
3195 return true;
3196}
3197
3198template <typename A, typename R>
3199int UnwindCursor<A, R>::stepThroughSigReturn(Registers_riscv &) {
3200 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
3201 // - 128-byte siginfo struct
3202 // - ucontext_t struct:
3203 // - 8-byte long (__uc_flags)
3204 // - 8-byte pointer (*uc_link)
3205 // - 24-byte uc_stack
3206 // - 8-byte uc_sigmask
3207 // - 120-byte of padding to allow sigset_t to be expanded in the future
3208 // - 8 bytes of padding because sigcontext has 16-byte alignment
3209 // - struct sigcontext uc_mcontext
3210 // [1]
3211 // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
3212 const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
3213
3214 const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
3215 _registers.setIP(_addressSpace.get64(sigctx));
3216 for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) {
3217 uint64_t value = _addressSpace.get64(sigctx + static_cast<pint_t>(i * 8));
3218 _registers.setRegister(i, value);
3219 }
3220 _isSignalFrame = true;
3221 return UNW_STEP_SUCCESS;
3222}
3223#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
3224 // defined(_LIBUNWIND_TARGET_RISCV)
3225
3226#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \
3227 defined(_LIBUNWIND_TARGET_S390X)
3228template <typename A, typename R>
3229bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
3230 // Look for the sigreturn trampoline. The trampoline's body is a
3231 // specific instruction (see below). Typically the trampoline comes from the
3232 // vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its
3233 // own restorer function, though, or user-mode QEMU might write a trampoline
3234 // onto the stack.
3235 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
3236 // The PC might contain an invalid address if the unwind info is bad, so
3237 // directly accessing it could cause a SIGSEGV.
3238 if (!isReadableAddr(pc))
3239 return false;
3240 const auto inst = *reinterpret_cast<const uint16_t *>(pc);
3241 if (inst == 0x0a77 || inst == 0x0aad) {
3242 _info = {};
3243 _info.start_ip = pc;
3244 _info.end_ip = pc + 2;
3245 _isSigReturn = true;
3246 return true;
3247 }
3248 return false;
3249}
3250
3251template <typename A, typename R>
3252int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
3253 // Determine current SP.
3254 const pint_t sp = static_cast<pint_t>(this->getReg(UNW_REG_SP));
3255 // According to the s390x ABI, the CFA is at (incoming) SP + 160.
3256 const pint_t cfa = sp + 160;
3257
3258 // Determine current PC and instruction there (this must be either
3259 // a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn").
3260 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
3261 const uint16_t inst = _addressSpace.get16(pc);
3262
3263 // Find the addresses of the signo and sigcontext in the frame.
3264 pint_t pSigctx = 0;
3265 pint_t pSigno = 0;
3266
3267 // "svc __NR_sigreturn" uses a non-RT signal trampoline frame.
3268 if (inst == 0x0a77) {
3269 // Layout of a non-RT signal trampoline frame, starting at the CFA:
3270 // - 8-byte signal mask
3271 // - 8-byte pointer to sigcontext, followed by signo
3272 // - 4-byte signo
3273 pSigctx = _addressSpace.get64(cfa + 8);
3274 pSigno = pSigctx + 344;
3275 }
3276
3277 // "svc __NR_rt_sigreturn" uses a RT signal trampoline frame.
3278 if (inst == 0x0aad) {
3279 // Layout of a RT signal trampoline frame, starting at the CFA:
3280 // - 8-byte retcode (+ alignment)
3281 // - 128-byte siginfo struct (starts with signo)
3282 // - ucontext struct:
3283 // - 8-byte long (uc_flags)
3284 // - 8-byte pointer (uc_link)
3285 // - 24-byte stack_t
3286 // - 8 bytes of padding because sigcontext has 16-byte alignment
3287 // - sigcontext/mcontext_t
3288 pSigctx = cfa + 8 + 128 + 8 + 8 + 24 + 8;
3289 pSigno = cfa + 8;
3290 }
3291
3292 assert(pSigctx != 0);
3293 assert(pSigno != 0);
3294
3295 // Offsets from sigcontext to each register.
3296 const pint_t kOffsetPc = 8;
3297 const pint_t kOffsetGprs = 16;
3298 const pint_t kOffsetFprs = 216;
3299
3300 // Restore all registers.
3301 for (int i = 0; i < 16; ++i) {
3302 uint64_t value = _addressSpace.get64(pSigctx + kOffsetGprs +
3303 static_cast<pint_t>(i * 8));
3304 _registers.setRegister(UNW_S390X_R0 + i, value);
3305 }
3306 for (int i = 0; i < 16; ++i) {
3307 static const int fpr[16] = {
3308 UNW_S390X_F0, UNW_S390X_F1, UNW_S390X_F2, UNW_S390X_F3,
3309 UNW_S390X_F4, UNW_S390X_F5, UNW_S390X_F6, UNW_S390X_F7,
3310 UNW_S390X_F8, UNW_S390X_F9, UNW_S390X_F10, UNW_S390X_F11,
3311 UNW_S390X_F12, UNW_S390X_F13, UNW_S390X_F14, UNW_S390X_F15
3312 };
3313 double value = _addressSpace.getDouble(pSigctx + kOffsetFprs +
3314 static_cast<pint_t>(i * 8));
3315 _registers.setFloatRegister(fpr[i], value);
3316 }
3317 _registers.setIP(_addressSpace.get64(pSigctx + kOffsetPc));
3318
3319 // SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
3320 // after the faulting instruction rather than before it.
3321 // Do not set _isSignalFrame in that case.
3322 uint32_t signo = _addressSpace.get32(pSigno);
3323 _isSignalFrame = (signo != 4 && signo != 5 && signo != 8);
3324
3325 return UNW_STEP_SUCCESS;
3326}
3327#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
3328 // defined(_LIBUNWIND_TARGET_S390X)
3329
3330#if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3331template <typename A, typename R>
3332bool UnwindCursor<A, R>::setInfoForSigReturn() {
3333 Dl_info dlinfo;
3334 const auto isSignalHandler = [&](pint_t addr) {
3335 if (!dladdr(reinterpret_cast<void *>(addr), &dlinfo))
3336 return false;
3337 if (strcmp(dlinfo.dli_fname, "commpage"))
3338 return false;
3339 if (dlinfo.dli_sname == NULL ||
3340 strcmp(dlinfo.dli_sname, "commpage_signal_handler"))
3341 return false;
3342 return true;
3343 };
3344
3345 pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
3346 if (!isSignalHandler(pc))
3347 return false;
3348
3349 pint_t start = reinterpret_cast<pint_t>(dlinfo.dli_saddr);
3350
3351 static size_t signalHandlerSize = 0;
3352 if (signalHandlerSize == 0) {
3353 size_t boundLow = 0;
3354 size_t boundHigh = static_cast<size_t>(-1);
3355
3356 area_info areaInfo;
3357 if (get_area_info(area_for(dlinfo.dli_saddr), &areaInfo) == B_OK)
3358 boundHigh = areaInfo.size;
3359
3360 while (boundLow < boundHigh) {
3361 size_t boundMid = boundLow + ((boundHigh - boundLow) / 2);
3362 pint_t test = start + boundMid;
3363 if (test >= start && isSignalHandler(test))
3364 boundLow = boundMid + 1;
3365 else
3366 boundHigh = boundMid;
3367 }
3368
3369 signalHandlerSize = boundHigh;
3370 }
3371
3372 _info = {};
3373 _info.start_ip = start;
3374 _info.end_ip = start + signalHandlerSize;
3375 _isSigReturn = true;
3376
3377 return true;
3378}
3379
3380template <typename A, typename R>
3381int UnwindCursor<A, R>::stepThroughSigReturn() {
3382 _isSignalFrame = true;
3383
3384#if defined(_LIBUNWIND_TARGET_X86_64)
3385 // Layout of the stack before function call:
3386 // - signal_frame_data
3387 // + siginfo_t (public struct, fairly stable)
3388 // + ucontext_t (public struct, fairly stable)
3389 // - mcontext_t -> Offset 0x70, this is what we want.
3390 // - frame->ip (8 bytes)
3391 // - frame->bp (8 bytes). Not written by the kernel,
3392 // but the signal handler has a "push %rbp" instruction.
3393 pint_t bp = this->getReg(UNW_X86_64_RBP);
3394 vregs *regs = (vregs *)(bp + 0x70);
3395
3396 _registers.setRegister(UNW_REG_IP, regs->rip);
3397 _registers.setRegister(UNW_REG_SP, regs->rsp);
3398 _registers.setRegister(UNW_X86_64_RAX, regs->rax);
3399 _registers.setRegister(UNW_X86_64_RDX, regs->rdx);
3400 _registers.setRegister(UNW_X86_64_RCX, regs->rcx);
3401 _registers.setRegister(UNW_X86_64_RBX, regs->rbx);
3402 _registers.setRegister(UNW_X86_64_RSI, regs->rsi);
3403 _registers.setRegister(UNW_X86_64_RDI, regs->rdi);
3404 _registers.setRegister(UNW_X86_64_RBP, regs->rbp);
3405 _registers.setRegister(UNW_X86_64_R8, regs->r8);
3406 _registers.setRegister(UNW_X86_64_R9, regs->r9);
3407 _registers.setRegister(UNW_X86_64_R10, regs->r10);
3408 _registers.setRegister(UNW_X86_64_R11, regs->r11);
3409 _registers.setRegister(UNW_X86_64_R12, regs->r12);
3410 _registers.setRegister(UNW_X86_64_R13, regs->r13);
3411 _registers.setRegister(UNW_X86_64_R14, regs->r14);
3412 _registers.setRegister(UNW_X86_64_R15, regs->r15);
3413 // TODO: XMM
3414#endif // defined(_LIBUNWIND_TARGET_X86_64)
3415
3416 return UNW_STEP_SUCCESS;
3417}
3418#endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3419
3420template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
3421 (void)stage2;
3422 // Bottom of stack is defined when unwind info cannot be found.
3423 if (_unwindInfoMissing)
3424 return UNW_STEP_END;
3425
3426 // Use unwinding info to modify register set as if function returned.
3427 int result;
3428#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \
3429 defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3430 if (_isSigReturn) {
3431 result = this->stepThroughSigReturn();
3432 } else
3433#endif
3434 {
3435#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
3436 result = this->stepWithCompactEncoding(stage2);
3437#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
3438 result = this->stepWithSEHData();
3439#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
3440 result = this->stepWithTBTableData();
3441#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
3442 result = this->stepWithDwarfFDE(stage2);
3443#elif defined(_LIBUNWIND_ARM_EHABI)
3444 result = this->stepWithEHABI();
3445#else
3446 #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
3447 _LIBUNWIND_SUPPORT_SEH_UNWIND or \
3448 _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
3449 _LIBUNWIND_ARM_EHABI
3450#endif
3451 }
3452
3453 // update info based on new PC
3454 if (result == UNW_STEP_SUCCESS) {
3455 this->setInfoBasedOnIPRegister(true);
3456 if (_unwindInfoMissing)
3457 return UNW_STEP_END;
3458 }
3459
3460 return result;
3461}
3462
3463template <typename A, typename R>
3464void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
3465 if (_unwindInfoMissing)
3466 memset(s: static_cast<void *>(info), c: 0, n: sizeof(*info));
3467 else
3468 *info = _info;
3469}
3470
3471template <typename A, typename R>
3472bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
3473 unw_word_t *offset) {
3474#if defined(_LIBUNWIND_TARGET_AARCH64_AUTHENTICATED_UNWINDING)
3475 typename R::reg_t rawPC = this->getReg(UNW_REG_IP);
3476 typename R::link_reg_t pc;
3477 _registers.loadAndAuthenticateLinkRegister(rawPC, &pc);
3478#else
3479 typename R::link_reg_t pc = this->getReg(regNum: UNW_REG_IP);
3480#endif
3481 return _addressSpace.template findFunctionName<R>(pc, buf, bufLen, offset);
3482}
3483
3484#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
3485template <typename A, typename R>
3486bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
3487 // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable.
3488
3489 const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);
3490 // We have to check that addr is nullptr because sigprocmask allows that
3491 // as an argument without failure.
3492 if (!sigsetAddr)
3493 return false;
3494 const auto saveErrno = errno;
3495 // We MUST use a raw syscall here, as wrappers may try to access
3496 // sigsetAddr which may cause a SIGSEGV. A raw syscall however is
3497 // safe. Additionally, we need to pass the kernel_sigset_size, which is
3498 // different from libc sizeof(sigset_t). For the majority of architectures,
3499 // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
3500 const auto kernelSigsetSize = NSIG / 8;
3501 [[maybe_unused]] const int Result = syscall(
3502 SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize);
3503 // Because our "how" is invalid, this syscall should always fail, and our
3504 // errno should always be EINVAL or an EFAULT. This relies on the Linux
3505 // kernel to check copy_from_user before checking if the "how" argument is
3506 // invalid.
3507 assert(Result == -1);
3508 assert(errno == EFAULT || errno == EINVAL);
3509 const auto readable = errno != EFAULT;
3510 errno = saveErrno;
3511 return readable;
3512}
3513#endif
3514
3515#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
3516extern "C" void *__libunwind_shstk_get_registers(unw_cursor_t *cursor) {
3517 AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
3518 return co->get_registers();
3519}
3520#endif
3521} // namespace libunwind
3522
3523#endif // __UNWINDCURSOR_HPP__
3524