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