VirtualBox

Changeset 2935 in kBuild for trunk/src/kWorker


Ignore:
Timestamp:
Sep 18, 2016 8:00:07 PM (8 years ago)
Author:
bird
Message:

kWorker: Optimized executable writable section restoring.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kWorker/kWorker.c

    r2934 r2935  
    100100# define KW_LOG(a) do { } while (0)
    101101#endif
     102
     103/** @def KWLDR_LOG
     104 * Loader related logging.
     105 * @param a     Argument list for kwDbgPrintf  */
     106#ifdef KW_LOG_ENABLED
     107# define KWLDR_LOG(a) kwDbgPrintf a
     108#else
     109# define KWLDR_LOG(a) do { } while (0)
     110#endif
     111
    102112
    103113/** @def KWFS_LOG
     
    214224        {
    215225            /** Where we load the image. */
    216             void               *pvLoad;
     226            KU8                *pbLoad;
    217227            /** Virgin copy of the image. */
    218             void               *pvCopy;
     228            KU8                *pbCopy;
    219229            /** Ldr pvBits argument.  This is NULL till we've successfully resolved
    220230             *  the imports. */
     
    232242            /** Set if we share memory with other executables. */
    233243            KBOOL               fUseLdBuf;
     244            /** Set after the first whole image copy is done. */
     245            KBOOL               fCanDoQuick;
     246            /** Number of quick copy chunks. */
     247            KU8                 cQuickCopyChunks;
     248            /** Number of quick zero chunks. */
     249            KU8                 cQuickZeroChunks;
     250            /** Quicker image copy instructions that skips non-writable parts when
     251             * possible.  Need to check fCanDoQuick, fUseLdBuf and previous executable
     252             * image. */
     253            struct
     254            {
     255                /** The copy destination.   */
     256                KU8            *pbDst;
     257                /** The copy source.   */
     258                KU8 const      *pbSrc;
     259                /** How much to copy. */
     260                KSIZE           cbToCopy;
     261            } aQuickCopyChunks[3];
     262            /** For handling BSS and zero alignment padding when using aQuickCopyChunks. */
     263            struct
     264            {
     265                /** Where to start zeroing. */
     266                KU8            *pbDst;
     267                /** How much to zero. */
     268                KSIZE           cbToZero;
     269            } aQuickZeroChunks[3];
    234270            /** Number of imported modules. */
    235271            KSIZE               cImpMods;
     
    755791/** The module currently occupying g_abDefLdBuf. */
    756792static PKWMODULE    g_pModInLdBuf = NULL;
     793
     794/** The module that previuosly occupied g_abDefLdBuf. */
     795static PKWMODULE    g_pModPrevInLdBuf = NULL;
    757796
    758797/** Module hash table. */
     
    14241463        if (!pMod->fNative)
    14251464        {
    1426             kHlpPageFree(pMod->u.Manual.pvCopy, pMod->cbImage);
    1427             kHlpPageFree(pMod->u.Manual.pvLoad, pMod->cbImage);
     1465            kHlpPageFree(pMod->u.Manual.pbCopy, pMod->cbImage);
     1466            kHlpPageFree(pMod->u.Manual.pbLoad, pMod->cbImage);
    14281467        }
    14291468
     
    16811720
    16821721/**
     1722 * Sets up the quick zero & copy tables for the non-native module.
     1723 *
     1724 * This is a worker for kwLdrModuleCreateNonNative.
     1725 *
     1726 * @param   pMod                The module.
     1727 */
     1728static void kwLdrModuleCreateNonNativeSetupQuickZeroAndCopy(PKWMODULE pMod)
     1729{
     1730    PCKLDRSEG   paSegs = pMod->pLdrMod->aSegments;
     1731    KU32        cSegs  = pMod->pLdrMod->cSegments;
     1732    KU32        iSeg;
     1733
     1734    KWLDR_LOG(("Setting up quick zero & copy for %s:\n", pMod->pszPath));
     1735    pMod->u.Manual.cQuickCopyChunks = 0;
     1736    pMod->u.Manual.cQuickZeroChunks = 0;
     1737
     1738    for (iSeg = 0; iSeg < cSegs; iSeg++)
     1739        switch (paSegs[iSeg].enmProt)
     1740        {
     1741            case KPROT_READWRITE:
     1742            case KPROT_WRITECOPY:
     1743            case KPROT_EXECUTE_READWRITE:
     1744            case KPROT_EXECUTE_WRITECOPY:
     1745                if (paSegs[iSeg].cbMapped)
     1746                {
     1747                    KU32 iChunk = pMod->u.Manual.cQuickCopyChunks;
     1748                    if (iChunk < K_ELEMENTS(pMod->u.Manual.aQuickCopyChunks))
     1749                    {
     1750                        /*
     1751                         * Check for trailing zero words.
     1752                         */
     1753                        KSIZE cbTrailingZeros;
     1754                        if (   paSegs[iSeg].cbMapped >= 64 * 2 * sizeof(KSIZE)
     1755                            && (paSegs[iSeg].cbMapped & 7) == 0
     1756                            && pMod->u.Manual.cQuickZeroChunks < K_ELEMENTS(pMod->u.Manual.aQuickZeroChunks) )
     1757                        {
     1758                            KSIZE const *pauNatural   = (KSIZE const *)&pMod->u.Manual.pbCopy[(KSIZE)paSegs[iSeg].RVA];
     1759                            KSIZE        cNatural     = paSegs[iSeg].cbMapped / sizeof(KSIZE);
     1760                            KSIZE        idxFirstZero = cNatural;
     1761                            while (idxFirstZero > 0)
     1762                                if (pauNatural[--idxFirstZero] == 0)
     1763                                { /* likely */ }
     1764                                else
     1765                                {
     1766                                    idxFirstZero++;
     1767                                    break;
     1768                                }
     1769                            cbTrailingZeros = (cNatural - idxFirstZero) * sizeof(KSIZE);
     1770                            if (cbTrailingZeros < 128)
     1771                                cbTrailingZeros = 0;
     1772                        }
     1773                        else
     1774                            cbTrailingZeros = 0;
     1775
     1776                        /*
     1777                         * Add quick copy entry.
     1778                         */
     1779                        if (cbTrailingZeros < paSegs[iSeg].cbMapped)
     1780                        {
     1781                            pMod->u.Manual.aQuickCopyChunks[iChunk].pbDst    = &pMod->u.Manual.pbLoad[(KSIZE)paSegs[iSeg].RVA];
     1782                            pMod->u.Manual.aQuickCopyChunks[iChunk].pbSrc    = &pMod->u.Manual.pbCopy[(KSIZE)paSegs[iSeg].RVA];
     1783                            pMod->u.Manual.aQuickCopyChunks[iChunk].cbToCopy = paSegs[iSeg].cbMapped - cbTrailingZeros;
     1784                            pMod->u.Manual.cQuickCopyChunks = iChunk + 1;
     1785                            KWLDR_LOG(("aQuickCopyChunks[%u]: %#p LB %#" KSIZE_PRI " <- %p (%*.*s)\n", iChunk,
     1786                                       pMod->u.Manual.aQuickCopyChunks[iChunk].pbDst,
     1787                                       pMod->u.Manual.aQuickCopyChunks[iChunk].cbToCopy,
     1788                                       pMod->u.Manual.aQuickCopyChunks[iChunk].pbSrc,
     1789                                       paSegs[iSeg].cchName, paSegs[iSeg].cchName, paSegs[iSeg].pchName));
     1790                        }
     1791
     1792                        /*
     1793                         * Add quick zero entry.
     1794                         */
     1795                        if (cbTrailingZeros)
     1796                        {
     1797                            KU32 iZero = pMod->u.Manual.cQuickZeroChunks;
     1798                            pMod->u.Manual.aQuickZeroChunks[iZero].pbDst    = pMod->u.Manual.aQuickCopyChunks[iChunk].pbDst
     1799                                                                            + pMod->u.Manual.aQuickCopyChunks[iChunk].cbToCopy;
     1800                            pMod->u.Manual.aQuickZeroChunks[iZero].cbToZero = cbTrailingZeros;
     1801                            pMod->u.Manual.cQuickZeroChunks = iZero + 1;
     1802                            KWLDR_LOG(("aQuickZeroChunks[%u]: %#p LB %#" KSIZE_PRI " <- zero (%*.*s)\n", iZero,
     1803                                       pMod->u.Manual.aQuickZeroChunks[iZero].pbDst,
     1804                                       pMod->u.Manual.aQuickZeroChunks[iZero].cbToZero,
     1805                                       paSegs[iSeg].cchName, paSegs[iSeg].cchName, paSegs[iSeg].pchName));
     1806                        }
     1807                    }
     1808                    else
     1809                    {
     1810                        /*
     1811                         * We're out of quick copy table entries, so just copy the whole darn thing.
     1812                         * We cannot 104% guarantee that the segments are in mapping order, so this is simpler.
     1813                         */
     1814                        kHlpAssertFailed();
     1815                        pMod->u.Manual.aQuickCopyChunks[0].pbDst    = pMod->u.Manual.pbLoad;
     1816                        pMod->u.Manual.aQuickCopyChunks[0].pbSrc    = pMod->u.Manual.pbCopy;
     1817                        pMod->u.Manual.aQuickCopyChunks[0].cbToCopy = pMod->cbImage;
     1818                        pMod->u.Manual.cQuickCopyChunks = 1;
     1819                        KWLDR_LOG(("Quick copy not possible!\n"));
     1820                        return;
     1821                    }
     1822                }
     1823                break;
     1824
     1825            default:
     1826                break;
     1827        }
     1828}
     1829
     1830
     1831/**
    16831832 * Creates a module using the our own loader.
    16841833 *
     
    17451894                    pMod->pLdrMod       = pLdrMod;
    17461895                    pMod->u.Manual.cImpMods = (KU32)cImports;
    1747                     pMod->u.Manual.fUseLdBuf = K_FALSE;
    17481896#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
    17491897                    pMod->u.Manual.fRegisteredFunctionTable = K_FALSE;
    17501898#endif
     1899                    pMod->u.Manual.fUseLdBuf = K_FALSE;
     1900                    pMod->u.Manual.fCanDoQuick = K_FALSE;
     1901                    pMod->u.Manual.cQuickZeroChunks = 0;
     1902                    pMod->u.Manual.cQuickCopyChunks = 0;
    17511903                    pMod->pszPath       = (char *)kHlpMemCopy(&pMod->u.Manual.apImpMods[cImports + 1], pszPath, cbPath);
    17521904                    pMod->pwszPath      = (wchar_t *)(pMod->pszPath + cbPath + (cbPath & 1));
     
    17581910                    fFixed = pLdrMod->enmType == KLDRTYPE_EXECUTABLE_FIXED
    17591911                          || pLdrMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED;
    1760                     pMod->u.Manual.pvLoad = fFixed ? (void *)(KUPTR)pLdrMod->aSegments[0].LinkAddress : NULL;
     1912                    pMod->u.Manual.pbLoad = fFixed ? (KU8 *)(KUPTR)pLdrMod->aSegments[0].LinkAddress : NULL;
    17611913                    pMod->cbImage = (KSIZE)kLdrModSize(pLdrMod);
    17621914                    if (   !fFixed
    17631915                        || pLdrMod->enmType != KLDRTYPE_EXECUTABLE_FIXED /* only allow fixed executables */
    1764                         || (KUPTR)pMod->u.Manual.pvLoad - (KUPTR)g_abDefLdBuf >= sizeof(g_abDefLdBuf)
    1765                         || sizeof(g_abDefLdBuf) - (KUPTR)pMod->u.Manual.pvLoad - (KUPTR)g_abDefLdBuf < pMod->cbImage)
    1766                         rc = kHlpPageAlloc(&pMod->u.Manual.pvLoad, pMod->cbImage, KPROT_EXECUTE_READWRITE, fFixed);
     1916                        || (KUPTR)pMod->u.Manual.pbLoad - (KUPTR)g_abDefLdBuf >= sizeof(g_abDefLdBuf)
     1917                        || sizeof(g_abDefLdBuf) - (KUPTR)pMod->u.Manual.pbLoad - (KUPTR)g_abDefLdBuf < pMod->cbImage)
     1918                        rc = kHlpPageAlloc((void **)&pMod->u.Manual.pbLoad, pMod->cbImage, KPROT_EXECUTE_READWRITE, fFixed);
    17671919                    else
    17681920                        pMod->u.Manual.fUseLdBuf = K_TRUE;
    17691921                    if (rc == 0)
    17701922                    {
    1771                         rc = kHlpPageAlloc(&pMod->u.Manual.pvCopy, pMod->cbImage, KPROT_READWRITE, K_FALSE);
     1923                        rc = kHlpPageAlloc(&pMod->u.Manual.pbCopy, pMod->cbImage, KPROT_READWRITE, K_FALSE);
    17721924                        if (rc == 0)
    17731925                        {
    1774 
    17751926                            KI32 iImp;
    17761927
     
    17781929                             * Link the module (unless it's an executable image) and process the imports.
    17791930                             */
    1780                             pMod->hOurMod = (HMODULE)pMod->u.Manual.pvLoad;
     1931                            pMod->hOurMod = (HMODULE)pMod->u.Manual.pbLoad;
    17811932                            if (!fExe)
    17821933                                kwLdrModuleLink(pMod);
    17831934                            KW_LOG(("New module: %p LB %#010x %s (kLdr)\n",
    1784                                     pMod->u.Manual.pvLoad, pMod->cbImage, pMod->pszPath));
    1785                             kwDebuggerPrintf("TODO: .reload /f %s=%p\n", pMod->pszPath, pMod->u.Manual.pvLoad);
     1935                                    pMod->u.Manual.pbLoad, pMod->cbImage, pMod->pszPath));
     1936                            kwDebuggerPrintf("TODO: .reload /f %s=%p\n", pMod->pszPath, pMod->u.Manual.pbLoad);
    17861937
    17871938                            for (iImp = 0; iImp < cImports; iImp++)
     
    18001951                            if (rc == 0)
    18011952                            {
    1802                                 rc = kLdrModGetBits(pLdrMod, pMod->u.Manual.pvCopy, (KUPTR)pMod->u.Manual.pvLoad,
     1953                                rc = kLdrModGetBits(pLdrMod, pMod->u.Manual.pbCopy, (KUPTR)pMod->u.Manual.pbLoad,
    18031954                                                    kwLdrModuleGetImportCallback, pMod);
    18041955                                if (rc == 0)
     
    18091960                                     * loader did that already, right...
    18101961                                     */
    1811                                     KU8                        *pbImg = (KU8 *)pMod->u.Manual.pvCopy;
     1962                                    KU8                        *pbImg = (KU8 *)pMod->u.Manual.pbCopy;
    18121963                                    IMAGE_NT_HEADERS const     *pNtHdrs;
    18131964                                    IMAGE_DATA_DIRECTORY const *pXcptDir;
     
    18321983#endif
    18331984
     1985                                    kwLdrModuleCreateNonNativeSetupQuickZeroAndCopy(pMod);
     1986
    18341987                                    /*
    18351988                                     * Final finish.
    18361989                                     */
    1837                                     pMod->u.Manual.pvBits = pMod->u.Manual.pvCopy;
     1990                                    pMod->u.Manual.pvBits = pMod->u.Manual.pbCopy;
    18381991                                    pMod->u.Manual.enmState = KWMODSTATE_NEEDS_BITS;
    18391992                                    return pMod;
     
    18451998                        }
    18461999
    1847                         kHlpPageFree(pMod->u.Manual.pvLoad, pMod->cbImage);
     2000                        kHlpPageFree(pMod->u.Manual.pbLoad, pMod->cbImage);
    18482001                        kwErrPrintf("Failed to allocate %#x bytes\n", pMod->cbImage);
    18492002                    }
     
    18792032                                puValue, pfKind);
    18802033    else
    1881         rc = kLdrModQuerySymbol(pImpMod->pLdrMod, pImpMod->u.Manual.pvBits, (KUPTR)pImpMod->u.Manual.pvLoad,
     2034        rc = kLdrModQuerySymbol(pImpMod->pLdrMod, pImpMod->u.Manual.pvBits, (KUPTR)pImpMod->u.Manual.pbLoad,
    18822035                                iSymbol, pchSymbol, cchSymbol, pszVersion,
    18832036                                NULL /*pfnGetForwarder*/, NULL /*pvUSer*/,
     
    19202073{
    19212074    KLDRADDR uLdrAddrMain;
    1922     int rc = kLdrModQueryMainEntrypoint(pMod->pLdrMod,  pMod->u.Manual.pvBits, (KUPTR)pMod->u.Manual.pvLoad, &uLdrAddrMain);
     2075    int rc = kLdrModQueryMainEntrypoint(pMod->pLdrMod, pMod->u.Manual.pvBits, (KUPTR)pMod->u.Manual.pbLoad, &uLdrAddrMain);
    19232076    if (rc == 0)
    19242077    {
     
    21522305    if (!pMod->fNative)
    21532306    {
    2154         /* Need to copy bits? */
     2307        /*
     2308         * Need to copy bits?
     2309         */
    21552310        if (pMod->u.Manual.enmState == KWMODSTATE_NEEDS_BITS)
    21562311        {
     
    21642319                }
    21652320#endif
     2321                g_pModPrevInLdBuf = g_pModInLdBuf;
    21662322                g_pModInLdBuf = pMod;
    21672323            }
    21682324
    2169             kHlpMemCopy(pMod->u.Manual.pvLoad, pMod->u.Manual.pvCopy, pMod->cbImage);
     2325            /* Do quick zeroing and copying when we can. */
     2326            pMod->u.Manual.fCanDoQuick = K_FALSE;
     2327            if (   pMod->u.Manual.fCanDoQuick
     2328                && (   !pMod->u.Manual.fUseLdBuf
     2329                    || g_pModPrevInLdBuf == pMod))
     2330            {
     2331                /* Zero first. */
     2332                kHlpAssert(pMod->u.Manual.cQuickZeroChunks <= 3);
     2333                switch (pMod->u.Manual.cQuickZeroChunks)
     2334                {
     2335                    case 3: kHlpMemSet(pMod->u.Manual.aQuickZeroChunks[2].pbDst, 0, pMod->u.Manual.aQuickZeroChunks[2].cbToZero);
     2336                    case 2: kHlpMemSet(pMod->u.Manual.aQuickZeroChunks[1].pbDst, 0, pMod->u.Manual.aQuickZeroChunks[1].cbToZero);
     2337                    case 1: kHlpMemSet(pMod->u.Manual.aQuickZeroChunks[0].pbDst, 0, pMod->u.Manual.aQuickZeroChunks[0].cbToZero);
     2338                    case 0: break;
     2339                }
     2340
     2341                /* Then copy. */
     2342                kHlpAssert(pMod->u.Manual.cQuickCopyChunks > 0);
     2343                kHlpAssert(pMod->u.Manual.cQuickCopyChunks <= 3);
     2344                switch (pMod->u.Manual.cQuickCopyChunks)
     2345                {
     2346                    case 3: kHlpMemCopy(pMod->u.Manual.aQuickCopyChunks[2].pbDst, pMod->u.Manual.aQuickCopyChunks[2].pbSrc,
     2347                                        pMod->u.Manual.aQuickCopyChunks[2].cbToCopy);
     2348                    case 2: kHlpMemCopy(pMod->u.Manual.aQuickCopyChunks[1].pbDst, pMod->u.Manual.aQuickCopyChunks[1].pbSrc,
     2349                                        pMod->u.Manual.aQuickCopyChunks[1].cbToCopy);
     2350                    case 1: kHlpMemCopy(pMod->u.Manual.aQuickCopyChunks[0].pbDst, pMod->u.Manual.aQuickCopyChunks[0].pbSrc,
     2351                                        pMod->u.Manual.aQuickCopyChunks[0].cbToCopy);
     2352                    case 0: break;
     2353                }
     2354            }
     2355            /* Must copy the whole image. */
     2356            else
     2357            {
     2358                kHlpMemCopy(pMod->u.Manual.pbLoad, pMod->u.Manual.pbCopy, pMod->cbImage);
     2359                pMod->u.Manual.fCanDoQuick = K_TRUE;
     2360            }
    21702361            pMod->u.Manual.enmState = KWMODSTATE_NEEDS_INIT;
    21712362        }
    21722363
    21732364#if defined(KBUILD_OS_WINDOWS) && defined(KBUILD_ARCH_AMD64)
    2174         /* Need to register function table? */
     2365        /*
     2366         * Need to register function table?
     2367         */
    21752368        if (   !pMod->u.Manual.fRegisteredFunctionTable
    21762369            && pMod->u.Manual.cFunctions > 0)
     
    21782371            pMod->u.Manual.fRegisteredFunctionTable = RtlAddFunctionTable(pMod->u.Manual.paFunctions,
    21792372                                                                          pMod->u.Manual.cFunctions,
    2180                                                                           (KUPTR)pMod->u.Manual.pvLoad) != FALSE;
     2373                                                                          (KUPTR)pMod->u.Manual.pbLoad) != FALSE;
    21812374            kHlpAssert(pMod->u.Manual.fRegisteredFunctionTable);
    21822375        }
     
    21852378        if (pMod->u.Manual.enmState == KWMODSTATE_NEEDS_INIT)
    21862379        {
    2187             /* Must do imports first, but mark our module as being initialized to avoid
    2188                endless recursion should there be a dependency loop. */
     2380            /*
     2381             * Must do imports first, but mark our module as being initialized to avoid
     2382             * endless recursion should there be a dependency loop.
     2383             */
    21892384            KSIZE iImp;
    21902385            pMod->u.Manual.enmState = KWMODSTATE_BEING_INITED;
     
    21972392            }
    21982393
    2199             rc = kLdrModCallInit(pMod->pLdrMod, pMod->u.Manual.pvLoad, (KUPTR)pMod->u.Manual.pvLoad);
     2394            rc = kLdrModCallInit(pMod->pLdrMod, pMod->u.Manual.pbLoad, (KUPTR)pMod->hOurMod);
    22002395            if (rc == 0)
    22012396                pMod->u.Manual.enmState = KWMODSTATE_READY;
     
    40814276        int rc = kLdrModQuerySymbol(pMod->pLdrMod,
    40824277                                    pMod->fNative ? NULL : pMod->u.Manual.pvBits,
    4083                                     pMod->fNative ? KLDRMOD_BASEADDRESS_MAP : (KUPTR)pMod->u.Manual.pvLoad,
     4278                                    pMod->fNative ? KLDRMOD_BASEADDRESS_MAP : (KUPTR)pMod->u.Manual.pbLoad,
    40844279                                    KU32_MAX /*iSymbol*/,
    40854280                                    pszProc,
     
    82718466            __except (EXCEPTION_EXECUTE_HANDLER)
    82728467            {
     8468                kwErrPrintf("Caught exception %#x!\n", GetExceptionCode());
    82738469                rcExit = 512;
    82748470            }
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