Team Fortress 2 Source Code as on 22/4/2020
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.

583 lines
17 KiB

  1. //--------------------
  2. // PROGRAM: PEDUMP
  3. // FILE: COMMON.C
  4. // AUTHOR: Matt Pietrek - 1993
  5. //--------------------
  6. #include <windows.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include "common.h"
  10. PIMAGE_SYMBOL PCOFFSymbolTable = 0; // RVA to COFF symbol table (if present)
  11. DWORD COFFSymbolCount = 0; // Number of symbols in COFF symbol table
  12. typedef struct
  13. {
  14. WORD flag;
  15. PSTR name;
  16. } WORD_FLAG_DESCRIPTIONS;
  17. typedef struct
  18. {
  19. DWORD flag;
  20. PSTR name;
  21. } DWORD_FLAG_DESCRIPTIONS;
  22. // Bitfield values and names for the IMAGE_FILE_HEADER flags
  23. WORD_FLAG_DESCRIPTIONS ImageFileHeaderCharacteristics[] =
  24. {
  25. { IMAGE_FILE_RELOCS_STRIPPED, "RELOCS_STRIPPED" },
  26. { IMAGE_FILE_EXECUTABLE_IMAGE, "EXECUTABLE_IMAGE" },
  27. { IMAGE_FILE_LINE_NUMS_STRIPPED, "LINE_NUMS_STRIPPED" },
  28. { IMAGE_FILE_LOCAL_SYMS_STRIPPED, "LOCAL_SYMS_STRIPPED" },
  29. { IMAGE_FILE_MINIMAL_OBJECT, "MINIMAL_OBJECT" },
  30. { IMAGE_FILE_UPDATE_OBJECT, "UPDATE_OBJECT" },
  31. { IMAGE_FILE_16BIT_MACHINE, "16BIT_MACHINE" },
  32. { IMAGE_FILE_BYTES_REVERSED_LO, "BYTES_REVERSED_LO" },
  33. { IMAGE_FILE_32BIT_MACHINE, "32BIT_MACHINE" },
  34. { IMAGE_FILE_PATCH, "PATCH" },
  35. { IMAGE_FILE_SYSTEM, "SYSTEM" },
  36. { IMAGE_FILE_DLL, "DLL" },
  37. { IMAGE_FILE_BYTES_REVERSED_HI, "BYTES_REVERSED_HI" }
  38. };
  39. #define NUMBER_IMAGE_HEADER_FLAGS \
  40. (sizeof(ImageFileHeaderCharacteristics) / sizeof(WORD_FLAG_DESCRIPTIONS))
  41. //
  42. // Dump the IMAGE_FILE_HEADER for a PE file or an OBJ
  43. //
  44. void DumpHeader(PIMAGE_FILE_HEADER pImageFileHeader)
  45. {
  46. UINT headerFieldWidth = 30;
  47. UINT i;
  48. char *szMachine;
  49. printf("File Header\n");
  50. switch( pImageFileHeader->Machine )
  51. {
  52. case IMAGE_FILE_MACHINE_I386: szMachine = "i386"; break;
  53. case IMAGE_FILE_MACHINE_I860: szMachine = "i860"; break;
  54. case IMAGE_FILE_MACHINE_R3000: szMachine = "R3000"; break;
  55. case IMAGE_FILE_MACHINE_R4000: szMachine = "R4000"; break;
  56. case IMAGE_FILE_MACHINE_ALPHA: szMachine = "alpha"; break;
  57. default: szMachine = "unknown"; break;
  58. }
  59. printf(" %-*s%04X (%s)\n", headerFieldWidth, "Machine:",
  60. pImageFileHeader->Machine, szMachine);
  61. printf(" %-*s%04X\n", headerFieldWidth, "Number of Sections:",
  62. pImageFileHeader->NumberOfSections);
  63. printf(" %-*s%08X\n", headerFieldWidth, "TimeDateStamp:",
  64. pImageFileHeader->TimeDateStamp);
  65. printf(" %-*s%08X\n", headerFieldWidth, "PointerToSymbolTable:",
  66. pImageFileHeader->PointerToSymbolTable);
  67. printf(" %-*s%08X\n", headerFieldWidth, "NumberOfSymbols:",
  68. pImageFileHeader->NumberOfSymbols);
  69. printf(" %-*s%04X\n", headerFieldWidth, "SizeOfOptionalHeader:",
  70. pImageFileHeader->SizeOfOptionalHeader);
  71. printf(" %-*s%04X\n", headerFieldWidth, "Characteristics:",
  72. pImageFileHeader->Characteristics);
  73. for ( i=0; i < NUMBER_IMAGE_HEADER_FLAGS; i++ )
  74. {
  75. if ( pImageFileHeader->Characteristics &
  76. ImageFileHeaderCharacteristics[i].flag )
  77. printf( " %s\n", ImageFileHeaderCharacteristics[i].name );
  78. }
  79. }
  80. // Bitfield values and names for the DllCharacteritics flags
  81. WORD_FLAG_DESCRIPTIONS DllCharacteristics[] =
  82. {
  83. { IMAGE_LIBRARY_PROCESS_INIT, "PROCESS_INIT" },
  84. { IMAGE_LIBRARY_PROCESS_TERM, "PROCESS_TERM" },
  85. { IMAGE_LIBRARY_THREAD_INIT, "THREAD_INIT" },
  86. { IMAGE_LIBRARY_THREAD_TERM, "THREAD_TERM" },
  87. };
  88. #define NUMBER_DLL_CHARACTERISTICS \
  89. (sizeof(DllCharacteristics) / sizeof(WORD_FLAG_DESCRIPTIONS))
  90. // Bitfield values and names for the LoaderFlags flags
  91. DWORD_FLAG_DESCRIPTIONS LoaderFlags[] =
  92. {
  93. { IMAGE_LOADER_FLAGS_BREAK_ON_LOAD, "BREAK_ON_LOAD" },
  94. { IMAGE_LOADER_FLAGS_DEBUG_ON_LOAD, "DEBUG_ON_LOAD" }
  95. };
  96. #define NUMBER_LOADER_FLAGS \
  97. (sizeof(LoaderFlags) / sizeof(DWORD_FLAG_DESCRIPTIONS))
  98. // Names of the data directory elements that are defined
  99. char *ImageDirectoryNames[] = {
  100. "EXPORT", "IMPORT", "RESOURCE", "EXCEPTION", "SECURITY", "BASERELOC",
  101. "DEBUG", "COPYRIGHT", "GLOBALPTR", "TLS", "LOAD_CONFIG" };
  102. #define NUMBER_IMAGE_DIRECTORY_ENTRYS \
  103. (sizeof(ImageDirectoryNames)/sizeof(char *))
  104. //
  105. // Dump the IMAGE_OPTIONAL_HEADER from a PE file
  106. //
  107. void DumpOptionalHeader(PIMAGE_OPTIONAL_HEADER optionalHeader)
  108. {
  109. UINT width = 30;
  110. char *s;
  111. UINT i;
  112. printf("Optional Header\n");
  113. printf(" %-*s%04X\n", width, "Magic", optionalHeader->Magic);
  114. printf(" %-*s%u.%02u\n", width, "linker version",
  115. optionalHeader->MajorLinkerVersion,
  116. optionalHeader->MinorLinkerVersion);
  117. printf(" %-*s%X\n", width, "size of code", optionalHeader->SizeOfCode);
  118. printf(" %-*s%X\n", width, "size of initialized data",
  119. optionalHeader->SizeOfInitializedData);
  120. printf(" %-*s%X\n", width, "size of uninitialized data",
  121. optionalHeader->SizeOfUninitializedData);
  122. printf(" %-*s%X\n", width, "entrypoint RVA",
  123. optionalHeader->AddressOfEntryPoint);
  124. printf(" %-*s%X\n", width, "base of code", optionalHeader->BaseOfCode);
  125. printf(" %-*s%X\n", width, "base of data", optionalHeader->BaseOfData);
  126. printf(" %-*s%X\n", width, "image base", optionalHeader->ImageBase);
  127. printf(" %-*s%X\n", width, "section align",
  128. optionalHeader->SectionAlignment);
  129. printf(" %-*s%X\n", width, "file align", optionalHeader->FileAlignment);
  130. printf(" %-*s%u.%02u\n", width, "required OS version",
  131. optionalHeader->MajorOperatingSystemVersion,
  132. optionalHeader->MinorOperatingSystemVersion);
  133. printf(" %-*s%u.%02u\n", width, "image version",
  134. optionalHeader->MajorImageVersion,
  135. optionalHeader->MinorImageVersion);
  136. printf(" %-*s%u.%02u\n", width, "subsystem version",
  137. optionalHeader->MajorSubsystemVersion,
  138. optionalHeader->MinorSubsystemVersion);
  139. printf(" %-*s%X\n", width, "Reserved1", optionalHeader->Reserved1);
  140. printf(" %-*s%X\n", width, "size of image", optionalHeader->SizeOfImage);
  141. printf(" %-*s%X\n", width, "size of headers",
  142. optionalHeader->SizeOfHeaders);
  143. printf(" %-*s%X\n", width, "checksum", optionalHeader->CheckSum);
  144. switch( optionalHeader->Subsystem )
  145. {
  146. case IMAGE_SUBSYSTEM_NATIVE: s = "Native"; break;
  147. case IMAGE_SUBSYSTEM_WINDOWS_GUI: s = "Windows GUI"; break;
  148. case IMAGE_SUBSYSTEM_WINDOWS_CUI: s = "Windows character"; break;
  149. case IMAGE_SUBSYSTEM_OS2_CUI: s = "OS/2 character"; break;
  150. case IMAGE_SUBSYSTEM_POSIX_CUI: s = "Posix character"; break;
  151. default: s = "unknown";
  152. }
  153. printf(" %-*s%04X (%s)\n", width, "Subsystem",
  154. optionalHeader->Subsystem, s);
  155. printf(" %-*s%04X\n", width, "DLL flags",
  156. optionalHeader->DllCharacteristics);
  157. for ( i=0; i < NUMBER_DLL_CHARACTERISTICS; i++ )
  158. {
  159. if ( optionalHeader->DllCharacteristics &
  160. DllCharacteristics[i].flag )
  161. printf( " %s", DllCharacteristics[i].name );
  162. }
  163. if ( optionalHeader->DllCharacteristics )
  164. printf("\n");
  165. printf(" %-*s%X\n", width, "stack reserve size",
  166. optionalHeader->SizeOfStackReserve);
  167. printf(" %-*s%X\n", width, "stack commit size",
  168. optionalHeader->SizeOfStackCommit);
  169. printf(" %-*s%X\n", width, "heap reserve size",
  170. optionalHeader->SizeOfHeapReserve);
  171. printf(" %-*s%X\n", width, "heap commit size",
  172. optionalHeader->SizeOfHeapCommit);
  173. printf(" %-*s%08X\n", width, "loader flags",
  174. optionalHeader->LoaderFlags);
  175. for ( i=0; i < NUMBER_LOADER_FLAGS; i++ )
  176. {
  177. if ( optionalHeader->LoaderFlags &
  178. LoaderFlags[i].flag )
  179. printf( " %s", LoaderFlags[i].name );
  180. }
  181. if ( optionalHeader->LoaderFlags )
  182. printf("\n");
  183. printf(" %-*s%X\n", width, "RVAs & sizes",
  184. optionalHeader->NumberOfRvaAndSizes);
  185. printf("\nData Directory\n");
  186. for ( i=0; i < optionalHeader->NumberOfRvaAndSizes; i++)
  187. {
  188. printf( " %-12s rva: %08X size: %08X\n",
  189. (i >= NUMBER_IMAGE_DIRECTORY_ENTRYS)
  190. ? "unused" : ImageDirectoryNames[i],
  191. optionalHeader->DataDirectory[i].VirtualAddress,
  192. optionalHeader->DataDirectory[i].Size);
  193. }
  194. }
  195. // Bitfield values and names for the IMAGE_SECTION_HEADER flags
  196. DWORD_FLAG_DESCRIPTIONS SectionCharacteristics[] =
  197. {
  198. { IMAGE_SCN_CNT_CODE, "CODE" },
  199. { IMAGE_SCN_CNT_INITIALIZED_DATA, "INITIALIZED_DATA" },
  200. { IMAGE_SCN_CNT_UNINITIALIZED_DATA, "UNINITIALIZED_DATA" },
  201. { IMAGE_SCN_LNK_INFO, "LNK_INFO" },
  202. { IMAGE_SCN_LNK_OVERLAY, "LNK_OVERLAY" },
  203. { IMAGE_SCN_LNK_REMOVE, "LNK_REMOVE" },
  204. { IMAGE_SCN_LNK_COMDAT, "LNK_COMDAT" },
  205. { IMAGE_SCN_MEM_DISCARDABLE, "MEM_DISCARDABLE" },
  206. { IMAGE_SCN_MEM_NOT_CACHED, "MEM_NOT_CACHED" },
  207. { IMAGE_SCN_MEM_NOT_PAGED, "MEM_NOT_PAGED" },
  208. { IMAGE_SCN_MEM_SHARED, "MEM_SHARED" },
  209. { IMAGE_SCN_MEM_EXECUTE, "MEM_EXECUTE" },
  210. { IMAGE_SCN_MEM_READ, "MEM_READ" },
  211. { IMAGE_SCN_MEM_WRITE, "MEM_WRITE" },
  212. };
  213. #define NUMBER_SECTION_CHARACTERISTICS \
  214. (sizeof(SectionCharacteristics) / sizeof(DWORD_FLAG_DESCRIPTIONS))
  215. //
  216. // Dump the section table from a PE file or an OBJ
  217. //
  218. void DumpSectionTable(PIMAGE_SECTION_HEADER section,
  219. unsigned cSections,
  220. BOOL IsEXE)
  221. {
  222. unsigned i, j;
  223. printf("Section Table\n");
  224. for ( i=1; i <= cSections; i++, section++ )
  225. {
  226. printf( " %02X %-8.8s %s: %08X VirtAddr: %08X\n",
  227. i, section->Name,
  228. IsEXE ? "VirtSize" : "PhysAddr",
  229. section->Misc.VirtualSize, section->VirtualAddress);
  230. printf( " raw data offs: %08X raw data size: %08X\n",
  231. section->PointerToRawData, section->SizeOfRawData );
  232. printf( " relocation offs: %08X relocations: %08X\n",
  233. section->PointerToRelocations, section->NumberOfRelocations );
  234. printf( " line # offs: %08X line #'s: %08X\n",
  235. section->PointerToLinenumbers, section->NumberOfLinenumbers );
  236. printf( " characteristics: %08X\n", section->Characteristics);
  237. printf(" ");
  238. for ( j=0; j < NUMBER_SECTION_CHARACTERISTICS; j++ )
  239. {
  240. if ( section->Characteristics &
  241. SectionCharacteristics[j].flag )
  242. printf( " %s", SectionCharacteristics[j].name );
  243. }
  244. printf("\n\n");
  245. }
  246. }
  247. //
  248. // Used by the DumpSymbolTable() routine. It purpose is to filter out
  249. // the non-normal section numbers and give them meaningful names.
  250. //
  251. void GetSectionName(WORD section, PSTR buffer, unsigned cbBuffer)
  252. {
  253. char tempbuffer[10];
  254. switch ( (SHORT)section )
  255. {
  256. case IMAGE_SYM_UNDEFINED: strcpy(tempbuffer, "UNDEF"); break;
  257. case IMAGE_SYM_ABSOLUTE: strcpy(tempbuffer, "ABS "); break;
  258. case IMAGE_SYM_DEBUG: strcpy(tempbuffer, "DEBUG"); break;
  259. default: wsprintf(tempbuffer, "%-5X", section);
  260. }
  261. strncpy(buffer, tempbuffer, cbBuffer-1);
  262. }
  263. // The names of the first group of possible symbol table storage classes
  264. char * SzStorageClass1[] = {
  265. "NULL","AUTOMATIC","EXTERNAL","STATIC","REGISTER","EXTERNAL_DEF","LABEL",
  266. "UNDEFINED_LABEL","MEMBER_OF_STRUCT","ARGUMENT","STRUCT_TAG",
  267. "MEMBER_OF_UNION","UNION_TAG","TYPE_DEFINITION","UNDEFINED_STATIC",
  268. "ENUM_TAG","MEMBER_OF_ENUM","REGISTER_PARAM","BIT_FIELD"
  269. };
  270. // The names of the second group of possible symbol table storage classes
  271. char * SzStorageClass2[] = {
  272. "BLOCK","FUNCTION","END_OF_STRUCT","FILE","SECTION","WEAK_EXTERNAL"
  273. };
  274. //
  275. // Given a symbol storage class value, return a descriptive ASCII string
  276. //
  277. PSTR GetSZStorageClass(BYTE storageClass)
  278. {
  279. if ( storageClass <= IMAGE_SYM_CLASS_BIT_FIELD )
  280. return SzStorageClass1[storageClass];
  281. else if ( (storageClass >= IMAGE_SYM_CLASS_BLOCK)
  282. && (storageClass <= IMAGE_SYM_CLASS_WEAK_EXTERNAL) )
  283. return SzStorageClass2[storageClass-IMAGE_SYM_CLASS_BLOCK];
  284. else
  285. return "???";
  286. }
  287. //
  288. // Dumps the auxillary symbol for a regular symbol. It takes a pointer
  289. // to the regular symbol, since the routine needs the information in
  290. // that record.
  291. //
  292. void DumpAuxSymbols(PIMAGE_SYMBOL pSymbolTable)
  293. {
  294. PIMAGE_AUX_SYMBOL auxSym;
  295. auxSym = (PIMAGE_AUX_SYMBOL)(pSymbolTable+1);
  296. if ( pSymbolTable->StorageClass == IMAGE_SYM_CLASS_FILE )
  297. printf(" * %s\n", auxSym);
  298. else if ( (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_EXTERNAL) )
  299. {
  300. if ( (pSymbolTable->Type & 0xF0) == (IMAGE_SYM_DTYPE_FUNCTION << 4))
  301. {
  302. printf(" * tag: %04X size: %04X Line #'s: %08X next fn: %04X\n",
  303. auxSym->Sym.TagIndex, auxSym->Sym.Misc.TotalSize,
  304. auxSym->Sym.FcnAry.Function.PointerToLinenumber,
  305. auxSym->Sym.FcnAry.Function.PointerToNextFunction);
  306. }
  307. }
  308. else if ( (pSymbolTable->StorageClass == IMAGE_SYM_CLASS_STATIC) )
  309. {
  310. printf(
  311. " * Section: %04X Len: %05X Relocs: %04X LineNums: %04X\n",
  312. auxSym->Section.Number, auxSym->Section.Length,
  313. auxSym->Section.NumberOfRelocations,
  314. auxSym->Section.NumberOfLinenumbers);
  315. }
  316. }
  317. //
  318. // Given a COFF symbol table index, look up its name. This function assumes
  319. // that the COFFSymbolCount and PCOFFSymbolTable variables have been already
  320. // set up.
  321. //
  322. BOOL LookupSymbolName(DWORD index, PSTR buffer, UINT length)
  323. {
  324. PSTR stringTable;
  325. if ( index >= COFFSymbolCount )
  326. return FALSE;
  327. if ( PCOFFSymbolTable == 0 )
  328. return FALSE;
  329. if ( PCOFFSymbolTable[index].N.Name.Short != 0 )
  330. {
  331. strncpy(buffer, PCOFFSymbolTable[index].N.ShortName, min(8,length));
  332. buffer[8] = 0;
  333. }
  334. else
  335. {
  336. stringTable = (PSTR)&PCOFFSymbolTable[COFFSymbolCount];
  337. strncpy(buffer,
  338. stringTable + PCOFFSymbolTable[index].N.Name.Long, length);
  339. buffer[length-1] = 0;
  340. }
  341. return TRUE;
  342. }
  343. //
  344. // Dumps a COFF symbol table from an EXE or OBJ
  345. //
  346. void DumpSymbolTable(PIMAGE_SYMBOL pSymbolTable, unsigned cSymbols)
  347. {
  348. unsigned i;
  349. PSTR stringTable;
  350. char sectionName[10];
  351. printf("Symbol Table - %X entries (* = auxillary symbol)\n", cSymbols);
  352. printf(
  353. "Indx Name Value Section cAux Type Storage\n"
  354. "---- -------------------- -------- ---------- ----- ------- --------\n");
  355. // The string table apparently starts right after the symbol table
  356. stringTable = (PSTR)&pSymbolTable[cSymbols];
  357. for ( i=0; i < cSymbols; i++ )
  358. {
  359. printf("%04X ", i);
  360. if ( pSymbolTable->N.Name.Short != 0 )
  361. printf("%-20.8s", pSymbolTable->N.ShortName);
  362. else
  363. printf("%-20s", stringTable + pSymbolTable->N.Name.Long);
  364. printf(" %08X", pSymbolTable->Value);
  365. GetSectionName(pSymbolTable->SectionNumber, sectionName,
  366. sizeof(sectionName));
  367. printf(" sect:%s aux:%X type:%02X st:%s\n",
  368. sectionName,
  369. pSymbolTable->NumberOfAuxSymbols,
  370. pSymbolTable->Type,
  371. GetSZStorageClass(pSymbolTable->StorageClass) );
  372. if ( pSymbolTable->NumberOfAuxSymbols )
  373. DumpAuxSymbols(pSymbolTable);
  374. // Take into account any aux symbols
  375. i += pSymbolTable->NumberOfAuxSymbols;
  376. pSymbolTable += pSymbolTable->NumberOfAuxSymbols;
  377. pSymbolTable++;
  378. }
  379. }
  380. //
  381. // Given a section name, look it up in the section table and return a
  382. // pointer to the start of its raw data area.
  383. //
  384. LPVOID GetSectionPtr(PSTR name, PIMAGE_NT_HEADERS pNTHeader, DWORD imageBase)
  385. {
  386. PIMAGE_SECTION_HEADER section;
  387. unsigned i;
  388. section = (PIMAGE_SECTION_HEADER)(pNTHeader+1);
  389. for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  390. {
  391. if ( strnicmp(section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0 )
  392. return (LPVOID)(section->PointerToRawData + imageBase);
  393. }
  394. return 0;
  395. }
  396. //
  397. // Given a section name, look it up in the section table and return a
  398. // pointer to its IMAGE_SECTION_HEADER
  399. //
  400. PIMAGE_SECTION_HEADER GetSectionHeader(PSTR name, PIMAGE_NT_HEADERS pNTHeader)
  401. {
  402. PIMAGE_SECTION_HEADER section;
  403. unsigned i;
  404. section = (PIMAGE_SECTION_HEADER)(pNTHeader+1);
  405. for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
  406. {
  407. if ( strnicmp(section->Name, name, IMAGE_SIZEOF_SHORT_NAME) == 0 )
  408. return section;
  409. }
  410. return 0;
  411. }
  412. //
  413. // Do a hexadecimal dump of the raw data for all the sections. You
  414. // could just dump one section by adjusting the PIMAGE_SECTION_HEADER
  415. // and cSections parameters
  416. //
  417. void DumpRawSectionData(PIMAGE_SECTION_HEADER section,
  418. PVOID base,
  419. unsigned cSections)
  420. {
  421. unsigned i;
  422. char name[IMAGE_SIZEOF_SHORT_NAME + 1];
  423. printf("Section Hex Dumps\n");
  424. for ( i=0; i < cSections; i++, section++ )
  425. {
  426. // Make a copy of the section name so that we can ensure that
  427. // it's null-terminated
  428. memcpy(name, section->Name, IMAGE_SIZEOF_SHORT_NAME);
  429. name[IMAGE_SIZEOF_SHORT_NAME] = 0;
  430. // Don't dump sections that don't exist in the file!
  431. if ( section->PointerToRawData == 0 )
  432. continue;
  433. printf( "section %02X (%s) size: %08X file offs: %08X\n",
  434. i, name, section->SizeOfRawData, section->PointerToRawData);
  435. HexDump( MakePtr(PBYTE, base, section->PointerToRawData),
  436. section->SizeOfRawData );
  437. printf("\n");
  438. }
  439. }
  440. //
  441. // Dump a range of line numbers from the COFF debug information
  442. //
  443. void DumpLineNumbers(PIMAGE_LINENUMBER pln, DWORD count)
  444. {
  445. char buffer[64];
  446. DWORD i;
  447. printf("Line Numbers\n");
  448. for (i=0; i < count; i++)
  449. {
  450. if ( pln->Linenumber == 0 ) // A symbol table index
  451. {
  452. buffer[0] = 0;
  453. LookupSymbolName(pln->Type.SymbolTableIndex, buffer,
  454. sizeof(buffer));
  455. printf("SymIndex: %X (%s)\n", pln->Type.SymbolTableIndex,
  456. buffer);
  457. }
  458. else // A regular line number
  459. printf(" Addr: %05X Line: %04X\n",
  460. pln->Type.VirtualAddress, pln->Linenumber);
  461. pln++;
  462. }
  463. }
  464. // Number of hex values displayed per line
  465. #define HEX_DUMP_WIDTH 16
  466. //
  467. // Dump a region of memory in a hexadecimal format
  468. //
  469. void HexDump(PBYTE ptr, DWORD length)
  470. {
  471. char buffer[256];
  472. PSTR buffPtr;
  473. unsigned cOutput, i;
  474. DWORD bytesToGo=length;
  475. while ( bytesToGo )
  476. {
  477. cOutput = bytesToGo >= HEX_DUMP_WIDTH ? HEX_DUMP_WIDTH : bytesToGo;
  478. buffPtr = buffer;
  479. buffPtr += wsprintf(buffPtr, "%08X: ", length-bytesToGo );
  480. for ( i=0; i < HEX_DUMP_WIDTH; i++ )
  481. {
  482. buffPtr += wsprintf(buffPtr,
  483. i < cOutput ? "%02X " : " ",
  484. *(ptr+i) );
  485. // Put an extra space between the 1st and 2nd half of the bytes
  486. // on each line.
  487. if ( i == (HEX_DUMP_WIDTH/2)-1 )
  488. buffPtr += wsprintf(buffPtr, " ");
  489. }
  490. for ( i=0; i < cOutput; i++ )
  491. {
  492. char c;
  493. c = '.';
  494. if ( isascii(*(ptr + i)) )
  495. c = isprint(*(ptr + i)) ? *(ptr + i) : '.';
  496. buffPtr += wsprintf(buffPtr, "%c", c);
  497. }
  498. puts(buffer); // Can't use printf(), since there may be a '%'
  499. // in the string.
  500. bytesToGo -= cOutput;
  501. ptr += HEX_DUMP_WIDTH;
  502. }
  503. }