340
* memchr() with alignment considerations.
342
* @returns Pointer to matching byte, NULL if none found.
343
* @param pb Where to search. Aligned.
344
* @param b What to search for.
345
* @param cb How much to search .
346
* @param uAlign The alignment restriction of the result.
348
static const uint8_t *pgmR3DbgAlignedMemChr(const uint8_t *pb, uint8_t b, size_t cb, uint32_t uAlign)
350
const uint8_t *pbRet;
353
pbRet = (const uint8_t *)memchr(pb, b, cb);
354
if ((uintptr_t)pbRet & (uAlign - 1))
359
size_t cbLeft = cb - (pbRet - pb);
365
pbRet = (const uint8_t *)memchr(pbRet, b, cbLeft);
366
} while ((uintptr_t)pbRet & (uAlign - 1));
341
393
* Scans a page for a byte string, keeping track of potential
344
396
* @returns true and *poff on match.
345
397
* false on mismatch.
346
398
* @param pbPage Pointer to the current page.
347
* @param poff Input: The offset into the page.
399
* @param poff Input: The offset into the page (aligned).
348
400
* Output: The page offset of the match on success.
349
401
* @param cb The number of bytes to search, starting of *poff.
402
* @param uAlign The needle alignment. This is of course less than a page.
350
403
* @param pabNeedle The byte string to search for.
351
404
* @param cbNeedle The length of the byte string.
352
405
* @param pabPrev The buffer that keeps track of a partial match that we
356
409
* Output: The number of partial matching bytes from this page.
357
410
* Initialize to 0 before the first call to this function.
359
static bool pgmR3DbgScanPage(const uint8_t *pbPage, int32_t *poff, uint32_t cb,
412
static bool pgmR3DbgScanPage(const uint8_t *pbPage, int32_t *poff, uint32_t cb, uint32_t uAlign,
360
413
const uint8_t *pabNeedle, size_t cbNeedle,
361
414
uint8_t *pabPrev, size_t *pcbPrev)
379
432
/* check out the remainder of the previous page. */
380
433
const uint8_t *pb = pabPrev;
383
pb = (const uint8_t *)memchr(pb + 1, *pabNeedle, cbPrev);
436
if (cbPrev <= uAlign)
439
pb = pgmR3DbgAlignedMemChr(pb + uAlign, *pabNeedle, cbPrev, uAlign);
386
442
cbPrev = *pcbPrev - (pb - pabPrev);
452
508
* @param pVM Pointer to the shared VM structure.
453
509
* @param GCPhys Where to start searching.
454
510
* @param cbRange The number of bytes to search.
511
* @param GCPhysAlign The alignment of the needle. Must be a power of two
512
* and less or equal to 4GB.
455
513
* @param pabNeedle The byte string to search for.
456
514
* @param cbNeedle The length of the byte string. Max 256 bytes.
457
515
* @param pGCPhysHit Where to store the address of the first occurence on success.
459
VMMR3DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit)
517
VMMR3DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, RTGCPHYS GCPhysAlign,
518
const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit)
462
521
* Validate and adjust the input a bit.
478
537
if (GCPhys + cbNeedle - 1 < GCPhys)
479
538
return VERR_DBGF_MEM_NOT_FOUND;
481
const RTGCPHYS GCPhysLast = GCPhys + cbRange - 1 >= GCPhys
482
? GCPhys + cbRange - 1
541
return VERR_INVALID_PARAMETER;
542
if (GCPhysAlign > UINT32_MAX)
543
return VERR_NOT_POWER_OF_TWO;
544
if (GCPhysAlign & (GCPhysAlign - 1))
545
return VERR_INVALID_PARAMETER;
547
if (GCPhys & (GCPhysAlign - 1))
549
RTGCPHYS Adj = GCPhysAlign - (GCPhys & (GCPhysAlign - 1));
551
|| GCPhys + Adj < GCPhys)
552
return VERR_DBGF_MEM_NOT_FOUND;
557
const bool fAllZero = ASMMemIsAll8(pabNeedle, cbNeedle, 0) == NULL;
558
const uint32_t cIncPages = GCPhysAlign <= PAGE_SIZE
560
: GCPhysAlign >> PAGE_SHIFT;
561
const RTGCPHYS GCPhysLast = GCPhys + cbRange - 1 >= GCPhys
562
? GCPhys + cbRange - 1
486
566
* Search the memory - ignore MMIO and zero pages, also don't
511
591
* Iterate the relevant pages.
513
uint8_t abPrev[MAX_NEEDLE_SIZE];
515
const uint32_t cPages = pRam->cb >> PAGE_SHIFT;
516
for (uint32_t iPage = off >> PAGE_SHIFT; iPage < cPages; iPage++)
593
uint8_t abPrev[MAX_NEEDLE_SIZE];
595
const uint32_t cPages = pRam->cb >> PAGE_SHIFT;
596
uint32_t iPage = off >> PAGE_SHIFT;
597
uint32_t offPage = GCPhys & PAGE_OFFSET_MASK;
598
GCPhys &= ~(RTGCPHYS)PAGE_OFFSET_MASK;
518
601
PPGMPAGE pPage = &pRam->aPages[iPage];
519
if ( !PGM_PAGE_IS_ZERO(pPage)
602
if ( ( !PGM_PAGE_IS_ZERO(pPage)
520
604
&& !PGM_PAGE_IS_MMIO(pPage))
524
int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK, &pvPage, &Lock);
608
int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvPage, &Lock);
525
609
if (RT_SUCCESS(rc))
527
int32_t offPage = (GCPhys & PAGE_OFFSET_MASK);
528
uint32_t cbSearch = (GCPhys ^ GCPhysLast) & ~(RTGCPHYS)PAGE_OFFSET_MASK
529
? PAGE_SIZE - (uint32_t)offPage
530
: (GCPhysLast & PAGE_OFFSET_MASK) + 1 - (uint32_t)offPage;
531
bool fRc = pgmR3DbgScanPage((uint8_t const *)pvPage, &offPage, cbSearch,
532
pabNeedle, cbNeedle, &abPrev[0], &cbPrev);
611
int32_t offHit = offPage;
613
if (GCPhysAlign < PAGE_SIZE)
615
uint32_t cbSearch = (GCPhys ^ GCPhysLast) & ~(RTGCPHYS)PAGE_OFFSET_MASK
616
? PAGE_SIZE - (uint32_t)offPage
617
: (GCPhysLast & PAGE_OFFSET_MASK) + 1 - (uint32_t)offPage;
618
fRc = pgmR3DbgScanPage((uint8_t const *)pvPage, &offHit, cbSearch, (uint32_t)GCPhysAlign,
619
pabNeedle, cbNeedle, &abPrev[0], &cbPrev);
622
fRc = memcmp(pvPage, pabNeedle, cbNeedle) == 0
623
&& (GCPhysLast - GCPhys) >= cbNeedle;
533
624
PGMPhysReleasePageMappingLock(pVM, &Lock);
536
*pGCPhysHit = (GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK) + offPage;
627
*pGCPhysHit = GCPhys + offHit;
538
629
return VINF_SUCCESS;
547
638
/* advance to the next page. */
548
GCPhys |= PAGE_OFFSET_MASK;
549
if (GCPhys++ >= GCPhysLast)
639
GCPhys += (RTGCPHYS)cIncPages << PAGE_SHIFT;
640
if (GCPhys >= GCPhysLast) /* (may not always hit, but we're run out of ranges.) */
552
643
return VERR_DBGF_MEM_NOT_FOUND;
646
if ( iPage < cIncPages
571
666
* @param pVM Pointer to the shared VM structure.
572
667
* @param pVCpu The CPU context to search in.
573
668
* @param GCPtr Where to start searching.
669
* @param GCPtrAlign The alignment of the needle. Must be a power of two
670
* and less or equal to 4GB.
574
671
* @param cbRange The number of bytes to search. Max 256 bytes.
575
672
* @param pabNeedle The byte string to search for.
576
673
* @param cbNeedle The length of the byte string.
577
674
* @param pGCPtrHit Where to store the address of the first occurence on success.
579
VMMR3DECL(int) PGMR3DbgScanVirtual(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, RTGCPTR cbRange, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPtrHit)
676
VMMR3DECL(int) PGMR3DbgScanVirtual(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, RTGCPTR cbRange, RTGCPTR GCPtrAlign,
677
const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPtrHit)
581
679
VMCPU_ASSERT_EMT(pVCpu);
599
697
if (GCPtr + cbNeedle - 1 < GCPtr)
600
698
return VERR_DBGF_MEM_NOT_FOUND;
701
return VERR_INVALID_PARAMETER;
702
if (GCPtrAlign > UINT32_MAX)
703
return VERR_NOT_POWER_OF_TWO;
704
if (GCPtrAlign & (GCPtrAlign - 1))
705
return VERR_INVALID_PARAMETER;
707
if (GCPtr & (GCPtrAlign - 1))
709
RTGCPTR Adj = GCPtrAlign - (GCPtr & (GCPtrAlign - 1));
711
|| GCPtr + Adj < GCPtr)
712
return VERR_DBGF_MEM_NOT_FOUND;
603
718
* Search the memory - ignore MMIO, zero and not-present pages.
720
const bool fAllZero = ASMMemIsAll8(pabNeedle, cbNeedle, 0) == NULL;
605
721
PGMMODE enmMode = PGMGetGuestMode(pVCpu);
606
722
RTGCPTR GCPtrMask = PGMMODE_IS_LONG_MODE(enmMode) ? UINT64_MAX : UINT32_MAX;
607
723
uint8_t abPrev[MAX_NEEDLE_SIZE];
608
724
size_t cbPrev = 0;
725
const uint32_t cIncPages = GCPtrAlign <= PAGE_SIZE
727
: GCPtrAlign >> PAGE_SHIFT;
609
728
const RTGCPTR GCPtrLast = GCPtr + cbRange - 1 >= GCPtr
610
729
? (GCPtr + cbRange - 1) & GCPtrMask
612
731
RTGCPTR cPages = (((GCPtrLast - GCPtr) + (GCPtr & PAGE_OFFSET_MASK)) >> PAGE_SHIFT) + 1;
732
uint32_t offPage = GCPtr & PAGE_OFFSET_MASK;
733
GCPtr &= ~(RTGCPTR)PAGE_OFFSET_MASK;
616
737
int rc = PGMPhysGCPtr2GCPhys(pVCpu, GCPtr, &GCPhys);
619
740
PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
621
&& !PGM_PAGE_IS_ZERO(pPage) /** @todo handle all zero needle. */
742
&& ( !PGM_PAGE_IS_ZERO(pPage)
622
744
&& !PGM_PAGE_IS_MMIO(pPage))
624
746
void const *pvPage;
625
747
PGMPAGEMAPLOCK Lock;
626
rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys & ~(RTGCPTR)PAGE_OFFSET_MASK, &pvPage, &Lock);
748
rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvPage, &Lock);
627
749
if (RT_SUCCESS(rc))
629
int32_t offPage = (GCPtr & PAGE_OFFSET_MASK);
630
uint32_t cbSearch = cPages > 0
631
? PAGE_SIZE - (uint32_t)offPage
632
: (GCPtrLast & PAGE_OFFSET_MASK) + 1 - (uint32_t)offPage;
633
bool fRc = pgmR3DbgScanPage((uint8_t const *)pvPage, &offPage, cbSearch,
634
pabNeedle, cbNeedle, &abPrev[0], &cbPrev);
751
int32_t offHit = offPage;
753
if (GCPtrAlign < PAGE_SIZE)
755
uint32_t cbSearch = cPages > 0
756
? PAGE_SIZE - (uint32_t)offPage
757
: (GCPtrLast & PAGE_OFFSET_MASK) + 1 - (uint32_t)offPage;
758
fRc = pgmR3DbgScanPage((uint8_t const *)pvPage, &offHit, cbSearch, (uint32_t)GCPtrAlign,
759
pabNeedle, cbNeedle, &abPrev[0], &cbPrev);
762
fRc = memcmp(pvPage, pabNeedle, cbNeedle) == 0
763
&& (GCPtrLast - GCPtr) >= cbNeedle;
635
764
PGMPhysReleasePageMappingLock(pVM, &Lock);
638
*pGCPtrHit = (GCPtr & ~(RTGCPTR)PAGE_OFFSET_MASK) + offPage;
767
*pGCPtrHit = GCPtr + offHit;
639
768
return VINF_SUCCESS;