Path: blob/main/system/lib/libunwind/src/UnwindCursor.hpp
6178 views
//===----------------------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//7// C++ interface to lower levels of libunwind8//===----------------------------------------------------------------------===//910#ifndef __UNWINDCURSOR_HPP__11#define __UNWINDCURSOR_HPP__1213#include "shadow_stack_unwind.h"14#include <stdint.h>15#include <stdio.h>16#include <stdlib.h>17#include <unwind.h>1819#ifdef _WIN3220#include <windows.h>21#include <ntverp.h>22#endif23#ifdef __APPLE__24#include <mach-o/dyld.h>25#endif26#ifdef _AIX27#include <dlfcn.h>28#include <sys/debug.h>29#include <sys/pseg.h>30#endif3132#if defined(_LIBUNWIND_TARGET_LINUX) && \33(defined(_LIBUNWIND_TARGET_AARCH64) || \34defined(_LIBUNWIND_TARGET_LOONGARCH) || \35defined(_LIBUNWIND_TARGET_RISCV) || defined(_LIBUNWIND_TARGET_S390X))36#include <errno.h>37#include <signal.h>38#include <sys/syscall.h>39#include <unistd.h>40#define _LIBUNWIND_CHECK_LINUX_SIGRETURN 141#endif4243#if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)44#include <OS.h>45#include <signal.h>46#define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 147#endif4849#include "AddressSpace.hpp"50#include "CompactUnwinder.hpp"51#include "config.h"52#include "DwarfInstructions.hpp"53#include "EHHeaderParser.hpp"54#include "libunwind.h"55#include "libunwind_ext.h"56#include "Registers.hpp"57#include "RWMutex.hpp"58#include "Unwind-EHABI.h"5960#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)61// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and62// earlier) SDKs.63// MinGW-w64 has always provided this struct.64#if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \65!defined(__MINGW32__) && VER_PRODUCTBUILD < 800066struct _DISPATCHER_CONTEXT {67ULONG64 ControlPc;68ULONG64 ImageBase;69PRUNTIME_FUNCTION FunctionEntry;70ULONG64 EstablisherFrame;71ULONG64 TargetIp;72PCONTEXT ContextRecord;73PEXCEPTION_ROUTINE LanguageHandler;74PVOID HandlerData;75PUNWIND_HISTORY_TABLE HistoryTable;76ULONG ScopeIndex;77ULONG Fill0;78};79#endif8081struct UNWIND_INFO {82uint8_t Version : 3;83uint8_t Flags : 5;84uint8_t SizeOfProlog;85uint8_t CountOfCodes;86uint8_t FrameRegister : 4;87uint8_t FrameOffset : 4;88uint16_t UnwindCodes[2];89};9091#pragma clang diagnostic push92#pragma clang diagnostic ignored "-Wgnu-anonymous-struct"93union UNWIND_INFO_ARM {94DWORD HeaderData;95struct {96DWORD FunctionLength : 18;97DWORD Version : 2;98DWORD ExceptionDataPresent : 1;99DWORD EpilogInHeader : 1;100DWORD FunctionFragment : 1;101DWORD EpilogCount : 5;102DWORD CodeWords : 4;103};104};105#pragma clang diagnostic pop106107extern "C" _Unwind_Reason_Code __libunwind_seh_personality(108int, _Unwind_Action, uint64_t, _Unwind_Exception *,109struct _Unwind_Context *);110111#endif112113namespace libunwind {114115#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)116/// Cache of recently found FDEs.117template <typename A>118class _LIBUNWIND_HIDDEN DwarfFDECache {119typedef typename A::pint_t pint_t;120public:121static constexpr pint_t kSearchAll = static_cast<pint_t>(-1);122static pint_t findFDE(pint_t mh, pint_t pc);123static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);124static void removeAllIn(pint_t mh);125static void iterateCacheEntries(void (*func)(unw_word_t ip_start,126unw_word_t ip_end,127unw_word_t fde, unw_word_t mh));128129private:130131struct entry {132pint_t mh;133pint_t ip_start;134pint_t ip_end;135pint_t fde;136};137138// These fields are all static to avoid needing an initializer.139// There is only one instance of this class per process.140static RWMutex _lock;141#ifdef __APPLE__142static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);143static bool _registeredForDyldUnloads;144#endif145static entry *_buffer;146static entry *_bufferUsed;147static entry *_bufferEnd;148static entry _initialBuffer[64];149};150151template <typename A>152typename DwarfFDECache<A>::entry *153DwarfFDECache<A>::_buffer = _initialBuffer;154155template <typename A>156typename DwarfFDECache<A>::entry *157DwarfFDECache<A>::_bufferUsed = _initialBuffer;158159template <typename A>160typename DwarfFDECache<A>::entry *161DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];162163template <typename A>164typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];165166template <typename A>167RWMutex DwarfFDECache<A>::_lock;168169#ifdef __APPLE__170template <typename A>171bool DwarfFDECache<A>::_registeredForDyldUnloads = false;172#endif173174template <typename A>175typename DwarfFDECache<A>::pint_t DwarfFDECache<A>::findFDE(pint_t mh,176pint_t pc) {177pint_t result = 0;178_LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());179for (entry *p = _buffer; p < _bufferUsed; ++p) {180if ((mh == p->mh) || (mh == kSearchAll)) {181if ((p->ip_start <= pc) && (pc < p->ip_end)) {182result = p->fde;183break;184}185}186}187_LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared());188return result;189}190191template <typename A>192void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,193pint_t fde) {194#if !defined(_LIBUNWIND_NO_HEAP)195_LIBUNWIND_LOG_IF_FALSE(_lock.lock());196if (_bufferUsed >= _bufferEnd) {197size_t oldSize = (size_t)(_bufferEnd - _buffer);198size_t newSize = oldSize * 4;199// Can't use operator new (we are below it).200entry *newBuffer = (entry *)malloc(newSize * sizeof(entry));201memcpy(newBuffer, _buffer, oldSize * sizeof(entry));202if (_buffer != _initialBuffer)203free(_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__214if (!_registeredForDyldUnloads) {215_dyld_register_func_for_remove_image(&dyldUnloadHook);216_registeredForDyldUnloads = true;217}218#endif219_LIBUNWIND_LOG_IF_FALSE(_lock.unlock());220#endif221}222223template <typename A>224void DwarfFDECache<A>::removeAllIn(pint_t mh) {225_LIBUNWIND_LOG_IF_FALSE(_lock.lock());226entry *d = _buffer;227for (const entry *s = _buffer; s < _bufferUsed; ++s) {228if (s->mh != mh) {229if (d != s)230*d = *s;231++d;232}233}234_bufferUsed = d;235_LIBUNWIND_LOG_IF_FALSE(_lock.unlock());236}237238#ifdef __APPLE__239template <typename A>240void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {241removeAllIn((pint_t) mh);242}243#endif244245template <typename A>246void DwarfFDECache<A>::iterateCacheEntries(void (*func)(247unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {248_LIBUNWIND_LOG_IF_FALSE(_lock.lock());249for (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)255256#define arrayoffsetof(type, index, field) \257(sizeof(type) * (index) + offsetof(type, field))258259#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)260template <typename A> class UnwindSectionHeader {261public:262UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)263: _addressSpace(addressSpace), _addr(addr) {}264265uint32_t version() const {266return _addressSpace.get32(_addr +267offsetof(unwind_info_section_header, version));268}269uint32_t commonEncodingsArraySectionOffset() const {270return _addressSpace.get32(_addr +271offsetof(unwind_info_section_header,272commonEncodingsArraySectionOffset));273}274uint32_t commonEncodingsArrayCount() const {275return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,276commonEncodingsArrayCount));277}278uint32_t personalityArraySectionOffset() const {279return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,280personalityArraySectionOffset));281}282uint32_t personalityArrayCount() const {283return _addressSpace.get32(284_addr + offsetof(unwind_info_section_header, personalityArrayCount));285}286uint32_t indexSectionOffset() const {287return _addressSpace.get32(288_addr + offsetof(unwind_info_section_header, indexSectionOffset));289}290uint32_t indexCount() const {291return _addressSpace.get32(292_addr + offsetof(unwind_info_section_header, indexCount));293}294295private:296A &_addressSpace;297typename A::pint_t _addr;298};299300template <typename A> class UnwindSectionIndexArray {301public:302UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr)303: _addressSpace(addressSpace), _addr(addr) {}304305uint32_t functionOffset(uint32_t index) const {306return _addressSpace.get32(307_addr + arrayoffsetof(unwind_info_section_header_index_entry, index,308functionOffset));309}310uint32_t secondLevelPagesSectionOffset(uint32_t index) const {311return _addressSpace.get32(312_addr + arrayoffsetof(unwind_info_section_header_index_entry, index,313secondLevelPagesSectionOffset));314}315uint32_t lsdaIndexArraySectionOffset(uint32_t index) const {316return _addressSpace.get32(317_addr + arrayoffsetof(unwind_info_section_header_index_entry, index,318lsdaIndexArraySectionOffset));319}320321private:322A &_addressSpace;323typename A::pint_t _addr;324};325326template <typename A> class UnwindSectionRegularPageHeader {327public:328UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr)329: _addressSpace(addressSpace), _addr(addr) {}330331uint32_t kind() const {332return _addressSpace.get32(333_addr + offsetof(unwind_info_regular_second_level_page_header, kind));334}335uint16_t entryPageOffset() const {336return _addressSpace.get16(337_addr + offsetof(unwind_info_regular_second_level_page_header,338entryPageOffset));339}340uint16_t entryCount() const {341return _addressSpace.get16(342_addr +343offsetof(unwind_info_regular_second_level_page_header, entryCount));344}345346private:347A &_addressSpace;348typename A::pint_t _addr;349};350351template <typename A> class UnwindSectionRegularArray {352public:353UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr)354: _addressSpace(addressSpace), _addr(addr) {}355356uint32_t functionOffset(uint32_t index) const {357return _addressSpace.get32(358_addr + arrayoffsetof(unwind_info_regular_second_level_entry, index,359functionOffset));360}361uint32_t encoding(uint32_t index) const {362return _addressSpace.get32(363_addr +364arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding));365}366367private:368A &_addressSpace;369typename A::pint_t _addr;370};371372template <typename A> class UnwindSectionCompressedPageHeader {373public:374UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr)375: _addressSpace(addressSpace), _addr(addr) {}376377uint32_t kind() const {378return _addressSpace.get32(379_addr +380offsetof(unwind_info_compressed_second_level_page_header, kind));381}382uint16_t entryPageOffset() const {383return _addressSpace.get16(384_addr + offsetof(unwind_info_compressed_second_level_page_header,385entryPageOffset));386}387uint16_t entryCount() const {388return _addressSpace.get16(389_addr +390offsetof(unwind_info_compressed_second_level_page_header, entryCount));391}392uint16_t encodingsPageOffset() const {393return _addressSpace.get16(394_addr + offsetof(unwind_info_compressed_second_level_page_header,395encodingsPageOffset));396}397uint16_t encodingsCount() const {398return _addressSpace.get16(399_addr + offsetof(unwind_info_compressed_second_level_page_header,400encodingsCount));401}402403private:404A &_addressSpace;405typename A::pint_t _addr;406};407408template <typename A> class UnwindSectionCompressedArray {409public:410UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr)411: _addressSpace(addressSpace), _addr(addr) {}412413uint32_t functionOffset(uint32_t index) const {414return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(415_addressSpace.get32(_addr + index * sizeof(uint32_t)));416}417uint16_t encodingIndex(uint32_t index) const {418return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(419_addressSpace.get32(_addr + index * sizeof(uint32_t)));420}421422private:423A &_addressSpace;424typename A::pint_t _addr;425};426427template <typename A> class UnwindSectionLsdaArray {428public:429UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr)430: _addressSpace(addressSpace), _addr(addr) {}431432uint32_t functionOffset(uint32_t index) const {433return _addressSpace.get32(434_addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,435index, functionOffset));436}437uint32_t lsdaOffset(uint32_t index) const {438return _addressSpace.get32(439_addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,440index, lsdaOffset));441}442443private:444A &_addressSpace;445typename A::pint_t _addr;446};447#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)448449class _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.453void operator delete(void *, size_t) {}454455virtual ~AbstractUnwindCursor() {}456virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }457virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }458virtual void setReg(int, unw_word_t) {459_LIBUNWIND_ABORT("setReg not implemented");460}461virtual bool validFloatReg(int) {462_LIBUNWIND_ABORT("validFloatReg not implemented");463}464virtual unw_fpreg_t getFloatReg(int) {465_LIBUNWIND_ABORT("getFloatReg not implemented");466}467virtual void setFloatReg(int, unw_fpreg_t) {468_LIBUNWIND_ABORT("setFloatReg not implemented");469}470virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); }471virtual void getInfo(unw_proc_info_t *) {472_LIBUNWIND_ABORT("getInfo not implemented");473}474virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }475virtual bool isSignalFrame() {476_LIBUNWIND_ABORT("isSignalFrame not implemented");477}478virtual bool getFunctionName(char *, size_t, unw_word_t *) {479_LIBUNWIND_ABORT("getFunctionName not implemented");480}481virtual void setInfoBasedOnIPRegister(bool = false) {482_LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");483}484virtual const char *getRegisterName(int) {485_LIBUNWIND_ABORT("getRegisterName not implemented");486}487#ifdef __arm__488virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }489#endif490491#ifdef _AIX492virtual uintptr_t getDataRelBase() {493_LIBUNWIND_ABORT("getDataRelBase not implemented");494}495#endif496497#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)498virtual void *get_registers() {499_LIBUNWIND_ABORT("get_registers not implemented");500}501#endif502};503504#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)505506/// \c UnwindCursor contains all state (including all register values) during507/// an unwind. This is normally stack-allocated inside a unw_cursor_t.508template <typename A, typename R>509class UnwindCursor : public AbstractUnwindCursor {510typedef typename A::pint_t pint_t;511public:512UnwindCursor(unw_context_t *context, A &as);513UnwindCursor(CONTEXT *context, A &as);514UnwindCursor(A &as, void *threadArg);515virtual ~UnwindCursor() {}516virtual bool validReg(int);517virtual unw_word_t getReg(int);518virtual void setReg(int, unw_word_t);519virtual bool validFloatReg(int);520virtual unw_fpreg_t getFloatReg(int);521virtual void setFloatReg(int, unw_fpreg_t);522virtual int step(bool = false);523virtual void getInfo(unw_proc_info_t *);524virtual void jumpto();525virtual bool isSignalFrame();526virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);527virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);528virtual const char *getRegisterName(int num);529#ifdef __arm__530virtual void saveVFPAsX();531#endif532533DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }534void setDispatcherContext(DISPATCHER_CONTEXT *disp) {535_dispContext = *disp;536_info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);537if (_dispContext.LanguageHandler) {538_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);539} else540_info.handler = 0;541}542543// libunwind does not and should not depend on C++ library which means that we544// need our own definition of inline placement new.545static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }546547private:548549pint_t getLastPC() const { return _dispContext.ControlPc; }550void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }551RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {552#ifdef __arm__553// Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.554pc &= ~1U;555#endif556// If pc points exactly at the end of the range, we might resolve the557// next function instead. Decrement pc by 1 to fit inside the current558// function.559pc -= 1;560_dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,561&_dispContext.ImageBase,562_dispContext.HistoryTable);563*base = _dispContext.ImageBase;564return _dispContext.FunctionEntry;565}566bool getInfoFromSEH(pint_t pc);567int 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,575NULL);576// Update some fields of the unwind info now, since we have them.577_info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);578if (_dispContext.LanguageHandler) {579_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);580} else581_info.handler = 0;582return UNW_STEP_SUCCESS;583}584585A &_addressSpace;586unw_proc_info_t _info;587DISPATCHER_CONTEXT _dispContext;588CONTEXT _msContext;589UNWIND_HISTORY_TABLE _histTable;590bool _unwindInfoMissing;591};592593594template <typename A, typename R>595UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)596: _addressSpace(as), _unwindInfoMissing(false) {597static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),598"UnwindCursor<> does not fit in unw_cursor_t");599static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),600"UnwindCursor<> requires more alignment than unw_cursor_t");601memset(&_info, 0, sizeof(_info));602memset(&_histTable, 0, sizeof(_histTable));603memset(&_dispContext, 0, sizeof(_dispContext));604_dispContext.ContextRecord = &_msContext;605_dispContext.HistoryTable = &_histTable;606// Initialize MS context from ours.607R r(context);608RtlCaptureContext(&_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);628union {629v128 v;630M128A m;631} t;632t.v = r.getVectorRegister(UNW_X86_64_XMM0);633_msContext.Xmm0 = t.m;634t.v = r.getVectorRegister(UNW_X86_64_XMM1);635_msContext.Xmm1 = t.m;636t.v = r.getVectorRegister(UNW_X86_64_XMM2);637_msContext.Xmm2 = t.m;638t.v = r.getVectorRegister(UNW_X86_64_XMM3);639_msContext.Xmm3 = t.m;640t.v = r.getVectorRegister(UNW_X86_64_XMM4);641_msContext.Xmm4 = t.m;642t.v = r.getVectorRegister(UNW_X86_64_XMM5);643_msContext.Xmm5 = t.m;644t.v = r.getVectorRegister(UNW_X86_64_XMM6);645_msContext.Xmm6 = t.m;646t.v = r.getVectorRegister(UNW_X86_64_XMM7);647_msContext.Xmm7 = t.m;648t.v = r.getVectorRegister(UNW_X86_64_XMM8);649_msContext.Xmm8 = t.m;650t.v = r.getVectorRegister(UNW_X86_64_XMM9);651_msContext.Xmm9 = t.m;652t.v = r.getVectorRegister(UNW_X86_64_XMM10);653_msContext.Xmm10 = t.m;654t.v = r.getVectorRegister(UNW_X86_64_XMM11);655_msContext.Xmm11 = t.m;656t.v = r.getVectorRegister(UNW_X86_64_XMM12);657_msContext.Xmm12 = t.m;658t.v = r.getVectorRegister(UNW_X86_64_XMM13);659_msContext.Xmm13 = t.m;660t.v = r.getVectorRegister(UNW_X86_64_XMM14);661_msContext.Xmm14 = t.m;662t.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);681for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {682union {683uint64_t w;684double d;685} d;686d.d = r.getFloatRegister(i);687_msContext.D[i - UNW_ARM_D0] = d.w;688}689#elif defined(_LIBUNWIND_TARGET_AARCH64)690for (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);694for (int i = UNW_AARCH64_V0; i <= UNW_ARM64_D31; ++i)695_msContext.V[i - UNW_AARCH64_V0].D[0] = r.getFloatRegister(i);696#endif697}698699template <typename A, typename R>700UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)701: _addressSpace(as), _unwindInfoMissing(false) {702static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),703"UnwindCursor<> does not fit in unw_cursor_t");704memset(&_info, 0, sizeof(_info));705memset(&_histTable, 0, sizeof(_histTable));706memset(&_dispContext, 0, sizeof(_dispContext));707_dispContext.ContextRecord = &_msContext;708_dispContext.HistoryTable = &_histTable;709_msContext = *context;710}711712713template <typename A, typename R>714bool UnwindCursor<A, R>::validReg(int regNum) {715if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;716#if defined(_LIBUNWIND_TARGET_X86_64)717if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP) return true;718#elif defined(_LIBUNWIND_TARGET_ARM)719if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) ||720regNum == UNW_ARM_RA_AUTH_CODE)721return true;722#elif defined(_LIBUNWIND_TARGET_AARCH64)723if (regNum >= UNW_AARCH64_X0 && regNum <= UNW_ARM64_X30) return true;724#endif725return false;726}727728template <typename A, typename R>729unw_word_t UnwindCursor<A, R>::getReg(int regNum) {730switch (regNum) {731#if defined(_LIBUNWIND_TARGET_X86_64)732case UNW_X86_64_RIP:733case UNW_REG_IP: return _msContext.Rip;734case UNW_X86_64_RAX: return _msContext.Rax;735case UNW_X86_64_RDX: return _msContext.Rdx;736case UNW_X86_64_RCX: return _msContext.Rcx;737case UNW_X86_64_RBX: return _msContext.Rbx;738case UNW_REG_SP:739case UNW_X86_64_RSP: return _msContext.Rsp;740case UNW_X86_64_RBP: return _msContext.Rbp;741case UNW_X86_64_RSI: return _msContext.Rsi;742case UNW_X86_64_RDI: return _msContext.Rdi;743case UNW_X86_64_R8: return _msContext.R8;744case UNW_X86_64_R9: return _msContext.R9;745case UNW_X86_64_R10: return _msContext.R10;746case UNW_X86_64_R11: return _msContext.R11;747case UNW_X86_64_R12: return _msContext.R12;748case UNW_X86_64_R13: return _msContext.R13;749case UNW_X86_64_R14: return _msContext.R14;750case UNW_X86_64_R15: return _msContext.R15;751#elif defined(_LIBUNWIND_TARGET_ARM)752case UNW_ARM_R0: return _msContext.R0;753case UNW_ARM_R1: return _msContext.R1;754case UNW_ARM_R2: return _msContext.R2;755case UNW_ARM_R3: return _msContext.R3;756case UNW_ARM_R4: return _msContext.R4;757case UNW_ARM_R5: return _msContext.R5;758case UNW_ARM_R6: return _msContext.R6;759case UNW_ARM_R7: return _msContext.R7;760case UNW_ARM_R8: return _msContext.R8;761case UNW_ARM_R9: return _msContext.R9;762case UNW_ARM_R10: return _msContext.R10;763case UNW_ARM_R11: return _msContext.R11;764case UNW_ARM_R12: return _msContext.R12;765case UNW_REG_SP:766case UNW_ARM_SP: return _msContext.Sp;767case UNW_ARM_LR: return _msContext.Lr;768case UNW_REG_IP:769case UNW_ARM_IP: return _msContext.Pc;770#elif defined(_LIBUNWIND_TARGET_AARCH64)771case UNW_REG_SP: return _msContext.Sp;772case UNW_REG_IP: return _msContext.Pc;773default: return _msContext.X[regNum - UNW_AARCH64_X0];774#endif775}776_LIBUNWIND_ABORT("unsupported register");777}778779template <typename A, typename R>780void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {781switch (regNum) {782#if defined(_LIBUNWIND_TARGET_X86_64)783case UNW_X86_64_RIP:784case UNW_REG_IP: _msContext.Rip = value; break;785case UNW_X86_64_RAX: _msContext.Rax = value; break;786case UNW_X86_64_RDX: _msContext.Rdx = value; break;787case UNW_X86_64_RCX: _msContext.Rcx = value; break;788case UNW_X86_64_RBX: _msContext.Rbx = value; break;789case UNW_REG_SP:790case UNW_X86_64_RSP: _msContext.Rsp = value; break;791case UNW_X86_64_RBP: _msContext.Rbp = value; break;792case UNW_X86_64_RSI: _msContext.Rsi = value; break;793case UNW_X86_64_RDI: _msContext.Rdi = value; break;794case UNW_X86_64_R8: _msContext.R8 = value; break;795case UNW_X86_64_R9: _msContext.R9 = value; break;796case UNW_X86_64_R10: _msContext.R10 = value; break;797case UNW_X86_64_R11: _msContext.R11 = value; break;798case UNW_X86_64_R12: _msContext.R12 = value; break;799case UNW_X86_64_R13: _msContext.R13 = value; break;800case UNW_X86_64_R14: _msContext.R14 = value; break;801case UNW_X86_64_R15: _msContext.R15 = value; break;802#elif defined(_LIBUNWIND_TARGET_ARM)803case UNW_ARM_R0: _msContext.R0 = value; break;804case UNW_ARM_R1: _msContext.R1 = value; break;805case UNW_ARM_R2: _msContext.R2 = value; break;806case UNW_ARM_R3: _msContext.R3 = value; break;807case UNW_ARM_R4: _msContext.R4 = value; break;808case UNW_ARM_R5: _msContext.R5 = value; break;809case UNW_ARM_R6: _msContext.R6 = value; break;810case UNW_ARM_R7: _msContext.R7 = value; break;811case UNW_ARM_R8: _msContext.R8 = value; break;812case UNW_ARM_R9: _msContext.R9 = value; break;813case UNW_ARM_R10: _msContext.R10 = value; break;814case UNW_ARM_R11: _msContext.R11 = value; break;815case UNW_ARM_R12: _msContext.R12 = value; break;816case UNW_REG_SP:817case UNW_ARM_SP: _msContext.Sp = value; break;818case UNW_ARM_LR: _msContext.Lr = value; break;819case UNW_REG_IP:820case UNW_ARM_IP: _msContext.Pc = value; break;821#elif defined(_LIBUNWIND_TARGET_AARCH64)822case UNW_REG_SP: _msContext.Sp = value; break;823case UNW_REG_IP: _msContext.Pc = value; break;824case UNW_AARCH64_X0:825case UNW_AARCH64_X1:826case UNW_AARCH64_X2:827case UNW_AARCH64_X3:828case UNW_AARCH64_X4:829case UNW_AARCH64_X5:830case UNW_AARCH64_X6:831case UNW_AARCH64_X7:832case UNW_AARCH64_X8:833case UNW_AARCH64_X9:834case UNW_AARCH64_X10:835case UNW_AARCH64_X11:836case UNW_AARCH64_X12:837case UNW_AARCH64_X13:838case UNW_AARCH64_X14:839case UNW_AARCH64_X15:840case UNW_AARCH64_X16:841case UNW_AARCH64_X17:842case UNW_AARCH64_X18:843case UNW_AARCH64_X19:844case UNW_AARCH64_X20:845case UNW_AARCH64_X21:846case UNW_AARCH64_X22:847case UNW_AARCH64_X23:848case UNW_AARCH64_X24:849case UNW_AARCH64_X25:850case UNW_AARCH64_X26:851case UNW_AARCH64_X27:852case UNW_AARCH64_X28:853case UNW_AARCH64_FP:854case UNW_AARCH64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;855#endif856default:857_LIBUNWIND_ABORT("unsupported register");858}859}860861template <typename A, typename R>862bool UnwindCursor<A, R>::validFloatReg(int regNum) {863#if defined(_LIBUNWIND_TARGET_ARM)864if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;865if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;866#elif defined(_LIBUNWIND_TARGET_AARCH64)867if (regNum >= UNW_AARCH64_V0 && regNum <= UNW_ARM64_D31) return true;868#else869(void)regNum;870#endif871return false;872}873874template <typename A, typename R>875unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {876#if defined(_LIBUNWIND_TARGET_ARM)877if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {878union {879uint32_t w;880float f;881} d;882d.w = _msContext.S[regNum - UNW_ARM_S0];883return d.f;884}885if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {886union {887uint64_t w;888double d;889} d;890d.w = _msContext.D[regNum - UNW_ARM_D0];891return d.d;892}893_LIBUNWIND_ABORT("unsupported float register");894#elif defined(_LIBUNWIND_TARGET_AARCH64)895return _msContext.V[regNum - UNW_AARCH64_V0].D[0];896#else897(void)regNum;898_LIBUNWIND_ABORT("float registers unimplemented");899#endif900}901902template <typename A, typename R>903void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {904#if defined(_LIBUNWIND_TARGET_ARM)905if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {906union {907uint32_t w;908float f;909} d;910d.f = (float)value;911_msContext.S[regNum - UNW_ARM_S0] = d.w;912}913if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {914union {915uint64_t w;916double d;917} d;918d.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#else925(void)regNum;926(void)value;927_LIBUNWIND_ABORT("float registers unimplemented");928#endif929}930931template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {932RtlRestoreContext(&_msContext, nullptr);933}934935#ifdef __arm__936template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}937#endif938939template <typename A, typename R>940const char *UnwindCursor<A, R>::getRegisterName(int regNum) {941return R::getRegisterName(regNum);942}943944template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {945return false;946}947948#else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)949950/// UnwindCursor contains all state (including all register values) during951/// an unwind. This is normally stack allocated inside a unw_cursor_t.952template <typename A, typename R>953class UnwindCursor : public AbstractUnwindCursor{954typedef typename A::pint_t pint_t;955public:956UnwindCursor(unw_context_t *context, A &as);957UnwindCursor(A &as, void *threadArg);958virtual ~UnwindCursor() {}959virtual bool validReg(int);960virtual unw_word_t getReg(int);961virtual void setReg(int, unw_word_t);962virtual bool validFloatReg(int);963virtual unw_fpreg_t getFloatReg(int);964virtual void setFloatReg(int, unw_fpreg_t);965virtual int step(bool stage2 = false);966virtual void getInfo(unw_proc_info_t *);967virtual void jumpto();968virtual bool isSignalFrame();969virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off);970virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false);971virtual const char *getRegisterName(int num);972#ifdef __arm__973virtual void saveVFPAsX();974#endif975976#ifdef _AIX977virtual uintptr_t getDataRelBase();978#endif979980#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)981virtual void *get_registers() { return &_registers; }982#endif983984// libunwind does not and should not depend on C++ library which means that we985// need our own definition of inline placement new.986static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }987988private:989990#if defined(_LIBUNWIND_ARM_EHABI)991bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s);992993int stepWithEHABI() {994size_t len = 0;995size_t off = 0;996// FIXME: Calling decode_eht_entry() here is violating the libunwind997// abstraction layer.998const uint32_t *ehtp =999decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info),1000&off, &len);1001if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) !=1002_URC_CONTINUE_UNWIND)1003return UNW_STEP_END;1004return UNW_STEP_SUCCESS;1005}1006#endif10071008#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)1009bool setInfoForSigReturn() {1010R dummy;1011return setInfoForSigReturn(dummy);1012}1013int stepThroughSigReturn() {1014R dummy;1015return stepThroughSigReturn(dummy);1016}1017bool isReadableAddr(const pint_t addr) const;1018#if defined(_LIBUNWIND_TARGET_AARCH64)1019bool setInfoForSigReturn(Registers_arm64 &);1020int stepThroughSigReturn(Registers_arm64 &);1021#endif1022#if defined(_LIBUNWIND_TARGET_LOONGARCH)1023bool setInfoForSigReturn(Registers_loongarch &);1024int stepThroughSigReturn(Registers_loongarch &);1025#endif1026#if defined(_LIBUNWIND_TARGET_RISCV)1027bool setInfoForSigReturn(Registers_riscv &);1028int stepThroughSigReturn(Registers_riscv &);1029#endif1030#if defined(_LIBUNWIND_TARGET_S390X)1031bool setInfoForSigReturn(Registers_s390x &);1032int stepThroughSigReturn(Registers_s390x &);1033#endif1034template <typename Registers> bool setInfoForSigReturn(Registers &) {1035return false;1036}1037template <typename Registers> int stepThroughSigReturn(Registers &) {1038return UNW_STEP_END;1039}1040#elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)1041bool setInfoForSigReturn();1042int stepThroughSigReturn();1043#endif10441045#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)1046bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,1047const typename CFI_Parser<A>::CIE_Info &cieInfo,1048pint_t pc, uintptr_t dso_base);1049bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s,1050uint32_t fdeSectionOffsetHint=0);1051int stepWithDwarfFDE(bool stage2) {1052return DwarfInstructions<A, R>::stepWithDwarf(1053_addressSpace, (pint_t)this->getReg(UNW_REG_IP),1054(pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2);1055}1056#endif10571058#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)1059bool getInfoFromCompactEncodingSection(pint_t pc,1060const UnwindInfoSections §s);1061int stepWithCompactEncoding(bool stage2 = false) {1062#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)1063if ( compactSaysUseDwarf() )1064return stepWithDwarfFDE(stage2);1065#endif1066R dummy;1067return stepWithCompactEncoding(dummy);1068}10691070#if defined(_LIBUNWIND_TARGET_X86_64)1071int stepWithCompactEncoding(Registers_x86_64 &) {1072return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(1073_info.format, _info.start_ip, _addressSpace, _registers);1074}1075#endif10761077#if defined(_LIBUNWIND_TARGET_I386)1078int stepWithCompactEncoding(Registers_x86 &) {1079return CompactUnwinder_x86<A>::stepWithCompactEncoding(1080_info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);1081}1082#endif10831084#if defined(_LIBUNWIND_TARGET_PPC)1085int stepWithCompactEncoding(Registers_ppc &) {1086return UNW_EINVAL;1087}1088#endif10891090#if defined(_LIBUNWIND_TARGET_PPC64)1091int stepWithCompactEncoding(Registers_ppc64 &) {1092return UNW_EINVAL;1093}1094#endif109510961097#if defined(_LIBUNWIND_TARGET_AARCH64)1098int stepWithCompactEncoding(Registers_arm64 &) {1099return CompactUnwinder_arm64<A>::stepWithCompactEncoding(1100_info.format, _info.start_ip, _addressSpace, _registers);1101}1102#endif11031104#if defined(_LIBUNWIND_TARGET_MIPS_O32)1105int stepWithCompactEncoding(Registers_mips_o32 &) {1106return UNW_EINVAL;1107}1108#endif11091110#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)1111int stepWithCompactEncoding(Registers_mips_newabi &) {1112return UNW_EINVAL;1113}1114#endif11151116#if defined(_LIBUNWIND_TARGET_LOONGARCH)1117int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; }1118#endif11191120#if defined(_LIBUNWIND_TARGET_SPARC)1121int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }1122#endif11231124#if defined(_LIBUNWIND_TARGET_SPARC64)1125int stepWithCompactEncoding(Registers_sparc64 &) { return UNW_EINVAL; }1126#endif11271128#if defined (_LIBUNWIND_TARGET_RISCV)1129int stepWithCompactEncoding(Registers_riscv &) {1130return UNW_EINVAL;1131}1132#endif11331134bool compactSaysUseDwarf(uint32_t *offset=NULL) const {1135R dummy;1136return compactSaysUseDwarf(dummy, offset);1137}11381139#if defined(_LIBUNWIND_TARGET_X86_64)1140bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {1141if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {1142if (offset)1143*offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);1144return true;1145}1146return false;1147}1148#endif11491150#if defined(_LIBUNWIND_TARGET_I386)1151bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {1152if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {1153if (offset)1154*offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);1155return true;1156}1157return false;1158}1159#endif11601161#if defined(_LIBUNWIND_TARGET_PPC)1162bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {1163return true;1164}1165#endif11661167#if defined(_LIBUNWIND_TARGET_PPC64)1168bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {1169return true;1170}1171#endif11721173#if defined(_LIBUNWIND_TARGET_AARCH64)1174bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {1175if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {1176if (offset)1177*offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);1178return true;1179}1180return false;1181}1182#endif11831184#if defined(_LIBUNWIND_TARGET_MIPS_O32)1185bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const {1186return true;1187}1188#endif11891190#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)1191bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {1192return true;1193}1194#endif11951196#if defined(_LIBUNWIND_TARGET_LOONGARCH)1197bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const {1198return true;1199}1200#endif12011202#if defined(_LIBUNWIND_TARGET_SPARC)1203bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }1204#endif12051206#if defined(_LIBUNWIND_TARGET_SPARC64)1207bool compactSaysUseDwarf(Registers_sparc64 &, uint32_t *) const {1208return true;1209}1210#endif12111212#if defined (_LIBUNWIND_TARGET_RISCV)1213bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const {1214return true;1215}1216#endif12171218#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)12191220#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)1221compact_unwind_encoding_t dwarfEncoding() const {1222R dummy;1223return dwarfEncoding(dummy);1224}12251226#if defined(_LIBUNWIND_TARGET_X86_64)1227compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {1228return UNWIND_X86_64_MODE_DWARF;1229}1230#endif12311232#if defined(_LIBUNWIND_TARGET_I386)1233compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {1234return UNWIND_X86_MODE_DWARF;1235}1236#endif12371238#if defined(_LIBUNWIND_TARGET_PPC)1239compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {1240return 0;1241}1242#endif12431244#if defined(_LIBUNWIND_TARGET_PPC64)1245compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {1246return 0;1247}1248#endif12491250#if defined(_LIBUNWIND_TARGET_AARCH64)1251compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {1252return UNWIND_ARM64_MODE_DWARF;1253}1254#endif12551256#if defined(_LIBUNWIND_TARGET_ARM)1257compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const {1258return 0;1259}1260#endif12611262#if defined (_LIBUNWIND_TARGET_OR1K)1263compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {1264return 0;1265}1266#endif12671268#if defined (_LIBUNWIND_TARGET_HEXAGON)1269compact_unwind_encoding_t dwarfEncoding(Registers_hexagon &) const {1270return 0;1271}1272#endif12731274#if defined (_LIBUNWIND_TARGET_MIPS_O32)1275compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const {1276return 0;1277}1278#endif12791280#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)1281compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {1282return 0;1283}1284#endif12851286#if defined(_LIBUNWIND_TARGET_LOONGARCH)1287compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const {1288return 0;1289}1290#endif12911292#if defined(_LIBUNWIND_TARGET_SPARC)1293compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }1294#endif12951296#if defined(_LIBUNWIND_TARGET_SPARC64)1297compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const {1298return 0;1299}1300#endif13011302#if defined (_LIBUNWIND_TARGET_RISCV)1303compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const {1304return 0;1305}1306#endif13071308#if defined (_LIBUNWIND_TARGET_S390X)1309compact_unwind_encoding_t dwarfEncoding(Registers_s390x &) const {1310return 0;1311}1312#endif13131314#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)13151316#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)1317// For runtime environments using SEH unwind data without Windows runtime1318// support.1319pint_t getLastPC() const { /* FIXME: Implement */ return 0; }1320void setLastPC(pint_t pc) { /* FIXME: Implement */ }1321RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {1322/* FIXME: Implement */1323*base = 0;1324return nullptr;1325}1326bool getInfoFromSEH(pint_t pc);1327int stepWithSEHData() { /* FIXME: Implement */ return 0; }1328#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)13291330#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)1331bool getInfoFromTBTable(pint_t pc, R ®isters);1332int stepWithTBTable(pint_t pc, tbtable *TBTable, R ®isters,1333bool &isSignalFrame);1334int stepWithTBTableData() {1335return stepWithTBTable(reinterpret_cast<pint_t>(this->getReg(UNW_REG_IP)),1336reinterpret_cast<tbtable *>(_info.unwind_info),1337_registers, _isSignalFrame);1338}1339#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)13401341A &_addressSpace;1342R _registers;1343unw_proc_info_t _info;1344bool _unwindInfoMissing;1345bool _isSignalFrame;1346#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \1347defined(_LIBUNWIND_TARGET_HAIKU)1348bool _isSigReturn = false;1349#endif1350};135113521353template <typename A, typename R>1354UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)1355: _addressSpace(as), _registers(context), _unwindInfoMissing(false),1356_isSignalFrame(false) {1357static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),1358"UnwindCursor<> does not fit in unw_cursor_t");1359static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),1360"UnwindCursor<> requires more alignment than unw_cursor_t");1361memset(&_info, 0, sizeof(_info));1362}13631364template <typename A, typename R>1365UnwindCursor<A, R>::UnwindCursor(A &as, void *)1366: _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {1367memset(&_info, 0, sizeof(_info));1368// FIXME1369// fill in _registers from thread arg1370}137113721373template <typename A, typename R>1374bool UnwindCursor<A, R>::validReg(int regNum) {1375return _registers.validRegister(regNum);1376}13771378template <typename A, typename R>1379unw_word_t UnwindCursor<A, R>::getReg(int regNum) {1380return _registers.getRegister(regNum);1381}13821383template <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}13871388template <typename A, typename R>1389bool UnwindCursor<A, R>::validFloatReg(int regNum) {1390return _registers.validFloatRegister(regNum);1391}13921393template <typename A, typename R>1394unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {1395return _registers.getFloatRegister(regNum);1396}13971398template <typename A, typename R>1399void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {1400_registers.setFloatRegister(regNum, value);1401}14021403template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {1404_registers.jumpto();1405}14061407#ifdef __arm__1408template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {1409_registers.saveVFPAsX();1410}1411#endif14121413#ifdef _AIX1414template <typename A, typename R>1415uintptr_t UnwindCursor<A, R>::getDataRelBase() {1416return reinterpret_cast<uintptr_t>(_info.extra);1417}1418#endif14191420template <typename A, typename R>1421const char *UnwindCursor<A, R>::getRegisterName(int regNum) {1422return _registers.getRegisterName(regNum);1423}14241425template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {1426return _isSignalFrame;1427}14281429#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)14301431#if defined(_LIBUNWIND_ARM_EHABI)1432template<typename A>1433struct EHABISectionIterator {1434typedef EHABISectionIterator _Self;14351436typedef typename A::pint_t value_type;1437typedef typename A::pint_t* pointer;1438typedef typename A::pint_t& reference;1439typedef size_t size_type;1440typedef size_t difference_type;14411442static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {1443return _Self(addressSpace, sects, 0);1444}1445static _Self end(A& addressSpace, const UnwindInfoSections& sects) {1446return _Self(addressSpace, sects,1447sects.arm_section_length / sizeof(EHABIIndexEntry));1448}14491450EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)1451: _i(i), _addressSpace(&addressSpace), _sects(§s) {}14521453_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; }14571458_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; }14601461size_t operator-(const _Self& other) const { return _i - other._i; }14621463bool operator==(const _Self& other) const {1464assert(_addressSpace == other._addressSpace);1465assert(_sects == other._sects);1466return _i == other._i;1467}14681469bool operator!=(const _Self& other) const {1470assert(_addressSpace == other._addressSpace);1471assert(_sects == other._sects);1472return _i != other._i;1473}14741475typename A::pint_t operator*() const { return functionAddress(); }14761477typename A::pint_t functionAddress() const {1478typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(1479EHABIIndexEntry, _i, functionOffset);1480return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));1481}14821483typename A::pint_t dataAddress() {1484typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(1485EHABIIndexEntry, _i, data);1486return indexAddr;1487}14881489private:1490size_t _i;1491A* _addressSpace;1492const UnwindInfoSections* _sects;1493};14941495namespace {14961497template <typename A>1498EHABISectionIterator<A> EHABISectionUpperBound(1499EHABISectionIterator<A> first,1500EHABISectionIterator<A> last,1501typename A::pint_t value) {1502size_t len = last - first;1503while (len > 0) {1504size_t l2 = len / 2;1505EHABISectionIterator<A> m = first + l2;1506if (value < *m) {1507len = l2;1508} else {1509first = ++m;1510len -= l2 + 1;1511}1512}1513return first;1514}15151516}15171518template <typename A, typename R>1519bool UnwindCursor<A, R>::getInfoFromEHABISection(1520pint_t pc,1521const UnwindInfoSections §s) {1522EHABISectionIterator<A> begin =1523EHABISectionIterator<A>::begin(_addressSpace, sects);1524EHABISectionIterator<A> end =1525EHABISectionIterator<A>::end(_addressSpace, sects);1526if (begin == end)1527return false;15281529EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc);1530if (itNextPC == begin)1531return false;1532EHABISectionIterator<A> itThisPC = itNextPC - 1;15331534pint_t thisPC = itThisPC.functionAddress();1535// If an exception is thrown from a function, corresponding to the last entry1536// in the table, we don't really know the function extent and have to choose a1537// value for nextPC. Choosing max() will allow the range check during trace to1538// succeed.1539pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress();1540pint_t indexDataAddr = itThisPC.dataAddress();15411542if (indexDataAddr == 0)1543return false;15441545uint32_t indexData = _addressSpace.get32(indexDataAddr);1546if (indexData == UNW_EXIDX_CANTUNWIND)1547return false;15481549// If the high bit is set, the exception handling table entry is inline inside1550// the index table entry on the second word (aka |indexDataAddr|). Otherwise,1551// the table points at an offset in the exception handling table (section 51552// EHABI).1553pint_t exceptionTableAddr;1554uint32_t exceptionTableData;1555bool isSingleWordEHT;1556if (indexData & 0x80000000) {1557exceptionTableAddr = indexDataAddr;1558// TODO(ajwong): Should this data be 0?1559exceptionTableData = indexData;1560isSingleWordEHT = true;1561} else {1562exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);1563exceptionTableData = _addressSpace.get32(exceptionTableAddr);1564isSingleWordEHT = false;1565}15661567// 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.1571unw_word_t personalityRoutine = 0xbadf00d;1572bool scope32 = false;1573uintptr_t lsda;15741575// If the high bit in the exception handling table entry is set, the entry is1576// in compact form (section 6.3 EHABI).1577if (exceptionTableData & 0x80000000) {1578// Grab the index of the personality routine from the compact form.1579uint32_t choice = (exceptionTableData & 0x0f000000) >> 24;1580uint32_t extraWords = 0;1581switch (choice) {1582case 0:1583personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;1584extraWords = 0;1585scope32 = false;1586lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4);1587break;1588case 1:1589personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;1590extraWords = (exceptionTableData & 0x00ff0000) >> 16;1591scope32 = false;1592lsda = exceptionTableAddr + (extraWords + 1) * 4;1593break;1594case 2:1595personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;1596extraWords = (exceptionTableData & 0x00ff0000) >> 16;1597scope32 = true;1598lsda = exceptionTableAddr + (extraWords + 1) * 4;1599break;1600default:1601_LIBUNWIND_ABORT("unknown personality routine");1602return false;1603}16041605if (isSingleWordEHT) {1606if (extraWords != 0) {1607_LIBUNWIND_ABORT("index inlined table detected but pr function "1608"requires extra words");1609return false;1610}1611}1612} else {1613pint_t personalityAddr =1614exceptionTableAddr + signExtendPrel31(exceptionTableData);1615personalityRoutine = personalityAddr;16161617// ARM EHABI # 6.2, # 9.21618//1619// +---- ehtp1620// v1621// +--------------------------------------+1622// | +--------+--------+--------+-------+ |1623// | |0| prel31 to personalityRoutine | |1624// | +--------+--------+--------+-------+ |1625// | | N | unwind opcodes | | <-- UnwindData1626// | +--------+--------+--------+-------+ |1627// | | Word 2 unwind opcodes | |1628// | +--------+--------+--------+-------+ |1629// | ... |1630// | +--------+--------+--------+-------+ |1631// | | Word N unwind opcodes | |1632// | +--------+--------+--------+-------+ |1633// | | LSDA | | <-- lsda1634// | | ... | |1635// | +--------+--------+--------+-------+ |1636// +--------------------------------------+16371638uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;1639uint32_t FirstDataWord = *UnwindData;1640size_t N = ((FirstDataWord >> 24) & 0xff);1641size_t NDataWords = N + 1;1642lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);1643}16441645_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?16521653return true;1654}1655#endif16561657#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)1658template <typename A, typename R>1659bool UnwindCursor<A, R>::getInfoFromFdeCie(1660const typename CFI_Parser<A>::FDE_Info &fdeInfo,1661const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc,1662uintptr_t dso_base) {1663typename CFI_Parser<A>::PrologInfo prolog;1664if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,1665R::getArch(), &prolog)) {1666// Save off parsed FDE info1667_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, so1672// 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);1679return true;1680}1681return false;1682}16831684template <typename A, typename R>1685bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,1686const UnwindInfoSections §s,1687uint32_t fdeSectionOffsetHint) {1688typename CFI_Parser<A>::FDE_Info fdeInfo;1689typename CFI_Parser<A>::CIE_Info cieInfo;1690bool foundFDE = false;1691bool foundInCache = false;1692// If compact encoding table gave offset into dwarf section, go directly there1693if (fdeSectionOffsetHint != 0) {1694foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,1695sects.dwarf_section_length,1696sects.dwarf_section + fdeSectionOffsetHint,1697&fdeInfo, &cieInfo);1698}1699#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)1700if (!foundFDE && (sects.dwarf_index_section != 0)) {1701foundFDE = EHHeaderParser<A>::findFDE(1702_addressSpace, pc, sects.dwarf_index_section,1703(uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);1704}1705#endif1706if (!foundFDE) {1707// otherwise, search cache of previously found FDEs.1708pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);1709if (cachedFDE != 0) {1710foundFDE =1711CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,1712sects.dwarf_section_length,1713cachedFDE, &fdeInfo, &cieInfo);1714foundInCache = foundFDE;1715}1716}1717if (!foundFDE) {1718// Still not found, do full scan of __eh_frame section.1719foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,1720sects.dwarf_section_length, 0,1721&fdeInfo, &cieInfo);1722}1723if (foundFDE) {1724if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) {1725// Add to cache (to make next lookup faster) if we had no hint1726// and there was no index.1727if (!foundInCache && (fdeSectionOffsetHint == 0)) {1728#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)1729if (sects.dwarf_index_section == 0)1730#endif1731DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,1732fdeInfo.fdeStart);1733}1734return true;1735}1736}1737//_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);1738return false;1739}1740#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)174117421743#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)1744template <typename A, typename R>1745bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,1746const UnwindInfoSections §s) {1747const bool log = false;1748if (log)1749fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",1750(uint64_t)pc, (uint64_t)sects.dso_base);17511752const UnwindSectionHeader<A> sectionHeader(_addressSpace,1753sects.compact_unwind_section);1754if (sectionHeader.version() != UNWIND_SECTION_VERSION)1755return false;17561757// do a binary search of top level index to find page with unwind info1758pint_t targetFunctionOffset = pc - sects.dso_base;1759const UnwindSectionIndexArray<A> topIndex(_addressSpace,1760sects.compact_unwind_section1761+ sectionHeader.indexSectionOffset());1762uint32_t low = 0;1763uint32_t high = sectionHeader.indexCount();1764uint32_t last = high - 1;1765while (low < high) {1766uint32_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));1769if (topIndex.functionOffset(mid) <= targetFunctionOffset) {1770if ((mid == last) ||1771(topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {1772low = mid;1773break;1774} else {1775low = mid + 1;1776}1777} else {1778high = mid;1779}1780}1781const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);1782const uint32_t firstLevelNextPageFunctionOffset =1783topIndex.functionOffset(low + 1);1784const pint_t secondLevelAddr =1785sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);1786const pint_t lsdaArrayStartAddr =1787sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);1788const pint_t lsdaArrayEndAddr =1789sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);1790if (log)1791fprintf(stderr, "\tfirst level search for result index=%d "1792"to secondLevelAddr=0x%llX\n",1793low, (uint64_t) secondLevelAddr);1794// do a binary search of second level page index1795uint32_t encoding = 0;1796pint_t funcStart = 0;1797pint_t funcEnd = 0;1798pint_t lsda = 0;1799pint_t personality = 0;1800uint32_t pageKind = _addressSpace.get32(secondLevelAddr);1801if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {1802// regular page1803UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,1804secondLevelAddr);1805UnwindSectionRegularArray<A> pageIndex(1806_addressSpace, secondLevelAddr + pageHeader.entryPageOffset());1807// binary search looks for entry with e where index[e].offset <= pc <1808// index[e+1].offset1809if (log)1810fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "1811"regular page starting at secondLevelAddr=0x%llX\n",1812(uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);1813low = 0;1814high = pageHeader.entryCount();1815while (low < high) {1816uint32_t mid = (low + high) / 2;1817if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {1818if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {1819// at end of table1820low = mid;1821funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;1822break;1823} else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {1824// next is too big, so we found it1825low = mid;1826funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;1827break;1828} else {1829low = mid + 1;1830}1831} else {1832high = mid;1833}1834}1835encoding = pageIndex.encoding(low);1836funcStart = pageIndex.functionOffset(low) + sects.dso_base;1837if (pc < funcStart) {1838if (log)1839fprintf(1840stderr,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);1843return false;1844}1845if (pc > funcEnd) {1846if (log)1847fprintf(1848stderr,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);1851return false;1852}1853} else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {1854// compressed page1855UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,1856secondLevelAddr);1857UnwindSectionCompressedArray<A> pageIndex(1858_addressSpace, secondLevelAddr + pageHeader.entryPageOffset());1859const 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].offset1863if (log)1864fprintf(stderr, "\tbinary search of compressed page starting at "1865"secondLevelAddr=0x%llX\n",1866(uint64_t) secondLevelAddr);1867low = 0;1868last = pageHeader.entryCount() - 1;1869high = pageHeader.entryCount();1870while (low < high) {1871uint32_t mid = (low + high) / 2;1872if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {1873if ((mid == last) ||1874(pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {1875low = mid;1876break;1877} else {1878low = mid + 1;1879}1880} else {1881high = mid;1882}1883}1884funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset1885+ sects.dso_base;1886if (low < last)1887funcEnd =1888pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset1889+ sects.dso_base;1890else1891funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;1892if (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);1897return false;1898}1899if (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);1904return false;1905}1906uint16_t encodingIndex = pageIndex.encodingIndex(low);1907if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) {1908// encoding is in common table in section header1909encoding = _addressSpace.get32(1910sects.compact_unwind_section +1911sectionHeader.commonEncodingsArraySectionOffset() +1912encodingIndex * sizeof(uint32_t));1913} else {1914// encoding is in page specific table1915uint16_t pageEncodingIndex =1916encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount();1917encoding = _addressSpace.get32(secondLevelAddr +1918pageHeader.encodingsPageOffset() +1919pageEncodingIndex * 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);1925return false;1926}19271928// look up LSDA, if encoding says function has one1929if (encoding & UNWIND_HAS_LSDA) {1930UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);1931uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);1932low = 0;1933high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /1934sizeof(unwind_info_section_header_lsda_index_entry);1935// binary search looks for entry with exact match for functionOffset1936if (log)1937fprintf(stderr,1938"\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",1939funcStartOffset);1940while (low < high) {1941uint32_t mid = (low + high) / 2;1942if (lsdaIndex.functionOffset(mid) == funcStartOffset) {1943lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;1944break;1945} else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {1946low = mid + 1;1947} else {1948high = mid;1949}1950}1951if (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",1954encoding, (uint64_t) pc);1955return false;1956}1957}19581959// extract personality routine, if encoding says function has one1960uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>1961(__builtin_ctz(UNWIND_PERSONALITY_MASK));1962if (personalityIndex != 0) {1963--personalityIndex; // change 1-based to zero-based index1964if (personalityIndex >= sectionHeader.personalityArrayCount()) {1965_LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, "1966"but personality table has only %d entries",1967encoding, personalityIndex,1968sectionHeader.personalityArrayCount());1969return false;1970}1971int32_t personalityDelta = (int32_t)_addressSpace.get32(1972sects.compact_unwind_section +1973sectionHeader.personalityArraySectionOffset() +1974personalityIndex * sizeof(uint32_t));1975pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;1976personality = _addressSpace.getP(personalityPointer);1977if (log)1978fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "1979"personalityDelta=0x%08X, personality=0x%08llX\n",1980(uint64_t) pc, personalityDelta, (uint64_t) personality);1981}19821983if (log)1984fprintf(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;1997return true;1998}1999#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)200020012002#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)2003template <typename A, typename R>2004bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {2005pint_t base;2006RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);2007if (!unwindEntry) {2008_LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);2009return 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_642019_info.end_ip = base + unwindEntry->EndAddress;2020// Only fill in the handler and LSDA if they're stale.2021if (pc != getLastPC()) {2022UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);2023if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {2024// The personality is given in the UNWIND_INFO itself. The LSDA immediately2025// follows the UNWIND_INFO. (This follows how both Clang and MSVC emit2026// these structures.)2027// N.B. UNWIND_INFO structs are DWORD-aligned.2028uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;2029const 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 =2033reinterpret_cast<EXCEPTION_ROUTINE *>(base + *handler);2034if (*handler) {2035_info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);2036} else2037_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)20442045#if defined(_LIBUNWIND_TARGET_AARCH64)2046#define FUNC_LENGTH_UNIT 42047#define XDATA_TYPE IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA2048#else2049#define FUNC_LENGTH_UNIT 22050#define XDATA_TYPE UNWIND_INFO_ARM2051#endif2052if (unwindEntry->Flag != 0) { // Packed unwind info2053_info.end_ip =2054_info.start_ip + unwindEntry->FunctionLength * FUNC_LENGTH_UNIT;2055// Only fill in the handler and LSDA if they're stale.2056if (pc != getLastPC()) {2057// Packed unwind info doesn't have an exception handler.2058_info.lsda = 0;2059_info.handler = 0;2060}2061} else {2062XDATA_TYPE *xdata =2063reinterpret_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.2066if (pc != getLastPC()) {2067if (xdata->ExceptionDataPresent) {2068uint32_t offset = 1; // The main xdata2069uint32_t codeWords = xdata->CodeWords;2070uint32_t epilogScopes = xdata->EpilogCount;2071if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) {2072// The extension word has got the same layout for both ARM and ARM642073uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];2074codeWords = (extensionWord >> 16) & 0xff;2075epilogScopes = extensionWord & 0xffff;2076offset++;2077}2078if (!xdata->EpilogInHeader)2079offset += epilogScopes;2080offset += codeWords;2081uint32_t *exceptionHandlerInfo =2082reinterpret_cast<uint32_t *>(xdata) + offset;2083_dispContext.HandlerData = &exceptionHandlerInfo[1];2084_dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>(2085base + exceptionHandlerInfo[0]);2086_info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);2087if (exceptionHandlerInfo[0])2088_info.handler =2089reinterpret_cast<unw_word_t>(__libunwind_seh_personality);2090else2091_info.handler = 0;2092} else {2093_info.lsda = 0;2094_info.handler = 0;2095}2096}2097}2098#endif2099setLastPC(pc);2100return true;2101}2102#endif21032104#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)2105// Masks for traceback table field xtbtable.2106enum xTBTableMask : uint8_t {2107reservedBit = 0x02, // The traceback table was incorrectly generated if set2108// (see comments in function getInfoFromTBTable().2109ehInfoBit = 0x08 // Exception handling info is present if set2110};21112112enum frameType : unw_word_t {2113frameWithXLEHStateTable = 0,2114frameWithEHInfo = 12115};21162117extern "C" {2118typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,2119uint64_t,2120_Unwind_Exception *,2121struct _Unwind_Context *);2122}21232124static __xlcxx_personality_v0_t *xlcPersonalityV0;2125static RWMutex xlcPersonalityV0InitLock;21262127template <typename A, typename R>2128bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R ®isters) {2129uint32_t *p = reinterpret_cast<uint32_t *>(pc);21302131// Keep looking forward until a word of 0 is found. The traceback2132// table starts at the following word.2133while (*p)2134++p;2135tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);21362137if (_LIBUNWIND_TRACING_UNWINDING) {2138char functionBuf[512];2139const char *functionName = functionBuf;2140unw_word_t offset;2141if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {2142functionName = ".anonymous.";2143}2144_LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",2145__func__, functionName,2146reinterpret_cast<void *>(TBTable));2147}21482149// If the traceback table does not contain necessary info, bypass this frame.2150if (!TBTable->tb.has_tboff)2151return false;21522153// Structure tbtable_ext contains important data we are looking for.2154p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);21552156// Skip field parminfo if it exists.2157if (TBTable->tb.fixedparms || TBTable->tb.floatparms)2158++p;21592160// p now points to tb_offset, the offset from start of function to TB table.2161unw_word_t start_ip =2162reinterpret_cast<unw_word_t>(TBTable) - *p - sizeof(uint32_t);2163unw_word_t end_ip = reinterpret_cast<unw_word_t>(TBTable);2164++p;21652166_LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",2167reinterpret_cast<void *>(start_ip),2168reinterpret_cast<void *>(end_ip));21692170// Skip field hand_mask if it exists.2171if (TBTable->tb.int_hndl)2172++p;21732174unw_word_t lsda = 0;2175unw_word_t handler = 0;2176unw_word_t flags = frameType::frameWithXLEHStateTable;21772178if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl) {2179// State table info is available. The ctl_info field indicates the2180// number of CTL anchors. There should be only one entry for the C++2181// state table.2182assert(*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.2185pint_t stateTableOffset = *p++;21862187int framePointerReg;21882189// Skip fields name_len and name if exist.2190if (TBTable->tb.name_present) {2191const uint16_t name_len = *(reinterpret_cast<uint16_t *>(p));2192p = reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p) + name_len +2193sizeof(uint16_t));2194}21952196if (TBTable->tb.uses_alloca)2197framePointerReg = *(reinterpret_cast<char *>(p));2198else2199framePointerReg = 1; // default frame pointer == SP22002201_LIBUNWIND_TRACE_UNWINDING(2202"framePointerReg=%d, framePointer=%p, "2203"stateTableOffset=%#lx\n",2204framePointerReg,2205reinterpret_cast<void *>(_registers.getRegister(framePointerReg)),2206stateTableOffset);2207lsda = _registers.getRegister(framePointerReg) + stateTableOffset;22082209// Since the traceback table generated by the legacy XLC++ does not2210// provide the location of the personality for the state table,2211// function __xlcxx_personality_v0(), which is the personality for the state2212// table and is exported from libc++abi, is directly assigned as the2213// handler here. When a legacy XLC++ frame is encountered, the symbol2214// is resolved dynamically using dlopen() to avoid a hard dependency of2215// libunwind on libc++abi in cases such as non-C++ applications.22162217// Resolve the function pointer to the state table personality if it has2218// not already been done.2219if (xlcPersonalityV0 == NULL) {2220xlcPersonalityV0InitLock.lock();2221if (xlcPersonalityV0 == NULL) {2222// Resolve __xlcxx_personality_v0 using dlopen().2223const char *libcxxabi = "libc++abi.a(libc++abi.so.1)";2224void *libHandle;2225// The AIX dlopen() sets errno to 0 when it is successful, which2226// clobbers the value of errno from the user code. This is an AIX2227// bug because according to POSIX it should not set errno to 0. To2228// workaround before AIX fixes the bug, errno is saved and restored.2229int saveErrno = errno;2230libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);2231if (libHandle == NULL) {2232_LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno);2233assert(0 && "dlopen() failed");2234}2235xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(2236dlsym(libHandle, "__xlcxx_personality_v0"));2237if (xlcPersonalityV0 == NULL) {2238_LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);2239dlclose(libHandle);2240assert(0 && "dlsym() failed");2241}2242errno = saveErrno;2243}2244xlcPersonalityV0InitLock.unlock();2245}2246handler = reinterpret_cast<unw_word_t>(xlcPersonalityV0);2247_LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",2248reinterpret_cast<void *>(lsda),2249reinterpret_cast<void *>(handler));2250} else if (TBTable->tb.longtbtable) {2251// This frame has the traceback table extension. Possible cases are2252// 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that2253// is not EH aware; or, 3) a frame of other languages. We need to figure out2254// if the traceback table extension contains the 'eh_info' structure.2255//2256// We also need to deal with the complexity arising from some XL compiler2257// versions use the wrong ordering of 'longtbtable' and 'has_vec' bits2258// where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice2259// 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 of2263// 'struct tbtable_ext'. It is not really a structure but a dummy to2264// 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 data2274// following 'alloca_reg' can be treated either as 'struct vec_ext' or2275// 'unsigned char xtbtable'. 'xtbtable' bits are defined in2276// </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently2277// unused and should not be set. 'struct vec_ext' is defined in2278// </usr/include/sys/debug.h> as follows:2279//2280// struct vec_ext {2281// unsigned vr_saved:6; /* Number of non-volatile vector regs saved2282// */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 it2291// is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',2292// we checks if the 7th bit is set or not because 'xtbtable' should2293// never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved2294// in the future to make sure the mitigation works. This mitigation2295// is not 100% bullet proof because 'struct vec_ext' may not always have2296// 'saves_vrsave' bit set.2297//2298// 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for2299// checking the 7th bit.23002301// p points to field name len.2302uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);23032304// Skip fields name_len and name if they exist.2305if (TBTable->tb.name_present) {2306const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));2307charPtr = charPtr + name_len + sizeof(uint16_t);2308}23092310// Skip field alloc_reg if it exists.2311if (TBTable->tb.uses_alloca)2312++charPtr;23132314// Check traceback table bit has_vec. Skip struct vec_ext if it exists.2315if (TBTable->tb.has_vec)2316// Note struct vec_ext does exist at this point because whether the2317// ordering of longtbtable and has_vec bits is correct or not, both2318// are set.2319charPtr += sizeof(struct vec_ext);23202321// charPtr points to field 'xtbtable'. Check if the EH info is available.2322// Also check if the reserved bit of the extended traceback table field2323// 'xtbtable' is set. If it is, the traceback table was incorrectly2324// 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 the2326// frame.2327if ((*charPtr & xTBTableMask::ehInfoBit) &&2328!(*charPtr & xTBTableMask::reservedBit)) {2329// Mark this frame has the new EH info.2330flags = frameType::frameWithEHInfo;23312332// eh_info is available.2333charPtr++;2334// The pointer is 4-byte aligned.2335if (reinterpret_cast<uintptr_t>(charPtr) % 4)2336charPtr += 4 - reinterpret_cast<uintptr_t>(charPtr) % 4;2337uintptr_t *ehInfo =2338reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(2339registers.getRegister(2) +2340*(reinterpret_cast<uintptr_t *>(charPtr)))));23412342// ehInfo points to structure en_info. The first member is version.2343// Only version 0 is currently supported.2344assert(*(reinterpret_cast<uint32_t *>(ehInfo)) == 0 &&2345"libunwind: ehInfo version other than 0 is not supported");23462347// Increment ehInfo to point to member lsda.2348++ehInfo;2349lsda = *ehInfo++;23502351// enInfo now points to member personality.2352handler = *ehInfo;23532354_LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",2355lsda, handler);2356}2357}23582359_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);23692370return true;2371}23722373// 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,2376R ®isters, bool &isSignalFrame) {2377if (_LIBUNWIND_TRACING_UNWINDING) {2378char functionBuf[512];2379const char *functionName = functionBuf;2380unw_word_t offset;2381if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {2382functionName = ".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),2388reinterpret_cast<void *>(pc),2389reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr,2390TBTable->tb.stores_bc);2391}23922393#if defined(__powerpc64__)2394// Instruction to reload TOC register "ld r2,40(r1)"2395const uint32_t loadTOCRegInst = 0xe8410028;2396const int32_t unwPPCF0Index = UNW_PPC64_F0;2397const int32_t unwPPCV0Index = UNW_PPC64_V0;2398#else2399// Instruction to reload TOC register "lwz r2,20(r1)"2400const uint32_t loadTOCRegInst = 0x80410014;2401const int32_t unwPPCF0Index = UNW_PPC_F0;2402const int32_t unwPPCV0Index = UNW_PPC_V0;2403#endif24042405// lastStack points to the stack frame of the next routine up.2406pint_t curStack = static_cast<pint_t>(registers.getSP());2407pint_t lastStack = *reinterpret_cast<pint_t *>(curStack);24082409if (lastStack == 0)2410return UNW_STEP_END;24112412R newRegisters = registers;24132414// If backchain is not stored, use the current stack frame.2415if (!TBTable->tb.stores_bc)2416lastStack = curStack;24172418// Return address is the address after call site instruction.2419pint_t returnAddress;24202421if (isSignalFrame) {2422_LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",2423reinterpret_cast<void *>(lastStack));24242425sigcontext *sigContext = reinterpret_cast<sigcontext *>(2426reinterpret_cast<char *>(lastStack) + STKMINALIGN);2427returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;24282429bool useSTKMIN = false;2430if (returnAddress < 0x10000000) {2431// Try again using STKMIN.2432sigContext = reinterpret_cast<sigcontext *>(2433reinterpret_cast<char *>(lastStack) + STKMIN);2434returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;2435if (returnAddress < 0x10000000) {2436_LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",2437reinterpret_cast<void *>(returnAddress),2438reinterpret_cast<void *>(sigContext));2439return UNW_EBADFRAME;2440}2441useSTKMIN = true;2442}2443_LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "2444"sigContext=%p, returnAddress=%p. "2445"Seems to be a valid address",2446useSTKMIN ? "STKMIN" : "STKMINALIGN",2447reinterpret_cast<void *>(sigContext),2448reinterpret_cast<void *>(returnAddress));24492450// Restore the condition register from sigcontext.2451newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);24522453// Save the LR in sigcontext for stepping up when the function that2454// raised the signal is a leaf function. This LR has the return address2455// to the caller of the leaf function.2456newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr);2457_LIBUNWIND_TRACE_UNWINDING(2458"Save LR=%p from sigcontext",2459reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr));24602461// Restore GPRs from sigcontext.2462for (int i = 0; i < 32; ++i)2463newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);24642465// Restore FPRs from sigcontext.2466for (int i = 0; i < 32; ++i)2467newRegisters.setFloatRegister(i + unwPPCF0Index,2468sigContext->sc_jmpbuf.jmp_context.fpr[i]);24692470// Restore vector registers if there is an associated extended context2471// structure.2472if (sigContext->sc_jmpbuf.jmp_context.msr & __EXTCTX) {2473ucontext_t *uContext = reinterpret_cast<ucontext_t *>(sigContext);2474if (uContext->__extctx->__extctx_magic == __EXTCTX_MAGIC) {2475for (int i = 0; i < 32; ++i)2476newRegisters.setVectorRegister(2477i + unwPPCV0Index, *(reinterpret_cast<v128 *>(2478&(uContext->__extctx->__vmx.__vr[i]))));2479}2480}2481} else {2482// Step up a normal frame.24832484if (!TBTable->tb.saves_lr && registers.getLR()) {2485// This case should only occur if we were called from a signal handler2486// and the signal occurred in a function that doesn't save the LR.2487returnAddress = static_cast<pint_t>(registers.getLR());2488_LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",2489reinterpret_cast<void *>(returnAddress));2490} else {2491// Otherwise, use the LR value in the stack link area.2492returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];2493}24942495// Reset LR in the current context.2496newRegisters.setLR(static_cast<uintptr_t>(NULL));24972498_LIBUNWIND_TRACE_UNWINDING(2499"Extract info from lastStack=%p, returnAddress=%p",2500reinterpret_cast<void *>(lastStack),2501reinterpret_cast<void *>(returnAddress));2502_LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",2503TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,2504TBTable->tb.saves_cr);25052506// Restore FP registers.2507char *ptrToRegs = reinterpret_cast<char *>(lastStack);2508double *FPRegs = reinterpret_cast<double *>(2509ptrToRegs - (TBTable->tb.fpr_saved * sizeof(double)));2510for (int i = 0; i < TBTable->tb.fpr_saved; ++i)2511newRegisters.setFloatRegister(251232 - TBTable->tb.fpr_saved + i + unwPPCF0Index, FPRegs[i]);25132514// Restore GP registers.2515ptrToRegs = reinterpret_cast<char *>(FPRegs);2516uintptr_t *GPRegs = reinterpret_cast<uintptr_t *>(2517ptrToRegs - (TBTable->tb.gpr_saved * sizeof(uintptr_t)));2518for (int i = 0; i < TBTable->tb.gpr_saved; ++i)2519newRegisters.setRegister(32 - TBTable->tb.gpr_saved + i, GPRegs[i]);25202521// Restore Vector registers.2522ptrToRegs = reinterpret_cast<char *>(GPRegs);25232524// Restore vector registers only if this is a Clang frame. Also2525// check if traceback table bit has_vec is set. If it is, structure2526// vec_ext is available.2527if (_info.flags == frameType::frameWithEHInfo && TBTable->tb.has_vec) {25282529// Get to the vec_ext structure to check if vector registers are saved.2530uint32_t *p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);25312532// Skip field parminfo if exists.2533if (TBTable->tb.fixedparms || TBTable->tb.floatparms)2534++p;25352536// Skip field tb_offset if exists.2537if (TBTable->tb.has_tboff)2538++p;25392540// Skip field hand_mask if exists.2541if (TBTable->tb.int_hndl)2542++p;25432544// Skip fields ctl_info and ctl_info_disp if exist.2545if (TBTable->tb.has_ctl) {2546// Skip field ctl_info.2547++p;2548// Skip field ctl_info_disp.2549++p;2550}25512552// Skip fields name_len and name if exist.2553// p is supposed to point to field name_len now.2554uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);2555if (TBTable->tb.name_present) {2556const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));2557charPtr = charPtr + name_len + sizeof(uint16_t);2558}25592560// Skip field alloc_reg if it exists.2561if (TBTable->tb.uses_alloca)2562++charPtr;25632564struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);25652566_LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved);25672568// Restore vector register(s) if saved on the stack.2569if (vec_ext->vr_saved) {2570// Saved vector registers are 16-byte aligned.2571if (reinterpret_cast<uintptr_t>(ptrToRegs) % 16)2572ptrToRegs -= reinterpret_cast<uintptr_t>(ptrToRegs) % 16;2573v128 *VecRegs = reinterpret_cast<v128 *>(ptrToRegs - vec_ext->vr_saved *2574sizeof(v128));2575for (int i = 0; i < vec_ext->vr_saved; ++i) {2576newRegisters.setVectorRegister(257732 - vec_ext->vr_saved + i + unwPPCV0Index, VecRegs[i]);2578}2579}2580}2581if (TBTable->tb.saves_cr) {2582// Get the saved condition register. The condition register is only2583// a single word.2584newRegisters.setCR(2585*(reinterpret_cast<uint32_t *>(lastStack + sizeof(uintptr_t))));2586}25872588// Restore the SP.2589newRegisters.setSP(lastStack);25902591// The first instruction after return.2592uint32_t firstInstruction = *(reinterpret_cast<uint32_t *>(returnAddress));25932594// Do we need to set the TOC register?2595_LIBUNWIND_TRACE_UNWINDING(2596"Current gpr2=%p",2597reinterpret_cast<void *>(newRegisters.getRegister(2)));2598if (firstInstruction == loadTOCRegInst) {2599_LIBUNWIND_TRACE_UNWINDING(2600"Set gpr2=%p from frame",2601reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));2602newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);2603}2604}2605_LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",2606reinterpret_cast<void *>(lastStack),2607reinterpret_cast<void *>(returnAddress),2608reinterpret_cast<void *>(pc));26092610// The return address is the address after call site instruction, so2611// setting IP to that simulates a return.2612newRegisters.setIP(reinterpret_cast<uintptr_t>(returnAddress));26132614// Simulate the step by replacing the register set with the new ones.2615registers = newRegisters;26162617// Check if the next frame is a signal frame.2618pint_t nextStack = *(reinterpret_cast<pint_t *>(registers.getSP()));26192620// Return address is the address after call site instruction.2621pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2];26222623if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) {2624_LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "2625"nextStack=%p, next return address=%p\n",2626reinterpret_cast<void *>(nextStack),2627reinterpret_cast<void *>(nextReturnAddress));2628isSignalFrame = true;2629} else {2630isSignalFrame = false;2631}2632return UNW_STEP_SUCCESS;2633}2634#endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)26352636template <typename A, typename R>2637void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {2638#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \2639defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)2640_isSigReturn = false;2641#endif26422643pint_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.2647pc &= (pint_t)~0x1;2648#endif26492650// Exit early if at the top of the stack.2651if (pc == 0) {2652_unwindInfoMissing = true;2653return;2654}26552656// If the last line of a function is a "throw" the compiler sometimes2657// emits no instructions after the call to __cxa_throw. This means2658// 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 return2660// address.2661if (isReturnAddress)2662#if defined(_AIX)2663// PC needs to be a 4-byte aligned address to be able to look for a2664// word of 0 that indicates the start of the traceback table at the end2665// of a function on AIX.2666pc -= 4;2667#else2668--pc;2669#endif26702671#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 signal2674// handler points to first non-executed instruction, while FDE/CIE expects IP2675// to be after the first non-executed instruction.2676if (_isSignalFrame)2677++pc;2678#endif26792680// Ask address space object to find unwind sections for this pc.2681UnwindInfoSections sects;2682if (_addressSpace.findUnwindSections(pc, sects)) {2683#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)2684// If there is a compact unwind encoding table, look there first.2685if (sects.compact_unwind_section != 0) {2686if (this->getInfoFromCompactEncodingSection(pc, sects)) {2687#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)2688// Found info in table, done unless encoding says to use dwarf.2689uint32_t dwarfOffset;2690if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {2691if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {2692// found info in dwarf, done2693return;2694}2695}2696#endif2697// If unwind table has entry, but entry says there is no unwind info,2698// record that we have no unwind info.2699if (_info.format == 0)2700_unwindInfoMissing = true;2701return;2702}2703}2704#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)27052706#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)2707// If there is SEH unwind info, look there next.2708if (this->getInfoFromSEH(pc))2709return;2710#endif27112712#if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)2713// If there is unwind info in the traceback table, look there next.2714if (this->getInfoFromTBTable(pc, _registers))2715return;2716#endif27172718#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)2719// If there is dwarf unwind info, look there next.2720if (sects.dwarf_section != 0) {2721if (this->getInfoFromDwarfSection(pc, sects)) {2722// found info in dwarf, done2723return;2724}2725}2726#endif27272728#if defined(_LIBUNWIND_ARM_EHABI)2729// If there is ARM EHABI unwind info, look there next.2730if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))2731return;2732#endif2733}27342735#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)2736// There is no static unwind info for this pc. Look to see if an FDE was2737// dynamically registered for it.2738pint_t cachedFDE = DwarfFDECache<A>::findFDE(DwarfFDECache<A>::kSearchAll,2739pc);2740if (cachedFDE != 0) {2741typename CFI_Parser<A>::FDE_Info fdeInfo;2742typename CFI_Parser<A>::CIE_Info cieInfo;2743if (!CFI_Parser<A>::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo))2744if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))2745return;2746}27472748// Lastly, ask AddressSpace object about platform specific ways to locate2749// other FDEs.2750pint_t fde;2751if (_addressSpace.findOtherFDE(pc, fde)) {2752typename CFI_Parser<A>::FDE_Info fdeInfo;2753typename CFI_Parser<A>::CIE_Info cieInfo;2754if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {2755// Double check this FDE is for a function that includes the pc.2756if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd))2757if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))2758return;2759}2760}2761#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)27622763#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \2764defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)2765if (setInfoForSigReturn())2766return;2767#endif27682769// no unwind info, flag that we can't reliably unwind2770_unwindInfoMissing = true;2771}27722773#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \2774defined(_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 two2778// specific instructions (see below). Typically the trampoline comes from the2779// vDSO[1] (i.e. the __kernel_rt_sigreturn function). A libc might provide its2780// own restorer function, though, or user-mode QEMU might write a trampoline2781// onto the stack.2782//2783// This special code path is a fallback that is only used if the trampoline2784// lacks proper (e.g. DWARF) unwind info. On AArch64, a new DWARF register2785// constant for the PC needs to be defined before DWARF can handle a signal2786// 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 is2788// 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.S2792const 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, so2794// directly accessing it could cause a SIGSEGV.2795if (!isReadableAddr(pc))2796return false;2797auto *instructions = reinterpret_cast<const uint32_t *>(pc);2798// Look for instructions: mov x8, #0x8b; svc #0x02799if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001)2800return false;28012802_info = {};2803_info.start_ip = pc;2804_info.end_ip = pc + 4;2805_isSigReturn = true;2806return true;2807}28082809template <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 struct2813// - ucontext struct:2814// - 8-byte long (uc_flags)2815// - 8-byte pointer (uc_link)2816// - 24-byte stack_t2817// - 128-byte signal set2818// - 8 bytes of padding because sigcontext has 16-byte alignment2819// - sigcontext/mcontext_t2820// [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c2821const pint_t kOffsetSpToSigcontext = (128 + 8 + 8 + 24 + 128 + 8); // 30428222823// Offsets from sigcontext to each register.2824const pint_t kOffsetGprs = 8; // offset to "__u64 regs[31]" field2825const pint_t kOffsetSp = 256; // offset to "__u64 sp" field2826const pint_t kOffsetPc = 264; // offset to "__u64 pc" field28272828pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;28292830for (int i = 0; i <= 30; ++i) {2831uint64_t value = _addressSpace.get64(sigctx + kOffsetGprs +2832static_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;2838return UNW_STEP_SUCCESS;2839}2840#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&2841// defined(_LIBUNWIND_TARGET_AARCH64)28422843#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \2844defined(_LIBUNWIND_TARGET_LOONGARCH)2845template <typename A, typename R>2846bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_loongarch &) {2847const 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, so2849// directly accessing it could cause a SIGSEGV.2850if (!isReadableAddr(pc))2851return false;2852const auto *instructions = reinterpret_cast<const uint32_t *>(pc);2853// Look for the two instructions used in the sigreturn trampoline2854// __vdso_rt_sigreturn:2855//2856// 0x03822c0b li a7,0x8b2857// 0x002b0000 syscall 02858if (instructions[0] != 0x03822c0b || instructions[1] != 0x002b0000)2859return false;28602861_info = {};2862_info.start_ip = pc;2863_info.end_ip = pc + 4;2864_isSigReturn = true;2865return true;2866}28672868template <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 struct2872// - ucontext_t struct:2873// - 8-byte long (__uc_flags)2874// - 8-byte pointer (*uc_link)2875// - 24-byte uc_stack2876// - 8-byte uc_sigmask2877// - 120-byte of padding to allow sigset_t to be expanded in the future2878// - 8 bytes of padding because sigcontext has 16-byte alignment2879// - struct sigcontext uc_mcontext2880// [1]2881// https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c2882const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;28832884const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;2885_registers.setIP(_addressSpace.get64(sigctx));2886for (int i = UNW_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) {2887// skip R02888uint64_t value =2889_addressSpace.get64(sigctx + static_cast<pint_t>((i + 1) * 8));2890_registers.setRegister(i, value);2891}2892_isSignalFrame = true;2893return UNW_STEP_SUCCESS;2894}2895#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&2896// defined(_LIBUNWIND_TARGET_LOONGARCH)28972898#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \2899defined(_LIBUNWIND_TARGET_RISCV)2900template <typename A, typename R>2901bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {2902const 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, so2904// directly accessing it could cause a SIGSEGV.2905if (!isReadableAddr(pc))2906return false;2907const auto *instructions = reinterpret_cast<const uint32_t *>(pc);2908// Look for the two instructions used in the sigreturn trampoline2909// __vdso_rt_sigreturn:2910//2911// 0x08b00893 li a7,0x8b2912// 0x00000073 ecall2913if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073)2914return false;29152916_info = {};2917_info.start_ip = pc;2918_info.end_ip = pc + 4;2919_isSigReturn = true;2920return true;2921}29222923template <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 struct2927// - ucontext_t struct:2928// - 8-byte long (__uc_flags)2929// - 8-byte pointer (*uc_link)2930// - 24-byte uc_stack2931// - 8-byte uc_sigmask2932// - 120-byte of padding to allow sigset_t to be expanded in the future2933// - 8 bytes of padding because sigcontext has 16-byte alignment2934// - struct sigcontext uc_mcontext2935// [1]2936// https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c2937const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;29382939const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;2940_registers.setIP(_addressSpace.get64(sigctx));2941for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) {2942uint64_t value = _addressSpace.get64(sigctx + static_cast<pint_t>(i * 8));2943_registers.setRegister(i, value);2944}2945_isSignalFrame = true;2946return UNW_STEP_SUCCESS;2947}2948#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&2949// defined(_LIBUNWIND_TARGET_RISCV)29502951#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) && \2952defined(_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 a2956// specific instruction (see below). Typically the trampoline comes from the2957// vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its2958// own restorer function, though, or user-mode QEMU might write a trampoline2959// onto the stack.2960const 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, so2962// directly accessing it could cause a SIGSEGV.2963if (!isReadableAddr(pc))2964return false;2965const auto inst = *reinterpret_cast<const uint16_t *>(pc);2966if (inst == 0x0a77 || inst == 0x0aad) {2967_info = {};2968_info.start_ip = pc;2969_info.end_ip = pc + 2;2970_isSigReturn = true;2971return true;2972}2973return false;2974}29752976template <typename A, typename R>2977int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {2978// Determine current SP.2979const 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.2981const pint_t cfa = sp + 160;29822983// Determine current PC and instruction there (this must be either2984// a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn").2985const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));2986const uint16_t inst = _addressSpace.get16(pc);29872988// Find the addresses of the signo and sigcontext in the frame.2989pint_t pSigctx = 0;2990pint_t pSigno = 0;29912992// "svc __NR_sigreturn" uses a non-RT signal trampoline frame.2993if (inst == 0x0a77) {2994// Layout of a non-RT signal trampoline frame, starting at the CFA:2995// - 8-byte signal mask2996// - 8-byte pointer to sigcontext, followed by signo2997// - 4-byte signo2998pSigctx = _addressSpace.get64(cfa + 8);2999pSigno = pSigctx + 344;3000}30013002// "svc __NR_rt_sigreturn" uses a RT signal trampoline frame.3003if (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_t3011// - 8 bytes of padding because sigcontext has 16-byte alignment3012// - sigcontext/mcontext_t3013pSigctx = cfa + 8 + 128 + 8 + 8 + 24 + 8;3014pSigno = cfa + 8;3015}30163017assert(pSigctx != 0);3018assert(pSigno != 0);30193020// Offsets from sigcontext to each register.3021const pint_t kOffsetPc = 8;3022const pint_t kOffsetGprs = 16;3023const pint_t kOffsetFprs = 216;30243025// Restore all registers.3026for (int i = 0; i < 16; ++i) {3027uint64_t value = _addressSpace.get64(pSigctx + kOffsetGprs +3028static_cast<pint_t>(i * 8));3029_registers.setRegister(UNW_S390X_R0 + i, value);3030}3031for (int i = 0; i < 16; ++i) {3032static const int fpr[16] = {3033UNW_S390X_F0, UNW_S390X_F1, UNW_S390X_F2, UNW_S390X_F3,3034UNW_S390X_F4, UNW_S390X_F5, UNW_S390X_F6, UNW_S390X_F7,3035UNW_S390X_F8, UNW_S390X_F9, UNW_S390X_F10, UNW_S390X_F11,3036UNW_S390X_F12, UNW_S390X_F13, UNW_S390X_F14, UNW_S390X_F153037};3038double value = _addressSpace.getDouble(pSigctx + kOffsetFprs +3039static_cast<pint_t>(i * 8));3040_registers.setFloatRegister(fpr[i], value);3041}3042_registers.setIP(_addressSpace.get64(pSigctx + kOffsetPc));30433044// SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr3045// after the faulting instruction rather than before it.3046// Do not set _isSignalFrame in that case.3047uint32_t signo = _addressSpace.get32(pSigno);3048_isSignalFrame = (signo != 4 && signo != 5 && signo != 8);30493050return UNW_STEP_SUCCESS;3051}3052#endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&3053// defined(_LIBUNWIND_TARGET_S390X)30543055#if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)3056template <typename A, typename R>3057bool UnwindCursor<A, R>::setInfoForSigReturn() {3058Dl_info dlinfo;3059const auto isSignalHandler = [&](pint_t addr) {3060if (!dladdr(reinterpret_cast<void *>(addr), &dlinfo))3061return false;3062if (strcmp(dlinfo.dli_fname, "commpage"))3063return false;3064if (dlinfo.dli_sname == NULL ||3065strcmp(dlinfo.dli_sname, "commpage_signal_handler"))3066return false;3067return true;3068};30693070pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));3071if (!isSignalHandler(pc))3072return false;30733074pint_t start = reinterpret_cast<pint_t>(dlinfo.dli_saddr);30753076static size_t signalHandlerSize = 0;3077if (signalHandlerSize == 0) {3078size_t boundLow = 0;3079size_t boundHigh = static_cast<size_t>(-1);30803081area_info areaInfo;3082if (get_area_info(area_for(dlinfo.dli_saddr), &areaInfo) == B_OK)3083boundHigh = areaInfo.size;30843085while (boundLow < boundHigh) {3086size_t boundMid = boundLow + ((boundHigh - boundLow) / 2);3087pint_t test = start + boundMid;3088if (test >= start && isSignalHandler(test))3089boundLow = boundMid + 1;3090else3091boundHigh = boundMid;3092}30933094signalHandlerSize = boundHigh;3095}30963097_info = {};3098_info.start_ip = start;3099_info.end_ip = start + signalHandlerSize;3100_isSigReturn = true;31013102return true;3103}31043105template <typename A, typename R>3106int UnwindCursor<A, R>::stepThroughSigReturn() {3107_isSignalFrame = true;31083109#if defined(_LIBUNWIND_TARGET_X86_64)3110// Layout of the stack before function call:3111// - signal_frame_data3112// + 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.3118pint_t bp = this->getReg(UNW_X86_64_RBP);3119vregs *regs = (vregs *)(bp + 0x70);31203121_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: XMM3139#endif // defined(_LIBUNWIND_TARGET_X86_64)31403141return UNW_STEP_SUCCESS;3142}3143#endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)31443145template <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.3148if (_unwindInfoMissing)3149return UNW_STEP_END;31503151// Use unwinding info to modify register set as if function returned.3152int result;3153#if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) || \3154defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)3155if (_isSigReturn) {3156result = this->stepThroughSigReturn();3157} else3158#endif3159{3160#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)3161result = this->stepWithCompactEncoding(stage2);3162#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)3163result = this->stepWithSEHData();3164#elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)3165result = this->stepWithTBTableData();3166#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)3167result = this->stepWithDwarfFDE(stage2);3168#elif defined(_LIBUNWIND_ARM_EHABI)3169result = this->stepWithEHABI();3170#else3171#error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \3172_LIBUNWIND_SUPPORT_SEH_UNWIND or \3173_LIBUNWIND_SUPPORT_DWARF_UNWIND or \3174_LIBUNWIND_ARM_EHABI3175#endif3176}31773178// update info based on new PC3179if (result == UNW_STEP_SUCCESS) {3180this->setInfoBasedOnIPRegister(true);3181if (_unwindInfoMissing)3182return UNW_STEP_END;3183}31843185return result;3186}31873188template <typename A, typename R>3189void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {3190if (_unwindInfoMissing)3191memset(info, 0, sizeof(*info));3192else3193*info = _info;3194}31953196template <typename A, typename R>3197bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,3198unw_word_t *offset) {3199return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),3200buf, bufLen, offset);3201}32023203#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.32073208const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);3209// We have to check that addr is nullptr because sigprocmask allows that3210// as an argument without failure.3211if (!sigsetAddr)3212return false;3213const auto saveErrno = errno;3214// We MUST use a raw syscall here, as wrappers may try to access3215// sigsetAddr which may cause a SIGSEGV. A raw syscall however is3216// safe. Additionally, we need to pass the kernel_sigset_size, which is3217// different from libc sizeof(sigset_t). For the majority of architectures,3218// it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.3219const auto kernelSigsetSize = NSIG / 8;3220[[maybe_unused]] const int Result = syscall(3221SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize);3222// Because our "how" is invalid, this syscall should always fail, and our3223// errno should always be EINVAL or an EFAULT. This relies on the Linux3224// kernel to check copy_from_user before checking if the "how" argument is3225// invalid.3226assert(Result == -1);3227assert(errno == EFAULT || errno == EINVAL);3228const auto readable = errno != EFAULT;3229errno = saveErrno;3230return readable;3231}3232#endif32333234#if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)3235extern "C" void *__libunwind_shstk_get_registers(unw_cursor_t *cursor) {3236AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;3237return co->get_registers();3238}3239#endif3240} // namespace libunwind32413242#endif // __UNWINDCURSOR_HPP__324332443245