Changeset 73150 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jul 16, 2018 10:03:41 AM (6 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/Makefile.kmk
r73088 r73150 99 99 VMMR3/DBGFLog.cpp \ 100 100 VMMR3/DBGFMem.cpp \ 101 VMMR3/DBGFR3ModInMem.cpp \ 101 102 VMMR3/DBGFOS.cpp \ 102 103 VMMR3/DBGFR3PlugIn.cpp \ -
trunk/src/VBox/VMM/VMMR3/DBGFR3ModInMem.cpp
r73119 r73150 1 1 /* $Id$ */ 2 2 /** @file 3 * DBG PlugInWindows - Debugger and Guest OS Digger Plugin For Windows NT.3 * DBGFR3ModInMemPe - In memory PE module 'loader'. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2009-201 7Oracle Corporation7 * Copyright (C) 2009-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 20 20 * Header Files * 21 21 *********************************************************************************************************************************/ 22 #define LOG_GROUP LOG_GROUP_DBGF /// @todo add new log group. 23 #include "DBGPlugIns.h" 22 #define LOG_GROUP LOG_GROUP_DBGF 24 23 #include <VBox/vmm/dbgf.h> 24 25 25 #include <VBox/err.h> 26 #include <VBox/param.h>27 26 #include <iprt/ldr.h> 28 27 #include <iprt/mem.h> 29 #include <iprt/stream.h>30 28 #include <iprt/string.h> 31 29 #include <iprt/formats/pecoff.h> 32 30 #include <iprt/formats/mz.h> 31 #include <iprt/formats/elf.h> 33 32 34 33 … … 36 35 * Structures and Typedefs * 37 36 *********************************************************************************************************************************/ 38 39 /** @name Internal WinNT structures40 * @{ */41 /**42 * PsLoadedModuleList entry for 32-bit NT aka LDR_DATA_TABLE_ENTRY.43 * Tested with XP.44 */45 typedef struct NTMTE3246 {47 struct48 {49 uint32_t Flink;50 uint32_t Blink;51 } InLoadOrderLinks,52 InMemoryOrderModuleList,53 InInitializationOrderModuleList;54 uint32_t DllBase;55 uint32_t EntryPoint;56 /** @note This field is not a size in NT 3.1. It's NULL for images loaded by the57 * boot loader, for other images it looks like some kind of pointer. */58 uint32_t SizeOfImage;59 struct60 {61 uint16_t Length;62 uint16_t MaximumLength;63 uint32_t Buffer;64 } FullDllName,65 BaseDllName;66 uint32_t Flags;67 uint16_t LoadCount;68 uint16_t TlsIndex;69 /* ... there is more ... */70 } NTMTE32;71 typedef NTMTE32 *PNTMTE32;72 73 /**74 * PsLoadedModuleList entry for 64-bit NT aka LDR_DATA_TABLE_ENTRY.75 */76 typedef struct NTMTE6477 {78 struct79 {80 uint64_t Flink;81 uint64_t Blink;82 } InLoadOrderLinks, /**< 0x00 */83 InMemoryOrderModuleList, /**< 0x10 */84 InInitializationOrderModuleList; /**< 0x20 */85 uint64_t DllBase; /**< 0x30 */86 uint64_t EntryPoint; /**< 0x38 */87 uint32_t SizeOfImage; /**< 0x40 */88 uint32_t Alignment; /**< 0x44 */89 struct90 {91 uint16_t Length; /**< 0x48,0x58 */92 uint16_t MaximumLength; /**< 0x4a,0x5a */93 uint32_t Alignment; /**< 0x4c,0x5c */94 uint64_t Buffer; /**< 0x50,0x60 */95 } FullDllName, /**< 0x48 */96 BaseDllName; /**< 0x58 */97 uint32_t Flags; /**< 0x68 */98 uint16_t LoadCount; /**< 0x6c */99 uint16_t TlsIndex; /**< 0x6e */100 /* ... there is more ... */101 } NTMTE64;102 typedef NTMTE64 *PNTMTE64;103 104 /** MTE union. */105 typedef union NTMTE106 {107 NTMTE32 vX_32;108 NTMTE64 vX_64;109 } NTMTE;110 typedef NTMTE *PNTMTE;111 112 113 /**114 * The essential bits of the KUSER_SHARED_DATA structure.115 */116 typedef struct NTKUSERSHAREDDATA117 {118 uint32_t TickCountLowDeprecated;119 uint32_t TickCountMultiplier;120 struct121 {122 uint32_t LowPart;123 int32_t High1Time;124 int32_t High2Time;125 126 } InterruptTime,127 SystemTime,128 TimeZoneBias;129 uint16_t ImageNumberLow;130 uint16_t ImageNumberHigh;131 RTUTF16 NtSystemRoot[260];132 uint32_t MaxStackTraceDepth;133 uint32_t CryptoExponent;134 uint32_t TimeZoneId;135 uint32_t LargePageMinimum;136 uint32_t Reserved2[7];137 uint32_t NtProductType;138 uint8_t ProductTypeIsValid;139 uint8_t abPadding[3];140 uint32_t NtMajorVersion;141 uint32_t NtMinorVersion;142 /* uint8_t ProcessorFeatures[64];143 ...144 */145 } NTKUSERSHAREDDATA;146 typedef NTKUSERSHAREDDATA *PNTKUSERSHAREDDATA;147 148 /** KI_USER_SHARED_DATA for i386 */149 #define NTKUSERSHAREDDATA_WINNT32 UINT32_C(0xffdf0000)150 /** KI_USER_SHARED_DATA for AMD64 */151 #define NTKUSERSHAREDDATA_WINNT64 UINT64_C(0xfffff78000000000)152 153 /** NTKUSERSHAREDDATA::NtProductType */154 typedef enum NTPRODUCTTYPE155 {156 kNtProductType_Invalid = 0,157 kNtProductType_WinNt = 1,158 kNtProductType_LanManNt,159 kNtProductType_Server160 } NTPRODUCTTYPE;161 162 163 /** NT image header union. */164 typedef union NTHDRSU165 {166 IMAGE_NT_HEADERS32 vX_32;167 IMAGE_NT_HEADERS64 vX_64;168 } NTHDRS;169 /** Pointer to NT image header union. */170 typedef NTHDRS *PNTHDRS;171 /** Pointer to const NT image header union. */172 typedef NTHDRS const *PCNTHDRS;173 174 /** @} */175 176 177 178 typedef enum DBGDIGGERWINNTVER179 {180 DBGDIGGERWINNTVER_UNKNOWN,181 DBGDIGGERWINNTVER_3_1,182 DBGDIGGERWINNTVER_3_5,183 DBGDIGGERWINNTVER_4_0,184 DBGDIGGERWINNTVER_5_0,185 DBGDIGGERWINNTVER_5_1,186 DBGDIGGERWINNTVER_6_0187 } DBGDIGGERWINNTVER;188 189 /**190 * WinNT guest OS digger instance data.191 */192 typedef struct DBGDIGGERWINNT193 {194 /** Whether the information is valid or not.195 * (For fending off illegal interface method calls.) */196 bool fValid;197 /** 32-bit (true) or 64-bit (false) */198 bool f32Bit;199 /** Set if NT 3.1 was detected.200 * This implies both Misc.VirtualSize and NTMTE32::SizeOfImage are zero. */201 bool fNt31;202 203 /** The NT version. */204 DBGDIGGERWINNTVER enmVer;205 /** NTKUSERSHAREDDATA::NtProductType */206 NTPRODUCTTYPE NtProductType;207 /** NTKUSERSHAREDDATA::NtMajorVersion */208 uint32_t NtMajorVersion;209 /** NTKUSERSHAREDDATA::NtMinorVersion */210 uint32_t NtMinorVersion;211 212 /** The address of the ntoskrnl.exe image. */213 DBGFADDRESS KernelAddr;214 /** The address of the ntoskrnl.exe module table entry. */215 DBGFADDRESS KernelMteAddr;216 /** The address of PsLoadedModuleList. */217 DBGFADDRESS PsLoadedModuleListAddr;218 } DBGDIGGERWINNT;219 /** Pointer to the linux guest OS digger instance data. */220 typedef DBGDIGGERWINNT *PDBGDIGGERWINNT;221 222 223 37 /** 224 38 * The WinNT digger's loader reader instance data. 225 39 */ 226 typedef struct DBG DIGGERWINNTRDR40 typedef struct DBGFMODPERDR 227 41 { 228 42 /** The VM handle (referenced). */ … … 251 65 uint32_t offMem; 252 66 } aMappings[1]; 253 } DBG DIGGERWINNTRDR;67 } DBGFMODPERDR; 254 68 /** Pointer a WinNT loader reader instance data. */ 255 typedef DBGDIGGERWINNTRDR *PDBGDIGGERWINNTRDR; 256 257 258 /********************************************************************************************************************************* 259 * Defined Constants And Macros * 260 *********************************************************************************************************************************/ 261 /** Validates a 32-bit Windows NT kernel address */ 262 #define WINNT32_VALID_ADDRESS(Addr) ((Addr) > UINT32_C(0x80000000) && (Addr) < UINT32_C(0xfffff000)) 263 /** Validates a 64-bit Windows NT kernel address */ 264 #define WINNT64_VALID_ADDRESS(Addr) ((Addr) > UINT64_C(0xffff800000000000) && (Addr) < UINT64_C(0xfffffffffffff000)) 265 /** Validates a kernel address. */ 266 #define WINNT_VALID_ADDRESS(pThis, Addr) ((pThis)->f32Bit ? WINNT32_VALID_ADDRESS(Addr) : WINNT64_VALID_ADDRESS(Addr)) 267 /** Versioned and bitness wrapper. */ 268 #define WINNT_UNION(pThis, pUnion, Member) ((pThis)->f32Bit ? (pUnion)->vX_32. Member : (pUnion)->vX_64. Member ) 269 270 /** The length (in chars) of the kernel file name (no path). */ 271 #define WINNT_KERNEL_BASE_NAME_LEN 12 272 273 /** WindowsNT on little endian ASCII systems. */ 274 #define DIG_WINNT_MOD_TAG UINT64_C(0x54696e646f774e54) 275 276 277 /********************************************************************************************************************************* 278 * Internal Functions * 279 *********************************************************************************************************************************/ 280 static DECLCALLBACK(int) dbgDiggerWinNtInit(PUVM pUVM, void *pvData); 281 282 283 /********************************************************************************************************************************* 284 * Global Variables * 285 *********************************************************************************************************************************/ 286 /** Kernel names. */ 287 static const RTUTF16 g_wszKernelNames[][WINNT_KERNEL_BASE_NAME_LEN + 1] = 288 { 289 { 'n', 't', 'o', 's', 'k', 'r', 'n', 'l', '.', 'e', 'x', 'e' } 290 }; 291 292 293 294 /** @callback_method_impl{PFNRTLDRRDRMEMREAD} */ 295 static DECLCALLBACK(int) dbgDiggerWinNtRdr_Read(void *pvBuf, size_t cb, size_t off, void *pvUser) 296 { 297 PDBGDIGGERWINNTRDR pThis = (PDBGDIGGERWINNTRDR)pvUser; 298 uint32_t offFile = (uint32_t)off; 69 typedef DBGFMODPERDR *PDBGFMODPERDR; 70 71 /** 72 * Stack buffer. 73 */ 74 typedef union DBGFMODINMEMBUF 75 { 76 uint8_t ab[0x2000]; 77 IMAGE_DOS_HEADER DosHdr; 78 IMAGE_NT_HEADERS32 Nt32; 79 IMAGE_NT_HEADERS64 Nt64; 80 } DBGFMODINMEMBUF; 81 /** Pointer to stack buffer. */ 82 typedef DBGFMODINMEMBUF *PDBGFMODINMEMBUF; 83 84 85 86 /** 87 * Handles in-memory ELF images. 88 * 89 * @returns VBox status code. 90 * @param pUVM The user mode VM handle. 91 * @param pImageAddr The image address. 92 * @param fFlags Flags, DBGFMODINMEM_F_XXX. 93 * @param pszName The image name, optional. 94 * @param enmArch The image arch if we force it, pass 95 * RTLDRARCH_WHATEVER if you don't care. 96 * @param cbImage Image size. Pass 0 if not known. 97 * @param puBuf The header buffer. 98 * @param phDbgMod Where to return the resulting debug module on success. 99 * @param pErrInfo Where to return extended error info on failure. 100 */ 101 static int dbgfR3ModInMemElf(PUVM pUVM, PCDBGFADDRESS pImageAddr, uint32_t fFlags, const char *pszName, 102 RTLDRARCH enmArch, uint32_t cbImage, PDBGFMODINMEMBUF puBuf, 103 PRTDBGMOD phDbgMod, PRTERRINFO pErrInfo) 104 { 105 RT_NOREF(pUVM, fFlags, pszName, enmArch, cbImage, puBuf, phDbgMod); 106 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_INVALID_EXE_SIGNATURE, "Found ELF magic at %RGv", pImageAddr->FlatPtr); 107 } 108 109 110 /** 111 * @callback_method_impl{PFNRTLDRRDRMEMREAD} 112 */ 113 static DECLCALLBACK(int) dbgfModInMemPeRdr_Read(void *pvBuf, size_t cb, size_t off, void *pvUser) 114 { 115 PDBGFMODPERDR pThis = (PDBGFMODPERDR)pvUser; 116 uint32_t offFile = (uint32_t)off; 299 117 AssertReturn(offFile == off, VERR_INVALID_PARAMETER); 300 118 … … 381 199 382 200 383 /** @callback_method_impl{PFNRTLDRRDRMEMDTOR} */ 384 static DECLCALLBACK(void) dbgDiggerWinNtRdr_Dtor(void *pvUser) 385 { 386 PDBGDIGGERWINNTRDR pThis = (PDBGDIGGERWINNTRDR)pvUser; 201 /** 202 * @callback_method_impl{PFNRTLDRRDRMEMDTOR} 203 */ 204 static DECLCALLBACK(void) dbgfModInMemPeRdr_Dtor(void *pvUser) 205 { 206 PDBGFMODPERDR pThis = (PDBGFMODPERDR)pvUser; 387 207 388 208 VMR3ReleaseUVM(pThis->pUVM); … … 395 215 * Checks if the section headers look okay. 396 216 * 397 * @returns true / false.398 * @param paSh sPointer to the section headers.399 * @param cSh sNumber of headers.217 * @returns VBox status code. 218 * @param paShdrs Pointer to the section headers. 219 * @param cShdrs Number of headers. 400 220 * @param cbImage The image size reported by NT. 401 221 * @param cbImageFromHdr The image size by the linker in the header. … … 411 231 * the resource directory. These images will have 412 232 * a page aligned cbImage. 413 */ 414 static bool dbgDiggerWinNtCheckSectHdrsAndImgSize(PCIMAGE_SECTION_HEADER paShs, uint32_t cShs, uint32_t cbImage, 415 uint32_t cbImageFromHdr, uint32_t uRvaRsrc, uint32_t cbSectAlign, 416 bool fNt31, uint32_t *pcbImageCorrect) 233 * 234 * @param pErrInfo Where to return more error details. 235 */ 236 static int dbgfR3ModPeCheckSectHdrsAndImgSize(PCIMAGE_SECTION_HEADER paShdrs, uint32_t cShdrs, uint32_t cbImage, 237 uint32_t cbImageFromHdr, uint32_t uRvaRsrc, uint32_t cbSectAlign, 238 bool fNt31, uint32_t *pcbImageCorrect, PRTERRINFO pErrInfo) 417 239 { 418 240 *pcbImageCorrect = cbImage; 419 241 420 for (uint32_t i = 0; i < cShs; i++) 421 { 422 if (!paShs[i].Name[0]) 423 { 424 Log(("DigWinNt: Section header #%u has no name\n", i)); 425 return false; 426 } 427 428 if (paShs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD) 242 for (uint32_t i = 0; i < cShdrs; i++) 243 { 244 if (!paShdrs[i].Name[0]) 245 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "Section header #%u has no name", i); 246 247 if (paShdrs[i].Characteristics & IMAGE_SCN_TYPE_NOLOAD) 429 248 continue; 430 249 431 250 /* Tweak to determine the virtual size if the linker didn't set it (NT 3.1). */ 432 251 /** @todo this isn't really perfect. cbImage is kind of wrong... */ 433 uint32_t cbVirtual = paSh s[i].Misc.VirtualSize;252 uint32_t cbVirtual = paShdrs[i].Misc.VirtualSize; 434 253 if (cbVirtual == 0) 435 254 { 436 for (uint32_t j = i + 1; j < cSh s; j++)437 if ( !(paShs[j].Characteristics & IMAGE_SCN_TYPE_NOLOAD)438 && paSh s[j].VirtualAddress > paShs[i].VirtualAddress)255 for (uint32_t j = i + 1; j < cShdrs; j++) 256 if ( !(paShdrs[j].Characteristics & IMAGE_SCN_TYPE_NOLOAD) 257 && paShdrs[j].VirtualAddress > paShdrs[i].VirtualAddress) 439 258 { 440 cbVirtual = paSh s[j].VirtualAddress - paShs[i].VirtualAddress;259 cbVirtual = paShdrs[j].VirtualAddress - paShdrs[i].VirtualAddress; 441 260 break; 442 261 } 443 262 if (!cbVirtual) 444 263 { 445 if (paSh s[i].VirtualAddress < cbImageFromHdr)446 cbVirtual = cbImageFromHdr - paSh s[i].VirtualAddress;447 else if (paSh s[i].SizeOfRawData > 0)448 cbVirtual = RT_ALIGN(paSh s[i].SizeOfRawData, _4K);264 if (paShdrs[i].VirtualAddress < cbImageFromHdr) 265 cbVirtual = cbImageFromHdr - paShdrs[i].VirtualAddress; 266 else if (paShdrs[i].SizeOfRawData > 0) 267 cbVirtual = RT_ALIGN(paShdrs[i].SizeOfRawData, _4K); 449 268 } 450 269 } … … 452 271 /* Check that sizes are within the same range and that both sizes and 453 272 addresses are within reasonable limits. */ 454 if ( RT_ALIGN(cbVirtual, _64K) < RT_ALIGN(paSh s[i].SizeOfRawData, _64K)273 if ( RT_ALIGN(cbVirtual, _64K) < RT_ALIGN(paShdrs[i].SizeOfRawData, _64K) 455 274 || cbVirtual >= _1G 456 || paShs[i].SizeOfRawData >= _1G) 457 { 458 Log(("DigWinNt: Section header #%u (%.8s) has a VirtualSize=%#x (%#x) and SizeOfRawData=%#x, that's too much data!\n", 459 i, paShs[i].Name, cbVirtual, paShs[i].Misc.VirtualSize, paShs[i].SizeOfRawData)); 460 return false; 461 } 462 uint32_t uRvaEnd = paShs[i].VirtualAddress + cbVirtual; 463 if (uRvaEnd >= _1G || uRvaEnd < paShs[i].VirtualAddress) 464 { 465 Log(("DigWinNt: Section header #%u (%.8s) has a VirtualSize=%#x (%#x) and VirtualAddr=%#x, %#x in total, that's too much!\n", 466 i, paShs[i].Name, cbVirtual, paShs[i].Misc.VirtualSize, paShs[i].VirtualAddress, uRvaEnd)); 467 return false; 468 } 275 || paShdrs[i].SizeOfRawData >= _1G) 276 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, 277 "Section header #%u (%.8s) has a VirtualSize=%#x (%#x) and SizeOfRawData=%#x, that's too much data!", 278 i, paShdrs[i].Name, cbVirtual, paShdrs[i].Misc.VirtualSize, paShdrs[i].SizeOfRawData); 279 uint32_t uRvaEnd = paShdrs[i].VirtualAddress + cbVirtual; 280 if (uRvaEnd >= _1G || uRvaEnd < paShdrs[i].VirtualAddress) 281 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, 282 "Section header #%u (%.8s) has a VirtualSize=%#x (%#x) and VirtualAddr=%#x, %#x in total, that's too much!", 283 i, paShdrs[i].Name, cbVirtual, paShdrs[i].Misc.VirtualSize, paShdrs[i].VirtualAddress, uRvaEnd); 469 284 470 285 /* Check for images chopped off around '.rsrc'. */ … … 475 290 /* Check that the section is within the image. */ 476 291 if (uRvaEnd > cbImage && fNt31) 477 { 478 Log(("DigWinNt: Section header #%u has a virtual address range beyond the image: %#x TO %#x cbImage=%#x\n", 479 i, paShs[i].VirtualAddress, uRvaEnd, cbImage)); 480 return false; 481 } 292 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, 293 "Section header #%u has a virtual address range beyond the image: %#x TO %#x cbImage=%#x", 294 i, paShdrs[i].VirtualAddress, uRvaEnd, cbImage); 482 295 } 483 296 484 297 Assert(*pcbImageCorrect == cbImage || !(*pcbImageCorrect & 0xfff)); 485 298 *pcbImageCorrect = cbImage; 486 return true;299 return VINF_SUCCESS; 487 300 } 488 301 … … 491 304 * Create a loader module for the in-guest-memory PE module. 492 305 */ 493 static int dbgDiggerWinNtCreateLdrMod(PDBGDIGGERWINNT pThis, PUVM pUVM, const char *pszName, PCDBGFADDRESS pImageAddr, 494 uint32_t cbImage, uint8_t *pbBuf, size_t cbBuf, 495 uint32_t offHdrs, PCNTHDRS pHdrs, PRTLDRMOD phLdrMod) 306 static int dbgfR3ModInMemPeCreateLdrMod(PUVM pUVM, uint32_t fFlags, const char *pszName, PCDBGFADDRESS pImageAddr, 307 uint32_t cbImage, uint32_t cbImageFromHdr, bool f32Bit, 308 uint32_t cShdrs, PCIMAGE_SECTION_HEADER paShdrs, uint32_t cbSectAlign, 309 uint32_t cDataDir, PCIMAGE_DATA_DIRECTORY paDataDir, uint32_t offHdrs, 310 PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo) 496 311 { 497 312 /* 498 313 * Allocate and create a reader instance. 499 314 */ 500 uint32_t const cShs = WINNT_UNION(pThis, pHdrs, FileHeader.NumberOfSections); 501 PDBGDIGGERWINNTRDR pRdr = (PDBGDIGGERWINNTRDR)RTMemAlloc(RT_UOFFSETOF_DYN(DBGDIGGERWINNTRDR, aMappings[cShs + 2])); 315 PDBGFMODPERDR pRdr = (PDBGFMODPERDR)RTMemAlloc(RT_UOFFSETOF_DYN(DBGFMODPERDR, aMappings[cShdrs + 2])); 502 316 if (!pRdr) 503 317 return VERR_NO_MEMORY; … … 512 326 513 327 /* 514 * Use the section table to construct a more accurate view of the file/ 515 * image if it's in the buffer (it should be). 328 * Use the section table to construct a more accurate view of the file/image. 516 329 */ 517 330 uint32_t uRvaRsrc = UINT32_MAX; 518 if (WINNT_UNION(pThis, pHdrs, OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]).Size > 0) 519 uRvaRsrc = WINNT_UNION(pThis, pHdrs, OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE]).VirtualAddress; 520 uint32_t offShs = offHdrs 521 + ( pThis->f32Bit 522 ? pHdrs->vX_32.FileHeader.SizeOfOptionalHeader + RT_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) 523 : pHdrs->vX_64.FileHeader.SizeOfOptionalHeader + RT_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader)); 524 uint32_t cbShs = cShs * sizeof(IMAGE_SECTION_HEADER); 525 PCIMAGE_SECTION_HEADER paShs = (PCIMAGE_SECTION_HEADER)(pbBuf + offShs); 526 if ( offShs + cbShs <= RT_MIN(cbImage, cbBuf) 527 && dbgDiggerWinNtCheckSectHdrsAndImgSize(paShs, cShs, cbImage, WINNT_UNION(pThis, pHdrs, OptionalHeader.SizeOfImage), 528 uRvaRsrc, WINNT_UNION(pThis, pHdrs, OptionalHeader.SectionAlignment), 529 pThis->fNt31, &pRdr->cbCorrectImageSize)) 331 if ( cDataDir > IMAGE_DIRECTORY_ENTRY_RESOURCE 332 && paDataDir[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size > 0) 333 uRvaRsrc = paDataDir[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; 334 335 int rc = dbgfR3ModPeCheckSectHdrsAndImgSize(paShdrs, cShdrs, cbImage, cbImageFromHdr, uRvaRsrc, cbSectAlign, 336 RT_BOOL(fFlags & DBGFMODINMEM_F_PE_NT31), &pRdr->cbCorrectImageSize, pErrInfo); 337 if (RT_SUCCESS(rc)) 530 338 { 531 339 pRdr->cMappings = 0; 532 340 533 for (uint32_t i = 0; i < cSh s; i++)534 if ( paSh s[i].SizeOfRawData > 0535 && paSh s[i].PointerToRawData > 0)341 for (uint32_t i = 0; i < cShdrs; i++) 342 if ( paShdrs[i].SizeOfRawData > 0 343 && paShdrs[i].PointerToRawData > 0) 536 344 { 537 345 uint32_t j = 1; … … 540 348 else 541 349 { 542 while (j < pRdr->cMappings && pRdr->aMappings[j].offFile < paSh s[i].PointerToRawData)350 while (j < pRdr->cMappings && pRdr->aMappings[j].offFile < paShdrs[i].PointerToRawData) 543 351 j++; 544 352 if (j < pRdr->cMappings) 545 353 memmove(&pRdr->aMappings[j + 1], &pRdr->aMappings[j], (pRdr->cMappings - j) * sizeof(pRdr->aMappings)); 546 354 } 547 pRdr->aMappings[j].offFile = paSh s[i].PointerToRawData;548 pRdr->aMappings[j].offMem = paSh s[i].VirtualAddress;549 pRdr->aMappings[j].cbMem = i + 1 < cSh s550 ? paSh s[i + 1].VirtualAddress - paShs[i].VirtualAddress551 : paSh s[i].Misc.VirtualSize;355 pRdr->aMappings[j].offFile = paShdrs[i].PointerToRawData; 356 pRdr->aMappings[j].offMem = paShdrs[i].VirtualAddress; 357 pRdr->aMappings[j].cbMem = i + 1 < cShdrs 358 ? paShdrs[i + 1].VirtualAddress - paShdrs[i].VirtualAddress 359 : paShdrs[i].Misc.VirtualSize; 552 360 if (j == pRdr->cMappings) 553 pRdr->cbImage = paSh s[i].PointerToRawData + paShs[i].SizeOfRawData;361 pRdr->cbImage = paShdrs[i].PointerToRawData + paShdrs[i].SizeOfRawData; 554 362 pRdr->cMappings++; 555 363 } … … 568 376 } 569 377 } 378 else if (fFlags & DBGFMODINMEM_F_NO_READER_FALLBACK) 379 return rc; 570 380 else 571 381 { … … 582 392 if (pRdr->cbCorrectImageSize != cbImage) 583 393 { 584 Log(("DigWinNT: The image is really %#x bytes long, not %#x as mapped by NT!\n", pRdr->cbCorrectImageSize, cbImage)); 585 pRdr->offSizeOfImage = pThis->f32Bit 394 Log(("dbgfR3ModInMemPeCreateLdrMod: The image is really %#x bytes long, not %#x as mapped by NT!\n", 395 pRdr->cbCorrectImageSize, cbImage)); 396 pRdr->offSizeOfImage = f32Bit 586 397 ? offHdrs + RT_OFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader.SizeOfImage) 587 398 : offHdrs + RT_OFFSETOF(IMAGE_NT_HEADERS64, OptionalHeader.SizeOfImage); … … 593 404 */ 594 405 RTLDRMOD hLdrMod; 595 intrc = RTLdrOpenInMemory(pszName, RTLDR_O_FOR_DEBUG, RTLDRARCH_WHATEVER, pRdr->cbImage,596 dbgDiggerWinNtRdr_Read, dbgDiggerWinNtRdr_Dtor, pRdr,597 &hLdrMod);406 rc = RTLdrOpenInMemory(pszName, RTLDR_O_FOR_DEBUG, RTLDRARCH_WHATEVER, pRdr->cbImage, 407 dbgfModInMemPeRdr_Read, dbgfModInMemPeRdr_Dtor, pRdr, 408 &hLdrMod, pErrInfo); 598 409 if (RT_SUCCESS(rc)) 599 410 *phLdrMod = hLdrMod; … … 605 416 606 417 /** 418 * Handles in-memory PE images. 419 * 420 * @returns VBox status code. 421 * @param pUVM The user mode VM handle. 422 * @param pImageAddr The image address. 423 * @param fFlags Flags, DBGFMODINMEM_F_XXX. 424 * @param pszName The image name, optional. 425 * @param enmArch The image arch if we force it, pass 426 * RTLDRARCH_WHATEVER if you don't care. 427 * @param cbImage Image size. Pass 0 if not known. 428 * @param offPeHdrs Offset of the PE header. 429 * @param cbPeHdrsPart1 How read into uBuf at @a offPeHdrs. 430 * @param puBuf The header buffer. 431 * @param phDbgMod Where to return the resulting debug module on success. 432 * @param pErrInfo Where to return extended error info on failure. 433 */ 434 static int dbgfR3ModInMemPe(PUVM pUVM, PCDBGFADDRESS pImageAddr, uint32_t fFlags, const char *pszName, RTLDRARCH enmArch, 435 uint32_t cbImage, uint32_t offPeHdrs, uint32_t cbPeHdrsPart1, PDBGFMODINMEMBUF puBuf, 436 PRTDBGMOD phDbgMod, PRTERRINFO pErrInfo) 437 { 438 /* 439 * Read the optional header and the section table after validating the 440 * info we need from the file header. 441 */ 442 /* Check the opt hdr size and number of sections as these are used to determine how much to read next. */ 443 if ( puBuf->Nt32.FileHeader.SizeOfOptionalHeader < sizeof(IMAGE_OPTIONAL_HEADER32) 444 || puBuf->Nt32.FileHeader.SizeOfOptionalHeader > sizeof(IMAGE_OPTIONAL_HEADER64) + 128) 445 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "Invalid SizeOfOptionalHeader value: %#RX32", 446 puBuf->Nt32.FileHeader.SizeOfOptionalHeader); 447 448 if ( puBuf->Nt32.FileHeader.NumberOfSections < 1 449 || puBuf->Nt32.FileHeader.NumberOfSections > 190 /* what fits in our 8K buffer */) 450 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "NumberOfSections is out of range: %#RX32 (1..190)", 451 puBuf->Nt32.FileHeader.NumberOfSections); 452 453 /* Read the optional header and section table. */ 454 uint32_t const cbHdrs = RT_UOFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader) 455 + puBuf->Nt32.FileHeader.SizeOfOptionalHeader 456 + puBuf->Nt32.FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER); 457 AssertReturn(cbHdrs <= sizeof(*puBuf), RTERRINFO_LOG_SET_F(pErrInfo, VERR_INTERNAL_ERROR_2, "cbHdrs=%#x", cbHdrs)); 458 459 DBGFADDRESS PeHdrPart2Addr = *pImageAddr; 460 DBGFR3AddrAdd(&PeHdrPart2Addr, offPeHdrs + cbPeHdrsPart1); 461 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &PeHdrPart2Addr, &puBuf->ab[cbPeHdrsPart1], cbHdrs - cbPeHdrsPart1); 462 if (RT_FAILURE(rc)) 463 return RTERRINFO_LOG_SET_F(pErrInfo, rc, 464 "Failed to read the second part of the PE headers at %RGv (off=%#RX32 + %#RX32): %Rrc", 465 PeHdrPart2Addr.FlatPtr, offPeHdrs, cbPeHdrsPart1, rc); 466 467 /* 468 * Check the image architecture and determine the bitness. 469 */ 470 RTLDRARCH enmArchActual; 471 bool f32Bit; 472 switch (puBuf->Nt32.FileHeader.Machine) 473 { 474 case IMAGE_FILE_MACHINE_I386: 475 enmArchActual = RTLDRARCH_X86_32; 476 f32Bit = true; 477 break; 478 case IMAGE_FILE_MACHINE_AMD64: 479 enmArchActual = RTLDRARCH_AMD64; 480 f32Bit = false; 481 break; 482 case IMAGE_FILE_MACHINE_ARM: 483 case IMAGE_FILE_MACHINE_THUMB: 484 case IMAGE_FILE_MACHINE_ARMNT: 485 enmArchActual = RTLDRARCH_ARM32; 486 f32Bit = true; 487 break; 488 case IMAGE_FILE_MACHINE_ARM64: 489 enmArchActual = RTLDRARCH_ARM64; 490 f32Bit = false; 491 break; 492 default: 493 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDR_ARCH_MISMATCH, "Unknown machine: %#x", puBuf->Nt32.FileHeader.Machine); 494 } 495 if ( enmArch != RTLDRARCH_WHATEVER 496 && enmArch != enmArchActual) 497 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_LDR_ARCH_MISMATCH, "Found %s expected %s", 498 RTLdrArchName(enmArchActual), RTLdrArchName(enmArch)); 499 500 /* 501 * Check optional header magic and size. 502 */ 503 uint16_t const uOptMagic = f32Bit ? IMAGE_NT_OPTIONAL_HDR32_MAGIC : IMAGE_NT_OPTIONAL_HDR64_MAGIC; 504 if (puBuf->Nt32.OptionalHeader.Magic != uOptMagic) 505 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "Unexpected optional header magic: %#x (expected %#x)", 506 puBuf->Nt32.OptionalHeader.Magic, uOptMagic); 507 508 uint32_t const cDataDir = f32Bit ? puBuf->Nt32.OptionalHeader.NumberOfRvaAndSizes : puBuf->Nt64.OptionalHeader.NumberOfRvaAndSizes; 509 if ( cDataDir <= IMAGE_DIRECTORY_ENTRY_BASERELOC /* a bit random */ 510 || cDataDir > 32 /* also random */) 511 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "Unexpected data directory size: %#x", cDataDir); 512 513 uint32_t cbOptHdr = f32Bit ? sizeof(IMAGE_OPTIONAL_HEADER32) : sizeof(IMAGE_OPTIONAL_HEADER64); 514 cbOptHdr -= sizeof(IMAGE_DATA_DIRECTORY) * IMAGE_NUMBEROF_DIRECTORY_ENTRIES; 515 cbOptHdr += sizeof(IMAGE_DATA_DIRECTORY) * cDataDir; 516 if (puBuf->Nt32.FileHeader.SizeOfOptionalHeader != cbOptHdr) 517 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_BAD_EXE_FORMAT, "Unexpected optional header size: %#x (expected %#x)", 518 puBuf->Nt32.FileHeader.SizeOfOptionalHeader, cbOptHdr); 519 520 uint32_t const cbSectAlign = f32Bit ? puBuf->Nt32.OptionalHeader.SectionAlignment : puBuf->Nt64.OptionalHeader.SectionAlignment; 521 PCIMAGE_SECTION_HEADER pSHdrs = (PCIMAGE_SECTION_HEADER)((uintptr_t)&puBuf->Nt32.OptionalHeader + cbOptHdr); 522 PCIMAGE_DATA_DIRECTORY paDataDir = (PCIMAGE_DATA_DIRECTORY)((uintptr_t)pSHdrs - cDataDir * sizeof(IMAGE_DATA_DIRECTORY)); 523 524 /* 525 * Establish the image size. 526 */ 527 uint32_t cbImageFromHdr = f32Bit ? puBuf->Nt32.OptionalHeader.SizeOfImage : puBuf->Nt64.OptionalHeader.SizeOfImage; 528 if ( !cbImage 529 || (fFlags & DBGFMODINMEM_F_PE_NT31)) 530 cbImage = RT_ALIGN(cbImageFromHdr, _4K); 531 else if (RT_ALIGN(cbImageFromHdr, _4K) != RT_ALIGN(cbImage, _4K)) 532 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_MISMATCH, "Image size mismatch: input=%#x header=%#x", cbImage, cbImageFromHdr); 533 534 /* 535 * Guess the image name if not specified. 536 */ 537 //char szImageName[64]; 538 if (!pszName) 539 { 540 /** @todo */ 541 } 542 543 /* 544 * Create the module using the in memory image first, falling back on cached image. 545 */ 546 RTLDRMOD hLdrMod; 547 rc = dbgfR3ModInMemPeCreateLdrMod(pUVM, fFlags, pszName, pImageAddr, cbImage, cbImageFromHdr, f32Bit, 548 puBuf->Nt32.FileHeader.NumberOfSections, pSHdrs, cbSectAlign, cDataDir, paDataDir, 549 offPeHdrs, &hLdrMod, pErrInfo); 550 if (RT_FAILURE(rc)) 551 hLdrMod = NIL_RTLDRMOD; 552 553 RTDBGMOD hMod; 554 rc = RTDbgModCreateFromPeImage(&hMod, pszName, NULL, &hLdrMod, cbImageFromHdr, 555 puBuf->Nt32.FileHeader.TimeDateStamp, DBGFR3AsGetConfig(pUVM)); 556 if (RT_SUCCESS(rc)) 557 *phDbgMod = hMod; 558 else if (!(fFlags & DBGFMODINMEM_F_NO_CONTAINER_FALLBACK)) 559 { 560 /* 561 * Fallback is a container module. 562 */ 563 rc = RTDbgModCreate(&hMod, pszName, cbImage, 0); 564 if (RT_SUCCESS(rc)) 565 { 566 rc = RTDbgModSymbolAdd(hMod, "Headers", 0 /*iSeg*/, 0, cbImage, 0 /*fFlags*/, NULL); 567 AssertRC(rc); 568 } 569 } 570 return rc; 571 } 572 573 574 575 /** 607 576 * Process a PE image found in guest memory. 608 577 * 609 * @param pThis The instance data.610 578 * @param pUVM The user mode VM handle. 611 * @param pszName The image name.612 579 * @param pImageAddr The image address. 613 * @param cbImage The size of the image. 614 * @param pbBuf Scratch buffer containing the first 615 * RT_MIN(cbBuf, cbImage) bytes of the image. 616 * @param cbBuf The scratch buffer size. 617 */ 618 static void dbgDiggerWinNtProcessImage(PDBGDIGGERWINNT pThis, PUVM pUVM, const char *pszName, 619 PCDBGFADDRESS pImageAddr, uint32_t cbImage, 620 uint8_t *pbBuf, size_t cbBuf) 621 { 622 LogFlow(("DigWinNt: %RGp %#x %s\n", pImageAddr->FlatPtr, cbImage, pszName)); 623 624 /* 625 * NT 3.1 doesn't set the image size in the MTEs, so a little 626 * bit of tweaking is necessary here. 627 */ 628 uint32_t const cbImageValidate = !pThis->fNt31 ? cbImage : _64M; 629 630 /* 631 * Do some basic validation first. 632 * This is the usual exteremely verbose and messy code... 633 */ 634 Assert(cbBuf >= sizeof(IMAGE_NT_HEADERS64)); 635 if ( (cbImage < sizeof(IMAGE_NT_HEADERS64) && !pThis->fNt31) 636 || cbImage >= _1M * 256) 637 { 638 Log(("DigWinNt: %s: Bad image size: %#x\n", pszName, cbImage)); 639 return; 640 } 641 642 /* Dig out the NT/PE headers. */ 643 IMAGE_DOS_HEADER const *pMzHdr = (IMAGE_DOS_HEADER const *)pbBuf; 644 PCNTHDRS pHdrs; 645 uint32_t offHdrs; 646 if (pMzHdr->e_magic != IMAGE_DOS_SIGNATURE) 647 { 648 offHdrs = 0; 649 pHdrs = (PCNTHDRS)pbBuf; 650 } 651 else if ( pMzHdr->e_lfanew >= cbImageValidate 652 || pMzHdr->e_lfanew < sizeof(*pMzHdr) 653 || pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) > cbImageValidate) 654 { 655 Log(("DigWinNt: %s: PE header to far into image: %#x cbImage=%#x\n", pszName, pMzHdr->e_lfanew, cbImage)); 656 return; 657 } 658 else if ( pMzHdr->e_lfanew < cbBuf 659 && pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) <= cbBuf) 660 { 661 offHdrs = pMzHdr->e_lfanew; 662 pHdrs = (NTHDRS const *)(pbBuf + offHdrs); 663 } 580 * @param fFlags Flags, DBGFMODINMEM_F_XXX. 581 * @param pszName The image name, optional. 582 * @param enmArch The image arch if we force it, pass 583 * RTLDRARCH_WHATEVER if you don't care. 584 * @param cbImage Image size. Pass 0 if not known. 585 * @param phDbgMod Where to return the resulting debug module on success. 586 * @param pErrInfo Where to return extended error info on failure. 587 */ 588 VMMR3DECL(int) DBGFR3ModInMem(PUVM pUVM, PCDBGFADDRESS pImageAddr, uint32_t fFlags, const char *pszName, 589 RTLDRARCH enmArch, uint32_t cbImage, PRTDBGMOD phDbgMod, PRTERRINFO pErrInfo) 590 { 591 /* 592 * Validate and adjust. 593 */ 594 AssertPtrReturn(phDbgMod, VERR_INVALID_POINTER); 595 *phDbgMod = NIL_RTDBGMOD; 596 AssertPtrReturn(pImageAddr, VERR_INVALID_POINTER); 597 AssertMsgReturn(cbImage == 0 || cbImage >= sizeof(IMAGE_NT_HEADERS32) + sizeof(IMAGE_DOS_HEADER), 598 ("cbImage=%#x\n", cbImage), VERR_INVALID_PARAMETER); 599 AssertMsgReturn(!(fFlags & ~DBGFMODINMEM_F_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_FLAGS); 600 if (enmArch == RTLDRARCH_HOST) 601 enmArch = RTLdrGetHostArch(); 602 603 /* 604 * Look for an image header we can work with. 605 */ 606 DBGFMODINMEMBUF uBuf; 607 RT_ZERO(uBuf); 608 609 int rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, pImageAddr, &uBuf, sizeof(uBuf.DosHdr)); 610 if (RT_FAILURE(rc)) 611 return RTERRINFO_LOG_SET_F(pErrInfo, rc, "Failed to read DOS header at %RGv: %Rrc", pImageAddr->FlatPtr, rc); 612 613 if (uBuf.ab[0] == ELFMAG0 && uBuf.ab[1] == ELFMAG1 && uBuf.ab[2] == ELFMAG2 && uBuf.ab[3] == ELFMAG3) 614 return dbgfR3ModInMemElf(pUVM, pImageAddr, fFlags, pszName, enmArch, cbImage, &uBuf, phDbgMod, pErrInfo); 615 616 uint32_t offNewHdrs; 617 if (uBuf.DosHdr.e_magic == IMAGE_DOS_SIGNATURE) 618 { 619 offNewHdrs = uBuf.DosHdr.e_lfanew; 620 if ( offNewHdrs < 16 621 || offNewHdrs > (cbImage ? _2M : cbImage - sizeof(IMAGE_NT_HEADERS32))) 622 return RTERRINFO_LOG_SET_F(pErrInfo, rc, "e_lfanew value is out of range: %RX32 (16..%u)", 623 offNewHdrs, (cbImage ? _2M : cbImage - sizeof(IMAGE_NT_HEADERS32))); 624 } 625 else if (uBuf.Nt32.Signature == IMAGE_NT_SIGNATURE) 626 offNewHdrs = 0; 664 627 else 665 { 666 Log(("DigWinNt: %s: PE header to far into image (lazy bird): %#x\n", pszName, pMzHdr->e_lfanew)); 667 return; 668 } 669 if (pHdrs->vX_32.Signature != IMAGE_NT_SIGNATURE) 670 { 671 Log(("DigWinNt: %s: Bad PE signature: %#x\n", pszName, pHdrs->vX_32.Signature)); 672 return; 673 } 674 675 /* The file header is the same on both archs */ 676 if (pHdrs->vX_32.FileHeader.Machine != (pThis->f32Bit ? IMAGE_FILE_MACHINE_I386 : IMAGE_FILE_MACHINE_AMD64)) 677 { 678 Log(("DigWinNt: %s: Invalid FH.Machine: %#x\n", pszName, pHdrs->vX_32.FileHeader.Machine)); 679 return; 680 } 681 if (pHdrs->vX_32.FileHeader.SizeOfOptionalHeader != (pThis->f32Bit ? sizeof(IMAGE_OPTIONAL_HEADER32) : sizeof(IMAGE_OPTIONAL_HEADER64))) 682 { 683 Log(("DigWinNt: %s: Invalid FH.SizeOfOptionalHeader: %#x\n", pszName, pHdrs->vX_32.FileHeader.SizeOfOptionalHeader)); 684 return; 685 } 686 if (WINNT_UNION(pThis, pHdrs, FileHeader.NumberOfSections) > 64) 687 { 688 Log(("DigWinNt: %s: Too many sections: %#x\n", pszName, WINNT_UNION(pThis, pHdrs, FileHeader.NumberOfSections))); 689 return; 690 } 691 692 const uint32_t TimeDateStamp = pHdrs->vX_32.FileHeader.TimeDateStamp; 693 694 /* The optional header is not... */ 695 if (WINNT_UNION(pThis, pHdrs, OptionalHeader.Magic) != (pThis->f32Bit ? IMAGE_NT_OPTIONAL_HDR32_MAGIC : IMAGE_NT_OPTIONAL_HDR64_MAGIC)) 696 { 697 Log(("DigWinNt: %s: Invalid OH.Magic: %#x\n", pszName, WINNT_UNION(pThis, pHdrs, OptionalHeader.Magic))); 698 return; 699 } 700 uint32_t cbImageFromHdr = WINNT_UNION(pThis, pHdrs, OptionalHeader.SizeOfImage); 701 if (pThis->fNt31) 702 cbImage = RT_ALIGN(cbImageFromHdr, _4K); 703 else if (RT_ALIGN(cbImageFromHdr, _4K) != RT_ALIGN(cbImage, _4K)) 704 { 705 Log(("DigWinNt: %s: Invalid OH.SizeOfImage: %#x, expected %#x\n", pszName, cbImageFromHdr, cbImage)); 706 return; 707 } 708 if (WINNT_UNION(pThis, pHdrs, OptionalHeader.NumberOfRvaAndSizes) != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) 709 { 710 Log(("DigWinNt: %s: Invalid OH.NumberOfRvaAndSizes: %#x\n", pszName, WINNT_UNION(pThis, pHdrs, OptionalHeader.NumberOfRvaAndSizes))); 711 return; 712 } 713 714 /* 715 * Create the module using the in memory image first, falling back 716 * on cached image. 717 */ 718 RTLDRMOD hLdrMod; 719 int rc = dbgDiggerWinNtCreateLdrMod(pThis, pUVM, pszName, pImageAddr, cbImage, pbBuf, cbBuf, offHdrs, pHdrs, 720 &hLdrMod); 628 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_INVALID_EXE_SIGNATURE, "Unknown image magic at %RGv: %.8Rhxs", 629 pImageAddr->FlatPtr, uBuf.ab); 630 631 /* 632 * Read the next bit of header, assuming PE so stop at the end of 633 * the COFF file header. 634 */ 635 DBGFADDRESS PeHdrAddr = *pImageAddr; 636 DBGFR3AddrAdd(&PeHdrAddr, offNewHdrs); 637 uint32_t const cbPeHdrsPart1 = RT_UOFFSETOF(IMAGE_NT_HEADERS32, OptionalHeader); 638 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &PeHdrAddr, &uBuf, cbPeHdrsPart1); 721 639 if (RT_FAILURE(rc)) 722 hLdrMod = NIL_RTLDRMOD; 723 724 RTDBGMOD hMod; 725 rc = RTDbgModCreateFromPeImage(&hMod, pszName, NULL, hLdrMod, 726 cbImageFromHdr, TimeDateStamp, DBGFR3AsGetConfig(pUVM)); 727 if (RT_FAILURE(rc)) 728 { 729 /* 730 * Final fallback is a container module. 731 */ 732 rc = RTDbgModCreate(&hMod, pszName, cbImage, 0); 733 if (RT_FAILURE(rc)) 734 return; 735 736 rc = RTDbgModSymbolAdd(hMod, "Headers", 0 /*iSeg*/, 0, cbImage, 0 /*fFlags*/, NULL); 737 AssertRC(rc); 738 } 739 740 /* Tag the module. */ 741 rc = RTDbgModSetTag(hMod, DIG_WINNT_MOD_TAG); 742 AssertRC(rc); 743 744 /* 745 * Link the module. 746 */ 747 RTDBGAS hAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL); 748 if (hAs != NIL_RTDBGAS) 749 rc = RTDbgAsModuleLink(hAs, hMod, pImageAddr->FlatPtr, RTDBGASLINK_FLAGS_REPLACE /*fFlags*/); 750 else 751 rc = VERR_INTERNAL_ERROR; 752 RTDbgModRelease(hMod); 753 RTDbgAsRelease(hAs); 640 return RTERRINFO_LOG_SET_F(pErrInfo, rc, "Failed to read PE/LX/NE headers at %RGv (off=%#RX32): %Rrc", 641 PeHdrAddr.FlatPtr, offNewHdrs, rc); 642 643 if (uBuf.Nt32.Signature == IMAGE_NT_SIGNATURE) 644 return dbgfR3ModInMemPe(pUVM, pImageAddr, fFlags, pszName, enmArch, cbImage, offNewHdrs, cbPeHdrsPart1, &uBuf, 645 phDbgMod, pErrInfo); 646 647 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_INVALID_EXE_SIGNATURE, "No PE/LX/NE header at %RGv (off=%#RX32): %.8Rhxs", 648 PeHdrAddr.FlatPtr, offNewHdrs, uBuf.ab); 754 649 } 755 650 756 757 /**758 * @copydoc DBGFOSREG::pfnQueryInterface759 */760 static DECLCALLBACK(void *) dbgDiggerWinNtQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)761 {762 RT_NOREF3(pUVM, pvData, enmIf);763 return NULL;764 }765 766 767 /**768 * @copydoc DBGFOSREG::pfnQueryVersion769 */770 static DECLCALLBACK(int) dbgDiggerWinNtQueryVersion(PUVM pUVM, void *pvData, char *pszVersion, size_t cchVersion)771 {772 RT_NOREF1(pUVM);773 PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;774 Assert(pThis->fValid);775 const char *pszNtProductType;776 switch (pThis->NtProductType)777 {778 case kNtProductType_WinNt: pszNtProductType = "-WinNT"; break;779 case kNtProductType_LanManNt: pszNtProductType = "-LanManNT"; break;780 case kNtProductType_Server: pszNtProductType = "-Server"; break;781 default: pszNtProductType = ""; break;782 }783 RTStrPrintf(pszVersion, cchVersion, "%u.%u-%s%s", pThis->NtMajorVersion, pThis->NtMinorVersion,784 pThis->f32Bit ? "x86" : "AMD64", pszNtProductType);785 return VINF_SUCCESS;786 }787 788 789 /**790 * @copydoc DBGFOSREG::pfnTerm791 */792 static DECLCALLBACK(void) dbgDiggerWinNtTerm(PUVM pUVM, void *pvData)793 {794 RT_NOREF1(pUVM);795 PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;796 Assert(pThis->fValid);797 798 pThis->fValid = false;799 }800 801 802 /**803 * @copydoc DBGFOSREG::pfnRefresh804 */805 static DECLCALLBACK(int) dbgDiggerWinNtRefresh(PUVM pUVM, void *pvData)806 {807 PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;808 NOREF(pThis);809 Assert(pThis->fValid);810 811 /*812 * For now we'll flush and reload everything.813 */814 RTDBGAS hDbgAs = DBGFR3AsResolveAndRetain(pUVM, DBGF_AS_KERNEL);815 if (hDbgAs != NIL_RTDBGAS)816 {817 uint32_t iMod = RTDbgAsModuleCount(hDbgAs);818 while (iMod-- > 0)819 {820 RTDBGMOD hMod = RTDbgAsModuleByIndex(hDbgAs, iMod);821 if (hMod != NIL_RTDBGMOD)822 {823 if (RTDbgModGetTag(hMod) == DIG_WINNT_MOD_TAG)824 {825 int rc = RTDbgAsModuleUnlink(hDbgAs, hMod);826 AssertRC(rc);827 }828 RTDbgModRelease(hMod);829 }830 }831 RTDbgAsRelease(hDbgAs);832 }833 834 dbgDiggerWinNtTerm(pUVM, pvData);835 return dbgDiggerWinNtInit(pUVM, pvData);836 }837 838 839 /**840 * @copydoc DBGFOSREG::pfnInit841 */842 static DECLCALLBACK(int) dbgDiggerWinNtInit(PUVM pUVM, void *pvData)843 {844 PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;845 Assert(!pThis->fValid);846 847 union848 {849 uint8_t au8[0x2000];850 RTUTF16 wsz[0x2000/2];851 NTKUSERSHAREDDATA UserSharedData;852 } u;853 DBGFADDRESS Addr;854 int rc;855 856 /*857 * Figure the NT version.858 */859 DBGFR3AddrFromFlat(pUVM, &Addr, pThis->f32Bit ? NTKUSERSHAREDDATA_WINNT32 : NTKUSERSHAREDDATA_WINNT64);860 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &u, PAGE_SIZE);861 if (RT_SUCCESS(rc))862 {863 pThis->NtProductType = u.UserSharedData.ProductTypeIsValid && u.UserSharedData.NtProductType <= kNtProductType_Server864 ? (NTPRODUCTTYPE)u.UserSharedData.NtProductType865 : kNtProductType_Invalid;866 pThis->NtMajorVersion = u.UserSharedData.NtMajorVersion;867 pThis->NtMinorVersion = u.UserSharedData.NtMinorVersion;868 }869 else if (pThis->fNt31)870 {871 pThis->NtProductType = kNtProductType_WinNt;872 pThis->NtMajorVersion = 3;873 pThis->NtMinorVersion = 1;874 }875 else876 {877 Log(("DigWinNt: Error reading KUSER_SHARED_DATA: %Rrc\n", rc));878 return rc;879 }880 881 /*882 * Dig out the module chain.883 */884 DBGFADDRESS AddrPrev = pThis->PsLoadedModuleListAddr;885 Addr = pThis->KernelMteAddr;886 do887 {888 /* Read the validate the MTE. */889 NTMTE Mte;890 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &Mte, pThis->f32Bit ? sizeof(Mte.vX_32) : sizeof(Mte.vX_64));891 if (RT_FAILURE(rc))892 break;893 if (WINNT_UNION(pThis, &Mte, InLoadOrderLinks.Blink) != AddrPrev.FlatPtr)894 {895 Log(("DigWinNt: Bad Mte At %RGv - backpointer\n", Addr.FlatPtr));896 break;897 }898 if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, InLoadOrderLinks.Flink)) )899 {900 Log(("DigWinNt: Bad Mte at %RGv - forward pointer\n", Addr.FlatPtr));901 break;902 }903 if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, BaseDllName.Buffer)))904 {905 Log(("DigWinNt: Bad Mte at %RGv - BaseDllName=%llx\n", Addr.FlatPtr, WINNT_UNION(pThis, &Mte, BaseDllName.Buffer)));906 break;907 }908 if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, FullDllName.Buffer)))909 {910 Log(("DigWinNt: Bad Mte at %RGv - FullDllName=%llx\n", Addr.FlatPtr, WINNT_UNION(pThis, &Mte, FullDllName.Buffer)));911 break;912 }913 if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, DllBase)))914 {915 Log(("DigWinNt: Bad Mte at %RGv - DllBase=%llx\n", Addr.FlatPtr, WINNT_UNION(pThis, &Mte, DllBase) ));916 break;917 }918 919 uint32_t const cbImageMte = !pThis->fNt31 ? WINNT_UNION(pThis, &Mte, SizeOfImage) : 0;920 if ( !pThis->fNt31921 && ( cbImageMte > _256M922 || WINNT_UNION(pThis, &Mte, EntryPoint) - WINNT_UNION(pThis, &Mte, DllBase) > cbImageMte) )923 {924 Log(("DigWinNt: Bad Mte at %RGv - EntryPoint=%llx SizeOfImage=%x DllBase=%llx\n",925 Addr.FlatPtr, WINNT_UNION(pThis, &Mte, EntryPoint), cbImageMte, WINNT_UNION(pThis, &Mte, DllBase)));926 break;927 }928 929 /* Read the full name. */930 DBGFADDRESS AddrName;931 DBGFR3AddrFromFlat(pUVM, &AddrName, WINNT_UNION(pThis, &Mte, FullDllName.Buffer));932 uint16_t cbName = WINNT_UNION(pThis, &Mte, FullDllName.Length);933 if (cbName < sizeof(u))934 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrName, &u, cbName);935 else936 rc = VERR_OUT_OF_RANGE;937 if (RT_FAILURE(rc))938 {939 DBGFR3AddrFromFlat(pUVM, &AddrName, WINNT_UNION(pThis, &Mte, BaseDllName.Buffer));940 cbName = WINNT_UNION(pThis, &Mte, BaseDllName.Length);941 if (cbName < sizeof(u))942 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &AddrName, &u, cbName);943 else944 rc = VERR_OUT_OF_RANGE;945 }946 if (RT_SUCCESS(rc))947 {948 u.wsz[cbName/2] = '\0';949 char *pszName;950 rc = RTUtf16ToUtf8(u.wsz, &pszName);951 if (RT_SUCCESS(rc))952 {953 /* Read the start of the PE image and pass it along to a worker. */954 DBGFADDRESS ImageAddr;955 DBGFR3AddrFromFlat(pUVM, &ImageAddr, WINNT_UNION(pThis, &Mte, DllBase));956 uint32_t cbImageBuf = RT_MIN(sizeof(u), RT_MAX(cbImageMte, _4K));957 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &ImageAddr, &u, cbImageBuf);958 if (RT_SUCCESS(rc))959 dbgDiggerWinNtProcessImage(pThis,960 pUVM,961 pszName,962 &ImageAddr,963 cbImageMte,964 &u.au8[0],965 sizeof(u));966 RTStrFree(pszName);967 }968 }969 970 /* next */971 AddrPrev = Addr;972 DBGFR3AddrFromFlat(pUVM, &Addr, WINNT_UNION(pThis, &Mte, InLoadOrderLinks.Flink));973 } while ( Addr.FlatPtr != pThis->KernelMteAddr.FlatPtr974 && Addr.FlatPtr != pThis->PsLoadedModuleListAddr.FlatPtr);975 976 pThis->fValid = true;977 return VINF_SUCCESS;978 }979 980 981 /**982 * @copydoc DBGFOSREG::pfnProbe983 */984 static DECLCALLBACK(bool) dbgDiggerWinNtProbe(PUVM pUVM, void *pvData)985 {986 PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;987 DBGFADDRESS Addr;988 union989 {990 uint8_t au8[8192];991 uint16_t au16[8192/2];992 uint32_t au32[8192/4];993 IMAGE_DOS_HEADER MzHdr;994 RTUTF16 wsz[8192/2];995 } u;996 997 union998 {999 NTMTE32 v32;1000 NTMTE64 v64;1001 } uMte, uMte2, uMte3;1002 1003 /*1004 * Look for the PAGELK section name that seems to be a part of all kernels.1005 * Then try find the module table entry for it. Since it's the first entry1006 * in the PsLoadedModuleList we can easily validate the list head and report1007 * success.1008 *1009 * Note! We ASSUME the section name is 8 byte aligned.1010 */1011 CPUMMODE enmMode = DBGFR3CpuGetMode(pUVM, 0 /*idCpu*/);1012 uint64_t const uStart = enmMode == CPUMMODE_LONG ? UINT64_C(0xffff080000000000) : UINT32_C(0x80001000);1013 uint64_t const uEnd = enmMode == CPUMMODE_LONG ? UINT64_C(0xffffffffffff0000) : UINT32_C(0xffff0000);1014 DBGFADDRESS KernelAddr;1015 for (DBGFR3AddrFromFlat(pUVM, &KernelAddr, uStart);1016 KernelAddr.FlatPtr < uEnd;1017 KernelAddr.FlatPtr += PAGE_SIZE)1018 {1019 bool fNt31 = false;1020 DBGFADDRESS const RetryAddress = KernelAddr;1021 int rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, uEnd - KernelAddr.FlatPtr,1022 8, "PAGELK\0", sizeof("PAGELK\0"), &KernelAddr);1023 if ( rc == VERR_DBGF_MEM_NOT_FOUND1024 && enmMode != CPUMMODE_LONG)1025 {1026 /* NT3.1 didn't have a PAGELK section, so look for _TEXT instead. The1027 following VirtualSize is zero, so check for that too. */1028 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &RetryAddress, uEnd - RetryAddress.FlatPtr,1029 8, "_TEXT\0\0\0\0\0\0", sizeof("_TEXT\0\0\0\0\0\0"), &KernelAddr);1030 fNt31 = true;1031 }1032 if (RT_FAILURE(rc))1033 break;1034 DBGFR3AddrSub(&KernelAddr, KernelAddr.FlatPtr & PAGE_OFFSET_MASK);1035 1036 /* MZ + PE header. */1037 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &KernelAddr, &u, sizeof(u));1038 if ( RT_SUCCESS(rc)1039 && u.MzHdr.e_magic == IMAGE_DOS_SIGNATURE1040 && !(u.MzHdr.e_lfanew & 0x7)1041 && u.MzHdr.e_lfanew >= 0x0801042 && u.MzHdr.e_lfanew <= 0x400) /* W8 is at 0x288*/1043 {1044 if (enmMode != CPUMMODE_LONG)1045 {1046 IMAGE_NT_HEADERS32 const *pHdrs = (IMAGE_NT_HEADERS32 const *)&u.au8[u.MzHdr.e_lfanew];1047 if ( pHdrs->Signature == IMAGE_NT_SIGNATURE1048 && pHdrs->FileHeader.Machine == IMAGE_FILE_MACHINE_I3861049 && pHdrs->FileHeader.SizeOfOptionalHeader == sizeof(pHdrs->OptionalHeader)1050 && pHdrs->FileHeader.NumberOfSections >= 10 /* the kernel has lots */1051 && (pHdrs->FileHeader.Characteristics & (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL)) == IMAGE_FILE_EXECUTABLE_IMAGE1052 && pHdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC1053 && pHdrs->OptionalHeader.NumberOfRvaAndSizes == IMAGE_NUMBEROF_DIRECTORY_ENTRIES1054 )1055 {1056 /* Find the MTE. */1057 RT_ZERO(uMte);1058 uMte.v32.DllBase = KernelAddr.FlatPtr;1059 uMte.v32.EntryPoint = KernelAddr.FlatPtr + pHdrs->OptionalHeader.AddressOfEntryPoint;1060 uMte.v32.SizeOfImage = !fNt31 ? pHdrs->OptionalHeader.SizeOfImage : 0; /* NT 3.1 didn't set the size. */1061 DBGFADDRESS HitAddr;1062 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, uEnd - KernelAddr.FlatPtr,1063 4 /*align*/, &uMte.v32.DllBase, 3 * sizeof(uint32_t), &HitAddr);1064 while (RT_SUCCESS(rc))1065 {1066 /* check the name. */1067 DBGFADDRESS MteAddr = HitAddr;1068 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrSub(&MteAddr, RT_OFFSETOF(NTMTE32, DllBase)),1069 &uMte2.v32, sizeof(uMte2.v32));1070 if ( RT_SUCCESS(rc)1071 && uMte2.v32.DllBase == uMte.v32.DllBase1072 && uMte2.v32.EntryPoint == uMte.v32.EntryPoint1073 && uMte2.v32.SizeOfImage == uMte.v32.SizeOfImage1074 && WINNT32_VALID_ADDRESS(uMte2.v32.InLoadOrderLinks.Flink)1075 && WINNT32_VALID_ADDRESS(uMte2.v32.BaseDllName.Buffer)1076 && WINNT32_VALID_ADDRESS(uMte2.v32.FullDllName.Buffer)1077 && uMte2.v32.BaseDllName.Length <= 1281078 && uMte2.v32.FullDllName.Length <= 2601079 )1080 {1081 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, uMte2.v32.BaseDllName.Buffer),1082 u.wsz, uMte2.v32.BaseDllName.Length);1083 u.wsz[uMte2.v32.BaseDllName.Length / 2] = '\0';1084 if ( RT_SUCCESS(rc)1085 && ( !RTUtf16ICmp(u.wsz, g_wszKernelNames[0])1086 /* || !RTUtf16ICmp(u.wsz, g_wszKernelNames[1]) */1087 )1088 )1089 {1090 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/,1091 DBGFR3AddrFromFlat(pUVM, &Addr, uMte2.v32.InLoadOrderLinks.Blink),1092 &uMte3.v32, RT_SIZEOFMEMB(NTMTE32, InLoadOrderLinks));1093 if ( RT_SUCCESS(rc)1094 && uMte3.v32.InLoadOrderLinks.Flink == MteAddr.FlatPtr1095 && WINNT32_VALID_ADDRESS(uMte3.v32.InLoadOrderLinks.Blink) )1096 {1097 Log(("DigWinNt: MteAddr=%RGv KernelAddr=%RGv SizeOfImage=%x &PsLoadedModuleList=%RGv (32-bit)\n",1098 MteAddr.FlatPtr, KernelAddr.FlatPtr, uMte2.v32.SizeOfImage, Addr.FlatPtr));1099 pThis->KernelAddr = KernelAddr;1100 pThis->KernelMteAddr = MteAddr;1101 pThis->PsLoadedModuleListAddr = Addr;1102 pThis->f32Bit = true;1103 pThis->fNt31 = fNt31;1104 return true;1105 }1106 }1107 else if (RT_SUCCESS(rc))1108 {1109 Log2(("DigWinNt: Wrong module: MteAddr=%RGv ImageAddr=%RGv SizeOfImage=%#x '%ls'\n",1110 MteAddr.FlatPtr, KernelAddr.FlatPtr, uMte2.v32.SizeOfImage, u.wsz));1111 break; /* Not NT kernel */1112 }1113 }1114 1115 /* next */1116 DBGFR3AddrAdd(&HitAddr, 4);1117 if (HitAddr.FlatPtr < uEnd)1118 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &HitAddr, uEnd - HitAddr.FlatPtr,1119 4 /*align*/, &uMte.v32.DllBase, 3 * sizeof(uint32_t), &HitAddr);1120 else1121 rc = VERR_DBGF_MEM_NOT_FOUND;1122 }1123 }1124 }1125 else1126 {1127 IMAGE_NT_HEADERS64 const *pHdrs = (IMAGE_NT_HEADERS64 const *)&u.au8[u.MzHdr.e_lfanew];1128 if ( pHdrs->Signature == IMAGE_NT_SIGNATURE1129 && pHdrs->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD641130 && pHdrs->FileHeader.SizeOfOptionalHeader == sizeof(pHdrs->OptionalHeader)1131 && pHdrs->FileHeader.NumberOfSections >= 10 /* the kernel has lots */1132 && (pHdrs->FileHeader.Characteristics & (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))1133 == IMAGE_FILE_EXECUTABLE_IMAGE1134 && pHdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC1135 && pHdrs->OptionalHeader.NumberOfRvaAndSizes == IMAGE_NUMBEROF_DIRECTORY_ENTRIES1136 )1137 {1138 /* Find the MTE. */1139 RT_ZERO(uMte.v64);1140 uMte.v64.DllBase = KernelAddr.FlatPtr;1141 uMte.v64.EntryPoint = KernelAddr.FlatPtr + pHdrs->OptionalHeader.AddressOfEntryPoint;1142 uMte.v64.SizeOfImage = pHdrs->OptionalHeader.SizeOfImage;1143 DBGFADDRESS ScanAddr;1144 DBGFADDRESS HitAddr;1145 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &ScanAddr, uStart),1146 uEnd - uStart, 8 /*align*/, &uMte.v64.DllBase, 5 * sizeof(uint32_t), &HitAddr);1147 while (RT_SUCCESS(rc))1148 {1149 /* Read the start of the MTE and check some basic members. */1150 DBGFADDRESS MteAddr = HitAddr;1151 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrSub(&MteAddr, RT_OFFSETOF(NTMTE64, DllBase)),1152 &uMte2.v64, sizeof(uMte2.v64));1153 if ( RT_SUCCESS(rc)1154 && uMte2.v64.DllBase == uMte.v64.DllBase1155 && uMte2.v64.EntryPoint == uMte.v64.EntryPoint1156 && uMte2.v64.SizeOfImage == uMte.v64.SizeOfImage1157 && WINNT64_VALID_ADDRESS(uMte2.v64.InLoadOrderLinks.Flink)1158 && WINNT64_VALID_ADDRESS(uMte2.v64.BaseDllName.Buffer)1159 && WINNT64_VALID_ADDRESS(uMte2.v64.FullDllName.Buffer)1160 && uMte2.v64.BaseDllName.Length <= 1281161 && uMte2.v64.FullDllName.Length <= 2601162 )1163 {1164 /* Try read the base name and compare with known NT kernel names. */1165 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, DBGFR3AddrFromFlat(pUVM, &Addr, uMte2.v64.BaseDllName.Buffer),1166 u.wsz, uMte2.v64.BaseDllName.Length);1167 u.wsz[uMte2.v64.BaseDllName.Length / 2] = '\0';1168 if ( RT_SUCCESS(rc)1169 && ( !RTUtf16ICmp(u.wsz, g_wszKernelNames[0])1170 /* || !RTUtf16ICmp(u.wsz, g_wszKernelNames[1]) */1171 )1172 )1173 {1174 /* Read the link entry of the previous entry in the list and check that its1175 forward pointer points at the MTE we've found. */1176 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/,1177 DBGFR3AddrFromFlat(pUVM, &Addr, uMte2.v64.InLoadOrderLinks.Blink),1178 &uMte3.v64, RT_SIZEOFMEMB(NTMTE64, InLoadOrderLinks));1179 if ( RT_SUCCESS(rc)1180 && uMte3.v64.InLoadOrderLinks.Flink == MteAddr.FlatPtr1181 && WINNT64_VALID_ADDRESS(uMte3.v64.InLoadOrderLinks.Blink) )1182 {1183 Log(("DigWinNt: MteAddr=%RGv KernelAddr=%RGv SizeOfImage=%x &PsLoadedModuleList=%RGv (32-bit)\n",1184 MteAddr.FlatPtr, KernelAddr.FlatPtr, uMte2.v64.SizeOfImage, Addr.FlatPtr));1185 pThis->KernelAddr = KernelAddr;1186 pThis->KernelMteAddr = MteAddr;1187 pThis->PsLoadedModuleListAddr = Addr;1188 pThis->f32Bit = false;1189 pThis->fNt31 = false;1190 return true;1191 }1192 }1193 else if (RT_SUCCESS(rc))1194 {1195 Log2(("DigWinNt: Wrong module: MteAddr=%RGv ImageAddr=%RGv SizeOfImage=%#x '%ls'\n",1196 MteAddr.FlatPtr, KernelAddr.FlatPtr, uMte2.v64.SizeOfImage, u.wsz));1197 break; /* Not NT kernel */1198 }1199 }1200 1201 /* next */1202 DBGFR3AddrAdd(&HitAddr, 8);1203 if (HitAddr.FlatPtr < uEnd)1204 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &HitAddr, uEnd - HitAddr.FlatPtr,1205 8 /*align*/, &uMte.v64.DllBase, 3 * sizeof(uint32_t), &HitAddr);1206 else1207 rc = VERR_DBGF_MEM_NOT_FOUND;1208 }1209 }1210 }1211 }1212 }1213 return false;1214 }1215 1216 1217 /**1218 * @copydoc DBGFOSREG::pfnDestruct1219 */1220 static DECLCALLBACK(void) dbgDiggerWinNtDestruct(PUVM pUVM, void *pvData)1221 {1222 RT_NOREF2(pUVM, pvData);1223 }1224 1225 1226 /**1227 * @copydoc DBGFOSREG::pfnConstruct1228 */1229 static DECLCALLBACK(int) dbgDiggerWinNtConstruct(PUVM pUVM, void *pvData)1230 {1231 RT_NOREF1(pUVM);1232 PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;1233 pThis->fValid = false;1234 pThis->f32Bit = false;1235 pThis->enmVer = DBGDIGGERWINNTVER_UNKNOWN;1236 return VINF_SUCCESS;1237 }1238 1239 1240 const DBGFOSREG g_DBGDiggerWinNt =1241 {1242 /* .u32Magic = */ DBGFOSREG_MAGIC,1243 /* .fFlags = */ 0,1244 /* .cbData = */ sizeof(DBGDIGGERWINNT),1245 /* .szName = */ "WinNT",1246 /* .pfnConstruct = */ dbgDiggerWinNtConstruct,1247 /* .pfnDestruct = */ dbgDiggerWinNtDestruct,1248 /* .pfnProbe = */ dbgDiggerWinNtProbe,1249 /* .pfnInit = */ dbgDiggerWinNtInit,1250 /* .pfnRefresh = */ dbgDiggerWinNtRefresh,1251 /* .pfnTerm = */ dbgDiggerWinNtTerm,1252 /* .pfnQueryVersion = */ dbgDiggerWinNtQueryVersion,1253 /* .pfnQueryInterface = */ dbgDiggerWinNtQueryInterface,1254 /* .u32EndMagic = */ DBGFOSREG_MAGIC1255 };1256
Note:
See TracChangeset
for help on using the changeset viewer.