DBGPlugInWinNt.cpp revision df66753ca310c5d36c3ae2cf36f78bbe333ece4f
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * DBGPlugInWindows - Debugger and Guest OS Digger Plugin For Windows NT.
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2009-2013 Oracle Corporation
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * available from http://www.virtualbox.org. This file is free software;
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * General Public License (GPL) as published by the Free Software
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Header Files *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define LOG_GROUP LOG_GROUP_DBGF ///@todo add new log group.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include "../Runtime/include/internal/ldrMZ.h" /* ugly */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include "../Runtime/include/internal/ldrPE.h" /* ugly */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Structures and Typedefs *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @name Internal WinNT structures
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * PsLoadedModuleList entry for 32-bit NT aka LDR_DATA_TABLE_ENTRY.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Tested with XP.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsynctypedef struct NTMTE32
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* ... there is more ... */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * PsLoadedModuleList entry for 32-bit NT aka LDR_DATA_TABLE_ENTRY.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Tested with XP.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @todo This is incomplete and just to get rid of warnings.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsynctypedef struct NTMTE64
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* ... there is more ... */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** MTE union. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsynctypedef union NTMTE
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The essential bits of the KUSER_SHARED_DATA structure.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* uint8_t ProcessorFeatures[64];
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** KI_USER_SHARED_DATA for i386 */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define NTKUSERSHAREDDATA_WINNT32 UINT32_C(0xffdf0000)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** KI_USER_SHARED_DATA for AMD64 */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define NTKUSERSHAREDDATA_WINNT64 UINT64_C(0xfffff78000000000)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** NTKUSERSHAREDDATA::NtProductType */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * PDB v2.0 in image debug info.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The URL is constructed from the timestamp and the %02x age?
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int32_t Offset; /**< Always 0. Used to be the offset to the real debug info. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** The CV_INFO_PDB20 signature. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define CV_SIGNATURE_PDB20 RT_MAKE_U32_FROM_U8('N','B','1','0')
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * PDB v7.0 in image debug info.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The URL is constructed from the signature and the %02x age.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncAssertCompileMemberOffset(CV_INFO_PDB70, Signature, 4);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncAssertCompileMemberOffset(CV_INFO_PDB70, Age, 4 + 16);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** The CV_INFO_PDB70 signature. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define CV_SIGNATURE_PDB70 RT_MAKE_U32_FROM_U8('R','S','D','S')
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * WinNT guest OS digger instance data.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** Whether the information is valid or not.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * (For fending off illegal interface method calls.) */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** 32-bit (true) or 64-bit (false) */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** The NT version. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** NTKUSERSHAREDDATA::NtProductType */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** NTKUSERSHAREDDATA::NtMajorVersion */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** NTKUSERSHAREDDATA::NtMinorVersion */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** The address of the ntoskrnl.exe image. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** The address of the ntoskrnl.exe module table entry. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** The address of PsLoadedModuleList. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Pointer to the linux guest OS digger instance data. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Defined Constants And Macros *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Validates a 32-bit Windows NT kernel address */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define WINNT32_VALID_ADDRESS(Addr) ((Addr) > UINT32_C(0x80000000) && (Addr) < UINT32_C(0xfffff000))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Validates a 64-bit Windows NT kernel address */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define WINNT64_VALID_ADDRESS(Addr) ((Addr) > UINT64_C(0xffffffff80000000) && (Addr) < UINT64_C(0xfffffffffffff000))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Validates a kernel address. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define WINNT_VALID_ADDRESS(pThis, Addr) ((pThis)->f32Bit ? WINNT32_VALID_ADDRESS(Addr) : WINNT64_VALID_ADDRESS(Addr))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Versioned and bitness wrapper. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define WINNT_UNION(pThis, pUnion, Member) ((pThis)->f32Bit ? (pUnion)->vX_32. Member : (pUnion)->vX_64. Member )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** The length (in chars) of the kernel file name (no path). */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** WindowsNT on little endian ASCII systems. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#define DIG_WINNT_MOD_TAG UINT64_C(0x54696e646f774e54)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Internal Functions *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(int) dbgDiggerWinNtInit(PUVM pUVM, void *pvData);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Global Variables *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Kernel names. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic const RTUTF16 g_wszKernelNames[][WINNT_KERNEL_BASE_NAME_LEN + 1] =
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync { 'n', 't', 'o', 's', 'k', 'r', 'n', 'l', '.', 'e', 'x', 'e' }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Process a PE image found in guest memory.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param pThis The instance data.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param pUVM The user mode VM handle.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param pszName The image name.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param pImageAddr The image address.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param cbImage The size of the image.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param pbBuf Scratch buffer containing the first
98427c0ab08697e468c26dc33ee9571308577867vboxsync * RT_MIN(cbBuf, cbImage) bytes of the image.
98427c0ab08697e468c26dc33ee9571308577867vboxsync * @param cbBuf The scratch buffer size.
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic void dbgDiggerWinNtProcessImage(PDBGDIGGERWINNT pThis, PUVM pUVM, const char *pszName,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync LogFlow(("DigWinNt: %RGp %#x %s\n", pImageAddr->FlatPtr, cbImage, pszName));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Do some basic validation first.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * This is the usual exteremely verbose and messy code...
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: Bad image size: %#x\n", pszName, cbImage));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Dig out the NT/PE headers. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync IMAGE_DOS_HEADER const *pMzHdr = (IMAGE_DOS_HEADER const *)pbBuf;
b529ce62f7f41042866f179ea4c103e913f499e0vboxsync typedef union NTHDRSU
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) > cbImage)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: PE header to far into image: %#x cbImage=%#x\n", pMzHdr->e_lfanew, cbImage));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) <= cbBuf)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: PE header to far into image (lazy bird): %#x\n", pMzHdr->e_lfanew));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: Bad PE signature: %#x\n", pszName, pHdrs->vX_32.Signature));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* The file header is the same on both archs */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pHdrs->vX_32.FileHeader.Machine != (pThis->f32Bit ? IMAGE_FILE_MACHINE_I386 : IMAGE_FILE_MACHINE_AMD64))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: Invalid FH.Machine: %#x\n", pszName, pHdrs->vX_32.FileHeader.Machine));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (pHdrs->vX_32.FileHeader.SizeOfOptionalHeader != (pThis->f32Bit ? sizeof(IMAGE_OPTIONAL_HEADER32) : sizeof(IMAGE_OPTIONAL_HEADER64)))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: Invalid FH.SizeOfOptionalHeader: %#x\n", pszName, pHdrs->vX_32.FileHeader.SizeOfOptionalHeader));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const uint32_t TimeDateStamp = pHdrs->vX_32.FileHeader.TimeDateStamp;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* The optional header is not... */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (WINNT_UNION(pThis, pHdrs, OptionalHeader.Magic) != (pThis->f32Bit ? IMAGE_NT_OPTIONAL_HDR32_MAGIC : IMAGE_NT_OPTIONAL_HDR64_MAGIC))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: Invalid OH.Magic: %#x\n", pszName, WINNT_UNION(pThis, pHdrs, OptionalHeader.Magic)));
df66753ca310c5d36c3ae2cf36f78bbe333ece4fvboxsync if (RT_ALIGN(WINNT_UNION(pThis, pHdrs, OptionalHeader.SizeOfImage), _4K) != RT_ALIGN(cbImage, _4K))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: %s: Invalid OH.SizeOfImage: %#x, expected %#x\n", pszName, WINNT_UNION(pThis, pHdrs, OptionalHeader.SizeOfImage), cbImage));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (WINNT_UNION(pThis, pHdrs, OptionalHeader.NumberOfRvaAndSizes) != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
df66753ca310c5d36c3ae2cf36f78bbe333ece4fvboxsync Log(("DigWinNt: %s: Invalid OH.NumberOfRvaAndSizes: %#x\n", pszName, WINNT_UNION(pThis, pHdrs, OptionalHeader.NumberOfRvaAndSizes)));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync IMAGE_DATA_DIRECTORY const *pDir = &WINNT_UNION(pThis, pHdrs, OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* dig into the section table... */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Create the module.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = RTDbgModCreate(&hMod, pszName, cbImage, 0 /*fFlags*/);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTDbgModSetTag(hMod, DIG_WINNT_MOD_TAG); AssertRC(rc);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* temp hack: */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTDbgModSymbolAdd(hMod, "start", 0 /*iSeg*/, 0, cbImage, 0 /*fFlags*/, NULL); AssertRC(rc);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* add sections? */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Dig out debug info if possible. What we're after is the CODEVIEW part.
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, pbBuf, RT_MIN(cbDebugDir, cbBuf));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync IMAGE_DEBUG_DIRECTORY const *pa = (IMAGE_DEBUG_DIRECTORY const *)pbBuf;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t c = RT_MIN(RT_MIN(cbDebugDir, cbBuf) / sizeof(*pa), 10);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (uint32_t i = 0; i < c; i++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pa[i].AddressOfRawData + pa[i].SizeOfData <= cbImage
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pa[i].TimeDateStamp == TimeDateStamp /* too paranoid? */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Link the module.
98427c0ab08697e468c26dc33ee9571308577867vboxsync RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = RTDbgAsModuleLink(hAs, hMod, pImageAddr->FlatPtr, RTDBGASLINK_FLAGS_REPLACE /*fFlags*/);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnQueryInterface
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(void *) dbgDiggerWinNtQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnQueryVersion
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(int) dbgDiggerWinNtQueryVersion(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case kNtProductType_WinNt: pszNtProductType = "-WinNT"; break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case kNtProductType_LanManNt: pszNtProductType = "-LanManNT"; break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync case kNtProductType_Server: pszNtProductType = "-Server"; break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTStrPrintf(pszVersion, cchVersion, "%u.%u%s", pThis->NtMajorVersion, pThis->NtMinorVersion, pszNtProductType);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnTerm
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(void) dbgDiggerWinNtTerm(PUVM pUVM, void *pvData)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnRefresh
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(int) dbgDiggerWinNtRefresh(PUVM pUVM, void *pvData)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * For now we'll flush and reload everything.
98427c0ab08697e468c26dc33ee9571308577867vboxsync RTDBGAS hDbgAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync while (iMod-- > 0)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync RTDBGMOD hMod = RTDbgAsModuleByIndex(hDbgAs, iMod);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnInit
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(int) dbgDiggerWinNtInit(PUVM pUVM, void *pvData)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Figure the NT version.
98427c0ab08697e468c26dc33ee9571308577867vboxsync DBGFR3AddrFromFlat(pUVM, &Addr, pThis->f32Bit ? NTKUSERSHAREDDATA_WINNT32 : NTKUSERSHAREDDATA_WINNT64);
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &u, PAGE_SIZE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->NtProductType = u.UserSharedData.ProductTypeIsValid && u.UserSharedData.NtProductType <= kNtProductType_Server
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->NtMajorVersion = u.UserSharedData.NtMajorVersion;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pThis->NtMinorVersion = u.UserSharedData.NtMinorVersion;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Dig out the module chain.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DBGFADDRESS AddrPrev = pThis->PsLoadedModuleListAddr;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Read the validate the MTE. */
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &Mte, pThis->f32Bit ? sizeof(Mte.vX_32) : sizeof(Mte.vX_64));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (WINNT_UNION(pThis, &Mte, InLoadOrderLinks.Blink) != AddrPrev.FlatPtr)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: Bad Mte At %RGv - backpointer\n", Addr.FlatPtr));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, InLoadOrderLinks.Flink)) )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: Bad Mte at %RGv - forward pointer\n", Addr.FlatPtr));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, BaseDllName.Buffer)))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: Bad Mte at %RGv - BaseDllName=%llx\n", Addr.FlatPtr, WINNT_UNION(pThis, &Mte, BaseDllName.Buffer)));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, FullDllName.Buffer)))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: Bad Mte at %RGv - FullDllName=%llx\n", Addr.FlatPtr, WINNT_UNION(pThis, &Mte, FullDllName.Buffer)));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if ( !WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, DllBase))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || WINNT_UNION(pThis, &Mte, EntryPoint) - WINNT_UNION(pThis, &Mte, DllBase) > WINNT_UNION(pThis, &Mte, SizeOfImage) )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: Bad Mte at %RGv - EntryPoint=%llx SizeOfImage=%x DllBase=%llx\n",
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Addr.FlatPtr, WINNT_UNION(pThis, &Mte, EntryPoint), WINNT_UNION(pThis, &Mte, SizeOfImage), WINNT_UNION(pThis, &Mte, DllBase)));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Read the full name. */
98427c0ab08697e468c26dc33ee9571308577867vboxsync DBGFR3AddrFromFlat(pUVM, &AddrName, WINNT_UNION(pThis, &Mte, FullDllName.Buffer));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint16_t cbName = WINNT_UNION(pThis, &Mte, FullDllName.Length);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (cbName < sizeof(u))
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrName, &u, cbName);
98427c0ab08697e468c26dc33ee9571308577867vboxsync DBGFR3AddrFromFlat(pUVM, &AddrName, WINNT_UNION(pThis, &Mte, BaseDllName.Buffer));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cbName = WINNT_UNION(pThis, &Mte, BaseDllName.Length);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (cbName < sizeof(u))
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrName, &u, cbName);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Read the start of the PE image and pass it along to a worker. */
98427c0ab08697e468c26dc33ee9571308577867vboxsync DBGFR3AddrFromFlat(pUVM, &ImageAddr, WINNT_UNION(pThis, &Mte, DllBase));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint32_t cbImageBuf = RT_MIN(sizeof(u), WINNT_UNION(pThis, &Mte, SizeOfImage));
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &ImageAddr, &u, cbImageBuf);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync sizeof(u));
98427c0ab08697e468c26dc33ee9571308577867vboxsync DBGFR3AddrFromFlat(pUVM, &Addr, WINNT_UNION(pThis, &Mte, InLoadOrderLinks.Flink));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync } while ( Addr.FlatPtr != pThis->KernelMteAddr.FlatPtr
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && Addr.FlatPtr != pThis->PsLoadedModuleListAddr.FlatPtr);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnProbe
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(bool) dbgDiggerWinNtProbe(PUVM pUVM, void *pvData)
df66753ca310c5d36c3ae2cf36f78bbe333ece4fvboxsync * Look for the PAGELK section name that seems to be a part of all kernels.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Then try find the module table entry for it. Since it's the first entry
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * in the PsLoadedModuleList we can easily validate the list head and report
98427c0ab08697e468c26dc33ee9571308577867vboxsync CPUMMODE enmMode = DBGFR3CpuGetMode(pUVM, 0 /*idCpu*/);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** @todo when 32-bit is working, add support for 64-bit windows nt. */
98427c0ab08697e468c26dc33ee9571308577867vboxsync for (DBGFR3AddrFromFlat(pUVM, &KernelAddr, UINT32_C(0x80001000));
98427c0ab08697e468c26dc33ee9571308577867vboxsync int rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, UINT32_C(0xffff0000) - KernelAddr.FlatPtr,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync DBGFR3AddrSub(&KernelAddr, KernelAddr.FlatPtr & PAGE_OFFSET_MASK);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* MZ + PE header. */
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &KernelAddr, &u, sizeof(u));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync IMAGE_NT_HEADERS32 const *pHdrs = (IMAGE_NT_HEADERS32 const *)&u.au8[u.MzHdr.e_lfanew];
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pHdrs->FileHeader.Machine == IMAGE_FILE_MACHINE_I386
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pHdrs->FileHeader.SizeOfOptionalHeader == sizeof(pHdrs->OptionalHeader)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pHdrs->FileHeader.NumberOfSections >= 10 /* the kernel has lots */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && (pHdrs->FileHeader.Characteristics & (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL)) == IMAGE_FILE_EXECUTABLE_IMAGE
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pHdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && pHdrs->OptionalHeader.NumberOfRvaAndSizes == IMAGE_NUMBEROF_DIRECTORY_ENTRIES
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /** @todo need more ntoskrnl signs? */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Find the MTE. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Mte.EntryPoint = KernelAddr.FlatPtr + pHdrs->OptionalHeader.AddressOfEntryPoint;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Mte.SizeOfImage = pHdrs->OptionalHeader.SizeOfImage;
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, UINT32_MAX - KernelAddr.FlatPtr,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync 4 /*align*/, &Mte.DllBase, 3 * sizeof(uint32_t), &HitAddr);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* check the name. */
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrSub(&MteAddr, RT_OFFSETOF(NTMTE32, DllBase)),
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && WINNT32_VALID_ADDRESS(Mte2.InLoadOrderLinks.Flink)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && Mte2.InLoadOrderLinks.Blink > KernelAddr.FlatPtr /* list head inside ntoskrnl */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && Mte2.InLoadOrderLinks.Blink < KernelAddr.FlatPtr + Mte.SizeOfImage
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && Mte2.BaseDllName.Length <= Mte2.BaseDllName.MaximumLength
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && Mte2.BaseDllName.Length == WINNT_KERNEL_BASE_NAME_LEN * 2
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && Mte2.FullDllName.Length <= Mte2.FullDllName.MaximumLength
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, Mte2.BaseDllName.Buffer),
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* || !RTUtf16ICmp(u.wsz, g_wszKernelNames[1]) */
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, Mte2.InLoadOrderLinks.Blink),
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync && WINNT32_VALID_ADDRESS(Mte3.InLoadOrderLinks.Blink) )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Log(("DigWinNt: MteAddr=%RGv KernelAddr=%RGv SizeOfImage=%x &PsLoadedModuleList=%RGv (32-bit)\n",
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync MteAddr.FlatPtr, KernelAddr.FlatPtr, Mte2.SizeOfImage, Addr.FlatPtr));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return true;
98427c0ab08697e468c26dc33ee9571308577867vboxsync rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &HitAddr, UINT32_MAX - HitAddr.FlatPtr,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync 4 /*align*/, &Mte.DllBase, 3 * sizeof(uint32_t), &HitAddr);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnDestruct
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(void) dbgDiggerWinNtDestruct(PUVM pUVM, void *pvData)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @copydoc DBGFOSREG::pfnConstruct
98427c0ab08697e468c26dc33ee9571308577867vboxsyncstatic DECLCALLBACK(int) dbgDiggerWinNtConstruct(PUVM pUVM, void *pvData)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* .fFlags = */ 0,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* .pfnQueryVersion = */ dbgDiggerWinNtQueryVersion,
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* .pfnQueryInterface = */ dbgDiggerWinNtQueryInterface,