📄 unwind.c
字号:
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;
}
}
//------------------------------------------------------------------------------
//
// 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.
//
//------------------------------------------------------------------------------
BOOL
UnwindLoadMultiple(
ARMI instr,
PULONG Register
)
{
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;
}
//------------------------------------------------------------------------------
//
// 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.
//
//------------------------------------------------------------------------------
BOOL
UnwindLoadI(
ARMI instr,
PULONG Register
)
{
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;
}
//------------------------------------------------------------------------------
//
// 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
CheckConditionCodes(
ULONG CPSR,
DWORD instr
)
{
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, or 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 + -