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