~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/VMM/PGMDbg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
336
336
}
337
337
 
338
338
 
 
339
/**
 
340
 * memchr() with alignment considerations.
 
341
 *
 
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.
 
347
 */
 
348
static const uint8_t *pgmR3DbgAlignedMemChr(const uint8_t *pb, uint8_t b, size_t cb, uint32_t uAlign)
 
349
{
 
350
    const uint8_t *pbRet;
 
351
    if (uAlign <= 32)
 
352
    {
 
353
        pbRet = (const uint8_t *)memchr(pb, b, cb);
 
354
        if ((uintptr_t)pbRet & (uAlign - 1))
 
355
        {
 
356
            do
 
357
            {
 
358
                pbRet++;
 
359
                size_t cbLeft = cb - (pbRet - pb);
 
360
                if (!cbLeft)
 
361
                {
 
362
                    pbRet = NULL;
 
363
                    break;
 
364
                }
 
365
                pbRet = (const uint8_t *)memchr(pbRet, b, cbLeft);
 
366
            } while ((uintptr_t)pbRet & (uAlign - 1));
 
367
        }
 
368
    }
 
369
    else
 
370
    {
 
371
        pbRet = NULL;
 
372
        if (cb)
 
373
        {
 
374
            for (;;)
 
375
            {
 
376
                if (*pb == b)
 
377
                {
 
378
                    pbRet = pb;
 
379
                    break;
 
380
                }
 
381
                if (cb <= uAlign)
 
382
                    break;
 
383
                cb -= uAlign;
 
384
                pb += uAlign;
 
385
            }
 
386
        }
 
387
    }
 
388
    return pbRet;
 
389
}
 
390
 
339
391
 
340
392
/**
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.
358
411
 */
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)
362
415
{
378
431
 
379
432
        /* check out the remainder of the previous page. */
380
433
        const uint8_t *pb = pabPrev;
381
 
        while (cbPrev-- > 0)
 
434
        for (;;)
382
435
        {
383
 
            pb = (const uint8_t *)memchr(pb + 1, *pabNeedle, cbPrev);
 
436
            if (cbPrev <= uAlign)
 
437
                break;
 
438
            cbPrev -= uAlign;
 
439
            pb = pgmR3DbgAlignedMemChr(pb + uAlign, *pabNeedle, cbPrev, uAlign);
384
440
            if (!pb)
385
441
                break;
386
442
            cbPrev = *pcbPrev - (pb - pabPrev);
404
460
    const uint8_t *pbEnd = pb + cb;
405
461
    for (;;)
406
462
    {
407
 
        pb = (const uint8_t *)memchr(pb, *pabNeedle, cb);
 
463
        pb = pgmR3DbgAlignedMemChr(pb, *pabNeedle, cb, uAlign);
408
464
        if (!pb)
409
465
            break;
410
466
        cb = pbEnd - pb;
429
485
            }
430
486
        }
431
487
 
432
 
        /* no match, skip a byte ahead. */
433
 
        if (cb <= 1)
 
488
        /* no match, skip ahead. */
 
489
        if (cb <= uAlign)
434
490
            break;
435
 
        pb++;
436
 
        cb--;
 
491
        pb += uAlign;
 
492
        cb -= uAlign;
437
493
    }
438
494
 
439
495
    return false;
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.
458
516
 */
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)
460
519
{
461
520
    /*
462
521
     * Validate and adjust the input a bit.
478
537
    if (GCPhys + cbNeedle - 1 < GCPhys)
479
538
        return VERR_DBGF_MEM_NOT_FOUND;
480
539
 
481
 
    const RTGCPHYS GCPhysLast = GCPhys + cbRange - 1 >= GCPhys
482
 
                              ? GCPhys + cbRange - 1
483
 
                              : ~(RTGCPHYS)0;
 
540
    if (!GCPhysAlign)
 
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;
 
546
 
 
547
    if (GCPhys & (GCPhysAlign - 1))
 
548
    {
 
549
        RTGCPHYS Adj = GCPhysAlign - (GCPhys & (GCPhysAlign - 1));
 
550
        if (    cbRange <= Adj
 
551
            ||  GCPhys + Adj < GCPhys)
 
552
            return VERR_DBGF_MEM_NOT_FOUND;
 
553
        GCPhys  += Adj;
 
554
        cbRange -= Adj;
 
555
    }
 
556
 
 
557
    const bool      fAllZero   = ASMMemIsAll8(pabNeedle, cbNeedle, 0) == NULL;
 
558
    const uint32_t  cIncPages  = GCPhysAlign <= PAGE_SIZE
 
559
                               ? 1
 
560
                               : GCPhysAlign >> PAGE_SHIFT;
 
561
    const RTGCPHYS  GCPhysLast = GCPhys + cbRange - 1 >= GCPhys
 
562
                               ? GCPhys + cbRange - 1
 
563
                               : ~(RTGCPHYS)0;
484
564
 
485
565
    /*
486
566
     * Search the memory - ignore MMIO and zero pages, also don't
510
590
            /*
511
591
             * Iterate the relevant pages.
512
592
             */
513
 
            uint8_t abPrev[MAX_NEEDLE_SIZE];
514
 
            size_t  cbPrev = 0;
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];
 
594
            size_t          cbPrev   = 0;
 
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;
 
599
            for (;; offPage = 0)
