111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===------------------------- UnwindCursor.hpp ---------------------------===// 211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// The LLVM Compiler Infrastructure 411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// This file is dual licensed under the MIT and the University of Illinois Open 611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Source Licenses. See LICENSE.TXT for details. 711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// 911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// C++ interface to lower levels of libuwind 1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert//===----------------------------------------------------------------------===// 1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifndef __UNWINDCURSOR_HPP__ 1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define __UNWINDCURSOR_HPP__ 1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <algorithm> 1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdint.h> 1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdio.h> 1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <stdlib.h> 1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <pthread.h> 2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <unwind.h> 2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __APPLE__ 2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #include <mach-o/dyld.h> 2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "config.h" 2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "AddressSpace.hpp" 2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "CompactUnwinder.hpp" 3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "config.h" 3111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "DwarfInstructions.hpp" 3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "EHHeaderParser.hpp" 3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "libunwind.h" 3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "Registers.hpp" 3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "Unwind-EHABI.h" 3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertnamespace libunwind { 3811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_DWARF_UNWIND 4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// Cache of recently found FDEs. 4111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass _LIBUNWIND_HIDDEN DwarfFDECache { 4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef typename A::pint_t pint_t; 4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static pint_t findFDE(pint_t mh, pint_t pc); 4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); 4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void removeAllIn(pint_t mh); 4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void iterateCacheEntries(void (*func)(unw_word_t ip_start, 4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t ip_end, 5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t fde, unw_word_t mh)); 5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert struct entry { 5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t mh; 5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t ip_start; 5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t ip_end; 5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t fde; 5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert }; 6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // These fields are all static to avoid needing an initializer. 6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // There is only one instance of this class per process. 6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static pthread_rwlock_t _lock; 6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __APPLE__ 6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide); 6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static bool _registeredForDyldUnloads; 6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Can't use std::vector<> here because this code is below libc++. 6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static entry *_buffer; 7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static entry *_bufferUsed; 7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static entry *_bufferEnd; 7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static entry _initialBuffer[64]; 7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 7611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypename DwarfFDECache<A>::entry * 7711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDwarfFDECache<A>::_buffer = _initialBuffer; 7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 7911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 8011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypename DwarfFDECache<A>::entry * 8111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDwarfFDECache<A>::_bufferUsed = _initialBuffer; 8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 8311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 8411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypename DwarfFDECache<A>::entry * 8511cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertDwarfFDECache<A>::_bufferEnd = &_initialBuffer[64]; 8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 8711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 8811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64]; 8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 9011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER; 9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __APPLE__ 9411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool DwarfFDECache<A>::_registeredForDyldUnloads = false; 9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 9811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 9911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttypename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) { 10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t result = 0; 10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_rdlock(&_lock)); 10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (entry *p = _buffer; p < _bufferUsed; ++p) { 10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mh == p->mh) || (mh == 0)) { 10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((p->ip_start <= pc) && (pc < p->ip_end)) { 10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = p->fde; 10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); 11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 11411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end, 11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t fde) { 11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); 11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_bufferUsed >= _bufferEnd) { 11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t oldSize = (size_t)(_bufferEnd - _buffer); 12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t newSize = oldSize * 4; 12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Can't use operator new (we are below it). 12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert entry *newBuffer = (entry *)malloc(newSize * sizeof(entry)); 12311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memcpy(newBuffer, _buffer, oldSize * sizeof(entry)); 12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_buffer != _initialBuffer) 12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert free(_buffer); 12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _buffer = newBuffer; 12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _bufferUsed = &newBuffer[oldSize]; 12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _bufferEnd = &newBuffer[newSize]; 12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _bufferUsed->mh = mh; 13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _bufferUsed->ip_start = ip_start; 13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _bufferUsed->ip_end = ip_end; 13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _bufferUsed->fde = fde; 13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++_bufferUsed; 13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __APPLE__ 13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!_registeredForDyldUnloads) { 13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _dyld_register_func_for_remove_image(&dyldUnloadHook); 13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _registeredForDyldUnloads = true; 13911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); 14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 14411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid DwarfFDECache<A>::removeAllIn(pint_t mh) { 14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); 14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert entry *d = _buffer; 14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (const entry *s = _buffer; s < _bufferUsed; ++s) { 14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (s->mh != mh) { 15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (d != s) 15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *d = *s; 15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert ++d; 15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _bufferUsed = d; 15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); 15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __APPLE__ 16011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) { 16211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert removeAllIn((pint_t) mh); 16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 16611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> 16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid DwarfFDECache<A>::iterateCacheEntries(void (*func)( 16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) { 16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock)); 17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert for (entry *p = _buffer; p < _bufferUsed; ++p) { 17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (*func)(p->ip_start, p->ip_end, p->fde, p->mh); 17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock)); 17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND 17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field)) 17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND 18111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> class UnwindSectionHeader { 18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionHeader(A &addressSpace, typename A::pint_t addr) 18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(addressSpace), _addr(addr) {} 18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t version() const { 18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32(_addr + 18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offsetof(unwind_info_section_header, version)); 18911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t commonEncodingsArraySectionOffset() const { 19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32(_addr + 19211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offsetof(unwind_info_section_header, 19311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert commonEncodingsArraySectionOffset)); 19411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 19511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t commonEncodingsArrayCount() const { 19611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, 19711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert commonEncodingsArrayCount)); 19811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 19911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t personalityArraySectionOffset() const { 20011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, 20111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personalityArraySectionOffset)); 20211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 20311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t personalityArrayCount() const { 20411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 20511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_section_header, personalityArrayCount)); 20611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 20711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t indexSectionOffset() const { 20811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 20911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_section_header, indexSectionOffset)); 21011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 21111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t indexCount() const { 21211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 21311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_section_header, indexCount)); 21411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 21511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 21611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 21711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 21811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t _addr; 21911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 22011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> class UnwindSectionIndexArray { 22211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 22311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr) 22411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(addressSpace), _addr(addr) {} 22511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 22611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t functionOffset(uint32_t index) const { 22711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 22811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 22911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert functionOffset)); 23011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 23111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t secondLevelPagesSectionOffset(uint32_t index) const { 23211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 23311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 23411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondLevelPagesSectionOffset)); 23511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 23611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t lsdaIndexArraySectionOffset(uint32_t index) const { 23711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 23811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 23911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lsdaIndexArraySectionOffset)); 24011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 24111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 24211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 24311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 24411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t _addr; 24511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 24611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 24711cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> class UnwindSectionRegularPageHeader { 24811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 24911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr) 25011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(addressSpace), _addr(addr) {} 25111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 25211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t kind() const { 25311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 25411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_regular_second_level_page_header, kind)); 25511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 25611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t entryPageOffset() const { 25711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get16( 25811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_regular_second_level_page_header, 25911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert entryPageOffset)); 26011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 26111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t entryCount() const { 26211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get16( 26311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + 26411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offsetof(unwind_info_regular_second_level_page_header, entryCount)); 26511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 26611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 26711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 26811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 26911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t _addr; 27011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 27111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 27211cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> class UnwindSectionRegularArray { 27311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 27411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr) 27511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(addressSpace), _addr(addr) {} 27611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 27711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t functionOffset(uint32_t index) const { 27811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 27911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index, 28011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert functionOffset)); 28111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 28211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t encoding(uint32_t index) const { 28311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 28411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + 28511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding)); 28611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 28711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 28811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 28911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 29011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t _addr; 29111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 29211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 29311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> class UnwindSectionCompressedPageHeader { 29411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 29511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr) 29611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(addressSpace), _addr(addr) {} 29711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 29811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t kind() const { 29911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 30011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + 30111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offsetof(unwind_info_compressed_second_level_page_header, kind)); 30211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 30311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t entryPageOffset() const { 30411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get16( 30511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_compressed_second_level_page_header, 30611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert entryPageOffset)); 30711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 30811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t entryCount() const { 30911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get16( 31011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + 31111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert offsetof(unwind_info_compressed_second_level_page_header, entryCount)); 31211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 31311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t encodingsPageOffset() const { 31411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get16( 31511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_compressed_second_level_page_header, 31611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encodingsPageOffset)); 31711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 31811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t encodingsCount() const { 31911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get16( 32011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + offsetof(unwind_info_compressed_second_level_page_header, 32111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encodingsCount)); 32211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 32311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 32411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 32511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 32611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t _addr; 32711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 32811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 32911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> class UnwindSectionCompressedArray { 33011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 33111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr) 33211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(addressSpace), _addr(addr) {} 33311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 33411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t functionOffset(uint32_t index) const { 33511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( 33611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addressSpace.get32(_addr + index * sizeof(uint32_t))); 33711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 33811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t encodingIndex(uint32_t index) const { 33911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX( 34011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addressSpace.get32(_addr + index * sizeof(uint32_t))); 34111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 34211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 34311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 34411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 34511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t _addr; 34611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 34711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 34811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A> class UnwindSectionLsdaArray { 34911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 35011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr) 35111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(addressSpace), _addr(addr) {} 35211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 35311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t functionOffset(uint32_t index) const { 35411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 35511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, 35611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert index, functionOffset)); 35711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 35811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t lsdaOffset(uint32_t index) const { 35911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.get32( 36011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry, 36111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert index, lsdaOffset)); 36211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 36311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 36411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 36511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 36611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t _addr; 36711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 36811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND 36911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 37011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass _LIBUNWIND_HIDDEN AbstractUnwindCursor { 37111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 37211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // NOTE: provide a class specific placement deallocation function (S5.3.4 p20) 37311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This avoids an unnecessary dependency to libc++abi. 37411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert void operator delete(void *, size_t) {} 37511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 37611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual ~AbstractUnwindCursor() {} 37711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } 37811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } 37911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void setReg(int, unw_word_t) { 38011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("setReg not implemented"); 38111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 38211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool validFloatReg(int) { 38311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("validFloatReg not implemented"); 38411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 38511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual unw_fpreg_t getFloatReg(int) { 38611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("getFloatReg not implemented"); 38711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 38811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void setFloatReg(int, unw_fpreg_t) { 38911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("setFloatReg not implemented"); 39011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual int step() { _LIBUNWIND_ABORT("step not implemented"); } 39211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void getInfo(unw_proc_info_t *) { 39311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("getInfo not implemented"); 39411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } 39611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool isSignalFrame() { 39711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("isSignalFrame not implemented"); 39811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 39911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool getFunctionName(char *, size_t, unw_word_t *) { 40011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("getFunctionName not implemented"); 40111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 40211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void setInfoBasedOnIPRegister(bool = false) { 40311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented"); 40411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 40511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual const char *getRegisterName(int) { 40611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("getRegisterName not implemented"); 40711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 40811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__ 40911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } 41011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 41111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 41211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 41311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// UnwindCursor contains all state (including all register values) during 41411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/// an unwind. This is normally stack allocated inside a unw_cursor_t. 41511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 41611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertclass UnwindCursor : public AbstractUnwindCursor{ 41711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef typename A::pint_t pint_t; 41811cd02dfb91661c65134cac258cf5924270e9d2Dan Albertpublic: 41911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindCursor(unw_context_t *context, A &as); 42011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindCursor(A &as, void *threadArg); 42111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual ~UnwindCursor() {} 42211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool validReg(int); 42311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual unw_word_t getReg(int); 42411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void setReg(int, unw_word_t); 42511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool validFloatReg(int); 42611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual unw_fpreg_t getFloatReg(int); 42711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void setFloatReg(int, unw_fpreg_t); 42811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual int step(); 42911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void getInfo(unw_proc_info_t *); 43011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void jumpto(); 43111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool isSignalFrame(); 43211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual bool getFunctionName(char *buf, size_t len, unw_word_t *off); 43311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void setInfoBasedOnIPRegister(bool isReturnAddress = false); 43411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual const char *getRegisterName(int num); 43511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__ 43611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert virtual void saveVFPAsX(); 43711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 43811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 43911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertprivate: 44011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 44111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if LIBCXXABI_ARM_EHABI 44211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections §s); 44311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 44411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 44511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_DWARF_UNWIND 44611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections §s, 44711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t fdeSectionOffsetHint=0); 44811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepWithDwarfFDE() { 44911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace, 45011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pint_t)this->getReg(UNW_REG_IP), 45111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pint_t)_info.unwind_info, 45211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _registers); 45311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 45411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 45511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 45611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND 45711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool getInfoFromCompactEncodingSection(pint_t pc, 45811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const UnwindInfoSections §s); 45911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepWithCompactEncoding() { 46011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #if _LIBUNWIND_SUPPORT_DWARF_UNWIND 46111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ( compactSaysUseDwarf() ) 46211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return stepWithDwarfFDE(); 46311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #endif 46411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert R dummy; 46511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return stepWithCompactEncoding(dummy); 46611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 46711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 46811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepWithCompactEncoding(Registers_x86_64 &) { 46911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return CompactUnwinder_x86_64<A>::stepWithCompactEncoding( 47011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.format, _info.start_ip, _addressSpace, _registers); 47111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 47211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 47311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepWithCompactEncoding(Registers_x86 &) { 47411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return CompactUnwinder_x86<A>::stepWithCompactEncoding( 47511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers); 47611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 47711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 47811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepWithCompactEncoding(Registers_ppc &) { 47911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNW_EINVAL; 48011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 48111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int stepWithCompactEncoding(Registers_arm64 &) { 48311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return CompactUnwinder_arm64<A>::stepWithCompactEncoding( 48411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.format, _info.start_ip, _addressSpace, _registers); 48511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 48611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 48711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool compactSaysUseDwarf(uint32_t *offset=NULL) const { 48811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert R dummy; 48911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return compactSaysUseDwarf(dummy, offset); 49011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 49111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 49211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const { 49311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) { 49411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (offset) 49511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET); 49611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 49711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 49811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 49911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 50011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 50111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const { 50211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) { 50311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (offset) 50411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET); 50511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 50611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 50711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 50811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 50911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 51011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const { 51111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 51211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 51311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 51411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const { 51511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) { 51611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (offset) 51711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET); 51811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 51911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 52011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 52111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 52211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND 52311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 52411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_DWARF_UNWIND 52511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert compact_unwind_encoding_t dwarfEncoding() const { 52611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert R dummy; 52711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return dwarfEncoding(dummy); 52811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 52911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 53011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const { 53111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNWIND_X86_64_MODE_DWARF; 53211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 53311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 53411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const { 53511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNWIND_X86_MODE_DWARF; 53611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 53711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 53811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const { 53911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return 0; 54011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 54111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 54211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { 54311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNWIND_ARM64_MODE_DWARF; 54411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 54511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND 54611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 54711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 54811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A &_addressSpace; 54911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert R _registers; 55011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_proc_info_t _info; 55111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool _unwindInfoMissing; 55211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool _isSignalFrame; 55311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 55411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 55511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 55611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 55711cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertUnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as) 55811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(as), _registers(context), _unwindInfoMissing(false), 55911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _isSignalFrame(false) { 56011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static_assert(sizeof(UnwindCursor<A, R>) < sizeof(unw_cursor_t), 56111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "UnwindCursor<> does not fit in unw_cursor_t"); 56211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(&_info, 0, sizeof(_info)); 56311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 56411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 56511cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 56611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertUnwindCursor<A, R>::UnwindCursor(A &as, void *) 56711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) { 56811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert memset(&_info, 0, sizeof(_info)); 56911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // FIXME 57011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // fill in _registers from thread arg 57111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 57211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 57311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 57411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 57511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool UnwindCursor<A, R>::validReg(int regNum) { 57611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _registers.validRegister(regNum); 57711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 57811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 57911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 58011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertunw_word_t UnwindCursor<A, R>::getReg(int regNum) { 58111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _registers.getRegister(regNum); 58211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 58311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 58411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 58511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) { 58611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _registers.setRegister(regNum, (typename A::pint_t)value); 58711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 58811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 58911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 59011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool UnwindCursor<A, R>::validFloatReg(int regNum) { 59111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _registers.validFloatRegister(regNum); 59211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 59311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 59411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 59511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertunw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) { 59611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _registers.getFloatRegister(regNum); 59711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 59811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 59911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 60011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { 60111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _registers.setFloatRegister(regNum, value); 60211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 60311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 60411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> void UnwindCursor<A, R>::jumpto() { 60511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _registers.jumpto(); 60611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 60711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 60811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#ifdef __arm__ 60911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() { 61011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _registers.saveVFPAsX(); 61111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 61211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 61311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 61411cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 61511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertconst char *UnwindCursor<A, R>::getRegisterName(int regNum) { 61611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _registers.getRegisterName(regNum); 61711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 61811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 61911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() { 62011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _isSignalFrame; 62111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 62211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 62311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if LIBCXXABI_ARM_EHABI 62411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct EHABIIndexEntry { 62511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t functionOffset; 62611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t data; 62711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 62811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 62911cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate<typename A> 63011cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstruct EHABISectionIterator { 63111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef EHABISectionIterator _Self; 63211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 63311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef std::random_access_iterator_tag iterator_category; 63411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef typename A::pint_t value_type; 63511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef typename A::pint_t* pointer; 63611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef typename A::pint_t& reference; 63711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef size_t size_type; 63811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typedef size_t difference_type; 63911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 64011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static _Self begin(A& addressSpace, const UnwindInfoSections& sects) { 64111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _Self(addressSpace, sects, 0); 64211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 64311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert static _Self end(A& addressSpace, const UnwindInfoSections& sects) { 64411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _Self(addressSpace, sects, sects.arm_section_length); 64511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 64611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 64711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i) 64811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert : _i(i), _addressSpace(&addressSpace), _sects(§s) {} 64911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 65011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Self& operator++() { ++_i; return *this; } 65111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Self& operator+=(size_t a) { _i += a; return *this; } 65211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Self& operator--() { assert(_i > 0); --_i; return *this; } 65311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; } 65411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 65511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } 65611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } 65711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 65811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t operator-(const _Self& other) { return _i - other._i; } 65911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 66011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool operator==(const _Self& other) const { 66111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(_addressSpace == other._addressSpace); 66211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert assert(_sects == other._sects); 66311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _i == other._i; 66411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 66511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 66611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t operator*() const { return functionAddress(); } 66711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 66811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t functionAddress() const { 66911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( 67011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABIIndexEntry, _i, functionOffset); 67111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr)); 67211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 67311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 67411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t dataAddress() { 67511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( 67611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABIIndexEntry, _i, data); 67711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return indexAddr; 67811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 67911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 68011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert private: 68111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t _i; 68211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert A* _addressSpace; 68311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const UnwindInfoSections* _sects; 68411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}; 68511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 68611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 68711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool UnwindCursor<A, R>::getInfoFromEHABISection( 68811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t pc, 68911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const UnwindInfoSections §s) { 69011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABISectionIterator<A> begin = 69111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABISectionIterator<A>::begin(_addressSpace, sects); 69211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABISectionIterator<A> end = 69311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABISectionIterator<A>::end(_addressSpace, sects); 69411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 69511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc); 69611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (itNextPC == begin || itNextPC == end) 69711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 69811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert EHABISectionIterator<A> itThisPC = itNextPC - 1; 69911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 70011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t thisPC = itThisPC.functionAddress(); 70111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t nextPC = itNextPC.functionAddress(); 70211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t indexDataAddr = itThisPC.dataAddress(); 70311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 70411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (indexDataAddr == 0) 70511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 70611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 70711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t indexData = _addressSpace.get32(indexDataAddr); 70811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (indexData == UNW_EXIDX_CANTUNWIND) 70911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 71011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 71111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If the high bit is set, the exception handling table entry is inline inside 71211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // the index table entry on the second word (aka |indexDataAddr|). Otherwise, 71311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // the table points at an offset in the exception handling table (section 5 EHABI). 71411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t exceptionTableAddr; 71511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t exceptionTableData; 71611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool isSingleWordEHT; 71711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (indexData & 0x80000000) { 71811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exceptionTableAddr = indexDataAddr; 71911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // TODO(ajwong): Should this data be 0? 72011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exceptionTableData = indexData; 72111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert isSingleWordEHT = true; 72211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 72311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData); 72411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exceptionTableData = _addressSpace.get32(exceptionTableAddr); 72511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert isSingleWordEHT = false; 72611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 72711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 72811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Now we know the 3 things: 72911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // exceptionTableAddr -- exception handler table entry. 73011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // exceptionTableData -- the data inside the first word of the eht entry. 73111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // isSingleWordEHT -- whether the entry is in the index. 73211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t personalityRoutine = 0xbadf00d; 73311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool scope32 = false; 73411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uintptr_t lsda = 0xbadf00d; 73511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 73611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If the high bit in the exception handling table entry is set, the entry is 73711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // in compact form (section 6.3 EHABI). 73811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (exceptionTableData & 0x80000000) { 73911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Grab the index of the personality routine from the compact form. 74011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t choice = (exceptionTableData & 0x0f000000) >> 24; 74111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t extraWords = 0; 74211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert switch (choice) { 74311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case 0: 74411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0; 74511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert extraWords = 0; 74611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert scope32 = false; 74711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 74811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case 1: 74911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1; 75011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert extraWords = (exceptionTableData & 0x00ff0000) >> 16; 75111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert scope32 = false; 75211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 75311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert case 2: 75411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2; 75511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert extraWords = (exceptionTableData & 0x00ff0000) >> 16; 75611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert scope32 = true; 75711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 75811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert default: 75911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("unknown personality routine"); 76011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 76111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 76211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 76311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (isSingleWordEHT) { 76411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (extraWords != 0) { 76511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_ABORT("index inlined table detected but pr function " 76611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "requires extra words"); 76711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 76811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 76911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 77011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 77111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t personalityAddr = 77211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert exceptionTableAddr + signExtendPrel31(exceptionTableData); 77311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personalityRoutine = personalityAddr; 77411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 77511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // ARM EHABI # 6.2, # 9.2 77611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // 77711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // +---- ehtp 77811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // v 77911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // +--------------------------------------+ 78011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | +--------+--------+--------+-------+ | 78111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | |0| prel31 to personalityRoutine | | 78211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | +--------+--------+--------+-------+ | 78311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | | N | unwind opcodes | | <-- UnwindData 78411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | +--------+--------+--------+-------+ | 78511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | | Word 2 unwind opcodes | | 78611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | +--------+--------+--------+-------+ | 78711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | ... | 78811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | +--------+--------+--------+-------+ | 78911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | | Word N unwind opcodes | | 79011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | +--------+--------+--------+-------+ | 79111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | | LSDA | | <-- lsda 79211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | | ... | | 79311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // | +--------+--------+--------+-------+ | 79411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // +--------------------------------------+ 79511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 79611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1; 79711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t FirstDataWord = *UnwindData; 79811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t N = ((FirstDataWord >> 24) & 0xff); 79911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert size_t NDataWords = N + 1; 80011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords); 80111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 80211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 80311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.start_ip = thisPC; 80411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.end_ip = nextPC; 80511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.handler = personalityRoutine; 80611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info = exceptionTableAddr; 80711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.lsda = lsda; 80811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0. 80911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0; // Use enum? 81011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 81111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 81211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 81311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 81411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 81511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_DWARF_UNWIND 81611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 81711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, 81811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const UnwindInfoSections §s, 81911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t fdeSectionOffsetHint) { 82011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename CFI_Parser<A>::FDE_Info fdeInfo; 82111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename CFI_Parser<A>::CIE_Info cieInfo; 82211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool foundFDE = false; 82311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert bool foundInCache = false; 82411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If compact encoding table gave offset into dwarf section, go directly there 82511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (fdeSectionOffsetHint != 0) { 82611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, 82711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint32_t)sects.dwarf_section_length, 82811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.dwarf_section + fdeSectionOffsetHint, 82911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &fdeInfo, &cieInfo); 83011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 83111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_DWARF_INDEX 83211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!foundFDE && (sects.dwarf_index_section != 0)) { 83311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert foundFDE = EHHeaderParser<A>::findFDE( 83411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addressSpace, pc, sects.dwarf_index_section, 83511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo); 83611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 83711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 83811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!foundFDE) { 83911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // otherwise, search cache of previously found FDEs. 84011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc); 84111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cachedFDE != 0) { 84211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert foundFDE = 84311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, 84411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint32_t)sects.dwarf_section_length, 84511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cachedFDE, &fdeInfo, &cieInfo); 84611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert foundInCache = foundFDE; 84711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 84811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 84911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!foundFDE) { 85011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Still not found, do full scan of __eh_frame section. 85111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section, 85211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint32_t)sects.dwarf_section_length, 0, 85311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &fdeInfo, &cieInfo); 85411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 85511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (foundFDE) { 85611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename CFI_Parser<A>::PrologInfo prolog; 85711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, 85811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert &prolog)) { 85911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Save off parsed FDE info 86011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.start_ip = fdeInfo.pcStart; 86111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.end_ip = fdeInfo.pcEnd; 86211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.lsda = fdeInfo.lsda; 86311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.handler = cieInfo.personality; 86411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.gp = prolog.spExtraArgSize; 86511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.flags = 0; 86611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.format = dwarfEncoding(); 86711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info = fdeInfo.fdeStart; 86811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; 86911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.extra = (unw_word_t) sects.dso_base; 87011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 87111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Add to cache (to make next lookup faster) if we had no hint 87211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // and there was no index. 87311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!foundInCache && (fdeSectionOffsetHint == 0)) { 87411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #if _LIBUNWIND_SUPPORT_DWARF_INDEX 87511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sects.dwarf_index_section == 0) 87611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #endif 87711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd, 87811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fdeInfo.fdeStart); 87911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 88011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 88111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 88211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 88311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc); 88411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 88511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 88611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND 88711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 88811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 88911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND 89011cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 89111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, 89211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const UnwindInfoSections §s) { 89311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const bool log = false; 89411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 89511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n", 89611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t)pc, (uint64_t)sects.dso_base); 89711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 89811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const UnwindSectionHeader<A> sectionHeader(_addressSpace, 89911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.compact_unwind_section); 90011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sectionHeader.version() != UNWIND_SECTION_VERSION) 90111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 90211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 90311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // do a binary search of top level index to find page with unwind info 90411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t targetFunctionOffset = pc - sects.dso_base; 90511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const UnwindSectionIndexArray<A> topIndex(_addressSpace, 90611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.compact_unwind_section 90711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert + sectionHeader.indexSectionOffset()); 90811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t low = 0; 90911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t high = sectionHeader.indexCount(); 91011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t last = high - 1; 91111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (low < high) { 91211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t mid = (low + high) / 2; 91311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", 91411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert //mid, low, high, topIndex.functionOffset(mid)); 91511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (topIndex.functionOffset(mid) <= targetFunctionOffset) { 91611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mid == last) || 91711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) { 91811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid; 91911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 92011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 92111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid + 1; 92211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 92311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 92411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert high = mid; 92511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 92611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 92711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low); 92811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t firstLevelNextPageFunctionOffset = 92911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert topIndex.functionOffset(low + 1); 93011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const pint_t secondLevelAddr = 93111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low); 93211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const pint_t lsdaArrayStartAddr = 93311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low); 93411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const pint_t lsdaArrayEndAddr = 93511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1); 93611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 93711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, "\tfirst level search for result index=%d " 93811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "to secondLevelAddr=0x%llX\n", 93911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low, (uint64_t) secondLevelAddr); 94011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // do a binary search of second level page index 94111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t encoding = 0; 94211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t funcStart = 0; 94311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t funcEnd = 0; 94411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t lsda = 0; 94511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t personality = 0; 94611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t pageKind = _addressSpace.get32(secondLevelAddr); 94711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) { 94811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // regular page 94911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace, 95011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondLevelAddr); 95111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionRegularArray<A> pageIndex( 95211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); 95311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // binary search looks for entry with e where index[e].offset <= pc < 95411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // index[e+1].offset 95511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 95611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in " 95711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "regular page starting at secondLevelAddr=0x%llX\n", 95811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr); 95911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = 0; 96011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert high = pageHeader.entryCount(); 96111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (low < high) { 96211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t mid = (low + high) / 2; 96311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pageIndex.functionOffset(mid) <= targetFunctionOffset) { 96411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (mid == (uint32_t)(pageHeader.entryCount() - 1)) { 96511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // at end of table 96611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid; 96711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; 96811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 96911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) { 97011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // next is too big, so we found it 97111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid; 97211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base; 97311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 97411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 97511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid + 1; 97611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 97711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 97811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert high = mid; 97911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 98011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 98111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encoding = pageIndex.encoding(low); 98211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcStart = pageIndex.functionOffset(low) + sects.dso_base; 98311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pc < funcStart) { 98411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 98511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf( 98611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stderr, 98711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", 98811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); 98911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 99011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 99111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pc > funcEnd) { 99211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 99311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf( 99411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert stderr, 99511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n", 99611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd); 99711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 99811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 99911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) { 100011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // compressed page 100111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace, 100211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert secondLevelAddr); 100311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionCompressedArray<A> pageIndex( 100411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _addressSpace, secondLevelAddr + pageHeader.entryPageOffset()); 100511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const uint32_t targetFunctionPageOffset = 100611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset); 100711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // binary search looks for entry with e where index[e].offset <= pc < 100811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // index[e+1].offset 100911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 101011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, "\tbinary search of compressed page starting at " 101111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "secondLevelAddr=0x%llX\n", 101211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) secondLevelAddr); 101311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = 0; 101411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert last = pageHeader.entryCount() - 1; 101511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert high = pageHeader.entryCount(); 101611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (low < high) { 101711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t mid = (low + high) / 2; 101811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) { 101911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((mid == last) || 102011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) { 102111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid; 102211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 102311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 102411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid + 1; 102511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 102611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 102711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert high = mid; 102811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 102911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 103011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset 103111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert + sects.dso_base; 103211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (low < last) 103311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcEnd = 103411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset 103511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert + sects.dso_base; 103611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert else 103711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base; 103811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pc < funcStart) { 103911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " 104011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "level compressed unwind table. funcStart=0x%llX\n", 104111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) pc, (uint64_t) funcStart); 104211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 104311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 104411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (pc > funcEnd) { 104511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second " 104611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "level compressed unwind table. funcEnd=0x%llX\n", 104711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) pc, (uint64_t) funcEnd); 104811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 104911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 105011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t encodingIndex = pageIndex.encodingIndex(low); 105111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) { 105211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // encoding is in common table in section header 105311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encoding = _addressSpace.get32( 105411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.compact_unwind_section + 105511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sectionHeader.commonEncodingsArraySectionOffset() + 105611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encodingIndex * sizeof(uint32_t)); 105711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 105811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // encoding is in page specific table 105911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint16_t pageEncodingIndex = 106011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount(); 106111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encoding = _addressSpace.get32(secondLevelAddr + 106211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pageHeader.encodingsPageOffset() + 106311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pageEncodingIndex * sizeof(uint32_t)); 106411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 106511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 106611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second " 106711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "level page\n", 106811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) sects.compact_unwind_section); 106911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 107011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 107111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 107211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // look up LSDA, if encoding says function has one 107311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (encoding & UNWIND_HAS_LSDA) { 107411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr); 107511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base); 107611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = 0; 107711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) / 107811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sizeof(unwind_info_section_header_lsda_index_entry); 107911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // binary search looks for entry with exact match for functionOffset 108011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 108111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, 108211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n", 108311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert funcStartOffset); 108411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert while (low < high) { 108511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t mid = (low + high) / 2; 108611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (lsdaIndex.functionOffset(mid) == funcStartOffset) { 108711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base; 108811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert break; 108911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) { 109011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert low = mid + 1; 109111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } else { 109211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert high = mid; 109311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 109411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 109511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (lsda == 0) { 109611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for " 109711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "pc=0x%0llX, but lsda table has no entry\n", 109811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encoding, (uint64_t) pc); 109911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 110011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 110111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 110211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 110311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // extact personality routine, if encoding says function has one 110411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >> 110511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (__builtin_ctz(UNWIND_PERSONALITY_MASK)); 110611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (personalityIndex != 0) { 110711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert --personalityIndex; // change 1-based to zero-based index 110811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (personalityIndex > sectionHeader.personalityArrayCount()) { 110911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d, " 111011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "but personality table has only %d entires\n", 111111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert encoding, personalityIndex, 111211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sectionHeader.personalityArrayCount()); 111311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return false; 111411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 111511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int32_t personalityDelta = (int32_t)_addressSpace.get32( 111611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sects.compact_unwind_section + 111711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert sectionHeader.personalityArraySectionOffset() + 111811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personalityIndex * sizeof(uint32_t)); 111911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta; 112011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert personality = _addressSpace.getP(personalityPointer); 112111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 112211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " 112311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "personalityDelta=0x%08X, personality=0x%08llX\n", 112411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) pc, personalityDelta, (uint64_t) personality); 112511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 112611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 112711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (log) 112811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), " 112911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n", 113011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart); 113111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.start_ip = funcStart; 113211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.end_ip = funcEnd; 113311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.lsda = lsda; 113411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.handler = personality; 113511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.gp = 0; 113611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.flags = 0; 113711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.format = encoding; 113811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info = 0; 113911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info_size = 0; 114011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.extra = sects.dso_base; 114111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return true; 114211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 114311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND 114411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 114511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 114611cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 114711cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) { 114811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t pc = (pint_t)this->getReg(UNW_REG_IP); 114911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if LIBCXXABI_ARM_EHABI 115011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Remove the thumb bit so the IP represents the actual instruction address. 115111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // This matches the behaviour of _Unwind_GetIP on arm. 115211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pc &= (pint_t)~0x1; 115311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 115411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 115511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If the last line of a function is a "throw" the compiler sometimes 115611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // emits no instructions after the call to __cxa_throw. This means 115711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // the return address is actually the start of the next function. 115811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // To disambiguate this, back up the pc when we know it is a return 115911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // address. 116011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (isReturnAddress) 116111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert --pc; 116211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 116311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Ask address space object to find unwind sections for this pc. 116411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert UnwindInfoSections sects; 116511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_addressSpace.findUnwindSections(pc, sects)) { 116611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND 116711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If there is a compact unwind encoding table, look there first. 116811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sects.compact_unwind_section != 0) { 116911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (this->getInfoFromCompactEncodingSection(pc, sects)) { 117011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #if _LIBUNWIND_SUPPORT_DWARF_UNWIND 117111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Found info in table, done unless encoding says to use dwarf. 117211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert uint32_t dwarfOffset; 117311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) { 117411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) { 117511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // found info in dwarf, done 117611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 117711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 117811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 117911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #endif 118011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If unwind table has entry, but entry says there is no unwind info, 118111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // record that we have no unwind info. 118211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_info.format == 0) 118311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _unwindInfoMissing = true; 118411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 118511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 118611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 118711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND 118811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 118911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_DWARF_UNWIND 119011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If there is dwarf unwind info, look there next. 119111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sects.dwarf_section != 0) { 119211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (this->getInfoFromDwarfSection(pc, sects)) { 119311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // found info in dwarf, done 119411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 119511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 119611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 119711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 119811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 119911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if LIBCXXABI_ARM_EHABI 120011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // If there is ARM EHABI unwind info, look there next. 120111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) 120211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 120311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 120411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 120511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 120611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_DWARF_UNWIND 120711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // There is no static unwind info for this pc. Look to see if an FDE was 120811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // dynamically registered for it. 120911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc); 121011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (cachedFDE != 0) { 121111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; 121211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; 121311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace, 121411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cachedFDE, &fdeInfo, &cieInfo); 121511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (msg == NULL) { 121611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename CFI_Parser<A>::PrologInfo prolog; 121711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, 121811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pc, &prolog)) { 121911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // save off parsed FDE info 122011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.start_ip = fdeInfo.pcStart; 122111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.end_ip = fdeInfo.pcEnd; 122211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.lsda = fdeInfo.lsda; 122311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.handler = cieInfo.personality; 122411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.gp = prolog.spExtraArgSize; 122511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Some frameless functions need SP 122611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // altered when resuming in function. 122711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.flags = 0; 122811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.format = dwarfEncoding(); 122911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info = fdeInfo.fdeStart; 123011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; 123111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.extra = 0; 123211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 123311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 123411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 123511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 123611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 123711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Lastly, ask AddressSpace object about platform specific ways to locate 123811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // other FDEs. 123911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert pint_t fde; 124011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_addressSpace.findOtherFDE(pc, fde)) { 124111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo; 124211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo; 124311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) { 124411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Double check this FDE is for a function that includes the pc. 124511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) { 124611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert typename CFI_Parser<A>::PrologInfo prolog; 124711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, 124811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert cieInfo, pc, &prolog)) { 124911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // save off parsed FDE info 125011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.start_ip = fdeInfo.pcStart; 125111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.end_ip = fdeInfo.pcEnd; 125211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.lsda = fdeInfo.lsda; 125311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.handler = cieInfo.personality; 125411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.gp = prolog.spExtraArgSize; 125511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.flags = 0; 125611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.format = dwarfEncoding(); 125711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info = fdeInfo.fdeStart; 125811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength; 125911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _info.extra = 0; 126011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return; 126111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 126211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 126311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 126411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 126511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // #if _LIBUNWIND_SUPPORT_DWARF_UNWIND 126611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 126711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // no unwind info, flag that we can't reliably unwind 126811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _unwindInfoMissing = true; 126911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 127011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 127111cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 127211cd02dfb91661c65134cac258cf5924270e9d2Dan Albertint UnwindCursor<A, R>::step() { 127311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Bottom of stack is defined is when unwind info cannot be found. 127411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_unwindInfoMissing) 127511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNW_STEP_END; 127611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 127711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // Use unwinding info to modify register set as if function returned. 127811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert int result; 127911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND 128011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = this->stepWithCompactEncoding(); 128111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND 128211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = this->stepWithDwarfFDE(); 128311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#elif LIBCXXABI_ARM_EHABI 128411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert result = UNW_STEP_SUCCESS; 128511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#else 128611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \ 128711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert _LIBUNWIND_SUPPORT_DWARF_UNWIND or \ 128811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert LIBCXXABI_ARM_EHABI 128911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif 129011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 129111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert // update info based on new PC 129211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (result == UNW_STEP_SUCCESS) { 129311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert this->setInfoBasedOnIPRegister(true); 129411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_unwindInfoMissing) 129511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return UNW_STEP_END; 129611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert if (_info.gp) 129711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp); 129811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert } 129911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 130011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return result; 130111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 130211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 130311cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 130411cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) { 130511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *info = _info; 130611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 130711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 130811cd02dfb91661c65134cac258cf5924270e9d2Dan Alberttemplate <typename A, typename R> 130911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertbool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen, 131011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert unw_word_t *offset) { 131111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP), 131211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert buf, bufLen, offset); 131311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} 131411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 131511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert} // namespace libunwind 131611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert 131711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif // __UNWINDCURSOR_HPP__ 1318