diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:15 +0300 |
commit | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch) | |
tree | da2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /contrib/libs/libunwind/src/CompactUnwinder.hpp | |
parent | 778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff) | |
download | ydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/libunwind/src/CompactUnwinder.hpp')
-rw-r--r-- | contrib/libs/libunwind/src/CompactUnwinder.hpp | 1292 |
1 files changed, 646 insertions, 646 deletions
diff --git a/contrib/libs/libunwind/src/CompactUnwinder.hpp b/contrib/libs/libunwind/src/CompactUnwinder.hpp index 0b2b5e111b..daa7b0cd15 100644 --- a/contrib/libs/libunwind/src/CompactUnwinder.hpp +++ b/contrib/libs/libunwind/src/CompactUnwinder.hpp @@ -1,697 +1,697 @@ //===----------------------------------------------------------------------===// -// +// // 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. -// -//===----------------------------------------------------------------------===// - -#ifndef __COMPACT_UNWINDER_HPP__ -#define __COMPACT_UNWINDER_HPP__ - -#include <stdint.h> -#include <stdlib.h> - -#include <libunwind.h> -#include <mach-o/compact_unwind_encoding.h> - -#include "Registers.hpp" - -#define EXTRACT_BITS(value, mask) \ - ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) - -namespace libunwind { - +// +// +// Does runtime stack unwinding using compact unwind encodings. +// +//===----------------------------------------------------------------------===// + +#ifndef __COMPACT_UNWINDER_HPP__ +#define __COMPACT_UNWINDER_HPP__ + +#include <stdint.h> +#include <stdlib.h> + +#include <libunwind.h> +#include <mach-o/compact_unwind_encoding.h> + +#include "Registers.hpp" + +#define EXTRACT_BITS(value, mask) \ + ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1)) + +namespace libunwind { + #if defined(_LIBUNWIND_TARGET_I386) -/// 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 " +/// 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 " + 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); -} + 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); +} #endif // _LIBUNWIND_TARGET_I386 - - + + #if defined(_LIBUNWIND_TARGET_X86_64) -/// 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 " +/// 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 " + 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); -} + 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); +} #endif // _LIBUNWIND_TARGET_X86_64 - - - + + + #if defined(_LIBUNWIND_TARGET_AARCH64) -/// 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) { +/// 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; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + savedRegisterLoc -= 8; + } + + if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { registers.setFloatRegister(UNW_AARCH64_V8, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; registers.setFloatRegister(UNW_AARCH64_V9, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { registers.setFloatRegister(UNW_AARCH64_V10, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; registers.setFloatRegister(UNW_AARCH64_V11, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { registers.setFloatRegister(UNW_AARCH64_V12, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; registers.setFloatRegister(UNW_AARCH64_V13, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { registers.setFloatRegister(UNW_AARCH64_V14, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + 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 + 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) { + + 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; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) { registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) { registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) { registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) { registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; + savedRegisterLoc -= 8; registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - - if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { + savedRegisterLoc -= 8; + } + + if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) { registers.setFloatRegister(UNW_AARCH64_V8, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; registers.setFloatRegister(UNW_AARCH64_V9, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) { registers.setFloatRegister(UNW_AARCH64_V10, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; registers.setFloatRegister(UNW_AARCH64_V11, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) { registers.setFloatRegister(UNW_AARCH64_V12, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; registers.setFloatRegister(UNW_AARCH64_V13, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; - } - if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { + addressSpace.getDouble(savedRegisterLoc)); + savedRegisterLoc -= 8; + } + if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) { registers.setFloatRegister(UNW_AARCH64_V14, - addressSpace.getDouble(savedRegisterLoc)); - savedRegisterLoc -= 8; + 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; -} + 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; +} #endif // _LIBUNWIND_TARGET_AARCH64 - - -} // namespace libunwind - -#endif // __COMPACT_UNWINDER_HPP__ + + +} // namespace libunwind + +#endif // __COMPACT_UNWINDER_HPP__ |