Update the address of the Free Software Foundation.
[wine] / programs / winedbg / symbol.c
1 /*
2  * Generate hash tables for Wine debugger symbols
3  *
4  * Copyright (C) 1993, Eric Youngdale.
5  *               2004-2005, Eric Pouech.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
24
25 #include "config.h"
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29
30 #include "debugger.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(winedbg);
34
35 static BOOL symbol_get_debug_start(DWORD mod_base, DWORD typeid, ULONG64* start)
36 {
37     DWORD                       count, tag;
38     char                        buffer[sizeof(TI_FINDCHILDREN_PARAMS) + 256 * sizeof(DWORD)];
39     TI_FINDCHILDREN_PARAMS*     fcp = (TI_FINDCHILDREN_PARAMS*)buffer;
40     int                         i;
41     struct dbg_type             type;
42
43     if (!typeid) return FALSE; /* native dbghelp not always fills the info field */
44     type.module = mod_base;
45     type.id = typeid;
46
47     if (!types_get_info(&type, TI_GET_CHILDRENCOUNT, &count)) return FALSE;
48     fcp->Start = 0;
49     while (count)
50     {
51         fcp->Count = min(count, 256);
52         if (types_get_info(&type, TI_FINDCHILDREN, fcp))
53         {
54             for (i = 0; i < min(fcp->Count, count); i++)
55             {
56                 type.id = fcp->ChildId[i];
57                 types_get_info(&type, TI_GET_SYMTAG, &tag);
58                 if (tag != SymTagFuncDebugStart) continue;
59                 return types_get_info(&type, TI_GET_ADDRESS, start);
60             }
61             count -= min(count, 256);
62             fcp->Start += 256;
63         }
64     }
65     return FALSE;
66 }
67
68 struct sgv_data
69 {
70 #define NUMDBGV                 100
71     struct
72     {
73         /* FIXME: NUMDBGV should be made variable */
74         struct dbg_lvalue               lvalue;
75         DWORD                           flags;
76     }                           syms[NUMDBGV];  /* out     : will be filled in with various found symbols */
77     int                         num;            /* out     : number of found symbols */
78     int                         num_thunks;     /* out     : number of thunks found */
79     const char*                 name;           /* in      : name of symbol to look up */
80     const char*                 filename;       /* in (opt): filename where to look up symbol */
81     int                         lineno;         /* in (opt): line number in filename where to look up symbol */
82     unsigned                    bp_disp : 1,    /* in      : whether if we take into account func address or func first displayable insn */
83                                 do_thunks : 1;  /* in      : whether we return thunks tags */
84     ULONG64                     frame_offset;   /* in      : frame for local & parameter variables look up */
85 };
86
87 static BOOL CALLBACK sgv_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
88 {
89     struct sgv_data*    sgv = (struct sgv_data*)ctx;
90     ULONG64             addr;
91     IMAGEHLP_LINE       il;
92     unsigned            cookie = DLV_TARGET, insp;
93
94     if (sym->Flags & SYMFLAG_REGISTER)
95     {
96         char    tmp[32];
97         DWORD*  val;
98         if (!memory_get_register(sym->Register, &val, tmp, sizeof(tmp)))
99         {
100             dbg_printf(" %s (register): %s\n", sym->Name, tmp);
101             return TRUE;
102         }
103         addr = (ULONG64)(DWORD_PTR)val;
104         cookie = DLV_HOST;
105     }
106     else if (sym->Flags & SYMFLAG_LOCAL) /* covers both local & parameters */
107     {
108         addr = sgv->frame_offset + sym->Address;
109     }
110     else if (sym->Flags & SYMFLAG_THUNK)
111     {
112         if (!sgv->do_thunks) return TRUE;
113         sgv->num_thunks++;
114         addr = sym->Address;
115     }
116     else
117     {
118         DWORD disp;
119         il.SizeOfStruct = sizeof(il);
120         SymGetLineFromAddr(dbg_curr_process->handle, sym->Address, &disp, &il);
121         if (sgv->filename && strcmp(sgv->filename, il.FileName))
122         {
123             WINE_FIXME("File name mismatch (%s / %s)\n", sgv->filename, il.FileName);
124             return TRUE;
125         }
126
127         if (sgv->lineno == -1)
128         {
129             if (!sgv->bp_disp || 
130                 !symbol_get_debug_start(sym->ModBase, sym->info, &addr))
131                 addr = sym->Address;
132         }
133         else
134         {
135             addr = 0;
136             do
137             {
138                 if (sgv->lineno == il.LineNumber)
139                 {
140                     addr = il.Address;
141                     break;
142                 }
143             } while (SymGetLineNext(dbg_curr_process->handle, &il));
144             if (!addr)
145             {
146                 WINE_FIXME("No line (%d) found for %s (setting to symbol)\n", 
147                            sgv->lineno, sgv->name);
148                 addr = sym->Address;
149             }
150         }
151     }
152
153     if (sgv->num >= NUMDBGV)
154     {
155         dbg_printf("Too many addresses for symbol '%s', limiting the first %d\n",
156                    sgv->name, NUMDBGV);
157         return FALSE;
158     }
159     WINE_TRACE("==> %s %s%s%s%s%s%s%s\n", 
160                sym->Name, 
161                (sym->Flags & SYMFLAG_FUNCTION) ? "func " : "",
162                (sym->Flags & SYMFLAG_FRAMEREL) ? "framerel " : "",
163                (sym->Flags & SYMFLAG_REGISTER) ? "register " : "",
164                (sym->Flags & SYMFLAG_REGREL) ? "regrel " : "",
165                (sym->Flags & SYMFLAG_PARAMETER) ? "param " : "",
166                (sym->Flags & SYMFLAG_LOCAL) ? "local " : "",
167                (sym->Flags & SYMFLAG_THUNK) ? "thunk " : "");
168
169     /* always keep the thunks at end of the array */
170     insp = sgv->num;
171     if (sgv->num_thunks && !(sym->Flags & SYMFLAG_THUNK))
172     {
173         insp -= sgv->num_thunks;
174         memmove(&sgv->syms[insp + 1], &sgv->syms[insp],
175                 sizeof(sgv->syms[0]) * sgv->num_thunks);
176     }
177     sgv->syms[insp].lvalue.cookie      = cookie;
178     sgv->syms[insp].lvalue.addr.Mode   = AddrModeFlat;
179     sgv->syms[insp].lvalue.addr.Offset = addr;
180     sgv->syms[insp].lvalue.type.module = sym->ModBase;
181     sgv->syms[insp].lvalue.type.id     = sym->TypeIndex;
182     sgv->syms[insp].flags              = sym->Flags;
183     sgv->num++;
184   
185     return TRUE;
186 }
187
188 /***********************************************************************
189  *           symbol_get_lvalue
190  *
191  * Get the address of a named symbol.
192  * Return values:
193  *      sglv_found:   if the symbol is found
194  *      sglv_unknown: if the symbol isn't found
195  *      sglv_aborted: some error occurred (likely, many symbols of same name exist,
196  *          and user didn't pick one of them)
197  */
198 enum sym_get_lval symbol_get_lvalue(const char* name, const int lineno,
199                                     struct dbg_lvalue* rtn, BOOL bp_disp)
200 {
201     struct sgv_data             sgv;
202     int                         i = 0;
203     char                        buffer[512];
204     DWORD                       opt;
205     IMAGEHLP_STACK_FRAME        ihsf;
206
207     if (strlen(name) + 4 > sizeof(buffer))
208     {
209         WINE_WARN("Too long symbol (%s)\n", name);
210         return sglv_unknown;
211     }
212
213     sgv.num        = 0;
214     sgv.num_thunks = 0;
215     sgv.name       = &buffer[2];
216     sgv.filename   = NULL;
217     sgv.lineno     = lineno;
218     sgv.bp_disp    = bp_disp ? TRUE : FALSE;
219     sgv.do_thunks  = DBG_IVAR(AlwaysShowThunks);
220
221     if (strchr(name, '!'))
222     {
223         strcpy(buffer, name);
224     }
225     else
226     {
227         buffer[0] = '*';
228         buffer[1] = '!';
229         strcpy(&buffer[2], name);
230     }
231
232     /* this is a wine specific options to return also ELF modules in the
233      * enumeration
234      */
235     SymSetOptions((opt = SymGetOptions()) | 0x40000000);
236     if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv))
237     {
238         SymSetOptions(opt);
239         return sglv_unknown;
240     }
241
242     if (!sgv.num && (name[0] != '_'))
243     {
244         char*   ptr = strchr(name, '!');
245
246         if (ptr++)
247         {
248             memmove(ptr + 1, ptr, strlen(ptr));
249             *ptr = '_';
250         }
251         else
252         {
253             buffer[0] = '*';
254             buffer[1] = '!';
255             buffer[2] = '_';
256             strcpy(&buffer[3], name);
257         }
258         if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv))
259         {
260             SymSetOptions(opt);
261             return sglv_unknown;
262         }
263     }
264     SymSetOptions(opt);
265
266     /* now grab local symbols */
267     if (stack_get_current_frame(&ihsf) && sgv.num < NUMDBGV)
268     {
269         sgv.frame_offset = ihsf.FrameOffset;
270         SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv);
271     }
272
273     if (!sgv.num)
274     {
275         dbg_printf("No symbols found for %s\n", name);
276         return sglv_unknown;
277     }
278
279     if (dbg_interactiveP)
280     {
281         if (sgv.num - sgv.num_thunks > 1 || /* many symbols non thunks (and showing only non thunks) */
282             (sgv.num > 1 && DBG_IVAR(AlwaysShowThunks)) || /* many symbols (showing symbols & thunks) */
283             (sgv.num == sgv.num_thunks && sgv.num_thunks > 1))
284         {
285             dbg_printf("Many symbols with name '%s', "
286                        "choose the one you want (<cr> to abort):\n", name);
287             for (i = 0; i < sgv.num; i++) 
288             {
289                 if (sgv.num - sgv.num_thunks > 1 && (sgv.syms[i].flags & SYMFLAG_THUNK) && !DBG_IVAR(AlwaysShowThunks))
290                     continue;
291                 dbg_printf("[%d]: ", i + 1);
292                 if (sgv.syms[i].flags & SYMFLAG_LOCAL)
293                 {
294                     dbg_printf("%s %sof %s\n",
295                                sgv.syms[i].flags & SYMFLAG_PARAMETER ? "Parameter" : "Local variable",
296                                sgv.syms[i].flags & (SYMFLAG_REGISTER|SYMFLAG_REGREL) ? "(in a register) " : "",
297                                name);
298                 }
299                 else if (sgv.syms[i].flags & SYMFLAG_THUNK) 
300                 {
301                     print_address(&sgv.syms[i].lvalue.addr, TRUE);
302                     /* FIXME: should display where the thunks points to */
303                     dbg_printf(" thunk %s\n", name);
304                 }
305                 else
306                 {
307                     print_address(&sgv.syms[i].lvalue.addr, TRUE);
308                     dbg_printf("\n");
309                 }
310             }
311             do
312             {
313                 i = 0;
314                 if (input_read_line("=> ", buffer, sizeof(buffer)))
315                 {
316                     if (buffer[0] == '\0') return sglv_aborted;
317                     i = atoi(buffer);
318                     if (i < 1 || i > sgv.num)
319                         dbg_printf("Invalid choice %d\n", i);
320                 }
321             } while (i < 1 || i > sgv.num);
322
323             /* The array is 0-based, but the choices are 1..n, 
324              * so we have to subtract one before returning.
325              */
326             i--;
327         }
328     }
329     else
330     {
331         /* FIXME: could display the list of non-picked up symbols */
332         if (sgv.num > 1)
333             dbg_printf("More than one symbol named %s, picking the first one\n", name);
334     }
335     *rtn = sgv.syms[i].lvalue;
336     return sglv_found;
337 }
338
339 BOOL symbol_is_local(const char* name)
340 {
341     struct sgv_data             sgv;
342     IMAGEHLP_STACK_FRAME        ihsf;
343
344     sgv.num        = 0;
345     sgv.num_thunks = 0;
346     sgv.name       = name;
347     sgv.filename   = NULL;
348     sgv.lineno     = 0;
349     sgv.bp_disp    = FALSE;
350     sgv.do_thunks  = FALSE;
351
352     if (stack_get_current_frame(&ihsf))
353     {
354         sgv.frame_offset = ihsf.FrameOffset;
355         SymEnumSymbols(dbg_curr_process->handle, 0, name, sgv_cb, (void*)&sgv);
356     }
357     return sgv.num > 0;
358 }
359
360 /***********************************************************************
361  *           symbol_read_symtable
362  *
363  * Read a symbol file into the hash table.
364  */
365 void symbol_read_symtable(const char* filename, unsigned long offset)
366 {
367     dbg_printf("No longer supported\n");
368
369 #if 0
370 /* FIXME: have to implement SymAddSymbol in dbghelp, but likely we'll need to link
371  * this with an already loaded module !! 
372  */
373     FILE*       symbolfile;
374     unsigned    addr;
375     char        type;
376     char*       cpnt;
377     char        buffer[256];
378     char        name[256];
379
380     if (!(symbolfile = fopen(filename, "r")))
381     {
382         WINE_WARN("Unable to open symbol table %s\n", filename);
383         return;
384     }
385
386     dbg_printf("Reading symbols from file %s\n", filename);
387
388     while (1)
389     {
390         fgets(buffer, sizeof(buffer), symbolfile);
391         if (feof(symbolfile)) break;
392
393         /* Strip any text after a # sign (i.e. comments) */
394         cpnt = strchr(buffer, '#');
395         if (cpnt) *cpnt = '\0';
396
397         /* Quietly ignore any lines that have just whitespace */
398         for (cpnt = buffer; *cpnt; cpnt++)
399         {
400             if (*cpnt != ' ' && *cpnt != '\t') break;
401         }
402         if (!*cpnt || *cpnt == '\n') continue;
403
404         if (sscanf(buffer, "%lx %c %s", &addr, &type, name) == 3)
405         {
406             if (value.addr.off + offset < value.addr.off)
407                 WINE_WARN("Address wrap around\n");
408             value.addr.off += offset;
409             SymAddSymbol(current_process->handle, BaseOfDll,
410                          name, addr, 0, 0);
411         }
412     }
413     fclose(symbolfile);
414 #endif
415 }
416
417 /***********************************************************************
418  *           symbol_get_function_line_status
419  *
420  * Find the symbol nearest to a given address.
421  */
422 enum dbg_line_status symbol_get_function_line_status(const ADDRESS* addr)
423 {
424     IMAGEHLP_LINE       il;
425     DWORD               disp;
426     ULONG64             disp64, start;
427     DWORD               lin = (DWORD)memory_to_linear_addr(addr);
428     char                buffer[sizeof(SYMBOL_INFO) + 256];
429     SYMBOL_INFO*        sym = (SYMBOL_INFO*)buffer;
430
431     il.SizeOfStruct = sizeof(il);
432     sym->SizeOfStruct = sizeof(SYMBOL_INFO);
433     sym->MaxNameLen = sizeof(buffer) - sizeof(SYMBOL_INFO);
434
435     /* do we have some info for lin address ? */
436     if (!SymFromAddr(dbg_curr_process->handle, lin, &disp64, sym))
437         return dbg_no_line_info;
438
439     switch (sym->Tag)
440     {
441     case SymTagThunk:
442         /* FIXME: so far dbghelp doesn't return the 16 <=> 32 thunks
443          * and furthermore, we no longer take care of them !!!
444          */
445         return dbg_in_a_thunk;
446     case SymTagFunction:
447     case SymTagPublicSymbol: break;
448     default:
449         WINE_FIXME("Unexpected sym-tag 0x%08lx\n", sym->Tag);
450     case SymTagData:
451         return dbg_no_line_info;
452     }
453     /* we should have a function now */
454     if (!SymGetLineFromAddr(dbg_curr_process->handle, lin, &disp, &il))
455         return dbg_no_line_info;
456
457     if (symbol_get_debug_start(sym->ModBase, sym->info, &start) && lin < start)
458         return dbg_not_on_a_line_number;
459     if (!sym->Size) sym->Size = 0x100000;
460     if (il.FileName && il.FileName[0] && disp < sym->Size)
461         return (disp == 0) ? dbg_on_a_line_number : dbg_not_on_a_line_number;
462
463     return dbg_no_line_info;
464 }
465
466 /***********************************************************************
467  *           symbol_get_line
468  *
469  * Find the symbol nearest to a given address.
470  * Returns sourcefile name and line number in a format that the listing
471  * handler can deal with.
472  */
473 BOOL symbol_get_line(const char* filename, const char* name, IMAGEHLP_LINE* line)
474 {
475     struct sgv_data     sgv;
476     char                buffer[512];
477     DWORD               opt, disp;
478
479     sgv.num        = 0;
480     sgv.num_thunks = 0;
481     sgv.name       = &buffer[2];
482     sgv.filename   = filename;
483     sgv.lineno     = -1;
484     sgv.bp_disp    = FALSE;
485     sgv.do_thunks  = FALSE;
486
487     buffer[0] = '*';
488     buffer[1] = '!';
489     strcpy(&buffer[2], name);
490
491     /* this is a wine specific options to return also ELF modules in the
492      * enumeration
493      */
494     SymSetOptions((opt = SymGetOptions()) | 0x40000000);
495     if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv))
496     {
497         SymSetOptions(opt);
498         return sglv_unknown;
499     }
500
501     if (!sgv.num && (name[0] != '_'))
502     {
503         buffer[2] = '_';
504         strcpy(&buffer[3], name);
505         if (!SymEnumSymbols(dbg_curr_process->handle, 0, buffer, sgv_cb, (void*)&sgv))
506         {
507             SymSetOptions(opt);
508             return sglv_unknown;
509         }
510     }
511     SymSetOptions(opt);
512
513     switch (sgv.num)
514     {
515     case 0:
516         if (filename)   dbg_printf("No such function %s in %s\n", name, filename);
517         else            dbg_printf("No such function %s\n", name);
518         return FALSE;
519     default:
520         WINE_FIXME("Several found, returning first (may not be what you want)...\n");
521     case 1:
522         return SymGetLineFromAddr(dbg_curr_process->handle, 
523                                   (DWORD)memory_to_linear_addr(&sgv.syms[0].lvalue.addr), 
524                                   &disp, line);
525     }
526     return TRUE;
527 }
528
529 static BOOL CALLBACK info_locals_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
530 {
531     ULONG               v, val;
532     char                buf[128];
533     struct dbg_type     type;
534
535     dbg_printf("\t");
536     type.module = sym->ModBase;
537     type.id = sym->TypeIndex;
538     types_print_type(&type, FALSE);
539
540     buf[0] = '\0';
541
542     if (sym->Flags & SYMFLAG_REGISTER)
543     {
544         char tmp[32];
545         DWORD* pval;
546         if (!memory_get_register(sym->Register, &pval, tmp, sizeof(tmp)))
547         {
548             dbg_printf(" %s (register): %s\n", sym->Name, tmp);
549             return TRUE;
550         }
551         sprintf(buf, " in register %s", tmp);
552         val = *pval;
553     }
554     else if (sym->Flags & SYMFLAG_LOCAL)
555     {
556         type.id = sym->TypeIndex;
557         v = (ULONG)ctx + sym->Address;
558
559         if (!dbg_read_memory((void*)v, &val, sizeof(val)))
560         {
561             dbg_printf(" %s (%s) *** cannot read at 0x%08lx\n", 
562                        sym->Name, (sym->Flags & SYMFLAG_PARAMETER) ? "parameter" : "local",
563                        v);
564             return TRUE;
565         }
566     }
567     dbg_printf(" %s = 0x%8.8lx (%s%s)\n", sym->Name, val, 
568                (sym->Flags & SYMFLAG_PARAMETER) ? "parameter" : "local", buf);
569
570     return TRUE;
571 }
572
573 int symbol_info_locals(void)
574 {
575     IMAGEHLP_STACK_FRAME        ihsf;
576     ADDRESS                     addr;
577
578     stack_get_current_frame(&ihsf);
579     addr.Mode = AddrModeFlat;
580     addr.Offset = ihsf.InstructionOffset;
581     print_address(&addr, FALSE);
582     dbg_printf(": (%08lx)\n", (DWORD_PTR)ihsf.FrameOffset);
583     SymEnumSymbols(dbg_curr_process->handle, 0, NULL, info_locals_cb, (void*)(DWORD_PTR)ihsf.FrameOffset);
584
585     return TRUE;
586
587 }
588
589 static BOOL CALLBACK symbols_info_cb(SYMBOL_INFO* sym, ULONG size, void* ctx)
590 {
591     struct dbg_type     type;
592     IMAGEHLP_MODULE     mi;
593
594     mi.SizeOfStruct = sizeof(mi);
595
596     if (!SymGetModuleInfo(dbg_curr_process->handle, sym->ModBase, &mi))
597         mi.ModuleName[0] = '\0';
598     else
599     {
600         size_t  len = strlen(mi.ModuleName);
601         if (len > 5 && !strcmp(mi.ModuleName + len - 5, "<elf>"))
602             mi.ModuleName[len - 5] = '\0';
603     }
604
605     dbg_printf("%08lx: %s!%s", (ULONG_PTR)sym->Address, mi.ModuleName, sym->Name);
606     type.id = sym->TypeIndex;
607     type.module = sym->ModBase;
608
609     if (sym->TypeIndex != dbg_itype_none && sym->TypeIndex != 0)
610     {
611         dbg_printf(" ");
612         types_print_type(&type, FALSE);
613     }
614     dbg_printf("\n");
615     return TRUE;
616 }
617
618 void symbol_info(const char* str)
619 {
620     char        buffer[512];
621     DWORD       opt;
622
623     if (strlen(str) + 3 >= sizeof(buffer))
624     {
625         dbg_printf("Symbol too long (%s)\n", str);
626         return;
627     }
628     buffer[0] = '*';
629     buffer[1] = '!';
630     strcpy(&buffer[2], str);
631     /* this is a wine specific options to return also ELF modules in the
632      * enumeration
633      */
634     SymSetOptions((opt = SymGetOptions()) | 0x40000000);
635     SymEnumSymbols(dbg_curr_process->handle, 0, buffer, symbols_info_cb, NULL);
636     SymSetOptions(opt);
637 }