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