2 * File msc.c - read VC++ debug information from COFF and eventually
5 * Copyright (C) 1996, Eric Youngdale.
7 * Note - this handles reading debug information for 32 bit applications
8 * that run under Windows-NT for example. I doubt that this would work well
9 * for 16 bit applications, but I don't think it really matters since the
10 * file format is different, and we should never get in here in such cases.
31 * For the type CODEVIEW debug directory entries, the debug directory
32 * points to a structure like this. The cv_name field is the name
33 * of an external .PDB file.
38 unsigned int cv_timestamp
;
44 unsigned int DataType
;
52 * This is the header that the COFF variety of debug header points to.
56 unsigned int SymbolOffset
;
57 unsigned int N_Linenum
;
58 unsigned int LinenumberOffset
;
59 unsigned int Unused
[4];
63 unsigned int VirtualAddr
;
68 unsigned int startaddr
;
79 unsigned int StrTaboff
;
86 unsigned char NumberOfAuxSymbols
;
89 struct CoffAuxSection
{
91 unsigned short NumberOfRelocations
;
92 unsigned short NumberOfLinenumbers
;
93 unsigned int CheckSum
;
98 struct deferred_debug_info
100 struct deferred_debug_info
* next
;
104 struct PE_Debug_dir
* dbgdir
;
108 struct deferred_debug_info
* dbglist
= NULL
;
111 * A simple macro that tells us whether a given COFF symbol is a
114 #define N_TMASK 0x0030
115 #define IMAGE_SYM_DTYPE_FUNCTION 2
117 #define ISFCN(x) (((x) & N_TMASK) == (IMAGE_SYM_DTYPE_FUNCTION << N_BTSHFT))
121 * This is what we are looking for in the COFF symbols.
123 #define IMAGE_SYM_CLASS_EXTERNAL 0x2
124 #define IMAGE_SYM_CLASS_STATIC 0x3
125 #define IMAGE_SYM_CLASS_FILE 0x67
128 * In this function, we keep track of deferred debugging information
129 * that we may need later if we were to need to use the internal debugger.
130 * We don't fully process it here for performance reasons.
133 DEBUG_RegisterDebugInfo(int fd
, struct pe_data
* pe
,
134 int load_addr
, u_long v_addr
, u_long size
)
137 struct PE_Debug_dir
* dbgptr
;
138 struct deferred_debug_info
* deefer
;
140 dbgptr
= (struct PE_Debug_dir
*) (load_addr
+ v_addr
);
141 for(; size
> 0; size
-= sizeof(*dbgptr
), dbgptr
++ )
145 case IMAGE_DEBUG_TYPE_COFF
:
146 case IMAGE_DEBUG_TYPE_CODEVIEW
:
147 case IMAGE_DEBUG_TYPE_MISC
:
149 * This is usually an indirection to a .DBG file.
150 * This is similar to (but a slightly older format) from the
153 * First check to see if the image was 'stripped'. If so, it
154 * means that this entry points to a .DBG file. Otherwise,
155 * it just points to itself, and we can ignore this.
157 if( (dbgptr
->type
== IMAGE_DEBUG_TYPE_MISC
)
158 && (pe
->pe_header
->coff
.Characteristics
& IMAGE_FILE_DEBUG_STRIPPED
) == 0 )
163 deefer
= (struct deferred_debug_info
*) xmalloc(sizeof(*deefer
));
166 deefer
->dbg_info
= NULL
;
167 deefer
->dbg_size
= 0;
170 * Read the important bits. What we do after this depends
171 * upon the type, but this is always enough so we are able
172 * to proceed if we know what we need to do next.
174 deefer
->dbg_size
= dbgptr
->dbgsize
;
175 deefer
->dbg_info
= (char *) xmalloc(dbgptr
->dbgsize
);
176 lseek(fd
, dbgptr
->dbgoff
, SEEK_SET
);
177 read(fd
, deefer
->dbg_info
, deefer
->dbg_size
);
179 deefer
->load_addr
= (char *) load_addr
;
180 deefer
->dbgdir
= dbgptr
;
181 deefer
->next
= dbglist
;
193 * Process COFF debugging information embedded in a Win32 application.
195 * FIXME - we need to process the source file information and the line
200 DEBUG_ProcessCoff(struct deferred_debug_info
* deefer
)
202 struct CoffAuxSection
* aux
;
203 struct CoffDebug
* coff
;
204 struct CoffSymbol
* coff_sym
;
205 struct CoffSymbol
* coff_symbol
;
206 struct CoffLinenum
* coff_linetab
;
215 int nfiles_alloc
= 0;
216 struct CoffFiles
* coff_files
= NULL
;
217 struct CoffFiles
* curr_file
= NULL
;
221 coff
= (struct CoffDebug
*) deefer
->dbg_info
;
223 coff_symbol
= (struct CoffSymbol
*) ((unsigned int) coff
+ coff
->SymbolOffset
);
224 coff_linetab
= (struct CoffLinenum
*) ((unsigned int) coff
+ coff
->LinenumberOffset
);
225 coff_strtab
= (char *) ((unsigned int) coff_symbol
+ 18*coff
->N_Sym
);
227 for(i
=0; i
< coff
->N_Sym
; i
++ )
230 * We do this because some compilers (i.e. gcc) incorrectly
231 * pad the structure up to a 4 byte boundary. The structure
232 * is really only 18 bytes long, so we have to manually make sure
235 * FIXME - there must be a way to have autoconf figure out the
236 * correct compiler option for this. If it is always gcc, that
237 * makes life simpler, but I don't want to force this.
239 coff_sym
= (struct CoffSymbol
*) ((unsigned int) coff_symbol
+ 18*i
);
240 naux
= coff_sym
->NumberOfAuxSymbols
;
242 if( coff_sym
->StorageClass
== IMAGE_SYM_CLASS_FILE
)
244 if( nfiles
+ 1 >= nfiles_alloc
)
247 coff_files
= (struct CoffFiles
*) realloc( coff_files
,
248 nfiles_alloc
* sizeof(struct CoffFiles
));
250 curr_file
= coff_files
+ nfiles
;
252 curr_file
->startaddr
= 0xffffffff;
253 curr_file
->endaddr
= 0;
254 curr_file
->filename
= ((char *) coff_sym
) + 18;
258 * This guy marks the size and location of the text section
259 * for the current file. We need to keep track of this so
260 * we can figure out what file the different global functions
263 if( (coff_sym
->StorageClass
== IMAGE_SYM_CLASS_STATIC
)
265 && (coff_sym
->SectionNumber
== 1) )
267 aux
= (struct CoffAuxSection
*) ((unsigned int) coff_sym
+ 18);
268 if( curr_file
->startaddr
> coff_sym
->Value
)
270 curr_file
->startaddr
= coff_sym
->Value
;
273 if( curr_file
->startaddr
> coff_sym
->Value
)
275 curr_file
->startaddr
= coff_sym
->Value
;
278 if( curr_file
->endaddr
< coff_sym
->Value
+ aux
->Length
)
280 curr_file
->endaddr
= coff_sym
->Value
+ aux
->Length
;
285 if( (coff_sym
->StorageClass
== IMAGE_SYM_CLASS_STATIC
)
287 && (coff_sym
->SectionNumber
== 1) )
290 * This is a normal static function when naux == 0.
291 * Just register it. The current file is the correct
292 * one in this instance.
294 if( coff_sym
->N
.Name
.NotLong
)
296 memcpy(namebuff
, coff_sym
->N
.ShortName
, 8);
298 nampnt
= &namebuff
[0];
302 nampnt
= coff_strtab
+ coff_sym
->N
.Name
.StrTaboff
;
306 new_addr
.off
= (int) (deefer
->load_addr
+ coff_sym
->Value
);
307 DEBUG_AddSymbol( nampnt
, &new_addr
, curr_file
->filename
);
310 if( (coff_sym
->StorageClass
== IMAGE_SYM_CLASS_EXTERNAL
)
311 && ISFCN(coff_sym
->Type
)
312 && (coff_sym
->SectionNumber
> 0) )
314 if( coff_sym
->N
.Name
.NotLong
)
316 memcpy(namebuff
, coff_sym
->N
.ShortName
, 8);
318 nampnt
= &namebuff
[0];
322 nampnt
= coff_strtab
+ coff_sym
->N
.Name
.StrTaboff
;
326 new_addr
.off
= (int) (deefer
->load_addr
+ coff_sym
->Value
);
329 fprintf(stderr
, "%d: %x %s\n", i
, new_addr
.off
, nampnt
);
333 * Now we need to figure out which file this guy belongs to.
336 for(j
=0; j
< nfiles
; j
++)
338 if( coff_files
[j
].startaddr
<= coff_sym
->Value
339 && coff_files
[j
].endaddr
> coff_sym
->Value
)
341 this_file
= coff_files
[j
].filename
;
345 DEBUG_AddSymbol( nampnt
, &new_addr
, this_file
);
349 * For now, skip past the aux entries.
357 if( coff_files
!= NULL
)
367 DEBUG_ProcessDeferredDebug()
369 struct deferred_debug_info
* deefer
;
370 struct CodeViewDebug
* cvd
;
371 struct MiscDebug
* misc
;
373 for(deefer
= dbglist
; deefer
; deefer
= deefer
->next
)
375 switch(deefer
->dbgdir
->type
)
377 case IMAGE_DEBUG_TYPE_COFF
:
379 * Standard COFF debug information that VC++ adds when you
380 * use /debugtype:both with the linker.
383 fprintf(stderr
, "Processing COFF symbols...\n");
385 DEBUG_ProcessCoff(deefer
);
387 case IMAGE_DEBUG_TYPE_CODEVIEW
:
389 * This is a pointer to a PDB file of some sort.
391 cvd
= (struct CodeViewDebug
*) deefer
->dbg_info
;
393 fprintf(stderr
, "Processing PDB file %s\n", cvd
->cv_name
);
396 case IMAGE_DEBUG_TYPE_MISC
:
398 * A pointer to a .DBG file of some sort.
400 misc
= (struct MiscDebug
*) deefer
->dbg_info
;
402 fprintf(stderr
, "Processing DBG file %s\n", misc
->Data
);
407 * We should never get here...