Changeset 62 for trunk/kLdr/kLdrModMachO.c
- Timestamp:
- Oct 16, 2013, 7:30:36 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModMachO.c
r61 r62 5 5 6 6 /* 7 * Copyright (c) 2006-20 07Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>7 * Copyright (c) 2006-2013 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net> 8 8 * 9 9 * Permission is hereby granted, free of charge, to any person … … 153 153 * This is 0 if not needed. */ 154 154 KU8 cbJmpStub; 155 /** When set the sections in the load command segments must be used when 156 * mapping or loading the image. */ 157 KBOOL fMapUsingLoadCommandSections; 155 /** Effective file type. If the original was a MH_OBJECT file, the 156 * corresponding MH_DSYM needs the segment translation of a MH_OBJECT too. 157 * The MH_DSYM normally has a separate __DWARF segment, but this is 158 * automatically skipped during the transation. */ 159 KU8 uEffFileType; 158 160 /** Pointer to the load commands. (endian converted) */ 159 161 KU8 *pbLoadCommands; … … 206 208 static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage, 207 209 KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, 208 PKBOOL pfCanLoad, PKLDRADDR pLinkAddress );210 PKBOOL pfCanLoad, PKLDRADDR pLinkAddress, KU8 *puEffFileType); 209 211 static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, KU32 cbStringPool); 210 212 static int kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress); … … 312 314 KLDRADDR LinkAddress; 313 315 KU8 cbJmpStub; 316 KU8 uEffFileType; 314 317 int rc; 315 318 *ppModMachO = NULL; … … 373 376 if (!rc) 374 377 rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, offImage, fOpenFlags, 375 &cSegments, &cSections, &cbStringPool, &fCanLoad, &LinkAddress );378 &cSegments, &cSections, &cbStringPool, &fCanLoad, &LinkAddress, &uEffFileType); 376 379 if (rc) 377 380 { … … 438 441 case CPU_SUBTYPE_XEON_MP: pMod->enmCpu = KCPU_P4; break; 439 442 break; 443 440 444 default: 445 /* Hack for kextutil output. */ 446 if ( s.Hdr32.cpusubtype == 0 447 && s.Hdr32.filetype == MH_OBJECT) 448 break; 441 449 return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE; 442 450 } … … 486 494 pModMachO->fMakeGot = fMakeGot; 487 495 pModMachO->cbJmpStub = cbJmpStub; 488 pModMachO-> fMapUsingLoadCommandSections = K_FALSE;496 pModMachO->uEffFileType = uEffFileType; 489 497 pModMachO->offSymbols = 0; 490 498 pModMachO->cSymbols = 0; … … 548 556 static int kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage, 549 557 KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, 550 PKBOOL pfCanLoad, PKLDRADDR pLinkAddress )558 PKBOOL pfCanLoad, PKLDRADDR pLinkAddress, KU8 *puEffFileType) 551 559 { 552 560 union … … 571 579 int fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 572 580 || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE; 581 KU8 uEffFileType = *puEffFileType = pHdr->filetype; 573 582 574 583 *pcSegments = 0; … … 627 636 #define VALIDATE_AND_ADD_SEGMENT(a_cBits) \ 628 637 do { \ 629 KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") /* Note: Not for non-object files. */ \ 638 KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") /* Note: Not for non-object files. */ \ 639 || ( !kHlpStrComp(pSrcSeg->segname, "__CTF") /* Their CTF tool did/does weird things, */ \ 640 && pSrcSeg->vmsize == 0) /* overlapping vmaddr and zero vmsize. */ \ 630 641 || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \ 642 \ 643 /* MH_DSYM files for MH_OBJECT files must have MH_OBJECT segment translation. */ \ 644 if ( uEffFileType == MH_DSYM \ 645 && cSegmentCommands == 0 \ 646 && pSrcSeg->segname[0] == '\0') \ 647 *puEffFileType = uEffFileType = MH_OBJECT; \ 631 648 \ 632 649 KLDRMODMACHO_CHECK_RETURN( pSrcSeg->filesize == 0 \ … … 634 651 && (KU64)pSrcSeg->fileoff + pSrcSeg->filesize <= cbFile), \ 635 652 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 636 KLDRMODMACHO_CHECK_RETURN(pSrcSeg->filesize <= pSrcSeg->vmsize, \ 653 KLDRMODMACHO_CHECK_RETURN( pSrcSeg->filesize <= pSrcSeg->vmsize \ 654 || (fSkipSeg && !kHlpStrComp(pSrcSeg->segname, "__CTF") /* see above */), \ 637 655 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 638 656 KLDRMODMACHO_CHECK_RETURN((pSrcSeg->maxprot & pSrcSeg->initprot) == pSrcSeg->initprot, \ … … 643 661 <= u.pLoadCmd->cmdsize - sizeof(segment_command_##a_cBits##_t), \ 644 662 KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \ 645 KLDRMODMACHO_CHECK_RETURN( pHdr->filetype != MH_OBJECT \ 646 || cSegmentCommands == 0,\ 663 KLDRMODMACHO_CHECK_RETURN( uEffFileType != MH_OBJECT \ 664 || cSegmentCommands == 0 \ 665 || ( cSegmentCommands == 1 \ 666 && uEffFileType == MH_OBJECT \ 667 && pHdr->filetype == MH_DSYM \ 668 && fSkipSeg), \ 647 669 KLDR_ERR_MACHO_BAD_OBJECT_FILE); \ 648 670 cSegmentCommands++; \ 649 671 \ 650 672 /* Add the segment, if not object file. */ \ 651 if (!fSkipSeg && pHdr->filetype != MH_OBJECT) \673 if (!fSkipSeg && uEffFileType != MH_OBJECT) \ 652 674 { \ 653 675 cbStringPool += kHlpStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)) + 1; \ … … 686 708 \ 687 709 /* validate */ \ 688 if ( pHdr->filetype != MH_OBJECT) \710 if (uEffFileType != MH_OBJECT) \ 689 711 KLDRMODMACHO_CHECK_RETURN(!kHlpStrComp(pSect->segname, pSrcSeg->segname),\ 690 712 KLDR_ERR_MACHO_BAD_SECTION); \ … … 776 798 if (fFileBits) \ 777 799 { \ 778 KLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \ 779 KLDR_ERR_MACHO_NON_CONT_SEG_BITS); \ 780 KLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \ 781 KLDR_ERR_MACHO_BAD_SECTION); \ 800 if (uEffFileType != MH_OBJECT) \ 801 { \ 802 KLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \ 803 KLDR_ERR_MACHO_NON_CONT_SEG_BITS); \ 804 KLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \ 805 KLDR_ERR_MACHO_BAD_SECTION); \ 806 } \ 782 807 KLDRMODMACHO_CHECK_RETURN(pSect->offset <= cbFile, \ 783 808 KLDR_ERR_MACHO_BAD_SECTION); \ … … 802 827 \ 803 828 /* Validate against file type (pointless?) and count the section, for object files add segment. */ \ 804 switch ( pHdr->filetype) \829 switch (uEffFileType) \ 805 830 { \ 806 831 case MH_OBJECT: \ … … 916 941 /* only one string in objects, please. */ 917 942 cSymbolTabs++; 918 if ( pHdr->filetype == MH_OBJECT943 if ( uEffFileType == MH_OBJECT 919 944 && cSymbolTabs != 1) 920 945 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_OBJECT_FILE); … … 1027 1052 KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND); 1028 1053 1029 switch ( pHdr->filetype)1054 switch (uEffFileType) 1030 1055 { 1031 1056 case MH_OBJECT: … … 1158 1183 * in the preparsing stage. \ 1159 1184 */ \ 1160 if (pModMachO-> Hdr.filetype != MH_OBJECT) \1185 if (pModMachO->uEffFileType != MH_OBJECT) \ 1161 1186 for (pSegItr = &pModMachO->pMod->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \ 1162 1187 if (!kHlpStrNComp(pSegItr->pchName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \ … … 1166 1191 * Create a new segment, unless we're supposed to skip this one. \ 1167 1192 */ \ 1168 if ( pModMachO-> Hdr.filetype != MH_OBJECT \1193 if ( pModMachO->uEffFileType != MH_OBJECT \ 1169 1194 && (cSectionsLeft == 0 || !(pFirstSect->flags & S_ATTR_DEBUG)) \ 1170 1195 && kHlpStrComp(pSrcSeg->segname, "__DWARF") ) \ … … 1183 1208 /* New segment if object file. */ \ 1184 1209 KBOOL fAddSegInner = K_FALSE; \ 1185 if ( pModMachO-> Hdr.filetype == MH_OBJECT \1210 if ( pModMachO->uEffFileType == MH_OBJECT \ 1186 1211 && !(pSect->flags & S_ATTR_DEBUG) \ 1187 1212 && kHlpStrComp(pSrcSeg->segname, "__DWARF") ) \ … … 1245 1270 1246 1271 case LC_SYMTAB: 1247 switch (pModMachO-> Hdr.filetype)1272 switch (pModMachO->uEffFileType) 1248 1273 { 1249 1274 case MH_OBJECT: … … 1512 1537 * Locate the segment. 1513 1538 */ 1514 iSeg = pMod->cSegments; 1515 if (!iSeg) 1539 if (!pMod->cSegments) 1516 1540 return KLDR_ERR_SYMBOL_NOT_FOUND; 1517 while ( pMod->aSegments[iSeg].cchName != cchSegName 1518 || kHlpMemComp(pMod->aSegments[iSeg].pchName, pchSegName, cchSegName) != 0) 1519 { 1520 if (!iSeg) 1521 return KLDR_ERR_SYMBOL_NOT_FOUND; 1522 iSeg--; 1523 } 1541 for (iSeg = 0; iSeg < pMod->cSegments; iSeg++) 1542 { 1543 if ( pMod->aSegments[iSeg].cchName >= cchSegName 1544 && kHlpMemComp(pMod->aSegments[iSeg].pchName, pchSegName, cchSegName) == 0) 1545 { 1546 section_32_t const *pSect; 1547 if ( pMod->aSegments[iSeg].cchName == cchSegName 1548 && pModMachO->Hdr.filetype != MH_OBJECT /* Good enough for __DWARF segs in MH_DHSYM, I hope. */) 1549 break; 1550 1551 pSect = (section_32_t *)pModMachO->aSegments[iSeg].paSections[0].pvMachoSection; 1552 if ( pModMachO->uEffFileType == MH_OBJECT 1553 && pMod->aSegments[iSeg].cchName > cchSegName + 1 1554 && pMod->aSegments[iSeg].pchName[cchSegName] == '.' 1555 && kHlpStrNComp(&pMod->aSegments[iSeg].pchName[cchSegName + 1], pSect->sectname, sizeof(pSect->sectname)) == 0 1556 && pMod->aSegments[iSeg].cchName - cchSegName - 1 <= sizeof(pSect->sectname) ) 1557 break; 1558 } 1559 } 1560 if (iSeg >= pMod->cSegments) 1561 return KLDR_ERR_SYMBOL_NOT_FOUND; 1524 1562 1525 1563 if (!s_aPrefixes[iPrefix].fSection) … … 1528 1566 * Calculate the segment start/end address. 1529 1567 */ 1530 uValue = pMod->aSegments[iSeg]. LinkAddress;1568 uValue = pMod->aSegments[iSeg].RVA; 1531 1569 if (!s_aPrefixes[iPrefix].fStart) 1532 1570 uValue += pMod->aSegments[iSeg].cb; … … 1554 1592 } 1555 1593 1556 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1557 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1558 { 1559 section_32_t *pSect = (section_32_t *)pModMachO->aSegments[iSeg].paSections[iSect].pvMachoSection; 1560 uValue = pSect->addr; 1561 if (!s_aPrefixes[iPrefix].fStart) 1562 uValue += pSect->size; 1563 } 1564 else 1565 { 1566 section_64_t *pSect = (section_64_t *)pModMachO->aSegments[iSeg].paSections[iSect].pvMachoSection; 1567 uValue = pSect->addr; 1568 if (!s_aPrefixes[iPrefix].fStart) 1569 uValue += pSect->size; 1570 } 1571 } 1572 1573 /* 1574 * Adjust the value from link to rva + base. 1575 */ 1576 uValue -= pMod->aSegments[iSeg].LinkAddress - pMod->aSegments[iSeg].RVA; 1594 uValue = pModMachO->aSegments[iSeg].paSections[iSect].RVA; 1595 if (!s_aPrefixes[iPrefix].fStart) 1596 uValue += pModMachO->aSegments[iSeg].paSections[iSect].cb; 1597 } 1598 1599 /* 1600 * Convert from RVA to load address. 1601 */ 1577 1602 uValue += BaseAddress; 1578 1603 if (puValue) … … 1753 1778 || ( paSyms[iSymbol].n_sect == 1 /* special hack for __mh_execute_header */ 1754 1779 && offSect == 0U - pSect->RVA 1755 && pModMachO-> Hdr.filetype != MH_OBJECT),1780 && pModMachO->uEffFileType != MH_OBJECT), 1756 1781 KLDR_ERR_MACHO_BAD_SYMBOL); 1757 1782 if (puValue) … … 1881 1906 || ( paSyms[iSymbol].n_sect == 1 /* special hack for __mh_execute_header */ 1882 1907 && offSect == 0U - pSect->RVA 1883 && pModMachO-> Hdr.filetype != MH_OBJECT),1908 && pModMachO->uEffFileType != MH_OBJECT), 1884 1909 KLDR_ERR_MACHO_BAD_SYMBOL); 1885 1910 if (puValue) … … 2033 2058 || ( paSyms[iSym].n_sect == 1 /* special hack for __mh_execute_header */ 2034 2059 && uValue == 0U - pSect->RVA 2035 && pModMachO-> Hdr.filetype != MH_OBJECT),2060 && pModMachO->uEffFileType != MH_OBJECT), 2036 2061 KLDR_ERR_MACHO_BAD_SYMBOL); 2037 2062 uValue += BaseAddress + pSect->RVA; … … 2145 2170 || ( paSyms[iSym].n_sect == 1 /* special hack for __mh_execute_header */ 2146 2171 && uValue == 0U - pSect->RVA 2147 && pModMachO-> Hdr.filetype != MH_OBJECT),2172 && pModMachO->uEffFileType != MH_OBJECT), 2148 2173 KLDR_ERR_MACHO_BAD_SYMBOL); 2149 2174 uValue += BaseAddress + pSect->RVA; … … 2341 2366 2342 2367 /* try do the prepare */ 2343 if (pModMachO->fMapUsingLoadCommandSections) 2344 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 2345 else 2346 { 2347 rc = kRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed); 2348 if (rc) 2349 return rc; 2350 } 2368 rc = kRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed); 2369 if (rc) 2370 return rc; 2351 2371 2352 2372 /* … … 2380 2400 * Try unmap the image. 2381 2401 */ 2382 if (pModMachO->fMapUsingLoadCommandSections) 2383 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 2384 else 2385 { 2386 rc = kRdrUnmap(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments); 2387 if (rc) 2388 return rc; 2389 } 2402 rc = kRdrUnmap(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments); 2403 if (rc) 2404 return rc; 2390 2405 2391 2406 /* … … 2451 2466 * Before doing anything we'll have to make all pages writable. 2452 2467 */ 2453 if (pModMachO->fMapUsingLoadCommandSections) 2454 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 2455 else 2456 { 2457 rc = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */); 2458 if (rc) 2459 return rc; 2460 } 2468 rc = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */); 2469 if (rc) 2470 return rc; 2461 2471 2462 2472 /* … … 2469 2479 * Restore protection. 2470 2480 */ 2471 if (pModMachO->fMapUsingLoadCommandSections) 2472 rc2 = KLDR_ERR_TODO; /* deal with this if it ever occurs. */ 2473 else 2474 rc2 = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */); 2481 rc2 = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */); 2475 2482 if (!rc && rc2) 2476 2483 rc = rc2; … … 3398 3405 /* 3399 3406 * When possible use the segment table to load the data. 3400 * If not iterate the load commands and execute the segment / section loads. 3401 */ 3402 if (pModMachO->fMapUsingLoadCommandSections) 3403 KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */ 3404 else 3405 { 3406 for (i = 0; i < pMod->cSegments; i++) 3407 { 3408 /* skip it? */ 3409 if ( pMod->aSegments[i].cbFile == -1 3410 || pMod->aSegments[i].offFile == -1 3411 || pMod->aSegments[i].LinkAddress == NIL_KLDRADDR 3412 || !pMod->aSegments[i].Alignment) 3413 continue; 3414 rc = kRdrRead(pMod->pRdr, 3415 (KU8 *)pvBits + (pMod->aSegments[i].LinkAddress - pModMachO->LinkAddress), 3416 pMod->aSegments[i].cbFile, 3417 pMod->aSegments[i].offFile); 3418 if (rc) 3419 return rc; 3420 } 3407 */ 3408 for (i = 0; i < pMod->cSegments; i++) 3409 { 3410 /* skip it? */ 3411 if ( pMod->aSegments[i].cbFile == -1 3412 || pMod->aSegments[i].offFile == -1 3413 || pMod->aSegments[i].LinkAddress == NIL_KLDRADDR 3414 || !pMod->aSegments[i].Alignment) 3415 continue; 3416 rc = kRdrRead(pMod->pRdr, 3417 (KU8 *)pvBits + pMod->aSegments[i].RVA, 3418 pMod->aSegments[i].cbFile, 3419 pMod->aSegments[i].offFile); 3420 if (rc) 3421 return rc; 3421 3422 } 3422 3423
Note:
See TracChangeset
for help on using the changeset viewer.