Buckets:
arudradey/ml-cpu-storage / emsdk /upstream /emscripten /system /lib /libunwind /src /CompactUnwinder.hpp
| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| // | |
| // Does runtime stack unwinding using compact unwind encodings. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| namespace libunwind { | |
| /// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka | |
| /// unwind) by modifying a Registers_x86 register set | |
| template <typename A> | |
| class CompactUnwinder_x86 { | |
| public: | |
| static int stepWithCompactEncoding(compact_unwind_encoding_t info, | |
| uint32_t functionStart, A &addressSpace, | |
| Registers_x86 ®isters); | |
| private: | |
| typename A::pint_t pint_t; | |
| static void frameUnwind(A &addressSpace, Registers_x86 ®isters); | |
| static void framelessUnwind(A &addressSpace, | |
| typename A::pint_t returnAddressLocation, | |
| Registers_x86 ®isters); | |
| static int | |
| stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding, | |
| uint32_t functionStart, A &addressSpace, | |
| Registers_x86 ®isters); | |
| static int stepWithCompactEncodingFrameless( | |
| compact_unwind_encoding_t compactEncoding, uint32_t functionStart, | |
| A &addressSpace, Registers_x86 ®isters, bool indirectStackSize); | |
| }; | |
| template <typename A> | |
| int CompactUnwinder_x86<A>::stepWithCompactEncoding( | |
| compact_unwind_encoding_t compactEncoding, uint32_t functionStart, | |
| A &addressSpace, Registers_x86 ®isters) { | |
| switch (compactEncoding & UNWIND_X86_MODE_MASK) { | |
| case UNWIND_X86_MODE_EBP_FRAME: | |
| return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart, | |
| addressSpace, registers); | |
| case UNWIND_X86_MODE_STACK_IMMD: | |
| return stepWithCompactEncodingFrameless(compactEncoding, functionStart, | |
| addressSpace, registers, false); | |
| case UNWIND_X86_MODE_STACK_IND: | |
| return stepWithCompactEncodingFrameless(compactEncoding, functionStart, | |
| addressSpace, registers, true); | |
| } | |
| _LIBUNWIND_ABORT("invalid compact unwind encoding"); | |
| } | |
| template <typename A> | |
| int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame( | |
| compact_unwind_encoding_t compactEncoding, uint32_t functionStart, | |
| A &addressSpace, Registers_x86 ®isters) { | |
| uint32_t savedRegistersOffset = | |
| EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET); | |
| uint32_t savedRegistersLocations = | |
| EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS); | |
| uint32_t savedRegisters = registers.getEBP() - 4 * savedRegistersOffset; | |
| for (int i = 0; i < 5; ++i) { | |
| switch (savedRegistersLocations & 0x7) { | |
| case UNWIND_X86_REG_NONE: | |
| // no register saved in this slot | |
| break; | |
| case UNWIND_X86_REG_EBX: | |
| registers.setEBX(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_ECX: | |
| registers.setECX(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_EDX: | |
| registers.setEDX(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_EDI: | |
| registers.setEDI(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_ESI: | |
| registers.setESI(addressSpace.get32(savedRegisters)); | |
| break; | |
| default: | |
| (void)functionStart; | |
| _LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for " | |
| "function starting at 0x%X", | |
| compactEncoding, functionStart); | |
| _LIBUNWIND_ABORT("invalid compact unwind encoding"); | |
| } | |
| savedRegisters += 4; | |
| savedRegistersLocations = (savedRegistersLocations >> 3); | |
| } | |
| frameUnwind(addressSpace, registers); | |
| return UNW_STEP_SUCCESS; | |
| } | |
| template <typename A> | |
| int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless( | |
| compact_unwind_encoding_t encoding, uint32_t functionStart, | |
| A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) { | |
| uint32_t stackSizeEncoded = | |
| EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE); | |
| uint32_t stackAdjust = | |
| EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST); | |
| uint32_t regCount = | |
| EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT); | |
| uint32_t permutation = | |
| EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION); | |
| uint32_t stackSize = stackSizeEncoded * 4; | |
| if (indirectStackSize) { | |
| // stack size is encoded in subl $xxx,%esp instruction | |
| uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); | |
| stackSize = subl + 4 * stackAdjust; | |
| } | |
| // decompress permutation | |
| uint32_t permunreg[6]; | |
| switch (regCount) { | |
| case 6: | |
| permunreg[0] = permutation / 120; | |
| permutation -= (permunreg[0] * 120); | |
| permunreg[1] = permutation / 24; | |
| permutation -= (permunreg[1] * 24); | |
| permunreg[2] = permutation / 6; | |
| permutation -= (permunreg[2] * 6); | |
| permunreg[3] = permutation / 2; | |
| permutation -= (permunreg[3] * 2); | |
| permunreg[4] = permutation; | |
| permunreg[5] = 0; | |
| break; | |
| case 5: | |
| permunreg[0] = permutation / 120; | |
| permutation -= (permunreg[0] * 120); | |
| permunreg[1] = permutation / 24; | |
| permutation -= (permunreg[1] * 24); | |
| permunreg[2] = permutation / 6; | |
| permutation -= (permunreg[2] * 6); | |
| permunreg[3] = permutation / 2; | |
| permutation -= (permunreg[3] * 2); | |
| permunreg[4] = permutation; | |
| break; | |
| case 4: | |
| permunreg[0] = permutation / 60; | |
| permutation -= (permunreg[0] * 60); | |
| permunreg[1] = permutation / 12; | |
| permutation -= (permunreg[1] * 12); | |
| permunreg[2] = permutation / 3; | |
| permutation -= (permunreg[2] * 3); | |
| permunreg[3] = permutation; | |
| break; | |
| case 3: | |
| permunreg[0] = permutation / 20; | |
| permutation -= (permunreg[0] * 20); | |
| permunreg[1] = permutation / 4; | |
| permutation -= (permunreg[1] * 4); | |
| permunreg[2] = permutation; | |
| break; | |
| case 2: | |
| permunreg[0] = permutation / 5; | |
| permutation -= (permunreg[0] * 5); | |
| permunreg[1] = permutation; | |
| break; | |
| case 1: | |
| permunreg[0] = permutation; | |
| break; | |
| } | |
| // re-number registers back to standard numbers | |
| int registersSaved[6]; | |
| bool used[7] = { false, false, false, false, false, false, false }; | |
| for (uint32_t i = 0; i < regCount; ++i) { | |
| uint32_t renum = 0; | |
| for (int u = 1; u < 7; ++u) { | |
| if (!used[u]) { | |
| if (renum == permunreg[i]) { | |
| registersSaved[i] = u; | |
| used[u] = true; | |
| break; | |
| } | |
| ++renum; | |
| } | |
| } | |
| } | |
| uint32_t savedRegisters = registers.getSP() + stackSize - 4 - 4 * regCount; | |
| for (uint32_t i = 0; i < regCount; ++i) { | |
| switch (registersSaved[i]) { | |
| case UNWIND_X86_REG_EBX: | |
| registers.setEBX(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_ECX: | |
| registers.setECX(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_EDX: | |
| registers.setEDX(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_EDI: | |
| registers.setEDI(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_ESI: | |
| registers.setESI(addressSpace.get32(savedRegisters)); | |
| break; | |
| case UNWIND_X86_REG_EBP: | |
| registers.setEBP(addressSpace.get32(savedRegisters)); | |
| break; | |
| default: | |
| _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " | |
| "function starting at 0x%X", | |
| encoding, functionStart); | |
| _LIBUNWIND_ABORT("invalid compact unwind encoding"); | |
| } | |
| savedRegisters += 4; | |
| } | |
| framelessUnwind(addressSpace, savedRegisters, registers); | |
| return UNW_STEP_SUCCESS; | |
| } | |
| template <typename A> | |
| void CompactUnwinder_x86<A>::frameUnwind(A &addressSpace, | |
| Registers_x86 ®isters) { | |
| typename A::pint_t bp = registers.getEBP(); | |
| // ebp points to old ebp | |
| registers.setEBP(addressSpace.get32(bp)); | |
| // old esp is ebp less saved ebp and return address | |
| registers.setSP((uint32_t)bp + 8); | |
| // pop return address into eip | |
| registers.setIP(addressSpace.get32(bp + 4)); | |
| } | |
| template <typename A> | |
| void CompactUnwinder_x86<A>::framelessUnwind( | |
| A &addressSpace, typename A::pint_t returnAddressLocation, | |
| Registers_x86 ®isters) { | |
| // return address is on stack after last saved register | |
| registers.setIP(addressSpace.get32(returnAddressLocation)); | |
| // old esp is before return address | |
| registers.setSP((uint32_t)returnAddressLocation + 4); | |
| } | |
| /// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka | |
| /// unwind) by modifying a Registers_x86_64 register set | |
| template <typename A> | |
| class CompactUnwinder_x86_64 { | |
| public: | |
| static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, | |
| uint64_t functionStart, A &addressSpace, | |
| Registers_x86_64 ®isters); | |
| private: | |
| typename A::pint_t pint_t; | |
| static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters); | |
| static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation, | |
| Registers_x86_64 ®isters); | |
| static int | |
| stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding, | |
| uint64_t functionStart, A &addressSpace, | |
| Registers_x86_64 ®isters); | |
| static int stepWithCompactEncodingFrameless( | |
| compact_unwind_encoding_t compactEncoding, uint64_t functionStart, | |
| A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize); | |
| }; | |
| template <typename A> | |
| int CompactUnwinder_x86_64<A>::stepWithCompactEncoding( | |
| compact_unwind_encoding_t compactEncoding, uint64_t functionStart, | |
| A &addressSpace, Registers_x86_64 ®isters) { | |
| switch (compactEncoding & UNWIND_X86_64_MODE_MASK) { | |
| case UNWIND_X86_64_MODE_RBP_FRAME: | |
| return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart, | |
| addressSpace, registers); | |
| case UNWIND_X86_64_MODE_STACK_IMMD: | |
| return stepWithCompactEncodingFrameless(compactEncoding, functionStart, | |
| addressSpace, registers, false); | |
| case UNWIND_X86_64_MODE_STACK_IND: | |
| return stepWithCompactEncodingFrameless(compactEncoding, functionStart, | |
| addressSpace, registers, true); | |
| } | |
| _LIBUNWIND_ABORT("invalid compact unwind encoding"); | |
| } | |
| template <typename A> | |
| int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame( | |
| compact_unwind_encoding_t compactEncoding, uint64_t functionStart, | |
| A &addressSpace, Registers_x86_64 ®isters) { | |
| uint32_t savedRegistersOffset = | |
| EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET); | |
| uint32_t savedRegistersLocations = | |
| EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS); | |
| uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset; | |
| for (int i = 0; i < 5; ++i) { | |
| switch (savedRegistersLocations & 0x7) { | |
| case UNWIND_X86_64_REG_NONE: | |
| // no register saved in this slot | |
| break; | |
| case UNWIND_X86_64_REG_RBX: | |
| registers.setRBX(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R12: | |
| registers.setR12(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R13: | |
| registers.setR13(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R14: | |
| registers.setR14(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R15: | |
| registers.setR15(addressSpace.get64(savedRegisters)); | |
| break; | |
| default: | |
| (void)functionStart; | |
| _LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for " | |
| "function starting at 0x%llX", | |
| compactEncoding, functionStart); | |
| _LIBUNWIND_ABORT("invalid compact unwind encoding"); | |
| } | |
| savedRegisters += 8; | |
| savedRegistersLocations = (savedRegistersLocations >> 3); | |
| } | |
| frameUnwind(addressSpace, registers); | |
| return UNW_STEP_SUCCESS; | |
| } | |
| template <typename A> | |
| int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless( | |
| compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace, | |
| Registers_x86_64 ®isters, bool indirectStackSize) { | |
| uint32_t stackSizeEncoded = | |
| EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE); | |
| uint32_t stackAdjust = | |
| EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST); | |
| uint32_t regCount = | |
| EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT); | |
| uint32_t permutation = | |
| EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION); | |
| uint32_t stackSize = stackSizeEncoded * 8; | |
| if (indirectStackSize) { | |
| // stack size is encoded in subl $xxx,%esp instruction | |
| uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded); | |
| stackSize = subl + 8 * stackAdjust; | |
| } | |
| // decompress permutation | |
| uint32_t permunreg[6]; | |
| switch (regCount) { | |
| case 6: | |
| permunreg[0] = permutation / 120; | |
| permutation -= (permunreg[0] * 120); | |
| permunreg[1] = permutation / 24; | |
| permutation -= (permunreg[1] * 24); | |
| permunreg[2] = permutation / 6; | |
| permutation -= (permunreg[2] * 6); | |
| permunreg[3] = permutation / 2; | |
| permutation -= (permunreg[3] * 2); | |
| permunreg[4] = permutation; | |
| permunreg[5] = 0; | |
| break; | |
| case 5: | |
| permunreg[0] = permutation / 120; | |
| permutation -= (permunreg[0] * 120); | |
| permunreg[1] = permutation / 24; | |
| permutation -= (permunreg[1] * 24); | |
| permunreg[2] = permutation / 6; | |
| permutation -= (permunreg[2] * 6); | |
| permunreg[3] = permutation / 2; | |
| permutation -= (permunreg[3] * 2); | |
| permunreg[4] = permutation; | |
| break; | |
| case 4: | |
| permunreg[0] = permutation / 60; | |
| permutation -= (permunreg[0] * 60); | |
| permunreg[1] = permutation / 12; | |
| permutation -= (permunreg[1] * 12); | |
| permunreg[2] = permutation / 3; | |
| permutation -= (permunreg[2] * 3); | |
| permunreg[3] = permutation; | |
| break; | |
| case 3: | |
| permunreg[0] = permutation / 20; | |
| permutation -= (permunreg[0] * 20); | |
| permunreg[1] = permutation / 4; | |
| permutation -= (permunreg[1] * 4); | |
| permunreg[2] = permutation; | |
| break; | |
| case 2: | |
| permunreg[0] = permutation / 5; | |
| permutation -= (permunreg[0] * 5); | |
| permunreg[1] = permutation; | |
| break; | |
| case 1: | |
| permunreg[0] = permutation; | |
| break; | |
| } | |
| // re-number registers back to standard numbers | |
| int registersSaved[6]; | |
| bool used[7] = { false, false, false, false, false, false, false }; | |
| for (uint32_t i = 0; i < regCount; ++i) { | |
| uint32_t renum = 0; | |
| for (int u = 1; u < 7; ++u) { | |
| if (!used[u]) { | |
| if (renum == permunreg[i]) { | |
| registersSaved[i] = u; | |
| used[u] = true; | |
| break; | |
| } | |
| ++renum; | |
| } | |
| } | |
| } | |
| uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount; | |
| for (uint32_t i = 0; i < regCount; ++i) { | |
| switch (registersSaved[i]) { | |
| case UNWIND_X86_64_REG_RBX: | |
| registers.setRBX(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R12: | |
| registers.setR12(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R13: | |
| registers.setR13(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R14: | |
| registers.setR14(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_R15: | |
| registers.setR15(addressSpace.get64(savedRegisters)); | |
| break; | |
| case UNWIND_X86_64_REG_RBP: | |
| registers.setRBP(addressSpace.get64(savedRegisters)); | |
| break; | |
| default: | |
| _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for " | |
| "function starting at 0x%llX", | |
| encoding, functionStart); | |
| _LIBUNWIND_ABORT("invalid compact unwind encoding"); | |
| } | |
| savedRegisters += 8; | |
| } | |
| framelessUnwind(addressSpace, savedRegisters, registers); | |
| return UNW_STEP_SUCCESS; | |
| } | |
| template <typename A> | |
| void CompactUnwinder_x86_64<A>::frameUnwind(A &addressSpace, | |
| Registers_x86_64 ®isters) { | |
| uint64_t rbp = registers.getRBP(); | |
| // ebp points to old ebp | |
| registers.setRBP(addressSpace.get64(rbp)); | |
| // old esp is ebp less saved ebp and return address | |
| registers.setSP(rbp + 16); | |
| // pop return address into eip | |
| registers.setIP(addressSpace.get64(rbp + 8)); | |
| } | |
| template <typename A> | |
| void CompactUnwinder_x86_64<A>::framelessUnwind(A &addressSpace, | |
| uint64_t returnAddressLocation, | |
| Registers_x86_64 ®isters) { | |
| // return address is on stack after last saved register | |
| registers.setIP(addressSpace.get64(returnAddressLocation)); | |
| // old esp is before return address | |
| registers.setSP(returnAddressLocation + 8); | |
| } | |
| /// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka | |
| /// unwind) by modifying a Registers_arm64 register set | |
| template <typename A> | |
| class CompactUnwinder_arm64 { | |
| public: | |
| static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding, | |
| uint64_t functionStart, A &addressSpace, | |
| Registers_arm64 ®isters); | |
| private: | |
| typename A::pint_t pint_t; | |
| static int | |
| stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding, | |
| uint64_t functionStart, A &addressSpace, | |
| Registers_arm64 ®isters); | |
| static int stepWithCompactEncodingFrameless( | |
| compact_unwind_encoding_t compactEncoding, uint64_t functionStart, | |
| A &addressSpace, Registers_arm64 ®isters); | |
| }; | |
| template <typename A> | |
| int CompactUnwinder_arm64<A>::stepWithCompactEncoding( | |
| compact_unwind_encoding_t compactEncoding, uint64_t functionStart, | |
| A &addressSpace, Registers_arm64 ®isters) { | |
| switch (compactEncoding & UNWIND_ARM64_MODE_MASK) { | |
| case UNWIND_ARM64_MODE_FRAME: | |
| return stepWithCompactEncodingFrame(compactEncoding, functionStart, | |
| addressSpace, registers); | |
| case UNWIND_ARM64_MODE_FRAMELESS: | |
| return stepWithCompactEncodingFrameless(compactEncoding, functionStart, | |
| addressSpace, registers); | |
| } | |
| _LIBUNWIND_ABORT("invalid compact unwind encoding"); | |
| } | |
| template <typename A> | |
| int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless( | |
| compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, | |
| Registers_arm64 ®isters) { | |
| uint32_t stackSize = | |
| 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK); | |
| uint64_t savedRegisterLoc = registers.getSP() + stackSize; | |
| if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V8, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V9, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V10, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V11, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V12, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V13, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V14, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V15, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| // subtract stack size off of sp | |
| registers.setSP(savedRegisterLoc); | |
| // set pc to be value in lr | |
| registers.setIP(registers.getRegister(UNW_AARCH64_LR)); | |
| return UNW_STEP_SUCCESS; | |
| } | |
| template <typename A> | |
| int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame( | |
| compact_unwind_encoding_t encoding, uint64_t, A &addressSpace, | |
| Registers_arm64 ®isters) { | |
| uint64_t savedRegisterLoc = registers.getFP() - 8; | |
| if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { | |
| registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V8, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V9, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V10, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V11, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V12, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V13, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { | |
| registers.setFloatRegister(UNW_AARCH64_V14, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| registers.setFloatRegister(UNW_AARCH64_V15, | |
| addressSpace.getDouble(savedRegisterLoc)); | |
| savedRegisterLoc -= 8; | |
| } | |
| uint64_t fp = registers.getFP(); | |
| // fp points to old fp | |
| registers.setFP(addressSpace.get64(fp)); | |
| // old sp is fp less saved fp and lr | |
| registers.setSP(fp + 16); | |
| // pop return address into pc | |
| registers.setIP(addressSpace.get64(fp + 8)); | |
| return UNW_STEP_SUCCESS; | |
| } | |
| } // namespace libunwind | |
Xet Storage Details
- Size:
- 26.1 kB
- Xet hash:
- ea72354340fe430a56af6a2b74d82611a4f76fe2198cbd19977cfb803b42e791
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.