Leaked source code of windows server 2003
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.

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