Ignore:
Timestamp:
Nov 5, 2006, 5:12:13 AM (19 years ago)
Author:
bird
Message:

Only the mapping left now.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModPE.c

    r2856 r2857  
    5959#define KLDRMODPE_RVA2TYPE(pvBits, uRVA, type) \
    6060        ( (type) ((uintptr_t)(pvBits) + (uRVA)) )
     61
     62/** @def KLDRMODPE_VALID_RVA
     63 * Checks that the specified RVA value is non-zero and within the bounds of the image.
     64 * @returns true/false.
     65 * @param   pModPE      The PE module interpreter instance.
     66 * @param   uRVA        The RVA to validate.
     67 */
     68#define KLDRMODPE_VALID_RVA(pModPE, uRVA) \
     69        ( (uRVA) && (uRVA) < (pModPE)->Hdrs.OptionalHeader.SizeOfImage )
    6170
    6271
     
    93102*   Internal Functions                                                         *
    94103*******************************************************************************/
    95 static int kldrModPECreateInstance(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODPE *ppMod);
    96 static void kldrModPEConvertLoadConfig(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg);
    97 static int kLdrModPEValidateOptionalHeader(PKLDRMODPE pModPE);
    98 static int kLdrModPEValidateSectionHeaders(PKLDRMODPE pModPE);
    99 static void kldrModPEConvertOptionalHeader(PIMAGE_OPTIONAL_HEADER64 pOptionalHeader);
    100 static int kldrModPEQueryForwarder(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,
    101                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind);
    102104static int32_t kldrModPENumberOfImports(PKLDRMOD pMod, const void *pvBits);
    103 static int kldrModPEUnprotect(PKLDRMODPE pModPE, const void *pvMapping);
    104 static int kldrModPEProtect(PKLDRMODPE pModPE, const void *pvMapping);
    105 static int kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
    106 static int kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
    107 static int kldrModPEDoCallDLL(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle);
    108 static int kldrModPEDoCallTLS(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle);
    109 static int kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
    110                                  PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     105static int  kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress,
     106                                  PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     107
     108static int  kldrModPEDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODPE *ppMod);
     109static void kldrModPEDoLoadConfigConversion(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg);
     110static int  kLdrModPEDoOptionalHeaderValidation(PKLDRMODPE pModPE);
     111static int  kLdrModPEDoSectionHeadersValidation(PKLDRMODPE pModPE);
     112static void kldrModPEDoOptionalHeaderConversion(PIMAGE_OPTIONAL_HEADER64 pOptionalHeader);
     113static int  kldrModPEDoForwarderQuery(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,
     114                                     PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind);
     115static int  kldrModPEUnprotect(PKLDRMODPE pModPE, const void *pvMapping);
     116static int  kldrModPEProtect(PKLDRMODPE pModPE, const void *pvMapping);
     117static int  kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
     118static int  kldrModPEDoImports32Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
     119                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     120static int  kldrModPEDoImports64Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
     121                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     122static int  kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     123static int  kldrModPEDoImportsFor32BitArch(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     124static int  kldrModPEDoImportsFor64BitArch(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     125static int  kldrModPEDoCallDLL(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle);
     126static int  kldrModPEDoCallTLS(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle);
     127static int32_t kldrModPEDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved);
    111128
    112129
     
    130147     * Create the instance data and do a minimal header validation.
    131148     */
    132     rc = kldrModPECreateInstance(pRdr, offNewHdr, &pModPE);
     149    rc = kldrModPEDoCreate(pRdr, offNewHdr, &pModPE);
    133150    if (!rc)
    134151    {
     
    147164 * simplify cleanup on failure.
    148165 */
    149 static int kldrModPECreateInstance(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODPE *ppModPE)
     166static int kldrModPEDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODPE *ppModPE)
    150167{
    151168    struct
     
    245262        return rc;
    246263    if (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader != sizeof(pModPE->Hdrs.OptionalHeader))
    247         kldrModPEConvertOptionalHeader(&pModPE->Hdrs.OptionalHeader);
     264        kldrModPEDoOptionalHeaderConversion(&pModPE->Hdrs.OptionalHeader);
    248265    off += pModPE->Hdrs.FileHeader.SizeOfOptionalHeader;
    249266    rc = kLdrRdrRead(pRdr, &pModPE->aShdrs[0], sizeof(IMAGE_SECTION_HEADER) * pModPE->Hdrs.FileHeader.NumberOfSections, off);
     
    254271     * Validate the two.
    255272     */
    256     rc = kLdrModPEValidateOptionalHeader(pModPE);
     273    rc = kLdrModPEDoOptionalHeaderValidation(pModPE);
    257274    if (rc)
    258275        return rc;
    259276    for (i = 0; i < pModPE->Hdrs.FileHeader.NumberOfSections; i++)
    260277    {
    261         rc = kLdrModPEValidateSectionHeaders(pModPE);
     278        rc = kLdrModPEDoSectionHeadersValidation(pModPE);
    262279        if (rc)
    263280            return rc;
     
    364381
    365382/**
    366  * Internal worker which validates the section headers.
    367  */
    368 static int kLdrModPEValidateOptionalHeader(PKLDRMODPE pModPE)
    369 {
    370     const unsigned fIs32Bit = pModPE->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32);
    371 
    372     /* the magic */
    373     if (    pModPE->Hdrs.OptionalHeader.Magic
    374         !=  (fIs32Bit ? IMAGE_NT_OPTIONAL_HDR32_MAGIC : IMAGE_NT_OPTIONAL_HDR64_MAGIC))
    375         return KLDR_ERR_PE_BAD_OPTIONAL_HEADER;
    376 
    377     /** @todo validate more */
    378     return 0;
    379 }
    380 
    381 
    382 /**
    383  * Internal worker which validates the section headers.
    384  */
    385 static int kLdrModPEValidateSectionHeaders(PKLDRMODPE pModPE)
    386 {
    387     /** @todo validate shdrs */
    388     return 0;
    389 }
    390 
    391 
    392 /**
    393383 * Converts a 32-bit optional header to a 64-bit one
    394384 *
    395385 * @param   pOptHdr     The optional header to convert.
    396386 */
    397 static void kldrModPEConvertOptionalHeader(PIMAGE_OPTIONAL_HEADER64 pOptHdr)
     387static void kldrModPEDoOptionalHeaderConversion(PIMAGE_OPTIONAL_HEADER64 pOptHdr)
    398388{
    399389    /* volatile everywhere! */
     
    434424 * @param   pOptHdr     The load config to convert.
    435425 */
    436 static void kldrModPEConvertLoadConfig(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg)
     426static void kldrModPEDoLoadConfigConversion(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg)
    437427{
    438428    /* volatile everywhere! */
     
    461451
    462452
     453/**
     454 * Internal worker which validates the section headers.
     455 */
     456static int kLdrModPEDoOptionalHeaderValidation(PKLDRMODPE pModPE)
     457{
     458    const unsigned fIs32Bit = pModPE->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32);
     459
     460    /* the magic */
     461    if (    pModPE->Hdrs.OptionalHeader.Magic
     462        !=  (fIs32Bit ? IMAGE_NT_OPTIONAL_HDR32_MAGIC : IMAGE_NT_OPTIONAL_HDR64_MAGIC))
     463        return KLDR_ERR_PE_BAD_OPTIONAL_HEADER;
     464
     465    /** @todo validate more */
     466    return 0;
     467}
     468
     469
     470/**
     471 * Internal worker which validates the section headers.
     472 */
     473static int kLdrModPEDoSectionHeadersValidation(PKLDRMODPE pModPE)
     474{
     475    /** @todo validate shdrs */
     476    return 0;
     477}
     478
     479
    463480/** @copydoc KLDRMODOPS::pfnDestroy */
    464481static int kldrModPEDestroy(PKLDRMOD pMod)
     
    504521 * @returns 0 on success, non-zero OS or kLdr status code on failure.
    505522 * @param   pModPE          The interpreter module instance
    506  * @param   fForReal        If set, unmap the user mapping. if clear, unmap the internal mapping.
    507  */
    508 static int kldrModPEDoUnmap(PKLDRMODPE pModPE, unsigned fForReal)
     523 * @param   pvMapping       The mapping to unmap.
     524 */
     525static int kldrModPEDoUnmap(PKLDRMODPE pModPE, const void *pvMapping)
    509526{
    510527    return -1;
     
    648665    if (    uRVA - pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
    649666        <   pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
    650         return kldrModPEQueryForwarder(pModPE, pvBits, KLDRMODPE_RVA2TYPE(pvBits, uRVA, const char *),
    651                                        pfnGetForwarder, pvUser, puValue, pfKind);
     667        return kldrModPEDoForwarderQuery(pModPE, pvBits, KLDRMODPE_RVA2TYPE(pvBits, uRVA, const char *),
     668                                         pfnGetForwarder, pvUser, puValue, pfKind);
    652669
    653670    /*
     
    680697 * @param   pfKind          Where to put the symbol kind. (optional)
    681698 */
    682 static int kldrModPEQueryForwarder(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,
    683                                    PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind)
     699static int kldrModPEDoForwarderQuery(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,
     700                                     PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind)
    684701{
    685702    const IMAGE_IMPORT_DESCRIPTOR *paImpDir;
     
    11131130     * We've got a common worker which does this.
    11141131     */
    1115     rc = kldrModPEDoMap(pModPE, 1 /* the real thing */);
     1132    rc = kldrModPEDoUnmap(pModPE, pModPE->pvMapping);
    11161133    if (rc)
    11171134        return rc;
     
    11901207                               pMod->aSegments[i].offFile,
    11911208                               pMod->aSegments[i].cbFile);
    1192 
    11931209    return rc;
    11941210}
     
    12151231
    12161232    /*
    1217      * Do we need to apply base relocations?
    1218      */
    1219     if (pModPE->Hdrs.OptionalHeader.ImageBase != (uintptr_t)pModPE->pvMapping)
    1220         rc = kldrModPEDoFixups(pModPE, (void *)pModPE->pvMapping, (uintptr_t)pModPE->pvMapping,
    1221                                pModPE->Hdrs.OptionalHeader.ImageBase);
     1233     * Apply base relocations.
     1234     */
     1235    rc = kldrModPEDoFixups(pModPE, (void *)pModPE->pvMapping, (uintptr_t)pModPE->pvMapping,
     1236                           pModPE->Hdrs.OptionalHeader.ImageBase);
    12221237
    12231238    /*
     
    12371252
    12381253
     1254/**
     1255 * Make all segment writable so we can apply fixups and setup imports.
     1256 *
     1257 * @returns 0 on success, non-zero kLdrRdrProtect() status code on failure.
     1258 * @param   pModPE          The PE module interpreter instance.
     1259 * @param   pvMapping       The base mapping to unprotect.
     1260 */
     1261static int  kldrModPEUnprotect(PKLDRMODPE pModPE, const void *pvMapping)
     1262{
     1263    PKLDRMOD    pMod = pModPE->pMod;
     1264    int         rc;
     1265    uint32_t    i;
     1266
     1267    /*
     1268     * Iterate the segments.
     1269     */
     1270    for (i = rc = 0; !rc && i < pMod->cSegments; i++)
     1271    {
     1272        KLDRPROT enmProt;
     1273
     1274        /* Skip segments that aren't mapped. */
     1275        if (!pMod->aSegments[i].Alignment)
     1276            continue;
     1277
     1278        /* calc writable protection and skip those which are already writable. */
     1279        enmProt = pMod->aSegments[i].enmProt;
     1280        switch (enmProt)
     1281        {
     1282            case KLDRPROT_NOACCESS:
     1283            case KLDRPROT_READWRITE:
     1284            case KLDRPROT_WRITECOPY:
     1285            case KLDRPROT_EXECUTE_READWRITE:
     1286            case KLDRPROT_EXECUTE_WRITECOPY:
     1287                continue;
     1288            case KLDRPROT_READONLY:
     1289                enmProt = KLDRPROT_WRITECOPY;
     1290                break;
     1291            case KLDRPROT_EXECUTE:
     1292            case KLDRPROT_EXECUTE_READ:
     1293                enmProt = KLDRPROT_EXECUTE_WRITECOPY;
     1294                break;
     1295            default:
     1296                KLDRMODPE_ASSERT(!"invalid");
     1297                continue;
     1298        }
     1299
     1300        rc = kLdrRdrProtect(pMod->pRdr,
     1301                            (uint8_t *)pvMapping + (pMod->aSegments[i].LinkAddress - pModPE->Hdrs.OptionalHeader.ImageBase),
     1302                            pMod->aSegments[i].cbMapped,
     1303                            enmProt);
     1304    }
     1305
     1306    return rc;
     1307}
     1308
     1309
     1310/**
     1311 * Restore the correct protection for the segments after we're done with fixups and imports.
     1312 *
     1313 * @returns 0 on success, non-zero kLdrRdrProtect() status code on failure.
     1314 * @param   pModPE          The PE module interpreter instance.
     1315 * @param   pvMapping       The base mapping to unprotect.
     1316 */
     1317static int  kldrModPEProtect(PKLDRMODPE pModPE, const void *pvMapping)
     1318{
     1319    PKLDRMOD    pMod = pModPE->pMod;
     1320    int         rc;
     1321    uint32_t    i;
     1322
     1323    /*
     1324     * Iterate the segments.
     1325     */
     1326    for (i = rc = 0; !rc && i < pMod->cSegments; i++)
     1327    {
     1328        KLDRPROT enmProt;
     1329
     1330        /* Skip segments that aren't mapped. */
     1331        if (!pMod->aSegments[i].Alignment)
     1332            continue;
     1333
     1334        /* Skip those which are already writable. */
     1335        enmProt = pMod->aSegments[i].enmProt;
     1336        switch (enmProt)
     1337        {
     1338            case KLDRPROT_NOACCESS:
     1339            case KLDRPROT_READWRITE:
     1340            case KLDRPROT_WRITECOPY:
     1341            case KLDRPROT_EXECUTE_READWRITE:
     1342            case KLDRPROT_EXECUTE_WRITECOPY:
     1343                continue;
     1344            case KLDRPROT_READONLY:
     1345            case KLDRPROT_EXECUTE:
     1346            case KLDRPROT_EXECUTE_READ:
     1347                break;
     1348            default:
     1349                KLDRMODPE_ASSERT(!"invalid");
     1350                continue;
     1351        }
     1352
     1353        rc = kLdrRdrProtect(pMod->pRdr,
     1354                            (uint8_t *)pvMapping + (pMod->aSegments[i].LinkAddress - pModPE->Hdrs.OptionalHeader.ImageBase),
     1355                            pMod->aSegments[i].cbMapped,
     1356                            enmProt);
     1357    }
     1358
     1359    return rc;
     1360}
     1361
     1362
     1363/**
     1364 * Applies base relocations to a (unprotected) image mapping.
     1365 *
     1366 * @returns 0 on success, non-zero kLdr status code on failure.
     1367 * @param   pModPE          The PE module interpreter instance.
     1368 * @param   pvMapping       The mapping to fixup.
     1369 * @param   NewBaseAddress  The address to fixup the mapping to.
     1370 * @param   OldBaseAddress  The address the mapping is currently fixed up to.
     1371 */
     1372static int  kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress)
     1373{
     1374    const KLDRADDR                  Delta = NewBaseAddress - OldBaseAddress;
     1375    uint32_t                        cbLeft = pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
     1376    const IMAGE_BASE_RELOCATION    *pBR, *pFirstBR;
     1377
     1378    /*
     1379     * Don't don anything if the delta is 0 or there aren't any relocations.
     1380     */
     1381    if (    !Delta
     1382        ||  !cbLeft
     1383        ||  !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
     1384        return 0;
     1385
     1386    /*
     1387     * Process the fixups block by block.
     1388     * (These blocks appears to be 4KB on all archs despite the native page size.)
     1389     */
     1390    pBR = pFirstBR = KLDRMODPE_RVA2TYPE(pvMapping,
     1391                                        pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
     1392                                        const IMAGE_BASE_RELOCATION *);
     1393    while (     cbLeft > sizeof(IMAGE_BASE_RELOCATION)
     1394           &&   pBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION) /* paranoia */)
     1395    {
     1396        union
     1397        {
     1398            uint8_t    *pu8;
     1399            uint16_t   *pu16;
     1400            uint32_t   *pu32;
     1401            uint64_t   *pu64;
     1402        }               uChunk,
     1403                        u;
     1404        const uint16_t *poffFixup = (const uint16_t *)(pBR + 1);
     1405        const uint32_t  cbBlock = KLDR_MIN(cbLeft, pBR->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION); /* more caution... */
     1406        uint32_t        cFixups = cbBlock / sizeof(poffFixup[0]);
     1407        uChunk.pu8 = KLDRMODPE_RVA2TYPE(pvMapping, pBR->VirtualAddress, uint8_t *);
     1408
     1409        /*
     1410         * Loop thru the fixups in this chunk.
     1411         */
     1412        while (cFixups > 0)
     1413        {
     1414            u.pu8 = uChunk.pu8 + (*poffFixup & 0xfff);
     1415            switch (*poffFixup >> 12) /* ordered by value. */
     1416            {
     1417                /* 0 - Alignment placeholder. */
     1418                case IMAGE_REL_BASED_ABSOLUTE:
     1419                    break;
     1420
     1421                /* 1 - 16-bit, add 2nd 16-bit part of the delta. (rare) */
     1422                case IMAGE_REL_BASED_HIGH:
     1423                    *u.pu16 += (uint16_t)(Delta >> 16);
     1424                    break;
     1425
     1426                /* 2 - 16-bit, add 1st 16-bit part of the delta. (rare) */
     1427                case IMAGE_REL_BASED_LOW:
     1428                    *u.pu16 += (uint16_t)Delta;
     1429                    break;
     1430
     1431                /* 3 - 32-bit, add delta. (frequent in 32-bit images) */
     1432                case IMAGE_REL_BASED_HIGHLOW:
     1433                    *u.pu32 += (uint32_t)Delta;
     1434                    break;
     1435
     1436                /* 4 - 16-bit, add 2nd 16-bit of the delta, sign adjust for the lower 16-bit. one arg. (rare)  */
     1437                case IMAGE_REL_BASED_HIGHADJ:
     1438                {
     1439                    int32_t i32;
     1440                    if (cFixups <= 1)
     1441                        return KLDR_ERR_PE_BAD_FIXUP;
     1442
     1443                    i32 = (uint32_t)*u.pu16 << 16;
     1444                    i32 |= *++poffFixup; cFixups--; /* the addend argument */
     1445                    i32 += (uint32_t)Delta;
     1446                    i32 += 0x8000;
     1447                    *u.pu16 = (uint16_t)(i32 >> 16);
     1448                    break;
     1449                }
     1450
     1451                /* 5 - 32-bit MIPS JMPADDR, no implemented. */
     1452                case IMAGE_REL_BASED_MIPS_JMPADDR:
     1453                    *u.pu32 = *u.pu32 & 0xc0000000
     1454                            | ((uint32_t)((*u.pu32 << 2) + (uint32_t)Delta) >> 2);
     1455                    break;
     1456
     1457                /* 6 - Intra section? Reserved value in later specs. Not implemented. */
     1458                case IMAGE_REL_BASED_SECTION:
     1459                    KLDRMODPE_ASSERT(!"SECTION");
     1460                    return KLDR_ERR_PE_BAD_FIXUP;
     1461
     1462                /* 7 - Relative intra section? Reserved value in later specs. Not implemented. */
     1463                case IMAGE_REL_BASED_REL32:
     1464                    KLDRMODPE_ASSERT(!"SECTION");
     1465                    return KLDR_ERR_PE_BAD_FIXUP;
     1466
     1467                /* 8 - reserved according to binutils... */
     1468                case 8:
     1469                    KLDRMODPE_ASSERT(!"RESERVERED8");
     1470                    return KLDR_ERR_PE_BAD_FIXUP;
     1471
     1472                /* 9 - IA64_IMM64 (/ MIPS_JMPADDR16), no specs nor need to support the platform yet.
     1473                 * Bet this requires more code than all the other fixups put together in good IA64 spirit :-) */
     1474                case IMAGE_REL_BASED_IA64_IMM64:
     1475                    KLDRMODPE_ASSERT(!"IA64_IMM64 / MIPS_JMPADDR16");
     1476                    return KLDR_ERR_PE_BAD_FIXUP;
     1477
     1478                /* 10 - 64-bit, add delta. (frequently in 64-bit images) */
     1479                case IMAGE_REL_BASED_DIR64:
     1480                    *u.pu64 += (uint64_t)Delta;
     1481                    break;
     1482
     1483                /* 11 - 16-bit, add 3rd 16-bit of the delta, sign adjust for the lower 32-bit. two args. (rare) */
     1484                case IMAGE_REL_BASED_HIGH3ADJ:
     1485                {
     1486                    int64_t i64;
     1487                    if (cFixups <= 2)
     1488                        return KLDR_ERR_PE_BAD_FIXUP;
     1489
     1490                    i64 = (uint64_t)*u.pu16 << 32
     1491                        | ((uint32_t)poffFixup[2] << 16)
     1492                        | poffFixup[1];
     1493                    i64 += Delta;
     1494                    i64 += 0x80008000UL;
     1495                    *u.pu16 = (uint16_t)(i64 >> 32);
     1496                    /* skip the addends arguments */
     1497                    poffFixup += 2;
     1498                    cFixups -= 2;
     1499                    break;
     1500                }
     1501
     1502                /* the rest are yet to be defined.*/
     1503                default:
     1504                    return KLDR_ERR_PE_BAD_FIXUP;
     1505            }
     1506
     1507            /*
     1508             * Next relocation.
     1509             */
     1510            poffFixup++;
     1511            cFixups--;
     1512        }
     1513
     1514
     1515        /*
     1516         * Next block.
     1517         */
     1518        cbLeft -= pBR->SizeOfBlock;
     1519        pBR = (PIMAGE_BASE_RELOCATION)((uintptr_t)pBR + pBR->SizeOfBlock);
     1520    }
     1521
     1522    return 0;
     1523}
     1524
     1525
     1526
     1527/**
     1528 * Resolves imports.
     1529 *
     1530 * @returns 0 on success, non-zero kLdr status code on failure.
     1531 * @param   pModPE          The PE module interpreter instance.
     1532 * @param   pvMapping       The mapping which imports should be resolved.
     1533 * @param   pfnGetImport    The callback for resolving an imported symbol.
     1534 * @param   pvUser          User argument to the callback.
     1535 */
     1536static int  kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
     1537{
     1538    const IMAGE_IMPORT_DESCRIPTOR *pImpDesc;
     1539
     1540    /*
     1541     * If no imports, there is nothing to do.
     1542     */
     1543    kldrModPENumberOfImports(pModPE->pMod, pvMapping);
     1544    if (!pModPE->cImportModules)
     1545        return 0;
     1546
     1547    pImpDesc = KLDRMODPE_RVA2TYPE(pvMapping,
     1548                                  pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,
     1549                                  const IMAGE_IMPORT_DESCRIPTOR *);
     1550    if (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32))
     1551        return kldrModPEDoImports32Bit(pModPE, pvMapping, pImpDesc, pfnGetImport, pvUser);
     1552    return kldrModPEDoImports64Bit(pModPE, pvMapping, pImpDesc, pfnGetImport, pvUser);
     1553}
     1554
     1555
     1556/**
     1557 * Resolves imports, 32-bit image.
     1558 *
     1559 * @returns 0 on success, non-zero kLdr status code on failure.
     1560 * @param   pModPE          The PE module interpreter instance.
     1561 * @param   pvMapping       The mapping which imports should be resolved.
     1562 * @param   pImpDesc        Pointer to the first import descriptor.
     1563 * @param   pfnGetImport    The callback for resolving an imported symbol.
     1564 * @param   pvUser          User argument to the callback.
     1565 */
     1566static int  kldrModPEDoImports32Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
     1567                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
     1568{
     1569    PKLDRMOD pMod = pModPE->pMod;
     1570    uint32_t iImp;
     1571
     1572    /*
     1573     * Iterate the import descriptors.
     1574     */
     1575    for (iImp = 0; iImp < pModPE->cImportModules; iImp++, pImpDesc++)
     1576    {
     1577        PIMAGE_THUNK_DATA32         pFirstThunk = KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, PIMAGE_THUNK_DATA32);
     1578        const IMAGE_THUNK_DATA32   *pThunk = pImpDesc->u.OriginalFirstThunk
     1579            ? KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->u.OriginalFirstThunk, const IMAGE_THUNK_DATA32 *)
     1580            : KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, const IMAGE_THUNK_DATA32 *);
     1581
     1582        /* Iterate the thunks. */
     1583        while (pThunk->u1.Ordinal != 0)
     1584        {
     1585            KLDRADDR    Value;
     1586            uint32_t    fKind;
     1587            int         rc;
     1588
     1589            /* Ordinal or name import? */
     1590            if (IMAGE_SNAP_BY_ORDINAL32(pThunk->u1.Ordinal))
     1591                rc = pfnGetImport(pMod, iImp, IMAGE_ORDINAL32(pThunk->u1.Ordinal), NULL, &Value, &fKind, pvUser);
     1592            else if (KLDRMODPE_VALID_RVA(pModPE, pThunk->u1.Ordinal))
     1593                rc = pfnGetImport(pMod, iImp, NIL_KLDRMOD_SYM_ORDINAL,
     1594                                  KLDRMODPE_RVA2TYPE(pvMapping, pThunk->u1.Ordinal, const char *),
     1595                                  &Value, &fKind, pvUser);
     1596            else
     1597            {
     1598                KLDRMODPE_ASSERT(!"bad 32-bit import");
     1599                return KLDR_ERR_PE_BAD_IMPORT;
     1600            }
     1601
     1602            /* Apply it. */
     1603            pFirstThunk->u1.Function = (uint32_t)Value;
     1604            if (pFirstThunk->u1.Function != Value)
     1605            {
     1606                KLDRMODPE_ASSERT(!"overflow");
     1607                return KLDR_ERR_ADDRESS_OVERFLOW;
     1608            }
     1609
     1610            /* next */
     1611            pThunk++;
     1612            pFirstThunk++;
     1613        }
     1614    }
     1615
     1616    return 0;
     1617}
     1618
     1619
     1620/**
     1621 * Resolves imports, 64-bit image.
     1622 *
     1623 * @returns 0 on success, non-zero kLdr status code on failure.
     1624 * @param   pModPE          The PE module interpreter instance.
     1625 * @param   pvMapping       The mapping which imports should be resolved.
     1626 * @param   pImpDesc        Pointer to the first import descriptor.
     1627 * @param   pfnGetImport    The callback for resolving an imported symbol.
     1628 * @param   pvUser          User argument to the callback.
     1629 */
     1630static int  kldrModPEDoImports64Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc,
     1631                                    PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
     1632{
     1633    PKLDRMOD pMod = pModPE->pMod;
     1634    uint32_t iImp;
     1635
     1636    /*
     1637     * Iterate the import descriptors.
     1638     */
     1639    for (iImp = 0; iImp < pModPE->cImportModules; iImp++, pImpDesc++)
     1640    {
     1641        PIMAGE_THUNK_DATA64         pFirstThunk = KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, PIMAGE_THUNK_DATA64);
     1642        const IMAGE_THUNK_DATA64   *pThunk = pImpDesc->u.OriginalFirstThunk
     1643            ? KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->u.OriginalFirstThunk, const IMAGE_THUNK_DATA64 *)
     1644            : KLDRMODPE_RVA2TYPE(pvMapping, pImpDesc->FirstThunk, const IMAGE_THUNK_DATA64 *);
     1645
     1646        /* Iterate the thunks. */
     1647        while (pThunk->u1.Ordinal != 0)
     1648        {
     1649            KLDRADDR    Value;
     1650            uint32_t    fKind;
     1651            int         rc;
     1652
     1653            /* Ordinal or name import? */
     1654            if (IMAGE_SNAP_BY_ORDINAL64(pThunk->u1.Ordinal))
     1655                rc = pfnGetImport(pMod, iImp, (uint32_t)IMAGE_ORDINAL64(pThunk->u1.Ordinal), NULL, &Value, &fKind, pvUser);
     1656            else if (KLDRMODPE_VALID_RVA(pModPE, pThunk->u1.Ordinal))
     1657                rc = pfnGetImport(pMod, iImp, NIL_KLDRMOD_SYM_ORDINAL,
     1658                                  KLDRMODPE_RVA2TYPE(pvMapping, pThunk->u1.Ordinal, const char *),
     1659                                  &Value, &fKind, pvUser);
     1660            else
     1661            {
     1662                KLDRMODPE_ASSERT(!"bad 64-bit import");
     1663                return KLDR_ERR_PE_BAD_IMPORT;
     1664            }
     1665
     1666            /* Apply it. */
     1667            pFirstThunk->u1.Function = Value;
     1668
     1669            /* next */
     1670            pThunk++;
     1671            pFirstThunk++;
     1672        }
     1673    }
     1674
     1675    return 0;
     1676}
     1677
     1678
     1679
    12391680/** @copydoc kLdrModCallInit */
    12401681static int kldrModPECallInit(PKLDRMOD pMod, uintptr_t uHandle)
     
    12601701            kldrModPEDoCallTLS(pModPE, DLL_PROCESS_DETACH, uHandle);
    12611702    }
     1703
     1704    return rc;
     1705}
     1706
     1707
     1708/**
     1709 * Call the DLL entrypoint.
     1710 *
     1711 * @returns 0 on success.
     1712 * @returns KLDR_ERR_MODULE_INIT_FAILED  or KLDR_ERR_THREAD_ATTACH_FAILED on failure.
     1713 * @param   pModPE          The PE module interpreter instance.
     1714 * @param   uOp             The operation (DLL_*).
     1715 * @param   uHandle         The module handle to present.
     1716 */
     1717static int  kldrModPEDoCallDLL(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle)
     1718{
     1719    int rc;
     1720
     1721    /*
     1722     * If no entrypoint there isn't anything to be done.
     1723     */
     1724    if (!pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint)
     1725        return 0;
     1726
     1727    /*
     1728     * Invoke the entrypoint and convert the boolean result to a kLdr status code.
     1729     */
     1730    rc = kldrModPEDoCall((uintptr_t)pModPE->pvMapping + pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint,
     1731                         uHandle, uOp, NULL);
     1732    if (rc)
     1733        rc = 0;
     1734    else if (uOp == DLL_PROCESS_ATTACH)
     1735        rc = KLDR_ERR_MODULE_INIT_FAILED;
     1736    else if (uOp == DLL_THREAD_ATTACH)
     1737        rc = KLDR_ERR_THREAD_ATTACH_FAILED;
     1738    else /* detach: ignore failures */
     1739        rc = 0;
     1740    return rc;
     1741}
     1742
     1743
     1744/**
     1745 * Call the TLS entrypoints.
     1746 *
     1747 * @returns 0 on success.
     1748 * @returns KLDR_ERR_THREAD_ATTACH_FAILED on failure.
     1749 * @param   pModPE          The PE module interpreter instance.
     1750 * @param   uOp             The operation (DLL_*).
     1751 * @param   uHandle         The module handle to present.
     1752 */
     1753static int  kldrModPEDoCallTLS(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle)
     1754{
     1755    /** @todo implement TLS support. */
     1756    return 0;
     1757}
     1758
     1759
     1760/**
     1761 * Do a 3 parameter callback.
     1762 *
     1763 * @returns 32-bit callback return.
     1764 * @param   uEntrypoint     The address of the function to be called.
     1765 * @param   uHandle         The first argument, the module handle.
     1766 * @param   uOp             The second argumnet, the reason we're calling.
     1767 * @param   pvReserved      The third argument, reserved argument. (figure this one out)
     1768 */
     1769static int32_t kldrModPEDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved)
     1770{
     1771    int32_t rc;
     1772
     1773/** @todo try/except */
     1774#if defined(__X86__) || defined(__i386__) || defined(_M_IX86)
     1775    /*
     1776     * Be very careful.
     1777     * Not everyone will have got the calling convention right.
     1778     */
     1779# ifdef __GNUC__
     1780    __asm__ __volatile__(
     1781        "pushl  %2\n\t"
     1782        "pushl  %1\n\t"
     1783        "pushl  %0\n\t"
     1784        "lea   12(%%esp), %2\n\t"
     1785        "call  *%3\n\t"
     1786        "movl   %2, %%esp\n\t"
     1787        : "=a" (rc)
     1788        : "d" (uOp),
     1789          "S" (0),
     1790          "c" (uEntrypoint),
     1791          "0" (uHandle));
     1792# elif defined(_MSC_VER)
     1793    __asm {
     1794        mov     eax, [uHandle]
     1795        mov     edx, [uOp]
     1796        mov     ecx, 0
     1797        mov     ebx, [uEntrypoint]
     1798        push    edi
     1799        mov     edi, esp
     1800        push    ecx
     1801        push    edx
     1802        push    eax
     1803        call    ebx
     1804        mov     esp, edi
     1805        pop     edi
     1806        mov     [rc], eax
     1807    }
     1808# else
     1809#  error "port me!"
     1810# endif
     1811
     1812#elif defined(__AMD64__) || defined(__x86_64__) || defined(_M_IX86)
     1813    /*
     1814     * For now, let's just get the work done...
     1815     */
     1816    /** @todo Deal with GCC / MSC differences in some sensible way. */
     1817    int (*pfn)(uintptr_t uHandle, uint32_t uOp, void *pvReserved);
     1818    pfn = (int (*)(uintptr_t uHandle, uint32_t uOp, void *pvReserved))uEntrypoint;
     1819    rc = pfn(uHandle, uOp, NULL);
     1820
     1821#else
     1822# error "port me"
     1823#endif
    12621824
    12631825    return rc;
     
    13301892
    13311893    /*
     1894     * Zero the entire buffer first to simplify things.
     1895     */
     1896    kLdrHlpMemSet(pvBits, 0, pModPE->Hdrs.OptionalHeader.SizeOfImage);
     1897
     1898    /*
    13321899     * Iterate the segments and read the data within them.
    13331900     */
    13341901    for (i = 0; i < pMod->cSegments; i++)
    13351902    {
    1336         /// @todo
    1337         rc = 0;
     1903        /* skip it? */
     1904        if (    pMod->aSegments[i].cbFile == -1
     1905            ||  pMod->aSegments[i].offFile == -1
     1906            ||  pMod->aSegments[i].LinkAddress == NIL_KLDRADDR
     1907            ||  !pMod->aSegments[i].Alignment)
     1908            continue;
     1909        rc = kLdrRdrRead(pMod->pRdr,
     1910                         (uint8_t *)pvBits + (pMod->aSegments[i].LinkAddress - pModPE->Hdrs.OptionalHeader.ImageBase),
     1911                         pMod->aSegments[i].cbFile,
     1912                         pMod->aSegments[i].offFile);
     1913        if (rc)
     1914            return rc;
    13381915    }
    13391916
Note: See TracChangeset for help on using the changeset viewer.