Changeset 2963 for trunk/kLdr/kLdrModMachO.c
- Timestamp:
- Feb 13, 2007, 9:40:28 AM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModMachO.c
r2962 r2963 64 64 /** The RVA of this section. */ 65 65 KLDRADDR RVA; 66 /** The file offset of this section. 66 /** The file offset of this section. 67 67 * This is -1 if the section doesn't have a file backing. */ 68 68 off_t offFile; … … 71 71 /** The array of fixups. (lazy loaded) */ 72 72 macho_relocation_info_t *paFixups; 73 /** The file offset of the fixups for this section. 73 /** The file offset of the fixups for this section. 74 74 * This is -1 if the section doesn't have any fixups. */ 75 75 off_t offFixups; … … 79 79 uint32_t iSegment; 80 80 /** Pointer to the Mach-O section structure. */ 81 void *pvMachoSection; 81 void *pvMachoSection; 82 82 } KLDRMODMACHOSECT, *PKLDRMODMACHOSECT; 83 83 84 84 /** 85 85 * Extra per-segment info. 86 * 86 * 87 87 * This is corresponds to a kLdr segment, not a Mach-O segment! 88 88 */ … … 91 91 /** The number of sections in the segment. */ 92 92 uint32_t cSections; 93 /** Pointer to the sections belonging to this segment. 94 * The array resides in the big memory chunk allocated for 93 /** Pointer to the sections belonging to this segment. 94 * The array resides in the big memory chunk allocated for 95 95 * the module handle, so it doesn't need freeing. */ 96 96 PKLDRMODMACHOSECT paSections; … … 167 167 static int kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO); 168 168 static int kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, off_t offFixups, uint32_t cFixups, void **pvFixups); 169 static int kldrModMachOMapVirginBits(PKLDRMODMACHO pModMachO); 169 170 170 171 static int kldrModMachODoQuerySymbol32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, const char *pchStrings, 171 uint32_t cchStrings, KLDRADDR BaseAddress, uint32_t iSymbol, const char *pchSymbol, 172 uint32_t cchStrings, KLDRADDR BaseAddress, uint32_t iSymbol, const char *pchSymbol, 172 173 size_t cchSymbol, PKLDRADDR puValue, uint32_t *pfKind); 173 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 174 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 174 175 const char *pchStrings, uint32_t cchStrings, KLDRADDR BaseAddress, 175 176 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); 176 177 static int kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 177 178 static int kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress); 178 static int kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits, 179 off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs, 180 KLDRADDR NewBaseAddress); 179 static int kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, PKLDRMODMACHOSECT pFixupSect, 180 macho_nlist_32_t *paSyms, uint32_t cSyms, KLDRADDR NewBaseAddress); 181 181 182 182 /*static int kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress); … … 297 297 */ 298 298 cchFilename = kLdrHlpStrLen(kLdrRdrName(pRdr)); 299 cb = KLDR_ALIGN_Z( KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments]) 299 cb = KLDR_ALIGN_Z( KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments]) 300 300 + sizeof(KLDRMODMACHOSECT) * cSections, 16) 301 301 + KLDR_OFFSETOF(KLDRMOD, aSegments[cSegments]) … … 524 524 cSegmentCommands++; 525 525 526 /* 527 * convert, validate and parse the sections. 526 /* 527 * convert, validate and parse the sections. 528 528 */ 529 529 cSectionsLeft = u.pSeg32->nsects; … … 556 556 case S_REGULAR: 557 557 case S_CSTRING_LITERALS: 558 case S_COALESCED: 558 559 if (pSect->reserved1 || pSect->reserved2) 559 560 return KLDR_ERR_MACHO_BAD_SECTION; … … 570 571 case S_16BYTE_LITERALS: 571 572 case S_SYMBOL_STUBS: 572 case S_COALESCED:573 573 case S_MOD_INIT_FUNC_POINTERS: 574 574 case S_MOD_TERM_FUNC_POINTERS: … … 583 583 | S_ATTR_LOC_RELOC | SECTION_TYPE)) 584 584 return KLDR_ERR_MACHO_BAD_SECTION; 585 if (!pSect->size)586 return KLDR_ERR_MACHO_BAD_SECTION;587 585 if ( pSect->addr - u.pSeg32->vmaddr > u.pSeg32->vmsize 588 586 || pSect->addr - u.pSeg32->vmaddr + pSect->size > u.pSeg32->vmsize) … … 592 590 || (((1 << pSect->align) - 1) & u.pSeg32->vmaddr)) 593 591 return KLDR_ERR_MACHO_BAD_SECTION; 594 if ( fFileBits 592 if ( fFileBits 595 593 && ( pSect->offset > cbFile 596 594 || (uint64_t)pSect->offset + pSect->size > cbFile)) … … 600 598 if (!pSect->nreloc && pSect->reloff) 601 599 return KLDR_ERR_MACHO_BAD_SECTION; 602 if ( pSect->nreloc 600 if ( pSect->nreloc 603 601 && ( pSect->reloff > cbFile 604 602 || (uint64_t)pSect->reloff + (off_t)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile) … … 647 645 648 646 /*case LC_SEGMENT_64: 649 copy 32-bit code 647 copy 32-bit code 650 648 break; 651 649 */ … … 665 663 cbSym = pHdr->magic == IMAGE_MACHO32_SIGNATURE 666 664 || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE 667 ? sizeof(macho_nlist_32_t) 665 ? sizeof(macho_nlist_32_t) 668 666 : sizeof(macho_nlist_64_t); 669 667 if ( u.pSymTab->symoff >= cbFile … … 681 679 break; 682 680 } 681 682 case LC_DYSYMTAB: 683 /** @todo deal with this! */ 684 break; 683 685 684 686 case LC_THREAD: … … 727 729 case LC_FVMFILE: 728 730 case LC_PREPAGE: 729 case LC_DYSYMTAB:730 731 case LC_LOAD_DYLIB: 731 732 case LC_ID_DYLIB: … … 820 821 pModMachO->LinkAddress = u.pSeg32->vmaddr; 821 822 822 /* 823 * convert, validate and parse the sections. 823 /* 824 * convert, validate and parse the sections. 824 825 */ 825 826 cSectionsLeft = u.pSeg32->nsects; … … 888 889 return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */ 889 890 890 /* If there are file bits, ensure they are in the current flow. 891 /* If there are file bits, ensure they are in the current flow. 891 892 (yes, we are very very careful here, I know.) */ 892 if ( pSect->offset 893 if ( pSect->offset 893 894 && pSeg[-1].cbFile == pSeg[-1].cb) 894 895 { … … 899 900 if (fOk) 900 901 pSeg[-1].cbFile = (off_t)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size; 901 else 902 else 902 903 { 903 904 904 905 pSeg[-1].cbFile = pSeg[-1].offFile = -1; 905 906 pModMachO->fMapUsingLoadCommandSections = 1; … … 947 948 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 948 949 949 /* 950 /* 950 951 * Adjust mapping addresses calculating the image size. 951 952 */ … … 1055 1056 * Refuse segmented requests for now. 1056 1057 */ 1057 if ( pfKind 1058 if ( pfKind 1058 1059 && (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) != KLDRSYMKIND_REQ_FLAT) 1059 1060 return KLDR_ERR_TODO; … … 1069 1070 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1070 1071 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1071 rc = kldrModMachODoQuerySymbol32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1072 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol, 1072 rc = kldrModMachODoQuerySymbol32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1073 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol, 1073 1074 cchSymbol, puValue, pfKind); 1074 1075 else 1075 1076 rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */ 1076 /*rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1077 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol, 1077 /*rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1078 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol, 1078 1079 cchSymbol, puValue, pfKind);*/ 1079 1080 … … 1090 1091 /** 1091 1092 * Lookup a symbol in a 32-bit symbol table. 1092 * 1093 * 1093 1094 * @returns See kLdrModQuerySymbol. 1094 * @param pModMachO 1095 * @param pModMachO 1095 1096 * @param paSyms Pointer to the symbol table. 1096 1097 * @param cSyms Number of symbols in the table. 1097 1098 * @param pchStrings Pointer to the string table. 1098 1099 * @param cchStrings Size of the string table. 1099 * @param BaseAddress Adjusted base address, see kLdrModQuerySymbol. 1100 * @param BaseAddress Adjusted base address, see kLdrModQuerySymbol. 1100 1101 * @param iSymbol See kLdrModQuerySymbol. 1101 1102 * @param pchSymbol See kLdrModQuerySymbol. … … 1118 1119 cchStrings -= cchSymbol; 1119 1120 1120 for (iSymbol = 0; iSymbol < cSyms; iSymbol++) 1121 /* external symbols are usually at the end, so search the other way. */ 1122 for (iSymbol = cSyms - 1; iSymbol != UINT32_MAX; iSymbol--) 1121 1123 { 1122 1124 const char *psz; … … 1131 1133 if (paSyms[iSymbol].n_type & MACHO_N_PEXT) /*??*/ 1132 1134 continue; 1133 1135 1134 1136 /* get name */ 1135 if (!paSyms[iSymbol].n_un.n_strx) 1137 if (!paSyms[iSymbol].n_un.n_strx) 1136 1138 continue; 1137 1139 if ((uint32_t)paSyms[iSymbol].n_un.n_strx >= cchStrings) … … 1146 1148 break; 1147 1149 } 1148 if (iSymbol >= cSyms)1150 if (iSymbol == UINT32_MAX) 1149 1151 return KLDR_ERR_SYMBOL_NOT_FOUND; 1150 1152 } … … 1159 1161 } 1160 1162 1161 /* 1163 /* 1162 1164 * Calc the return values. 1163 1165 */ 1164 1166 if (pfKind) 1165 1167 { 1166 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1168 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1167 1169 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1168 1170 *pfKind = KLDRSYMKIND_32BIT | KLDRSYMKIND_NO_TYPE; … … 1189 1191 *puValue = RVA + BaseAddress; 1190 1192 1191 if ( pfKind 1193 if ( pfKind 1192 1194 && (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE))) 1193 1195 *pfKind = (*pfKind & ~KLDRSYMKIND_TYPE_MASK) | KLDRSYMKIND_CODE; … … 1238 1240 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1239 1241 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1240 rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1241 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, 1242 rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1243 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, 1242 1244 fFlags, pfnCallback, pvUser); 1243 1245 else 1244 1246 rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */ 1245 /*rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1247 /*rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 1246 1248 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, pfnCallback, pvUser);*/ 1247 1249 } … … 1256 1258 /** 1257 1259 * Enum a 32-bit symbol table. 1258 * 1260 * 1259 1261 * @returns See kLdrModQuerySymbol. 1260 * @param pModMachO 1262 * @param pModMachO 1261 1263 * @param paSyms Pointer to the symbol table. 1262 1264 * @param cSyms Number of symbols in the table. 1263 1265 * @param pchStrings Pointer to the string table. 1264 1266 * @param cchStrings Size of the string table. 1265 * @param BaseAddress Adjusted base address, see kLdrModEnumSymbols. 1267 * @param BaseAddress Adjusted base address, see kLdrModEnumSymbols. 1266 1268 * @param fFlags See kLdrModEnumSymbols. 1267 1269 * @param pfnCallback See kLdrModEnumSymbols. 1268 1270 * @param pvUser See kLdrModEnumSymbols. 1269 1271 */ 1270 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 1272 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 1271 1273 const char *pchStrings, uint32_t cchStrings, KLDRADDR BaseAddress, 1272 1274 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) … … 1301 1303 if (paSyms[iSym].n_type & MACHO_N_PEXT) /*??*/ 1302 1304 continue; 1303 if (!paSyms[iSym].n_un.n_strx) 1305 if (!paSyms[iSym].n_un.n_strx) 1304 1306 continue; 1305 1307 } 1306 1308 1307 /* 1308 * Gather symbol info 1309 /* 1310 * Gather symbol info 1309 1311 */ 1310 1312 … … 1679 1681 * Resolve imports and apply base relocations. 1680 1682 */ 1681 rc = kldrModMachORelocateBits(pMod, pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping, pModMachO->LinkAddress, 1683 rc = kldrModMachORelocateBits(pMod, pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping, pModMachO->LinkAddress, 1682 1684 pfnGetImport, pvUser); 1683 1685 … … 1720 1722 * We currently ignore REFERENCE_TYPE. 1721 1723 */ 1722 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1724 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1723 1725 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1724 1726 { … … 1735 1737 size_t cchSymbol; 1736 1738 uint32_t fKind = KLDRSYMKIND_REQ_FLAT; 1737 KLDRADDR Value; 1739 KLDRADDR Value; 1738 1740 1739 1741 /** @todo Implement N_REF_TO_WEAK. */ … … 1783 1785 size_t cchSymbol; 1784 1786 uint32_t fKind = KLDRSYMKIND_REQ_FLAT; 1785 KLDRADDR Value; 1787 KLDRADDR Value; 1786 1788 1787 1789 /** @todo Implement N_REF_TO_WEAK. */ … … 1834 1836 uint32_t iSeg; 1835 1837 int rc; 1836 int (*pfnFixupSection)(PKLDRMODMACHO, uint8_t *, size_t, off_t, const macho_relocation_info_t *, uint32_t, KLDRADDR);1837 1838 1838 1839 … … 1847 1848 * Iterate over the segments and their sections and apply fixups. 1848 1849 */ 1849 pfnFixupSection = NULL;1850 1850 for (iSeg = rc = 0; !rc && iSeg < pModMachO->pMod->cSegments; iSeg++) 1851 1851 { … … 1873 1873 * Apply the fixups. 1874 1874 */ 1875 if (!pfnFixupSection)1876 {1877 /* determin the function for applying fixups. */1878 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE1879 || pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE)1880 pfnFixupSection = kldrModMachOObjFixupSectionGeneric;1881 else1882 {1883 rc = KLDR_ERR_TODO; /* save space for now. */1884 break;1885 }1886 }1887 1888 1875 pbSectBits = (uint8_t *)pvMapping + (uintptr_t)pSect->RVA; 1889 rc = pfnFixupSection(pModMachO, pbSectBits, (size_t)pSect->cb, pSect->offFile, 1890 pSect->paFixups, pSect->cFixups, NewBaseAddress); 1876 if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE) /** @todo this aint right. */ 1877 rc = kldrModMachOFixupSectionGeneric32Bit(pModMachO, pbSectBits, pSect, 1878 (macho_nlist_32_t *)pModMachO->pvaSymbols, 1879 pModMachO->cSymbols, NewBaseAddress); 1880 else 1881 rc = KLDR_ERR_TODO; /* save space for now. */ 1891 1882 if (rc) 1892 1883 break; … … 1898 1889 1899 1890 1900 static int kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits, 1901 off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs, 1902 KLDRADDR NewBaseAddress) 1903 { 1891 /** 1892 * Applies generic fixups to a section in an image of the same endian-ness 1893 * as the host CPU. 1894 * 1895 * @returns 0 on success, non-zero kLdr status code on failure. 1896 * @param pModMachO The Mach-O module interpreter instance. 1897 * @param pbSectBits Pointer to the section bits. 1898 * @param pFixupSect The section being fixed up. 1899 * @param NewBaseAddress The new base image address. 1900 */ 1901 static int kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, PKLDRMODMACHOSECT pFixupSect, 1902 macho_nlist_32_t *paSyms, uint32_t cSyms, KLDRADDR NewBaseAddress) 1903 { 1904 const macho_relocation_info_t *paFixups = pFixupSect->paFixups; 1905 const uint32_t cFixups = pFixupSect->cFixups; 1906 size_t cbSectBits = (size_t)pFixupSect->cb; 1907 const uint8_t *pbSectVirginBits; 1908 uint32_t iFixup; 1909 KLDRPU uFixVirgin; 1910 KLDRPU uFix; 1911 KLDRADDR SymAddr; 1912 int rc; 1913 1914 /* 1915 * Find the virgin bits. 1916 */ 1917 if (pFixupSect->offFile != -1) 1918 { 1919 rc = kldrModMachOMapVirginBits(pModMachO); 1920 if (rc) 1921 return rc; 1922 pbSectVirginBits = (const uint8_t *)pModMachO->pvBits + pFixupSect->offFile; 1923 } 1924 else 1925 pbSectVirginBits = NULL; 1926 1927 /* 1928 * Iterate the fixups and apply them. 1929 */ 1930 for (iFixup = 0; iFixup < cFixups; iFixup++) 1931 { 1932 union 1933 { 1934 macho_relocation_info_t r; 1935 scattered_relocation_info_t s; 1936 } Fixup; 1937 Fixup.r = paFixups[iFixup]; 1938 1939 if (!(Fixup.r.r_address & R_SCATTERED)) 1940 { 1941 /* sanity */ 1942 if ((uint32_t)Fixup.r.r_address >= cbSectBits) 1943 return KLDR_ERR_BAD_FIXUP; 1944 1945 /* calc fixup addresses. */ 1946 uFix.pv = pbSectBits + Fixup.r.r_address; 1947 uFixVirgin.pv = pbSectVirginBits ? (uint8_t *)pbSectVirginBits + Fixup.r.r_address : 0; 1948 1949 /* 1950 * Calc the symbol value. 1951 */ 1952 /* The addend is stored in the code. */ 1953 /** @todo Deal with unaligned accesses on non x86 platforms. */ 1954 switch (Fixup.r.r_length) 1955 { 1956 case 0: SymAddr = *uFixVirgin.pi8; break; 1957 case 1: SymAddr = *uFixVirgin.pi16; break; 1958 case 2: SymAddr = *uFixVirgin.pi32; break; 1959 case 3: SymAddr = *uFixVirgin.pi64; break; 1960 } 1961 1962 /* Add symbol / section address. */ 1963 if (Fixup.r.r_extern) 1964 { 1965 const macho_nlist_32_t *pSym; 1966 if (Fixup.r.r_symbolnum >= cSyms) 1967 return KLDR_ERR_BAD_FIXUP; 1968 pSym = &paSyms[Fixup.r.r_symbolnum]; 1969 1970 if (pSym->n_type & MACHO_N_STAB) 1971 return KLDR_ERR_BAD_FIXUP; 1972 1973 switch (pSym->n_type & MACHO_N_TYPE) 1974 { 1975 case MACHO_N_SECT: 1976 { 1977 PKLDRMODMACHOSECT pSymSect; 1978 if ((uint32_t)pSym->n_sect - 1 > pModMachO->cSections) 1979 return KLDR_ERR_MACHO_BAD_SYMBOL; 1980 pSymSect = &pModMachO->paSections[pSym->n_sect - 1]; 1981 1982 SymAddr += pSym->n_value - pModMachO->LinkAddress + pSymSect->RVA; 1983 break; 1984 } 1985 1986 case MACHO_N_UNDF: 1987 case MACHO_N_ABS: 1988 SymAddr += pSym->n_value; 1989 break; 1990 1991 case MACHO_N_INDR: 1992 case MACHO_N_PBUD: 1993 return KLDR_ERR_TODO; 1994 default: 1995 return KLDR_ERR_MACHO_BAD_SYMBOL; 1996 } 1997 } 1998 else if (Fixup.r.r_symbolnum != R_ABS) 1999 { 2000 PKLDRMODMACHOSECT pSymSect; 2001 if (Fixup.r.r_symbolnum > pModMachO->cSections) 2002 return KLDR_ERR_BAD_FIXUP; 2003 pSymSect = &pModMachO->paSections[Fixup.r.r_symbolnum - 1]; 2004 SymAddr += NewBaseAddress + pSymSect->RVA; 2005 } 2006 2007 /* adjust for PC relative */ 2008 if (Fixup.r.r_pcrel) 2009 SymAddr -= Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress; 2010 } 2011 else 2012 { 2013 PKLDRMODMACHOSECT pSymSect; 2014 uint32_t iSymSect; 2015 KLDRADDR Value; 2016 2017 /* sanity */ 2018 KLDRMODMACHO_ASSERT(Fixup.s.r_scattered); 2019 if ((uint32_t)Fixup.s.r_address >= cbSectBits) 2020 return KLDR_ERR_BAD_FIXUP; 2021 2022 /* calc fixup addresses. */ 2023 uFix.pv = pbSectBits + Fixup.s.r_address; 2024 uFixVirgin.pv = pbSectVirginBits ? (uint8_t *)pbSectVirginBits + Fixup.s.r_address : 0; 2025 2026 /* 2027 * Calc the symbol value. 2028 */ 2029 /* The addend is stored in the code. */ 2030 switch (Fixup.s.r_length) 2031 { 2032 case 0: SymAddr = *uFixVirgin.pi8; break; 2033 case 1: SymAddr = *uFixVirgin.pi16; break; 2034 case 2: SymAddr = *uFixVirgin.pi32; break; 2035 case 3: SymAddr = *uFixVirgin.pi64; break; 2036 } 2037 2038 /* Calc the section number from the r_value and adjust the value. */ 2039 pSymSect = NULL; 2040 Value = Fixup.s.r_value - pModMachO->LinkAddress; 2041 for (iSymSect = 0; iSymSect < pModMachO->cSections; iSymSect++) 2042 { 2043 KLDRADDR off = Value - pModMachO->paSections[iSymSect].RVA; 2044 if (off < pModMachO->paSections[iSymSect].cb) 2045 { 2046 pSymSect = &pModMachO->paSections[iSymSect]; 2047 break; 2048 } 2049 else if (off == pModMachO->paSections[iSymSect].cb) /* edge case */ 2050 pSymSect = &pModMachO->paSections[iSymSect]; 2051 } 2052 if (!pSymSect) 2053 return KLDR_ERR_BAD_FIXUP; 2054 2055 /** @todo this looking up of the r_value section isn't strictly required unless we're going to remove sections from the link. */ 2056 SymAddr += NewBaseAddress + pSymSect->RVA + (Value - pSymSect->RVA); 2057 2058 /* adjust for PC relative */ 2059 if (Fixup.s.r_pcrel) 2060 SymAddr -= Fixup.s.r_address + pFixupSect->RVA + NewBaseAddress; 2061 2062 Fixup.r.r_length = ((scattered_relocation_info_t *)&paFixups[iFixup])->r_length; 2063 Fixup.r.r_type = ((scattered_relocation_info_t *)&paFixups[iFixup])->r_type; 2064 } 2065 2066 /* 2067 * Write back the fixed up value. 2068 */ 2069 if (Fixup.r.r_type == GENERIC_RELOC_VANILLA) 2070 { 2071 switch (Fixup.r.r_length) 2072 { 2073 case 0: *uFix.pu8 = (uint8_t)SymAddr; break; 2074 case 1: *uFix.pu16 = (uint16_t)SymAddr; break; 2075 case 2: *uFix.pu32 = (uint32_t)SymAddr; break; 2076 case 3: *uFix.pu64 = (uint64_t)SymAddr; break; 2077 } 2078 } 2079 else if (Fixup.r.r_type <= GENERIC_RELOC_LOCAL_SECTDIFF) 2080 return KLDR_ERR_TODO; 2081 else 2082 return KLDR_ERR_BAD_FIXUP; 2083 } 1904 2084 1905 2085 return 0; … … 1909 2089 /** 1910 2090 * Loads the symbol table for a MH_OBJECT file. 1911 * 2091 * 1912 2092 * The symbol table is pointed to by KLDRMODMACHO::pvaSymbols. 1913 * 2093 * 1914 2094 * @returns 0 on success, non-zero kLdr status code on failure. 1915 * @param pModMachO The Mach-O module interpret instance.2095 * @param pModMachO The Mach-O module interpreter instance. 1916 2096 */ 1917 2097 static int kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO) … … 1919 2099 int rc = 0; 1920 2100 1921 if ( !pModMachO->pvaSymbols 2101 if ( !pModMachO->pvaSymbols 1922 2102 && pModMachO->cSymbols) 1923 2103 { … … 1958 2138 pModMachO->pvaSymbols = pvSyms; 1959 2139 pModMachO->pchStrings = (char *)pvStrings; 1960 2140 1961 2141 /* perform endian conversion? */ 1962 2142 if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) … … 1971 2151 pSym++; 1972 2152 } 1973 } 2153 } 1974 2154 else if (pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 1975 2155 { … … 2000 2180 2001 2181 /** 2002 * Loads the fixups at the given address and performs endian 2182 * Loads the fixups at the given address and performs endian 2003 2183 * conversion if necessary. 2004 * 2184 * 2005 2185 * @returns 0 on success, non-zero kLdr status code on failure. 2006 * @param pModMachO The Mach-O module interpret instance.2186 * @param pModMachO The Mach-O module interpreter instance. 2007 2187 * @param offFixups The file offset of the fixups. 2008 2188 * @param cFixups The number of fixups to load. … … 2030 2210 2031 2211 /* do endian conversion if necessary. */ 2032 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 2212 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 2033 2213 || pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE) 2034 2214 { … … 2044 2224 else 2045 2225 kldrHlpFree(paFixups); 2226 return rc; 2227 } 2228 2229 2230 /** 2231 * Maps the virgin file bits into memory if not already done. 2232 * 2233 * @returns 0 on success, non-zero kLdr status code on failure. 2234 * @param pModMachO The Mach-O module interpreter instance. 2235 */ 2236 static int kldrModMachOMapVirginBits(PKLDRMODMACHO pModMachO) 2237 { 2238 int rc = 0; 2239 if (!pModMachO->pvBits) 2240 rc = kLdrRdrAllMap(pModMachO->pMod->pRdr, &pModMachO->pvBits); 2046 2241 return rc; 2047 2242 }
Note:
See TracChangeset
for help on using the changeset viewer.