📄 unwind.c
字号:
// We know that as of this instruction, r11 is a valid frame // pointer. Therefore, it contains the stack value immediately // before the STM that set up the stack frame. So, we scan // backward to find the STM, pretend it was a STM using r11 as the // base register with no update, and reverse-execute it. j = i - 1; while (j >= 0 && (Prolog[j].instruction & STM_MASK) != STM_INSTR) j--; if ( j >= 0 ){ // Tweak the instruction so it will be reverse-executed // correctly. A convenient side-effect of this is that it // prevents it from being recognized as a STM when we continue // reverse-executing, which is good because we don't want to do it // again. Prolog[j].ldm.l = TRUE; Prolog[j].ldm.rn = 11; Prolog[j].ldm.w = FALSE; if (!UnwindLoadMultiple(Prolog[j], Register)) return ControlPc; } } } // The continuation address is contained in the link register. *EstablisherFrame = Register[13]; if (!HaveExceptionPc) NextPc = Register[14] - 4; return NextPc;}VOIDUnwindDataProcess(ARMI instr, PULONG Register)/*++Routine Description: This function executes an ARM data processing instruction using the current register set. It automatically updates the destination register.Arguments: instr The ARM 32-bit instruction Register Pointer to the ARM integer registers.Return Value: None.--*/{ ULONG Op1, Op2; ULONG Cflag = (Register[16] & 0x20000000L) == 0x20000000L; // CPSR ULONG shift; // We are checking for all addressing modes and op codes, even though // the prolog and epilog don't use them all right now. In the future, // more instructions and addressing modes may be added. // // Figure out the addressing mode (there are 11 of them), and get the // operands. Op1 = Register[instr.dataproc.rn]; if (instr.dataproc.bits == 0x1) { // Immediate addressing - Type 1 Op2 = _lrotr(instr.dpi.immediate, instr.dpi.rotate * 2); } else { // Register addressing - start by getting the value of Rm. Op2 = Register[instr.dpshi.rm]; if (instr.dprre.bits == 0x6) { // Rotate right with extended - Type 11 Op2 = (Cflag << 31) | (Op2 >> 1); } else if (instr.dataproc.operand2 & 0x10) { // Register shifts. Types 4, 6, 8, and 10 // // Get the shift value from the least-significant byte of the // shift register. shift = Register[instr.dpshr.rs] & 0xFF; switch(instr.dpshr.bits) { case 0x1: // 4 Logical shift left by register if (shift >= 32) Op2 = 0; else Op2 = Op2 << shift; break; case 0x3: // 6 Logical shift right by register if (shift >= 32) Op2 = 0; else Op2 = Op2 >> shift; break; case 0x5: // 8 Arithmetic shift right by register if (shift >= 32) { if (Op2 & 0x80000000) Op2 = 0xffffffff; else Op2 = 0; } else Op2 = (LONG)Op2 >> shift; break; case 0x7: // 10 Rotate right by register if ((shift & 0xf) != 0) Op2 = _lrotl(Op2, shift); default: break; } } else { // Immediate shifts. Types 2, 3, 5, 7, and 9 // // Get the shift value from the instruction. shift = instr.dpshi.shift; switch(instr.dpshi.bits) { case 0x0: // 2,3 Register, Logical shift left by immediate if (shift != 0) Op2 = Op2 << shift; break; case 0x2: // 5 Logical shift right by immediate if (shift == 0) Op2 = 0; else Op2 = Op2 >> shift; break; case 0x4: // 7 Arithmetic shift right by immediate if (shift == 0) Op2 = 0; else Op2 = (LONG)Op2 >> shift; break; case 0x6: // 9 Rotate right by immediate Op2 = _lrotl(Op2, shift); break; default: break; } } } // Determine the result (the new PC), based on the opcode. switch(instr.dataproc.opcode) { case OP_AND: Register[instr.dataproc.rd] = Op1 & Op2; break; case OP_EOR: Register[instr.dataproc.rd] = Op1 ^ Op2; break; case OP_SUB: Register[instr.dataproc.rd] = Op1 - Op2; break; case OP_RSB: Register[instr.dataproc.rd] = Op2 - Op1; break; case OP_ADD: Register[instr.dataproc.rd] = Op1 + Op2; break; case OP_ADC: Register[instr.dataproc.rd] = (Op1 + Op2) + Cflag; break; case OP_SBC: Register[instr.dataproc.rd] = (Op1 - Op2) - ~Cflag; break; case OP_RSC: Register[instr.dataproc.rd] = (Op2 - Op1) - ~Cflag; break; case OP_ORR: Register[instr.dataproc.rd] = Op1 | Op2; break; case OP_MOV: Register[instr.dataproc.rd] = Op2; break; case OP_BIC: Register[instr.dataproc.rd] = Op1 & ~Op2; break; case OP_MVN: Register[instr.dataproc.rd] = ~Op2; break; case OP_TST: case OP_TEQ: case OP_CMP: case OP_CMN: default: // These instructions do not have a destination register. // There is nothing to do. break; }}BOOLUnwindLoadMultiple(ARMI instr, PULONG Register)/*++Routine Description: This function executes an ARM load multiple instruction.Arguments: instr The ARM 32-bit instruction Register Pointer to the ARM integer registers.Return Value: TRUE if successful, FALSE otherwise.--*/{ LONG i; ULONG RegList; PULONG Rn; // Load multiple with the PC bit set. We are currently checking for all // four addressing modes, even though decrement before and increment // after are the only modes currently used in the epilog and prolog. // // Rn is the address at which to begin, and RegList is the bit map of which // registers to read. Rn = (PULONG)Register[instr.ldm.rn]; RegList = instr.ldm.reglist; if (instr.ldm.p) { if (instr.ldm.u) { // Increment before for(i = 0; i <= 15; i++) { if (RegList & 0x1) { Rn++; if (!ReadMemory(Rn, &Register[i], 4)) return FALSE; } RegList = RegList >> 1; } } else { // Decrement before for(i = 15; i >= 0; i--) { if (RegList & 0x8000) { Rn--; if (!ReadMemory(Rn, &Register[i], 4)) return FALSE; } RegList = RegList << 1; } } } else { if (instr.ldm.u) { // Increment after for(i = 0; i <= 15; i++) { if (RegList & 0x1) { if (!ReadMemory(Rn, &Register[i], 4)) return FALSE; Rn++; } RegList = RegList >> 1; } } else { // Decrement after for(i = 15; i >= 0; i--) { if (RegList & 0x8000) { if (!ReadMemory(Rn, &Register[i], 4)) return FALSE; Rn--; } RegList = RegList << 1; } } } if (instr.ldm.w) Register[instr.ldm.rn] = (ULONG)Rn; // Update the base register. return TRUE;}BOOLUnwindLoadI(ARMI instr, PULONG Register)/*++Routine Description: This function executes an ARM load instruction with an immediat offset.Arguments: instr The ARM 32-bit instruction Register Pointer to the ARM integer registers.Return Value: TRUE if successful, FALSE otherwise.--*/{ LONG offset; LONG size; PULONG Rn; Rn = (PULONG)Register[instr.ldr.rn]; offset = instr.ldr.offset; if (instr.ldr.u == 0) offset = -offset; if (instr.ldr.b == 0) size = 4; else size = 1; if (instr.ldm.p) { // add offset before transfer if (!ReadMemory(Rn + offset, &Register[instr.ldr.rd], size)) return FALSE; if (instr.ldr.w) Register[instr.ldr.rn] += offset; } else { if (!ReadMemory(Rn, &Register[instr.ldr.rd], size)) return FALSE; if (instr.ldr.w) Register[instr.ldr.rn] += offset; } return TRUE;}BOOLCheckConditionCodes(ULONG CPSR, DWORD instr)/*++Routine Description: Checks the condition codes of the instruction and the values of the condition flags in the current program status register, and determines whether or not the instruction will be executed.Arguments: CPSR - The value of the Current Program Status Register. instr - The instruction to analyze.Return Value: TRUE if the instruction will be executed, FALSE otherwise.--*/{ BOOL Execute = FALSE; BOOL Nset = (CPSR & 0x80000000L) == 0x80000000L; BOOL Zset = (CPSR & 0x40000000L) == 0x40000000L; BOOL Cset = (CPSR & 0x20000000L) == 0x20000000L; BOOL Vset = (CPSR & 0x10000000L) == 0x10000000L; switch(instr & COND_MASK) { case COND_EQ: // Z set if (Zset) Execute = TRUE; break; case COND_NE: // Z clear if (!Zset) Execute = TRUE; break; case COND_CS: // C set if (Cset) Execute = TRUE; break; case COND_CC: // C clear if (!Cset) Execute = TRUE; break; case COND_MI: // N set if (Nset) Execute = TRUE; break; case COND_PL: // N clear if (!Nset) Execute = TRUE; break; case COND_VS: // V set if (Vset) Execute = TRUE; break; case COND_VC: // V clear if (!Vset) Execute = TRUE; break; case COND_HI: // C set and Z clear if (Cset && !Zset) Execute = TRUE; break; case COND_LS: // C clear or Z set if (!Cset || Zset) Execute = TRUE; break; case COND_GE: // N == V if ((Nset && Vset) || (!Nset && !Vset)) Execute = TRUE; break; case COND_LT: // N != V if ((Nset && !Vset) || (!Nset && Vset)) Execute = TRUE; break; case COND_GT: // Z clear, and N == V if (!Zset && ((Nset && Vset) || (!Nset && !Vset))) Execute = TRUE; break; case COND_LE: // Z set, and N != V if (Zset && ((Nset && !Vset) || (!Nset && Vset))) Execute = TRUE; break; case COND_AL: // Always execute Execute = TRUE; break; default: case COND_NV: // Never - undefined. Execute = FALSE; break; } return Execute;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -