- Timestamp:
- Feb 11, 2007, 4:15:35 PM (19 years ago)
- Location:
- trunk/kLdr
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdr.h
r2958 r2961 50 50 typedef int64_t intmax_t; 51 51 typedef uint64_t uintmax_t; 52 # define UINT16_C(c) (c ## U) 52 # define UINT8_C(c) (c) 53 # define UINT16_C(c) (c) 53 54 # define UINT32_C(c) (c ## U) 54 55 # define UINT64_C(c) (c ## ULL) 56 # define INT8_C(c) (c) 55 57 # define INT16_C(c) (c) 56 58 # define INT32_C(c) (c) … … 1190 1192 /** Couldn't fit the address value into the field. Typically a relocation kind of error. */ 1191 1193 #define KLDR_ERR_ADDRESS_OVERFLOW (KLDR_ERR_BASE + 56) 1194 /** Couldn't fit a calculated size value into the native size type of the host. */ 1195 #define KLDR_ERR_SIZE_OVERFLOW (KLDR_ERR_BASE + 57) 1192 1196 /** Thread attach failed. */ 1193 #define KLDR_ERR_THREAD_ATTACH_FAILED (KLDR_ERR_BASE + 5 7)1197 #define KLDR_ERR_THREAD_ATTACH_FAILED (KLDR_ERR_BASE + 58) 1194 1198 /** The file reader can't take more concurrent mappings. */ 1195 #define KLDR_ERR_TOO_MANY_MAPPINGS (KLDR_ERR_BASE + 5 8)1199 #define KLDR_ERR_TOO_MANY_MAPPINGS (KLDR_ERR_BASE + 59) 1196 1200 /** The module wasn't a DLL or object file. */ 1197 #define KLDR_ERR_NOT_DLL (KLDR_ERR_BASE + 59)1201 #define KLDR_ERR_NOT_DLL (KLDR_ERR_BASE + 60) 1198 1202 /** The module wasn't an EXE. */ 1199 #define KLDR_ERR_NOT_EXE (KLDR_ERR_BASE + 6 0)1203 #define KLDR_ERR_NOT_EXE (KLDR_ERR_BASE + 61) 1200 1204 /** Not implemented yet. */ 1201 #define KLDR_ERR_TODO (KLDR_ERR_BASE + 6 1)1205 #define KLDR_ERR_TODO (KLDR_ERR_BASE + 62) 1202 1206 1203 1207 1204 1208 /** @name kLdrModPE status codes 1205 1209 * @{ */ 1206 #define KLDR_ERR_PE_BASE (KLDR_ERR_BASE + 6 2)1210 #define KLDR_ERR_PE_BASE (KLDR_ERR_BASE + 63) 1207 1211 /** The machine isn't supported by the interpreter. */ 1208 1212 #define KLDR_ERR_PE_UNSUPPORTED_MACHINE (KLDR_ERR_PE_BASE + 0) … … 1281 1285 /** The image is 32-bit and contains 64-bit load commands or vise versa. */ 1282 1286 #define KLDR_ERR_MACHO_BIT_MIX (KLDR_ERR_MACHO_BASE + 12) 1283 /** The bad MH_OBJECT file. */1287 /** Bad MH_OBJECT file. */ 1284 1288 #define KLDR_ERR_MACHO_BAD_OBJECT_FILE (KLDR_ERR_MACHO_BASE + 13) 1289 /** Bad symbol table entry. */ 1290 #define KLDR_ERR_MACHO_BAD_SYMBOL (KLDR_ERR_MACHO_BASE + 14) 1285 1291 /** @} */ 1286 1292 1287 1293 /** End of the valid kLdr status codes. */ 1288 #define KLDR_ERR_END (KLDR_ERR_MACHO_BASE + 1 4)1294 #define KLDR_ERR_END (KLDR_ERR_MACHO_BASE + 15) 1289 1295 1290 1296 const char *kLdrErrStr(int rc); -
trunk/kLdr/kLdrModMachO.c
r2956 r2961 34 34 #include "kLdrModMachO.h" 35 35 36 /* quick hack for now. */37 typedef struct nlist38 {39 uint32_t n_strx;40 uint8_t n_type;41 int8_t n_other;42 int16_t n_desc;43 uint32_t n_value;44 } nlist_t;45 46 36 47 37 /******************************************************************************* … … 61 51 #endif 62 52 63 /** @def KLDRMODMACHO_RVA2TYPE64 * Converts a RVA to a pointer of the specified type.65 * @param pvBits The bits (image base).66 * @param uRVA The image relative virtual address.67 * @param type The type to cast to.68 */69 #define KLDRMODMACHO_RVA2TYPE(pvBits, uRVA, type) \70 ( (type) ((uintptr_t)(pvBits) + (uintptr_t)(uRVA)) )71 72 /** @def KLDRMODMACHO_VALID_RVA73 * Checks that the specified RVA value is non-zero and within the bounds of the image.74 * @returns true/false.75 * @param pModPE The PE module interpreter instance.76 * @param uRVA The RVA to validate.77 */78 #define KLDRMODMACHO_VALID_RVA(pModPE, uRVA) \79 ( (uRVA) && (uRVA) < (pModPE)->Hdrs.OptionalHeader.SizeOfImage )80 81 82 53 83 54 /******************************************************************************* 84 55 * Structures and Typedefs * 85 56 *******************************************************************************/ 57 /** 58 * Mach-O section details. 59 */ 60 typedef struct KLDRMODMACHOSECT 61 { 62 /** The size of the section (in bytes). */ 63 KLDRSIZE cb; 64 /** The RVA of this section. */ 65 KLDRADDR RVA; 66 /** The file offset of this section. 67 * This is -1 if the section doesn't have a file backing. */ 68 off_t offFile; 69 /** The number of fixups. */ 70 uint32_t cFixups; 71 /** The array of fixups. (lazy loaded) */ 72 macho_relocation_info_t *paFixups; 73 /** The file offset of the fixups for this section. 74 * This is -1 if the section doesn't have any fixups. */ 75 off_t offFixups; 76 /** Pointer to the Mach-O section structure. */ 77 void *pvMachoSection; 78 79 } KLDRMODMACHOSECT, *PKLDRMODMACHOSECT; 80 81 /** 82 * Extra per-segment info. 83 * 84 * This is corresponds to a kLdr segment, not a Mach-O segment! 85 */ 86 typedef struct KLDRMODMACHOSEG 87 { 88 /** The number of sections in the segment. */ 89 uint32_t cSections; 90 /** Pointer to the sections belonging to this segment. 91 * The array resides in the big memory chunk allocated for 92 * the module handle, so it doesn't need freeing. */ 93 PKLDRMODMACHOSECT paSections; 94 95 } KLDRMODMACHOSEG, *PKLDRMODMACHOSEG; 96 86 97 /** 87 98 * Instance data for the Mach-O MH_OBJECT module interpreter. … … 116 127 uint32_t cSymbols; 117 128 /** The pointer to the loaded symbol table. */ 118 void *p aSymbols;129 void *pvaSymbols; 119 130 /** The offset of the string table. */ 120 131 off_t offStrings; … … 122 133 uint32_t cbStrings; 123 134 /** Pointer to the loaded string table. */ 124 char *pbStrings; 135 char *pchStrings; 136 /** Array of segments parallel to the one in KLDRMOD. */ 137 KLDRMODMACHOSEG aSegments[1]; 125 138 } KLDRMODMACHO, *PKLDRMODMACHO; 139 126 140 127 141 … … 137 151 static int kldrModMachODoCreate(PKLDRRDR pRdr, PKLDRMODMACHO *ppMod); 138 152 static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, PKLDRRDR pRdr, 139 uint32_t *pcSegments, uint32_t *pc bStringPool);153 uint32_t *pcSegments, uint32_t *pcSections, uint32_t *pcbStringPool); 140 154 static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool); 155 /*static int kldrModMachOLoadLoadCommands(PKLDRMODMACHO pModMachO);*/ 141 156 static int kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO); 142 static int kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress); 143 static int kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 157 static int kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, off_t offFixups, uint32_t cFixups, void **pvFixups); 158 159 static int kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 160 static int kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress); 161 static int kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits, 162 off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs, 163 KLDRADDR NewBaseAddress); 164 165 /*static int kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress); 166 static int kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);*/ 144 167 145 168 … … 195 218 uint8_t *pbLoadCommands; 196 219 uint32_t cSegments; 220 uint32_t cSections; 197 221 uint32_t cbStringPool; 198 222 size_t cchFilename; … … 244 268 ? sizeof(mach_header_32_t) : sizeof(mach_header_64_t)); 245 269 if (!rc) 246 rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, &cSegments, &c bStringPool);270 rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, &cSegments, &cSections, &cbStringPool); 247 271 if (rc) 248 272 { … … 256 280 */ 257 281 cchFilename = kLdrHlpStrLen(kLdrRdrName(pRdr)); 258 cb = KLDR_ALIGN_Z(sizeof(KLDRMODMACHO), 16) 282 cb = KLDR_ALIGN_Z( KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments]) 283 + sizeof(KLDRMODMACHOSECT) * cSections, 16) 259 284 + KLDR_OFFSETOF(KLDRMOD, aSegments[cSegments]) 260 285 + cchFilename + 1 … … 267 292 268 293 /* KLDRMOD */ 269 pMod = (PKLDRMOD)((uint8_t *)pModMachO + KLDR_ALIGN_Z(sizeof(KLDRMODMACHO), 16)); 294 pMod = (PKLDRMOD)((uint8_t *)pModMachO + KLDR_ALIGN_Z( KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments]) 295 + sizeof(KLDRMODMACHOSECT) * cSections, 16)); 270 296 pMod->pvData = pModMachO; 271 297 pMod->pRdr = pRdr; … … 348 374 pModMachO->offSymbols = 0; 349 375 pModMachO->cSymbols = 0; 350 pModMachO->p aSymbols = NULL;376 pModMachO->pvaSymbols = NULL; 351 377 pModMachO->offStrings = 0; 352 378 pModMachO->cbStrings = 0; 353 pModMachO->p bStrings = NULL;379 pModMachO->pchStrings = NULL; 354 380 355 381 /* … … 372 398 * 373 399 * The conversion that's preformed is format endian to host endian. 374 * The preparsing has to do with segment counting and string pool sizing.400 * The preparsing has to do with segment counting, section counting and string pool sizing. 375 401 * 376 402 * @returns 0 on success. … … 380 406 * @param pRdr The file reader. 381 407 * @param pcSegments Where to store the segment count. 408 * @param pcSegments Where to store the section count. 382 409 * @param pcbStringPool Where to store the string pool size. 383 410 */ 384 411 static int kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, PKLDRRDR pRdr, 385 uint32_t *pcSegments, uint32_t *pc bStringPool)412 uint32_t *pcSegments, uint32_t *pcSections, uint32_t *pcbStringPool) 386 413 { 387 414 union … … 397 424 const uint64_t cbFile = kLdrRdrSize(pRdr); 398 425 uint32_t cSegments = 0; 426 uint32_t cSections = 0; 399 427 uint32_t cbStringPool = 0; 400 428 uint32_t cLeft = pHdr->ncmds; … … 407 435 408 436 *pcSegments = 0; 437 *pcSections = 0; 409 438 *pcbStringPool = 0; 410 439 … … 554 583 if ( pSect->nreloc 555 584 && ( pSect->reloff > cbFile 556 || (uint64_t)pSect->reloff + (off_t)pSect->nreloc * sizeof( nlist_t)) > cbFile)585 || (uint64_t)pSect->reloff + (off_t)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile) 557 586 return KLDR_ERR_MACHO_BAD_SECTION; 558 587 … … 584 613 cbStringPool += kLdrHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; 585 614 } 615 cSections++; 586 616 break; 587 617 } … … 603 633 604 634 case LC_SYMTAB: 635 { 636 size_t cbSym; 605 637 if (fConvertEndian) 606 638 { … … 612 644 613 645 /* verify */ 646 cbSym = pHdr->magic == IMAGE_MACHO32_SIGNATURE 647 || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 648 ? sizeof(macho_nlist_32_t) 649 : sizeof(macho_nlist_64_t); 614 650 if ( u.pSymTab->symoff >= cbFile 615 || (uint64_t)u.pSymTab->symoff + u.pSymTab->nsyms * sizeof(nlist_t)> kLdrRdrSize(pRdr))651 || (uint64_t)u.pSymTab->symoff + u.pSymTab->nsyms * cbSym > kLdrRdrSize(pRdr)) 616 652 return KLDR_ERR_MACHO_BAD_LOAD_COMMAND; 617 653 if ( u.pSymTab->stroff >= cbFile … … 625 661 return KLDR_ERR_MACHO_BAD_OBJECT_FILE; 626 662 break; 663 } 627 664 628 665 case LC_THREAD: … … 707 744 708 745 *pcSegments = cSegments; 746 *pcSections = cSections; 709 747 *pcbStringPool = cbStringPool; 710 748 … … 739 777 int fFirstSegment = 1; 740 778 PKLDRSEG pSeg = &pModMachO->pMod->aSegments[0]; 779 PKLDRMODMACHOSEG pSegExtra = &pModMachO->aSegments[0]; 780 PKLDRMODMACHOSECT pSectExtra = (PKLDRMODMACHOSECT)&pModMachO->aSegments[pModMachO->pMod->cSegments]; 741 781 const uint32_t cSegments = pModMachO->pMod->cSegments; 742 782 uint32_t i; … … 779 819 || kLdrHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname))) 780 820 { 821 /* close the previous segment */ 822 if (pSegExtra != &pModMachO->aSegments[1]) 823 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 824 781 825 /* new segment. */ 782 826 pSeg->pvUser = NULL; … … 799 843 pSeg->MapAddress = 0; 800 844 845 pSegExtra->cSections = 0; 846 pSegExtra->paSections = pSectExtra; 847 801 848 pSeg++; 849 pSegExtra++; 802 850 fFirstSegment = 0; 803 851 } 804 else if (!fFirstSegment)852 else 805 853 { 806 854 /* update exiting segment */ … … 832 880 /** @todo update the protection... */ 833 881 } 882 883 /* Section info. */ 884 pSectExtra->cb = pSect->size; 885 pSectExtra->RVA = pSect->addr; 886 pSectExtra->offFile = pSect->offset ? pSect->offset : -1; 887 pSectExtra->cFixups = pSect->nreloc; 888 pSectExtra->paFixups = NULL; 889 pSectExtra->offFixups = pSect->nreloc ? pSect->reloff : -1; 890 pSectExtra->pvMachoSection = pSect; 891 pSectExtra++; 834 892 break; 835 893 } … … 862 920 } /* while more commands */ 863 921 922 /* 923 * Close the last segment (if any). 924 */ 925 if (pSegExtra != &pModMachO->aSegments[1]) 926 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 927 864 928 /* 865 929 * Adjust mapping addresses calculating the image size. … … 897 961 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 898 962 int rc = 0; 963 uint32_t i, j; 899 964 KLDRMODMACHO_ASSERT(!pModMachO->pvMapping); 965 966 i = pMod->cSegments; 967 while (i-- > 0) 968 { 969 j = pModMachO->aSegments[i].cSections; 970 while (j-- > 0) 971 { 972 kldrHlpFree(pModMachO->aSegments[i].paSections[j].paFixups); 973 pModMachO->aSegments[i].paSections[j].paFixups = NULL; 974 } 975 } 900 976 901 977 if (pMod->pRdr) … … 908 984 kldrHlpFree(pModMachO->pbLoadCommands); 909 985 pModMachO->pbLoadCommands = NULL; 910 kldrHlpFree(pModMachO->p bStrings);911 pModMachO->p bStrings = NULL;912 kldrHlpFree(pModMachO->p aSymbols);913 pModMachO->p aSymbols = NULL;986 kldrHlpFree(pModMachO->pchStrings); 987 pModMachO->pchStrings = NULL; 988 kldrHlpFree(pModMachO->pvaSymbols); 989 pModMachO->pvaSymbols = NULL; 914 990 kldrHlpFree(pModMachO); 915 991 return rc; … … 1531 1607 */ 1532 1608 rc = kldrModMachODoFixups(pModMachO, (void *)pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping, 1533 pModMachO->Hdrs.OptionalHeader.ImageBase);1609 pModMachO->Hdrs.OptionalHeader.ImageBase); 1534 1610 1535 1611 /* … … 1551 1627 1552 1628 /** 1553 * Applies base relocations to a (unprotected) image mapping.1629 * MH_OBJECT: Resolves undefined symbols (imports). 1554 1630 * 1555 1631 * @returns 0 on success, non-zero kLdr status code on failure. 1556 * @param pModMachO The PE module interpreter instance. 1632 * @param pModMachO The Mach-O module interpreter instance. 1633 * @param pfnGetImport The callback for resolving an imported symbol. 1634 * @param pvUser User argument to the callback. 1635 */ 1636 static int kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 1637 { 1638 const uint32_t cSyms = pModMachO->cSymbols; 1639 uint32_t iSym; 1640 int rc; 1641 1642 /* 1643 * Ensure that we've got the symbol table and section fixups handy. 1644 */ 1645 rc = kldrModMachOLoadObjSymTab(pModMachO); 1646 if (rc) 1647 return rc; 1648 1649 /* 1650 * Iterate the symbol table and resolve undefined symbols. 1651 * We currently ignore REFERENCE_TYPE. 1652 */ 1653 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1654 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1655 { 1656 macho_nlist_32_t *paSyms = (macho_nlist_32_t *)pModMachO->pvaSymbols; 1657 for (iSym = 0; iSym < cSyms; iSym++) 1658 { 1659 /* skip stabs */ 1660 if (paSyms[iSym].n_type & MACHO_N_STAB) 1661 continue; 1662 1663 if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1664 { 1665 const char *pszSymbol; 1666 size_t cchSymbol; 1667 uint32_t fKind = KLDRSYMKIND_REQ_FLAT; 1668 KLDRADDR Value; 1669 1670 /** @todo Implement N_REF_TO_WEAK. */ 1671 if (paSyms[iSym].n_desc & N_REF_TO_WEAK) 1672 return KLDR_ERR_TODO; 1673 1674 /* Get the symbol name and try resolve it. */ 1675 if ((uint32_t)paSyms[iSym].n_un.n_strx >= pModMachO->cbStrings) 1676 return KLDR_ERR_MACHO_BAD_SYMBOL; 1677 pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx]; 1678 cchSymbol = kLdrHlpStrLen(pszSymbol); 1679 rc = pfnGetImport(pModMachO->pMod, NIL_KLDRMOD_IMPORT, iSym, pszSymbol, cchSymbol, NULL, 1680 &Value, &fKind, pvUser); 1681 if (rc) 1682 { 1683 /* weak reference? */ 1684 if (!(paSyms[iSym].n_desc & N_WEAK_REF)) 1685 break; 1686 Value = 0; 1687 } 1688 1689 /* Update the symbol. */ 1690 paSyms[iSym].n_value = (uint32_t)Value; 1691 if (paSyms[iSym].n_value != Value) 1692 { 1693 rc = KLDR_ERR_ADDRESS_OVERFLOW; 1694 break; 1695 } 1696 } 1697 else if (paSyms[iSym].n_desc & N_WEAK_DEF) 1698 return KLDR_ERR_TODO; /** @todo implement weak symbols. */ 1699 } 1700 } 1701 else 1702 { 1703 /* (Identical to the 32-bit code, just different paSym type. (and n_strx is unsigned)) */ 1704 macho_nlist_64_t *paSyms = (macho_nlist_64_t *)pModMachO->pvaSymbols; 1705 for (iSym = 0; iSym < cSyms; iSym++) 1706 { 1707 /* skip stabs */ 1708 if (paSyms[iSym].n_type & MACHO_N_STAB) 1709 continue; 1710 1711 if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1712 { 1713 const char *pszSymbol; 1714 size_t cchSymbol; 1715 uint32_t fKind = KLDRSYMKIND_REQ_FLAT; 1716 KLDRADDR Value; 1717 1718 /** @todo Implement N_REF_TO_WEAK. */ 1719 if (paSyms[iSym].n_desc & N_REF_TO_WEAK) 1720 return KLDR_ERR_TODO; 1721 1722 /* Get the symbol name and try resolve it. */ 1723 if (paSyms[iSym].n_un.n_strx >= pModMachO->cbStrings) 1724 return KLDR_ERR_MACHO_BAD_SYMBOL; 1725 pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx]; 1726 cchSymbol = kLdrHlpStrLen(pszSymbol); 1727 rc = pfnGetImport(pModMachO->pMod, NIL_KLDRMOD_IMPORT, iSym, pszSymbol, cchSymbol, NULL, 1728 &Value, &fKind, pvUser); 1729 if (rc) 1730 { 1731 /* weak reference? */ 1732 if (!(paSyms[iSym].n_desc & N_WEAK_REF)) 1733 break; 1734 Value = 0; 1735 } 1736 1737 /* Update the symbol. */ 1738 paSyms[iSym].n_value = Value; 1739 if (paSyms[iSym].n_value != Value) 1740 { 1741 rc = KLDR_ERR_ADDRESS_OVERFLOW; 1742 break; 1743 } 1744 } 1745 else if (paSyms[iSym].n_desc & N_WEAK_DEF) 1746 return KLDR_ERR_TODO; /** @todo implement weak symbols. */ 1747 } 1748 } 1749 1750 return rc; 1751 } 1752 1753 1754 /** 1755 * MH_OBJECT: Applies base relocations to a (unprotected) image mapping. 1756 * 1757 * @returns 0 on success, non-zero kLdr status code on failure. 1758 * @param pModMachO The Mach-O module interpreter instance. 1557 1759 * @param pvMapping The mapping to fixup. 1558 1760 * @param NewBaseAddress The address to fixup the mapping to. 1559 1761 * @param OldBaseAddress The address the mapping is currently fixed up to. 1560 1762 */ 1561 static int kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress) 1562 { 1563 #if 0 1564 const KLDRADDR Delta = NewBaseAddress - OldBaseAddress; 1565 uint32_t cbLeft = pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 1566 const IMAGE_BASE_RELOCATION *pBR, *pFirstBR; 1567 1568 /* 1569 * Don't don anything if the delta is 0 or there aren't any relocations. 1570 */ 1571 if ( !Delta 1572 || !cbLeft 1573 || !pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) 1574 return 0; 1575 1576 /* 1577 * Process the fixups block by block. 1578 * (These blocks appears to be 4KB on all archs despite the native page size.) 1579 */ 1580 pBR = pFirstBR = KLDRMODMACHO_RVA2TYPE(pvMapping, 1581 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, 1582 const IMAGE_BASE_RELOCATION *); 1583 while ( cbLeft > sizeof(IMAGE_BASE_RELOCATION) 1584 && pBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION) /* paranoia */) 1585 { 1586 union 1763 static int kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress) 1764 { 1765 uint32_t iSeg; 1766 int rc; 1767 int (*pfnFixupSection)(PKLDRMODMACHO, uint8_t *, size_t, off_t, const macho_relocation_info_t *, uint32_t, KLDRADDR); 1768 1769 1770 /* 1771 * Ensure that we've got the symbol table and section fixups handy. 1772 */ 1773 rc = kldrModMachOLoadObjSymTab(pModMachO); 1774 if (rc) 1775 return rc; 1776 1777 /* 1778 * Iterate over the segments and their sections and apply fixups. 1779 */ 1780 pfnFixupSection = NULL; 1781 for (iSeg = rc = 0; !rc && iSeg < pModMachO->pMod->cSegments; iSeg++) 1782 { 1783 PKLDRMODMACHOSEG pSeg = &pModMachO->aSegments[iSeg]; 1784 uint32_t iSect; 1785 1786 for (iSect = 0; iSect < pSeg->cSections; iSect++) 1587 1787 { 1588 uint8_t *pu8; 1589 uint16_t *pu16; 1590 uint32_t *pu32; 1591 uint64_t *pu64; 1592 } uChunk, 1593 u; 1594 const uint16_t *poffFixup = (const uint16_t *)(pBR + 1); 1595 const uint32_t cbBlock = KLDR_MIN(cbLeft, pBR->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION); /* more caution... */ 1596 uint32_t cFixups = cbBlock / sizeof(poffFixup[0]); 1597 uChunk.pu8 = KLDRMODMACHO_RVA2TYPE(pvMapping, pBR->VirtualAddress, uint8_t *); 1598 1599 /* 1600 * Loop thru the fixups in this chunk. 1601 */ 1602 while (cFixups > 0) 1603 { 1604 u.pu8 = uChunk.pu8 + (*poffFixup & 0xfff); 1605 switch (*poffFixup >> 12) /* ordered by value. */ 1788 PKLDRMODMACHOSECT pSect = &pSeg->paSections[iSect]; 1789 uint8_t *pbSectBits; 1790 1791 /* skip sections without fixups. */ 1792 if (!pSect->cFixups) 1793 continue; 1794 1795 /* lazy load (and endian convert) the fixups. */ 1796 if (!pSect->paFixups) 1606 1797 { 1607 /* 0 - Alignment placeholder. */1608 case IMAGE_REL_BASED_ABSOLUTE:1798 rc = kldrModMachOLoadFixups(pModMachO, pSect->offFixups, pSect->cFixups, &pSect->paFixups); 1799 if (rc) 1609 1800 break; 1610 1611 /* 1 - 16-bit, add 2nd 16-bit part of the delta. (rare) */ 1612 case IMAGE_REL_BASED_HIGH: 1613 *u.pu16 += (uint16_t)(Delta >> 16); 1614 break; 1615 1616 /* 2 - 16-bit, add 1st 16-bit part of the delta. (rare) */ 1617 case IMAGE_REL_BASED_LOW: 1618 *u.pu16 += (uint16_t)Delta; 1619 break; 1620 1621 /* 3 - 32-bit, add delta. (frequent in 32-bit images) */ 1622 case IMAGE_REL_BASED_HIGHLOW: 1623 *u.pu32 += (uint32_t)Delta; 1624 break; 1625 1626 /* 4 - 16-bit, add 2nd 16-bit of the delta, sign adjust for the lower 16-bit. one arg. (rare) */ 1627 case IMAGE_REL_BASED_HIGHADJ: 1801 } 1802 1803 /* 1804 * Apply the fixups. 1805 */ 1806 if (!pfnFixupSection) 1807 { 1808 /* determin the function for applying fixups. */ 1809 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1810 || pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE) 1811 pfnFixupSection = kldrModMachOObjFixupSectionGeneric; 1812 else 1628 1813 { 1629 int32_t i32; 1630 if (cFixups <= 1) 1631 return KLDR_ERR_PE_BAD_FIXUP; 1632 1633 i32 = (uint32_t)*u.pu16 << 16; 1634 i32 |= *++poffFixup; cFixups--; /* the addend argument */ 1635 i32 += (uint32_t)Delta; 1636 i32 += 0x8000; 1637 *u.pu16 = (uint16_t)(i32 >> 16); 1814 rc = KLDR_ERR_TODO; /* save space for now. */ 1638 1815 break; 1639 1816 } 1640 1641 /* 5 - 32-bit MIPS JMPADDR, no implemented. */ 1642 case IMAGE_REL_BASED_MIPS_JMPADDR: 1643 *u.pu32 = (*u.pu32 & 0xc0000000) 1644 | ((uint32_t)((*u.pu32 << 2) + (uint32_t)Delta) >> 2); 1645 break; 1646 1647 /* 6 - Intra section? Reserved value in later specs. Not implemented. */ 1648 case IMAGE_REL_BASED_SECTION: 1649 KLDRMODMACHO_ASSERT(!"SECTION"); 1650 return KLDR_ERR_PE_BAD_FIXUP; 1651 1652 /* 7 - Relative intra section? Reserved value in later specs. Not implemented. */ 1653 case IMAGE_REL_BASED_REL32: 1654 KLDRMODMACHO_ASSERT(!"SECTION"); 1655 return KLDR_ERR_PE_BAD_FIXUP; 1656 1657 /* 8 - reserved according to binutils... */ 1658 case 8: 1659 KLDRMODMACHO_ASSERT(!"RESERVERED8"); 1660 return KLDR_ERR_PE_BAD_FIXUP; 1661 1662 /* 9 - IA64_IMM64 (/ MIPS_JMPADDR16), no specs nor need to support the platform yet. 1663 * Bet this requires more code than all the other fixups put together in good IA64 spirit :-) */ 1664 case IMAGE_REL_BASED_IA64_IMM64: 1665 KLDRMODMACHO_ASSERT(!"IA64_IMM64 / MIPS_JMPADDR16"); 1666 return KLDR_ERR_PE_BAD_FIXUP; 1667 1668 /* 10 - 64-bit, add delta. (frequently in 64-bit images) */ 1669 case IMAGE_REL_BASED_DIR64: 1670 *u.pu64 += (uint64_t)Delta; 1671 break; 1672 1673 /* 11 - 16-bit, add 3rd 16-bit of the delta, sign adjust for the lower 32-bit. two args. (rare) */ 1674 case IMAGE_REL_BASED_HIGH3ADJ: 1817 } 1818 1819 pbSectBits = (uint8_t *)pvMapping + (uintptr_t)pSect->RVA; 1820 rc = pfnFixupSection(pModMachO, pbSectBits, (size_t)pSect->cb, pSect->offFile, 1821 pSect->paFixups, pSect->cFixups, NewBaseAddress); 1822 if (rc) 1823 break; 1824 } 1825 } 1826 1827 return rc; 1828 } 1829 1830 1831 static int kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits, 1832 off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs, 1833 KLDRADDR NewBaseAddress) 1834 { 1835 1836 return 0; 1837 } 1838 1839 1840 /** 1841 * Loads the symbol table for a MH_OBJECT file. 1842 * 1843 * The symbol table is pointed to by KLDRMODMACHO::pvaSymbols. 1844 * 1845 * @returns 0 on success, non-zero kLdr status code on failure. 1846 * @param pModMachO The Mach-O module interpret instance. 1847 */ 1848 static int kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO) 1849 { 1850 int rc = 0; 1851 1852 if ( !pModMachO->pvaSymbols 1853 && pModMachO->cSymbols) 1854 { 1855 size_t cbSyms; 1856 size_t cbSym; 1857 void *pvSyms; 1858 void *pvStrings; 1859 1860 /* sanity */ 1861 if ( !pModMachO->offSymbols 1862 || (pModMachO->cbStrings && !pModMachO->offStrings)) 1863 return KLDR_ERR_MACHO_BAD_OBJECT_FILE; 1864 1865 /* allocate */ 1866 cbSym = pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1867 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 1868 ? sizeof(macho_nlist_32_t) 1869 : sizeof(macho_nlist_64_t); 1870 cbSyms = pModMachO->cSymbols * cbSym; 1871 if (cbSyms / cbSym != pModMachO->cSymbols) 1872 return KLDR_ERR_SIZE_OVERFLOW; 1873 rc = KLDR_ERR_NO_MEMORY; 1874 pvSyms = kldrHlpAlloc(cbSyms); 1875 if (pvSyms) 1876 { 1877 if (pModMachO->cbStrings) 1878 pvStrings = kldrHlpAlloc(pModMachO->cbStrings); 1879 else 1880 pvStrings = kldrHlpAllocZ(4); 1881 if (pvStrings) 1882 { 1883 /* read */ 1884 rc = kLdrRdrRead(pModMachO->pMod->pRdr, pvSyms, cbSyms, pModMachO->offSymbols); 1885 if (!rc && pModMachO->cbStrings) 1886 rc = kLdrRdrRead(pModMachO->pMod->pRdr, pvStrings, pModMachO->cbStrings, pModMachO->offStrings); 1887 if (!rc) 1675 1888 { 1676 int64_t i64; 1677 if (cFixups <= 2) 1678 return KLDR_ERR_PE_BAD_FIXUP; 1679 1680 i64 = (uint64_t)*u.pu16 << 32 1681 | ((uint32_t)poffFixup[2] << 16) 1682 | poffFixup[1]; 1683 i64 += Delta; 1684 i64 += 0x80008000UL; 1685 *u.pu16 = (uint16_t)(i64 >> 32); 1686 /* skip the addends arguments */ 1687 poffFixup += 2; 1688 cFixups -= 2; 1689 break; 1889 pModMachO->pvaSymbols = pvSyms; 1890 pModMachO->pchStrings = (char *)pvStrings; 1891 1892 /* perform endian conversion? */ 1893 if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1894 { 1895 uint32_t cLeft = pModMachO->cSymbols; 1896 macho_nlist_32_t *pSym = (macho_nlist_32_t *)pvSyms; 1897 while (cLeft-- > 0) 1898 { 1899 pSym->n_un.n_strx = KLDRHLP_E2E_U32(pSym->n_un.n_strx); 1900 pSym->n_desc = (int16_t)KLDRHLP_E2E_U16(pSym->n_desc); 1901 pSym->n_value = KLDRHLP_E2E_U32(pSym->n_value); 1902 pSym++; 1903 } 1904 } 1905 else if (pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 1906 { 1907 uint32_t cLeft = pModMachO->cSymbols; 1908 macho_nlist_64_t *pSym = (macho_nlist_64_t *)pvSyms; 1909 while (cLeft-- > 0) 1910 { 1911 pSym->n_un.n_strx = KLDRHLP_E2E_U32(pSym->n_un.n_strx); 1912 pSym->n_desc = (int16_t)KLDRHLP_E2E_U16(pSym->n_desc); 1913 pSym->n_value = KLDRHLP_E2E_U64(pSym->n_value); 1914 pSym++; 1915 } 1916 } 1917 1918 return 0; 1690 1919 } 1691 1692 /* the rest are yet to be defined.*/ 1693 default: 1694 return KLDR_ERR_PE_BAD_FIXUP; 1920 kldrHlpFree(pvStrings); 1695 1921 } 1696 1697 /* 1698 * Next relocation. 1699 */ 1700 poffFixup++; 1701 cFixups--; 1922 kldrHlpFree(pvSyms); 1702 1923 } 1703 1704 1705 /* 1706 * Next block. 1707 */ 1708 cbLeft -= pBR->SizeOfBlock; 1709 pBR = (PIMAGE_BASE_RELOCATION)((uintptr_t)pBR + pBR->SizeOfBlock); 1710 } 1711 1712 #endif 1713 return 0; 1714 } 1715 1924 } 1925 else 1926 KLDRMODMACHO_ASSERT(pModMachO->pchStrings); 1927 1928 return rc; 1929 } 1716 1930 1717 1931 1718 1932 /** 1719 * Resolves imports. 1720 * 1933 * Loads the fixups at the given address and performs endian 1934 * conversion if necessary. 1935 * 1721 1936 * @returns 0 on success, non-zero kLdr status code on failure. 1722 * @param pModMachO The PE module interpreterinstance.1723 * @param pvMapping The mapping which imports should be resolved.1724 * @param pfnGetImport The callback for resolving an imported symbol.1725 * @param p vUser User argument to the callback.1937 * @param pModMachO The Mach-O module interpret instance. 1938 * @param offFixups The file offset of the fixups. 1939 * @param cFixups The number of fixups to load. 1940 * @param ppaFixups Where to put the pointer to the allocated fixup array. 1726 1941 */ 1727 static int kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 1728 { 1729 /* for when loading non-objects. */ 1730 return 0; 1942 static int kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, off_t offFixups, uint32_t cFixups, macho_relocation_info_t **ppaFixups) 1943 { 1944 macho_relocation_info_t *paFixups; 1945 size_t cbFixups; 1946 int rc; 1947 1948 /* allocate the memory. */ 1949 cbFixups = cFixups * sizeof(*paFixups); 1950 if (cbFixups / sizeof(*paFixups) != cFixups) 1951 return KLDR_ERR_SIZE_OVERFLOW; 1952 paFixups = (macho_relocation_info_t *)kldrHlpAlloc(cbFixups); 1953 if (!paFixups) 1954 return KLDR_ERR_NO_MEMORY; 1955 1956 /* read the fixups. */ 1957 rc = kLdrRdrRead(pModMachO->pMod->pRdr, paFixups, cbFixups, offFixups); 1958 if (!rc) 1959 { 1960 *ppaFixups = paFixups; 1961 1962 /* do endian conversion if necessary. */ 1963 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 1964 || pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 1965 { 1966 uint32_t iFixup; 1967 for (iFixup = 0; iFixup < cFixups; iFixup++) 1968 { 1969 uint32_t *pu32 = (uint32_t *)&paFixups[iFixup]; 1970 pu32[0] = KLDRHLP_E2E_U32(pu32[0]); 1971 pu32[1] = KLDRHLP_E2E_U32(pu32[1]); 1972 } 1973 } 1974 } 1975 else 1976 kldrHlpFree(paFixups); 1977 return rc; 1731 1978 } 1732 1979 … … 1821 2068 * Call workers to do the jobs. 1822 2069 */ 1823 rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress); 1824 if (pModMachO->Hdr.filetype != MH_OBJECT) 1825 rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser); 2070 if (pModMachO->Hdr.filetype == MH_OBJECT) 2071 { 2072 rc = kldrModMachOObjDoImports(pModMachO, pfnGetImport, pvUser); 2073 if (!rc) 2074 rc = kldrModMachOObjDoFixups(pModMachO, pvBits, NewBaseAddress); 2075 2076 } 2077 else 2078 rc = KLDR_ERR_TODO; 2079 /*{ 2080 rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser); 2081 if (!rc) 2082 rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser); 2083 }*/ 1826 2084 1827 2085 return rc; -
trunk/kLdr/kLdrModMachO.h
r2958 r2961 667 667 union 668 668 { 669 int32_t n_strx;/**< Offset (index) into the string table. 0 means "". */669 uint32_t n_strx; /**< Offset (index) into the string table. 0 means "". */ 670 670 } n_un; 671 671 uint8_t n_type; /**< Symbol type. */
Note:
See TracChangeset
for help on using the changeset viewer.