Changeset 2538 for trunk/src/win32k/pe2lx/pe2lx.cpp
- Timestamp:
- Jan 28, 2000, 12:45:59 AM (26 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/win32k/pe2lx/pe2lx.cpp
r2501 r2538 1 /* $Id: pe2lx.cpp,v 1.1 5 2000-01-22 18:21:03bird Exp $1 /* $Id: pe2lx.cpp,v 1.16 2000-01-27 23:45:59 bird Exp $ 2 2 * 3 3 * Pe2Lx class implementation. Ring 0 and Ring 3 4 4 * 5 * Copyright (c) 1998- 1999knut st. osmundsen (knut.stange.osmundsen@pmsc.no)5 * Copyright (c) 1998-2000 knut st. osmundsen (knut.stange.osmundsen@pmsc.no) 6 6 * Copyright (c) 1998 Sander van Leeuwen (sandervl@xs4all.nl) 7 7 * Copyright (c) 1998 Peter Fitzsimmons … … 104 104 #include <exe386.h> /* OS/2 LX structs and definitions. */ 105 105 106 #include "malloc.h" /* win32k malloc. Not C library! */ 106 #include "malloc.h" /* win32k malloc (resident). Not C library! */ 107 #include "smalloc.h" /* win32k swappable heap. */ 108 #include "rmalloc.h" /* win32k resident heap. */ 107 109 108 110 #include <string.h> /* C library string.h. */ … … 249 251 pachImpModuleNames(NULL), offCurImpModuleName(0), cchIMNAllocated(0), 250 252 pachImpFunctionNames(NULL), offCurImpFunctionName(0), cchIFNAllocated(0), 251 offNtHeaders(0), pNtHdrs(NULL), ulImageBase(0UL) 253 offNtHeaders(0), pNtHdrs(NULL), ulImageBase(0UL), pBaseRelocs(0), 254 fApplyFixups(~0UL), fDeltaOnly(0) 252 255 { 253 256 memset(&LXHdr, 0, sizeof(LXHdr)); … … 326 329 pNtHdrs = NULL; 327 330 } 331 if (pBaseRelocs != NULL) 332 { 333 sfree(pBaseRelocs); 334 pBaseRelocs = NULL; 335 } 336 _res_heapmin(); 337 _swp_heapmin(); 328 338 } 329 339 … … 705 715 706 716 Yield(); 717 _res_heapmin(); 718 #if 0 /* testing */ 719 testApplyFixups(); 720 #endif 707 721 708 722 return NO_ERROR; … … 1022 1036 * 1023 1037 * @sketch Find RVA. 1038 * @remarks Some more information on relocations: 1039 * From Web: 1040 * IMAGE_REL_I386_ABSOLUTE Reference is absolute, no relocation is necessary 1041 * IMAGE_REL_I386_DIR16 Direct 16-bit reference to the symbols virtual address 1042 * IMAGE_REL_I386_REL16 PC-relative 16-bit reference to the symbols virtual address 1043 * IMAGE_REL_I386_DIR32 Direct 32-bit reference to the symbols virtual address 1044 * IMAGE_REL_I386_DIR32NB Direct 32-bit reference to the symbols virtual address, base not included 1045 * IMAGE_REL_I386_SEG12 Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address 1046 * IMAGE_REL_I386_SECTION ? 1047 * IMAGE_REL_I386_SECREL ? 1048 * IMAGE_REL_I386_REL32 PC-relative 32-bit reference to the symbols virtual address 1049 * 1050 * From TIS: 1051 * Type = 4bit fixup type. This value has the following definitions: 1052 * 0h Absolute. This is a NOP. The fixup is skipped. 1053 * 1h High. Add the high 16 bits of the delta to the 16 bit field at Offset. 1054 * The 16bit field represents the high value of a 32 bit word. 1055 * 2h Low. Add the low 16 bits of the delta to the 16 bit field at Offset. 1056 * The 16 bit field represents the low half value of a 32 bit word. This 1057 * fixup will only be emitted for a RISC machine when the image Object 1058 * Align isn't the default of 64K. 1059 * 3h Highlow. Apply the 32 bit delta to the 32 bit field at Offset. 1060 * 4h Highadjust. This fixup requires a full 32 bit value. The high 16 bits 1061 * is located at Offset, and the low 16 bits is located in the next Offset 1062 * array element (this array element is included in the Size field). The 1063 * two need to be combined into a signed variable. Add the 32 bit delta. 1064 * Then add 0x8000 and store the high 16 bits of the signed variable to 1065 * the 16 bit field at Offset. 1066 * 5h Mipsjmpaddr. 1067 * 1068 * TODO: implement the above mentioned fixups. 1024 1069 */ 1025 1070 ULONG Pe2Lx::applyFixups(PMTE pMTE, ULONG iObject, ULONG iPageTable, PVOID pvPage, 1026 1071 ULONG ulPageAddress, PVOID pvPTDA) 1027 1072 { 1028 ULONG ulRVA; 1029 1030 NOREF(ulRVA); 1031 1032 NOREF(pMTE); 1033 NOREF(iObject); 1073 APIRET rc; 1074 1075 if (fApplyFixups != FALSE && pBaseRelocs != NULL) 1076 { 1077 ULONG ulRVAPage; 1078 ULONG ulDelta; 1079 PSMTE pSMTE = pMTE->mte_swapmte; 1080 1081 /* validate input */ 1082 if (pSMTE < (PSMTE)0x10000) 1083 { 1084 printErr(("Invalid pSMTE(0x%08x)\n", pSMTE)); 1085 return ERROR_INVALID_PARAMETER; 1086 } 1087 #ifdef DEBUG 1088 if (pSMTE->smte_objcnt <= iObject) 1089 { 1090 printErr(("Invalid iObject(%d), smte_objcnt=%d\n", iObject, pSMTE->smte_objcnt)); 1091 return ERROR_INVALID_PARAMETER; 1092 } 1093 if (cObjects <= iObject) 1094 { 1095 printErr(("Invalid iObject(%d), cObjects=%d\n", iObject, cObjects)); 1096 return ERROR_INVALID_PARAMETER; 1097 } 1098 #endif 1099 1100 /* some calculations */ 1101 ulDelta = pSMTE->smte_objtab[iObject].ote_base - paObjects[iObject].ulRVA - ulImageBase; 1102 ulRVAPage = paObjects[iObject].ulRVA + ulPageAddress - pSMTE->smte_objtab[iObject].ote_base; 1103 1104 /* check if the fixup needs to be applied? */ 1105 if (fApplyFixups == ~0UL) 1106 { 1107 fDeltaOnly = TRUE; /* IMPORTANT: Later code assumes that this is true when fAllInOneObject is true. */ 1108 if (fAllInOneObject) 1109 fApplyFixups = ulImageBase == pSMTE->smte_objtab[0].ote_base; 1110 else 1111 { 1112 int i = 0; 1113 #ifdef DEBUG 1114 if (cObjects != pSMTE->smte_objcnt) 1115 printErr(("cObject(%d) != smte_objcnt(%d)\n", cObjects, pSMTE->smte_objcnt)); 1116 #endif 1117 fApplyFixups = FALSE; 1118 while (i < cObjects && (!fApplyFixups || fDeltaOnly)) 1119 { 1120 register ULONG ulTmp = pSMTE->smte_objtab[i].ote_base - ulImageBase - paObjects[i].ulRVA; 1121 if (ulTmp != 0) 1122 fApplyFixups = TRUE; 1123 if (ulTmp != ulDelta) 1124 fDeltaOnly = FALSE; 1125 i++; 1126 } 1127 } 1128 if (!fApplyFixups) 1129 return NO_ERROR; 1130 } 1131 1132 PIMAGE_BASE_RELOCATION pbr = pBaseRelocs; 1133 ULONG ulBefore; 1134 ULONG ulAfter; 1135 ULONG flRead = 0; /* bitmask: 0 = no read, 1 = ulBefore is read, 2 = ulAfter is read */ 1136 1137 while ((unsigned)pbr - (unsigned)pBaseRelocs + 8 < cbBaseRelocs /* 8= VirtualAddress and SizeOfBlock members */ 1138 && pbr->VirtualAddress < ulRVAPage + PAGESIZE) 1139 { 1140 if (pbr->VirtualAddress + PAGESIZE >= ulRVAPage) 1141 { 1142 PWORD pwoffFixup = &pbr->TypeOffset[0]; 1143 ULONG cRelocations = (pbr->SizeOfBlock - offsetof(IMAGE_BASE_RELOCATION, TypeOffset)) / sizeof(WORD); /* note that sizeof(BaseReloc) is 12 bytes! */ 1144 1145 /* Some bound checking just to be sure it works... */ 1146 if ((unsigned)pbr - (unsigned)pBaseRelocs + pbr->SizeOfBlock > cbBaseRelocs) 1147 { 1148 printWar(("Block ends after BaseRelocation datadirectory.\n")); 1149 cRelocations = (((unsigned)pBaseRelocs + cbBaseRelocs) - (unsigned)pbr - offsetof(IMAGE_BASE_RELOCATION, TypeOffset)) / sizeof(WORD); 1150 } 1151 1152 while (cRelocations != 0) 1153 { 1154 static char acbFixupTypes[16] = {0x00, 0x02, 0x02, 0x04, 1155 0xFF, 0xFF, 0xFF, 0xFF, 1156 0xFF, 0xFF, 0xFF, 0xFF, 1157 0xFF, 0xFF, 0xFF, 0xFF}; 1158 int offFixup = *pwoffFixup & (PAGESIZE-1); 1159 int fType = *pwoffFixup >> 12; 1160 int cbFixup = acbFixupTypes[fType]; 1161 1162 if (cbFixup != 0 && cbFixup <= 4 1163 && offFixup + pbr->VirtualAddress + (cbFixup-1) >= ulRVAPage 1164 && offFixup + pbr->VirtualAddress < ulRVAPage + PAGESIZE 1165 ) 1166 { 1167 ULONG iObj; 1168 ULONG ulTarget; 1169 PULONG pul; /* Pointer to fixup target */ 1170 ULONG ul; /* Crosspage fixups: Conent of fixup target */ 1171 unsigned uShift1; /* Crosspage fixups: Shift */ 1172 unsigned uShift2; /* Crosspage fixups: Inverse of Shift1 */ 1173 1174 if (offFixup + pbr->VirtualAddress < ulRVAPage) 1175 { /* 1176 * Crosspagefixup - from the page before 1177 */ 1178 uShift1 = (unsigned)((offFixup + pbr->VirtualAddress) % cbFixup) * 8; 1179 uShift2 = cbFixup * 8 - uShift1; 1180 pul = (PULONG)pvPage; 1181 ul = *pul; 1182 if (!fDeltaOnly && fType == IMAGE_REL_BASED_HIGHLOW) 1183 { 1184 /* Read? */ 1185 if ((flRead & 1) == 0) 1186 { 1187 rc = readAtRVA(ulRVAPage - 4, SSToDS(&ulBefore), sizeof(ulBefore)); 1188 if (rc != NO_ERROR) 1189 { 1190 printErr(("readAtRVA(0x%08x, ulBefore..) failed with rc=%d\n", ulRVAPage-4, rc)); 1191 return rc; 1192 } 1193 flRead |= 1; 1194 } 1195 /* Get target pointer, find it's object and apply the fixup */ 1196 ulTarget = (ulBefore >> uShift1) | (ul << uShift2); 1197 ulTarget -= ulImageBase; /* ulTarget is now an RVA */ 1198 iObj = 0UL; 1199 while (iObj < cObjects 1200 && ulTarget >= (iObj + 1 < cObjects ? paObjects[iObj+1].ulRVA 1201 : ALIGN(paObjects[iObj].cbVirtual, PAGESIZE) + paObjects[iObj].ulRVA) 1202 ) 1203 iObj++; 1204 if (iObj < cObjects) 1205 *pul = ((pSMTE->smte_objtab[iObj].ote_base + ulTarget - paObjects[iObj].ulRVA) >> uShift2) 1206 | (ul & ((~0UL) << uShift1)); 1207 else 1208 *pul = (((ulDelta >> uShift2) + ul) & ((~0UL) >> uShift2)) | (ul & ((~0UL) << uShift1)); 1209 } 1210 else 1211 { /* apply delta fixup */ 1212 switch (fType) 1213 { 1214 case IMAGE_REL_BASED_HIGHLOW: 1215 *pul = (((ulDelta >> uShift2) + ul) & ((~0UL) >> uShift2)) | (ul & ((~0UL) << uShift1)); 1216 break; 1217 case IMAGE_REL_BASED_HIGH: 1218 case IMAGE_REL_BASED_HIGHADJ: /* According to M$ docs these seems to be the same fixups. */ 1219 case IMAGE_REL_BASED_HIGH3ADJ: 1220 *pul = (((ulDelta >> 24) + ul) & 0xFF) | (ul & 0xFFFFFF00UL); 1221 break; 1222 case IMAGE_REL_BASED_LOW: 1223 *pul = (((ulDelta >> 8) + ul) & 0xFF) | (ul & 0xFFFFFF00UL); 1224 break; 1225 } 1226 } 1227 } 1228 else if (offFixup + pbr->VirtualAddress + cbFixup > ulRVAPage + PAGESIZE) 1229 { /* 1230 * Crosspagefixup - into the page afterwards 1231 */ 1232 uShift1 = (unsigned)((offFixup + pbr->VirtualAddress) % cbFixup) * 8; 1233 uShift2 = cbFixup * 8 - uShift1; 1234 pul = (PULONG)((unsigned)pvPage + PAGESIZE - sizeof(ULONG)); 1235 ul = *pul; 1236 if (!fDeltaOnly && fType == IMAGE_REL_BASED_HIGHLOW) 1237 { 1238 /* Read? */ 1239 if ((flRead & 2) == 0) 1240 { 1241 rc = readAtRVA(ulRVAPage+PAGESIZE, SSToDS(&ulAfter), sizeof(ulAfter)); 1242 if (rc != NO_ERROR) 1243 { 1244 printErr(("readAtRVA(0x%08x, ulAfter..) failed with rc=%d\n", ulRVAPage+PAGESIZE, rc)); 1245 return rc; 1246 } 1247 flRead |= 2; 1248 } 1249 /* Get target pointer, find it's object and apply the fixup */ 1250 ulTarget = (ulAfter << uShift2) | (ul >> uShift1); 1251 ulTarget -= ulImageBase; /* ulTarget is now an RVA */ 1252 iObj = 0UL; 1253 while (iObj < cObjects 1254 && ulTarget >= (iObj + 1 < cObjects ? paObjects[iObj+1].ulRVA 1255 : ALIGN(paObjects[iObj].cbVirtual, PAGESIZE) + paObjects[iObj].ulRVA) 1256 ) 1257 iObj++; 1258 if (iObj < cObjects) 1259 *pul = ((pSMTE->smte_objtab[iObj].ote_base + ulTarget - paObjects[iObj].ulRVA) << uShift1) 1260 | (ul & ((~0UL) >> uShift2)); 1261 else 1262 *pul += ulDelta << uShift1; 1263 } 1264 else 1265 { /* apply delta fixup */ 1266 switch (fType) 1267 { 1268 case IMAGE_REL_BASED_HIGHLOW: 1269 *pul += ulDelta << uShift1; 1270 break; 1271 case IMAGE_REL_BASED_HIGH: 1272 case IMAGE_REL_BASED_HIGHADJ: /* According to M$ docs these seems to be the same fixups. */ 1273 case IMAGE_REL_BASED_HIGH3ADJ: 1274 *pul += ulDelta << 8; 1275 break; 1276 case IMAGE_REL_BASED_LOW: 1277 *pul += ulDelta << 24; 1278 break; 1279 } 1280 } 1281 } 1282 else 1283 { /* 1284 * Common fixup 1285 */ 1286 pul = (PULONG)((unsigned)pvPage + offFixup + pbr->VirtualAddress - ulRVAPage); 1287 switch (fType) 1288 { 1289 case IMAGE_REL_BASED_HIGHLOW: 1290 if (fDeltaOnly) 1291 *pul += ulDelta; 1292 else 1293 { 1294 ulTarget = *pul; 1295 ulTarget -= ulImageBase; /* ulTarget is now an RVA */ 1296 iObj = 0UL; 1297 while (iObj < cObjects 1298 && ulTarget >= (iObj + 1 < cObjects ? paObjects[iObj+1].ulRVA 1299 : ALIGN(paObjects[iObj].cbVirtual, PAGESIZE) + paObjects[iObj].ulRVA) 1300 ) 1301 iObj++; 1302 if (iObj < cObjects) 1303 *pul = pSMTE->smte_objtab[iObj].ote_base + ulTarget - paObjects[iObj].ulRVA; 1304 else 1305 *pul += ulDelta; 1306 } 1307 break; 1308 /* Will probably not work very well until the 64KB object alignment is gone! */ 1309 case IMAGE_REL_BASED_HIGH: 1310 case IMAGE_REL_BASED_HIGHADJ: /* According to M$ docs these seems to be the same fixups. */ 1311 case IMAGE_REL_BASED_HIGH3ADJ: 1312 printInf(("IMAGE_REL_BASED_HIGH offset=0x%08x\n", offFixup)); 1313 *(PUSHORT)pul += (USHORT)(ulDelta >> 16); 1314 break; 1315 /* Will probably not work very well until the 64KB object alignment is gone! */ 1316 case IMAGE_REL_BASED_LOW: 1317 printInf(("IMAGE_REL_BASED_LOW offset=0x%08x\n", offFixup)); 1318 *(PUSHORT)pul += (USHORT)ulDelta; 1319 break; 1320 } 1321 } 1322 } 1323 1324 /* Next offset/type */ 1325 pwoffFixup++; 1326 cRelocations--; 1327 } 1328 } 1329 1330 /* next */ 1331 pbr = (PIMAGE_BASE_RELOCATION)((unsigned)pbr + pbr->SizeOfBlock); 1332 } 1333 } 1034 1334 NOREF(iPageTable); 1035 NOREF(pvPage);1036 NOREF(ulPageAddress);1037 1335 NOREF(pvPTDA); 1038 1336 … … 1043 1341 1044 1342 #ifndef RING0 1343 /** 1344 * This method test the applyFixups method. 1345 * @returns Last rc from applyFixups. 1346 * @status 1347 * @author knut st. osmundsen 1348 * @remark Testing only... 1349 */ 1350 ULONG Pe2Lx::testApplyFixups() 1351 { 1352 static SMTE smte; 1353 static MTE mte; 1354 static achPage[PAGESIZE]; 1355 int i; 1356 APIRET rc; 1357 1358 mte.mte_swapmte = ⪬ 1359 smte.smte_objcnt = cObjects; 1360 smte.smte_objtab = (POTE)malloc(cObjects * sizeof(OTE)); 1361 makeObjectTable(); 1362 memcpy(smte.smte_objtab, paObjTab, sizeof(OTE) * cObjects); 1363 smte.smte_objtab[0].ote_base = 0x125D0000; 1364 for (i = 1; i < cObjects; i++) 1365 smte.smte_objtab[i].ote_base = ALIGN(smte.smte_objtab[i-1].ote_size + smte.smte_objtab[i-1].ote_base, 0x10000); 1366 1367 rc = loadBaseRelocations(); 1368 if (rc != NO_ERROR) 1369 { 1370 printErr(("loadBaseRelocations failed with rc=%d\n", rc)); 1371 return rc; 1372 } 1373 1374 rc = readAtRVA(0x00000000, &achPage[0], PAGESIZE); 1375 if (rc != NO_ERROR) 1376 { 1377 printErr(("readAtRVA failed with rc=%d\n")); 1378 return rc; 1379 } 1380 rc = applyFixups(&mte, 0, ~0UL, &achPage[0], 0x125D0000, NULL); 1381 1382 rc = readAtRVA(0x00001000, &achPage[0], PAGESIZE); 1383 if (rc != NO_ERROR) 1384 { 1385 printErr(("readAtRVA failed with rc=%d\n")); 1386 return rc; 1387 } 1388 rc = applyFixups(&mte, 1, 1, &achPage[0], 0x125E0000, NULL); 1389 1390 return rc; 1391 } 1392 1393 1394 1045 1395 /** 1046 1396 * Writes the virtual LX file to a file. (Ring 3 only!) … … 1804 2154 ULONG ulRVAFirstThunk; /* Current first thunk array RVA. Points at current entry. */ 1805 2155 ULONG ulRVAOrgFirstThunk; /* Current original first thunk array RVA. Points at current entry. */ 1806 2156 #ifndef RING0 1807 2157 BOOL fBaseRelocs; /* fBaseReloc is set when a valid base reloc directory is present. */ 1808 2158 ULONG ulRVABaseReloc; /* RVA of the current base relocation chunk. (Not the first!) */ … … 1811 2161 BufferedRVARead *pPageReader; /* Buffered reader for page reads; ie. getting the target address. */ 1812 2162 BufferedRVARead *pRelocReader; /* Buffered reader for relocation reads; ie getting the type/offset word. */ 1813 2163 #endif 1814 2164 ULONG ulRVAPage; /* RVA for the current page. */ 1815 2165 ULONG ul; /* temporary unsigned long variable. Many uses. */ … … 1848 2198 1849 2199 /* Check if empty base relocation directory. */ 2200 #ifndef RING0 1850 2201 fBaseRelocs = (cbBaseRelocs = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size) > 0UL 1851 2202 && … … 1853 2204 && 1854 2205 ulRVABaseReloc < pNtHdrs->OptionalHeader.SizeOfImage; 1855 2206 #endif 1856 2207 printInf(("\n")); 2208 #ifndef RING0 1857 2209 printInf(("Make fixups, fBaseReloc=%s, fImports=%s\n", 1858 2210 fBaseRelocs ? "true" : "false", 1859 2211 fImports ? "true" : "false")); 2212 #else 2213 printInf(("Make fixups, fImports=%s\n", fImports ? "true" : "false")); 2214 #endif 1860 2215 printInf(("\n")); 1861 2216 1862 2217 /* create reader buffers */ 2218 #ifndef RING0 1863 2219 if (fBaseRelocs) 1864 2220 { … … 1870 2226 else 1871 2227 pRelocReader = pPageReader = NULL; 2228 #endif 1872 2229 if (fImports) 1873 2230 { … … 1884 2241 if (rc != NO_ERROR) 1885 2242 { /* error: clean up and return! */ 2243 #ifndef RING0 1886 2244 if (pPageReader != NULL) 1887 2245 delete pPageReader; 1888 2246 if (pRelocReader != NULL) 1889 2247 delete pRelocReader; 2248 #endif 1890 2249 if (pImportReader != NULL) 1891 2250 delete pImportReader; … … 1936 2295 } 1937 2296 2297 1938 2298 /* read start of the first basereloc chunk */ 2299 #ifndef RING0 1939 2300 if (fBaseRelocs && rc == NO_ERROR) 1940 2301 rc = pRelocReader->readAtRVA(ulRVABaseReloc, SSToDS(&BaseReloc), sizeof(BaseReloc)); 2302 #endif 1941 2303 1942 2304 … … 2053 2415 2054 2416 /* check for fixups for this page. ASSUMES that fixups are sorted and that each chunk covers one page, no more no less. */ 2417 #ifndef RING0 2055 2418 if (fBaseRelocs && BaseReloc.VirtualAddress == ulRVAPage) 2056 2419 { … … 2118 2481 fBaseRelocs = FALSE; 2119 2482 } 2483 #endif /*ifndef RING */ 2120 2484 2121 2485 /** next **/ … … 2140 2504 2141 2505 /* finished! - cleanup! */ 2506 #ifndef RING0 2142 2507 if (pPageReader != NULL) 2143 2508 delete pPageReader; 2144 2509 if (pRelocReader != NULL) 2145 2510 delete pRelocReader; 2511 #endif 2146 2512 if (pImportReader != NULL) 2147 2513 delete pImportReader; … … 2157 2523 finalizeFixups(); 2158 2524 } 2525 #ifdef RING0 2526 /* load base relocations... */ 2527 if (rc == NO_ERROR) 2528 return loadBaseRelocations(); 2529 #endif 2159 2530 return rc; 2160 2531 } … … 2402 2773 pNtHdrs = NULL; 2403 2774 } 2775 } 2776 2777 2778 /** 2779 * Loads the baserelocations from the PE-file. 2780 * @returns NO_ERROR on success, appropriate error message. 2781 * @sketch 2782 * @status completely implemented; untestd. 2783 * @author knut st. osmundsen 2784 */ 2785 ULONG Pe2Lx::loadBaseRelocations() 2786 { 2787 APIRET rc; 2788 ULONG ulRVA; 2789 2790 /* ? */ 2791 rc = loadNtHeaders(); 2792 if (rc != NO_ERROR) 2793 return rc; 2794 /* end ? */ 2795 2796 ulRVA = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; 2797 cbBaseRelocs = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 2798 2799 if (ulRVA > 0UL && cbBaseRelocs > 0UL && ulRVA < ~0UL && cbBaseRelocs < ~0UL) 2800 { 2801 pBaseRelocs = (PIMAGE_BASE_RELOCATION)smalloc((size_t)cbBaseRelocs); 2802 if (pBaseRelocs != NULL) 2803 { 2804 rc = readAtRVA(ulRVA, pBaseRelocs, cbBaseRelocs); 2805 if (rc != NO_ERROR) 2806 { 2807 printErr(("readAtRVA(0x%08x, 0x%08x, 0x%08x) failed with rc = %d\n", 2808 ulRVA, pBaseRelocs, cbBaseRelocs, rc)); 2809 sfree(pBaseRelocs); 2810 pBaseRelocs = NULL; 2811 } 2812 #ifdef DEBUG 2813 else 2814 { 2815 PIMAGE_BASE_RELOCATION pbrCur = pBaseRelocs; 2816 while ((void*)pbrCur < (void*)((unsigned)pBaseRelocs + cbBaseRelocs)) 2817 { 2818 if ((unsigned)pbrCur->SizeOfBlock + (unsigned)pbrCur > (unsigned)pBaseRelocs + cbBaseRelocs) 2819 printErr(("Debug-check - Chunk is larger than the base relocation directory. " 2820 "SizeOfBlock=0x%08x, VirtualAddress=0x%08x\n", 2821 pbrCur->SizeOfBlock, pbrCur->VirtualAddress)); 2822 pbrCur = (PIMAGE_BASE_RELOCATION)((unsigned)pbrCur + pbrCur->SizeOfBlock); 2823 } 2824 } 2825 #endif 2826 return rc; 2827 } 2828 else 2829 { 2830 printErr(("rmalloc failed when allocating memory for pBaseReloc, cbSize=0x%x(%d)\n", 2831 cbBaseRelocs, cbBaseRelocs)); 2832 rc = ERROR_NOT_ENOUGH_MEMORY; 2833 } 2834 } 2835 else 2836 { 2837 pBaseRelocs = NULL; 2838 cbBaseRelocs = 0; 2839 } 2840 2841 return NO_ERROR; 2404 2842 } 2405 2843 … … 3867 4305 3868 4306 /** 4307 * Reads a chunk of data at the spcified RVA. 4308 * @returns NO_ERROR on success. 4309 * ERROR_INVALID_PARAMETER 4310 * <Whatever rc ReadAt returns> 4311 * @param ulRVA RVA to read from. Within the filesize. 4312 * @param pvBuffer Pointer to output buffer. pvBuffer > 64KB 4313 * @param cbBuffer Number of bytes to read. 0 < cbBuffer > 256MB 4314 * @status completely implemented; tested. 4315 * @author knut st. osmundsen 4316 */ 4317 ULONG Pe2Lx::readAtRVA(ULONG ulRVA, PVOID pvBuffer, ULONG cbBuffer) 4318 { 4319 #ifdef DEBUG 4320 if (ulRVA == ~0UL || (ULONG)pvBuffer < 0x10000UL || cbBuffer == 0UL || cbBuffer >= 0x10000000UL) 4321 return ERROR_INVALID_PARAMETER; 4322 #endif 4323 4324 ULONG iObj = 0; 4325 while (cbBuffer != 0UL) 4326 { 4327 while (iObj < cObjects 4328 && ulRVA >= (iObj + 1 < cObjects ? paObjects[iObj+1].ulRVA 4329 : paObjects[iObj].ulRVA + ALIGN(paObjects[iObj].cbVirtual, PAGESIZE)) 4330 ) 4331 iObj++; 4332 if (iObj >= cObjects) 4333 return ERROR_INVALID_PARAMETER; 4334 4335 /* ulRVA points at physical or virtual data? */ 4336 if (ulRVA < paObjects[iObj].ulRVA + paObjects[iObj].cbPhysical) 4337 { /* physical data - read from file */ 4338 APIRET rc; 4339 ULONG cbToRead = min(paObjects[iObj].ulRVA + paObjects[iObj].cbPhysical - ulRVA, cbBuffer); 4340 rc = ReadAt(hFile, 4341 ulRVA - paObjects[iObj].ulRVA + paObjects[iObj].offPEFile, 4342 pvBuffer, 4343 cbToRead 4344 ); 4345 if (rc != NO_ERROR) 4346 return rc; 4347 ulRVA += cbToRead; 4348 cbBuffer -= cbToRead; 4349 pvBuffer = (void*)((unsigned)pvBuffer + cbToRead); 4350 } 4351 else 4352 { /* virtual data - memset(,0,) */ 4353 ULONG cbToSet = (iObj + 1 < cObjects ? paObjects[iObj+1].ulRVA 4354 : paObjects[iObj].ulRVA + ALIGN(paObjects[iObj].cbVirtual, PAGESIZE)) 4355 - ulRVA; /* calcs size of virtual data left in this object */ 4356 cbToSet = min(cbToSet, cbBuffer); 4357 4358 memset(pvBuffer, 0, (size_t)cbToSet); 4359 ulRVA += cbToSet; 4360 cbBuffer -= cbToSet; 4361 pvBuffer = (void*)((unsigned)pvBuffer + cbToSet); 4362 } 4363 } /* while */ 4364 4365 return NO_ERROR; 4366 } 4367 4368 4369 4370 /** 3869 4371 * Check if the modulename exists in the lielist. If not the passed in modulename is returned. 3870 4372 * @returns Pointer (readonly) to Odin32 modulename. … … 4237 4739 4238 4740 /* where to read? */ 4239 if (ulRVA != this->ulRVA + sizeof(achBuffer) != ulRVA || this->ulRVA != ~0UL)4741 if (ulRVA != this->ulRVA + sizeof(achBuffer) || this->ulRVA == ~0UL) 4240 4742 ulRVARead = this->ulRVA = ulRVA & ~(PAGESIZE-1UL); /* align on page boundrary - ASSUMES: buffersize >= PAGESIZE! */ 4241 4743 else … … 4246 4748 while (cbLeftToRead != 0UL) 4247 4749 { 4248 while (iObj < cObjects && ulRVARead >= (iObj + 1 < cObjects ? paObjects[iObj+1].ulRVA 4249 : paObjects[iObj].ulRVA + ALIGN(paObjects[iObj].cbVirtual, PAGESIZE)) 4750 while (iObj < cObjects 4751 && ulRVARead >= (iObj + 1 < cObjects ? paObjects[iObj+1].ulRVA 4752 : paObjects[iObj].ulRVA + ALIGN(paObjects[iObj].cbVirtual, PAGESIZE)) 4250 4753 ) 4251 4754 iObj++;
Note:
See TracChangeset
for help on using the changeset viewer.