xref: /freebsd/contrib/llvm-project/libunwind/src/UnwindCursor.hpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
1 //===----------------------------------------------------------------------===//
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 "shadow_stack_unwind.h"
15 #include <stdint.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unwind.h>
19 
20 #ifdef _WIN32
21   #include <windows.h>
22   #include <ntverp.h>
23 #endif
24 #ifdef __APPLE__
25   #include <mach-o/dyld.h>
26 #endif
27 #ifdef _AIX
28 #include <dlfcn.h>
29 #include <sys/debug.h>
30 #include <sys/pseg.h>
31 #endif
32 
33 #if defined(_LIBUNWIND_TARGET_LINUX) &&                                        \
34     (defined(_LIBUNWIND_TARGET_AARCH64) ||                                     \
35      defined(_LIBUNWIND_TARGET_LOONGARCH) ||                                   \
36      defined(_LIBUNWIND_TARGET_RISCV) || defined(_LIBUNWIND_TARGET_S390X))
37 #include <errno.h>
38 #include <signal.h>
39 #include <sys/syscall.h>
40 #include <unistd.h>
41 #define _LIBUNWIND_CHECK_LINUX_SIGRETURN 1
42 #endif
43 
44 #if defined(_LIBUNWIND_TARGET_HAIKU) && defined(_LIBUNWIND_TARGET_X86_64)
45 #include <OS.h>
46 #include <signal.h>
47 #define _LIBUNWIND_CHECK_HAIKU_SIGRETURN 1
48 #endif
49 
50 #include "AddressSpace.hpp"
51 #include "CompactUnwinder.hpp"
52 #include "config.h"
53 #include "DwarfInstructions.hpp"
54 #include "EHHeaderParser.hpp"
55 #include "libunwind.h"
56 #include "libunwind_ext.h"
57 #include "Registers.hpp"
58 #include "RWMutex.hpp"
59 #include "Unwind-EHABI.h"
60 
61 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
62 // Provide a definition for the DISPATCHER_CONTEXT struct for old (Win7 and
63 // earlier) SDKs.
64 // MinGW-w64 has always provided this struct.
65   #if defined(_WIN32) && defined(_LIBUNWIND_TARGET_X86_64) && \
66       !defined(__MINGW32__) && VER_PRODUCTBUILD < 8000
67 struct _DISPATCHER_CONTEXT {
68   ULONG64 ControlPc;
69   ULONG64 ImageBase;
70   PRUNTIME_FUNCTION FunctionEntry;
71   ULONG64 EstablisherFrame;
72   ULONG64 TargetIp;
73   PCONTEXT ContextRecord;
74   PEXCEPTION_ROUTINE LanguageHandler;
75   PVOID HandlerData;
76   PUNWIND_HISTORY_TABLE HistoryTable;
77   ULONG ScopeIndex;
78   ULONG Fill0;
79 };
80   #endif
81 
82 struct UNWIND_INFO {
83   uint8_t Version : 3;
84   uint8_t Flags : 5;
85   uint8_t SizeOfProlog;
86   uint8_t CountOfCodes;
87   uint8_t FrameRegister : 4;
88   uint8_t FrameOffset : 4;
89   uint16_t UnwindCodes[2];
90 };
91 
92 #pragma clang diagnostic push
93 #pragma clang diagnostic ignored "-Wgnu-anonymous-struct"
94 union UNWIND_INFO_ARM {
95   DWORD HeaderData;
96   struct {
97     DWORD FunctionLength : 18;
98     DWORD Version : 2;
99     DWORD ExceptionDataPresent : 1;
100     DWORD EpilogInHeader : 1;
101     DWORD FunctionFragment : 1;
102     DWORD EpilogCount : 5;
103     DWORD CodeWords : 4;
104   };
105 };
106 #pragma clang diagnostic pop
107 
108 extern "C" _Unwind_Reason_Code __libunwind_seh_personality(
109     int, _Unwind_Action, uint64_t, _Unwind_Exception *,
110     struct _Unwind_Context *);
111 
112 #endif
113 
114 namespace libunwind {
115 
116 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
117 /// Cache of recently found FDEs.
118 template <typename A>
119 class _LIBUNWIND_HIDDEN DwarfFDECache {
120   typedef typename A::pint_t pint_t;
121 public:
122   static constexpr pint_t kSearchAll = static_cast<pint_t>(-1);
123   static pint_t findFDE(pint_t mh, pint_t pc);
124   static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde);
125   static void removeAllIn(pint_t mh);
126   static void iterateCacheEntries(void (*func)(unw_word_t ip_start,
127                                                unw_word_t ip_end,
128                                                unw_word_t fde, unw_word_t mh));
129 
130 private:
131 
132   struct entry {
133     pint_t mh;
134     pint_t ip_start;
135     pint_t ip_end;
136     pint_t fde;
137   };
138 
139   // These fields are all static to avoid needing an initializer.
140   // There is only one instance of this class per process.
141   static RWMutex _lock;
142 #ifdef __APPLE__
143   static void dyldUnloadHook(const struct mach_header *mh, intptr_t slide);
144   static bool _registeredForDyldUnloads;
145 #endif
146   static entry *_buffer;
147   static entry *_bufferUsed;
148   static entry *_bufferEnd;
149   static entry _initialBuffer[64];
150 };
151 
152 template <typename A>
153 typename DwarfFDECache<A>::entry *
154 DwarfFDECache<A>::_buffer = _initialBuffer;
155 
156 template <typename A>
157 typename DwarfFDECache<A>::entry *
158 DwarfFDECache<A>::_bufferUsed = _initialBuffer;
159 
160 template <typename A>
161 typename DwarfFDECache<A>::entry *
162 DwarfFDECache<A>::_bufferEnd = &_initialBuffer[64];
163 
164 template <typename A>
165 typename DwarfFDECache<A>::entry DwarfFDECache<A>::_initialBuffer[64];
166 
167 template <typename A>
168 RWMutex DwarfFDECache<A>::_lock;
169 
170 #ifdef __APPLE__
171 template <typename A>
172 bool DwarfFDECache<A>::_registeredForDyldUnloads = false;
173 #endif
174 
175 template <typename A>
findFDE(pint_t mh,pint_t pc)176 typename DwarfFDECache<A>::pint_t DwarfFDECache<A>::findFDE(pint_t mh,
177                                                             pint_t pc) {
178   pint_t result = 0;
179   _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared());
180   for (entry *p = _buffer; p < _bufferUsed; ++p) {
181     if ((mh == p->mh) || (mh == kSearchAll)) {
182       if ((p->ip_start <= pc) && (pc < p->ip_end)) {
183         result = p->fde;
184         break;
185       }
186     }
187   }
188   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock_shared());
189   return result;
190 }
191 
192 template <typename A>
add(pint_t mh,pint_t ip_start,pint_t ip_end,pint_t fde)193 void DwarfFDECache<A>::add(pint_t mh, pint_t ip_start, pint_t ip_end,
194                            pint_t fde) {
195 #if !defined(_LIBUNWIND_NO_HEAP)
196   _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
197   if (_bufferUsed >= _bufferEnd) {
198     size_t oldSize = (size_t)(_bufferEnd - _buffer);
199     size_t newSize = oldSize * 4;
200     // Can't use operator new (we are below it).
201     entry *newBuffer = (entry *)malloc(newSize * sizeof(entry));
202     memcpy(newBuffer, _buffer, oldSize * sizeof(entry));
203     if (_buffer != _initialBuffer)
204       free(_buffer);
205     _buffer = newBuffer;
206     _bufferUsed = &newBuffer[oldSize];
207     _bufferEnd = &newBuffer[newSize];
208   }
209   _bufferUsed->mh = mh;
210   _bufferUsed->ip_start = ip_start;
211   _bufferUsed->ip_end = ip_end;
212   _bufferUsed->fde = fde;
213   ++_bufferUsed;
214 #ifdef __APPLE__
215   if (!_registeredForDyldUnloads) {
216     _dyld_register_func_for_remove_image(&dyldUnloadHook);
217     _registeredForDyldUnloads = true;
218   }
219 #endif
220   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
221 #endif
222 }
223 
224 template <typename A>
removeAllIn(pint_t mh)225 void DwarfFDECache<A>::removeAllIn(pint_t mh) {
226   _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
227   entry *d = _buffer;
228   for (const entry *s = _buffer; s < _bufferUsed; ++s) {
229     if (s->mh != mh) {
230       if (d != s)
231         *d = *s;
232       ++d;
233     }
234   }
235   _bufferUsed = d;
236   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
237 }
238 
239 #ifdef __APPLE__
240 template <typename A>
dyldUnloadHook(const struct mach_header * mh,intptr_t)241 void DwarfFDECache<A>::dyldUnloadHook(const struct mach_header *mh, intptr_t ) {
242   removeAllIn((pint_t) mh);
243 }
244 #endif
245 
246 template <typename A>
iterateCacheEntries(void (* func)(unw_word_t ip_start,unw_word_t ip_end,unw_word_t fde,unw_word_t mh))247 void DwarfFDECache<A>::iterateCacheEntries(void (*func)(
248     unw_word_t ip_start, unw_word_t ip_end, unw_word_t fde, unw_word_t mh)) {
249   _LIBUNWIND_LOG_IF_FALSE(_lock.lock());
250   for (entry *p = _buffer; p < _bufferUsed; ++p) {
251     (*func)(p->ip_start, p->ip_end, p->fde, p->mh);
252   }
253   _LIBUNWIND_LOG_IF_FALSE(_lock.unlock());
254 }
255 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
256 
257 #define arrayoffsetof(type, index, field)                                      \
258   (sizeof(type) * (index) + offsetof(type, field))
259 
260 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
261 template <typename A> class UnwindSectionHeader {
262 public:
UnwindSectionHeader(A & addressSpace,typename A::pint_t addr)263   UnwindSectionHeader(A &addressSpace, typename A::pint_t addr)
264       : _addressSpace(addressSpace), _addr(addr) {}
265 
version() const266   uint32_t version() const {
267     return _addressSpace.get32(_addr +
268                                offsetof(unwind_info_section_header, version));
269   }
commonEncodingsArraySectionOffset() const270   uint32_t commonEncodingsArraySectionOffset() const {
271     return _addressSpace.get32(_addr +
272                                offsetof(unwind_info_section_header,
273                                         commonEncodingsArraySectionOffset));
274   }
commonEncodingsArrayCount() const275   uint32_t commonEncodingsArrayCount() const {
276     return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
277                                                 commonEncodingsArrayCount));
278   }
personalityArraySectionOffset() const279   uint32_t personalityArraySectionOffset() const {
280     return _addressSpace.get32(_addr + offsetof(unwind_info_section_header,
281                                                 personalityArraySectionOffset));
282   }
personalityArrayCount() const283   uint32_t personalityArrayCount() const {
284     return _addressSpace.get32(
285         _addr + offsetof(unwind_info_section_header, personalityArrayCount));
286   }
indexSectionOffset() const287   uint32_t indexSectionOffset() const {
288     return _addressSpace.get32(
289         _addr + offsetof(unwind_info_section_header, indexSectionOffset));
290   }
indexCount() const291   uint32_t indexCount() const {
292     return _addressSpace.get32(
293         _addr + offsetof(unwind_info_section_header, indexCount));
294   }
295 
296 private:
297   A                     &_addressSpace;
298   typename A::pint_t     _addr;
299 };
300 
301 template <typename A> class UnwindSectionIndexArray {
302 public:
UnwindSectionIndexArray(A & addressSpace,typename A::pint_t addr)303   UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr)
304       : _addressSpace(addressSpace), _addr(addr) {}
305 
functionOffset(uint32_t index) const306   uint32_t functionOffset(uint32_t index) const {
307     return _addressSpace.get32(
308         _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
309                               functionOffset));
310   }
secondLevelPagesSectionOffset(uint32_t index) const311   uint32_t secondLevelPagesSectionOffset(uint32_t index) const {
312     return _addressSpace.get32(
313         _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
314                               secondLevelPagesSectionOffset));
315   }
lsdaIndexArraySectionOffset(uint32_t index) const316   uint32_t lsdaIndexArraySectionOffset(uint32_t index) const {
317     return _addressSpace.get32(
318         _addr + arrayoffsetof(unwind_info_section_header_index_entry, index,
319                               lsdaIndexArraySectionOffset));
320   }
321 
322 private:
323   A                   &_addressSpace;
324   typename A::pint_t   _addr;
325 };
326 
327 template <typename A> class UnwindSectionRegularPageHeader {
328 public:
UnwindSectionRegularPageHeader(A & addressSpace,typename A::pint_t addr)329   UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr)
330       : _addressSpace(addressSpace), _addr(addr) {}
331 
kind() const332   uint32_t kind() const {
333     return _addressSpace.get32(
334         _addr + offsetof(unwind_info_regular_second_level_page_header, kind));
335   }
entryPageOffset() const336   uint16_t entryPageOffset() const {
337     return _addressSpace.get16(
338         _addr + offsetof(unwind_info_regular_second_level_page_header,
339                          entryPageOffset));
340   }
entryCount() const341   uint16_t entryCount() const {
342     return _addressSpace.get16(
343         _addr +
344         offsetof(unwind_info_regular_second_level_page_header, entryCount));
345   }
346 
347 private:
348   A &_addressSpace;
349   typename A::pint_t _addr;
350 };
351 
352 template <typename A> class UnwindSectionRegularArray {
353 public:
UnwindSectionRegularArray(A & addressSpace,typename A::pint_t addr)354   UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr)
355       : _addressSpace(addressSpace), _addr(addr) {}
356 
functionOffset(uint32_t index) const357   uint32_t functionOffset(uint32_t index) const {
358     return _addressSpace.get32(
359         _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index,
360                               functionOffset));
361   }
encoding(uint32_t index) const362   uint32_t encoding(uint32_t index) const {
363     return _addressSpace.get32(
364         _addr +
365         arrayoffsetof(unwind_info_regular_second_level_entry, index, encoding));
366   }
367 
368 private:
369   A &_addressSpace;
370   typename A::pint_t _addr;
371 };
372 
373 template <typename A> class UnwindSectionCompressedPageHeader {
374 public:
UnwindSectionCompressedPageHeader(A & addressSpace,typename A::pint_t addr)375   UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr)
376       : _addressSpace(addressSpace), _addr(addr) {}
377 
kind() const378   uint32_t kind() const {
379     return _addressSpace.get32(
380         _addr +
381         offsetof(unwind_info_compressed_second_level_page_header, kind));
382   }
entryPageOffset() const383   uint16_t entryPageOffset() const {
384     return _addressSpace.get16(
385         _addr + offsetof(unwind_info_compressed_second_level_page_header,
386                          entryPageOffset));
387   }
entryCount() const388   uint16_t entryCount() const {
389     return _addressSpace.get16(
390         _addr +
391         offsetof(unwind_info_compressed_second_level_page_header, entryCount));
392   }
encodingsPageOffset() const393   uint16_t encodingsPageOffset() const {
394     return _addressSpace.get16(
395         _addr + offsetof(unwind_info_compressed_second_level_page_header,
396                          encodingsPageOffset));
397   }
encodingsCount() const398   uint16_t encodingsCount() const {
399     return _addressSpace.get16(
400         _addr + offsetof(unwind_info_compressed_second_level_page_header,
401                          encodingsCount));
402   }
403 
404 private:
405   A &_addressSpace;
406   typename A::pint_t _addr;
407 };
408 
409 template <typename A> class UnwindSectionCompressedArray {
410 public:
UnwindSectionCompressedArray(A & addressSpace,typename A::pint_t addr)411   UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr)
412       : _addressSpace(addressSpace), _addr(addr) {}
413 
functionOffset(uint32_t index) const414   uint32_t functionOffset(uint32_t index) const {
415     return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET(
416         _addressSpace.get32(_addr + index * sizeof(uint32_t)));
417   }
encodingIndex(uint32_t index) const418   uint16_t encodingIndex(uint32_t index) const {
419     return UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX(
420         _addressSpace.get32(_addr + index * sizeof(uint32_t)));
421   }
422 
423 private:
424   A &_addressSpace;
425   typename A::pint_t _addr;
426 };
427 
428 template <typename A> class UnwindSectionLsdaArray {
429 public:
UnwindSectionLsdaArray(A & addressSpace,typename A::pint_t addr)430   UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr)
431       : _addressSpace(addressSpace), _addr(addr) {}
432 
functionOffset(uint32_t index) const433   uint32_t functionOffset(uint32_t index) const {
434     return _addressSpace.get32(
435         _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
436                               index, functionOffset));
437   }
lsdaOffset(uint32_t index) const438   uint32_t lsdaOffset(uint32_t index) const {
439     return _addressSpace.get32(
440         _addr + arrayoffsetof(unwind_info_section_header_lsda_index_entry,
441                               index, lsdaOffset));
442   }
443 
444 private:
445   A                   &_addressSpace;
446   typename A::pint_t   _addr;
447 };
448 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
449 
450 class _LIBUNWIND_HIDDEN AbstractUnwindCursor {
451 public:
452   // NOTE: provide a class specific placement deallocation function (S5.3.4 p20)
453   // This avoids an unnecessary dependency to libc++abi.
operator delete(void *,size_t)454   void operator delete(void *, size_t) {}
455 
~AbstractUnwindCursor()456   virtual ~AbstractUnwindCursor() {}
validReg(int)457   virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); }
getReg(int)458   virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); }
setReg(int,unw_word_t)459   virtual void setReg(int, unw_word_t) {
460     _LIBUNWIND_ABORT("setReg not implemented");
461   }
validFloatReg(int)462   virtual bool validFloatReg(int) {
463     _LIBUNWIND_ABORT("validFloatReg not implemented");
464   }
getFloatReg(int)465   virtual unw_fpreg_t getFloatReg(int) {
466     _LIBUNWIND_ABORT("getFloatReg not implemented");
467   }
setFloatReg(int,unw_fpreg_t)468   virtual void setFloatReg(int, unw_fpreg_t) {
469     _LIBUNWIND_ABORT("setFloatReg not implemented");
470   }
step(bool=false)471   virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); }
getInfo(unw_proc_info_t *)472   virtual void getInfo(unw_proc_info_t *) {
473     _LIBUNWIND_ABORT("getInfo not implemented");
474   }
jumpto()475   virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); }
isSignalFrame()476   virtual bool isSignalFrame() {
477     _LIBUNWIND_ABORT("isSignalFrame not implemented");
478   }
getFunctionName(char *,size_t,unw_word_t *)479   virtual bool getFunctionName(char *, size_t, unw_word_t *) {
480     _LIBUNWIND_ABORT("getFunctionName not implemented");
481   }
setInfoBasedOnIPRegister(bool=false)482   virtual void setInfoBasedOnIPRegister(bool = false) {
483     _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented");
484   }
getRegisterName(int)485   virtual const char *getRegisterName(int) {
486     _LIBUNWIND_ABORT("getRegisterName not implemented");
487   }
488 #ifdef __arm__
saveVFPAsX()489   virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); }
490 #endif
491 
492 #ifdef _AIX
getDataRelBase()493   virtual uintptr_t getDataRelBase() {
494     _LIBUNWIND_ABORT("getDataRelBase not implemented");
495   }
496 #endif
497 
498 #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
get_registers()499   virtual void *get_registers() {
500     _LIBUNWIND_ABORT("get_registers not implemented");
501   }
502 #endif
503 };
504 
505 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
506 
507 /// \c UnwindCursor contains all state (including all register values) during
508 /// an unwind.  This is normally stack-allocated inside a unw_cursor_t.
509 template <typename A, typename R>
510 class UnwindCursor : public AbstractUnwindCursor {
511   typedef typename A::pint_t pint_t;
512 public:
513                       UnwindCursor(unw_context_t *context, A &as);
514                       UnwindCursor(CONTEXT *context, A &as);
515                       UnwindCursor(A &as, void *threadArg);
~UnwindCursor()516   virtual             ~UnwindCursor() {}
517   virtual bool        validReg(int);
518   virtual unw_word_t  getReg(int);
519   virtual void        setReg(int, unw_word_t);
520   virtual bool        validFloatReg(int);
521   virtual unw_fpreg_t getFloatReg(int);
522   virtual void        setFloatReg(int, unw_fpreg_t);
523   virtual int         step(bool = false);
524   virtual void        getInfo(unw_proc_info_t *);
525   virtual void        jumpto();
526   virtual bool        isSignalFrame();
527   virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
528   virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
529   virtual const char *getRegisterName(int num);
530 #ifdef __arm__
531   virtual void        saveVFPAsX();
532 #endif
533 
getDispatcherContext()534   DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; }
setDispatcherContext(DISPATCHER_CONTEXT * disp)535   void setDispatcherContext(DISPATCHER_CONTEXT *disp) {
536     _dispContext = *disp;
537     _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
538     if (_dispContext.LanguageHandler) {
539       _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
540     } else
541       _info.handler = 0;
542   }
543 
544   // libunwind does not and should not depend on C++ library which means that we
545   // need our own definition of inline placement new.
operator new(size_t,UnwindCursor<A,R> * p)546   static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
547 
548 private:
549 
getLastPC() const550   pint_t getLastPC() const { return _dispContext.ControlPc; }
setLastPC(pint_t pc)551   void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; }
lookUpSEHUnwindInfo(pint_t pc,pint_t * base)552   RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
553 #ifdef __arm__
554     // Remove the thumb bit; FunctionEntry ranges don't include the thumb bit.
555     pc &= ~1U;
556 #endif
557     // If pc points exactly at the end of the range, we might resolve the
558     // next function instead. Decrement pc by 1 to fit inside the current
559     // function.
560     pc -= 1;
561     _dispContext.FunctionEntry = RtlLookupFunctionEntry(pc,
562                                                         &_dispContext.ImageBase,
563                                                         _dispContext.HistoryTable);
564     *base = _dispContext.ImageBase;
565     return _dispContext.FunctionEntry;
566   }
567   bool getInfoFromSEH(pint_t pc);
stepWithSEHData()568   int stepWithSEHData() {
569     _dispContext.LanguageHandler = RtlVirtualUnwind(UNW_FLAG_UHANDLER,
570                                                     _dispContext.ImageBase,
571                                                     _dispContext.ControlPc,
572                                                     _dispContext.FunctionEntry,
573                                                     _dispContext.ContextRecord,
574                                                     &_dispContext.HandlerData,
575                                                     &_dispContext.EstablisherFrame,
576                                                     NULL);
577     // Update some fields of the unwind info now, since we have them.
578     _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
579     if (_dispContext.LanguageHandler) {
580       _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
581     } else
582       _info.handler = 0;
583     return UNW_STEP_SUCCESS;
584   }
585 
586   A                   &_addressSpace;
587   unw_proc_info_t      _info;
588   DISPATCHER_CONTEXT   _dispContext;
589   CONTEXT              _msContext;
590   UNWIND_HISTORY_TABLE _histTable;
591   bool                 _unwindInfoMissing;
592 };
593 
594 
595 template <typename A, typename R>
UnwindCursor(unw_context_t * context,A & as)596 UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
597     : _addressSpace(as), _unwindInfoMissing(false) {
598   static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
599                 "UnwindCursor<> does not fit in unw_cursor_t");
600   static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
601                 "UnwindCursor<> requires more alignment than unw_cursor_t");
602   memset(&_info, 0, sizeof(_info));
603   memset(&_histTable, 0, sizeof(_histTable));
604   memset(&_dispContext, 0, sizeof(_dispContext));
605   _dispContext.ContextRecord = &_msContext;
606   _dispContext.HistoryTable = &_histTable;
607   // Initialize MS context from ours.
608   R r(context);
609   RtlCaptureContext(&_msContext);
610   _msContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_FLOATING_POINT;
611 #if defined(_LIBUNWIND_TARGET_X86_64)
612   _msContext.Rax = r.getRegister(UNW_X86_64_RAX);
613   _msContext.Rcx = r.getRegister(UNW_X86_64_RCX);
614   _msContext.Rdx = r.getRegister(UNW_X86_64_RDX);
615   _msContext.Rbx = r.getRegister(UNW_X86_64_RBX);
616   _msContext.Rsp = r.getRegister(UNW_X86_64_RSP);
617   _msContext.Rbp = r.getRegister(UNW_X86_64_RBP);
618   _msContext.Rsi = r.getRegister(UNW_X86_64_RSI);
619   _msContext.Rdi = r.getRegister(UNW_X86_64_RDI);
620   _msContext.R8 = r.getRegister(UNW_X86_64_R8);
621   _msContext.R9 = r.getRegister(UNW_X86_64_R9);
622   _msContext.R10 = r.getRegister(UNW_X86_64_R10);
623   _msContext.R11 = r.getRegister(UNW_X86_64_R11);
624   _msContext.R12 = r.getRegister(UNW_X86_64_R12);
625   _msContext.R13 = r.getRegister(UNW_X86_64_R13);
626   _msContext.R14 = r.getRegister(UNW_X86_64_R14);
627   _msContext.R15 = r.getRegister(UNW_X86_64_R15);
628   _msContext.Rip = r.getRegister(UNW_REG_IP);
629   union {
630     v128 v;
631     M128A m;
632   } t;
633   t.v = r.getVectorRegister(UNW_X86_64_XMM0);
634   _msContext.Xmm0 = t.m;
635   t.v = r.getVectorRegister(UNW_X86_64_XMM1);
636   _msContext.Xmm1 = t.m;
637   t.v = r.getVectorRegister(UNW_X86_64_XMM2);
638   _msContext.Xmm2 = t.m;
639   t.v = r.getVectorRegister(UNW_X86_64_XMM3);
640   _msContext.Xmm3 = t.m;
641   t.v = r.getVectorRegister(UNW_X86_64_XMM4);
642   _msContext.Xmm4 = t.m;
643   t.v = r.getVectorRegister(UNW_X86_64_XMM5);
644   _msContext.Xmm5 = t.m;
645   t.v = r.getVectorRegister(UNW_X86_64_XMM6);
646   _msContext.Xmm6 = t.m;
647   t.v = r.getVectorRegister(UNW_X86_64_XMM7);
648   _msContext.Xmm7 = t.m;
649   t.v = r.getVectorRegister(UNW_X86_64_XMM8);
650   _msContext.Xmm8 = t.m;
651   t.v = r.getVectorRegister(UNW_X86_64_XMM9);
652   _msContext.Xmm9 = t.m;
653   t.v = r.getVectorRegister(UNW_X86_64_XMM10);
654   _msContext.Xmm10 = t.m;
655   t.v = r.getVectorRegister(UNW_X86_64_XMM11);
656   _msContext.Xmm11 = t.m;
657   t.v = r.getVectorRegister(UNW_X86_64_XMM12);
658   _msContext.Xmm12 = t.m;
659   t.v = r.getVectorRegister(UNW_X86_64_XMM13);
660   _msContext.Xmm13 = t.m;
661   t.v = r.getVectorRegister(UNW_X86_64_XMM14);
662   _msContext.Xmm14 = t.m;
663   t.v = r.getVectorRegister(UNW_X86_64_XMM15);
664   _msContext.Xmm15 = t.m;
665 #elif defined(_LIBUNWIND_TARGET_ARM)
666   _msContext.R0 = r.getRegister(UNW_ARM_R0);
667   _msContext.R1 = r.getRegister(UNW_ARM_R1);
668   _msContext.R2 = r.getRegister(UNW_ARM_R2);
669   _msContext.R3 = r.getRegister(UNW_ARM_R3);
670   _msContext.R4 = r.getRegister(UNW_ARM_R4);
671   _msContext.R5 = r.getRegister(UNW_ARM_R5);
672   _msContext.R6 = r.getRegister(UNW_ARM_R6);
673   _msContext.R7 = r.getRegister(UNW_ARM_R7);
674   _msContext.R8 = r.getRegister(UNW_ARM_R8);
675   _msContext.R9 = r.getRegister(UNW_ARM_R9);
676   _msContext.R10 = r.getRegister(UNW_ARM_R10);
677   _msContext.R11 = r.getRegister(UNW_ARM_R11);
678   _msContext.R12 = r.getRegister(UNW_ARM_R12);
679   _msContext.Sp = r.getRegister(UNW_ARM_SP);
680   _msContext.Lr = r.getRegister(UNW_ARM_LR);
681   _msContext.Pc = r.getRegister(UNW_ARM_IP);
682   for (int i = UNW_ARM_D0; i <= UNW_ARM_D31; ++i) {
683     union {
684       uint64_t w;
685       double d;
686     } d;
687     d.d = r.getFloatRegister(i);
688     _msContext.D[i - UNW_ARM_D0] = d.w;
689   }
690 #elif defined(_LIBUNWIND_TARGET_AARCH64)
691   for (int i = UNW_AARCH64_X0; i <= UNW_ARM64_X30; ++i)
692     _msContext.X[i - UNW_AARCH64_X0] = r.getRegister(i);
693   _msContext.Sp = r.getRegister(UNW_REG_SP);
694   _msContext.Pc = r.getRegister(UNW_REG_IP);
695   for (int i = UNW_AARCH64_V0; i <= UNW_ARM64_D31; ++i)
696     _msContext.V[i - UNW_AARCH64_V0].D[0] = r.getFloatRegister(i);
697 #endif
698 }
699 
700 template <typename A, typename R>
UnwindCursor(CONTEXT * context,A & as)701 UnwindCursor<A, R>::UnwindCursor(CONTEXT *context, A &as)
702     : _addressSpace(as), _unwindInfoMissing(false) {
703   static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
704                 "UnwindCursor<> does not fit in unw_cursor_t");
705   memset(&_info, 0, sizeof(_info));
706   memset(&_histTable, 0, sizeof(_histTable));
707   memset(&_dispContext, 0, sizeof(_dispContext));
708   _dispContext.ContextRecord = &_msContext;
709   _dispContext.HistoryTable = &_histTable;
710   _msContext = *context;
711 }
712 
713 
714 template <typename A, typename R>
validReg(int regNum)715 bool UnwindCursor<A, R>::validReg(int regNum) {
716   if (regNum == UNW_REG_IP || regNum == UNW_REG_SP) return true;
717 #if defined(_LIBUNWIND_TARGET_X86_64)
718   if (regNum >= UNW_X86_64_RAX && regNum <= UNW_X86_64_RIP) return true;
719 #elif defined(_LIBUNWIND_TARGET_ARM)
720   if ((regNum >= UNW_ARM_R0 && regNum <= UNW_ARM_R15) ||
721       regNum == UNW_ARM_RA_AUTH_CODE)
722     return true;
723 #elif defined(_LIBUNWIND_TARGET_AARCH64)
724   if (regNum >= UNW_AARCH64_X0 && regNum <= UNW_ARM64_X30) return true;
725 #endif
726   return false;
727 }
728 
729 template <typename A, typename R>
getReg(int regNum)730 unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
731   switch (regNum) {
732 #if defined(_LIBUNWIND_TARGET_X86_64)
733   case UNW_X86_64_RIP:
734   case UNW_REG_IP: return _msContext.Rip;
735   case UNW_X86_64_RAX: return _msContext.Rax;
736   case UNW_X86_64_RDX: return _msContext.Rdx;
737   case UNW_X86_64_RCX: return _msContext.Rcx;
738   case UNW_X86_64_RBX: return _msContext.Rbx;
739   case UNW_REG_SP:
740   case UNW_X86_64_RSP: return _msContext.Rsp;
741   case UNW_X86_64_RBP: return _msContext.Rbp;
742   case UNW_X86_64_RSI: return _msContext.Rsi;
743   case UNW_X86_64_RDI: return _msContext.Rdi;
744   case UNW_X86_64_R8: return _msContext.R8;
745   case UNW_X86_64_R9: return _msContext.R9;
746   case UNW_X86_64_R10: return _msContext.R10;
747   case UNW_X86_64_R11: return _msContext.R11;
748   case UNW_X86_64_R12: return _msContext.R12;
749   case UNW_X86_64_R13: return _msContext.R13;
750   case UNW_X86_64_R14: return _msContext.R14;
751   case UNW_X86_64_R15: return _msContext.R15;
752 #elif defined(_LIBUNWIND_TARGET_ARM)
753   case UNW_ARM_R0: return _msContext.R0;
754   case UNW_ARM_R1: return _msContext.R1;
755   case UNW_ARM_R2: return _msContext.R2;
756   case UNW_ARM_R3: return _msContext.R3;
757   case UNW_ARM_R4: return _msContext.R4;
758   case UNW_ARM_R5: return _msContext.R5;
759   case UNW_ARM_R6: return _msContext.R6;
760   case UNW_ARM_R7: return _msContext.R7;
761   case UNW_ARM_R8: return _msContext.R8;
762   case UNW_ARM_R9: return _msContext.R9;
763   case UNW_ARM_R10: return _msContext.R10;
764   case UNW_ARM_R11: return _msContext.R11;
765   case UNW_ARM_R12: return _msContext.R12;
766   case UNW_REG_SP:
767   case UNW_ARM_SP: return _msContext.Sp;
768   case UNW_ARM_LR: return _msContext.Lr;
769   case UNW_REG_IP:
770   case UNW_ARM_IP: return _msContext.Pc;
771 #elif defined(_LIBUNWIND_TARGET_AARCH64)
772   case UNW_REG_SP: return _msContext.Sp;
773   case UNW_REG_IP: return _msContext.Pc;
774   default: return _msContext.X[regNum - UNW_AARCH64_X0];
775 #endif
776   }
777   _LIBUNWIND_ABORT("unsupported register");
778 }
779 
780 template <typename A, typename R>
setReg(int regNum,unw_word_t value)781 void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
782   switch (regNum) {
783 #if defined(_LIBUNWIND_TARGET_X86_64)
784   case UNW_X86_64_RIP:
785   case UNW_REG_IP: _msContext.Rip = value; break;
786   case UNW_X86_64_RAX: _msContext.Rax = value; break;
787   case UNW_X86_64_RDX: _msContext.Rdx = value; break;
788   case UNW_X86_64_RCX: _msContext.Rcx = value; break;
789   case UNW_X86_64_RBX: _msContext.Rbx = value; break;
790   case UNW_REG_SP:
791   case UNW_X86_64_RSP: _msContext.Rsp = value; break;
792   case UNW_X86_64_RBP: _msContext.Rbp = value; break;
793   case UNW_X86_64_RSI: _msContext.Rsi = value; break;
794   case UNW_X86_64_RDI: _msContext.Rdi = value; break;
795   case UNW_X86_64_R8: _msContext.R8 = value; break;
796   case UNW_X86_64_R9: _msContext.R9 = value; break;
797   case UNW_X86_64_R10: _msContext.R10 = value; break;
798   case UNW_X86_64_R11: _msContext.R11 = value; break;
799   case UNW_X86_64_R12: _msContext.R12 = value; break;
800   case UNW_X86_64_R13: _msContext.R13 = value; break;
801   case UNW_X86_64_R14: _msContext.R14 = value; break;
802   case UNW_X86_64_R15: _msContext.R15 = value; break;
803 #elif defined(_LIBUNWIND_TARGET_ARM)
804   case UNW_ARM_R0: _msContext.R0 = value; break;
805   case UNW_ARM_R1: _msContext.R1 = value; break;
806   case UNW_ARM_R2: _msContext.R2 = value; break;
807   case UNW_ARM_R3: _msContext.R3 = value; break;
808   case UNW_ARM_R4: _msContext.R4 = value; break;
809   case UNW_ARM_R5: _msContext.R5 = value; break;
810   case UNW_ARM_R6: _msContext.R6 = value; break;
811   case UNW_ARM_R7: _msContext.R7 = value; break;
812   case UNW_ARM_R8: _msContext.R8 = value; break;
813   case UNW_ARM_R9: _msContext.R9 = value; break;
814   case UNW_ARM_R10: _msContext.R10 = value; break;
815   case UNW_ARM_R11: _msContext.R11 = value; break;
816   case UNW_ARM_R12: _msContext.R12 = value; break;
817   case UNW_REG_SP:
818   case UNW_ARM_SP: _msContext.Sp = value; break;
819   case UNW_ARM_LR: _msContext.Lr = value; break;
820   case UNW_REG_IP:
821   case UNW_ARM_IP: _msContext.Pc = value; break;
822 #elif defined(_LIBUNWIND_TARGET_AARCH64)
823   case UNW_REG_SP: _msContext.Sp = value; break;
824   case UNW_REG_IP: _msContext.Pc = value; break;
825   case UNW_AARCH64_X0:
826   case UNW_AARCH64_X1:
827   case UNW_AARCH64_X2:
828   case UNW_AARCH64_X3:
829   case UNW_AARCH64_X4:
830   case UNW_AARCH64_X5:
831   case UNW_AARCH64_X6:
832   case UNW_AARCH64_X7:
833   case UNW_AARCH64_X8:
834   case UNW_AARCH64_X9:
835   case UNW_AARCH64_X10:
836   case UNW_AARCH64_X11:
837   case UNW_AARCH64_X12:
838   case UNW_AARCH64_X13:
839   case UNW_AARCH64_X14:
840   case UNW_AARCH64_X15:
841   case UNW_AARCH64_X16:
842   case UNW_AARCH64_X17:
843   case UNW_AARCH64_X18:
844   case UNW_AARCH64_X19:
845   case UNW_AARCH64_X20:
846   case UNW_AARCH64_X21:
847   case UNW_AARCH64_X22:
848   case UNW_AARCH64_X23:
849   case UNW_AARCH64_X24:
850   case UNW_AARCH64_X25:
851   case UNW_AARCH64_X26:
852   case UNW_AARCH64_X27:
853   case UNW_AARCH64_X28:
854   case UNW_AARCH64_FP:
855   case UNW_AARCH64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break;
856 #endif
857   default:
858     _LIBUNWIND_ABORT("unsupported register");
859   }
860 }
861 
862 template <typename A, typename R>
validFloatReg(int regNum)863 bool UnwindCursor<A, R>::validFloatReg(int regNum) {
864 #if defined(_LIBUNWIND_TARGET_ARM)
865   if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) return true;
866   if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) return true;
867 #elif defined(_LIBUNWIND_TARGET_AARCH64)
868   if (regNum >= UNW_AARCH64_V0 && regNum <= UNW_ARM64_D31) return true;
869 #else
870   (void)regNum;
871 #endif
872   return false;
873 }
874 
875 template <typename A, typename R>
getFloatReg(int regNum)876 unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
877 #if defined(_LIBUNWIND_TARGET_ARM)
878   if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
879     union {
880       uint32_t w;
881       float f;
882     } d;
883     d.w = _msContext.S[regNum - UNW_ARM_S0];
884     return d.f;
885   }
886   if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
887     union {
888       uint64_t w;
889       double d;
890     } d;
891     d.w = _msContext.D[regNum - UNW_ARM_D0];
892     return d.d;
893   }
894   _LIBUNWIND_ABORT("unsupported float register");
895 #elif defined(_LIBUNWIND_TARGET_AARCH64)
896   return _msContext.V[regNum - UNW_AARCH64_V0].D[0];
897 #else
898   (void)regNum;
899   _LIBUNWIND_ABORT("float registers unimplemented");
900 #endif
901 }
902 
903 template <typename A, typename R>
setFloatReg(int regNum,unw_fpreg_t value)904 void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
905 #if defined(_LIBUNWIND_TARGET_ARM)
906   if (regNum >= UNW_ARM_S0 && regNum <= UNW_ARM_S31) {
907     union {
908       uint32_t w;
909       float f;
910     } d;
911     d.f = (float)value;
912     _msContext.S[regNum - UNW_ARM_S0] = d.w;
913   }
914   if (regNum >= UNW_ARM_D0 && regNum <= UNW_ARM_D31) {
915     union {
916       uint64_t w;
917       double d;
918     } d;
919     d.d = value;
920     _msContext.D[regNum - UNW_ARM_D0] = d.w;
921   }
922   _LIBUNWIND_ABORT("unsupported float register");
923 #elif defined(_LIBUNWIND_TARGET_AARCH64)
924   _msContext.V[regNum - UNW_AARCH64_V0].D[0] = value;
925 #else
926   (void)regNum;
927   (void)value;
928   _LIBUNWIND_ABORT("float registers unimplemented");
929 #endif
930 }
931 
jumpto()932 template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
933   RtlRestoreContext(&_msContext, nullptr);
934 }
935 
936 #ifdef __arm__
saveVFPAsX()937 template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {}
938 #endif
939 
940 template <typename A, typename R>
getRegisterName(int regNum)941 const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
942   return R::getRegisterName(regNum);
943 }
944 
isSignalFrame()945 template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
946   return false;
947 }
948 
949 #else  // !defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) || !defined(_WIN32)
950 
951 /// UnwindCursor contains all state (including all register values) during
952 /// an unwind.  This is normally stack allocated inside a unw_cursor_t.
953 template <typename A, typename R>
954 class UnwindCursor : public AbstractUnwindCursor{
955   typedef typename A::pint_t pint_t;
956 public:
957                       UnwindCursor(unw_context_t *context, A &as);
958                       UnwindCursor(A &as, void *threadArg);
~UnwindCursor()959   virtual             ~UnwindCursor() {}
960   virtual bool        validReg(int);
961   virtual unw_word_t  getReg(int);
962   virtual void        setReg(int, unw_word_t);
963   virtual bool        validFloatReg(int);
964   virtual unw_fpreg_t getFloatReg(int);
965   virtual void        setFloatReg(int, unw_fpreg_t);
966   virtual int         step(bool stage2 = false);
967   virtual void        getInfo(unw_proc_info_t *);
968   virtual void        jumpto();
969   virtual bool        isSignalFrame();
970   virtual bool        getFunctionName(char *buf, size_t len, unw_word_t *off);
971   virtual void        setInfoBasedOnIPRegister(bool isReturnAddress = false);
972   virtual const char *getRegisterName(int num);
973 #ifdef __arm__
974   virtual void        saveVFPAsX();
975 #endif
976 
977 #ifdef _AIX
978   virtual uintptr_t getDataRelBase();
979 #endif
980 
981 #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
get_registers()982   virtual void *get_registers() { return &_registers; }
983 #endif
984 
985   // libunwind does not and should not depend on C++ library which means that we
986   // need our own definition of inline placement new.
operator new(size_t,UnwindCursor<A,R> * p)987   static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; }
988 
989 private:
990 
991 #if defined(_LIBUNWIND_ARM_EHABI)
992   bool getInfoFromEHABISection(pint_t pc, const UnwindInfoSections &sects);
993 
stepWithEHABI()994   int stepWithEHABI() {
995     size_t len = 0;
996     size_t off = 0;
997     // FIXME: Calling decode_eht_entry() here is violating the libunwind
998     // abstraction layer.
999     const uint32_t *ehtp =
1000         decode_eht_entry(reinterpret_cast<const uint32_t *>(_info.unwind_info),
1001                          &off, &len);
1002     if (_Unwind_VRS_Interpret((_Unwind_Context *)this, ehtp, off, len) !=
1003             _URC_CONTINUE_UNWIND)
1004       return UNW_STEP_END;
1005     return UNW_STEP_SUCCESS;
1006   }
1007 #endif
1008 
1009 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
setInfoForSigReturn()1010   bool setInfoForSigReturn() {
1011     R dummy;
1012     return setInfoForSigReturn(dummy);
1013   }
stepThroughSigReturn()1014   int stepThroughSigReturn() {
1015     R dummy;
1016     return stepThroughSigReturn(dummy);
1017   }
1018   bool isReadableAddr(const pint_t addr) const;
1019 #if defined(_LIBUNWIND_TARGET_AARCH64)
1020   bool setInfoForSigReturn(Registers_arm64 &);
1021   int stepThroughSigReturn(Registers_arm64 &);
1022 #endif
1023 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
1024   bool setInfoForSigReturn(Registers_loongarch &);
1025   int stepThroughSigReturn(Registers_loongarch &);
1026 #endif
1027 #if defined(_LIBUNWIND_TARGET_RISCV)
1028   bool setInfoForSigReturn(Registers_riscv &);
1029   int stepThroughSigReturn(Registers_riscv &);
1030 #endif
1031 #if defined(_LIBUNWIND_TARGET_S390X)
1032   bool setInfoForSigReturn(Registers_s390x &);
1033   int stepThroughSigReturn(Registers_s390x &);
1034 #endif
setInfoForSigReturn(Registers &)1035   template <typename Registers> bool setInfoForSigReturn(Registers &) {
1036     return false;
1037   }
stepThroughSigReturn(Registers &)1038   template <typename Registers> int stepThroughSigReturn(Registers &) {
1039     return UNW_STEP_END;
1040   }
1041 #elif defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
1042   bool setInfoForSigReturn();
1043   int stepThroughSigReturn();
1044 #endif
1045 
1046 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1047   bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo,
1048                          const typename CFI_Parser<A>::CIE_Info &cieInfo,
1049                          pint_t pc, uintptr_t dso_base);
1050   bool getInfoFromDwarfSection(pint_t pc, const UnwindInfoSections &sects,
1051                                             uint32_t fdeSectionOffsetHint=0);
stepWithDwarfFDE(bool stage2)1052   int stepWithDwarfFDE(bool stage2) {
1053     return DwarfInstructions<A, R>::stepWithDwarf(
1054         _addressSpace, (pint_t)this->getReg(UNW_REG_IP),
1055         (pint_t)_info.unwind_info, _registers, _isSignalFrame, stage2);
1056   }
1057 #endif
1058 
1059 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1060   bool getInfoFromCompactEncodingSection(pint_t pc,
1061                                             const UnwindInfoSections &sects);
stepWithCompactEncoding(bool stage2=false)1062   int stepWithCompactEncoding(bool stage2 = false) {
1063 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1064     if ( compactSaysUseDwarf() )
1065       return stepWithDwarfFDE(stage2);
1066 #endif
1067     R dummy;
1068     return stepWithCompactEncoding(dummy);
1069   }
1070 
1071 #if defined(_LIBUNWIND_TARGET_X86_64)
stepWithCompactEncoding(Registers_x86_64 &)1072   int stepWithCompactEncoding(Registers_x86_64 &) {
1073     return CompactUnwinder_x86_64<A>::stepWithCompactEncoding(
1074         _info.format, _info.start_ip, _addressSpace, _registers);
1075   }
1076 #endif
1077 
1078 #if defined(_LIBUNWIND_TARGET_I386)
stepWithCompactEncoding(Registers_x86 &)1079   int stepWithCompactEncoding(Registers_x86 &) {
1080     return CompactUnwinder_x86<A>::stepWithCompactEncoding(
1081         _info.format, (uint32_t)_info.start_ip, _addressSpace, _registers);
1082   }
1083 #endif
1084 
1085 #if defined(_LIBUNWIND_TARGET_PPC)
stepWithCompactEncoding(Registers_ppc &)1086   int stepWithCompactEncoding(Registers_ppc &) {
1087     return UNW_EINVAL;
1088   }
1089 #endif
1090 
1091 #if defined(_LIBUNWIND_TARGET_PPC64)
stepWithCompactEncoding(Registers_ppc64 &)1092   int stepWithCompactEncoding(Registers_ppc64 &) {
1093     return UNW_EINVAL;
1094   }
1095 #endif
1096 
1097 
1098 #if defined(_LIBUNWIND_TARGET_AARCH64)
stepWithCompactEncoding(Registers_arm64 &)1099   int stepWithCompactEncoding(Registers_arm64 &) {
1100     return CompactUnwinder_arm64<A>::stepWithCompactEncoding(
1101         _info.format, _info.start_ip, _addressSpace, _registers);
1102   }
1103 #endif
1104 
1105 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
stepWithCompactEncoding(Registers_mips_o32 &)1106   int stepWithCompactEncoding(Registers_mips_o32 &) {
1107     return UNW_EINVAL;
1108   }
1109 #endif
1110 
1111 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
stepWithCompactEncoding(Registers_mips_newabi &)1112   int stepWithCompactEncoding(Registers_mips_newabi &) {
1113     return UNW_EINVAL;
1114   }
1115 #endif
1116 
1117 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
stepWithCompactEncoding(Registers_loongarch &)1118   int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; }
1119 #endif
1120 
1121 #if defined(_LIBUNWIND_TARGET_SPARC)
stepWithCompactEncoding(Registers_sparc &)1122   int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; }
1123 #endif
1124 
1125 #if defined(_LIBUNWIND_TARGET_SPARC64)
stepWithCompactEncoding(Registers_sparc64 &)1126   int stepWithCompactEncoding(Registers_sparc64 &) { return UNW_EINVAL; }
1127 #endif
1128 
1129 #if defined (_LIBUNWIND_TARGET_RISCV)
stepWithCompactEncoding(Registers_riscv &)1130   int stepWithCompactEncoding(Registers_riscv &) {
1131     return UNW_EINVAL;
1132   }
1133 #endif
1134 
compactSaysUseDwarf(uint32_t * offset=NULL) const1135   bool compactSaysUseDwarf(uint32_t *offset=NULL) const {
1136     R dummy;
1137     return compactSaysUseDwarf(dummy, offset);
1138   }
1139 
1140 #if defined(_LIBUNWIND_TARGET_X86_64)
compactSaysUseDwarf(Registers_x86_64 &,uint32_t * offset) const1141   bool compactSaysUseDwarf(Registers_x86_64 &, uint32_t *offset) const {
1142     if ((_info.format & UNWIND_X86_64_MODE_MASK) == UNWIND_X86_64_MODE_DWARF) {
1143       if (offset)
1144         *offset = (_info.format & UNWIND_X86_64_DWARF_SECTION_OFFSET);
1145       return true;
1146     }
1147     return false;
1148   }
1149 #endif
1150 
1151 #if defined(_LIBUNWIND_TARGET_I386)
compactSaysUseDwarf(Registers_x86 &,uint32_t * offset) const1152   bool compactSaysUseDwarf(Registers_x86 &, uint32_t *offset) const {
1153     if ((_info.format & UNWIND_X86_MODE_MASK) == UNWIND_X86_MODE_DWARF) {
1154       if (offset)
1155         *offset = (_info.format & UNWIND_X86_DWARF_SECTION_OFFSET);
1156       return true;
1157     }
1158     return false;
1159   }
1160 #endif
1161 
1162 #if defined(_LIBUNWIND_TARGET_PPC)
compactSaysUseDwarf(Registers_ppc &,uint32_t *) const1163   bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const {
1164     return true;
1165   }
1166 #endif
1167 
1168 #if defined(_LIBUNWIND_TARGET_PPC64)
compactSaysUseDwarf(Registers_ppc64 &,uint32_t *) const1169   bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const {
1170     return true;
1171   }
1172 #endif
1173 
1174 #if defined(_LIBUNWIND_TARGET_AARCH64)
compactSaysUseDwarf(Registers_arm64 &,uint32_t * offset) const1175   bool compactSaysUseDwarf(Registers_arm64 &, uint32_t *offset) const {
1176     if ((_info.format & UNWIND_ARM64_MODE_MASK) == UNWIND_ARM64_MODE_DWARF) {
1177       if (offset)
1178         *offset = (_info.format & UNWIND_ARM64_DWARF_SECTION_OFFSET);
1179       return true;
1180     }
1181     return false;
1182   }
1183 #endif
1184 
1185 #if defined(_LIBUNWIND_TARGET_MIPS_O32)
compactSaysUseDwarf(Registers_mips_o32 &,uint32_t *) const1186   bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const {
1187     return true;
1188   }
1189 #endif
1190 
1191 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI)
compactSaysUseDwarf(Registers_mips_newabi &,uint32_t *) const1192   bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const {
1193     return true;
1194   }
1195 #endif
1196 
1197 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
compactSaysUseDwarf(Registers_loongarch &,uint32_t *) const1198   bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const {
1199     return true;
1200   }
1201 #endif
1202 
1203 #if defined(_LIBUNWIND_TARGET_SPARC)
compactSaysUseDwarf(Registers_sparc &,uint32_t *) const1204   bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; }
1205 #endif
1206 
1207 #if defined(_LIBUNWIND_TARGET_SPARC64)
compactSaysUseDwarf(Registers_sparc64 &,uint32_t *) const1208   bool compactSaysUseDwarf(Registers_sparc64 &, uint32_t *) const {
1209     return true;
1210   }
1211 #endif
1212 
1213 #if defined (_LIBUNWIND_TARGET_RISCV)
compactSaysUseDwarf(Registers_riscv &,uint32_t *) const1214   bool compactSaysUseDwarf(Registers_riscv &, uint32_t *) const {
1215     return true;
1216   }
1217 #endif
1218 
1219 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1220 
1221 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
dwarfEncoding() const1222   compact_unwind_encoding_t dwarfEncoding() const {
1223     R dummy;
1224     return dwarfEncoding(dummy);
1225   }
1226 
1227 #if defined(_LIBUNWIND_TARGET_X86_64)
dwarfEncoding(Registers_x86_64 &) const1228   compact_unwind_encoding_t dwarfEncoding(Registers_x86_64 &) const {
1229     return UNWIND_X86_64_MODE_DWARF;
1230   }
1231 #endif
1232 
1233 #if defined(_LIBUNWIND_TARGET_I386)
dwarfEncoding(Registers_x86 &) const1234   compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const {
1235     return UNWIND_X86_MODE_DWARF;
1236   }
1237 #endif
1238 
1239 #if defined(_LIBUNWIND_TARGET_PPC)
dwarfEncoding(Registers_ppc &) const1240   compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const {
1241     return 0;
1242   }
1243 #endif
1244 
1245 #if defined(_LIBUNWIND_TARGET_PPC64)
dwarfEncoding(Registers_ppc64 &) const1246   compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const {
1247     return 0;
1248   }
1249 #endif
1250 
1251 #if defined(_LIBUNWIND_TARGET_AARCH64)
dwarfEncoding(Registers_arm64 &) const1252   compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const {
1253     return UNWIND_ARM64_MODE_DWARF;
1254   }
1255 #endif
1256 
1257 #if defined(_LIBUNWIND_TARGET_ARM)
dwarfEncoding(Registers_arm &) const1258   compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const {
1259     return 0;
1260   }
1261 #endif
1262 
1263 #if defined (_LIBUNWIND_TARGET_OR1K)
dwarfEncoding(Registers_or1k &) const1264   compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const {
1265     return 0;
1266   }
1267 #endif
1268 
1269 #if defined (_LIBUNWIND_TARGET_HEXAGON)
dwarfEncoding(Registers_hexagon &) const1270   compact_unwind_encoding_t dwarfEncoding(Registers_hexagon &) const {
1271     return 0;
1272   }
1273 #endif
1274 
1275 #if defined (_LIBUNWIND_TARGET_MIPS_O32)
dwarfEncoding(Registers_mips_o32 &) const1276   compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const {
1277     return 0;
1278   }
1279 #endif
1280 
1281 #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI)
dwarfEncoding(Registers_mips_newabi &) const1282   compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const {
1283     return 0;
1284   }
1285 #endif
1286 
1287 #if defined(_LIBUNWIND_TARGET_LOONGARCH)
dwarfEncoding(Registers_loongarch &) const1288   compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const {
1289     return 0;
1290   }
1291 #endif
1292 
1293 #if defined(_LIBUNWIND_TARGET_SPARC)
dwarfEncoding(Registers_sparc &) const1294   compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; }
1295 #endif
1296 
1297 #if defined(_LIBUNWIND_TARGET_SPARC64)
dwarfEncoding(Registers_sparc64 &) const1298   compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const {
1299     return 0;
1300   }
1301 #endif
1302 
1303 #if defined (_LIBUNWIND_TARGET_RISCV)
dwarfEncoding(Registers_riscv &) const1304   compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const {
1305     return 0;
1306   }
1307 #endif
1308 
1309 #if defined (_LIBUNWIND_TARGET_S390X)
dwarfEncoding(Registers_s390x &) const1310   compact_unwind_encoding_t dwarfEncoding(Registers_s390x &) const {
1311     return 0;
1312   }
1313 #endif
1314 
1315 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1316 
1317 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1318   // For runtime environments using SEH unwind data without Windows runtime
1319   // support.
getLastPC() const1320   pint_t getLastPC() const { /* FIXME: Implement */ return 0; }
setLastPC(pint_t pc)1321   void setLastPC(pint_t pc) { /* FIXME: Implement */ }
lookUpSEHUnwindInfo(pint_t pc,pint_t * base)1322   RUNTIME_FUNCTION *lookUpSEHUnwindInfo(pint_t pc, pint_t *base) {
1323     /* FIXME: Implement */
1324     *base = 0;
1325     return nullptr;
1326   }
1327   bool getInfoFromSEH(pint_t pc);
stepWithSEHData()1328   int stepWithSEHData() { /* FIXME: Implement */ return 0; }
1329 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1330 
1331 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1332   bool getInfoFromTBTable(pint_t pc, R &registers);
1333   int stepWithTBTable(pint_t pc, tbtable *TBTable, R &registers,
1334                       bool &isSignalFrame);
stepWithTBTableData()1335   int stepWithTBTableData() {
1336     return stepWithTBTable(reinterpret_cast<pint_t>(this->getReg(UNW_REG_IP)),
1337                            reinterpret_cast<tbtable *>(_info.unwind_info),
1338                            _registers, _isSignalFrame);
1339   }
1340 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
1341 
1342   A               &_addressSpace;
1343   R                _registers;
1344   unw_proc_info_t  _info;
1345   bool             _unwindInfoMissing;
1346   bool             _isSignalFrame;
1347 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) ||                               \
1348     defined(_LIBUNWIND_TARGET_HAIKU)
1349   bool             _isSigReturn = false;
1350 #endif
1351 };
1352 
1353 
1354 template <typename A, typename R>
UnwindCursor(unw_context_t * context,A & as)1355 UnwindCursor<A, R>::UnwindCursor(unw_context_t *context, A &as)
1356     : _addressSpace(as), _registers(context), _unwindInfoMissing(false),
1357       _isSignalFrame(false) {
1358   static_assert((check_fit<UnwindCursor<A, R>, unw_cursor_t>::does_fit),
1359                 "UnwindCursor<> does not fit in unw_cursor_t");
1360   static_assert((alignof(UnwindCursor<A, R>) <= alignof(unw_cursor_t)),
1361                 "UnwindCursor<> requires more alignment than unw_cursor_t");
1362   memset(&_info, 0, sizeof(_info));
1363 }
1364 
1365 template <typename A, typename R>
UnwindCursor(A & as,void *)1366 UnwindCursor<A, R>::UnwindCursor(A &as, void *)
1367     : _addressSpace(as), _unwindInfoMissing(false), _isSignalFrame(false) {
1368   memset(&_info, 0, sizeof(_info));
1369   // FIXME
1370   // fill in _registers from thread arg
1371 }
1372 
1373 
1374 template <typename A, typename R>
validReg(int regNum)1375 bool UnwindCursor<A, R>::validReg(int regNum) {
1376   return _registers.validRegister(regNum);
1377 }
1378 
1379 template <typename A, typename R>
getReg(int regNum)1380 unw_word_t UnwindCursor<A, R>::getReg(int regNum) {
1381   return _registers.getRegister(regNum);
1382 }
1383 
1384 template <typename A, typename R>
setReg(int regNum,unw_word_t value)1385 void UnwindCursor<A, R>::setReg(int regNum, unw_word_t value) {
1386   _registers.setRegister(regNum, (typename A::pint_t)value);
1387 }
1388 
1389 template <typename A, typename R>
validFloatReg(int regNum)1390 bool UnwindCursor<A, R>::validFloatReg(int regNum) {
1391   return _registers.validFloatRegister(regNum);
1392 }
1393 
1394 template <typename A, typename R>
getFloatReg(int regNum)1395 unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) {
1396   return _registers.getFloatRegister(regNum);
1397 }
1398 
1399 template <typename A, typename R>
setFloatReg(int regNum,unw_fpreg_t value)1400 void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) {
1401   _registers.setFloatRegister(regNum, value);
1402 }
1403 
jumpto()1404 template <typename A, typename R> void UnwindCursor<A, R>::jumpto() {
1405   _registers.jumpto();
1406 }
1407 
1408 #ifdef __arm__
saveVFPAsX()1409 template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {
1410   _registers.saveVFPAsX();
1411 }
1412 #endif
1413 
1414 #ifdef _AIX
1415 template <typename A, typename R>
getDataRelBase()1416 uintptr_t UnwindCursor<A, R>::getDataRelBase() {
1417   return reinterpret_cast<uintptr_t>(_info.extra);
1418 }
1419 #endif
1420 
1421 template <typename A, typename R>
getRegisterName(int regNum)1422 const char *UnwindCursor<A, R>::getRegisterName(int regNum) {
1423   return _registers.getRegisterName(regNum);
1424 }
1425 
isSignalFrame()1426 template <typename A, typename R> bool UnwindCursor<A, R>::isSignalFrame() {
1427   return _isSignalFrame;
1428 }
1429 
1430 #endif // defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
1431 
1432 #if defined(_LIBUNWIND_ARM_EHABI)
1433 template<typename A>
1434 struct EHABISectionIterator {
1435   typedef EHABISectionIterator _Self;
1436 
1437   typedef typename A::pint_t value_type;
1438   typedef typename A::pint_t* pointer;
1439   typedef typename A::pint_t& reference;
1440   typedef size_t size_type;
1441   typedef size_t difference_type;
1442 
beginlibunwind::EHABISectionIterator1443   static _Self begin(A& addressSpace, const UnwindInfoSections& sects) {
1444     return _Self(addressSpace, sects, 0);
1445   }
endlibunwind::EHABISectionIterator1446   static _Self end(A& addressSpace, const UnwindInfoSections& sects) {
1447     return _Self(addressSpace, sects,
1448                  sects.arm_section_length / sizeof(EHABIIndexEntry));
1449   }
1450 
EHABISectionIteratorlibunwind::EHABISectionIterator1451   EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i)
1452       : _i(i), _addressSpace(&addressSpace), _sects(&sects) {}
1453 
operator ++libunwind::EHABISectionIterator1454   _Self& operator++() { ++_i; return *this; }
operator +=libunwind::EHABISectionIterator1455   _Self& operator+=(size_t a) { _i += a; return *this; }
operator --libunwind::EHABISectionIterator1456   _Self& operator--() { assert(_i > 0); --_i; return *this; }
operator -=libunwind::EHABISectionIterator1457   _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; }
1458 
operator +libunwind::EHABISectionIterator1459   _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; }
operator -libunwind::EHABISectionIterator1460   _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; }
1461 
operator -libunwind::EHABISectionIterator1462   size_t operator-(const _Self& other) const { return _i - other._i; }
1463 
operator ==libunwind::EHABISectionIterator1464   bool operator==(const _Self& other) const {
1465     assert(_addressSpace == other._addressSpace);
1466     assert(_sects == other._sects);
1467     return _i == other._i;
1468   }
1469 
operator !=libunwind::EHABISectionIterator1470   bool operator!=(const _Self& other) const {
1471     assert(_addressSpace == other._addressSpace);
1472     assert(_sects == other._sects);
1473     return _i != other._i;
1474   }
1475 
operator *libunwind::EHABISectionIterator1476   typename A::pint_t operator*() const { return functionAddress(); }
1477 
functionAddresslibunwind::EHABISectionIterator1478   typename A::pint_t functionAddress() const {
1479     typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1480         EHABIIndexEntry, _i, functionOffset);
1481     return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr));
1482   }
1483 
dataAddresslibunwind::EHABISectionIterator1484   typename A::pint_t dataAddress() {
1485     typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof(
1486         EHABIIndexEntry, _i, data);
1487     return indexAddr;
1488   }
1489 
1490  private:
1491   size_t _i;
1492   A* _addressSpace;
1493   const UnwindInfoSections* _sects;
1494 };
1495 
1496 namespace {
1497 
1498 template <typename A>
EHABISectionUpperBound(EHABISectionIterator<A> first,EHABISectionIterator<A> last,typename A::pint_t value)1499 EHABISectionIterator<A> EHABISectionUpperBound(
1500     EHABISectionIterator<A> first,
1501     EHABISectionIterator<A> last,
1502     typename A::pint_t value) {
1503   size_t len = last - first;
1504   while (len > 0) {
1505     size_t l2 = len / 2;
1506     EHABISectionIterator<A> m = first + l2;
1507     if (value < *m) {
1508         len = l2;
1509     } else {
1510         first = ++m;
1511         len -= l2 + 1;
1512     }
1513   }
1514   return first;
1515 }
1516 
1517 }
1518 
1519 template <typename A, typename R>
getInfoFromEHABISection(pint_t pc,const UnwindInfoSections & sects)1520 bool UnwindCursor<A, R>::getInfoFromEHABISection(
1521     pint_t pc,
1522     const UnwindInfoSections &sects) {
1523   EHABISectionIterator<A> begin =
1524       EHABISectionIterator<A>::begin(_addressSpace, sects);
1525   EHABISectionIterator<A> end =
1526       EHABISectionIterator<A>::end(_addressSpace, sects);
1527   if (begin == end)
1528     return false;
1529 
1530   EHABISectionIterator<A> itNextPC = EHABISectionUpperBound(begin, end, pc);
1531   if (itNextPC == begin)
1532     return false;
1533   EHABISectionIterator<A> itThisPC = itNextPC - 1;
1534 
1535   pint_t thisPC = itThisPC.functionAddress();
1536   // If an exception is thrown from a function, corresponding to the last entry
1537   // in the table, we don't really know the function extent and have to choose a
1538   // value for nextPC. Choosing max() will allow the range check during trace to
1539   // succeed.
1540   pint_t nextPC = (itNextPC == end) ? UINTPTR_MAX : itNextPC.functionAddress();
1541   pint_t indexDataAddr = itThisPC.dataAddress();
1542 
1543   if (indexDataAddr == 0)
1544     return false;
1545 
1546   uint32_t indexData = _addressSpace.get32(indexDataAddr);
1547   if (indexData == UNW_EXIDX_CANTUNWIND)
1548     return false;
1549 
1550   // If the high bit is set, the exception handling table entry is inline inside
1551   // the index table entry on the second word (aka |indexDataAddr|). Otherwise,
1552   // the table points at an offset in the exception handling table (section 5
1553   // EHABI).
1554   pint_t exceptionTableAddr;
1555   uint32_t exceptionTableData;
1556   bool isSingleWordEHT;
1557   if (indexData & 0x80000000) {
1558     exceptionTableAddr = indexDataAddr;
1559     // TODO(ajwong): Should this data be 0?
1560     exceptionTableData = indexData;
1561     isSingleWordEHT = true;
1562   } else {
1563     exceptionTableAddr = indexDataAddr + signExtendPrel31(indexData);
1564     exceptionTableData = _addressSpace.get32(exceptionTableAddr);
1565     isSingleWordEHT = false;
1566   }
1567 
1568   // Now we know the 3 things:
1569   //   exceptionTableAddr -- exception handler table entry.
1570   //   exceptionTableData -- the data inside the first word of the eht entry.
1571   //   isSingleWordEHT -- whether the entry is in the index.
1572   unw_word_t personalityRoutine = 0xbadf00d;
1573   bool scope32 = false;
1574   uintptr_t lsda;
1575 
1576   // If the high bit in the exception handling table entry is set, the entry is
1577   // in compact form (section 6.3 EHABI).
1578   if (exceptionTableData & 0x80000000) {
1579     // Grab the index of the personality routine from the compact form.
1580     uint32_t choice = (exceptionTableData & 0x0f000000) >> 24;
1581     uint32_t extraWords = 0;
1582     switch (choice) {
1583       case 0:
1584         personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr0;
1585         extraWords = 0;
1586         scope32 = false;
1587         lsda = isSingleWordEHT ? 0 : (exceptionTableAddr + 4);
1588         break;
1589       case 1:
1590         personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr1;
1591         extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1592         scope32 = false;
1593         lsda = exceptionTableAddr + (extraWords + 1) * 4;
1594         break;
1595       case 2:
1596         personalityRoutine = (unw_word_t) &__aeabi_unwind_cpp_pr2;
1597         extraWords = (exceptionTableData & 0x00ff0000) >> 16;
1598         scope32 = true;
1599         lsda = exceptionTableAddr + (extraWords + 1) * 4;
1600         break;
1601       default:
1602         _LIBUNWIND_ABORT("unknown personality routine");
1603         return false;
1604     }
1605 
1606     if (isSingleWordEHT) {
1607       if (extraWords != 0) {
1608         _LIBUNWIND_ABORT("index inlined table detected but pr function "
1609                          "requires extra words");
1610         return false;
1611       }
1612     }
1613   } else {
1614     pint_t personalityAddr =
1615         exceptionTableAddr + signExtendPrel31(exceptionTableData);
1616     personalityRoutine = personalityAddr;
1617 
1618     // ARM EHABI # 6.2, # 9.2
1619     //
1620     //  +---- ehtp
1621     //  v
1622     // +--------------------------------------+
1623     // | +--------+--------+--------+-------+ |
1624     // | |0| prel31 to personalityRoutine   | |
1625     // | +--------+--------+--------+-------+ |
1626     // | |      N |      unwind opcodes     | |  <-- UnwindData
1627     // | +--------+--------+--------+-------+ |
1628     // | | Word 2        unwind opcodes     | |
1629     // | +--------+--------+--------+-------+ |
1630     // | ...                                  |
1631     // | +--------+--------+--------+-------+ |
1632     // | | Word N        unwind opcodes     | |
1633     // | +--------+--------+--------+-------+ |
1634     // | | LSDA                             | |  <-- lsda
1635     // | | ...                              | |
1636     // | +--------+--------+--------+-------+ |
1637     // +--------------------------------------+
1638 
1639     uint32_t *UnwindData = reinterpret_cast<uint32_t*>(exceptionTableAddr) + 1;
1640     uint32_t FirstDataWord = *UnwindData;
1641     size_t N = ((FirstDataWord >> 24) & 0xff);
1642     size_t NDataWords = N + 1;
1643     lsda = reinterpret_cast<uintptr_t>(UnwindData + NDataWords);
1644   }
1645 
1646   _info.start_ip = thisPC;
1647   _info.end_ip = nextPC;
1648   _info.handler = personalityRoutine;
1649   _info.unwind_info = exceptionTableAddr;
1650   _info.lsda = lsda;
1651   // flags is pr_cache.additional. See EHABI #7.2 for definition of bit 0.
1652   _info.flags = (isSingleWordEHT ? 1 : 0) | (scope32 ? 0x2 : 0);  // Use enum?
1653 
1654   return true;
1655 }
1656 #endif
1657 
1658 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1659 template <typename A, typename R>
getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info & fdeInfo,const typename CFI_Parser<A>::CIE_Info & cieInfo,pint_t pc,uintptr_t dso_base)1660 bool UnwindCursor<A, R>::getInfoFromFdeCie(
1661     const typename CFI_Parser<A>::FDE_Info &fdeInfo,
1662     const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc,
1663     uintptr_t dso_base) {
1664   typename CFI_Parser<A>::PrologInfo prolog;
1665   if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc,
1666                                           R::getArch(), &prolog)) {
1667     // Save off parsed FDE info
1668     _info.start_ip          = fdeInfo.pcStart;
1669     _info.end_ip            = fdeInfo.pcEnd;
1670     _info.lsda              = fdeInfo.lsda;
1671     _info.handler           = cieInfo.personality;
1672     // Some frameless functions need SP altered when resuming in function, so
1673     // propagate spExtraArgSize.
1674     _info.gp                = prolog.spExtraArgSize;
1675     _info.flags             = 0;
1676     _info.format            = dwarfEncoding();
1677     _info.unwind_info       = fdeInfo.fdeStart;
1678     _info.unwind_info_size  = static_cast<uint32_t>(fdeInfo.fdeLength);
1679     _info.extra             = static_cast<unw_word_t>(dso_base);
1680     return true;
1681   }
1682   return false;
1683 }
1684 
1685 template <typename A, typename R>
getInfoFromDwarfSection(pint_t pc,const UnwindInfoSections & sects,uint32_t fdeSectionOffsetHint)1686 bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc,
1687                                                 const UnwindInfoSections &sects,
1688                                                 uint32_t fdeSectionOffsetHint) {
1689   typename CFI_Parser<A>::FDE_Info fdeInfo;
1690   typename CFI_Parser<A>::CIE_Info cieInfo;
1691   bool foundFDE = false;
1692   bool foundInCache = false;
1693   // If compact encoding table gave offset into dwarf section, go directly there
1694   if (fdeSectionOffsetHint != 0) {
1695     foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1696                                     sects.dwarf_section_length,
1697                                     sects.dwarf_section + fdeSectionOffsetHint,
1698                                     &fdeInfo, &cieInfo);
1699   }
1700 #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1701   if (!foundFDE && (sects.dwarf_index_section != 0)) {
1702     foundFDE = EHHeaderParser<A>::findFDE(
1703         _addressSpace, pc, sects.dwarf_index_section,
1704         (uint32_t)sects.dwarf_index_section_length, &fdeInfo, &cieInfo);
1705   }
1706 #endif
1707   if (!foundFDE) {
1708     // otherwise, search cache of previously found FDEs.
1709     pint_t cachedFDE = DwarfFDECache<A>::findFDE(sects.dso_base, pc);
1710     if (cachedFDE != 0) {
1711       foundFDE =
1712           CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1713                                  sects.dwarf_section_length,
1714                                  cachedFDE, &fdeInfo, &cieInfo);
1715       foundInCache = foundFDE;
1716     }
1717   }
1718   if (!foundFDE) {
1719     // Still not found, do full scan of __eh_frame section.
1720     foundFDE = CFI_Parser<A>::findFDE(_addressSpace, pc, sects.dwarf_section,
1721                                       sects.dwarf_section_length, 0,
1722                                       &fdeInfo, &cieInfo);
1723   }
1724   if (foundFDE) {
1725     if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, sects.dso_base)) {
1726       // Add to cache (to make next lookup faster) if we had no hint
1727       // and there was no index.
1728       if (!foundInCache && (fdeSectionOffsetHint == 0)) {
1729   #if defined(_LIBUNWIND_SUPPORT_DWARF_INDEX)
1730         if (sects.dwarf_index_section == 0)
1731   #endif
1732         DwarfFDECache<A>::add(sects.dso_base, fdeInfo.pcStart, fdeInfo.pcEnd,
1733                               fdeInfo.fdeStart);
1734       }
1735       return true;
1736     }
1737   }
1738   //_LIBUNWIND_DEBUG_LOG("can't find/use FDE for pc=0x%llX", (uint64_t)pc);
1739   return false;
1740 }
1741 #endif // defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
1742 
1743 
1744 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
1745 template <typename A, typename R>
getInfoFromCompactEncodingSection(pint_t pc,const UnwindInfoSections & sects)1746 bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc,
1747                                               const UnwindInfoSections &sects) {
1748   const bool log = false;
1749   if (log)
1750     fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX, mh=0x%llX)\n",
1751             (uint64_t)pc, (uint64_t)sects.dso_base);
1752 
1753   const UnwindSectionHeader<A> sectionHeader(_addressSpace,
1754                                                 sects.compact_unwind_section);
1755   if (sectionHeader.version() != UNWIND_SECTION_VERSION)
1756     return false;
1757 
1758   // do a binary search of top level index to find page with unwind info
1759   pint_t targetFunctionOffset = pc - sects.dso_base;
1760   const UnwindSectionIndexArray<A> topIndex(_addressSpace,
1761                                            sects.compact_unwind_section
1762                                          + sectionHeader.indexSectionOffset());
1763   uint32_t low = 0;
1764   uint32_t high = sectionHeader.indexCount();
1765   uint32_t last = high - 1;
1766   while (low < high) {
1767     uint32_t mid = (low + high) / 2;
1768     //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n",
1769     //mid, low, high, topIndex.functionOffset(mid));
1770     if (topIndex.functionOffset(mid) <= targetFunctionOffset) {
1771       if ((mid == last) ||
1772           (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) {
1773         low = mid;
1774         break;
1775       } else {
1776         low = mid + 1;
1777       }
1778     } else {
1779       high = mid;
1780     }
1781   }
1782   const uint32_t firstLevelFunctionOffset = topIndex.functionOffset(low);
1783   const uint32_t firstLevelNextPageFunctionOffset =
1784       topIndex.functionOffset(low + 1);
1785   const pint_t secondLevelAddr =
1786       sects.compact_unwind_section + topIndex.secondLevelPagesSectionOffset(low);
1787   const pint_t lsdaArrayStartAddr =
1788       sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low);
1789   const pint_t lsdaArrayEndAddr =
1790       sects.compact_unwind_section + topIndex.lsdaIndexArraySectionOffset(low+1);
1791   if (log)
1792     fprintf(stderr, "\tfirst level search for result index=%d "
1793                     "to secondLevelAddr=0x%llX\n",
1794                     low, (uint64_t) secondLevelAddr);
1795   // do a binary search of second level page index
1796   uint32_t encoding = 0;
1797   pint_t funcStart = 0;
1798   pint_t funcEnd = 0;
1799   pint_t lsda = 0;
1800   pint_t personality = 0;
1801   uint32_t pageKind = _addressSpace.get32(secondLevelAddr);
1802   if (pageKind == UNWIND_SECOND_LEVEL_REGULAR) {
1803     // regular page
1804     UnwindSectionRegularPageHeader<A> pageHeader(_addressSpace,
1805                                                  secondLevelAddr);
1806     UnwindSectionRegularArray<A> pageIndex(
1807         _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1808     // binary search looks for entry with e where index[e].offset <= pc <
1809     // index[e+1].offset
1810     if (log)
1811       fprintf(stderr, "\tbinary search for targetFunctionOffset=0x%08llX in "
1812                       "regular page starting at secondLevelAddr=0x%llX\n",
1813               (uint64_t) targetFunctionOffset, (uint64_t) secondLevelAddr);
1814     low = 0;
1815     high = pageHeader.entryCount();
1816     while (low < high) {
1817       uint32_t mid = (low + high) / 2;
1818       if (pageIndex.functionOffset(mid) <= targetFunctionOffset) {
1819         if (mid == (uint32_t)(pageHeader.entryCount() - 1)) {
1820           // at end of table
1821           low = mid;
1822           funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1823           break;
1824         } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) {
1825           // next is too big, so we found it
1826           low = mid;
1827           funcEnd = pageIndex.functionOffset(low + 1) + sects.dso_base;
1828           break;
1829         } else {
1830           low = mid + 1;
1831         }
1832       } else {
1833         high = mid;
1834       }
1835     }
1836     encoding = pageIndex.encoding(low);
1837     funcStart = pageIndex.functionOffset(low) + sects.dso_base;
1838     if (pc < funcStart) {
1839       if (log)
1840         fprintf(
1841             stderr,
1842             "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1843             (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1844       return false;
1845     }
1846     if (pc > funcEnd) {
1847       if (log)
1848         fprintf(
1849             stderr,
1850             "\tpc not in table, pc=0x%llX, funcStart=0x%llX, funcEnd=0x%llX\n",
1851             (uint64_t) pc, (uint64_t) funcStart, (uint64_t) funcEnd);
1852       return false;
1853     }
1854   } else if (pageKind == UNWIND_SECOND_LEVEL_COMPRESSED) {
1855     // compressed page
1856     UnwindSectionCompressedPageHeader<A> pageHeader(_addressSpace,
1857                                                     secondLevelAddr);
1858     UnwindSectionCompressedArray<A> pageIndex(
1859         _addressSpace, secondLevelAddr + pageHeader.entryPageOffset());
1860     const uint32_t targetFunctionPageOffset =
1861         (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset);
1862     // binary search looks for entry with e where index[e].offset <= pc <
1863     // index[e+1].offset
1864     if (log)
1865       fprintf(stderr, "\tbinary search of compressed page starting at "
1866                       "secondLevelAddr=0x%llX\n",
1867               (uint64_t) secondLevelAddr);
1868     low = 0;
1869     last = pageHeader.entryCount() - 1;
1870     high = pageHeader.entryCount();
1871     while (low < high) {
1872       uint32_t mid = (low + high) / 2;
1873       if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) {
1874         if ((mid == last) ||
1875             (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) {
1876           low = mid;
1877           break;
1878         } else {
1879           low = mid + 1;
1880         }
1881       } else {
1882         high = mid;
1883       }
1884     }
1885     funcStart = pageIndex.functionOffset(low) + firstLevelFunctionOffset
1886                                                               + sects.dso_base;
1887     if (low < last)
1888       funcEnd =
1889           pageIndex.functionOffset(low + 1) + firstLevelFunctionOffset
1890                                                               + sects.dso_base;
1891     else
1892       funcEnd = firstLevelNextPageFunctionOffset + sects.dso_base;
1893     if (pc < funcStart) {
1894       _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1895                            "not in second level compressed unwind table. "
1896                            "funcStart=0x%llX",
1897                             (uint64_t) pc, (uint64_t) funcStart);
1898       return false;
1899     }
1900     if (pc > funcEnd) {
1901       _LIBUNWIND_DEBUG_LOG("malformed __unwind_info, pc=0x%llX "
1902                            "not in second level compressed unwind table. "
1903                            "funcEnd=0x%llX",
1904                            (uint64_t) pc, (uint64_t) funcEnd);
1905       return false;
1906     }
1907     uint16_t encodingIndex = pageIndex.encodingIndex(low);
1908     if (encodingIndex < sectionHeader.commonEncodingsArrayCount()) {
1909       // encoding is in common table in section header
1910       encoding = _addressSpace.get32(
1911           sects.compact_unwind_section +
1912           sectionHeader.commonEncodingsArraySectionOffset() +
1913           encodingIndex * sizeof(uint32_t));
1914     } else {
1915       // encoding is in page specific table
1916       uint16_t pageEncodingIndex =
1917           encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount();
1918       encoding = _addressSpace.get32(secondLevelAddr +
1919                                      pageHeader.encodingsPageOffset() +
1920                                      pageEncodingIndex * sizeof(uint32_t));
1921     }
1922   } else {
1923     _LIBUNWIND_DEBUG_LOG(
1924         "malformed __unwind_info at 0x%0llX bad second level page",
1925         (uint64_t)sects.compact_unwind_section);
1926     return false;
1927   }
1928 
1929   // look up LSDA, if encoding says function has one
1930   if (encoding & UNWIND_HAS_LSDA) {
1931     UnwindSectionLsdaArray<A> lsdaIndex(_addressSpace, lsdaArrayStartAddr);
1932     uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base);
1933     low = 0;
1934     high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) /
1935                     sizeof(unwind_info_section_header_lsda_index_entry);
1936     // binary search looks for entry with exact match for functionOffset
1937     if (log)
1938       fprintf(stderr,
1939               "\tbinary search of lsda table for targetFunctionOffset=0x%08X\n",
1940               funcStartOffset);
1941     while (low < high) {
1942       uint32_t mid = (low + high) / 2;
1943       if (lsdaIndex.functionOffset(mid) == funcStartOffset) {
1944         lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base;
1945         break;
1946       } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) {
1947         low = mid + 1;
1948       } else {
1949         high = mid;
1950       }
1951     }
1952     if (lsda == 0) {
1953       _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with HAS_LSDA bit set for "
1954                     "pc=0x%0llX, but lsda table has no entry",
1955                     encoding, (uint64_t) pc);
1956       return false;
1957     }
1958   }
1959 
1960   // extract personality routine, if encoding says function has one
1961   uint32_t personalityIndex = (encoding & UNWIND_PERSONALITY_MASK) >>
1962                               (__builtin_ctz(UNWIND_PERSONALITY_MASK));
1963   if (personalityIndex != 0) {
1964     --personalityIndex; // change 1-based to zero-based index
1965     if (personalityIndex >= sectionHeader.personalityArrayCount()) {
1966       _LIBUNWIND_DEBUG_LOG("found encoding 0x%08X with personality index %d,  "
1967                             "but personality table has only %d entries",
1968                             encoding, personalityIndex,
1969                             sectionHeader.personalityArrayCount());
1970       return false;
1971     }
1972     int32_t personalityDelta = (int32_t)_addressSpace.get32(
1973         sects.compact_unwind_section +
1974         sectionHeader.personalityArraySectionOffset() +
1975         personalityIndex * sizeof(uint32_t));
1976     pint_t personalityPointer = sects.dso_base + (pint_t)personalityDelta;
1977     personality = _addressSpace.getP(personalityPointer);
1978     if (log)
1979       fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1980                       "personalityDelta=0x%08X, personality=0x%08llX\n",
1981               (uint64_t) pc, personalityDelta, (uint64_t) personality);
1982   }
1983 
1984   if (log)
1985     fprintf(stderr, "getInfoFromCompactEncodingSection(pc=0x%llX), "
1986                     "encoding=0x%08X, lsda=0x%08llX for funcStart=0x%llX\n",
1987             (uint64_t) pc, encoding, (uint64_t) lsda, (uint64_t) funcStart);
1988   _info.start_ip = funcStart;
1989   _info.end_ip = funcEnd;
1990   _info.lsda = lsda;
1991   _info.handler = personality;
1992   _info.gp = 0;
1993   _info.flags = 0;
1994   _info.format = encoding;
1995   _info.unwind_info = 0;
1996   _info.unwind_info_size = 0;
1997   _info.extra = sects.dso_base;
1998   return true;
1999 }
2000 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2001 
2002 
2003 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2004 template <typename A, typename R>
getInfoFromSEH(pint_t pc)2005 bool UnwindCursor<A, R>::getInfoFromSEH(pint_t pc) {
2006   pint_t base;
2007   RUNTIME_FUNCTION *unwindEntry = lookUpSEHUnwindInfo(pc, &base);
2008   if (!unwindEntry) {
2009     _LIBUNWIND_DEBUG_LOG("\tpc not in table, pc=0x%llX", (uint64_t) pc);
2010     return false;
2011   }
2012   _info.gp = 0;
2013   _info.flags = 0;
2014   _info.format = 0;
2015   _info.unwind_info_size = sizeof(RUNTIME_FUNCTION);
2016   _info.unwind_info = reinterpret_cast<unw_word_t>(unwindEntry);
2017   _info.extra = base;
2018   _info.start_ip = base + unwindEntry->BeginAddress;
2019 #ifdef _LIBUNWIND_TARGET_X86_64
2020   _info.end_ip = base + unwindEntry->EndAddress;
2021   // Only fill in the handler and LSDA if they're stale.
2022   if (pc != getLastPC()) {
2023     UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData);
2024     if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) {
2025       // The personality is given in the UNWIND_INFO itself. The LSDA immediately
2026       // follows the UNWIND_INFO. (This follows how both Clang and MSVC emit
2027       // these structures.)
2028       // N.B. UNWIND_INFO structs are DWORD-aligned.
2029       uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1;
2030       const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]);
2031       _info.lsda = reinterpret_cast<unw_word_t>(handler+1);
2032       _dispContext.HandlerData = reinterpret_cast<void *>(_info.lsda);
2033       _dispContext.LanguageHandler =
2034           reinterpret_cast<EXCEPTION_ROUTINE *>(base + *handler);
2035       if (*handler) {
2036         _info.handler = reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
2037       } else
2038         _info.handler = 0;
2039     } else {
2040       _info.lsda = 0;
2041       _info.handler = 0;
2042     }
2043   }
2044 #elif defined(_LIBUNWIND_TARGET_AARCH64) || defined(_LIBUNWIND_TARGET_ARM)
2045 
2046 #if defined(_LIBUNWIND_TARGET_AARCH64)
2047 #define FUNC_LENGTH_UNIT 4
2048 #define XDATA_TYPE IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY_XDATA
2049 #else
2050 #define FUNC_LENGTH_UNIT 2
2051 #define XDATA_TYPE UNWIND_INFO_ARM
2052 #endif
2053   if (unwindEntry->Flag != 0) { // Packed unwind info
2054     _info.end_ip =
2055         _info.start_ip + unwindEntry->FunctionLength * FUNC_LENGTH_UNIT;
2056     // Only fill in the handler and LSDA if they're stale.
2057     if (pc != getLastPC()) {
2058       // Packed unwind info doesn't have an exception handler.
2059       _info.lsda = 0;
2060       _info.handler = 0;
2061     }
2062   } else {
2063     XDATA_TYPE *xdata =
2064         reinterpret_cast<XDATA_TYPE *>(base + unwindEntry->UnwindData);
2065     _info.end_ip = _info.start_ip + xdata->FunctionLength * FUNC_LENGTH_UNIT;
2066     // Only fill in the handler and LSDA if they're stale.
2067     if (pc != getLastPC()) {
2068       if (xdata->ExceptionDataPresent) {
2069         uint32_t offset = 1; // The main xdata
2070         uint32_t codeWords = xdata->CodeWords;
2071         uint32_t epilogScopes = xdata->EpilogCount;
2072         if (xdata->EpilogCount == 0 && xdata->CodeWords == 0) {
2073           // The extension word has got the same layout for both ARM and ARM64
2074           uint32_t extensionWord = reinterpret_cast<uint32_t *>(xdata)[1];
2075           codeWords = (extensionWord >> 16) & 0xff;
2076           epilogScopes = extensionWord & 0xffff;
2077           offset++;
2078         }
2079         if (!xdata->EpilogInHeader)
2080           offset += epilogScopes;
2081         offset += codeWords;
2082         uint32_t *exceptionHandlerInfo =
2083             reinterpret_cast<uint32_t *>(xdata) + offset;
2084         _dispContext.HandlerData = &exceptionHandlerInfo[1];
2085         _dispContext.LanguageHandler = reinterpret_cast<EXCEPTION_ROUTINE *>(
2086             base + exceptionHandlerInfo[0]);
2087         _info.lsda = reinterpret_cast<unw_word_t>(_dispContext.HandlerData);
2088         if (exceptionHandlerInfo[0])
2089           _info.handler =
2090               reinterpret_cast<unw_word_t>(__libunwind_seh_personality);
2091         else
2092           _info.handler = 0;
2093       } else {
2094         _info.lsda = 0;
2095         _info.handler = 0;
2096       }
2097     }
2098   }
2099 #endif
2100   setLastPC(pc);
2101   return true;
2102 }
2103 #endif
2104 
2105 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2106 // Masks for traceback table field xtbtable.
2107 enum xTBTableMask : uint8_t {
2108   reservedBit = 0x02, // The traceback table was incorrectly generated if set
2109                       // (see comments in function getInfoFromTBTable().
2110   ehInfoBit = 0x08    // Exception handling info is present if set
2111 };
2112 
2113 enum frameType : unw_word_t {
2114   frameWithXLEHStateTable = 0,
2115   frameWithEHInfo = 1
2116 };
2117 
2118 extern "C" {
2119 typedef _Unwind_Reason_Code __xlcxx_personality_v0_t(int, _Unwind_Action,
2120                                                      uint64_t,
2121                                                      _Unwind_Exception *,
2122                                                      struct _Unwind_Context *);
2123 }
2124 
2125 static __xlcxx_personality_v0_t *xlcPersonalityV0;
2126 static RWMutex xlcPersonalityV0InitLock;
2127 
2128 template <typename A, typename R>
getInfoFromTBTable(pint_t pc,R & registers)2129 bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R &registers) {
2130   uint32_t *p = reinterpret_cast<uint32_t *>(pc);
2131 
2132   // Keep looking forward until a word of 0 is found. The traceback
2133   // table starts at the following word.
2134   while (*p)
2135     ++p;
2136   tbtable *TBTable = reinterpret_cast<tbtable *>(p + 1);
2137 
2138   if (_LIBUNWIND_TRACING_UNWINDING) {
2139     char functionBuf[512];
2140     const char *functionName = functionBuf;
2141     unw_word_t offset;
2142     if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
2143       functionName = ".anonymous.";
2144     }
2145     _LIBUNWIND_TRACE_UNWINDING("%s: Look up traceback table of func=%s at %p",
2146                                __func__, functionName,
2147                                reinterpret_cast<void *>(TBTable));
2148   }
2149 
2150   // If the traceback table does not contain necessary info, bypass this frame.
2151   if (!TBTable->tb.has_tboff)
2152     return false;
2153 
2154   // Structure tbtable_ext contains important data we are looking for.
2155   p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
2156 
2157   // Skip field parminfo if it exists.
2158   if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
2159     ++p;
2160 
2161   // p now points to tb_offset, the offset from start of function to TB table.
2162   unw_word_t start_ip =
2163       reinterpret_cast<unw_word_t>(TBTable) - *p - sizeof(uint32_t);
2164   unw_word_t end_ip = reinterpret_cast<unw_word_t>(TBTable);
2165   ++p;
2166 
2167   _LIBUNWIND_TRACE_UNWINDING("start_ip=%p, end_ip=%p\n",
2168                              reinterpret_cast<void *>(start_ip),
2169                              reinterpret_cast<void *>(end_ip));
2170 
2171   // Skip field hand_mask if it exists.
2172   if (TBTable->tb.int_hndl)
2173     ++p;
2174 
2175   unw_word_t lsda = 0;
2176   unw_word_t handler = 0;
2177   unw_word_t flags = frameType::frameWithXLEHStateTable;
2178 
2179   if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl) {
2180     // State table info is available. The ctl_info field indicates the
2181     // number of CTL anchors. There should be only one entry for the C++
2182     // state table.
2183     assert(*p == 1 && "libunwind: there must be only one ctl_info entry");
2184     ++p;
2185     // p points to the offset of the state table into the stack.
2186     pint_t stateTableOffset = *p++;
2187 
2188     int framePointerReg;
2189 
2190     // Skip fields name_len and name if exist.
2191     if (TBTable->tb.name_present) {
2192       const uint16_t name_len = *(reinterpret_cast<uint16_t *>(p));
2193       p = reinterpret_cast<uint32_t *>(reinterpret_cast<char *>(p) + name_len +
2194                                        sizeof(uint16_t));
2195     }
2196 
2197     if (TBTable->tb.uses_alloca)
2198       framePointerReg = *(reinterpret_cast<char *>(p));
2199     else
2200       framePointerReg = 1; // default frame pointer == SP
2201 
2202     _LIBUNWIND_TRACE_UNWINDING(
2203         "framePointerReg=%d, framePointer=%p, "
2204         "stateTableOffset=%#lx\n",
2205         framePointerReg,
2206         reinterpret_cast<void *>(_registers.getRegister(framePointerReg)),
2207         stateTableOffset);
2208     lsda = _registers.getRegister(framePointerReg) + stateTableOffset;
2209 
2210     // Since the traceback table generated by the legacy XLC++ does not
2211     // provide the location of the personality for the state table,
2212     // function __xlcxx_personality_v0(), which is the personality for the state
2213     // table and is exported from libc++abi, is directly assigned as the
2214     // handler here. When a legacy XLC++ frame is encountered, the symbol
2215     // is resolved dynamically using dlopen() to avoid a hard dependency of
2216     // libunwind on libc++abi in cases such as non-C++ applications.
2217 
2218     // Resolve the function pointer to the state table personality if it has
2219     // not already been done.
2220     if (xlcPersonalityV0 == NULL) {
2221       xlcPersonalityV0InitLock.lock();
2222       if (xlcPersonalityV0 == NULL) {
2223         // Resolve __xlcxx_personality_v0 using dlopen().
2224         const char *libcxxabi = "libc++abi.a(libc++abi.so.1)";
2225         void *libHandle;
2226         // The AIX dlopen() sets errno to 0 when it is successful, which
2227         // clobbers the value of errno from the user code. This is an AIX
2228         // bug because according to POSIX it should not set errno to 0. To
2229         // workaround before AIX fixes the bug, errno is saved and restored.
2230         int saveErrno = errno;
2231         libHandle = dlopen(libcxxabi, RTLD_MEMBER | RTLD_NOW);
2232         if (libHandle == NULL) {
2233           _LIBUNWIND_TRACE_UNWINDING("dlopen() failed with errno=%d\n", errno);
2234           assert(0 && "dlopen() failed");
2235         }
2236         xlcPersonalityV0 = reinterpret_cast<__xlcxx_personality_v0_t *>(
2237             dlsym(libHandle, "__xlcxx_personality_v0"));
2238         if (xlcPersonalityV0 == NULL) {
2239           _LIBUNWIND_TRACE_UNWINDING("dlsym() failed with errno=%d\n", errno);
2240           dlclose(libHandle);
2241           assert(0 && "dlsym() failed");
2242         }
2243         errno = saveErrno;
2244       }
2245       xlcPersonalityV0InitLock.unlock();
2246     }
2247     handler = reinterpret_cast<unw_word_t>(xlcPersonalityV0);
2248     _LIBUNWIND_TRACE_UNWINDING("State table: LSDA=%p, Personality=%p\n",
2249                                reinterpret_cast<void *>(lsda),
2250                                reinterpret_cast<void *>(handler));
2251   } else if (TBTable->tb.longtbtable) {
2252     // This frame has the traceback table extension. Possible cases are
2253     // 1) a C++ frame that has the 'eh_info' structure; 2) a C++ frame that
2254     // is not EH aware; or, 3) a frame of other languages. We need to figure out
2255     // if the traceback table extension contains the 'eh_info' structure.
2256     //
2257     // We also need to deal with the complexity arising from some XL compiler
2258     // versions use the wrong ordering of 'longtbtable' and 'has_vec' bits
2259     // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice
2260     // versa. For frames of code generated by those compilers, the 'longtbtable'
2261     // bit may be set but there isn't really a traceback table extension.
2262     //
2263     // In </usr/include/sys/debug.h>, there is the following definition of
2264     // 'struct tbtable_ext'. It is not really a structure but a dummy to
2265     // collect the description of optional parts of the traceback table.
2266     //
2267     // struct tbtable_ext {
2268     //   ...
2269     //   char alloca_reg;        /* Register for alloca automatic storage */
2270     //   struct vec_ext vec_ext; /* Vector extension (if has_vec is set) */
2271     //   unsigned char xtbtable; /* More tbtable fields, if longtbtable is set*/
2272     // };
2273     //
2274     // Depending on how the 'has_vec'/'longtbtable' bit is interpreted, the data
2275     // following 'alloca_reg' can be treated either as 'struct vec_ext' or
2276     // 'unsigned char xtbtable'. 'xtbtable' bits are defined in
2277     // </usr/include/sys/debug.h> as flags. The 7th bit '0x02' is currently
2278     // unused and should not be set. 'struct vec_ext' is defined in
2279     // </usr/include/sys/debug.h> as follows:
2280     //
2281     // struct vec_ext {
2282     //   unsigned vr_saved:6;      /* Number of non-volatile vector regs saved
2283     //   */
2284     //                             /* first register saved is assumed to be */
2285     //                             /* 32 - vr_saved                         */
2286     //   unsigned saves_vrsave:1;  /* Set if vrsave is saved on the stack */
2287     //   unsigned has_varargs:1;
2288     //   ...
2289     // };
2290     //
2291     // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it
2292     // is 'struct vec_ext' or 'xtbtable' that follows 'alloca_reg',
2293     // we checks if the 7th bit is set or not because 'xtbtable' should
2294     // never have the 7th bit set. The 7th bit of 'xtbtable' will be reserved
2295     // in the future to make sure the mitigation works. This mitigation
2296     // is not 100% bullet proof because 'struct vec_ext' may not always have
2297     // 'saves_vrsave' bit set.
2298     //
2299     // 'reservedBit' is defined in enum 'xTBTableMask' above as the mask for
2300     // checking the 7th bit.
2301 
2302     // p points to field name len.
2303     uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
2304 
2305     // Skip fields name_len and name if they exist.
2306     if (TBTable->tb.name_present) {
2307       const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
2308       charPtr = charPtr + name_len + sizeof(uint16_t);
2309     }
2310 
2311     // Skip field alloc_reg if it exists.
2312     if (TBTable->tb.uses_alloca)
2313       ++charPtr;
2314 
2315     // Check traceback table bit has_vec. Skip struct vec_ext if it exists.
2316     if (TBTable->tb.has_vec)
2317       // Note struct vec_ext does exist at this point because whether the
2318       // ordering of longtbtable and has_vec bits is correct or not, both
2319       // are set.
2320       charPtr += sizeof(struct vec_ext);
2321 
2322     // charPtr points to field 'xtbtable'. Check if the EH info is available.
2323     // Also check if the reserved bit of the extended traceback table field
2324     // 'xtbtable' is set. If it is, the traceback table was incorrectly
2325     // generated by an XL compiler that uses the wrong ordering of 'longtbtable'
2326     // and 'has_vec' bits and this is in fact 'struct vec_ext'. So skip the
2327     // frame.
2328     if ((*charPtr & xTBTableMask::ehInfoBit) &&
2329         !(*charPtr & xTBTableMask::reservedBit)) {
2330       // Mark this frame has the new EH info.
2331       flags = frameType::frameWithEHInfo;
2332 
2333       // eh_info is available.
2334       charPtr++;
2335       // The pointer is 4-byte aligned.
2336       if (reinterpret_cast<uintptr_t>(charPtr) % 4)
2337         charPtr += 4 - reinterpret_cast<uintptr_t>(charPtr) % 4;
2338       uintptr_t *ehInfo =
2339           reinterpret_cast<uintptr_t *>(*(reinterpret_cast<uintptr_t *>(
2340               registers.getRegister(2) +
2341               *(reinterpret_cast<uintptr_t *>(charPtr)))));
2342 
2343       // ehInfo points to structure en_info. The first member is version.
2344       // Only version 0 is currently supported.
2345       assert(*(reinterpret_cast<uint32_t *>(ehInfo)) == 0 &&
2346              "libunwind: ehInfo version other than 0 is not supported");
2347 
2348       // Increment ehInfo to point to member lsda.
2349       ++ehInfo;
2350       lsda = *ehInfo++;
2351 
2352       // enInfo now points to member personality.
2353       handler = *ehInfo;
2354 
2355       _LIBUNWIND_TRACE_UNWINDING("Range table: LSDA=%#lx, Personality=%#lx\n",
2356                                  lsda, handler);
2357     }
2358   }
2359 
2360   _info.start_ip = start_ip;
2361   _info.end_ip = end_ip;
2362   _info.lsda = lsda;
2363   _info.handler = handler;
2364   _info.gp = 0;
2365   _info.flags = flags;
2366   _info.format = 0;
2367   _info.unwind_info = reinterpret_cast<unw_word_t>(TBTable);
2368   _info.unwind_info_size = 0;
2369   _info.extra = registers.getRegister(2);
2370 
2371   return true;
2372 }
2373 
2374 // Step back up the stack following the frame back link.
2375 template <typename A, typename R>
stepWithTBTable(pint_t pc,tbtable * TBTable,R & registers,bool & isSignalFrame)2376 int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable,
2377                                         R &registers, bool &isSignalFrame) {
2378   if (_LIBUNWIND_TRACING_UNWINDING) {
2379     char functionBuf[512];
2380     const char *functionName = functionBuf;
2381     unw_word_t offset;
2382     if (!getFunctionName(functionBuf, sizeof(functionBuf), &offset)) {
2383       functionName = ".anonymous.";
2384     }
2385     _LIBUNWIND_TRACE_UNWINDING(
2386         "%s: Look up traceback table of func=%s at %p, pc=%p, "
2387         "SP=%p, saves_lr=%d, stores_bc=%d",
2388         __func__, functionName, reinterpret_cast<void *>(TBTable),
2389         reinterpret_cast<void *>(pc),
2390         reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr,
2391         TBTable->tb.stores_bc);
2392   }
2393 
2394 #if defined(__powerpc64__)
2395   // Instruction to reload TOC register "ld r2,40(r1)"
2396   const uint32_t loadTOCRegInst = 0xe8410028;
2397   const int32_t unwPPCF0Index = UNW_PPC64_F0;
2398   const int32_t unwPPCV0Index = UNW_PPC64_V0;
2399 #else
2400   // Instruction to reload TOC register "lwz r2,20(r1)"
2401   const uint32_t loadTOCRegInst = 0x80410014;
2402   const int32_t unwPPCF0Index = UNW_PPC_F0;
2403   const int32_t unwPPCV0Index = UNW_PPC_V0;
2404 #endif
2405 
2406   // lastStack points to the stack frame of the next routine up.
2407   pint_t curStack = static_cast<pint_t>(registers.getSP());
2408   pint_t lastStack = *reinterpret_cast<pint_t *>(curStack);
2409 
2410   if (lastStack == 0)
2411     return UNW_STEP_END;
2412 
2413   R newRegisters = registers;
2414 
2415   // If backchain is not stored, use the current stack frame.
2416   if (!TBTable->tb.stores_bc)
2417     lastStack = curStack;
2418 
2419   // Return address is the address after call site instruction.
2420   pint_t returnAddress;
2421 
2422   if (isSignalFrame) {
2423     _LIBUNWIND_TRACE_UNWINDING("Possible signal handler frame: lastStack=%p",
2424                                reinterpret_cast<void *>(lastStack));
2425 
2426     sigcontext *sigContext = reinterpret_cast<sigcontext *>(
2427         reinterpret_cast<char *>(lastStack) + STKMINALIGN);
2428     returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
2429 
2430     bool useSTKMIN = false;
2431     if (returnAddress < 0x10000000) {
2432       // Try again using STKMIN.
2433       sigContext = reinterpret_cast<sigcontext *>(
2434           reinterpret_cast<char *>(lastStack) + STKMIN);
2435       returnAddress = sigContext->sc_jmpbuf.jmp_context.iar;
2436       if (returnAddress < 0x10000000) {
2437         _LIBUNWIND_TRACE_UNWINDING("Bad returnAddress=%p from sigcontext=%p",
2438                                    reinterpret_cast<void *>(returnAddress),
2439                                    reinterpret_cast<void *>(sigContext));
2440         return UNW_EBADFRAME;
2441       }
2442       useSTKMIN = true;
2443     }
2444     _LIBUNWIND_TRACE_UNWINDING("Returning from a signal handler %s: "
2445                                "sigContext=%p, returnAddress=%p. "
2446                                "Seems to be a valid address",
2447                                useSTKMIN ? "STKMIN" : "STKMINALIGN",
2448                                reinterpret_cast<void *>(sigContext),
2449                                reinterpret_cast<void *>(returnAddress));
2450 
2451     // Restore the condition register from sigcontext.
2452     newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr);
2453 
2454     // Save the LR in sigcontext for stepping up when the function that
2455     // raised the signal is a leaf function. This LR has the return address
2456     // to the caller of the leaf function.
2457     newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr);
2458     _LIBUNWIND_TRACE_UNWINDING(
2459         "Save LR=%p from sigcontext",
2460         reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr));
2461 
2462     // Restore GPRs from sigcontext.
2463     for (int i = 0; i < 32; ++i)
2464       newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]);
2465 
2466     // Restore FPRs from sigcontext.
2467     for (int i = 0; i < 32; ++i)
2468       newRegisters.setFloatRegister(i + unwPPCF0Index,
2469                                     sigContext->sc_jmpbuf.jmp_context.fpr[i]);
2470 
2471     // Restore vector registers if there is an associated extended context
2472     // structure.
2473     if (sigContext->sc_jmpbuf.jmp_context.msr & __EXTCTX) {
2474       ucontext_t *uContext = reinterpret_cast<ucontext_t *>(sigContext);
2475       if (uContext->__extctx->__extctx_magic == __EXTCTX_MAGIC) {
2476         for (int i = 0; i < 32; ++i)
2477           newRegisters.setVectorRegister(
2478               i + unwPPCV0Index, *(reinterpret_cast<v128 *>(
2479                                      &(uContext->__extctx->__vmx.__vr[i]))));
2480       }
2481     }
2482   } else {
2483     // Step up a normal frame.
2484 
2485     if (!TBTable->tb.saves_lr && registers.getLR()) {
2486       // This case should only occur if we were called from a signal handler
2487       // and the signal occurred in a function that doesn't save the LR.
2488       returnAddress = static_cast<pint_t>(registers.getLR());
2489       _LIBUNWIND_TRACE_UNWINDING("Use saved LR=%p",
2490                                  reinterpret_cast<void *>(returnAddress));
2491     } else {
2492       // Otherwise, use the LR value in the stack link area.
2493       returnAddress = reinterpret_cast<pint_t *>(lastStack)[2];
2494     }
2495 
2496     // Reset LR in the current context.
2497     newRegisters.setLR(static_cast<uintptr_t>(NULL));
2498 
2499     _LIBUNWIND_TRACE_UNWINDING(
2500         "Extract info from lastStack=%p, returnAddress=%p",
2501         reinterpret_cast<void *>(lastStack),
2502         reinterpret_cast<void *>(returnAddress));
2503     _LIBUNWIND_TRACE_UNWINDING("fpr_regs=%d, gpr_regs=%d, saves_cr=%d",
2504                                TBTable->tb.fpr_saved, TBTable->tb.gpr_saved,
2505                                TBTable->tb.saves_cr);
2506 
2507     // Restore FP registers.
2508     char *ptrToRegs = reinterpret_cast<char *>(lastStack);
2509     double *FPRegs = reinterpret_cast<double *>(
2510         ptrToRegs - (TBTable->tb.fpr_saved * sizeof(double)));
2511     for (int i = 0; i < TBTable->tb.fpr_saved; ++i)
2512       newRegisters.setFloatRegister(
2513           32 - TBTable->tb.fpr_saved + i + unwPPCF0Index, FPRegs[i]);
2514 
2515     // Restore GP registers.
2516     ptrToRegs = reinterpret_cast<char *>(FPRegs);
2517     uintptr_t *GPRegs = reinterpret_cast<uintptr_t *>(
2518         ptrToRegs - (TBTable->tb.gpr_saved * sizeof(uintptr_t)));
2519     for (int i = 0; i < TBTable->tb.gpr_saved; ++i)
2520       newRegisters.setRegister(32 - TBTable->tb.gpr_saved + i, GPRegs[i]);
2521 
2522     // Restore Vector registers.
2523     ptrToRegs = reinterpret_cast<char *>(GPRegs);
2524 
2525     // Restore vector registers only if this is a Clang frame. Also
2526     // check if traceback table bit has_vec is set. If it is, structure
2527     // vec_ext is available.
2528     if (_info.flags == frameType::frameWithEHInfo && TBTable->tb.has_vec) {
2529 
2530       // Get to the vec_ext structure to check if vector registers are saved.
2531       uint32_t *p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext);
2532 
2533       // Skip field parminfo if exists.
2534       if (TBTable->tb.fixedparms || TBTable->tb.floatparms)
2535         ++p;
2536 
2537       // Skip field tb_offset if exists.
2538       if (TBTable->tb.has_tboff)
2539         ++p;
2540 
2541       // Skip field hand_mask if exists.
2542       if (TBTable->tb.int_hndl)
2543         ++p;
2544 
2545       // Skip fields ctl_info and ctl_info_disp if exist.
2546       if (TBTable->tb.has_ctl) {
2547         // Skip field ctl_info.
2548         ++p;
2549         // Skip field ctl_info_disp.
2550         ++p;
2551       }
2552 
2553       // Skip fields name_len and name if exist.
2554       // p is supposed to point to field name_len now.
2555       uint8_t *charPtr = reinterpret_cast<uint8_t *>(p);
2556       if (TBTable->tb.name_present) {
2557         const uint16_t name_len = *(reinterpret_cast<uint16_t *>(charPtr));
2558         charPtr = charPtr + name_len + sizeof(uint16_t);
2559       }
2560 
2561       // Skip field alloc_reg if it exists.
2562       if (TBTable->tb.uses_alloca)
2563         ++charPtr;
2564 
2565       struct vec_ext *vec_ext = reinterpret_cast<struct vec_ext *>(charPtr);
2566 
2567       _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved);
2568 
2569       // Restore vector register(s) if saved on the stack.
2570       if (vec_ext->vr_saved) {
2571         // Saved vector registers are 16-byte aligned.
2572         if (reinterpret_cast<uintptr_t>(ptrToRegs) % 16)
2573           ptrToRegs -= reinterpret_cast<uintptr_t>(ptrToRegs) % 16;
2574         v128 *VecRegs = reinterpret_cast<v128 *>(ptrToRegs - vec_ext->vr_saved *
2575                                                                  sizeof(v128));
2576         for (int i = 0; i < vec_ext->vr_saved; ++i) {
2577           newRegisters.setVectorRegister(
2578               32 - vec_ext->vr_saved + i + unwPPCV0Index, VecRegs[i]);
2579         }
2580       }
2581     }
2582     if (TBTable->tb.saves_cr) {
2583       // Get the saved condition register. The condition register is only
2584       // a single word.
2585       newRegisters.setCR(
2586           *(reinterpret_cast<uint32_t *>(lastStack + sizeof(uintptr_t))));
2587     }
2588 
2589     // Restore the SP.
2590     newRegisters.setSP(lastStack);
2591 
2592     // The first instruction after return.
2593     uint32_t firstInstruction = *(reinterpret_cast<uint32_t *>(returnAddress));
2594 
2595     // Do we need to set the TOC register?
2596     _LIBUNWIND_TRACE_UNWINDING(
2597         "Current gpr2=%p",
2598         reinterpret_cast<void *>(newRegisters.getRegister(2)));
2599     if (firstInstruction == loadTOCRegInst) {
2600       _LIBUNWIND_TRACE_UNWINDING(
2601           "Set gpr2=%p from frame",
2602           reinterpret_cast<void *>(reinterpret_cast<pint_t *>(lastStack)[5]));
2603       newRegisters.setRegister(2, reinterpret_cast<pint_t *>(lastStack)[5]);
2604     }
2605   }
2606   _LIBUNWIND_TRACE_UNWINDING("lastStack=%p, returnAddress=%p, pc=%p\n",
2607                              reinterpret_cast<void *>(lastStack),
2608                              reinterpret_cast<void *>(returnAddress),
2609                              reinterpret_cast<void *>(pc));
2610 
2611   // The return address is the address after call site instruction, so
2612   // setting IP to that simulates a return.
2613   newRegisters.setIP(reinterpret_cast<uintptr_t>(returnAddress));
2614 
2615   // Simulate the step by replacing the register set with the new ones.
2616   registers = newRegisters;
2617 
2618   // Check if the next frame is a signal frame.
2619   pint_t nextStack = *(reinterpret_cast<pint_t *>(registers.getSP()));
2620 
2621   // Return address is the address after call site instruction.
2622   pint_t nextReturnAddress = reinterpret_cast<pint_t *>(nextStack)[2];
2623 
2624   if (nextReturnAddress > 0x01 && nextReturnAddress < 0x10000) {
2625     _LIBUNWIND_TRACE_UNWINDING("The next is a signal handler frame: "
2626                                "nextStack=%p, next return address=%p\n",
2627                                reinterpret_cast<void *>(nextStack),
2628                                reinterpret_cast<void *>(nextReturnAddress));
2629     isSignalFrame = true;
2630   } else {
2631     isSignalFrame = false;
2632   }
2633   return UNW_STEP_SUCCESS;
2634 }
2635 #endif // defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2636 
2637 template <typename A, typename R>
setInfoBasedOnIPRegister(bool isReturnAddress)2638 void UnwindCursor<A, R>::setInfoBasedOnIPRegister(bool isReturnAddress) {
2639 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) ||                               \
2640     defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
2641   _isSigReturn = false;
2642 #endif
2643 
2644   pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2645 #if defined(_LIBUNWIND_ARM_EHABI)
2646   // Remove the thumb bit so the IP represents the actual instruction address.
2647   // This matches the behaviour of _Unwind_GetIP on arm.
2648   pc &= (pint_t)~0x1;
2649 #endif
2650 
2651   // Exit early if at the top of the stack.
2652   if (pc == 0) {
2653     _unwindInfoMissing = true;
2654     return;
2655   }
2656 
2657   // If the last line of a function is a "throw" the compiler sometimes
2658   // emits no instructions after the call to __cxa_throw.  This means
2659   // the return address is actually the start of the next function.
2660   // To disambiguate this, back up the pc when we know it is a return
2661   // address.
2662   if (isReturnAddress)
2663 #if defined(_AIX)
2664     // PC needs to be a 4-byte aligned address to be able to look for a
2665     // word of 0 that indicates the start of the traceback table at the end
2666     // of a function on AIX.
2667     pc -= 4;
2668 #else
2669     --pc;
2670 #endif
2671 
2672 #if !(defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)) &&            \
2673     !defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2674   // In case of this is frame of signal handler, the IP saved in the signal
2675   // handler points to first non-executed instruction, while FDE/CIE expects IP
2676   // to be after the first non-executed instruction.
2677   if (_isSignalFrame)
2678     ++pc;
2679 #endif
2680 
2681   // Ask address space object to find unwind sections for this pc.
2682   UnwindInfoSections sects;
2683   if (_addressSpace.findUnwindSections(pc, sects)) {
2684 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2685     // If there is a compact unwind encoding table, look there first.
2686     if (sects.compact_unwind_section != 0) {
2687       if (this->getInfoFromCompactEncodingSection(pc, sects)) {
2688   #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2689         // Found info in table, done unless encoding says to use dwarf.
2690         uint32_t dwarfOffset;
2691         if ((sects.dwarf_section != 0) && compactSaysUseDwarf(&dwarfOffset)) {
2692           if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) {
2693             // found info in dwarf, done
2694             return;
2695           }
2696         }
2697   #endif
2698         // If unwind table has entry, but entry says there is no unwind info,
2699         // record that we have no unwind info.
2700         if (_info.format == 0)
2701           _unwindInfoMissing = true;
2702         return;
2703       }
2704     }
2705 #endif // defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
2706 
2707 #if defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
2708     // If there is SEH unwind info, look there next.
2709     if (this->getInfoFromSEH(pc))
2710       return;
2711 #endif
2712 
2713 #if defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
2714     // If there is unwind info in the traceback table, look there next.
2715     if (this->getInfoFromTBTable(pc, _registers))
2716       return;
2717 #endif
2718 
2719 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2720     // If there is dwarf unwind info, look there next.
2721     if (sects.dwarf_section != 0) {
2722       if (this->getInfoFromDwarfSection(pc, sects)) {
2723         // found info in dwarf, done
2724         return;
2725       }
2726     }
2727 #endif
2728 
2729 #if defined(_LIBUNWIND_ARM_EHABI)
2730     // If there is ARM EHABI unwind info, look there next.
2731     if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects))
2732       return;
2733 #endif
2734   }
2735 
2736 #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2737   // There is no static unwind info for this pc. Look to see if an FDE was
2738   // dynamically registered for it.
2739   pint_t cachedFDE = DwarfFDECache<A>::findFDE(DwarfFDECache<A>::kSearchAll,
2740                                                pc);
2741   if (cachedFDE != 0) {
2742     typename CFI_Parser<A>::FDE_Info fdeInfo;
2743     typename CFI_Parser<A>::CIE_Info cieInfo;
2744     if (!CFI_Parser<A>::decodeFDE(_addressSpace, cachedFDE, &fdeInfo, &cieInfo))
2745       if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))
2746         return;
2747   }
2748 
2749   // Lastly, ask AddressSpace object about platform specific ways to locate
2750   // other FDEs.
2751   pint_t fde;
2752   if (_addressSpace.findOtherFDE(pc, fde)) {
2753     typename CFI_Parser<A>::FDE_Info fdeInfo;
2754     typename CFI_Parser<A>::CIE_Info cieInfo;
2755     if (!CFI_Parser<A>::decodeFDE(_addressSpace, fde, &fdeInfo, &cieInfo)) {
2756       // Double check this FDE is for a function that includes the pc.
2757       if ((fdeInfo.pcStart <= pc) && (pc < fdeInfo.pcEnd))
2758         if (getInfoFromFdeCie(fdeInfo, cieInfo, pc, 0))
2759           return;
2760     }
2761   }
2762 #endif // #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
2763 
2764 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) ||                               \
2765     defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
2766   if (setInfoForSigReturn())
2767     return;
2768 #endif
2769 
2770   // no unwind info, flag that we can't reliably unwind
2771   _unwindInfoMissing = true;
2772 }
2773 
2774 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&                               \
2775     defined(_LIBUNWIND_TARGET_AARCH64)
2776 template <typename A, typename R>
setInfoForSigReturn(Registers_arm64 &)2777 bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_arm64 &) {
2778   // Look for the sigreturn trampoline. The trampoline's body is two
2779   // specific instructions (see below). Typically the trampoline comes from the
2780   // vDSO[1] (i.e. the __kernel_rt_sigreturn function). A libc might provide its
2781   // own restorer function, though, or user-mode QEMU might write a trampoline
2782   // onto the stack.
2783   //
2784   // This special code path is a fallback that is only used if the trampoline
2785   // lacks proper (e.g. DWARF) unwind info. On AArch64, a new DWARF register
2786   // constant for the PC needs to be defined before DWARF can handle a signal
2787   // trampoline. This code may segfault if the target PC is unreadable, e.g.:
2788   //  - The PC points at a function compiled without unwind info, and which is
2789   //    part of an execute-only mapping (e.g. using -Wl,--execute-only).
2790   //  - The PC is invalid and happens to point to unreadable or unmapped memory.
2791   //
2792   // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/vdso/sigreturn.S
2793   const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2794   // The PC might contain an invalid address if the unwind info is bad, so
2795   // directly accessing it could cause a SIGSEGV.
2796   if (!isReadableAddr(pc))
2797     return false;
2798   auto *instructions = reinterpret_cast<const uint32_t *>(pc);
2799   // Look for instructions: mov x8, #0x8b; svc #0x0
2800   if (instructions[0] != 0xd2801168 || instructions[1] != 0xd4000001)
2801     return false;
2802 
2803   _info = {};
2804   _info.start_ip = pc;
2805   _info.end_ip = pc + 4;
2806   _isSigReturn = true;
2807   return true;
2808 }
2809 
2810 template <typename A, typename R>
stepThroughSigReturn(Registers_arm64 &)2811 int UnwindCursor<A, R>::stepThroughSigReturn(Registers_arm64 &) {
2812   // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2813   //  - 128-byte siginfo struct
2814   //  - ucontext struct:
2815   //     - 8-byte long (uc_flags)
2816   //     - 8-byte pointer (uc_link)
2817   //     - 24-byte stack_t
2818   //     - 128-byte signal set
2819   //     - 8 bytes of padding because sigcontext has 16-byte alignment
2820   //     - sigcontext/mcontext_t
2821   // [1] https://github.com/torvalds/linux/blob/master/arch/arm64/kernel/signal.c
2822   const pint_t kOffsetSpToSigcontext = (128 + 8 + 8 + 24 + 128 + 8); // 304
2823 
2824   // Offsets from sigcontext to each register.
2825   const pint_t kOffsetGprs = 8; // offset to "__u64 regs[31]" field
2826   const pint_t kOffsetSp = 256; // offset to "__u64 sp" field
2827   const pint_t kOffsetPc = 264; // offset to "__u64 pc" field
2828 
2829   pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
2830 
2831   for (int i = 0; i <= 30; ++i) {
2832     uint64_t value = _addressSpace.get64(sigctx + kOffsetGprs +
2833                                          static_cast<pint_t>(i * 8));
2834     _registers.setRegister(UNW_AARCH64_X0 + i, value);
2835   }
2836   _registers.setSP(_addressSpace.get64(sigctx + kOffsetSp));
2837   _registers.setIP(_addressSpace.get64(sigctx + kOffsetPc));
2838   _isSignalFrame = true;
2839   return UNW_STEP_SUCCESS;
2840 }
2841 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2842        // defined(_LIBUNWIND_TARGET_AARCH64)
2843 
2844 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&                               \
2845     defined(_LIBUNWIND_TARGET_LOONGARCH)
2846 template <typename A, typename R>
setInfoForSigReturn(Registers_loongarch &)2847 bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_loongarch &) {
2848   const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
2849   // The PC might contain an invalid address if the unwind info is bad, so
2850   // directly accessing it could cause a SIGSEGV.
2851   if (!isReadableAddr(pc))
2852     return false;
2853   const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
2854   // Look for the two instructions used in the sigreturn trampoline
2855   // __vdso_rt_sigreturn:
2856   //
2857   // 0x03822c0b li a7,0x8b
2858   // 0x002b0000 syscall 0
2859   if (instructions[0] != 0x03822c0b || instructions[1] != 0x002b0000)
2860     return false;
2861 
2862   _info = {};
2863   _info.start_ip = pc;
2864   _info.end_ip = pc + 4;
2865   _isSigReturn = true;
2866   return true;
2867 }
2868 
2869 template <typename A, typename R>
stepThroughSigReturn(Registers_loongarch &)2870 int UnwindCursor<A, R>::stepThroughSigReturn(Registers_loongarch &) {
2871   // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2872   //  - 128-byte siginfo struct
2873   //  - ucontext_t struct:
2874   //     - 8-byte long (__uc_flags)
2875   //     - 8-byte pointer (*uc_link)
2876   //     - 24-byte uc_stack
2877   //     - 8-byte uc_sigmask
2878   //     - 120-byte of padding to allow sigset_t to be expanded in the future
2879   //     - 8 bytes of padding because sigcontext has 16-byte alignment
2880   //     - struct sigcontext uc_mcontext
2881   // [1]
2882   // https://github.com/torvalds/linux/blob/master/arch/loongarch/kernel/signal.c
2883   const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
2884 
2885   const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
2886   _registers.setIP(_addressSpace.get64(sigctx));
2887   for (int i = UNW_LOONGARCH_R1; i <= UNW_LOONGARCH_R31; ++i) {
2888     // skip R0
2889     uint64_t value =
2890         _addressSpace.get64(sigctx + static_cast<pint_t>((i + 1) * 8));
2891     _registers.setRegister(i, value);
2892   }
2893   _isSignalFrame = true;
2894   return UNW_STEP_SUCCESS;
2895 }
2896 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2897        // defined(_LIBUNWIND_TARGET_LOONGARCH)
2898 
2899 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&                               \
2900     defined(_LIBUNWIND_TARGET_RISCV)
2901 template <typename A, typename R>
setInfoForSigReturn(Registers_riscv &)2902 bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_riscv &) {
2903   const pint_t pc = static_cast<pint_t>(getReg(UNW_REG_IP));
2904   // The PC might contain an invalid address if the unwind info is bad, so
2905   // directly accessing it could cause a SIGSEGV.
2906   if (!isReadableAddr(pc))
2907     return false;
2908   const auto *instructions = reinterpret_cast<const uint32_t *>(pc);
2909   // Look for the two instructions used in the sigreturn trampoline
2910   // __vdso_rt_sigreturn:
2911   //
2912   // 0x08b00893 li a7,0x8b
2913   // 0x00000073 ecall
2914   if (instructions[0] != 0x08b00893 || instructions[1] != 0x00000073)
2915     return false;
2916 
2917   _info = {};
2918   _info.start_ip = pc;
2919   _info.end_ip = pc + 4;
2920   _isSigReturn = true;
2921   return true;
2922 }
2923 
2924 template <typename A, typename R>
stepThroughSigReturn(Registers_riscv &)2925 int UnwindCursor<A, R>::stepThroughSigReturn(Registers_riscv &) {
2926   // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
2927   //  - 128-byte siginfo struct
2928   //  - ucontext_t struct:
2929   //     - 8-byte long (__uc_flags)
2930   //     - 8-byte pointer (*uc_link)
2931   //     - 24-byte uc_stack
2932   //     - 8-byte uc_sigmask
2933   //     - 120-byte of padding to allow sigset_t to be expanded in the future
2934   //     - 8 bytes of padding because sigcontext has 16-byte alignment
2935   //     - struct sigcontext uc_mcontext
2936   // [1]
2937   // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
2938   const pint_t kOffsetSpToSigcontext = 128 + 8 + 8 + 24 + 8 + 128;
2939 
2940   const pint_t sigctx = _registers.getSP() + kOffsetSpToSigcontext;
2941   _registers.setIP(_addressSpace.get64(sigctx));
2942   for (int i = UNW_RISCV_X1; i <= UNW_RISCV_X31; ++i) {
2943     uint64_t value = _addressSpace.get64(sigctx + static_cast<pint_t>(i * 8));
2944     _registers.setRegister(i, value);
2945   }
2946   _isSignalFrame = true;
2947   return UNW_STEP_SUCCESS;
2948 }
2949 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
2950        // defined(_LIBUNWIND_TARGET_RISCV)
2951 
2952 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&                               \
2953     defined(_LIBUNWIND_TARGET_S390X)
2954 template <typename A, typename R>
setInfoForSigReturn(Registers_s390x &)2955 bool UnwindCursor<A, R>::setInfoForSigReturn(Registers_s390x &) {
2956   // Look for the sigreturn trampoline. The trampoline's body is a
2957   // specific instruction (see below). Typically the trampoline comes from the
2958   // vDSO (i.e. the __kernel_[rt_]sigreturn function). A libc might provide its
2959   // own restorer function, though, or user-mode QEMU might write a trampoline
2960   // onto the stack.
2961   const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2962   // The PC might contain an invalid address if the unwind info is bad, so
2963   // directly accessing it could cause a SIGSEGV.
2964   if (!isReadableAddr(pc))
2965     return false;
2966   const auto inst = *reinterpret_cast<const uint16_t *>(pc);
2967   if (inst == 0x0a77 || inst == 0x0aad) {
2968     _info = {};
2969     _info.start_ip = pc;
2970     _info.end_ip = pc + 2;
2971     _isSigReturn = true;
2972     return true;
2973   }
2974   return false;
2975 }
2976 
2977 template <typename A, typename R>
stepThroughSigReturn(Registers_s390x &)2978 int UnwindCursor<A, R>::stepThroughSigReturn(Registers_s390x &) {
2979   // Determine current SP.
2980   const pint_t sp = static_cast<pint_t>(this->getReg(UNW_REG_SP));
2981   // According to the s390x ABI, the CFA is at (incoming) SP + 160.
2982   const pint_t cfa = sp + 160;
2983 
2984   // Determine current PC and instruction there (this must be either
2985   // a "svc __NR_sigreturn" or "svc __NR_rt_sigreturn").
2986   const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
2987   const uint16_t inst = _addressSpace.get16(pc);
2988 
2989   // Find the addresses of the signo and sigcontext in the frame.
2990   pint_t pSigctx = 0;
2991   pint_t pSigno = 0;
2992 
2993   // "svc __NR_sigreturn" uses a non-RT signal trampoline frame.
2994   if (inst == 0x0a77) {
2995     // Layout of a non-RT signal trampoline frame, starting at the CFA:
2996     //  - 8-byte signal mask
2997     //  - 8-byte pointer to sigcontext, followed by signo
2998     //  - 4-byte signo
2999     pSigctx = _addressSpace.get64(cfa + 8);
3000     pSigno = pSigctx + 344;
3001   }
3002 
3003   // "svc __NR_rt_sigreturn" uses a RT signal trampoline frame.
3004   if (inst == 0x0aad) {
3005     // Layout of a RT signal trampoline frame, starting at the CFA:
3006     //  - 8-byte retcode (+ alignment)
3007     //  - 128-byte siginfo struct (starts with signo)
3008     //  - ucontext struct:
3009     //     - 8-byte long (uc_flags)
3010     //     - 8-byte pointer (uc_link)
3011     //     - 24-byte stack_t
3012     //     - 8 bytes of padding because sigcontext has 16-byte alignment
3013     //     - sigcontext/mcontext_t
3014     pSigctx = cfa + 8 + 128 + 8 + 8 + 24 + 8;
3015     pSigno = cfa + 8;
3016   }
3017 
3018   assert(pSigctx != 0);
3019   assert(pSigno != 0);
3020 
3021   // Offsets from sigcontext to each register.
3022   const pint_t kOffsetPc = 8;
3023   const pint_t kOffsetGprs = 16;
3024   const pint_t kOffsetFprs = 216;
3025 
3026   // Restore all registers.
3027   for (int i = 0; i < 16; ++i) {
3028     uint64_t value = _addressSpace.get64(pSigctx + kOffsetGprs +
3029                                          static_cast<pint_t>(i * 8));
3030     _registers.setRegister(UNW_S390X_R0 + i, value);
3031   }
3032   for (int i = 0; i < 16; ++i) {
3033     static const int fpr[16] = {
3034       UNW_S390X_F0, UNW_S390X_F1, UNW_S390X_F2, UNW_S390X_F3,
3035       UNW_S390X_F4, UNW_S390X_F5, UNW_S390X_F6, UNW_S390X_F7,
3036       UNW_S390X_F8, UNW_S390X_F9, UNW_S390X_F10, UNW_S390X_F11,
3037       UNW_S390X_F12, UNW_S390X_F13, UNW_S390X_F14, UNW_S390X_F15
3038     };
3039     double value = _addressSpace.getDouble(pSigctx + kOffsetFprs +
3040                                            static_cast<pint_t>(i * 8));
3041     _registers.setFloatRegister(fpr[i], value);
3042   }
3043   _registers.setIP(_addressSpace.get64(pSigctx + kOffsetPc));
3044 
3045   // SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
3046   // after the faulting instruction rather than before it.
3047   // Do not set _isSignalFrame in that case.
3048   uint32_t signo = _addressSpace.get32(pSigno);
3049   _isSignalFrame = (signo != 4 && signo != 5 && signo != 8);
3050 
3051   return UNW_STEP_SUCCESS;
3052 }
3053 #endif // defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) &&
3054        // defined(_LIBUNWIND_TARGET_S390X)
3055 
3056 #if defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3057 template <typename A, typename R>
setInfoForSigReturn()3058 bool UnwindCursor<A, R>::setInfoForSigReturn() {
3059   Dl_info dlinfo;
3060   const auto isSignalHandler = [&](pint_t addr) {
3061     if (!dladdr(reinterpret_cast<void *>(addr), &dlinfo))
3062       return false;
3063     if (strcmp(dlinfo.dli_fname, "commpage"))
3064       return false;
3065     if (dlinfo.dli_sname == NULL ||
3066         strcmp(dlinfo.dli_sname, "commpage_signal_handler"))
3067       return false;
3068     return true;
3069   };
3070 
3071   pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP));
3072   if (!isSignalHandler(pc))
3073     return false;
3074 
3075   pint_t start = reinterpret_cast<pint_t>(dlinfo.dli_saddr);
3076 
3077   static size_t signalHandlerSize = 0;
3078   if (signalHandlerSize == 0) {
3079     size_t boundLow = 0;
3080     size_t boundHigh = static_cast<size_t>(-1);
3081 
3082     area_info areaInfo;
3083     if (get_area_info(area_for(dlinfo.dli_saddr), &areaInfo) == B_OK)
3084       boundHigh = areaInfo.size;
3085 
3086     while (boundLow < boundHigh) {
3087       size_t boundMid = boundLow + ((boundHigh - boundLow) / 2);
3088       pint_t test = start + boundMid;
3089       if (test >= start && isSignalHandler(test))
3090         boundLow = boundMid + 1;
3091       else
3092         boundHigh = boundMid;
3093     }
3094 
3095     signalHandlerSize = boundHigh;
3096   }
3097 
3098   _info = {};
3099   _info.start_ip = start;
3100   _info.end_ip = start + signalHandlerSize;
3101   _isSigReturn = true;
3102 
3103   return true;
3104 }
3105 
3106 template <typename A, typename R>
stepThroughSigReturn()3107 int UnwindCursor<A, R>::stepThroughSigReturn() {
3108   _isSignalFrame = true;
3109 
3110 #if defined(_LIBUNWIND_TARGET_X86_64)
3111   // Layout of the stack before function call:
3112   // - signal_frame_data
3113   //   + siginfo_t    (public struct, fairly stable)
3114   //   + ucontext_t   (public struct, fairly stable)
3115   //     - mcontext_t -> Offset 0x70, this is what we want.
3116   // - frame->ip (8 bytes)
3117   // - frame->bp (8 bytes). Not written by the kernel,
3118   //   but the signal handler has a "push %rbp" instruction.
3119   pint_t bp = this->getReg(UNW_X86_64_RBP);
3120   vregs *regs = (vregs *)(bp + 0x70);
3121 
3122   _registers.setRegister(UNW_REG_IP, regs->rip);
3123   _registers.setRegister(UNW_REG_SP, regs->rsp);
3124   _registers.setRegister(UNW_X86_64_RAX, regs->rax);
3125   _registers.setRegister(UNW_X86_64_RDX, regs->rdx);
3126   _registers.setRegister(UNW_X86_64_RCX, regs->rcx);
3127   _registers.setRegister(UNW_X86_64_RBX, regs->rbx);
3128   _registers.setRegister(UNW_X86_64_RSI, regs->rsi);
3129   _registers.setRegister(UNW_X86_64_RDI, regs->rdi);
3130   _registers.setRegister(UNW_X86_64_RBP, regs->rbp);
3131   _registers.setRegister(UNW_X86_64_R8, regs->r8);
3132   _registers.setRegister(UNW_X86_64_R9, regs->r9);
3133   _registers.setRegister(UNW_X86_64_R10, regs->r10);
3134   _registers.setRegister(UNW_X86_64_R11, regs->r11);
3135   _registers.setRegister(UNW_X86_64_R12, regs->r12);
3136   _registers.setRegister(UNW_X86_64_R13, regs->r13);
3137   _registers.setRegister(UNW_X86_64_R14, regs->r14);
3138   _registers.setRegister(UNW_X86_64_R15, regs->r15);
3139   // TODO: XMM
3140 #endif // defined(_LIBUNWIND_TARGET_X86_64)
3141 
3142   return UNW_STEP_SUCCESS;
3143 }
3144 #endif // defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3145 
step(bool stage2)3146 template <typename A, typename R> int UnwindCursor<A, R>::step(bool stage2) {
3147   (void)stage2;
3148   // Bottom of stack is defined is when unwind info cannot be found.
3149   if (_unwindInfoMissing)
3150     return UNW_STEP_END;
3151 
3152   // Use unwinding info to modify register set as if function returned.
3153   int result;
3154 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN) ||                               \
3155     defined(_LIBUNWIND_CHECK_HAIKU_SIGRETURN)
3156   if (_isSigReturn) {
3157     result = this->stepThroughSigReturn();
3158   } else
3159 #endif
3160   {
3161 #if defined(_LIBUNWIND_SUPPORT_COMPACT_UNWIND)
3162     result = this->stepWithCompactEncoding(stage2);
3163 #elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND)
3164     result = this->stepWithSEHData();
3165 #elif defined(_LIBUNWIND_SUPPORT_TBTAB_UNWIND)
3166     result = this->stepWithTBTableData();
3167 #elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND)
3168     result = this->stepWithDwarfFDE(stage2);
3169 #elif defined(_LIBUNWIND_ARM_EHABI)
3170     result = this->stepWithEHABI();
3171 #else
3172   #error Need _LIBUNWIND_SUPPORT_COMPACT_UNWIND or \
3173               _LIBUNWIND_SUPPORT_SEH_UNWIND or \
3174               _LIBUNWIND_SUPPORT_DWARF_UNWIND or \
3175               _LIBUNWIND_ARM_EHABI
3176 #endif
3177   }
3178 
3179   // update info based on new PC
3180   if (result == UNW_STEP_SUCCESS) {
3181     this->setInfoBasedOnIPRegister(true);
3182     if (_unwindInfoMissing)
3183       return UNW_STEP_END;
3184   }
3185 
3186   return result;
3187 }
3188 
3189 template <typename A, typename R>
getInfo(unw_proc_info_t * info)3190 void UnwindCursor<A, R>::getInfo(unw_proc_info_t *info) {
3191   if (_unwindInfoMissing)
3192     memset(info, 0, sizeof(*info));
3193   else
3194     *info = _info;
3195 }
3196 
3197 template <typename A, typename R>
getFunctionName(char * buf,size_t bufLen,unw_word_t * offset)3198 bool UnwindCursor<A, R>::getFunctionName(char *buf, size_t bufLen,
3199                                                            unw_word_t *offset) {
3200   return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP),
3201                                          buf, bufLen, offset);
3202 }
3203 
3204 #if defined(_LIBUNWIND_CHECK_LINUX_SIGRETURN)
3205 template <typename A, typename R>
isReadableAddr(const pint_t addr) const3206 bool UnwindCursor<A, R>::isReadableAddr(const pint_t addr) const {
3207   // We use SYS_rt_sigprocmask, inspired by Abseil's AddressIsReadable.
3208 
3209   const auto sigsetAddr = reinterpret_cast<sigset_t *>(addr);
3210   // We have to check that addr is nullptr because sigprocmask allows that
3211   // as an argument without failure.
3212   if (!sigsetAddr)
3213     return false;
3214   const auto saveErrno = errno;
3215   // We MUST use a raw syscall here, as wrappers may try to access
3216   // sigsetAddr which may cause a SIGSEGV. A raw syscall however is
3217   // safe. Additionally, we need to pass the kernel_sigset_size, which is
3218   // different from libc sizeof(sigset_t). For the majority of architectures,
3219   // it's 64 bits (_NSIG), and libc NSIG is _NSIG + 1.
3220   const auto kernelSigsetSize = NSIG / 8;
3221   [[maybe_unused]] const int Result = syscall(
3222       SYS_rt_sigprocmask, /*how=*/~0, sigsetAddr, nullptr, kernelSigsetSize);
3223   // Because our "how" is invalid, this syscall should always fail, and our
3224   // errno should always be EINVAL or an EFAULT. This relies on the Linux
3225   // kernel to check copy_from_user before checking if the "how" argument is
3226   // invalid.
3227   assert(Result == -1);
3228   assert(errno == EFAULT || errno == EINVAL);
3229   const auto readable = errno != EFAULT;
3230   errno = saveErrno;
3231   return readable;
3232 }
3233 #endif
3234 
3235 #if defined(_LIBUNWIND_USE_CET) || defined(_LIBUNWIND_USE_GCS)
__libunwind_shstk_get_registers(unw_cursor_t * cursor)3236 extern "C" void *__libunwind_shstk_get_registers(unw_cursor_t *cursor) {
3237   AbstractUnwindCursor *co = (AbstractUnwindCursor *)cursor;
3238   return co->get_registers();
3239 }
3240 #endif
3241 } // namespace libunwind
3242 
3243 #endif // __UNWINDCURSOR_HPP__
3244