VirtualBox

source: vbox/trunk/src/VBox/VMM/PGMDbg.cpp@ 19141

Last change on this file since 19141 was 18927, checked in by vboxsync, 16 years ago

Big step to separate VMM data structures for guest SMP. (pgm, em)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 20.9 KB
Line 
1/* $Id: PGMDbg.cpp 18927 2009-04-16 11:41:38Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor - Debugger & Debugging APIs.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22/*******************************************************************************
23* Header Files *
24*******************************************************************************/
25#define LOG_GROUP LOG_GROUP_PGM
26#include <VBox/pgm.h>
27#include <VBox/stam.h>
28#include "PGMInternal.h"
29#include <VBox/vm.h>
30#include <iprt/assert.h>
31#include <iprt/asm.h>
32#include <iprt/string.h>
33#include <VBox/log.h>
34#include <VBox/param.h>
35#include <VBox/err.h>
36
37/** The max needle size that we will bother searching for
38 * This must not be more than half a page! */
39#define MAX_NEEDLE_SIZE 256
40
41
42/**
43 * Converts a R3 pointer to a GC physical address.
44 *
45 * Only for the debugger.
46 *
47 * @returns VBox status code.
48 * @retval VINF_SUCCESS on success, *pGCPhys is set.
49 * @retval VERR_INVALID_POINTER if the pointer is not within the GC physical memory.
50 *
51 * @param pVM The VM handle.
52 * @param R3Ptr The R3 pointer to convert.
53 * @param pGCPhys Where to store the GC physical address on success.
54 */
55VMMR3DECL(int) PGMR3DbgR3Ptr2GCPhys(PVM pVM, RTR3PTR R3Ptr, PRTGCPHYS pGCPhys)
56{
57 *pGCPhys = NIL_RTGCPHYS;
58 return VERR_NOT_IMPLEMENTED;
59}
60
61
62/**
63 * Converts a R3 pointer to a HC physical address.
64 *
65 * Only for the debugger.
66 *
67 * @returns VBox status code.
68 * @retval VINF_SUCCESS on success, *pHCPhys is set.
69 * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid GC physical page but has no physical backing.
70 * @retval VERR_INVALID_POINTER if the pointer is not within the GC physical memory.
71 *
72 * @param pVM The VM handle.
73 * @param R3Ptr The R3 pointer to convert.
74 * @param pHCPhys Where to store the HC physical address on success.
75 */
76VMMR3DECL(int) PGMR3DbgR3Ptr2HCPhys(PVM pVM, RTR3PTR R3Ptr, PRTHCPHYS pHCPhys)
77{
78 *pHCPhys = NIL_RTHCPHYS;
79 return VERR_NOT_IMPLEMENTED;
80}
81
82
83/**
84 * Converts a HC physical address to a GC physical address.
85 *
86 * Only for the debugger.
87 *
88 * @returns VBox status code
89 * @retval VINF_SUCCESS on success, *pGCPhys is set.
90 * @retval VERR_INVALID_POINTER if the HC physical address is not within the GC physical memory.
91 *
92 * @param pVM The VM handle.
93 * @param HCPhys The HC physical address to convert.
94 * @param pGCPhys Where to store the GC physical address on success.
95 */
96VMMR3DECL(int) PGMR3DbgHCPhys2GCPhys(PVM pVM, RTHCPHYS HCPhys, PRTGCPHYS pGCPhys)
97{
98 /*
99 * Validate and adjust the input a bit.
100 */
101 if (HCPhys == NIL_RTHCPHYS)
102 return VERR_INVALID_POINTER;
103 unsigned off = HCPhys & PAGE_OFFSET_MASK;
104 HCPhys &= X86_PTE_PAE_PG_MASK;
105 if (HCPhys == 0)
106 return VERR_INVALID_POINTER;
107
108 for (PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
109 pRam;
110 pRam = pRam->CTX_SUFF(pNext))
111 {
112 uint32_t iPage = pRam->cb >> PAGE_SHIFT;
113 while (iPage-- > 0)
114 if (PGM_PAGE_GET_HCPHYS(&pRam->aPages[iPage]) == HCPhys)
115 {
116 *pGCPhys = pRam->GCPhys + (iPage << PAGE_SHIFT) + off;
117 return VINF_SUCCESS;
118 }
119 }
120 return VERR_INVALID_POINTER;
121}
122
123
124/**
125 * Read physical memory API for the debugger, similar to
126 * PGMPhysSimpleReadGCPhys.
127 *
128 * @returns VBox status code.
129 *
130 * @param pVM The VM handle.
131 * @param pvDst Where to store what's read.
132 * @param GCPhysDst Where to start reading from.
133 * @param cb The number of bytes to attempt reading.
134 * @param fFlags Flags, MBZ.
135 * @param pcbRead For store the actual number of bytes read, pass NULL if
136 * partial reads are unwanted.
137 */
138VMMR3DECL(int) PGMR3DbgReadGCPhys(PVM pVM, void *pvDst, RTGCPHYS GCPhysSrc, size_t cb, uint32_t fFlags, size_t *pcbRead)
139{
140 /* validate */
141 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
142 AssertReturn(pVM, VERR_INVALID_PARAMETER);
143
144 /* try simple first. */
145 int rc = PGMPhysSimpleReadGCPhys(pVM, pvDst, GCPhysSrc, cb);
146 if (RT_SUCCESS(rc) || !pcbRead)
147 return rc;
148
149 /* partial read that failed, chop it up in pages. */
150 *pcbRead = 0;
151 size_t const cbReq = cb;
152 rc = VINF_SUCCESS;
153 while (cb > 0)
154 {
155 size_t cbChunk = PAGE_SIZE;
156 cbChunk -= GCPhysSrc & PAGE_OFFSET_MASK;
157 if (cbChunk > cb)
158 cbChunk = cb;
159
160 rc = PGMPhysSimpleReadGCPhys(pVM, pvDst, GCPhysSrc, cbChunk);
161
162 /* advance */
163 if (RT_FAILURE(rc))
164 break;
165 *pcbRead += cbChunk;
166 cb -= cbChunk;
167 GCPhysSrc += cbChunk;
168 pvDst = (uint8_t *)pvDst + cbChunk;
169 }
170
171 return *pcbRead && RT_FAILURE(rc) ? -rc : rc;
172}
173
174
175/**
176 * Write physical memory API for the debugger, similar to
177 * PGMPhysSimpleWriteGCPhys.
178 *
179 * @returns VBox status code.
180 *
181 * @param pVM The VM handle.
182 * @param GCPhysDst Where to start writing.
183 * @param pvSrc What to write.
184 * @param cb The number of bytes to attempt writing.
185 * @param fFlags Flags, MBZ.
186 * @param pcbWritten For store the actual number of bytes written, pass NULL
187 * if partial writes are unwanted.
188 */
189VMMR3DECL(int) PGMR3DbgWriteGCPhys(PVM pVM, RTGCPHYS GCPhysDst, const void *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten)
190{
191 /* validate */
192 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
193 AssertReturn(pVM, VERR_INVALID_PARAMETER);
194
195 /* try simple first. */
196 int rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysDst, pvSrc, cb);
197 if (RT_SUCCESS(rc) || !pcbWritten)
198 return rc;
199
200 /* partial write that failed, chop it up in pages. */
201 *pcbWritten = 0;
202 rc = VINF_SUCCESS;
203 while (cb > 0)
204 {
205 size_t cbChunk = PAGE_SIZE;
206 cbChunk -= GCPhysDst & PAGE_OFFSET_MASK;
207 if (cbChunk > cb)
208 cbChunk = cb;
209
210 rc = PGMPhysSimpleWriteGCPhys(pVM, GCPhysDst, pvSrc, cbChunk);
211
212 /* advance */
213 if (RT_FAILURE(rc))
214 break;
215 *pcbWritten += cbChunk;
216 cb -= cbChunk;
217 GCPhysDst += cbChunk;
218 pvSrc = (uint8_t const *)pvSrc + cbChunk;
219 }
220
221 return *pcbWritten && RT_FAILURE(rc) ? -rc : rc;
222
223}
224
225
226/**
227 * Read virtual memory API for the debugger, similar to PGMPhysSimpleReadGCPtr.
228 *
229 * @returns VBox status code.
230 *
231 * @param pVM The VM handle.
232 * @param pvDst Where to store what's read.
233 * @param GCPtrDst Where to start reading from.
234 * @param cb The number of bytes to attempt reading.
235 * @param fFlags Flags, MBZ.
236 * @param pcbRead For store the actual number of bytes read, pass NULL if
237 * partial reads are unwanted.
238 */
239VMMR3DECL(int) PGMR3DbgReadGCPtr(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb, uint32_t fFlags, size_t *pcbRead)
240{
241 /* validate */
242 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
243 AssertReturn(pVM, VERR_INVALID_PARAMETER);
244
245 /* @todo SMP support! */
246 PVMCPU pVCpu = &pVM->aCpus[0];
247
248/** @todo deal with HMA */
249 /* try simple first. */
250 int rc = PGMPhysSimpleReadGCPtr(pVCpu, pvDst, GCPtrSrc, cb);
251 if (RT_SUCCESS(rc) || !pcbRead)
252 return rc;
253
254 /* partial read that failed, chop it up in pages. */
255 *pcbRead = 0;
256 rc = VINF_SUCCESS;
257 while (cb > 0)
258 {
259 size_t cbChunk = PAGE_SIZE;
260 cbChunk -= GCPtrSrc & PAGE_OFFSET_MASK;
261 if (cbChunk > cb)
262 cbChunk = cb;
263
264 rc = PGMPhysSimpleReadGCPtr(pVCpu, pvDst, GCPtrSrc, cbChunk);
265
266 /* advance */
267 if (RT_FAILURE(rc))
268 break;
269 *pcbRead += cbChunk;
270 cb -= cbChunk;
271 GCPtrSrc += cbChunk;
272 pvDst = (uint8_t *)pvDst + cbChunk;
273 }
274
275 return *pcbRead && RT_FAILURE(rc) ? -rc : rc;
276
277}
278
279
280/**
281 * Write virtual memory API for the debugger, similar to
282 * PGMPhysSimpleWriteGCPtr.
283 *
284 * @returns VBox status code.
285 *
286 * @param pVM The VM handle.
287 * @param GCPtrDst Where to start writing.
288 * @param pvSrc What to write.
289 * @param cb The number of bytes to attempt writing.
290 * @param fFlags Flags, MBZ.
291 * @param pcbWritten For store the actual number of bytes written, pass NULL
292 * if partial writes are unwanted.
293 */
294VMMR3DECL(int) PGMR3DbgWriteGCPtr(PVM pVM, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten)
295{
296 /* validate */
297 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
298 AssertReturn(pVM, VERR_INVALID_PARAMETER);
299
300 /* @todo SMP support! */
301 PVMCPU pVCpu = &pVM->aCpus[0];
302
303/** @todo deal with HMA */
304 /* try simple first. */
305 int rc = PGMPhysSimpleWriteGCPtr(pVCpu, GCPtrDst, pvSrc, cb);
306 if (RT_SUCCESS(rc) || !pcbWritten)
307 return rc;
308
309 /* partial write that failed, chop it up in pages. */
310 *pcbWritten = 0;
311 rc = VINF_SUCCESS;
312 while (cb > 0)
313 {
314 size_t cbChunk = PAGE_SIZE;
315 cbChunk -= GCPtrDst & PAGE_OFFSET_MASK;
316 if (cbChunk > cb)
317 cbChunk = cb;
318
319 rc = PGMPhysSimpleWriteGCPtr(pVCpu, GCPtrDst, pvSrc, cbChunk);
320
321 /* advance */
322 if (RT_FAILURE(rc))
323 break;
324 *pcbWritten += cbChunk;
325 cb -= cbChunk;
326 GCPtrDst += cbChunk;
327 pvSrc = (uint8_t const *)pvSrc + cbChunk;
328 }
329
330 return *pcbWritten && RT_FAILURE(rc) ? -rc : rc;
331
332}
333
334
335
336/**
337 * Scans a page for a byte string, keeping track of potential
338 * cross page matches.
339 *
340 * @returns true and *poff on match.
341 * false on mismatch.
342 * @param pbPage Pointer to the current page.
343 * @param poff Input: The offset into the page.
344 * Output: The page offset of the match on success.
345 * @param cb The number of bytes to search, starting of *poff.
346 * @param pabNeedle The byte string to search for.
347 * @param cbNeedle The length of the byte string.
348 * @param pabPrev The buffer that keeps track of a partial match that we
349 * bring over from the previous page. This buffer must be
350 * at least cbNeedle - 1 big.
351 * @param pcbPrev Input: The number of partial matching bytes from the previous page.
352 * Output: The number of partial matching bytes from this page.
353 * Initialize to 0 before the first call to this function.
354 */
355static bool pgmR3DbgScanPage(const uint8_t *pbPage, int32_t *poff, uint32_t cb,
356 const uint8_t *pabNeedle, size_t cbNeedle,
357 uint8_t *pabPrev, size_t *pcbPrev)
358{
359 /*
360 * Try complete any partial match from the previous page.
361 */
362 if (*pcbPrev > 0)
363 {
364 size_t cbPrev = *pcbPrev;
365 Assert(!*poff);
366 Assert(cbPrev < cbNeedle);
367 if (!memcmp(pbPage, pabNeedle + cbPrev, cbNeedle - cbPrev))
368 {
369 if (cbNeedle - cbPrev > cb)
370 return false;
371 *poff = -(int32_t)cbPrev;
372 return true;
373 }
374
375 /* check out the remainder of the previous page. */
376 const uint8_t *pb = pabPrev;
377 while (cbPrev-- > 0)
378 {
379 pb = (const uint8_t *)memchr(pb + 1, *pabNeedle, cbPrev);
380 if (!pb)
381 break;
382 cbPrev = *pcbPrev - (pb - pabPrev);
383 if ( !memcmp(pb + 1, &pabNeedle[1], cbPrev - 1)
384 && !memcmp(pbPage, pabNeedle + cbPrev, cbNeedle - cbPrev))
385 {
386 if (cbNeedle - cbPrev > cb)
387 return false;
388 *poff = -(int32_t)cbPrev;
389 return true;
390 }
391 }
392
393 *pcbPrev = 0;
394 }
395
396 /*
397 * Match the body of the page.
398 */
399 const uint8_t *pb = pbPage + *poff;
400 const uint8_t *pbEnd = pb + cb;
401 for (;;)
402 {
403 pb = (const uint8_t *)memchr(pb, *pabNeedle, cb);
404 if (!pb)
405 break;
406 cb = pbEnd - pb;
407 if (cb >= cbNeedle)
408 {
409 /* match? */
410 if (!memcmp(pb + 1, &pabNeedle[1], cbNeedle - 1))
411 {
412 *poff = pb - pbPage;
413 return true;
414 }
415 }
416 else
417 {
418 /* paritial match at the end of the page? */
419 if (!memcmp(pb + 1, &pabNeedle[1], cb - 1))
420 {
421 /* We're copying one byte more that we really need here, but wtf. */
422 memcpy(pabPrev, pb, cb);
423 *pcbPrev = cb;
424 return false;
425 }
426 }
427
428 /* no match, skip a byte ahead. */
429 if (cb <= 1)
430 break;
431 pb++;
432 cb--;
433 }
434
435 return false;
436}
437
438
439/**
440 * Scans guest physical memory for a byte string.
441 *
442 * @returns VBox status codes:
443 * @retval VINF_SUCCESS and *pGCPtrHit on success.
444 * @retval VERR_DBGF_MEM_NOT_FOUND if not found.
445 * @retval VERR_INVALID_POINTER if any of the pointer arguments are invalid.
446 * @retval VERR_INVALID_ARGUMENT if any other arguments are invalid.
447 *
448 * @param pVM Pointer to the shared VM structure.
449 * @param GCPhys Where to start searching.
450 * @param cbRange The number of bytes to search.
451 * @param pabNeedle The byte string to search for.
452 * @param cbNeedle The length of the byte string. Max 256 bytes.
453 * @param pGCPhysHit Where to store the address of the first occurence on success.
454 */
455VMMR3DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit)
456{
457 /*
458 * Validate and adjust the input a bit.
459 */
460 if (!VALID_PTR(pGCPhysHit))
461 return VERR_INVALID_POINTER;
462 *pGCPhysHit = NIL_RTGCPHYS;
463
464 if ( !VALID_PTR(pabNeedle)
465 || GCPhys == NIL_RTGCPHYS)
466 return VERR_INVALID_POINTER;
467 if (!cbNeedle)
468 return VERR_INVALID_PARAMETER;
469 if (cbNeedle > MAX_NEEDLE_SIZE)
470 return VERR_INVALID_PARAMETER;
471
472 if (!cbRange)
473 return VERR_DBGF_MEM_NOT_FOUND;
474 if (GCPhys + cbNeedle - 1 < GCPhys)
475 return VERR_DBGF_MEM_NOT_FOUND;
476
477 const RTGCPHYS GCPhysLast = GCPhys + cbRange - 1 >= GCPhys
478 ? GCPhys + cbRange - 1
479 : ~(RTGCPHYS)0;
480
481 /*
482 * Search the memory - ignore MMIO and zero pages, also don't
483 * bother to match across ranges.
484 */
485 for (PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
486 pRam;
487 pRam = pRam->CTX_SUFF(pNext))
488 {
489 /*
490 * If the search range starts prior to the current ram range record,
491 * adjust the search range and possibly conclude the search.
492 */
493 RTGCPHYS off;
494 if (GCPhys < pRam->GCPhys)
495 {
496 if (GCPhysLast < pRam->GCPhys)
497 break;
498 GCPhys = pRam->GCPhys;
499 off = 0;
500 }
501 else
502 off = GCPhys - pRam->GCPhys;
503 if (off < pRam->cb)
504 {
505 /*
506 * Iterate the relevant pages.
507 */
508 uint8_t abPrev[MAX_NEEDLE_SIZE];
509 size_t cbPrev = 0;
510 const uint32_t cPages = pRam->cb >> PAGE_SHIFT;
511 for (uint32_t iPage = off >> PAGE_SHIFT; iPage < cPages; iPage++)
512 {
513 PPGMPAGE pPage = &pRam->aPages[iPage];
514 if ( !PGM_PAGE_IS_ZERO(pPage)
515 && !PGM_PAGE_IS_MMIO(pPage))
516 {
517 void const *pvPage;
518 PGMPAGEMAPLOCK Lock;
519 int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK, &pvPage, &Lock);
520 if (RT_SUCCESS(rc))
521 {
522 int32_t offPage = (GCPhys & PAGE_OFFSET_MASK);
523 uint32_t cbSearch = (GCPhys ^ GCPhysLast) & ~(RTGCPHYS)PAGE_OFFSET_MASK
524 ? PAGE_SIZE - (uint32_t)offPage
525 : (GCPhysLast & PAGE_OFFSET_MASK) + 1 - (uint32_t)offPage;
526 bool fRc = pgmR3DbgScanPage((uint8_t const *)pvPage, &offPage, cbSearch,
527 pabNeedle, cbNeedle, &abPrev[0], &cbPrev);
528 PGMPhysReleasePageMappingLock(pVM, &Lock);
529 if (fRc)
530 {
531 *pGCPhysHit = (GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK) + offPage;
532 return VINF_SUCCESS;
533 }
534 }
535 else
536 cbPrev = 0; /* ignore error. */
537 }
538 else
539 cbPrev = 0;
540
541 /* advance to the next page. */
542 GCPhys |= PAGE_OFFSET_MASK;
543 if (GCPhys++ >= GCPhysLast)
544 return VERR_DBGF_MEM_NOT_FOUND;
545 }
546 }
547 }
548 return VERR_DBGF_MEM_NOT_FOUND;
549}
550
551
552/**
553 * Scans (guest) virtual memory for a byte string.
554 *
555 * @returns VBox status codes:
556 * @retval VINF_SUCCESS and *pGCPtrHit on success.
557 * @retval VERR_DBGF_MEM_NOT_FOUND if not found.
558 * @retval VERR_INVALID_POINTER if any of the pointer arguments are invalid.
559 * @retval VERR_INVALID_ARGUMENT if any other arguments are invalid.
560 *
561 * @param pVM Pointer to the shared VM structure.
562 * @param GCPtr Where to start searching.
563 * @param cbRange The number of bytes to search. Max 256 bytes.
564 * @param pabNeedle The byte string to search for.
565 * @param cbNeedle The length of the byte string.
566 * @param pGCPtrHit Where to store the address of the first occurence on success.
567 */
568VMMR3DECL(int) PGMR3DbgScanVirtual(PVM pVM, RTGCPTR GCPtr, RTGCPTR cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPtrHit)
569{
570 /** @todo SMP support! */
571 PVMCPU pVCpu = &pVM->aCpus[0];
572
573 /*
574 * Validate and adjust the input a bit.
575 */
576 if (!VALID_PTR(pGCPtrHit))
577 return VERR_INVALID_POINTER;
578 *pGCPtrHit = 0;
579
580 if (!VALID_PTR(pabNeedle))
581 return VERR_INVALID_POINTER;
582 if (!cbNeedle)
583 return VERR_INVALID_PARAMETER;
584 if (cbNeedle > MAX_NEEDLE_SIZE)
585 return VERR_INVALID_PARAMETER;
586
587 if (!cbRange)
588 return VERR_DBGF_MEM_NOT_FOUND;
589 if (GCPtr + cbNeedle - 1 < GCPtr)
590 return VERR_DBGF_MEM_NOT_FOUND;
591
592 /*
593 * Search the memory - ignore MMIO, zero and not-present pages.
594 */
595 uint8_t abPrev[MAX_NEEDLE_SIZE];
596 size_t cbPrev = 0;
597 const RTGCPTR GCPtrLast = GCPtr + cbRange - 1 >= GCPtr
598 ? GCPtr + cbRange - 1
599 : ~(RTGCPTR)0;
600 RTGCPTR cPages = (((GCPtrLast - GCPtr) + (GCPtr & PAGE_OFFSET_MASK)) >> PAGE_SHIFT) + 1;
601 while (cPages-- > 0)
602 {
603 RTGCPHYS GCPhys;
604 int rc = PGMPhysGCPtr2GCPhys(pVCpu, GCPtr, &GCPhys);
605 if (RT_SUCCESS(rc))
606 {
607 PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
608 if ( pPage
609///@todo && !PGM_PAGE_IS_ZERO(pPage)
610 && !PGM_PAGE_IS_MMIO(pPage))
611 {
612 void const *pvPage;
613 PGMPAGEMAPLOCK Lock;
614 rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys & ~(RTGCPTR)PAGE_OFFSET_MASK, &pvPage, &Lock);
615 if (RT_SUCCESS(rc))
616 {
617 int32_t offPage = (GCPtr & PAGE_OFFSET_MASK);
618 uint32_t cbSearch = cPages > 0
619 ? PAGE_SIZE - (uint32_t)offPage
620 : (GCPtrLast & PAGE_OFFSET_MASK) + 1 - (uint32_t)offPage;
621 bool fRc = pgmR3DbgScanPage((uint8_t const *)pvPage, &offPage, cbSearch,
622 pabNeedle, cbNeedle, &abPrev[0], &cbPrev);
623 PGMPhysReleasePageMappingLock(pVM, &Lock);
624 if (fRc)
625 {
626 *pGCPtrHit = (GCPtr & ~(RTGCPTR)PAGE_OFFSET_MASK) + offPage;
627 return VINF_SUCCESS;
628 }
629 }
630 else
631 cbPrev = 0; /* ignore error. */
632 }
633 else
634 cbPrev = 0;
635 }
636 else
637 cbPrev = 0; /* ignore error. */
638
639 /* advance to the next page. */
640 GCPtr |= PAGE_OFFSET_MASK;
641 GCPtr++;
642 }
643 return VERR_DBGF_MEM_NOT_FOUND;
644}
645
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