- Timestamp:
- Feb 13, 2007, 9:40:28 AM (18 years ago)
- Location:
- trunk/kLdr
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdr.h
r2962 r2963 58 58 # define INT32_C(c) (c) 59 59 # define INT64_C(c) (c ## LL) 60 # define INT8_MIN (INT8_C(-0x7f) - 1) 61 # define INT16_MIN (INT16_C(-0x7fff) - 1) 62 # define INT32_MIN (INT32_C(-0x7fffffff) - 1) 63 # define INT64_MIN (INT64_C(-0x7fffffffffffffff) - 1) 64 # define INT8_MAX INT8_C(0x7f) 65 # define INT16_MAX INT16_C(0x7fff) 66 # define INT32_MAX INT32_C(0x7fffffff) 67 # define INT64_MAX INT64_C(0x7fffffffffffffff) 68 # define UINT8_MAX UINT8_C(0xff) 69 # define UINT16_MAX UINT16_C(0xffff) 70 # define UINT32_MAX UINT32_C(0xffffffff) 71 # define UINT64_MAX UINT64_C(0xffffffffffffffff) 60 72 # else 61 73 # include <stdint.h> … … 64 76 65 77 66 /** @defgroup grp_kLdr Rdr kLdrRdr - The file provider78 /** @defgroup grp_kLdrBasic kLdr Basic Types 67 79 * @{ */ 68 80 … … 101 113 #endif 102 114 103 /** Pointer to a loader segment. */ 104 typedef struct KLDRSEG *PKLDRSEG; 105 /** Pointer to a loader segment. */ 106 typedef const struct KLDRSEG *PCKLDRSEG; 107 108 115 116 /** 117 * Union of all the integer types. 118 */ 119 typedef union KLDRU 120 { 121 int8_t i8; /**< int8_t view. */ 122 uint8_t u8; /**< uint8_t view. */ 123 int16_t i16; /**< int16_t view. */ 124 uint16_t u16; /**< uint16_t view. */ 125 int32_t i32; /**< int32_t view. */ 126 uint32_t u32; /**< uint32_t view. */ 127 int64_t i64; /**< int64_t view. */ 128 uint64_t u64; /**< uint64_t view. */ 129 130 int8_t ai8[8]; /**< int8_t array view . */ 131 uint8_t au8[8]; /**< uint8_t array view. */ 132 int16_t ai16[4];/**< int16_t array view . */ 133 uint16_t au16[4];/**< uint16_t array view. */ 134 int32_t ai32[2];/**< int32_t array view . */ 135 uint32_t au32[2];/**< uint32_t array view. */ 136 137 signed char ch; /**< signed char view. */ 138 unsigned char uch; /**< unsigned char view. */ 139 signed short s; /**< signed short view. */ 140 unsigned short us; /**< unsigned short view. */ 141 signed int i; /**< signed int view. */ 142 unsigned int u; /**< unsigned int view. */ 143 signed long l; /**< signed long view. */ 144 unsigned long ul; /**< unsigned long view. */ 145 void *pv; /**< void pointer view. */ 146 147 KLDRADDR Addr; /**< kLdr address view. */ 148 KLDRSIZE Size; /**< kLdr size view. */ 149 } KLDRU; 150 /** Pointer to an integer union. */ 151 typedef KLDRU *PKLDRU; 152 /** Pointer to a const integer union. */ 153 typedef const KLDRU *PCKLDRU; 154 155 156 /** 157 * Union of pointers to all the integer types. 158 */ 159 typedef union KLDRPU 160 { 161 int8_t *pi8; /**< int8_t view. */ 162 uint8_t *pu8; /**< uint8_t view. */ 163 int16_t *pi16; /**< int16_t view. */ 164 uint16_t *pu16; /**< uint16_t view. */ 165 int32_t *pi32; /**< int32_t view. */ 166 uint32_t *pu32; /**< uint32_t view. */ 167 int64_t *pi64; /**< int64_t view. */ 168 uint64_t *pu64; /**< uint64_t view. */ 169 170 signed char *pch; /**< signed char view. */ 171 unsigned char *puch; /**< unsigned char view. */ 172 signed short *ps; /**< signed short view. */ 173 unsigned short *pus; /**< unsigned short view. */ 174 signed int *pi; /**< signed int view. */ 175 unsigned int *pu; /**< unsigned int view. */ 176 signed long *pl; /**< signed long view. */ 177 unsigned long *pul; /**< unsigned long view. */ 178 void *pv; /**< void pointer view. */ 179 } KLDRPU; 180 /** Pointer to an integer pointer union. */ 181 typedef KLDRPU *PKLDRPU; 182 /** Pointer to a const integer pointer union. */ 183 typedef const KLDRPU *PCKLDRPU; 109 184 110 185 … … 142 217 } KLDRPROT; 143 218 219 /** Pointer to a loader segment. */ 220 typedef struct KLDRSEG *PKLDRSEG; 221 /** Pointer to a loader segment. */ 222 typedef const struct KLDRSEG *PCKLDRSEG; 223 224 /** @} */ 225 226 227 /** @defgroup grp_kLdrRdr kLdrRdr - The file provider 228 * @{ */ 144 229 145 230 /** Pointer to a file provider instance core. */ -
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 } -
trunk/kLdr/kLdrModMachO.h
r2962 r2963 641 641 /** 642 642 * The 32-bit Mach-O version of the nlist structure. 643 * 644 * This differs from the a.out nlist struct in that the unused n_other field 643 * 644 * This differs from the a.out nlist struct in that the unused n_other field 645 645 * was renamed to n_sect and used for keeping the relevant section number. 646 646 * @remark This structure is not name mach_nlist_32 in the Apple headers, but nlist. … … 648 648 typedef struct macho_nlist_32 649 649 { 650 union 650 union 651 651 { 652 652 int32_t n_strx; /**< Offset (index) into the string table. 0 means "". */ … … 665 665 typedef struct macho_nlist_64 666 666 { 667 union 667 union 668 668 { 669 669 uint32_t n_strx; /**< Offset (index) into the string table. 0 means "". */ … … 676 676 677 677 678 /** @name Symbol Type Constants (macho_nlist_32_t::n_type, macho_nlist_64_t::n_type) 679 * 678 /** @name Symbol Type Constants (macho_nlist_32_t::n_type, macho_nlist_64_t::n_type) 679 * 680 680 * In the Mach-O world n_type is somewhat similar to a.out, meaning N_EXT, N_UNDF, N_ABS 681 681 * and the debug symbols are essentially the same, but the remaining stuff is different. 682 * The main reason for this is that the encoding of section has been moved to n_sect 683 * to permit up to 255 sections instead of the fixed 3 a.out sections (not counting 682 * The main reason for this is that the encoding of section has been moved to n_sect 683 * to permit up to 255 sections instead of the fixed 3 a.out sections (not counting 684 684 * the abs symbols and set vectors). 685 * 686 * To avoid confusion with a.out the Mach-O constants has been fitted with a MACHO_ 685 * 686 * To avoid confusion with a.out the Mach-O constants has been fitted with a MACHO_ 687 687 * prefix here. 688 * 689 * Common symbols (aka communal symbols and comdefs) are represented by 690 * n_type = MACHO_N_EXT | MACHO_N_UNDF, n_sect = NO_SECT and n_value giving 688 * 689 * Common symbols (aka communal symbols and comdefs) are represented by 690 * n_type = MACHO_N_EXT | MACHO_N_UNDF, n_sect = NO_SECT and n_value giving 691 691 * the size. 692 * 693 * 692 * 693 * 694 694 * Symbol table entries can be inserted directly in the assembly code using 695 695 * this notation: … … 697 697 * .stabs "n_name", n_type, n_sect, n_desc, n_value 698 698 * @endcode 699 * 699 * 700 700 * (1) The line number is optional, GCC doesn't set it. 701 701 * (2) The type is optional, GCC doesn't set it. … … 729 729 #define MACHO_N_PC UINT8_C(0x30) /**< Global pascal symbol. "name",, NO_SECT, subtype?, line (3) */ 730 730 /* omits N_NSYMS, N_NOMAP and N_OBJ. */ 731 #define MACHO_N_OPT UINT8_C(0x3c) /**< Options for the debugger related to the language of the 731 #define MACHO_N_OPT UINT8_C(0x3c) /**< Options for the debugger related to the language of the 732 732 source file. "options?",,,, */ 733 733 #define MACHO_N_RSYM UINT8_C(0x40) /**< Register variable. "name",, NO_SECT, type, register */ … … 758 758 #define MACHO_N_ECOMM UINT8_C(0xe4) /**< End common. "name",, section, 0, 0 */ 759 759 #define MACHO_N_ECOML UINT8_C(0xe8) /**< End local common. 0,, section, 0, address */ 760 #define MACHO_N_LENG UINT8_C(0xfe) /**< Length-value of the preceding entry. 760 #define MACHO_N_LENG UINT8_C(0xfe) /**< Length-value of the preceding entry. 761 761 "name",, NO_SECT, 0, length */ 762 762 763 763 /** @} */ 764 764 765 /** @name Symbol Description Bits (macho_nlist_32_t::n_desc, macho_nlist_64_t::n_desc) 766 * 767 * Mach-O puts the n_desc field to a number of uses, like lazy binding , library 765 /** @name Symbol Description Bits (macho_nlist_32_t::n_desc, macho_nlist_64_t::n_desc) 766 * 767 * Mach-O puts the n_desc field to a number of uses, like lazy binding , library 768 768 * ordinal numbers for -twolevel_namespace, stripping and weak symbol handling. 769 * 770 * @remark The REFERENCE_FLAGS_* are really not flags in the normal sense (bit), 769 * 770 * @remark The REFERENCE_FLAGS_* are really not flags in the normal sense (bit), 771 771 * they are more like enum values. 772 772 * @{ … … 802 802 /** Weak external symbol. Symbol can be missing, in which case it's will have the value 0. */ 803 803 #define N_WEAK_REF UINT16_C(0x0040) 804 /** Weak symbol definition. The symbol can be overridden by another weak 805 * symbol already present or by a non-weak (strong) symbol definition. 806 * Currently only supported for coalesed symbols. 804 /** Weak symbol definition. The symbol can be overridden by another weak 805 * symbol already present or by a non-weak (strong) symbol definition. 806 * Currently only supported for coalesed symbols. 807 807 * @remark This bit means something differently for undefined symbols, see N_REF_TO_WEAK. 808 808 */ … … 822 822 /** 823 823 * Relocation entry. 824 * 825 * Differs from a.out in the meaning of r_symbolnum when r_extern=0 and 826 * that r_pad is made into r_type. 827 * 824 * 825 * Differs from a.out in the meaning of r_symbolnum when r_extern=0 and 826 * that r_pad is made into r_type. 827 * 828 828 * @remark This structure and type has been prefixed with macho_ to avoid 829 829 * confusion with the original a.out type. 830 830 */ 831 typedef struct macho_relocation_info 832 { 833 int32_t r_address; /**< Section relative address of the fixup. 834 The top bit (signed) indicates that this is a scattered 831 typedef struct macho_relocation_info 832 { 833 int32_t r_address; /**< Section relative address of the fixup. 834 The top bit (signed) indicates that this is a scattered 835 835 relocation if set, see scattered_relocation_info_t. */ 836 836 uint32_t r_symbolnum : 24, /**< r_extern=1: Symbol table index, relocate with the address of this symbol. … … 845 845 #define R_ABS 0 846 846 847 /** Flag in r_address indicating that the relocation is of the 847 /** Flag in r_address indicating that the relocation is of the 848 848 * scattered_relocation_info_t kind and not macho_relocation_info_t. */ 849 849 #define R_SCATTERED UINT32_C(0x80000000) … … 851 851 /** 852 852 * Scattered relocation. 853 * 854 * This is a hack mainly for RISC machines which restricts section size 853 * 854 * This is a hack mainly for RISC machines which restricts section size 855 855 * to 16MB among other things. 856 * 856 * 857 857 * The reason for the big/little endian differences here is of course because 858 * of the R_SCATTERED mask and the way bitfields are implemented by the 858 * of the R_SCATTERED mask and the way bitfields are implemented by the 859 859 * C/C++ compilers. 860 860 */ … … 876 876 # error "Neither KLDR_LITTLE_ENDIAN nor KLDR_BIG_ENDIAN is defined!" 877 877 #endif 878 int32_t r_value; /**< The value the fixup is refering to ( Without offset added). */878 int32_t r_value; /**< The value the fixup is refering to (without offset added). */ 879 879 } scattered_relocation_info_t; 880 880 … … 884 884 typedef enum reloc_type_generic 885 885 { 886 GENERIC_RELOC_VANILLA = 0, /**< Standard relocation. */ 886 GENERIC_RELOC_VANILLA = 0, /**< Standard relocation. */ 887 887 GENERIC_RELOC_PAIR, /**< Follows GENERIC_RELOC_SECTDIFF. */ 888 888 GENERIC_RELOC_SECTDIFF, /**< ??? */ -
trunk/kLdr/kLdrRdrFile.c
r2893 r2963 934 934 } 935 935 936 *ppvBits = pRdrFile->pvMapping; 936 937 pRdrFile->cMappings++; 937 938 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.