Ignore:
Timestamp:
Nov 10, 2006, 4:04:42 AM (19 years ago)
Author:
bird
Message:

Put the PE module interpreter thru the wringer and learnt how much the window file mapping API sucks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModPE.c

    r2860 r2861  
    113113static int  kldrModPEDoForwarderQuery(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,
    114114                                     PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind);
    115 static int  kldrModPEUnprotect(PKLDRMODPE pModPE, const void *pvMapping);
    116 static int  kldrModPEProtect(PKLDRMODPE pModPE, const void *pvMapping);
    117115static int  kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
    118116static int  kldrModPEDoImports32Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
     
    554552    unsigned    fFixed;
    555553    void       *pvBase;
    556     size_t      cb;
    557554    int         rc;
    558555    uint32_t    i;
    559556
    560557    /*
    561      * Prepare it.
    562      */
    563     /* size */
    564     cb = (size_t)pMod->pOps->pfnSize(pModPE->pMod);
    565     if (cb != pMod->pOps->pfnSize(pModPE->pMod))
    566         return KLDR_ERR_ADDRESS_OVERFLOW;
    567 
     558     * Map it.
     559     */
    568560    /* fixed image? */
    569561    fFixed = fForReal
     
    580572
    581573    /* try do the prepare */
    582     rc = kLdrRdrPrepare(pMod->pRdr, &pvBase, cb, fFixed);
     574    rc = kLdrRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed);
    583575    if (rc)
    584576        return rc;
    585577
    586578    /*
    587      * Map the segments (sub sections in PE terms).
    588      */
    589     for (i = 0; i < pMod->cSegments; i++)
    590     {
    591         void *pvSeg;
    592 
    593         if (!pMod->aSegments[i].Alignment)
    594             continue;
    595 
    596         pvSeg = (uint8_t *)pvBase + pMod->aSegments[i].RVA;
    597         rc = kLdrRdrMap(pMod->pRdr, pvSeg, pMod->aSegments[i].cbMapped, pMod->aSegments[i].enmProt,
    598                         pMod->aSegments[i].offFile, pMod->aSegments[i].cbFile);
    599         if (rc)
     579     * Update the segments with their map addresses.
     580     */
     581    if (fForReal)
     582    {
     583        for (i = 0; i < pMod->cSegments; i++)
    600584        {
    601             /* bailout */
    602             while (i-- > 0)
    603             {
    604                 if (!pMod->aSegments[i].Alignment)
    605                     continue;
    606 
    607                 kLdrRdrUnmap(pMod->pRdr, (void *)pMod->aSegments[i].MapAddress, pMod->aSegments[i].cbMapped);
    608                 pMod->aSegments[i].MapAddress = 0;
    609             }
    610             break;
     585            if (pMod->aSegments[i].RVA != NIL_KLDRADDR)
     586                pMod->aSegments[i].MapAddress = (uintptr_t)pvBase + (uintptr_t)pMod->aSegments[i].RVA;
    611587        }
    612         pMod->aSegments[i].MapAddress = (uintptr_t)pvSeg;
    613     }
    614 
    615     if (!rc)
    616     {
    617         if (fForReal)
    618             pModPE->pvMapping = pvBase;
    619         else
    620             pModPE->pvBits = pvBase;
     588        pModPE->pvMapping = pvBase;
    621589    }
    622590    else
    623         kLdrRdrUnprepare(pMod->pRdr, pvBase, cb);
    624     return rc;
     591        pModPE->pvBits = pvBase;
     592    return 0;
    625593}
    626594
     
    640608    PKLDRMOD    pMod = pModPE->pMod;
    641609    size_t      cb = (size_t)pMod->pOps->pfnSize(pModPE->pMod);
    642     int         rc2;
    643     int         rc = 0;
     610    int         rc;
    644611    uint32_t    i;
    645612
    646613    /*
    647      * Unmap the segments (sub sections in PE terms).
    648      */
    649     for (i = 0; i < pMod->cSegments; i++)
    650     {
    651         if (!pMod->aSegments[i].MapAddress)
    652             continue;
    653 
    654         rc2 = kLdrRdrUnmap(pMod->pRdr, (void *)pMod->aSegments[i].MapAddress, pMod->aSegments[i].cbMapped);
    655         if (!rc2)
     614     * Try unmap the image.
     615     */
     616    rc = kLdrRdrUnmap(pMod->pRdr, (void *)pvMapping, pMod->cSegments, pMod->aSegments);
     617    if (rc)
     618        return rc;
     619
     620    /*
     621     * Update the segments to reflect that they aren't mapped any longer.
     622     */
     623    if (pModPE->pvMapping == pvMapping)
     624    {
     625        pModPE->pvMapping = NULL;
     626        for (i = 0; i < pMod->cSegments; i++)
    656627            pMod->aSegments[i].MapAddress = 0;
    657         else if (!rc)
    658             rc = rc2;
    659     }
    660 
    661     /*
    662      * 'Unprepare' the mapping region.
    663      */
    664     if (!rc)
    665     {
    666         rc = kLdrRdrUnprepare(pMod->pRdr, (void *)pvMapping, cb);
    667         if (!rc)
    668         {
    669             if (pModPE->pvBits == pvMapping)
    670                 pModPE->pvBits = NULL;
    671             if (pModPE->pvMapping == pvMapping)
    672                 pModPE->pvMapping = NULL;
    673         }
    674     }
    675 
    676     return rc;
     628    }
     629    if (pModPE->pvBits == pvMapping)
     630        pModPE->pvBits = NULL;
     631
     632    return 0;
    677633}
    678634
     
    717673        else
    718674        {
    719             /** @todo do an internal mapping. */
    720             rc = -1;
     675            /* create an internal mapping. */
     676            rc = kldrModPEDoMap(pModPE, 0 /* not for real */);
     677            if (rc)
     678                return rc;
     679            KLDRMODPE_ASSERT(pModPE->pvBits);
     680            *ppvBits = pModPE->pvBits;
    721681        }
    722682    }
     
    13361296static int kldrModPEReload(PKLDRMOD pMod)
    13371297{
    1338     PKLDRMODPE      pModPE = (PKLDRMODPE)pMod->pvData;
    1339     uint32_t        i;
    1340     int             rc;
    1341     const size_t    cbPage = kLdrRdrPageSize(pMod->pRdr);
     1298    PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData;
    13421299
    13431300    /*
     
    13471304        return KLDR_ERR_NOT_MAPPED;
    13481305
    1349     /*
    1350      * Iterate the objects and ask the file provider to undo all the changes.
    1351      */
    1352     for (i = rc = 0; !rc && i < pMod->cSegments; i++)
    1353         rc = kLdrRdrRefreshMap(pMod->pRdr,
    1354                                (void *)pMod->aSegments[i].MapAddress,
    1355                                (size_t)pMod->aSegments[i].cb,
    1356                                pMod->aSegments[i].enmProt,
    1357                                pMod->aSegments[i].offFile,
    1358                                pMod->aSegments[i].cbFile);
    1359     return rc;
     1306    /* the file provider does it all */
     1307    return kLdrRdrRefresh(pMod->pRdr, (void *)pModPE->pvMapping, pMod->cSegments, pMod->aSegments);
    13601308}
    13611309
     
    13761324     * Before doing anything we'll have to make all pages writable.
    13771325     */
    1378     rc = kldrModPEUnprotect(pModPE, pModPE->pvMapping);
     1326    rc = kLdrRdrProtect(pMod->pRdr, (void *)pModPE->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
    13791327    if (rc)
    13801328        return rc;
     
    13951343     * Restore protection.
    13961344     */
    1397     rc2 = kldrModPEProtect(pModPE, pModPE->pvMapping);
     1345    rc2 = kLdrRdrProtect(pMod->pRdr, (void *)pModPE->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
    13981346    if (!rc && rc2)
    13991347        rc = rc2;
    1400     return rc;
    1401 }
    1402 
    1403 
    1404 /**
    1405  * Make all segment writable so we can apply fixups and setup imports.
    1406  *
    1407  * @returns 0 on success, non-zero kLdrRdrProtect() status code on failure.
    1408  * @param   pModPE          The PE module interpreter instance.
    1409  * @param   pvMapping       The base mapping to unprotect.
    1410  */
    1411 static int  kldrModPEUnprotect(PKLDRMODPE pModPE, const void *pvMapping)
    1412 {
    1413     PKLDRMOD    pMod = pModPE->pMod;
    1414     int         rc;
    1415     uint32_t    i;
    1416 
    1417     /*
    1418      * Iterate the segments.
    1419      */
    1420     for (i = rc = 0; !rc && i < pMod->cSegments; i++)
    1421     {
    1422         KLDRPROT enmProt;
    1423 
    1424         /* Skip segments that aren't mapped. */
    1425         if (!pMod->aSegments[i].Alignment)
    1426             continue;
    1427 
    1428         /* calc writable protection and skip those which are already writable. */
    1429         enmProt = pMod->aSegments[i].enmProt;
    1430         switch (enmProt)
    1431         {
    1432             case KLDRPROT_NOACCESS:
    1433             case KLDRPROT_READWRITE:
    1434             case KLDRPROT_WRITECOPY:
    1435             case KLDRPROT_EXECUTE_READWRITE:
    1436             case KLDRPROT_EXECUTE_WRITECOPY:
    1437                 continue;
    1438             case KLDRPROT_READONLY:
    1439                 enmProt = KLDRPROT_WRITECOPY;
    1440                 break;
    1441             case KLDRPROT_EXECUTE:
    1442             case KLDRPROT_EXECUTE_READ:
    1443                 enmProt = KLDRPROT_EXECUTE_WRITECOPY;
    1444                 break;
    1445             default:
    1446                 KLDRMODPE_ASSERT(!"invalid");
    1447                 continue;
    1448         }
    1449 
    1450         rc = kLdrRdrProtect(pMod->pRdr,
    1451                             (uint8_t *)pvMapping + (pMod->aSegments[i].LinkAddress - pModPE->Hdrs.OptionalHeader.ImageBase),
    1452                             pMod->aSegments[i].cbMapped,
    1453                             enmProt);
    1454     }
    1455 
    1456     return rc;
    1457 }
    1458 
    1459 
    1460 /**
    1461  * Restore the correct protection for the segments after we're done with fixups and imports.
    1462  *
    1463  * @returns 0 on success, non-zero kLdrRdrProtect() status code on failure.
    1464  * @param   pModPE          The PE module interpreter instance.
    1465  * @param   pvMapping       The base mapping to unprotect.
    1466  */
    1467 static int  kldrModPEProtect(PKLDRMODPE pModPE, const void *pvMapping)
    1468 {
    1469     PKLDRMOD    pMod = pModPE->pMod;
    1470     int         rc;
    1471     uint32_t    i;
    1472 
    1473     /*
    1474      * Iterate the segments.
    1475      */
    1476     for (i = rc = 0; !rc && i < pMod->cSegments; i++)
    1477     {
    1478         KLDRPROT enmProt;
    1479 
    1480         /* Skip segments that aren't mapped. */
    1481         if (!pMod->aSegments[i].Alignment)
    1482             continue;
    1483 
    1484         /* Skip those which are already writable. */
    1485         enmProt = pMod->aSegments[i].enmProt;
    1486         switch (enmProt)
    1487         {
    1488             case KLDRPROT_NOACCESS:
    1489             case KLDRPROT_READWRITE:
    1490             case KLDRPROT_WRITECOPY:
    1491             case KLDRPROT_EXECUTE_READWRITE:
    1492             case KLDRPROT_EXECUTE_WRITECOPY:
    1493                 continue;
    1494             case KLDRPROT_READONLY:
    1495             case KLDRPROT_EXECUTE:
    1496             case KLDRPROT_EXECUTE_READ:
    1497                 break;
    1498             default:
    1499                 KLDRMODPE_ASSERT(!"invalid");
    1500                 continue;
    1501         }
    1502 
    1503         rc = kLdrRdrProtect(pMod->pRdr,
    1504                             (uint8_t *)pvMapping + (pMod->aSegments[i].LinkAddress - pModPE->Hdrs.OptionalHeader.ImageBase),
    1505                             pMod->aSegments[i].cbMapped,
    1506                             enmProt);
    1507     }
    1508 
    15091348    return rc;
    15101349}
Note: See TracChangeset for help on using the changeset viewer.