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.

2148 lines
62 KiB

  1. #include "ext.h"
  2. #include "globals.h"
  3. #include <cmnutil.hpp>
  4. // globals
  5. EXT_API_VERSION ExtApiVersion = { (VER_PRODUCTVERSION_W >> 8), (VER_PRODUCTVERSION_W & 0xff), EXT_API_VERSION_NUMBER64, 0 };
  6. WINDBG_EXTENSION_APIS ExtensionApis;
  7. USHORT SavedMajorVersion;
  8. USHORT SavedMinorVersion;
  9. typedef struct {
  10. DWORD64 base;
  11. DWORD64 end;
  12. char name[64];
  13. } LMINFO, *PLMINFO;
  14. typedef struct {
  15. CHAR name[4098];
  16. DWORD64 addr;
  17. CHAR image[4098];
  18. DWORD machine;
  19. USHORT HdrType;
  20. ULONG DebugType;
  21. ULONG64 DebugDataVA;
  22. ULONG nDebugDirs;
  23. ULONG SymType;
  24. time_t TimeDateStamp;
  25. ULONG CheckSum;
  26. ULONG SizeOfImage;
  27. ULONG Characteristics;
  28. ULONG SymLoadError;
  29. BOOL omap;
  30. CHAR PdbFileName[MAX_PATH + 1];
  31. ULONG PdbSrc;
  32. CHAR ImageFileName[MAX_PATH + 1];
  33. ULONG ImageType;
  34. ULONG ImageSrc;
  35. ULONG numsyms;
  36. CVDD cvrec;
  37. } MODULE_INFO, *PMODULE_INFO, *PMODULE_INFOx;
  38. typedef struct _MACHINE_TYPE {
  39. ULONG MachineId;
  40. PCHAR MachineName;
  41. } MACHINE_TYPE;
  42. typedef struct _ERROR_TYPE {
  43. ULONG ErrorVal;
  44. PCHAR Desc;
  45. } ERROR_TYPE;
  46. const ERROR_TYPE SymLoadErrorDesc[] = {
  47. {SYMLOAD_OK, "Symbols loaded successfully"},
  48. {SYMLOAD_PDBUNMATCHED, "Unmatched PDB"},
  49. {SYMLOAD_PDBNOTFOUND, "PDB not found"},
  50. {SYMLOAD_DBGNOTFOUND, "DBG not found"},
  51. {SYMLOAD_OTHERERROR, "Error in load symbols"},
  52. {SYMLOAD_OUTOFMEMORY, "DBGHELP Out of memory"},
  53. {SYMLOAD_HEADERPAGEDOUT, "Image header paged out"},
  54. {(EC_FORMAT << 8), "Unrecognized pdb format"},
  55. {(EC_CORRUPT << 8), "Cvinfo is corrupt"},
  56. {(EC_ACCESS_DENIED << 8), "Pdb read access denied"},
  57. {SYMLOAD_DEFERRED, "No error - symbol load deferred"},
  58. };
  59. MACHINE_TYPE Machines[] = {
  60. {IMAGE_FILE_MACHINE_UNKNOWN, "UNKNOWN"},
  61. {IMAGE_FILE_MACHINE_I386, "I386"},
  62. {IMAGE_FILE_MACHINE_R3000, "R3000"},
  63. {IMAGE_FILE_MACHINE_R4000, "R4000"},
  64. {IMAGE_FILE_MACHINE_R10000, "R10000"},
  65. {IMAGE_FILE_MACHINE_WCEMIPSV2, "WCEMIPSV2"},
  66. {IMAGE_FILE_MACHINE_ALPHA, "ALPHA"},
  67. {IMAGE_FILE_MACHINE_POWERPC, "POWERPC"},
  68. {IMAGE_FILE_MACHINE_POWERPCFP, "POWERPCFP"},
  69. {IMAGE_FILE_MACHINE_SH3, "SH3"},
  70. {IMAGE_FILE_MACHINE_SH3DSP, "SH3DSP"},
  71. {IMAGE_FILE_MACHINE_SH3E, "SH3E"},
  72. {IMAGE_FILE_MACHINE_SH4, "SH4"},
  73. {IMAGE_FILE_MACHINE_SH5, "SH5"},
  74. {IMAGE_FILE_MACHINE_ARM, "ARM"},
  75. {IMAGE_FILE_MACHINE_AM33, "AM33"},
  76. {IMAGE_FILE_MACHINE_THUMB, "THUMB"},
  77. {IMAGE_FILE_MACHINE_IA64, "IA64"},
  78. {IMAGE_FILE_MACHINE_MIPS16, "MIPS16"},
  79. {IMAGE_FILE_MACHINE_MIPSFPU, "MIPSFPU"},
  80. {IMAGE_FILE_MACHINE_MIPSFPU16, "MIPSFPU16"},
  81. {IMAGE_FILE_MACHINE_ALPHA64, "ALPHA64"},
  82. {IMAGE_FILE_MACHINE_TRICORE, "TRICORE"},
  83. {IMAGE_FILE_MACHINE_CEF, "CEF"},
  84. {IMAGE_FILE_MACHINE_CEE, "CEE"},
  85. {IMAGE_FILE_MACHINE_AMD64, "AMD X86-64"},
  86. };
  87. char *ImageDebugType[] = {
  88. "UNKNOWN",
  89. "COFF",
  90. "CODEVIEW",
  91. "FPO",
  92. "MISC",
  93. "EXCEPTION",
  94. "FIXUP",
  95. "OMAP TO SRC",
  96. "OMAP FROM SRC"
  97. "BORLAND",
  98. "RESERVED10",
  99. "CLSID",
  100. };
  101. char *gSymTypeLabel[NumSymTypes] = {
  102. "NONE", "COFF", "CV", "PDB", "EXPORT", "DEFERRED", "SYM16", "DIA PDB", "VIRTUAL"
  103. };
  104. char *gSrcLabel[] = {
  105. "", // srcNone
  106. "symbol search path", // srcSearchPath
  107. "image path", // srcImagePath
  108. "dbg file path", // srcDbgPath
  109. "symbol server", // srcSymSrv
  110. "image header", // srcCVRec
  111. "debugger", // srcHandle
  112. "loaded memory" // srcMemory
  113. };
  114. char *gImageTypeLabel[] = {
  115. "DEFERRED", // dsNone,
  116. "MEMORY", // dsInProc,
  117. "FILE", // dsImage,
  118. "DBG", // dsDbg,
  119. "PDB" // dsPdb
  120. };
  121. void TruncateArgs(LPSTR args);
  122. void lmiDumpModuleInfo(HANDLE hp,PMODULE_INFO mdi);
  123. BOOL lmiGetModuleDumpInfo(HANDLE hp, PMODULE_ENTRY me, PMODULE_INFO mdi);
  124. #ifdef __cplusplus
  125. extern "C" {
  126. #endif
  127. typedef enum DFT
  128. {
  129. dftUnknown,
  130. dftObject,
  131. dftPE,
  132. dftROM,
  133. dftDBG,
  134. dftPEF,
  135. } DFT;
  136. IMAGE_NT_HEADERS64 ImageNtHeaders;
  137. PIMAGE_FILE_HEADER ImageFileHdr;
  138. PIMAGE_OPTIONAL_HEADER64 ImageOptionalHdr;
  139. PIMAGE_SECTION_HEADER SectionHdrs;
  140. ULONG NumSections;
  141. ULONG64 Base;
  142. ULONG64 ImageNtHeadersAddr, SectionHdrsAddr;// , ImageFileHdrAddr, ImageOptionalHdrAddr,
  143. DFT dft;
  144. BOOL
  145. TranslateFilePointerToVirtualAddress(
  146. IN ULONG FilePointer,
  147. OUT PULONG VirtualAddress
  148. );
  149. LPEXT_API_VERSION
  150. ExtensionApiVersion(
  151. VOID
  152. )
  153. {
  154. return &ExtApiVersion;
  155. }
  156. VOID
  157. WinDbgExtensionDllInit(
  158. PWINDBG_EXTENSION_APIS64 lpExtensionApis,
  159. USHORT MajorVersion,
  160. USHORT MinorVersion
  161. )
  162. {
  163. ExtensionApis = *lpExtensionApis;
  164. SavedMajorVersion = MajorVersion;
  165. SavedMinorVersion = MinorVersion;
  166. }
  167. #ifdef __cplusplus
  168. }
  169. #endif
  170. BOOL
  171. ReadFilePtr(
  172. LPCSTR path,
  173. LPSTR contents
  174. )
  175. {
  176. BOOL rc;
  177. HANDLE hptr;
  178. DWORD fsize;
  179. DWORD cb;
  180. LPSTR p;
  181. char ptrfile[MAX_PATH + 1];
  182. char file[MAX_PATH + 1];
  183. rc = false;
  184. if (!path || !*path)
  185. return rc;
  186. // check for existance of file pointer
  187. if (!CopyString(ptrfile, path, _MAX_PATH))
  188. return false;
  189. if (!fileexists(ptrfile))
  190. return false;
  191. hptr = CreateFile(ptrfile,
  192. GENERIC_READ,
  193. FILE_SHARE_READ,
  194. NULL,
  195. OPEN_EXISTING,
  196. FILE_ATTRIBUTE_NORMAL,
  197. NULL);
  198. if (hptr == INVALID_HANDLE_VALUE)
  199. return false;
  200. // test validity of file pointer
  201. fsize = GetFileSize(hptr, NULL);
  202. if (!fsize || fsize > MAX_PATH)
  203. goto cleanup;
  204. // read it
  205. ZeroMemory(file, _MAX_PATH * sizeof(path[0]));
  206. if (!ReadFile(hptr, file, fsize, &cb, 0))
  207. goto cleanup;
  208. if (cb != fsize)
  209. goto cleanup;
  210. rc = true;
  211. // trim string down to the CR
  212. for (p = file; *p; p++) {
  213. if (*p == 10 || *p == 13)
  214. {
  215. *p = 0;
  216. break;
  217. }
  218. }
  219. CopyString(contents, file, MAX_PATH + 1);
  220. cleanup:
  221. // done
  222. if (hptr)
  223. CloseHandle(hptr);
  224. return rc;
  225. }
  226. DECLARE_API(fptr)
  227. {
  228. char contents[MAX_PATH + 1] = "";
  229. ReadFilePtr(args, contents);
  230. if (*contents)
  231. dprintf("%s\n", contents);
  232. }
  233. DECLARE_API(vc7fpo)
  234. {
  235. g_vc7fpo = !g_vc7fpo;
  236. dprintf((g_vc7fpo) ? "VC7FPO - Enabled\n" : "VC7FPO - Disabled\n");
  237. }
  238. DECLARE_API(stackdbg)
  239. {
  240. if (*args && *args != ';') {
  241. for (;;) {
  242. while (*args == ' ' || *args == '\t') {
  243. args++;
  244. }
  245. if (*args == '-' || *args == '/') {
  246. switch(*(args + 1)) {
  247. case 'c':
  248. g_StackDebugIo = SDB_CALLBACK_OUT;
  249. break;
  250. case 'd':
  251. g_StackDebugIo = SDB_DEBUG_OUT;
  252. break;
  253. default:
  254. // Assume it's the beginning of an expression.
  255. goto Expr;
  256. }
  257. args += 2;
  258. } else {
  259. break;
  260. }
  261. }
  262. Expr:
  263. g_StackDebugMask = (ULONG)GetExpression(args);
  264. }
  265. if (g_StackDebugMask == 0) {
  266. dprintf("Stack debugging is off\n");
  267. } else {
  268. dprintf("Stack debugging mask is 0x%08x, output via %s\n",
  269. g_StackDebugMask, g_StackDebugIo == SDB_DEBUG_OUT ?
  270. "debug output" : "callback");
  271. }
  272. }
  273. DECLARE_API(sym)
  274. {
  275. if (strstr(args, "noisy")) {
  276. SymSetOptions(g.SymOptions | SYMOPT_DEBUG);
  277. symsrvSetCallback(true);
  278. } else if (strstr(args, "quiet")) {
  279. SymSetOptions(g.SymOptions & ~SYMOPT_DEBUG);
  280. if (!g.hLog)
  281. symsrvSetCallback(false);
  282. } else if (strstr(args, "prompts off")) {
  283. if (!option(SYMOPT_NO_PROMPTS)) {
  284. SymSetOptions(g.SymOptions | SYMOPT_NO_PROMPTS);
  285. symsrvSetPrompts();
  286. }
  287. } else if (strstr(args, "prompts")) {
  288. if (option(SYMOPT_NO_PROMPTS)) {
  289. SymSetOptions(g.SymOptions & ~SYMOPT_NO_PROMPTS);
  290. symsrvClose();
  291. }
  292. } else {
  293. dprintf("!sym <noisy/quiet - prompts/prompts off> - ");
  294. }
  295. dprintf(option(SYMOPT_DEBUG) ? "noisy mode" : "quiet mode");
  296. dprintf(option(SYMOPT_NO_PROMPTS) ? " - symbol prompts off\n" : " - symbol prompts on\n");
  297. }
  298. DECLARE_API(symsrv)
  299. {
  300. if (strstr(args, "close")) {
  301. symsrvClose();
  302. dprintf("symbol server client has been closed\n");
  303. } else
  304. dprintf("!symsrv close - closes the symbol server client so it can be updated\n");
  305. }
  306. int __cdecl
  307. CompareBase(
  308. const void *e1,
  309. const void *e2
  310. )
  311. {
  312. PLMINFO mod1 = (PLMINFO)e1;
  313. PLMINFO mod2 = (PLMINFO)e2;
  314. LONGLONG diff = mod1->base - mod2->base;
  315. if (diff < 0)
  316. return -1;
  317. else if (diff > 0)
  318. return 1;
  319. else
  320. return 0;
  321. }
  322. #define MAX_FORMAT_STRINGS 8
  323. LPSTR
  324. FormatAddr64(
  325. ULONG64 addr,
  326. BOOL format64
  327. )
  328. {
  329. static CHAR strings[MAX_FORMAT_STRINGS][18];
  330. static int next = 0;
  331. LPSTR string;
  332. string = strings[next];
  333. ++next;
  334. if (next >= MAX_FORMAT_STRINGS)
  335. next = 0;
  336. if (format64)
  337. PrintString(string, 18, "%08x`%08x", (ULONG)(addr>>32), (ULONG)addr);
  338. else
  339. PrintString(string, 18, "%08x", (ULONG)addr);
  340. return string;
  341. }
  342. int __cdecl
  343. CompareNames(
  344. const void *e1,
  345. const void *e2
  346. )
  347. {
  348. PLMINFO mod1 = (PLMINFO)e1;
  349. PLMINFO mod2 = (PLMINFO)e2;
  350. return strcmp( mod1->name, mod2->name );
  351. }
  352. DECLARE_API(lm)
  353. {
  354. PPROCESS_ENTRY pe;
  355. HANDLE hp;
  356. PLIST_ENTRY next;
  357. PMODULE_ENTRY mi;
  358. PLMINFO mods;
  359. PLMINFO mod;
  360. DWORD count;
  361. BOOL format64;
  362. GetCurrentProcessHandle (&hp);
  363. if (!hp) {
  364. dprintf("Couldn't get process handle\n");
  365. return;
  366. }
  367. pe = FindProcessEntry(hp);
  368. if (!pe) {
  369. dprintf("Couldn't find process 0x%x\n", hp);
  370. SetLastError(ERROR_INVALID_HANDLE);
  371. return;
  372. }
  373. next = pe->ModuleList.Flink;
  374. if (!next)
  375. return;
  376. for (count = 0; (PVOID)next != (PVOID)&pe->ModuleList; count++) {
  377. mi = CONTAINING_RECORD( next, MODULE_ENTRY, ListEntry );
  378. next = mi->ListEntry.Flink;
  379. }
  380. mods = (PLMINFO)MemAlloc(count * sizeof(LMINFO));
  381. if (!mods)
  382. return;
  383. ZeroMemory(mods, count * sizeof(LMINFO));
  384. format64 = false;
  385. next = pe->ModuleList.Flink;
  386. for (mod = mods; (PVOID)next != (PVOID)&pe->ModuleList; mod++) {
  387. mi = CONTAINING_RECORD( next, MODULE_ENTRY, ListEntry );
  388. mod->base = mi->BaseOfDll;
  389. mod->end = mod->base + mi->DllSize;
  390. CopyStrArray(mod->name, mi->ModuleName);
  391. format64 = IsImageMachineType64(mi->MachineType);
  392. next = mi->ListEntry.Flink;
  393. }
  394. qsort(mods, count, sizeof(LMINFO), CompareBase);
  395. dprintf("%d loaded modules...\n", count);
  396. if (format64)
  397. dprintf(" base - end name\n", mod->base, mod->end, mod->name);
  398. else
  399. dprintf(" base - end name\n", mod->base, mod->end, mod->name);
  400. for (mod = mods; count > 0; mod++, count--) {
  401. dprintf("0x%s - ", FormatAddr64(mod->base, format64));
  402. dprintf("0x%s ", FormatAddr64(mod->end, format64));
  403. dprintf("%s\n", mod->name);
  404. }
  405. MemFree(mods);
  406. }
  407. DECLARE_API(lmi)
  408. {
  409. PPROCESS_ENTRY pe;
  410. PMODULE_ENTRY mi = NULL;
  411. MODULE_INFO mdi;
  412. DWORD64 addr;
  413. HANDLE hp = 0;
  414. char argstr[1024];
  415. char *pc;
  416. if (!args[0] || !CopyStrArray(argstr, args)) {
  417. dprintf("You must specify a module\n");
  418. return;
  419. }
  420. _strlwr(argstr);
  421. TruncateArgs(argstr);
  422. dprintf("Loaded Module Info: [%s] ", argstr);
  423. GetCurrentProcessHandle(&hp);
  424. if (!hp) {
  425. dprintf("couldn't get process handle\n");
  426. return;
  427. }
  428. pe = FindProcessEntry(hp);
  429. if (!pe) {
  430. dprintf("Couldn't find process 0x%x while looking for %s\n", hp, argstr);
  431. SetLastError(ERROR_INVALID_HANDLE);
  432. return;
  433. }
  434. dprintf("\n");
  435. if (mi = FindModule(hp, pe, argstr, false)) {
  436. if (lmiGetModuleDumpInfo(hp, mi, &mdi)) {
  437. lmiDumpModuleInfo(hp, &mdi);
  438. } else {
  439. // dprintf("Cannot get module info for %s\n", argstr);
  440. }
  441. if (SectionHdrs) {
  442. free(SectionHdrs);
  443. SectionHdrs = NULL;
  444. }
  445. dprintf(" Load Report: %s\n", SymbolStatus(mi, 17));
  446. return;
  447. }
  448. GetExpressionEx(args, &addr, NULL);
  449. if (!addr) {
  450. dprintf("%s not found\n", argstr);
  451. SetLastError(ERROR_MOD_NOT_FOUND);
  452. return;
  453. }
  454. mi = GetModuleForPC( pe, addr, false );
  455. if (!mi) {
  456. dprintf("%I64lx is not a valid address\n", addr);
  457. return;
  458. }
  459. if (lmiGetModuleDumpInfo(hp, mi, &mdi)) {
  460. lmiDumpModuleInfo(hp, &mdi);
  461. }
  462. if (SectionHdrs) {
  463. free(SectionHdrs);
  464. SectionHdrs = NULL;
  465. }
  466. dprintf(" Load Report: %s\n", SymbolStatus(mi, 17));
  467. }
  468. DECLARE_API(omap)
  469. {
  470. PPROCESS_ENTRY pe;
  471. PMODULE_ENTRY mi = NULL;
  472. HANDLE hp = 0;
  473. char argstr[1024];
  474. POMAP pomap;
  475. DWORD i;
  476. if (!CopyStrArray(argstr, args))
  477. return;
  478. _strlwr(argstr);
  479. TruncateArgs(argstr);
  480. dprintf("Dump OMAP: [%s] ", argstr);
  481. GetCurrentProcessHandle (&hp);
  482. if (!hp) {
  483. dprintf("couldn't get process handle\n");
  484. return;
  485. }
  486. pe = FindProcessEntry(hp);
  487. if (!pe) {
  488. dprintf("Couldn't find process 0x%x while looking for %s\n", hp, argstr);
  489. SetLastError(ERROR_INVALID_HANDLE);
  490. return;
  491. }
  492. dprintf("\n");
  493. mi = FindModule(hp, pe, argstr, false);
  494. if (!mi)
  495. return;
  496. i = sizeof(DWORD);
  497. if (!mi->pOmapFrom)
  498. return;
  499. dprintf("\nOMAP FROM:\n");
  500. for(i = 0, pomap = mi->pOmapFrom;
  501. i < 100; // mi->cOmapFrom;
  502. i++, pomap++)
  503. {
  504. dprintf("%8x <-%8x\n", pomap->rva, pomap->rvaTo);
  505. }
  506. if (!mi->pOmapTo)
  507. return;
  508. dprintf("\nOMAP TO:\n");
  509. for(i = 0, pomap = mi->pOmapTo;
  510. i < 100; // mi->cOmapTo;
  511. i++, pomap++)
  512. {
  513. dprintf("%8x ->%8x\n", pomap->rva, pomap->rvaTo);
  514. }
  515. }
  516. BOOL
  517. cbSrcFiles(
  518. PSOURCEFILE pSourceFile,
  519. PVOID UserContext
  520. )
  521. {
  522. PMODULE_ENTRY mi;
  523. PCHAR mname;
  524. if (!pSourceFile)
  525. return false;
  526. mi = GetModFromAddr((PPROCESS_ENTRY)UserContext, pSourceFile->ModBase);
  527. if (!mi)
  528. return true;
  529. dprintf(" %s!%s\n", (*mi->AliasName) ? mi->AliasName : mi->ModuleName, pSourceFile->FileName);
  530. return true;
  531. }
  532. DECLARE_API(srcfiles)
  533. {
  534. HANDLE hp = 0;
  535. char argstr[1024];
  536. BOOL rc;
  537. PPROCESS_ENTRY pe;
  538. if (!CopyStrArray(argstr, args))
  539. return;
  540. _strlwr(argstr);
  541. TruncateArgs(argstr);
  542. dprintf("Source Files: [%s]\n", argstr);
  543. GetCurrentProcessHandle (&hp);
  544. if (!hp) {
  545. dprintf("couldn't get process handle\n");
  546. return;
  547. }
  548. pe = FindProcessEntry(hp);
  549. if (!pe) {
  550. dprintf("Couldn't find process 0x%x while looking for %s\n", hp, argstr);
  551. SetLastError(ERROR_INVALID_HANDLE);
  552. return;
  553. }
  554. rc = SymEnumSourceFiles(hp, 0, argstr, cbSrcFiles, pe);
  555. }
  556. VOID
  557. DumpSecHdr (
  558. IN DWORD i,
  559. IN PIMAGE_SECTION_HEADER Sh
  560. )
  561. {
  562. dprintf(" %2d %s\n", i, Sh->Name);
  563. }
  564. VOID
  565. DumpSecs(
  566. BOOL fFullDump
  567. )
  568. {
  569. IMAGE_SECTION_HEADER sh;
  570. const char *p;
  571. DWORD li;
  572. DWORD cb;
  573. BOOL Ok;
  574. int i, j;
  575. CHAR szName[IMAGE_SIZEOF_SHORT_NAME + 1];
  576. if (ImageFileHdr->NumberOfSections < 1)
  577. return;
  578. dprintf(" Sections: # Name\n");
  579. for (i = 1; i <= ImageFileHdr->NumberOfSections; i++) {
  580. sh = SectionHdrs[i-1];
  581. CopyStrArray(szName, (char *) sh.Name);
  582. DumpSecHdr(i, &sh);
  583. }
  584. }
  585. BOOL
  586. lmiGetModuleDumpInfo(
  587. HANDLE hp,
  588. PMODULE_ENTRY me,
  589. PMODULE_INFOx mdi)
  590. {
  591. BOOL rc;
  592. DWORD cb;
  593. ULONG nDebugDirs;
  594. ULONG64 ddva;
  595. IMAGE_SEPARATE_DEBUG_HEADER sdh;
  596. IMAGE_DOS_HEADER DosHeader;
  597. IMAGE_NT_HEADERS32 NtHeader32;
  598. IMAGE_NT_HEADERS64 NtHeader64;
  599. PIMAGE_FILE_HEADER FileHeader;
  600. PIMAGE_ROM_OPTIONAL_HEADER rom;
  601. PIMAGE_DATA_DIRECTORY datadir;
  602. DWORD64 offset;
  603. BOOL b64;
  604. ZeroMemory(mdi, sizeof(MODULE_INFO));
  605. CopyStrArray(mdi->name, me->ModuleName);
  606. mdi->addr = me->BaseOfDll;
  607. CopyString(mdi->image, me->ImageName, DIMA(mdi->image));
  608. if (!mdi->addr) {
  609. dprintf("Module does not have base address\n");
  610. return false;
  611. }
  612. mdi->SymType = me->SymType;
  613. mdi->SymLoadError = me->SymLoadError;
  614. if (me->SymType == SymVirtual)
  615. return true;
  616. if (me->SymType == SymDeferred) {
  617. mdi->SymLoadError = SYMLOAD_DEFERRED;
  618. }
  619. rc = ReadMemory(mdi->addr, &DosHeader, sizeof(DosHeader), &cb);
  620. if (!rc || cb != sizeof(DosHeader)) {
  621. dprintf("Cannot read Image header @ %p\n", mdi->addr);
  622. return false;
  623. }
  624. mdi->HdrType = DosHeader.e_magic;
  625. mdi->omap = me->cOmapFrom ? true : false;
  626. mdi->PdbSrc = me->PdbSrc;
  627. if (me->LoadedPdbName)
  628. CopyStrArray(mdi->PdbFileName, me->LoadedPdbName);
  629. mdi->ImageSrc = me->ImageSrc;
  630. if (me->LoadedImageName)
  631. CopyStrArray(mdi->ImageFileName, me->LoadedImageName);
  632. mdi->ImageType = me->ImageType;
  633. if (DosHeader.e_magic == IMAGE_DOS_SIGNATURE) {
  634. rc = ReadMemory(mdi->addr + DosHeader.e_lfanew, &NtHeader32, sizeof(NtHeader32), &cb);
  635. if (!rc || cb != sizeof(NtHeader32)) {
  636. dprintf("Cannot read Image NT header @ %p\n", mdi->addr + DosHeader.e_lfanew);
  637. return false;
  638. }
  639. mdi->machine = NtHeader32.FileHeader.Machine;
  640. mdi->TimeDateStamp = NtHeader32.FileHeader.TimeDateStamp;
  641. if (NtHeader32.Signature != IMAGE_NT_SIGNATURE) {
  642. // if header is not NT sig, this is a ROM image
  643. rom = (PIMAGE_ROM_OPTIONAL_HEADER)&NtHeader32.OptionalHeader;
  644. if (rom->Magic == IMAGE_ROM_OPTIONAL_HDR_MAGIC) {
  645. ImageFileHdr = &NtHeader32.FileHeader;
  646. mdi->SizeOfImage = rom->SizeOfCode;
  647. mdi->CheckSum = 0;
  648. nDebugDirs = 0;
  649. if (!(ImageFileHdr->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) {
  650. // Get the debug dir VA
  651. }
  652. } else {
  653. dprintf("Unknown NT Image signature\n");
  654. return false;
  655. }
  656. } else {
  657. // otherwise, get info from appropriate header type for 32 or 64 bit
  658. if (IsImageMachineType64(NtHeader32.FileHeader.Machine)) {
  659. // Reread the header as a 64bit header.
  660. rc = ReadMemory(mdi->addr + DosHeader.e_lfanew, &NtHeader64, sizeof(NtHeader64), &cb);
  661. if (!rc || cb != sizeof(NtHeader64)) {
  662. dprintf("Cannot read Image NT header @ %p\n", mdi->addr + DosHeader.e_lfanew);
  663. return false;
  664. }
  665. ImageFileHdr = &NtHeader64.FileHeader;
  666. mdi->CheckSum = NtHeader64.OptionalHeader.CheckSum;
  667. mdi->SizeOfImage = NtHeader64.OptionalHeader.SizeOfImage;
  668. datadir = NtHeader64.OptionalHeader.DataDirectory;
  669. } else {
  670. ImageFileHdr = &NtHeader32.FileHeader;
  671. datadir = NtHeader32.OptionalHeader.DataDirectory;
  672. mdi->SizeOfImage = NtHeader32.OptionalHeader.SizeOfImage;
  673. mdi->CheckSum = NtHeader32.OptionalHeader.CheckSum;
  674. }
  675. mdi->DebugDataVA = mdi->addr + datadir[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
  676. mdi->nDebugDirs = datadir[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof(IMAGE_DEBUG_DIRECTORY);
  677. }
  678. // read the section headers
  679. mdi->Characteristics = ImageFileHdr->Characteristics;
  680. SectionHdrs = (PIMAGE_SECTION_HEADER) malloc((NumSections = ImageFileHdr->NumberOfSections)*
  681. sizeof(IMAGE_SECTION_HEADER));
  682. if (!SectionHdrs) {
  683. dprintf("Cannot allocate memory for reading sections\n");
  684. return false;
  685. }
  686. offset = mdi->addr + DosHeader.e_lfanew;
  687. b64 = IsImageMachineType64(ImageFileHdr->Machine);
  688. SectionHdrsAddr = offset + (b64 ? sizeof(IMAGE_NT_HEADERS64) : sizeof(IMAGE_NT_HEADERS32)) +
  689. ImageFileHdr->SizeOfOptionalHeader - (b64 ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32));
  690. rc = ReadMemory(SectionHdrsAddr,
  691. SectionHdrs,
  692. (NumSections) * sizeof(IMAGE_SECTION_HEADER),
  693. &cb);
  694. if (!rc) {
  695. dprintf("Can't read section headers\n");
  696. } else {
  697. if (cb != NumSections * sizeof(IMAGE_SECTION_HEADER)) {
  698. dprintf("\n***\n*** Some section headers may be missing ***\n***\n\n");
  699. NumSections = (USHORT)(cb / sizeof(IMAGE_SECTION_HEADER));
  700. }
  701. #if 0
  702. DumpSecs(false);
  703. #endif
  704. }
  705. } else if (DosHeader.e_magic == IMAGE_SEPARATE_DEBUG_SIGNATURE) {
  706. rc = ReadMemory(mdi->addr, &sdh, sizeof(sdh), &cb);
  707. if (!rc || cb != sizeof(sdh)) {
  708. dprintf("Cannot read Image Debug header @ %p\n", mdi->addr);
  709. return false;
  710. }
  711. mdi->machine = sdh.Machine;
  712. mdi->TimeDateStamp = sdh.TimeDateStamp;
  713. mdi->CheckSum = sdh.CheckSum;
  714. mdi->SizeOfImage = sdh.SizeOfImage;
  715. mdi->Characteristics = sdh.Characteristics;
  716. if (sdh.DebugDirectorySize) {
  717. mdi->nDebugDirs = (int)(sdh.DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY));
  718. mdi->DebugDataVA = sizeof(IMAGE_SEPARATE_DEBUG_HEADER)
  719. + (sdh.NumberOfSections * sizeof(IMAGE_SECTION_HEADER))
  720. + sdh.ExportedNamesSize;
  721. }
  722. } else {
  723. dprintf("Unknown image\n");
  724. return false;
  725. }
  726. mdi->numsyms = me->numsyms;
  727. memcpy(&mdi->cvrec, &me->CVRec, min(sizeof(mdi->cvrec), sizeof(me->CVRec)));
  728. return true;
  729. }
  730. BOOL
  731. DumpDbgDirectories(
  732. HANDLE hp,
  733. PMODULE_INFOx mdi
  734. )
  735. {
  736. ULONG rc, cb;
  737. IMAGE_DEBUG_DIRECTORY dd;
  738. IMAGE_DEBUG_MISC md;
  739. ULONG64 ddva;
  740. ULONG nDebugDirs;
  741. PCVDD pcv;
  742. ULONG64 cvAddr;
  743. ULONG cvSize;
  744. PCHAR pCV;
  745. CHAR ImgData[MAX_PATH];
  746. IMAGE_COFF_SYMBOLS_HEADER CoffHdr;
  747. ULONG va;
  748. nDebugDirs = mdi->nDebugDirs;
  749. ddva = mdi->DebugDataVA;
  750. dprintf("Debug Data Dirs: Type Size VA Pointer\n");
  751. for (;nDebugDirs; dprintf("\n"), nDebugDirs--) {
  752. rc = ReadMemory(ddva, &dd, sizeof(dd), &cb);
  753. if (!rc || cb != sizeof(dd))
  754. return false;
  755. if (dd.Type) {
  756. dprintf("%21s ", // dd.Type,
  757. (dd.Type < sizeof (ImageDebugType) / sizeof(char *)) ? ImageDebugType[dd.Type] : "??");
  758. dprintf(
  759. "%5lx, %5lx, %7lx ",
  760. dd.SizeOfData,
  761. dd.AddressOfRawData,
  762. dd.PointerToRawData);
  763. if (!TranslateFilePointerToVirtualAddress(dd.PointerToRawData, &va)) {
  764. dprintf(" [Debug data not mapped]");
  765. if (dd.Type == IMAGE_DEBUG_TYPE_CODEVIEW)
  766. dprintf(" - Can't validate symbols, if present.");
  767. goto nextDebugDir;
  768. }
  769. switch(dd.Type)
  770. {
  771. case IMAGE_DEBUG_TYPE_MISC:
  772. if (!dd.PointerToRawData) {
  773. dprintf("[Data not mapped]");
  774. break;
  775. }
  776. rc = ReadMemory(mdi->addr + dd.PointerToRawData, &md, sizeof(md), &cb);
  777. if (!rc || cb != sizeof(md) || md.DataType != IMAGE_DEBUG_MISC_EXENAME) {
  778. dprintf("[Data not mapped]");
  779. goto nextDebugDir;
  780. }
  781. rc = ReadMemory(mdi->addr + dd.PointerToRawData + FIELD_OFFSET(IMAGE_DEBUG_MISC, Data),
  782. ImgData, MAX_PATH, &cb);
  783. if (rc && cb)
  784. dprintf(" %s", ImgData);
  785. break;
  786. case IMAGE_DEBUG_TYPE_CODEVIEW:
  787. if (dd.AddressOfRawData) {
  788. cvAddr = mdi->addr + dd.AddressOfRawData;
  789. } else if (dd.PointerToRawData) {
  790. cvAddr = mdi->addr + dd.PointerToRawData;
  791. } else {
  792. break;
  793. }
  794. cvSize = dd.SizeOfData;
  795. if (!(pCV = (PCHAR)MemAlloc(dd.SizeOfData + 1)))
  796. break;
  797. pcv = (PCVDD)pCV;
  798. rc = ReadMemory(cvAddr,pCV, cvSize, &cb);
  799. if (rc && cb == cvSize) {
  800. char *c = (char *)&pcv->dwSig;
  801. dprintf("%c%c%c%c - ", *c, *(c + 1), *(c + 2), *(c + 3));
  802. } else {
  803. pcv->dwSig = 0;
  804. }
  805. switch (pcv->dwSig)
  806. {
  807. case 0:
  808. dprintf("[Debug data not mapped] - can't validate symbols, if present.");
  809. break;
  810. case '01BN':
  811. pCV[cvSize] = 0;
  812. dprintf("Sig: %lx, Age: %lx,%sPdb: %s",
  813. pcv->nb10i.sig,
  814. pcv->nb10i.age,
  815. (strlen(pCV) > 14 ? "\n " : " "),
  816. pcv->nb10i.szPdb);
  817. break;
  818. case 'SDSR':
  819. pCV[cvSize] = 0;
  820. dprintf("GUID: (0x%8x, 0x%4x, 0x%4x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x)\n",
  821. pcv->rsdsi.guidSig.Data1,
  822. pcv->rsdsi.guidSig.Data2,
  823. pcv->rsdsi.guidSig.Data3,
  824. pcv->rsdsi.guidSig.Data4[0],
  825. pcv->rsdsi.guidSig.Data4[1],
  826. pcv->rsdsi.guidSig.Data4[2],
  827. pcv->rsdsi.guidSig.Data4[3],
  828. pcv->rsdsi.guidSig.Data4[4],
  829. pcv->rsdsi.guidSig.Data4[5],
  830. pcv->rsdsi.guidSig.Data4[6],
  831. pcv->rsdsi.guidSig.Data4[7]);
  832. dprintf(" Age: %lx, Pdb: %s",
  833. pcv->rsdsi.age,
  834. pcv->rsdsi.szPdb);
  835. break;
  836. case '80BN':
  837. case '90BN':
  838. case '11BN':
  839. break;
  840. default:
  841. dprintf("unrecognized symbol format ID");
  842. break;
  843. }
  844. MemFree(pCV);
  845. break;
  846. case IMAGE_DEBUG_TYPE_COFF:
  847. if (!dd.PointerToRawData) {
  848. dprintf("[Data paged out] - unable to load COFF info.");
  849. break;
  850. }
  851. rc = ReadMemory(mdi->addr + dd.PointerToRawData, &CoffHdr, sizeof(CoffHdr), &cb);
  852. if (!rc || cb != sizeof(CoffHdr)) {
  853. dprintf("[Data paged out] - unable to load COFF info.");
  854. break;
  855. }
  856. dprintf("NumSyms %#lx, Numlines %#lx",
  857. mdi->numsyms, // CoffHdr.NumberOfSymbols,
  858. CoffHdr.NumberOfLinenumbers);
  859. break;
  860. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  861. dprintf("BBT Optimized");
  862. break;
  863. default:
  864. dprintf("[Data not mapped]");
  865. break;
  866. }
  867. }
  868. nextDebugDir:
  869. ddva += sizeof (dd);
  870. }
  871. return true;
  872. }
  873. void lmiDumpModuleInfo(
  874. HANDLE hp,
  875. PMODULE_INFO mdi
  876. )
  877. {
  878. ULONG i;
  879. const char *time;
  880. dprintf(" Module: %s\n", mdi->name);
  881. dprintf(" Base Address: %p%s", mdi->addr, mdi->addr ? "\n" : " is INVALID\n");
  882. dprintf(" Image Name: %s\n", mdi->image);
  883. if (mdi->SymType == SymVirtual)
  884. goto symboltype;
  885. dprintf(" Machine Type: %d", mdi->machine);
  886. for (i=0;i<sizeof(Machines)/sizeof(MACHINE_TYPE);i++) {
  887. if (mdi->machine == Machines[i].MachineId) {
  888. dprintf(" (%s)", Machines[i].MachineName);
  889. break;
  890. }
  891. }
  892. dprintf("\n Time Stamp: %lx", mdi->TimeDateStamp);
  893. if ((time = ctime((time_t *) &mdi->TimeDateStamp)) != NULL) {
  894. dprintf( " %s", time);
  895. } else
  896. dprintf("\n");
  897. dprintf(" Size: %x\n", mdi->SizeOfImage);
  898. dprintf(" CheckSum: %lx\n", mdi->CheckSum);
  899. dprintf("Characteristics: %lx %s %s\n",
  900. mdi->Characteristics,
  901. ((mdi->Characteristics & IMAGE_FILE_DEBUG_STRIPPED) ? "stripped":""),
  902. (mdi->omap ? "perf" : "")
  903. );
  904. if (mdi->nDebugDirs) {
  905. DumpDbgDirectories(hp, mdi);
  906. } else {
  907. dprintf("Debug Directories not present\n");
  908. }
  909. switch (mdi->ImageType)
  910. {
  911. case dsInProc:
  912. case dsImage:
  913. if (mdi->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
  914. break;
  915. case dsDbg:
  916. case dsPdb:
  917. dprintf(" Image Type: %-9s", gImageTypeLabel[mdi->ImageType]);
  918. dprintf("- Image read successfully from %s.", gSrcLabel[mdi->ImageSrc]);
  919. if (mdi->ImageSrc != srcNone && mdi->ImageSrc != srcMemory)
  920. dprintf("\n %s", mdi->ImageFileName);
  921. dprintf("\n");
  922. break;
  923. case dsNone:
  924. default:
  925. break;
  926. }
  927. symboltype:
  928. dprintf(" Symbol Type: %-9s", gSymTypeLabel[mdi->SymType]);
  929. for (i=0;i< sizeof(SymLoadErrorDesc) / sizeof (ERROR_TYPE); i++) {
  930. if (mdi->SymLoadError == SymLoadErrorDesc[i].ErrorVal) {
  931. dprintf("- %s", SymLoadErrorDesc[i].Desc);
  932. break;
  933. }
  934. }
  935. if (mdi->PdbSrc != srcNone) {
  936. dprintf(" from %s.", gSrcLabel[mdi->PdbSrc]);
  937. if (*mdi->PdbFileName)
  938. dprintf("\n %s", mdi->PdbFileName);
  939. dprintf("\n");
  940. } else {
  941. dprintf("\n");
  942. }
  943. }
  944. void TruncateArgs(
  945. LPSTR sz
  946. )
  947. {
  948. PSTR p;
  949. for (p = sz; !isspace(*p); p++) {
  950. if (!*p)
  951. break;
  952. }
  953. *p = 0;
  954. }
  955. // STYP_ flags values for MIPS ROM images
  956. #define STYP_REG 0x00000000
  957. #define STYP_TEXT 0x00000020
  958. #define STYP_INIT 0x80000000
  959. #define STYP_RDATA 0x00000100
  960. #define STYP_DATA 0x00000040
  961. #define STYP_LIT8 0x08000000
  962. #define STYP_LIT4 0x10000000
  963. #define STYP_SDATA 0x00000200
  964. #define STYP_SBSS 0x00000080
  965. #define STYP_BSS 0x00000400
  966. #define STYP_LIB 0x40000000
  967. #define STYP_UCODE 0x00000800
  968. #define S_NRELOC_OVFL 0x20000000
  969. #define IMAGE_SCN_MEM_SYSHEAP 0x00010000 // Obsolete
  970. #define IMAGE_SCN_MEM_PROTECTED 0x00004000 // Obsolete
  971. const static char * const MachineName[] = {
  972. "Unknown",
  973. "i386",
  974. "Alpha AXP",
  975. "Alpha AXP64",
  976. "Intel IA64",
  977. "AMD X86-64",
  978. "ARM 32-bit",
  979. };
  980. const static char * const SubsystemName[] = {
  981. "Unknown",
  982. "Native",
  983. "Windows GUI",
  984. "Windows CUI",
  985. "Posix CUI",
  986. };
  987. const static char * const DirectoryEntryName[] = {
  988. "Export",
  989. "Import",
  990. "Resource",
  991. "Exception",
  992. "Security",
  993. "Base Relocation",
  994. "Debug",
  995. "Description",
  996. "Special",
  997. "Thread Storage",
  998. "Load Configuration",
  999. "Bound Import",
  1000. "Import Address Table",
  1001. "Reserved",
  1002. "Reserved",
  1003. "Reserved",
  1004. 0
  1005. };
  1006. VOID
  1007. dhDumpHeaders (
  1008. VOID
  1009. );
  1010. VOID
  1011. dhDumpSections(
  1012. VOID
  1013. );
  1014. VOID
  1015. dhDumpImage(
  1016. ULONG64 xBase,
  1017. BOOL DoHeaders,
  1018. BOOL DoSections
  1019. );
  1020. VOID
  1021. dhdh(
  1022. IN PSTR lpArgs
  1023. )
  1024. {
  1025. BOOL DoAll;
  1026. BOOL DoSections;
  1027. BOOL DoHeaders;
  1028. CHAR c;
  1029. PCHAR p;
  1030. ULONG64 xBase;
  1031. //
  1032. // Evaluate the argument string to get the address of the
  1033. // image to dump.
  1034. //
  1035. DoAll = true;
  1036. DoHeaders = false;
  1037. DoSections = false;
  1038. xBase = 0;
  1039. while (*lpArgs) {
  1040. while (isspace(*lpArgs)) {
  1041. lpArgs++;
  1042. }
  1043. if (*lpArgs == '/' || *lpArgs == '-') {
  1044. // process switch
  1045. switch (*++lpArgs) {
  1046. case 'a': // dump everything we can
  1047. case 'A':
  1048. ++lpArgs;
  1049. DoAll = true;
  1050. break;
  1051. default: // invalid switch
  1052. case 'h': // help
  1053. case 'H':
  1054. case '?':
  1055. dprintf("Usage: dh [options] address\n");
  1056. dprintf("\n");
  1057. dprintf("Dumps headers from an image based at address\n");
  1058. dprintf("\n");
  1059. dprintf("Options:\n");
  1060. dprintf("\n");
  1061. dprintf(" -a Dump everything\n");
  1062. dprintf(" -f Dump file headers\n");
  1063. dprintf(" -s Dump section headers\n");
  1064. dprintf("\n");
  1065. return;
  1066. case 'f':
  1067. case 'F':
  1068. ++lpArgs;
  1069. DoAll = false;
  1070. DoHeaders = true;
  1071. break;
  1072. case 's':
  1073. case 'S':
  1074. ++lpArgs;
  1075. DoAll = false;
  1076. DoSections = true;
  1077. break;
  1078. }
  1079. } else if (*lpArgs) {
  1080. if (xBase != 0) {
  1081. dprintf("Invalid extra argument\n");
  1082. return;
  1083. }
  1084. p = lpArgs;
  1085. while (*p && !isspace(*p)) {
  1086. p++;
  1087. }
  1088. c = *p;
  1089. *p = 0;
  1090. xBase = GetExpression(lpArgs);
  1091. *p = c;
  1092. lpArgs=p;
  1093. }
  1094. }
  1095. if ( !xBase ) {
  1096. return;
  1097. }
  1098. dhDumpImage(xBase, DoAll || DoHeaders, DoAll || DoSections);
  1099. }
  1100. DECLARE_API(dh)
  1101. {
  1102. dhdh( (PSTR)args );
  1103. }
  1104. BOOL
  1105. dhReadNtHeader(
  1106. ULONG64 Address,
  1107. PIMAGE_NT_HEADERS64 pNtHdrs
  1108. )
  1109. {
  1110. ULONG cb;
  1111. BOOL Ok;
  1112. Ok = ReadMemory(Address, pNtHdrs, sizeof(*pNtHdrs), &cb);
  1113. if (IsImageMachineType64(pNtHdrs->FileHeader.Machine))
  1114. {
  1115. Ok = Ok && (cb == sizeof(*pNtHdrs));
  1116. }
  1117. else
  1118. {
  1119. IMAGE_NT_HEADERS32 nthdr32;
  1120. Ok = ReadMemory(Address, &nthdr32, sizeof(nthdr32), &cb);
  1121. Ok = Ok && (cb == sizeof(nthdr32));
  1122. ImageNtHdr32To64(&nthdr32, pNtHdrs);
  1123. }
  1124. return Ok;
  1125. }
  1126. VOID
  1127. dhDumpImage(
  1128. ULONG64 xBase,
  1129. BOOL DoHeaders,
  1130. BOOL DoSections
  1131. )
  1132. {
  1133. IMAGE_DOS_HEADER DosHeader;
  1134. ULONG cb;
  1135. ULONG64 Offset;
  1136. BOOL Ok;
  1137. Base = xBase;
  1138. Ok = ReadMemory(Base, &DosHeader, sizeof(DosHeader), &cb);
  1139. if (!Ok) {
  1140. dprintf("Can't read file header: error == %d\n", GetLastError());
  1141. return;
  1142. }
  1143. if (cb != sizeof(DosHeader) || DosHeader.e_magic != IMAGE_DOS_SIGNATURE) {
  1144. dprintf("No file header\n");
  1145. return;
  1146. }
  1147. Offset = Base + DosHeader.e_lfanew;
  1148. if (!dhReadNtHeader(ImageNtHeadersAddr=Offset, &ImageNtHeaders)) {
  1149. dprintf("Bad file header\n");
  1150. return;
  1151. }
  1152. ImageFileHdr = &ImageNtHeaders.FileHeader;
  1153. ImageOptionalHdr = &ImageNtHeaders.OptionalHeader;
  1154. if (ImageFileHdr->SizeOfOptionalHeader == sizeof(IMAGE_ROM_OPTIONAL_HEADER)) {
  1155. dft = dftROM;
  1156. } else if (ImageFileHdr->Characteristics & IMAGE_FILE_DLL) {
  1157. dft = dftPE;
  1158. } else if (ImageFileHdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) {
  1159. dft = dftPE;
  1160. } else if (ImageFileHdr->SizeOfOptionalHeader == 0) {
  1161. dft = dftObject;
  1162. } else {
  1163. dft = dftUnknown;
  1164. }
  1165. if (DoHeaders) {
  1166. dhDumpHeaders();
  1167. }
  1168. if (DoSections) {
  1169. SectionHdrs = (PIMAGE_SECTION_HEADER) malloc((NumSections = ImageFileHdr->NumberOfSections)*
  1170. sizeof(IMAGE_SECTION_HEADER));
  1171. if (!SectionHdrs) {
  1172. dprintf("Cannot allocate memory for dumping sections\n");
  1173. return;
  1174. }
  1175. __try {
  1176. BOOL b64 = IsImageMachineType64(ImageFileHdr->Machine);
  1177. SectionHdrsAddr = Offset + (b64 ? sizeof(IMAGE_NT_HEADERS64) : sizeof(IMAGE_NT_HEADERS32)) +
  1178. ImageFileHdr->SizeOfOptionalHeader - (b64 ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32));
  1179. Ok = ReadMemory(
  1180. SectionHdrsAddr,
  1181. SectionHdrs,
  1182. (NumSections) * sizeof(IMAGE_SECTION_HEADER),
  1183. &cb);
  1184. if (!Ok) {
  1185. dprintf("Can't read section headers\n");
  1186. } else {
  1187. if (cb != NumSections * sizeof(IMAGE_SECTION_HEADER)) {
  1188. dprintf("\n***\n*** Some section headers may be missing ***\n***\n\n");
  1189. NumSections = (USHORT)(cb / sizeof(IMAGE_SECTION_HEADER));
  1190. }
  1191. dhDumpSections();
  1192. }
  1193. }
  1194. __finally {
  1195. if (SectionHdrs) {
  1196. free(SectionHdrs);
  1197. SectionHdrs = 0;
  1198. }
  1199. }
  1200. }
  1201. }
  1202. VOID
  1203. dhDumpHeaders (
  1204. VOID
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. Formats the file header and optional header.
  1209. Arguments:
  1210. None.
  1211. Return Value:
  1212. None.
  1213. --*/
  1214. {
  1215. int i, j;
  1216. const char *time;
  1217. const char *name;
  1218. DWORD dw;
  1219. // Print out file type
  1220. switch (dft) {
  1221. case dftObject :
  1222. dprintf("\nFile Type: COFF OBJECT\n");
  1223. break;
  1224. case dftPE :
  1225. if (ImageFileHdr->Characteristics & IMAGE_FILE_DLL) {
  1226. dprintf("\nFile Type: DLL\n");
  1227. } else {
  1228. dprintf("\nFile Type: EXECUTABLE IMAGE\n");
  1229. }
  1230. break;
  1231. case dftROM :
  1232. dprintf("\nFile Type: ROM IMAGE\n");
  1233. break;
  1234. default :
  1235. dprintf("\nFile Type: UNKNOWN\n");
  1236. break;
  1237. }
  1238. switch (ImageFileHdr->Machine) {
  1239. case IMAGE_FILE_MACHINE_I386 : i = 1; break;
  1240. case IMAGE_FILE_MACHINE_ALPHA : i = 2; break;
  1241. case IMAGE_FILE_MACHINE_ALPHA64 : i = 3; break;
  1242. case IMAGE_FILE_MACHINE_IA64 : i = 4; break;
  1243. case IMAGE_FILE_MACHINE_AMD64 : i = 5; break;
  1244. case IMAGE_FILE_MACHINE_ARM : i = 6; break;
  1245. default : i = 0;
  1246. }
  1247. dprintf(
  1248. "FILE HEADER VALUES\n"
  1249. "%8hX machine (%s)\n"
  1250. "%8hX number of sections\n"
  1251. "%8lX time date stamp",
  1252. ImageFileHdr->Machine,
  1253. MachineName[i],
  1254. ImageFileHdr->NumberOfSections,
  1255. ImageFileHdr->TimeDateStamp);
  1256. if ((time = ctime((time_t *) &ImageFileHdr->TimeDateStamp)) != NULL) {
  1257. dprintf( " %s", time);
  1258. }
  1259. dprintf("\n");
  1260. dprintf(
  1261. "%8lX file pointer to symbol table\n"
  1262. "%8lX number of symbols\n"
  1263. "%8hX size of optional header\n"
  1264. "%8hX characteristics\n",
  1265. ImageFileHdr->PointerToSymbolTable,
  1266. ImageFileHdr->NumberOfSymbols,
  1267. ImageFileHdr->SizeOfOptionalHeader,
  1268. ImageFileHdr->Characteristics);
  1269. for (dw = ImageFileHdr->Characteristics, j = 0; dw; dw >>= 1, j++) {
  1270. if (dw & 1) {
  1271. switch (1 << j) {
  1272. case IMAGE_FILE_RELOCS_STRIPPED : name = "Relocations stripped"; break;
  1273. case IMAGE_FILE_EXECUTABLE_IMAGE : name = "Executable"; break;
  1274. case IMAGE_FILE_LINE_NUMS_STRIPPED : name = "Line numbers stripped"; break;
  1275. case IMAGE_FILE_LOCAL_SYMS_STRIPPED : name = "Symbols stripped"; break;
  1276. case IMAGE_FILE_LARGE_ADDRESS_AWARE : name = "App can handle >2gb addresses"; break;
  1277. case IMAGE_FILE_BYTES_REVERSED_LO : name = "Bytes reversed"; break;
  1278. case IMAGE_FILE_32BIT_MACHINE : name = "32 bit word machine"; break;
  1279. case IMAGE_FILE_DEBUG_STRIPPED : name = "Debug information stripped"; break;
  1280. case IMAGE_FILE_SYSTEM : name = "System"; break;
  1281. case IMAGE_FILE_DLL : name = "DLL"; break;
  1282. case IMAGE_FILE_BYTES_REVERSED_HI : name = ""; break;
  1283. default : name = "RESERVED - UNKNOWN";
  1284. }
  1285. if (*name) {
  1286. dprintf( " %s\n", name);
  1287. }
  1288. }
  1289. }
  1290. if (ImageFileHdr->SizeOfOptionalHeader != 0) {
  1291. char szLinkerVersion[30];
  1292. PrintString(szLinkerVersion,
  1293. DIMA(szLinkerVersion),
  1294. "%u.%02u",
  1295. ImageOptionalHdr->MajorLinkerVersion,
  1296. ImageOptionalHdr->MinorLinkerVersion);
  1297. dprintf(
  1298. "\n"
  1299. "OPTIONAL HEADER VALUES\n"
  1300. "%8hX magic #\n"
  1301. "%8s linker version\n"
  1302. "%8lX size of code\n"
  1303. "%8lX size of initialized data\n"
  1304. "%8lX size of uninitialized data\n"
  1305. "%8lX address of entry point\n"
  1306. "%8lX base of code\n"
  1307. ,
  1308. ImageOptionalHdr->Magic,
  1309. szLinkerVersion,
  1310. ImageOptionalHdr->SizeOfCode,
  1311. ImageOptionalHdr->SizeOfInitializedData,
  1312. ImageOptionalHdr->SizeOfUninitializedData,
  1313. ImageOptionalHdr->AddressOfEntryPoint,
  1314. ImageOptionalHdr->BaseOfCode
  1315. );
  1316. // dprintf("%p base of image\n",
  1317. // ImageOptionalHdr->ImageBase
  1318. // );
  1319. }
  1320. if (dft == dftROM) {
  1321. PIMAGE_ROM_OPTIONAL_HEADER romOptionalHdr;
  1322. romOptionalHdr = (PIMAGE_ROM_OPTIONAL_HEADER) &ImageOptionalHdr;
  1323. dprintf(
  1324. " ----- rom -----\n"
  1325. "%8lX base of bss\n"
  1326. "%8lX gpr mask\n"
  1327. " cpr mask\n"
  1328. " %08lX %08lX %08lX %08lX\n"
  1329. "%8hX gp value\n",
  1330. romOptionalHdr->BaseOfBss,
  1331. romOptionalHdr->GprMask,
  1332. romOptionalHdr->CprMask[0],
  1333. romOptionalHdr->CprMask[1],
  1334. romOptionalHdr->CprMask[2],
  1335. romOptionalHdr->CprMask[3],
  1336. romOptionalHdr->GpValue);
  1337. }
  1338. if ((ImageFileHdr->SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER32)) ||
  1339. (ImageFileHdr->SizeOfOptionalHeader == sizeof(IMAGE_OPTIONAL_HEADER64)))
  1340. {
  1341. char szOSVersion[30];
  1342. char szImageVersion[30];
  1343. char szSubsystemVersion[30];
  1344. switch (ImageOptionalHdr->Subsystem) {
  1345. case IMAGE_SUBSYSTEM_POSIX_CUI : i = 4; break;
  1346. case IMAGE_SUBSYSTEM_WINDOWS_CUI : i = 3; break;
  1347. case IMAGE_SUBSYSTEM_WINDOWS_GUI : i = 2; break;
  1348. case IMAGE_SUBSYSTEM_NATIVE : i = 1; break;
  1349. default : i = 0;
  1350. }
  1351. PrintString(szOSVersion,
  1352. DIMA(szOSVersion),
  1353. "%hu.%02hu",
  1354. ImageOptionalHdr->MajorOperatingSystemVersion,
  1355. ImageOptionalHdr->MinorOperatingSystemVersion);
  1356. PrintString(szImageVersion,
  1357. DIMA(szImageVersion),
  1358. "%hu.%02hu",
  1359. ImageOptionalHdr->MajorImageVersion,
  1360. ImageOptionalHdr->MinorImageVersion);
  1361. PrintString(szSubsystemVersion,
  1362. DIMA(szSubsystemVersion),
  1363. "%hu.%02hu",
  1364. ImageOptionalHdr->MajorSubsystemVersion,
  1365. ImageOptionalHdr->MinorSubsystemVersion);
  1366. dprintf(
  1367. " ----- new -----\n"
  1368. "%p image base\n"
  1369. "%8lX section alignment\n"
  1370. "%8lX file alignment\n"
  1371. "%8hX subsystem (%s)\n"
  1372. "%8s operating system version\n"
  1373. "%8s image version\n"
  1374. "%8s subsystem version\n"
  1375. "%8lX size of image\n"
  1376. "%8lX size of headers\n"
  1377. "%8lX checksum\n",
  1378. ImageOptionalHdr->ImageBase,
  1379. ImageOptionalHdr->SectionAlignment,
  1380. ImageOptionalHdr->FileAlignment,
  1381. ImageOptionalHdr->Subsystem,
  1382. SubsystemName[i],
  1383. szOSVersion,
  1384. szImageVersion,
  1385. szSubsystemVersion,
  1386. ImageOptionalHdr->SizeOfImage,
  1387. ImageOptionalHdr->SizeOfHeaders,
  1388. ImageOptionalHdr->CheckSum);
  1389. dprintf(
  1390. "%p size of stack reserve\n"
  1391. "%p size of stack commit\n"
  1392. "%p size of heap reserve\n"
  1393. "%p size of heap commit\n",
  1394. ImageOptionalHdr->SizeOfStackReserve,
  1395. ImageOptionalHdr->SizeOfStackCommit,
  1396. ImageOptionalHdr->SizeOfHeapReserve,
  1397. ImageOptionalHdr->SizeOfHeapCommit);
  1398. for (i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) {
  1399. if (!DirectoryEntryName[i]) {
  1400. break;
  1401. }
  1402. dprintf( "%8lX [%8lX] address [size] of %s Directory\n",
  1403. ImageOptionalHdr->DataDirectory[i].VirtualAddress,
  1404. ImageOptionalHdr->DataDirectory[i].Size,
  1405. DirectoryEntryName[i]
  1406. );
  1407. }
  1408. dprintf( "\n" );
  1409. }
  1410. }
  1411. VOID
  1412. DumpSectionHeader (
  1413. IN DWORD i,
  1414. IN PIMAGE_SECTION_HEADER Sh
  1415. )
  1416. {
  1417. const char *name;
  1418. char *szUnDName;
  1419. DWORD li, lj;
  1420. WORD memFlags;
  1421. dprintf("\nSECTION HEADER #%hX\n%8.8s name", i, Sh->Name);
  1422. #if 0
  1423. if (Sh->Name[0] == '/') {
  1424. name = SzObjSectionName((char *) Sh->Name, (char *) DumpStringTable);
  1425. dprintf(" (%s)", name);
  1426. }
  1427. #endif
  1428. dprintf( "\n");
  1429. dprintf( "%8lX %s\n"
  1430. "%8lX virtual address\n"
  1431. "%8lX size of raw data\n"
  1432. "%8lX file pointer to raw data\n"
  1433. "%8lX file pointer to relocation table\n",
  1434. Sh->Misc.PhysicalAddress,
  1435. (dft == dftObject) ? "physical address" : "virtual size",
  1436. Sh->VirtualAddress,
  1437. Sh->SizeOfRawData,
  1438. Sh->PointerToRawData,
  1439. Sh->PointerToRelocations);
  1440. dprintf( "%8lX file pointer to line numbers\n"
  1441. "%8hX number of relocations\n"
  1442. "%8hX number of line numbers\n"
  1443. "%8lX flags\n",
  1444. Sh->PointerToLinenumbers,
  1445. Sh->NumberOfRelocations,
  1446. Sh->NumberOfLinenumbers,
  1447. Sh->Characteristics);
  1448. memFlags = 0;
  1449. li = Sh->Characteristics;
  1450. if (dft == dftROM) {
  1451. for (lj = 0L; li; li = li >> 1, lj++) {
  1452. if (li & 1) {
  1453. switch ((li & 1) << lj) {
  1454. case STYP_REG : name = "Regular"; break;
  1455. case STYP_TEXT : name = "Text"; memFlags = 1; break;
  1456. case STYP_INIT : name = "Init Code"; memFlags = 1; break;
  1457. case STYP_RDATA : name = "Data"; memFlags = 2; break;
  1458. case STYP_DATA : name = "Data"; memFlags = 6; break;
  1459. case STYP_LIT8 : name = "Literal 8"; break;
  1460. case STYP_LIT4 : name = "Literal 4"; break;
  1461. case STYP_SDATA : name = "GP Init Data"; memFlags = 6; break;
  1462. case STYP_SBSS : name = "GP Uninit Data"; memFlags = 6; break;
  1463. case STYP_BSS : name = "Uninit Data"; memFlags = 6; break;
  1464. case STYP_LIB : name = "Library"; break;
  1465. case STYP_UCODE : name = "UCode"; break;
  1466. case S_NRELOC_OVFL : name = "Non-Relocatable overlay"; memFlags = 1; break;
  1467. default : name = "RESERVED - UNKNOWN";
  1468. }
  1469. dprintf( " %s\n", name);
  1470. }
  1471. }
  1472. } else {
  1473. // Clear the padding bits
  1474. li &= ~0x00700000;
  1475. for (lj = 0L; li; li = li >> 1, lj++) {
  1476. if (li & 1) {
  1477. switch ((li & 1) << lj) {
  1478. case IMAGE_SCN_TYPE_NO_PAD : name = "No Pad"; break;
  1479. case IMAGE_SCN_CNT_CODE : name = "Code"; break;
  1480. case IMAGE_SCN_CNT_INITIALIZED_DATA : name = "Initialized Data"; break;
  1481. case IMAGE_SCN_CNT_UNINITIALIZED_DATA : name = "Uninitialized Data"; break;
  1482. case IMAGE_SCN_LNK_OTHER : name = "Other"; break;
  1483. case IMAGE_SCN_LNK_INFO : name = "Info"; break;
  1484. case IMAGE_SCN_LNK_REMOVE : name = "Remove"; break;
  1485. case IMAGE_SCN_LNK_COMDAT : name = "Communal"; break;
  1486. case IMAGE_SCN_MEM_DISCARDABLE: name = "Discardable"; break;
  1487. case IMAGE_SCN_MEM_NOT_CACHED: name = "Not Cached"; break;
  1488. case IMAGE_SCN_MEM_NOT_PAGED: name = "Not Paged"; break;
  1489. case IMAGE_SCN_MEM_SHARED : name = "Shared"; break;
  1490. case IMAGE_SCN_MEM_EXECUTE : name = ""; memFlags |= 1; break;
  1491. case IMAGE_SCN_MEM_READ : name = ""; memFlags |= 2; break;
  1492. case IMAGE_SCN_MEM_WRITE : name = ""; memFlags |= 4; break;
  1493. case IMAGE_SCN_MEM_FARDATA : name = "Far Data"; break;
  1494. case IMAGE_SCN_MEM_SYSHEAP : name = "Sys Heap"; break;
  1495. case IMAGE_SCN_MEM_PURGEABLE: name = "Purgeable or 16-Bit"; break;
  1496. case IMAGE_SCN_MEM_LOCKED : name = "Locked"; break;
  1497. case IMAGE_SCN_MEM_PRELOAD : name = "Preload"; break;
  1498. case IMAGE_SCN_MEM_PROTECTED: name = "Protected"; break;
  1499. default : name = "RESERVED - UNKNOWN";
  1500. }
  1501. if (*name) {
  1502. dprintf( " %s\n", name);
  1503. }
  1504. }
  1505. }
  1506. // print alignment
  1507. switch (Sh->Characteristics & 0x00700000) {
  1508. default: name = "(no align specified)"; break;
  1509. case IMAGE_SCN_ALIGN_1BYTES: name = "1 byte align"; break;
  1510. case IMAGE_SCN_ALIGN_2BYTES: name = "2 byte align"; break;
  1511. case IMAGE_SCN_ALIGN_4BYTES: name = "4 byte align"; break;
  1512. case IMAGE_SCN_ALIGN_8BYTES: name = "8 byte align"; break;
  1513. case IMAGE_SCN_ALIGN_16BYTES: name = "16 byte align"; break;
  1514. case IMAGE_SCN_ALIGN_32BYTES: name = "32 byte align"; break;
  1515. case IMAGE_SCN_ALIGN_64BYTES: name = "64 byte align"; break;
  1516. }
  1517. dprintf( " %s\n", name);
  1518. }
  1519. if (memFlags) {
  1520. switch(memFlags) {
  1521. case 1 : name = "Execute Only"; break;
  1522. case 2 : name = "Read Only"; break;
  1523. case 3 : name = "Execute Read"; break;
  1524. case 4 : name = "Write Only"; break;
  1525. case 5 : name = "Execute Write"; break;
  1526. case 6 : name = "Read Write"; break;
  1527. case 7 : name = "Execute Read Write"; break;
  1528. default : name = "Unknown Memory Flags"; break;
  1529. }
  1530. dprintf( " %s\n", name);
  1531. }
  1532. }
  1533. VOID
  1534. DumpDebugDirectory (
  1535. IN PIMAGE_DEBUG_DIRECTORY DebugDir
  1536. )
  1537. {
  1538. BOOL Ok;
  1539. DWORD cb;
  1540. CVDD cv;
  1541. PIMAGE_DEBUG_MISC miscData;
  1542. PIMAGE_DEBUG_MISC miscDataCur;
  1543. ULONG VirtualAddress;
  1544. DWORD len;
  1545. switch (DebugDir->Type){
  1546. case IMAGE_DEBUG_TYPE_COFF:
  1547. dprintf( "\tcoff ");
  1548. break;
  1549. case IMAGE_DEBUG_TYPE_CODEVIEW:
  1550. dprintf( "\tcv ");
  1551. break;
  1552. case IMAGE_DEBUG_TYPE_FPO:
  1553. dprintf( "\tfpo ");
  1554. break;
  1555. case IMAGE_DEBUG_TYPE_MISC:
  1556. dprintf( "\tmisc ");
  1557. break;
  1558. case IMAGE_DEBUG_TYPE_FIXUP:
  1559. dprintf( "\tfixup ");
  1560. break;
  1561. case IMAGE_DEBUG_TYPE_OMAP_TO_SRC:
  1562. dprintf( "\t-> src ");
  1563. break;
  1564. case IMAGE_DEBUG_TYPE_OMAP_FROM_SRC:
  1565. dprintf( "\tsrc -> ");
  1566. break;
  1567. case IMAGE_DEBUG_TYPE_EXCEPTION:
  1568. dprintf( "\tpdata ");
  1569. break;
  1570. default:
  1571. dprintf( "\t(%6lu)", DebugDir->Type);
  1572. break;
  1573. }
  1574. dprintf( "%8x %8x %8x",
  1575. DebugDir->SizeOfData,
  1576. DebugDir->AddressOfRawData,
  1577. DebugDir->PointerToRawData);
  1578. if (DebugDir->PointerToRawData &&
  1579. DebugDir->Type == IMAGE_DEBUG_TYPE_MISC)
  1580. {
  1581. if (!TranslateFilePointerToVirtualAddress(DebugDir->PointerToRawData, &VirtualAddress)) {
  1582. dprintf(" [Debug data not mapped]\n");
  1583. } else {
  1584. len = DebugDir->SizeOfData;
  1585. miscData = (PIMAGE_DEBUG_MISC) malloc(len);
  1586. if (!miscData) {
  1587. goto DebugTypeCodeView;
  1588. }
  1589. __try {
  1590. Ok = ReadMemory(Base + VirtualAddress, miscData, len, &cb);
  1591. if (!Ok || cb != len) {
  1592. dprintf("Can't read debug data\n");
  1593. } else {
  1594. miscDataCur = miscData;
  1595. do {
  1596. if (miscDataCur->DataType == IMAGE_DEBUG_MISC_EXENAME) {
  1597. if (ImageOptionalHdr->MajorLinkerVersion == 2 &&
  1598. ImageOptionalHdr->MinorLinkerVersion < 37) {
  1599. dprintf( "\tImage Name: %s", miscDataCur->Reserved);
  1600. } else {
  1601. dprintf( "\tImage Name: %s", miscDataCur->Data);
  1602. }
  1603. break;
  1604. }
  1605. len -= miscDataCur->Length;
  1606. miscDataCur = (PIMAGE_DEBUG_MISC) ((PCHAR) miscDataCur + miscData->Length);
  1607. } while (len > 0);
  1608. }
  1609. }
  1610. __finally {
  1611. if (miscData) {
  1612. free(miscData);
  1613. }
  1614. }
  1615. }
  1616. }
  1617. DebugTypeCodeView:
  1618. if (DebugDir->PointerToRawData &&
  1619. DebugDir->Type == IMAGE_DEBUG_TYPE_CODEVIEW) {
  1620. if (DebugDir->AddressOfRawData) {
  1621. VirtualAddress = DebugDir->AddressOfRawData;
  1622. }
  1623. if (!DebugDir->AddressOfRawData &&
  1624. !TranslateFilePointerToVirtualAddress(DebugDir->PointerToRawData, &VirtualAddress)) {
  1625. dprintf(" [Debug data not mapped]\n");
  1626. } else {
  1627. len = DebugDir->SizeOfData;
  1628. Ok = ReadMemory(Base + VirtualAddress, &cv, len, &cb);
  1629. if (!Ok || cb != len) {
  1630. dprintf("\tCan't read debug data cb=%lx\n", cb);
  1631. } else {
  1632. if (cv.dwSig == '01BN') {
  1633. dprintf( "\tFormat: NB10, %x, %x, %s", cv.nb10i.sig, cv.nb10i.age, cv.nb10i.szPdb);
  1634. } else if (cv.dwSig == 'SDSR') {
  1635. dprintf( "\tFormat: RSDS, guid, %x, %s", cv.rsdsi.age, cv.rsdsi.szPdb);
  1636. } else {
  1637. dprintf( "\tFormat: UNKNOWN");
  1638. }
  1639. }
  1640. }
  1641. }
  1642. dprintf( "\n");
  1643. }
  1644. VOID
  1645. DumpDebugDirectories (
  1646. PIMAGE_SECTION_HEADER sh
  1647. )
  1648. /*++
  1649. Routine Description:
  1650. Print out the contents of all debug directories
  1651. Arguments:
  1652. sh - Section header for section that contains debug dirs
  1653. Return Value:
  1654. None.
  1655. --*/
  1656. {
  1657. int numDebugDirs;
  1658. IMAGE_DEBUG_DIRECTORY debugDir;
  1659. ULONG64 DebugDirAddr;
  1660. ULONG64 pc;
  1661. DWORD cb;
  1662. BOOL Ok;
  1663. if (dft == dftROM) {
  1664. DebugDirAddr = (Base + sh->VirtualAddress);
  1665. pc = DebugDirAddr;
  1666. Ok = ReadMemory(pc, &debugDir, sizeof(IMAGE_DEBUG_DIRECTORY), &cb);
  1667. if (!Ok || cb != sizeof(IMAGE_DEBUG_DIRECTORY)) {
  1668. dprintf("Can't read debug dir\n");
  1669. return;
  1670. }
  1671. numDebugDirs = 0;
  1672. while (debugDir.Type != 0) {
  1673. numDebugDirs++;
  1674. pc += sizeof(IMAGE_DEBUG_DIRECTORY);
  1675. Ok = ReadMemory(pc, &debugDir, sizeof(IMAGE_DEBUG_DIRECTORY), &cb);
  1676. if (!Ok || cb != sizeof(IMAGE_DEBUG_DIRECTORY)) {
  1677. break;
  1678. }
  1679. }
  1680. } else {
  1681. DebugDirAddr = (Base + ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress);
  1682. numDebugDirs = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size / sizeof(IMAGE_DEBUG_DIRECTORY);
  1683. }
  1684. dprintf("\n\nDebug Directories(%d)\n",numDebugDirs);
  1685. dprintf("\tType Size Address Pointer\n\n");
  1686. pc = DebugDirAddr;
  1687. while (numDebugDirs) {
  1688. Ok = ReadMemory(pc, &debugDir, sizeof(IMAGE_DEBUG_DIRECTORY), &cb);
  1689. if (!Ok || cb != sizeof(IMAGE_DEBUG_DIRECTORY)) {
  1690. dprintf("Can't read debug dir\n");
  1691. break;
  1692. }
  1693. pc += sizeof(IMAGE_DEBUG_DIRECTORY);
  1694. DumpDebugDirectory(&debugDir);
  1695. numDebugDirs--;
  1696. }
  1697. }
  1698. VOID
  1699. dhDumpSections(
  1700. )
  1701. {
  1702. IMAGE_SECTION_HEADER sh;
  1703. const char *p;
  1704. DWORD li;
  1705. DWORD cb;
  1706. BOOL Ok;
  1707. int i, j;
  1708. CHAR szName[IMAGE_SIZEOF_SHORT_NAME + 1];
  1709. for (i = 1; i <= ImageFileHdr->NumberOfSections; i++) {
  1710. sh = SectionHdrs[i-1];
  1711. //szName = SzObjSectionName((char *) sh.Name, (char *) DumpStringTable);
  1712. CopyStrArray(szName, (char *) sh.Name);
  1713. DumpSectionHeader(i, &sh);
  1714. if (dft == dftROM) {
  1715. if (!(ImageFileHdr->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)) {
  1716. // If we're looking at the .rdata section and the symbols
  1717. // aren't stripped, the debug directory must be here.
  1718. if (!strcmp(szName, ".rdata")) {
  1719. DumpDebugDirectories(&sh);
  1720. //DumpDebugData(&sh);
  1721. }
  1722. }
  1723. } else if (dft == dftPE) {
  1724. if ((li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress) != 0) {
  1725. if (li >= sh.VirtualAddress && li < sh.VirtualAddress+sh.SizeOfRawData) {
  1726. DumpDebugDirectories(&sh);
  1727. //DumpDebugData(&sh);
  1728. }
  1729. }
  1730. #if 0
  1731. if (Switch.Dump.PData) {
  1732. li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
  1733. if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) {
  1734. DumpFunctionTable(pimage, rgsym, (char *) DumpStringTable, &sh);
  1735. }
  1736. }
  1737. if (Switch.Dump.Imports) {
  1738. li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
  1739. if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) {
  1740. DumpImports(&sh);
  1741. }
  1742. }
  1743. if (Switch.Dump.Exports) {
  1744. li = ImageOptionalHdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
  1745. if ((li != 0) && (li >= sh.VirtualAddress) && (li < sh.VirtualAddress+sh.SizeOfRawData)) {
  1746. // UNDONE: Is this check really necessary?
  1747. if (ImageFileHdr->Machine != IMAGE_FILE_MACHINE_MPPC_601) {
  1748. DumpExports(&sh);
  1749. }
  1750. }
  1751. }
  1752. #endif
  1753. }
  1754. }
  1755. }
  1756. BOOL
  1757. TranslateFilePointerToVirtualAddress(
  1758. IN ULONG FilePointer,
  1759. OUT PULONG VirtualAddress
  1760. )
  1761. {
  1762. ULONG i;
  1763. PIMAGE_SECTION_HEADER sh;
  1764. *VirtualAddress = 0;
  1765. for (i = 1; i <= NumSections; i++) {
  1766. sh = &SectionHdrs[i-1];
  1767. if (sh->PointerToRawData <= FilePointer &&
  1768. FilePointer < sh->PointerToRawData + sh->SizeOfRawData) {
  1769. *VirtualAddress = FilePointer - sh->PointerToRawData + sh->VirtualAddress;
  1770. return true;
  1771. }
  1772. }
  1773. return false;
  1774. }