Release 961222
[wine/multimedia.git] / debugger / msc.c
blobdc29ca98a85805cf3fe8ba8956038c06d90dab8a
1 /*
2 * File msc.c - read VC++ debug information from COFF and eventually
3 * from PDB files.
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.
13 #include <stdio.h>
16 #include <sys/mman.h>
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <limits.h>
20 #include <strings.h>
21 #include <unistd.h>
22 #include <malloc.h>
24 #include "win.h"
25 #include "pe_image.h"
26 #include "debugger.h"
27 #include "peexe.h"
28 #include "xmalloc.h"
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.
35 struct CodeViewDebug
37 char cv_nbtype[8];
38 unsigned int cv_timestamp;
39 char cv_unknown[4];
40 char cv_name[1];
43 struct MiscDebug {
44 unsigned int DataType;
45 unsigned int Length;
46 char Unicode;
47 char Reserved[3];
48 char Data[1];
52 * This is the header that the COFF variety of debug header points to.
54 struct CoffDebug {
55 unsigned int N_Sym;
56 unsigned int SymbolOffset;
57 unsigned int N_Linenum;
58 unsigned int LinenumberOffset;
59 unsigned int Unused[4];
62 struct CoffLinenum {
63 unsigned int VirtualAddr;
64 unsigned int Linenum;
67 struct CoffFiles {
68 unsigned int startaddr;
69 unsigned int endaddr;
70 char * filename;
74 struct CoffSymbol {
75 union {
76 char ShortName[8];
77 struct {
78 unsigned int NotLong;
79 unsigned int StrTaboff;
80 } Name;
81 } N;
82 unsigned int Value;
83 short SectionNumber;
84 short Type;
85 char StorageClass;
86 unsigned char NumberOfAuxSymbols;
89 struct CoffAuxSection{
90 unsigned int Length;
91 unsigned short NumberOfRelocations;
92 unsigned short NumberOfLinenumbers;
93 unsigned int CheckSum;
94 short Number;
95 char Selection;
96 } Section;
98 struct deferred_debug_info
100 struct deferred_debug_info * next;
101 char * load_addr;
102 char * dbg_info;
103 int dbg_size;
104 struct PE_Debug_dir * dbgdir;
105 struct pe_data * pe;
108 struct deferred_debug_info * dbglist = NULL;
111 * A simple macro that tells us whether a given COFF symbol is a
112 * function or not.
114 #define N_TMASK 0x0030
115 #define IMAGE_SYM_DTYPE_FUNCTION 2
116 #define N_BTSHFT 4
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)
136 int rtn = FALSE;
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++ )
143 switch(dbgptr->type)
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
151 * PDB file.
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 )
160 break;
163 deefer = (struct deferred_debug_info *) xmalloc(sizeof(*deefer));
164 deefer->pe = pe;
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;
182 dbglist = deefer;
183 break;
184 default:
188 return (rtn);
193 * Process COFF debugging information embedded in a Win32 application.
195 * FIXME - we need to process the source file information and the line
196 * numbers.
198 static
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;
207 char * coff_strtab;
208 int i;
209 DBG_ADDR new_addr;
210 int rtn = FALSE;
211 int naux;
212 char namebuff[9];
213 char * nampnt;
214 int nfiles = 0;
215 int nfiles_alloc = 0;
216 struct CoffFiles * coff_files = NULL;
217 struct CoffFiles * curr_file = NULL;
218 char * this_file;
219 int j;
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
233 * we get it right.
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 )
246 nfiles_alloc += 10;
247 coff_files = (struct CoffFiles *) realloc( coff_files,
248 nfiles_alloc * sizeof(struct CoffFiles));
250 curr_file = coff_files + nfiles;
251 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
261 * go with.
263 if( (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
264 && (naux != 0)
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)
286 && (naux == 0)
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);
297 namebuff[8] = '\0';
298 nampnt = &namebuff[0];
300 else
302 nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
305 new_addr.seg = 0;
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);
317 namebuff[8] = '\0';
318 nampnt = &namebuff[0];
320 else
322 nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
325 new_addr.seg = 0;
326 new_addr.off = (int) (deefer->load_addr + coff_sym->Value);
328 #if 0
329 fprintf(stderr, "%d: %x %s\n", i, new_addr.off, nampnt);
330 #endif
333 * Now we need to figure out which file this guy belongs to.
335 this_file = NULL;
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;
342 break;
345 DEBUG_AddSymbol( nampnt, &new_addr, this_file );
349 * For now, skip past the aux entries.
351 i += naux;
355 rtn = TRUE;
357 if( coff_files != NULL )
359 free(coff_files);
362 return (rtn);
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.
382 #if 0
383 fprintf(stderr, "Processing COFF symbols...\n");
384 #endif
385 DEBUG_ProcessCoff(deefer);
386 break;
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;
392 #if 0
393 fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name);
394 #endif
395 break;
396 case IMAGE_DEBUG_TYPE_MISC:
398 * A pointer to a .DBG file of some sort.
400 misc = (struct MiscDebug *) deefer->dbg_info;
401 #if 0
402 fprintf(stderr, "Processing DBG file %s\n", misc->Data);
403 #endif
404 break;
405 default:
407 * We should never get here...
409 break;
412 return TRUE;