⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unwind.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
                if (!ReadMemorySanitized((PVOID)(EpilogPc+4), &instr2, 4))
                    return ControlPc;
                if ((instr2.instruction & B_BL_MASK) == B_INSTR ||
                    (instr2.instruction & BX_MASK) == BX_INSTR) {

                    if (!UnwindLoadMultiple(instr, Register))
                        return ControlPc;
                    *EstablisherFrame = Register[13];
                    return Register[14] - 4;
                } else
                    ExecutingEpilog = FALSE;
            } else
                ExecutingEpilog = FALSE;
            
            EpilogPc += 4;
        }
    }
    
    // We were not in the epilog. Load in the prolog, and reverse execute it.
    cb = PrologEndAddress - BeginAddress;
    if (cb > sizeof(Prolog)) {
        ASSERT(FALSE);    // prolog too large
        return ControlPc;
    }
    
    //
    //  Thumb assembly functions which switch to ARM via "bx pc" will have
    //  the low bit of the BeginAddress set. Align the BeginAddress
    //
    Address = BeginAddress & ~0x03;

    //  Read the prolog and restore debugger inserted break instructions to
    //  real instruction
    DEBUGMSG(ZONE_SEH, (TEXT("Reading Prolog @%8.8x\r\n"), Address));
    if (!ReadMemorySanitized((PVOID)Address, (PVOID)Prolog, cb))
        return ControlPc;
    
    // Check to see if we're already in the prolog.
    if (ControlPc < PrologEndAddress)
        cb = ControlPc - BeginAddress;
    else
        *InFunction = TRUE;
    *EstablisherFrame = Register[13];

    HaveExceptionPc = FALSE;
    
    // Reverse execute starting with the last instruction in the prolog
    // that has been executed.
    for (i = cb/4 - 1 ; i >= 0 ; --i) {

        // Test for these instructions:
        //
        //      SUB SP, X - stack allocation
        //
        //      MOV X, SP - save stack value
        //
        //      STMDB R13, {PC} - special instruction in fake prolog
        //
        //      STMDB - save incoming registers
        //
        //      MOV R11, X or
        //      ADD R11, X or
        //      SUB R11, X    - FP (frame pointer) setup
        //

        if ((Prolog[i].instruction & MOV_SP_MASK) == MOV_SP_INSTR) {

            Register[13] = Register[Prolog[i].dataproc.rd];

        } else if ((Prolog[i].instruction & SUB_SP_MASK) == SUB_SP_INSTR) {
            //
            // ldr       r12, [pc, #Immed]
            // sub       sp, sp, r12
            //
            // This is a stack link.  Unlink the stack.

            DEBUGMSG(ZONE_SEH, (TEXT("%d: stack link instr.\r\n"), i));
            if (Prolog[i].dataproc.bits != 0x1 && Prolog[i].dpshi.rm == 0xc) {
                
                // Look for an LDR instruction above this one.
                j = i - 1;
                while (j >= 0 && (Prolog[j].instruction & LDR_MASK) != LDR_PC_INSTR)
                    j--;

                if (j < 0) {
                    ASSERT(FALSE);  // This should never happen
                    return ControlPc;
                }
                
                // Get the address of the ldr instruction + 8 + the offset
                Address = j*4 + BeginAddress + Prolog[j].ldr.offset + 8;

                // R12 is the value at that location.
                if (!ReadMemory((PVOID)Address, (PVOID)&Register[12], 4))
                    return ControlPc;
            }
            
            // Change the subtract to an add, and execute the instruction
            Prolog[i].dataproc.opcode = OP_ADD;
            UnwindDataProcess(Prolog[i], Register);

        } else if ((Prolog[i].instruction & ADD_SP_MASK) == ADD_SP_INSTR) {
            //
            // ldr       r12, [pc, #Immed]
            // add       sp, sp, r12
            //
            // This is a stack link.  Unlink the stack.

            DEBUGMSG(ZONE_SEH, (TEXT("%d: stack link instr.\r\n"), i));
            if (Prolog[i].dataproc.bits != 0x1 && Prolog[i].dpshi.rm == 0xc) {
                // Look for an LDR instruction above this one.
                j = i - 1;
                while (j >= 0 && (Prolog[j].instruction & LDR_MASK) != LDR_PC_INSTR)
                    j--;
                
                if (j < 0) {
                    ASSERT(FALSE);  // This should never happen
                    return ControlPc;
                }

                // Get the address of the ldr instruction + 8 + the offset
                Address = j*4 + BeginAddress + Prolog[j].ldr.offset + 8;

                // R12 is the value at that location.
                if (!ReadMemory((PVOID)Address, (PVOID)&Register[12], 4))
                    return ControlPc;
            }
            
            // Change the subtract to an add, and execute the instruction
            Prolog[i].dataproc.opcode = OP_SUB;
            UnwindDataProcess(Prolog[i], Register);

        } else if ((Prolog[i].instruction & STM_PC_MASK) == STM_PC_INSTR) {
            //
            // STMDB R13!, { PC }
            //
            // This is an instruction that will not appear in a real prolog
            // (or probably anywhere else).  It is used as a marker in a fake
            // prolog as described below.
            //
            // In the usual case, the link register gets set by a call
            // instruction so the PC value should point to the instruction
            // that sets the link register.  In an interrupt or exception
            // frame, the link register and PC value are independent.  By
            // convention, the fake prolog for these frames (see
            // CaptureContext in armtrap.s) contains the STMDB instruction
            // shown above to lead the unwinder to the faulting PC location.
            //

            if (!ReadMemory((PULONG)Register[13], &NextPc, 4))
                return ControlPc;
            Register[13] += 4;
            HaveExceptionPc = TRUE;
        }
        else if ((Prolog[i].instruction & STM_MASK) == STM_INSTR) {
            //
            //  Invert the Load, Increment and Before bits:
            //
            Prolog[i].instruction ^= 0x01900000;
            if (!UnwindLoadMultiple(Prolog[i], Register))
                return ControlPc;

        } else if ((Prolog[i].instruction & STRI_LR_SPU_MASK)
                                                        == STRI_LR_SPU_INSTR) {

            // Store of the link register that updates the stack as a base
            // register must be reverse executed to restore LR and SP
            // to their values on entry. This type of prolog is generated
            // for finally funclets.
            ///NKDbgPrintfW(L"%d: STRI for  mask=%4.4x.\r\n", i, Prolog[i].ldr.offset);
            //
            //  Invert the Load, Increment and Before bits:
            //

            Prolog[i].instruction ^= 0x01900000;
            if (!UnwindLoadI(Prolog[i], Register))
                return ControlPc;

        } else if ((Prolog[i].instruction & ARM_MRS_MASK) == ARM_MRS_INSTR) {

            //
            // An "MRS rd, cpsr" instruction exists in CaptureContext to
            //  preserve the Psr register when unwinding out of system calls.
            //

            Context->Psr = Register[Prolog[i].mrs.rd];

        } else if ((Prolog[i].instruction & ADD_FP_MASK) == ADD_FP_INSTR
                   || (Prolog[i].instruction & SUB_FP_MASK) == SUB_FP_INSTR
                   || (Prolog[i].instruction & MOV_FP_MASK) == MOV_FP_INSTR) {

            // 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;
}




//------------------------------------------------------------------------------
//
//  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.
//
//------------------------------------------------------------------------------
VOID
UnwindDataProcess(
    ARMI instr,
    PULONG Register
    )
{
    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;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -