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

📄 kdbreak.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
Routine Description:

    This routine intanciate (replace original instruction with software trap)
    on a given breakpoint table entry.

Arguments:

    [in] BpHandle - Supplies the BpHandle to instanciate

Return Value:

    Same value as BpHandle if succeeded
    0 or negative value if failed

--*/

int KdpInstantiateSwBreakpoint (int BpHandle)
{
    int bphRet = BpHandle;
    DWORD Index = BpHandle - 1;
    BOOL fAccessible = FALSE;
    void * Address = NULL;
    ULONG ulBpInstrLen = sizeof (KDP_BREAKPOINT_TYPE);
    KDP_BREAKPOINT_TYPE KdpBreakpointInstruction = KDP_BREAKPOINT_VALUE;

    DEBUGGERMSG (KDZONE_SWBP, (L"++KdpInstantiateSwBreakpoint (%d)\r\n", BpHandle));

    if ((Index < BREAKPOINT_TABLE_SIZE) &&
        g_aBreakpointTable [Index].wRefCount &&
        (g_aBreakpointTable [Index].Flags & KD_BREAKPOINT_SUSPENDED))
    { // Check that entry is good
        BYTE *pbBpKAddr;
        Address = g_aBreakpointTable [Index].Address;
        g_aBreakpointTable[Index].KAddr = NULL;
        pbBpKAddr = MapToDebuggeeCtxKernEquivIfAcc ((BYTE *) Address, TRUE); // Kernel equivalent if this address is paged-in (do not force page-in)
        if (pbBpKAddr)
        { // Memory is paged
#if defined(MIPSII) || defined(THUMBSUPPORT)
            if (g_aBreakpointTable [Index].Flags & KD_BREAKPOINT_16BIT)
            {
                ulBpInstrLen = sizeof (KDP_BREAKPOINT_16BIT_TYPE);
                KdpBreakpointInstruction = KDP_BREAKPOINT_16BIT_VALUE;
            }
#endif
            /* Save the KAddr for the scenario in which the debugger is unable to find the
             * KAddr during delete (module pages decommitted/lost before attempt to delete
             * breakpoint). */
            g_aBreakpointTable[Index].KAddr = pbBpKAddr;

            // Get the instruction to be replaced
            if (KdpMoveMemory ((char *) &Content, pbBpKAddr, ulBpInstrLen ) != ulBpInstrLen)
            {
                DEBUGGERMSG (KDZONE_ALERT, (L"  KdpInstantiateSwBreakpoint: Cannot read access apparently paged KAddress (0x%08X)\r\n", pbBpKAddr));
            }
            else
            {
                DEBUGGERMSG (KDZONE_SWBP, (L"  KdpInstantiateSwBreakpoint: Successfully reading BP location\r\n"));
                fAccessible = TRUE;
                KdpSanitize ((BYTE *) &Content, pbBpKAddr, ulBpInstrLen, FALSE);
                DEBUGGERMSG (KDZONE_SWBP, (L"  KdpInstantiateSwBreakpoint: Successfully read 0x%08X at 0x%08X\r\n", (DWORD) Content, pbBpKAddr));
            }

            if (fAccessible)
            {
                BOOL fBpSet = FALSE;
                BOOL fRomBp = FALSE;

                // determine whether the address is in ROM space
                if (kdpIsROM (pbBpKAddr, 1))
                {
                    fRomBp = TRUE;
                    DEBUGGERMSG (KDZONE_SWBP, (L"  KdpInstantiateSwBreakpoint: Breakpoint is reported in ROM\r\n"));
                }
                else
                {
                    fBpSet = KdpWriteBpAndVerify (pbBpKAddr, &KdpBreakpointInstruction, ulBpInstrLen);
                    if (!fBpSet)
                    { // the write failed
                        DEBUGGERMSG (KDZONE_SWBP, (L"  KdpInstantiateSwBreakpoint: Breakpoint could not be set - assume it is a ROM BP\r\n"));
                        fRomBp = TRUE;
                    }
                }

                if (fRomBp && *(g_kdKernData.pfForcedPaging))
                { // if BP in ROM and we are in High VM intrusiveness mode
                    int bphRomRet;
                    int idxRom2Ram = 0;
                    void* pvBpRamAddr;

                    DEBUGGERMSG (KDZONE_SWBP, (TEXT("  KdpInstantiateSwBreakpoint: Address is in ROM space\r\n")));

                    bphRomRet = KdpRomSwBpAttemptRamPageRemap (Address, pbBpKAddr, &idxRom2Ram, &pvBpRamAddr);

                    if (bphRomRet != KD_BPHND_ROMBP_SUCCESS)
                    {
                        // If we failed, there is no point doing anything else,
                        // so just leave returning the ROM BP error
                        bphRet = bphRomRet;
                    }
                    else
                    { // Try again
                        fBpSet = KdpWriteBpAndVerify (pvBpRamAddr, &KdpBreakpointInstruction, ulBpInstrLen);
                        if (!fBpSet)
                        { // the write failed again
                            bphRet = KD_BPHND_INVALID_GEN_ERR;

                            DEBUGGERMSG (KDZONE_ALERT, (TEXT("  KdpInstantiateSwBreakpoint: Failed to write in remapped ROM!\r\n")));
                            // fail to instanciate ROM BP, revert mapping
                            KdpRestoreRomVmPageMapping (idxRom2Ram);
                        }
                    }
                }

                if (fBpSet)
                { // The BP was written
                    DEBUGGERMSG (KDZONE_SWBP, (L"  KdpInstantiateSwBreakpoint: Updating BP entry\r\n"));
                    g_aBreakpointTable [Index].Content = Content;
                    g_aBreakpointTable [Index].Flags &= ~KD_BREAKPOINT_SUSPENDED;
                    g_aBreakpointTable[Index].Flags |= KD_BREAKPOINT_WRITTEN;

                    // Check if the address is in ROM and increment the use count.
                    // We need to do this even if fRomBp == FALSE, since 
                    // a ROM page may already be remapped to RAM.
                    fRomBp = KdpIncCountIfRomSwBp(Address);
                    
                    if (fRomBp)
                    {
                        g_aBreakpointTable [Index].Flags |= KD_BREAKPOINT_INROM;
                    }
                }
                else
                {
                    DEBUGGERMSG (KDZONE_SWBP, (L"  KdpInstantiateSwBreakpoint: BP cannot set (probably ROM BP in kernel code or ROM BP while in non-intrusive mode)!\r\n"));
                    if (bphRet > KD_BPHND_INVALID_GEN_ERR) bphRet = KD_BPHND_INVALID_GEN_ERR;
                }
            }
        }
        else
        {
            DEBUGGERMSG (KDZONE_SWBP, (L"  KdpInstantiateSwBreakpoint: Unpaged address\r\n"));
        }
    }
    else
    {
        DEBUGGERMSG (KDZONE_ALERT, (L"  KdpInstantiateSwBreakpoint: invalid BP entry\r\n"));
    }

    DEBUGGERMSG (KDZONE_SWBP, (L"--KdpInstantiateSwBreakpoint (bph=%i)\r\n", bphRet));
    return bphRet;
}


