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