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> 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> 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> 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> 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> 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: 263 UnwindSectionHeader(A &addressSpace, typename A::pint_t addr) 264 : _addressSpace(addressSpace), _addr(addr) {} 265 266 uint32_t version() const { 267 return _addressSpace.get32(_addr + 268 offsetof(unwind_info_section_header, version)); 269 } 270 uint32_t commonEncodingsArraySectionOffset() const { 271 return _addressSpace.get32(_addr + 272 offsetof(unwind_info_section_header, 273 commonEncodingsArraySectionOffset)); 274 } 275 uint32_t commonEncodingsArrayCount() const { 276 return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, 277 commonEncodingsArrayCount)); 278 } 279 uint32_t personalityArraySectionOffset() const { 280 return _addressSpace.get32(_addr + offsetof(unwind_info_section_header, 281 personalityArraySectionOffset)); 282 } 283 uint32_t personalityArrayCount() const { 284 return _addressSpace.get32( 285 _addr + offsetof(unwind_info_section_header, personalityArrayCount)); 286 } 287 uint32_t indexSectionOffset() const { 288 return _addressSpace.get32( 289 _addr + offsetof(unwind_info_section_header, indexSectionOffset)); 290 } 291 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: 303 UnwindSectionIndexArray(A &addressSpace, typename A::pint_t addr) 304 : _addressSpace(addressSpace), _addr(addr) {} 305 306 uint32_t functionOffset(uint32_t index) const { 307 return _addressSpace.get32( 308 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 309 functionOffset)); 310 } 311 uint32_t secondLevelPagesSectionOffset(uint32_t index) const { 312 return _addressSpace.get32( 313 _addr + arrayoffsetof(unwind_info_section_header_index_entry, index, 314 secondLevelPagesSectionOffset)); 315 } 316 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: 329 UnwindSectionRegularPageHeader(A &addressSpace, typename A::pint_t addr) 330 : _addressSpace(addressSpace), _addr(addr) {} 331 332 uint32_t kind() const { 333 return _addressSpace.get32( 334 _addr + offsetof(unwind_info_regular_second_level_page_header, kind)); 335 } 336 uint16_t entryPageOffset() const { 337 return _addressSpace.get16( 338 _addr + offsetof(unwind_info_regular_second_level_page_header, 339 entryPageOffset)); 340 } 341 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: 354 UnwindSectionRegularArray(A &addressSpace, typename A::pint_t addr) 355 : _addressSpace(addressSpace), _addr(addr) {} 356 357 uint32_t functionOffset(uint32_t index) const { 358 return _addressSpace.get32( 359 _addr + arrayoffsetof(unwind_info_regular_second_level_entry, index, 360 functionOffset)); 361 } 362 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: 375 UnwindSectionCompressedPageHeader(A &addressSpace, typename A::pint_t addr) 376 : _addressSpace(addressSpace), _addr(addr) {} 377 378 uint32_t kind() const { 379 return _addressSpace.get32( 380 _addr + 381 offsetof(unwind_info_compressed_second_level_page_header, kind)); 382 } 383 uint16_t entryPageOffset() const { 384 return _addressSpace.get16( 385 _addr + offsetof(unwind_info_compressed_second_level_page_header, 386 entryPageOffset)); 387 } 388 uint16_t entryCount() const { 389 return _addressSpace.get16( 390 _addr + 391 offsetof(unwind_info_compressed_second_level_page_header, entryCount)); 392 } 393 uint16_t encodingsPageOffset() const { 394 return _addressSpace.get16( 395 _addr + offsetof(unwind_info_compressed_second_level_page_header, 396 encodingsPageOffset)); 397 } 398 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: 411 UnwindSectionCompressedArray(A &addressSpace, typename A::pint_t addr) 412 : _addressSpace(addressSpace), _addr(addr) {} 413 414 uint32_t functionOffset(uint32_t index) const { 415 return UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET( 416 _addressSpace.get32(_addr + index * sizeof(uint32_t))); 417 } 418 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: 430 UnwindSectionLsdaArray(A &addressSpace, typename A::pint_t addr) 431 : _addressSpace(addressSpace), _addr(addr) {} 432 433 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 } 438 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. 454 void operator delete(void *, size_t) {} 455 456 virtual ~AbstractUnwindCursor() {} 457 virtual bool validReg(int) { _LIBUNWIND_ABORT("validReg not implemented"); } 458 virtual unw_word_t getReg(int) { _LIBUNWIND_ABORT("getReg not implemented"); } 459 virtual void setReg(int, unw_word_t) { 460 _LIBUNWIND_ABORT("setReg not implemented"); 461 } 462 virtual bool validFloatReg(int) { 463 _LIBUNWIND_ABORT("validFloatReg not implemented"); 464 } 465 virtual unw_fpreg_t getFloatReg(int) { 466 _LIBUNWIND_ABORT("getFloatReg not implemented"); 467 } 468 virtual void setFloatReg(int, unw_fpreg_t) { 469 _LIBUNWIND_ABORT("setFloatReg not implemented"); 470 } 471 virtual int step(bool = false) { _LIBUNWIND_ABORT("step not implemented"); } 472 virtual void getInfo(unw_proc_info_t *) { 473 _LIBUNWIND_ABORT("getInfo not implemented"); 474 } 475 virtual void jumpto() { _LIBUNWIND_ABORT("jumpto not implemented"); } 476 virtual bool isSignalFrame() { 477 _LIBUNWIND_ABORT("isSignalFrame not implemented"); 478 } 479 virtual bool getFunctionName(char *, size_t, unw_word_t *) { 480 _LIBUNWIND_ABORT("getFunctionName not implemented"); 481 } 482 virtual void setInfoBasedOnIPRegister(bool = false) { 483 _LIBUNWIND_ABORT("setInfoBasedOnIPRegister not implemented"); 484 } 485 virtual const char *getRegisterName(int) { 486 _LIBUNWIND_ABORT("getRegisterName not implemented"); 487 } 488 #ifdef __arm__ 489 virtual void saveVFPAsX() { _LIBUNWIND_ABORT("saveVFPAsX not implemented"); } 490 #endif 491 492 #ifdef _AIX 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) 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); 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 534 DISPATCHER_CONTEXT *getDispatcherContext() { return &_dispContext; } 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. 546 static void *operator new(size_t, UnwindCursor<A, R> *p) { return p; } 547 548 private: 549 550 pint_t getLastPC() const { return _dispContext.ControlPc; } 551 void setLastPC(pint_t pc) { _dispContext.ControlPc = pc; } 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); 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> 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> 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> 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> 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> 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> 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> 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> 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 932 template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { 933 RtlRestoreContext(&_msContext, nullptr); 934 } 935 936 #ifdef __arm__ 937 template <typename A, typename R> void UnwindCursor<A, R>::saveVFPAsX() {} 938 #endif 939 940 template <typename A, typename R> 941 const char *UnwindCursor<A, R>::getRegisterName(int regNum) { 942 return R::getRegisterName(regNum); 943 } 944 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); 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) 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. 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 §s); 993 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) 1010 bool setInfoForSigReturn() { 1011 R dummy; 1012 return setInfoForSigReturn(dummy); 1013 } 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 1035 template <typename Registers> bool setInfoForSigReturn(Registers &) { 1036 return false; 1037 } 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 §s, 1051 uint32_t fdeSectionOffsetHint=0); 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 §s); 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) 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) 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) 1086 int stepWithCompactEncoding(Registers_ppc &) { 1087 return UNW_EINVAL; 1088 } 1089 #endif 1090 1091 #if defined(_LIBUNWIND_TARGET_PPC64) 1092 int stepWithCompactEncoding(Registers_ppc64 &) { 1093 return UNW_EINVAL; 1094 } 1095 #endif 1096 1097 1098 #if defined(_LIBUNWIND_TARGET_AARCH64) 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) 1106 int stepWithCompactEncoding(Registers_mips_o32 &) { 1107 return UNW_EINVAL; 1108 } 1109 #endif 1110 1111 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) 1112 int stepWithCompactEncoding(Registers_mips_newabi &) { 1113 return UNW_EINVAL; 1114 } 1115 #endif 1116 1117 #if defined(_LIBUNWIND_TARGET_LOONGARCH) 1118 int stepWithCompactEncoding(Registers_loongarch &) { return UNW_EINVAL; } 1119 #endif 1120 1121 #if defined(_LIBUNWIND_TARGET_SPARC) 1122 int stepWithCompactEncoding(Registers_sparc &) { return UNW_EINVAL; } 1123 #endif 1124 1125 #if defined(_LIBUNWIND_TARGET_SPARC64) 1126 int stepWithCompactEncoding(Registers_sparc64 &) { return UNW_EINVAL; } 1127 #endif 1128 1129 #if defined (_LIBUNWIND_TARGET_RISCV) 1130 int stepWithCompactEncoding(Registers_riscv &) { 1131 return UNW_EINVAL; 1132 } 1133 #endif 1134 1135 bool compactSaysUseDwarf(uint32_t *offset=NULL) const { 1136 R dummy; 1137 return compactSaysUseDwarf(dummy, offset); 1138 } 1139 1140 #if defined(_LIBUNWIND_TARGET_X86_64) 1141 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) 1152 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) 1163 bool compactSaysUseDwarf(Registers_ppc &, uint32_t *) const { 1164 return true; 1165 } 1166 #endif 1167 1168 #if defined(_LIBUNWIND_TARGET_PPC64) 1169 bool compactSaysUseDwarf(Registers_ppc64 &, uint32_t *) const { 1170 return true; 1171 } 1172 #endif 1173 1174 #if defined(_LIBUNWIND_TARGET_AARCH64) 1175 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) 1186 bool compactSaysUseDwarf(Registers_mips_o32 &, uint32_t *) const { 1187 return true; 1188 } 1189 #endif 1190 1191 #if defined(_LIBUNWIND_TARGET_MIPS_NEWABI) 1192 bool compactSaysUseDwarf(Registers_mips_newabi &, uint32_t *) const { 1193 return true; 1194 } 1195 #endif 1196 1197 #if defined(_LIBUNWIND_TARGET_LOONGARCH) 1198 bool compactSaysUseDwarf(Registers_loongarch &, uint32_t *) const { 1199 return true; 1200 } 1201 #endif 1202 1203 #if defined(_LIBUNWIND_TARGET_SPARC) 1204 bool compactSaysUseDwarf(Registers_sparc &, uint32_t *) const { return true; } 1205 #endif 1206 1207 #if defined(_LIBUNWIND_TARGET_SPARC64) 1208 bool compactSaysUseDwarf(Registers_sparc64 &, uint32_t *) const { 1209 return true; 1210 } 1211 #endif 1212 1213 #if defined (_LIBUNWIND_TARGET_RISCV) 1214 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) 1222 compact_unwind_encoding_t dwarfEncoding() const { 1223 R dummy; 1224 return dwarfEncoding(dummy); 1225 } 1226 1227 #if defined(_LIBUNWIND_TARGET_X86_64) 1228 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) 1234 compact_unwind_encoding_t dwarfEncoding(Registers_x86 &) const { 1235 return UNWIND_X86_MODE_DWARF; 1236 } 1237 #endif 1238 1239 #if defined(_LIBUNWIND_TARGET_PPC) 1240 compact_unwind_encoding_t dwarfEncoding(Registers_ppc &) const { 1241 return 0; 1242 } 1243 #endif 1244 1245 #if defined(_LIBUNWIND_TARGET_PPC64) 1246 compact_unwind_encoding_t dwarfEncoding(Registers_ppc64 &) const { 1247 return 0; 1248 } 1249 #endif 1250 1251 #if defined(_LIBUNWIND_TARGET_AARCH64) 1252 compact_unwind_encoding_t dwarfEncoding(Registers_arm64 &) const { 1253 return UNWIND_ARM64_MODE_DWARF; 1254 } 1255 #endif 1256 1257 #if defined(_LIBUNWIND_TARGET_ARM) 1258 compact_unwind_encoding_t dwarfEncoding(Registers_arm &) const { 1259 return 0; 1260 } 1261 #endif 1262 1263 #if defined (_LIBUNWIND_TARGET_OR1K) 1264 compact_unwind_encoding_t dwarfEncoding(Registers_or1k &) const { 1265 return 0; 1266 } 1267 #endif 1268 1269 #if defined (_LIBUNWIND_TARGET_HEXAGON) 1270 compact_unwind_encoding_t dwarfEncoding(Registers_hexagon &) const { 1271 return 0; 1272 } 1273 #endif 1274 1275 #if defined (_LIBUNWIND_TARGET_MIPS_O32) 1276 compact_unwind_encoding_t dwarfEncoding(Registers_mips_o32 &) const { 1277 return 0; 1278 } 1279 #endif 1280 1281 #if defined (_LIBUNWIND_TARGET_MIPS_NEWABI) 1282 compact_unwind_encoding_t dwarfEncoding(Registers_mips_newabi &) const { 1283 return 0; 1284 } 1285 #endif 1286 1287 #if defined(_LIBUNWIND_TARGET_LOONGARCH) 1288 compact_unwind_encoding_t dwarfEncoding(Registers_loongarch &) const { 1289 return 0; 1290 } 1291 #endif 1292 1293 #if defined(_LIBUNWIND_TARGET_SPARC) 1294 compact_unwind_encoding_t dwarfEncoding(Registers_sparc &) const { return 0; } 1295 #endif 1296 1297 #if defined(_LIBUNWIND_TARGET_SPARC64) 1298 compact_unwind_encoding_t dwarfEncoding(Registers_sparc64 &) const { 1299 return 0; 1300 } 1301 #endif 1302 1303 #if defined (_LIBUNWIND_TARGET_RISCV) 1304 compact_unwind_encoding_t dwarfEncoding(Registers_riscv &) const { 1305 return 0; 1306 } 1307 #endif 1308 1309 #if defined (_LIBUNWIND_TARGET_S390X) 1310 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. 1320 pint_t getLastPC() const { /* FIXME: Implement */ return 0; } 1321 void setLastPC(pint_t pc) { /* FIXME: Implement */ } 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); 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 ®isters); 1333 int stepWithTBTable(pint_t pc, tbtable *TBTable, R ®isters, 1334 bool &isSignalFrame); 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> 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> 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> 1375 bool UnwindCursor<A, R>::validReg(int regNum) { 1376 return _registers.validRegister(regNum); 1377 } 1378 1379 template <typename A, typename R> 1380 unw_word_t UnwindCursor<A, R>::getReg(int regNum) { 1381 return _registers.getRegister(regNum); 1382 } 1383 1384 template <typename A, typename R> 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> 1390 bool UnwindCursor<A, R>::validFloatReg(int regNum) { 1391 return _registers.validFloatRegister(regNum); 1392 } 1393 1394 template <typename A, typename R> 1395 unw_fpreg_t UnwindCursor<A, R>::getFloatReg(int regNum) { 1396 return _registers.getFloatRegister(regNum); 1397 } 1398 1399 template <typename A, typename R> 1400 void UnwindCursor<A, R>::setFloatReg(int regNum, unw_fpreg_t value) { 1401 _registers.setFloatRegister(regNum, value); 1402 } 1403 1404 template <typename A, typename R> void UnwindCursor<A, R>::jumpto() { 1405 _registers.jumpto(); 1406 } 1407 1408 #ifdef __arm__ 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> 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> 1422 const char *UnwindCursor<A, R>::getRegisterName(int regNum) { 1423 return _registers.getRegisterName(regNum); 1424 } 1425 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 1443 static _Self begin(A& addressSpace, const UnwindInfoSections& sects) { 1444 return _Self(addressSpace, sects, 0); 1445 } 1446 static _Self end(A& addressSpace, const UnwindInfoSections& sects) { 1447 return _Self(addressSpace, sects, 1448 sects.arm_section_length / sizeof(EHABIIndexEntry)); 1449 } 1450 1451 EHABISectionIterator(A& addressSpace, const UnwindInfoSections& sects, size_t i) 1452 : _i(i), _addressSpace(&addressSpace), _sects(§s) {} 1453 1454 _Self& operator++() { ++_i; return *this; } 1455 _Self& operator+=(size_t a) { _i += a; return *this; } 1456 _Self& operator--() { assert(_i > 0); --_i; return *this; } 1457 _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; } 1458 1459 _Self operator+(size_t a) { _Self out = *this; out._i += a; return out; } 1460 _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } 1461 1462 size_t operator-(const _Self& other) const { return _i - other._i; } 1463 1464 bool operator==(const _Self& other) const { 1465 assert(_addressSpace == other._addressSpace); 1466 assert(_sects == other._sects); 1467 return _i == other._i; 1468 } 1469 1470 bool operator!=(const _Self& other) const { 1471 assert(_addressSpace == other._addressSpace); 1472 assert(_sects == other._sects); 1473 return _i != other._i; 1474 } 1475 1476 typename A::pint_t operator*() const { return functionAddress(); } 1477 1478 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 1484 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> 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> 1520 bool UnwindCursor<A, R>::getInfoFromEHABISection( 1521 pint_t pc, 1522 const UnwindInfoSections §s) { 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> 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> 1686 bool UnwindCursor<A, R>::getInfoFromDwarfSection(pint_t pc, 1687 const UnwindInfoSections §s, 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> 1746 bool UnwindCursor<A, R>::getInfoFromCompactEncodingSection(pint_t pc, 1747 const UnwindInfoSections §s) { 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> 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> 2129 bool UnwindCursor<A, R>::getInfoFromTBTable(pint_t pc, R ®isters) { 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> 2376 int UnwindCursor<A, R>::stepWithTBTable(pint_t pc, tbtable *TBTable, 2377 R ®isters, 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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 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> 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> 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> 3206 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) 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