/*++

Routine Name:

    KdpHandlePageInBreakpoints

Routine Description:

   This routine is called in response to the OS having performed a page in.
   The function will determine whether any breakpoints need to be set in the
   address range of the recently paged-in page and will attempt to instantiate
   those breakpoints by calling into KdpAddBreakpoint.

   ASSUMPTIONS:
   -XIP ROM code is never paged in or out
   -We get multiple notifications in case of multiple VM mappings of the same code.
    This is not the case for virtually copied data but we are going to assume that
    users will never put code in virtually copied pages themselves. In that unlikely case,
    the breakpoints will simply have potential side effects in case of page out / back in.

Arguments:

    [in] ulAddress - supplies the starting address of the page just paged in
    [in] ulNumPages - The number of pages that were paged in.  This is added to make
                    module load / process load of non-pageable modules / processes faster.

Return Value:

    None.

--*/

VOID KdpHandlePageInBreakpoints (ULONG ulAddress, ULONG ulNumPages)
{
    int cBp = 0; // Counter of BP tested to speed up iteration
    int nIndex;
    ULONG ulStartAddress = ulAddress;
    ULONG ulEndAddress = ulStartAddress + (ulNumPages * PAGE_SIZE);

    DEBUGGERMSG (KDZONE_VIRTMEM && KDZONE_SWBP, (L"++KdpHandlePageInBreakpoints (0x%08X - 0x%08X, %d)\r\n", ulStartAddress, ulEndAddress, ulNumPages));

    // Search the global table to see if there are any addresses within
    // the page that was just paged in that were supposed
    // to have BP's instantiated. This includes addresses that had trap
    // instructions in them, but were paged out, and those that were
    // not paged in until now and never had a BP written to them. Attempt
    // to write BP's to all addresses within the page that fullfil those
    // requirements.

    // NOTE: Don't try to debug this code using KdStub itself as it will likely modify the BP table
    //  in order to step

    for (nIndex = 0;
         (cBp < g_nTotalNumDistinctSwCodeBps) && (nIndex < BREAKPOINT_TABLE_SIZE);
         nIndex++)
    {
        BYTE bFlagsTemp = g_aBreakpointTable [nIndex].Flags;
        if (g_aBreakpointTable [nIndex].wRefCount)
        {
            ULONG ulAddrTemp = (ULONG) g_aBreakpointTable [nIndex].Address;
            cBp++; // Note: even suspended BP are counted here as they are part of the g_nTotalNumDistinctSwCodeBps

            if (!(kdpKData->dwInDebugger && (bFlagsTemp & KD_BREAKPOINT_SUSPENDED))  &&
                (ulAddrTemp >= ulStartAddress) && 
                (ulAddrTemp < ulEndAddress))
            { // Any BP in range, except if suspended while in debugger:
                ULONG ulBpInstrLen = sizeof (KDP_BREAKPOINT_TYPE);
                KDP_BREAKPOINT_TYPE KdpBreakpointInstruction = KDP_BREAKPOINT_VALUE;
#if defined(MIPSII) || defined(THUMBSUPPORT)
                if (bFlagsTemp & KD_BREAKPOINT_16BIT)
                {
                    ulBpInstrLen = sizeof (KDP_BREAKPOINT_16BIT_TYPE);
                    KdpBreakpointInstruction = KDP_BREAKPOINT_16BIT_VALUE;
                }
#endif
                ReadBack = 0;
                if (ulBpInstrLen != KdpMoveMemory ((char *) &ReadBack, (char *) ulAddrTemp, ulBpInstrLen))
                {
                    DEBUGGERMSG (KDZONE_VIRTMEM && KDZONE_SWBP, (L"  KdpHandlePageInBreakpoints: Failed to read instruction of BP\r\n"));
                }
                else
                {
                    BOOL fIsBpInstr = !memcmp (&ReadBack, &KdpBreakpointInstruction, ulBpInstrLen);
                    if (fIsBpInstr)
                    { // SW Breakpoint instruction already present - Re-instantiation not necessary - Probably new mapping (VirtualCopy) notification only
                        DEBUGGERMSG (KDZONE_SWBP, (L"  KdpHandlePageInBreakpoints: existing instruction already a SW breakpoint - this must be a VirtualCopy PageIn notification - bypassing BP instantiation\r\n"));
                    }
                    else
                    { // should be reinstantiated
                        DEBUGGERMSG (KDZONE_VIRTMEM && KDZONE_SWBP, (L"  KdpHandlePageInBreakpoints: Found address (0x%08X) within page range(0x%08X - 0x%08X) with flag %02X\r\n", ulAddrTemp, ulStartAddress, ulEndAddress, bFlagsTemp));              
                        g_aBreakpointTable [nIndex].Flags |= KD_BREAKPOINT_SUSPENDED; // tag as suspended until actual instantiation succeeds
                        KdpInstantiateSwBreakpoint (nIndex + 1); // Attempt instanciations
                    }
                }
            }
        }
    }

    // If we are in break state while this notification happens, then tell the host debugger to refresh its memory
    if ((kdpKData->dwInDebugger) && !(*(g_kdKernData.pfForcedPaging))) g_fDbgKdStateMemoryChanged = TRUE; // Note: will only be passed on next reply to debugger command

    DEBUGGERMSG (KDZONE_VIRTMEM && KDZONE_SWBP, (L"--KdpHandlePageInBreakpoints\r\n"));
}


