VirtualBox

Changeset 106379 in vbox for trunk/src/VBox/Debugger


Ignore:
Timestamp:
Oct 16, 2024 1:45:18 PM (4 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
165192
Message:

Debugger/DBGPlugInWinNt.cpp: Make it detect and extract symbols from Windows/ARM64 guests, bugref:10393

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGPlugInWinNt.cpp

    r106061 r106379  
    251251     * (For fending off illegal interface method calls.) */
    252252    bool                fValid;
    253     /** 32-bit (true) or 64-bit (false) */
    254     bool                f32Bit;
    255253    /** Set if NT 3.1 was detected.
    256254     * This implies both Misc.VirtualSize and NTMTE32::SizeOfImage are zero. */
    257255    bool                fNt31;
     256    /** Detected architecture. */
     257    RTLDRARCH           enmArch;
    258258
    259259    /** The NT version. */
     
    271271    DBGFADDRESS         BootMgrAddr;
    272272    /** The address of the winload.exe image if early during boot.
    273      * When this is set, f32Bit has also been determined.  */
     273     * When this is set, enmArch has also been determined.  */
    274274    DBGFADDRESS         WinLoadAddr;
    275275
     
    342342/** Validates a 64-bit Windows NT kernel address */
    343343#define WINNT64_VALID_ADDRESS(Addr)         ((Addr) > UINT64_C(0xffff800000000000) && (Addr) < UINT64_C(0xfffffffffffff000))
     344/** Returns whether this is a 32-bit Windows NT kernel. */
     345#define WINNT_IS_32BIT(a_pThis)             ((a_pThis)->enmArch == RTLDRARCH_X86_32)
    344346/** Validates a kernel address. */
    345 #define WINNT_VALID_ADDRESS(pThis, Addr)    ((pThis)->f32Bit ? WINNT32_VALID_ADDRESS(Addr) : WINNT64_VALID_ADDRESS(Addr))
     347#define WINNT_VALID_ADDRESS(pThis, Addr)    (WINNT_IS_32BIT(pThis) ? WINNT32_VALID_ADDRESS(Addr) : WINNT64_VALID_ADDRESS(Addr))
    346348/** Versioned and bitness wrapper. */
    347 #define WINNT_UNION(pThis, pUnion, Member)  ((pThis)->f32Bit ? (pUnion)->vX_32. Member : (pUnion)->vX_64. Member )
     349#define WINNT_UNION(pThis, pUnion, Member)  (WINNT_IS_32BIT(pThis) ? (pUnion)->vX_32. Member : (pUnion)->vX_64. Member )
    348350
    349351/** The length (in chars) of the kernel file name (no path). */
     
    443445    char aszFmtStr[_1K]; /* Restricted size. */
    444446    DBGFADDRESS AddrVaList;
    445     if (!pThis->f32Bit)
     447    if (pThis->enmArch != RTLDRARCH_X86_32)
    446448    {
    447449        /*
     
    520522    {
    521523        uint32_t cbInsn = 0;
    522         rc = DISInstr(&abInstr[0], pThis->f32Bit ? DISCPUMODE_32BIT : DISCPUMODE_64BIT, &DisState, &cbInsn);
     524        rc = DISInstr(&abInstr[0], pThis->enmArch == RTLDRARCH_X86_32 ? DISCPUMODE_32BIT : DISCPUMODE_64BIT, &DisState, &cbInsn);
    523525        if (   RT_SUCCESS(rc)
    524526            && DisState.pCurInstr->uOpcode == OP_CALL
     
    702704            PDBGFADDRESS pKpcrbAddr = &pThis->paKpcrbAddr[idCpu];
    703705
    704             if (pThis->f32Bit)
     706            if (pThis->enmArch == RTLDRARCH_X86_32)
    705707            {
    706708                /* Read FS base */
     
    970972 */
    971973static bool dbgDiggerWinNtIsWinLoad(PUVM pUVM, PCVMMR3VTABLE pVMM, PCDBGFADDRESS pAddr, uint8_t const *pbHdrs, size_t cbHdrs,
    972                                     bool *pf32Bit, uint32_t *pcbImage, uint32_t *puNtMajorVersion, uint32_t *puNtMinorVersion)
    973 {
    974     if (pf32Bit)
    975         *pf32Bit = false;
     974                                    RTLDRARCH *penmArch, uint32_t *pcbImage, uint32_t *puNtMajorVersion, uint32_t *puNtMinorVersion)
     975{
     976    if (penmArch)
     977        *penmArch = RTLDRARCH_X86_32;
    976978    if (pcbImage)
    977979        *pcbImage = 0;
     
    10071009        return false;
    10081010    bool f32Bit;
     1011    RTLDRARCH enmArch;
    10091012    if (pHdrs32->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
     1013    {
    10101014        f32Bit = true;
     1015        enmArch = RTLDRARCH_X86_32;
     1016    }
    10111017    else if (pHdrs32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
     1018    {
    10121019        f32Bit = false;
     1020        enmArch = RTLDRARCH_AMD64;
     1021    }
     1022    else if (pHdrs32->FileHeader.Machine == IMAGE_FILE_MACHINE_ARM64)
     1023    {
     1024        f32Bit = false;
     1025        enmArch = RTLDRARCH_ARM64;
     1026    }
    10131027    else
    10141028        return false;
     
    10861100        return false;
    10871101
    1088     if (pf32Bit)
    1089         *pf32Bit  = f32Bit;
     1102    if (penmArch)
     1103        *penmArch  = enmArch;
    10901104    if (pcbImage)
    10911105        *pcbImage = pHdrs32->OptionalHeader.SizeOfImage;
     
    11331147     */
    11341148    if (enmArch == RTLDRARCH_WHATEVER)
    1135         enmArch = pThis->f32Bit ? RTLDRARCH_X86_32 : RTLDRARCH_AMD64;
     1149        enmArch = pThis->enmArch;
    11361150    RTERRINFOSTATIC ErrInfo;
    11371151    RTDBGMOD        hDbgMod = NIL_RTDBGMOD;
     
    12281242        *puBuildNumber = pData->NtBuildNumber;
    12291243    if (pf32Bit)
    1230         *pf32Bit = pData->f32Bit;
     1244        *pf32Bit = WINNT_IS_32BIT(pData);
    12311245    return VINF_SUCCESS;
    12321246}
     
    14641478    }
    14651479
     1480    const char *pszArch;
     1481    switch (pThis->enmArch)
     1482    {
     1483        case RTLDRARCH_X86_32: pszArch = "x86";   break;
     1484        case RTLDRARCH_AMD64:  pszArch = "AMD64"; break;
     1485        case RTLDRARCH_ARM64:  pszArch = "ARM64"; break;
     1486        default:               pszArch = "<??>";  break;
     1487    }
    14661488    RTStrPrintf(pszVersion, cchVersion, "%u.%u-%s%s (BuildNumber %u)", pThis->NtMajorVersion, pThis->NtMinorVersion,
    1467                 pThis->f32Bit ? "x86" : "AMD64", pszNtProductType, pThis->NtBuildNumber);
     1489                pszArch, pszNtProductType, pThis->NtBuildNumber);
    14681490    return VINF_SUCCESS;
    14691491}
     
    16051627     * Try figure the NT version.
    16061628     */
    1607     pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pThis->f32Bit ? NTKUSERSHAREDDATA_WINNT32 : NTKUSERSHAREDDATA_WINNT64);
     1629    pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, WINNT_IS_32BIT(pThis) ? NTKUSERSHAREDDATA_WINNT32 : NTKUSERSHAREDDATA_WINNT64);
    16081630    rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &u, GUEST_PAGE_SIZE);
    16091631    if (RT_SUCCESS(rc))
     
    16411663        /* Read the validate the MTE. */
    16421664        NTMTE Mte;
    1643         rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &Mte, pThis->f32Bit ? sizeof(Mte.vX_32) : sizeof(Mte.vX_64));
     1665        rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &Mte, WINNT_IS_32BIT(pThis) ? sizeof(Mte.vX_32) : sizeof(Mte.vX_64));
    16441666        if (RT_FAILURE(rc))
    16451667            break;
     
    17681790    RT_ZERO(pThis->KernelMteAddr);
    17691791    RT_ZERO(pThis->PsLoadedModuleListAddr);
    1770     pThis->f32Bit = false;
    1771     pThis->fNt31  = false;
     1792    pThis->enmArch = RTLDRARCH_WHATEVER;
     1793    pThis->fNt31   = false;
    17721794
    17731795    /*
     
    18081830                                                                    Addr.FlatPtr & ~(RTGCUINTPTR)GUEST_PAGE_OFFSET_MASK),
    18091831                                        &u.au8[0], sizeof(u));
    1810             bool f32Bit = false;
    1811             if (RT_SUCCESS(rc) && dbgDiggerWinNtIsWinLoad(pUVM, pVMM, &AddrMz, &u.au8[0], sizeof(u), &f32Bit, NULL, NULL, NULL))
     1832            RTLDRARCH enmArch = RTLDRARCH_WHATEVER;
     1833            if (RT_SUCCESS(rc) && dbgDiggerWinNtIsWinLoad(pUVM, pVMM, &AddrMz, &u.au8[0], sizeof(u), &enmArch, NULL, NULL, NULL))
    18121834            {
    18131835                pThis->WinLoadAddr = AddrMz;
    1814                 pThis->f32Bit      = f32Bit;
     1836                pThis->enmArch     = enmArch;
    18151837                fRet = true;
    18161838                break;
     
    18241846     */
    18251847    CPUMMODE const enmMode = pVMM->pfnDBGFR3CpuGetMode(pUVM, 0 /*idCpu*/);
    1826     if (enmMode != CPUMMODE_PROTECTED && enmMode != CPUMMODE_LONG)
     1848    if (enmMode != CPUMMODE_PROTECTED && enmMode != CPUMMODE_LONG && enmMode != CPUMMODE_ARMV8_AARCH64)
    18271849        return fRet;
    18281850    bool const      f64Bit = enmMode == CPUMMODE_LONG
    1829                           || (DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr) && !pThis->f32Bit);
     1851                          || enmMode == CPUMMODE_ARMV8_AARCH64
     1852                          || (DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr) && !WINNT_IS_32BIT(pThis));
    18301853    uint64_t const  uStart = f64Bit ? UINT64_C(0xffff800000000000) : UINT32_C(0x80001000);
    18311854    uint64_t const  uEnd   = f64Bit ? UINT64_C(0xffffffffffff0000) : UINT32_C(0xffff0000);
    18321855
    1833     /*
    1834      * To approximately locate the kernel we examine the IDTR handlers.
    1835      *
    1836      * The exception/trap/fault handlers are all in NT kernel image, we pick
    1837      * KiPageFault here.
    1838      */
    1839     uint64_t uIdtrBase = 0;
    1840     uint16_t uIdtrLimit = 0;
    1841     int rc = pVMM->pfnDBGFR3RegCpuQueryXdtr(pUVM, 0, DBGFREG_IDTR, &uIdtrBase, &uIdtrLimit);
    1842     AssertRCReturn(rc, fRet);
    1843 
    1844     const uint16_t cbMinIdtr = (X86_XCPT_PF + 1) * (f64Bit ? sizeof(X86DESC64GATE) : sizeof(X86DESCGATE));
    1845     if (uIdtrLimit < cbMinIdtr)
    1846         return fRet;
    1847 
    1848     rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, uIdtrBase), &u, cbMinIdtr);
    1849     if (RT_FAILURE(rc))
    1850         return fRet;
    1851 
    18521856    uint64_t uKrnlStart = uStart;
    18531857    uint64_t uKrnlEnd   = uEnd;
    1854     if (f64Bit)
    1855     {
    1856         uint64_t uHandler = u.a64Gates[X86_XCPT_PF].u16OffsetLow
    1857                           | ((uint32_t)u.a64Gates[X86_XCPT_PF].u16OffsetHigh << 16)
    1858                           | ((uint64_t)u.a64Gates[X86_XCPT_PF].u32OffsetTop  << 32);
    1859         if (uHandler >= uStart && uHandler <= uEnd)
    1860         {
    1861             uKrnlStart = (uHandler & ~(uint64_t)_4M) - _512M;
    1862             uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
    1863         }
    1864         else if (!DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1858
     1859    int rc;
     1860    if (enmMode == CPUMMODE_ARMV8_AARCH64)
     1861    {
     1862        /*
     1863         * To approximately locate the kernel we use the exception table base address
     1864         * which contains actual instructions so it is located in the NT kernel image.
     1865         */
     1866        uint64_t uVBarBase = 0;
     1867        rc = pVMM->pfnDBGFR3RegCpuQueryU64(pUVM, 0, DBGFREG_ARMV8_VBAR_EL1, &uVBarBase);
     1868        AssertRCReturn(rc, fRet);
     1869
     1870        if (f64Bit)
     1871        {
     1872            if (uVBarBase >= uStart && uVBarBase <= uEnd)
     1873            {
     1874                uKrnlStart = (uVBarBase & ~(uint64_t)_4M) - _512M;
     1875                uKrnlEnd   = (uVBarBase + (uint64_t)_4M) & ~(uint64_t)_4M;
     1876            }
     1877            else if (!DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1878                return fRet;
     1879        }
     1880        else
     1881        {
     1882            AssertFailed();
    18651883            return fRet;
     1884        }
    18661885    }
    18671886    else
    18681887    {
    1869         uint32_t uHandler = RT_MAKE_U32(u.a32Gates[X86_XCPT_PF].u16OffsetLow, u.a32Gates[X86_XCPT_PF].u16OffsetHigh);
    1870         if (uHandler >= uStart && uHandler <= uEnd)
    1871         {
    1872             uKrnlStart = (uHandler & ~(uint64_t)_4M) - _64M;
    1873             uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
    1874         }
    1875         else if (!DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1888        /*
     1889         * To approximately locate the kernel we examine the IDTR handlers.
     1890         *
     1891         * The exception/trap/fault handlers are all in NT kernel image, we pick
     1892         * KiPageFault here.
     1893         */
     1894        uint64_t uIdtrBase = 0;
     1895        uint16_t uIdtrLimit = 0;
     1896        rc = pVMM->pfnDBGFR3RegCpuQueryXdtr(pUVM, 0, DBGFREG_IDTR, &uIdtrBase, &uIdtrLimit);
     1897        AssertRCReturn(rc, fRet);
     1898
     1899        const uint16_t cbMinIdtr = (X86_XCPT_PF + 1) * (f64Bit ? sizeof(X86DESC64GATE) : sizeof(X86DESCGATE));
     1900        if (uIdtrLimit < cbMinIdtr)
    18761901            return fRet;
     1902
     1903        rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, uIdtrBase), &u, cbMinIdtr);
     1904        if (RT_FAILURE(rc))
     1905            return fRet;
     1906
     1907        if (f64Bit)
     1908        {
     1909            uint64_t uHandler = u.a64Gates[X86_XCPT_PF].u16OffsetLow
     1910                              | ((uint32_t)u.a64Gates[X86_XCPT_PF].u16OffsetHigh << 16)
     1911                              | ((uint64_t)u.a64Gates[X86_XCPT_PF].u32OffsetTop  << 32);
     1912            if (uHandler >= uStart && uHandler <= uEnd)
     1913            {
     1914                uKrnlStart = (uHandler & ~(uint64_t)_4M) - _512M;
     1915                uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
     1916            }
     1917            else if (!DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1918                return fRet;
     1919        }
     1920        else
     1921        {
     1922            uint32_t uHandler = RT_MAKE_U32(u.a32Gates[X86_XCPT_PF].u16OffsetLow, u.a32Gates[X86_XCPT_PF].u16OffsetHigh);
     1923            if (uHandler >= uStart && uHandler <= uEnd)
     1924            {
     1925                uKrnlStart = (uHandler & ~(uint64_t)_4M) - _64M;
     1926                uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
     1927            }
     1928            else if (!DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1929                return fRet;
     1930        }
    18771931    }
    18781932
     
    19762030                                    pThis->KernelMteAddr            = MteAddr;
    19772031                                    pThis->PsLoadedModuleListAddr   = Addr;
    1978                                     pThis->f32Bit                   = true;
     2032                                    pThis->enmArch                  = RTLDRARCH_X86_32;
    19792033                                    pThis->fNt31                    = fNt31;
    19802034                                    return true;
     
    20032057                IMAGE_NT_HEADERS64 const *pHdrs = (IMAGE_NT_HEADERS64 const *)&u.au8[u.MzHdr.e_lfanew];
    20042058                if (    pHdrs->Signature                            == IMAGE_NT_SIGNATURE
    2005                     &&  pHdrs->FileHeader.Machine                   == IMAGE_FILE_MACHINE_AMD64
    2006                     &&  pHdrs->FileHeader.SizeOfOptionalHeader      == sizeof(pHdrs->OptionalHeader)
     2059                    &&  (   pHdrs->FileHeader.Machine               == IMAGE_FILE_MACHINE_AMD64
     2060                         || pHdrs->FileHeader.Machine               == IMAGE_FILE_MACHINE_ARM64)
     2061                    //&&  pHdrs->FileHeader.SizeOfOptionalHeader      == sizeof(pHdrs->OptionalHeader)
    20072062                    &&  pHdrs->FileHeader.NumberOfSections          >= 10 /* the kernel has lots */
    2008                     &&      (pHdrs->FileHeader.Characteristics & (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))
    2009                          == IMAGE_FILE_EXECUTABLE_IMAGE
     2063                    //&&      (pHdrs->FileHeader.Characteristics & (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))
     2064                    //   == (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL)
    20102065                    &&  pHdrs->OptionalHeader.Magic                 == IMAGE_NT_OPTIONAL_HDR64_MAGIC
    2011                     &&  pHdrs->OptionalHeader.NumberOfRvaAndSizes   == IMAGE_NUMBEROF_DIRECTORY_ENTRIES
     2066                    //&&  pHdrs->OptionalHeader.NumberOfRvaAndSizes   == IMAGE_NUMBEROF_DIRECTORY_ENTRIES
    20122067                    )
    20132068                {
     
    20602115                                    && WINNT64_VALID_ADDRESS(uMte3.v64.InLoadOrderLinks.Blink) )
    20612116                                {
    2062                                     Log(("DigWinNt: MteAddr=%RGv KernelAddr=%RGv SizeOfImage=%x &PsLoadedModuleList=%RGv (32-bit)\n",
     2117                                    Log(("DigWinNt: MteAddr=%RGv KernelAddr=%RGv SizeOfImage=%x &PsLoadedModuleList=%RGv (64-bit)\n",
    20632118                                         MteAddr.FlatPtr, KernelAddr.FlatPtr, uMte2.v64.SizeOfImage, Addr.FlatPtr));
    20642119                                    pThis->KernelAddr               = KernelAddr;
    20652120                                    pThis->KernelMteAddr            = MteAddr;
    20662121                                    pThis->PsLoadedModuleListAddr   = Addr;
    2067                                     pThis->f32Bit                   = false;
     2122                                    pThis->enmArch                  =   enmMode == CPUMMODE_LONG
     2123                                                                      ? RTLDRARCH_AMD64
     2124                                                                      : RTLDRARCH_ARM64;
    20682125                                    pThis->fNt31                    = false;
    20692126                                    return true;
     
    21122169    PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;
    21132170    pThis->fValid      = false;
    2114     pThis->f32Bit      = false;
     2171    pThis->enmArch     = RTLDRARCH_WHATEVER;
    21152172    pThis->enmVer      = DBGDIGGERWINNTVER_UNKNOWN;
    21162173
Note: See TracChangeset for help on using the changeset viewer.

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