Use return address register from CIE. Move DwarfInstructions::lastRestoreReg() to Register::lastDwarfRegNum().

llvm-svn: 207467
This commit is contained in:
Nick Kledzik 2014-04-28 23:43:21 +00:00
parent 275c5fc9c2
commit 0c790015df
3 changed files with 20 additions and 91 deletions

View File

@ -74,21 +74,6 @@ private:
assert(0 && "getCFA(): unknown location");
__builtin_unreachable();
}
// x86 specific variants
static int lastRestoreReg(const Registers_x86 &);
static bool isReturnAddressRegister(int regNum, const Registers_x86 &);
// x86_64 specific variants
static int lastRestoreReg(const Registers_x86_64 &);
static bool isReturnAddressRegister(int regNum, const Registers_x86_64 &);
// ppc specific variants
static int lastRestoreReg(const Registers_ppc &);
static bool isReturnAddressRegister(int regNum, const Registers_ppc &);
// arm64 specific variants
static bool isReturnAddressRegister(int regNum, const Registers_arm64 &);
static int lastRestoreReg(const Registers_arm64 &);
};
@ -176,17 +161,21 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
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]));
@ -194,7 +183,7 @@ int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc,
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))
@ -763,73 +752,6 @@ DwarfInstructions<A, R>::evaluateExpression(pint_t expression, A &addressSpace,
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);
}
//
// 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);
}
//
// 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);
}
//
// 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;
}
} // namespace libunwind

View File

@ -49,6 +49,7 @@ public:
int dataAlignFactor;
bool isSignalFrame;
bool fdesHaveAugmentationData;
uint8_t returnAddressRegister;
};
/// Information about an FDE (Frame Description Entry)
@ -295,7 +296,9 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie,
// parse data alignment factor
cieInfo->dataAlignFactor = (int)addressSpace.getSLEB128(p, cieContentEnd);
// parse return address register
addressSpace.getULEB128(p, cieContentEnd);
uint64_t raReg = addressSpace.getULEB128(p, cieContentEnd);
assert(raReg < 255 && "return address register too large");
cieInfo->returnAddressRegister = (uint8_t)raReg;
// parse augmentation data based on augmentation string
const char *result = NULL;
if (addressSpace.get8(strStart) == 'z') {

View File

@ -44,6 +44,7 @@ public:
void setVectorRegister(int num, v128 value);
const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return 8; }
uint32_t getSP() const { return _registers.__esp; }
void setSP(uint32_t value) { _registers.__esp = value; }
@ -231,6 +232,7 @@ public:
void setVectorRegister(int num, v128 value);
const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return 16; }
uint64_t getSP() const { return _registers.__rsp; }
void setSP(uint64_t value) { _registers.__rsp = value; }
@ -478,6 +480,7 @@ public:
void setVectorRegister(int num, v128 value);
const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return 112; }
uint64_t getSP() const { return _registers.__r1; }
void setSP(uint32_t value) { _registers.__r1 = value; }
@ -1031,6 +1034,7 @@ public:
void setVectorRegister(int num, v128 value);
const char *getRegisterName(int num);
void jumpto();
static int lastDwarfRegNum() { return 95; }
uint64_t getSP() const { return _registers.__sp; }
void setSP(uint64_t value) { _registers.__sp = value; }