/*++

Routine Name:

    KdpCleanupIfRomSwBp

Routine Description:

    This routine is usually called when a breakpoint has sucessfully
    been removed from the argument address. It determines whether the
    argument address is within the range of any of the used pre-allocated
    RAM pages, and if so decrements the breakpoint use count variable
    for that page. If the count is zero (since that was the last breakpoint)
    then the page is remapped to point to the orginal ROM page address and
    the RAM page is marked as free.

Arguments:

    [in] pvAddr - supplies the address where a breakpoint was just removed from

Return Value:

    TRUE if BP was in ROM.

--*/

BOOL KdpCleanupIfRomSwBp (void * pvAddr)
{
    int nIndex = 0;
    DWORD dwROMAddrTemp = 0;
    DWORD dwAddr = (DWORD) pvAddr;
    BOOL fRet = FALSE;

    DEBUGGERMSG (KDZONE_SWBP, (TEXT ("++KdpCleanupIfRomSwBp (0x%08X)\r\n"), dwAddr));

    for (nIndex = 0; (nIndex < NB_ROM2RAM_PAGES) && !fRet; nIndex++)
    {
        dwROMAddrTemp = (DWORD) (g_aRom2RamPageTable[nIndex].pvROMAddr);

        // Check if the address of the breakpoint just deleted
        // falls in any of our preallocated/remapped ROM/RAM pages
        if ((dwAddr >= dwROMAddrTemp) && (dwAddr < dwROMAddrTemp + PAGE_SIZE))
        {
            DEBUGGERMSG (KDZONE_SWBP, (TEXT ("  KdpCleanupIfRomSwBp: Address found in page %d between (0x%08X) and (0x%08X)\r\n"), nIndex, dwROMAddrTemp, dwROMAddrTemp+PAGE_SIZE));
            fRet = TRUE;

            // Decrement the breakpoint use count for that page
             g_aRom2RamPageTable[nIndex].nBPCount--;

            DEBUGGERMSG (KDZONE_SWBP, (TEXT ("  KdpCleanupIfRomSwBp: Page %d Count decremented to %d\r\n"), nIndex, g_aRom2RamPageTable[nIndex].nBPCount));

            // If that pages count variable is zero, we better remap the VA that used
            // to point to ROM, back to ROM (since it was changed to point to the RAM
            // page until now) - mark the page as free
            if (!g_aRom2RamPageTable[nIndex].nBPCount)
            {
                DEBUGGERMSG (KDZONE_SWBP, (TEXT("  KdpCleanupIfRomSwBp: Count is 0, freeing page\r\n")));

                if (!KdpRestoreRomVmPageMapping (nIndex))
                {
                    DEBUGGERMSG (KDZONE_ALERT, (TEXT("  KdpCleanupIfRomSwBp: ROM to RAM unmap failed! System may become unstable\r\n")));
                    // If remapping failed, there's not much we can do
                }
            }
        }
    }

    DEBUGGERMSG (KDZONE_SWBP, (TEXT ("--KdpCleanupIfRomSwBp (found=%d)\r\n"),fRet));
    return fRet;
}

/*++

Routine Description:

    This routine adds an entry to the breakpoint table and returns a handle
    to the breakpoint table entry.

Arguments:

    [in] Address - Supplies the address where to set the breakpoint.

Return Value:

    A value of zero is returned if the specified address is already in the
    breakpoint table, there are no free entries in the breakpoint table, the
    specified address is not correctly aligned, or the specified address is
    not valid. Otherwise, the index of the assigned breakpoint table entry
    plus one is returned as the function value.

--*/

ULONG KdpAddBreakpoint (PVOID Address)
{
    int bphRet = KD_BPHND_INVALID_GEN_ERR;

⌨️ 快捷键说明

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