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.

763 lines
19 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: dmple.cpp
  7. *
  8. * File Comments:
  9. *
  10. *
  11. ***********************************************************************/
  12. #include "link.h"
  13. #include "exe_vxd.h"
  14. #define Switch (pimageDump->Switch)
  15. #ifdef DUMPLX
  16. struct o32_map_lx
  17. {
  18. unsigned long o32_pagedataoffset; // File offset of page
  19. unsigned short o32_pagesize; // Number of bytes of data
  20. unsigned short o32_pageflags;
  21. };
  22. #endif
  23. static LONG foHdr;
  24. static struct e32_exe exe;
  25. #if 0
  26. #ifdef DUMPLX
  27. const static char * const szLXModType[] = {
  28. "EXE",
  29. "DLL",
  30. "Unknown",
  31. "Protected DLL",
  32. "Physical Device Driver",
  33. "Virtual Device Driver",
  34. "Unknown",
  35. "Unknown"
  36. };
  37. #endif
  38. const static char * const szVXDType[] = {
  39. "Unknown",
  40. "Unknown",
  41. "Unknown",
  42. "Unknown",
  43. "Unknown",
  44. "Static",
  45. "Unknown",
  46. "Dynamic"
  47. };
  48. #endif
  49. struct
  50. {
  51. DWORD dwMask;
  52. const char *szName;
  53. } const rgo32flags[] =
  54. {
  55. { OBJRSRC, "Resource" },
  56. { OBJDISCARD, "Discardable" },
  57. { OBJSHARED, "Shared" },
  58. { OBJPRELOAD, "Has preload pages" },
  59. { OBJINVALID, "Has invalid pages" },
  60. { OBJRESIDENT, "Resident" },
  61. { OBJALIAS16, "16:16 alias" },
  62. { OBJBIGDEF, "32-bit" },
  63. { OBJCONFORM, "Conforming" },
  64. { OBJIOPL, "Message" },
  65. };
  66. const char * const rgszLeAccess[] =
  67. {
  68. NULL,
  69. "Read Only",
  70. "Write Only",
  71. "Read Write",
  72. "Execute Only",
  73. "Execute Read",
  74. "Execute Write",
  75. "Execute Read Write",
  76. };
  77. void DumpLeObjectHeader(size_t iobj, const o32_obj *pobj)
  78. {
  79. fprintf(InfoStream,
  80. "\n"
  81. "OBJECT HEADER #%X\n"
  82. "%8lX virtual size\n"
  83. "%8lX virtual address\n"
  84. "%8lX flags\n",
  85. iobj,
  86. O32_SIZE(*pobj),
  87. O32_BASE(*pobj),
  88. O32_FLAGS(*pobj));
  89. if (O32_FLAGS(*pobj) & (OBJREAD | OBJWRITE | OBJEXEC)) {
  90. fprintf(InfoStream, " %s\n", rgszLeAccess[O32_FLAGS(*pobj) & 7]);
  91. }
  92. for (size_t iflag = 0; iflag < sizeof(rgo32flags) / sizeof(rgo32flags[0]); iflag++) {
  93. if ((O32_FLAGS(*pobj) & rgo32flags[iflag].dwMask) == 0) {
  94. continue;
  95. }
  96. const char *szName = rgo32flags[iflag].szName;
  97. #ifdef DUMPLX
  98. if ((dft == dftLX) && (rgo32flags[iflag].dwMask == OBJIOPL)) {
  99. szName = "IOPL";
  100. }
  101. #endif // DUMPLX
  102. fprintf(InfoStream, " %s\n", szName);
  103. }
  104. fprintf(InfoStream,
  105. "%8lX map index\n"
  106. "%8lX map size\n"
  107. "%8lX reserved\n",
  108. O32_PAGEMAP(*pobj),
  109. O32_MAPSIZE(*pobj),
  110. O32_RESERVED(*pobj));
  111. }
  112. #ifdef DUMPLX
  113. void DumpLxPageMap(size_t iobj, const o32_obj *pobj, const o32_map_lx *rgmap)
  114. {
  115. fprintf(InfoStream,
  116. " Logical File Page\n"
  117. " Page Offset Size Flags\n"
  118. " -------- -------- ---- ----------\n");
  119. DWORD cmap = O32_MAPSIZE(*pobj);
  120. const o32_map_lx *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
  121. for (DWORD imap = 0; imap < cmap; imap++, pmap++) {
  122. DWORD fo = 0;
  123. const char *szType;
  124. switch (pmap->o32_pageflags) {
  125. case VALID :
  126. fo = E32_DATAPAGE(exe);
  127. szType = "Valid";
  128. break;
  129. case ITERDATA :
  130. fo = E32_ITERMAP(exe);
  131. szType = "Iterated";
  132. break;
  133. case INVALID :
  134. szType = "Invalid";
  135. break;
  136. case ZEROED :
  137. szType = "Zeroed";
  138. break;
  139. case RANGE :
  140. szType = "Range";
  141. break;
  142. case 5 /* ITERDATA2 */ :
  143. fo = E32_DATAPAGE(exe);
  144. szType = "Compressed";
  145. break;
  146. default :
  147. szType = "Unknown";
  148. break;
  149. }
  150. if ((fo != 0) && (pmap->o32_pagedataoffset != 0)) {
  151. fo += pmap->o32_pagedataoffset << E32_LASTPAGESIZE(exe);
  152. }
  153. fprintf(InfoStream,
  154. " %08lX %08lX %04lX %s\n",
  155. 1 + imap,
  156. fo,
  157. pmap->o32_pagesize,
  158. szType);
  159. }
  160. }
  161. #endif // DUMPLX
  162. void DumpLePageMap(size_t iobj, const o32_obj *pobj, const o32_map *rgmap)
  163. {
  164. fprintf(InfoStream,
  165. "\n"
  166. "OBJECT PAGE MAP #%X\n"
  167. "\n",
  168. iobj);
  169. #ifdef DUMPLX
  170. if (dft == dftLX) {
  171. DumpLxPageMap(iobj, pobj, (o32_map_lx *) rgmap);
  172. return;
  173. }
  174. #endif // DUMPLX
  175. fprintf(InfoStream,
  176. " Logical Physical File Flags\n"
  177. " Page Page Offset Flags\n"
  178. " -------- -------- -------- --------\n");
  179. DWORD cmap = O32_MAPSIZE(*pobj);
  180. const o32_map *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
  181. for (DWORD imap = 0; imap < cmap; imap++, pmap++) {
  182. DWORD fo = 0;
  183. const char *szType;
  184. switch (PAGEFLAGS(*pmap)) {
  185. case VALID :
  186. fo = E32_DATAPAGE(exe);
  187. szType = "Valid";
  188. break;
  189. case ITERDATA :
  190. szType = "Iterated";
  191. break;
  192. case INVALID :
  193. szType = "Invalid";
  194. break;
  195. case ZEROED :
  196. szType = "Zeroed";
  197. break;
  198. case RANGE :
  199. szType = "Range";
  200. break;
  201. default :
  202. szType = "Unknown";
  203. break;
  204. }
  205. DWORD ippage = GETPAGEIDX(*pmap);
  206. if ((fo != 0) && (ippage != 0)) {
  207. fo += (ippage - 1) * E32_PAGESIZE(exe);
  208. }
  209. fprintf(InfoStream,
  210. " %08lX %08lX %08lX %s\n",
  211. 1 + imap,
  212. ippage,
  213. fo,
  214. szType);
  215. }
  216. }
  217. #ifdef DUMPLX
  218. void ReadLxIterData(INT FileReadHandle, BYTE *rgb, DWORD cbFile)
  219. {
  220. BYTE *pb = rgb;
  221. while (cbFile > 0)
  222. {
  223. WORD wRepeat;
  224. WORD cb;
  225. // Read the iteration record header
  226. FileRead(FileReadHandle, &wRepeat, sizeof(WORD));
  227. FileRead(FileReadHandle, &cb, sizeof(WORD));
  228. cbFile -= sizeof(WORD) + sizeof(WORD);
  229. if (cb == 0) {
  230. continue;
  231. }
  232. if (wRepeat == 0) {
  233. FileSeek(FileReadHandle, cb, SEEK_CUR);
  234. continue;
  235. }
  236. const BYTE *pbSrc = pb;
  237. FileRead(FileReadHandle, pb, cb);
  238. pb += cb;
  239. while (--wRepeat > 0) {
  240. memcpy(pb, pbSrc, cb);
  241. pb += cb;
  242. }
  243. cbFile -= cb;
  244. }
  245. }
  246. void ReadLxIterData2(INT FileReadHandle, BYTE *rgb, DWORD cbFile)
  247. {
  248. BYTE *pb = rgb;
  249. while (cbFile > 0)
  250. {
  251. BYTE bOpcode;
  252. // Read opcode byte
  253. FileRead(FileReadHandle, &bOpcode, sizeof(BYTE));
  254. cbFile--;
  255. switch (bOpcode & 3) {
  256. BYTE bCount;
  257. BYTE b;
  258. WORD w;
  259. case 0 :
  260. if (bOpcode != 0) {
  261. bCount = bOpcode >> 2;
  262. FileRead(FileReadHandle, pb, bCount);
  263. cbFile -= bCount;
  264. pb += bCount;
  265. break;
  266. }
  267. FileRead(FileReadHandle, &bCount, sizeof(BYTE));
  268. cbFile--;
  269. if (bCount == 0) {
  270. return;
  271. }
  272. FileRead(FileReadHandle, &b, sizeof(BYTE));
  273. cbFile--;
  274. memset(pb, b, bCount);
  275. pb += bCount;
  276. break;
  277. case 1 :
  278. FileRead(FileReadHandle, &b, sizeof(BYTE));
  279. cbFile--;
  280. w = ((WORD) b << 1) + ((bOpcode & 0x80) != 0x00);
  281. bCount = (bOpcode >> 2) & 0x3;
  282. FileRead(FileReadHandle, pb, bCount);
  283. cbFile -= bCount;
  284. pb += bCount;
  285. bCount = ((bOpcode >> 4) & 0x7) + 3;
  286. memcpy(pb, pb - w, bCount);
  287. pb += bCount;
  288. break;
  289. case 2 :
  290. FileRead(FileReadHandle, &b, sizeof(BYTE));
  291. cbFile--;
  292. w = ((WORD) b << 8) + bOpcode;
  293. bCount = ((bOpcode >> 2) & 0x3) + 3;
  294. w >>= 4;
  295. memcpy(pb, pb - w, bCount);
  296. pb += bCount;
  297. break;
  298. case 3 :
  299. FileRead(FileReadHandle, &w, sizeof(WORD));
  300. cbFile -= sizeof(WORD);
  301. bCount = (bOpcode >> 2) & 0xf;
  302. FileRead(FileReadHandle, pb, bCount);
  303. cbFile -= bCount;
  304. pb += bCount;
  305. bCount = ((bOpcode >> 6) & 0x3) + ((w << 2) & 0x3c);
  306. w >>= 4;
  307. memcpy(pb, pb - w, bCount);
  308. pb += bCount;
  309. break;
  310. }
  311. }
  312. }
  313. void LoadLxObject(const o32_obj *pobj, const o32_map_lx *rgmap, BYTE *rgb)
  314. {
  315. DWORD cb = O32_SIZE(*pobj);
  316. DWORD cmap = O32_MAPSIZE(*pobj);
  317. BYTE *pb = rgb;
  318. const o32_map_lx *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
  319. for (DWORD imap = 0; imap < cmap; imap++, pmap++, pb += E32_PAGESIZE(exe)) {
  320. DWORD fo;
  321. switch (pmap->o32_pageflags) {
  322. case VALID :
  323. fo = E32_DATAPAGE(exe);
  324. break;
  325. case ITERDATA :
  326. fo = E32_ITERMAP(exe);
  327. break;
  328. case INVALID :
  329. case ZEROED :
  330. continue;
  331. case 5 /* ITERDATA2 */ :
  332. fo = E32_DATAPAGE(exe);
  333. break;
  334. default :
  335. printf("LINK : warning : Unknown page type (%u)\n", pmap->o32_pageflags);
  336. continue;
  337. }
  338. fo += pmap->o32_pagedataoffset << E32_LASTPAGESIZE(exe);
  339. if (FileSeek(FileReadHandle, fo, SEEK_SET) == -1) {
  340. Error(NULL, CANTSEEKFILE, fo);
  341. }
  342. DWORD cbPage = pmap->o32_pagesize;
  343. switch (pmap->o32_pageflags) {
  344. case VALID :
  345. FileRead(FileReadHandle, pb, cbPage);
  346. break;
  347. case ITERDATA :
  348. ReadLxIterData(FileReadHandle, pb, cbPage);
  349. break;
  350. case 5 /* ITERDATA2 */ :
  351. ReadLxIterData2(FileReadHandle, pb, cbPage);
  352. break;
  353. }
  354. }
  355. }
  356. #endif // DUMPLX
  357. DWORD CbLoadLeObject(const o32_obj *pobj, const o32_map *rgmap, BYTE **ppb)
  358. {
  359. *ppb = NULL;
  360. DWORD cb = O32_SIZE(*pobj);
  361. if (cb == 0) {
  362. return(0);
  363. }
  364. DWORD cmap = O32_MAPSIZE(*pobj);
  365. if (cmap == 0) {
  366. return(0);
  367. }
  368. DWORD cbAlloc = (cb + E32_PAGESIZE(exe) - 1) & ~(E32_PAGESIZE(exe) - 1);
  369. BYTE *pb = *ppb = (BYTE *) PvAllocZ(cbAlloc);
  370. #ifdef DUMPLX
  371. if (dft == dftLX) {
  372. LoadLxObject(pobj, (o32_map_lx *) rgmap, pb);
  373. return(cb);
  374. }
  375. #endif // DUMPLX
  376. const o32_map *pmap = rgmap + O32_PAGEMAP(*pobj) - 1;
  377. for (DWORD imap = 0; imap < cmap; imap++, pmap++, pb += E32_PAGESIZE(exe)) {
  378. DWORD ippage = GETPAGEIDX(*pmap);
  379. if (ippage == 0) {
  380. continue;
  381. }
  382. if (PAGEFLAGS(*pmap) != VALID) {
  383. continue;
  384. }
  385. DWORD fo = E32_DATAPAGE(exe) + (ippage - 1) * E32_PAGESIZE(exe);
  386. if (FileSeek(FileReadHandle, fo, SEEK_SET) == -1) {
  387. Error(NULL, CANTSEEKFILE, fo);
  388. }
  389. DWORD cbPage = E32_PAGESIZE(exe);
  390. if (ippage == E32_MPAGES(exe)) {
  391. cbPage = E32_LASTPAGESIZE(exe);
  392. }
  393. FileRead(FileReadHandle, pb, cbPage);
  394. }
  395. return(cb);
  396. }
  397. void DumpLeSections(void)
  398. {
  399. InternalError.Phase = "DumpLeSections";
  400. o32_obj *rgobj = (o32_obj *) PvAlloc(E32_OBJCNT(exe) * sizeof(o32_obj));
  401. FileSeek(FileReadHandle, foHdr + E32_OBJTAB(exe), SEEK_SET);
  402. FileRead(FileReadHandle, rgobj, E32_OBJCNT(exe) * sizeof(o32_obj));
  403. size_t cbMap = E32_MPAGES(exe) * sizeof(o32_map);
  404. #ifdef DUMPLX
  405. if (dft == dftLX) {
  406. cbMap = E32_MPAGES(exe) * sizeof(o32_map_lx);
  407. }
  408. #endif // DUMPLX
  409. o32_map *rgmap = (o32_map *) PvAlloc(cbMap);
  410. FileSeek(FileReadHandle, foHdr + E32_OBJMAP(exe), SEEK_SET);
  411. FileRead(FileReadHandle, rgmap, cbMap);
  412. const o32_obj *pobj = rgobj;
  413. for (size_t iobj = 1; iobj <= E32_OBJCNT(exe); iobj++, pobj++) {
  414. if (Switch.Dump.Headers) {
  415. DumpLeObjectHeader(iobj, pobj);
  416. if (O32_MAPSIZE(*pobj) != 0) {
  417. DumpLePageMap(iobj, pobj, rgmap);
  418. }
  419. }
  420. BOOL fDisasm = Switch.Dump.Disasm && (O32_FLAGS(*pobj) & OBJEXEC);
  421. BOOL fRawData = Switch.Dump.RawData;
  422. if (fDisasm || fRawData) {
  423. BYTE *pbRawData;
  424. DWORD cbRawData = CbLoadLeObject(pobj, rgmap, &pbRawData);
  425. if (cbRawData != 0) {
  426. BOOL f16Bit = FALSE;
  427. DWORD addr = O32_BASE(*pobj);
  428. if ((O32_FLAGS(*pobj) & OBJALIAS16) != 0) {
  429. f16Bit = TRUE;
  430. addr = ((DWORD) iobj) << 16;
  431. }
  432. if (fDisasm) {
  433. fputc('\n', InfoStream);
  434. DisasmBuffer(IMAGE_FILE_MACHINE_I386,
  435. f16Bit,
  436. addr,
  437. pbRawData,
  438. cbRawData,
  439. NULL,
  440. 0,
  441. 0,
  442. InfoStream);
  443. }
  444. if (fRawData) {
  445. fprintf(InfoStream, "\nRAW DATA #%hX\n", iobj);
  446. DumpRawData(addr, pbRawData, cbRawData);
  447. }
  448. }
  449. FreePv(pbRawData);
  450. }
  451. }
  452. FreePv(rgmap);
  453. FreePv(rgobj);
  454. }
  455. void DumpLeFile(const char *szFilename)
  456. {
  457. foHdr = FileSeek(FileReadHandle, -(LONG) sizeof(DWORD), SEEK_CUR);
  458. FileRead(FileReadHandle, &exe, sizeof(exe));
  459. const char *szType;
  460. if ((E32_OS(exe) == 4 /* NE_DEV386 */) &&
  461. (E32_MFLAGS(exe) & E32NOTP) &&
  462. (((E32_MFLAGS(exe) & E32MODMASK) == E32MODVDEV) ||
  463. ((E32_MFLAGS(exe) & E32MODMASK) == E32MODVDEVDYN))) {
  464. szType = "VXD";
  465. } else {
  466. szType = "LE Executable";
  467. }
  468. #ifdef DUMPLX
  469. if (dft == dftLX) {
  470. szType = "LX Executable";
  471. }
  472. #endif // DUMPLX
  473. fprintf(InfoStream, "\nFile Type: %s\n", szType);
  474. if (Switch.Dump.Headers) {
  475. fprintf(InfoStream,
  476. "\n"
  477. "%8hX magic number\n"
  478. "%8hX byte order\n"
  479. "%8hX word order\n"
  480. "%8lX executable format level\n"
  481. "%8hX CPU type (**)\n"
  482. "%8hX operating system (**)\n"
  483. "%8lX module version\n"
  484. "%8lX module flags\n"
  485. "%8lX number of memory pages\n"
  486. "%8lX object number of entry point\n"
  487. "%8lX offset of entry point\n"
  488. "%8lX object number of stack\n"
  489. "%8lX offset of stack\n"
  490. "%8lX memory page size\n",
  491. (E32_MAGIC2(exe) << 8) + E32_MAGIC1(exe),
  492. E32_BORDER(exe),
  493. E32_WORDER(exe),
  494. E32_LEVEL(exe),
  495. E32_CPU(exe),
  496. E32_OS(exe),
  497. E32_VER(exe),
  498. E32_MFLAGS(exe),
  499. E32_MPAGES(exe),
  500. E32_STARTOBJ(exe),
  501. E32_EIP(exe),
  502. E32_STACKOBJ(exe),
  503. E32_ESP(exe),
  504. E32_PAGESIZE(exe));
  505. fprintf(InfoStream,
  506. #ifdef DUMPLX
  507. (dft == dftLX) ?
  508. "%8lX page alignment shift\n" :
  509. #endif // DUMPLX
  510. "%8lX bytes on last page\n",
  511. E32_LASTPAGESIZE(exe));
  512. fprintf(InfoStream,
  513. "%8lX fixup section size\n"
  514. "%8lX fixup section checksum\n"
  515. "%8lX loader section size\n"
  516. "%8lX loader section checksum\n"
  517. "%8lX object table\n"
  518. "%8lX object table entries\n"
  519. "%8lX object map\n"
  520. "%8lX iterated data map\n"
  521. "%8lX resource table\n"
  522. "%8lX resource table entries\n"
  523. "%8lX resident names table\n"
  524. "%8lX entry table\n"
  525. "%8lX module directives table\n"
  526. "%8lX module directives entries\n"
  527. "%8lX fixup page table\n"
  528. "%8lX fixup record table\n"
  529. "%8lX imported modules name table\n"
  530. "%8lX imported modules\n"
  531. "%8lX imported procedures name table\n"
  532. "%8lX page checksum table\n"
  533. "%8lX enumerated data pages\n"
  534. "%8lX preload page count\n"
  535. "%8lX non-resident name table\n"
  536. "%8lX non-resident name table size\n"
  537. "%8lX non-resident name checksum\n"
  538. "%8lX automatic data object\n"
  539. "%8lX debug information\n"
  540. "%8lX debug information size\n"
  541. "%8lX preload instance page count\n"
  542. "%8lX demand instance page count\n"
  543. "%8lX extra heap allocation\n",
  544. E32_FIXUPSIZE(exe),
  545. E32_FIXUPSUM(exe),
  546. E32_LDRSIZE(exe),
  547. E32_LDRSUM(exe),
  548. E32_OBJTAB(exe),
  549. E32_OBJCNT(exe),
  550. E32_OBJMAP(exe),
  551. E32_ITERMAP(exe),
  552. E32_RSRCTAB(exe),
  553. E32_RSRCCNT(exe),
  554. E32_RESTAB(exe),
  555. E32_ENTTAB(exe),
  556. E32_DIRTAB(exe),
  557. E32_DIRCNT(exe),
  558. E32_FPAGETAB(exe),
  559. E32_FRECTAB(exe),
  560. E32_IMPMOD(exe),
  561. E32_IMPMODCNT(exe),
  562. E32_IMPPROC(exe),
  563. E32_PAGESUM(exe),
  564. E32_DATAPAGE(exe),
  565. E32_PRELOAD(exe),
  566. E32_NRESTAB(exe),
  567. E32_CBNRESTAB(exe),
  568. E32_NRESSUM(exe),
  569. E32_AUTODATA(exe),
  570. E32_DEBUGINFO(exe),
  571. E32_DEBUGLEN(exe),
  572. E32_INSTPRELOAD(exe),
  573. E32_INSTDEMAND(exe),
  574. E32_HEAPSIZE(exe));
  575. BOOL fVXD = (E32_OS(exe) == 4 /* NE_DEV386 */) &&
  576. (E32_MFLAGS(exe) & E32MODDLL);
  577. #ifdef DUMPLX
  578. if (dft == dftLX) {
  579. fVXD = FALSE;
  580. }
  581. #endif // DUMPLX
  582. if (fVXD) {
  583. fprintf(InfoStream,
  584. "%8lX offset of Windows resources\n"
  585. "%8lX size of Windows resources\n"
  586. "%8hX device id\n"
  587. "%8hX DDK version\n",
  588. exe.e32_winresoff,
  589. exe.e32_winreslen,
  590. exe.Dev386_Device_ID,
  591. exe.Dev386_DDK_Version);
  592. }
  593. }
  594. DumpLeSections();
  595. }