517
600
            {
518
601
                PPGMPAGE pPage = &pRam->aPages[iPage];
519
 
                if (    !PGM_PAGE_IS_ZERO(pPage)
 
602
                if (    (   !PGM_PAGE_IS_ZERO(pPage)
 
603
                         || fAllZero)
520
604
                    &&  !PGM_PAGE_IS_MMIO(pPage))
521
605
                {
522
 
                    void const *pvPage;
523
 
                    PGMPAGEMAPLOCK Lock;
524
 
                    int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK, &pvPage, &Lock);
 
606
                    void const     *pvPage;
 
607
                    PGMPAGEMAPLOCK  Lock;
 
608
                    int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvPage, &Lock);
525
609
                    if (RT_SUCCESS(rc))
526
610
                    {
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;
 
612
                        bool        fRc;
 
613
                        if (GCPhysAlign < PAGE_SIZE)
 
614
                        {
 
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);
 
620
                        }
 
621
                        else
 
622
                            fRc = memcmp(pvPage, pabNeedle, cbNeedle) == 0
 
623
                               && (GCPhysLast - GCPhys) >= cbNeedle;
533
624
                        PGMPhysReleasePageMappingLock(pVM, &Lock);
534
625
                        if (fRc)
535
626
                        {
536
 
                            *pGCPhysHit = (GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK) + offPage;
 
627
                            *pGCPhysHit = GCPhys + offHit;
537
628
                            pgmUnlock(pVM);
538
629
                            return VINF_SUCCESS;
539
630
                        }
545
636
                    cbPrev = 0;
546
637
 
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.) */
550
641
                {
551
642
                    pgmUnlock(pVM);
552
643
                    return VERR_DBGF_MEM_NOT_FOUND;
553
644
                }
 
645
                iPage += cIncPages;
 
646
                if (    iPage < cIncPages
 
647
                    ||  iPage >= cPages)
 
648
                    break;
554
649
            }
555
650
        }
556
651
    }
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.
578
675
 */
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)
580
678
{
581
679
    VMCPU_ASSERT_EMT(pVCpu);
582
680
 
599
697
    if (GCPtr + cbNeedle - 1 < GCPtr)
600
698
        return VERR_DBGF_MEM_NOT_FOUND;
601
699
 
 
700
    if (!GCPtrAlign)
 
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;
 
706
 
 
707
    if (GCPtr & (GCPtrAlign - 1))
 
708
    {
 
709
        RTGCPTR Adj = GCPtrAlign - (GCPtr & (GCPtrAlign - 1));
 
710
        if (    cbRange <= Adj
 
711
            ||  GCPtr + Adj < GCPtr)
 
712
            return VERR_DBGF_MEM_NOT_FOUND;
 
713
        GCPtr   += Adj;
 
714
        cbRange -= Adj;
 
715
    }
 
716
 
602
717
    /*
603
718
     * Search the memory - ignore MMIO, zero and not-present pages.
604
719
     */
 
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
 
726
                              ? 1
 
727
                              : GCPtrAlign >> PAGE_SHIFT;
609
728
    const RTGCPTR   GCPtrLast = GCPtr + cbRange - 1 >= GCPtr
610
729
                              ? (GCPtr + cbRange - 1) & GCPtrMask
611
730
                              : GCPtrMask;
612
731
    RTGCPTR         cPages    = (((GCPtrLast - GCPtr) + (GCPtr & PAGE_OFFSET_MASK)) >> PAGE_SHIFT) + 1;
613
 
    while (cPages-- > 0)
 
732
    uint32_t        offPage   = GCPtr & PAGE_OFFSET_MASK;
 
733
    GCPtr &= ~(RTGCPTR)PAGE_OFFSET_MASK;
 
734
    for (;; offPage = 0)
614
735
    {
615
736
        RTGCPHYS GCPhys;
616
737
        int rc = PGMPhysGCPtr2GCPhys(pVCpu, GCPtr, &GCPhys);
618
739
        {
619
740
            PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
620
741
            if (    pPage
621
 
                &&  !PGM_PAGE_IS_ZERO(pPage) /** @todo handle all zero needle. */
 
742
                &&  (   !PGM_PAGE_IS_ZERO(pPage)
 
743
                     || fAllZero)
622
744
                &&  !PGM_PAGE_IS_MMIO(pPage))
623
745
            {
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))
628
750
                {
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;
 
752
                    bool    fRc;
 
753
                    if (GCPtrAlign < PAGE_SIZE)
 
754
                    {
 
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);
 
760
                    }
 
761
                    else
 
762
                        fRc = memcmp(pvPage, pabNeedle, cbNeedle) == 0
 
763
                           && (GCPtrLast - GCPtr) >= cbNeedle;
635
764
                    PGMPhysReleasePageMappingLock(pVM, &Lock);
636
765
                    if (fRc)
637
766
                    {
638
 
                        *pGCPtrHit = (GCPtr & ~(RTGCPTR)PAGE_OFFSET_MASK) + offPage;
 
767
                        *pGCPtrHit = GCPtr + offHit;
639
768
                        return VINF_SUCCESS;
640
769
                    }
641
770
                }
649
778
            cbPrev = 0; /* ignore error. */
650
779
 
651
780
        /* advance to the next page. */
652
 
        GCPtr |= PAGE_OFFSET_MASK;
653
 
        GCPtr++;
654
 
        GCPtr &= GCPtrMask;
 
781
        if (cPages <= cIncPages)
 
782
            break;
 
783
        cPages -= cIncPages;
 
784
        GCPtr += (RTGCPTR)cIncPages << PAGE_SHIFT;
655
785
    }
656
786
    return VERR_DBGF_MEM_NOT_FOUND;
657
787
}