1b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//===------------------------- UnwindCursor.hpp ---------------------------===//
2b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
3b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//                     The LLVM Compiler Infrastructure
4b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
5b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// This file is dual licensed under the MIT and the University of Illinois Open
6b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// Source Licenses. See LICENSE.TXT for details.
7b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
8b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//
9b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik// C++ interface to lower levels of libuwind
10b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik//===----------------------------------------------------------------------===//
11b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
12b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#ifndef __UNWINDCURSOR_HPP__
13b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#define __UNWINDCURSOR_HPP__
14b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
15e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <algorithm>
16b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdint.h>
17b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdio.h>
18b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <stdlib.h>
19b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include <pthread.h>
20e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#include <unwind.h>
21b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
226dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick Kledzik#if __APPLE__
236dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick Kledzik  #include <mach-o/dyld.h>
246dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick Kledzik#endif
256dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick Kledzik
26b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "libunwind.h"
27b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
28b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "AddressSpace.hpp"
29b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "Registers.hpp"
30b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "DwarfInstructions.hpp"
31b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "CompactUnwinder.hpp"
32b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#include "config.h"
33b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
34b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziknamespace libunwind {
35b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
36b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
37b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// Cache of recently found FDEs.
38b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
39b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikclass _LIBUNWIND_HIDDEN DwarfFDECache {
40b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename A::pint_t pint_t;
41b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
42b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static pint_t findFDE(pint_t mh, pint_t pc);
43b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
44b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static void removeAllIn(pint_t mh);
45b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
46b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                               unw_word_t ip_end,
47b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                               unw_word_t fde, unw_word_t mh));
48b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
49b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
50b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
51b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  struct entry {
52b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    pint_t mh;
53b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    pint_t ip_start;
54b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    pint_t ip_end;
55b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    pint_t fde;
56b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  };
57b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
58b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // These fields are all static to avoid needing an initializer.
59b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // There is only one instance of this class per process.
60b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static pthread_rwlock_t _lock;
61b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if __APPLE__
62b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
63b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static bool _registeredForDyldUnloads;
64b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif
65b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Can't use std::vector<> here because this code is below libc++.
66b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static entry *_buffer;
67b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static entry *_bufferUsed;
68b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static entry *_bufferEnd;
69b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static entry _initialBuffer[64];
70b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
71b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
72b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
73b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktypename DwarfFDECache<A>::entry *
74b78da9875b6e35187b5d584746c78faaf3230a3dNick KledzikDwarfFDECache<A>::_buffer = _initialBuffer;
75b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
76b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
77b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktypename DwarfFDECache<A>::entry *
78b78da9875b6e35187b5d584746c78faaf3230a3dNick KledzikDwarfFDECache<A>::_bufferUsed = _initialBuffer;
79b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
80b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
81b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktypename DwarfFDECache<A>::entry *
82b78da9875b6e35187b5d584746c78faaf3230a3dNick KledzikDwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
83b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
84b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
85b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktypename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
86b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
87b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
88b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpthread_rwlock_t DwarfFDECache<A>::_lock = PTHREAD_RWLOCK_INITIALIZER;
89b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
90b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if __APPLE__
91b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
92b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikbool DwarfFDECache<A>::_registeredForDyldUnloads = false;
93b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif
94b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
95b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
96b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktypename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
97b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t result = 0;
98b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_rdlock(&_lock));
99b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  for (entry *p = _buffer; p < _bufferUsed; ++p) {
100b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if ((mh == p->mh) || (mh == 0)) {
101b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if ((p->ip_start <= pc) && (pc < p->ip_end)) {
102b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        result = p->fde;
103b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
104b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
105b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
106b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
107b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
108b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return result;
109b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
110b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
111b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
112b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikvoid DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
113b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                           pint_t fde) {
114b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock));
115b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (_bufferUsed >= _bufferEnd) {
116b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    size_t oldSize = (size_t)(_bufferEnd - _buffer);
117b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    size_t newSize = oldSize * 4;
118b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // Can't use operator new (we are below it).
119b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    entry *newBuffer = (entry *)malloc(newSize * sizeof(entry));
120b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    memcpy(newBuffer, _buffer, oldSize * sizeof(entry));
121b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (_buffer != _initialBuffer)
122b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      free(_buffer);
123b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _buffer = newBuffer;
124b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _bufferUsed = &newBuffer[oldSize];
125b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _bufferEnd = &newBuffer[newSize];
126b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
127b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _bufferUsed->mh = mh;
128b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _bufferUsed->ip_start = ip_start;
129b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _bufferUsed->ip_end = ip_end;
130b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _bufferUsed->fde = fde;
131b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  ++_bufferUsed;
132b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if __APPLE__
133b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (!_registeredForDyldUnloads) {
134b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _dyld_register_func_for_remove_image(&dyldUnloadHook);
135b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _registeredForDyldUnloads = true;
136b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
137b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif
138b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
139b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
140b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
141b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
142b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikvoid DwarfFDECache<A>::removeAllIn(pint_t mh) {
143b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock));
144b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  entry *d = _buffer;
145b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  for (const entry *s = _buffer; s < _bufferUsed; ++s) {
146b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (s->mh != mh) {
147b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (d != s)
148b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        *d = *s;
149b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      ++d;
150b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
151b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
152b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _bufferUsed = d;
153b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
154b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
155b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
156e085735cbedc82b1064f05ff796e32e906a95036Dan Albert#if __APPLE__
157b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
158b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikvoid DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {
159b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  removeAllIn((pint_t) mh);
160b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
161e085735cbedc82b1064f05ff796e32e906a95036Dan Albert#endif
162b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
163b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A>
164b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikvoid DwarfFDECache<A>::iterateCacheEntries(void (*func)(
165b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
166b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_wrlock(&_lock));
167b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  for (entry *p = _buffer; p < _bufferUsed; ++p) {
168b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    (*func)(p->ip_start, p->ip_end, p->fde, p->mh);
169b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
170b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _LIBUNWIND_LOG_NON_ZERO(::pthread_rwlock_unlock(&_lock));
171b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
172b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
173b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
174b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
175b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
176b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
177b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
178b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A> class UnwindSectionHeader {
179b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
180b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)
181b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      : _addressSpace(addressSpace), _addr(addr) {}
182b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
183b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t version() const {
184b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(_addr +
185b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                               offsetof(unwind_info_section_header, version));
186b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
187b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t commonEncodingsArraySectionOffset() const {
188b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(_addr +
189b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                               offsetof(unwind_info_section_header,
190b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                        commonEncodingsArraySectionOffset));
191b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
192b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t commonEncodingsArrayCount() const {
193b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
194b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                commonEncodingsArrayCount));
195b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
196b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t personalityArraySectionOffset() const {
197b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
198b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                personalityArraySectionOffset));
199b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
200b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t personalityArrayCount() const {
201b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
202b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_section_header, personalityArrayCount));
203b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
204b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t indexSectionOffset() const {
205b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
206b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_section_header, indexSectionOffset));
207b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
208b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t indexCount() const {
209b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
210b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_section_header, indexCount));
211b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
212b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
213b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
214b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A                     &_addressSpace;
215b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename A::pint_t     _addr;
216b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
217b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
218b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A> class UnwindSectionIndexArray {
219b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
220b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr)
221b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      : _addressSpace(addressSpace), _addr(addr) {}
222b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
223b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t functionOffset(uint32_t index) const {
224b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
225b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
226b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              functionOffset));
227b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
228b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t secondLevelPagesSectionOffset(uint32_t index) const {
229b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
230b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
231b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              secondLevelPagesSectionOffset));
232b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
233b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t lsdaIndexArraySectionOffset(uint32_t index) const {
234b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
235b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
236b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              lsdaIndexArraySectionOffset));
237b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
238b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
239b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
240b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A                   &_addressSpace;
241b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename A::pint_t   _addr;
242b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
243b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
244b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A> class UnwindSectionRegularPageHeader {
245b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
246b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr)
247b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      : _addressSpace(addressSpace), _addr(addr) {}
248b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
249b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t kind() const {
250b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
251b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_regular_second_level_page_header, kind));
252b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
253b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint16_t entryPageOffset() const {
254b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get16(
255b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_regular_second_level_page_header,
256b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                         entryPageOffset));
257b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
258b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint16_t entryCount() const {
259b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get16(
260b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr +
261b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        offsetof(unwind_info_regular_second_level_page_header, entryCount));
262b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
263b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
264b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
265b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A &_addressSpace;
266b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename A::pint_t _addr;
267b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
268b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
269b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A> class UnwindSectionRegularArray {
270b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
271b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr)
272b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      : _addressSpace(addressSpace), _addr(addr) {}
273b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
274b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t functionOffset(uint32_t index) const {
275b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
276b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index,
277b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              functionOffset));
278b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
279b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t encoding(uint32_t index) const {
280b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
281b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr +
282b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding));
283b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
284b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
285b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
286b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A &_addressSpace;
287b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename A::pint_t _addr;
288b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
289b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
290b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A> class UnwindSectionCompressedPageHeader {
291b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
292b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr)
293b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      : _addressSpace(addressSpace), _addr(addr) {}
294b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
295b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t kind() const {
296b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
297b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr +
298b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        offsetof(unwind_info_compressed_second_level_page_header, kind));
299b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
300b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint16_t entryPageOffset() const {
301b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get16(
302b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_compressed_second_level_page_header,
303b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                         entryPageOffset));
304b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
305b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint16_t entryCount() const {
306b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get16(
307b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr +
308b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        offsetof(unwind_info_compressed_second_level_page_header, entryCount));
309b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
310b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint16_t encodingsPageOffset() const {
311b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get16(
312b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_compressed_second_level_page_header,
313b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                         encodingsPageOffset));
314b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
315b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint16_t encodingsCount() const {
316b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get16(
317b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + offsetof(unwind_info_compressed_second_level_page_header,
318b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                         encodingsCount));
319b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
320b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
321b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
322b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A &_addressSpace;
323b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename A::pint_t _addr;
324b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
325b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
326b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A> class UnwindSectionCompressedArray {
327b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
328b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr)
329b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      : _addressSpace(addressSpace), _addr(addr) {}
330b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
331b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t functionOffset(uint32_t index) const {
332b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
333b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addressSpace.get32(_addr + index * sizeof(uint32_t)));
334b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
335b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint16_t encodingIndex(uint32_t index) const {
336b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
337b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addressSpace.get32(_addr + index * sizeof(uint32_t)));
338b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
339b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
340b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
341b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A &_addressSpace;
342b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename A::pint_t _addr;
343b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
344b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
345b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A> class UnwindSectionLsdaArray {
346b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
347b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr)
348b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      : _addressSpace(addressSpace), _addr(addr) {}
349b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
350b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t functionOffset(uint32_t index) const {
351b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
352b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
353b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              index, functionOffset));
354b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
355b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t lsdaOffset(uint32_t index) const {
356b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return _addressSpace.get32(
357b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
358b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              index, lsdaOffset));
359b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
360b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
361b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
362b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A                   &_addressSpace;
363b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename A::pint_t   _addr;
364b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
365b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
366b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
367b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
368b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikclass _LIBUNWIND_HIDDEN AbstractUnwindCursor {
369b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
370e085735cbedc82b1064f05ff796e32e906a95036Dan Albert  virtual             ~AbstractUnwindCursor() {}
371b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        validReg(int) = 0;
372b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual unw_word_t  getReg(int) = 0;
373b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        setReg(int, unw_word_t) = 0;
374b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        validFloatReg(int) = 0;
375e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  virtual unw_fpreg_t getFloatReg(int) = 0;
376e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  virtual void        setFloatReg(int, unw_fpreg_t) = 0;
377b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual int         step() = 0;
378b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        getInfo(unw_proc_info_t *) = 0;
379b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        jumpto() = 0;
380b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        isSignalFrame() = 0;
381b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        getFunctionName(char *bf, size_t ln, unw_word_t *off) = 0;
382b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        setInfoBasedOnIPRegister(bool isReturnAddr = false) = 0;
383b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual const char *getRegisterName(int num) = 0;
384e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if __arm__
385e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  virtual void        saveVFPAsX() = 0;
386e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
387b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
388b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
389b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
390b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// UnwindCursor contains all state (including all register values) during
391b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik/// an unwind.  This is normally stack allocated inside a unw_cursor_t.
392b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
393b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikclass UnwindCursor : public AbstractUnwindCursor{
394b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typedef typename A::pint_t pint_t;
395b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikpublic:
396b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                      UnwindCursor(unw_context_t *context, A &as);
3976dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick Kledzik                      UnwindCursor(A &as, void *threadArg);
398b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual             ~UnwindCursor() {}
399b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        validReg(int);
400b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual unw_word_t  getReg(int);
401b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        setReg(int, unw_word_t);
402b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        validFloatReg(int);
403e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  virtual unw_fpreg_t getFloatReg(int);
404e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  virtual void        setFloatReg(int, unw_fpreg_t);
405b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual int         step();
406b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        getInfo(unw_proc_info_t *);
407b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        jumpto();
408b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        isSignalFrame();
409b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
410b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
411b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  virtual const char *getRegisterName(int num);
412e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if __arm__
413e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  virtual void        saveVFPAsX();
414e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
415b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
416b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  void            operator delete(void *, size_t) {}
417b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
418b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikprivate:
419b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
420e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if LIBCXXABI_ARM_EHABI
421e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
422e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
423e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
424b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
425b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
426b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                            uint32_t fdeSectionOffsetHint=0);
427b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  int stepWithDwarfFDE() {
428b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace,
429b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                              (pint_t)this->getReg(UNW_REG_IP),
430b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                              (pint_t)_info.unwind_info,
431b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                              _registers);
432b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
433b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif
434b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
435b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
436b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool getInfoFromCompactEncodingSection(pint_t pc,
437b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                            const UnwindInfoSections &sects);
438b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  int stepWithCompactEncoding() {
439b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
440b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if ( compactSaysUseDwarf() )
441b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return stepWithDwarfFDE();
442b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  #endif
443b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    R dummy;
444b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return stepWithCompactEncoding(dummy);
445b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
446b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
447b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  int stepWithCompactEncoding(Registers_x86_64 &) {
448b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
449b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.format, _info.start_ip, _addressSpace, _registers);
450b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
451b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
452b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  int stepWithCompactEncoding(Registers_x86 &) {
453b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return CompactUnwinder_x86<A>::stepWithCompactEncoding(
454b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
455b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
456b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
457b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  int stepWithCompactEncoding(Registers_ppc &) {
458b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return UNW_EINVAL;
459b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
460b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
461b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  int stepWithCompactEncoding(Registers_arm64 &) {
462b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
463b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.format, _info.start_ip, _addressSpace, _registers);
464b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
465b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
466b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
467b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    R dummy;
468b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return compactSaysUseDwarf(dummy, offset);
469b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
470b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
471b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
472b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
473b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (offset)
474b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
475b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return true;
476b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
477b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return false;
478b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
479b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
480b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
481b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
482b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (offset)
483b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);
484b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return true;
485b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
486b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return false;
487b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
488b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
489b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
490b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return true;
491b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
492b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
493b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
494b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
495b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (offset)
496b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);
497b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return true;
498b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
499b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return false;
500b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
501e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
502b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
503e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
504b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  compact_unwind_encoding_t dwarfEncoding() const {
505b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    R dummy;
506b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return dwarfEncoding(dummy);
507b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
508b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
509b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
510b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return UNWIND_X86_64_MODE_DWARF;
511b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
512b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
513b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
514b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return UNWIND_X86_MODE_DWARF;
515b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
516b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
517b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
518b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return 0;
519b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
520b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
521b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
522b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return UNWIND_ARM64_MODE_DWARF;
523b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
524e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
525b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
526b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
527b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  A               &_addressSpace;
528b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  R                _registers;
529b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  unw_proc_info_t  _info;
530b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool             _unwindInfoMissing;
531b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool             _isSignalFrame;
532b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik};
533b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
534b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
535b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
536b78da9875b6e35187b5d584746c78faaf3230a3dNick KledzikUnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
537b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    : _addressSpace(as), _registers(context), _unwindInfoMissing(false),
538b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _isSignalFrame(false) {
539b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  static_assert(sizeof(UnwindCursor<A, R>) < sizeof(unw_cursor_t),
540b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                "UnwindCursor<> does not fit in unw_cursor_t");
541e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  memset(&_info, 0, sizeof(_info));
542b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
543b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
544b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
5456dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick KledzikUnwindCursor<A, R>::UnwindCursor(A &as, void *)
546b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
547e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  memset(&_info, 0, sizeof(_info));
548b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // FIXME
5496dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick Kledzik  // fill in _registers from thread arg
550b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
551b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
5526dc154019d5f0997d7df1d9e9f3ba1425396dcd8Nick Kledzik
553b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
554b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikbool UnwindCursor<A, R>::validReg(int regNum) {
555b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _registers.validRegister(regNum);
556b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
557b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
558b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
559b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikunw_word_t UnwindCursor<A, R>::getReg(int regNum) {
560b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _registers.getRegister(regNum);
561b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
562b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
563b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
564b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikvoid UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
565b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _registers.setRegister(regNum, (typename A::pint_t)value);
566b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
567b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
568b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
569b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikbool UnwindCursor<A, R>::validFloatReg(int regNum) {
570b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _registers.validFloatRegister(regNum);
571b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
572b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
573b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
574e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertunw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
575b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _registers.getFloatRegister(regNum);
576b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
577b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
578b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
579e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertvoid UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
580b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _registers.setFloatRegister(regNum, value);
581b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
582b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
583b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
584b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _registers.jumpto();
585b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
586b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
587e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if __arm__
588e45805f0d3f8dafef1297cc7dc49e610713f023bDan Alberttemplate <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
589e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _registers.saveVFPAsX();
590e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
591e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
592e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
593b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
594b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikconst char *UnwindCursor<A, R>::getRegisterName(int regNum) {
595b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _registers.getRegisterName(regNum);
596b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
597b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
598b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
599b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _isSignalFrame;
600b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
601b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
602e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if LIBCXXABI_ARM_EHABI
603e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstruct EHABIIndexEntry {
604e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uint32_t functionOffset;
605e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uint32_t data;
606e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert};
607e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
608e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert// Unable to unwind in the ARM index table (section 5 EHABI).
609e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#define UNW_EXIDX_CANTUNWIND 0x1
610e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
611e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstatic inline uint32_t signExtendPrel31(uint32_t data) {
612e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return data | ((data & 0x40000000u) << 1);
613e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
614e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
615e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertextern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr0(
616e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
617e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertextern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr1(
618e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
619e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertextern "C" _Unwind_Reason_Code __aeabi_unwind_cpp_pr2(
620e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    _Unwind_State state, _Unwind_Control_Block *ucbp, _Unwind_Context *context);
621e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
622e45805f0d3f8dafef1297cc7dc49e610713f023bDan Alberttemplate<typename A>
623e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertstruct EHABISectionIterator {
624e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typedef EHABISectionIterator _Self;
625e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
626e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typedef std::random_access_iterator_tag iterator_category;
627e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typedef typename A::pint_t value_type;
628e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typedef typename A::pint_t* pointer;
629e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typedef typename A::pint_t& reference;
630e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typedef size_t size_type;
631e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typedef size_t difference_type;
632e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
633e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {
634e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return _Self(addressSpace, sects, 0);
635e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
636e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
637e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return _Self(addressSpace, sects, sects.arm_section_length);
638e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
639e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
640e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
641e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      : _addressSpace(&addressSpace), _sects(&sects), _i(i) {}
642e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
643e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Self& operator++() { ++_i; return *this; }
644e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Self& operator+=(size_t a) { _i += a; return *this; }
645e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Self& operator--() { assert(_i > 0); --_i; return *this; }
646e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; }
647e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
648e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; }
649e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; }
650e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
651e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  size_t operator-(const _Self& other) { return _i - other._i; }
652e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
653e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  bool operator==(const _Self& other) const {
654e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    assert(_addressSpace == other._addressSpace);
655e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    assert(_sects == other._sects);
656e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return _i == other._i;
657e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
658e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
659e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typename A::pint_t operator*() const { return functionAddress(); }
660e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
661e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typename A::pint_t functionAddress() const {
662e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
663e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        EHABIIndexEntry, _i, functionOffset);
664e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));
665e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
666e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
667e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  typename A::pint_t dataAddress() {
668e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
669e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        EHABIIndexEntry, _i, data);
670e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return indexAddr;
671e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
672e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
673e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert private:
674e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  size_t _i;
675e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  A* _addressSpace;
676e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  const UnwindInfoSections* _sects;
677e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert};
678e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
679e45805f0d3f8dafef1297cc7dc49e610713f023bDan Alberttemplate <typename A, typename R>
680e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albertbool UnwindCursor<A, R>::getInfoFromEHABISection(
681e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    pint_t pc,
682e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    const UnwindInfoSections &sects) {
683e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  EHABISectionIterator<A> begin =
684e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      EHABISectionIterator<A>::begin(_addressSpace, sects);
685e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  EHABISectionIterator<A> end =
686e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      EHABISectionIterator<A>::end(_addressSpace, sects);
687e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
688e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
689e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (itNextPC == begin || itNextPC == end)
690e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return false;
691e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  EHABISectionIterator<A> itThisPC = itNextPC - 1;
692e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
693e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  pint_t thisPC = itThisPC.functionAddress();
694e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  pint_t nextPC = itNextPC.functionAddress();
695e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  pint_t indexDataAddr = itThisPC.dataAddress();
696e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
697e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (indexDataAddr == 0)
698e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return false;
699e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
700e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uint32_t indexData = _addressSpace.get32(indexDataAddr);
701e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (indexData == UNW_EXIDX_CANTUNWIND)
702e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    return false;
703e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
704e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // If the high bit is set, the exception handling table entry is inline inside
705e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
706e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // the table points at an offset in the exception handling table (section 5 EHABI).
707e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  pint_t exceptionTableAddr;
708e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uint32_t exceptionTableData;
709e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  bool isSingleWordEHT;
710e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (indexData & 0x80000000) {
711e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    exceptionTableAddr = indexDataAddr;
712e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // TODO(ajwong): Should this data be 0?
713e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    exceptionTableData = indexData;
714e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    isSingleWordEHT = true;
715e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  } else {
716e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);
717e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    exceptionTableData = _addressSpace.get32(exceptionTableAddr);
718e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    isSingleWordEHT = false;
719e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
720e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
721e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Now we know the 3 things:
722e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  //   exceptionTableAddr -- exception handler table entry.
723e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  //   exceptionTableData -- the data inside the first word of the eht entry.
724e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  //   isSingleWordEHT -- whether the entry is in the index.
725e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  unw_word_t personalityRoutine = 0xbadf00d;
726e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  bool scope32 = false;
727e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  uintptr_t lsda = 0xbadf00d;
728e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
729e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // If the high bit in the exception handling table entry is set, the entry is
730e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // in compact form (section 6.3 EHABI).
731e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  if (exceptionTableData & 0x80000000) {
732e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // Grab the index of the personality routine from the compact form.
733e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    int choice = (exceptionTableData & 0x0f000000) >> 24;
734e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    int extraWords = 0;
735e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    switch (choice) {
736e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case 0:
737e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;
738e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        extraWords = 0;
739e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        scope32 = false;
740e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
741e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case 1:
742e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;
743e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        extraWords = (exceptionTableData & 0x00ff0000) >> 16;
744e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        scope32 = false;
745e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
746e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      case 2:
747e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;
748e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        extraWords = (exceptionTableData & 0x00ff0000) >> 16;
749e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        scope32 = true;
750e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        break;
751e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      default:
752e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_ABORT("unknown personality routine");
753e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return false;
754e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
755e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
756e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (isSingleWordEHT) {
757e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      if (extraWords != 0) {
758e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        _LIBUNWIND_ABORT("index inlined table detected but pr function "
759e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert                         "requires extra words");
760e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        return false;
761e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      }
762e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    }
763e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  } else {
764e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    pint_t personalityAddr =
765e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        exceptionTableAddr + signExtendPrel31(exceptionTableData);
766e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    personalityRoutine = personalityAddr;
767e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
768e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // ARM EHABI # 6.2, # 9.2
769e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    //
770e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    //  +---- ehtp
771e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    //  v
772e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // +--------------------------------------+
773e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | +--------+--------+--------+-------+ |
774e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | |0| prel31 to personalityRoutine   | |
775e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | +--------+--------+--------+-------+ |
776e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | |      N |      unwind opcodes     | |  <-- UnwindData
777e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | +--------+--------+--------+-------+ |
778e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | | Word 2        unwind opcodes     | |
779e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | +--------+--------+--------+-------+ |
780e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | ...                                  |
781e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | +--------+--------+--------+-------+ |
782e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | | Word N        unwind opcodes     | |
783e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | +--------+--------+--------+-------+ |
784e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | | LSDA                             | |  <-- lsda
785e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | | ...                              | |
786e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // | +--------+--------+--------+-------+ |
787e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // +--------------------------------------+
788e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
789e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;
790e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    uint32_t FirstDataWord = *UnwindData;
791e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    size_t N = ((FirstDataWord >> 24) & 0xff);
792e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    size_t NDataWords = N + 1;
793e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);
794e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  }
795e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
796e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _info.start_ip = thisPC;
797e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _info.end_ip = nextPC;
798e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _info.handler = personalityRoutine;
799e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _info.unwind_info = exceptionTableAddr;
800e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _info.lsda = lsda;
801e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
802e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0;  // Use enum?
803e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
804e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  return true;
805e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert}
806e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
807e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
808b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
809b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
810b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikbool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
811b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                const UnwindInfoSections &sects,
812b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                uint32_t fdeSectionOffsetHint) {
813b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename CFI_Parser<A>::FDE_Info fdeInfo;
814b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  typename CFI_Parser<A>::CIE_Info cieInfo;
815b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool foundFDE = false;
816b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  bool foundInCache = false;
817b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // If compact encoding table gave offset into dwarf section, go directly there
818b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (fdeSectionOffsetHint != 0) {
819b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
820b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                    (uint32_t)sects.dwarf_section_length,
821b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                    sects.dwarf_section + fdeSectionOffsetHint,
822b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                    &fdeInfo, &cieInfo);
823b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
824b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_DWARF_INDEX
825b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (!foundFDE && (sects.dwarf_index_section != 0)) {
826b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // Have eh_frame_hdr section which is index into dwarf section.
827b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // TO DO: implement index search
828b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
829b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif
830b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (!foundFDE) {
831b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // otherwise, search cache of previously found FDEs.
832b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);
833b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (cachedFDE != 0) {
834b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      foundFDE =
835b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
836b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 (uint32_t)sects.dwarf_section_length,
837b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                 cachedFDE, &fdeInfo, &cieInfo);
838b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      foundInCache = foundFDE;
839b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
840b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
841b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (!foundFDE) {
842b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // Still not found, do full scan of __eh_frame section.
843b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
844b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                      (uint32_t)sects.dwarf_section_length, 0,
845b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                      &fdeInfo, &cieInfo);
846b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
847b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (foundFDE) {
848b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    typename CFI_Parser<A>::PrologInfo prolog;
849b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
850b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                            &prolog)) {
851b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // Save off parsed FDE info
852b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.start_ip          = fdeInfo.pcStart;
853b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.end_ip            = fdeInfo.pcEnd;
854b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.lsda              = fdeInfo.lsda;
855b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.handler           = cieInfo.personality;
856b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.gp                = prolog.spExtraArgSize;
857b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.flags             = 0;
858b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.format            = dwarfEncoding();
859b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.unwind_info       = fdeInfo.fdeStart;
860b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.unwind_info_size  = (uint32_t)fdeInfo.fdeLength;
861b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _info.extra             = (unw_word_t) sects.dso_base;
862b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
863b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // Add to cache (to make next lookup faster) if we had no hint
864b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // and there was no index.
865b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (!foundInCache && (fdeSectionOffsetHint == 0)) {
866b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  #if _LIBUNWIND_SUPPORT_DWARF_INDEX
867b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        if (sects.dwarf_index_section == 0)
868b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  #endif
869b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
870b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              fdeInfo.fdeStart);
871b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
872b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return true;
873b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
874b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
875b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc);
876b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return false;
877b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
878b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
879b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
880b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
881b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
882b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
883b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikbool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
884b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                              const UnwindInfoSections &sects) {
885b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const bool log = false;
886b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (log)
887b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
888b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            (uint64_t)pc, (uint64_t)sects.dso_base);
889b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
890b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const UnwindSectionHeader<A> sectionHeader(_addressSpace,
891b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                sects.compact_unwind_section);
892b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (sectionHeader.version() != UNWIND_SECTION_VERSION)
893b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return false;
894b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
895b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // do a binary search of top level index to find page with unwind info
896b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t targetFunctionOffset = pc - sects.dso_base;
897b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const UnwindSectionIndexArray<A> topIndex(_addressSpace,
898b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                           sects.compact_unwind_section
899b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                         + sectionHeader.indexSectionOffset());
900b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t low = 0;
901b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t high = sectionHeader.indexCount();
902b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t last = high - 1;
903b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  while (low < high) {
904b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    uint32_t mid = (low + high) / 2;
905b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
906b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    //mid, low, high, topIndex.functionOffset(mid));
907b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (topIndex.functionOffset(mid) <= targetFunctionOffset) {
908b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if ((mid == last) ||
909b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {
910b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        low = mid;
911b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
912b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      } else {
913b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        low = mid + 1;
914b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
915b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    } else {
916b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      high = mid;
917b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
918b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
919b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
920b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const uint32_t firstLevelNextPageFunctionOffset =
921b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      topIndex.functionOffset(low + 1);
922b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const pint_t secondLevelAddr =
923b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);
924b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const pint_t lsdaArrayStartAddr =
925b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);
926b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  const pint_t lsdaArrayEndAddr =
927b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);
928b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (log)
929b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    fprintf(stderr, "\tfirst level search for result index=%d "
930b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                    "to secondLevelAddr=0x%llX\n",
931b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                    low, (uint64_t) secondLevelAddr);
932b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // do a binary search of second level page index
933b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t encoding = 0;
934b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t funcStart = 0;
935b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t funcEnd = 0;
936b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t lsda = 0;
937b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t personality = 0;
938b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t pageKind = _addressSpace.get32(secondLevelAddr);
939b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {
940b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // regular page
941b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,
942b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                 secondLevelAddr);
943b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    UnwindSectionRegularArray<A> pageIndex(
944b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
945b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // binary search looks for entry with e where index[e].offset <= pc <
946b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // index[e+1].offset
947b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (log)
948b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "
949b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                      "regular page starting at secondLevelAddr=0x%llX\n",
950b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik              (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);
951b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    low = 0;
952b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    high = pageHeader.entryCount();
953b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    while (low < high) {
954b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      uint32_t mid = (low + high) / 2;
955b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {
956b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {
957b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          // at end of table
958b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          low = mid;
959b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
960b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          break;
961b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {
962b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          // next is too big, so we found it
963b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          low = mid;
964b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;
965b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          break;
966b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        } else {
967b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          low = mid + 1;
968b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        }
969b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      } else {
970b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        high = mid;
971b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
972b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
973b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    encoding = pageIndex.encoding(low);
974b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    funcStart = pageIndex.functionOffset(low) + sects.dso_base;
975b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (pc < funcStart) {
976b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
977b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(
978b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            stderr,
979b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
980b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
981b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return false;
982b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
983b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (pc > funcEnd) {
984b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (log)
985b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        fprintf(
986b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            stderr,
987b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
988b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
989b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return false;
990b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
991b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {
992b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // compressed page
993b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,
994b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                    secondLevelAddr);
995b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    UnwindSectionCompressedArray<A> pageIndex(
996b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
997b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    const uint32_t targetFunctionPageOffset =
998b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset);
999b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // binary search looks for entry with e where index[e].offset <= pc <
1000b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // index[e+1].offset
1001b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (log)
1002b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      fprintf(stderr, "\tbinary search of compressed page starting at "
1003b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                      "secondLevelAddr=0x%llX\n",
1004b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik              (uint64_t) secondLevelAddr);
1005b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    low = 0;
1006b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    last = pageHeader.entryCount() - 1;
1007b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    high = pageHeader.entryCount();
1008b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    while (low < high) {
1009b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      uint32_t mid = (low + high) / 2;
1010b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {
1011b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        if ((mid == last) ||
1012b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {
1013b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          low = mid;
1014b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          break;
1015b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        } else {
1016b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          low = mid + 1;
1017b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        }
1018b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      } else {
1019b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        high = mid;
1020b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
1021b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1022b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset
1023b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                              + sects.dso_base;
1024b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (low < last)
1025b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      funcEnd =
1026b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset
1027b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                              + sects.dso_base;
1028b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    else
1029b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1030b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (pc < funcStart) {
1031b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second  "
1032b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                           "level compressed unwind table. funcStart=0x%llX\n",
1033b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            (uint64_t) pc, (uint64_t) funcStart);
1034b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return false;
1035b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1036b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (pc > funcEnd) {
1037b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second  "
1038b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                          "level compressed unwind table. funcEnd=0x%llX\n",
1039b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                           (uint64_t) pc, (uint64_t) funcEnd);
1040b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return false;
1041b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1042b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    uint16_t encodingIndex = pageIndex.encodingIndex(low);
1043b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) {
1044b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // encoding is in common table in section header
1045b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      encoding = _addressSpace.get32(
1046b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          sects.compact_unwind_section +
1047b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          sectionHeader.commonEncodingsArraySectionOffset() +
1048b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          encodingIndex * sizeof(uint32_t));
1049b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    } else {
1050b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // encoding is in page specific table
1051b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      uint16_t pageEncodingIndex =
1052b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount();
1053b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      encoding = _addressSpace.get32(secondLevelAddr +
1054b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                     pageHeader.encodingsPageOffset() +
1055b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                     pageEncodingIndex * sizeof(uint32_t));
1056b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1057b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  } else {
1058b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second "
1059b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                         "level page\n",
1060b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                          (uint64_t) sects.compact_unwind_section);
1061b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return false;
1062b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
1063b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1064b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // look up LSDA, if encoding says function has one
1065b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (encoding & UNWIND_HAS_LSDA) {
1066b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);
1067b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);
1068b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    low = 0;
1069b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /
1070b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                    sizeof(unwind_info_section_header_lsda_index_entry);
1071b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // binary search looks for entry with exact match for functionOffset
1072b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (log)
1073b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      fprintf(stderr,
1074b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik              "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1075b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik              funcStartOffset);
1076b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    while (low < high) {
1077b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      uint32_t mid = (low + high) / 2;
1078b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (lsdaIndex.functionOffset(mid) == funcStartOffset) {
1079b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;
1080b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        break;
1081b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {
1082b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        low = mid + 1;
1083b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      } else {
1084b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        high = mid;
1085b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
1086b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1087b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (lsda == 0) {
1088b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1089b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                    "pc=0x%0llX, but lsda table has no entry\n",
1090b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                    encoding, (uint64_t) pc);
1091b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return false;
1092b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1093b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
1094b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1095b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // extact personality routine, if encoding says function has one
1096b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
1097b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                              (__builtin_ctz(UNWIND_PERSONALITY_MASK));
1098b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (personalityIndex != 0) {
1099b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    --personalityIndex; // change 1-based to zero-based index
1100b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (personalityIndex > sectionHeader.personalityArrayCount()) {
1101b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d,  "
1102b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            "but personality table has only %d entires\n",
1103b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            encoding, personalityIndex,
1104b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                            sectionHeader.personalityArrayCount());
1105b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return false;
1106b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1107e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    int32_t personalityDelta = (int32_t)_addressSpace.get32(
1108e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        sects.compact_unwind_section +
1109e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert        sectionHeader.personalityArraySectionOffset() +
1110b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        personalityIndex * sizeof(uint32_t));
1111b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
1112b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    personality = _addressSpace.getP(personalityPointer);
1113b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (log)
1114b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1115b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                      "personalityDelta=0x%08X, personality=0x%08llX\n",
1116b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik              (uint64_t) pc, personalityDelta, (uint64_t) personality);
1117b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
1118b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1119b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (log)
1120b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1121b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                    "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1122b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart);
1123b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.start_ip = funcStart;
1124b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.end_ip = funcEnd;
1125b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.lsda = lsda;
1126b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.handler = personality;
1127b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.gp = 0;
1128b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.flags = 0;
1129b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.format = encoding;
1130b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.unwind_info = 0;
1131b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.unwind_info_size = 0;
1132b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _info.extra = sects.dso_base;
1133b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return true;
1134b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
1135b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
1136b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1137b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1138b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
1139b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikvoid UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
1140b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
1141e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if LIBCXXABI_ARM_EHABI
1142e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Remove the thumb bit so the IP represents the actual instruction address.
1143e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // This matches the behaviour of _Unwind_GetIP on arm.
1144e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  pc &= (pint_t)~0x1;
1145e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
1146b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1147b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // If the last line of a function is a "throw" the compiler sometimes
1148b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // emits no instructions after the call to __cxa_throw.  This means
1149b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // the return address is actually the start of the next function.
1150b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // To disambiguate this, back up the pc when we know it is a return
1151b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // address.
1152b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (isReturnAddress)
1153b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    --pc;
1154b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1155b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Ask address space object to find unwind sections for this pc.
1156b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  UnwindInfoSections sects;
1157b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (_addressSpace.findUnwindSections(pc, sects)) {
1158b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
1159b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // If there is a compact unwind encoding table, look there first.
1160b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (sects.compact_unwind_section != 0) {
1161b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (this->getInfoFromCompactEncodingSection(pc, sects)) {
1162b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
1163b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // Found info in table, done unless encoding says to use dwarf.
1164b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        uint32_t dwarfOffset;
1165b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
1166b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {
1167b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            // found info in dwarf, done
1168b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik            return;
1169b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          }
1170b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        }
1171b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  #endif
1172b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // If unwind table has entry, but entry says there is no unwind info,
1173b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // record that we have no unwind info.
1174b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        if (_info.format == 0)
1175b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _unwindInfoMissing = true;
1176b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return;
1177b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
1178b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1179b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
1180b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1181b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
1182b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    // If there is dwarf unwind info, look there next.
1183b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (sects.dwarf_section != 0) {
1184b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (this->getInfoFromDwarfSection(pc, sects)) {
1185b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // found info in dwarf, done
1186b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return;
1187b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
1188b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1189b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif
1190e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert
1191e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#if LIBCXXABI_ARM_EHABI
1192e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    // If there is ARM EHABI unwind info, look there next.
1193e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert    if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
1194e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert      return;
1195e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#endif
1196b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
1197b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1198b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_DWARF_UNWIND
1199b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // There is no static unwind info for this pc. Look to see if an FDE was
1200b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // dynamically registered for it.
1201b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
1202b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (cachedFDE != 0) {
1203b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1204b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1205b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace,
1206b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                cachedFDE, &fdeInfo, &cieInfo);
1207b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (msg == NULL) {
1208b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      typename CFI_Parser<A>::PrologInfo prolog;
1209b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
1210b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                                pc, &prolog)) {
1211b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        // save off parsed FDE info
1212b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.start_ip         = fdeInfo.pcStart;
1213b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.end_ip           = fdeInfo.pcEnd;
1214b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.lsda             = fdeInfo.lsda;
1215b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.handler          = cieInfo.personality;
1216b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.gp               = prolog.spExtraArgSize;
1217b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  // Some frameless functions need SP
1218b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                  // altered when resuming in function.
1219b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.flags            = 0;
1220b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.format           = dwarfEncoding();
1221b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.unwind_info      = fdeInfo.fdeStart;
1222b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1223b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        _info.extra            = 0;
1224b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        return;
1225b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
1226b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1227b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
1228b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1229b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Lastly, ask AddressSpace object about platform specific ways to locate
1230b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // other FDEs.
1231b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  pint_t fde;
1232b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (_addressSpace.findOtherFDE(pc, fde)) {
1233b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1234b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1235b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
1236b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      // Double check this FDE is for a function that includes the pc.
1237b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
1238b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        typename CFI_Parser<A>::PrologInfo prolog;
1239b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo,
1240b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                cieInfo, pc, &prolog)) {
1241b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          // save off parsed FDE info
1242b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.start_ip         = fdeInfo.pcStart;
1243b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.end_ip           = fdeInfo.pcEnd;
1244b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.lsda             = fdeInfo.lsda;
1245b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.handler          = cieInfo.personality;
1246b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.gp               = prolog.spExtraArgSize;
1247b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.flags            = 0;
1248b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.format           = dwarfEncoding();
1249b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.unwind_info      = fdeInfo.fdeStart;
1250b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1251b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          _info.extra            = 0;
1252b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik          return;
1253b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik        }
1254b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      }
1255b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    }
1256b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
1257b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
1258b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1259b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // no unwind info, flag that we can't reliably unwind
1260b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  _unwindInfoMissing = true;
1261b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
1262b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1263b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
1264b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikint UnwindCursor<A, R>::step() {
1265e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  // Bottom of stack is defined is when unwind info cannot be found.
1266b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (_unwindInfoMissing)
1267b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    return UNW_STEP_END;
1268b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1269b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // Use unwinding info to modify register set as if function returned.
1270b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  int result;
1271b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
1272b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  result = this->stepWithCompactEncoding();
1273b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#elif _LIBUNWIND_SUPPORT_DWARF_UNWIND
1274b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  result = this->stepWithDwarfFDE();
1275e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert#elif LIBCXXABI_ARM_EHABI
1276e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  result = UNW_STEP_SUCCESS;
1277b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#else
1278e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert  #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
1279e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
1280e45805f0d3f8dafef1297cc7dc49e610713f023bDan Albert              LIBCXXABI_ARM_EHABI
1281b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif
1282b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1283b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  // update info based on new PC
1284b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  if (result == UNW_STEP_SUCCESS) {
1285b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    this->setInfoBasedOnIPRegister(true);
1286b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik    if (_unwindInfoMissing)
1287b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik      return UNW_STEP_END;
12887dfc5215ff08e992ffe88c577ba15d641e610d75Joerg Sonnenberger    if (_info.gp)
12897dfc5215ff08e992ffe88c577ba15d641e610d75Joerg Sonnenberger      setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp);
1290b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  }
1291b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1292b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return result;
1293b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
1294b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1295b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
1296b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikvoid UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
1297b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  *info = _info;
1298b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
1299b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1300b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledziktemplate <typename A, typename R>
1301b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzikbool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
1302b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                                           unw_word_t *offset) {
1303b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik  return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),
1304b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik                                         buf, bufLen, offset);
1305b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}
1306b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1307b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik}; // namespace libunwind
1308b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik
1309b78da9875b6e35187b5d584746c78faaf3230a3dNick Kledzik#endif // __UNWINDCURSOR_HPP__
1310