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