710 lines · plain
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//8// Does runtime stack unwinding using compact unwind encodings.9//10//===----------------------------------------------------------------------===//11 12#ifndef __COMPACT_UNWINDER_HPP__13#define __COMPACT_UNWINDER_HPP__14 15#include <stdint.h>16#include <stdlib.h>17 18#include <libunwind.h>19#include <mach-o/compact_unwind_encoding.h>20 21#include "Registers.hpp"22#include "libunwind_ext.h"23 24#define EXTRACT_BITS(value, mask) \25 ((value >> __builtin_ctz(mask)) & (((1 << __builtin_popcount(mask))) - 1))26 27namespace libunwind {28 29#if defined(_LIBUNWIND_TARGET_I386)30/// CompactUnwinder_x86 uses a compact unwind info to virtually "step" (aka31/// unwind) by modifying a Registers_x86 register set32template <typename A>33class CompactUnwinder_x86 {34public:35 36 static int stepWithCompactEncoding(compact_unwind_encoding_t info,37 uint32_t functionStart, A &addressSpace,38 Registers_x86 ®isters);39 40private:41 typename A::pint_t pint_t;42 43 static void frameUnwind(A &addressSpace, Registers_x86 ®isters);44 static void framelessUnwind(A &addressSpace,45 typename A::pint_t returnAddressLocation,46 Registers_x86 ®isters);47 static int48 stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding,49 uint32_t functionStart, A &addressSpace,50 Registers_x86 ®isters);51 static int stepWithCompactEncodingFrameless(52 compact_unwind_encoding_t compactEncoding, uint32_t functionStart,53 A &addressSpace, Registers_x86 ®isters, bool indirectStackSize);54};55 56template <typename A>57int CompactUnwinder_x86<A>::stepWithCompactEncoding(58 compact_unwind_encoding_t compactEncoding, uint32_t functionStart,59 A &addressSpace, Registers_x86 ®isters) {60 switch (compactEncoding & UNWIND_X86_MODE_MASK) {61 case UNWIND_X86_MODE_EBP_FRAME:62 return stepWithCompactEncodingEBPFrame(compactEncoding, functionStart,63 addressSpace, registers);64 case UNWIND_X86_MODE_STACK_IMMD:65 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,66 addressSpace, registers, false);67 case UNWIND_X86_MODE_STACK_IND:68 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,69 addressSpace, registers, true);70 }71 _LIBUNWIND_ABORT("invalid compact unwind encoding");72}73 74template <typename A>75int CompactUnwinder_x86<A>::stepWithCompactEncodingEBPFrame(76 compact_unwind_encoding_t compactEncoding, uint32_t functionStart,77 A &addressSpace, Registers_x86 ®isters) {78 uint32_t savedRegistersOffset =79 EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_OFFSET);80 uint32_t savedRegistersLocations =81 EXTRACT_BITS(compactEncoding, UNWIND_X86_EBP_FRAME_REGISTERS);82 83 uint32_t savedRegisters = registers.getEBP() - 4 * savedRegistersOffset;84 for (int i = 0; i < 5; ++i) {85 switch (savedRegistersLocations & 0x7) {86 case UNWIND_X86_REG_NONE:87 // no register saved in this slot88 break;89 case UNWIND_X86_REG_EBX:90 registers.setEBX(addressSpace.get32(savedRegisters));91 break;92 case UNWIND_X86_REG_ECX:93 registers.setECX(addressSpace.get32(savedRegisters));94 break;95 case UNWIND_X86_REG_EDX:96 registers.setEDX(addressSpace.get32(savedRegisters));97 break;98 case UNWIND_X86_REG_EDI:99 registers.setEDI(addressSpace.get32(savedRegisters));100 break;101 case UNWIND_X86_REG_ESI:102 registers.setESI(addressSpace.get32(savedRegisters));103 break;104 default:105 (void)functionStart;106 _LIBUNWIND_DEBUG_LOG("bad register for EBP frame, encoding=%08X for "107 "function starting at 0x%X",108 compactEncoding, functionStart);109 _LIBUNWIND_ABORT("invalid compact unwind encoding");110 }111 savedRegisters += 4;112 savedRegistersLocations = (savedRegistersLocations >> 3);113 }114 frameUnwind(addressSpace, registers);115 return UNW_STEP_SUCCESS;116}117 118template <typename A>119int CompactUnwinder_x86<A>::stepWithCompactEncodingFrameless(120 compact_unwind_encoding_t encoding, uint32_t functionStart,121 A &addressSpace, Registers_x86 ®isters, bool indirectStackSize) {122 uint32_t stackSizeEncoded =123 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_SIZE);124 uint32_t stackAdjust =125 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_ADJUST);126 uint32_t regCount =127 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_COUNT);128 uint32_t permutation =129 EXTRACT_BITS(encoding, UNWIND_X86_FRAMELESS_STACK_REG_PERMUTATION);130 uint32_t stackSize = stackSizeEncoded * 4;131 if (indirectStackSize) {132 // stack size is encoded in subl $xxx,%esp instruction133 uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded);134 stackSize = subl + 4 * stackAdjust;135 }136 // decompress permutation137 uint32_t permunreg[6];138 switch (regCount) {139 case 6:140 permunreg[0] = permutation / 120;141 permutation -= (permunreg[0] * 120);142 permunreg[1] = permutation / 24;143 permutation -= (permunreg[1] * 24);144 permunreg[2] = permutation / 6;145 permutation -= (permunreg[2] * 6);146 permunreg[3] = permutation / 2;147 permutation -= (permunreg[3] * 2);148 permunreg[4] = permutation;149 permunreg[5] = 0;150 break;151 case 5:152 permunreg[0] = permutation / 120;153 permutation -= (permunreg[0] * 120);154 permunreg[1] = permutation / 24;155 permutation -= (permunreg[1] * 24);156 permunreg[2] = permutation / 6;157 permutation -= (permunreg[2] * 6);158 permunreg[3] = permutation / 2;159 permutation -= (permunreg[3] * 2);160 permunreg[4] = permutation;161 break;162 case 4:163 permunreg[0] = permutation / 60;164 permutation -= (permunreg[0] * 60);165 permunreg[1] = permutation / 12;166 permutation -= (permunreg[1] * 12);167 permunreg[2] = permutation / 3;168 permutation -= (permunreg[2] * 3);169 permunreg[3] = permutation;170 break;171 case 3:172 permunreg[0] = permutation / 20;173 permutation -= (permunreg[0] * 20);174 permunreg[1] = permutation / 4;175 permutation -= (permunreg[1] * 4);176 permunreg[2] = permutation;177 break;178 case 2:179 permunreg[0] = permutation / 5;180 permutation -= (permunreg[0] * 5);181 permunreg[1] = permutation;182 break;183 case 1:184 permunreg[0] = permutation;185 break;186 }187 // re-number registers back to standard numbers188 int registersSaved[6];189 bool used[7] = { false, false, false, false, false, false, false };190 for (uint32_t i = 0; i < regCount; ++i) {191 uint32_t renum = 0;192 for (int u = 1; u < 7; ++u) {193 if (!used[u]) {194 if (renum == permunreg[i]) {195 registersSaved[i] = u;196 used[u] = true;197 break;198 }199 ++renum;200 }201 }202 }203 uint32_t savedRegisters = registers.getSP() + stackSize - 4 - 4 * regCount;204 for (uint32_t i = 0; i < regCount; ++i) {205 switch (registersSaved[i]) {206 case UNWIND_X86_REG_EBX:207 registers.setEBX(addressSpace.get32(savedRegisters));208 break;209 case UNWIND_X86_REG_ECX:210 registers.setECX(addressSpace.get32(savedRegisters));211 break;212 case UNWIND_X86_REG_EDX:213 registers.setEDX(addressSpace.get32(savedRegisters));214 break;215 case UNWIND_X86_REG_EDI:216 registers.setEDI(addressSpace.get32(savedRegisters));217 break;218 case UNWIND_X86_REG_ESI:219 registers.setESI(addressSpace.get32(savedRegisters));220 break;221 case UNWIND_X86_REG_EBP:222 registers.setEBP(addressSpace.get32(savedRegisters));223 break;224 default:225 _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "226 "function starting at 0x%X",227 encoding, functionStart);228 _LIBUNWIND_ABORT("invalid compact unwind encoding");229 }230 savedRegisters += 4;231 }232 framelessUnwind(addressSpace, savedRegisters, registers);233 return UNW_STEP_SUCCESS;234}235 236 237template <typename A>238void CompactUnwinder_x86<A>::frameUnwind(A &addressSpace,239 Registers_x86 ®isters) {240 typename A::pint_t bp = registers.getEBP();241 // ebp points to old ebp242 registers.setEBP(addressSpace.get32(bp));243 // old esp is ebp less saved ebp and return address244 registers.setSP((uint32_t)bp + 8);245 // pop return address into eip246 registers.setIP(addressSpace.get32(bp + 4));247}248 249template <typename A>250void CompactUnwinder_x86<A>::framelessUnwind(251 A &addressSpace, typename A::pint_t returnAddressLocation,252 Registers_x86 ®isters) {253 // return address is on stack after last saved register254 registers.setIP(addressSpace.get32(returnAddressLocation));255 // old esp is before return address256 registers.setSP((uint32_t)returnAddressLocation + 4);257}258#endif // _LIBUNWIND_TARGET_I386259 260 261#if defined(_LIBUNWIND_TARGET_X86_64)262/// CompactUnwinder_x86_64 uses a compact unwind info to virtually "step" (aka263/// unwind) by modifying a Registers_x86_64 register set264template <typename A>265class CompactUnwinder_x86_64 {266public:267 268 static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,269 uint64_t functionStart, A &addressSpace,270 Registers_x86_64 ®isters);271 272private:273 typename A::pint_t pint_t;274 275 static void frameUnwind(A &addressSpace, Registers_x86_64 ®isters);276 static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation,277 Registers_x86_64 ®isters);278 static int279 stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding,280 uint64_t functionStart, A &addressSpace,281 Registers_x86_64 ®isters);282 static int stepWithCompactEncodingFrameless(283 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,284 A &addressSpace, Registers_x86_64 ®isters, bool indirectStackSize);285};286 287template <typename A>288int CompactUnwinder_x86_64<A>::stepWithCompactEncoding(289 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,290 A &addressSpace, Registers_x86_64 ®isters) {291 switch (compactEncoding & UNWIND_X86_64_MODE_MASK) {292 case UNWIND_X86_64_MODE_RBP_FRAME:293 return stepWithCompactEncodingRBPFrame(compactEncoding, functionStart,294 addressSpace, registers);295 case UNWIND_X86_64_MODE_STACK_IMMD:296 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,297 addressSpace, registers, false);298 case UNWIND_X86_64_MODE_STACK_IND:299 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,300 addressSpace, registers, true);301 }302 _LIBUNWIND_ABORT("invalid compact unwind encoding");303}304 305template <typename A>306int CompactUnwinder_x86_64<A>::stepWithCompactEncodingRBPFrame(307 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,308 A &addressSpace, Registers_x86_64 ®isters) {309 uint32_t savedRegistersOffset =310 EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_OFFSET);311 uint32_t savedRegistersLocations =312 EXTRACT_BITS(compactEncoding, UNWIND_X86_64_RBP_FRAME_REGISTERS);313 314 uint64_t savedRegisters = registers.getRBP() - 8 * savedRegistersOffset;315 for (int i = 0; i < 5; ++i) {316 switch (savedRegistersLocations & 0x7) {317 case UNWIND_X86_64_REG_NONE:318 // no register saved in this slot319 break;320 case UNWIND_X86_64_REG_RBX:321 registers.setRBX(addressSpace.get64(savedRegisters));322 break;323 case UNWIND_X86_64_REG_R12:324 registers.setR12(addressSpace.get64(savedRegisters));325 break;326 case UNWIND_X86_64_REG_R13:327 registers.setR13(addressSpace.get64(savedRegisters));328 break;329 case UNWIND_X86_64_REG_R14:330 registers.setR14(addressSpace.get64(savedRegisters));331 break;332 case UNWIND_X86_64_REG_R15:333 registers.setR15(addressSpace.get64(savedRegisters));334 break;335 default:336 (void)functionStart;337 _LIBUNWIND_DEBUG_LOG("bad register for RBP frame, encoding=%08X for "338 "function starting at 0x%llX",339 compactEncoding, functionStart);340 _LIBUNWIND_ABORT("invalid compact unwind encoding");341 }342 savedRegisters += 8;343 savedRegistersLocations = (savedRegistersLocations >> 3);344 }345 frameUnwind(addressSpace, registers);346 return UNW_STEP_SUCCESS;347}348 349template <typename A>350int CompactUnwinder_x86_64<A>::stepWithCompactEncodingFrameless(351 compact_unwind_encoding_t encoding, uint64_t functionStart, A &addressSpace,352 Registers_x86_64 ®isters, bool indirectStackSize) {353 uint32_t stackSizeEncoded =354 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);355 uint32_t stackAdjust =356 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);357 uint32_t regCount =358 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);359 uint32_t permutation =360 EXTRACT_BITS(encoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);361 uint32_t stackSize = stackSizeEncoded * 8;362 if (indirectStackSize) {363 // stack size is encoded in subl $xxx,%esp instruction364 uint32_t subl = addressSpace.get32(functionStart + stackSizeEncoded);365 stackSize = subl + 8 * stackAdjust;366 }367 // decompress permutation368 uint32_t permunreg[6];369 switch (regCount) {370 case 6:371 permunreg[0] = permutation / 120;372 permutation -= (permunreg[0] * 120);373 permunreg[1] = permutation / 24;374 permutation -= (permunreg[1] * 24);375 permunreg[2] = permutation / 6;376 permutation -= (permunreg[2] * 6);377 permunreg[3] = permutation / 2;378 permutation -= (permunreg[3] * 2);379 permunreg[4] = permutation;380 permunreg[5] = 0;381 break;382 case 5:383 permunreg[0] = permutation / 120;384 permutation -= (permunreg[0] * 120);385 permunreg[1] = permutation / 24;386 permutation -= (permunreg[1] * 24);387 permunreg[2] = permutation / 6;388 permutation -= (permunreg[2] * 6);389 permunreg[3] = permutation / 2;390 permutation -= (permunreg[3] * 2);391 permunreg[4] = permutation;392 break;393 case 4:394 permunreg[0] = permutation / 60;395 permutation -= (permunreg[0] * 60);396 permunreg[1] = permutation / 12;397 permutation -= (permunreg[1] * 12);398 permunreg[2] = permutation / 3;399 permutation -= (permunreg[2] * 3);400 permunreg[3] = permutation;401 break;402 case 3:403 permunreg[0] = permutation / 20;404 permutation -= (permunreg[0] * 20);405 permunreg[1] = permutation / 4;406 permutation -= (permunreg[1] * 4);407 permunreg[2] = permutation;408 break;409 case 2:410 permunreg[0] = permutation / 5;411 permutation -= (permunreg[0] * 5);412 permunreg[1] = permutation;413 break;414 case 1:415 permunreg[0] = permutation;416 break;417 }418 // re-number registers back to standard numbers419 int registersSaved[6];420 bool used[7] = { false, false, false, false, false, false, false };421 for (uint32_t i = 0; i < regCount; ++i) {422 uint32_t renum = 0;423 for (int u = 1; u < 7; ++u) {424 if (!used[u]) {425 if (renum == permunreg[i]) {426 registersSaved[i] = u;427 used[u] = true;428 break;429 }430 ++renum;431 }432 }433 }434 uint64_t savedRegisters = registers.getSP() + stackSize - 8 - 8 * regCount;435 for (uint32_t i = 0; i < regCount; ++i) {436 switch (registersSaved[i]) {437 case UNWIND_X86_64_REG_RBX:438 registers.setRBX(addressSpace.get64(savedRegisters));439 break;440 case UNWIND_X86_64_REG_R12:441 registers.setR12(addressSpace.get64(savedRegisters));442 break;443 case UNWIND_X86_64_REG_R13:444 registers.setR13(addressSpace.get64(savedRegisters));445 break;446 case UNWIND_X86_64_REG_R14:447 registers.setR14(addressSpace.get64(savedRegisters));448 break;449 case UNWIND_X86_64_REG_R15:450 registers.setR15(addressSpace.get64(savedRegisters));451 break;452 case UNWIND_X86_64_REG_RBP:453 registers.setRBP(addressSpace.get64(savedRegisters));454 break;455 default:456 _LIBUNWIND_DEBUG_LOG("bad register for frameless, encoding=%08X for "457 "function starting at 0x%llX",458 encoding, functionStart);459 _LIBUNWIND_ABORT("invalid compact unwind encoding");460 }461 savedRegisters += 8;462 }463 framelessUnwind(addressSpace, savedRegisters, registers);464 return UNW_STEP_SUCCESS;465}466 467 468template <typename A>469void CompactUnwinder_x86_64<A>::frameUnwind(A &addressSpace,470 Registers_x86_64 ®isters) {471 uint64_t rbp = registers.getRBP();472 // ebp points to old ebp473 registers.setRBP(addressSpace.get64(rbp));474 // old esp is ebp less saved ebp and return address475 registers.setSP(rbp + 16);476 // pop return address into eip477 registers.setIP(addressSpace.get64(rbp + 8));478}479 480template <typename A>481void CompactUnwinder_x86_64<A>::framelessUnwind(A &addressSpace,482 uint64_t returnAddressLocation,483 Registers_x86_64 ®isters) {484 // return address is on stack after last saved register485 registers.setIP(addressSpace.get64(returnAddressLocation));486 // old esp is before return address487 registers.setSP(returnAddressLocation + 8);488}489#endif // _LIBUNWIND_TARGET_X86_64490 491 492 493#if defined(_LIBUNWIND_TARGET_AARCH64)494/// CompactUnwinder_arm64 uses a compact unwind info to virtually "step" (aka495/// unwind) by modifying a Registers_arm64 register set496template <typename A>497class CompactUnwinder_arm64 {498public:499 500 static int stepWithCompactEncoding(compact_unwind_encoding_t compactEncoding,501 uint64_t functionStart, A &addressSpace,502 Registers_arm64 ®isters);503 504private:505 typename A::pint_t pint_t;506 507 static int508 stepWithCompactEncodingFrame(compact_unwind_encoding_t compactEncoding,509 uint64_t functionStart, A &addressSpace,510 Registers_arm64 ®isters);511 static int stepWithCompactEncodingFrameless(512 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,513 A &addressSpace, Registers_arm64 ®isters);514};515 516template <typename A>517int CompactUnwinder_arm64<A>::stepWithCompactEncoding(518 compact_unwind_encoding_t compactEncoding, uint64_t functionStart,519 A &addressSpace, Registers_arm64 ®isters) {520 switch (compactEncoding & UNWIND_ARM64_MODE_MASK) {521 case UNWIND_ARM64_MODE_FRAME:522 return stepWithCompactEncodingFrame(compactEncoding, functionStart,523 addressSpace, registers);524 case UNWIND_ARM64_MODE_FRAMELESS:525 return stepWithCompactEncodingFrameless(compactEncoding, functionStart,526 addressSpace, registers);527 }528 _LIBUNWIND_ABORT("invalid compact unwind encoding");529}530 531template <typename A>532int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrameless(533 compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,534 Registers_arm64 ®isters) {535 uint32_t stackSize =536 16 * EXTRACT_BITS(encoding, UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK);537 538 uint64_t savedRegisterLoc = registers.getSP() + stackSize;539 540 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {541 registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc));542 savedRegisterLoc -= 8;543 registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc));544 savedRegisterLoc -= 8;545 }546 if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {547 registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc));548 savedRegisterLoc -= 8;549 registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc));550 savedRegisterLoc -= 8;551 }552 if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {553 registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc));554 savedRegisterLoc -= 8;555 registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc));556 savedRegisterLoc -= 8;557 }558 if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {559 registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc));560 savedRegisterLoc -= 8;561 registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc));562 savedRegisterLoc -= 8;563 }564 if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {565 registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc));566 savedRegisterLoc -= 8;567 registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc));568 savedRegisterLoc -= 8;569 }570 571 if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {572 registers.setFloatRegister(UNW_AARCH64_V8,573 addressSpace.getDouble(savedRegisterLoc));574 savedRegisterLoc -= 8;575 registers.setFloatRegister(UNW_AARCH64_V9,576 addressSpace.getDouble(savedRegisterLoc));577 savedRegisterLoc -= 8;578 }579 if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {580 registers.setFloatRegister(UNW_AARCH64_V10,581 addressSpace.getDouble(savedRegisterLoc));582 savedRegisterLoc -= 8;583 registers.setFloatRegister(UNW_AARCH64_V11,584 addressSpace.getDouble(savedRegisterLoc));585 savedRegisterLoc -= 8;586 }587 if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {588 registers.setFloatRegister(UNW_AARCH64_V12,589 addressSpace.getDouble(savedRegisterLoc));590 savedRegisterLoc -= 8;591 registers.setFloatRegister(UNW_AARCH64_V13,592 addressSpace.getDouble(savedRegisterLoc));593 savedRegisterLoc -= 8;594 }595 if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {596 registers.setFloatRegister(UNW_AARCH64_V14,597 addressSpace.getDouble(savedRegisterLoc));598 savedRegisterLoc -= 8;599 registers.setFloatRegister(UNW_AARCH64_V15,600 addressSpace.getDouble(savedRegisterLoc));601 savedRegisterLoc -= 8;602 }603 604 // We load the link register prior to setting the new SP as the authentication605 // schema for LR entangles the SP of the old frame into the diversifier.606 Registers_arm64::reg_t linkRegister = registers.getRegister(UNW_AARCH64_LR);607 608 // subtract stack size off of sp609 registers.setSP(savedRegisterLoc);610 611 // Set pc to be value in lr. This needs to be performed after the new SP has612 // been set, as the PC authentication schema entangles the SP of the new613 // frame.614 registers.setIP(linkRegister);615 616 return UNW_STEP_SUCCESS;617}618 619template <typename A>620int CompactUnwinder_arm64<A>::stepWithCompactEncodingFrame(621 compact_unwind_encoding_t encoding, uint64_t, A &addressSpace,622 Registers_arm64 ®isters) {623 Registers_arm64::reg_t savedRegisterLoc = registers.getFP() - 8;624 625 if (encoding & UNWIND_ARM64_FRAME_X19_X20_PAIR) {626 registers.setRegister(UNW_AARCH64_X19, addressSpace.get64(savedRegisterLoc));627 savedRegisterLoc -= 8;628 registers.setRegister(UNW_AARCH64_X20, addressSpace.get64(savedRegisterLoc));629 savedRegisterLoc -= 8;630 }631 if (encoding & UNWIND_ARM64_FRAME_X21_X22_PAIR) {632 registers.setRegister(UNW_AARCH64_X21, addressSpace.get64(savedRegisterLoc));633 savedRegisterLoc -= 8;634 registers.setRegister(UNW_AARCH64_X22, addressSpace.get64(savedRegisterLoc));635 savedRegisterLoc -= 8;636 }637 if (encoding & UNWIND_ARM64_FRAME_X23_X24_PAIR) {638 registers.setRegister(UNW_AARCH64_X23, addressSpace.get64(savedRegisterLoc));639 savedRegisterLoc -= 8;640 registers.setRegister(UNW_AARCH64_X24, addressSpace.get64(savedRegisterLoc));641 savedRegisterLoc -= 8;642 }643 if (encoding & UNWIND_ARM64_FRAME_X25_X26_PAIR) {644 registers.setRegister(UNW_AARCH64_X25, addressSpace.get64(savedRegisterLoc));645 savedRegisterLoc -= 8;646 registers.setRegister(UNW_AARCH64_X26, addressSpace.get64(savedRegisterLoc));647 savedRegisterLoc -= 8;648 }649 if (encoding & UNWIND_ARM64_FRAME_X27_X28_PAIR) {650 registers.setRegister(UNW_AARCH64_X27, addressSpace.get64(savedRegisterLoc));651 savedRegisterLoc -= 8;652 registers.setRegister(UNW_AARCH64_X28, addressSpace.get64(savedRegisterLoc));653 savedRegisterLoc -= 8;654 }655 656 if (encoding & UNWIND_ARM64_FRAME_D8_D9_PAIR) {657 registers.setFloatRegister(UNW_AARCH64_V8,658 addressSpace.getDouble(savedRegisterLoc));659 savedRegisterLoc -= 8;660 registers.setFloatRegister(UNW_AARCH64_V9,661 addressSpace.getDouble(savedRegisterLoc));662 savedRegisterLoc -= 8;663 }664 if (encoding & UNWIND_ARM64_FRAME_D10_D11_PAIR) {665 registers.setFloatRegister(UNW_AARCH64_V10,666 addressSpace.getDouble(savedRegisterLoc));667 savedRegisterLoc -= 8;668 registers.setFloatRegister(UNW_AARCH64_V11,669 addressSpace.getDouble(savedRegisterLoc));670 savedRegisterLoc -= 8;671 }672 if (encoding & UNWIND_ARM64_FRAME_D12_D13_PAIR) {673 registers.setFloatRegister(UNW_AARCH64_V12,674 addressSpace.getDouble(savedRegisterLoc));675 savedRegisterLoc -= 8;676 registers.setFloatRegister(UNW_AARCH64_V13,677 addressSpace.getDouble(savedRegisterLoc));678 savedRegisterLoc -= 8;679 }680 if (encoding & UNWIND_ARM64_FRAME_D14_D15_PAIR) {681 registers.setFloatRegister(UNW_AARCH64_V14,682 addressSpace.getDouble(savedRegisterLoc));683 savedRegisterLoc -= 8;684 registers.setFloatRegister(UNW_AARCH64_V15,685 addressSpace.getDouble(savedRegisterLoc));686 savedRegisterLoc -= 8;687 }688 689 Registers_arm64::reg_t fp = registers.getFP();690 691 // fp points to old fp692 registers.setFP(addressSpace.get64(fp));693 694 // Old sp is fp less saved fp and lr. We need to set this prior to setting695 // the lr as the pointer authentication schema for the lr incorporates the696 // sp as part of the diversifier.697 registers.setSP(fp + 16);698 699 // pop return address into pc700 registers.setIP(addressSpace.get64(fp + 8));701 702 return UNW_STEP_SUCCESS;703}704#endif // _LIBUNWIND_TARGET_AARCH64705 706 707} // namespace libunwind708 709#endif // __COMPACT_UNWINDER_HPP__710