Release 961222
[wine] / debugger / msc.c
1 /*
2  * File msc.c - read VC++ debug information from COFF and eventually
3  * from PDB files.
4  *
5  * Copyright (C) 1996, Eric Youngdale.
6  *
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.
11  */
12
13 #include <stdio.h>
14
15
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>
23
24 #include "win.h"
25 #include "pe_image.h"
26 #include "debugger.h"
27 #include "peexe.h"
28 #include "xmalloc.h"
29
30 /*
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.
34  */
35 struct CodeViewDebug
36 {
37         char                cv_nbtype[8];
38         unsigned int        cv_timestamp;
39         char                cv_unknown[4];
40         char                cv_name[1];
41 };
42
43 struct MiscDebug {
44     unsigned int       DataType;
45     unsigned int       Length;
46     char               Unicode;
47     char               Reserved[3];
48     char               Data[1];
49 };
50
51 /*
52  * This is the header that the COFF variety of debug header points to.
53  */
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];
60 };
61
62 struct CoffLinenum {
63         unsigned int    VirtualAddr;
64         unsigned int    Linenum;
65 };
66
67 struct CoffFiles {
68         unsigned int    startaddr;
69         unsigned int    endaddr;
70         char          * filename;
71 };
72
73
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;
87 };
88
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;
97
98 struct deferred_debug_info
99 {
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;
106 };
107
108 struct deferred_debug_info * dbglist = NULL;
109
110 /*
111  * A simple macro that tells us whether a given COFF symbol is a
112  * function or not.
113  */
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))
118
119
120 /*
121  * This is what we are looking for in the COFF symbols.
122  */
123 #define IMAGE_SYM_CLASS_EXTERNAL            0x2
124 #define IMAGE_SYM_CLASS_STATIC              0x3
125 #define IMAGE_SYM_CLASS_FILE                0x67
126
127 /*
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.
131  */
132 int
133 DEBUG_RegisterDebugInfo(int fd, struct pe_data * pe, 
134                         int load_addr, u_long v_addr, u_long size)
135 {
136   int                     rtn = FALSE;
137   struct PE_Debug_dir   * dbgptr;
138   struct deferred_debug_info * deefer;
139
140   dbgptr = (struct PE_Debug_dir *) (load_addr + v_addr);
141   for(; size > 0; size -= sizeof(*dbgptr), dbgptr++ )
142     {
143       switch(dbgptr->type)
144         {
145         case IMAGE_DEBUG_TYPE_COFF:
146         case IMAGE_DEBUG_TYPE_CODEVIEW:
147         case IMAGE_DEBUG_TYPE_MISC:
148           /*
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.
152            *
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.
156            */
157           if(    (dbgptr->type == IMAGE_DEBUG_TYPE_MISC)
158               && (pe->pe_header->coff.Characteristics & IMAGE_FILE_DEBUG_STRIPPED) == 0 )
159             {
160               break;
161             }
162
163           deefer = (struct deferred_debug_info *) xmalloc(sizeof(*deefer));
164           deefer->pe = pe;
165
166           deefer->dbg_info = NULL;
167           deefer->dbg_size = 0;
168
169           /*
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.
173            */
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);
178
179           deefer->load_addr = (char *) load_addr;
180           deefer->dbgdir = dbgptr;
181           deefer->next = dbglist;
182           dbglist = deefer;
183           break;
184         default:
185         }
186     }
187
188   return (rtn);
189
190 }
191
192 /*
193  * Process COFF debugging information embedded in a Win32 application.
194  *
195  * FIXME - we need to process the source file information and the line
196  * numbers.
197  */
198 static
199 int
200 DEBUG_ProcessCoff(struct deferred_debug_info * deefer)
201 {
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;
220
221   coff = (struct CoffDebug *) deefer->dbg_info;
222
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);
226
227   for(i=0; i < coff->N_Sym; i++ )
228     {
229       /*
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.
234        *
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.
238        */
239       coff_sym = (struct CoffSymbol *) ((unsigned int) coff_symbol + 18*i);
240       naux = coff_sym->NumberOfAuxSymbols;
241
242       if( coff_sym->StorageClass == IMAGE_SYM_CLASS_FILE )
243         {
244           if( nfiles + 1 >= nfiles_alloc )
245             {
246               nfiles_alloc += 10;
247               coff_files = (struct CoffFiles *) realloc( coff_files,
248                         nfiles_alloc * sizeof(struct CoffFiles));
249             }
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;
255         }
256
257       /*
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.
262        */
263       if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
264           && (naux != 0)
265           && (coff_sym->SectionNumber == 1) )
266         {
267           aux = (struct CoffAuxSection *) ((unsigned int) coff_sym + 18);
268           if( curr_file->startaddr > coff_sym->Value )
269             {
270               curr_file->startaddr = coff_sym->Value;
271             }
272           
273           if( curr_file->startaddr > coff_sym->Value )
274             {
275               curr_file->startaddr = coff_sym->Value;
276             }
277           
278           if( curr_file->endaddr < coff_sym->Value + aux->Length )
279             {
280               curr_file->endaddr = coff_sym->Value + aux->Length;
281             }
282           
283         }
284
285       if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
286           && (naux == 0)
287           && (coff_sym->SectionNumber == 1) )
288         {
289           /*
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.
293            */
294           if( coff_sym->N.Name.NotLong )
295             {
296               memcpy(namebuff, coff_sym->N.ShortName, 8);
297               namebuff[8] = '\0';
298               nampnt = &namebuff[0];
299             }
300           else
301             {
302               nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
303             }
304
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 );
308         }
309
310       if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
311           && ISFCN(coff_sym->Type)
312           && (coff_sym->SectionNumber > 0) )
313         {
314           if( coff_sym->N.Name.NotLong )
315             {
316               memcpy(namebuff, coff_sym->N.ShortName, 8);
317               namebuff[8] = '\0';
318               nampnt = &namebuff[0];
319             }
320           else
321             {
322               nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
323             }
324
325           new_addr.seg = 0;
326           new_addr.off = (int) (deefer->load_addr + coff_sym->Value);
327
328 #if 0
329           fprintf(stderr, "%d: %x %s\n", i, new_addr.off, nampnt);
330 #endif
331
332           /*
333            * Now we need to figure out which file this guy belongs to.
334            */
335           this_file = NULL;
336           for(j=0; j < nfiles; j++)
337             {
338               if( coff_files[j].startaddr <= coff_sym->Value
339                   && coff_files[j].endaddr > coff_sym->Value )
340                 {
341                   this_file = coff_files[j].filename;
342                   break;
343                 }
344             }
345           DEBUG_AddSymbol( nampnt, &new_addr, this_file );
346         }
347           
348       /*
349        * For now, skip past the aux entries.
350        */
351       i += naux;
352       
353     }
354     
355   rtn = TRUE;
356
357   if( coff_files != NULL )
358     {
359       free(coff_files);
360     }
361
362   return (rtn);
363
364 }
365
366 int
367 DEBUG_ProcessDeferredDebug()
368 {
369   struct deferred_debug_info * deefer;
370   struct CodeViewDebug       * cvd;
371   struct MiscDebug           * misc;
372
373   for(deefer = dbglist; deefer; deefer = deefer->next)
374     {
375       switch(deefer->dbgdir->type)
376         {
377         case IMAGE_DEBUG_TYPE_COFF:
378           /*
379            * Standard COFF debug information that VC++ adds when you
380            * use /debugtype:both with the linker.
381            */
382 #if 0
383           fprintf(stderr, "Processing COFF symbols...\n");
384 #endif
385           DEBUG_ProcessCoff(deefer);
386           break;
387         case IMAGE_DEBUG_TYPE_CODEVIEW:
388           /*
389            * This is a pointer to a PDB file of some sort.
390            */
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:
397           /*
398            * A pointer to a .DBG file of some sort.
399            */
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:
406           /*
407            * We should never get here...
408            */
409           break;
410         }
411     }
412   return TRUE;
413 }