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_dbg_dircount
- 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 CodeView subsection%c...\n", g_dbg_dircount
,
334 (g_dbg_dircount
== 1) ? '.' : 's');
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
);
355 /* Find the .rdata section.
357 for (i
= 0; i
< g_numsects
; i
++)
358 if (strcmp (g_secthdrs
[i
].Name
, ".rdata") == 0)
361 filepos
= g_secthdrs
[i
].PointerToRawData
;
365 if (!ReadDebugDir (debugfile
, g_dbg_dircount
, &g_debugdirs
))
368 /* Print out the contents of the directories.
370 for (i
= 0; i
< g_dbg_dircount
; i
++)
372 /* Remember start of debug data...for later
374 if (g_debugdirs
[i
].Type
== IMAGE_DEBUG_TYPE_CODEVIEW
)
376 g_dwStartOfCodeView
= g_debugdirs
[i
].PointerToRawData
;
378 printf ("\n[ Found start of CodeView data, at 0x%lx ]\n\n", g_dwStartOfCodeView
);
383 PrintDebugDirectoryType (g_debugdirs
[i
].Type
);
384 printf (" Characteristics = [0x%8lx]\n", g_debugdirs
[i
].Characteristics
);
385 printf (" TimeDateStamp = [0x%8lx]\n", g_debugdirs
[i
].TimeDateStamp
);
386 printf (" Version = %d.%d\n", g_debugdirs
[i
].MajorVersion
, g_debugdirs
[i
].MinorVersion
);
387 printf (" SizeOfData = [0x%8lx]\n", g_debugdirs
[i
].SizeOfData
);
388 printf (" AddressOfRawData = [0x%8lx]\n", g_debugdirs
[i
].AddressOfRawData
);
389 printf (" PointerToRawData = [0x%8lx]\n", g_debugdirs
[i
].PointerToRawData
);
396 void PrintSubsectionName (int ssNum
)
401 printf ("sstModule");
404 printf ("sstAlignSym");
407 printf ("sstSrcModule");
410 printf ("sstLibraries");
413 printf ("sstGlobalSym");
416 printf ("sstGlobalPub");
419 printf ("sstGlobalTypes");
422 printf ("sstSegMap");
425 printf ("sstFileIndex");
428 printf ("sstStaticSym");
432 printf ("<undefined> - %x", ssNum
);
436 int DumpCodeViewSummary (OMFDirEntry
*entries
, long entrycount
)
439 int modulecount
= 0, alignsymcount
= 0, srcmodulecount
= 0, librariescount
= 0;
440 int globalsymcount
= 0, globalpubcount
= 0, globaltypescount
= 0;
441 int segmapcount
= 0, fileindexcount
= 0, staticsymcount
= 0;
443 if (entries
== NULL
|| entrycount
== 0)
446 for (i
= 0; i
< entrycount
; i
++)
448 switch ((int)g_cvEntries
[i
].SubSection
)
483 /* This one has to be > 0
485 printf ("\nFound: %d sstModule subsections\n", modulecount
);
487 if (alignsymcount
> 0) printf (" %d sstAlignSym subsections\n", alignsymcount
);
488 if (srcmodulecount
> 0) printf (" %d sstSrcModule subsections\n", srcmodulecount
);
489 if (librariescount
> 0) printf (" %d sstLibraries subsections\n", librariescount
);
490 if (globalsymcount
> 0) printf (" %d sstGlobalSym subsections\n", globalsymcount
);
491 if (globalpubcount
> 0) printf (" %d sstGlobalPub subsections\n", globalpubcount
);
492 if (globaltypescount
> 0) printf (" %d sstGlobalTypes subsections\n", globaltypescount
);
493 if (segmapcount
> 0) printf (" %d sstSegMap subsections\n", segmapcount
);
494 if (fileindexcount
> 0) printf (" %d sstFileIndex subsections\n", fileindexcount
);
495 if (staticsymcount
> 0) printf (" %d sstStaticSym subsections\n", staticsymcount
);
500 int DumpCodeViewHeaders (FILE *debugfile
)
502 printf ("\n============================================================\n");
503 printf (" CODEVIEW HEADERS\n");
504 printf ("============================================================\n");
506 PrintFilePos (debugfile
);
508 fseek (debugfile
, g_dwStartOfCodeView
, SEEK_SET
);
509 printf ("CodeView Directory Table begins at filepos = 0x%lx\n\n", ftell (debugfile
));
511 if (!ReadCodeViewHeader (debugfile
, &g_cvSig
, &g_cvHeader
))
514 printf ("Signature = %.4s\n", g_cvSig
.Signature
);
515 printf ("filepos = [0x%8lx]\n", g_cvSig
.filepos
);
516 printf ("File Location of debug directories = [0x%8lx]\n\n", g_cvSig
.filepos
+ g_dwStartOfCodeView
);
518 printf ("Size of header = [0x%4x]\n", g_cvHeader
.cbDirHeader
);
519 printf ("Size per entry = [0x%4x]\n", g_cvHeader
.cbDirEntry
);
520 printf ("# of entries = [0x%8lx] (%ld)\n", g_cvHeader
.cDir
, g_cvHeader
.cDir
);
521 printf ("Offset to NextDir = [0x%8lx]\n", g_cvHeader
.lfoNextDir
);
522 printf ("Flags = [0x%8lx]\n", g_cvHeader
.flags
);
524 if (!ReadCodeViewDirectory (debugfile
, g_cvHeader
.cDir
, &g_cvEntries
))
527 DumpCodeViewSummary (g_cvEntries
, g_cvHeader
.cDir
);
533 * Print out the info contained in the sstModule section of a single module
535 int DumpModuleInfo (int index
)
539 if (g_cvEntries
== NULL
|| g_cvModules
== NULL
)
542 printf ("---------------------- sstModule ----------------------\n");
544 /* Print out some juicy module data
546 printf (" '%s' module holds %d segment(s) (style %c%c)\n",
547 g_cvModules
[index
].Name
, g_cvModules
[index
].cSeg
,
548 g_cvModules
[index
].Style
[0], g_cvModules
[index
].Style
[1]);
550 /* Print out info from module's OMFDirEntry
552 printf (" file offset = [0x%8lx]\n", g_cvEntries
[index
].lfo
);
553 printf (" size = [0x%8lx]\n\n", g_cvEntries
[index
].cb
);
555 for (segnum
= 0; segnum
< g_cvModules
[index
].cSeg
; segnum
++)
557 printf (" segment #%d: offset = [0x%8lx], size = [0x%8lx]\n",
558 g_cvModules
[index
].SegInfo
[segnum
].Seg
,
559 g_cvModules
[index
].SegInfo
[segnum
].Off
,
560 g_cvModules
[index
].SegInfo
[segnum
].cbSeg
);
566 int DumpGlobalPubInfo (int index
, FILE *debugfile
)
569 unsigned long sectionsize
;
577 char nametmp
[256] = { 0 }; /* Zero out */
579 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
580 g_cvEntries
[index
].SubSection
!= sstGlobalPub
)
583 printf ("-------------------- sstGlobalPub --------------------\n");
585 sectionsize
= g_cvEntries
[index
].cb
;
586 printf (" offset = [0x%8lx]\n size = [0x%8lx]\n", g_cvEntries
[index
].lfo
, sectionsize
);
588 fileoffset
= g_dwStartOfCodeView
+ g_cvEntries
[index
].lfo
;
589 printf (" GlobalPub section starts at file offset 0x%lx\n", fileoffset
);
590 printf (" Symbol table starts at 0x%lx\n", fileoffset
+ sizeof (OMFSymHash
));
593 printf (" [iMod = %d] [index = %d]\n", g_cvEntries
[index
].iMod
, index
);
596 printf ("\n ----- Begin Symbol Table -----\n");
597 printf (" (type) (symbol name) (offset) (len) (seg) (ind)\n");
599 /* Read the section header.
601 if (!ReadChunk (debugfile
, (void*)&header
, sizeof (OMFSymHash
), fileoffset
))
603 PrintFilePos (debugfile
);
605 /* Read the entire sstGlobalPub symbol table.
607 symbols
= malloc (header
.cbSymbol
);
608 if (!ReadChunk (debugfile
, (void*)symbols
, header
.cbSymbol
, -1))
611 /* We don't know how many symbols are in this block of memory...only what
612 * the total size of the block is. Because the symbol's name is tacked
613 * on to the end of the PUBSYM32 struct, each symbol may take up a different
614 * # of bytes. This makes it harder to parse through the symbol table,
615 * since we won't know the exact location of the following symbol until we've
616 * already parsed the current one.
619 while (curpos
< symbols
+ header
.cbSymbol
)
621 /* Point to the next PUBSYM32 in the table.
623 sym
= (PUBSYM32
*)curpos
;
625 /* Ugly hack to find the start of the (length-prefixed) name string.
626 * Must be careful about pointer math (i.e. can't use 'sym').
628 * FIXME: Should take into account the length...this approach hopes
629 * for a coincidental NULL after the string.
631 symlen
= *(curpos
+ sizeof (PUBSYM32
));
632 symname
= curpos
+ sizeof (PUBSYM32
) + 1;
634 /* " (type) (symbol name) (offset) (len) (seg) (typind)" */
636 snprintf (nametmp
, symlen
+ 1, "%s", symname
);
637 printf (" 0x%04x %-30.30s [0x%8lx] [0x%4x] %d %ld\n",
638 sym
->rectyp
, nametmp
, sym
->off
, sym
->reclen
, sym
->seg
, sym
->typind
);
640 /* The entire record is null-padded to the nearest 4-byte
641 * boundary, so we must do a little extra math to keep things straight.
643 recordlen
= sym
->reclen
;
645 recordlen
+= 4 - (recordlen
% 4);
647 /* printf ("Padding length of %d bytes to %d\n", sym->reclen, recordlen); */
652 printf (" Freeing symbol memory...\n");
658 int DumpGlobalSymInfo (int index
, FILE *debugfile
)
660 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
661 g_cvEntries
[index
].SubSection
!= sstGlobalSym
)
664 /*** NOT YET IMPLEMENTED ***/
665 printf ("---Found section ");
666 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
667 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
668 printf (" of module #%d---\n", index
+ 1);
673 int DumpStaticSymInfo (int index
, FILE *debugfile
)
675 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
676 g_cvEntries
[index
].SubSection
!= sstStaticSym
)
679 /*** NOT YET IMPLEMENTED ***/
680 printf ("---Found section ");
681 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
682 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
683 printf (" of module #%d---\n", index
+ 1);
688 int DumpLibrariesInfo (int index
, FILE *debugfile
)
690 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
691 g_cvEntries
[index
].SubSection
!= sstLibraries
)
694 /*** NOT YET IMPLEMENTED ***/
695 printf ("---Found section ");
696 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
697 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
698 printf (" of module #%d---\n", index
+ 1);
703 int DumpGlobalTypesInfo (int index
, FILE *debugfile
)
705 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
706 g_cvEntries
[index
].SubSection
!= sstGlobalTypes
)
709 /*** NOT YET IMPLEMENTED ***/
710 printf ("---Found section ");
711 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
712 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
713 printf (" of module #%d---\n", index
+ 1);
718 int DumpSegMapInfo (int index
, FILE *debugfile
)
720 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
721 g_cvEntries
[index
].SubSection
!= sstSegMap
)
724 printf ("-------------------- sstSegMap --------------------\n");
726 printf ("---Found section ");
727 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
728 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
729 printf (" of module #%d---\n", index
+ 1);
734 int DumpFileIndexInfo (int index
, FILE *debugfile
)
736 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
737 g_cvEntries
[index
].SubSection
!= sstFileIndex
)
740 /*** NOT YET IMPLEMENTED ***/
741 printf ("---Found section ");
742 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
743 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
744 printf (" of module #%d---\n", index
+ 1);
749 int DumpSrcModuleInfo (int index
, FILE *debugfile
)
762 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
763 g_cvEntries
[index
].SubSection
!= sstSrcModule
)
766 printf ("--------------------- sstSrcModule --------------------\n");
767 printf (" file offset = [0x%8lx]\n", g_dwStartOfCodeView
+ g_cvEntries
[index
].lfo
);
768 printf (" size = [0x%8lx]\n", g_cvEntries
[index
].cb
);
770 /* Where in the .DBG file should we start reading?
772 fileoffset
= g_dwStartOfCodeView
+ g_cvEntries
[index
].lfo
;
774 /* Allocate a chunk of memory for the entire sstSrcModule
776 rawdata
= malloc (g_cvEntries
[index
].cb
);
779 printf ("ERROR - Unable to allocate %ld bytes for DumpSrcModuleInfo()\n",
780 g_cvEntries
[index
].cb
);
784 /* Read in the entire sstSrcModule from the .DBG file. We'll process it
785 * bit by bit, but passing memory pointers into the various functions in
788 if (!ReadChunk (debugfile
, (void*)rawdata
, g_cvEntries
[index
].cb
, fileoffset
))
791 moduledatalen
= PrintSrcModuleInfo (rawdata
, &filecount
, &segcount
);
793 printf ("*** PrintSrcModuleInfo() returned %d\n", moduledatalen
);
796 curpos
= rawdata
+ moduledatalen
;
797 filedatalen
= PrintSrcModuleFileInfo (curpos
);
799 printf ("*** PrintSrcModuleFileInfo() returned %d\n", filedatalen
);
802 curpos
+= filedatalen
;
803 for (i
= 0; i
< segcount
; i
++)
805 linedatalen
= PrintSrcModuleLineInfo (curpos
, i
);
807 printf ("*** PrintSrcModuleLineInfo() returned %d\n", linedatalen
);
810 curpos
+= linedatalen
;
818 int DumpAlignSymInfo (int index
, FILE *debugfile
)
820 if (g_cvEntries
== NULL
|| debugfile
== NULL
||
821 g_cvEntries
[index
].SubSection
!= sstAlignSym
)
824 /*** NOT YET IMPLEMENTED ***/
825 printf ("--------------------- sstAlignSym ---------------------\n");
826 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
827 printf (" of module #%d\n", index
+ 1);
833 * Print out the info of all related modules (e.g. sstAlignSym, sstSrcModule)
834 * for the desired sub-section (i.e. sstModule).
836 int DumpRelatedSections (int index
, FILE *debugfile
)
840 if (g_cvEntries
== NULL
)
843 /* printf ("...Scanning %ld entries for matches on module #%d\n", g_cvHeader.cDir, module_num); */
845 for (i
= 0; i
< g_cvHeader
.cDir
; i
++)
847 if (g_cvEntries
[i
].iMod
!= (index
+ 1) ||
848 g_cvEntries
[i
].SubSection
== sstModule
)
851 /* Pass in index of entry in g_cvEntries array to individual sub-section
852 * dumping functions. Each function will figure out where in the file its
853 * sub-section lies and seek the file position itself, before parsing out
856 switch (g_cvEntries
[i
].SubSection
)
859 DumpAlignSymInfo (i
, debugfile
);
862 DumpSrcModuleInfo (i
, debugfile
);
866 printf ("---Found section ");
867 PrintSubsectionName (g_cvEntries
[i
].SubSection
);
868 printf (" [iMod = %d] [i = %d]", g_cvEntries
[i
].iMod
, i
);
869 printf (" of module #%d---\n", index
+ 1);
876 int DumpMiscSections (int index
, FILE *debugfile
)
878 /* The module # 65535 is reserved for all free-standing modules, not
879 * associated with a sstModule sub-section. These are the only sections
880 * we wish to process here.
882 if (g_cvEntries
== NULL
|| g_cvEntries
[index
].iMod
!= 65535)
885 /* Pass in index of entry in g_cvEntries array to individual sub-section
886 * dumping functions. Each function will figure out where in the file its
887 * sub-section lies and seek the file position itself, before parsing out
890 switch (g_cvEntries
[index
].SubSection
)
893 DumpGlobalPubInfo (index
, debugfile
);
896 DumpGlobalSymInfo (index
, debugfile
);
899 DumpStaticSymInfo (index
, debugfile
);
902 DumpLibrariesInfo (index
, debugfile
);
905 DumpGlobalTypesInfo (index
, debugfile
);
908 DumpSegMapInfo (index
, debugfile
);
911 DumpFileIndexInfo (index
, debugfile
);
915 printf ("---Found section ");
916 PrintSubsectionName (g_cvEntries
[index
].SubSection
);
917 printf (" [iMod = %d] [index = %d]", g_cvEntries
[index
].iMod
, index
);
918 printf (" of module #%d---\n", index
+ 1);
924 int DumpAllModules (FILE *debugfile
)
928 if (g_cvHeader
.cDir
== 0 || g_cvEntries
== NULL
)
930 printf ("ERROR: Bailing out of Module Data Dump\n");
931 printf ("%ld %p\n", g_cvHeader
.cDir
, g_cvEntries
);
935 printf ("\n============================================================\n");
936 printf (" MODULE LISTING\n");
937 printf ("============================================================\n");
939 /* Seek to beginning of debug data
941 fseek (debugfile
, g_dwStartOfCodeView
+ g_cvEntries
[0].lfo
, SEEK_SET
);
943 printf ("[ Moving to filepos = 0x%lx to read in CodeView module info ]\n",
947 /* Load all OMFModuleFull data from file into memory
949 if (!ReadModuleData (debugfile
, g_cvHeader
.cDir
, g_cvEntries
,
950 &g_module_count
, &g_cvModules
))
952 PrintFilePos (debugfile
);
956 /* Print out bulk of info (depends on the fact that all sstModule's
957 * are packed at the beginning of the array).
959 printf ("Found %d modules\n", g_module_count
);
960 for (i
= 0; i
< g_module_count
; i
++)
962 printf ("\n====================== Module #%d ======================\n", i
+ 1);
964 DumpRelatedSections (i
, debugfile
);
965 printf ("=======================================================\n");
968 printf ("\n============================================================\n");
969 printf (" MISCELLANEOUS MODULES\n");
970 printf ("============================================================\n");
972 for (i
= 0; i
< g_cvHeader
.cDir
; i
++)
974 DumpMiscSections (i
, debugfile
);
982 * Free Global data used by OMFModuleFull structs. Can't just use free() because
983 * the 'SegInfo' and 'Name' fields also have allocated memory.
985 void FreeCVModules ()
988 OMFModuleFull
*module
;
990 for (i
= 0; i
< g_module_count
; i
++)
992 module
= &(g_cvModules
[i
]);
994 free (module
->SegInfo
);
1000 int DumpCVFile (LPSTR filename
)
1004 if (strlen (filename
) == 0)
1007 debugfile
= fopen (filename
, "r");
1008 if (debugfile
== NULL
)
1010 printf ("============================================================\n");
1011 printf (" ERROR: Unable to open file [%s]\n", filename
);
1012 printf ("============================================================\n");
1016 printf ("============================================================\n");
1017 printf (" Performing bindump on file %s\n", filename
);
1018 printf ("============================================================\n\n");
1020 if (!DumpFileHeaders (debugfile
))
1022 printf ("============================================================\n");
1023 printf (" ERROR: Bailed out while printing file headers!\n");
1024 printf ("============================================================\n");
1029 g_numsects
= g_nthdr
.FileHeader
.NumberOfSections
;
1031 g_numsects
= g_dbghdr
.NumberOfSections
;
1033 if (!DumpSectionHeaders (debugfile
))
1035 printf ("============================================================\n");
1036 printf (" ERROR: Bailed out while printing section headers\n");
1037 printf ("============================================================\n");
1042 g_dbg_dircount
= g_nthdr
.OptionalHeader
.DataDirectory
[IMAGE_FILE_DEBUG_DIRECTORY
].Size
/
1043 sizeof (IMAGE_DEBUG_DIRECTORY
);
1045 g_dbg_dircount
= g_dbghdr
.DebugDirectorySize
/ sizeof (IMAGE_DEBUG_DIRECTORY
);
1048 printf ("\n[ Found %d debug directories in %s file. ]\n", g_dbg_dircount
,
1049 g_exe_mode
? "PE" : "DBG");
1052 if (!DumpDebugDir (debugfile
))
1054 printf ("============================================================\n");
1055 printf (" ERROR: Bailed out while printing Debug Directories\n");
1056 printf ("============================================================\n");
1060 /* Only dump CodeView data if we know where it is!
1062 if (g_dwStartOfCodeView
== 0)
1064 printf ("============================================================\n");
1065 printf (" ERROR: Unable to find CodeView info!\n");
1066 printf ("============================================================\n");
1070 if (!DumpCodeViewHeaders (debugfile
))
1072 printf ("============================================================\n");
1073 printf (" ERROR: Bailed out while printing CodeView headers\n");
1074 printf ("============================================================\n");
1078 if (!DumpAllModules (debugfile
))
1080 printf ("============================================================\n");
1081 printf (" ERROR: Bailed out while printing CodeView debug info\n");
1082 printf ("============================================================\n");
1086 /* Clean up our trash
1088 printf ("Shutting down...\n");
1093 /* FIXME: For some reason, this call segfaults...check it out later */
1094 /* free (g_cvEntries); */
1096 /* printf ("Freeing module data..."); */
1097 /* FreeCVModules (); */
1102 int main(int argc
, char *argv
[])
1108 printf ("Usage:\n\tcvdump FILE [FILES...]\n");
1112 for (i
= 1; i
< argc
; i
++)
1113 DumpCVFile (argv
[i
]);