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.

1943 lines
55 KiB

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