Changeset 2856 for trunk/kLdr/kLdrModPE.c
- Timestamp:
- Nov 4, 2006, 11:19:33 PM (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModPE.c
r2855 r2856 33 33 #include "kLdrInternal.h" 34 34 #include "kLdrModPE.h" 35 35 36 36 37 /******************************************************************************* … … 73 74 /** Pointer to the RDR mapping of the raw file bits. NULL if not mapped. */ 74 75 const void *pvBits; 75 /** Whether we've mapped the image or not. */76 uint32_t fMapped : 1;76 /** Pointer to the user mapping. */ 77 const void *pvMapping; 77 78 /** Reserved flags. */ 78 uint32_t f3 1Reserved;79 uint32_t f32Reserved; 79 80 /** The number of imported modules. 80 81 * If ~(uint32_t)0 this hasn't been determined yet. */ … … 100 101 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind); 101 102 static int32_t kldrModPENumberOfImports(PKLDRMOD pMod, const void *pvBits); 103 static int kldrModPEUnprotect(PKLDRMODPE pModPE, const void *pvMapping); 104 static int kldrModPEProtect(PKLDRMODPE pModPE, const void *pvMapping); 105 static int kldrModPEDoFixups(PKLDRMODPE pModPE, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress); 106 static int kldrModPEDoImports(PKLDRMODPE pModPE, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 107 static int kldrModPEDoCallDLL(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle); 108 static int kldrModPEDoCallTLS(PKLDRMODPE pModPE, unsigned uOp, uintptr_t uHandle); 109 static int kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 110 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 102 111 103 112 … … 221 230 pModPE->pMod = pMod; 222 231 pModPE->pvBits = NULL; 223 pModPE->fMapped = 0; 224 pModPE->f31Reserved = 0; 232 pModPE->f32Reserved = 0; 225 233 pModPE->cImportModules = ~(uint32_t)0; 226 234 pModPE->offHdrs = offNewHdr >= 0 ? offNewHdr : 0; … … 473 481 474 482 /** 483 * Performs the mapping of the image. 484 * 485 * This can be used to do the internal mapping as well as the 486 * user requested mapping. fForReal indicates which is desired. 487 * 488 * @returns 0 on success, non-zero OS or kLdr status code on failure. 489 * @param pModPE The interpreter module instance 490 * @param fForReal If set, do the user mapping. if clear, do the internal mapping. 491 */ 492 static int kldrModPEDoMap(PKLDRMODPE pModPE, unsigned fForReal) 493 { 494 return -1; 495 } 496 497 498 /** 499 * Unmaps a image mapping. 500 * 501 * This can be used to do the internal mapping as well as the 502 * user requested mapping. fForReal indicates which is desired. 503 * 504 * @returns 0 on success, non-zero OS or kLdr status code on failure. 505 * @param pModPE The interpreter module instance 506 * @param fForReal If set, unmap the user mapping. if clear, unmap the internal mapping. 507 */ 508 static int kldrModPEDoUnmap(PKLDRMODPE pModPE, unsigned fForReal) 509 { 510 return -1; 511 } 512 513 514 /** 475 515 * Gets usable bits and the right base address. 476 516 * … … 505 545 if (!*ppvBits) 506 546 { 507 if (pModPE-> fMapped)508 *ppvBits = (void *)(uintptr_t)pModPE->pMod->aSegments[0].MapAddress;547 if (pModPE->pvMapping) 548 *ppvBits = pModPE->pvMapping; 509 549 else if (pModPE->pvBits) 510 550 *ppvBits = pModPE->pvBits; … … 888 928 /* 889 929 * We'll have to walk the import descriptors to figure out their number. 890 * First, make sure we've got mapped bits and resolve any base address aliases.930 * First, make sure we've got mapped bits. 891 931 */ 892 932 if (kldrModPEBitsAndBaseAddress(pModPE, &pvBits, NULL)) … … 931 971 int rc; 932 972 973 /* 974 * Resolve base address alias if any. 975 */ 933 976 rc = kldrModPEBitsAndBaseAddress(pModPE, NULL, &BaseAddress); 934 977 if (rc) 935 978 return rc; 936 979 980 /* 981 * Convert the address from the header. 982 */ 937 983 *pMainEPAddress = pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint 938 984 ? BaseAddress + pModPE->Hdrs.OptionalHeader.AddressOfEntryPoint … … 943 989 944 990 /** @copydoc kLdrModEnumDbgInfo */ 945 int (* pfnEnumDbgInfo)(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser); 991 static int kldrModPEEnumDbgInfo(PKLDRMOD pMod, const void *pvBits, PFNKLDRENUMDBG pfnCallback, void *pvUser) 992 { 993 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 994 const IMAGE_DEBUG_DIRECTORY *pDbgDir; 995 uint32_t iDbgInfo; 996 uint32_t cb; 997 int rc; 998 999 /* 1000 * Check that there is a debug directory first. 1001 */ 1002 cb = pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; 1003 if ( cb < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */ 1004 || !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) 1005 return 0; 1006 1007 /* 1008 * Make sure we've got mapped bits. 1009 */ 1010 rc = kldrModPEBitsAndBaseAddress(pModPE, &pvBits, NULL); 1011 if (rc) 1012 return rc; 1013 1014 /* 1015 * Enumerate the debug directory. 1016 */ 1017 pDbgDir = KLDRMODPE_RVA2TYPE(pvBits, 1018 pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress, 1019 const IMAGE_DEBUG_DIRECTORY *); 1020 for (iDbgInfo = 0;; iDbgInfo++, pDbgDir++, cb -= sizeof(IMAGE_DEBUG_DIRECTORY)) 1021 { 1022 KLDRDBGINFOTYPE enmDbgInfoType; 1023 1024 /* convert the type. */ 1025 switch (pDbgDir->Type) 1026 { 1027 case IMAGE_DEBUG_TYPE_UNKNOWN: 1028 case IMAGE_DEBUG_TYPE_FPO: 1029 case IMAGE_DEBUG_TYPE_COFF: //stabs dialect?? 1030 case IMAGE_DEBUG_TYPE_MISC: 1031 case IMAGE_DEBUG_TYPE_EXCEPTION: 1032 case IMAGE_DEBUG_TYPE_FIXUP: 1033 case IMAGE_DEBUG_TYPE_BORLAND: 1034 default: 1035 enmDbgInfoType = KLDRDBGINFOTYPE_UNKNOWN; 1036 break; 1037 case IMAGE_DEBUG_TYPE_CODEVIEW: 1038 enmDbgInfoType = KLDRDBGINFOTYPE_CODEVIEW; 1039 break; 1040 } 1041 1042 rc = pfnCallback(pMod, iDbgInfo, 1043 enmDbgInfoType, pDbgDir->MajorVersion, pDbgDir->MinorVersion, 1044 pDbgDir->PointerToRawData ? pDbgDir->PointerToRawData : -1, 1045 pDbgDir->AddressOfRawData ? pDbgDir->AddressOfRawData : NIL_KLDRADDR, 1046 pDbgDir->SizeOfData, 1047 NULL, 1048 pvUser); 1049 if (rc) 1050 break; 1051 1052 /* next */ 1053 if (cb <= sizeof(IMAGE_DEBUG_DIRECTORY)) 1054 break; 1055 } 1056 1057 return rc; 1058 } 1059 946 1060 947 1061 /** @copydoc kLdrModHasDbgInfo */ 948 int (* pfnHasDbgInfo)(PKLDRMOD pMod, const void *pvBits); 1062 static int kldrModPEHasDbgInfo(PKLDRMOD pMod, const void *pvBits) 1063 { 1064 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1065 1066 /* 1067 * Base this entirely on the presence of a debug directory. 1068 */ 1069 if ( pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size 1070 < sizeof(IMAGE_DEBUG_DIRECTORY) /* screw borland linkers */ 1071 || !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) 1072 return KLDR_ERR_NO_DEBUG_INFO; 1073 return 0; 1074 } 1075 1076 949 1077 /** @copydoc kLdrModMap */ 950 int (* pfnMap)(PKLDRMOD pMod); 1078 static int kldrModPEMap(PKLDRMOD pMod) 1079 { 1080 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1081 int rc; 1082 1083 /* 1084 * Already mapped? 1085 */ 1086 if (pModPE->pvMapping) 1087 return KLDR_ERR_ALREADY_MAPPED; 1088 1089 /* 1090 * We've got a common worker which does this. 1091 */ 1092 rc = kldrModPEDoMap(pModPE, 1 /* the real thing */); 1093 if (rc) 1094 return rc; 1095 KLDRMODPE_ASSERT(pModPE->pvMapping); 1096 return 0; 1097 } 1098 1099 951 1100 /** @copydoc kLdrModUnmap */ 952 int (* pfnUnmap)(PKLDRMOD pMod); 1101 static int kldrModPEUnmap(PKLDRMOD pMod) 1102 { 1103 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1104 int rc; 1105 1106 /* 1107 * Mapped? 1108 */ 1109 if (!pModPE->pvMapping) 1110 return KLDR_ERR_NOT_MAPPED; 1111 1112 /* 1113 * We've got a common worker which does this. 1114 */ 1115 rc = kldrModPEDoMap(pModPE, 1 /* the real thing */); 1116 if (rc) 1117 return rc; 1118 KLDRMODPE_ASSERT(pModPE->pvMapping); 1119 return 0; 1120 1121 } 1122 1123 953 1124 /** @copydoc kLdrModAllocTLS */ 954 int (* pfnAllocTLS)(PKLDRMOD pMod); 1125 static int kldrModPEAllocTLS(PKLDRMOD pMod) 1126 { 1127 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1128 1129 /* 1130 * Mapped? 1131 */ 1132 if (!pModPE->pvMapping) 1133 return KLDR_ERR_NOT_MAPPED; 1134 1135 /* 1136 * If no TLS directory then there is nothing to do. 1137 */ 1138 if ( !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size 1139 || !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress) 1140 return 0; 1141 /** @todo implement TLS. */ 1142 return -1; 1143 } 1144 1145 955 1146 /** @copydoc kLdrModFreeTLS */ 956 void (* pfnFreeTLS)(PKLDRMOD pMod); 1147 static void kldrModPEFreeTLS(PKLDRMOD pMod) 1148 { 1149 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1150 1151 /* 1152 * Mapped? 1153 */ 1154 if (!pModPE->pvMapping) 1155 return; 1156 1157 /* 1158 * If no TLS directory then there is nothing to do. 1159 */ 1160 if ( !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size 1161 || !pModPE->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress) 1162 return; 1163 /** @todo implement TLS. */ 1164 return; 1165 } 1166 1167 957 1168 /** @copydoc kLdrModReload */ 958 int (* pfnReload)(PKLDRMOD pMod); 1169 static int kldrModPEReload(PKLDRMOD pMod) 1170 { 1171 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1172 uint32_t i; 1173 int rc; 1174 const size_t cbPage = kLdrRdrPageSize(pMod->pRdr); 1175 1176 /* 1177 * Mapped? 1178 */ 1179 if (!pModPE->pvMapping) 1180 return KLDR_ERR_NOT_MAPPED; 1181 1182 /* 1183 * Iterate the objects and ask the file provider to undo all the changes. 1184 */ 1185 for (i = rc = 0; !rc && i < pMod->cSegments; i++) 1186 rc = kLdrRdrRefreshMap(pMod->pRdr, 1187 (void *)pMod->aSegments[i].MapAddress, 1188 (size_t)pMod->aSegments[i].cb, 1189 pMod->aSegments[i].enmProt, 1190 pMod->aSegments[i].offFile, 1191 pMod->aSegments[i].cbFile); 1192 1193 return rc; 1194 } 1195 1196 959 1197 /** @copydoc kLdrModFixupMapping */ 960 int (* pfnFixupMapping)(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 1198 static int kldrModPEFixupMapping(PKLDRMOD pMod, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 1199 { 1200 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1201 int rc, rc2; 1202 1203 /* 1204 * Mapped? 1205 */ 1206 if (!pModPE->pvMapping) 1207 return KLDR_ERR_NOT_MAPPED; 1208 1209 /* 1210 * Before doing anything we'll have to make all pages writable. 1211 */ 1212 rc = kldrModPEUnprotect(pModPE, pModPE->pvMapping); 1213 if (rc) 1214 return rc; 1215 1216 /* 1217 * Do we need to apply base relocations? 1218 */ 1219 if (pModPE->Hdrs.OptionalHeader.ImageBase != (uintptr_t)pModPE->pvMapping) 1220 rc = kldrModPEDoFixups(pModPE, (void *)pModPE->pvMapping, (uintptr_t)pModPE->pvMapping, 1221 pModPE->Hdrs.OptionalHeader.ImageBase); 1222 1223 /* 1224 * Resolve imports. 1225 */ 1226 if (!rc) 1227 rc = kldrModPEDoImports(pModPE, (void *)pModPE->pvMapping, pfnGetImport, pvUser); 1228 1229 /* 1230 * Restore protection. 1231 */ 1232 rc2 = kldrModPEProtect(pModPE, pModPE->pvMapping); 1233 if (!rc && rc2) 1234 rc = rc2; 1235 return rc; 1236 } 1237 1238 961 1239 /** @copydoc kLdrModCallInit */ 962 int (* pfnCallInit)(PKLDRMOD pMod); 1240 static int kldrModPECallInit(PKLDRMOD pMod, uintptr_t uHandle) 1241 { 1242 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1243 int rc; 1244 1245 /* 1246 * Mapped? 1247 */ 1248 if (!pModPE->pvMapping) 1249 return KLDR_ERR_NOT_MAPPED; 1250 1251 /* 1252 * Do TLS callbacks first and then call the init/term function if it's a DLL. 1253 */ 1254 rc = kldrModPEDoCallTLS(pModPE, DLL_PROCESS_ATTACH, uHandle); 1255 if ( !rc 1256 && (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL)) 1257 { 1258 rc = kldrModPEDoCallDLL(pModPE, DLL_PROCESS_ATTACH, uHandle); 1259 if (rc) 1260 kldrModPEDoCallTLS(pModPE, DLL_PROCESS_DETACH, uHandle); 1261 } 1262 1263 return rc; 1264 } 1265 1266 963 1267 /** @copydoc kLdrModCallTerm */ 964 int (* pfnCallTerm)(PKLDRMOD pMod); 1268 static int kldrModPECallTerm(PKLDRMOD pMod, uintptr_t uHandle) 1269 { 1270 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1271 1272 /* 1273 * Mapped? 1274 */ 1275 if (!pModPE->pvMapping) 1276 return KLDR_ERR_NOT_MAPPED; 1277 1278 /* 1279 * Do TLS callbacks first. 1280 */ 1281 kldrModPEDoCallTLS(pModPE, DLL_PROCESS_DETACH, uHandle); 1282 if (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL) 1283 kldrModPEDoCallDLL(pModPE, DLL_PROCESS_DETACH, uHandle); 1284 1285 return 0; 1286 } 1287 1288 965 1289 /** @copydoc kLdrModCallThread */ 966 int (* pfnCallThread)(PKLDRMOD pMod, unsigned fAttachingOrDetaching); 1290 static int kldrModPECallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching) 1291 { 1292 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1293 unsigned uOp = fAttachingOrDetaching ? DLL_THREAD_ATTACH : DLL_THREAD_DETACH; 1294 int rc; 1295 1296 /* 1297 * Do TLS callbacks first and then call the init/term function if it's a DLL. 1298 */ 1299 rc = kldrModPEDoCallTLS(pModPE, uOp, uHandle); 1300 if (!fAttachingOrDetaching) 1301 rc = 0; 1302 if ( !rc 1303 && (pModPE->Hdrs.FileHeader.Characteristics & IMAGE_FILE_DLL)) 1304 { 1305 rc = kldrModPEDoCallDLL(pModPE, uOp, uHandle); 1306 if (!fAttachingOrDetaching) 1307 rc = 0; 1308 if (rc) 1309 kldrModPEDoCallTLS(pModPE, uOp, uHandle); 1310 } 1311 1312 return rc; 1313 } 1314 1315 967 1316 /** @copydoc kLdrModSize */ 968 size_t (* pfnSize)(PKLDRMOD pMod); 1317 static KLDRADDR kldrModPESize(PKLDRMOD pMod) 1318 { 1319 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1320 return pModPE->Hdrs.OptionalHeader.SizeOfImage; 1321 } 1322 1323 969 1324 /** @copydoc kLdrModGetBits */ 970 int (* pfnGetBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 1325 static int kldrModPEGetBits(PKLDRMOD pMod, void *pvBits, KLDRADDR BaseAddress, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 1326 { 1327 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1328 uint32_t i; 1329 int rc; 1330 1331 /* 1332 * Iterate the segments and read the data within them. 1333 */ 1334 for (i = 0; i < pMod->cSegments; i++) 1335 { 1336 /// @todo 1337 rc = 0; 1338 } 1339 1340 /* 1341 * Perform relocations. 1342 */ 1343 return kldrModPERelocateBits(pMod, pvBits, BaseAddress, pModPE->Hdrs.OptionalHeader.ImageBase, pfnGetImport, pvUser); 1344 1345 } 1346 1347 971 1348 /** @copydoc kLdrModRelocateBits */ 972 int (* pfnRelocateBits)(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 973 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 974 1349 static int kldrModPERelocateBits(PKLDRMOD pMod, void *pvBits, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress, 1350 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser) 1351 { 1352 PKLDRMODPE pModPE = (PKLDRMODPE)pMod->pvData; 1353 int rc; 1354 1355 /* 1356 * Call workers to do the jobs. 1357 */ 1358 rc = kldrModPEDoFixups(pModPE, pvBits, NewBaseAddress, OldBaseAddress); 1359 if (!rc) 1360 rc = kldrModPEDoImports(pModPE, pvBits, pfnGetImport, pvUser); 1361 1362 return rc; 1363 } 1364
Note:
See TracChangeset
for help on using the changeset viewer.