brintos

brintos / llvm-project-archived public Read only

0
0
Text · 117.8 KiB · 33fcd84 Raw
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 &sects);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 &sects,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 &sects);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 &registers);1354  int stepWithTBTable(pint_t pc, tbtable *TBTable, R &registers,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(&sects) {}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 &sects) {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 &sects,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 &sects) {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 &registers) {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 &registers, 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