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