int DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, R ®isters) { FDE_Info fdeInfo; CIE_Info cieInfo; if (CFI_Parser<A>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo) == NULL) { PrologInfo prolog; if (CFI_Parser<A>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &prolog)) { // get pointer to cfa (architecture specific) pint_t cfa = getCFA(addressSpace, prolog, registers); // restore registers that dwarf says were saved R newRegisters = registers; pint_t returnAddress = 0; 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])); else if (registers.validVectorRegister(i)) newRegisters.setVectorRegister( i, getSavedVectorRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); else if (i == (int)cieInfo.returnAddressRegister) returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]); else if (registers.validRegister(i)) newRegisters.setRegister( i, getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); else return UNW_EBADREG; } } // By definition, the CFA is the stack pointer at the call site, so // restoring SP means setting it to CFA. newRegisters.setSP(cfa); // Return address is address after call site instruction, so setting IP to // that does simualates a return. newRegisters.setIP(returnAddress); // Simulate the step by replacing the register set with the new ones. registers = newRegisters; return UNW_STEP_SUCCESS; } } return UNW_EBADFRAME; }
step_result DwarfInstructions<A, R>::stepWithDwarf(A &addressSpace, pint_t pc, pint_t fdeStart, R ®isters, unw_proc_info_t *ctx) { typename CFI_Parser<A, R>::FDE_Info fdeInfo; typename CFI_Parser<A, R>::CIE_Info cieInfo; if (!CFI_Parser<A, R>::decodeFDE(addressSpace, fdeStart, &fdeInfo, &cieInfo, ctx)) return UNW_STEP_FAILED; typename CFI_Parser<A, R>::PrologInfo prolog; if (!CFI_Parser<A, R>::parseFDEInstructions(addressSpace, fdeInfo, cieInfo, pc, &prolog, ctx)) return UNW_STEP_FAILED; // Create working copy of the register set. R newRegisters = registers; // Get pointer to CFA by the architecture-specific code. pint_t cfa = getCFA(addressSpace, prolog, registers); // Restore registers according to DWARF instructions pint_t returnAddress = 0; for (int i = 0; i <= lastRestoreReg(newRegisters); ++i) { if (prolog.savedRegisters[i].location == CFI_Parser<A, R>::kRegisterUnused) continue; if (i == (int)cieInfo.returnAddressRegister) returnAddress = getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i]); else if (registers.validRegister(i)) newRegisters.setRegister(i, getSavedRegister(addressSpace, registers, cfa, prolog.savedRegisters[i])); else if (registers.validFloatVectorRegister(i)) newRegisters.copyFloatVectorRegister( i, computeRegisterLocation(addressSpace, registers, cfa, prolog.savedRegisters[i])); else return UNW_STEP_FAILED; } // The CFA is defined as the stack pointer at the call site. // Therefore the SP is restored by setting it to the CFA. newRegisters.setSP(cfa); newRegisters.setIP(returnAddress + R::RETURN_OFFSET); returnAddress += R::RETURN_OFFSET; returnAddress &= ~R::RETURN_MASK; newRegisters.setIP(returnAddress); // Now replace register set with the working copy. registers = newRegisters; return UNW_STEP_SUCCESS; }