VirtualBox

source: vbox/trunk/src/VBox/Additions/common/testcase/tstPageFusion.cpp@ 37955

Last change on this file since 37955 was 37955, checked in by vboxsync, 13 years ago

Moved VBox/x86.h/mac to iprt/x86.h/mac.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.2 KB
Line 
1/* $Id: tstPageFusion.cpp 37955 2011-07-14 12:23:02Z vboxsync $ */
2/** @file
3 * VBoxService - Guest page sharing testcase
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <iprt/assert.h>
23#include <iprt/asm.h>
24#include <iprt/mem.h>
25#include <iprt/stream.h>
26#include <iprt/string.h>
27#include <iprt/initterm.h>
28#include <VBox/VBoxGuestLib.h>
29#include <iprt/x86.h>
30#include <stdio.h>
31
32
33/*******************************************************************************
34* Global Variables *
35*******************************************************************************/
36
37#ifdef RT_OS_WINDOWS
38#include <Windows.h>
39#include <process.h> /* Needed for file version information. */
40#include <tlhelp32.h>
41#include <psapi.h>
42#include <winternl.h>
43
44#define SystemModuleInformation 11
45
46typedef struct _RTL_PROCESS_MODULE_INFORMATION
47{
48 ULONG Section;
49 PVOID MappedBase;
50 PVOID ImageBase;
51 ULONG ImageSize;
52 ULONG Flags;
53 USHORT LoadOrderIndex;
54 USHORT InitOrderIndex;
55 USHORT LoadCount;
56 USHORT OffsetToFileName;
57 CHAR FullPathName[256];
58} RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION;
59
60typedef struct _RTL_PROCESS_MODULES
61{
62 ULONG NumberOfModules;
63 RTL_PROCESS_MODULE_INFORMATION Modules[1];
64} RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES;
65
66typedef NTSTATUS (WINAPI *PFNZWQUERYSYSTEMINFORMATION)(ULONG, PVOID, ULONG, PULONG);
67static PFNZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
68static HMODULE hNtdll = 0;
69
70#define PAGE_STATE_INVALID 0
71#define PAGE_STATE_SHARED 1
72#define PAGE_STATE_READ_WRITE 2
73#define PAGE_STATE_READ_ONLY 3
74#define PAGE_STATE_NOT_PRESENT 4
75
76/* Page counters. */
77static unsigned cNotPresentPages = 0;
78static unsigned cWritablePages = 0;
79static unsigned cSharedPages = 0;
80static unsigned cPrivatePages = 0;
81
82/**
83 * Registers a new module with the VMM
84 * @param pModule Module ptr
85 */
86void VBoxServicePageSharingCheckModule(MODULEENTRY32 *pModule)
87{
88 DWORD dwModuleSize = pModule->modBaseSize;
89 BYTE *pBaseAddress = pModule->modBaseAddr;
90 bool fFirstLine = true;
91 unsigned uPageState, uLastPageState;
92 bool fLastWritable = false;
93 BYTE *pLastBaseAddress = pBaseAddress;
94
95 uPageState = uLastPageState = PAGE_STATE_INVALID;
96
97 printf("Check module %s base %p size %x\n", pModule->szModule, pBaseAddress, dwModuleSize);
98 do
99 {
100 bool fShared;
101 uint64_t uPageFlags;
102
103#ifdef RT_ARCH_X86
104 int rc = VbglR3PageIsShared((uint32_t)pLastBaseAddress, &fShared, &uPageFlags);
105#else
106 int rc = VbglR3PageIsShared((RTGCPTR)pLastBaseAddress, &fShared, &uPageFlags);
107#endif
108 if (RT_FAILURE(rc))
109 printf("VbglR3PageIsShared %p failed with %d\n", pLastBaseAddress, rc);
110
111 if (RT_SUCCESS(rc))
112 {
113 if (uPageFlags & X86_PTE_P)
114 {
115 if (uPageFlags & X86_PTE_RW)
116 {
117 cWritablePages++;
118 uPageState = PAGE_STATE_READ_WRITE;
119 }
120 else
121 if (fShared)
122 {
123 cSharedPages++;
124 uPageState = PAGE_STATE_SHARED;
125 }
126 else
127 {
128 cPrivatePages++;
129 uPageState = PAGE_STATE_READ_ONLY;
130 }
131 }
132 else
133 {
134 cNotPresentPages++;
135 uPageState = PAGE_STATE_NOT_PRESENT;
136 }
137
138 if ( !fFirstLine
139 && uPageState != uLastPageState)
140 {
141 printf("0x%p\n", pLastBaseAddress + 0xfff);
142 }
143
144 if (uPageState != uLastPageState)
145 {
146 switch (uPageState)
147 {
148 case PAGE_STATE_READ_WRITE:
149 printf("%s RW 0x%p - ", pModule->szModule, pBaseAddress);
150 break;
151 case PAGE_STATE_SHARED:
152 printf("%s SHARED 0x%p - ", pModule->szModule, pBaseAddress);
153 break;
154 case PAGE_STATE_READ_ONLY:
155 printf("%s PRIV 0x%p - ", pModule->szModule, pBaseAddress);
156 break;
157 case PAGE_STATE_NOT_PRESENT:
158 printf("%s NP 0x%p - ", pModule->szModule, pBaseAddress);
159 break;
160 }
161
162 fFirstLine = false;
163 }
164 uLastPageState = uPageState;
165 }
166 else
167 if (!fFirstLine)
168 {
169 printf("0x%p\n", pLastBaseAddress + 0xfff);
170 fFirstLine = true;
171 }
172
173 if (dwModuleSize > PAGE_SIZE)
174 dwModuleSize -= PAGE_SIZE;
175 else
176 dwModuleSize = 0;
177
178 pLastBaseAddress = pBaseAddress;
179 pBaseAddress += PAGE_SIZE;
180 }
181 while (dwModuleSize);
182
183 printf("0x%p\n", pLastBaseAddress + 0xfff);
184 return;
185}
186
187/**
188 * Inspect all loaded modules for the specified process
189 * @param dwProcessId Process id
190 */
191void VBoxServicePageSharingInspectModules(DWORD dwProcessId)
192{
193 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
194 if (hSnapshot == INVALID_HANDLE_VALUE)
195 {
196 printf("VBoxServicePageSharingInspectModules: CreateToolhelp32Snapshot failed with %d\n", GetLastError());
197 return;
198 }
199
200 printf("VBoxServicePageSharingInspectModules\n");
201
202 MODULEENTRY32 ModuleInfo;
203 BOOL bRet;
204
205 ModuleInfo.dwSize = sizeof(ModuleInfo);
206 bRet = Module32First(hSnapshot, &ModuleInfo);
207 do
208 {
209 /** todo when changing this make sure VBoxService.exe is excluded! */
210 char *pszDot = strrchr(ModuleInfo.szModule, '.');
211 if ( pszDot
212 && (pszDot[1] == 'e' || pszDot[1] == 'E'))
213 continue; /* ignore executables for now. */
214
215 VBoxServicePageSharingCheckModule(&ModuleInfo);
216 }
217 while (Module32Next(hSnapshot, &ModuleInfo));
218
219 CloseHandle(hSnapshot);
220}
221
222/**
223 * Inspect all running processes for executables and dlls that might be worth sharing
224 * with other VMs.
225 *
226 */
227void VBoxServicePageSharingInspectGuest()
228{
229 VBoxServicePageSharingInspectModules(GetCurrentProcessId());
230
231 printf("\n\nUSER RESULTS\n");
232 printf("cNotPresentPages = %d\n", cNotPresentPages);
233 printf("cWritablePages = %d\n", cWritablePages);
234 printf("cPrivatePages = %d\n", cPrivatePages);
235 printf("cSharedPages = %d\n", cSharedPages);
236
237 cNotPresentPages = 0;
238 cWritablePages = 0;
239 cPrivatePages = 0;
240 cSharedPages = 0;
241
242 /* Check all loaded kernel modules. */
243 if (ZwQuerySystemInformation)
244 {
245 ULONG cbBuffer = 0;
246 PVOID pBuffer = NULL;
247 PRTL_PROCESS_MODULES pSystemModules;
248
249 NTSTATUS ret = ZwQuerySystemInformation(SystemModuleInformation, (PVOID)&cbBuffer, 0, &cbBuffer);
250 if (!cbBuffer)
251 {
252 printf("ZwQuerySystemInformation returned length 0\n");
253 goto skipkernelmodules;
254 }
255
256 pBuffer = RTMemAllocZ(cbBuffer);
257 if (!pBuffer)
258 goto skipkernelmodules;
259
260 ret = ZwQuerySystemInformation(SystemModuleInformation, pBuffer, cbBuffer, &cbBuffer);
261 if (ret != 0)
262 {
263 printf("ZwQuerySystemInformation returned %x (1)\n", ret);
264 goto skipkernelmodules;
265 }
266
267 pSystemModules = (PRTL_PROCESS_MODULES)pBuffer;
268 for (unsigned i = 0; i < pSystemModules->NumberOfModules; i++)
269 {
270 /* User-mode modules seem to have no flags set; skip them as we detected them above. */
271 if (pSystemModules->Modules[i].Flags == 0)
272 continue;
273
274 /* New module; register it. */
275 char szFullFilePath[512];
276 MODULEENTRY32 ModuleInfo;
277
278 strcpy(ModuleInfo.szModule, &pSystemModules->Modules[i].FullPathName[pSystemModules->Modules[i].OffsetToFileName]);
279 GetSystemDirectoryA(szFullFilePath, sizeof(szFullFilePath));
280
281 /* skip \Systemroot\system32 */
282 char *lpPath = strchr(&pSystemModules->Modules[i].FullPathName[1], '\\');
283 if (!lpPath)
284 {
285 printf("Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName);
286 break;
287 }
288
289 lpPath = strchr(lpPath+1, '\\');
290 if (!lpPath)
291 {
292 printf("Unexpected kernel module name %s\n", pSystemModules->Modules[i].FullPathName);
293 break;
294 }
295
296 strcat(szFullFilePath, lpPath);
297 strcpy(ModuleInfo.szExePath, szFullFilePath);
298 ModuleInfo.modBaseAddr = (BYTE *)pSystemModules->Modules[i].ImageBase;
299 ModuleInfo.modBaseSize = pSystemModules->Modules[i].ImageSize;
300
301 VBoxServicePageSharingCheckModule(&ModuleInfo);
302 }
303skipkernelmodules:
304 if (pBuffer)
305 RTMemFree(pBuffer);
306 }
307 printf("\n\nKERNEL RESULTS\n");
308 printf("cNotPresentPages = %d\n", cNotPresentPages);
309 printf("cWritablePages = %d\n", cWritablePages);
310 printf("cPrivatePages = %d\n", cPrivatePages);
311 printf("cSharedPages = %d\n", cSharedPages);
312}
313#else
314void VBoxServicePageSharingInspectGuest()
315{
316 /* @todo other platforms */
317}
318#endif
319
320
321/** @copydoc VBOXSERVICE::pfnInit */
322static DECLCALLBACK(int) VBoxServicePageSharingInit(void)
323{
324 printf("VBoxServicePageSharingInit\n");
325
326#ifdef RT_OS_WINDOWS
327 hNtdll = LoadLibrary("ntdll.dll");
328
329 if (hNtdll)
330 ZwQuerySystemInformation = (PFNZWQUERYSYSTEMINFORMATION)GetProcAddress(hNtdll, "ZwQuerySystemInformation");
331#endif
332
333 /* @todo report system name and version */
334 /* Never fail here. */
335 return VINF_SUCCESS;
336}
337
338static DECLCALLBACK(void) VBoxServicePageSharingTerm(void)
339{
340 printf("VBoxServicePageSharingTerm\n");
341
342#ifdef RT_OS_WINDOWS
343 if (hNtdll)
344 FreeLibrary(hNtdll);
345#endif
346 return;
347}
348
349int main(int argc, char **argv)
350{
351 int rc = VINF_SUCCESS;
352 /*
353 * Init globals and such.
354 */
355 RTR3Init();
356
357 /*
358 * Connect to the kernel part before daemonizing so we can fail
359 * and complain if there is some kind of problem. We need to initialize
360 * the guest lib *before* we do the pre-init just in case one of services
361 * needs do to some initial stuff with it.
362 */
363 printf("Calling VbgR3Init()\n");
364 rc = VbglR3Init();
365 if (RT_FAILURE(rc))
366 {
367 printf("VbglR3Init failed with rc=%Rrc.\n", rc);
368 return -1;
369 }
370 VBoxServicePageSharingInit();
371
372 VBoxServicePageSharingInspectGuest();
373
374 VBoxServicePageSharingTerm();
375 return 0;
376}
377
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette