~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/programs/winedbg/symbol.c

Version: ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.