Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

524 lines
14 KiB

4 years ago
  1. /***********************************************************************
  2. * Microsoft (R) 32-Bit Incremental Linker
  3. *
  4. * Copyright (C) Microsoft Corp 1992-1996. All rights reserved.
  5. *
  6. * File: pdata.cpp
  7. *
  8. * File Comments:
  9. *
  10. * This module handles the re-ordering of the pdata section.
  11. *
  12. ***********************************************************************/
  13. #include "link.h"
  14. struct TFIXUP
  15. {
  16. DWORD rva;
  17. WORD ftype;
  18. WORD wAdj;
  19. };
  20. void
  21. LoadPdata(
  22. PIMAGE pimage,
  23. INT FileHandle,
  24. IMAGE_SECTION_HEADER *pshPdata,
  25. IMAGE_SECTION_HEADER *pshReloc,
  26. PIMAGE_RUNTIME_FUNCTION_ENTRY *prgrfe,
  27. DWORD *pcrfe,
  28. TFIXUP **prgtfixup,
  29. DWORD *pctfixup
  30. )
  31. {
  32. *pshPdata = NullSectionHdr;
  33. *pshReloc = NullSectionHdr;
  34. DWORD rvaPdata = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
  35. DWORD rvaReloc = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
  36. DWORD fo = CoffHeaderSeek + sizeof(IMAGE_FILE_HEADER) + pimage->ImgFileHdr.SizeOfOptionalHeader;
  37. FileSeek(FileHandle, fo, SEEK_SET);
  38. for (DWORD i = 0; i < pimage->ImgFileHdr.NumberOfSections; i++) {
  39. IMAGE_SECTION_HEADER sh;
  40. FileRead(FileHandle, &sh, sizeof(sh));
  41. if ((rvaPdata >= sh.VirtualAddress) && (rvaPdata < sh.VirtualAddress+sh.SizeOfRawData)) {
  42. *pshPdata = sh;
  43. continue;
  44. }
  45. if ((rvaReloc >= sh.VirtualAddress) && (rvaReloc < sh.VirtualAddress+sh.SizeOfRawData)) {
  46. *pshReloc = sh;
  47. continue;
  48. }
  49. }
  50. DWORD cbRfe = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
  51. DWORD crfe = cbRfe / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  52. PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe = (PIMAGE_RUNTIME_FUNCTION_ENTRY) PvAlloc(cbRfe);
  53. FileSeek(FileHandle, pshPdata->PointerToRawData, SEEK_SET);
  54. FileRead(FileHandle, rgrfe, cbRfe);
  55. DWORD foReloc = rvaReloc - pshReloc->VirtualAddress + pshReloc->PointerToRawData;
  56. FileSeek(FileHandle, foReloc, SEEK_SET);
  57. DWORD cbReloc = pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
  58. DWORD cbTfixup = (cbReloc ? (cbReloc / sizeof(WORD)) : 1) * sizeof(TFIXUP);
  59. TFIXUP *rgtfixup = (TFIXUP *) PvAlloc(cbTfixup);
  60. DWORD ctfixup = 0;
  61. if (cbReloc != 0) {
  62. WORD *rgwReloc = (WORD *) PvAlloc(0xffff);
  63. while (cbReloc > 0) {
  64. IMAGE_BASE_RELOCATION bre;
  65. FileRead(FileHandle, &bre, IMAGE_SIZEOF_BASE_RELOCATION);
  66. if (bre.SizeOfBlock == 0) {
  67. break;
  68. }
  69. DWORD cbBlock = bre.SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION;
  70. FileRead(FileHandle, rgwReloc, cbBlock);
  71. DWORD cw = cbBlock / sizeof(WORD);
  72. for (DWORD iw = 0; iw < cw; iw++) {
  73. if (rgwReloc[iw] == 0) { // indicates a pad
  74. continue;
  75. }
  76. DWORD ib = rgwReloc[iw] & 0xfff;
  77. rgtfixup[ctfixup].rva = bre.VirtualAddress + ib;
  78. rgtfixup[ctfixup].ftype = rgwReloc[iw] >> 12;
  79. if (rgtfixup[ctfixup].ftype == IMAGE_REL_BASED_HIGHADJ) {
  80. rgtfixup[ctfixup].wAdj = rgwReloc[++iw];
  81. }
  82. ctfixup++;
  83. }
  84. cbReloc -= bre.SizeOfBlock;
  85. }
  86. FreePv(rgwReloc);
  87. }
  88. *prgrfe = rgrfe;
  89. *pcrfe = crfe;
  90. *prgtfixup = rgtfixup;
  91. *pctfixup = ctfixup;
  92. }
  93. int __cdecl cmpPprfePprfeBeginAddress(void const *pprfe1, void const *pprfe2)
  94. {
  95. DWORD addr1 = (*(PIMAGE_RUNTIME_FUNCTION_ENTRY *) pprfe1)->BeginAddress;
  96. DWORD addr2 = (*(PIMAGE_RUNTIME_FUNCTION_ENTRY *) pprfe2)->BeginAddress;
  97. if (addr1 == 0) {
  98. return(1);
  99. }
  100. if (addr2 == 0) {
  101. return(-1);
  102. }
  103. if (addr1 < addr2) {
  104. return(-1);
  105. }
  106. if (addr1 > addr2) {
  107. return(1);
  108. }
  109. return(0);
  110. }
  111. int __cdecl cmpPtfixupPtfixupRva(void const *ptfixup1, void const *ptfixup2)
  112. {
  113. DWORD rva1 = ((TFIXUP *) ptfixup1)->rva;
  114. DWORD rva2 = ((TFIXUP *) ptfixup2)->rva;
  115. if (rva1 < rva2) {
  116. return(-1);
  117. }
  118. if (rva1 > rva2) {
  119. return(1);
  120. }
  121. return(0);
  122. }
  123. void
  124. SortFunctionTable(
  125. PIMAGE pimage
  126. )
  127. /*++
  128. Routine Description:
  129. Re-Order the pdata section according to the beginning address and
  130. also simultaneously adjust the relocations.
  131. Arguments:
  132. none.
  133. Return Value:
  134. none
  135. --*/
  136. {
  137. if (psecException->cbVirtualSize == 0) {
  138. // Nothing to do
  139. return;
  140. }
  141. assert(psecException->rva != 0);
  142. // Read in the section headers for .pdata and .reloc
  143. IMAGE_SECTION_HEADER shPdata;
  144. IMAGE_SECTION_HEADER shReloc;
  145. PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe;
  146. DWORD crfe;
  147. TFIXUP *rgtfixup;
  148. DWORD ctfixup;
  149. LoadPdata(pimage, FileWriteHandle, &shPdata, &shReloc, &rgrfe, &crfe, &rgtfixup, &ctfixup);
  150. PIMAGE_RUNTIME_FUNCTION_ENTRY *rgprfe = (PIMAGE_RUNTIME_FUNCTION_ENTRY *) PvAlloc(crfe * sizeof(PIMAGE_RUNTIME_FUNCTION_ENTRY));
  151. for (DWORD irfe = 0; irfe < crfe; irfe++) {
  152. rgprfe[irfe] = rgrfe + irfe;
  153. }
  154. // Sort the runtime function entries by address
  155. qsort(rgprfe, crfe, sizeof(PIMAGE_RUNTIME_FUNCTION_ENTRY), cmpPprfePprfeBeginAddress);
  156. // Write out the now sorted entries
  157. FileSeek(FileWriteHandle, shPdata.PointerToRawData, SEEK_SET);
  158. for (irfe = 0; irfe < crfe; irfe++) {
  159. FileWrite(FileWriteHandle, rgprfe[irfe], sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY));
  160. }
  161. // Build a map from old RFE index to new RFE index
  162. DWORD *mpirfeOldirfeNew = (DWORD *) PvAlloc(crfe * sizeof(DWORD));
  163. for (irfe = 0; irfe < crfe; irfe++) {
  164. DWORD irfeOld = rgprfe[irfe] - rgrfe;
  165. mpirfeOldirfeNew[irfeOld] = irfe;
  166. }
  167. DWORD rvaMin = psecException->rva;
  168. DWORD rvaMax = rvaMin + psecException->cbVirtualSize;
  169. // Update the temp fixups with the new RVA where each is applied
  170. TFIXUP *ptfixup = rgtfixup;
  171. for (DWORD itfixup = 0; itfixup < ctfixup; itfixup++, ptfixup++) {
  172. if ((ptfixup->rva < rvaMin) || (ptfixup->rva >= rvaMax)) {
  173. continue;
  174. }
  175. DWORD irfeOld = (ptfixup->rva - rvaMin) / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  176. DWORD irfeNew = mpirfeOldirfeNew[irfeOld];
  177. DWORD ib = (irfeNew - irfeOld) * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  178. ptfixup->rva += ib;
  179. }
  180. if (pimage->Switch.Link.DebugType & FixupDebug) {
  181. // Update debug FIXUPs (SaveDebugFixup) with the new RVAs
  182. FileSeek(FileWriteHandle, pconFixupDebug->foRawDataDest, SEEK_SET);
  183. DWORD cxfixup = pconFixupDebug->cbRawData / sizeof(XFIXUP);
  184. for (DWORD ixfixup = 0; ixfixup < cxfixup; ixfixup++) {
  185. XFIXUP xfixup;
  186. FileRead(FileWriteHandle, &xfixup, sizeof(XFIXUP));
  187. if ((xfixup.rva < rvaMin) || (xfixup.rva >= rvaMax)) {
  188. continue;
  189. }
  190. DWORD irfeOld = (xfixup.rva - rvaMin) / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  191. DWORD irfeNew = mpirfeOldirfeNew[irfeOld];
  192. DWORD ib = (irfeNew - irfeOld) * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  193. if (ib != 0) {
  194. xfixup.rva += ib;
  195. FileSeek(FileWriteHandle, -(long) sizeof(XFIXUP), SEEK_CUR);
  196. FileWrite(FileWriteHandle, &xfixup, sizeof(XFIXUP));
  197. }
  198. }
  199. }
  200. // We are done with these now
  201. FreePv(mpirfeOldirfeNew);
  202. FreePv(rgprfe);
  203. FreePv(rgrfe);
  204. if (ctfixup != 0) {
  205. // Sort the temp fixups by RVA
  206. qsort(rgtfixup, ctfixup, sizeof(TFIXUP), cmpPtfixupPtfixupRva);
  207. // Write out the now sorted entries
  208. WORD *fixups = (WORD *) PvAlloc(0xffff);
  209. DWORD rvaReloc = psecBaseReloc->rva;
  210. DWORD foReloc = rvaReloc - shReloc.VirtualAddress + shReloc.PointerToRawData;
  211. FileSeek(FileWriteHandle, foReloc, SEEK_SET);
  212. DWORD i = 0;
  213. DWORD cb = 0;
  214. while (i < ctfixup) {
  215. DWORD rva = rgtfixup[i].rva & 0xfffff000;
  216. IMAGE_BASE_RELOCATION bre;
  217. bre.VirtualAddress = rva;
  218. DWORD j = 0;
  219. for (;;) {
  220. DWORD ib = rgtfixup[i].rva & 0xfff;
  221. fixups[j] = (WORD) ((rgtfixup[i].ftype << 12) | ib);
  222. if (rgtfixup[i].ftype == IMAGE_REL_BASED_HIGHADJ) {
  223. fixups[++j] = rgtfixup[i].wAdj;
  224. }
  225. i++;
  226. j++;
  227. if ((rgtfixup[i].rva & 0xfffff000) != rva) {
  228. break;
  229. }
  230. if (i == ctfixup) {
  231. break;
  232. }
  233. }
  234. bre.SizeOfBlock = IMAGE_SIZEOF_BASE_RELOCATION + (j * sizeof(WORD));
  235. if (bre.SizeOfBlock & 0x2) {
  236. bre.SizeOfBlock += 2;
  237. fixups[j] = 0;
  238. }
  239. cb += bre.SizeOfBlock;
  240. FileWrite(FileWriteHandle, &bre, IMAGE_SIZEOF_BASE_RELOCATION);
  241. FileWrite(FileWriteHandle, fixups, bre.SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION);
  242. }
  243. pimage->ImgOptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = cb;
  244. FreePv(fixups);
  245. }
  246. FreePv(rgtfixup);
  247. }
  248. void
  249. DumpDbgFunctionTable(
  250. DWORD foTable,
  251. DWORD cbTable
  252. )
  253. {
  254. DWORD cfe;
  255. DWORD ife = 0;
  256. cfe = cbTable / sizeof(IMAGE_FUNCTION_ENTRY);
  257. fprintf(InfoStream, "\nFunction Table (%lu)\n\n", cfe);
  258. fprintf(InfoStream, " Begin End PrologEnd\n\n");
  259. FileSeek(FileReadHandle, foTable, SEEK_SET);
  260. while (cfe--) {
  261. IMAGE_FUNCTION_ENTRY fe;
  262. FileRead(FileReadHandle, &fe, sizeof(IMAGE_FUNCTION_ENTRY));
  263. fprintf(InfoStream, "%08lX %08lX %08lX %08lX\n",
  264. ife * sizeof(IMAGE_FUNCTION_ENTRY),
  265. fe.StartingAddress,
  266. fe.EndingAddress,
  267. fe.EndOfPrologue);
  268. ife++;
  269. }
  270. }
  271. void
  272. DumpFunctionTable(
  273. PIMAGE pimage,
  274. PIMAGE_SYMBOL rgsym,
  275. const char *StringTable
  276. )
  277. {
  278. IMAGE_SECTION_HEADER shPdata;
  279. IMAGE_SECTION_HEADER shReloc;
  280. PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe;
  281. DWORD crfe;
  282. TFIXUP *rgtfixup;
  283. DWORD ctfixup;
  284. LoadPdata(pimage, FileReadHandle, &shPdata, &shReloc, &rgrfe, &crfe, &rgtfixup, &ctfixup);
  285. fprintf(InfoStream, "\nFunction Table (%lu)\n\n", crfe);
  286. fprintf(InfoStream, " Begin End Excptn ExcpDat Prolog Fixups Function Name\n\n");
  287. DWORD rvaRfe = shPdata.VirtualAddress;
  288. PIMAGE_RUNTIME_FUNCTION_ENTRY prfe = rgrfe;
  289. DWORD itfixup = 0;
  290. while ((itfixup < ctfixup) && (rgtfixup[itfixup].rva < rvaRfe)) {
  291. itfixup++;
  292. }
  293. for (DWORD irfe = 0; irfe < crfe; irfe++, prfe++) {
  294. DWORD ib = irfe * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  295. fprintf(InfoStream, "%08lX %08lX %08lX %08lX %08lX %08lX ",
  296. ib,
  297. prfe->BeginAddress,
  298. prfe->EndAddress,
  299. (DWORD) prfe->ExceptionHandler,
  300. (DWORD) prfe->HandlerData,
  301. prfe->PrologEndAddress);
  302. DWORD i;
  303. for (i = 0; i < 5; i++) {
  304. if ((itfixup < ctfixup) && (rgtfixup[itfixup].rva == rvaRfe)) {
  305. fputc('Y', InfoStream);
  306. itfixup++;
  307. } else {
  308. fputc('N', InfoStream);
  309. }
  310. rvaRfe += sizeof(DWORD);
  311. }
  312. if (rgsym != NULL) {
  313. DWORD rva = prfe->BeginAddress - pimage->ImgOptHdr.ImageBase;
  314. PIMAGE_SYMBOL psymNext = rgsym;
  315. for (i = 0; i < pimage->ImgFileHdr.NumberOfSymbols; i++) {
  316. PIMAGE_SYMBOL psym;
  317. psym = FetchNextSymbol(&psymNext);
  318. if ((psym->Value == rva) && (psym->NumberOfAuxSymbols == 0)) {
  319. fprintf(InfoStream, " %s", SzNameSymPb(*psym, StringTable));
  320. break;
  321. }
  322. }
  323. }
  324. fputc('\n', InfoStream);
  325. }
  326. FreePv(rgrfe);
  327. FreePv(rgtfixup);
  328. }
  329. void
  330. DumpObjFunctionTable(
  331. PIMAGE_SECTION_HEADER sh,
  332. SHORT SectionNumber
  333. )
  334. {
  335. DWORD crfe;
  336. DWORD irfe = 0;
  337. crfe = sh->SizeOfRawData / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY);
  338. fprintf(InfoStream, "\nFUNCTION TABLE #%d (%lu)\n\n", SectionNumber, crfe);
  339. fprintf(InfoStream, " Begin End Excptn ExcpDat PrologEnd\n\n");
  340. while (crfe--) {
  341. IMAGE_RUNTIME_FUNCTION_ENTRY rfe;
  342. FileRead(FileReadHandle, &rfe, sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY));
  343. fprintf(InfoStream, "%08lX %08lX %08lX %08lX %08lX %08lX\n",
  344. irfe * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY),
  345. rfe.BeginAddress,
  346. rfe.EndAddress,
  347. (DWORD) rfe.ExceptionHandler,
  348. (DWORD) rfe.HandlerData,
  349. rfe.PrologEndAddress);
  350. irfe++;
  351. }
  352. }
  353. void
  354. DumpPexFunctionTable(
  355. PIMAGE_RUNTIME_FUNCTION_ENTRY rgrfe,
  356. DWORD crfe
  357. )
  358. {
  359. fprintf(InfoStream, "\nFUNCTION TABLE (%lu)\n\n", crfe);
  360. fprintf(InfoStream, " Begin End Excptn ExcpDat PrologEnd\n\n");
  361. PIMAGE_RUNTIME_FUNCTION_ENTRY prfe = rgrfe;
  362. for (DWORD irfe = 0; irfe < crfe; irfe++, prfe++) {
  363. fprintf(InfoStream, "%08lX %08lX %08lX %08lX %08lX %08lX\n",
  364. irfe * sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY),
  365. DwSwap(prfe->BeginAddress),
  366. DwSwap(prfe->EndAddress),
  367. DwSwap((DWORD) prfe->ExceptionHandler),
  368. DwSwap((DWORD) prfe->HandlerData),
  369. DwSwap(prfe->PrologEndAddress));
  370. }
  371. }