Lines Matching +full:early +full:- +full:to +full:- +full:mid

1 //===----------------------------------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 // C++ interface to lower levels of libunwind
9 //===----------------------------------------------------------------------===//
25 #include <mach-o/dyld.h>
52 #include "Unwind-EHABI.h"
57 // MinGW-w64 has always provided this struct.
99 static constexpr pint_t kSearchAll = static_cast<pint_t>(-1);
116 // These fields are all static to avoid needing an initializer.
157 if ((mh == p->mh) || (mh == kSearchAll)) { in findFDE()
158 if ((p->ip_start <= pc) && (pc < p->ip_end)) { in findFDE()
159 result = p->fde; in findFDE()
174 size_t oldSize = (size_t)(_bufferEnd - _buffer); in add()
185 _bufferUsed->mh = mh; in add()
186 _bufferUsed->ip_start = ip_start; in add()
187 _bufferUsed->ip_end = ip_end; in add()
188 _bufferUsed->fde = fde; in add()
205 if (s->mh != mh) { in removeAllIn()
227 (*func)(p->ip_start, p->ip_end, p->fde, p->mh); in iterateCacheEntries()
429 // This avoids an unnecessary dependency to libc++abi.
484 /// an unwind. This is normally stack-allocated inside a unw_cursor_t.
534 // next function instead. Decrement pc by 1 to fit inside the current in lookUpSEHUnwindInfo()
536 pc -= 1; in lookUpSEHUnwindInfo()
664 _msContext.D[i - UNW_ARM_D0] = d.w; in UnwindCursor()
668 _msContext.X[i - UNW_AARCH64_X0] = r.getRegister(i); in UnwindCursor()
672 _msContext.V[i - UNW_AARCH64_V0].D[0] = r.getFloatRegister(i); in UnwindCursor()
750 default: return _msContext.X[regNum - UNW_AARCH64_X0]; in getReg()
831 case UNW_AARCH64_LR: _msContext.X[regNum - UNW_ARM64_X0] = value; break; in setReg()
859 d.w = _msContext.S[regNum - UNW_ARM_S0]; in getFloatReg()
867 d.w = _msContext.D[regNum - UNW_ARM_D0]; in getFloatReg()
872 return _msContext.V[regNum - UNW_AARCH64_V0].D[0]; in getFloatReg()
888 _msContext.S[regNum - UNW_ARM_S0] = d.w; in setFloatReg()
896 _msContext.D[regNum - UNW_ARM_D0] = d.w; in setFloatReg()
900 _msContext.V[regNum - UNW_AARCH64_V0].D[0] = value; in setFloatReg()
1023 _addressSpace, (pint_t)this->getReg(UNW_REG_IP), in stepWithDwarfFDE()
1305 return stepWithTBTable(reinterpret_cast<pint_t>(this->getReg(UNW_REG_IP)), in stepWithTBTableData()
1424 _Self& operator--() { assert(_i > 0); --_i; return *this; } in operator --()
1425 _Self& operator-=(size_t a) { assert(_i >= a); _i -= a; return *this; } in operator -=()
1428 _Self operator-(size_t a) { assert(_i >= a); _Self out = *this; out._i -= a; return out; } in operator -()
1430 size_t operator-(const _Self& other) const { return _i - other._i; } in operator -()
1447 typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( in functionAddress()
1449 return indexAddr + signExtendPrel31(_addressSpace->get32(indexAddr)); in functionAddress()
1453 typename A::pint_t indexAddr = _sects->arm_section + arrayoffsetof( in dataAddress()
1471 size_t len = last - first; in EHABISectionUpperBound()
1479 len -= l2 + 1; in EHABISectionUpperBound()
1501 EHABISectionIterator<A> itThisPC = itNextPC - 1; in getInfoFromEHABISection()
1504 // If an exception is thrown from a function, corresponding to the last entry in getInfoFromEHABISection()
1505 // in the table, we don't really know the function extent and have to choose a in getInfoFromEHABISection()
1506 // value for nextPC. Choosing max() will allow the range check during trace to in getInfoFromEHABISection()
1537 // exceptionTableAddr -- exception handler table entry. in getInfoFromEHABISection()
1538 // exceptionTableData -- the data inside the first word of the eht entry. in getInfoFromEHABISection()
1539 // isSingleWordEHT -- whether the entry is in the index. in getInfoFromEHABISection()
1588 // +---- ehtp in getInfoFromEHABISection()
1590 // +--------------------------------------+ in getInfoFromEHABISection()
1591 // | +--------+--------+--------+-------+ | in getInfoFromEHABISection()
1592 // | |0| prel31 to personalityRoutine | | in getInfoFromEHABISection()
1593 // | +--------+--------+--------+-------+ | in getInfoFromEHABISection()
1594 // | | N | unwind opcodes | | <-- UnwindData in getInfoFromEHABISection()
1595 // | +--------+--------+--------+-------+ | in getInfoFromEHABISection()
1597 // | +--------+--------+--------+-------+ | in getInfoFromEHABISection()
1599 // | +--------+--------+--------+-------+ | in getInfoFromEHABISection()
1601 // | +--------+--------+--------+-------+ | in getInfoFromEHABISection()
1602 // | | LSDA | | <-- lsda in getInfoFromEHABISection()
1604 // | +--------+--------+--------+-------+ | in getInfoFromEHABISection()
1605 // +--------------------------------------+ in getInfoFromEHABISection()
1694 // Add to cache (to make next lookup faster) if we had no hint in getInfoFromDwarfSection()
1726 // do a binary search of top level index to find page with unwind info in getInfoFromCompactEncodingSection()
1727 pint_t targetFunctionOffset = pc - sects.dso_base; in getInfoFromCompactEncodingSection()
1733 uint32_t last = high - 1; in getInfoFromCompactEncodingSection()
1735 uint32_t mid = (low + high) / 2; in getInfoFromCompactEncodingSection() local
1736 //if ( log ) fprintf(stderr, "\tmid=%d, low=%d, high=%d, *mid=0x%08X\n", in getInfoFromCompactEncodingSection()
1737 //mid, low, high, topIndex.functionOffset(mid)); in getInfoFromCompactEncodingSection()
1738 if (topIndex.functionOffset(mid) <= targetFunctionOffset) { in getInfoFromCompactEncodingSection()
1739 if ((mid == last) || in getInfoFromCompactEncodingSection()
1740 (topIndex.functionOffset(mid + 1) > targetFunctionOffset)) { in getInfoFromCompactEncodingSection()
1741 low = mid; in getInfoFromCompactEncodingSection()
1744 low = mid + 1; in getInfoFromCompactEncodingSection()
1747 high = mid; in getInfoFromCompactEncodingSection()
1761 "to secondLevelAddr=0x%llX\n", in getInfoFromCompactEncodingSection()
1785 uint32_t mid = (low + high) / 2; in getInfoFromCompactEncodingSection() local
1786 if (pageIndex.functionOffset(mid) <= targetFunctionOffset) { in getInfoFromCompactEncodingSection()
1787 if (mid == (uint32_t)(pageHeader.entryCount() - 1)) { in getInfoFromCompactEncodingSection()
1789 low = mid; in getInfoFromCompactEncodingSection()
1792 } else if (pageIndex.functionOffset(mid + 1) > targetFunctionOffset) { in getInfoFromCompactEncodingSection()
1794 low = mid; in getInfoFromCompactEncodingSection()
1798 low = mid + 1; in getInfoFromCompactEncodingSection()
1801 high = mid; in getInfoFromCompactEncodingSection()
1829 (uint32_t)(targetFunctionOffset - firstLevelFunctionOffset); in getInfoFromCompactEncodingSection()
1837 last = pageHeader.entryCount() - 1; in getInfoFromCompactEncodingSection()
1840 uint32_t mid = (low + high) / 2; in getInfoFromCompactEncodingSection() local
1841 if (pageIndex.functionOffset(mid) <= targetFunctionPageOffset) { in getInfoFromCompactEncodingSection()
1842 if ((mid == last) || in getInfoFromCompactEncodingSection()
1843 (pageIndex.functionOffset(mid + 1) > targetFunctionPageOffset)) { in getInfoFromCompactEncodingSection()
1844 low = mid; in getInfoFromCompactEncodingSection()
1847 low = mid + 1; in getInfoFromCompactEncodingSection()
1850 high = mid; in getInfoFromCompactEncodingSection()
1885 encodingIndex - (uint16_t)sectionHeader.commonEncodingsArrayCount(); in getInfoFromCompactEncodingSection()
1900 uint32_t funcStartOffset = (uint32_t)(funcStart - sects.dso_base); in getInfoFromCompactEncodingSection()
1902 high = (uint32_t)(lsdaArrayEndAddr - lsdaArrayStartAddr) / in getInfoFromCompactEncodingSection()
1910 uint32_t mid = (low + high) / 2; in getInfoFromCompactEncodingSection() local
1911 if (lsdaIndex.functionOffset(mid) == funcStartOffset) { in getInfoFromCompactEncodingSection()
1912 lsda = lsdaIndex.lsdaOffset(mid) + sects.dso_base; in getInfoFromCompactEncodingSection()
1914 } else if (lsdaIndex.functionOffset(mid) < funcStartOffset) { in getInfoFromCompactEncodingSection()
1915 low = mid + 1; in getInfoFromCompactEncodingSection()
1917 high = mid; in getInfoFromCompactEncodingSection()
1932 --personalityIndex; // change 1-based to zero-based index in getInfoFromCompactEncodingSection()
1986 _info.start_ip = base + unwindEntry->BeginAddress; in getInfoFromSEH()
1988 _info.end_ip = base + unwindEntry->EndAddress; in getInfoFromSEH()
1991 UNWIND_INFO *xdata = reinterpret_cast<UNWIND_INFO *>(base + unwindEntry->UnwindData); in getInfoFromSEH()
1992 if (xdata->Flags & (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER)) { in getInfoFromSEH()
1996 // N.B. UNWIND_INFO structs are DWORD-aligned. in getInfoFromSEH()
1997 uint32_t lastcode = (xdata->CountOfCodes + 1) & ~1; in getInfoFromSEH()
1998 const uint32_t *handler = reinterpret_cast<uint32_t *>(&xdata->UnwindCodes[lastcode]); in getInfoFromSEH()
2065 if (!TBTable->tb.has_tboff) in getInfoFromTBTable()
2069 p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext); in getInfoFromTBTable()
2072 if (TBTable->tb.fixedparms || TBTable->tb.floatparms) in getInfoFromTBTable()
2075 // p now points to tb_offset, the offset from start of function to TB table. in getInfoFromTBTable()
2077 reinterpret_cast<unw_word_t>(TBTable) - *p - sizeof(uint32_t); in getInfoFromTBTable()
2086 if (TBTable->tb.int_hndl) in getInfoFromTBTable()
2093 if (TBTable->tb.lang == TB_CPLUSPLUS && TBTable->tb.has_ctl) { in getInfoFromTBTable()
2099 // p points to the offset of the state table into the stack. in getInfoFromTBTable()
2105 if (TBTable->tb.name_present) { in getInfoFromTBTable()
2111 if (TBTable->tb.uses_alloca) in getInfoFromTBTable()
2129 // is resolved dynamically using dlopen() to avoid hard dependency from in getInfoFromTBTable()
2132 // Resolve the function pointer to the state table personality if it has in getInfoFromTBTable()
2145 // The AIX dlopen() sets errno to 0 when it is successful, which in getInfoFromTBTable()
2147 // bug because according to POSIX it should not set errno to 0. To in getInfoFromTBTable()
2172 } else if (TBTable->tb.longtbtable) { in getInfoFromTBTable()
2175 // is not EH aware; or, 3) a frame of other languages. We need to figure out in getInfoFromTBTable()
2178 // We also need to deal with the complexity arising from some XL compiler in getInfoFromTBTable()
2180 // where the 'longtbtable' bit is meant to be the 'has_vec' bit and vice in getInfoFromTBTable()
2185 // 'struct tbtable_ext'. It is not really a structure but a dummy to in getInfoFromTBTable()
2203 // unsigned vr_saved:6; /* Number of non-volatile vector regs saved in getInfoFromTBTable()
2205 // /* first register saved is assumed to be */ in getInfoFromTBTable()
2206 // /* 32 - vr_saved */ in getInfoFromTBTable()
2212 // Here, the 7th bit is used as 'saves_vrsave'. To determine whether it in getInfoFromTBTable()
2216 // in the future to make sure the mitigation works. This mitigation in getInfoFromTBTable()
2223 // p points to field name len. in getInfoFromTBTable()
2227 if (TBTable->tb.name_present) { in getInfoFromTBTable()
2233 if (TBTable->tb.uses_alloca) in getInfoFromTBTable()
2237 if (TBTable->tb.has_vec) in getInfoFromTBTable()
2243 // charPtr points to field 'xtbtable'. Check if the EH info is available. in getInfoFromTBTable()
2256 // The pointer is 4-byte aligned. in getInfoFromTBTable()
2258 charPtr += 4 - reinterpret_cast<uintptr_t>(charPtr) % 4; in getInfoFromTBTable()
2264 // ehInfo points to structure en_info. The first member is version. in getInfoFromTBTable()
2269 // Increment ehInfo to point to member lsda. in getInfoFromTBTable()
2273 // enInfo now points to member personality. in getInfoFromTBTable()
2311 reinterpret_cast<void *>(registers.getSP()), TBTable->tb.saves_lr, in stepWithTBTable()
2312 TBTable->tb.stores_bc); in stepWithTBTable()
2316 // Instruction to reload TOC register "ld r2,40(r1)" in stepWithTBTable()
2321 // Instruction to reload TOC register "lwz r2,20(r1)" in stepWithTBTable()
2327 // lastStack points to the stack frame of the next routine up. in stepWithTBTable()
2337 if (!TBTable->tb.stores_bc) in stepWithTBTable()
2349 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar; in stepWithTBTable()
2356 returnAddress = sigContext->sc_jmpbuf.jmp_context.iar; in stepWithTBTable()
2367 "Seems to be a valid address", in stepWithTBTable()
2373 newRegisters.setCR(sigContext->sc_jmpbuf.jmp_context.cr); in stepWithTBTable()
2377 // to the caller of the leaf function. in stepWithTBTable()
2378 newRegisters.setLR(sigContext->sc_jmpbuf.jmp_context.lr); in stepWithTBTable()
2381 reinterpret_cast<void *>(sigContext->sc_jmpbuf.jmp_context.lr)); in stepWithTBTable()
2385 newRegisters.setRegister(i, sigContext->sc_jmpbuf.jmp_context.gpr[i]); in stepWithTBTable()
2390 sigContext->sc_jmpbuf.jmp_context.fpr[i]); in stepWithTBTable()
2394 if (sigContext->sc_jmpbuf.jmp_context.msr & __EXTCTX) { in stepWithTBTable()
2396 if (uContext->__extctx->__extctx_magic == __EXTCTX_MAGIC) { in stepWithTBTable()
2400 &(uContext->__extctx->__vmx.__vr[i])))); in stepWithTBTable()
2406 if (!TBTable->tb.saves_lr && registers.getLR()) { in stepWithTBTable()
2425 TBTable->tb.fpr_saved, TBTable->tb.gpr_saved, in stepWithTBTable()
2426 TBTable->tb.saves_cr); in stepWithTBTable()
2431 ptrToRegs - (TBTable->tb.fpr_saved * sizeof(double))); in stepWithTBTable()
2432 for (int i = 0; i < TBTable->tb.fpr_saved; ++i) in stepWithTBTable()
2434 32 - TBTable->tb.fpr_saved + i + unwPPCF0Index, FPRegs[i]); in stepWithTBTable()
2439 ptrToRegs - (TBTable->tb.gpr_saved * sizeof(uintptr_t))); in stepWithTBTable()
2440 for (int i = 0; i < TBTable->tb.gpr_saved; ++i) in stepWithTBTable()
2441 newRegisters.setRegister(32 - TBTable->tb.gpr_saved + i, GPRegs[i]); in stepWithTBTable()
2449 if (_info.flags == frameType::frameWithEHInfo && TBTable->tb.has_vec) { in stepWithTBTable()
2451 // Get to the vec_ext structure to check if vector registers are saved. in stepWithTBTable()
2452 uint32_t *p = reinterpret_cast<uint32_t *>(&TBTable->tb_ext); in stepWithTBTable()
2455 if (TBTable->tb.fixedparms || TBTable->tb.floatparms) in stepWithTBTable()
2459 if (TBTable->tb.has_tboff) in stepWithTBTable()
2463 if (TBTable->tb.int_hndl) in stepWithTBTable()
2467 if (TBTable->tb.has_ctl) { in stepWithTBTable()
2475 // p is supposed to point to field name_len now. in stepWithTBTable()
2477 if (TBTable->tb.name_present) { in stepWithTBTable()
2483 if (TBTable->tb.uses_alloca) in stepWithTBTable()
2488 _LIBUNWIND_TRACE_UNWINDING("vr_saved=%d", vec_ext->vr_saved); in stepWithTBTable()
2491 if (vec_ext->vr_saved) { in stepWithTBTable()
2492 // Saved vector registers are 16-byte aligned. in stepWithTBTable()
2494 ptrToRegs -= reinterpret_cast<uintptr_t>(ptrToRegs) % 16; in stepWithTBTable()
2495 v128 *VecRegs = reinterpret_cast<v128 *>(ptrToRegs - vec_ext->vr_saved * in stepWithTBTable()
2497 for (int i = 0; i < vec_ext->vr_saved; ++i) { in stepWithTBTable()
2499 32 - vec_ext->vr_saved + i + unwPPCV0Index, VecRegs[i]); in stepWithTBTable()
2503 if (TBTable->tb.saves_cr) { in stepWithTBTable()
2516 // Do we need to set the TOC register? in stepWithTBTable()
2533 // setting IP to that simulates a return. in stepWithTBTable()
2564 pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); in setInfoBasedOnIPRegister()
2571 // Exit early if at the top of the stack. in setInfoBasedOnIPRegister()
2578 // emits no instructions after the call to __cxa_throw. This means in setInfoBasedOnIPRegister()
2580 // To disambiguate this, back up the pc when we know it is a return in setInfoBasedOnIPRegister()
2584 // PC needs to be a 4-byte aligned address to be able to look for a in setInfoBasedOnIPRegister()
2587 pc -= 4; in setInfoBasedOnIPRegister()
2589 --pc; in setInfoBasedOnIPRegister()
2595 // handler points to first non-executed instruction, while FDE/CIE expects IP in setInfoBasedOnIPRegister()
2596 // to be after the first non-executed instruction. in setInfoBasedOnIPRegister()
2601 // Ask address space object to find unwind sections for this pc. in setInfoBasedOnIPRegister()
2607 if (this->getInfoFromCompactEncodingSection(pc, sects)) { in setInfoBasedOnIPRegister()
2609 // Found info in table, done unless encoding says to use dwarf. in setInfoBasedOnIPRegister()
2612 if (this->getInfoFromDwarfSection(pc, sects, dwarfOffset)) { in setInfoBasedOnIPRegister()
2629 if (this->getInfoFromSEH(pc)) in setInfoBasedOnIPRegister()
2635 if (this->getInfoFromTBTable(pc, _registers)) in setInfoBasedOnIPRegister()
2642 if (this->getInfoFromDwarfSection(pc, sects)) { in setInfoBasedOnIPRegister()
2651 if (sects.arm_section != 0 && this->getInfoFromEHABISection(pc, sects)) in setInfoBasedOnIPRegister()
2657 // There is no static unwind info for this pc. Look to see if an FDE was in setInfoBasedOnIPRegister()
2669 // Lastly, ask AddressSpace object about platform specific ways to locate in setInfoBasedOnIPRegister()
2700 // own restorer function, though, or user-mode QEMU might write a trampoline in setInfoForSigReturn()
2705 // constant for the PC needs to be defined before DWARF can handle a signal in setInfoForSigReturn()
2707 // - The PC points at a function compiled without unwind info, and which is in setInfoForSigReturn()
2708 // part of an execute-only mapping (e.g. using -Wl,--execute-only). in setInfoForSigReturn()
2709 // - The PC is invalid and happens to point to unreadable or unmapped memory. in setInfoForSigReturn()
2712 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); in setInfoForSigReturn()
2731 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is: in stepThroughSigReturn()
2732 // - 128-byte siginfo struct in stepThroughSigReturn()
2733 // - ucontext struct: in stepThroughSigReturn()
2734 // - 8-byte long (uc_flags) in stepThroughSigReturn()
2735 // - 8-byte pointer (uc_link) in stepThroughSigReturn()
2736 // - 24-byte stack_t in stepThroughSigReturn()
2737 // - 128-byte signal set in stepThroughSigReturn()
2738 // - 8 bytes of padding because sigcontext has 16-byte alignment in stepThroughSigReturn()
2739 // - sigcontext/mcontext_t in stepThroughSigReturn()
2743 // Offsets from sigcontext to each register. in stepThroughSigReturn()
2744 const pint_t kOffsetGprs = 8; // offset to "__u64 regs[31]" field in stepThroughSigReturn()
2745 const pint_t kOffsetSp = 256; // offset to "__u64 sp" field in stepThroughSigReturn()
2746 const pint_t kOffsetPc = 264; // offset to "__u64 pc" field in stepThroughSigReturn()
2790 // In the signal trampoline frame, sp points to an rt_sigframe[1], which is: in stepThroughSigReturn()
2791 // - 128-byte siginfo struct in stepThroughSigReturn()
2792 // - ucontext_t struct: in stepThroughSigReturn()
2793 // - 8-byte long (__uc_flags) in stepThroughSigReturn()
2794 // - 8-byte pointer (*uc_link) in stepThroughSigReturn()
2795 // - 24-byte uc_stack in stepThroughSigReturn()
2796 // - 8-byte uc_sigmask in stepThroughSigReturn()
2797 // - 120-byte of padding to allow sigset_t to be expanded in the future in stepThroughSigReturn()
2798 // - 8 bytes of padding because sigcontext has 16-byte alignment in stepThroughSigReturn()
2799 // - struct sigcontext uc_mcontext in stepThroughSigReturn()
2823 // own restorer function, though, or user-mode QEMU might write a trampoline in setInfoForSigReturn()
2825 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); in setInfoForSigReturn()
2844 const pint_t sp = static_cast<pint_t>(this->getReg(UNW_REG_SP)); in stepThroughSigReturn()
2845 // According to the s390x ABI, the CFA is at (incoming) SP + 160. in stepThroughSigReturn()
2850 const pint_t pc = static_cast<pint_t>(this->getReg(UNW_REG_IP)); in stepThroughSigReturn()
2857 // "svc __NR_sigreturn" uses a non-RT signal trampoline frame. in stepThroughSigReturn()
2859 // Layout of a non-RT signal trampoline frame, starting at the CFA: in stepThroughSigReturn()
2860 // - 8-byte signal mask in stepThroughSigReturn()
2861 // - 8-byte pointer to sigcontext, followed by signo in stepThroughSigReturn()
2862 // - 4-byte signo in stepThroughSigReturn()
2870 // - 8-byte retcode (+ alignment) in stepThroughSigReturn()
2871 // - 128-byte siginfo struct (starts with signo) in stepThroughSigReturn()
2872 // - ucontext struct: in stepThroughSigReturn()
2873 // - 8-byte long (uc_flags) in stepThroughSigReturn()
2874 // - 8-byte pointer (uc_link) in stepThroughSigReturn()
2875 // - 24-byte stack_t in stepThroughSigReturn()
2876 // - 8 bytes of padding because sigcontext has 16-byte alignment in stepThroughSigReturn()
2877 // - sigcontext/mcontext_t in stepThroughSigReturn()
2885 // Offsets from sigcontext to each register. in stepThroughSigReturn()
2926 // Use unwinding info to modify register set as if function returned. in step()
2930 result = this->stepThroughSigReturn(); in step()
2935 result = this->stepWithCompactEncoding(stage2); in step()
2937 result = this->stepWithSEHData(); in step()
2939 result = this->stepWithTBTableData(); in step()
2941 result = this->stepWithDwarfFDE(stage2); in step()
2943 result = this->stepWithEHABI(); in step()
2954 this->setInfoBasedOnIPRegister(true); in step()
2973 return _addressSpace.findFunctionName((pint_t)this->getReg(UNW_REG_IP), in getFunctionName()
2983 // We have to check that addr is nullptr because sigprocmask allows that in isReadableAddr()
2988 // We MUST use a raw syscall here, as wrappers may try to access in isReadableAddr()
2990 // safe. Additionally, we need to pass the kernel_sigset_size, which is in isReadableAddr()
2998 // kernel to check copy_from_user before checking if the "how" argument is in isReadableAddr()
3000 assert(Result == -1); in isReadableAddr()
3011 return co->get_registers(); in __libunwind_cet_get_registers()