Changeset 29952 in vbox
- Timestamp:
- Jun 1, 2010 3:02:07 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServicePageSharing.cpp
r29939 r29952 45 45 #include <tlhelp32.h> 46 46 #include <psapi.h> 47 #include <winternl.h> 47 48 48 49 typedef struct … … 54 55 } KNOWN_MODULE, *PKNOWN_MODULE; 55 56 57 #define SystemModuleInformation 11 58 59 typedef struct _RTL_PROCESS_MODULE_INFORMATION 60 { 61 ULONG Section; 62 PVOID MappedBase; 63 PVOID ImageBase; 64 ULONG ImageSize; 65 ULONG Flags; 66 USHORT LoadOrderIndex; 67 USHORT InitOrderIndex; 68 USHORT LoadCount; 69 USHORT OffsetToFileName; 70 CHAR FullPathName[256]; 71 } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 72 73 typedef struct _RTL_PROCESS_MODULES 74 { 75 ULONG NumberOfModules; 76 RTL_PROCESS_MODULE_INFORMATION Modules[1]; 77 } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 78 79 typedef NTSTATUS (WINAPI *PFNZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG); 80 static PFNZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL; 81 static HMODULE hNtdll = 0; 82 83 56 84 static DECLCALLBACK(int) VBoxServicePageSharingEmptyTreeCallback(PAVLPVNODECORE pNode, void *); 57 85 … … 60 88 /** 61 89 * Registers a new module with the VMM 62 * @param pModule Module ptr 90 * @param pModule Module ptr 91 * @param fValidateMemory Validate/touch memory pages or not 63 92 */ 64 void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule )93 void VBoxServicePageSharingRegisterModule(PKNOWN_MODULE pModule, bool fValidateMemory) 65 94 { 66 95 VMMDEVSHAREDREGIONDESC aRegions[VMMDEVSHAREDREGIONDESC_MAX]; … … 128 157 129 158 unsigned idxRegion = 0; 130 do 131 { 132 MEMORY_BASIC_INFORMATION MemInfo; 133 134 SIZE_T ret = VirtualQuery(pBaseAddress, &MemInfo, sizeof(MemInfo)); 135 Assert(ret); 136 if (!ret) 159 160 if (fValidateMemory) 161 { 162 do 137 163 { 138 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VirtualQueryEx failed with %d\n", GetLastError()); 139 break; 140 } 141 142 if ( MemInfo.State == MEM_COMMIT 143 && MemInfo.Type == MEM_IMAGE) 144 { 145 switch (MemInfo.Protect) 164 MEMORY_BASIC_INFORMATION MemInfo; 165 166 SIZE_T ret = VirtualQuery(pBaseAddress, &MemInfo, sizeof(MemInfo)); 167 Assert(ret); 168 if (!ret) 146 169 { 147 case PAGE_EXECUTE: 148 case PAGE_EXECUTE_READ: 149 case PAGE_READONLY: 150 { 151 char *pRegion = (char *)MemInfo.BaseAddress; 152 153 /* Skip the first region as it only contains the image file header. */ 154 if (pRegion != (char *)pModule->Info.modBaseAddr) 155 { 156 /* Touch all pages. */ 157 while (pRegion < (char *)MemInfo.BaseAddress + MemInfo.RegionSize) 158 { 159 /* Try to trick the optimizer to leave the page touching code in place. */ 160 ASMProbeReadByte(pRegion); 161 pRegion += PAGE_SIZE; 162 } 163 } 164 aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)MemInfo.BaseAddress; 165 aRegions[idxRegion].cbRegion = MemInfo.RegionSize; 166 idxRegion++; 167 170 VBoxServiceVerbose(3, "VBoxServicePageSharingRegisterModule: VirtualQueryEx failed with %d\n", GetLastError()); 168 171 break; 169 172 } 170 173 171 default: 172 break; /* ignore */ 174 if ( MemInfo.State == MEM_COMMIT 175 && MemInfo.Type == MEM_IMAGE) 176 { 177 switch (MemInfo.Protect) 178 { 179 case PAGE_EXECUTE: 180 case PAGE_EXECUTE_READ: 181 case PAGE_READONLY: 182 { 183 char *pRegion = (char *)MemInfo.BaseAddress; 184 185 /* Skip the first region as it only contains the image file header. */ 186 if (pRegion != (char *)pModule->Info.modBaseAddr) 187 { 188 /* Touch all pages. */ 189 while (pRegion < (char *)MemInfo.BaseAddress + MemInfo.RegionSize) 190 { 191 /* Try to trick the optimizer to leave the page touching code in place. */ 192 ASMProbeReadByte(pRegion); 193 pRegion += PAGE_SIZE; 194 } 195 } 196 aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)MemInfo.BaseAddress; 197 aRegions[idxRegion].cbRegion = MemInfo.RegionSize; 198 idxRegion++; 199 200 break; 201 } 202 203 default: 204 break; /* ignore */ 205 } 173 206 } 207 208 pBaseAddress = (BYTE *)MemInfo.BaseAddress + MemInfo.RegionSize; 209 if (dwModuleSize > MemInfo.RegionSize) 210 { 211 dwModuleSize -= MemInfo.RegionSize; 212 } 213 else 214 { 215 dwModuleSize = 0; 216 break; 217 } 218 219 if (idxRegion >= RT_ELEMENTS(aRegions)) 220 break; /* out of room */ 174 221 } 175 176 pBaseAddress = (BYTE *)MemInfo.BaseAddress + MemInfo.RegionSize; 177 if (dwModuleSize > MemInfo.RegionSize) 178 { 179 dwModuleSize -= MemInfo.RegionSize; 180 } 181 else 182 { 183 dwModuleSize = 0; 184 break; 185 } 186 187 if (idxRegion >= RT_ELEMENTS(aRegions)) 188 break; /* out of room */ 189 } 190 while (dwModuleSize); 191 222 while (dwModuleSize); 223 } 224 else 225 { 226 /* We can't probe kernel memory ranges, so pretend it's one big region. */ 227 aRegions[idxRegion].GCRegionAddr = (RTGCPTR64)pBaseAddress; 228 aRegions[idxRegion].cbRegion = dwModuleSize; 229 idxRegion++; 230 } 192 231 VBoxServiceVerbose(3, "VbglR3RegisterSharedModule %s %s base=%p size=%x cregions=%d\n", pModule->Info.szModule, pModule->szFileVersion, pModule->Info.modBaseAddr, pModule->Info.modBaseSize, idxRegion); 193 232 int rc = VbglR3RegisterSharedModule(pModule->Info.szModule, pModule->szFileVersion, (RTGCPTR64)pModule->Info.modBaseAddr, … … 259 298 pModule->hModule = LoadLibraryEx(ModuleInfo.szExePath, 0, DONT_RESOLVE_DLL_REFERENCES); 260 299 if (pModule->hModule) 261 VBoxServicePageSharingRegisterModule(pModule); 300 VBoxServicePageSharingRegisterModule(pModule, true /* validate pages */); 301 302 VBoxServiceVerbose(3, "\n\n MODULE NAME: %s", ModuleInfo.szModule ); 303 VBoxServiceVerbose(3, "\n executable = %s", ModuleInfo.szExePath ); 304 VBoxServiceVerbose(3, "\n process ID = 0x%08X", ModuleInfo.th32ProcessID ); 305 VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) ModuleInfo.modBaseAddr ); 306 VBoxServiceVerbose(3, "\n base size = %d", ModuleInfo.modBaseSize ); 262 307 263 308 pRec = &pModule->Core; … … 265 310 bool ret = RTAvlPVInsert(ppNewTree, pRec); 266 311 Assert(ret); NOREF(ret); 267 268 VBoxServiceVerbose(3, "\n\n MODULE NAME: %s", ModuleInfo.szModule );269 VBoxServiceVerbose(3, "\n executable = %s", ModuleInfo.szExePath );270 VBoxServiceVerbose(3, "\n process ID = 0x%08X", ModuleInfo.th32ProcessID );271 VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) ModuleInfo.modBaseAddr );272 VBoxServiceVerbose(3, "\n base size = %d", ModuleInfo.modBaseSize );273 312 } 274 313 } … … 315 354 CloseHandle(hSnapshot); 316 355 356 #if 0 357 /* Check all loaded kernel modules. */ 358 ULONG cbBuffer; 359 PVOID pBuffer = NULL; 360 PRTL_PROCESS_MODULES pSystemModules; 361 362 NTSTATUS ret = ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&cbBuffer, 0, &cbBuffer); 363 if (ret != STATUS_SUCCESS) 364 goto skipkernelmodules; 365 366 pBuffer = malloc(cbBuffer); 367 if (!pBuffer) 368 goto skipkernelmodules; 369 370 ret = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, cbBuffer, &cbBuffer); 371 if (ret != STATUS_SUCCESS) 372 goto skipkernelmodules; 373 374 pSystemModules = (PRTL_PROCESS_MODULES)pBuffer; 375 for (unsigned i = 0; i < pSystemModules->NumberOfModules; i++) 376 { 377 /* Found it before? */ 378 PAVLPVNODECORE pRec = RTAvlPVGet(&pNewTree, pSystemModules->Modules[i].ImageBase); 379 if (!pRec) 380 { 381 pRec = RTAvlPVRemove(&pKnownModuleTree, pSystemModules->Modules[i].ImageBase); 382 if (!pRec) 383 { 384 /* New module; register it. */ 385 char szFullFilePath[512]; 386 PKNOWN_MODULE pModule = (PKNOWN_MODULE)RTMemAllocZ(sizeof(*pModule)); 387 Assert(pModule); 388 if (!pModule) 389 break; 390 391 strcpy(pModule->Info.szModule, &pSystemModules->Modules[i].FullPathName[pSystemModules->Modules[i].OffsetToFileName]); 392 GetSystemDirectoryA(szFullFilePath, sizeof(szFullFilePath)); 393 394 /* skip \Systemroot\system32 */ 395 char *lpPath = strstr(pSystemModules->Modules[i].FullPathName, "\\system32"); 396 if (!lpPath) 397 { 398 VBoxServiceVerbose(1, "Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName); 399 RTMemFree(pModule); 400 break; 401 } 402 403 lpPath = strchr(lpPath+1, '\\'); 404 if (!lpPath) 405 { 406 VBoxServiceVerbose(1, "Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName); 407 RTMemFree(pModule); 408 break; 409 } 410 411 strcat(szFullFilePath, lpPath); 412 strcpy(pModule->Info.szExePath, szFullFilePath); 413 pModule->Info.modBaseAddr = (BYTE *)pSystemModules->Modules[i].ImageBase; 414 pModule->Info.modBaseSize = pSystemModules->Modules[i].ImageSize; 415 416 pModule->Core.Key = pSystemModules->Modules[i].ImageBase; 417 VBoxServicePageSharingRegisterModule(pModule, false /* don't check memory pages */); 418 419 VBoxServiceVerbose(3, "\n\n KERNEL MODULE NAME: %s", pModule->Info.szModule ); 420 VBoxServiceVerbose(3, "\n executable = %s", pModule->Info.szExePath ); 421 VBoxServiceVerbose(3, "\n base address = 0x%08X", (DWORD) pModule->Info.modBaseAddr ); 422 VBoxServiceVerbose(3, "\n base size = %d", pModule->Info.modBaseSize ); 423 424 pRec = &pModule->Core; 425 } 426 bool ret = RTAvlPVInsert(&pNewTree, pRec); 427 Assert(ret); NOREF(ret); 428 } 429 } 430 431 skipkernelmodules: 432 if (pBuffer) 433 free(pBuffer); 434 #endif 435 317 436 /* Delete leftover modules in the old tree. */ 318 437 RTAvlPVDestroy(&pKnownModuleTree, VBoxServicePageSharingEmptyTreeCallback, NULL); … … 382 501 int rc = RTSemEventMultiCreate(&g_PageSharingEvent); 383 502 AssertRCReturn(rc, rc); 503 504 #if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4) 505 hNtdll = LoadLibrary("ntdll.dll"); 506 507 if (hNtdll) 508 ZwQuerySystemInformation = (PFNZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "ZwQuerySystemInformation"); 509 #endif 384 510 385 511 /* @todo report system name and version */ … … 454 580 { 455 581 VBoxServiceVerbose(3, "VBoxServicePageSharingTerm\n"); 582 583 #if defined(RT_OS_WINDOWS) && !defined(TARGET_NT4) 584 if (hNtdll) 585 FreeLibrary(hNtdll); 586 #endif 456 587 return; 457 588 }
Note:
See TracChangeset
for help on using the changeset viewer.