Home | History | Annotate | Download | only in src
      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 _LIBUNWIND_ARM_EHABI
    442   bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
    443 
    444   int stepWithEHABI() {
    445     size_t len = 0;
    446     size_t off = 0;
    447     // FIXME: Calling decode_eht_entry() here is violating the libunwind
    448     // abstraction layer.
    449     const uint32_t *ehtp =
    450         decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info),
    451                          &off, &len);
    452     if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) !=
    453             _URC_CONTINUE_UNWIND)
    454       return UNW_STEP_END;
    455     return UNW_STEP_SUCCESS;
    456   }
    457 #endif
    458 
    459 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
    460   bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
    461                                             uint32_t fdeSectionOffsetHint=0);
    462   int stepWithDwarfFDE() {
    463     return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace,
    464                                               (pint_t)this->getReg(UNW_REG_IP),
    465                                               (pint_t)_info.unwind_info,
    466                                               _registers);
    467   }
    468 #endif
    469 
    470 #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
    471   bool getInfoFromCompactEncodingSection(pint_t pc,
    472                                             const UnwindInfoSections &sects);
    473   int stepWithCompactEncoding() {
    474   #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
    475     if ( compactSaysUseDwarf() )
    476       return stepWithDwarfFDE();
    477   #endif
    478     R dummy;
    479     return stepWithCompactEncoding(dummy);
    480   }
    481 
    482   int stepWithCompactEncoding(Registers_x86_64 &) {
    483     return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
    484         _info.format, _info.start_ip, _addressSpace, _registers);
    485   }
    486 
    487   int stepWithCompactEncoding(Registers_x86 &) {
    488     return CompactUnwinder_x86<A>::stepWithCompactEncoding(
    489         _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
    490   }
    491 
    492   int stepWithCompactEncoding(Registers_ppc &) {
    493     return UNW_EINVAL;
    494   }
    495 
    496   int stepWithCompactEncoding(Registers_arm64 &) {
    497     return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
    498         _info.format, _info.start_ip, _addressSpace, _registers);
    499   }
    500 
    501   bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
    502     R dummy;
    503     return compactSaysUseDwarf(dummy, offset);
    504   }
    505 
    506   bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
    507     if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
    508       if (offset)
    509         *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
    510       return true;
    511     }
    512     return false;
    513   }
    514 
    515   bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
    516     if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
    517       if (offset)
    518         *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);
    519       return true;
    520     }
    521     return false;
    522   }
    523 
    524   bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
    525     return true;
    526   }
    527 
    528   bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
    529     if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
    530       if (offset)
    531         *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);
    532       return true;
    533     }
    534     return false;
    535   }
    536 #endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
    537 
    538 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
    539   compact_unwind_encoding_t dwarfEncoding() const {
    540     R dummy;
    541     return dwarfEncoding(dummy);
    542   }
    543 
    544   compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
    545     return UNWIND_X86_64_MODE_DWARF;
    546   }
    547 
    548   compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
    549     return UNWIND_X86_MODE_DWARF;
    550   }
    551 
    552   compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
    553     return 0;
    554   }
    555 
    556   compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
    557     return UNWIND_ARM64_MODE_DWARF;
    558   }
    559 #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
    560 
    561 
    562   A               &_addressSpace;
    563   R                _registers;
    564   unw_proc_info_t  _info;
    565   bool             _unwindInfoMissing;
    566   bool             _isSignalFrame;
    567 };
    568 
    569 
    570 template <typename A, typename R>
    571 UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
    572     : _addressSpace(as), _registers(context), _unwindInfoMissing(false),
    573       _isSignalFrame(false) {
    574   static_assert(sizeof(UnwindCursor<A, R>) < sizeof(unw_cursor_t),
    575                 "UnwindCursor<> does not fit in unw_cursor_t");
    576   memset(&_info, 0, sizeof(_info));
    577 }
    578 
    579 template <typename A, typename R>
    580 UnwindCursor<A, R>::UnwindCursor(A &as, void *)
    581     : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
    582   memset(&_info, 0, sizeof(_info));
    583   // FIXME
    584   // fill in _registers from thread arg
    585 }
    586 
    587 
    588 template <typename A, typename R>
    589 bool UnwindCursor<A, R>::validReg(int regNum) {
    590   return _registers.validRegister(regNum);
    591 }
    592 
    593 template <typename A, typename R>
    594 unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
    595   return _registers.getRegister(regNum);
    596 }
    597 
    598 template <typename A, typename R>
    599 void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
    600   _registers.setRegister(regNum, (typename A::pint_t)value);
    601 }
    602 
    603 template <typename A, typename R>
    604 bool UnwindCursor<A, R>::validFloatReg(int regNum) {
    605   return _registers.validFloatRegister(regNum);
    606 }
    607 
    608 template <typename A, typename R>
    609 unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
    610   return _registers.getFloatRegister(regNum);
    611 }
    612 
    613 template <typename A, typename R>
    614 void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
    615   _registers.setFloatRegister(regNum, value);
    616 }
    617 
    618 template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
    619   _registers.jumpto();
    620 }
    621 
    622 #ifdef __arm__
    623 template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
    624   _registers.saveVFPAsX();
    625 }
    626 #endif
    627 
    628 template <typename A, typename R>
    629 const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
    630   return _registers.getRegisterName(regNum);
    631 }
    632 
    633 template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
    634   return _isSignalFrame;
    635 }
    636 
    637 #if _LIBUNWIND_ARM_EHABI
    638 struct EHABIIndexEntry {
    639   uint32_t functionOffset;
    640   uint32_t data;
    641 };
    642 
    643 template<typename A>
    644 struct EHABISectionIterator {
    645   typedef EHABISectionIterator _Self;
    646 
    647   typedef std::random_access_iterator_tag iterator_category;
    648   typedef typename A::pint_t value_type;
    649   typedef typename A::pint_t* pointer;
    650   typedef typename A::pint_t& reference;
    651   typedef size_t size_type;
    652   typedef size_t difference_type;
    653 
    654   static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {
    655     return _Self(addressSpace, sects, 0);
    656   }
    657   static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
    658     return _Self(addressSpace, sects, sects.arm_section_length);
    659   }
    660 
    661   EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
    662       : _i(i), _addressSpace(&addressSpace), _sects(&sects) {}
    663 
    664   _Self& operator++() { ++_i; return *this; }
    665   _Self& operator+=(size_t a) { _i += a; return *this; }
    666   _Self& operator--() { assert(_i > 0); --_i; return *this; }
    667   _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; }
    668 
    669   _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; }
    670   _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; }
    671 
    672   size_t operator-(const _Self& other) { return _i - other._i; }
    673 
    674   bool operator==(const _Self& other) const {
    675     assert(_addressSpace == other._addressSpace);
    676     assert(_sects == other._sects);
    677     return _i == other._i;
    678   }
    679 
    680   typename A::pint_t operator*() const { return functionAddress(); }
    681 
    682   typename A::pint_t functionAddress() const {
    683     typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
    684         EHABIIndexEntry, _i, functionOffset);
    685     return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));
    686   }
    687 
    688   typename A::pint_t dataAddress() {
    689     typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
    690         EHABIIndexEntry, _i, data);
    691     return indexAddr;
    692   }
    693 
    694  private:
    695   size_t _i;
    696   A* _addressSpace;
    697   const UnwindInfoSections* _sects;
    698 };
    699 
    700 template <typename A, typename R>
    701 bool UnwindCursor<A, R>::getInfoFromEHABISection(
    702     pint_t pc,
    703     const UnwindInfoSections &sects) {
    704   EHABISectionIterator<A> begin =
    705       EHABISectionIterator<A>::begin(_addressSpace, sects);
    706   EHABISectionIterator<A> end =
    707       EHABISectionIterator<A>::end(_addressSpace, sects);
    708 
    709   EHABISectionIterator<A> itNextPC = std::upper_bound(begin, end, pc);
    710   if (itNextPC == begin || itNextPC == end)
    711     return false;
    712   EHABISectionIterator<A> itThisPC = itNextPC - 1;
    713 
    714   pint_t thisPC = itThisPC.functionAddress();
    715   pint_t nextPC = itNextPC.functionAddress();
    716   pint_t indexDataAddr = itThisPC.dataAddress();
    717 
    718   if (indexDataAddr == 0)
    719     return false;
    720 
    721   uint32_t indexData = _addressSpace.get32(indexDataAddr);
    722   if (indexData == UNW_EXIDX_CANTUNWIND)
    723     return false;
    724 
    725   // If the high bit is set, the exception handling table entry is inline inside
    726   // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
    727   // the table points at an offset in the exception handling table (section 5 EHABI).
    728   pint_t exceptionTableAddr;
    729   uint32_t exceptionTableData;
    730   bool isSingleWordEHT;
    731   if (indexData & 0x80000000) {
    732     exceptionTableAddr = indexDataAddr;
    733     // TODO(ajwong): Should this data be 0?
    734     exceptionTableData = indexData;
    735     isSingleWordEHT = true;
    736   } else {
    737     exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);
    738     exceptionTableData = _addressSpace.get32(exceptionTableAddr);
    739     isSingleWordEHT = false;
    740   }
    741 
    742   // Now we know the 3 things:
    743   //   exceptionTableAddr -- exception handler table entry.
    744   //   exceptionTableData -- the data inside the first word of the eht entry.
    745   //   isSingleWordEHT -- whether the entry is in the index.
    746   unw_word_t personalityRoutine = 0xbadf00d;
    747   bool scope32 = false;
    748   uintptr_t lsda;
    749 
    750   // If the high bit in the exception handling table entry is set, the entry is
    751   // in compact form (section 6.3 EHABI).
    752   if (exceptionTableData & 0x80000000) {
    753     // Grab the index of the personality routine from the compact form.
    754     uint32_t choice = (exceptionTableData & 0x0f000000) >> 24;
    755     uint32_t extraWords = 0;
    756     switch (choice) {
    757       case 0:
    758         personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;
    759         extraWords = 0;
    760         scope32 = false;
    761         lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4);
    762         break;
    763       case 1:
    764         personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;
    765         extraWords = (exceptionTableData & 0x00ff0000) >> 16;
    766         scope32 = false;
    767         lsda = exceptionTableAddr + (extraWords + 1) * 4;
    768         break;
    769       case 2:
    770         personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;
    771         extraWords = (exceptionTableData & 0x00ff0000) >> 16;
    772         scope32 = true;
    773         lsda = exceptionTableAddr + (extraWords + 1) * 4;
    774         break;
    775       default:
    776         _LIBUNWIND_ABORT("unknown personality routine");
    777         return false;
    778     }
    779 
    780     if (isSingleWordEHT) {
    781       if (extraWords != 0) {
    782         _LIBUNWIND_ABORT("index inlined table detected but pr function "
    783                          "requires extra words");
    784         return false;
    785       }
    786     }
    787   } else {
    788     pint_t personalityAddr =
    789         exceptionTableAddr + signExtendPrel31(exceptionTableData);
    790     personalityRoutine = personalityAddr;
    791 
    792     // ARM EHABI # 6.2, # 9.2
    793     //
    794     //  +---- ehtp
    795     //  v
    796     // +--------------------------------------+
    797     // | +--------+--------+--------+-------+ |
    798     // | |0| prel31 to personalityRoutine   | |
    799     // | +--------+--------+--------+-------+ |
    800     // | |      N |      unwind opcodes     | |  <-- UnwindData
    801     // | +--------+--------+--------+-------+ |
    802     // | | Word 2        unwind opcodes     | |
    803     // | +--------+--------+--------+-------+ |
    804     // | ...                                  |
    805     // | +--------+--------+--------+-------+ |
    806     // | | Word N        unwind opcodes     | |
    807     // | +--------+--------+--------+-------+ |
    808     // | | LSDA                             | |  <-- lsda
    809     // | | ...                              | |
    810     // | +--------+--------+--------+-------+ |
    811     // +--------------------------------------+
    812 
    813     uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;
    814     uint32_t FirstDataWord = *UnwindData;
    815     size_t N = ((FirstDataWord >> 24) & 0xff);
    816     size_t NDataWords = N + 1;
    817     lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);
    818   }
    819 
    820   _info.start_ip = thisPC;
    821   _info.end_ip = nextPC;
    822   _info.handler = personalityRoutine;
    823   _info.unwind_info = exceptionTableAddr;
    824   _info.lsda = lsda;
    825   // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
    826   _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0;  // Use enum?
    827 
    828   return true;
    829 }
    830 #endif
    831 
    832 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
    833 template <typename A, typename R>
    834 bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
    835                                                 const UnwindInfoSections &sects,
    836                                                 uint32_t fdeSectionOffsetHint) {
    837   typename CFI_Parser<A>::FDE_Info fdeInfo;
    838   typename CFI_Parser<A>::CIE_Info cieInfo;
    839   bool foundFDE = false;
    840   bool foundInCache = false;
    841   // If compact encoding table gave offset into dwarf section, go directly there
    842   if (fdeSectionOffsetHint != 0) {
    843     foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
    844                                     (uint32_t)sects.dwarf_section_length,
    845                                     sects.dwarf_section + fdeSectionOffsetHint,
    846                                     &fdeInfo, &cieInfo);
    847   }
    848 #if _LIBUNWIND_SUPPORT_DWARF_INDEX
    849   if (!foundFDE && (sects.dwarf_index_section != 0)) {
    850     foundFDE = EHHeaderParser<A>::findFDE(
    851         _addressSpace, pc, sects.dwarf_index_section,
    852         (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
    853   }
    854 #endif
    855   if (!foundFDE) {
    856     // otherwise, search cache of previously found FDEs.
    857     pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);
    858     if (cachedFDE != 0) {
    859       foundFDE =
    860           CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
    861                                  (uint32_t)sects.dwarf_section_length,
    862                                  cachedFDE, &fdeInfo, &cieInfo);
    863       foundInCache = foundFDE;
    864     }
    865   }
    866   if (!foundFDE) {
    867     // Still not found, do full scan of __eh_frame section.
    868     foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
    869                                       (uint32_t)sects.dwarf_section_length, 0,
    870                                       &fdeInfo, &cieInfo);
    871   }
    872   if (foundFDE) {
    873     typename CFI_Parser<A>::PrologInfo prolog;
    874     if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
    875                                             &prolog)) {
    876       // Save off parsed FDE info
    877       _info.start_ip          = fdeInfo.pcStart;
    878       _info.end_ip            = fdeInfo.pcEnd;
    879       _info.lsda              = fdeInfo.lsda;
    880       _info.handler           = cieInfo.personality;
    881       _info.gp                = prolog.spExtraArgSize;
    882       _info.flags             = 0;
    883       _info.format            = dwarfEncoding();
    884       _info.unwind_info       = fdeInfo.fdeStart;
    885       _info.unwind_info_size  = (uint32_t)fdeInfo.fdeLength;
    886       _info.extra             = (unw_word_t) sects.dso_base;
    887 
    888       // Add to cache (to make next lookup faster) if we had no hint
    889       // and there was no index.
    890       if (!foundInCache && (fdeSectionOffsetHint == 0)) {
    891   #if _LIBUNWIND_SUPPORT_DWARF_INDEX
    892         if (sects.dwarf_index_section == 0)
    893   #endif
    894         DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
    895                               fdeInfo.fdeStart);
    896       }
    897       return true;
    898     }
    899   }
    900   //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX\n", (uint64_t)pc);
    901   return false;
    902 }
    903 #endif // _LIBUNWIND_SUPPORT_DWARF_UNWIND
    904 
    905 
    906 #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
    907 template <typename A, typename R>
    908 bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
    909                                               const UnwindInfoSections &sects) {
    910   const bool log = false;
    911   if (log)
    912     fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
    913             (uint64_t)pc, (uint64_t)sects.dso_base);
    914 
    915   const UnwindSectionHeader<A> sectionHeader(_addressSpace,
    916                                                 sects.compact_unwind_section);
    917   if (sectionHeader.version() != UNWIND_SECTION_VERSION)
    918     return false;
    919 
    920   // do a binary search of top level index to find page with unwind info
    921   pint_t targetFunctionOffset = pc - sects.dso_base;
    922   const UnwindSectionIndexArray<A> topIndex(_addressSpace,
    923                                            sects.compact_unwind_section
    924                                          + sectionHeader.indexSectionOffset());
    925   uint32_t low = 0;
    926   uint32_t high = sectionHeader.indexCount();
    927   uint32_t last = high - 1;
    928   while (low < high) {
    929     uint32_t mid = (low + high) / 2;
    930     //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
    931     //mid, low, high, topIndex.functionOffset(mid));
    932     if (topIndex.functionOffset(mid) <= targetFunctionOffset) {
    933       if ((mid == last) ||
    934           (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {
    935         low = mid;
    936         break;
    937       } else {
    938         low = mid + 1;
    939       }
    940     } else {
    941       high = mid;
    942     }
    943   }
    944   const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
    945   const uint32_t firstLevelNextPageFunctionOffset =
    946       topIndex.functionOffset(low + 1);
    947   const pint_t secondLevelAddr =
    948       sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);
    949   const pint_t lsdaArrayStartAddr =
    950       sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);
    951   const pint_t lsdaArrayEndAddr =
    952       sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);
    953   if (log)
    954     fprintf(stderr, "\tfirst level search for result index=%d "
    955                     "to secondLevelAddr=0x%llX\n",
    956                     low, (uint64_t) secondLevelAddr);
    957   // do a binary search of second level page index
    958   uint32_t encoding = 0;
    959   pint_t funcStart = 0;
    960   pint_t funcEnd = 0;
    961   pint_t lsda = 0;
    962   pint_t personality = 0;
    963   uint32_t pageKind = _addressSpace.get32(secondLevelAddr);
    964   if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {
    965     // regular page
    966     UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,
    967                                                  secondLevelAddr);
    968     UnwindSectionRegularArray<A> pageIndex(
    969         _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
    970     // binary search looks for entry with e where index[e].offset <= pc <
    971     // index[e+1].offset
    972     if (log)
    973       fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "
    974                       "regular page starting at secondLevelAddr=0x%llX\n",
    975               (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);
    976     low = 0;
    977     high = pageHeader.entryCount();
    978     while (low < high) {
    979       uint32_t mid = (low + high) / 2;
    980       if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {
    981         if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {
    982           // at end of table
    983           low = mid;
    984           funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
    985           break;
    986         } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {
    987           // next is too big, so we found it
    988           low = mid;
    989           funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;
    990           break;
    991         } else {
    992           low = mid + 1;
    993         }
    994       } else {
    995         high = mid;
    996       }
    997     }
    998     encoding = pageIndex.encoding(low);
    999     funcStart = pageIndex.functionOffset(low) + sects.dso_base;
   1000     if (pc < funcStart) {
   1001       if (log)
   1002         fprintf(
   1003             stderr,
   1004             "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
   1005             (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
   1006       return false;
   1007     }
   1008     if (pc > funcEnd) {
   1009       if (log)
   1010         fprintf(
   1011             stderr,
   1012             "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
   1013             (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
   1014       return false;
   1015     }
   1016   } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {
   1017     // compressed page
   1018     UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,
   1019                                                     secondLevelAddr);
   1020     UnwindSectionCompressedArray<A> pageIndex(
   1021         _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
   1022     const uint32_t targetFunctionPageOffset =
   1023         (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset);
   1024     // binary search looks for entry with e where index[e].offset <= pc <
   1025     // index[e+1].offset
   1026     if (log)
   1027       fprintf(stderr, "\tbinary search of compressed page starting at "
   1028                       "secondLevelAddr=0x%llX\n",
   1029               (uint64_t) secondLevelAddr);
   1030     low = 0;
   1031     last = pageHeader.entryCount() - 1;
   1032     high = pageHeader.entryCount();
   1033     while (low < high) {
   1034       uint32_t mid = (low + high) / 2;
   1035       if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {
   1036         if ((mid == last) ||
   1037             (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {
   1038           low = mid;
   1039           break;
   1040         } else {
   1041           low = mid + 1;
   1042         }
   1043       } else {
   1044         high = mid;
   1045       }
   1046     }
   1047     funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset
   1048                                                               + sects.dso_base;
   1049     if (low < last)
   1050       funcEnd =
   1051           pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset
   1052                                                               + sects.dso_base;
   1053     else
   1054       funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
   1055     if (pc < funcStart) {
   1056       _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second  "
   1057                            "level compressed unwind table. funcStart=0x%llX\n",
   1058                             (uint64_t) pc, (uint64_t) funcStart);
   1059       return false;
   1060     }
   1061     if (pc > funcEnd) {
   1062       _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second  "
   1063                           "level compressed unwind table. funcEnd=0x%llX\n",
   1064                            (uint64_t) pc, (uint64_t) funcEnd);
   1065       return false;
   1066     }
   1067     uint16_t encodingIndex = pageIndex.encodingIndex(low);
   1068     if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) {
   1069       // encoding is in common table in section header
   1070       encoding = _addressSpace.get32(
   1071           sects.compact_unwind_section +
   1072           sectionHeader.commonEncodingsArraySectionOffset() +
   1073           encodingIndex * sizeof(uint32_t));
   1074     } else {
   1075       // encoding is in page specific table
   1076       uint16_t pageEncodingIndex =
   1077           encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount();
   1078       encoding = _addressSpace.get32(secondLevelAddr +
   1079                                      pageHeader.encodingsPageOffset() +
   1080                                      pageEncodingIndex * sizeof(uint32_t));
   1081     }
   1082   } else {
   1083     _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second "
   1084                          "level page\n",
   1085                           (uint64_t) sects.compact_unwind_section);
   1086     return false;
   1087   }
   1088 
   1089   // look up LSDA, if encoding says function has one
   1090   if (encoding & UNWIND_HAS_LSDA) {
   1091     UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);
   1092     uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);
   1093     low = 0;
   1094     high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /
   1095                     sizeof(unwind_info_section_header_lsda_index_entry);
   1096     // binary search looks for entry with exact match for functionOffset
   1097     if (log)
   1098       fprintf(stderr,
   1099               "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
   1100               funcStartOffset);
   1101     while (low < high) {
   1102       uint32_t mid = (low + high) / 2;
   1103       if (lsdaIndex.functionOffset(mid) == funcStartOffset) {
   1104         lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;
   1105         break;
   1106       } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {
   1107         low = mid + 1;
   1108       } else {
   1109         high = mid;
   1110       }
   1111     }
   1112     if (lsda == 0) {
   1113       _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
   1114                     "pc=0x%0llX, but lsda table has no entry\n",
   1115                     encoding, (uint64_t) pc);
   1116       return false;
   1117     }
   1118   }
   1119 
   1120   // extact personality routine, if encoding says function has one
   1121   uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
   1122                               (__builtin_ctz(UNWIND_PERSONALITY_MASK));
   1123   if (personalityIndex != 0) {
   1124     --personalityIndex; // change 1-based to zero-based index
   1125     if (personalityIndex > sectionHeader.personalityArrayCount()) {
   1126       _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d,  "
   1127                             "but personality table has only %d entires\n",
   1128                             encoding, personalityIndex,
   1129                             sectionHeader.personalityArrayCount());
   1130       return false;
   1131     }
   1132     int32_t personalityDelta = (int32_t)_addressSpace.get32(
   1133         sects.compact_unwind_section +
   1134         sectionHeader.personalityArraySectionOffset() +
   1135         personalityIndex * sizeof(uint32_t));
   1136     pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
   1137     personality = _addressSpace.getP(personalityPointer);
   1138     if (log)
   1139       fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
   1140                       "personalityDelta=0x%08X, personality=0x%08llX\n",
   1141               (uint64_t) pc, personalityDelta, (uint64_t) personality);
   1142   }
   1143 
   1144   if (log)
   1145     fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
   1146                     "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
   1147             (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart);
   1148   _info.start_ip = funcStart;
   1149   _info.end_ip = funcEnd;
   1150   _info.lsda = lsda;
   1151   _info.handler = personality;
   1152   _info.gp = 0;
   1153   _info.flags = 0;
   1154   _info.format = encoding;
   1155   _info.unwind_info = 0;
   1156   _info.unwind_info_size = 0;
   1157   _info.extra = sects.dso_base;
   1158   return true;
   1159 }
   1160 #endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
   1161 
   1162 
   1163 template <typename A, typename R>
   1164 void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
   1165   pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
   1166 #if _LIBUNWIND_ARM_EHABI
   1167   // Remove the thumb bit so the IP represents the actual instruction address.
   1168   // This matches the behaviour of _Unwind_GetIP on arm.
   1169   pc &= (pint_t)~0x1;
   1170 #endif
   1171 
   1172   // If the last line of a function is a "throw" the compiler sometimes
   1173   // emits no instructions after the call to __cxa_throw.  This means
   1174   // the return address is actually the start of the next function.
   1175   // To disambiguate this, back up the pc when we know it is a return
   1176   // address.
   1177   if (isReturnAddress)
   1178     --pc;
   1179 
   1180   // Ask address space object to find unwind sections for this pc.
   1181   UnwindInfoSections sects;
   1182   if (_addressSpace.findUnwindSections(pc, sects)) {
   1183 #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
   1184     // If there is a compact unwind encoding table, look there first.
   1185     if (sects.compact_unwind_section != 0) {
   1186       if (this->getInfoFromCompactEncodingSection(pc, sects)) {
   1187   #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
   1188         // Found info in table, done unless encoding says to use dwarf.
   1189         uint32_t dwarfOffset;
   1190         if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
   1191           if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {
   1192             // found info in dwarf, done
   1193             return;
   1194           }
   1195         }
   1196   #endif
   1197         // If unwind table has entry, but entry says there is no unwind info,
   1198         // record that we have no unwind info.
   1199         if (_info.format == 0)
   1200           _unwindInfoMissing = true;
   1201         return;
   1202       }
   1203     }
   1204 #endif // _LIBUNWIND_SUPPORT_COMPACT_UNWIND
   1205 
   1206 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
   1207     // If there is dwarf unwind info, look there next.
   1208     if (sects.dwarf_section != 0) {
   1209       if (this->getInfoFromDwarfSection(pc, sects)) {
   1210         // found info in dwarf, done
   1211         return;
   1212       }
   1213     }
   1214 #endif
   1215 
   1216 #if _LIBUNWIND_ARM_EHABI
   1217     // If there is ARM EHABI unwind info, look there next.
   1218     if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
   1219       return;
   1220 #endif
   1221   }
   1222 
   1223 #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
   1224   // There is no static unwind info for this pc. Look to see if an FDE was
   1225   // dynamically registered for it.
   1226   pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
   1227   if (cachedFDE != 0) {
   1228     CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
   1229     CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
   1230     const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace,
   1231                                                 cachedFDE, &fdeInfo, &cieInfo);
   1232     if (msg == NULL) {
   1233       typename CFI_Parser<A>::PrologInfo prolog;
   1234       if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
   1235                                                                 pc, &prolog)) {
   1236         // save off parsed FDE info
   1237         _info.start_ip         = fdeInfo.pcStart;
   1238         _info.end_ip           = fdeInfo.pcEnd;
   1239         _info.lsda             = fdeInfo.lsda;
   1240         _info.handler          = cieInfo.personality;
   1241         _info.gp               = prolog.spExtraArgSize;
   1242                                   // Some frameless functions need SP
   1243                                   // altered when resuming in function.
   1244         _info.flags            = 0;
   1245         _info.format           = dwarfEncoding();
   1246         _info.unwind_info      = fdeInfo.fdeStart;
   1247         _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
   1248         _info.extra            = 0;
   1249         return;
   1250       }
   1251     }
   1252   }
   1253 
   1254   // Lastly, ask AddressSpace object about platform specific ways to locate
   1255   // other FDEs.
   1256   pint_t fde;
   1257   if (_addressSpace.findOtherFDE(pc, fde)) {
   1258     CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
   1259     CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
   1260     if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
   1261       // Double check this FDE is for a function that includes the pc.
   1262       if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
   1263         typename CFI_Parser<A>::PrologInfo prolog;
   1264         if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo,
   1265                                                 cieInfo, pc, &prolog)) {
   1266           // save off parsed FDE info
   1267           _info.start_ip         = fdeInfo.pcStart;
   1268           _info.end_ip           = fdeInfo.pcEnd;
   1269           _info.lsda             = fdeInfo.lsda;
   1270           _info.handler          = cieInfo.personality;
   1271           _info.gp               = prolog.spExtraArgSize;
   1272           _info.flags            = 0;
   1273           _info.format           = dwarfEncoding();
   1274           _info.unwind_info      = fdeInfo.fdeStart;
   1275           _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
   1276           _info.extra            = 0;
   1277           return;
   1278         }
   1279       }
   1280     }
   1281   }
   1282 #endif // #if _LIBUNWIND_SUPPORT_DWARF_UNWIND
   1283 
   1284   // no unwind info, flag that we can't reliably unwind
   1285   _unwindInfoMissing = true;
   1286 }
   1287 
   1288 template <typename A, typename R>
   1289 int UnwindCursor<A, R>::step() {
   1290   // Bottom of stack is defined is when unwind info cannot be found.
   1291   if (_unwindInfoMissing)
   1292     return UNW_STEP_END;
   1293 
   1294   // Use unwinding info to modify register set as if function returned.
   1295   int result;
   1296 #if _LIBUNWIND_SUPPORT_COMPACT_UNWIND
   1297   result = this->stepWithCompactEncoding();
   1298 #elif _LIBUNWIND_SUPPORT_DWARF_UNWIND
   1299   result = this->stepWithDwarfFDE();
   1300 #elif _LIBUNWIND_ARM_EHABI
   1301   result = this->stepWithEHABI();
   1302 #else
   1303   #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
   1304               _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
   1305               _LIBUNWIND_ARM_EHABI
   1306 #endif
   1307 
   1308   // update info based on new PC
   1309   if (result == UNW_STEP_SUCCESS) {
   1310     this->setInfoBasedOnIPRegister(true);
   1311     if (_unwindInfoMissing)
   1312       return UNW_STEP_END;
   1313     if (_info.gp)
   1314       setReg(UNW_REG_SP, getReg(UNW_REG_SP) + _info.gp);
   1315   }
   1316 
   1317   return result;
   1318 }
   1319 
   1320 template <typename A, typename R>
   1321 void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
   1322   *info = _info;
   1323 }
   1324 
   1325 template <typename A, typename R>
   1326 bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
   1327                                                            unw_word_t *offset) {
   1328   return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),
   1329                                          buf, bufLen, offset);
   1330 }
   1331 
   1332 } // namespace libunwind
   1333 
   1334 #endif // __UNWINDCURSOR_HPP__
   1335