- Timestamp:
- Feb 11, 2007, 6:55:04 PM (19 years ago)
- Location:
- trunk/kLdr
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdr.h
r2961 r2962 650 650 /** Request a segmented symbol address. */ 651 651 #define KLDRSYMKIND_REQ_SEGMENTED 0x40000000 652 /** Request type mask. */ 653 #define KLDRSYMKIND_REQ_TYPE_MASK 0x40000000 652 654 /** @} */ 653 655 -
trunk/kLdr/kLdrModMachO.c
r2961 r2962 74 74 * This is -1 if the section doesn't have any fixups. */ 75 75 off_t offFixups; 76 /** Mach-O section flags. */ 77 uint32_t fFlags; 78 /** kLdr segment index. */ 79 uint32_t iSegment; 76 80 /** Pointer to the Mach-O section structure. */ 77 void *pvMachoSection; 78 81 void *pvMachoSection; 79 82 } KLDRMODMACHOSECT, *PKLDRMODMACHOSECT; 80 83 … … 103 106 /** Pointer to the module. (Follows the section table.) */ 104 107 PKLDRMOD pMod; 105 /** Pointer to the RDR mapping of the raw file bits. NULL if not mapped. */108 /** Pointer to the RDR file mapping of the raw file bits. NULL if not mapped. */ 106 109 const void *pvBits; 107 110 /** Pointer to the user mapping. */ 108 const void*pvMapping;111 void *pvMapping; 109 112 110 113 /** The link address. */ … … 131 134 off_t offStrings; 132 135 /** The size of the of the string table. */ 133 uint32_t c bStrings;136 uint32_t cchStrings; 134 137 /** Pointer to the loaded string table. */ 135 138 char *pchStrings; 139 140 /** The number of sections. */ 141 uint32_t cSections; 142 /** Pointer to the section array running in parallel to the Mach-O one. */ 143 PKLDRMODMACHOSECT paSections; 144 136 145 /** Array of segments parallel to the one in KLDRMOD. */ 137 146 KLDRMODMACHOSEG aSegments[1]; … … 153 162 uint32_t *pcSegments, uint32_t *pcSections, uint32_t *pcbStringPool); 154 163 static int kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool); 164 static int kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress); 165 155 166 /*static int kldrModMachOLoadLoadCommands(PKLDRMODMACHO pModMachO);*/ 156 167 static int kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO); 157 168 static int kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, off_t offFixups, uint32_t cFixups, void **pvFixups); 158 169 170 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 size_t cchSymbol, PKLDRADDR puValue, uint32_t *pfKind); 173 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 174 const char *pchStrings, uint32_t cchStrings, KLDRADDR BaseAddress, 175 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser); 159 176 static int kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 160 177 static int kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress); … … 376 393 pModMachO->pvaSymbols = NULL; 377 394 pModMachO->offStrings = 0; 378 pModMachO->c bStrings = 0;395 pModMachO->cchStrings = 0; 379 396 pModMachO->pchStrings = NULL; 397 pModMachO->cSections = cSections; 398 pModMachO->paSections = (PKLDRMODMACHOSECT)&pModMachO->aSegments[pModMachO->pMod->cSegments]; 380 399 381 400 /* … … 778 797 PKLDRSEG pSeg = &pModMachO->pMod->aSegments[0]; 779 798 PKLDRMODMACHOSEG pSegExtra = &pModMachO->aSegments[0]; 780 PKLDRMODMACHOSECT pSectExtra = (PKLDRMODMACHOSECT)&pModMachO->aSegments[pModMachO->pMod->cSegments];799 PKLDRMODMACHOSECT pSectExtra = pModMachO->paSections; 781 800 const uint32_t cSegments = pModMachO->pMod->cSegments; 782 801 uint32_t i; … … 812 831 case MH_OBJECT: 813 832 { 814 /* Don't load debug symbols. (test this) */ 833 /* Section data extract. */ 834 pSectExtra->cb = pSect->size; 835 pSectExtra->RVA = pSect->addr; 836 pSectExtra->offFile = pSect->offset ? pSect->offset : -1; 837 pSectExtra->cFixups = pSect->nreloc; 838 pSectExtra->paFixups = NULL; 839 pSectExtra->offFixups = pSect->nreloc ? pSect->reloff : -1; 840 pSectExtra->fFlags = pSect->flags; 841 pSectExtra->iSegment = pSegExtra - &pModMachO->aSegments[0]; 842 pSectExtra->pvMachoSection = pSect; 843 844 /* Don't load debug symbols. (test this!) */ 815 845 if (pSect->flags & S_ATTR_DEBUG) 816 846 break; … … 820 850 { 821 851 /* close the previous segment */ 822 if (pSegExtra != &pModMachO->aSegments[ 1])852 if (pSegExtra != &pModMachO->aSegments[0]) 823 853 pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections; 824 854 … … 880 910 /** @todo update the protection... */ 881 911 } 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 912 pSectExtra++; 892 913 break; … … 910 931 pModMachO->cSymbols = u.pSymTab->nsyms; 911 932 pModMachO->offStrings = u.pSymTab->stroff; 912 pModMachO->c bStrings = u.pSymTab->strsize;933 pModMachO->cchStrings = u.pSymTab->strsize; 913 934 break; 914 935 } … … 994 1015 995 1016 /** 996 * Performs the mapping of the image. 997 * 998 * This can be used to do the internal mapping as well as the 999 * user requested mapping. fForReal indicates which is desired. 1000 * 1001 * @returns 0 on success, non-zero OS or kLdr status code on failure. 1002 * @param pModMachO The interpreter module instance 1003 * @param fForReal If set, do the user mapping. if clear, do the internal mapping. 1004 */ 1005 static int kldrModMachODoMap(PKLDRMODMACHO pModMachO, unsigned fForReal) 1006 { 1007 #if 0 1008 PKLDRMOD pMod = pModMachO->pMod; 1009 unsigned fFixed; 1010 void *pvBase; 1011 int rc; 1012 uint32_t i; 1013 1014 /* 1015 * Map it. 1016 */ 1017 /* fixed image? */ 1018 fFixed = fForReal 1019 && ( pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED 1020 || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED); 1021 if (!fFixed) 1022 pvBase = NULL; 1023 else 1024 { 1025 pvBase = (void *)(uintptr_t)pMod->aSegments[0].LinkAddress; 1026 if ((uintptr_t)pvBase != pMod->aSegments[0].LinkAddress) 1027 return KLDR_ERR_ADDRESS_OVERFLOW; 1028 } 1029 1030 /* try do the prepare */ 1031 rc = kLdrRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed); 1032 if (rc) 1033 return rc; 1034 1035 /* 1036 * Update the segments with their map addresses. 1037 */ 1038 if (fForReal) 1039 { 1040 for (i = 0; i < pMod->cSegments; i++) 1041 { 1042 if (pMod->aSegments[i].RVA != NIL_KLDRADDR) 1043 pMod->aSegments[i].MapAddress = (uintptr_t)pvBase + (uintptr_t)pMod->aSegments[i].RVA; 1044 } 1045 pModMachO->pvMapping = pvBase; 1046 } 1047 else 1048 pModMachO->pvBits = pvBase; 1049 #endif 1050 return 0; 1051 } 1052 1053 1054 /** 1055 * Unmaps a image mapping. 1056 * 1057 * This can be used to do the internal mapping as well as the 1058 * user requested mapping. fForReal indicates which is desired. 1059 * 1060 * @returns 0 on success, non-zero OS or kLdr status code on failure. 1061 * @param pModMachO The interpreter module instance 1062 * @param pvMapping The mapping to unmap. 1063 */ 1064 static int kldrModMachODoUnmap(PKLDRMODMACHO pModMachO, const void *pvMapping) 1065 { 1066 #if 0 1067 PKLDRMOD pMod = pModMachO->pMod; 1068 int rc; 1069 uint32_t i; 1070 1071 /* 1072 * Try unmap the image. 1073 */ 1074 rc = kLdrRdrUnmap(pMod->pRdr, (void *)pvMapping, pMod->cSegments, pMod->aSegments); 1075 if (rc) 1076 return rc; 1077 1078 /* 1079 * Update the segments to reflect that they aren't mapped any longer. 1080 */ 1081 if (pModMachO->pvMapping == pvMapping) 1082 { 1083 pModMachO->pvMapping = NULL; 1084 for (i = 0; i < pMod->cSegments; i++) 1085 pMod->aSegments[i].MapAddress = 0; 1086 } 1087 if (pModMachO->pvBits == pvMapping) 1088 pModMachO->pvBits = NULL; 1089 #endif 1090 1091 return 0; 1092 } 1093 1094 1095 /** 1096 * Gets usable bits and the right base address. 1017 * Gets the right base address. 1097 1018 * 1098 1019 * @returns 0 on success. 1099 * @returns A non-zero status code if the BaseAddress isn't right or some problem is encountered 1100 * featch in a temp mapping the bits. 1101 * @param pModMachO The interpreter module instance 1102 * @param ppvBits The bits address, IN & OUT. 1020 * @returns A non-zero status code if the BaseAddress isn't right. 1021 * @param pModMachO The interpreter module instance 1103 1022 * @param pBaseAddress The base address, IN & OUT. Optional. 1104 1023 */ 1105 static int kldrModMachOBitsAndBaseAddress(PKLDRMODMACHO pModMachO, const void **ppvBits, PKLDRADDR pBaseAddress) 1106 { 1107 int rc = 0; 1108 1109 /* 1110 * Correct the base address. 1111 * 1112 * We don't use the base address for interpreting the bits in this 1113 * interpreter, which makes things relativly simple. 1114 */ 1115 if (pBaseAddress) 1116 { 1117 if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP) 1118 *pBaseAddress = pModMachO->pMod->aSegments[0].MapAddress; 1119 else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK) 1120 *pBaseAddress = pModMachO->LinkAddress; 1121 } 1122 1123 /* 1124 * Get bits. 1125 */ 1126 if (ppvBits && !*ppvBits) 1127 { 1128 if (pModMachO->pvMapping) 1129 *ppvBits = pModMachO->pvMapping; 1130 else if (pModMachO->pvBits) 1131 *ppvBits = pModMachO->pvBits; 1132 else 1133 { 1134 /* create an internal mapping. */ 1135 rc = kldrModMachODoMap(pModMachO, 0 /* not for real */); 1136 if (rc) 1137 return rc; 1138 KLDRMODMACHO_ASSERT(pModMachO->pvBits); 1139 *ppvBits = pModMachO->pvBits; 1140 } 1141 } 1024 static int kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress) 1025 { 1026 /* 1027 * Adjust the base address. 1028 */ 1029 if (*pBaseAddress == KLDRMOD_BASEADDRESS_MAP) 1030 *pBaseAddress = pModMachO->pMod->aSegments[0].MapAddress; 1031 else if (*pBaseAddress == KLDRMOD_BASEADDRESS_LINK) 1032 *pBaseAddress = pModMachO->LinkAddress; 1142 1033 1143 1034 return 0; 1144 1035 } 1036 1145 1037 1146 1038 … … 1149 1041 const char *pchSymbol, size_t cchSymbol, const char *pszVersion, 1150 1042 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind) 1151 1152 { 1153 #if 0 1154 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1155 const uint32_t *paExportRVAs; 1156 const IMAGE_EXPORT_DIRECTORY *pExpDir; 1157 uint32_t iExpOrd; 1158 uint32_t uRVA; 1159 int rc; 1160 1161 /* 1162 * Make sure we've got mapped bits and resolve any base address aliases. 1163 */ 1164 rc = kldrModMachOBitsAndBaseAddress(pModMachO, &pvBits, &BaseAddress); 1043 { 1044 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1045 int rc; 1046 1047 /* 1048 * Resolve defaults. 1049 */ 1050 rc = kldrModMachOAdjustBaseAddress(pModMachO, &BaseAddress); 1165 1051 if (rc) 1166 1052 return rc; 1167 if ( pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size 1168 < sizeof(IMAGE_EXPORT_DIRECTORY)) 1169 return KLDR_ERR_SYMBOL_NOT_FOUND; 1170 if (pszVersion && *pszVersion) 1171 return KLDR_ERR_SYMBOL_NOT_FOUND; 1172 1173 pExpDir = KLDRMODMACHO_RVA2TYPE(pvBits, 1174 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress, 1175 PIMAGE_EXPORT_DIRECTORY); 1176 if (!pchSymbol) 1177 { 1178 /* 1179 * Simple, calculate the unbased ordinal and bounds check it. 1053 1054 /* 1055 * Refuse segmented requests for now. 1056 */ 1057 if ( pfKind 1058 && (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) != KLDRSYMKIND_REQ_FLAT) 1059 return KLDR_ERR_TODO; 1060 1061 /* 1062 * Take action according to file type. 1063 */ 1064 if (pModMachO->Hdr.filetype == MH_OBJECT) 1065 { 1066 rc = kldrModMachOLoadObjSymTab(pModMachO); 1067 if (!rc) 1068 { 1069 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1070 || 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, 1073 cchSymbol, puValue, pfKind); 1074 else 1075 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, 1078 cchSymbol, puValue, pfKind);*/ 1079 1080 } 1081 } 1082 else 1083 rc = KLDR_ERR_TODO; 1084 1085 return rc; 1086 } 1087 1088 1089 1090 /** 1091 * Lookup a symbol in a 32-bit symbol table. 1092 * 1093 * @returns See kLdrModQuerySymbol. 1094 * @param pModMachO 1095 * @param paSyms Pointer to the symbol table. 1096 * @param cSyms Number of symbols in the table. 1097 * @param pchStrings Pointer to the string table. 1098 * @param cchStrings Size of the string table. 1099 * @param BaseAddress Adjusted base address, see kLdrModQuerySymbol. 1100 * @param iSymbol See kLdrModQuerySymbol. 1101 * @param pchSymbol See kLdrModQuerySymbol. 1102 * @param cchSymbol See kLdrModQuerySymbol. 1103 * @param puValue See kLdrModQuerySymbol. 1104 * @param pfKind See kLdrModQuerySymbol. 1105 */ 1106 static int kldrModMachODoQuerySymbol32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, const char *pchStrings, 1107 uint32_t cchStrings, KLDRADDR BaseAddress, uint32_t iSymbol, const char *pchSymbol, size_t cchSymbol, 1108 PKLDRADDR puValue, uint32_t *pfKind) 1109 { 1110 /* 1111 * Find a valid symbol matching the search criteria. 1112 */ 1113 if (iSymbol == NIL_KLDRMOD_SYM_ORDINAL) 1114 { 1115 /* simplify validation. */ 1116 if (cchStrings <= cchSymbol) 1117 return KLDR_ERR_SYMBOL_NOT_FOUND; 1118 cchStrings -= cchSymbol; 1119 1120 for (iSymbol = 0; iSymbol < cSyms; iSymbol++) 1121 { 1122 const char *psz; 1123 1124 /* Skip irrellevant and non-public symbols. */ 1125 if (paSyms[iSymbol].n_type & MACHO_N_STAB) 1126 continue; 1127 if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1128 continue; 1129 if (!(paSyms[iSymbol].n_type & MACHO_N_EXT)) /*??*/ 1130 continue; 1131 if (paSyms[iSymbol].n_type & MACHO_N_PEXT) /*??*/ 1132 continue; 1133 1134 /* get name */ 1135 if (!paSyms[iSymbol].n_un.n_strx) 1136 continue; 1137 if ((uint32_t)paSyms[iSymbol].n_un.n_strx >= cchStrings) 1138 continue; 1139 psz = &pchStrings[paSyms[iSymbol].n_un.n_strx]; 1140 if (psz[cchSymbol]) 1141 continue; 1142 if (kLdrHlpMemComp(psz, pchSymbol, cchSymbol)) 1143 continue; 1144 1145 /* match! */ 1146 break; 1147 } 1148 if (iSymbol >= cSyms) 1149 return KLDR_ERR_SYMBOL_NOT_FOUND; 1150 } 1151 else 1152 { 1153 if (iSymbol >= cSyms) 1154 return KLDR_ERR_SYMBOL_NOT_FOUND; 1155 if (paSyms[iSymbol].n_type & MACHO_N_STAB) 1156 return KLDR_ERR_SYMBOL_NOT_FOUND; 1157 if ((paSyms[iSymbol].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1158 return KLDR_ERR_SYMBOL_NOT_FOUND; 1159 } 1160 1161 /* 1162 * Calc the return values. 1163 */ 1164 if (pfKind) 1165 { 1166 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1167 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE) 1168 *pfKind = KLDRSYMKIND_32BIT | KLDRSYMKIND_NO_TYPE; 1169 else 1170 *pfKind = KLDRSYMKIND_64BIT | KLDRSYMKIND_NO_TYPE; 1171 if (paSyms[iSymbol].n_desc & N_WEAK_DEF) 1172 *pfKind |= KLDRSYMKIND_WEAK; 1173 } 1174 1175 switch (paSyms[iSymbol].n_type & MACHO_N_TYPE) 1176 { 1177 case MACHO_N_SECT: 1178 { 1179 PKLDRMODMACHOSECT pSect; 1180 KLDRADDR RVA; 1181 if ((uint32_t)(paSyms[iSymbol].n_sect - 1) >= pModMachO->cSections) 1182 return KLDR_ERR_MACHO_BAD_SYMBOL; 1183 pSect = &pModMachO->paSections[paSyms[iSymbol].n_sect - 1]; 1184 1185 RVA = paSyms[iSymbol].n_value - pModMachO->LinkAddress; 1186 if (RVA - pSect->RVA >= pSect->cb) 1187 return KLDR_ERR_MACHO_BAD_SYMBOL; 1188 if (puValue) 1189 *puValue = RVA + BaseAddress; 1190 1191 if ( pfKind 1192 && (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE))) 1193 *pfKind = (*pfKind & ~KLDRSYMKIND_TYPE_MASK) | KLDRSYMKIND_CODE; 1194 break; 1195 } 1196 1197 case MACHO_N_ABS: 1198 if (puValue) 1199 *puValue = paSyms[iSymbol].n_value; 1200 /*if (pfKind) 1201 pfKind |= KLDRSYMKIND_ABS;*/ 1202 break; 1203 1204 case MACHO_N_PBUD: 1205 case MACHO_N_INDR: 1206 /** @todo implement indirect and prebound symbols. */ 1207 default: 1208 KLDRMODMACHO_ASSERT(0); 1209 return KLDR_ERR_TODO; 1210 } 1211 1212 return 0; 1213 } 1214 1215 1216 /** @copydoc kLdrModEnumSymbols */ 1217 static int kldrModMachOEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress, 1218 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) 1219 { 1220 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1221 int rc; 1222 1223 /* 1224 * Resolve defaults. 1225 */ 1226 rc = kldrModMachOAdjustBaseAddress(pModMachO, &BaseAddress); 1227 if (rc) 1228 return rc; 1229 1230 /* 1231 * Take action according to file type. 1232 */ 1233 if (pModMachO->Hdr.filetype == MH_OBJECT) 1234 { 1235 rc = kldrModMachOLoadObjSymTab(pModMachO); 1236 if (!rc) 1237 { 1238 if ( pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1239 || 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 fFlags, pfnCallback, pvUser); 1243 else 1244 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, 1246 pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, pfnCallback, pvUser);*/ 1247 } 1248 } 1249 else 1250 rc = KLDR_ERR_TODO; 1251 1252 return rc; 1253 } 1254 1255 1256 /** 1257 * Enum a 32-bit symbol table. 1258 * 1259 * @returns See kLdrModQuerySymbol. 1260 * @param pModMachO 1261 * @param paSyms Pointer to the symbol table. 1262 * @param cSyms Number of symbols in the table. 1263 * @param pchStrings Pointer to the string table. 1264 * @param cchStrings Size of the string table. 1265 * @param BaseAddress Adjusted base address, see kLdrModEnumSymbols. 1266 * @param fFlags See kLdrModEnumSymbols. 1267 * @param pfnCallback See kLdrModEnumSymbols. 1268 * @param pvUser See kLdrModEnumSymbols. 1269 */ 1270 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 1271 const char *pchStrings, uint32_t cchStrings, KLDRADDR BaseAddress, 1272 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser) 1273 { 1274 const uint32_t fKindBase = pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 1275 || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 1276 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT; 1277 uint32_t iSym; 1278 int rc; 1279 1280 /* 1281 * Iterate the symbol table. 1282 */ 1283 for (iSym = 0; iSym < cSyms; iSym++) 1284 { 1285 uint32_t fKind; 1286 KLDRADDR uValue; 1287 const char *psz; 1288 size_t cch; 1289 1290 /* Skip debug symbols and undefined symbols. */ 1291 if (paSyms[iSym].n_type & MACHO_N_STAB) 1292 continue; 1293 if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF) 1294 continue; 1295 1296 /* Skip non-public symbols unless they are requested explicitly. */ 1297 if (!(fFlags & KLDRMOD_ENUM_SYMS_FLAGS_ALL)) 1298 { 1299 if (!(paSyms[iSym].n_type & MACHO_N_EXT)) /*??*/ 1300 continue; 1301 if (paSyms[iSym].n_type & MACHO_N_PEXT) /*??*/ 1302 continue; 1303 if (!paSyms[iSym].n_un.n_strx) 1304 continue; 1305 } 1306 1307 /* 1308 * Gather symbol info 1180 1309 */ 1181 iExpOrd = iSymbol - pExpDir->Base; 1182 if (iExpOrd >= KLDR_MAX(pExpDir->NumberOfNames, pExpDir->NumberOfFunctions)) 1183 return KLDR_ERR_SYMBOL_NOT_FOUND; 1184 } 1185 else 1186 { 1187 /* 1188 * Do a binary search for the name. 1189 * (The name table is sorted in ascending ordered by the linker.) 1190 */ 1191 const uint32_t *paRVANames = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNames, const uint32_t *); 1192 const uint16_t *paOrdinals = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNameOrdinals, const uint16_t *); 1193 int32_t iStart = 1; /* one based binary searching is simpler. */ 1194 int32_t iEnd = pExpDir->NumberOfNames; 1195 1196 for (;;) 1310 1311 /* name */ 1312 if ((uint32_t)paSyms[iSym].n_un.n_strx >= cchStrings) 1313 return KLDR_ERR_MACHO_BAD_SYMBOL; 1314 psz = &pchStrings[paSyms[iSym].n_un.n_strx]; 1315 cch = kLdrHlpStrLen(psz); 1316 if (!cch) 1317 psz = NULL; 1318 1319 /* kind & value */ 1320 fKind = fKindBase; 1321 if (paSyms[iSym].n_desc & N_WEAK_DEF) 1322 fKind |= KLDRSYMKIND_WEAK; 1323 switch (paSyms[iSym].n_type & MACHO_N_TYPE) 1197 1324 { 1198 int32_t i; 1199 int diff; 1200 const char *pszName; 1201 1202 /* done? */ 1203 if (iStart > iEnd) 1325 case MACHO_N_SECT: 1204 1326 { 1205 #ifdef KLDRMODMACHO_STRICT /* Make sure the linker and we both did our job right. */ 1206 for (i = 0; i < (int32_t)pExpDir->NumberOfNames; i++) 1207 1208 { 1209 pszName = KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[i], const char *); 1210 KLDRMODMACHO_ASSERT(kLdrHlpStrNComp(pszName, pchSymbol, cchSymbol) || pszName[cchSymbol]); 1211 KLDRMODMACHO_ASSERT(i == 0 || kLdrHlpStrComp(pszName, KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[i - 1], const char *))); 1212 } 1213 #endif 1214 return KLDR_ERR_SYMBOL_NOT_FOUND; 1215 } 1216 1217 i = (iEnd - iStart) / 2 + iStart; 1218 pszName = KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[i - 1], const char *); 1219 diff = kLdrHlpStrNComp(pszName, pchSymbol, cchSymbol); 1220 if (!diff) 1221 diff = pszName[cchSymbol] - 0; 1222 if (diff < 0) 1223 iStart = i + 1; /* The symbol must be after the current name. */ 1224 else if (diff) 1225 iEnd = i - 1; /* The symbol must be before the current name. */ 1226 else 1227 { 1228 iExpOrd = paOrdinals[i - 1]; /* match! */ 1327 PKLDRMODMACHOSECT pSect; 1328 if ((uint32_t)(paSyms[iSym].n_sect - 1) >= pModMachO->cSections) 1329 return KLDR_ERR_MACHO_BAD_SYMBOL; 1330 pSect = &pModMachO->paSections[paSyms[iSym].n_sect - 1]; 1331 1332 uValue = paSyms[iSym].n_value - pModMachO->LinkAddress; 1333 if (uValue - pSect->RVA >= pSect->cb) 1334 return KLDR_ERR_MACHO_BAD_SYMBOL; 1335 uValue += BaseAddress; 1336 1337 if (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE)) 1338 fKind |= KLDRSYMKIND_CODE; 1339 else 1340 fKind |= KLDRSYMKIND_NO_TYPE; 1229 1341 break; 1230 1342 } 1343 1344 case MACHO_N_ABS: 1345 uValue = paSyms[iSym].n_value; 1346 fKind |= KLDRSYMKIND_NO_TYPE /*KLDRSYMKIND_ABS*/; 1347 break; 1348 1349 case MACHO_N_PBUD: 1350 case MACHO_N_INDR: 1351 /** @todo implement indirect and prebound symbols. */ 1352 default: 1353 KLDRMODMACHO_ASSERT(0); 1354 return KLDR_ERR_TODO; 1231 1355 } 1232 }1233 1234 /*1235 * Lookup the address in the 'symbol' table.1236 */1237 paExportRVAs = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfFunctions, const uint32_t *);1238 uRVA = paExportRVAs[iExpOrd];1239 if ( uRVA - pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress1240 < pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)1241 return kldrModMachODoForwarderQuery(pModMachO, pvBits, KLDRMODMACHO_RVA2TYPE(pvBits, uRVA, const char *),1242 pfnGetForwarder, pvUser, puValue, pfKind);1243 1244 /*1245 * Set the return value.1246 */1247 if (puValue)1248 *puValue = BaseAddress + uRVA;1249 if (pfKind)1250 *pfKind = (pModMachO->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)1251 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)1252 | KLDRSYMKIND_NO_TYPE;1253 #endif1254 return 0;1255 }1256 1257 1258 /** @copydoc kLdrModEnumSymbols */1259 static int kldrModMachOEnumSymbols(PKLDRMOD pMod, const void *pvBits, KLDRADDR BaseAddress,1260 uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)1261 {1262 #if 01263 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;1264 const uint32_t *paFunctions;1265 const IMAGE_EXPORT_DIRECTORY *pExpDir;1266 const uint32_t *paRVANames;1267 const uint16_t *paOrdinals;1268 uint32_t iFunction;1269 uint32_t cFunctions;1270 uint32_t cNames;1271 int rc;1272 1273 /*1274 * Make sure we've got mapped bits and resolve any base address aliases.1275 */1276 rc = kldrModMachOBitsAndBaseAddress(pModMachO, &pvBits, &BaseAddress);1277 if (rc)1278 return rc;1279 1280 if ( pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size1281 < sizeof(IMAGE_EXPORT_DIRECTORY))1282 return 0; /* no exports to enumerate, return success. */1283 1284 pExpDir = KLDRMODMACHO_RVA2TYPE(pvBits,1285 pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress,1286 PIMAGE_EXPORT_DIRECTORY);1287 1288 /*1289 * Enumerate the ordinal exports.1290 */1291 paRVANames = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNames, const uint32_t *);1292 paOrdinals = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfNameOrdinals, const uint16_t *);1293 paFunctions = KLDRMODMACHO_RVA2TYPE(pvBits, pExpDir->AddressOfFunctions, const uint32_t *);1294 cFunctions = pExpDir->NumberOfFunctions;1295 cNames = pExpDir->NumberOfNames;1296 for (iFunction = 0; iFunction < cFunctions; iFunction++)1297 {1298 unsigned fFoundName;1299 uint32_t iName;1300 const uint32_t uRVA = paFunctions[iFunction];1301 const KLDRADDR uValue = BaseAddress + uRVA;1302 uint32_t fKind = (pModMachO->Hdrs.FileHeader.SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)1303 ? KLDRSYMKIND_32BIT : KLDRSYMKIND_64BIT)1304 | KLDRSYMKIND_NO_TYPE;1305 if ( uRVA - pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress1306 < pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)1307 fKind |= KLDRSYMKIND_FORWARDER;1308 1356 1309 1357 /* 1310 * Any symbol names?1358 * Do callback. 1311 1359 */ 1312 fFoundName = 0; 1313 for (iName = 0; iName < cNames; iName++) 1314 { 1315 const char *pszName; 1316 if (paOrdinals[iName] != iFunction) 1317 continue; 1318 fFoundName = 1; 1319 pszName = KLDRMODMACHO_RVA2TYPE(pvBits, paRVANames[iName], const char *); 1320 rc = pfnCallback(pMod, iFunction + pExpDir->Base, pszName, kLdrHlpStrLen(pszName), NULL, 1321 uValue, fKind, pvUser); 1322 if (rc) 1323 return rc; 1324 } 1325 1326 /* 1327 * If no names, call once with the ordinal only. 1328 */ 1329 if (!fFoundName) 1330 { 1331 rc = pfnCallback(pMod, iFunction + pExpDir->Base, NULL, 0, NULL, uValue, fKind, pvUser); 1332 if (rc) 1333 return rc; 1334 } 1335 } 1336 #endif 1360 rc = pfnCallback(pModMachO->pMod, iSym, psz, cch, NULL, uValue, fKind, pvUser); 1361 if (rc) 1362 return rc; 1363 } 1337 1364 return 0; 1338 1365 } … … 1502 1529 static int kldrModMachOMap(PKLDRMOD pMod) 1503 1530 { 1504 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1505 int rc; 1531 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1532 unsigned fFixed; 1533 uint32_t i; 1534 void *pvBase; 1535 int rc; 1506 1536 1507 1537 /* … … 1512 1542 1513 1543 /* 1514 * We've got a common worker which does this. 1515 */ 1516 rc = kldrModMachODoMap(pModMachO, 1 /* the real thing */); 1517 if (rc) 1518 return rc; 1519 KLDRMODMACHO_ASSERT(pModMachO->pvMapping); 1544 * Map it. 1545 */ 1546 /* fixed image? */ 1547 fFixed = pMod->enmType == KLDRTYPE_EXECUTABLE_FIXED 1548 || pMod->enmType == KLDRTYPE_SHARED_LIBRARY_FIXED; 1549 if (!fFixed) 1550 pvBase = NULL; 1551 else 1552 { 1553 pvBase = (void *)(uintptr_t)pMod->aSegments[0].LinkAddress; 1554 if ((uintptr_t)pvBase != pMod->aSegments[0].LinkAddress) 1555 return KLDR_ERR_ADDRESS_OVERFLOW; 1556 } 1557 1558 /* try do the prepare */ 1559 if (pModMachO->fMapUsingLoadCommandSections) 1560 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */ 1561 else 1562 { 1563 rc = kLdrRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed); 1564 if (rc) 1565 return rc; 1566 } 1567 1568 /* 1569 * Update the segments with their map addresses. 1570 */ 1571 for (i = 0; i < pMod->cSegments; i++) 1572 { 1573 if (pMod->aSegments[i].RVA != NIL_KLDRADDR) 1574 pMod->aSegments[i].MapAddress = (uintptr_t)pvBase + (uintptr_t)pMod->aSegments[i].RVA; 1575 } 1576 pModMachO->pvMapping = pvBase; 1577 1520 1578 return 0; 1521 1579 } … … 1525 1583 static int kldrModMachOUnmap(PKLDRMOD pMod) 1526 1584 { 1527 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1528 int rc; 1585 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1586 uint32_t i; 1587 int rc; 1529 1588 1530 1589 /* … … 1535 1594 1536 1595 /* 1537 * We've got a common worker which does this. 1538 */ 1539 rc = kldrModMachODoUnmap(pModMachO, pModMachO->pvMapping); 1540 if (rc) 1541 return rc; 1542 KLDRMODMACHO_ASSERT(pModMachO->pvMapping); 1596 * Try unmap the image. 1597 */ 1598 if (pModMachO->fMapUsingLoadCommandSections) 1599 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */ 1600 else 1601 { 1602 rc = kLdrRdrUnmap(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments); 1603 if (rc) 1604 return rc; 1605 } 1606 1607 /* 1608 * Update the segments to reflect that they aren't mapped any longer. 1609 */ 1610 pModMachO->pvMapping = NULL; 1611 for (i = 0; i < pMod->cSegments; i++) 1612 pMod->aSegments[i].MapAddress = 0; 1613 1543 1614 return 0; 1544 1545 1615 } 1546 1616 … … 1549 1619 static int kldrModMachOAllocTLS(PKLDRMOD pMod) 1550 1620 { 1551 PKLDRMODMACHO 1621 PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData; 1552 1622 1553 1623 /* … … 1556 1626 if (!pModMachO->pvMapping) 1557 1627 return KLDR_ERR_NOT_MAPPED; 1558 1559 1628 return 0; 1560 1629 } … … 1579 1648 1580 1649 /* the file provider does it all */ 1581 return kLdrRdrRefresh(pMod->pRdr, (void *)pModMachO->pvMapping, pMod->cSegments, pMod->aSegments);1650 return kLdrRdrRefresh(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments); 1582 1651 } 1583 1652 … … 1598 1667 * Before doing anything we'll have to make all pages writable. 1599 1668 */ 1600 rc = kLdrRdrProtect(pMod->pRdr, (void *)pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */); 1601 if (rc) 1602 return rc; 1603 1604 #if 0 1605 /* 1606 * Apply base relocations. 1607 */ 1608 rc = kldrModMachODoFixups(pModMachO, (void *)pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping, 1609 pModMachO->Hdrs.OptionalHeader.ImageBase); 1610 1611 /* 1612 * Resolve imports. 1613 */ 1614 if (!rc) 1615 rc = kldrModMachODoImports(pModMachO, (void *)pModMachO->pvMapping, pfnGetImport, pvUser); 1616 #endif 1669 if (pModMachO->fMapUsingLoadCommandSections) 1670 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */ 1671 else 1672 { 1673 rc = kLdrRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */); 1674 if (rc) 1675 return rc; 1676 } 1677 1678 /* 1679 * Resolve imports and apply base relocations. 1680 */ 1681 rc = kldrModMachORelocateBits(pMod, pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping, pModMachO->LinkAddress, 1682 pfnGetImport, pvUser); 1617 1683 1618 1684 /* 1619 1685 * Restore protection. 1620 1686 */ 1621 rc2 = kLdrRdrProtect(pMod->pRdr, (void *)pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */); 1687 if (pModMachO->fMapUsingLoadCommandSections) 1688 rc2 = KLDR_ERR_TODO; /* deal with this if it ever occurs. */ 1689 else 1690 rc2 = kLdrRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */); 1622 1691 if (!rc && rc2) 1623 1692 rc = rc2; … … 1673 1742 1674 1743 /* Get the symbol name and try resolve it. */ 1675 if ((uint32_t)paSyms[iSym].n_un.n_strx >= pModMachO->c bStrings)1744 if ((uint32_t)paSyms[iSym].n_un.n_strx >= pModMachO->cchStrings) 1676 1745 return KLDR_ERR_MACHO_BAD_SYMBOL; 1677 1746 pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx]; … … 1721 1790 1722 1791 /* Get the symbol name and try resolve it. */ 1723 if (paSyms[iSym].n_un.n_strx >= pModMachO->c bStrings)1792 if (paSyms[iSym].n_un.n_strx >= pModMachO->cchStrings) 1724 1793 return KLDR_ERR_MACHO_BAD_SYMBOL; 1725 1794 pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx]; … … 1860 1929 /* sanity */ 1861 1930 if ( !pModMachO->offSymbols 1862 || (pModMachO->c bStrings && !pModMachO->offStrings))1931 || (pModMachO->cchStrings && !pModMachO->offStrings)) 1863 1932 return KLDR_ERR_MACHO_BAD_OBJECT_FILE; 1864 1933 … … 1875 1944 if (pvSyms) 1876 1945 { 1877 if (pModMachO->c bStrings)1878 pvStrings = kldrHlpAlloc(pModMachO->c bStrings);1946 if (pModMachO->cchStrings) 1947 pvStrings = kldrHlpAlloc(pModMachO->cchStrings); 1879 1948 else 1880 1949 pvStrings = kldrHlpAllocZ(4); … … 1883 1952 /* read */ 1884 1953 rc = kLdrRdrRead(pModMachO->pMod->pRdr, pvSyms, cbSyms, pModMachO->offSymbols); 1885 if (!rc && pModMachO->c bStrings)1886 rc = kLdrRdrRead(pModMachO->pMod->pRdr, pvStrings, pModMachO->c bStrings, pModMachO->offStrings);1954 if (!rc && pModMachO->cchStrings) 1955 rc = kLdrRdrRead(pModMachO->pMod->pRdr, pvStrings, pModMachO->cchStrings, pModMachO->offStrings); 1887 1956 if (!rc) 1888 1957 { … … 2027 2096 * If not iterate the load commands and execute the segment / section loads. 2028 2097 */ 2029 if (!pModMachO->fMapUsingLoadCommandSections) 2098 if (pModMachO->fMapUsingLoadCommandSections) 2099 return KLDR_ERR_TODO; /* deal with this if it ever occurs. */ 2100 else 2030 2101 { 2031 2102 for (i = 0; i < pMod->cSegments; i++) … … 2044 2115 return rc; 2045 2116 } 2046 }2047 else2048 {2049 /** @todo implement this */2050 return KLDR_ERR_TODO;2051 2117 } 2052 2118 -
trunk/kLdr/kLdrModMachO.h
r2961 r2962 709 709 #define MACHO_N_EXT UINT8_C(0x01) /**< External symbol (when set) (N_EXT). */ 710 710 #define MACHO_N_TYPE UINT8_C(0x0e) /**< Symbol type (N_TYPE without the 8th bit). */ 711 #define MACHO_N_PEXT UINT8_C(0x10) /**< Private extern symbol (when set). Mach-O specific.*/711 #define MACHO_N_PEXT UINT8_C(0x10) /**< Private extern symbol (when set). (M) */ 712 712 #define MACHO_N_STAB UINT8_C(0xe0) /**< Debug symbol mask (N_STAB). */ 713 713 … … 715 715 #define MACHO_N_UNDF UINT8_C(0x00) /**< MACHO_N_TYPE: Undefined symbol (N_UNDF). n_sect = NO_SECT. */ 716 716 #define MACHO_N_ABS UINT8_C(0x02) /**< MACHO_N_TYPE: Absolute symbol (N_UNDF). n_sect = NO_SECT. */ 717 #define MACHO_N_INDR UINT8_C(0x0a) /**< MACHO_N_TYPE: Indirect symbol, n_value is the index of the symbol. Mach-O specific.*/718 #define MACHO_N_PBUD UINT8_C(0x0c) /**< MACHO_N_TYPE: Prebound undefined symbo (defined in a dylib). Mach-O specific.*/719 #define MACHO_N_SECT UINT8_C(0x0e) /**< MACHO_N_TYPE: Defined in the section given by n_sects. Mach-O specific.*/717 #define MACHO_N_INDR UINT8_C(0x0a) /**< MACHO_N_TYPE: Indirect symbol, n_value is the index of the symbol. (M) */ 718 #define MACHO_N_PBUD UINT8_C(0x0c) /**< MACHO_N_TYPE: Prebound undefined symbo (defined in a dylib). (M) */ 719 #define MACHO_N_SECT UINT8_C(0x0e) /**< MACHO_N_TYPE: Defined in the section given by n_sects. (M) */ 720 720 721 721 /* Debug symbols. */
Note:
See TracChangeset
for help on using the changeset viewer.