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