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

📄 kdbreak.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
    ULONG Index;
    BOOLEAN Accessible = FALSE;
    BOOLEAN Mode16Bit = FALSE; // used for Thumb and MIPS16
    BOOLEAN KAccessible = FALSE;
    KDP_BREAKPOINT_TYPE KdpBreakpointInstruction = KDP_BREAKPOINT_VALUE;
    ULONG ulBpInstrLen = sizeof (KDP_BREAKPOINT_TYPE);
    BOOL fBpSet = FALSE;

    BOOL fAddrUnpaged = FALSE;
    BOOL fKAddrUnpaged = FALSE;
    BOOL fUpdateBPTable = FALSE;
    BOOL fAttemptToWrite = FALSE;

    DEBUGGERMSG (KDZONE_SWBP, (L"++KdpAddBreakpoint (0x%08X)\r\n", Address));

#if defined(MIPSII) || defined(THUMBSUPPORT)
    //  update the breakpoint Instruction and ulBpInstrLen if stopped within
    //  16-bit code. (16-bit code indicated by LSB of Address)
    if (Is16BitSupported && ((ULONG) Address & 1))
    {
        DEBUGGERMSG (KDZONE_SWBP,(L"  KdpAddBreakpoint: 16 Bit breakpoint\r\n"));
        ulBpInstrLen = sizeof (KDP_BREAKPOINT_16BIT_TYPE);
        KdpBreakpointInstruction = KDP_BREAKPOINT_16BIT_VALUE;
        Address = (PVOID) ((ULONG) Address & ~1);
        Mode16Bit = TRUE;
    }
#endif

    // If the specified address is not properly aligned, then return zero.
    if ((ULONG) Address & (ulBpInstrLen - 1))
    {
        DEBUGGERMSG (KDZONE_SWBP, (L"  KdpAddBreakpoint: Address not aligned\r\n"));
    }
    else
    {
        int bphFreeEntry = KD_BPHND_INVALID_GEN_ERR;
        // Find an empty spot or identical entry in the table of BP
        for (Index = 0; (Index < BREAKPOINT_TABLE_SIZE) && (bphRet == KD_BPHND_INVALID_GEN_ERR); Index++)
        {
            if ((bphFreeEntry == KD_BPHND_INVALID_GEN_ERR) && !(g_aBreakpointTable [Index].wRefCount))
            {
                bphFreeEntry = Index + 1; // remember 1st free entry
            }
            if (g_aBreakpointTable [Index].wRefCount &&
                (g_aBreakpointTable [Index].Address == Address))
            {
                // Then we have a dup entry
                DEBUGGERMSG (KDZONE_SWBP | KDZONE_ALERT, (L"  KdpAddBreakpoint: Dup - Found existing BP (0x%08X) - should not happening if host-side aliasing / ref count! Risk of improper single steping!!!!\r\n", Address));
                bphRet = Index + 1;
                ++(g_aBreakpointTable [Index].wRefCount);
            }
        }

        if (bphRet == KD_BPHND_INVALID_GEN_ERR)
        { // if no dup, use free entry
            bphRet = bphFreeEntry;
            if (bphRet != KD_BPHND_INVALID_GEN_ERR)
            { // free entry available
                int bphTemp;
                // Create table entry
                bphRet = bphFreeEntry;
                g_aBreakpointTable [bphRet - 1].wRefCount = 1;
                g_aBreakpointTable [bphRet - 1].Address = Address;
                g_aBreakpointTable [bphRet - 1].Flags = KD_BREAKPOINT_SUSPENDED; // Reserve suspended until actually instantiated
                if (Mode16Bit)
                {
                    g_aBreakpointTable [bphRet - 1].Flags |= KD_BREAKPOINT_16BIT;
                }
                bphTemp = KdpInstantiateSwBreakpoint (bphRet);
                if (bphRet != bphTemp)
                { // Instantiation will never be possible for this BP
                    g_aBreakpointTable [bphRet - 1].Flags = 0; // discard BP entry
                    g_aBreakpointTable [bphRet - 1].Content = 0;
                    g_aBreakpointTable [bphRet - 1].Address = NULL;
                    g_aBreakpointTable [bphRet - 1].wRefCount = 0;
                    bphRet = bphTemp;
                }
                else
                {
                    g_nTotalNumDistinctSwCodeBps++;
                }
            }
            else
            {
                DEBUGGERMSG (KDZONE_SWBP, (L"  KdpAddBreakpoint: Maximum number of Breakpoints reach. Cannot handle this one\r\n"));
            }
        }
    }

    DEBUGGERMSG (KDZONE_SWBP, (L"--KdpAddBreakpoint: (handle = %i)\r\n", bphRet));
    return bphRet;
}


