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...