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

📄 kdbreak.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
/*++


Module Name:

    kdbreak.c

Abstract:

    This module implements machine dependent functions to add and delete
    breakpoints from the kernel debugger breakpoint table.

Revision History:

--*/

#include "kdp.h"


// The following variables are global for a reason.  Do not move them to the stack or bad things happen
// when flushing instructions.
KDP_BREAKPOINT_TYPE Content;
KDP_BREAKPOINT_TYPE ReadBack;

static BREAKPOINT_ENTRY g_aBreakpointTable [BREAKPOINT_TABLE_SIZE];

// This int holds the total number of distinct SW Code breakpoints that are set or need to be set
int g_nTotalNumDistinctSwCodeBps;


BOOL KdpWriteBpAndVerify (void * pvAddress, void * pbData, ULONG nSize)
{
    BOOL fRet = FALSE;
    BOOL fMcRet = FALSE;
    ULONG nRbSize;
    ULONG nMmSize;

    DEBUGGERMSG (KDZONE_SWBP, (L"++KdpWriteBpAndVerify (Addr=0x%08X, size=%d)\r\n", pvAddress, nSize));

    ReadBack = 0;
    nRbSize = KdpMoveMemory ((char *) &ReadBack, (char *) pvAddress, nSize);
    DEBUGGERMSG (KDZONE_SWBP, (L"  KdpWriteBpAndVerify: %s %d byte%s at 0x%08X, Data = 0x%0*X \r\n",
                                (nRbSize == nSize) ? L"Read " : L"Failed to read ", nSize,
                                (nRbSize == 1) ? L"" : L"s", pvAddress, nSize*2, ReadBack));

    nMmSize = KdpMoveMemory ((char *) pvAddress, pbData, nSize);
    DEBUGGERMSG (KDZONE_SWBP, (L"  KdpWriteBpAndVerify: %s %d byte%s at 0x%08X, Data = 0x%0*X \r\n",
                                (nMmSize == nSize) ? L"Wrote" : L"Failed to write", nSize,
                                (nMmSize == 1) ? L"" : L"s", pvAddress, nSize*2 ,*((KDP_BREAKPOINT_TYPE *) pbData)));

    ReadBack = 0;
    nRbSize = KdpMoveMemory ((char *) &ReadBack, (char *) pvAddress, nSize);
    if (nRbSize != nSize)
    {
        DEBUGGERMSG (KDZONE_SWBP, (L"  KdpWriteBpAndVerify: Failed to read back %d byte%s at 0x%08X (read %d)\r\n",
                                   nSize, (nMmSize == 1) ? L"" : L"s", nRbSize));
    }
    else
    {
        fMcRet = !memcmp (&ReadBack, pbData, nSize);
        DEBUGGERMSG (KDZONE_SWBP, (L"  KdpWriteBpAndVerify: Write%s was successful", fMcRet ? L"" : L" NOT"));
        if (fMcRet)
        {
            DEBUGGERMSG (KDZONE_SWBP, (L" (read back OK)\r\n"));
            fRet = TRUE;
        }
        else
        {
            DEBUGGERMSG (KDZONE_SWBP, (L" (read back 0x%0*X instead of 0x%0*X)\r\n", nSize*2, ReadBack, nSize*2, *((KDP_BREAKPOINT_TYPE *) pbData)));
        }
    }

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

    return fRet;
}


/*++

Routine Name:

    KdpRomSwBpAttemptRamPageRemap

Routine Description:

    This routine is called by the breakpoint addition routine when a breakpoint
    add request is made in ROM address space. When this function exits, if it
    has succeeded, the address can be used transparently by other functions -
    breakpoints can be successfully added or removed at that address.

    Basic algorithm:
    This is equivalent to Copy-On-Write.
    We have a certain number of pre-allocated RAM pages. The argument ROM virtual address
    is within a ROM page. That ROM page will be copied to one of the free, pre-allocated
    RAM pages. The section table will be remapped so that the VA that used to point to the
    ROM page (that contained the argument address) now points to the RAM page. SW BP
    (trap instructions) can then be safely set at that address, and excution of
    code can carry on. If a RAM page consists of an address range that the argument
    is within, then nothing needs to be done. Various error cases are handled and
    returned to the caller, to be returned to PB. If this function fails, other functions
    need not worry since no permanent changes would have been made. Also, a count variable
    is maintained for each RAM page, and is incremented when a breakpoint is set in it,
    and decremented when one is removed from within it. When the count variable is zero,
    the ROM virtual address is remapped to its original ROM page address, and
    the RAM page is marked as free (done by KdpRestoreRomVmPageMapping).

Arguments:

    [in] pvRomAddr - supplies the ROM virtual address where a breakpoint needs to be set
    [in] pvRomKAddr - supplies the ROM statically mapped kernel address equivalent where a breakpoint needs to be set
    [out] pidxRomRamTbl - return index of Rom2Ram table entry just used for remapping if succeeded

Return Value:

    Will return greater than 0 for success, or 0 or negative values for various error conditions

--*/

