brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.0 KiB · cd2e0e3 Raw
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 &registers);39 40private:41  typename A::pint_t pint_t;42 43  static void frameUnwind(A &addressSpace, Registers_x86 &registers);44  static void framelessUnwind(A &addressSpace,45                              typename A::pint_t returnAddressLocation,46                              Registers_x86 &registers);47  static int48      stepWithCompactEncodingEBPFrame(compact_unwind_encoding_t compactEncoding,49                                      uint32_t functionStart, A &addressSpace,50                                      Registers_x86 &registers);51  static int stepWithCompactEncodingFrameless(52      compact_unwind_encoding_t compactEncoding, uint32_t functionStart,53      A &addressSpace, Registers_x86 &registers, 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 &registers) {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 &registers) {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 &registers, 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 &registers) {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 &registers) {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 &registers);271 272private:273  typename A::pint_t pint_t;274 275  static void frameUnwind(A &addressSpace, Registers_x86_64 &registers);276  static void framelessUnwind(A &addressSpace, uint64_t returnAddressLocation,277                              Registers_x86_64 &registers);278  static int279      stepWithCompactEncodingRBPFrame(compact_unwind_encoding_t compactEncoding,280                                      uint64_t functionStart, A &addressSpace,281                                      Registers_x86_64 &registers);282  static int stepWithCompactEncodingFrameless(283      compact_unwind_encoding_t compactEncoding, uint64_t functionStart,284      A &addressSpace, Registers_x86_64 &registers, 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 &registers) {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 &registers) {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 &registers, 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 &registers) {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 &registers) {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 &registers);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 &registers);511  static int stepWithCompactEncodingFrameless(512      compact_unwind_encoding_t compactEncoding, uint64_t functionStart,513      A &addressSpace, Registers_arm64 &registers);514};515 516template <typename A>517int CompactUnwinder_arm64<A>::stepWithCompactEncoding(518    compact_unwind_encoding_t compactEncoding, uint64_t functionStart,519    A &addressSpace, Registers_arm64 &registers) {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 &registers) {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 &registers) {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