1//===------------------------- UnwindCursor.hpp ---------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//
8// C++ interface to lower levels of libunwind
9//===----------------------------------------------------------------------===//
10
11#ifndef __UNWINDCURSOR_HPP__
12#define __UNWINDCURSOR_HPP__
13
14#include <stdint.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <unwind.h>
18
19#ifdef _WIN32
20  #include <windows.h>
21  #include <ntverp.h>
22#endif
23#ifdef __APPLE__
24  #include <mach-o/dyld.h>
25#endif
26
27#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
28// Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
29// earlier) SDKs.
30// MinGW-w64 has always provided this struct.
31  #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
32      !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
33struct _DISPATCHER_CONTEXT {
34  ULONG64 ControlPc;
35  ULONG64 ImageBase;
36  PRUNTIME_FUNCTION FunctionEntry;
37  ULONG64 EstablisherFrame;
38  ULONG64 TargetIp;
39  PCONTEXT ContextRecord;
40  PEXCEPTION_ROUTINE LanguageHandler;
41  PVOID HandlerData;
42  PUNWIND_HISTORY_TABLE HistoryTable;
43  ULONG ScopeIndex;
44  ULONG Fill0;
45};
46  #endif
47
48struct UNWIND_INFO {
49  uint8_t Version : 3;
50  uint8_t Flags : 5;
51  uint8_t SizeOfProlog;
52  uint8_t CountOfCodes;
53  uint8_t FrameRegister : 4;
54  uint8_t FrameOffset : 4;
55  uint16_t UnwindCodes[2];
56};
57
58extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
59    int, _Unwind_Action, uint64_t, _Unwind_Exception *,
60    struct _Unwind_Context *);
61
62#endif
63
64#include "config.h"
65
66#include "AddressSpace.hpp"
67#include "CompactUnwinder.hpp"
68#include "config.h"
69#include "DwarfInstructions.hpp"
70#include "EHHeaderParser.hpp"
71#include "libunwind.h"
72#include "Registers.hpp"
73#include "RWMutex.hpp"
74#include "Unwind-EHABI.h"
75
76namespace libunwind {
77
78#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
79/// Cache of recently found FDEs.
80template <typename A>
81class _LIBUNWIND_HIDDEN DwarfFDECache {
82  typedef typename A::pint_t pint_t;
83public:
84  static pint_t findFDE(pint_t mh, pint_t pc);
85  static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
86  static void removeAllIn(pint_t mh);
87  static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
88                                               unw_word_t ip_end,
89                                               unw_word_t fde, unw_word_t mh));
90
91private:
92
93  struct entry {
94    pint_t mh;
95    pint_t ip_start;
96    pint_t ip_end;
97    pint_t fde;
98  };
99
100  // These fields are all static to avoid needing an initializer.
101  // There is only one instance of this class per process.
102  static RWMutex _lock;
103#ifdef __APPLE__
104  static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
105  static bool _registeredForDyldUnloads;
106#endif
107  static entry *_buffer;
108  static entry *_bufferUsed;
109  static entry *_bufferEnd;
110  static entry _initialBuffer[64];
111};
112
113template <typename A>
114typename DwarfFDECache<A>::entry *
115DwarfFDECache<A>::_buffer = _initialBuffer;
116
117template <typename A>
118typename DwarfFDECache<A>::entry *
119DwarfFDECache<A>::_bufferUsed = _initialBuffer;
120
121template <typename A>
122typename DwarfFDECache<A>::entry *
123DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
124
125template <typename A>
126typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
127
128template <typename A>
129RWMutex DwarfFDECache<A>::_lock;
130
131#ifdef __APPLE__
132template <typename A>
133bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
134#endif
135
136template <typename A>
137typename A::pint_t DwarfFDECache<A>::findFDE(pint_t mh, pint_t pc) {
138  pint_t result = 0;
139  _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
140  for (entry *p = _buffer; p < _bufferUsed; ++p) {
141    if ((mh == p->mh) || (mh == 0)) {
142      if ((p->ip_start <= pc) && (pc < p->ip_end)) {
143        result = p->fde;
144        break;
145      }
146    }
147  }
148  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared());
149  return result;
150}
151
152template <typename A>
153void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
154                           pint_t fde) {
155#if !defined(_LIBUNWIND_NO_HEAP)
156  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
157  if (_bufferUsed >= _bufferEnd) {
158    size_t oldSize = (size_t)(_bufferEnd - _buffer);
159    size_t newSize = oldSize * 4;
160    // Can't use operator new (we are below it).
161    entry *newBuffer = (entry *)malloc(newSize * sizeof(entry));
162    memcpy(newBuffer, _buffer, oldSize * sizeof(entry));
163    if (_buffer != _initialBuffer)
164      free(_buffer);
165    _buffer = newBuffer;
166    _bufferUsed = &newBuffer[oldSize];
167    _bufferEnd = &newBuffer[newSize];
168  }
169  _bufferUsed->mh = mh;
170  _bufferUsed->ip_start = ip_start;
171  _bufferUsed->ip_end = ip_end;
172  _bufferUsed->fde = fde;
173  ++_bufferUsed;
174#ifdef __APPLE__
175  if (!_registeredForDyldUnloads) {
176    _dyld_register_func_for_remove_image(&dyldUnloadHook);
177    _registeredForDyldUnloads = true;
178  }
179#endif
180  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
181#endif
182}
183
184template <typename A>
185void DwarfFDECache<A>::removeAllIn(pint_t mh) {
186  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
187  entry *d = _buffer;
188  for (const entry *s = _buffer; s < _bufferUsed; ++s) {
189    if (s->mh != mh) {
190      if (d != s)
191        *d = *s;
192      ++d;
193    }
194  }
195  _bufferUsed = d;
196  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
197}
198
199#ifdef __APPLE__
200template <typename A>
201void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {
202  removeAllIn((pint_t) mh);
203}
204#endif
205
206template <typename A>
207void DwarfFDECache<A>::iterateCacheEntries(void (*func)(
208    unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
209  _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
210  for (entry *p = _buffer; p < _bufferUsed; ++p) {
211    (*func)(p->ip_start, p->ip_end, p->fde, p->mh);
212  }
213  _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
214}
215#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
216
217
218#define arrayoffsetof(type, index, field) ((size_t)(&((type *)0)[index].field))
219
220#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
221template <typename A> class UnwindSectionHeader {
222public:
223  UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)
224      : _addressSpace(addressSpace), _addr(addr) {}
225
226  uint32_t version() const {
227    return _addressSpace.get32(_addr +
228                               offsetof(unwind_info_section_header, version));
229  }
230  uint32_t commonEncodingsArraySectionOffset() const {
231    return _addressSpace.get32(_addr +
232                               offsetof(unwind_info_section_header,
233                                        commonEncodingsArraySectionOffset));
234  }
235  uint32_t commonEncodingsArrayCount() const {
236    return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
237                                                commonEncodingsArrayCount));
238  }
239  uint32_t personalityArraySectionOffset() const {
240    return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
241                                                personalityArraySectionOffset));
242  }
243  uint32_t personalityArrayCount() const {
244    return _addressSpace.get32(
245        _addr + offsetof(unwind_info_section_header, personalityArrayCount));
246  }
247  uint32_t indexSectionOffset() const {
248    return _addressSpace.get32(
249        _addr + offsetof(unwind_info_section_header, indexSectionOffset));
250  }
251  uint32_t indexCount() const {
252    return _addressSpace.get32(
253        _addr + offsetof(unwind_info_section_header, indexCount));
254  }
255
256private:
257  A                     &_addressSpace;
258  typename A::pint_t     _addr;
259};
260
261template <typename A> class UnwindSectionIndexArray {
262public:
263  UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr)
264      : _addressSpace(addressSpace), _addr(addr) {}
265
266  uint32_t functionOffset(uint32_t index) const {
267    return _addressSpace.get32(
268        _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
269                              functionOffset));
270  }
271  uint32_t secondLevelPagesSectionOffset(uint32_t index) const {
272    return _addressSpace.get32(
273        _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
274                              secondLevelPagesSectionOffset));
275  }
276  uint32_t lsdaIndexArraySectionOffset(uint32_t index) const {
277    return _addressSpace.get32(
278        _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
279                              lsdaIndexArraySectionOffset));
280  }
281
282private:
283  A                   &_addressSpace;
284  typename A::pint_t   _addr;
285};
286
287template <typename A> class UnwindSectionRegularPageHeader {
288public:
289  UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr)
290      : _addressSpace(addressSpace), _addr(addr) {}
291
292  uint32_t kind() const {
293    return _addressSpace.get32(
294        _addr + offsetof(unwind_info_regular_second_level_page_header, kind));
295  }
296  uint16_t entryPageOffset() const {
297    return _addressSpace.get16(
298        _addr + offsetof(unwind_info_regular_second_level_page_header,
299                         entryPageOffset));
300  }
301  uint16_t entryCount() const {
302    return _addressSpace.get16(
303        _addr +
304        offsetof(unwind_info_regular_second_level_page_header, entryCount));
305  }
306
307private:
308  A &_addressSpace;
309  typename A::pint_t _addr;
310};
311
312template <typename A> class UnwindSectionRegularArray {
313public:
314  UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr)
315      : _addressSpace(addressSpace), _addr(addr) {}
316
317  uint32_t functionOffset(uint32_t index) const {
318    return _addressSpace.get32(
319        _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index,
320                              functionOffset));
321  }
322  uint32_t encoding(uint32_t index) const {
323    return _addressSpace.get32(
324        _addr +
325        arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding));
326  }
327
328private:
329  A &_addressSpace;
330  typename A::pint_t _addr;
331};
332
333template <typename A> class UnwindSectionCompressedPageHeader {
334public:
335  UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr)
336      : _addressSpace(addressSpace), _addr(addr) {}
337
338  uint32_t kind() const {
339    return _addressSpace.get32(
340        _addr +
341        offsetof(unwind_info_compressed_second_level_page_header, kind));
342  }
343  uint16_t entryPageOffset() const {
344    return _addressSpace.get16(
345        _addr + offsetof(unwind_info_compressed_second_level_page_header,
346                         entryPageOffset));
347  }
348  uint16_t entryCount() const {
349    return _addressSpace.get16(
350        _addr +
351        offsetof(unwind_info_compressed_second_level_page_header, entryCount));
352  }
353  uint16_t encodingsPageOffset() const {
354    return _addressSpace.get16(
355        _addr + offsetof(unwind_info_compressed_second_level_page_header,
356                         encodingsPageOffset));
357  }
358  uint16_t encodingsCount() const {
359    return _addressSpace.get16(
360        _addr + offsetof(unwind_info_compressed_second_level_page_header,
361                         encodingsCount));
362  }
363
364private:
365  A &_addressSpace;
366  typename A::pint_t _addr;
367};
368
369template <typename A> class UnwindSectionCompressedArray {
370public:
371  UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr)
372      : _addressSpace(addressSpace), _addr(addr) {}
373
374  uint32_t functionOffset(uint32_t index) const {
375    return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
376        _addressSpace.get32(_addr + index * sizeof(uint32_t)));
377  }
378  uint16_t encodingIndex(uint32_t index) const {
379    return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
380        _addressSpace.get32(_addr + index * sizeof(uint32_t)));
381  }
382
383private:
384  A &_addressSpace;
385  typename A::pint_t _addr;
386};
387
388template <typename A> class UnwindSectionLsdaArray {
389public:
390  UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr)
391      : _addressSpace(addressSpace), _addr(addr) {}
392
393  uint32_t functionOffset(uint32_t index) const {
394    return _addressSpace.get32(
395        _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
396                              index, functionOffset));
397  }
398  uint32_t lsdaOffset(uint32_t index) const {
399    return _addressSpace.get32(
400        _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
401                              index, lsdaOffset));
402  }
403
404private:
405  A                   &_addressSpace;
406  typename A::pint_t   _addr;
407};
408#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
409
410class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
411public:
412  // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
413  // This avoids an unnecessary dependency to libc++abi.
414  void operator delete(void *, size_t) {}
415
416  virtual ~AbstractUnwindCursor() {}
417  virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
418  virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
419  virtual void setReg(int, unw_word_t) {
420    _LIBUNWIND_ABORT("setReg not implemented");
421  }
422  virtual bool validFloatReg(int) {
423    _LIBUNWIND_ABORT("validFloatReg not implemented");
424  }
425  virtual unw_fpreg_t getFloatReg(int) {
426    _LIBUNWIND_ABORT("getFloatReg not implemented");
427  }
428  virtual void setFloatReg(int, unw_fpreg_t) {
429    _LIBUNWIND_ABORT("setFloatReg not implemented");
430  }
431  virtual int step() { _LIBUNWIND_ABORT("step not implemented"); }
432  virtual void getInfo(unw_proc_info_t *) {
433    _LIBUNWIND_ABORT("getInfo not implemented");
434  }
435  virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
436  virtual bool isSignalFrame() {
437    _LIBUNWIND_ABORT("isSignalFrame not implemented");
438  }
439  virtual bool getFunctionName(char *, size_t, unw_word_t *) {
440    _LIBUNWIND_ABORT("getFunctionName not implemented");
441  }
442  virtual void setInfoBasedOnIPRegister(bool = false) {
443    _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
444  }
445  virtual const char *getRegisterName(int) {
446    _LIBUNWIND_ABORT("getRegisterName not implemented");
447  }
448#ifdef __arm__
449  virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
450#endif
451};
452
453#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
454
455/// \c UnwindCursor contains all state (including all register values) during
456/// an unwind.  This is normally stack-allocated inside a unw_cursor_t.
457template <typename A, typename R>
458class UnwindCursor : public AbstractUnwindCursor {
459  typedef typename A::pint_t pint_t;
460public:
461                      UnwindCursor(unw_context_t *context, A &as);
462                      UnwindCursor(CONTEXT *context, A &as);
463                      UnwindCursor(A &as, void *threadArg);
464  virtual             ~UnwindCursor() {}
465  virtual bool        validReg(int);
466  virtual unw_word_t  getReg(int);
467  virtual void        setReg(int, unw_word_t);
468  virtual bool        validFloatReg(int);
469  virtual unw_fpreg_t getFloatReg(int);
470  virtual void        setFloatReg(int, unw_fpreg_t);
471  virtual int         step();
472  virtual void        getInfo(unw_proc_info_t *);
473  virtual void        jumpto();
474  virtual bool        isSignalFrame();
475  virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
476  virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
477  virtual const char *getRegisterName(int num);
478#ifdef __arm__
479  virtual void        saveVFPAsX();
480#endif
481
482  DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
483  void setDispatcherContext(DISPATCHER_CONTEXT *disp) { _dispContext = *disp; }
484
485  // libunwind does not and should not depend on C++ library which means that we
486  // need our own defition of inline placement new.
487  static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
488
489private:
490
491  pint_t getLastPC() const { return _dispContext.ControlPc; }
492  void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
493  RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
494    _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
495                                                        &_dispContext.ImageBase,
496                                                        _dispContext.HistoryTable);
497    *base = _dispContext.ImageBase;
498    return _dispContext.FunctionEntry;
499  }
500  bool getInfoFromSEH(pint_t pc);
501  int stepWithSEHData() {
502    _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
503                                                    _dispContext.ImageBase,
504                                                    _dispContext.ControlPc,
505                                                    _dispContext.FunctionEntry,
506                                                    _dispContext.ContextRecord,
507                                                    &_dispContext.HandlerData,
508                                                    &_dispContext.EstablisherFrame,
509                                                    NULL);
510    // Update some fields of the unwind info now, since we have them.
511    _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
512    if (_dispContext.LanguageHandler) {
513      _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
514    } else
515      _info.handler = 0;
516    return UNW_STEP_SUCCESS;
517  }
518
519  A                   &_addressSpace;
520  unw_proc_info_t      _info;
521  DISPATCHER_CONTEXT   _dispContext;
522  CONTEXT              _msContext;
523  UNWIND_HISTORY_TABLE _histTable;
524  bool                 _unwindInfoMissing;
525};
526
527
528template <typename A, typename R>
529UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
530    : _addressSpace(as), _unwindInfoMissing(false) {
531  static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
532                "UnwindCursor<> does not fit in unw_cursor_t");
533  memset(&_info, 0, sizeof(_info));
534  memset(&_histTable, 0, sizeof(_histTable));
535  _dispContext.ContextRecord = &_msContext;
536  _dispContext.HistoryTable = &_histTable;
537  // Initialize MS context from ours.
538  R r(context);
539  _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
540#if defined(_LIBUNWIND_TARGET_X86_64)
541  _msContext.Rax = r.getRegister(UNW_X86_64_RAX);
542  _msContext.Rcx = r.getRegister(UNW_X86_64_RCX);
543  _msContext.Rdx = r.getRegister(UNW_X86_64_RDX);
544  _msContext.Rbx = r.getRegister(UNW_X86_64_RBX);
545  _msContext.Rsp = r.getRegister(UNW_X86_64_RSP);
546  _msContext.Rbp = r.getRegister(UNW_X86_64_RBP);
547  _msContext.Rsi = r.getRegister(UNW_X86_64_RSI);
548  _msContext.Rdi = r.getRegister(UNW_X86_64_RDI);
549  _msContext.R8 = r.getRegister(UNW_X86_64_R8);
550  _msContext.R9 = r.getRegister(UNW_X86_64_R9);
551  _msContext.R10 = r.getRegister(UNW_X86_64_R10);
552  _msContext.R11 = r.getRegister(UNW_X86_64_R11);
553  _msContext.R12 = r.getRegister(UNW_X86_64_R12);
554  _msContext.R13 = r.getRegister(UNW_X86_64_R13);
555  _msContext.R14 = r.getRegister(UNW_X86_64_R14);
556  _msContext.R15 = r.getRegister(UNW_X86_64_R15);
557  _msContext.Rip = r.getRegister(UNW_REG_IP);
558  union {
559    v128 v;
560    M128A m;
561  } t;
562  t.v = r.getVectorRegister(UNW_X86_64_XMM0);
563  _msContext.Xmm0 = t.m;
564  t.v = r.getVectorRegister(UNW_X86_64_XMM1);
565  _msContext.Xmm1 = t.m;
566  t.v = r.getVectorRegister(UNW_X86_64_XMM2);
567  _msContext.Xmm2 = t.m;
568  t.v = r.getVectorRegister(UNW_X86_64_XMM3);
569  _msContext.Xmm3 = t.m;
570  t.v = r.getVectorRegister(UNW_X86_64_XMM4);
571  _msContext.Xmm4 = t.m;
572  t.v = r.getVectorRegister(UNW_X86_64_XMM5);
573  _msContext.Xmm5 = t.m;
574  t.v = r.getVectorRegister(UNW_X86_64_XMM6);
575  _msContext.Xmm6 = t.m;
576  t.v = r.getVectorRegister(UNW_X86_64_XMM7);
577  _msContext.Xmm7 = t.m;
578  t.v = r.getVectorRegister(UNW_X86_64_XMM8);
579  _msContext.Xmm8 = t.m;
580  t.v = r.getVectorRegister(UNW_X86_64_XMM9);
581  _msContext.Xmm9 = t.m;
582  t.v = r.getVectorRegister(UNW_X86_64_XMM10);
583  _msContext.Xmm10 = t.m;
584  t.v = r.getVectorRegister(UNW_X86_64_XMM11);
585  _msContext.Xmm11 = t.m;
586  t.v = r.getVectorRegister(UNW_X86_64_XMM12);
587  _msContext.Xmm12 = t.m;
588  t.v = r.getVectorRegister(UNW_X86_64_XMM13);
589  _msContext.Xmm13 = t.m;
590  t.v = r.getVectorRegister(UNW_X86_64_XMM14);
591  _msContext.Xmm14 = t.m;
592  t.v = r.getVectorRegister(UNW_X86_64_XMM15);
593  _msContext.Xmm15 = t.m;
594#elif defined(_LIBUNWIND_TARGET_ARM)
595  _msContext.R0 = r.getRegister(UNW_ARM_R0);
596  _msContext.R1 = r.getRegister(UNW_ARM_R1);
597  _msContext.R2 = r.getRegister(UNW_ARM_R2);
598  _msContext.R3 = r.getRegister(UNW_ARM_R3);
599  _msContext.R4 = r.getRegister(UNW_ARM_R4);
600  _msContext.R5 = r.getRegister(UNW_ARM_R5);
601  _msContext.R6 = r.getRegister(UNW_ARM_R6);
602  _msContext.R7 = r.getRegister(UNW_ARM_R7);
603  _msContext.R8 = r.getRegister(UNW_ARM_R8);
604  _msContext.R9 = r.getRegister(UNW_ARM_R9);
605  _msContext.R10 = r.getRegister(UNW_ARM_R10);
606  _msContext.R11 = r.getRegister(UNW_ARM_R11);
607  _msContext.R12 = r.getRegister(UNW_ARM_R12);
608  _msContext.Sp = r.getRegister(UNW_ARM_SP);
609  _msContext.Lr = r.getRegister(UNW_ARM_LR);
610  _msContext.Pc = r.getRegister(UNW_ARM_IP);
611  for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {
612    union {
613      uint64_t w;
614      double d;
615    } d;
616    d.d = r.getFloatRegister(i);
617    _msContext.D[i - UNW_ARM_D0] = d.w;
618  }
619#elif defined(_LIBUNWIND_TARGET_AARCH64)
620  for (int i = UNW_ARM64_X0; i <= UNW_ARM64_X30; ++i)
621    _msContext.X[i - UNW_ARM64_X0] = r.getRegister(i);
622  _msContext.Sp = r.getRegister(UNW_REG_SP);
623  _msContext.Pc = r.getRegister(UNW_REG_IP);
624  for (int i = UNW_ARM64_D0; i <= UNW_ARM64_D31; ++i)
625    _msContext.V[i - UNW_ARM64_D0].D[0] = r.getFloatRegister(i);
626#endif
627}
628
629template <typename A, typename R>
630UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
631    : _addressSpace(as), _unwindInfoMissing(false) {
632  static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
633                "UnwindCursor<> does not fit in unw_cursor_t");
634  memset(&_info, 0, sizeof(_info));
635  memset(&_histTable, 0, sizeof(_histTable));
636  _dispContext.ContextRecord = &_msContext;
637  _dispContext.HistoryTable = &_histTable;
638  _msContext = *context;
639}
640
641
642template <typename A, typename R>
643bool UnwindCursor<A, R>::validReg(int regNum) {
644  if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
645#if defined(_LIBUNWIND_TARGET_X86_64)
646  if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_R15) return true;
647#elif defined(_LIBUNWIND_TARGET_ARM)
648  if (regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) return true;
649#elif defined(_LIBUNWIND_TARGET_AARCH64)
650  if (regNum >= UNW_ARM64_X0 && regNum <= UNW_ARM64_X30) return true;
651#endif
652  return false;
653}
654
655template <typename A, typename R>
656unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
657  switch (regNum) {
658#if defined(_LIBUNWIND_TARGET_X86_64)
659  case UNW_REG_IP: return _msContext.Rip;
660  case UNW_X86_64_RAX: return _msContext.Rax;
661  case UNW_X86_64_RDX: return _msContext.Rdx;
662  case UNW_X86_64_RCX: return _msContext.Rcx;
663  case UNW_X86_64_RBX: return _msContext.Rbx;
664  case UNW_REG_SP:
665  case UNW_X86_64_RSP: return _msContext.Rsp;
666  case UNW_X86_64_RBP: return _msContext.Rbp;
667  case UNW_X86_64_RSI: return _msContext.Rsi;
668  case UNW_X86_64_RDI: return _msContext.Rdi;
669  case UNW_X86_64_R8: return _msContext.R8;
670  case UNW_X86_64_R9: return _msContext.R9;
671  case UNW_X86_64_R10: return _msContext.R10;
672  case UNW_X86_64_R11: return _msContext.R11;
673  case UNW_X86_64_R12: return _msContext.R12;
674  case UNW_X86_64_R13: return _msContext.R13;
675  case UNW_X86_64_R14: return _msContext.R14;
676  case UNW_X86_64_R15: return _msContext.R15;
677#elif defined(_LIBUNWIND_TARGET_ARM)
678  case UNW_ARM_R0: return _msContext.R0;
679  case UNW_ARM_R1: return _msContext.R1;
680  case UNW_ARM_R2: return _msContext.R2;
681  case UNW_ARM_R3: return _msContext.R3;
682  case UNW_ARM_R4: return _msContext.R4;
683  case UNW_ARM_R5: return _msContext.R5;
684  case UNW_ARM_R6: return _msContext.R6;
685  case UNW_ARM_R7: return _msContext.R7;
686  case UNW_ARM_R8: return _msContext.R8;
687  case UNW_ARM_R9: return _msContext.R9;
688  case UNW_ARM_R10: return _msContext.R10;
689  case UNW_ARM_R11: return _msContext.R11;
690  case UNW_ARM_R12: return _msContext.R12;
691  case UNW_REG_SP:
692  case UNW_ARM_SP: return _msContext.Sp;
693  case UNW_ARM_LR: return _msContext.Lr;
694  case UNW_REG_IP:
695  case UNW_ARM_IP: return _msContext.Pc;
696#elif defined(_LIBUNWIND_TARGET_AARCH64)
697  case UNW_REG_SP: return _msContext.Sp;
698  case UNW_REG_IP: return _msContext.Pc;
699  default: return _msContext.X[regNum - UNW_ARM64_X0];
700#endif
701  }
702  _LIBUNWIND_ABORT("unsupported register");
703}
704
705template <typename A, typename R>
706void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
707  switch (regNum) {
708#if defined(_LIBUNWIND_TARGET_X86_64)
709  case UNW_REG_IP: _msContext.Rip = value; break;
710  case UNW_X86_64_RAX: _msContext.Rax = value; break;
711  case UNW_X86_64_RDX: _msContext.Rdx = value; break;
712  case UNW_X86_64_RCX: _msContext.Rcx = value; break;
713  case UNW_X86_64_RBX: _msContext.Rbx = value; break;
714  case UNW_REG_SP:
715  case UNW_X86_64_RSP: _msContext.Rsp = value; break;
716  case UNW_X86_64_RBP: _msContext.Rbp = value; break;
717  case UNW_X86_64_RSI: _msContext.Rsi = value; break;
718  case UNW_X86_64_RDI: _msContext.Rdi = value; break;
719  case UNW_X86_64_R8: _msContext.R8 = value; break;
720  case UNW_X86_64_R9: _msContext.R9 = value; break;
721  case UNW_X86_64_R10: _msContext.R10 = value; break;
722  case UNW_X86_64_R11: _msContext.R11 = value; break;
723  case UNW_X86_64_R12: _msContext.R12 = value; break;
724  case UNW_X86_64_R13: _msContext.R13 = value; break;
725  case UNW_X86_64_R14: _msContext.R14 = value; break;
726  case UNW_X86_64_R15: _msContext.R15 = value; break;
727#elif defined(_LIBUNWIND_TARGET_ARM)
728  case UNW_ARM_R0: _msContext.R0 = value; break;
729  case UNW_ARM_R1: _msContext.R1 = value; break;
730  case UNW_ARM_R2: _msContext.R2 = value; break;
731  case UNW_ARM_R3: _msContext.R3 = value; break;
732  case UNW_ARM_R4: _msContext.R4 = value; break;
733  case UNW_ARM_R5: _msContext.R5 = value; break;
734  case UNW_ARM_R6: _msContext.R6 = value; break;
735  case UNW_ARM_R7: _msContext.R7 = value; break;
736  case UNW_ARM_R8: _msContext.R8 = value; break;
737  case UNW_ARM_R9: _msContext.R9 = value; break;
738  case UNW_ARM_R10: _msContext.R10 = value; break;
739  case UNW_ARM_R11: _msContext.R11 = value; break;
740  case UNW_ARM_R12: _msContext.R12 = value; break;
741  case UNW_REG_SP:
742  case UNW_ARM_SP: _msContext.Sp = value; break;
743  case UNW_ARM_LR: _msContext.Lr = value; break;
744  case UNW_REG_IP:
745  case UNW_ARM_IP: _msContext.Pc = value; break;
746#elif defined(_LIBUNWIND_TARGET_AARCH64)
747  case UNW_REG_SP: _msContext.Sp = value; break;
748  case UNW_REG_IP: _msContext.Pc = value; break;
749  case UNW_ARM64_X0:
750  case UNW_ARM64_X1:
751  case UNW_ARM64_X2:
752  case UNW_ARM64_X3:
753  case UNW_ARM64_X4:
754  case UNW_ARM64_X5:
755  case UNW_ARM64_X6:
756  case UNW_ARM64_X7:
757  case UNW_ARM64_X8:
758  case UNW_ARM64_X9:
759  case UNW_ARM64_X10:
760  case UNW_ARM64_X11:
761  case UNW_ARM64_X12:
762  case UNW_ARM64_X13:
763  case UNW_ARM64_X14:
764  case UNW_ARM64_X15:
765  case UNW_ARM64_X16:
766  case UNW_ARM64_X17:
767  case UNW_ARM64_X18:
768  case UNW_ARM64_X19:
769  case UNW_ARM64_X20:
770  case UNW_ARM64_X21:
771  case UNW_ARM64_X22:
772  case UNW_ARM64_X23:
773  case UNW_ARM64_X24:
774  case UNW_ARM64_X25:
775  case UNW_ARM64_X26:
776  case UNW_ARM64_X27:
777  case UNW_ARM64_X28:
778  case UNW_ARM64_FP:
779  case UNW_ARM64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
780#endif
781  default:
782    _LIBUNWIND_ABORT("unsupported register");
783  }
784}
785
786template <typename A, typename R>
787bool UnwindCursor<A, R>::validFloatReg(int regNum) {
788#if defined(_LIBUNWIND_TARGET_ARM)
789  if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
790  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
791#elif defined(_LIBUNWIND_TARGET_AARCH64)
792  if (regNum >= UNW_ARM64_D0 && regNum <= UNW_ARM64_D31) return true;
793#else
794  (void)regNum;
795#endif
796  return false;
797}
798
799template <typename A, typename R>
800unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
801#if defined(_LIBUNWIND_TARGET_ARM)
802  if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
803    union {
804      uint32_t w;
805      float f;
806    } d;
807    d.w = _msContext.S[regNum - UNW_ARM_S0];
808    return d.f;
809  }
810  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
811    union {
812      uint64_t w;
813      double d;
814    } d;
815    d.w = _msContext.D[regNum - UNW_ARM_D0];
816    return d.d;
817  }
818  _LIBUNWIND_ABORT("unsupported float register");
819#elif defined(_LIBUNWIND_TARGET_AARCH64)
820  return _msContext.V[regNum - UNW_ARM64_D0].D[0];
821#else
822  (void)regNum;
823  _LIBUNWIND_ABORT("float registers unimplemented");
824#endif
825}
826
827template <typename A, typename R>
828void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
829#if defined(_LIBUNWIND_TARGET_ARM)
830  if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
831    union {
832      uint32_t w;
833      float f;
834    } d;
835    d.f = value;
836    _msContext.S[regNum - UNW_ARM_S0] = d.w;
837  }
838  if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
839    union {
840      uint64_t w;
841      double d;
842    } d;
843    d.d = value;
844    _msContext.D[regNum - UNW_ARM_D0] = d.w;
845  }
846  _LIBUNWIND_ABORT("unsupported float register");
847#elif defined(_LIBUNWIND_TARGET_AARCH64)
848  _msContext.V[regNum - UNW_ARM64_D0].D[0] = value;
849#else
850  (void)regNum;
851  (void)value;
852  _LIBUNWIND_ABORT("float registers unimplemented");
853#endif
854}
855
856template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
857  RtlRestoreContext(&_msContext, nullptr);
858}
859
860#ifdef __arm__
861template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}
862#endif
863
864template <typename A, typename R>
865const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
866  return R::getRegisterName(regNum);
867}
868
869template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
870  return false;
871}
872
873#else  // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
874
875/// UnwindCursor contains all state (including all register values) during
876/// an unwind.  This is normally stack allocated inside a unw_cursor_t.
877template <typename A, typename R>
878class UnwindCursor : public AbstractUnwindCursor{
879  typedef typename A::pint_t pint_t;
880public:
881                      UnwindCursor(unw_context_t *context, A &as);
882                      UnwindCursor(A &as, void *threadArg);
883  virtual             ~UnwindCursor() {}
884  virtual bool        validReg(int);
885  virtual unw_word_t  getReg(int);
886  virtual void        setReg(int, unw_word_t);
887  virtual bool        validFloatReg(int);
888  virtual unw_fpreg_t getFloatReg(int);
889  virtual void        setFloatReg(int, unw_fpreg_t);
890  virtual int         step();
891  virtual void        getInfo(unw_proc_info_t *);
892  virtual void        jumpto();
893  virtual bool        isSignalFrame();
894  virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
895  virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
896  virtual const char *getRegisterName(int num);
897#ifdef __arm__
898  virtual void        saveVFPAsX();
899#endif
900
901  // libunwind does not and should not depend on C++ library which means that we
902  // need our own defition of inline placement new.
903  static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
904
905private:
906
907#if defined(_LIBUNWIND_ARM_EHABI)
908  bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
909
910  int stepWithEHABI() {
911    size_t len = 0;
912    size_t off = 0;
913    // FIXME: Calling decode_eht_entry() here is violating the libunwind
914    // abstraction layer.
915    const uint32_t *ehtp =
916        decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info),
917                         &off, &len);
918    if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) !=
919            _URC_CONTINUE_UNWIND)
920      return UNW_STEP_END;
921    return UNW_STEP_SUCCESS;
922  }
923#endif
924
925#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
926  bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
927                                            uint32_t fdeSectionOffsetHint=0);
928  int stepWithDwarfFDE() {
929    return DwarfInstructions<A, R>::stepWithDwarf(_addressSpace,
930                                              (pint_t)this->getReg(UNW_REG_IP),
931                                              (pint_t)_info.unwind_info,
932                                              _registers);
933  }
934#endif
935
936#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
937  bool getInfoFromCompactEncodingSection(pint_t pc,
938                                            const UnwindInfoSections &sects);
939  int stepWithCompactEncoding() {
940  #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
941    if ( compactSaysUseDwarf() )
942      return stepWithDwarfFDE();
943  #endif
944    R dummy;
945    return stepWithCompactEncoding(dummy);
946  }
947
948#if defined(_LIBUNWIND_TARGET_X86_64)
949  int stepWithCompactEncoding(Registers_x86_64 &) {
950    return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
951        _info.format, _info.start_ip, _addressSpace, _registers);
952  }
953#endif
954
955#if defined(_LIBUNWIND_TARGET_I386)
956  int stepWithCompactEncoding(Registers_x86 &) {
957    return CompactUnwinder_x86<A>::stepWithCompactEncoding(
958        _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
959  }
960#endif
961
962#if defined(_LIBUNWIND_TARGET_PPC)
963  int stepWithCompactEncoding(Registers_ppc &) {
964    return UNW_EINVAL;
965  }
966#endif
967
968#if defined(_LIBUNWIND_TARGET_PPC64)
969  int stepWithCompactEncoding(Registers_ppc64 &) {
970    return UNW_EINVAL;
971  }
972#endif
973
974
975#if defined(_LIBUNWIND_TARGET_AARCH64)
976  int stepWithCompactEncoding(Registers_arm64 &) {
977    return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
978        _info.format, _info.start_ip, _addressSpace, _registers);
979  }
980#endif
981
982#if defined(_LIBUNWIND_TARGET_MIPS_O32)
983  int stepWithCompactEncoding(Registers_mips_o32 &) {
984    return UNW_EINVAL;
985  }
986#endif
987
988#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
989  int stepWithCompactEncoding(Registers_mips_newabi &) {
990    return UNW_EINVAL;
991  }
992#endif
993
994#if defined(_LIBUNWIND_TARGET_SPARC)
995  int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
996#endif
997
998  bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
999    R dummy;
1000    return compactSaysUseDwarf(dummy, offset);
1001  }
1002
1003#if defined(_LIBUNWIND_TARGET_X86_64)
1004  bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
1005    if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
1006      if (offset)
1007        *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
1008      return true;
1009    }
1010    return false;
1011  }
1012#endif
1013
1014#if defined(_LIBUNWIND_TARGET_I386)
1015  bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
1016    if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
1017      if (offset)
1018        *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);
1019      return true;
1020    }
1021    return false;
1022  }
1023#endif
1024
1025#if defined(_LIBUNWIND_TARGET_PPC)
1026  bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
1027    return true;
1028  }
1029#endif
1030
1031#if defined(_LIBUNWIND_TARGET_PPC64)
1032  bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {
1033    return true;
1034  }
1035#endif
1036
1037#if defined(_LIBUNWIND_TARGET_AARCH64)
1038  bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
1039    if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
1040      if (offset)
1041        *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);
1042      return true;
1043    }
1044    return false;
1045  }
1046#endif
1047
1048#if defined(_LIBUNWIND_TARGET_MIPS_O32)
1049  bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const {
1050    return true;
1051  }
1052#endif
1053
1054#if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
1055  bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
1056    return true;
1057  }
1058#endif
1059
1060#if defined(_LIBUNWIND_TARGET_SPARC)
1061  bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
1062#endif
1063
1064#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1065
1066#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1067  compact_unwind_encoding_t dwarfEncoding() const {
1068    R dummy;
1069    return dwarfEncoding(dummy);
1070  }
1071
1072#if defined(_LIBUNWIND_TARGET_X86_64)
1073  compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
1074    return UNWIND_X86_64_MODE_DWARF;
1075  }
1076#endif
1077
1078#if defined(_LIBUNWIND_TARGET_I386)
1079  compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
1080    return UNWIND_X86_MODE_DWARF;
1081  }
1082#endif
1083
1084#if defined(_LIBUNWIND_TARGET_PPC)
1085  compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
1086    return 0;
1087  }
1088#endif
1089
1090#if defined(_LIBUNWIND_TARGET_PPC64)
1091  compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {
1092    return 0;
1093  }
1094#endif
1095
1096#if defined(_LIBUNWIND_TARGET_AARCH64)
1097  compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
1098    return UNWIND_ARM64_MODE_DWARF;
1099  }
1100#endif
1101
1102#if defined(_LIBUNWIND_TARGET_ARM)
1103  compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const {
1104    return 0;
1105  }
1106#endif
1107
1108#if defined (_LIBUNWIND_TARGET_OR1K)
1109  compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
1110    return 0;
1111  }
1112#endif
1113
1114#if defined (_LIBUNWIND_TARGET_MIPS_O32)
1115  compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const {
1116    return 0;
1117  }
1118#endif
1119
1120#if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
1121  compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
1122    return 0;
1123  }
1124#endif
1125
1126#if defined(_LIBUNWIND_TARGET_SPARC)
1127  compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
1128#endif
1129
1130#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1131
1132#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1133  // For runtime environments using SEH unwind data without Windows runtime
1134  // support.
1135  pint_t getLastPC() const { /* FIXME: Implement */ return 0; }
1136  void setLastPC(pint_t pc) { /* FIXME: Implement */ }
1137  RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
1138    /* FIXME: Implement */
1139    *base = 0;
1140    return nullptr;
1141  }
1142  bool getInfoFromSEH(pint_t pc);
1143  int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1144#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1145
1146
1147  A               &_addressSpace;
1148  R                _registers;
1149  unw_proc_info_t  _info;
1150  bool             _unwindInfoMissing;
1151  bool             _isSignalFrame;
1152};
1153
1154
1155template <typename A, typename R>
1156UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
1157    : _addressSpace(as), _registers(context), _unwindInfoMissing(false),
1158      _isSignalFrame(false) {
1159  static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
1160                "UnwindCursor<> does not fit in unw_cursor_t");
1161  memset(&_info, 0, sizeof(_info));
1162}
1163
1164template <typename A, typename R>
1165UnwindCursor<A, R>::UnwindCursor(A &as, void *)
1166    : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
1167  memset(&_info, 0, sizeof(_info));
1168  // FIXME
1169  // fill in _registers from thread arg
1170}
1171
1172
1173template <typename A, typename R>
1174bool UnwindCursor<A, R>::validReg(int regNum) {
1175  return _registers.validRegister(regNum);
1176}
1177
1178template <typename A, typename R>
1179unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
1180  return _registers.getRegister(regNum);
1181}
1182
1183template <typename A, typename R>
1184void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
1185  _registers.setRegister(regNum, (typename A::pint_t)value);
1186}
1187
1188template <typename A, typename R>
1189bool UnwindCursor<A, R>::validFloatReg(int regNum) {
1190  return _registers.validFloatRegister(regNum);
1191}
1192
1193template <typename A, typename R>
1194unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
1195  return _registers.getFloatRegister(regNum);
1196}
1197
1198template <typename A, typename R>
1199void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
1200  _registers.setFloatRegister(regNum, value);
1201}
1202
1203template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
1204  _registers.jumpto();
1205}
1206
1207#ifdef __arm__
1208template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
1209  _registers.saveVFPAsX();
1210}
1211#endif
1212
1213template <typename A, typename R>
1214const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
1215  return _registers.getRegisterName(regNum);
1216}
1217
1218template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
1219  return _isSignalFrame;
1220}
1221
1222#endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1223
1224#if defined(_LIBUNWIND_ARM_EHABI)
1225struct EHABIIndexEntry {
1226  uint32_t functionOffset;
1227  uint32_t data;
1228};
1229
1230template<typename A>
1231struct EHABISectionIterator {
1232  typedef EHABISectionIterator _Self;
1233
1234  typedef typename A::pint_t value_type;
1235  typedef typename A::pint_t* pointer;
1236  typedef typename A::pint_t& reference;
1237  typedef size_t size_type;
1238  typedef size_t difference_type;
1239
1240  static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {
1241    return _Self(addressSpace, sects, 0);
1242  }
1243  static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
1244    return _Self(addressSpace, sects,
1245                 sects.arm_section_length / sizeof(EHABIIndexEntry));
1246  }
1247
1248  EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
1249      : _i(i), _addressSpace(&addressSpace), _sects(&sects) {}
1250
1251  _Self& operator++() { ++_i; return *this; }
1252  _Self& operator+=(size_t a) { _i += a; return *this; }
1253  _Self& operator--() { assert(_i > 0); --_i; return *this; }
1254  _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; }
1255
1256  _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; }
1257  _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; }
1258
1259  size_t operator-(const _Self& other) { return _i - other._i; }
1260
1261  bool operator==(const _Self& other) const {
1262    assert(_addressSpace == other._addressSpace);
1263    assert(_sects == other._sects);
1264    return _i == other._i;
1265  }
1266
1267  typename A::pint_t operator*() const { return functionAddress(); }
1268
1269  typename A::pint_t functionAddress() const {
1270    typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1271        EHABIIndexEntry, _i, functionOffset);
1272    return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));
1273  }
1274
1275  typename A::pint_t dataAddress() {
1276    typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1277        EHABIIndexEntry, _i, data);
1278    return indexAddr;
1279  }
1280
1281 private:
1282  size_t _i;
1283  A* _addressSpace;
1284  const UnwindInfoSections* _sects;
1285};
1286
1287namespace {
1288
1289template <typename A>
1290EHABISectionIterator<A> EHABISectionUpperBound(
1291    EHABISectionIterator<A> first,
1292    EHABISectionIterator<A> last,
1293    typename A::pint_t value) {
1294  size_t len = last - first;
1295  while (len > 0) {
1296    size_t l2 = len / 2;
1297    EHABISectionIterator<A> m = first + l2;
1298    if (value < *m) {
1299        len = l2;
1300    } else {
1301        first = ++m;
1302        len -= l2 + 1;
1303    }
1304  }
1305  return first;
1306}
1307
1308}
1309
1310template <typename A, typename R>
1311bool UnwindCursor<A, R>::getInfoFromEHABISection(
1312    pint_t pc,
1313    const UnwindInfoSections &sects) {
1314  EHABISectionIterator<A> begin =
1315      EHABISectionIterator<A>::begin(_addressSpace, sects);
1316  EHABISectionIterator<A> end =
1317      EHABISectionIterator<A>::end(_addressSpace, sects);
1318  if (begin == end)
1319    return false;
1320
1321  EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc);
1322  if (itNextPC == begin)
1323    return false;
1324  EHABISectionIterator<A> itThisPC = itNextPC - 1;
1325
1326  pint_t thisPC = itThisPC.functionAddress();
1327  // If an exception is thrown from a function, corresponding to the last entry
1328  // in the table, we don't really know the function extent and have to choose a
1329  // value for nextPC. Choosing max() will allow the range check during trace to
1330  // succeed.
1331  pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress();
1332  pint_t indexDataAddr = itThisPC.dataAddress();
1333
1334  if (indexDataAddr == 0)
1335    return false;
1336
1337  uint32_t indexData = _addressSpace.get32(indexDataAddr);
1338  if (indexData == UNW_EXIDX_CANTUNWIND)
1339    return false;
1340
1341  // If the high bit is set, the exception handling table entry is inline inside
1342  // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1343  // the table points at an offset in the exception handling table (section 5 EHABI).
1344  pint_t exceptionTableAddr;
1345  uint32_t exceptionTableData;
1346  bool isSingleWordEHT;
1347  if (indexData & 0x80000000) {
1348    exceptionTableAddr = indexDataAddr;
1349    // TODO(ajwong): Should this data be 0?
1350    exceptionTableData = indexData;
1351    isSingleWordEHT = true;
1352  } else {
1353    exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);
1354    exceptionTableData = _addressSpace.get32(exceptionTableAddr);
1355    isSingleWordEHT = false;
1356  }
1357
1358  // Now we know the 3 things:
1359  //   exceptionTableAddr -- exception handler table entry.
1360  //   exceptionTableData -- the data inside the first word of the eht entry.
1361  //   isSingleWordEHT -- whether the entry is in the index.
1362  unw_word_t personalityRoutine = 0xbadf00d;
1363  bool scope32 = false;
1364  uintptr_t lsda;
1365
1366  // If the high bit in the exception handling table entry is set, the entry is
1367  // in compact form (section 6.3 EHABI).
1368  if (exceptionTableData & 0x80000000) {
1369    // Grab the index of the personality routine from the compact form.
1370    uint32_t choice = (exceptionTableData & 0x0f000000) >> 24;
1371    uint32_t extraWords = 0;
1372    switch (choice) {
1373      case 0:
1374        personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;
1375        extraWords = 0;
1376        scope32 = false;
1377        lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4);
1378        break;
1379      case 1:
1380        personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;
1381        extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1382        scope32 = false;
1383        lsda = exceptionTableAddr + (extraWords + 1) * 4;
1384        break;
1385      case 2:
1386        personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;
1387        extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1388        scope32 = true;
1389        lsda = exceptionTableAddr + (extraWords + 1) * 4;
1390        break;
1391      default:
1392        _LIBUNWIND_ABORT("unknown personality routine");
1393        return false;
1394    }
1395
1396    if (isSingleWordEHT) {
1397      if (extraWords != 0) {
1398        _LIBUNWIND_ABORT("index inlined table detected but pr function "
1399                         "requires extra words");
1400        return false;
1401      }
1402    }
1403  } else {
1404    pint_t personalityAddr =
1405        exceptionTableAddr + signExtendPrel31(exceptionTableData);
1406    personalityRoutine = personalityAddr;
1407
1408    // ARM EHABI # 6.2, # 9.2
1409    //
1410    //  +---- ehtp
1411    //  v
1412    // +--------------------------------------+
1413    // | +--------+--------+--------+-------+ |
1414    // | |0| prel31 to personalityRoutine   | |
1415    // | +--------+--------+--------+-------+ |
1416    // | |      N |      unwind opcodes     | |  <-- UnwindData
1417    // | +--------+--------+--------+-------+ |
1418    // | | Word 2        unwind opcodes     | |
1419    // | +--------+--------+--------+-------+ |
1420    // | ...                                  |
1421    // | +--------+--------+--------+-------+ |
1422    // | | Word N        unwind opcodes     | |
1423    // | +--------+--------+--------+-------+ |
1424    // | | LSDA                             | |  <-- lsda
1425    // | | ...                              | |
1426    // | +--------+--------+--------+-------+ |
1427    // +--------------------------------------+
1428
1429    uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;
1430    uint32_t FirstDataWord = *UnwindData;
1431    size_t N = ((FirstDataWord >> 24) & 0xff);
1432    size_t NDataWords = N + 1;
1433    lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);
1434  }
1435
1436  _info.start_ip = thisPC;
1437  _info.end_ip = nextPC;
1438  _info.handler = personalityRoutine;
1439  _info.unwind_info = exceptionTableAddr;
1440  _info.lsda = lsda;
1441  // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1442  _info.flags = isSingleWordEHT ? 1 : 0 | scope32 ? 0x2 : 0;  // Use enum?
1443
1444  return true;
1445}
1446#endif
1447
1448#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1449template <typename A, typename R>
1450bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
1451                                                const UnwindInfoSections &sects,
1452                                                uint32_t fdeSectionOffsetHint) {
1453  typename CFI_Parser<A>::FDE_Info fdeInfo;
1454  typename CFI_Parser<A>::CIE_Info cieInfo;
1455  bool foundFDE = false;
1456  bool foundInCache = false;
1457  // If compact encoding table gave offset into dwarf section, go directly there
1458  if (fdeSectionOffsetHint != 0) {
1459    foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1460                                    (uint32_t)sects.dwarf_section_length,
1461                                    sects.dwarf_section + fdeSectionOffsetHint,
1462                                    &fdeInfo, &cieInfo);
1463  }
1464#if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1465  if (!foundFDE && (sects.dwarf_index_section != 0)) {
1466    foundFDE = EHHeaderParser<A>::findFDE(
1467        _addressSpace, pc, sects.dwarf_index_section,
1468        (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
1469  }
1470#endif
1471  if (!foundFDE) {
1472    // otherwise, search cache of previously found FDEs.
1473    pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);
1474    if (cachedFDE != 0) {
1475      foundFDE =
1476          CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1477                                 (uint32_t)sects.dwarf_section_length,
1478                                 cachedFDE, &fdeInfo, &cieInfo);
1479      foundInCache = foundFDE;
1480    }
1481  }
1482  if (!foundFDE) {
1483    // Still not found, do full scan of __eh_frame section.
1484    foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1485                                      (uint32_t)sects.dwarf_section_length, 0,
1486                                      &fdeInfo, &cieInfo);
1487  }
1488  if (foundFDE) {
1489    typename CFI_Parser<A>::PrologInfo prolog;
1490    if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
1491                                            R::getArch(), &prolog)) {
1492      // Save off parsed FDE info
1493      _info.start_ip          = fdeInfo.pcStart;
1494      _info.end_ip            = fdeInfo.pcEnd;
1495      _info.lsda              = fdeInfo.lsda;
1496      _info.handler           = cieInfo.personality;
1497      _info.gp                = prolog.spExtraArgSize;
1498      _info.flags             = 0;
1499      _info.format            = dwarfEncoding();
1500      _info.unwind_info       = fdeInfo.fdeStart;
1501      _info.unwind_info_size  = (uint32_t)fdeInfo.fdeLength;
1502      _info.extra             = (unw_word_t) sects.dso_base;
1503
1504      // Add to cache (to make next lookup faster) if we had no hint
1505      // and there was no index.
1506      if (!foundInCache && (fdeSectionOffsetHint == 0)) {
1507  #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1508        if (sects.dwarf_index_section == 0)
1509  #endif
1510        DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
1511                              fdeInfo.fdeStart);
1512      }
1513      return true;
1514    }
1515  }
1516  //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1517  return false;
1518}
1519#endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1520
1521
1522#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1523template <typename A, typename R>
1524bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
1525                                              const UnwindInfoSections &sects) {
1526  const bool log = false;
1527  if (log)
1528    fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1529            (uint64_t)pc, (uint64_t)sects.dso_base);
1530
1531  const UnwindSectionHeader<A> sectionHeader(_addressSpace,
1532                                                sects.compact_unwind_section);
1533  if (sectionHeader.version() != UNWIND_SECTION_VERSION)
1534    return false;
1535
1536  // do a binary search of top level index to find page with unwind info
1537  pint_t targetFunctionOffset = pc - sects.dso_base;
1538  const UnwindSectionIndexArray<A> topIndex(_addressSpace,
1539                                           sects.compact_unwind_section
1540                                         + sectionHeader.indexSectionOffset());
1541  uint32_t low = 0;
1542  uint32_t high = sectionHeader.indexCount();
1543  uint32_t last = high - 1;
1544  while (low < high) {
1545    uint32_t mid = (low + high) / 2;
1546    //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1547    //mid, low, high, topIndex.functionOffset(mid));
1548    if (topIndex.functionOffset(mid) <= targetFunctionOffset) {
1549      if ((mid == last) ||
1550          (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {
1551        low = mid;
1552        break;
1553      } else {
1554        low = mid + 1;
1555      }
1556    } else {
1557      high = mid;
1558    }
1559  }
1560  const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
1561  const uint32_t firstLevelNextPageFunctionOffset =
1562      topIndex.functionOffset(low + 1);
1563  const pint_t secondLevelAddr =
1564      sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);
1565  const pint_t lsdaArrayStartAddr =
1566      sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);
1567  const pint_t lsdaArrayEndAddr =
1568      sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);
1569  if (log)
1570    fprintf(stderr, "\tfirst level search for result index=%d "
1571                    "to secondLevelAddr=0x%llX\n",
1572                    low, (uint64_t) secondLevelAddr);
1573  // do a binary search of second level page index
1574  uint32_t encoding = 0;
1575  pint_t funcStart = 0;
1576  pint_t funcEnd = 0;
1577  pint_t lsda = 0;
1578  pint_t personality = 0;
1579  uint32_t pageKind = _addressSpace.get32(secondLevelAddr);
1580  if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {
1581    // regular page
1582    UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,
1583                                                 secondLevelAddr);
1584    UnwindSectionRegularArray<A> pageIndex(
1585        _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1586    // binary search looks for entry with e where index[e].offset <= pc <
1587    // index[e+1].offset
1588    if (log)
1589      fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "
1590                      "regular page starting at secondLevelAddr=0x%llX\n",
1591              (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);
1592    low = 0;
1593    high = pageHeader.entryCount();
1594    while (low < high) {
1595      uint32_t mid = (low + high) / 2;
1596      if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {
1597        if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {
1598          // at end of table
1599          low = mid;
1600          funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1601          break;
1602        } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {
1603          // next is too big, so we found it
1604          low = mid;
1605          funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;
1606          break;
1607        } else {
1608          low = mid + 1;
1609        }
1610      } else {
1611        high = mid;
1612      }
1613    }
1614    encoding = pageIndex.encoding(low);
1615    funcStart = pageIndex.functionOffset(low) + sects.dso_base;
1616    if (pc < funcStart) {
1617      if (log)
1618        fprintf(
1619            stderr,
1620            "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1621            (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1622      return false;
1623    }
1624    if (pc > funcEnd) {
1625      if (log)
1626        fprintf(
1627            stderr,
1628            "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1629            (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1630      return false;
1631    }
1632  } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {
1633    // compressed page
1634    UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,
1635                                                    secondLevelAddr);
1636    UnwindSectionCompressedArray<A> pageIndex(
1637        _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1638    const uint32_t targetFunctionPageOffset =
1639        (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset);
1640    // binary search looks for entry with e where index[e].offset <= pc <
1641    // index[e+1].offset
1642    if (log)
1643      fprintf(stderr, "\tbinary search of compressed page starting at "
1644                      "secondLevelAddr=0x%llX\n",
1645              (uint64_t) secondLevelAddr);
1646    low = 0;
1647    last = pageHeader.entryCount() - 1;
1648    high = pageHeader.entryCount();
1649    while (low < high) {
1650      uint32_t mid = (low + high) / 2;
1651      if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {
1652        if ((mid == last) ||
1653            (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {
1654          low = mid;
1655          break;
1656        } else {
1657          low = mid + 1;
1658        }
1659      } else {
1660        high = mid;
1661      }
1662    }
1663    funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset
1664                                                              + sects.dso_base;
1665    if (low < last)
1666      funcEnd =
1667          pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset
1668                                                              + sects.dso_base;
1669    else
1670      funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1671    if (pc < funcStart) {
1672      _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second  "
1673                           "level compressed unwind table. funcStart=0x%llX",
1674                            (uint64_t) pc, (uint64_t) funcStart);
1675      return false;
1676    }
1677    if (pc > funcEnd) {
1678      _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX not in second  "
1679                          "level compressed unwind table. funcEnd=0x%llX",
1680                           (uint64_t) pc, (uint64_t) funcEnd);
1681      return false;
1682    }
1683    uint16_t encodingIndex = pageIndex.encodingIndex(low);
1684    if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) {
1685      // encoding is in common table in section header
1686      encoding = _addressSpace.get32(
1687          sects.compact_unwind_section +
1688          sectionHeader.commonEncodingsArraySectionOffset() +
1689          encodingIndex * sizeof(uint32_t));
1690    } else {
1691      // encoding is in page specific table
1692      uint16_t pageEncodingIndex =
1693          encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount();
1694      encoding = _addressSpace.get32(secondLevelAddr +
1695                                     pageHeader.encodingsPageOffset() +
1696                                     pageEncodingIndex * sizeof(uint32_t));
1697    }
1698  } else {
1699    _LIBUNWIND_DEBUG_LOG("malformed __unwind_info at 0x%0llX bad second "
1700                         "level page",
1701                          (uint64_t) sects.compact_unwind_section);
1702    return false;
1703  }
1704
1705  // look up LSDA, if encoding says function has one
1706  if (encoding & UNWIND_HAS_LSDA) {
1707    UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);
1708    uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);
1709    low = 0;
1710    high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /
1711                    sizeof(unwind_info_section_header_lsda_index_entry);
1712    // binary search looks for entry with exact match for functionOffset
1713    if (log)
1714      fprintf(stderr,
1715              "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1716              funcStartOffset);
1717    while (low < high) {
1718      uint32_t mid = (low + high) / 2;
1719      if (lsdaIndex.functionOffset(mid) == funcStartOffset) {
1720        lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;
1721        break;
1722      } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {
1723        low = mid + 1;
1724      } else {
1725        high = mid;
1726      }
1727    }
1728    if (lsda == 0) {
1729      _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1730                    "pc=0x%0llX, but lsda table has no entry",
1731                    encoding, (uint64_t) pc);
1732      return false;
1733    }
1734  }
1735
1736  // extact personality routine, if encoding says function has one
1737  uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
1738                              (__builtin_ctz(UNWIND_PERSONALITY_MASK));
1739  if (personalityIndex != 0) {
1740    --personalityIndex; // change 1-based to zero-based index
1741    if (personalityIndex > sectionHeader.personalityArrayCount()) {
1742      _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d,  "
1743                            "but personality table has only %d entries",
1744                            encoding, personalityIndex,
1745                            sectionHeader.personalityArrayCount());
1746      return false;
1747    }
1748    int32_t personalityDelta = (int32_t)_addressSpace.get32(
1749        sects.compact_unwind_section +
1750        sectionHeader.personalityArraySectionOffset() +
1751        personalityIndex * sizeof(uint32_t));
1752    pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
1753    personality = _addressSpace.getP(personalityPointer);
1754    if (log)
1755      fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1756                      "personalityDelta=0x%08X, personality=0x%08llX\n",
1757              (uint64_t) pc, personalityDelta, (uint64_t) personality);
1758  }
1759
1760  if (log)
1761    fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1762                    "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1763            (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart);
1764  _info.start_ip = funcStart;
1765  _info.end_ip = funcEnd;
1766  _info.lsda = lsda;
1767  _info.handler = personality;
1768  _info.gp = 0;
1769  _info.flags = 0;
1770  _info.format = encoding;
1771  _info.unwind_info = 0;
1772  _info.unwind_info_size = 0;
1773  _info.extra = sects.dso_base;
1774  return true;
1775}
1776#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1777
1778
1779#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1780template <typename A, typename R>
1781bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
1782  pint_t base;
1783  RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);
1784  if (!unwindEntry) {
1785    _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);
1786    return false;
1787  }
1788  _info.gp = 0;
1789  _info.flags = 0;
1790  _info.format = 0;
1791  _info.unwind_info_size = sizeof(RUNTIME_FUNCTION);
1792  _info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry);
1793  _info.extra = base;
1794  _info.start_ip = base + unwindEntry->BeginAddress;
1795#ifdef _LIBUNWIND_TARGET_X86_64
1796  _info.end_ip = base + unwindEntry->EndAddress;
1797  // Only fill in the handler and LSDA if they're stale.
1798  if (pc != getLastPC()) {
1799    UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);
1800    if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {
1801      // The personality is given in the UNWIND_INFO itself. The LSDA immediately
1802      // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
1803      // these structures.)
1804      // N.B. UNWIND_INFO structs are DWORD-aligned.
1805      uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
1806      const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
1807      _info.lsda = reinterpret_cast<unw_word_t>(handler+1);
1808      if (*handler) {
1809        _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
1810      } else
1811        _info.handler = 0;
1812    } else {
1813      _info.lsda = 0;
1814      _info.handler = 0;
1815    }
1816  }
1817#elif defined(_LIBUNWIND_TARGET_ARM)
1818  _info.end_ip = _info.start_ip + unwindEntry->FunctionLength;
1819  _info.lsda = 0; // FIXME
1820  _info.handler = 0; // FIXME
1821#endif
1822  setLastPC(pc);
1823  return true;
1824}
1825#endif
1826
1827
1828template <typename A, typename R>
1829void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
1830  pint_t pc = (pint_t)this->getReg(UNW_REG_IP);
1831#if defined(_LIBUNWIND_ARM_EHABI)
1832  // Remove the thumb bit so the IP represents the actual instruction address.
1833  // This matches the behaviour of _Unwind_GetIP on arm.
1834  pc &= (pint_t)~0x1;
1835#endif
1836
1837  // If the last line of a function is a "throw" the compiler sometimes
1838  // emits no instructions after the call to __cxa_throw.  This means
1839  // the return address is actually the start of the next function.
1840  // To disambiguate this, back up the pc when we know it is a return
1841  // address.
1842  if (isReturnAddress)
1843    --pc;
1844
1845  // Ask address space object to find unwind sections for this pc.
1846  UnwindInfoSections sects;
1847  if (_addressSpace.findUnwindSections(pc, sects)) {
1848#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1849    // If there is a compact unwind encoding table, look there first.
1850    if (sects.compact_unwind_section != 0) {
1851      if (this->getInfoFromCompactEncodingSection(pc, sects)) {
1852  #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1853        // Found info in table, done unless encoding says to use dwarf.
1854        uint32_t dwarfOffset;
1855        if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
1856          if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {
1857            // found info in dwarf, done
1858            return;
1859          }
1860        }
1861  #endif
1862        // If unwind table has entry, but entry says there is no unwind info,
1863        // record that we have no unwind info.
1864        if (_info.format == 0)
1865          _unwindInfoMissing = true;
1866        return;
1867      }
1868    }
1869#endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1870
1871#if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1872    // If there is SEH unwind info, look there next.
1873    if (this->getInfoFromSEH(pc))
1874      return;
1875#endif
1876
1877#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1878    // If there is dwarf unwind info, look there next.
1879    if (sects.dwarf_section != 0) {
1880      if (this->getInfoFromDwarfSection(pc, sects)) {
1881        // found info in dwarf, done
1882        return;
1883      }
1884    }
1885#endif
1886
1887#if defined(_LIBUNWIND_ARM_EHABI)
1888    // If there is ARM EHABI unwind info, look there next.
1889    if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
1890      return;
1891#endif
1892  }
1893
1894#if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1895  // There is no static unwind info for this pc. Look to see if an FDE was
1896  // dynamically registered for it.
1897  pint_t cachedFDE = DwarfFDECache<A>::findFDE(0, pc);
1898  if (cachedFDE != 0) {
1899    CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1900    CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1901    const char *msg = CFI_Parser<A>::decodeFDE(_addressSpace,
1902                                                cachedFDE, &fdeInfo, &cieInfo);
1903    if (msg == NULL) {
1904      typename CFI_Parser<A>::PrologInfo prolog;
1905      if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
1906                                              pc, R::getArch(), &prolog)) {
1907        // save off parsed FDE info
1908        _info.start_ip         = fdeInfo.pcStart;
1909        _info.end_ip           = fdeInfo.pcEnd;
1910        _info.lsda             = fdeInfo.lsda;
1911        _info.handler          = cieInfo.personality;
1912        _info.gp               = prolog.spExtraArgSize;
1913                                  // Some frameless functions need SP
1914                                  // altered when resuming in function.
1915        _info.flags            = 0;
1916        _info.format           = dwarfEncoding();
1917        _info.unwind_info      = fdeInfo.fdeStart;
1918        _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1919        _info.extra            = 0;
1920        return;
1921      }
1922    }
1923  }
1924
1925  // Lastly, ask AddressSpace object about platform specific ways to locate
1926  // other FDEs.
1927  pint_t fde;
1928  if (_addressSpace.findOtherFDE(pc, fde)) {
1929    CFI_Parser<LocalAddressSpace>::FDE_Info fdeInfo;
1930    CFI_Parser<LocalAddressSpace>::CIE_Info cieInfo;
1931    if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
1932      // Double check this FDE is for a function that includes the pc.
1933      if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd)) {
1934        typename CFI_Parser<A>::PrologInfo prolog;
1935        if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo,
1936                                                pc, R::getArch(), &prolog)) {
1937          // save off parsed FDE info
1938          _info.start_ip         = fdeInfo.pcStart;
1939          _info.end_ip           = fdeInfo.pcEnd;
1940          _info.lsda             = fdeInfo.lsda;
1941          _info.handler          = cieInfo.personality;
1942          _info.gp               = prolog.spExtraArgSize;
1943          _info.flags            = 0;
1944          _info.format           = dwarfEncoding();
1945          _info.unwind_info      = fdeInfo.fdeStart;
1946          _info.unwind_info_size = (uint32_t)fdeInfo.fdeLength;
1947          _info.extra            = 0;
1948          return;
1949        }
1950      }
1951    }
1952  }
1953#endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1954
1955  // no unwind info, flag that we can't reliably unwind
1956  _unwindInfoMissing = true;
1957}
1958
1959template <typename A, typename R>
1960int UnwindCursor<A, R>::step() {
1961  // Bottom of stack is defined is when unwind info cannot be found.
1962  if (_unwindInfoMissing)
1963    return UNW_STEP_END;
1964
1965  // Use unwinding info to modify register set as if function returned.
1966  int result;
1967#if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1968  result = this->stepWithCompactEncoding();
1969#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1970  result = this->stepWithSEHData();
1971#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1972  result = this->stepWithDwarfFDE();
1973#elif defined(_LIBUNWIND_ARM_EHABI)
1974  result = this->stepWithEHABI();
1975#else
1976  #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
1977              _LIBUNWIND_SUPPORT_SEH_UNWIND or \
1978              _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
1979              _LIBUNWIND_ARM_EHABI
1980#endif
1981
1982  // update info based on new PC
1983  if (result == UNW_STEP_SUCCESS) {
1984    this->setInfoBasedOnIPRegister(true);
1985    if (_unwindInfoMissing)
1986      return UNW_STEP_END;
1987  }
1988
1989  return result;
1990}
1991
1992template <typename A, typename R>
1993void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
1994  *info = _info;
1995}
1996
1997template <typename A, typename R>
1998bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
1999                                                           unw_word_t *offset) {
2000  return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),
2001                                         buf, bufLen, offset);
2002}
2003
2004} // namespace libunwind
2005
2006#endif // __UNWINDCURSOR_HPP__
2007