int KdpRomSwBpAttemptRamPageRemap (void * pvRomAddr, void * pvRomKAddr, int *pidxRomRamTbl, void **ppvRamAddr)
{
    int nIndex = 0, nIndToBeUsed = 0, idxRomRamTbl = 0;
    DWORD dwTempROMAddr = 0;
    DWORD dwTempRAMAddr = 0;
    DWORD dwRomAddr = (DWORD) pvRomAddr;
    DWORD dwRamAddr = 0;
    BOOL fAddrInRange = FALSE, fFreePageFound = FALSE;
    int bphRet = KD_BPHND_INVALID_GEN_ERR;
    int nBytesCopied = 0;

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

    // Try and find a RAM remap page that contains the range of addresses
    // that the given address falls into OR find a free RAM remap page for it
    for (nIndex = 0; (nIndex < NB_ROM2RAM_PAGES) && !fAddrInRange; nIndex++)
    {
        dwTempROMAddr = (DWORD) (g_aRom2RamPageTable[nIndex].pvROMAddr);
        if (dwTempROMAddr)
        { // Used entry
            if ((dwRomAddr >= dwTempROMAddr) &&
                (dwRomAddr < dwTempROMAddr + PAGE_SIZE))
            { // Argument within range of one existing remaped page
                fAddrInRange = TRUE;
                nIndToBeUsed = nIndex;
            }
        }
        else
        { // A free page available
            if (!fFreePageFound)
            {
                fFreePageFound = TRUE;
                nIndToBeUsed = nIndex;
            }
        }
    }

    if (fAddrInRange)
    {
        DEBUGGERMSG (KDZONE_SWBP, (TEXT ("  KdpRomSwBpAttemptRamPageRemap: Address found in existing RAM page (%i)\r\n"), nIndToBeUsed));
        idxRomRamTbl = nIndToBeUsed;
        dwRamAddr = (DWORD) (g_aRom2RamPageTable[nIndToBeUsed].pbRAMAddr); 
        dwRamAddr += (dwRomAddr & (PAGE_SIZE - 1));   
        bphRet = KD_BPHND_ROMBP_SUCCESS;
    }
    else
    {
        if (!fFreePageFound)
        {
            DEBUGGERMSG (KDZONE_SWBP, (TEXT ("  KdpRomSwBpAttemptRamPageRemap: Address not in range and no free pages!\r\n")));
            bphRet = KD_BPHND_ROMBP_ERROR_INSUFFICIENT_PAGES;
        }
        else
        { // found a free page for the ROM address (and one page worth of code)
            char* pbROMSource = (char *) (dwRomAddr & ~(PAGE_SIZE - 1)); // Get page start boundary
            dwTempRAMAddr = (DWORD) (g_aRom2RamPageTable[nIndToBeUsed].pbRAMAddr);
            if  (dwTempRAMAddr & (PAGE_SIZE - 1))
            {
                DEBUGGERMSG (KDZONE_ALERT, (TEXT("  KdpRomSwBpAttemptRamPageRemap: ERROR: RAMPageAddr=0x%08X is not align on a page.\r\n"), dwTempRAMAddr));
            }
            else
            {
                DEBUGGERMSG (KDZONE_SWBP, (TEXT("  KdpRomSwBpAttemptRamPageRemap: Use new page (%i), RAMPageAddr=0x%08X, ROMPageAddr=0x%08X\r\n"), nIndToBeUsed, dwTempRAMAddr, (DWORD) pbROMSource));
                // Attempt the copy of the ROM page containing the argument to the free RAM page found
                nBytesCopied = KdpMoveMemory ((char *) dwTempRAMAddr, (char *) pbROMSource, PAGE_SIZE);
                if (nBytesCopied != PAGE_SIZE)
                {
                    DEBUGGERMSG (KDZONE_ALERT, (TEXT("  KdpRomSwBpAttemptRamPageRemap: KdpMoveMemory failed, copied %d bytes\r\n"), nBytesCopied));
                    bphRet = KD_BPHND_ERROR_COPY_FAILED;
                }
                else
                {
                    // Remap the addresses so that the ROM page boundary virtual address will now point to
                    // the RAM address (also the start of a page boundary)
                    if (!KdpRemapVirtualMemory ((void *) pbROMSource, (void *) dwTempRAMAddr, NULL))
                    {
                        DEBUGGERMSG (KDZONE_SWBP, (TEXT ("  KdpRomSwBpAttemptRamPageRemap: KdpRemapVirtualMemory failed\r\n")));
                        bphRet = KD_BPHND_ROMBP_ERROR_REMAP_FAILED;
                    }
                    else
                    {
                        idxRomRamTbl = nIndToBeUsed;

                        // Save all pertinent info and return success, if we got to this point
                        g_aRom2RamPageTable[nIndToBeUsed].pvROMAddr = (void *) pbROMSource;
                        g_aRom2RamPageTable[nIndToBeUsed].pvROMAddrKern = (void *)(((DWORD)pvRomKAddr) & ~(PAGE_SIZE - 1)); // Save page start boundary
                        dwRamAddr = (DWORD) (g_aRom2RamPageTable[nIndToBeUsed].pbRAMAddr);
                        dwRamAddr += (dwRomAddr & (PAGE_SIZE - 1));   
                        bphRet = KD_BPHND_ROMBP_SUCCESS;

                        DEBUGGERMSG(KDZONE_SWBP, (TEXT("  KdpRomSwBpAttemptRamPageRemap: ROM to RAM mapping Table updated\r\n")));
                    }
                }
            }
        }
    }
    if (pidxRomRamTbl) *pidxRomRamTbl = idxRomRamTbl;
    if (ppvRamAddr) *ppvRamAddr = (void *)dwRamAddr;
    DEBUGGERMSG (KDZONE_SWBP, (TEXT("--KdpRomSwBpAttemptRamPageRemap bphRet=%i, idxRomRamTbl=%i, dwRamAddr=0x%08X\r\n"), bphRet, idxRomRamTbl, dwRamAddr));
    return bphRet;
}