/*++

Routine Description:

    This routine deletes an entry from the breakpoint table.

Arguments:

    [in] Handle - Supplies the index plus one of the breakpoint table entry
        which is to be deleted.

Return Value:

    A value of FALSE is returned if the specified handle is not a valid
    value or the breakpoint cannot be deleted because the old instruction
    cannot be replaced. Otherwise, a value of TRUE is returned.

--*/

BOOLEAN KdpDeleteBreakpoint (ULONG Handle)
{
    BOOLEAN fRet = FALSE;
    KDP_BREAKPOINT_TYPE KdpBreakpointInstruction = KDP_BREAKPOINT_VALUE;
    ULONG ulBpInstrLen = sizeof (KDP_BREAKPOINT_TYPE);
    ULONG Index = Handle - 1; // Handles are 1-based; 0 is an invalid handle value

    DEBUGGERMSG (KDZONE_SWBP, (L"++KdpDeleteBreakpoint Handle=%i\r\n", Handle));

    // If the specified handle is not valid, then return FALSE.
    if ((Index >= BREAKPOINT_TABLE_SIZE) ||
        !(g_aBreakpointTable[Index].wRefCount))
    {
        DEBUGGERMSG (KDZONE_ALERT, (L"  KdpDeleteBreakpoint: Invalid handle\r\n"));
    }
    else 
    {
        --g_aBreakpointTable [Index].wRefCount;
        if (!(g_aBreakpointTable [Index].wRefCount))
        { // ref count null: really delete BP
            BYTE *pbBpKAddr = MapToDebuggeeCtxKernEquivIfAcc ((BYTE *) (g_aBreakpointTable [Index].Address), TRUE);
#if defined(MIPSII) || defined(THUMBSUPPORT)
            // Determine the breakpoint instruction and size
            if (Is16BitSupported && (g_aBreakpointTable[Index].Flags & KD_BREAKPOINT_16BIT))
            {
                ulBpInstrLen = sizeof (KDP_BREAKPOINT_16BIT_TYPE);
                KdpBreakpointInstruction = KDP_BREAKPOINT_16BIT_VALUE;
            }
#endif

            // Kdstub does not know when page is paged out. If we did, we could
            // sanitize it to have readonly mem in RAM behave similarily to
            // readonly mem in ROM. This block assumes that the kaddr used to
            // write the breakpoint is still valid.
            if (!pbBpKAddr)
            {
                if (g_aBreakpointTable[Index].KAddr)
                {
                    KDP_BREAKPOINT_TYPE Instruction = 0;

                    // Just in case there is an access violation on memmove.
                    __try
                    {
                        if (memmove (&Instruction, g_aBreakpointTable[Index].KAddr, ulBpInstrLen))
                        {
                            if (Instruction == KdpBreakpointInstruction)            // If Breakpoint Found.
                            {
                                DEBUGGERMSG (KDZONE_SWBP,
                                    (L"  KdpDeleteBreakpoint: Found BP at kaddr(0x%08X) - Preemptively restoring instruction.\r\n",
                                        g_aBreakpointTable[Index].KAddr));
                                pbBpKAddr = g_aBreakpointTable[Index].KAddr;        // Mark it for cleaning.
                            }
                            else
                                DEBUGGERMSG (KDZONE_SWBP,
                                    (L"  KdpDeleteBreakpoint: No BP found at kaddr(0x%08X) - Not restoring instruction.\r\n",
                                        g_aBreakpointTable[Index].KAddr));
                        }
                    }
                    __except (EXCEPTION_EXECUTE_HANDLER)
                    {
                        DEBUGGERMSG (KDZONE_SWBP,
                            (L"  KdpDeleteBreakpoint: Unable to read kaddr(0x%08X) - Not restoring instruction.\r\n",
                                g_aBreakpointTable[Index].KAddr));
                    }
                }
            }

            if (!pbBpKAddr) // Test accessibility (won't page-in)
            { // If the breakpoint is not instatiated, then just nullify the table entry, no need to copy anything
                DEBUGGERMSG (KDZONE_SWBP, (L"  KdpDeleteBreakpoint: Deleting entry for unpaged address (0x%08X)\r\n", g_aBreakpointTable[Index].Address));
                fRet = TRUE;
            }
            else
            { // Otherwise, if the BP is actually set, then replace the old instruction and nullify the entry
                fRet = KdpWriteBpAndVerify (pbBpKAddr, &g_aBreakpointTable [Index].Content, ulBpInstrLen);
                if (!fRet)
                {
                    DEBUGGERMSG (KDZONE_ALERT, (L"  KdpDeleteBreakpoint: Could not write original instruction back for BP (%i) Addr=0x%08X, KAddr=0x%08X\r\n", Index, g_aBreakpointTable[Index].Address, pbBpKAddr));
                }
            }

            if (g_aBreakpointTable [Index].Flags & KD_BREAKPOINT_INROM)
            { // If BP was in ROM, cleanup remapping to RAM
                KdpCleanupIfRomSwBp (g_aBreakpointTable[Index].Address);
            }

            // Delete breakpoint table entry and return TRUE.
            g_aBreakpointTable[Index].Flags = 0;
            g_aBreakpointTable[Index].Content = 0;
            g_aBreakpointTable[Index].Address = NULL;
            g_aBreakpointTable[Index].KAddr = NULL;
            if (g_nTotalNumDistinctSwCodeBps) g_nTotalNumDistinctSwCodeBps--;
        }
        else if (!(g_aBreakpointTable[Index].Flags & KD_BREAKPOINT_WRITTEN))
        {
            // Breakpoint was never written.  This should never happen.
            DEBUGGERMSG (KDZONE_SWBP | KDZONE_ALERT, (L"  KdpDeleteBreakpoint: Deleting entry for unwritten breakpoint @(0x%08X)\r\n", g_aBreakpointTable[Index].Address));
            fRet = TRUE;
        } 
        else
        {
            DEBUGGERMSG (KDZONE_SWBP | KDZONE_ALERT, (L"  KdpDeleteBreakpoint: Dup - Removing multi-ref BP @(0x%08X) - should not happening if host-side aliasing / ref count! Risk of improper single steping!!!!\r\n", g_aBreakpointTable[Index].Address));
            fRet = TRUE;
        }
    }

    DEBUGGERMSG (KDZONE_SWBP, (L"--KdpDeleteBreakpoint (%d)\r\n", (int) fRet));
    return fRet;
}


/*++

Routine Description:

    Call KdpDeleteBreakpoint on every breakpoint handle and ignore the result.  If all
    goes well, this should remove all breakpoints in the system and allow it to
    execute normally.

--*/

VOID KdpDeleteAllBreakpoints (VOID)
{
    ULONG i;

    DEBUGGERMSG (KDZONE_SWBP, (L"++KdpDeleteAllBreakpoints\r\n"));

    // handles are 1-based
    for (i = 1; g_nTotalNumDistinctSwCodeBps && (i <= BREAKPOINT_TABLE_SIZE); i++)
    {
        if (g_aBreakpointTable [i - 1].wRefCount) KdpDeleteBreakpoint (i);
    }

    memset (g_aBreakpointTable, 0, sizeof (g_aBreakpointTable)); // clean up (necessary for 1st time init)

    DEBUGGERMSG(KDZONE_SWBP, (L"--KdpDeleteAllBreakpoints\r\n"));
}


/*++

Routine Description:

    Suspend the specified breakpoint by restoring its instruction

Arguments:

    Index - index of the breakpoint to suspend (NOTE: NOT THE HANDLE)

Return Value:

    TRUE - the breakpoint was suspended
    FALSE - otherwise

--*/

BOOLEAN KdpSuspendBreakpoint (ULONG Index)
{
    BOOLEAN fRet = FALSE;
    KDP_BREAKPOINT_TYPE KdpBreakpointInstruction = KDP_BREAKPOINT_VALUE;
    ULONG ulBpInstrLen = sizeof (KDP_BREAKPOINT_TYPE);

    DEBUGGERMSG (KDZONE_SWBP, (L"++KdpSuspendBreakpoint (handle=%i)\r\n", Index + 1));

    // Determine the breakpoint instruction and size
#if defined(MIPSII) || defined(THUMBSUPPORT)
    if (Is16BitSupported && (g_aBreakpointTable[Index].Flags & KD_BREAKPOINT_16BIT))
    {
        ulBpInstrLen = sizeof(KDP_BREAKPOINT_16BIT_TYPE);
        KdpBreakpointInstruction = KDP_BREAKPOINT_16BIT_VALUE;
    }
#endif
    // Replace the instruction contents.
    if (g_aBreakpointTable [Index].wRefCount &&
        !(g_aBreakpointTable [Index].Flags & KD_BREAKPOINT_SUSPENDED))
    {
        BYTE *pbBpKAddr = MapToDebuggeeCtxKernEquivIfAcc ((BYTE *) (g_aBreakpointTable [Index].Address), TRUE);

        if (pbBpKAddr)
        {
            DEBUGGERMSG (KDZONE_SWBP, (L"  KdpSuspendBreakpoint: Suspending BP 0x%08X\r\n", g_aBreakpointTable[Index].Address));
            fRet = KdpWriteBpAndVerify (pbBpKAddr, &g_aBreakpointTable [Index].Content, ulBpInstrLen);
            if (!fRet)
            {
                DEBUGGERMSG (KDZONE_ALERT, (L"  KdpSuspendBreakpoint: Suspend failed!\r\n"));
            }
        }
        else
        {
            DEBUGGERMSG (KDZONE_ALERT, (L"  KdpSuspendBreakpoint: BP at 0x%08X not mapped!\r\n", g_aBreakpointTable[Index].Address));
        }
        g_aBreakpointTable [Index].Flags |= KD_BREAKPOINT_SUSPENDED; // Tag suspended in all cases (in not writable, the SW trap instr is virtually removed)
    }

    DEBUGGERMSG(KDZONE_SWBP, (L"--KdpSuspendBreakpoint (%d)\r\n", (int) fRet));

    return fRet;
}


/*++

Routine Description:

    Suspend all breakpoints that are currently in use and not already suspened.

--*/

VOID KdpSuspendAllBreakpoints (VOID)
{
    ULONG Index;

    DEBUGGERMSG(KDZONE_SWBP, (L"++KdpSuspendAllBreakpoints\r\n"));

    // Examine each entry in the table in turn
    for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index++)
    {
        // Make sure breakpoint is in use and not already suspended
        if (g_aBreakpointTable [Index].wRefCount &&
            !(g_aBreakpointTable [Index].Flags & KD_BREAKPOINT_SUSPENDED))
        {
            KdpSuspendBreakpoint (Index);
        }
    }
    DEBUGGERMSG (KDZONE_SWBP, (L"--KdpSuspendAllBreakpoints\r\n"));
}


/*++

Routine Description:

    Reinstate any breakpoints that were suspended. This function should be called before exitting KdpTrap.

--*/

VOID KdpReinstateSuspendedBreakpoints (VOID)
{
    int Index;

⌨️ 快捷键说明

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