1*0b57cec5SDimitry Andric //===------------------------- UnwindCursor.hpp ---------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric // 8*0b57cec5SDimitry Andric // C++ interface to lower levels of libunwind 9*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10*0b57cec5SDimitry Andric 11*0b57cec5SDimitry Andric #ifndef __UNWINDCURSOR_HPP__ 12*0b57cec5SDimitry Andric #define __UNWINDCURSOR_HPP__ 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include <stdint.h> 15*0b57cec5SDimitry Andric #include <stdio.h> 16*0b57cec5SDimitry Andric #include <stdlib.h> 17*0b57cec5SDimitry Andric #include <unwind.h> 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric #ifdef _WIN32 20*0b57cec5SDimitry Andric #include <windows.h> 21*0b57cec5SDimitry Andric #include <ntverp.h> 22*0b57cec5SDimitry Andric #endif 23*0b57cec5SDimitry Andric #ifdef __APPLE__ 24*0b57cec5SDimitry Andric #include <mach-o/dyld.h> 25*0b57cec5SDimitry Andric #endif 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 28*0b57cec5SDimitry Andric // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and 29*0b57cec5SDimitry Andric // earlier) SDKs. 30*0b57cec5SDimitry Andric // MinGW-w64 has always provided this struct. 31*0b57cec5SDimitry Andric #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \ 32*0b57cec5SDimitry Andric !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000 33*0b57cec5SDimitry Andric struct _DISPATCHER_CONTEXT { 34*0b57cec5SDimitry Andric ULONG64 ControlPc; 35*0b57cec5SDimitry Andric ULONG64 ImageBase; 36*0b57cec5SDimitry Andric PRUNTIME_FUNCTION FunctionEntry; 37*0b57cec5SDimitry Andric ULONG64 EstablisherFrame; 38*0b57cec5SDimitry Andric ULONG64 TargetIp; 39*0b57cec5SDimitry Andric PCONTEXT ContextRecord; 40*0b57cec5SDimitry Andric PEXCEPTION_ROUTINE LanguageHandler; 41*0b57cec5SDimitry Andric PVOID HandlerData; 42*0b57cec5SDimitry Andric PUNWIND_HISTORY_TABLE HistoryTable; 43*0b57cec5SDimitry Andric ULONG ScopeIndex; 44*0b57cec5SDimitry Andric ULONG Fill0; 45*0b57cec5SDimitry Andric }; 46*0b57cec5SDimitry Andric #endif 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric struct UNWIND_INFO { 49*0b57cec5SDimitry Andric uint8_t Version : 3; 50*0b57cec5SDimitry Andric uint8_t Flags : 5; 51*0b57cec5SDimitry Andric uint8_t SizeOfProlog; 52*0b57cec5SDimitry Andric uint8_t CountOfCodes; 53*0b57cec5SDimitry Andric uint8_t FrameRegister : 4; 54*0b57cec5SDimitry Andric uint8_t FrameOffset : 4; 55*0b57cec5SDimitry Andric uint16_t UnwindCodes[2]; 56*0b57cec5SDimitry Andric }; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric extern "C" _Unwind_Reason_Code __libunwind_seh_personality( 59*0b57cec5SDimitry Andric int, _Unwind_Action, uint64_t, _Unwind_Exception *, 60*0b57cec5SDimitry Andric struct _Unwind_Context *); 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric #endif 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric #include "config.h" 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric #include "AddressSpace.hpp" 67*0b57cec5SDimitry Andric #include "CompactUnwinder.hpp" 68*0b57cec5SDimitry Andric #include "config.h" 69*0b57cec5SDimitry Andric #include "DwarfInstructions.hpp" 70*0b57cec5SDimitry Andric #include "EHHeaderParser.hpp" 71*0b57cec5SDimitry Andric #include "libunwind.h" 72*0b57cec5SDimitry Andric #include "Registers.hpp" 73*0b57cec5SDimitry Andric #include "RWMutex.hpp" 74*0b57cec5SDimitry Andric #include "Unwind-EHABI.h" 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric namespace libunwind { 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 79*0b57cec5SDimitry Andric /// Cache of recently found FDEs. 80*0b57cec5SDimitry Andric template <typename A> 81*0b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN DwarfFDECache { 82*0b57cec5SDimitry Andric typedef typename A::pint_t pint_t; 83*0b57cec5SDimitry Andric public: 84*0b57cec5SDimitry Andric static pint_t findFDE(pint_t mh, pint_t pc); 85*0b57cec5SDimitry Andric static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); 86*0b57cec5SDimitry Andric static void removeAllIn(pint_t mh); 87*0b57cec5SDimitry Andric static void iterateCacheEntries(void (*func)(unw_word_t ip_start, 88*0b57cec5SDimitry Andric unw_word_t ip_end, 89*0b57cec5SDimitry Andric unw_word_t fde, unw_word_t mh)); 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric private: 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric struct entry { 94*0b57cec5SDimitry Andric pint_t mh; 95*0b57cec5SDimitry Andric pint_t ip_start; 96*0b57cec5SDimitry Andric pint_t ip_end; 97*0b57cec5SDimitry Andric pint_t fde; 98*0b57cec5SDimitry Andric }; 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric // These fields are all static to avoid needing an initializer. 101*0b57cec5SDimitry Andric // There is only one instance of this class per process. 102*0b57cec5SDimitry Andric static RWMutex _lock; 103*0b57cec5SDimitry Andric #ifdef __APPLE__ 104*0b57cec5SDimitry Andric static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); 105*0b57cec5SDimitry Andric static bool _registeredForDyldUnloads; 106*0b57cec5SDimitry Andric #endif 107*0b57cec5SDimitry Andric static entry *_buffer; 108*0b57cec5SDimitry Andric static entry *_bufferUsed; 109*0b57cec5SDimitry Andric static entry *_bufferEnd; 110*0b57cec5SDimitry Andric static entry _initialBuffer[64]; 111*0b57cec5SDimitry Andric }; 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric template <typename A> 114*0b57cec5SDimitry Andric typename DwarfFDECache<A>::entry * 115*0b57cec5SDimitry Andric DwarfFDECache<A>::_buffer = _initialBuffer; 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric template <typename A> 118*0b57cec5SDimitry Andric typename DwarfFDECache<A>::entry * 119*0b57cec5SDimitry Andric DwarfFDECache<A>::_bufferUsed = _initialBuffer; 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric template <typename A> 122*0b57cec5SDimitry Andric typename DwarfFDECache<A>::entry * 123*0b57cec5SDimitry Andric DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64]; 124*0b57cec5SDimitry Andric 125*0b57cec5SDimitry Andric template <typename A> 126*0b57cec5SDimitry Andric typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64]; 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric template <typename A> 129*0b57cec5SDimitry Andric RWMutex DwarfFDECache<A>::_lock; 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric #ifdef __APPLE__ 132*0b57cec5SDimitry Andric template <typename A> 133*0b57cec5SDimitry Andric bool DwarfFDECache<A>::_registeredForDyldUnloads = false; 134*0b57cec5SDimitry Andric #endif 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric template <typename A> 137*0b57cec5SDimitry Andric typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { 138*0b57cec5SDimitry Andric pint_t result = 0; 139*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); 140*0b57cec5SDimitry Andric for (entry *p = _buffer; p < _bufferUsed; ++p) { 141*0b57cec5SDimitry Andric if ((mh == p->mh) || (mh == 0)) { 142*0b57cec5SDimitry Andric if ((p->ip_start <= pc) && (pc < p->ip_end)) { 143*0b57cec5SDimitry Andric result = p->fde; 144*0b57cec5SDimitry Andric break; 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric } 147*0b57cec5SDimitry Andric } 148*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared()); 149*0b57cec5SDimitry Andric return result; 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric template <typename A> 153*0b57cec5SDimitry Andric void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, 154*0b57cec5SDimitry Andric pint_t fde) { 155*0b57cec5SDimitry Andric #if !defined(_LIBUNWIND_NO_HEAP) 156*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); 157*0b57cec5SDimitry Andric if (_bufferUsed >= _bufferEnd) { 158*0b57cec5SDimitry Andric size_t oldSize = (size_t)(_bufferEnd - _buffer); 159*0b57cec5SDimitry Andric size_t newSize = oldSize * 4; 160*0b57cec5SDimitry Andric // Can't use operator new (we are below it). 161*0b57cec5SDimitry Andric entry *newBuffer = (entry *)malloc(newSize * sizeof(entry)); 162*0b57cec5SDimitry Andric memcpy(newBuffer, _buffer, oldSize * sizeof(entry)); 163*0b57cec5SDimitry Andric if (_buffer != _initialBuffer) 164*0b57cec5SDimitry Andric free(_buffer); 165*0b57cec5SDimitry Andric _buffer = newBuffer; 166*0b57cec5SDimitry Andric _bufferUsed = &newBuffer[oldSize]; 167*0b57cec5SDimitry Andric _bufferEnd = &newBuffer[newSize]; 168*0b57cec5SDimitry Andric } 169*0b57cec5SDimitry Andric _bufferUsed->mh = mh; 170*0b57cec5SDimitry Andric _bufferUsed->ip_start = ip_start; 171*0b57cec5SDimitry Andric _bufferUsed->ip_end = ip_end; 172*0b57cec5SDimitry Andric _bufferUsed->fde = fde; 173*0b57cec5SDimitry Andric ++_bufferUsed; 174*0b57cec5SDimitry Andric #ifdef __APPLE__ 175*0b57cec5SDimitry Andric if (!_registeredForDyldUnloads) { 176*0b57cec5SDimitry Andric _dyld_register_func_for_remove_image(&dyldUnloadHook); 177*0b57cec5SDimitry Andric _registeredForDyldUnloads = true; 178*0b57cec5SDimitry Andric } 179*0b57cec5SDimitry Andric #endif 180*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); 181*0b57cec5SDimitry Andric #endif 182*0b57cec5SDimitry Andric } 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric template <typename A> 185*0b57cec5SDimitry Andric void DwarfFDECache<A>::removeAllIn(pint_t mh) { 186*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); 187*0b57cec5SDimitry Andric entry *d = _buffer; 188*0b57cec5SDimitry Andric for (const entry *s = _buffer; s < _bufferUsed; ++s) { 189*0b57cec5SDimitry Andric if (s->mh != mh) { 190*0b57cec5SDimitry Andric if (d != s) 191*0b57cec5SDimitry Andric *d = *s; 192*0b57cec5SDimitry Andric ++d; 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric } 195*0b57cec5SDimitry Andric _bufferUsed = d; 196*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); 197*0b57cec5SDimitry Andric } 198*0b57cec5SDimitry Andric 199*0b57cec5SDimitry Andric #ifdef __APPLE__ 200*0b57cec5SDimitry Andric template <typename A> 201*0b57cec5SDimitry Andric void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { 202*0b57cec5SDimitry Andric removeAllIn((pint_t) mh); 203*0b57cec5SDimitry Andric } 204*0b57cec5SDimitry Andric #endif 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric template <typename A> 207*0b57cec5SDimitry Andric void DwarfFDECache<A>::iterateCacheEntries(void (*func)( 208*0b57cec5SDimitry Andric unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { 209*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.lock()); 210*0b57cec5SDimitry Andric for (entry *p = _buffer; p < _bufferUsed; ++p) { 211*0b57cec5SDimitry Andric (*func)(p->ip_start, p->ip_end, p->fde, p->mh); 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric _LIBUNWIND_LOG_IF_FALSE(_lock.unlock()); 214*0b57cec5SDimitry Andric } 215*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 216*0b57cec5SDimitry Andric 217*0b57cec5SDimitry Andric 218*0b57cec5SDimitry Andric #define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) 219*0b57cec5SDimitry Andric 220*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 221*0b57cec5SDimitry Andric template <typename A> class UnwindSectionHeader { 222*0b57cec5SDimitry Andric public: 223*0b57cec5SDimitry Andric UnwindSectionHeader(A &addressSpace, typename A::pint_t addr) 224*0b57cec5SDimitry Andric : _addressSpace(addressSpace), _addr(addr) {} 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric uint32_t version() const { 227*0b57cec5SDimitry Andric return _addressSpace.get32(_addr + 228*0b57cec5SDimitry Andric offsetof(unwind_info_section_header, version)); 229*0b57cec5SDimitry Andric } 230*0b57cec5SDimitry Andric uint32_t commonEncodingsArraySectionOffset() const { 231*0b57cec5SDimitry Andric return _addressSpace.get32(_addr + 232*0b57cec5SDimitry Andric offsetof(unwind_info_section_header, 233*0b57cec5SDimitry Andric commonEncodingsArraySectionOffset)); 234*0b57cec5SDimitry Andric } 235*0b57cec5SDimitry Andric uint32_t commonEncodingsArrayCount() const { 236*0b57cec5SDimitry Andric return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, 237*0b57cec5SDimitry Andric commonEncodingsArrayCount)); 238*0b57cec5SDimitry Andric } 239*0b57cec5SDimitry Andric uint32_t personalityArraySectionOffset() const { 240*0b57cec5SDimitry Andric return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, 241*0b57cec5SDimitry Andric personalityArraySectionOffset)); 242*0b57cec5SDimitry Andric } 243*0b57cec5SDimitry Andric uint32_t personalityArrayCount() const { 244*0b57cec5SDimitry Andric return _addressSpace.get32( 245*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_section_header, personalityArrayCount)); 246*0b57cec5SDimitry Andric } 247*0b57cec5SDimitry Andric uint32_t indexSectionOffset() const { 248*0b57cec5SDimitry Andric return _addressSpace.get32( 249*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_section_header, indexSectionOffset)); 250*0b57cec5SDimitry Andric } 251*0b57cec5SDimitry Andric uint32_t indexCount() const { 252*0b57cec5SDimitry Andric return _addressSpace.get32( 253*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_section_header, indexCount)); 254*0b57cec5SDimitry Andric } 255*0b57cec5SDimitry Andric 256*0b57cec5SDimitry Andric private: 257*0b57cec5SDimitry Andric A &_addressSpace; 258*0b57cec5SDimitry Andric typename A::pint_t _addr; 259*0b57cec5SDimitry Andric }; 260*0b57cec5SDimitry Andric 261*0b57cec5SDimitry Andric template <typename A> class UnwindSectionIndexArray { 262*0b57cec5SDimitry Andric public: 263*0b57cec5SDimitry Andric UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr) 264*0b57cec5SDimitry Andric : _addressSpace(addressSpace), _addr(addr) {} 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric uint32_t functionOffset(uint32_t index) const { 267*0b57cec5SDimitry Andric return _addressSpace.get32( 268*0b57cec5SDimitry Andric _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 269*0b57cec5SDimitry Andric functionOffset)); 270*0b57cec5SDimitry Andric } 271*0b57cec5SDimitry Andric uint32_t secondLevelPagesSectionOffset(uint32_t index) const { 272*0b57cec5SDimitry Andric return _addressSpace.get32( 273*0b57cec5SDimitry Andric _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 274*0b57cec5SDimitry Andric secondLevelPagesSectionOffset)); 275*0b57cec5SDimitry Andric } 276*0b57cec5SDimitry Andric uint32_t lsdaIndexArraySectionOffset(uint32_t index) const { 277*0b57cec5SDimitry Andric return _addressSpace.get32( 278*0b57cec5SDimitry Andric _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 279*0b57cec5SDimitry Andric lsdaIndexArraySectionOffset)); 280*0b57cec5SDimitry Andric } 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric private: 283*0b57cec5SDimitry Andric A &_addressSpace; 284*0b57cec5SDimitry Andric typename A::pint_t _addr; 285*0b57cec5SDimitry Andric }; 286*0b57cec5SDimitry Andric 287*0b57cec5SDimitry Andric template <typename A> class UnwindSectionRegularPageHeader { 288*0b57cec5SDimitry Andric public: 289*0b57cec5SDimitry Andric UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr) 290*0b57cec5SDimitry Andric : _addressSpace(addressSpace), _addr(addr) {} 291*0b57cec5SDimitry Andric 292*0b57cec5SDimitry Andric uint32_t kind() const { 293*0b57cec5SDimitry Andric return _addressSpace.get32( 294*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_regular_second_level_page_header, kind)); 295*0b57cec5SDimitry Andric } 296*0b57cec5SDimitry Andric uint16_t entryPageOffset() const { 297*0b57cec5SDimitry Andric return _addressSpace.get16( 298*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_regular_second_level_page_header, 299*0b57cec5SDimitry Andric entryPageOffset)); 300*0b57cec5SDimitry Andric } 301*0b57cec5SDimitry Andric uint16_t entryCount() const { 302*0b57cec5SDimitry Andric return _addressSpace.get16( 303*0b57cec5SDimitry Andric _addr + 304*0b57cec5SDimitry Andric offsetof(unwind_info_regular_second_level_page_header, entryCount)); 305*0b57cec5SDimitry Andric } 306*0b57cec5SDimitry Andric 307*0b57cec5SDimitry Andric private: 308*0b57cec5SDimitry Andric A &_addressSpace; 309*0b57cec5SDimitry Andric typename A::pint_t _addr; 310*0b57cec5SDimitry Andric }; 311*0b57cec5SDimitry Andric 312*0b57cec5SDimitry Andric template <typename A> class UnwindSectionRegularArray { 313*0b57cec5SDimitry Andric public: 314*0b57cec5SDimitry Andric UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr) 315*0b57cec5SDimitry Andric : _addressSpace(addressSpace), _addr(addr) {} 316*0b57cec5SDimitry Andric 317*0b57cec5SDimitry Andric uint32_t functionOffset(uint32_t index) const { 318*0b57cec5SDimitry Andric return _addressSpace.get32( 319*0b57cec5SDimitry Andric _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index, 320*0b57cec5SDimitry Andric functionOffset)); 321*0b57cec5SDimitry Andric } 322*0b57cec5SDimitry Andric uint32_t encoding(uint32_t index) const { 323*0b57cec5SDimitry Andric return _addressSpace.get32( 324*0b57cec5SDimitry Andric _addr + 325*0b57cec5SDimitry Andric arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); 326*0b57cec5SDimitry Andric } 327*0b57cec5SDimitry Andric 328*0b57cec5SDimitry Andric private: 329*0b57cec5SDimitry Andric A &_addressSpace; 330*0b57cec5SDimitry Andric typename A::pint_t _addr; 331*0b57cec5SDimitry Andric }; 332*0b57cec5SDimitry Andric 333*0b57cec5SDimitry Andric template <typename A> class UnwindSectionCompressedPageHeader { 334*0b57cec5SDimitry Andric public: 335*0b57cec5SDimitry Andric UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr) 336*0b57cec5SDimitry Andric : _addressSpace(addressSpace), _addr(addr) {} 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric uint32_t kind() const { 339*0b57cec5SDimitry Andric return _addressSpace.get32( 340*0b57cec5SDimitry Andric _addr + 341*0b57cec5SDimitry Andric offsetof(unwind_info_compressed_second_level_page_header, kind)); 342*0b57cec5SDimitry Andric } 343*0b57cec5SDimitry Andric uint16_t entryPageOffset() const { 344*0b57cec5SDimitry Andric return _addressSpace.get16( 345*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_compressed_second_level_page_header, 346*0b57cec5SDimitry Andric entryPageOffset)); 347*0b57cec5SDimitry Andric } 348*0b57cec5SDimitry Andric uint16_t entryCount() const { 349*0b57cec5SDimitry Andric return _addressSpace.get16( 350*0b57cec5SDimitry Andric _addr + 351*0b57cec5SDimitry Andric offsetof(unwind_info_compressed_second_level_page_header, entryCount)); 352*0b57cec5SDimitry Andric } 353*0b57cec5SDimitry Andric uint16_t encodingsPageOffset() const { 354*0b57cec5SDimitry Andric return _addressSpace.get16( 355*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_compressed_second_level_page_header, 356*0b57cec5SDimitry Andric encodingsPageOffset)); 357*0b57cec5SDimitry Andric } 358*0b57cec5SDimitry Andric uint16_t encodingsCount() const { 359*0b57cec5SDimitry Andric return _addressSpace.get16( 360*0b57cec5SDimitry Andric _addr + offsetof(unwind_info_compressed_second_level_page_header, 361*0b57cec5SDimitry Andric encodingsCount)); 362*0b57cec5SDimitry Andric } 363*0b57cec5SDimitry Andric 364*0b57cec5SDimitry Andric private: 365*0b57cec5SDimitry Andric A &_addressSpace; 366*0b57cec5SDimitry Andric typename A::pint_t _addr; 367*0b57cec5SDimitry Andric }; 368*0b57cec5SDimitry Andric 369*0b57cec5SDimitry Andric template <typename A> class UnwindSectionCompressedArray { 370*0b57cec5SDimitry Andric public: 371*0b57cec5SDimitry Andric UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr) 372*0b57cec5SDimitry Andric : _addressSpace(addressSpace), _addr(addr) {} 373*0b57cec5SDimitry Andric 374*0b57cec5SDimitry Andric uint32_t functionOffset(uint32_t index) const { 375*0b57cec5SDimitry Andric return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( 376*0b57cec5SDimitry Andric _addressSpace.get32(_addr + index * sizeof(uint32_t))); 377*0b57cec5SDimitry Andric } 378*0b57cec5SDimitry Andric uint16_t encodingIndex(uint32_t index) const { 379*0b57cec5SDimitry Andric return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( 380*0b57cec5SDimitry Andric _addressSpace.get32(_addr + index * sizeof(uint32_t))); 381*0b57cec5SDimitry Andric } 382*0b57cec5SDimitry Andric 383*0b57cec5SDimitry Andric private: 384*0b57cec5SDimitry Andric A &_addressSpace; 385*0b57cec5SDimitry Andric typename A::pint_t _addr; 386*0b57cec5SDimitry Andric }; 387*0b57cec5SDimitry Andric 388*0b57cec5SDimitry Andric template <typename A> class UnwindSectionLsdaArray { 389*0b57cec5SDimitry Andric public: 390*0b57cec5SDimitry Andric UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr) 391*0b57cec5SDimitry Andric : _addressSpace(addressSpace), _addr(addr) {} 392*0b57cec5SDimitry Andric 393*0b57cec5SDimitry Andric uint32_t functionOffset(uint32_t index) const { 394*0b57cec5SDimitry Andric return _addressSpace.get32( 395*0b57cec5SDimitry Andric _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, 396*0b57cec5SDimitry Andric index, functionOffset)); 397*0b57cec5SDimitry Andric } 398*0b57cec5SDimitry Andric uint32_t lsdaOffset(uint32_t index) const { 399*0b57cec5SDimitry Andric return _addressSpace.get32( 400*0b57cec5SDimitry Andric _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, 401*0b57cec5SDimitry Andric index, lsdaOffset)); 402*0b57cec5SDimitry Andric } 403*0b57cec5SDimitry Andric 404*0b57cec5SDimitry Andric private: 405*0b57cec5SDimitry Andric A &_addressSpace; 406*0b57cec5SDimitry Andric typename A::pint_t _addr; 407*0b57cec5SDimitry Andric }; 408*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 409*0b57cec5SDimitry Andric 410*0b57cec5SDimitry Andric class _LIBUNWIND_HIDDEN AbstractUnwindCursor { 411*0b57cec5SDimitry Andric public: 412*0b57cec5SDimitry Andric // NOTE: provide a class specific placement deallocation function (S5.3.4 p20) 413*0b57cec5SDimitry Andric // This avoids an unnecessary dependency to libc++abi. 414*0b57cec5SDimitry Andric void operator delete(void *, size_t) {} 415*0b57cec5SDimitry Andric 416*0b57cec5SDimitry Andric virtual ~AbstractUnwindCursor() {} 417*0b57cec5SDimitry Andric virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } 418*0b57cec5SDimitry Andric virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } 419*0b57cec5SDimitry Andric virtual void setReg(int, unw_word_t) { 420*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("setReg not implemented"); 421*0b57cec5SDimitry Andric } 422*0b57cec5SDimitry Andric virtual bool validFloatReg(int) { 423*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("validFloatReg not implemented"); 424*0b57cec5SDimitry Andric } 425*0b57cec5SDimitry Andric virtual unw_fpreg_t getFloatReg(int) { 426*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("getFloatReg not implemented"); 427*0b57cec5SDimitry Andric } 428*0b57cec5SDimitry Andric virtual void setFloatReg(int, unw_fpreg_t) { 429*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("setFloatReg not implemented"); 430*0b57cec5SDimitry Andric } 431*0b57cec5SDimitry Andric virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } 432*0b57cec5SDimitry Andric virtual void getInfo(unw_proc_info_t *) { 433*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("getInfo not implemented"); 434*0b57cec5SDimitry Andric } 435*0b57cec5SDimitry Andric virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } 436*0b57cec5SDimitry Andric virtual bool isSignalFrame() { 437*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("isSignalFrame not implemented"); 438*0b57cec5SDimitry Andric } 439*0b57cec5SDimitry Andric virtual bool getFunctionName(char *, size_t, unw_word_t *) { 440*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("getFunctionName not implemented"); 441*0b57cec5SDimitry Andric } 442*0b57cec5SDimitry Andric virtual void setInfoBasedOnIPRegister(bool = false) { 443*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented"); 444*0b57cec5SDimitry Andric } 445*0b57cec5SDimitry Andric virtual const char *getRegisterName(int) { 446*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("getRegisterName not implemented"); 447*0b57cec5SDimitry Andric } 448*0b57cec5SDimitry Andric #ifdef __arm__ 449*0b57cec5SDimitry Andric virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } 450*0b57cec5SDimitry Andric #endif 451*0b57cec5SDimitry Andric }; 452*0b57cec5SDimitry Andric 453*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32) 454*0b57cec5SDimitry Andric 455*0b57cec5SDimitry Andric /// \c UnwindCursor contains all state (including all register values) during 456*0b57cec5SDimitry Andric /// an unwind. This is normally stack-allocated inside a unw_cursor_t. 457*0b57cec5SDimitry Andric template <typename A, typename R> 458*0b57cec5SDimitry Andric class UnwindCursor : public AbstractUnwindCursor { 459*0b57cec5SDimitry Andric typedef typename A::pint_t pint_t; 460*0b57cec5SDimitry Andric public: 461*0b57cec5SDimitry Andric UnwindCursor(unw_context_t *context, A &as); 462*0b57cec5SDimitry Andric UnwindCursor(CONTEXT *context, A &as); 463*0b57cec5SDimitry Andric UnwindCursor(A &as, void *threadArg); 464*0b57cec5SDimitry Andric virtual ~UnwindCursor() {} 465*0b57cec5SDimitry Andric virtual bool validReg(int); 466*0b57cec5SDimitry Andric virtual unw_word_t getReg(int); 467*0b57cec5SDimitry Andric virtual void setReg(int, unw_word_t); 468*0b57cec5SDimitry Andric virtual bool validFloatReg(int); 469*0b57cec5SDimitry Andric virtual unw_fpreg_t getFloatReg(int); 470*0b57cec5SDimitry Andric virtual void setFloatReg(int, unw_fpreg_t); 471*0b57cec5SDimitry Andric virtual int step(); 472*0b57cec5SDimitry Andric virtual void getInfo(unw_proc_info_t *); 473*0b57cec5SDimitry Andric virtual void jumpto(); 474*0b57cec5SDimitry Andric virtual bool isSignalFrame(); 475*0b57cec5SDimitry Andric virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); 476*0b57cec5SDimitry Andric virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); 477*0b57cec5SDimitry Andric virtual const char *getRegisterName(int num); 478*0b57cec5SDimitry Andric #ifdef __arm__ 479*0b57cec5SDimitry Andric virtual void saveVFPAsX(); 480*0b57cec5SDimitry Andric #endif 481*0b57cec5SDimitry Andric 482*0b57cec5SDimitry Andric DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; } 483*0b57cec5SDimitry Andric void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; } 484*0b57cec5SDimitry Andric 485*0b57cec5SDimitry Andric // libunwind does not and should not depend on C++ library which means that we 486*0b57cec5SDimitry Andric // need our own defition of inline placement new. 487*0b57cec5SDimitry Andric static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; } 488*0b57cec5SDimitry Andric 489*0b57cec5SDimitry Andric private: 490*0b57cec5SDimitry Andric 491*0b57cec5SDimitry Andric pint_t getLastPC() const { return _dispContext.ControlPc; } 492*0b57cec5SDimitry Andric void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; } 493*0b57cec5SDimitry Andric RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { 494*0b57cec5SDimitry Andric _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc, 495*0b57cec5SDimitry Andric &_dispContext.ImageBase, 496*0b57cec5SDimitry Andric _dispContext.HistoryTable); 497*0b57cec5SDimitry Andric *base = _dispContext.ImageBase; 498*0b57cec5SDimitry Andric return _dispContext.FunctionEntry; 499*0b57cec5SDimitry Andric } 500*0b57cec5SDimitry Andric bool getInfoFromSEH(pint_t pc); 501*0b57cec5SDimitry Andric int stepWithSEHData() { 502*0b57cec5SDimitry Andric _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER, 503*0b57cec5SDimitry Andric _dispContext.ImageBase, 504*0b57cec5SDimitry Andric _dispContext.ControlPc, 505*0b57cec5SDimitry Andric _dispContext.FunctionEntry, 506*0b57cec5SDimitry Andric _dispContext.ContextRecord, 507*0b57cec5SDimitry Andric &_dispContext.HandlerData, 508*0b57cec5SDimitry Andric &_dispContext.EstablisherFrame, 509*0b57cec5SDimitry Andric NULL); 510*0b57cec5SDimitry Andric // Update some fields of the unwind info now, since we have them. 511*0b57cec5SDimitry Andric _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData); 512*0b57cec5SDimitry Andric if (_dispContext.LanguageHandler) { 513*0b57cec5SDimitry Andric _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality); 514*0b57cec5SDimitry Andric } else 515*0b57cec5SDimitry Andric _info.handler = 0; 516*0b57cec5SDimitry Andric return UNW_STEP_SUCCESS; 517*0b57cec5SDimitry Andric } 518*0b57cec5SDimitry Andric 519*0b57cec5SDimitry Andric A &_addressSpace; 520*0b57cec5SDimitry Andric unw_proc_info_t _info; 521*0b57cec5SDimitry Andric DISPATCHER_CONTEXT _dispContext; 522*0b57cec5SDimitry Andric CONTEXT _msContext; 523*0b57cec5SDimitry Andric UNWIND_HISTORY_TABLE _histTable; 524*0b57cec5SDimitry Andric bool _unwindInfoMissing; 525*0b57cec5SDimitry Andric }; 526*0b57cec5SDimitry Andric 527*0b57cec5SDimitry Andric 528*0b57cec5SDimitry Andric template <typename A, typename R> 529*0b57cec5SDimitry Andric UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) 530*0b57cec5SDimitry Andric : _addressSpace(as), _unwindInfoMissing(false) { 531*0b57cec5SDimitry Andric static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), 532*0b57cec5SDimitry Andric "UnwindCursor<> does not fit in unw_cursor_t"); 533*0b57cec5SDimitry Andric memset(&_info, 0, sizeof(_info)); 534*0b57cec5SDimitry Andric memset(&_histTable, 0, sizeof(_histTable)); 535*0b57cec5SDimitry Andric _dispContext.ContextRecord = &_msContext; 536*0b57cec5SDimitry Andric _dispContext.HistoryTable = &_histTable; 537*0b57cec5SDimitry Andric // Initialize MS context from ours. 538*0b57cec5SDimitry Andric R r(context); 539*0b57cec5SDimitry Andric _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT; 540*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64) 541*0b57cec5SDimitry Andric _msContext.Rax = r.getRegister(UNW_X86_64_RAX); 542*0b57cec5SDimitry Andric _msContext.Rcx = r.getRegister(UNW_X86_64_RCX); 543*0b57cec5SDimitry Andric _msContext.Rdx = r.getRegister(UNW_X86_64_RDX); 544*0b57cec5SDimitry Andric _msContext.Rbx = r.getRegister(UNW_X86_64_RBX); 545*0b57cec5SDimitry Andric _msContext.Rsp = r.getRegister(UNW_X86_64_RSP); 546*0b57cec5SDimitry Andric _msContext.Rbp = r.getRegister(UNW_X86_64_RBP); 547*0b57cec5SDimitry Andric _msContext.Rsi = r.getRegister(UNW_X86_64_RSI); 548*0b57cec5SDimitry Andric _msContext.Rdi = r.getRegister(UNW_X86_64_RDI); 549*0b57cec5SDimitry Andric _msContext.R8 = r.getRegister(UNW_X86_64_R8); 550*0b57cec5SDimitry Andric _msContext.R9 = r.getRegister(UNW_X86_64_R9); 551*0b57cec5SDimitry Andric _msContext.R10 = r.getRegister(UNW_X86_64_R10); 552*0b57cec5SDimitry Andric _msContext.R11 = r.getRegister(UNW_X86_64_R11); 553*0b57cec5SDimitry Andric _msContext.R12 = r.getRegister(UNW_X86_64_R12); 554*0b57cec5SDimitry Andric _msContext.R13 = r.getRegister(UNW_X86_64_R13); 555*0b57cec5SDimitry Andric _msContext.R14 = r.getRegister(UNW_X86_64_R14); 556*0b57cec5SDimitry Andric _msContext.R15 = r.getRegister(UNW_X86_64_R15); 557*0b57cec5SDimitry Andric _msContext.Rip = r.getRegister(UNW_REG_IP); 558*0b57cec5SDimitry Andric union { 559*0b57cec5SDimitry Andric v128 v; 560*0b57cec5SDimitry Andric M128A m; 561*0b57cec5SDimitry Andric } t; 562*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM0); 563*0b57cec5SDimitry Andric _msContext.Xmm0 = t.m; 564*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM1); 565*0b57cec5SDimitry Andric _msContext.Xmm1 = t.m; 566*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM2); 567*0b57cec5SDimitry Andric _msContext.Xmm2 = t.m; 568*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM3); 569*0b57cec5SDimitry Andric _msContext.Xmm3 = t.m; 570*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM4); 571*0b57cec5SDimitry Andric _msContext.Xmm4 = t.m; 572*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM5); 573*0b57cec5SDimitry Andric _msContext.Xmm5 = t.m; 574*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM6); 575*0b57cec5SDimitry Andric _msContext.Xmm6 = t.m; 576*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM7); 577*0b57cec5SDimitry Andric _msContext.Xmm7 = t.m; 578*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM8); 579*0b57cec5SDimitry Andric _msContext.Xmm8 = t.m; 580*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM9); 581*0b57cec5SDimitry Andric _msContext.Xmm9 = t.m; 582*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM10); 583*0b57cec5SDimitry Andric _msContext.Xmm10 = t.m; 584*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM11); 585*0b57cec5SDimitry Andric _msContext.Xmm11 = t.m; 586*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM12); 587*0b57cec5SDimitry Andric _msContext.Xmm12 = t.m; 588*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM13); 589*0b57cec5SDimitry Andric _msContext.Xmm13 = t.m; 590*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM14); 591*0b57cec5SDimitry Andric _msContext.Xmm14 = t.m; 592*0b57cec5SDimitry Andric t.v = r.getVectorRegister(UNW_X86_64_XMM15); 593*0b57cec5SDimitry Andric _msContext.Xmm15 = t.m; 594*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_ARM) 595*0b57cec5SDimitry Andric _msContext.R0 = r.getRegister(UNW_ARM_R0); 596*0b57cec5SDimitry Andric _msContext.R1 = r.getRegister(UNW_ARM_R1); 597*0b57cec5SDimitry Andric _msContext.R2 = r.getRegister(UNW_ARM_R2); 598*0b57cec5SDimitry Andric _msContext.R3 = r.getRegister(UNW_ARM_R3); 599*0b57cec5SDimitry Andric _msContext.R4 = r.getRegister(UNW_ARM_R4); 600*0b57cec5SDimitry Andric _msContext.R5 = r.getRegister(UNW_ARM_R5); 601*0b57cec5SDimitry Andric _msContext.R6 = r.getRegister(UNW_ARM_R6); 602*0b57cec5SDimitry Andric _msContext.R7 = r.getRegister(UNW_ARM_R7); 603*0b57cec5SDimitry Andric _msContext.R8 = r.getRegister(UNW_ARM_R8); 604*0b57cec5SDimitry Andric _msContext.R9 = r.getRegister(UNW_ARM_R9); 605*0b57cec5SDimitry Andric _msContext.R10 = r.getRegister(UNW_ARM_R10); 606*0b57cec5SDimitry Andric _msContext.R11 = r.getRegister(UNW_ARM_R11); 607*0b57cec5SDimitry Andric _msContext.R12 = r.getRegister(UNW_ARM_R12); 608*0b57cec5SDimitry Andric _msContext.Sp = r.getRegister(UNW_ARM_SP); 609*0b57cec5SDimitry Andric _msContext.Lr = r.getRegister(UNW_ARM_LR); 610*0b57cec5SDimitry Andric _msContext.Pc = r.getRegister(UNW_ARM_IP); 611*0b57cec5SDimitry Andric for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) { 612*0b57cec5SDimitry Andric union { 613*0b57cec5SDimitry Andric uint64_t w; 614*0b57cec5SDimitry Andric double d; 615*0b57cec5SDimitry Andric } d; 616*0b57cec5SDimitry Andric d.d = r.getFloatRegister(i); 617*0b57cec5SDimitry Andric _msContext.D[i - UNW_ARM_D0] = d.w; 618*0b57cec5SDimitry Andric } 619*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_AARCH64) 620*0b57cec5SDimitry Andric for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i) 621*0b57cec5SDimitry Andric _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i); 622*0b57cec5SDimitry Andric _msContext.Sp = r.getRegister(UNW_REG_SP); 623*0b57cec5SDimitry Andric _msContext.Pc = r.getRegister(UNW_REG_IP); 624*0b57cec5SDimitry Andric for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i) 625*0b57cec5SDimitry Andric _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i); 626*0b57cec5SDimitry Andric #endif 627*0b57cec5SDimitry Andric } 628*0b57cec5SDimitry Andric 629*0b57cec5SDimitry Andric template <typename A, typename R> 630*0b57cec5SDimitry Andric UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as) 631*0b57cec5SDimitry Andric : _addressSpace(as), _unwindInfoMissing(false) { 632*0b57cec5SDimitry Andric static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), 633*0b57cec5SDimitry Andric "UnwindCursor<> does not fit in unw_cursor_t"); 634*0b57cec5SDimitry Andric memset(&_info, 0, sizeof(_info)); 635*0b57cec5SDimitry Andric memset(&_histTable, 0, sizeof(_histTable)); 636*0b57cec5SDimitry Andric _dispContext.ContextRecord = &_msContext; 637*0b57cec5SDimitry Andric _dispContext.HistoryTable = &_histTable; 638*0b57cec5SDimitry Andric _msContext = *context; 639*0b57cec5SDimitry Andric } 640*0b57cec5SDimitry Andric 641*0b57cec5SDimitry Andric 642*0b57cec5SDimitry Andric template <typename A, typename R> 643*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::validReg(int regNum) { 644*0b57cec5SDimitry Andric if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true; 645*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64) 646*0b57cec5SDimitry Andric if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true; 647*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_ARM) 648*0b57cec5SDimitry Andric if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true; 649*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_AARCH64) 650*0b57cec5SDimitry Andric if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true; 651*0b57cec5SDimitry Andric #endif 652*0b57cec5SDimitry Andric return false; 653*0b57cec5SDimitry Andric } 654*0b57cec5SDimitry Andric 655*0b57cec5SDimitry Andric template <typename A, typename R> 656*0b57cec5SDimitry Andric unw_word_t UnwindCursor<A, R>::getReg(int regNum) { 657*0b57cec5SDimitry Andric switch (regNum) { 658*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64) 659*0b57cec5SDimitry Andric case UNW_REG_IP: return _msContext.Rip; 660*0b57cec5SDimitry Andric case UNW_X86_64_RAX: return _msContext.Rax; 661*0b57cec5SDimitry Andric case UNW_X86_64_RDX: return _msContext.Rdx; 662*0b57cec5SDimitry Andric case UNW_X86_64_RCX: return _msContext.Rcx; 663*0b57cec5SDimitry Andric case UNW_X86_64_RBX: return _msContext.Rbx; 664*0b57cec5SDimitry Andric case UNW_REG_SP: 665*0b57cec5SDimitry Andric case UNW_X86_64_RSP: return _msContext.Rsp; 666*0b57cec5SDimitry Andric case UNW_X86_64_RBP: return _msContext.Rbp; 667*0b57cec5SDimitry Andric case UNW_X86_64_RSI: return _msContext.Rsi; 668*0b57cec5SDimitry Andric case UNW_X86_64_RDI: return _msContext.Rdi; 669*0b57cec5SDimitry Andric case UNW_X86_64_R8: return _msContext.R8; 670*0b57cec5SDimitry Andric case UNW_X86_64_R9: return _msContext.R9; 671*0b57cec5SDimitry Andric case UNW_X86_64_R10: return _msContext.R10; 672*0b57cec5SDimitry Andric case UNW_X86_64_R11: return _msContext.R11; 673*0b57cec5SDimitry Andric case UNW_X86_64_R12: return _msContext.R12; 674*0b57cec5SDimitry Andric case UNW_X86_64_R13: return _msContext.R13; 675*0b57cec5SDimitry Andric case UNW_X86_64_R14: return _msContext.R14; 676*0b57cec5SDimitry Andric case UNW_X86_64_R15: return _msContext.R15; 677*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_ARM) 678*0b57cec5SDimitry Andric case UNW_ARM_R0: return _msContext.R0; 679*0b57cec5SDimitry Andric case UNW_ARM_R1: return _msContext.R1; 680*0b57cec5SDimitry Andric case UNW_ARM_R2: return _msContext.R2; 681*0b57cec5SDimitry Andric case UNW_ARM_R3: return _msContext.R3; 682*0b57cec5SDimitry Andric case UNW_ARM_R4: return _msContext.R4; 683*0b57cec5SDimitry Andric case UNW_ARM_R5: return _msContext.R5; 684*0b57cec5SDimitry Andric case UNW_ARM_R6: return _msContext.R6; 685*0b57cec5SDimitry Andric case UNW_ARM_R7: return _msContext.R7; 686*0b57cec5SDimitry Andric case UNW_ARM_R8: return _msContext.R8; 687*0b57cec5SDimitry Andric case UNW_ARM_R9: return _msContext.R9; 688*0b57cec5SDimitry Andric case UNW_ARM_R10: return _msContext.R10; 689*0b57cec5SDimitry Andric case UNW_ARM_R11: return _msContext.R11; 690*0b57cec5SDimitry Andric case UNW_ARM_R12: return _msContext.R12; 691*0b57cec5SDimitry Andric case UNW_REG_SP: 692*0b57cec5SDimitry Andric case UNW_ARM_SP: return _msContext.Sp; 693*0b57cec5SDimitry Andric case UNW_ARM_LR: return _msContext.Lr; 694*0b57cec5SDimitry Andric case UNW_REG_IP: 695*0b57cec5SDimitry Andric case UNW_ARM_IP: return _msContext.Pc; 696*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_AARCH64) 697*0b57cec5SDimitry Andric case UNW_REG_SP: return _msContext.Sp; 698*0b57cec5SDimitry Andric case UNW_REG_IP: return _msContext.Pc; 699*0b57cec5SDimitry Andric default: return _msContext.X[regNum - UNW_ARM64_X0]; 700*0b57cec5SDimitry Andric #endif 701*0b57cec5SDimitry Andric } 702*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported register"); 703*0b57cec5SDimitry Andric } 704*0b57cec5SDimitry Andric 705*0b57cec5SDimitry Andric template <typename A, typename R> 706*0b57cec5SDimitry Andric void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) { 707*0b57cec5SDimitry Andric switch (regNum) { 708*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64) 709*0b57cec5SDimitry Andric case UNW_REG_IP: _msContext.Rip = value; break; 710*0b57cec5SDimitry Andric case UNW_X86_64_RAX: _msContext.Rax = value; break; 711*0b57cec5SDimitry Andric case UNW_X86_64_RDX: _msContext.Rdx = value; break; 712*0b57cec5SDimitry Andric case UNW_X86_64_RCX: _msContext.Rcx = value; break; 713*0b57cec5SDimitry Andric case UNW_X86_64_RBX: _msContext.Rbx = value; break; 714*0b57cec5SDimitry Andric case UNW_REG_SP: 715*0b57cec5SDimitry Andric case UNW_X86_64_RSP: _msContext.Rsp = value; break; 716*0b57cec5SDimitry Andric case UNW_X86_64_RBP: _msContext.Rbp = value; break; 717*0b57cec5SDimitry Andric case UNW_X86_64_RSI: _msContext.Rsi = value; break; 718*0b57cec5SDimitry Andric case UNW_X86_64_RDI: _msContext.Rdi = value; break; 719*0b57cec5SDimitry Andric case UNW_X86_64_R8: _msContext.R8 = value; break; 720*0b57cec5SDimitry Andric case UNW_X86_64_R9: _msContext.R9 = value; break; 721*0b57cec5SDimitry Andric case UNW_X86_64_R10: _msContext.R10 = value; break; 722*0b57cec5SDimitry Andric case UNW_X86_64_R11: _msContext.R11 = value; break; 723*0b57cec5SDimitry Andric case UNW_X86_64_R12: _msContext.R12 = value; break; 724*0b57cec5SDimitry Andric case UNW_X86_64_R13: _msContext.R13 = value; break; 725*0b57cec5SDimitry Andric case UNW_X86_64_R14: _msContext.R14 = value; break; 726*0b57cec5SDimitry Andric case UNW_X86_64_R15: _msContext.R15 = value; break; 727*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_ARM) 728*0b57cec5SDimitry Andric case UNW_ARM_R0: _msContext.R0 = value; break; 729*0b57cec5SDimitry Andric case UNW_ARM_R1: _msContext.R1 = value; break; 730*0b57cec5SDimitry Andric case UNW_ARM_R2: _msContext.R2 = value; break; 731*0b57cec5SDimitry Andric case UNW_ARM_R3: _msContext.R3 = value; break; 732*0b57cec5SDimitry Andric case UNW_ARM_R4: _msContext.R4 = value; break; 733*0b57cec5SDimitry Andric case UNW_ARM_R5: _msContext.R5 = value; break; 734*0b57cec5SDimitry Andric case UNW_ARM_R6: _msContext.R6 = value; break; 735*0b57cec5SDimitry Andric case UNW_ARM_R7: _msContext.R7 = value; break; 736*0b57cec5SDimitry Andric case UNW_ARM_R8: _msContext.R8 = value; break; 737*0b57cec5SDimitry Andric case UNW_ARM_R9: _msContext.R9 = value; break; 738*0b57cec5SDimitry Andric case UNW_ARM_R10: _msContext.R10 = value; break; 739*0b57cec5SDimitry Andric case UNW_ARM_R11: _msContext.R11 = value; break; 740*0b57cec5SDimitry Andric case UNW_ARM_R12: _msContext.R12 = value; break; 741*0b57cec5SDimitry Andric case UNW_REG_SP: 742*0b57cec5SDimitry Andric case UNW_ARM_SP: _msContext.Sp = value; break; 743*0b57cec5SDimitry Andric case UNW_ARM_LR: _msContext.Lr = value; break; 744*0b57cec5SDimitry Andric case UNW_REG_IP: 745*0b57cec5SDimitry Andric case UNW_ARM_IP: _msContext.Pc = value; break; 746*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_AARCH64) 747*0b57cec5SDimitry Andric case UNW_REG_SP: _msContext.Sp = value; break; 748*0b57cec5SDimitry Andric case UNW_REG_IP: _msContext.Pc = value; break; 749*0b57cec5SDimitry Andric case UNW_ARM64_X0: 750*0b57cec5SDimitry Andric case UNW_ARM64_X1: 751*0b57cec5SDimitry Andric case UNW_ARM64_X2: 752*0b57cec5SDimitry Andric case UNW_ARM64_X3: 753*0b57cec5SDimitry Andric case UNW_ARM64_X4: 754*0b57cec5SDimitry Andric case UNW_ARM64_X5: 755*0b57cec5SDimitry Andric case UNW_ARM64_X6: 756*0b57cec5SDimitry Andric case UNW_ARM64_X7: 757*0b57cec5SDimitry Andric case UNW_ARM64_X8: 758*0b57cec5SDimitry Andric case UNW_ARM64_X9: 759*0b57cec5SDimitry Andric case UNW_ARM64_X10: 760*0b57cec5SDimitry Andric case UNW_ARM64_X11: 761*0b57cec5SDimitry Andric case UNW_ARM64_X12: 762*0b57cec5SDimitry Andric case UNW_ARM64_X13: 763*0b57cec5SDimitry Andric case UNW_ARM64_X14: 764*0b57cec5SDimitry Andric case UNW_ARM64_X15: 765*0b57cec5SDimitry Andric case UNW_ARM64_X16: 766*0b57cec5SDimitry Andric case UNW_ARM64_X17: 767*0b57cec5SDimitry Andric case UNW_ARM64_X18: 768*0b57cec5SDimitry Andric case UNW_ARM64_X19: 769*0b57cec5SDimitry Andric case UNW_ARM64_X20: 770*0b57cec5SDimitry Andric case UNW_ARM64_X21: 771*0b57cec5SDimitry Andric case UNW_ARM64_X22: 772*0b57cec5SDimitry Andric case UNW_ARM64_X23: 773*0b57cec5SDimitry Andric case UNW_ARM64_X24: 774*0b57cec5SDimitry Andric case UNW_ARM64_X25: 775*0b57cec5SDimitry Andric case UNW_ARM64_X26: 776*0b57cec5SDimitry Andric case UNW_ARM64_X27: 777*0b57cec5SDimitry Andric case UNW_ARM64_X28: 778*0b57cec5SDimitry Andric case UNW_ARM64_FP: 779*0b57cec5SDimitry Andric case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; 780*0b57cec5SDimitry Andric #endif 781*0b57cec5SDimitry Andric default: 782*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported register"); 783*0b57cec5SDimitry Andric } 784*0b57cec5SDimitry Andric } 785*0b57cec5SDimitry Andric 786*0b57cec5SDimitry Andric template <typename A, typename R> 787*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::validFloatReg(int regNum) { 788*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_ARM) 789*0b57cec5SDimitry Andric if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true; 790*0b57cec5SDimitry Andric if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true; 791*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_AARCH64) 792*0b57cec5SDimitry Andric if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true; 793*0b57cec5SDimitry Andric #else 794*0b57cec5SDimitry Andric (void)regNum; 795*0b57cec5SDimitry Andric #endif 796*0b57cec5SDimitry Andric return false; 797*0b57cec5SDimitry Andric } 798*0b57cec5SDimitry Andric 799*0b57cec5SDimitry Andric template <typename A, typename R> 800*0b57cec5SDimitry Andric unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) { 801*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_ARM) 802*0b57cec5SDimitry Andric if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { 803*0b57cec5SDimitry Andric union { 804*0b57cec5SDimitry Andric uint32_t w; 805*0b57cec5SDimitry Andric float f; 806*0b57cec5SDimitry Andric } d; 807*0b57cec5SDimitry Andric d.w = _msContext.S[regNum - UNW_ARM_S0]; 808*0b57cec5SDimitry Andric return d.f; 809*0b57cec5SDimitry Andric } 810*0b57cec5SDimitry Andric if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { 811*0b57cec5SDimitry Andric union { 812*0b57cec5SDimitry Andric uint64_t w; 813*0b57cec5SDimitry Andric double d; 814*0b57cec5SDimitry Andric } d; 815*0b57cec5SDimitry Andric d.w = _msContext.D[regNum - UNW_ARM_D0]; 816*0b57cec5SDimitry Andric return d.d; 817*0b57cec5SDimitry Andric } 818*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported float register"); 819*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_AARCH64) 820*0b57cec5SDimitry Andric return _msContext.V[regNum - UNW_ARM64_D0].D[0]; 821*0b57cec5SDimitry Andric #else 822*0b57cec5SDimitry Andric (void)regNum; 823*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("float registers unimplemented"); 824*0b57cec5SDimitry Andric #endif 825*0b57cec5SDimitry Andric } 826*0b57cec5SDimitry Andric 827*0b57cec5SDimitry Andric template <typename A, typename R> 828*0b57cec5SDimitry Andric void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { 829*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_ARM) 830*0b57cec5SDimitry Andric if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) { 831*0b57cec5SDimitry Andric union { 832*0b57cec5SDimitry Andric uint32_t w; 833*0b57cec5SDimitry Andric float f; 834*0b57cec5SDimitry Andric } d; 835*0b57cec5SDimitry Andric d.f = value; 836*0b57cec5SDimitry Andric _msContext.S[regNum - UNW_ARM_S0] = d.w; 837*0b57cec5SDimitry Andric } 838*0b57cec5SDimitry Andric if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) { 839*0b57cec5SDimitry Andric union { 840*0b57cec5SDimitry Andric uint64_t w; 841*0b57cec5SDimitry Andric double d; 842*0b57cec5SDimitry Andric } d; 843*0b57cec5SDimitry Andric d.d = value; 844*0b57cec5SDimitry Andric _msContext.D[regNum - UNW_ARM_D0] = d.w; 845*0b57cec5SDimitry Andric } 846*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("unsupported float register"); 847*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_AARCH64) 848*0b57cec5SDimitry Andric _msContext.V[regNum - UNW_ARM64_D0].D[0] = value; 849*0b57cec5SDimitry Andric #else 850*0b57cec5SDimitry Andric (void)regNum; 851*0b57cec5SDimitry Andric (void)value; 852*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("float registers unimplemented"); 853*0b57cec5SDimitry Andric #endif 854*0b57cec5SDimitry Andric } 855*0b57cec5SDimitry Andric 856*0b57cec5SDimitry Andric template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { 857*0b57cec5SDimitry Andric RtlRestoreContext(&_msContext, nullptr); 858*0b57cec5SDimitry Andric } 859*0b57cec5SDimitry Andric 860*0b57cec5SDimitry Andric #ifdef __arm__ 861*0b57cec5SDimitry Andric template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {} 862*0b57cec5SDimitry Andric #endif 863*0b57cec5SDimitry Andric 864*0b57cec5SDimitry Andric template <typename A, typename R> 865*0b57cec5SDimitry Andric const char *UnwindCursor<A, R>::getRegisterName(int regNum) { 866*0b57cec5SDimitry Andric return R::getRegisterName(regNum); 867*0b57cec5SDimitry Andric } 868*0b57cec5SDimitry Andric 869*0b57cec5SDimitry Andric template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() { 870*0b57cec5SDimitry Andric return false; 871*0b57cec5SDimitry Andric } 872*0b57cec5SDimitry Andric 873*0b57cec5SDimitry Andric #else // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32) 874*0b57cec5SDimitry Andric 875*0b57cec5SDimitry Andric /// UnwindCursor contains all state (including all register values) during 876*0b57cec5SDimitry Andric /// an unwind. This is normally stack allocated inside a unw_cursor_t. 877*0b57cec5SDimitry Andric template <typename A, typename R> 878*0b57cec5SDimitry Andric class UnwindCursor : public AbstractUnwindCursor{ 879*0b57cec5SDimitry Andric typedef typename A::pint_t pint_t; 880*0b57cec5SDimitry Andric public: 881*0b57cec5SDimitry Andric UnwindCursor(unw_context_t *context, A &as); 882*0b57cec5SDimitry Andric UnwindCursor(A &as, void *threadArg); 883*0b57cec5SDimitry Andric virtual ~UnwindCursor() {} 884*0b57cec5SDimitry Andric virtual bool validReg(int); 885*0b57cec5SDimitry Andric virtual unw_word_t getReg(int); 886*0b57cec5SDimitry Andric virtual void setReg(int, unw_word_t); 887*0b57cec5SDimitry Andric virtual bool validFloatReg(int); 888*0b57cec5SDimitry Andric virtual unw_fpreg_t getFloatReg(int); 889*0b57cec5SDimitry Andric virtual void setFloatReg(int, unw_fpreg_t); 890*0b57cec5SDimitry Andric virtual int step(); 891*0b57cec5SDimitry Andric virtual void getInfo(unw_proc_info_t *); 892*0b57cec5SDimitry Andric virtual void jumpto(); 893*0b57cec5SDimitry Andric virtual bool isSignalFrame(); 894*0b57cec5SDimitry Andric virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); 895*0b57cec5SDimitry Andric virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); 896*0b57cec5SDimitry Andric virtual const char *getRegisterName(int num); 897*0b57cec5SDimitry Andric #ifdef __arm__ 898*0b57cec5SDimitry Andric virtual void saveVFPAsX(); 899*0b57cec5SDimitry Andric #endif 900*0b57cec5SDimitry Andric 901*0b57cec5SDimitry Andric // libunwind does not and should not depend on C++ library which means that we 902*0b57cec5SDimitry Andric // need our own defition of inline placement new. 903*0b57cec5SDimitry Andric static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; } 904*0b57cec5SDimitry Andric 905*0b57cec5SDimitry Andric private: 906*0b57cec5SDimitry Andric 907*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 908*0b57cec5SDimitry Andric bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); 909*0b57cec5SDimitry Andric 910*0b57cec5SDimitry Andric int stepWithEHABI() { 911*0b57cec5SDimitry Andric size_t len = 0; 912*0b57cec5SDimitry Andric size_t off = 0; 913*0b57cec5SDimitry Andric // FIXME: Calling decode_eht_entry() here is violating the libunwind 914*0b57cec5SDimitry Andric // abstraction layer. 915*0b57cec5SDimitry Andric const uint32_t *ehtp = 916*0b57cec5SDimitry Andric decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info), 917*0b57cec5SDimitry Andric &off, &len); 918*0b57cec5SDimitry Andric if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) != 919*0b57cec5SDimitry Andric _URC_CONTINUE_UNWIND) 920*0b57cec5SDimitry Andric return UNW_STEP_END; 921*0b57cec5SDimitry Andric return UNW_STEP_SUCCESS; 922*0b57cec5SDimitry Andric } 923*0b57cec5SDimitry Andric #endif 924*0b57cec5SDimitry Andric 925*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 926*0b57cec5SDimitry Andric bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, 927*0b57cec5SDimitry Andric uint32_t fdeSectionOffsetHint=0); 928*0b57cec5SDimitry Andric int stepWithDwarfFDE() { 929*0b57cec5SDimitry Andric return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace, 930*0b57cec5SDimitry Andric (pint_t)this->getReg(UNW_REG_IP), 931*0b57cec5SDimitry Andric (pint_t)_info.unwind_info, 932*0b57cec5SDimitry Andric _registers); 933*0b57cec5SDimitry Andric } 934*0b57cec5SDimitry Andric #endif 935*0b57cec5SDimitry Andric 936*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 937*0b57cec5SDimitry Andric bool getInfoFromCompactEncodingSection(pint_t pc, 938*0b57cec5SDimitry Andric const UnwindInfoSections §s); 939*0b57cec5SDimitry Andric int stepWithCompactEncoding() { 940*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 941*0b57cec5SDimitry Andric if ( compactSaysUseDwarf() ) 942*0b57cec5SDimitry Andric return stepWithDwarfFDE(); 943*0b57cec5SDimitry Andric #endif 944*0b57cec5SDimitry Andric R dummy; 945*0b57cec5SDimitry Andric return stepWithCompactEncoding(dummy); 946*0b57cec5SDimitry Andric } 947*0b57cec5SDimitry Andric 948*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64) 949*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_x86_64 &) { 950*0b57cec5SDimitry Andric return CompactUnwinder_x86_64<A>::stepWithCompactEncoding( 951*0b57cec5SDimitry Andric _info.format, _info.start_ip, _addressSpace, _registers); 952*0b57cec5SDimitry Andric } 953*0b57cec5SDimitry Andric #endif 954*0b57cec5SDimitry Andric 955*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_I386) 956*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_x86 &) { 957*0b57cec5SDimitry Andric return CompactUnwinder_x86<A>::stepWithCompactEncoding( 958*0b57cec5SDimitry Andric _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers); 959*0b57cec5SDimitry Andric } 960*0b57cec5SDimitry Andric #endif 961*0b57cec5SDimitry Andric 962*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC) 963*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_ppc &) { 964*0b57cec5SDimitry Andric return UNW_EINVAL; 965*0b57cec5SDimitry Andric } 966*0b57cec5SDimitry Andric #endif 967*0b57cec5SDimitry Andric 968*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC64) 969*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_ppc64 &) { 970*0b57cec5SDimitry Andric return UNW_EINVAL; 971*0b57cec5SDimitry Andric } 972*0b57cec5SDimitry Andric #endif 973*0b57cec5SDimitry Andric 974*0b57cec5SDimitry Andric 975*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_AARCH64) 976*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_arm64 &) { 977*0b57cec5SDimitry Andric return CompactUnwinder_arm64<A>::stepWithCompactEncoding( 978*0b57cec5SDimitry Andric _info.format, _info.start_ip, _addressSpace, _registers); 979*0b57cec5SDimitry Andric } 980*0b57cec5SDimitry Andric #endif 981*0b57cec5SDimitry Andric 982*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_MIPS_O32) 983*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_mips_o32 &) { 984*0b57cec5SDimitry Andric return UNW_EINVAL; 985*0b57cec5SDimitry Andric } 986*0b57cec5SDimitry Andric #endif 987*0b57cec5SDimitry Andric 988*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) 989*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_mips_newabi &) { 990*0b57cec5SDimitry Andric return UNW_EINVAL; 991*0b57cec5SDimitry Andric } 992*0b57cec5SDimitry Andric #endif 993*0b57cec5SDimitry Andric 994*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_SPARC) 995*0b57cec5SDimitry Andric int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } 996*0b57cec5SDimitry Andric #endif 997*0b57cec5SDimitry Andric 998*0b57cec5SDimitry Andric bool compactSaysUseDwarf(uint32_t *offset=NULL) const { 999*0b57cec5SDimitry Andric R dummy; 1000*0b57cec5SDimitry Andric return compactSaysUseDwarf(dummy, offset); 1001*0b57cec5SDimitry Andric } 1002*0b57cec5SDimitry Andric 1003*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64) 1004*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const { 1005*0b57cec5SDimitry Andric if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) { 1006*0b57cec5SDimitry Andric if (offset) 1007*0b57cec5SDimitry Andric *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET); 1008*0b57cec5SDimitry Andric return true; 1009*0b57cec5SDimitry Andric } 1010*0b57cec5SDimitry Andric return false; 1011*0b57cec5SDimitry Andric } 1012*0b57cec5SDimitry Andric #endif 1013*0b57cec5SDimitry Andric 1014*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_I386) 1015*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const { 1016*0b57cec5SDimitry Andric if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) { 1017*0b57cec5SDimitry Andric if (offset) 1018*0b57cec5SDimitry Andric *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET); 1019*0b57cec5SDimitry Andric return true; 1020*0b57cec5SDimitry Andric } 1021*0b57cec5SDimitry Andric return false; 1022*0b57cec5SDimitry Andric } 1023*0b57cec5SDimitry Andric #endif 1024*0b57cec5SDimitry Andric 1025*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC) 1026*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const { 1027*0b57cec5SDimitry Andric return true; 1028*0b57cec5SDimitry Andric } 1029*0b57cec5SDimitry Andric #endif 1030*0b57cec5SDimitry Andric 1031*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC64) 1032*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const { 1033*0b57cec5SDimitry Andric return true; 1034*0b57cec5SDimitry Andric } 1035*0b57cec5SDimitry Andric #endif 1036*0b57cec5SDimitry Andric 1037*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_AARCH64) 1038*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const { 1039*0b57cec5SDimitry Andric if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) { 1040*0b57cec5SDimitry Andric if (offset) 1041*0b57cec5SDimitry Andric *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET); 1042*0b57cec5SDimitry Andric return true; 1043*0b57cec5SDimitry Andric } 1044*0b57cec5SDimitry Andric return false; 1045*0b57cec5SDimitry Andric } 1046*0b57cec5SDimitry Andric #endif 1047*0b57cec5SDimitry Andric 1048*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_MIPS_O32) 1049*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const { 1050*0b57cec5SDimitry Andric return true; 1051*0b57cec5SDimitry Andric } 1052*0b57cec5SDimitry Andric #endif 1053*0b57cec5SDimitry Andric 1054*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) 1055*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const { 1056*0b57cec5SDimitry Andric return true; 1057*0b57cec5SDimitry Andric } 1058*0b57cec5SDimitry Andric #endif 1059*0b57cec5SDimitry Andric 1060*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_SPARC) 1061*0b57cec5SDimitry Andric bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } 1062*0b57cec5SDimitry Andric #endif 1063*0b57cec5SDimitry Andric 1064*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1065*0b57cec5SDimitry Andric 1066*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1067*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding() const { 1068*0b57cec5SDimitry Andric R dummy; 1069*0b57cec5SDimitry Andric return dwarfEncoding(dummy); 1070*0b57cec5SDimitry Andric } 1071*0b57cec5SDimitry Andric 1072*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_X86_64) 1073*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const { 1074*0b57cec5SDimitry Andric return UNWIND_X86_64_MODE_DWARF; 1075*0b57cec5SDimitry Andric } 1076*0b57cec5SDimitry Andric #endif 1077*0b57cec5SDimitry Andric 1078*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_I386) 1079*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const { 1080*0b57cec5SDimitry Andric return UNWIND_X86_MODE_DWARF; 1081*0b57cec5SDimitry Andric } 1082*0b57cec5SDimitry Andric #endif 1083*0b57cec5SDimitry Andric 1084*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC) 1085*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const { 1086*0b57cec5SDimitry Andric return 0; 1087*0b57cec5SDimitry Andric } 1088*0b57cec5SDimitry Andric #endif 1089*0b57cec5SDimitry Andric 1090*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_PPC64) 1091*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const { 1092*0b57cec5SDimitry Andric return 0; 1093*0b57cec5SDimitry Andric } 1094*0b57cec5SDimitry Andric #endif 1095*0b57cec5SDimitry Andric 1096*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_AARCH64) 1097*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { 1098*0b57cec5SDimitry Andric return UNWIND_ARM64_MODE_DWARF; 1099*0b57cec5SDimitry Andric } 1100*0b57cec5SDimitry Andric #endif 1101*0b57cec5SDimitry Andric 1102*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_ARM) 1103*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const { 1104*0b57cec5SDimitry Andric return 0; 1105*0b57cec5SDimitry Andric } 1106*0b57cec5SDimitry Andric #endif 1107*0b57cec5SDimitry Andric 1108*0b57cec5SDimitry Andric #if defined (_LIBUNWIND_TARGET_OR1K) 1109*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const { 1110*0b57cec5SDimitry Andric return 0; 1111*0b57cec5SDimitry Andric } 1112*0b57cec5SDimitry Andric #endif 1113*0b57cec5SDimitry Andric 1114*0b57cec5SDimitry Andric #if defined (_LIBUNWIND_TARGET_RISCV) 1115*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { 1116*0b57cec5SDimitry Andric return 0; 1117*0b57cec5SDimitry Andric } 1118*0b57cec5SDimitry Andric #endif 1119*0b57cec5SDimitry Andric 1120*0b57cec5SDimitry Andric #if defined (_LIBUNWIND_TARGET_MIPS_O32) 1121*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { 1122*0b57cec5SDimitry Andric return 0; 1123*0b57cec5SDimitry Andric } 1124*0b57cec5SDimitry Andric #endif 1125*0b57cec5SDimitry Andric 1126*0b57cec5SDimitry Andric #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI) 1127*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const { 1128*0b57cec5SDimitry Andric return 0; 1129*0b57cec5SDimitry Andric } 1130*0b57cec5SDimitry Andric #endif 1131*0b57cec5SDimitry Andric 1132*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_TARGET_SPARC) 1133*0b57cec5SDimitry Andric compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } 1134*0b57cec5SDimitry Andric #endif 1135*0b57cec5SDimitry Andric 1136*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1137*0b57cec5SDimitry Andric 1138*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 1139*0b57cec5SDimitry Andric // For runtime environments using SEH unwind data without Windows runtime 1140*0b57cec5SDimitry Andric // support. 1141*0b57cec5SDimitry Andric pint_t getLastPC() const { /* FIXME: Implement */ return 0; } 1142*0b57cec5SDimitry Andric void setLastPC(pint_t pc) { /* FIXME: Implement */ } 1143*0b57cec5SDimitry Andric RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) { 1144*0b57cec5SDimitry Andric /* FIXME: Implement */ 1145*0b57cec5SDimitry Andric *base = 0; 1146*0b57cec5SDimitry Andric return nullptr; 1147*0b57cec5SDimitry Andric } 1148*0b57cec5SDimitry Andric bool getInfoFromSEH(pint_t pc); 1149*0b57cec5SDimitry Andric int stepWithSEHData() { /* FIXME: Implement */ return 0; } 1150*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 1151*0b57cec5SDimitry Andric 1152*0b57cec5SDimitry Andric 1153*0b57cec5SDimitry Andric A &_addressSpace; 1154*0b57cec5SDimitry Andric R _registers; 1155*0b57cec5SDimitry Andric unw_proc_info_t _info; 1156*0b57cec5SDimitry Andric bool _unwindInfoMissing; 1157*0b57cec5SDimitry Andric bool _isSignalFrame; 1158*0b57cec5SDimitry Andric }; 1159*0b57cec5SDimitry Andric 1160*0b57cec5SDimitry Andric 1161*0b57cec5SDimitry Andric template <typename A, typename R> 1162*0b57cec5SDimitry Andric UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) 1163*0b57cec5SDimitry Andric : _addressSpace(as), _registers(context), _unwindInfoMissing(false), 1164*0b57cec5SDimitry Andric _isSignalFrame(false) { 1165*0b57cec5SDimitry Andric static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit), 1166*0b57cec5SDimitry Andric "UnwindCursor<> does not fit in unw_cursor_t"); 1167*0b57cec5SDimitry Andric memset(&_info, 0, sizeof(_info)); 1168*0b57cec5SDimitry Andric } 1169*0b57cec5SDimitry Andric 1170*0b57cec5SDimitry Andric template <typename A, typename R> 1171*0b57cec5SDimitry Andric UnwindCursor<A, R>::UnwindCursor(A &as, void *) 1172*0b57cec5SDimitry Andric : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { 1173*0b57cec5SDimitry Andric memset(&_info, 0, sizeof(_info)); 1174*0b57cec5SDimitry Andric // FIXME 1175*0b57cec5SDimitry Andric // fill in _registers from thread arg 1176*0b57cec5SDimitry Andric } 1177*0b57cec5SDimitry Andric 1178*0b57cec5SDimitry Andric 1179*0b57cec5SDimitry Andric template <typename A, typename R> 1180*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::validReg(int regNum) { 1181*0b57cec5SDimitry Andric return _registers.validRegister(regNum); 1182*0b57cec5SDimitry Andric } 1183*0b57cec5SDimitry Andric 1184*0b57cec5SDimitry Andric template <typename A, typename R> 1185*0b57cec5SDimitry Andric unw_word_t UnwindCursor<A, R>::getReg(int regNum) { 1186*0b57cec5SDimitry Andric return _registers.getRegister(regNum); 1187*0b57cec5SDimitry Andric } 1188*0b57cec5SDimitry Andric 1189*0b57cec5SDimitry Andric template <typename A, typename R> 1190*0b57cec5SDimitry Andric void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) { 1191*0b57cec5SDimitry Andric _registers.setRegister(regNum, (typename A::pint_t)value); 1192*0b57cec5SDimitry Andric } 1193*0b57cec5SDimitry Andric 1194*0b57cec5SDimitry Andric template <typename A, typename R> 1195*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::validFloatReg(int regNum) { 1196*0b57cec5SDimitry Andric return _registers.validFloatRegister(regNum); 1197*0b57cec5SDimitry Andric } 1198*0b57cec5SDimitry Andric 1199*0b57cec5SDimitry Andric template <typename A, typename R> 1200*0b57cec5SDimitry Andric unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) { 1201*0b57cec5SDimitry Andric return _registers.getFloatRegister(regNum); 1202*0b57cec5SDimitry Andric } 1203*0b57cec5SDimitry Andric 1204*0b57cec5SDimitry Andric template <typename A, typename R> 1205*0b57cec5SDimitry Andric void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { 1206*0b57cec5SDimitry Andric _registers.setFloatRegister(regNum, value); 1207*0b57cec5SDimitry Andric } 1208*0b57cec5SDimitry Andric 1209*0b57cec5SDimitry Andric template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { 1210*0b57cec5SDimitry Andric _registers.jumpto(); 1211*0b57cec5SDimitry Andric } 1212*0b57cec5SDimitry Andric 1213*0b57cec5SDimitry Andric #ifdef __arm__ 1214*0b57cec5SDimitry Andric template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() { 1215*0b57cec5SDimitry Andric _registers.saveVFPAsX(); 1216*0b57cec5SDimitry Andric } 1217*0b57cec5SDimitry Andric #endif 1218*0b57cec5SDimitry Andric 1219*0b57cec5SDimitry Andric template <typename A, typename R> 1220*0b57cec5SDimitry Andric const char *UnwindCursor<A, R>::getRegisterName(int regNum) { 1221*0b57cec5SDimitry Andric return _registers.getRegisterName(regNum); 1222*0b57cec5SDimitry Andric } 1223*0b57cec5SDimitry Andric 1224*0b57cec5SDimitry Andric template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() { 1225*0b57cec5SDimitry Andric return _isSignalFrame; 1226*0b57cec5SDimitry Andric } 1227*0b57cec5SDimitry Andric 1228*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 1229*0b57cec5SDimitry Andric 1230*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 1231*0b57cec5SDimitry Andric struct EHABIIndexEntry { 1232*0b57cec5SDimitry Andric uint32_t functionOffset; 1233*0b57cec5SDimitry Andric uint32_t data; 1234*0b57cec5SDimitry Andric }; 1235*0b57cec5SDimitry Andric 1236*0b57cec5SDimitry Andric template<typename A> 1237*0b57cec5SDimitry Andric struct EHABISectionIterator { 1238*0b57cec5SDimitry Andric typedef EHABISectionIterator _Self; 1239*0b57cec5SDimitry Andric 1240*0b57cec5SDimitry Andric typedef typename A::pint_t value_type; 1241*0b57cec5SDimitry Andric typedef typename A::pint_t* pointer; 1242*0b57cec5SDimitry Andric typedef typename A::pint_t& reference; 1243*0b57cec5SDimitry Andric typedef size_t size_type; 1244*0b57cec5SDimitry Andric typedef size_t difference_type; 1245*0b57cec5SDimitry Andric 1246*0b57cec5SDimitry Andric static _Self begin(A& addressSpace, const UnwindInfoSections& sects) { 1247*0b57cec5SDimitry Andric return _Self(addressSpace, sects, 0); 1248*0b57cec5SDimitry Andric } 1249*0b57cec5SDimitry Andric static _Self end(A& addressSpace, const UnwindInfoSections& sects) { 1250*0b57cec5SDimitry Andric return _Self(addressSpace, sects, 1251*0b57cec5SDimitry Andric sects.arm_section_length / sizeof(EHABIIndexEntry)); 1252*0b57cec5SDimitry Andric } 1253*0b57cec5SDimitry Andric 1254*0b57cec5SDimitry Andric EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i) 1255*0b57cec5SDimitry Andric : _i(i), _addressSpace(&addressSpace), _sects(§s) {} 1256*0b57cec5SDimitry Andric 1257*0b57cec5SDimitry Andric _Self& operator++() { ++_i; return *this; } 1258*0b57cec5SDimitry Andric _Self& operator+=(size_t a) { _i += a; return *this; } 1259*0b57cec5SDimitry Andric _Self& operator--() { assert(_i > 0); --_i; return *this; } 1260*0b57cec5SDimitry Andric _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; } 1261*0b57cec5SDimitry Andric 1262*0b57cec5SDimitry Andric _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } 1263*0b57cec5SDimitry Andric _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } 1264*0b57cec5SDimitry Andric 1265*0b57cec5SDimitry Andric size_t operator-(const _Self& other) { return _i - other._i; } 1266*0b57cec5SDimitry Andric 1267*0b57cec5SDimitry Andric bool operator==(const _Self& other) const { 1268*0b57cec5SDimitry Andric assert(_addressSpace == other._addressSpace); 1269*0b57cec5SDimitry Andric assert(_sects == other._sects); 1270*0b57cec5SDimitry Andric return _i == other._i; 1271*0b57cec5SDimitry Andric } 1272*0b57cec5SDimitry Andric 1273*0b57cec5SDimitry Andric typename A::pint_t operator*() const { return functionAddress(); } 1274*0b57cec5SDimitry Andric 1275*0b57cec5SDimitry Andric typename A::pint_t functionAddress() const { 1276*0b57cec5SDimitry Andric typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( 1277*0b57cec5SDimitry Andric EHABIIndexEntry, _i, functionOffset); 1278*0b57cec5SDimitry Andric return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr)); 1279*0b57cec5SDimitry Andric } 1280*0b57cec5SDimitry Andric 1281*0b57cec5SDimitry Andric typename A::pint_t dataAddress() { 1282*0b57cec5SDimitry Andric typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( 1283*0b57cec5SDimitry Andric EHABIIndexEntry, _i, data); 1284*0b57cec5SDimitry Andric return indexAddr; 1285*0b57cec5SDimitry Andric } 1286*0b57cec5SDimitry Andric 1287*0b57cec5SDimitry Andric private: 1288*0b57cec5SDimitry Andric size_t _i; 1289*0b57cec5SDimitry Andric A* _addressSpace; 1290*0b57cec5SDimitry Andric const UnwindInfoSections* _sects; 1291*0b57cec5SDimitry Andric }; 1292*0b57cec5SDimitry Andric 1293*0b57cec5SDimitry Andric namespace { 1294*0b57cec5SDimitry Andric 1295*0b57cec5SDimitry Andric template <typename A> 1296*0b57cec5SDimitry Andric EHABISectionIterator<A> EHABISectionUpperBound( 1297*0b57cec5SDimitry Andric EHABISectionIterator<A> first, 1298*0b57cec5SDimitry Andric EHABISectionIterator<A> last, 1299*0b57cec5SDimitry Andric typename A::pint_t value) { 1300*0b57cec5SDimitry Andric size_t len = last - first; 1301*0b57cec5SDimitry Andric while (len > 0) { 1302*0b57cec5SDimitry Andric size_t l2 = len / 2; 1303*0b57cec5SDimitry Andric EHABISectionIterator<A> m = first + l2; 1304*0b57cec5SDimitry Andric if (value < *m) { 1305*0b57cec5SDimitry Andric len = l2; 1306*0b57cec5SDimitry Andric } else { 1307*0b57cec5SDimitry Andric first = ++m; 1308*0b57cec5SDimitry Andric len -= l2 + 1; 1309*0b57cec5SDimitry Andric } 1310*0b57cec5SDimitry Andric } 1311*0b57cec5SDimitry Andric return first; 1312*0b57cec5SDimitry Andric } 1313*0b57cec5SDimitry Andric 1314*0b57cec5SDimitry Andric } 1315*0b57cec5SDimitry Andric 1316*0b57cec5SDimitry Andric template <typename A, typename R> 1317*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::getInfoFromEHABISection( 1318*0b57cec5SDimitry Andric pint_t pc, 1319*0b57cec5SDimitry Andric const UnwindInfoSections §s) { 1320*0b57cec5SDimitry Andric EHABISectionIterator<A> begin = 1321*0b57cec5SDimitry Andric EHABISectionIterator<A>::begin(_addressSpace, sects); 1322*0b57cec5SDimitry Andric EHABISectionIterator<A> end = 1323*0b57cec5SDimitry Andric EHABISectionIterator<A>::end(_addressSpace, sects); 1324*0b57cec5SDimitry Andric if (begin == end) 1325*0b57cec5SDimitry Andric return false; 1326*0b57cec5SDimitry Andric 1327*0b57cec5SDimitry Andric EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc); 1328*0b57cec5SDimitry Andric if (itNextPC == begin) 1329*0b57cec5SDimitry Andric return false; 1330*0b57cec5SDimitry Andric EHABISectionIterator<A> itThisPC = itNextPC - 1; 1331*0b57cec5SDimitry Andric 1332*0b57cec5SDimitry Andric pint_t thisPC = itThisPC.functionAddress(); 1333*0b57cec5SDimitry Andric // If an exception is thrown from a function, corresponding to the last entry 1334*0b57cec5SDimitry Andric // in the table, we don't really know the function extent and have to choose a 1335*0b57cec5SDimitry Andric // value for nextPC. Choosing max() will allow the range check during trace to 1336*0b57cec5SDimitry Andric // succeed. 1337*0b57cec5SDimitry Andric pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress(); 1338*0b57cec5SDimitry Andric pint_t indexDataAddr = itThisPC.dataAddress(); 1339*0b57cec5SDimitry Andric 1340*0b57cec5SDimitry Andric if (indexDataAddr == 0) 1341*0b57cec5SDimitry Andric return false; 1342*0b57cec5SDimitry Andric 1343*0b57cec5SDimitry Andric uint32_t indexData = _addressSpace.get32(indexDataAddr); 1344*0b57cec5SDimitry Andric if (indexData == UNW_EXIDX_CANTUNWIND) 1345*0b57cec5SDimitry Andric return false; 1346*0b57cec5SDimitry Andric 1347*0b57cec5SDimitry Andric // If the high bit is set, the exception handling table entry is inline inside 1348*0b57cec5SDimitry Andric // the index table entry on the second word (aka |indexDataAddr|). Otherwise, 1349*0b57cec5SDimitry Andric // the table points at an offset in the exception handling table (section 5 EHABI). 1350*0b57cec5SDimitry Andric pint_t exceptionTableAddr; 1351*0b57cec5SDimitry Andric uint32_t exceptionTableData; 1352*0b57cec5SDimitry Andric bool isSingleWordEHT; 1353*0b57cec5SDimitry Andric if (indexData & 0x80000000) { 1354*0b57cec5SDimitry Andric exceptionTableAddr = indexDataAddr; 1355*0b57cec5SDimitry Andric // TODO(ajwong): Should this data be 0? 1356*0b57cec5SDimitry Andric exceptionTableData = indexData; 1357*0b57cec5SDimitry Andric isSingleWordEHT = true; 1358*0b57cec5SDimitry Andric } else { 1359*0b57cec5SDimitry Andric exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData); 1360*0b57cec5SDimitry Andric exceptionTableData = _addressSpace.get32(exceptionTableAddr); 1361*0b57cec5SDimitry Andric isSingleWordEHT = false; 1362*0b57cec5SDimitry Andric } 1363*0b57cec5SDimitry Andric 1364*0b57cec5SDimitry Andric // Now we know the 3 things: 1365*0b57cec5SDimitry Andric // exceptionTableAddr -- exception handler table entry. 1366*0b57cec5SDimitry Andric // exceptionTableData -- the data inside the first word of the eht entry. 1367*0b57cec5SDimitry Andric // isSingleWordEHT -- whether the entry is in the index. 1368*0b57cec5SDimitry Andric unw_word_t personalityRoutine = 0xbadf00d; 1369*0b57cec5SDimitry Andric bool scope32 = false; 1370*0b57cec5SDimitry Andric uintptr_t lsda; 1371*0b57cec5SDimitry Andric 1372*0b57cec5SDimitry Andric // If the high bit in the exception handling table entry is set, the entry is 1373*0b57cec5SDimitry Andric // in compact form (section 6.3 EHABI). 1374*0b57cec5SDimitry Andric if (exceptionTableData & 0x80000000) { 1375*0b57cec5SDimitry Andric // Grab the index of the personality routine from the compact form. 1376*0b57cec5SDimitry Andric uint32_t choice = (exceptionTableData & 0x0f000000) >> 24; 1377*0b57cec5SDimitry Andric uint32_t extraWords = 0; 1378*0b57cec5SDimitry Andric switch (choice) { 1379*0b57cec5SDimitry Andric case 0: 1380*0b57cec5SDimitry Andric personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0; 1381*0b57cec5SDimitry Andric extraWords = 0; 1382*0b57cec5SDimitry Andric scope32 = false; 1383*0b57cec5SDimitry Andric lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4); 1384*0b57cec5SDimitry Andric break; 1385*0b57cec5SDimitry Andric case 1: 1386*0b57cec5SDimitry Andric personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1; 1387*0b57cec5SDimitry Andric extraWords = (exceptionTableData & 0x00ff0000) >> 16; 1388*0b57cec5SDimitry Andric scope32 = false; 1389*0b57cec5SDimitry Andric lsda = exceptionTableAddr + (extraWords + 1) * 4; 1390*0b57cec5SDimitry Andric break; 1391*0b57cec5SDimitry Andric case 2: 1392*0b57cec5SDimitry Andric personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2; 1393*0b57cec5SDimitry Andric extraWords = (exceptionTableData & 0x00ff0000) >> 16; 1394*0b57cec5SDimitry Andric scope32 = true; 1395*0b57cec5SDimitry Andric lsda = exceptionTableAddr + (extraWords + 1) * 4; 1396*0b57cec5SDimitry Andric break; 1397*0b57cec5SDimitry Andric default: 1398*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("unknown personality routine"); 1399*0b57cec5SDimitry Andric return false; 1400*0b57cec5SDimitry Andric } 1401*0b57cec5SDimitry Andric 1402*0b57cec5SDimitry Andric if (isSingleWordEHT) { 1403*0b57cec5SDimitry Andric if (extraWords != 0) { 1404*0b57cec5SDimitry Andric _LIBUNWIND_ABORT("index inlined table detected but pr function " 1405*0b57cec5SDimitry Andric "requires extra words"); 1406*0b57cec5SDimitry Andric return false; 1407*0b57cec5SDimitry Andric } 1408*0b57cec5SDimitry Andric } 1409*0b57cec5SDimitry Andric } else { 1410*0b57cec5SDimitry Andric pint_t personalityAddr = 1411*0b57cec5SDimitry Andric exceptionTableAddr + signExtendPrel31(exceptionTableData); 1412*0b57cec5SDimitry Andric personalityRoutine = personalityAddr; 1413*0b57cec5SDimitry Andric 1414*0b57cec5SDimitry Andric // ARM EHABI # 6.2, # 9.2 1415*0b57cec5SDimitry Andric // 1416*0b57cec5SDimitry Andric // +---- ehtp 1417*0b57cec5SDimitry Andric // v 1418*0b57cec5SDimitry Andric // +--------------------------------------+ 1419*0b57cec5SDimitry Andric // | +--------+--------+--------+-------+ | 1420*0b57cec5SDimitry Andric // | |0| prel31 to personalityRoutine | | 1421*0b57cec5SDimitry Andric // | +--------+--------+--------+-------+ | 1422*0b57cec5SDimitry Andric // | | N | unwind opcodes | | <-- UnwindData 1423*0b57cec5SDimitry Andric // | +--------+--------+--------+-------+ | 1424*0b57cec5SDimitry Andric // | | Word 2 unwind opcodes | | 1425*0b57cec5SDimitry Andric // | +--------+--------+--------+-------+ | 1426*0b57cec5SDimitry Andric // | ... | 1427*0b57cec5SDimitry Andric // | +--------+--------+--------+-------+ | 1428*0b57cec5SDimitry Andric // | | Word N unwind opcodes | | 1429*0b57cec5SDimitry Andric // | +--------+--------+--------+-------+ | 1430*0b57cec5SDimitry Andric // | | LSDA | | <-- lsda 1431*0b57cec5SDimitry Andric // | | ... | | 1432*0b57cec5SDimitry Andric // | +--------+--------+--------+-------+ | 1433*0b57cec5SDimitry Andric // +--------------------------------------+ 1434*0b57cec5SDimitry Andric 1435*0b57cec5SDimitry Andric uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1; 1436*0b57cec5SDimitry Andric uint32_t FirstDataWord = *UnwindData; 1437*0b57cec5SDimitry Andric size_t N = ((FirstDataWord >> 24) & 0xff); 1438*0b57cec5SDimitry Andric size_t NDataWords = N + 1; 1439*0b57cec5SDimitry Andric lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords); 1440*0b57cec5SDimitry Andric } 1441*0b57cec5SDimitry Andric 1442*0b57cec5SDimitry Andric _info.start_ip = thisPC; 1443*0b57cec5SDimitry Andric _info.end_ip = nextPC; 1444*0b57cec5SDimitry Andric _info.handler = personalityRoutine; 1445*0b57cec5SDimitry Andric _info.unwind_info = exceptionTableAddr; 1446*0b57cec5SDimitry Andric _info.lsda = lsda; 1447*0b57cec5SDimitry Andric // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. 1448*0b57cec5SDimitry Andric _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum? 1449*0b57cec5SDimitry Andric 1450*0b57cec5SDimitry Andric return true; 1451*0b57cec5SDimitry Andric } 1452*0b57cec5SDimitry Andric #endif 1453*0b57cec5SDimitry Andric 1454*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1455*0b57cec5SDimitry Andric template <typename A, typename R> 1456*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, 1457*0b57cec5SDimitry Andric const UnwindInfoSections §s, 1458*0b57cec5SDimitry Andric uint32_t fdeSectionOffsetHint) { 1459*0b57cec5SDimitry Andric typename CFI_Parser<A>::FDE_Info fdeInfo; 1460*0b57cec5SDimitry Andric typename CFI_Parser<A>::CIE_Info cieInfo; 1461*0b57cec5SDimitry Andric bool foundFDE = false; 1462*0b57cec5SDimitry Andric bool foundInCache = false; 1463*0b57cec5SDimitry Andric // If compact encoding table gave offset into dwarf section, go directly there 1464*0b57cec5SDimitry Andric if (fdeSectionOffsetHint != 0) { 1465*0b57cec5SDimitry Andric foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, 1466*0b57cec5SDimitry Andric (uint32_t)sects.dwarf_section_length, 1467*0b57cec5SDimitry Andric sects.dwarf_section + fdeSectionOffsetHint, 1468*0b57cec5SDimitry Andric &fdeInfo, &cieInfo); 1469*0b57cec5SDimitry Andric } 1470*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 1471*0b57cec5SDimitry Andric if (!foundFDE && (sects.dwarf_index_section != 0)) { 1472*0b57cec5SDimitry Andric foundFDE = EHHeaderParser<A>::findFDE( 1473*0b57cec5SDimitry Andric _addressSpace, pc, sects.dwarf_index_section, 1474*0b57cec5SDimitry Andric (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); 1475*0b57cec5SDimitry Andric } 1476*0b57cec5SDimitry Andric #endif 1477*0b57cec5SDimitry Andric if (!foundFDE) { 1478*0b57cec5SDimitry Andric // otherwise, search cache of previously found FDEs. 1479*0b57cec5SDimitry Andric pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc); 1480*0b57cec5SDimitry Andric if (cachedFDE != 0) { 1481*0b57cec5SDimitry Andric foundFDE = 1482*0b57cec5SDimitry Andric CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, 1483*0b57cec5SDimitry Andric (uint32_t)sects.dwarf_section_length, 1484*0b57cec5SDimitry Andric cachedFDE, &fdeInfo, &cieInfo); 1485*0b57cec5SDimitry Andric foundInCache = foundFDE; 1486*0b57cec5SDimitry Andric } 1487*0b57cec5SDimitry Andric } 1488*0b57cec5SDimitry Andric if (!foundFDE) { 1489*0b57cec5SDimitry Andric // Still not found, do full scan of __eh_frame section. 1490*0b57cec5SDimitry Andric foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, 1491*0b57cec5SDimitry Andric (uint32_t)sects.dwarf_section_length, 0, 1492*0b57cec5SDimitry Andric &fdeInfo, &cieInfo); 1493*0b57cec5SDimitry Andric } 1494*0b57cec5SDimitry Andric if (foundFDE) { 1495*0b57cec5SDimitry Andric typename CFI_Parser<A>::PrologInfo prolog; 1496*0b57cec5SDimitry Andric if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, 1497*0b57cec5SDimitry Andric R::getArch(), &prolog)) { 1498*0b57cec5SDimitry Andric // Save off parsed FDE info 1499*0b57cec5SDimitry Andric _info.start_ip = fdeInfo.pcStart; 1500*0b57cec5SDimitry Andric _info.end_ip = fdeInfo.pcEnd; 1501*0b57cec5SDimitry Andric _info.lsda = fdeInfo.lsda; 1502*0b57cec5SDimitry Andric _info.handler = cieInfo.personality; 1503*0b57cec5SDimitry Andric _info.gp = prolog.spExtraArgSize; 1504*0b57cec5SDimitry Andric _info.flags = 0; 1505*0b57cec5SDimitry Andric _info.format = dwarfEncoding(); 1506*0b57cec5SDimitry Andric _info.unwind_info = fdeInfo.fdeStart; 1507*0b57cec5SDimitry Andric _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; 1508*0b57cec5SDimitry Andric _info.extra = (unw_word_t) sects.dso_base; 1509*0b57cec5SDimitry Andric 1510*0b57cec5SDimitry Andric // Add to cache (to make next lookup faster) if we had no hint 1511*0b57cec5SDimitry Andric // and there was no index. 1512*0b57cec5SDimitry Andric if (!foundInCache && (fdeSectionOffsetHint == 0)) { 1513*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX) 1514*0b57cec5SDimitry Andric if (sects.dwarf_index_section == 0) 1515*0b57cec5SDimitry Andric #endif 1516*0b57cec5SDimitry Andric DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, 1517*0b57cec5SDimitry Andric fdeInfo.fdeStart); 1518*0b57cec5SDimitry Andric } 1519*0b57cec5SDimitry Andric return true; 1520*0b57cec5SDimitry Andric } 1521*0b57cec5SDimitry Andric } 1522*0b57cec5SDimitry Andric //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc); 1523*0b57cec5SDimitry Andric return false; 1524*0b57cec5SDimitry Andric } 1525*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1526*0b57cec5SDimitry Andric 1527*0b57cec5SDimitry Andric 1528*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1529*0b57cec5SDimitry Andric template <typename A, typename R> 1530*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, 1531*0b57cec5SDimitry Andric const UnwindInfoSections §s) { 1532*0b57cec5SDimitry Andric const bool log = false; 1533*0b57cec5SDimitry Andric if (log) 1534*0b57cec5SDimitry Andric fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", 1535*0b57cec5SDimitry Andric (uint64_t)pc, (uint64_t)sects.dso_base); 1536*0b57cec5SDimitry Andric 1537*0b57cec5SDimitry Andric const UnwindSectionHeader<A> sectionHeader(_addressSpace, 1538*0b57cec5SDimitry Andric sects.compact_unwind_section); 1539*0b57cec5SDimitry Andric if (sectionHeader.version() != UNWIND_SECTION_VERSION) 1540*0b57cec5SDimitry Andric return false; 1541*0b57cec5SDimitry Andric 1542*0b57cec5SDimitry Andric // do a binary search of top level index to find page with unwind info 1543*0b57cec5SDimitry Andric pint_t targetFunctionOffset = pc - sects.dso_base; 1544*0b57cec5SDimitry Andric const UnwindSectionIndexArray<A> topIndex(_addressSpace, 1545*0b57cec5SDimitry Andric sects.compact_unwind_section 1546*0b57cec5SDimitry Andric + sectionHeader.indexSectionOffset()); 1547*0b57cec5SDimitry Andric uint32_t low = 0; 1548*0b57cec5SDimitry Andric uint32_t high = sectionHeader.indexCount(); 1549*0b57cec5SDimitry Andric uint32_t last = high - 1; 1550*0b57cec5SDimitry Andric while (low < high) { 1551*0b57cec5SDimitry Andric uint32_t mid = (low + high) / 2; 1552*0b57cec5SDimitry Andric //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", 1553*0b57cec5SDimitry Andric //mid, low, high, topIndex.functionOffset(mid)); 1554*0b57cec5SDimitry Andric if (topIndex.functionOffset(mid) <= targetFunctionOffset) { 1555*0b57cec5SDimitry Andric if ((mid == last) || 1556*0b57cec5SDimitry Andric (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) { 1557*0b57cec5SDimitry Andric low = mid; 1558*0b57cec5SDimitry Andric break; 1559*0b57cec5SDimitry Andric } else { 1560*0b57cec5SDimitry Andric low = mid + 1; 1561*0b57cec5SDimitry Andric } 1562*0b57cec5SDimitry Andric } else { 1563*0b57cec5SDimitry Andric high = mid; 1564*0b57cec5SDimitry Andric } 1565*0b57cec5SDimitry Andric } 1566*0b57cec5SDimitry Andric const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low); 1567*0b57cec5SDimitry Andric const uint32_t firstLevelNextPageFunctionOffset = 1568*0b57cec5SDimitry Andric topIndex.functionOffset(low + 1); 1569*0b57cec5SDimitry Andric const pint_t secondLevelAddr = 1570*0b57cec5SDimitry Andric sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low); 1571*0b57cec5SDimitry Andric const pint_t lsdaArrayStartAddr = 1572*0b57cec5SDimitry Andric sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low); 1573*0b57cec5SDimitry Andric const pint_t lsdaArrayEndAddr = 1574*0b57cec5SDimitry Andric sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1); 1575*0b57cec5SDimitry Andric if (log) 1576*0b57cec5SDimitry Andric fprintf(stderr, "\tfirst level search for result index=%d " 1577*0b57cec5SDimitry Andric "to secondLevelAddr=0x%llX\n", 1578*0b57cec5SDimitry Andric low, (uint64_t) secondLevelAddr); 1579*0b57cec5SDimitry Andric // do a binary search of second level page index 1580*0b57cec5SDimitry Andric uint32_t encoding = 0; 1581*0b57cec5SDimitry Andric pint_t funcStart = 0; 1582*0b57cec5SDimitry Andric pint_t funcEnd = 0; 1583*0b57cec5SDimitry Andric pint_t lsda = 0; 1584*0b57cec5SDimitry Andric pint_t personality = 0; 1585*0b57cec5SDimitry Andric uint32_t pageKind = _addressSpace.get32(secondLevelAddr); 1586*0b57cec5SDimitry Andric if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) { 1587*0b57cec5SDimitry Andric // regular page 1588*0b57cec5SDimitry Andric UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace, 1589*0b57cec5SDimitry Andric secondLevelAddr); 1590*0b57cec5SDimitry Andric UnwindSectionRegularArray<A> pageIndex( 1591*0b57cec5SDimitry Andric _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); 1592*0b57cec5SDimitry Andric // binary search looks for entry with e where index[e].offset <= pc < 1593*0b57cec5SDimitry Andric // index[e+1].offset 1594*0b57cec5SDimitry Andric if (log) 1595*0b57cec5SDimitry Andric fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in " 1596*0b57cec5SDimitry Andric "regular page starting at secondLevelAddr=0x%llX\n", 1597*0b57cec5SDimitry Andric (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr); 1598*0b57cec5SDimitry Andric low = 0; 1599*0b57cec5SDimitry Andric high = pageHeader.entryCount(); 1600*0b57cec5SDimitry Andric while (low < high) { 1601*0b57cec5SDimitry Andric uint32_t mid = (low + high) / 2; 1602*0b57cec5SDimitry Andric if (pageIndex.functionOffset(mid) <= targetFunctionOffset) { 1603*0b57cec5SDimitry Andric if (mid == (uint32_t)(pageHeader.entryCount() - 1)) { 1604*0b57cec5SDimitry Andric // at end of table 1605*0b57cec5SDimitry Andric low = mid; 1606*0b57cec5SDimitry Andric funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; 1607*0b57cec5SDimitry Andric break; 1608*0b57cec5SDimitry Andric } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) { 1609*0b57cec5SDimitry Andric // next is too big, so we found it 1610*0b57cec5SDimitry Andric low = mid; 1611*0b57cec5SDimitry Andric funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base; 1612*0b57cec5SDimitry Andric break; 1613*0b57cec5SDimitry Andric } else { 1614*0b57cec5SDimitry Andric low = mid + 1; 1615*0b57cec5SDimitry Andric } 1616*0b57cec5SDimitry Andric } else { 1617*0b57cec5SDimitry Andric high = mid; 1618*0b57cec5SDimitry Andric } 1619*0b57cec5SDimitry Andric } 1620*0b57cec5SDimitry Andric encoding = pageIndex.encoding(low); 1621*0b57cec5SDimitry Andric funcStart = pageIndex.functionOffset(low) + sects.dso_base; 1622*0b57cec5SDimitry Andric if (pc < funcStart) { 1623*0b57cec5SDimitry Andric if (log) 1624*0b57cec5SDimitry Andric fprintf( 1625*0b57cec5SDimitry Andric stderr, 1626*0b57cec5SDimitry Andric "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", 1627*0b57cec5SDimitry Andric (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); 1628*0b57cec5SDimitry Andric return false; 1629*0b57cec5SDimitry Andric } 1630*0b57cec5SDimitry Andric if (pc > funcEnd) { 1631*0b57cec5SDimitry Andric if (log) 1632*0b57cec5SDimitry Andric fprintf( 1633*0b57cec5SDimitry Andric stderr, 1634*0b57cec5SDimitry Andric "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", 1635*0b57cec5SDimitry Andric (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); 1636*0b57cec5SDimitry Andric return false; 1637*0b57cec5SDimitry Andric } 1638*0b57cec5SDimitry Andric } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) { 1639*0b57cec5SDimitry Andric // compressed page 1640*0b57cec5SDimitry Andric UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace, 1641*0b57cec5SDimitry Andric secondLevelAddr); 1642*0b57cec5SDimitry Andric UnwindSectionCompressedArray<A> pageIndex( 1643*0b57cec5SDimitry Andric _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); 1644*0b57cec5SDimitry Andric const uint32_t targetFunctionPageOffset = 1645*0b57cec5SDimitry Andric (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset); 1646*0b57cec5SDimitry Andric // binary search looks for entry with e where index[e].offset <= pc < 1647*0b57cec5SDimitry Andric // index[e+1].offset 1648*0b57cec5SDimitry Andric if (log) 1649*0b57cec5SDimitry Andric fprintf(stderr, "\tbinary search of compressed page starting at " 1650*0b57cec5SDimitry Andric "secondLevelAddr=0x%llX\n", 1651*0b57cec5SDimitry Andric (uint64_t) secondLevelAddr); 1652*0b57cec5SDimitry Andric low = 0; 1653*0b57cec5SDimitry Andric last = pageHeader.entryCount() - 1; 1654*0b57cec5SDimitry Andric high = pageHeader.entryCount(); 1655*0b57cec5SDimitry Andric while (low < high) { 1656*0b57cec5SDimitry Andric uint32_t mid = (low + high) / 2; 1657*0b57cec5SDimitry Andric if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) { 1658*0b57cec5SDimitry Andric if ((mid == last) || 1659*0b57cec5SDimitry Andric (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) { 1660*0b57cec5SDimitry Andric low = mid; 1661*0b57cec5SDimitry Andric break; 1662*0b57cec5SDimitry Andric } else { 1663*0b57cec5SDimitry Andric low = mid + 1; 1664*0b57cec5SDimitry Andric } 1665*0b57cec5SDimitry Andric } else { 1666*0b57cec5SDimitry Andric high = mid; 1667*0b57cec5SDimitry Andric } 1668*0b57cec5SDimitry Andric } 1669*0b57cec5SDimitry Andric funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset 1670*0b57cec5SDimitry Andric + sects.dso_base; 1671*0b57cec5SDimitry Andric if (low < last) 1672*0b57cec5SDimitry Andric funcEnd = 1673*0b57cec5SDimitry Andric pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset 1674*0b57cec5SDimitry Andric + sects.dso_base; 1675*0b57cec5SDimitry Andric else 1676*0b57cec5SDimitry Andric funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; 1677*0b57cec5SDimitry Andric if (pc < funcStart) { 1678*0b57cec5SDimitry Andric _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " 1679*0b57cec5SDimitry Andric "level compressed unwind table. funcStart=0x%llX", 1680*0b57cec5SDimitry Andric (uint64_t) pc, (uint64_t) funcStart); 1681*0b57cec5SDimitry Andric return false; 1682*0b57cec5SDimitry Andric } 1683*0b57cec5SDimitry Andric if (pc > funcEnd) { 1684*0b57cec5SDimitry Andric _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " 1685*0b57cec5SDimitry Andric "level compressed unwind table. funcEnd=0x%llX", 1686*0b57cec5SDimitry Andric (uint64_t) pc, (uint64_t) funcEnd); 1687*0b57cec5SDimitry Andric return false; 1688*0b57cec5SDimitry Andric } 1689*0b57cec5SDimitry Andric uint16_t encodingIndex = pageIndex.encodingIndex(low); 1690*0b57cec5SDimitry Andric if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) { 1691*0b57cec5SDimitry Andric // encoding is in common table in section header 1692*0b57cec5SDimitry Andric encoding = _addressSpace.get32( 1693*0b57cec5SDimitry Andric sects.compact_unwind_section + 1694*0b57cec5SDimitry Andric sectionHeader.commonEncodingsArraySectionOffset() + 1695*0b57cec5SDimitry Andric encodingIndex * sizeof(uint32_t)); 1696*0b57cec5SDimitry Andric } else { 1697*0b57cec5SDimitry Andric // encoding is in page specific table 1698*0b57cec5SDimitry Andric uint16_t pageEncodingIndex = 1699*0b57cec5SDimitry Andric encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount(); 1700*0b57cec5SDimitry Andric encoding = _addressSpace.get32(secondLevelAddr + 1701*0b57cec5SDimitry Andric pageHeader.encodingsPageOffset() + 1702*0b57cec5SDimitry Andric pageEncodingIndex * sizeof(uint32_t)); 1703*0b57cec5SDimitry Andric } 1704*0b57cec5SDimitry Andric } else { 1705*0b57cec5SDimitry Andric _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second " 1706*0b57cec5SDimitry Andric "level page", 1707*0b57cec5SDimitry Andric (uint64_t) sects.compact_unwind_section); 1708*0b57cec5SDimitry Andric return false; 1709*0b57cec5SDimitry Andric } 1710*0b57cec5SDimitry Andric 1711*0b57cec5SDimitry Andric // look up LSDA, if encoding says function has one 1712*0b57cec5SDimitry Andric if (encoding & UNWIND_HAS_LSDA) { 1713*0b57cec5SDimitry Andric UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr); 1714*0b57cec5SDimitry Andric uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base); 1715*0b57cec5SDimitry Andric low = 0; 1716*0b57cec5SDimitry Andric high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) / 1717*0b57cec5SDimitry Andric sizeof(unwind_info_section_header_lsda_index_entry); 1718*0b57cec5SDimitry Andric // binary search looks for entry with exact match for functionOffset 1719*0b57cec5SDimitry Andric if (log) 1720*0b57cec5SDimitry Andric fprintf(stderr, 1721*0b57cec5SDimitry Andric "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", 1722*0b57cec5SDimitry Andric funcStartOffset); 1723*0b57cec5SDimitry Andric while (low < high) { 1724*0b57cec5SDimitry Andric uint32_t mid = (low + high) / 2; 1725*0b57cec5SDimitry Andric if (lsdaIndex.functionOffset(mid) == funcStartOffset) { 1726*0b57cec5SDimitry Andric lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base; 1727*0b57cec5SDimitry Andric break; 1728*0b57cec5SDimitry Andric } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) { 1729*0b57cec5SDimitry Andric low = mid + 1; 1730*0b57cec5SDimitry Andric } else { 1731*0b57cec5SDimitry Andric high = mid; 1732*0b57cec5SDimitry Andric } 1733*0b57cec5SDimitry Andric } 1734*0b57cec5SDimitry Andric if (lsda == 0) { 1735*0b57cec5SDimitry Andric _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for " 1736*0b57cec5SDimitry Andric "pc=0x%0llX, but lsda table has no entry", 1737*0b57cec5SDimitry Andric encoding, (uint64_t) pc); 1738*0b57cec5SDimitry Andric return false; 1739*0b57cec5SDimitry Andric } 1740*0b57cec5SDimitry Andric } 1741*0b57cec5SDimitry Andric 1742*0b57cec5SDimitry Andric // extact personality routine, if encoding says function has one 1743*0b57cec5SDimitry Andric uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> 1744*0b57cec5SDimitry Andric (__builtin_ctz(UNWIND_PERSONALITY_MASK)); 1745*0b57cec5SDimitry Andric if (personalityIndex != 0) { 1746*0b57cec5SDimitry Andric --personalityIndex; // change 1-based to zero-based index 1747*0b57cec5SDimitry Andric if (personalityIndex > sectionHeader.personalityArrayCount()) { 1748*0b57cec5SDimitry Andric _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " 1749*0b57cec5SDimitry Andric "but personality table has only %d entries", 1750*0b57cec5SDimitry Andric encoding, personalityIndex, 1751*0b57cec5SDimitry Andric sectionHeader.personalityArrayCount()); 1752*0b57cec5SDimitry Andric return false; 1753*0b57cec5SDimitry Andric } 1754*0b57cec5SDimitry Andric int32_t personalityDelta = (int32_t)_addressSpace.get32( 1755*0b57cec5SDimitry Andric sects.compact_unwind_section + 1756*0b57cec5SDimitry Andric sectionHeader.personalityArraySectionOffset() + 1757*0b57cec5SDimitry Andric personalityIndex * sizeof(uint32_t)); 1758*0b57cec5SDimitry Andric pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; 1759*0b57cec5SDimitry Andric personality = _addressSpace.getP(personalityPointer); 1760*0b57cec5SDimitry Andric if (log) 1761*0b57cec5SDimitry Andric fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " 1762*0b57cec5SDimitry Andric "personalityDelta=0x%08X, personality=0x%08llX\n", 1763*0b57cec5SDimitry Andric (uint64_t) pc, personalityDelta, (uint64_t) personality); 1764*0b57cec5SDimitry Andric } 1765*0b57cec5SDimitry Andric 1766*0b57cec5SDimitry Andric if (log) 1767*0b57cec5SDimitry Andric fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " 1768*0b57cec5SDimitry Andric "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", 1769*0b57cec5SDimitry Andric (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); 1770*0b57cec5SDimitry Andric _info.start_ip = funcStart; 1771*0b57cec5SDimitry Andric _info.end_ip = funcEnd; 1772*0b57cec5SDimitry Andric _info.lsda = lsda; 1773*0b57cec5SDimitry Andric _info.handler = personality; 1774*0b57cec5SDimitry Andric _info.gp = 0; 1775*0b57cec5SDimitry Andric _info.flags = 0; 1776*0b57cec5SDimitry Andric _info.format = encoding; 1777*0b57cec5SDimitry Andric _info.unwind_info = 0; 1778*0b57cec5SDimitry Andric _info.unwind_info_size = 0; 1779*0b57cec5SDimitry Andric _info.extra = sects.dso_base; 1780*0b57cec5SDimitry Andric return true; 1781*0b57cec5SDimitry Andric } 1782*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1783*0b57cec5SDimitry Andric 1784*0b57cec5SDimitry Andric 1785*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 1786*0b57cec5SDimitry Andric template <typename A, typename R> 1787*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) { 1788*0b57cec5SDimitry Andric pint_t base; 1789*0b57cec5SDimitry Andric RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base); 1790*0b57cec5SDimitry Andric if (!unwindEntry) { 1791*0b57cec5SDimitry Andric _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc); 1792*0b57cec5SDimitry Andric return false; 1793*0b57cec5SDimitry Andric } 1794*0b57cec5SDimitry Andric _info.gp = 0; 1795*0b57cec5SDimitry Andric _info.flags = 0; 1796*0b57cec5SDimitry Andric _info.format = 0; 1797*0b57cec5SDimitry Andric _info.unwind_info_size = sizeof(RUNTIME_FUNCTION); 1798*0b57cec5SDimitry Andric _info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry); 1799*0b57cec5SDimitry Andric _info.extra = base; 1800*0b57cec5SDimitry Andric _info.start_ip = base + unwindEntry->BeginAddress; 1801*0b57cec5SDimitry Andric #ifdef _LIBUNWIND_TARGET_X86_64 1802*0b57cec5SDimitry Andric _info.end_ip = base + unwindEntry->EndAddress; 1803*0b57cec5SDimitry Andric // Only fill in the handler and LSDA if they're stale. 1804*0b57cec5SDimitry Andric if (pc != getLastPC()) { 1805*0b57cec5SDimitry Andric UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData); 1806*0b57cec5SDimitry Andric if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) { 1807*0b57cec5SDimitry Andric // The personality is given in the UNWIND_INFO itself. The LSDA immediately 1808*0b57cec5SDimitry Andric // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit 1809*0b57cec5SDimitry Andric // these structures.) 1810*0b57cec5SDimitry Andric // N.B. UNWIND_INFO structs are DWORD-aligned. 1811*0b57cec5SDimitry Andric uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1; 1812*0b57cec5SDimitry Andric const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]); 1813*0b57cec5SDimitry Andric _info.lsda = reinterpret_cast<unw_word_t>(handler+1); 1814*0b57cec5SDimitry Andric if (*handler) { 1815*0b57cec5SDimitry Andric _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality); 1816*0b57cec5SDimitry Andric } else 1817*0b57cec5SDimitry Andric _info.handler = 0; 1818*0b57cec5SDimitry Andric } else { 1819*0b57cec5SDimitry Andric _info.lsda = 0; 1820*0b57cec5SDimitry Andric _info.handler = 0; 1821*0b57cec5SDimitry Andric } 1822*0b57cec5SDimitry Andric } 1823*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_TARGET_ARM) 1824*0b57cec5SDimitry Andric _info.end_ip = _info.start_ip + unwindEntry->FunctionLength; 1825*0b57cec5SDimitry Andric _info.lsda = 0; // FIXME 1826*0b57cec5SDimitry Andric _info.handler = 0; // FIXME 1827*0b57cec5SDimitry Andric #endif 1828*0b57cec5SDimitry Andric setLastPC(pc); 1829*0b57cec5SDimitry Andric return true; 1830*0b57cec5SDimitry Andric } 1831*0b57cec5SDimitry Andric #endif 1832*0b57cec5SDimitry Andric 1833*0b57cec5SDimitry Andric 1834*0b57cec5SDimitry Andric template <typename A, typename R> 1835*0b57cec5SDimitry Andric void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { 1836*0b57cec5SDimitry Andric pint_t pc = (pint_t)this->getReg(UNW_REG_IP); 1837*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 1838*0b57cec5SDimitry Andric // Remove the thumb bit so the IP represents the actual instruction address. 1839*0b57cec5SDimitry Andric // This matches the behaviour of _Unwind_GetIP on arm. 1840*0b57cec5SDimitry Andric pc &= (pint_t)~0x1; 1841*0b57cec5SDimitry Andric #endif 1842*0b57cec5SDimitry Andric 1843*0b57cec5SDimitry Andric // If the last line of a function is a "throw" the compiler sometimes 1844*0b57cec5SDimitry Andric // emits no instructions after the call to __cxa_throw. This means 1845*0b57cec5SDimitry Andric // the return address is actually the start of the next function. 1846*0b57cec5SDimitry Andric // To disambiguate this, back up the pc when we know it is a return 1847*0b57cec5SDimitry Andric // address. 1848*0b57cec5SDimitry Andric if (isReturnAddress) 1849*0b57cec5SDimitry Andric --pc; 1850*0b57cec5SDimitry Andric 1851*0b57cec5SDimitry Andric // Ask address space object to find unwind sections for this pc. 1852*0b57cec5SDimitry Andric UnwindInfoSections sects; 1853*0b57cec5SDimitry Andric if (_addressSpace.findUnwindSections(pc, sects)) { 1854*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1855*0b57cec5SDimitry Andric // If there is a compact unwind encoding table, look there first. 1856*0b57cec5SDimitry Andric if (sects.compact_unwind_section != 0) { 1857*0b57cec5SDimitry Andric if (this->getInfoFromCompactEncodingSection(pc, sects)) { 1858*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1859*0b57cec5SDimitry Andric // Found info in table, done unless encoding says to use dwarf. 1860*0b57cec5SDimitry Andric uint32_t dwarfOffset; 1861*0b57cec5SDimitry Andric if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) { 1862*0b57cec5SDimitry Andric if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) { 1863*0b57cec5SDimitry Andric // found info in dwarf, done 1864*0b57cec5SDimitry Andric return; 1865*0b57cec5SDimitry Andric } 1866*0b57cec5SDimitry Andric } 1867*0b57cec5SDimitry Andric #endif 1868*0b57cec5SDimitry Andric // If unwind table has entry, but entry says there is no unwind info, 1869*0b57cec5SDimitry Andric // record that we have no unwind info. 1870*0b57cec5SDimitry Andric if (_info.format == 0) 1871*0b57cec5SDimitry Andric _unwindInfoMissing = true; 1872*0b57cec5SDimitry Andric return; 1873*0b57cec5SDimitry Andric } 1874*0b57cec5SDimitry Andric } 1875*0b57cec5SDimitry Andric #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1876*0b57cec5SDimitry Andric 1877*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 1878*0b57cec5SDimitry Andric // If there is SEH unwind info, look there next. 1879*0b57cec5SDimitry Andric if (this->getInfoFromSEH(pc)) 1880*0b57cec5SDimitry Andric return; 1881*0b57cec5SDimitry Andric #endif 1882*0b57cec5SDimitry Andric 1883*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1884*0b57cec5SDimitry Andric // If there is dwarf unwind info, look there next. 1885*0b57cec5SDimitry Andric if (sects.dwarf_section != 0) { 1886*0b57cec5SDimitry Andric if (this->getInfoFromDwarfSection(pc, sects)) { 1887*0b57cec5SDimitry Andric // found info in dwarf, done 1888*0b57cec5SDimitry Andric return; 1889*0b57cec5SDimitry Andric } 1890*0b57cec5SDimitry Andric } 1891*0b57cec5SDimitry Andric #endif 1892*0b57cec5SDimitry Andric 1893*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_ARM_EHABI) 1894*0b57cec5SDimitry Andric // If there is ARM EHABI unwind info, look there next. 1895*0b57cec5SDimitry Andric if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) 1896*0b57cec5SDimitry Andric return; 1897*0b57cec5SDimitry Andric #endif 1898*0b57cec5SDimitry Andric } 1899*0b57cec5SDimitry Andric 1900*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1901*0b57cec5SDimitry Andric // There is no static unwind info for this pc. Look to see if an FDE was 1902*0b57cec5SDimitry Andric // dynamically registered for it. 1903*0b57cec5SDimitry Andric pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc); 1904*0b57cec5SDimitry Andric if (cachedFDE != 0) { 1905*0b57cec5SDimitry Andric CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; 1906*0b57cec5SDimitry Andric CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; 1907*0b57cec5SDimitry Andric const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace, 1908*0b57cec5SDimitry Andric cachedFDE, &fdeInfo, &cieInfo); 1909*0b57cec5SDimitry Andric if (msg == NULL) { 1910*0b57cec5SDimitry Andric typename CFI_Parser<A>::PrologInfo prolog; 1911*0b57cec5SDimitry Andric if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, 1912*0b57cec5SDimitry Andric pc, R::getArch(), &prolog)) { 1913*0b57cec5SDimitry Andric // save off parsed FDE info 1914*0b57cec5SDimitry Andric _info.start_ip = fdeInfo.pcStart; 1915*0b57cec5SDimitry Andric _info.end_ip = fdeInfo.pcEnd; 1916*0b57cec5SDimitry Andric _info.lsda = fdeInfo.lsda; 1917*0b57cec5SDimitry Andric _info.handler = cieInfo.personality; 1918*0b57cec5SDimitry Andric _info.gp = prolog.spExtraArgSize; 1919*0b57cec5SDimitry Andric // Some frameless functions need SP 1920*0b57cec5SDimitry Andric // altered when resuming in function. 1921*0b57cec5SDimitry Andric _info.flags = 0; 1922*0b57cec5SDimitry Andric _info.format = dwarfEncoding(); 1923*0b57cec5SDimitry Andric _info.unwind_info = fdeInfo.fdeStart; 1924*0b57cec5SDimitry Andric _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; 1925*0b57cec5SDimitry Andric _info.extra = 0; 1926*0b57cec5SDimitry Andric return; 1927*0b57cec5SDimitry Andric } 1928*0b57cec5SDimitry Andric } 1929*0b57cec5SDimitry Andric } 1930*0b57cec5SDimitry Andric 1931*0b57cec5SDimitry Andric // Lastly, ask AddressSpace object about platform specific ways to locate 1932*0b57cec5SDimitry Andric // other FDEs. 1933*0b57cec5SDimitry Andric pint_t fde; 1934*0b57cec5SDimitry Andric if (_addressSpace.findOtherFDE(pc, fde)) { 1935*0b57cec5SDimitry Andric CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; 1936*0b57cec5SDimitry Andric CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; 1937*0b57cec5SDimitry Andric if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { 1938*0b57cec5SDimitry Andric // Double check this FDE is for a function that includes the pc. 1939*0b57cec5SDimitry Andric if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { 1940*0b57cec5SDimitry Andric typename CFI_Parser<A>::PrologInfo prolog; 1941*0b57cec5SDimitry Andric if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, 1942*0b57cec5SDimitry Andric pc, R::getArch(), &prolog)) { 1943*0b57cec5SDimitry Andric // save off parsed FDE info 1944*0b57cec5SDimitry Andric _info.start_ip = fdeInfo.pcStart; 1945*0b57cec5SDimitry Andric _info.end_ip = fdeInfo.pcEnd; 1946*0b57cec5SDimitry Andric _info.lsda = fdeInfo.lsda; 1947*0b57cec5SDimitry Andric _info.handler = cieInfo.personality; 1948*0b57cec5SDimitry Andric _info.gp = prolog.spExtraArgSize; 1949*0b57cec5SDimitry Andric _info.flags = 0; 1950*0b57cec5SDimitry Andric _info.format = dwarfEncoding(); 1951*0b57cec5SDimitry Andric _info.unwind_info = fdeInfo.fdeStart; 1952*0b57cec5SDimitry Andric _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; 1953*0b57cec5SDimitry Andric _info.extra = 0; 1954*0b57cec5SDimitry Andric return; 1955*0b57cec5SDimitry Andric } 1956*0b57cec5SDimitry Andric } 1957*0b57cec5SDimitry Andric } 1958*0b57cec5SDimitry Andric } 1959*0b57cec5SDimitry Andric #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1960*0b57cec5SDimitry Andric 1961*0b57cec5SDimitry Andric // no unwind info, flag that we can't reliably unwind 1962*0b57cec5SDimitry Andric _unwindInfoMissing = true; 1963*0b57cec5SDimitry Andric } 1964*0b57cec5SDimitry Andric 1965*0b57cec5SDimitry Andric template <typename A, typename R> 1966*0b57cec5SDimitry Andric int UnwindCursor<A, R>::step() { 1967*0b57cec5SDimitry Andric // Bottom of stack is defined is when unwind info cannot be found. 1968*0b57cec5SDimitry Andric if (_unwindInfoMissing) 1969*0b57cec5SDimitry Andric return UNW_STEP_END; 1970*0b57cec5SDimitry Andric 1971*0b57cec5SDimitry Andric // Use unwinding info to modify register set as if function returned. 1972*0b57cec5SDimitry Andric int result; 1973*0b57cec5SDimitry Andric #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND) 1974*0b57cec5SDimitry Andric result = this->stepWithCompactEncoding(); 1975*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) 1976*0b57cec5SDimitry Andric result = this->stepWithSEHData(); 1977*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) 1978*0b57cec5SDimitry Andric result = this->stepWithDwarfFDE(); 1979*0b57cec5SDimitry Andric #elif defined(_LIBUNWIND_ARM_EHABI) 1980*0b57cec5SDimitry Andric result = this->stepWithEHABI(); 1981*0b57cec5SDimitry Andric #else 1982*0b57cec5SDimitry Andric #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \ 1983*0b57cec5SDimitry Andric _LIBUNWIND_SUPPORT_SEH_UNWIND or \ 1984*0b57cec5SDimitry Andric _LIBUNWIND_SUPPORT_DWARF_UNWIND or \ 1985*0b57cec5SDimitry Andric _LIBUNWIND_ARM_EHABI 1986*0b57cec5SDimitry Andric #endif 1987*0b57cec5SDimitry Andric 1988*0b57cec5SDimitry Andric // update info based on new PC 1989*0b57cec5SDimitry Andric if (result == UNW_STEP_SUCCESS) { 1990*0b57cec5SDimitry Andric this->setInfoBasedOnIPRegister(true); 1991*0b57cec5SDimitry Andric if (_unwindInfoMissing) 1992*0b57cec5SDimitry Andric return UNW_STEP_END; 1993*0b57cec5SDimitry Andric } 1994*0b57cec5SDimitry Andric 1995*0b57cec5SDimitry Andric return result; 1996*0b57cec5SDimitry Andric } 1997*0b57cec5SDimitry Andric 1998*0b57cec5SDimitry Andric template <typename A, typename R> 1999*0b57cec5SDimitry Andric void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) { 2000*0b57cec5SDimitry Andric *info = _info; 2001*0b57cec5SDimitry Andric } 2002*0b57cec5SDimitry Andric 2003*0b57cec5SDimitry Andric template <typename A, typename R> 2004*0b57cec5SDimitry Andric bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen, 2005*0b57cec5SDimitry Andric unw_word_t *offset) { 2006*0b57cec5SDimitry Andric return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP), 2007*0b57cec5SDimitry Andric buf, bufLen, offset); 2008*0b57cec5SDimitry Andric } 2009*0b57cec5SDimitry Andric 2010*0b57cec5SDimitry Andric } // namespace libunwind 2011*0b57cec5SDimitry Andric 2012*0b57cec5SDimitry Andric #endif // __UNWINDCURSOR_HPP__ 2013