2 * CVDump - Parses through a Visual Studio .DBG file in CodeView 4 format
3 * and dumps the info to STDOUT in a human-readable format
5 * Copyright 2000 John R. Sheets
15 DWORD g_dwStartOfCodeView
= 0;
17 int g_exe_mode
= TRUE
;
18 IMAGE_DOS_HEADER g_doshdr
;
19 IMAGE_SEPARATE_DEBUG_HEADER g_dbghdr
;
20 IMAGE_NT_HEADERS g_nthdr
;
22 IMAGE_SECTION_HEADER
*g_secthdrs
= NULL
;
26 IMAGE_DEBUG_DIRECTORY
*g_debugdirs
= NULL
;
28 OMFDirHeader g_cvHeader
;
29 OMFDirEntry
*g_cvEntries
= NULL
;
30 int g_module_count
= 0;
31 OMFModuleFull
*g_cvModules
= NULL
;
33 void PrintFilePos (FILE *file
)
36 printf (" *** Current file position = %lx\n", ftell (file
));
40 /* Calculate the file offset, based on the RVA.
42 DWORD
GetOffsetFromRVA (DWORD rva
)
49 /* Assumes all RVA's in the section headers are sorted in increasing
50 * order (which should be the case).
52 for (i
= g_numsects
- 1; i
>= 0; i
--)
54 sectbegin
= g_secthdrs
[i
].VirtualAddress
;
56 printf ("iter = %d, rva = 0x%lx, sectbegin = 0x%lx\n", i
, rva
, sectbegin
);
62 /* Calculate the difference between the section's RVA and file position.
64 offset
= g_secthdrs
[i
].VirtualAddress
- g_secthdrs
[i
].PointerToRawData
;
66 /* Calculate the actual file position.
68 filepos
= rva
- offset
;
71 printf (">>> Found RVA 0x%lx in section %d, at 0x%lx (section offset = 0x%lx)\n",
72 rva
, i
, filepos
, offset
);
78 int DumpFileHeaders (FILE *debugfile
)
82 hdrtype
= GetHeaderType (debugfile
);
84 if (hdrtype
== CV_DOS
)
86 if (!ReadDOSFileHeader (debugfile
, &g_doshdr
))
89 printf ("\n============================================================\n");
90 printf (" DOS FILE HEADER\n");
91 printf ("============================================================\n");
93 printf ("Magic Signature = [0x%4x]\n", g_doshdr
.e_magic
);
94 printf ("e_cblp = [0x%4x]\n", g_doshdr
.e_cblp
);
95 printf ("e_cp = [0x%4x]\n", g_doshdr
.e_cp
);
96 printf ("e_cric = [0x%4x]\n", g_doshdr
.e_crlc
);
97 printf ("e_cparhdr = [0x%4x]\n", g_doshdr
.e_cparhdr
);
98 printf ("e_minalloc = [0x%4x]\n", g_doshdr
.e_minalloc
);
99 printf ("e_maxalloc = [0x%4x]\n", g_doshdr
.e_maxalloc
);
100 printf ("e_ss = [0x%4x]\n", g_doshdr
.e_ss
);
101 printf ("e_sp = [0x%4x]\n", g_doshdr
.e_sp
);
102 printf ("e_csum = [0x%4x]\n", g_doshdr
.e_csum
);
103 printf ("e_ip = [0x%4x]\n", g_doshdr
.e_ip
);
104 printf ("e_cs = [0x%4x]\n", g_doshdr
.e_cs
);
105 printf ("e_lfarlc = [0x%4x]\n", g_doshdr
.e_lfarlc
);
106 printf ("e_ovno = [0x%4x]\n", g_doshdr
.e_ovno
);
107 printf ("e_res = [0x%4x ...]\n", g_doshdr
.e_res
[0]); /* worth FIXME? */
108 printf ("e_oemid = [0x%4x]\n", g_doshdr
.e_oemid
);
109 printf ("e_oeminfo = [0x%4x]\n", g_doshdr
.e_oeminfo
);
110 printf ("e_res2 = [0x%4x ...]\n", g_doshdr
.e_res2
[0]); /* worth FIXME? */
111 printf ("e_lfanew = [0x%8lx]\n", g_doshdr
.e_lfanew
);
113 /* Roll forward to next type */
114 hdrtype
= GetHeaderType (debugfile
);
117 if (hdrtype
== CV_NT
)
119 if (!ReadPEFileHeader (debugfile
, &g_nthdr
))
122 printf ("\n============================================================\n");
123 printf (" PE EXECUTABLE FILE HEADER\n");
124 printf ("============================================================\n");
126 printf ("Signature = [0x%8lx]\n", g_nthdr
.Signature
);
127 printf ("Machine = [0x%4x]\n", g_nthdr
.FileHeader
.Machine
);
128 printf ("# of Sections = [0x%4x]\n", g_nthdr
.FileHeader
.NumberOfSections
);
129 printf ("Time/Date Stamp = [0x%08lx]\n", g_nthdr
.FileHeader
.TimeDateStamp
);
130 printf ("Pointer to Symbol Table = [0x%8lx]\n", g_nthdr
.FileHeader
.PointerToSymbolTable
);
131 printf ("# of Symbols = [0x%8lx]\n", g_nthdr
.FileHeader
.NumberOfSymbols
);
132 printf ("Size of Opt. Hdr = [0x%4x]\n", g_nthdr
.FileHeader
.SizeOfOptionalHeader
);
133 printf ("Characteristics = [0x%4x]\n", g_nthdr
.FileHeader
.Characteristics
);
135 printf ("\n============================================================\n");
136 printf (" NT FILE HEADER\n");
137 printf ("============================================================\n");
139 printf ("Magic = [0x%4x]\n", g_nthdr
.OptionalHeader
.Magic
);
140 printf ("Linker Version = %d.%d\n", g_nthdr
.OptionalHeader
.MajorLinkerVersion
,
141 g_nthdr
.OptionalHeader
.MinorLinkerVersion
);
142 printf ("Size of Code = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfCode
);
143 printf ("Init. Data = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfInitializedData
);
144 printf ("Uninit. Data = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfUninitializedData
);
145 printf ("Entry Point = [0x%8lx]\n", g_nthdr
.OptionalHeader
.AddressOfEntryPoint
);
146 printf ("Base of Code = [0x%8lx]\n", g_nthdr
.OptionalHeader
.BaseOfCode
);
147 printf ("Base of Data = [0x%8lx]\n", g_nthdr
.OptionalHeader
.BaseOfData
);
149 printf ("\n============================================================\n");
150 printf (" NT OPTIONAL FILE HEADER\n");
151 printf ("============================================================\n");
153 printf ("Image Base = [0x%8lx]\n", g_nthdr
.OptionalHeader
.ImageBase
);
154 printf ("Section Alignment = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SectionAlignment
);
155 printf ("File Alignment = [0x%8lx]\n", g_nthdr
.OptionalHeader
.FileAlignment
);
156 printf ("OS Version = %d.%d\n", g_nthdr
.OptionalHeader
.MajorOperatingSystemVersion
,
157 g_nthdr
.OptionalHeader
.MinorOperatingSystemVersion
);
158 printf ("Image Version = %d.%d\n", g_nthdr
.OptionalHeader
.MajorImageVersion
,
159 g_nthdr
.OptionalHeader
.MinorImageVersion
);
160 printf ("Subsystem Version = %d.%d\n", g_nthdr
.OptionalHeader
.MajorSubsystemVersion
,
161 g_nthdr
.OptionalHeader
.MinorSubsystemVersion
);
162 printf ("Size of Image = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfImage
);
163 printf ("Size of Headers = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfHeaders
);
164 printf ("Checksum = [0x%8lx]\n", g_nthdr
.OptionalHeader
.CheckSum
);
165 printf ("Subsystem = [0x%4x]\n", g_nthdr
.OptionalHeader
.Subsystem
);
166 printf ("DLL Characteristics = [0x%4x]\n", g_nthdr
.OptionalHeader
.DllCharacteristics
);
167 printf ("Size of Stack Reserve = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfStackReserve
);
168 printf ("Size of Stack Commit = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfStackCommit
);
169 printf ("Size of Heap Reserve = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfHeapReserve
);
170 printf ("Size of Heap Commit = [0x%8lx]\n", g_nthdr
.OptionalHeader
.SizeOfHeapCommit
);
171 printf ("Loader Flags = [0x%8lx]\n", g_nthdr
.OptionalHeader
.LoaderFlags
);
172 printf ("# of RVA = [0x%8lx]\n", g_nthdr
.OptionalHeader
.NumberOfRvaAndSizes
);
174 printf ("\n============================================================\n");
175 printf (" RVA (RELATIVE VIRTUAL ADDRESS) TABLE\n");
176 printf ("============================================================\n");
178 printf ("NAME RVA SIZE\n");
179 printf ("Export [0x%8lx] [0x%8lx]\n",
180 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].VirtualAddress
,
181 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT
].Size
);
182 printf ("Import [0x%8lx] [0x%8lx]\n",
183 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].VirtualAddress
,
184 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IMPORT
].Size
);
185 printf ("Resource [0x%8lx] [0x%8lx]\n",
186 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].VirtualAddress
,
187 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_RESOURCE
].Size
);
188 printf ("Exception [0x%8lx] [0x%8lx]\n",
189 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXCEPTION
].VirtualAddress
,
190 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXCEPTION
].Size
);
191 printf ("Security [0x%8lx] [0x%8lx]\n",
192 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].VirtualAddress
,
193 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
);
194 printf ("Base Relocations [0x%8lx] [0x%8lx]\n",
195 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].VirtualAddress
,
196 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BASERELOC
].Size
);
197 printf ("Debug [0x%8lx] [0x%8lx]\n",
198 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
,
199 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DEBUG
].Size
);
200 printf ("Description [0x%8lx] [0x%8lx]\n",
201 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COPYRIGHT
].VirtualAddress
,
202 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COPYRIGHT
].Size
);
203 printf ("Special [0x%8lx] [0x%8lx]\n",
204 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_GLOBALPTR
].VirtualAddress
,
205 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_GLOBALPTR
].Size
);
206 printf ("Thread (TLS) [0x%8lx] [0x%8lx]\n",
207 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].VirtualAddress
,
208 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_TLS
].Size
);
209 printf ("Load Config [0x%8lx] [0x%8lx]\n",
210 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
].VirtualAddress
,
211 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
].Size
);
212 printf ("Bound Import [0x%8lx] [0x%8lx]\n",
213 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
].VirtualAddress
,
214 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
].Size
);
215 printf ("Import Addr Tbl [0x%8lx] [0x%8lx]\n",
216 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IAT
].VirtualAddress
,
217 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_IAT
].Size
);
218 printf ("Delay Import [0x%8lx] [0x%8lx]\n",
219 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].VirtualAddress
,
220 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
].Size
);
221 printf ("COM Descriptor [0x%8lx] [0x%8lx]\n",
222 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].VirtualAddress
,
223 g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
].Size
);
226 else if (hdrtype
== CV_DBG
)
228 if (!ReadDBGFileHeader (debugfile
, &g_dbghdr
))
233 printf ("[ Found DBG header...file is not a PE executable. ]\n");
236 printf ("\n============================================================\n");
237 printf (" STANDALONE DEBUG FILE HEADER (.DBG)\n");
238 printf ("============================================================\n");
240 printf ("Signature = [0x%4x]\n", g_dbghdr
.Signature
);
241 printf ("Flags = [0x%4x]\n", g_dbghdr
.Flags
);
242 printf ("Machine = [0x%4x]\n", g_dbghdr
.Machine
);
243 printf ("Characteristics = [0x%4x]\n", g_dbghdr
.Characteristics
);
244 printf ("TimeDateStamp = [0x%8lx]\n", g_dbghdr
.TimeDateStamp
);
245 printf ("CheckSum = [0x%8lx]\n", g_dbghdr
.CheckSum
);
246 printf ("ImageBase = [0x%8lx]\n", g_dbghdr
.ImageBase
);
247 printf ("SizeOfImage = [0x%8lx]\n", g_dbghdr
.SizeOfImage
);
248 printf ("NumberOfSections = [0x%8lx]\n", g_dbghdr
.NumberOfSections
);
249 printf ("ExportedNamesSize = [0x%8lx]\n", g_dbghdr
.ExportedNamesSize
);
250 printf ("DebugDirectorySize = [0x%8lx]\n", g_dbghdr
.DebugDirectorySize
);
258 int DumpSectionHeaders (FILE *debugfile
)
262 printf ("\n============================================================\n");
263 printf (" COFF SECTION HEADERS\n");
264 printf ("============================================================\n");
266 PrintFilePos (debugfile
);
267 if (!ReadSectionHeaders (debugfile
, g_numsects
, &g_secthdrs
))
270 /* Print out a quick list of section names
272 for (i
= 0; i
< g_numsects
; i
++)
273 printf ("%8s (0x%08lx bytes long, starts at 0x%08lx)\n", g_secthdrs
[i
].Name
,
274 g_secthdrs
[i
].SizeOfRawData
, g_secthdrs
[i
].PointerToRawData
);
276 /* Print out bulk of info
278 for (i
= 0; i
< g_numsects
; i
++)
280 printf ("\nContents of IMAGE_SECTION_HEADER %s:\n\n", g_secthdrs
[i
].Name
);
282 printf ("Name = %s\n", g_secthdrs
[i
].Name
);
283 printf ("VirtualSize = [0x%8lx]\n", g_secthdrs
[i
].Misc
.VirtualSize
);
284 printf ("VirtualAddress = [0x%8lx]\n", g_secthdrs
[i
].VirtualAddress
);
285 printf ("SizeOfRawData = [0x%8lx]\n", g_secthdrs
[i
].SizeOfRawData
);
286 printf ("PointerToRawData = [0x%8lx]\n", g_secthdrs
[i
].PointerToRawData
);
287 printf ("PointerToRelocations = [0x%8lx]\n", g_secthdrs
[i
].PointerToRelocations
);
288 printf ("PointerToLinenumbers = [0x%8lx]\n", g_secthdrs
[i
].PointerToLinenumbers
);
289 printf ("NumberOfRelocations = [0x%4x]\n", g_secthdrs
[i
].NumberOfRelocations
);
290 printf ("NumberOfLinenumbers = [0x%4x]\n", g_secthdrs
[i
].NumberOfLinenumbers
);
291 printf ("Characteristics = [0x%8lx]\n", g_secthdrs
[i
].Characteristics
);
297 void PrintDebugDirectoryType (DWORD type
)
301 case IMAGE_DEBUG_TYPE_UNKNOWN
:
302 printf ("<Unknown Directory> - %ld\n", type
);
304 case IMAGE_DEBUG_TYPE_COFF
:
305 printf ("COFF Directory:\n");
307 case IMAGE_DEBUG_TYPE_CODEVIEW
:
308 printf ("CodeView Directory:\n");
310 case IMAGE_DEBUG_TYPE_FPO
:
311 printf ("FPO Directory:\n");
313 case IMAGE_DEBUG_TYPE_MISC
:
314 printf ("MISC Directory:\n");
318 printf ("<Undefined Directory> - %ld\n", type
);
322 int DumpDebugDir (FILE *debugfile
)
327 printf ("\n============================================================\n");
328 printf (" CODEVIEW DEBUG DIRECTORY\n");
329 printf ("============================================================\n");
331 PrintFilePos (debugfile
);
333 printf ("Found %d Debug director%s...\n", g_dbg_dircount
,
334 (g_dbg_dircount
== 1) ? "y" : "ies");
336 if (g_dbg_dircount
== 0)
339 /* Find the location of the debug directory table.
343 /* Convert the RVA to a file offset.
345 filepos
= GetOffsetFromRVA (g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_FILE_DEBUG_DIRECTORY
].VirtualAddress
);
347 fseek (debugfile
, filepos
, SEEK_SET
);
348 PrintFilePos (debugfile
);
352 fseek( debugfile
, g_dbghdr
.ExportedNamesSize
, SEEK_CUR
);
353 PrintFilePos (debugfile
);
356 if (!ReadDebugDir (debugfile
, g_dbg_dircount
, &g_debugdirs
))
359 /* Print out the contents of the directories.
361 for (i
= 0; i
< g_dbg_dircount
; i
++)
363 /* Remember start of debug data...for later
365 if (g_debugdirs
[i
].Type
== IMAGE_DEBUG_TYPE_CODEVIEW
)
367 g_dwStartOfCodeView
= g_debugdirs
[i
].PointerToRawData
;
369 printf ("\n[ Found start of CodeView data, at 0x%lx ]\n\n", g_dwStartOfCodeView
);
374 PrintDebugDirectoryType (g_debugdirs
[i
].Type
);
375 printf (" Characteristics = [0x%8lx]\n", g_debugdirs
[i
].Characteristics
);
376 printf (" TimeDateStamp = [0x%8lx]\n", g_debugdirs
[i
].TimeDateStamp
);
377 printf (" Version = %d.%d\n", g_debugdirs
[i
].MajorVersion
, g_debugdirs
[i
].MinorVersion
);
378 printf (" SizeOfData = [0x%8lx]\n", g_debugdirs
[i
].SizeOfData
);
379 printf (" AddressOfRawData = [0x%8lx]\n", g_debugdirs
[i
].AddressOfRawData
);
380 printf (" PointerToRawData = [0x%8lx]\n", g_debugdirs
[i
].PointerToRawData
);
382 if (g_debugdirs
[i
].Type
== IMAGE_DEBUG_TYPE_MISC
)
384 IMAGE_DEBUG_DIRECTORY_MISC misc
;
385 int lastpos
= ftell (debugfile
);
388 /* FIXME: Not sure exactly what the contents are supposed to be. */
389 fseek (debugfile
, g_debugdirs
[i
].PointerToRawData
, SEEK_SET
);
390 bytes_read
= fread (&misc
, 1, sizeof (IMAGE_DEBUG_DIRECTORY_MISC
), debugfile
);
391 printf ("\n [0x%8lx]\n [0x%8lx]\n [0x%4x]\n [0x%4x]\n '%s'\n",
392 misc
.unknown1
, misc
.SizeOfData
, misc
.unknown2
,
393 misc
.unknown3
, misc
.Name
);
395 fseek (debugfile
, lastpos
, SEEK_SET
);
403 void PrintSubsectionName (int ssNum
)
408 printf ("sstModule");
411 printf ("sstAlignSym");
414 printf ("sstSrcModule");
417 printf ("sstLibraries");
420 printf ("sstGlobalSym");
423 printf ("sstGlobalPub");
426 printf ("sstGlobalTypes");
429 printf ("sstSegMap");
432 printf ("sstFileIndex");
435 printf ("sstStaticSym");
439 printf ("<undefined> - %x", ssNum
);
443 int DumpCodeViewSummary (OMFDirEntry
*entries
, long entrycount
)
446 int modulecount
= 0, alignsymcount
= 0, srcmodulecount
= 0, librariescount
= 0;
447 int globalsymcount
= 0, globalpubcount
= 0, globaltypescount
= 0;
448 int segmapcount
= 0, fileindexcount
= 0, staticsymcount
= 0;
450 if (entries
== NULL
|| entrycount
== 0)
453 for (i
= 0; i
< entrycount
; i
++)
455 switch ((int)g_cvEntries
[i
].SubSection
)
490 /* This one has to be > 0
492 printf ("\nFound: %d sstModule subsections\n", modulecount
);
494 if (alignsymcount
> 0) printf (" %d sstAlignSym subsections\n", alignsymcount
);
495 if (srcmodulecount
> 0) printf (" %d sstSrcModule subsections\n", srcmodulecount
);
496 if (librariescount
> 0) printf (" %d sstLibraries subsections\n", librariescount
);
497 if (globalsymcount
> 0) printf (" %d sstGlobalSym subsections\n", globalsymcount
);
498 if (globalpubcount
> 0) printf (" %d sstGlobalPub subsections\n", globalpubcount
);
499 if (globaltypescount
> 0) printf (" %d sstGlobalTypes subsections\n", globaltypescount
);
500 if (segmapcount
> 0) printf (" %d sstSegMap subsections\n", segmapcount
);
501 if (fileindexcount
> 0) printf (" %d sstFileIndex subsections\n", fileindexcount
);
502 if (staticsymcount
> 0) printf (" %d sstStaticSym subsections\n", staticsymcount
);
507 int DumpCodeViewHeaders (FILE *debugfile
)
509 printf ("\n============================================================\n");
510 printf (" CODEVIEW HEADERS\n");
511 printf ("============================================================\n");
513 PrintFilePos (debugfile
);
515 fseek (debugfile
, g_dwStartOfCodeView
, SEEK_SET
);
516 printf ("CodeView Directory Table begins at filepos = 0x%lx\n\n", ftell (debugfile
));
518 if (!ReadCodeViewHeader (debugfile
, &g_cvSig
, &g_cvHeader
))
521 printf ("Signature = %.4s\n", g_cvSig
.Signature
);
522 printf ("filepos = [0x%8lx]\n", g_cvSig
.filepos
);
523 printf ("File Location of debug directories = [0x%8lx]\n\n", g_cvSig
.filepos
+ g_dwStartOfCodeView
);
525 printf ("Size of header = [0x%4x]\n", g_cvHeader
.cbDirHeader
);
526 printf ("Size per entry = [0x%4x]\n", g_cvHeader
.cbDirEntry
);
527 printf ("# of entries = [0x%8lx] (%ld)\n", g_cvHeader
.cDir
, g_cvHeader
.cDir
);
528 printf ("Offset to NextDir = [0x%8lx]\n", g_cvHeader
.lfoNextDir
);
529 printf ("Flags = [0x%8lx]\n", g_cvHeader
.flags
);
531 if (!ReadCodeViewDirectory (debugfile
, g_cvHeader
.cDir
, &g_cvEntries
))
534 DumpCodeViewSummary (g_cvEntries
, g_cvHeader
.cDir
);
540 * Print out the info contained in the sstModule section of a single module
542 int DumpModuleInfo (int index
)
546 if (g_cvEntries
== NULL
|| g_cvModules
== NULL
)
549 printf ("---------------------- sstModule ----------------------\n");
551 /* Print out some juicy module data
553 printf (" '%s' module holds %d segment(s) (style %c%c)\n",
554 g_cvModules
[index
].Name
, g_cvModules
[index
].cSeg
,
555 g_cvModules
[index
].Style
[0], g_cvModules
[index
].Style
[1]);
557 /* Print out info from module's OMFDirEntry
559 printf (" file offset = [0x%8lx]\n", g_cvEntries
[index
].lfo
);
560 printf (" size = [0x%8lx]\n\n", g_cvEntries
[index
].cb
);
562 for (segnum
= 0; segnum
< g_cvModules
[index
].cSeg
; segnum
++)
564 printf (" segment #%d: offset = [0x%8lx], size = [0x%8lx]\n",
565 g_cvModules
[index
].SegInfo
[segnum
].Seg
,
566 g_cvModules
[index
].SegInfo
[segnum
].Off
,
567 g_cvModules
[index
].SegInfo
[segnum
].cbSeg
);
573 int DumpGlobalPubInfo (int index
, FILE *debugfile
)
576 unsigned long sectionsize
;
584 char nametmp
[256] = { 0 }; /* Zero out */
586 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
587 g_cvEntries
[index
].SubSection
!= sstGlobalPub
)
590 printf ("-------------------- sstGlobalPub --------------------\n");
592 sectionsize
= g_cvEntries
[index
].cb
;
593 printf (" offset = [0x%8lx]\n size = [0x%8lx]\n", g_cvEntries
[index
].lfo
, sectionsize
);
595 fileoffset
= g_dwStartOfCodeView
+ g_cvEntries
[index
].lfo
;
596 printf (" GlobalPub section starts at file offset 0x%lx\n", fileoffset
);
597 printf (" Symbol table starts at 0x%lx\n", fileoffset
+ sizeof (OMFSymHash
));
600 printf (" [iMod = %d] [index = %d]\n", g_cvEntries
[index
].iMod
, index
);
603 printf ("\n ----- Begin Symbol Table -----\n");
604 printf (" (type) (symbol name) (offset) (len) (seg) (ind)\n");
606 /* Read the section header.
608 if (!ReadChunk (debugfile
, (void*)&header
, sizeof (OMFSymHash
), fileoffset
))
610 PrintFilePos (debugfile
);
612 /* Read the entire sstGlobalPub symbol table.
614 symbols
= malloc (header
.cbSymbol
);
615 if (!ReadChunk (debugfile
, (void*)symbols
, header
.cbSymbol
, -1))
618 /* We don't know how many symbols are in this block of memory...only what
619 * the total size of the block is. Because the symbol's name is tacked
620 * on to the end of the PUBSYM32 struct, each symbol may take up a different
621 * # of bytes. This makes it harder to parse through the symbol table,
622 * since we won't know the exact location of the following symbol until we've
623 * already parsed the current one.
626 while (curpos
< symbols
+ header
.cbSymbol
)
628 /* Point to the next PUBSYM32 in the table.
630 sym
= (PUBSYM32
*)curpos
;
632 /* Ugly hack to find the start of the (length-prefixed) name string.
633 * Must be careful about pointer math (i.e. can't use 'sym').
635 * FIXME: Should take into account the length...this approach hopes
636 * for a coincidental NULL after the string.
638 symlen
= *(curpos
+ sizeof (PUBSYM32
));
639 symname
= curpos
+ sizeof (PUBSYM32
) + 1;
641 /* " (type) (symbol name) (offset) (len) (seg) (typind)" */
643 snprintf (nametmp
, symlen
+ 1, "%s", symname
);
644 printf (" 0x%04x %-30.30s [0x%8lx] [0x%4x] %d %ld\n",
645 sym
->rectyp
, nametmp
, sym
->off
, sym
->reclen
, sym
->seg
, sym
->typind
);
647 /* The entire record is null-padded to the nearest 4-byte
648 * boundary, so we must do a little extra math to keep things straight.
650 recordlen
= sym
->reclen
;
652 recordlen
+= 4 - (recordlen
% 4);
654 /* printf ("Padding length of %d bytes to %d\n", sym->reclen, recordlen); */
659 printf (" Freeing symbol memory...\n");
665 int DumpGlobalSymInfo (int index
, FILE *debugfile
)
667 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
668 g_cvEntries
[index
].SubSection
!= sstGlobalSym
)
671 /*** NOT YET IMPLEMENTED ***/
672 printf ("---Found section ");
673 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
674 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
675 printf (" of module #%d---\n", index
+ 1);
680 int DumpStaticSymInfo (int index
, FILE *debugfile
)
682 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
683 g_cvEntries
[index
].SubSection
!= sstStaticSym
)
686 /*** NOT YET IMPLEMENTED ***/
687 printf ("---Found section ");
688 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
689 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
690 printf (" of module #%d---\n", index
+ 1);
695 int DumpLibrariesInfo (int index
, FILE *debugfile
)
697 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
698 g_cvEntries
[index
].SubSection
!= sstLibraries
)
701 /*** NOT YET IMPLEMENTED ***/
702 printf ("---Found section ");
703 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
704 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
705 printf (" of module #%d---\n", index
+ 1);
710 int DumpGlobalTypesInfo (int index
, FILE *debugfile
)
712 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
713 g_cvEntries
[index
].SubSection
!= sstGlobalTypes
)
716 /*** NOT YET IMPLEMENTED ***/
717 printf ("---Found section ");
718 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
719 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
720 printf (" of module #%d---\n", index
+ 1);
725 int DumpSegMapInfo (int index
, FILE *debugfile
)
727 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
728 g_cvEntries
[index
].SubSection
!= sstSegMap
)
731 printf ("-------------------- sstSegMap --------------------\n");
733 printf ("---Found section ");
734 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
735 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
736 printf (" of module #%d---\n", index
+ 1);
741 int DumpFileIndexInfo (int index
, FILE *debugfile
)
743 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
744 g_cvEntries
[index
].SubSection
!= sstFileIndex
)
747 /*** NOT YET IMPLEMENTED ***/
748 printf ("---Found section ");
749 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
750 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
751 printf (" of module #%d---\n", index
+ 1);
756 int DumpSrcModuleInfo (int index
, FILE *debugfile
)
769 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
770 g_cvEntries
[index
].SubSection
!= sstSrcModule
)
773 printf ("--------------------- sstSrcModule --------------------\n");
774 printf (" file offset = [0x%8lx]\n", g_dwStartOfCodeView
+ g_cvEntries
[index
].lfo
);
775 printf (" size = [0x%8lx]\n", g_cvEntries
[index
].cb
);
777 /* Where in the .DBG file should we start reading?
779 fileoffset
= g_dwStartOfCodeView
+ g_cvEntries
[index
].lfo
;
781 /* Allocate a chunk of memory for the entire sstSrcModule
783 rawdata
= malloc (g_cvEntries
[index
].cb
);
786 printf ("ERROR - Unable to allocate %ld bytes for DumpSrcModuleInfo()\n",
787 g_cvEntries
[index
].cb
);
791 /* Read in the entire sstSrcModule from the .DBG file. We'll process it
792 * bit by bit, by passing memory pointers into the various functions in
795 if (!ReadChunk (debugfile
, (void*)rawdata
, g_cvEntries
[index
].cb
, fileoffset
))
798 moduledatalen
= PrintSrcModuleInfo (rawdata
, &filecount
, &segcount
);
800 printf ("*** PrintSrcModuleInfo() returned %d\n", moduledatalen
);
803 curpos
= rawdata
+ moduledatalen
;
804 filedatalen
= PrintSrcModuleFileInfo (curpos
);
806 printf ("*** PrintSrcModuleFileInfo() returned %d\n", filedatalen
);
809 curpos
+= filedatalen
;
810 for (i
= 0; i
< segcount
; i
++)
812 linedatalen
= PrintSrcModuleLineInfo (curpos
, i
);
814 printf ("*** PrintSrcModuleLineInfo() returned %d\n", linedatalen
);
817 curpos
+= linedatalen
;
825 int DumpAlignSymInfo (int index
, FILE *debugfile
)
827 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
828 g_cvEntries
[index
].SubSection
!= sstAlignSym
)
831 /*** NOT YET IMPLEMENTED ***/
832 printf ("--------------------- sstAlignSym ---------------------\n");
833 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
834 printf (" of module #%d\n", index
+ 1);
840 * Print out the info of all related modules (e.g. sstAlignSym, sstSrcModule)
841 * for the given sub-section index (i.e. sstModule).
843 int DumpRelatedSections (int index
, FILE *debugfile
)
847 if (g_cvEntries
== NULL
)
850 /* printf ("...Scanning %ld entries for matches on module #%d\n", g_cvHeader.cDir, module_num); */
852 for (i
= 0; i
< g_cvHeader
.cDir
; i
++)
854 if (g_cvEntries
[i
].iMod
!= (index
+ 1) ||
855 g_cvEntries
[i
].SubSection
== sstModule
)
858 /* Pass in index of entry in g_cvEntries array to individual sub-section
859 * dumping functions. Each function will figure out where in the file its
860 * sub-section lies and seek the file position itself, before parsing out
863 switch (g_cvEntries
[i
].SubSection
)
866 DumpAlignSymInfo (i
, debugfile
);
869 DumpSrcModuleInfo (i
, debugfile
);
873 printf ("---Found section ");
874 PrintSubsectionName (g_cvEntries
[i
].SubSection
);
875 printf (" [iMod = %d] [i = %d]", g_cvEntries
[i
].iMod
, i
);
876 printf (" of module #%d---\n", index
+ 1);
883 int DumpMiscSections (int index
, FILE *debugfile
)
885 /* The module # 65535 is reserved for all free-standing modules, not
886 * associated with a sstModule sub-section. These are the only sections
887 * we wish to process here.
889 if (g_cvEntries
== NULL
|| g_cvEntries
[index
].iMod
!= 65535)
892 /* Pass in index of entry in g_cvEntries array to individual sub-section
893 * dumping functions. Each function will figure out where in the file its
894 * sub-section lies and seek the file position itself, before parsing out
897 switch (g_cvEntries
[index
].SubSection
)
900 DumpGlobalPubInfo (index
, debugfile
);
903 DumpGlobalSymInfo (index
, debugfile
);
906 DumpStaticSymInfo (index
, debugfile
);
909 DumpLibrariesInfo (index
, debugfile
);
912 DumpGlobalTypesInfo (index
, debugfile
);
915 DumpSegMapInfo (index
, debugfile
);
918 DumpFileIndexInfo (index
, debugfile
);
922 printf ("---Found section ");
923 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
924 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
925 printf (" of module #%d---\n", index
+ 1);
931 int DumpAllModules (FILE *debugfile
)
935 if (g_cvHeader
.cDir
== 0)
937 printf ("\nStrange...found CodeView header, but no module entries\n\n");
941 if (g_cvEntries
== NULL
)
943 printf ("ERROR: Invalid entry table, bailing out of Module Data Dump\n");
944 printf ("%ld %p\n", g_cvHeader
.cDir
, g_cvEntries
);
948 printf ("\n============================================================\n");
949 printf (" MODULE LISTING\n");
950 printf ("============================================================\n");
952 /* Seek to beginning of debug data
954 fseek (debugfile
, g_dwStartOfCodeView
+ g_cvEntries
[0].lfo
, SEEK_SET
);
956 printf ("[ Moving to filepos = 0x%lx to read in CodeView module info ]\n",
960 /* Load all OMFModuleFull data from file into memory
962 if (!ReadModuleData (debugfile
, g_cvHeader
.cDir
, g_cvEntries
,
963 &g_module_count
, &g_cvModules
))
965 PrintFilePos (debugfile
);
969 /* Print out bulk of info (depends on the fact that all sstModule's
970 * are packed at the beginning of the array).
972 printf ("Found %d modules\n", g_module_count
);
973 for (i
= 0; i
< g_module_count
; i
++)
975 printf ("\n====================== Module #%d ======================\n", i
+ 1);
977 DumpRelatedSections (i
, debugfile
);
978 printf ("=======================================================\n");
981 printf ("\n============================================================\n");
982 printf (" MISCELLANEOUS MODULES\n");
983 printf ("============================================================\n");
985 for (i
= 0; i
< g_cvHeader
.cDir
; i
++)
987 DumpMiscSections (i
, debugfile
);
995 * Free Global data used by OMFModuleFull structs. Can't just use free() because
996 * the 'SegInfo' and 'Name' fields also have allocated memory.
998 void FreeCVModules ()
1001 OMFModuleFull
*module
;
1003 for (i
= 0; i
< g_module_count
; i
++)
1005 module
= &(g_cvModules
[i
]);
1007 free (module
->SegInfo
);
1008 free (module
->Name
);
1013 int DumpCVFile (LPSTR filename
)
1017 if (strlen (filename
) == 0)
1020 debugfile
= fopen (filename
, "r");
1021 if (debugfile
== NULL
)
1023 printf ("============================================================\n");
1024 printf (" ERROR: Unable to open file [%s]\n", filename
);
1025 printf ("============================================================\n");
1029 printf ("============================================================\n");
1030 printf (" Performing bindump on file %s\n", filename
);
1031 printf ("============================================================\n\n");
1033 if (!DumpFileHeaders (debugfile
))
1035 printf ("============================================================\n");
1036 printf (" ERROR: Bailed out while printing file headers!\n");
1037 printf ("============================================================\n");
1042 g_numsects
= g_nthdr
.FileHeader
.NumberOfSections
;
1044 g_numsects
= g_dbghdr
.NumberOfSections
;
1046 if (!DumpSectionHeaders (debugfile
))
1048 printf ("============================================================\n");
1049 printf (" ERROR: Bailed out while printing section headers\n");
1050 printf ("============================================================\n");
1055 g_dbg_dircount
= g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_FILE_DEBUG_DIRECTORY
].Size
/
1056 sizeof (IMAGE_DEBUG_DIRECTORY
);
1058 g_dbg_dircount
= g_dbghdr
.DebugDirectorySize
/ sizeof (IMAGE_DEBUG_DIRECTORY
);
1061 printf ("\n[ Found %d debug directories in %s file. ]\n", g_dbg_dircount
,
1062 g_exe_mode
? "PE" : "DBG");
1065 if (!DumpDebugDir (debugfile
))
1067 printf ("============================================================\n");
1068 printf (" ERROR: Bailed out while printing Debug Directories\n");
1069 printf ("============================================================\n");
1073 /* Only dump CodeView data if we know where it is!
1075 if (g_dwStartOfCodeView
== 0)
1077 printf ("============================================================\n");
1078 printf (" ERROR: Unable to find CodeView info!\n");
1079 printf ("============================================================\n");
1083 if (!DumpCodeViewHeaders (debugfile
))
1085 printf ("============================================================\n");
1086 printf (" ERROR: Bailed out while printing CodeView headers\n");
1087 printf ("============================================================\n");
1091 if (!DumpAllModules (debugfile
))
1093 printf ("============================================================\n");
1094 printf (" ERROR: Bailed out while printing CodeView debug info\n");
1095 printf ("============================================================\n");
1099 /* Clean up our trash
1101 printf ("Shutting down...\n");
1106 /* FIXME: For some reason, this call segfaults...check it out later */
1107 /* free (g_cvEntries); */
1109 /* printf ("Freeing module data..."); */
1110 /* FreeCVModules (); */
1115 int main(int argc
, char *argv
[])
1121 printf ("Usage:\n\tcvdump FILE [FILES...]\n");
1125 for (i
= 1; i
< argc
; i
++)
1126 DumpCVFile (argv
[i
]);