/*++

Routine Name:

    KdpRestoreRomVmPageMapping

Routine Description:

    This routine will attempt to restore the old page mapping that
    existed between a copied ROM/RAM page and the original ROM
    page, before it was remapped by KdpRomSwBpAttemptRamPageRemap.

Arguments:

    [in] ulROMTbaleIndex - supplies the index into the ROMRAM page table

Return Value:


--*/

BOOL KdpRestoreRomVmPageMapping (ULONG ulROMBPTableIndex)
{
    int nIndex = ulROMBPTableIndex;
    BOOL fRet = FALSE;
    DWORD dwFlags = 0;

    DEBUGGERMSG (KDZONE_SWBP, (TEXT ("++KdpRestoreRomVmPageMapping %d\r\n"), ulROMBPTableIndex));

    // Bounds check
    if (nIndex < NB_ROM2RAM_PAGES)
    {
        // Is the RAM page still in use?
        if (g_aRom2RamPageTable[nIndex].nBPCount > 0)
        {
            DEBUGGERMSG(KDZONE_SWBP, (TEXT("  KdpRestoreRomVmPageMapping: Cannot free page %d, still in use\r\n"), nIndex));
            fRet = TRUE;
        }
        else
        { // Page unused now, attempt the unmap
            DEBUGGERMSG (KDZONE_SWBP, (TEXT ("  KdpRestoreRomVmPageMapping: Remapping page %d from (0x%08X) back to (0x%8.8x)\r\n"), nIndex, (DWORD) (g_aRom2RamPageTable[nIndex].pbRAMAddr), (DWORD) (g_aRom2RamPageTable[nIndex].pvROMAddr)));

            // Perform the remapping
            dwFlags = PAGE_EXECUTE_READ;
            if (!KdpRemapVirtualMemory (g_aRom2RamPageTable[nIndex].pvROMAddr, g_aRom2RamPageTable[nIndex].pvROMAddrKern, &dwFlags))
            {
                DEBUGGERMSG (KDZONE_SWBP, (TEXT("  KdpRestoreRomVmPageMapping: Remap failed!\r\n")));
                fRet = FALSE;
            }
            else
            {
                g_aRom2RamPageTable[nIndex].pvROMAddr = 0; // Mark the page as free
                fRet = TRUE;
                DEBUGGERMSG (KDZONE_SWBP, (TEXT("  KdpRestoreRomVmPageMapping: Page remapped and freed\r\n")));
            }
        }
    }
    else
    {
        DEBUGGERMSG(KDZONE_SWBP, (TEXT("  KdpRestoreRomVmPageMapping: Error, bad index (%d)\r\n"), nIndex));
    }
    DEBUGGERMSG (KDZONE_SWBP, (TEXT("--KdpRestoreRomVmPageMapping\r\n")));
    return fRet;
}

/*++

Routine Name:

    KdpIncCountIfRomSwBp

Routine Description:

    This routine is usually called when a breakpoint has sucessfully
    been written to 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 increment the breakpoint use count variable
    for that page. 

Arguments:

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

Return Value:

    TRUE if BP was in ROM.

--*/

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

    DEBUGGERMSG (KDZONE_SWBP, (TEXT ("++KdpIncCountIfRomSwBp (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 added
        // falls in any of our preallocated/remapped ROM/RAM pages
        if ((dwAddr >= dwROMAddrTemp) && (dwAddr < dwROMAddrTemp + PAGE_SIZE))
        {
            DEBUGGERMSG (KDZONE_SWBP, (TEXT ("  KdpIncCountIfRomSwBp: Address found in page %d between (0x%08X) and (0x%08X)\r\n"), nIndex, dwROMAddrTemp, dwROMAddrTemp+PAGE_SIZE));
            fRet = TRUE;

            // Increment the breakpoint use count for that page
            g_aRom2RamPageTable[nIndex].nBPCount++;

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

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

/*++

⌨️ 快捷键说明

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