Changeset 2857 for trunk/kLdr/kLdrModPE.c
- Timestamp:
- Nov 5, 2006, 5:12:13 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModPE.c
r2856 r2857 59 59 #define KLDRMODPE_RVA2TYPE(pvBits, uRVA, type) \ 60 60 ( (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 ) 61 70 62 71 … … 93 102 * Internal Functions * 94 103 *******************************************************************************/ 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);102 104 static 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); 105 static int kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 106 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 107 108 static int kldrModPEDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODPE *ppMod); 109 static void kldrModPEDoLoadConfigConversion(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg); 110 static int kLdrModPEDoOptionalHeaderValidation(PKLDRMODPE pModPE); 111 static int kLdrModPEDoSectionHeadersValidation(PKLDRMODPE pModPE); 112 static void kldrModPEDoOptionalHeaderConversion(PIMAGE_OPTIONAL_HEADER64 pOptionalHeader); 113 static int kldrModPEDoForwarderQuery(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder, 114 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); 117 static int kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress); 118 static int kldrModPEDoImports32Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc, 119 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 120 static int kldrModPEDoImports64Bit(PKLDRMODPE pModPE, void *pvMapping, const IMAGE_IMPORT_DESCRIPTOR *pImpDesc, 121 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 122 static int kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 123 static int kldrModPEDoImportsFor32BitArch(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 124 static int kldrModPEDoImportsFor64BitArch(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 125 static int kldrModPEDoCallDLL(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle); 126 static int kldrModPEDoCallTLS(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle); 127 static int32_t kldrModPEDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved); 111 128 112 129 … … 130 147 * Create the instance data and do a minimal header validation. 131 148 */ 132 rc = kldrModPE CreateInstance(pRdr, offNewHdr, &pModPE);149 rc = kldrModPEDoCreate(pRdr, offNewHdr, &pModPE); 133 150 if (!rc) 134 151 { … … 147 164 * simplify cleanup on failure. 148 165 */ 149 static int kldrModPE CreateInstance(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODPE *ppModPE)166 static int kldrModPEDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODPE *ppModPE) 150 167 { 151 168 struct … … 245 262 return rc; 246 263 if (pModPE->Hdrs.FileHeader.SizeOfOptionalHeader != sizeof(pModPE->Hdrs.OptionalHeader)) 247 kldrModPE ConvertOptionalHeader(&pModPE->Hdrs.OptionalHeader);264 kldrModPEDoOptionalHeaderConversion(&pModPE->Hdrs.OptionalHeader); 248 265 off += pModPE->Hdrs.FileHeader.SizeOfOptionalHeader; 249 266 rc = kLdrRdrRead(pRdr, &pModPE->aShdrs[0], sizeof(IMAGE_SECTION_HEADER) * pModPE->Hdrs.FileHeader.NumberOfSections, off); … … 254 271 * Validate the two. 255 272 */ 256 rc = kLdrModPE ValidateOptionalHeader(pModPE);273 rc = kLdrModPEDoOptionalHeaderValidation(pModPE); 257 274 if (rc) 258 275 return rc; 259 276 for (i = 0; i < pModPE->Hdrs.FileHeader.NumberOfSections; i++) 260 277 { 261 rc = kLdrModPE ValidateSectionHeaders(pModPE);278 rc = kLdrModPEDoSectionHeadersValidation(pModPE); 262 279 if (rc) 263 280 return rc; … … 364 381 365 382 /** 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.Magic374 != (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 /**393 383 * Converts a 32-bit optional header to a 64-bit one 394 384 * 395 385 * @param pOptHdr The optional header to convert. 396 386 */ 397 static void kldrModPE ConvertOptionalHeader(PIMAGE_OPTIONAL_HEADER64 pOptHdr)387 static void kldrModPEDoOptionalHeaderConversion(PIMAGE_OPTIONAL_HEADER64 pOptHdr) 398 388 { 399 389 /* volatile everywhere! */ … … 434 424 * @param pOptHdr The load config to convert. 435 425 */ 436 static void kldrModPE ConvertLoadConfig(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg)426 static void kldrModPEDoLoadConfigConversion(PIMAGE_LOAD_CONFIG_DIRECTORY64 pLoadCfg) 437 427 { 438 428 /* volatile everywhere! */ … … 461 451 462 452 453 /** 454 * Internal worker which validates the section headers. 455 */ 456 static 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 */ 473 static int kLdrModPEDoSectionHeadersValidation(PKLDRMODPE pModPE) 474 { 475 /** @todo validate shdrs */ 476 return 0; 477 } 478 479 463 480 /** @copydoc KLDRMODOPS::pfnDestroy */ 464 481 static int kldrModPEDestroy(PKLDRMOD pMod) … … 504 521 * @returns 0 on success, non-zero OS or kLdr status code on failure. 505 522 * @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 */ 525 static int kldrModPEDoUnmap(PKLDRMODPE pModPE, const void *pvMapping) 509 526 { 510 527 return -1; … … 648 665 if ( uRVA - pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 649 666 < pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) 650 return kldrModPE QueryForwarder(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); 652 669 653 670 /* … … 680 697 * @param pfKind Where to put the symbol kind. (optional) 681 698 */ 682 static int kldrModPE QueryForwarder(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder,683 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind)699 static int kldrModPEDoForwarderQuery(PKLDRMODPE pModPE, const void *pvBits, const char *pszForwarder, 700 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind) 684 701 { 685 702 const IMAGE_IMPORT_DESCRIPTOR *paImpDir; … … 1113 1130 * We've got a common worker which does this. 1114 1131 */ 1115 rc = kldrModPEDo Map(pModPE, 1 /* the real thing */);1132 rc = kldrModPEDoUnmap(pModPE, pModPE->pvMapping); 1116 1133 if (rc) 1117 1134 return rc; … … 1190 1207 pMod->aSegments[i].offFile, 1191 1208 pMod->aSegments[i].cbFile); 1192 1193 1209 return rc; 1194 1210 } … … 1215 1231 1216 1232 /* 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); 1222 1237 1223 1238 /* … … 1237 1252 1238 1253 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 */ 1261 static 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 */ 1317 static 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 */ 1372 static 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 */ 1536 static 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 */ 1566 static 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 */ 1630 static 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 1239 1680 /** @copydoc kLdrModCallInit */ 1240 1681 static int kldrModPECallInit(PKLDRMOD pMod, uintptr_t uHandle) … … 1260 1701 kldrModPEDoCallTLS(pModPE, DLL_PROCESS_DETACH, uHandle); 1261 1702 } 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 */ 1717 static 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 */ 1753 static 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 */ 1769 static 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 1262 1824 1263 1825 return rc; … … 1330 1892 1331 1893 /* 1894 * Zero the entire buffer first to simplify things. 1895 */ 1896 kLdrHlpMemSet(pvBits, 0, pModPE->Hdrs.OptionalHeader.SizeOfImage); 1897 1898 /* 1332 1899 * Iterate the segments and read the data within them. 1333 1900 */ 1334 1901 for (i = 0; i < pMod->cSegments; i++) 1335 1902 { 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; 1338 1915 } 1339 1916
Note:
See TracChangeset
for help on using the changeset viewer.