static v128 getSavedVectorRegister(A &addressSpace, const R ®isters,
pint_t cfa, const RegisterLocation &savedReg);
- // x86 specific variants
- static int lastRestoreReg(const Registers_x86 &);
- static bool isReturnAddressRegister(int regNum, const Registers_x86 &);
static pint_t getCFA(A &addressSpace, const PrologInfo &prolog,
- const Registers_x86 &);
-
- // x86_64 specific variants
- static int lastRestoreReg(const Registers_x86_64 &);
- static bool isReturnAddressRegister(int regNum, const Registers_x86_64 &);
- static pint_t getCFA(A &addressSpace,
- const PrologInfo &prolog,
- const Registers_x86_64 &);
-
- // ppc specific variants
- static int lastRestoreReg(const Registers_ppc &);
- static bool isReturnAddressRegister(int regNum, const Registers_ppc &);
- static pint_t getCFA(A &addressSpace,
- const PrologInfo &prolog,
- const Registers_ppc &);
-
- // arm64 specific variants
- static bool isReturnAddressRegister(int regNum, const Registers_arm64 &);
- static int lastRestoreReg(const Registers_arm64 &);
- static pint_t getCFA(A &addressSpace,
- const PrologInfo &prolog,
- const Registers_arm64 &);
-
+ const R ®isters) {
+ if (prolog.cfaRegister != 0)
+ return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) +
+ prolog.cfaRegisterOffset);
+ if (prolog.cfaExpression != 0)
+ return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
+ registers, 0);
+ assert(0 && "getCFA(): unknown location");
+ __builtin_unreachable();
+ }
};
PrologInfo prolog;
if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc,
&prolog)) {
- R newRegisters = registers;
-
// get pointer to cfa (architecture specific)
pint_t cfa = getCFA(addressSpace, prolog, registers);
- // restore registers that dwarf says were saved
+ // restore registers that dwarf says were saved
+ R newRegisters = registers;
pint_t returnAddress = 0;
- for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) {
- if (prolog.savedRegisters[i].location !=
- CFI_Parser<A>::kRegisterUnused) {
- if (registers.validFloatRegister(i))
+ const int lastReg = R::lastDwarfRegNum();
+ assert((int)CFI_Parser<A>::kMaxRegisterNumber > lastReg
+ && "register range too large");
+ assert(lastReg <= (int)cieInfo.returnAddressRegister
+ && "register range does not contain return address register");
+ for (int i = 0; i <= lastReg; ++i) {
+ if (prolog.savedRegisters[i].location !=
+ CFI_Parser<A>::kRegisterUnused) {
+ if (registers.validFloatRegister(i))
newRegisters.setFloatRegister(
i, getSavedFloatRegister(addressSpace, registers, cfa,
prolog.savedRegisters[i]));
newRegisters.setVectorRegister(
i, getSavedVectorRegister(addressSpace, registers, cfa,
prolog.savedRegisters[i]));
- else if (isReturnAddressRegister(i, registers))
+ else if (i == (int)cieInfo.returnAddressRegister)
returnAddress = getSavedRegister(addressSpace, registers, cfa,
prolog.savedRegisters[i]);
else if (registers.validRegister(i))
return *sp;
}
-//
-// x86_64 specific functions
-//
-template <typename A, typename R>
-int DwarfInstructions<A, R>::lastRestoreReg(const Registers_x86_64 &) {
- static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
- > (int)DW_X86_64_RET_ADDR, "register number out of range");
- return DW_X86_64_RET_ADDR;
-}
-
-template <typename A, typename R>
-bool
-DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
- const Registers_x86_64 &) {
- return (regNum == DW_X86_64_RET_ADDR);
-}
-
-template <typename A, typename R>
-typename A::pint_t DwarfInstructions<A, R>::getCFA(
- A &addressSpace, const PrologInfo &prolog,
- const Registers_x86_64 ®isters) {
- if (prolog.cfaRegister != 0)
- return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister)
- + prolog.cfaRegisterOffset);
- else if (prolog.cfaExpression != 0)
- return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, registers, 0);
- else
- _LIBUNWIND_ABORT("getCFA(): unknown location for x86_64 cfa");
-}
-
-
-//
-// x86 specific functions
-//
-template <typename A, typename R>
-int DwarfInstructions<A, R>::lastRestoreReg(const Registers_x86 &) {
- static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
- > (int)DW_X86_RET_ADDR, "register number out of range");
- return DW_X86_RET_ADDR;
-}
-
-template <typename A, typename R>
-bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
- const Registers_x86 &) {
- return (regNum == DW_X86_RET_ADDR);
-}
-
-template <typename A, typename R>
-typename A::pint_t DwarfInstructions<A, R>::getCFA(
- A &addressSpace, const PrologInfo &prolog,
- const Registers_x86 ®isters) {
- if (prolog.cfaRegister != 0)
- return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister)
- + prolog.cfaRegisterOffset);
- else if (prolog.cfaExpression != 0)
- return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
- registers, 0);
- else
- _LIBUNWIND_ABORT("getCFA(): unknown location for x86 cfa");
-}
-
-
-//
-// ppc specific functions
-//
-template <typename A, typename R>
-int DwarfInstructions<A, R>::lastRestoreReg(const Registers_ppc &) {
- static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
- > (int)UNW_PPC_SPEFSCR, "register number out of range");
- return UNW_PPC_SPEFSCR;
-}
-
-template <typename A, typename R>
-bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
- const Registers_ppc &) {
- return (regNum == UNW_PPC_LR);
-}
-
-template <typename A, typename R>
-typename A::pint_t DwarfInstructions<A, R>::getCFA(
- A &addressSpace, const PrologInfo &prolog,
- const Registers_ppc ®isters) {
- if (prolog.cfaRegister != 0)
- return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
- else if (prolog.cfaExpression != 0)
- return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace,
- registers, 0);
- else
- _LIBUNWIND_ABORT("getCFA(): unknown location for ppc cfa");
-}
-
-
-
-//
-// arm64 specific functions
-//
-template <typename A, typename R>
-bool DwarfInstructions<A, R>::isReturnAddressRegister(int regNum,
- const Registers_arm64 &) {
- return (regNum == UNW_ARM64_LR);
-}
-
-template <typename A, typename R>
-int DwarfInstructions<A, R>::lastRestoreReg(const Registers_arm64 &) {
- static_assert((int)CFI_Parser<A>::kMaxRegisterNumber
- > (int)UNW_ARM64_D31, "register number out of range");
- return UNW_ARM64_D31;
-}
-
-template <typename A, typename R>
-typename A::pint_t DwarfInstructions<A, R>::getCFA(A&, const PrologInfo &prolog,
- const Registers_arm64 ®isters) {
- if (prolog.cfaRegister != 0)
- return registers.getRegister(prolog.cfaRegister) + prolog.cfaRegisterOffset;
- else
- _LIBUNWIND_ABORT("getCFA(): unsupported location for arm64 cfa");
-}
} // namespace libunwind