Source code of Windows XP (NT5)
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.

1102 lines
32 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. peext.c
  5. Abstract:
  6. This module contains the PE dump extensions
  7. Author:
  8. Kent Forschmiedt (kentf) 10-May-1995
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include <time.h>
  14. // STYP_ flags values for MIPS ROM images
  15. #define STYP_REG 0x00000000
  16. #define STYP_TEXT 0x00000020
  17. #define STYP_INIT 0x80000000
  18. #define STYP_RDATA 0x00000100
  19. #define STYP_DATA 0x00000040
  20. #define STYP_LIT8 0x08000000
  21. #define STYP_LIT4 0x10000000
  22. #define STYP_SDATA 0x00000200
  23. #define STYP_SBSS 0x00000080
  24. #define STYP_BSS 0x00000400
  25. #define STYP_LIB 0x40000000
  26. #define STYP_UCODE 0x00000800
  27. #define S_NRELOC_OVFL 0x20000000
  28. #define IMAGE_SCN_MEM_SYSHEAP 0x00010000 // Obsolete
  29. #define IMAGE_SCN_MEM_PROTECTED 0x00004000 // Obsolete
  30. const static char * const MachineName[] = {
  31. "Unknown",
  32. "i386",
  33. "Alpha AXP",
  34. "Alpha AXP64",
  35. "Intel IA64",
  36. };
  37. const static char * const SubsystemName[] = {
  38. "Unknown",
  39. "Native",
  40. "Windows GUI",
  41. "Windows CUI",
  42. "Posix CUI",
  43. };
  44. const static char * const DirectoryEntryName[] = {
  45. "Export",
  46. "Import",
  47. "Resource",
  48. "Exception",
  49. "Security",
  50. "Base Relocation",
  51. "Debug",
  52. "Description",
  53. "Special",
  54. "Thread Storage",
  55. "Load Configuration",
  56. "Bound Import",
  57. "Import Address Table",
  58. "Reserved",
  59. "Reserved",
  60. "Reserved",
  61. 0
  62. };
  63. typedef enum DFT
  64. {
  65. dftUnknown,
  66. dftObject,
  67. dftPE,
  68. dftROM,
  69. dftDBG,
  70. dftPEF,
  71. } DFT;
  72. typedef struct NB10I // NB10 debug info
  73. {
  74. DWORD nb10; // NB10
  75. DWORD off; // offset, always 0
  76. DWORD sig;
  77. DWORD age;
  78. } NB10I;
  79. IMAGE_NT_HEADERS ImageNtHeaders;
  80. PIMAGE_FILE_HEADER ImageFileHdr;
  81. PIMAGE_OPTIONAL_HEADER ImageOptionalHdr;
  82. PIMAGE_SECTION_HEADER SectionHdrs;
  83. ULONG64 Base;
  84. ULONG64 ImageNtHeadersAddr, ImageFileHdrAddr, ImageOptionalHdrAddr, SectionHdrsAddr;
  85. DFT dft;
  86. VOID
  87. DumpHeaders (
  88. VOID
  89. );
  90. VOID
  91. DumpSections(
  92. VOID
  93. );
  94. BOOL
  95. TranslateFilePointerToVirtualAddress(
  96. IN ULONG64 FilePointer,
  97. OUT PULONG64 VirtualAddress
  98. );
  99. VOID
  100. DumpImage(
  101. ULONG64 xBase,
  102. BOOL DoHeaders,
  103. BOOL DoSections
  104. );
  105. VOID
  106. ImageExtension(
  107. IN PSTR lpArgs
  108. );
  109. DECLARE_API( dh )
  110. {
  111. INIT_API();
  112. ImageExtension( (PSTR)args );
  113. EXIT_API();
  114. return S_OK;
  115. }
  116. VOID
  117. ImageExtension(
  118. IN PSTR lpArgs
  119. )
  120. {
  121. BOOL DoAll;
  122. BOOL DoSections;
  123. BOOL DoHeaders;
  124. CHAR c;
  125. PCHAR p;
  126. ULONG64 xBase;
  127. //
  128. // Evaluate the argument string to get the address of the
  129. // image to dump.
  130. //
  131. DoAll = TRUE;
  132. DoHeaders = FALSE;
  133. DoSections = FALSE;
  134. xBase = 0;
  135. while (*lpArgs) {
  136. while (isspace(*lpArgs)) {
  137. lpArgs++;
  138. }
  139. if (*lpArgs == '/' || *lpArgs == '-') {
  140. // process switch
  141. switch (*++lpArgs) {
  142. case 'a': // dump everything we can
  143. case 'A':
  144. ++lpArgs;
  145. DoAll = TRUE;
  146. break;
  147. default: // invalid switch
  148. case 'h': // help
  149. case 'H':
  150. case '?':
  151. dprintf("Usage: dh [options] address\n");
  152. dprintf("\n");
  153. dprintf("Dumps headers from an image based at address.\n");
  154. dprintf("\n");
  155. dprintf("Options:\n");
  156. dprintf("\n");
  157. dprintf(" -a Dump everything\n");
  158. dprintf(" -f Dump file headers\n");
  159. dprintf(" -s Dump section headers\n");
  160. dprintf("\n");
  161. return;
  162. case 'f':
  163. case 'F':
  164. ++lpArgs;
  165. DoAll = FALSE;
  166. DoHeaders = TRUE;
  167. break;
  168. case 's':
  169. case 'S':
  170. ++lpArgs;
  171. DoAll = FALSE;
  172. DoSections = TRUE;
  173. break;
  174. }
  175. } else if (*lpArgs) {
  176. if (xBase != 0) {
  177. dprintf("Invalid extra argument\n");
  178. return;
  179. }
  180. p = lpArgs;
  181. while (*p && !isspace(*p)) {
  182. p++;
  183. }
  184. c = *p;
  185. *p = 0;
  186. xBase = GetExpression(lpArgs);
  187. *p = c;
  188. lpArgs=p;
  189. }
  190. }
  191. if ( !xBase ) {
  192. return;
  193. }
  194. DumpImage(xBase, DoAll || DoHeaders, DoAll || DoSections);
  195. }
  196. VOID
  197. DumpImage(
  198. ULONG64 xBase,
  199. BOOL DoHeaders,
  200. BOOL DoSections
  201. )
  202. {
  203. IMAGE_DOS_HEADER DosHeader;
  204. ULONG cb;
  205. ULONG64 Offset;
  206. BOOL Ok;
  207. Base = xBase;
  208. Ok = ReadMemory(Base, &DosHeader, sizeof(DosHeader), &cb);
  209. if (!Ok) {
  210. dprintf("Can't read file header: error == %d\n", GetLastError());
  211. return;
  212. }
  213. if (cb != sizeof(DosHeader) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
  214. dprintf("No file header.\n");
  215. return;
  216. }
  217. Offset = Base + DosHeader.e_lfanew;
  218. Ok = ReadMemory(Offset, &ImageNtHeaders, sizeof(ImageNtHeaders), &cb);
  219. ImageNtHeadersAddr = Offset;
  220. if (!Ok) {
  221. dprintf("Can't read optional header: error == %d\n", GetLastError());
  222. return;
  223. }
  224. if (InitTypeRead(ImageNtHeadersAddr, IMAGE_NT_HEADERS)) {
  225. dprintf("Bad file header.\n");
  226. return;
  227. }
  228. ImageFileHdr = &ImageNtHeaders.FileHeader;
  229. ImageFileHdrAddr = ReadField(FileHeader);
  230. ImageOptionalHdr = &ImageNtHeaders.OptionalHeader;
  231. ImageOptionalHdrAddr = ReadField(OptionalHeader);
  232. if ((ULONG) ReadField(FileHeader.SizeOfOptionalHeader) == GetTypeSize("IMAGE_ROM_OPTIONAL_HEADER")) {
  233. dft = dftROM;
  234. } else if (ImageFileHdr->Characteristics & IMAGE_FILE_DLL) {
  235. dft = dftPE;
  236. } else if (ImageFileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) {
  237. dft = dftPE;
  238. } else if (ImageFileHdr->SizeOfOptionalHeader == 0) {
  239. dft = dftObject;
  240. } else {
  241. dft = dftUnknown;
  242. }
  243. if (DoHeaders) {
  244. DumpHeaders();
  245. }
  246. if (DoSections) {
  247. ULONG SectSize, NumSections;
  248. SectSize = GetTypeSize("IMAGE_SECTION_HEADER");
  249. InitTypeRead(ImageFileHdrAddr, IMAGE_FILE_HEADER);
  250. SectionHdrs = (PIMAGE_SECTION_HEADER) malloc((NumSections =(ULONG) ReadField(NumberOfSections) )*
  251. SectSize);
  252. try {
  253. SectionHdrsAddr = Offset + GetTypeSize("IMAGE_NT_HEADERS") +
  254. ReadField(SizeOfOptionalHeader) - GetTypeSize("IMAGE_OPTIONAL_HEADER");
  255. Ok = ReadMemory(
  256. SectionHdrsAddr,
  257. SectionHdrs,
  258. (NumSections) * SectSize,
  259. &cb);
  260. if (!Ok) {
  261. dprintf("Can't read section headers.\n");
  262. } else {
  263. if (cb != NumSections * SectSize) {
  264. dprintf("\n***\n*** Some section headers may be missing ***\n***\n\n");
  265. NumSections = (USHORT)(cb / SectSize);
  266. }
  267. DumpSections( );
  268. }
  269. }
  270. finally {
  271. if (SectionHdrs) {
  272. free(SectionHdrs);
  273. SectionHdrs = 0;
  274. }
  275. }
  276. }
  277. }
  278. VOID
  279. DumpHeaders (
  280. VOID
  281. )
  282. /*++
  283. Routine Description:
  284. Formats the file header and optional header.
  285. Arguments:
  286. None.
  287. Return Value:
  288. None.
  289. --*/
  290. {
  291. int i, j;
  292. const char *time;
  293. const char *name;
  294. DWORD dw;
  295. ULONG TimeDateStamp, SizeOfOptionalHeader, DirOff, DirSize;
  296. InitTypeRead(ImageFileHdrAddr, IMAGE_FILE_HEADER);
  297. // Print out file type
  298. switch (dft) {
  299. case dftObject :
  300. dprintf("\nFile Type: COFF OBJECT\n");
  301. break;
  302. case dftPE :
  303. if (ReadField(Characteristics) & IMAGE_FILE_DLL) {
  304. dprintf("\nFile Type: DLL\n");
  305. } else {
  306. dprintf("\nFile Type: EXECUTABLE IMAGE\n");
  307. }
  308. break;
  309. case dftROM :
  310. dprintf("\nFile Type: ROM IMAGE\n");
  311. break;
  312. default :
  313. dprintf("\nFile Type: UNKNOWN\n");
  314. break;
  315. }
  316. switch (ReadField(Machine)) {
  317. case IMAGE_FILE_MACHINE_I386 : i = 1; break;
  318. case IMAGE_FILE_MACHINE_ALPHA : i = 2; break;
  319. case IMAGE_FILE_MACHINE_ALPHA64 : i = 3; break;
  320. case IMAGE_FILE_MACHINE_IA64 : i = 4; break;
  321. default : i = 0;
  322. }
  323. dprintf(
  324. "FILE HEADER VALUES\n"
  325. "%8hX machine (%s)\n"
  326. "%8hX number of sections\n"
  327. "%8lX time date stamp",
  328. (ULONG) ReadField(Machine),
  329. MachineName[i],
  330. (ULONG) ReadField(NumberOfSections),
  331. TimeDateStamp = (ULONG) ReadField(TimeDateStamp));
  332. if ((time = ctime((time_t *) &TimeDateStamp)) != NULL) {
  333. dprintf( " %s", time);
  334. }
  335. dprintf("\n");
  336. dprintf(
  337. "%8lX file pointer to symbol table\n"
  338. "%8lX number of symbols\n"
  339. "%8hX size of optional header\n"
  340. "%8hX characteristics\n",
  341. (ULONG) ReadField(PointerToSymbolTable),
  342. (ULONG) ReadField(NumberOfSymbols),
  343. SizeOfOptionalHeader = (ULONG) ReadField(SizeOfOptionalHeader),
  344. (ULONG) ReadField(Characteristics));
  345. for (dw = (ULONG) ReadField(Characteristics), j = 0; dw; dw >>= 1, j++) {
  346. if (dw & 1) {
  347. switch (1 << j) {
  348. case IMAGE_FILE_RELOCS_STRIPPED : name = "Relocations stripped"; break;
  349. case IMAGE_FILE_EXECUTABLE_IMAGE : name = "Executable"; break;
  350. case IMAGE_FILE_LINE_NUMS_STRIPPED : name = "Line numbers stripped"; break;
  351. case IMAGE_FILE_LOCAL_SYMS_STRIPPED : name = "Symbols stripped"; break;
  352. case IMAGE_FILE_BYTES_REVERSED_LO : name = "Bytes reversed"; break;
  353. case IMAGE_FILE_32BIT_MACHINE : name = "32 bit word machine"; break;
  354. case IMAGE_FILE_DEBUG_STRIPPED : name = "Debug information stripped"; break;
  355. case IMAGE_FILE_SYSTEM : name = "System"; break;
  356. case IMAGE_FILE_DLL : name = "DLL"; break;
  357. case IMAGE_FILE_BYTES_REVERSED_HI : name = ""; break;
  358. default : name = "RESERVED - UNKNOWN";
  359. }
  360. if (*name) {
  361. dprintf( " %s\n", name);
  362. }
  363. }
  364. }
  365. if (SizeOfOptionalHeader != 0) {
  366. char szLinkerVersion[30];
  367. ULONG Ptr64 = IsPtr64();
  368. InitTypeRead(ImageOptionalHdrAddr, IMAGE_OPTIONAL_HEADER);
  369. sprintf(szLinkerVersion,
  370. "%u.%02u",
  371. (ULONG) ReadField(MajorLinkerVersion),
  372. (ULONG) ReadField(MinorLinkerVersion));
  373. dprintf(
  374. "\n"
  375. "OPTIONAL HEADER VALUES\n"
  376. "%8hX magic #\n"
  377. "%8s linker version\n"
  378. "%8lX size of code\n"
  379. "%8lX size of initialized data\n"
  380. "%8lX size of uninitialized data\n"
  381. "%8P address of entry point\n"
  382. "%8P base of code\n"
  383. ,
  384. (ULONG) ReadField(Magic),
  385. szLinkerVersion,
  386. (ULONG) ReadField(SizeOfCode),
  387. (ULONG) ReadField(SizeOfInitializedData),
  388. (ULONG) ReadField(SizeOfUninitializedData),
  389. ReadField(AddressOfEntryPoint),
  390. ReadField(BaseOfCode)
  391. );
  392. if (Ptr64) {
  393. dprintf("%8P base of data\n",
  394. ReadField(BaseOfData));
  395. }
  396. }
  397. if (dft == dftROM) {
  398. PIMAGE_ROM_OPTIONAL_HEADER romOptionalHdr;
  399. InitTypeRead(ImageOptionalHdrAddr, IMAGE_ROM_OPTIONAL_HEADER);
  400. // romOptionalHdr = (PIMAGE_ROM_OPTIONAL_HEADER) &ImageOptionalHdr;
  401. dprintf(
  402. " ----- rom -----\n"
  403. "%8lX base of bss\n"
  404. "%8lX gpr mask\n"
  405. " cpr mask\n"
  406. " %08lX %08lX %08lX %08lX\n"
  407. "%8hX gp value\n",
  408. (ULONG) ReadField(BaseOfBss),
  409. (ULONG) ReadField(GprMask),
  410. (ULONG) ReadField(CprMask[0]),
  411. (ULONG) ReadField(CprMask[1]),
  412. (ULONG) ReadField(CprMask[2]),
  413. (ULONG) ReadField(CprMask[3]),
  414. (ULONG) ReadField(GpValue));
  415. }
  416. if (SizeOfOptionalHeader == GetTypeSize("IMAGE_OPTIONAL_HEADER")) {
  417. char szOSVersion[30];
  418. char szImageVersion[30];
  419. char szSubsystemVersion[30];
  420. InitTypeRead(ImageOptionalHdrAddr, IMAGE_OPTIONAL_HEADER);
  421. switch ((ULONG) ReadField(Subsystem)) {
  422. case IMAGE_SUBSYSTEM_POSIX_CUI : i = 4; break;
  423. case IMAGE_SUBSYSTEM_WINDOWS_CUI : i = 3; break;
  424. case IMAGE_SUBSYSTEM_WINDOWS_GUI : i = 2; break;
  425. case IMAGE_SUBSYSTEM_NATIVE : i = 1; break;
  426. default : i = 0;
  427. }
  428. sprintf(szOSVersion,
  429. "%hu.%02hu",
  430. (USHORT) ReadField(MajorOperatingSystemVersion),
  431. (USHORT) ReadField(MinorOperatingSystemVersion));
  432. sprintf(szImageVersion,
  433. "%hu.%02hu",
  434. (USHORT) ReadField(MajorImageVersion),
  435. (USHORT) ReadField(MinorImageVersion));
  436. sprintf(szSubsystemVersion,
  437. "%hu.%02hu",
  438. (USHORT) ReadField(MajorSubsystemVersion),
  439. (USHORT) ReadField(MinorSubsystemVersion));
  440. dprintf(
  441. " ----- new -----\n"
  442. "%p image base\n"
  443. "%8lX section alignment\n"
  444. "%8lX file alignment\n"
  445. "%8hX subsystem (%s)\n"
  446. "%8s operating system version\n"
  447. "%8s image version\n"
  448. "%8s subsystem version\n",
  449. ReadField(ImageBase),
  450. (ULONG) ReadField(SectionAlignment),
  451. (ULONG) ReadField(FileAlignment),
  452. (USHORT) ReadField(Subsystem),
  453. SubsystemName[i],
  454. szOSVersion,
  455. szImageVersion,
  456. szSubsystemVersion);
  457. dprintf(
  458. "%8lX size of image\n"
  459. "%8lX size of headers\n"
  460. "%8lX checksum\n"
  461. "%p size of stack reserve\n"
  462. "%p size of stack commit\n"
  463. "%p size of heap reserve\n"
  464. "%p size of heap commit\n",
  465. (ULONG) ReadField(SizeOfImage),
  466. (ULONG) ReadField(SizeOfHeaders),
  467. (ULONG) ReadField(CheckSum),
  468. ReadField(SizeOfStackReserve),
  469. ReadField(SizeOfStackCommit),
  470. ReadField(SizeOfHeapReserve),
  471. ReadField(SizeOfHeapCommit));
  472. dprintf("%p Opt Hdr\n", ImageOptionalHdrAddr);
  473. GetFieldOffset("IMAGE_OPTIONAL_HEADER", "DataDirectory", &DirOff);
  474. DirSize = GetTypeSize("IMAGE_DATA_DIRECTORY");
  475. for (i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  476. if (!DirectoryEntryName[i]) {
  477. break;
  478. }
  479. InitTypeRead(ImageOptionalHdrAddr + DirOff + i*DirSize, IMAGE_DATA_DIRECTORY);
  480. dprintf( "%8P [%8lX] address [size] of %s Directory\n",
  481. ReadField(VirtualAddress),
  482. (ULONG) ReadField(Size),
  483. DirectoryEntryName[i]
  484. );
  485. }
  486. dprintf( "\n" );
  487. }
  488. }
  489. VOID
  490. DumpSectionHeader (
  491. IN DWORD i,
  492. IN ULONG64 Sh
  493. )
  494. {
  495. const char *name;
  496. char *szUnDName;
  497. DWORD li, lj;
  498. WORD memFlags;
  499. CHAR Name[40];
  500. InitTypeRead(Sh, IMAGE_SECTION_HEADER);
  501. GetFieldValue(Sh, "IMAGE_SECTION_HEADER", "Name", Name);
  502. dprintf("\nSECTION HEADER #%hX\n%8.8s name", i, Name);
  503. #if 0
  504. if (Sh->Name[0] == '/') {
  505. name = SzObjSectionName((char *) Sh->Name, (char *) DumpStringTable);
  506. dprintf(" (%s)", name);
  507. }
  508. #endif
  509. dprintf( "\n");
  510. dprintf( "%8P %s\n"
  511. "%8lX virtual address\n"
  512. "%8lX size of raw data\n"
  513. "%8lX file pointer to raw data\n"
  514. "%8lX file pointer to relocation table\n",
  515. ReadField(Misc.PhysicalAddress),
  516. (dft == dftObject) ? "physical address" : "virtual size",
  517. (ULONG) ReadField(VirtualAddress),
  518. (ULONG) ReadField(SizeOfRawData),
  519. (ULONG) ReadField(PointerToRawData),
  520. (ULONG) ReadField(PointerToRelocations));
  521. dprintf( "%8lX file pointer to line numbers\n"
  522. "%8hX number of relocations\n"
  523. "%8hX number of line numbers\n"
  524. "%8lX flags\n",
  525. (ULONG) ReadField(PointerToLinenumbers),
  526. (ULONG) ReadField(NumberOfRelocations),
  527. (ULONG) ReadField(NumberOfLinenumbers),
  528. (ULONG) ReadField(Characteristics));
  529. memFlags = 0;
  530. li = (ULONG) ReadField(Characteristics);
  531. if (dft == dftROM) {
  532. for (lj = 0L; li; li = li >> 1, lj++) {
  533. if (li & 1) {
  534. switch ((li & 1) << lj) {
  535. case STYP_REG : name = "Regular"; break;
  536. case STYP_TEXT : name = "Text"; memFlags = 1; break;
  537. case STYP_INIT : name = "Init Code"; memFlags = 1; break;
  538. case STYP_RDATA : name = "Data"; memFlags = 2; break;
  539. case STYP_DATA : name = "Data"; memFlags = 6; break;
  540. case STYP_LIT8 : name = "Literal 8"; break;
  541. case STYP_LIT4 : name = "Literal 4"; break;
  542. case STYP_SDATA : name = "GP Init Data"; memFlags = 6; break;
  543. case STYP_SBSS : name = "GP Uninit Data"; memFlags = 6; break;
  544. case STYP_BSS : name = "Uninit Data"; memFlags = 6; break;
  545. case STYP_LIB : name = "Library"; break;
  546. case STYP_UCODE : name = "UCode"; break;
  547. case S_NRELOC_OVFL : name = "Non-Relocatable overlay"; memFlags = 1; break;
  548. default : name = "RESERVED - UNKNOWN";
  549. }
  550. dprintf( " %s\n", name);
  551. }
  552. }
  553. } else {
  554. // Clear the padding bits
  555. li &= ~0x00700000;
  556. for (lj = 0L; li; li = li >> 1, lj++) {
  557. if (li & 1) {
  558. switch ((li & 1) << lj) {
  559. case IMAGE_SCN_TYPE_NO_PAD : name = "No Pad"; break;
  560. case IMAGE_SCN_CNT_CODE : name = "Code"; break;
  561. case IMAGE_SCN_CNT_INITIALIZED_DATA : name = "Initialized Data"; break;
  562. case IMAGE_SCN_CNT_UNINITIALIZED_DATA : name = "Uninitialized Data"; break;
  563. case IMAGE_SCN_LNK_OTHER : name = "Other"; break;
  564. case IMAGE_SCN_LNK_INFO : name = "Info"; break;
  565. case IMAGE_SCN_LNK_REMOVE : name = "Remove"; break;
  566. case IMAGE_SCN_LNK_COMDAT : name = "Communal"; break;
  567. case IMAGE_SCN_MEM_DISCARDABLE: name = "Discardable"; break;
  568. case IMAGE_SCN_MEM_NOT_CACHED: name = "Not Cached"; break;
  569. case IMAGE_SCN_MEM_NOT_PAGED: name = "Not Paged"; break;
  570. case IMAGE_SCN_MEM_SHARED : name = "Shared"; break;
  571. case IMAGE_SCN_MEM_EXECUTE : name = ""; memFlags |= 1; break;
  572. case IMAGE_SCN_MEM_READ : name = ""; memFlags |= 2; break;
  573. case IMAGE_SCN_MEM_WRITE : name = ""; memFlags |= 4; break;
  574. case IMAGE_SCN_MEM_FARDATA : name = "Far Data"; break;
  575. case IMAGE_SCN_MEM_SYSHEAP : name = "Sys Heap"; break;
  576. case IMAGE_SCN_MEM_PURGEABLE: name = "Purgeable or 16-Bit"; break;
  577. case IMAGE_SCN_MEM_LOCKED : name = "Locked"; break;
  578. case IMAGE_SCN_MEM_PRELOAD : name = "Preload"; break;
  579. case IMAGE_SCN_MEM_PROTECTED: name = "Protected"; break;
  580. default : name = "RESERVED - UNKNOWN";
  581. }
  582. if (*name) {
  583. dprintf( " %s\n", name);
  584. }
  585. }
  586. }
  587. // print alignment
  588. switch ((ULONG) ReadField(Characteristics) & 0x00700000) {
  589. default: name = "(no align specified)"; break;
  590. case IMAGE_SCN_ALIGN_1BYTES: name = "1 byte align"; break;
  591. case IMAGE_SCN_ALIGN_2BYTES: name = "2 byte align"; break;
  592. case IMAGE_SCN_ALIGN_4BYTES: name = "4 byte align"; break;
  593. case IMAGE_SCN_ALIGN_8BYTES: name = "8 byte align"; break;
  594. case IMAGE_SCN_ALIGN_16BYTES: name = "16 byte align"; break;
  595. case IMAGE_SCN_ALIGN_32BYTES: name = "32 byte align"; break;
  596. case IMAGE_SCN_ALIGN_64BYTES: name = "64 byte align"; break;
  597. }
  598. dprintf( " %s\n", name);
  599. }
  600. if (memFlags) {
  601. switch(memFlags) {
  602. case 1 : name = "Execute Only"; break;
  603. case 2 : name = "Read Only"; break;
  604. case 3 : name = "Execute Read"; break;
  605. case 4 : name = "Write Only"; break;
  606. case 5 : name = "Execute Write"; break;
  607. case 6 : name = "Read Write"; break;
  608. case 7 : name = "Execute Read Write"; break;
  609. default : name = "Unknown Memory Flags"; break;
  610. }
  611. dprintf( " %s\n", name);
  612. }
  613. }
  614. VOID
  615. DumpDebugDirectory (
  616. IN ULONG64 DebugDir
  617. )
  618. {
  619. BOOL Ok;
  620. DWORD cb;
  621. NB10I nb10i;
  622. PIMAGE_DEBUG_MISC miscData;
  623. PIMAGE_DEBUG_MISC miscDataCur;
  624. ULONG64 VirtualAddress;
  625. DWORD len;
  626. InitTypeRead(DebugDir, IMAGE_DEBUG_DIRECTORY );
  627. switch ((ULONG) ReadField(Type)){
  628. case IMAGE_DEBUG_TYPE_COFF:
  629. dprintf( "\tcoff ");
  630. break;
  631. case IMAGE_DEBUG_TYPE_CODEVIEW:
  632. dprintf( "\tcv ");
  633. break;
  634. case IMAGE_DEBUG_TYPE_FPO:
  635. dprintf( "\tfpo ");
  636. break;
  637. case IMAGE_DEBUG_TYPE_MISC:
  638. dprintf( "\tmisc ");
  639. break;
  640. case IMAGE_DEBUG_TYPE_FIXUP:
  641. dprintf( "\tfixup ");
  642. break;
  643. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  644. dprintf( "\t-> src ");
  645. break;
  646. case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  647. dprintf( "\tsrc -> ");
  648. break;
  649. case IMAGE_DEBUG_TYPE_EXCEPTION:
  650. dprintf( "\tpdata ");
  651. break;
  652. default:
  653. dprintf( "\t(%6lu)", (ULONG) ReadField(Type));
  654. break;
  655. }
  656. dprintf( "%8x %8x %8x",
  657. (ULONG) ReadField(SizeOfData),
  658. (ULONG) ReadField(AddressOfRawData),
  659. (ULONG) ReadField(PointerToRawData));
  660. if ((ULONG) ReadField(PointerToRawData) &&
  661. (ULONG) ReadField(Type) == IMAGE_DEBUG_TYPE_MISC)
  662. {
  663. if (!TranslateFilePointerToVirtualAddress(ReadField(PointerToRawData), &VirtualAddress)) {
  664. dprintf(" [Debug data not mapped]\n");
  665. } else {
  666. len = (ULONG) ReadField(SizeOfData);
  667. miscData = (PIMAGE_DEBUG_MISC) malloc(len);
  668. try {
  669. Ok = ReadMemory(Base + VirtualAddress, miscData, len, &cb);
  670. if (!Ok || cb != len) {
  671. dprintf("Can't read debug data\n");
  672. } else {
  673. miscDataCur = miscData;
  674. do {
  675. if (miscDataCur->DataType == IMAGE_DEBUG_MISC_EXENAME) {
  676. if (ImageOptionalHdr->MajorLinkerVersion == 2 &&
  677. ImageOptionalHdr->MinorLinkerVersion < 37) {
  678. dprintf( "\tImage Name: %s", miscDataCur->Reserved);
  679. } else {
  680. dprintf( "\tImage Name: %s", miscDataCur->Data);
  681. }
  682. break;
  683. }
  684. len -= miscDataCur->Length;
  685. miscDataCur = (PIMAGE_DEBUG_MISC) ((PCHAR) miscDataCur + miscData->Length);
  686. } while (len > 0);
  687. }
  688. }
  689. finally {
  690. if (miscData) {
  691. free(miscData);
  692. }
  693. }
  694. }
  695. }
  696. if ((ULONG) ReadField(PointerToRawData) &&
  697. (ULONG) ReadField(Type) == IMAGE_DEBUG_TYPE_CODEVIEW)
  698. {
  699. if (!TranslateFilePointerToVirtualAddress((ULONG) ReadField(PointerToRawData), &VirtualAddress)) {
  700. dprintf(" [Debug data not mapped]\n");
  701. } else {
  702. len = (ULONG) ReadField(SizeOfData);
  703. Ok = ReadMemory(Base + VirtualAddress, &nb10i, sizeof(nb10i), &cb);
  704. if (!Ok || cb != sizeof(nb10i)) {
  705. dprintf("Can't read debug data\n");
  706. } else {
  707. dprintf( "\tFormat: %4.4s", &nb10i.nb10);
  708. if (nb10i.nb10 == '01BN') {
  709. CHAR PdbName[MAX_PATH];
  710. if ((len - sizeof(nb10i) > MAX_PATH))
  711. len = MAX_PATH;
  712. Ok = ReadMemory(Base + VirtualAddress + sizeof(nb10i), PdbName, len-sizeof(nb10i), &cb);
  713. if (!Ok || cb != len-sizeof(nb10i)) {
  714. strcpy(PdbName, "<pdb name unavailable>");
  715. }
  716. dprintf( ", %x, %x, %s", nb10i.sig, nb10i.age, PdbName);
  717. }
  718. }
  719. }
  720. }
  721. dprintf( "\n");
  722. }
  723. VOID
  724. DumpDebugDirectories (
  725. ULONG64 sh
  726. )
  727. /*++
  728. Routine Description:
  729. Print out the contents of all debug directories
  730. Arguments:
  731. sh - Section header for section that contains debug dirs
  732. Return Value:
  733. None.
  734. --*/
  735. {
  736. int numDebugDirs;
  737. IMAGE_DEBUG_DIRECTORY debugDir;
  738. ULONG64 DebugDirAddr;
  739. ULONG64 pc;
  740. ULONG64 VA;
  741. DWORD cb, Sz, DebugDirSize;
  742. BOOL Ok;
  743. Sz = GetTypeSize("IMAGE_DATA_DIRECTORY");
  744. DebugDirSize = GetTypeSize("IMAGE_DEBUG_DIRECTORY");
  745. if (dft == dftROM) {
  746. GetFieldValue(sh, "IMAGE_SECTION_HEADER", "VirtualAddress", VA);
  747. DebugDirAddr = Base + VA;
  748. pc = DebugDirAddr;
  749. if (InitTypeRead(pc, IMAGE_DEBUG_DIRECTORY)) {
  750. dprintf("Can't read debug dir @%p\n", pc);
  751. return;
  752. }
  753. numDebugDirs = 0;
  754. while (ReadField(Type) != 0) {
  755. numDebugDirs++;
  756. pc += DebugDirSize;
  757. if (InitTypeRead(pc, IMAGE_DEBUG_DIRECTORY)) {
  758. break;
  759. }
  760. }
  761. } else {
  762. ULONG Off, DirSize;
  763. GetFieldOffset("IMAGE_OPTIONAL_HEADER", "DataDirectory", &Off);
  764. GetFieldValue(ImageOptionalHdrAddr + Off + Sz*IMAGE_DIRECTORY_ENTRY_DEBUG,
  765. "IMAGE_DATA_DIRECTORY", "VirtualAddress", VA);
  766. GetFieldValue(ImageOptionalHdrAddr + Off + Sz*IMAGE_DIRECTORY_ENTRY_DEBUG,
  767. "IMAGE_DATA_DIRECTORY", "Size", DirSize);
  768. DebugDirAddr = Base + VA; // ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  769. numDebugDirs = DirSize / DebugDirSize;
  770. // dprintf(" DD @%p, DD addr %p\n", ImageOptionalHdrAddr + Off + Sz*IMAGE_DIRECTORY_ENTRY_DEBUG,
  771. // DebugDirAddr);
  772. // ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof(IMAGE_DEBUG_DIRECTORY);
  773. }
  774. dprintf("\n\nDebug Directories(%d)\n",numDebugDirs);
  775. dprintf("\tType Size Address Pointer\n\n");
  776. pc = DebugDirAddr;
  777. while (numDebugDirs) {
  778. if (InitTypeRead(pc, IMAGE_DEBUG_DIRECTORY)) {
  779. dprintf("Can't read debug dir @%p\n", pc);
  780. break;
  781. }
  782. DumpDebugDirectory(pc);
  783. pc += Sz;
  784. numDebugDirs--;
  785. }
  786. }
  787. VOID
  788. DumpSections(
  789. VOID
  790. )
  791. {
  792. ULONG64 sh;
  793. const char *p;
  794. DWORD64 li;
  795. DWORD cb;
  796. BOOL Ok;
  797. ULONG i, j;
  798. CHAR szName[IMAGE_SIZEOF_SHORT_NAME + 1];
  799. ULONG NumberOfSections, SectSize, Characteristics;
  800. GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "NumberOfSections", NumberOfSections);
  801. GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "Characteristics", Characteristics);
  802. SectSize = GetTypeSize("IMAGE_SECTION_HEADER");
  803. for (i = 1; i <= NumberOfSections; i++) {
  804. sh = SectionHdrsAddr + (i-1)*SectSize;
  805. //szName = SzObjSectionName((char *) sh.Name, (char *) DumpStringTable);
  806. GetFieldValue(sh, "IMAGE_SECTION_HEADER", "Name", szName);
  807. // strncpy(szName, (char *) sh.Name, IMAGE_SIZEOF_SHORT_NAME);
  808. szName[IMAGE_SIZEOF_SHORT_NAME] = 0;
  809. DumpSectionHeader(i, sh);
  810. if (dft == dftROM) {
  811. if (!(Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) {
  812. // If we're looking at the .rdata section and the symbols
  813. // aren't stripped, the debug directory must be here.
  814. if (!strcmp(szName, ".rdata")) {
  815. DumpDebugDirectories(sh);
  816. //DumpDebugData(&sh);
  817. }
  818. }
  819. } else if (dft == dftPE) {
  820. UCHAR tmp[40];
  821. ULONG64 VA;
  822. sprintf(tmp, "DataDirectory[%d].VirtualAddress", IMAGE_DIRECTORY_ENTRY_DEBUG);
  823. GetFieldValue(ImageOptionalHdrAddr, "IMAGE_OPTIONAL_HEADER", tmp, li);
  824. // dprintf("Opt Hdr %p, %s = %p", ImageOptionalHdrAddr, tmp, li);
  825. if (li != 0) {
  826. InitTypeRead(sh, IMAGE_SECTION_HEADER);
  827. VA = ReadField(VirtualAddress);
  828. if (li >= VA && li < (VA + ReadField(SizeOfRawData))) {
  829. DumpDebugDirectories(sh);
  830. //DumpDebugData(&sh);
  831. }
  832. }
  833. #if 0
  834. if (Switch.Dump.PData) {
  835. li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
  836. if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) {
  837. DumpFunctionTable(pimage, rgsym, (char *) DumpStringTable, &sh);
  838. }
  839. }
  840. if (Switch.Dump.Imports) {
  841. li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  842. if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) {
  843. DumpImports(&sh);
  844. }
  845. }
  846. if (Switch.Dump.Exports) {
  847. li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  848. if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) {
  849. // UNDONE: Is this check really necessary?
  850. if (ImageFileHdr->Machine != IMAGE_FILE_MACHINE_MPPC_601) {
  851. DumpExports(&sh);
  852. }
  853. }
  854. }
  855. #endif
  856. }
  857. }
  858. }
  859. BOOL
  860. TranslateFilePointerToVirtualAddress(
  861. IN ULONG64 FilePointer,
  862. OUT PULONG64 VirtualAddress
  863. )
  864. {
  865. ULONG i;
  866. ULONG64 sh;
  867. ULONG NumberOfSections, SectSize, Characteristics;
  868. GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "NumberOfSections", NumberOfSections);
  869. GetFieldValue(ImageFileHdrAddr, "IMAGE_FILE_HEADER", "Characteristics", Characteristics);
  870. SectSize = GetTypeSize("IMAGE_SECTION_HEADER");
  871. for (i = 1; i <= NumberOfSections; i++) {
  872. sh = SectionHdrsAddr + (i-1)*SectSize;
  873. InitTypeRead(sh, IMAGE_SECTION_HEADER);
  874. if (ReadField(PointerToRawData) <= FilePointer &&
  875. FilePointer < ReadField(PointerToRawData) + ReadField(SizeOfRawData)) {
  876. *VirtualAddress = FilePointer - ReadField(PointerToRawData) + ReadField(VirtualAddress);
  877. return TRUE;
  878. }
  879. }
  880. return FALSE;
  881. }