ole32: Return an error in CoMarshalInterface if pStream is NULL.
[wine] / dlls / dbghelp / symbol.c
1 /*
2  * File symbol.c - management of symbols (lexical tree)
3  *
4  * Copyright (C) 1993, Eric Youngdale.
5  *               2004, 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
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <limits.h>
31 #include <sys/types.h>
32 #include <assert.h>
33 #ifdef HAVE_REGEX_H
34 # include <regex.h>
35 #endif
36
37 #include "wine/debug.h"
38 #include "dbghelp_private.h"
39 #include "winnls.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
42 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
43
44 inline static int cmp_addr(ULONG64 a1, ULONG64 a2)
45 {
46     if (a1 > a2) return 1;
47     if (a1 < a2) return -1;
48     return 0;
49 }
50
51 inline static int cmp_sorttab_addr(const struct module* module, int idx, ULONG64 addr)
52 {
53     ULONG64     ref;
54
55     symt_get_info(&module->addr_sorttab[idx]->symt, TI_GET_ADDRESS, &ref);
56     return cmp_addr(ref, addr);
57 }
58
59 int symt_cmp_addr(const void* p1, const void* p2)
60 {
61     const struct symt*  sym1 = *(const struct symt* const *)p1;
62     const struct symt*  sym2 = *(const struct symt* const *)p2;
63     ULONG64     a1, a2;
64
65     symt_get_info(sym1, TI_GET_ADDRESS, &a1);
66     symt_get_info(sym2, TI_GET_ADDRESS, &a2);
67     return cmp_addr(a1, a2);
68 }
69
70 static inline void re_append(char** mask, unsigned* len, char ch)
71 {
72     *mask = HeapReAlloc(GetProcessHeap(), 0, *mask, ++(*len));
73     (*mask)[*len - 2] = ch;
74 }
75
76 /* transforms a dbghelp's regular expression into a POSIX one
77  * Here are the valid dbghelp reg ex characters:
78  *      *       0 or more characters
79  *      ?       a single character
80  *      []      list
81  *      #       0 or more of preceding char
82  *      +       1 or more of preceding char
83  *      escapes \ on #, ?, [, ], *, +. don't work on -
84  */
85 static void compile_regex(const char* str, int numchar, regex_t* re, BOOL _case)
86 {
87     char*       mask = HeapAlloc(GetProcessHeap(), 0, 1);
88     unsigned    len = 1;
89     BOOL        in_escape = FALSE;
90     unsigned    flags = REG_NOSUB;
91
92     re_append(&mask, &len, '^');
93
94     while (*str && numchar--)
95     {
96         /* FIXME: this shouldn't be valid on '-' */
97         if (in_escape)
98         {
99             re_append(&mask, &len, '\\');
100             re_append(&mask, &len, *str);
101             in_escape = FALSE;
102         }
103         else switch (*str)
104         {
105         case '\\': in_escape = TRUE; break;
106         case '*':  re_append(&mask, &len, '.'); re_append(&mask, &len, '*'); break;
107         case '?':  re_append(&mask, &len, '.'); break;
108         case '#':  re_append(&mask, &len, '*'); break;
109         /* escape some valid characters in dbghelp reg exp:s */
110         case '$':  re_append(&mask, &len, '\\'); re_append(&mask, &len, '$'); break;
111         /* +, [, ], - are the same in dbghelp & POSIX, use them as any other char */
112         default:   re_append(&mask, &len, *str); break;
113         }
114         str++;
115     }
116     if (in_escape)
117     {
118         re_append(&mask, &len, '\\');
119         re_append(&mask, &len, '\\');
120     }
121     re_append(&mask, &len, '$');
122     mask[len - 1] = '\0';
123     if (_case) flags |= REG_ICASE;
124     if (regcomp(re, mask, flags)) FIXME("Couldn't compile %s\n", mask);
125     HeapFree(GetProcessHeap(), 0, mask);
126 }
127
128 struct symt_compiland* symt_new_compiland(struct module* module, 
129                                           unsigned long address, unsigned src_idx)
130 {
131     struct symt_compiland*    sym;
132
133     TRACE_(dbghelp_symt)("Adding compiland symbol %s:%s\n", 
134                          module->module.ModuleName, source_get(module, src_idx));
135     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
136     {
137         sym->symt.tag = SymTagCompiland;
138         sym->address  = address;
139         sym->source   = src_idx;
140         vector_init(&sym->vchildren, sizeof(struct symt*), 32);
141     }
142     return sym;
143 }
144
145 struct symt_public* symt_new_public(struct module* module, 
146                                     struct symt_compiland* compiland,
147                                     const char* name,
148                                     unsigned long address, unsigned size,
149                                     BOOL in_code, BOOL is_func)
150 {
151     struct symt_public* sym;
152     struct symt**       p;
153
154     TRACE_(dbghelp_symt)("Adding public symbol %s:%s @%lx\n", 
155                          module->module.ModuleName, name, address);
156     if ((dbghelp_options & SYMOPT_AUTO_PUBLICS) && 
157         symt_find_nearest(module, address) != NULL)
158         return NULL;
159     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
160     {
161         sym->symt.tag      = SymTagPublicSymbol;
162         sym->hash_elt.name = pool_strdup(&module->pool, name);
163         hash_table_add(&module->ht_symbols, &sym->hash_elt);
164         module->sortlist_valid = FALSE;
165         sym->container     = compiland ? &compiland->symt : NULL;
166         sym->address       = address;
167         sym->size          = size;
168         sym->in_code       = in_code;
169         sym->is_function   = is_func;
170         if (compiland)
171         {
172             p = vector_add(&compiland->vchildren, &module->pool);
173             *p = &sym->symt;
174         }
175     }
176     return sym;
177 }
178
179 struct symt_data* symt_new_global_variable(struct module* module, 
180                                            struct symt_compiland* compiland, 
181                                            const char* name, unsigned is_static,
182                                            unsigned long addr, unsigned long size,
183                                            struct symt* type)
184 {
185     struct symt_data*   sym;
186     struct symt**       p;
187     DWORD64             tsz;
188
189     TRACE_(dbghelp_symt)("Adding global symbol %s:%s @%lx %p\n", 
190                          module->module.ModuleName, name, addr, type);
191     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
192     {
193         sym->symt.tag      = SymTagData;
194         sym->hash_elt.name = pool_strdup(&module->pool, name);
195         hash_table_add(&module->ht_symbols, &sym->hash_elt);
196         module->sortlist_valid = FALSE;
197         sym->kind          = is_static ? DataIsFileStatic : DataIsGlobal;
198         sym->container     = compiland ? &compiland->symt : NULL;
199         sym->type          = type;
200         sym->u.var.offset  = addr;
201         if (type && size && symt_get_info(type, TI_GET_LENGTH, &tsz))
202         {
203             if (tsz != size)
204                 FIXME("Size mismatch for %s.%s between type (%s) and src (%lu)\n",
205                       module->module.ModuleName, name, 
206                       wine_dbgstr_longlong(tsz), size);
207         }
208         if (compiland)
209         {
210             p = vector_add(&compiland->vchildren, &module->pool);
211             *p = &sym->symt;
212         }
213     }
214     return sym;
215 }
216
217 struct symt_function* symt_new_function(struct module* module, 
218                                         struct symt_compiland* compiland, 
219                                         const char* name,
220                                         unsigned long addr, unsigned long size,
221                                         struct symt* sig_type)
222 {
223     struct symt_function*       sym;
224     struct symt**               p;
225
226     TRACE_(dbghelp_symt)("Adding global function %s:%s @%lx-%lx\n", 
227                          module->module.ModuleName, name, addr, addr + size - 1);
228
229     assert(!sig_type || sig_type->tag == SymTagFunctionType);
230     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
231     {
232         sym->symt.tag  = SymTagFunction;
233         sym->hash_elt.name = pool_strdup(&module->pool, name);
234         hash_table_add(&module->ht_symbols, &sym->hash_elt);
235         module->sortlist_valid = FALSE;
236         sym->container = &compiland->symt;
237         sym->address   = addr;
238         sym->type      = sig_type;
239         sym->size      = size;
240         vector_init(&sym->vlines,  sizeof(struct line_info), 64);
241         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
242         if (compiland)
243         {
244             p = vector_add(&compiland->vchildren, &module->pool);
245             *p = &sym->symt;
246         }
247     }
248     return sym;
249 }
250
251 void symt_add_func_line(struct module* module, struct symt_function* func,
252                         unsigned source_idx, int line_num, unsigned long offset)
253 {
254     struct line_info*   dli;
255     BOOL                last_matches = FALSE;
256
257     if (func == NULL || !(dbghelp_options & SYMOPT_LOAD_LINES)) return;
258
259     TRACE_(dbghelp_symt)("(%p)%s:%lx %s:%u\n", 
260                          func, func->hash_elt.name, offset, 
261                          source_get(module, source_idx), line_num);
262
263     assert(func->symt.tag == SymTagFunction);
264
265     dli = NULL;
266     while ((dli = vector_iter_down(&func->vlines, dli)))
267     {
268         if (dli->is_source_file)
269         {
270             last_matches = (source_idx == dli->u.source_file);
271             break;
272         }
273     }
274
275     if (!last_matches)
276     {
277         /* we shouldn't have line changes on first line of function */
278         dli = vector_add(&func->vlines, &module->pool);
279         dli->is_source_file = 1;
280         dli->is_first       = dli->is_last = 0;
281         dli->line_number    = 0;
282         dli->u.source_file  = source_idx;
283     }
284     dli = vector_add(&func->vlines, &module->pool);
285     dli->is_source_file = 0;
286     dli->is_first       = dli->is_last = 0;
287     dli->line_number    = line_num;
288     dli->u.pc_offset    = func->address + offset;
289 }
290
291 /******************************************************************
292  *             symt_add_func_local
293  *
294  * Adds a new local/parameter to a given function:
295  * In any cases, dt tells whether it's a local variable or a parameter
296  * If regno it's not 0:
297  *      - then variable is stored in a register
298  *      - otherwise, value is referenced by register + offset
299  * Otherwise, the variable is stored on the stack:
300  *      - offset is then the offset from the frame register
301  */
302 struct symt_data* symt_add_func_local(struct module* module, 
303                                       struct symt_function* func, 
304                                       enum DataKind dt,
305                                       const struct location* loc,
306                                       struct symt_block* block, 
307                                       struct symt* type, const char* name)
308 {
309     struct symt_data*   locsym;
310     struct symt**       p;
311
312     TRACE_(dbghelp_symt)("Adding local symbol (%s:%s): %s %p\n", 
313                          module->module.ModuleName, func->hash_elt.name, 
314                          name, type);
315
316     assert(func);
317     assert(func->symt.tag == SymTagFunction);
318     assert(dt == DataIsParam || dt == DataIsLocal);
319
320     locsym = pool_alloc(&module->pool, sizeof(*locsym));
321     locsym->symt.tag      = SymTagData;
322     locsym->hash_elt.name = pool_strdup(&module->pool, name);
323     locsym->hash_elt.next = NULL;
324     locsym->kind          = dt;
325     locsym->container     = &block->symt;
326     locsym->type          = type;
327     locsym->u.var         = *loc;
328     if (block)
329         p = vector_add(&block->vchildren, &module->pool);
330     else
331         p = vector_add(&func->vchildren, &module->pool);
332     *p = &locsym->symt;
333     return locsym;
334 }
335
336
337 struct symt_block* symt_open_func_block(struct module* module, 
338                                         struct symt_function* func,
339                                         struct symt_block* parent_block, 
340                                         unsigned pc, unsigned len)
341 {
342     struct symt_block*  block;
343     struct symt**       p;
344
345     assert(func);
346     assert(func->symt.tag == SymTagFunction);
347
348     assert(!parent_block || parent_block->symt.tag == SymTagBlock);
349     block = pool_alloc(&module->pool, sizeof(*block));
350     block->symt.tag = SymTagBlock;
351     block->address  = func->address + pc;
352     block->size     = len;
353     block->container = parent_block ? &parent_block->symt : &func->symt;
354     vector_init(&block->vchildren, sizeof(struct symt*), 4);
355     if (parent_block)
356         p = vector_add(&parent_block->vchildren, &module->pool);
357     else
358         p = vector_add(&func->vchildren, &module->pool);
359     *p = &block->symt;
360
361     return block;
362 }
363
364 struct symt_block* symt_close_func_block(struct module* module, 
365                                          struct symt_function* func,
366                                          struct symt_block* block, unsigned pc)
367 {
368     assert(func);
369     assert(func->symt.tag == SymTagFunction);
370
371     if (pc) block->size = func->address + pc - block->address;
372     return (block->container->tag == SymTagBlock) ? 
373         GET_ENTRY(block->container, struct symt_block, symt) : NULL;
374 }
375
376 struct symt_function_point* symt_add_function_point(struct module* module, 
377                                                     struct symt_function* func,
378                                                     enum SymTagEnum point, 
379                                                     const struct location* loc,
380                                                     const char* name)
381 {
382     struct symt_function_point* sym;
383     struct symt**               p;
384
385     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
386     {
387         sym->symt.tag = point;
388         sym->parent   = func;
389         sym->loc      = *loc;
390         sym->name     = name ? pool_strdup(&module->pool, name) : NULL;
391         p = vector_add(&func->vchildren, &module->pool);
392         *p = &sym->symt;
393     }
394     return sym;
395 }
396
397 BOOL symt_normalize_function(struct module* module, struct symt_function* func)
398 {
399     unsigned            len;
400     struct line_info*   dli;
401
402     assert(func);
403     /* We aren't adding any more locals or line numbers to this function.
404      * Free any spare memory that we might have allocated.
405      */
406     assert(func->symt.tag == SymTagFunction);
407
408 /* EPP     vector_pool_normalize(&func->vlines,    &module->pool); */
409 /* EPP     vector_pool_normalize(&func->vchildren, &module->pool); */
410
411     len = vector_length(&func->vlines);
412     if (len--)
413     {
414         dli = vector_at(&func->vlines,   0);  dli->is_first = 1;
415         dli = vector_at(&func->vlines, len);  dli->is_last  = 1;
416     }
417     return TRUE;
418 }
419
420 struct symt_thunk* symt_new_thunk(struct module* module, 
421                                   struct symt_compiland* compiland, 
422                                   const char* name, THUNK_ORDINAL ord,
423                                   unsigned long addr, unsigned long size)
424 {
425     struct symt_thunk*  sym;
426
427     TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n", 
428                          module->module.ModuleName, name, addr, addr + size - 1);
429
430     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
431     {
432         sym->symt.tag  = SymTagThunk;
433         sym->hash_elt.name = pool_strdup(&module->pool, name);
434         hash_table_add(&module->ht_symbols, &sym->hash_elt);
435         module->sortlist_valid = FALSE;
436         sym->container = &compiland->symt;
437         sym->address   = addr;
438         sym->size      = size;
439         sym->ordinal   = ord;
440         if (compiland)
441         {
442             struct symt**       p;
443             p = vector_add(&compiland->vchildren, &module->pool);
444             *p = &sym->symt;
445         }
446     }
447     return sym;
448 }
449
450 struct symt_data* symt_new_constant(struct module* module,
451                                     struct symt_compiland* compiland,
452                                     const char* name, struct symt* type,
453                                     const VARIANT* v)
454 {
455     struct symt_data*  sym;
456
457     TRACE_(dbghelp_symt)("Adding constant value %s:%s\n",
458                          module->module.ModuleName, name);
459
460     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
461     {
462         sym->symt.tag      = SymTagData;
463         sym->hash_elt.name = pool_strdup(&module->pool, name);
464         hash_table_add(&module->ht_symbols, &sym->hash_elt);
465         module->sortlist_valid = FALSE;
466         sym->kind          = DataIsConstant;
467         sym->container     = compiland ? &compiland->symt : NULL;
468         sym->type          = type;
469         sym->u.value       = *v;
470         if (compiland)
471         {
472             struct symt**       p;
473             p = vector_add(&compiland->vchildren, &module->pool);
474             *p = &sym->symt;
475         }
476     }
477     return sym;
478 }
479
480 /* expect sym_info->MaxNameLen to be set before being called */
481 static void symt_fill_sym_info(const struct module_pair* pair,
482                                const struct symt_function* func,
483                                const struct symt* sym, SYMBOL_INFO* sym_info)
484 {
485     const char* name;
486     DWORD64 size;
487
488     if (!symt_get_info(sym, TI_GET_TYPE, &sym_info->TypeIndex))
489         sym_info->TypeIndex = 0;
490     sym_info->info = (DWORD)sym;
491     sym_info->Reserved[0] = sym_info->Reserved[1] = 0;
492     if (!symt_get_info(sym, TI_GET_LENGTH, &size) &&
493         (!sym_info->TypeIndex ||
494          !symt_get_info((struct symt*)sym_info->TypeIndex, TI_GET_LENGTH, &size)))
495         size = 0;
496     sym_info->Size = (DWORD)size;
497     sym_info->ModBase = pair->requested->module.BaseOfImage;
498     sym_info->Flags = 0;
499     sym_info->Value = 0;
500
501     switch (sym->tag)
502     {
503     case SymTagData:
504         {
505             const struct symt_data*  data = (const struct symt_data*)sym;
506             switch (data->kind)
507             {
508             case DataIsParam:
509                 sym_info->Flags |= SYMFLAG_PARAMETER;
510                 /* fall through */
511             case DataIsLocal:
512                 {
513                     struct location loc = data->u.var;
514
515                     if (loc.kind >= loc_user)
516                         pair->effective->loc_compute(pair->pcs, pair->effective, func, &loc);
517
518                     switch (loc.kind)
519                     {
520                     case loc_error:
521                         /* for now we report error cases as a negative register number */
522                         sym_info->Flags |= SYMFLAG_LOCAL;
523                         /* fall through */
524                     case loc_register:
525                         sym_info->Flags |= SYMFLAG_REGISTER;
526                         sym_info->Register = loc.reg;
527                         sym_info->Address = 0;
528                         break;
529                     case loc_regrel:
530                         sym_info->Flags |= SYMFLAG_LOCAL | SYMFLAG_REGREL;
531                         /* FIXME: it's i386 dependent !!! */
532                         sym_info->Register = loc.reg ? loc.reg : CV_REG_EBP;
533                         sym_info->Address = loc.offset;
534                         break;
535                     default:
536                         FIXME("Shouldn't happen (kind=%d), debug reader backend is broken\n", loc.kind);
537                         assert(0);
538                     }
539                 }
540                 break;
541             case DataIsGlobal:
542             case DataIsFileStatic:
543                 symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
544                 sym_info->Register = 0;
545                 break;
546             case DataIsConstant:
547                 sym_info->Flags |= SYMFLAG_VALUEPRESENT;
548                 switch (data->u.value.n1.n2.vt)
549                 {
550                 case VT_I4:  sym_info->Value = (ULONG)data->u.value.n1.n2.n3.lVal; break;
551                 case VT_I2:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.iVal; break;
552                 case VT_I1:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.cVal; break;
553                 case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break;
554                 case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break;
555                 case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break;
556                 case VT_I1 | VT_BYREF: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.byref; break;
557                 default:
558                     FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
559                     sym_info->Value = 0;
560                     break;
561                 }
562                 break;
563             default:
564                 FIXME("Unhandled kind (%u) in sym data\n", data->kind);
565             }
566         }
567         break;
568     case SymTagPublicSymbol:
569         sym_info->Flags |= SYMFLAG_EXPORT;
570         symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
571         break;
572     case SymTagFunction:
573         sym_info->Flags |= SYMFLAG_FUNCTION;
574         symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
575         break;
576     case SymTagThunk:
577         sym_info->Flags |= SYMFLAG_THUNK;
578         symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
579         break;
580     default:
581         symt_get_info(sym, TI_GET_ADDRESS, &sym_info->Address);
582         sym_info->Register = 0;
583         break;
584     }
585     sym_info->Scope = 0; /* FIXME */
586     sym_info->Tag = sym->tag;
587     name = symt_get_name(sym);
588     if (sym_info->MaxNameLen)
589     {
590         if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) ||
591             (sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name, 
592                                                       sym_info->MaxNameLen, UNDNAME_COMPLETE) == 0))
593         {
594             sym_info->NameLen = min(strlen(name), sym_info->MaxNameLen - 1);
595             memcpy(sym_info->Name, name, sym_info->NameLen);
596             sym_info->Name[sym_info->NameLen] = '\0';
597         }
598     }
599     TRACE_(dbghelp_symt)("%p => %s %u %s\n",
600                          sym, sym_info->Name, sym_info->Size,
601                          wine_dbgstr_longlong(sym_info->Address));
602 }
603
604 struct sym_enum
605 {
606     PSYM_ENUMERATESYMBOLS_CALLBACK      cb;
607     PVOID                               user;
608     SYMBOL_INFO*                        sym_info;
609     DWORD                               index;
610     DWORD                               tag;
611     DWORD64                             addr;
612     char                                buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
613 };
614
615 static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair,
616                         const struct symt_function* func, const struct symt* sym)
617 {
618     symt_fill_sym_info(pair, func, sym, se->sym_info);
619     if (se->index && se->sym_info->info != se->index) return FALSE;
620     if (se->tag && se->sym_info->Tag != se->tag) return FALSE;
621     if (se->addr && !(se->addr >= se->sym_info->Address && se->addr < se->sym_info->Address + se->sym_info->Size)) return FALSE;
622     return !se->cb(se->sym_info, se->sym_info->Size, se->user);
623 }
624
625 static BOOL symt_enum_module(struct module_pair* pair, regex_t* regex,
626                              const struct sym_enum* se)
627 {
628     void*                       ptr;
629     struct symt_ht*             sym = NULL;
630     struct hash_table_iter      hti;
631
632     hash_table_iter_init(&pair->effective->ht_symbols, &hti, NULL);
633     while ((ptr = hash_table_iter_up(&hti)))
634     {
635         sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
636         if (sym->hash_elt.name &&
637             regexec(regex, sym->hash_elt.name, 0, NULL, 0) == 0)
638         {
639             se->sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
640             se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO);
641             if (send_symbol(se, pair, NULL, &sym->symt)) return TRUE;
642         }
643     }   
644     return FALSE;
645 }
646
647 /***********************************************************************
648  *              resort_symbols
649  *
650  * Rebuild sorted list of symbols for a module.
651  */
652 static BOOL resort_symbols(struct module* module)
653 {
654     void*                       ptr;
655     struct symt_ht*             sym;
656     struct hash_table_iter      hti;
657     ULONG64                     addr;
658
659     if (!(module->module.NumSyms = module->ht_symbols.num_elts))
660         return FALSE;
661     
662     if (module->addr_sorttab)
663         module->addr_sorttab = HeapReAlloc(GetProcessHeap(), 0,
664                                            module->addr_sorttab, 
665                                            module->module.NumSyms * sizeof(struct symt_ht*));
666     else
667         module->addr_sorttab = HeapAlloc(GetProcessHeap(), 0,
668                                          module->module.NumSyms * sizeof(struct symt_ht*));
669     if (!module->addr_sorttab) return FALSE;
670
671     module->num_sorttab = 0;
672     hash_table_iter_init(&module->ht_symbols, &hti, NULL);
673     while ((ptr = hash_table_iter_up(&hti)))
674     {
675         sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
676         assert(sym);
677         /* Don't store in sorttab symbol without address, they are of
678          * no use here (e.g. constant values)
679          * As the number of those symbols is very couple (a couple per module)
680          * we don't bother for the unused spots at the end of addr_sorttab
681          */
682         if (symt_get_info(&sym->symt, TI_GET_ADDRESS, &addr))
683             module->addr_sorttab[module->num_sorttab++] = sym;
684     }
685     qsort(module->addr_sorttab, module->num_sorttab, sizeof(struct symt_ht*), symt_cmp_addr);
686     return module->sortlist_valid = TRUE;
687 }
688
689 /* assume addr is in module */
690 struct symt_ht* symt_find_nearest(struct module* module, DWORD addr)
691 {
692     int         mid, high, low;
693     ULONG64     ref_addr, ref_size;
694
695     if (!module->sortlist_valid || !module->addr_sorttab)
696     {
697         if (!resort_symbols(module)) return NULL;
698     }
699
700     /*
701      * Binary search to find closest symbol.
702      */
703     low = 0;
704     high = module->num_sorttab;
705
706     symt_get_info(&module->addr_sorttab[0]->symt, TI_GET_ADDRESS, &ref_addr);
707     if (addr < ref_addr) return NULL;
708     if (high)
709     {
710         symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_ADDRESS, &ref_addr);
711         if (!symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_LENGTH, &ref_size) || !ref_size)
712             ref_size = 0x1000; /* arbitrary value */
713         if (addr >= ref_addr + ref_size) return NULL;
714     }
715     
716     while (high > low + 1)
717     {
718         mid = (high + low) / 2;
719         if (cmp_sorttab_addr(module, mid, addr) < 0)
720             low = mid;
721         else
722             high = mid;
723     }
724     if (low != high && high != module->num_sorttab &&
725         cmp_sorttab_addr(module, high, addr) <= 0)
726         low = high;
727
728     /* If found symbol is a public symbol, check if there are any other entries that
729      * might also have the same address, but would get better information
730      */
731     if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
732     {   
733         symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
734         if (low > 0 &&
735             module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
736             !cmp_sorttab_addr(module, low - 1, ref_addr))
737             low--;
738         else if (low < module->num_sorttab - 1 &&
739                  module->addr_sorttab[low + 1]->symt.tag != SymTagPublicSymbol &&
740                  !cmp_sorttab_addr(module, low + 1, ref_addr))
741             low++;
742     }
743     /* finally check that we fit into the found symbol */
744     symt_get_info(&module->addr_sorttab[low]->symt, TI_GET_ADDRESS, &ref_addr);
745     if (addr < ref_addr) return NULL;
746     if (!symt_get_info(&module->addr_sorttab[high - 1]->symt, TI_GET_LENGTH, &ref_size) || !ref_size)
747         ref_size = 0x1000; /* arbitrary value */
748     if (addr >= ref_addr + ref_size) return NULL;
749
750     return module->addr_sorttab[low];
751 }
752
753 static BOOL symt_enum_locals_helper(struct module_pair* pair,
754                                     regex_t* preg, const struct sym_enum* se,
755                                     struct symt_function* func, struct vector* v)
756 {
757     struct symt**       plsym = NULL;
758     struct symt*        lsym = NULL;
759     DWORD               pc = pair->pcs->ctx_frame.InstructionOffset;
760
761     while ((plsym = vector_iter_up(v, plsym)))
762     {
763         lsym = *plsym;
764         switch (lsym->tag)
765         {
766         case SymTagBlock:
767             {
768                 struct symt_block*  block = (struct symt_block*)lsym;
769                 if (pc < block->address || block->address + block->size <= pc)
770                     continue;
771                 if (!symt_enum_locals_helper(pair, preg, se, func, &block->vchildren))
772                     return FALSE;
773             }
774             break;
775         case SymTagData:
776             if (regexec(preg, symt_get_name(lsym), 0, NULL, 0) == 0)
777             {
778                 if (send_symbol(se, pair, func, lsym)) return FALSE;
779             }
780             break;
781         case SymTagLabel:
782         case SymTagFuncDebugStart:
783         case SymTagFuncDebugEnd:
784         case SymTagCustom:
785             break;
786         default:
787             FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag);
788             assert(0);
789         }
790     }
791     return TRUE;
792 }
793
794 static BOOL symt_enum_locals(struct process* pcs, const char* mask, 
795                              const struct sym_enum* se)
796 {
797     struct module_pair  pair;
798     struct symt_ht*     sym;
799     DWORD               pc = pcs->ctx_frame.InstructionOffset;
800
801     se->sym_info->SizeOfStruct = sizeof(*se->sym_info);
802     se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO);
803
804     pair.pcs = pcs;
805     pair.requested = module_find_by_addr(pair.pcs, pc, DMT_UNKNOWN);
806     if (!module_get_debug(&pair)) return FALSE;
807     if ((sym = symt_find_nearest(pair.effective, pc)) == NULL) return FALSE;
808
809     if (sym->symt.tag == SymTagFunction)
810     {
811         BOOL            ret;
812         regex_t         preg;
813
814         compile_regex(mask ? mask : "*", -1, &preg,
815                       dbghelp_options & SYMOPT_CASE_INSENSITIVE);
816         ret = symt_enum_locals_helper(&pair, &preg, se, (struct symt_function*)sym,
817                                       &((struct symt_function*)sym)->vchildren);
818         regfree(&preg);
819         return ret;
820         
821     }
822     return send_symbol(se, &pair, NULL, &sym->symt);
823 }
824
825 /******************************************************************
826  *              copy_symbolW
827  *
828  * Helper for transforming an ANSI symbol info into an UNICODE one.
829  * Assume that MaxNameLen is the same for both version (A & W).
830  */
831 static void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si)
832 {
833     siw->SizeOfStruct = si->SizeOfStruct;
834     siw->TypeIndex = si->TypeIndex; 
835     siw->Reserved[0] = si->Reserved[0];
836     siw->Reserved[1] = si->Reserved[1];
837     siw->Index = si->info; /* FIXME: see dbghelp.h */
838     siw->Size = si->Size;
839     siw->ModBase = si->ModBase;
840     siw->Flags = si->Flags;
841     siw->Value = si->Value;
842     siw->Address = si->Address;
843     siw->Register = si->Register;
844     siw->Scope = si->Scope;
845     siw->Tag = si->Tag;
846     siw->NameLen = si->NameLen;
847     siw->MaxNameLen = si->MaxNameLen;
848     MultiByteToWideChar(CP_ACP, 0, si->Name, -1, siw->Name, siw->MaxNameLen);
849 }
850
851 /******************************************************************
852  *              sym_enum
853  *
854  * Core routine for most of the enumeration of symbols
855  */
856 static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
857                      const struct sym_enum* se)
858 {
859     struct module_pair  pair;
860     const char*         bang;
861     regex_t             mod_regex, sym_regex;
862
863     pair.pcs = process_find_by_handle(hProcess);
864     if (BaseOfDll == 0)
865     {
866         /* do local variables ? */
867         if (!Mask || !(bang = strchr(Mask, '!')))
868             return symt_enum_locals(pair.pcs, Mask, se);
869
870         if (bang == Mask) return FALSE;
871
872         compile_regex(Mask, bang - Mask, &mod_regex, TRUE);
873         compile_regex(bang + 1, -1, &sym_regex, 
874                       dbghelp_options & SYMOPT_CASE_INSENSITIVE);
875         
876         for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next)
877         {
878             if (pair.requested->type == DMT_PE && module_get_debug(&pair))
879             {
880                 if (regexec(&mod_regex, pair.requested->module.ModuleName, 0, NULL, 0) == 0 &&
881                     symt_enum_module(&pair, &sym_regex, se))
882                     break;
883             }
884         }
885         /* not found in PE modules, retry on the ELF ones
886          */
887         if (!pair.requested && (dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES))
888         {
889             for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next)
890             {
891                 if (pair.requested->type == DMT_ELF &&
892                     !module_get_containee(pair.pcs, pair.requested) &&
893                     module_get_debug(&pair))
894                 {
895                     if (regexec(&mod_regex, pair.requested->module.ModuleName, 0, NULL, 0) == 0 &&
896                         symt_enum_module(&pair, &sym_regex, se))
897                     break;
898                 }
899             }
900         }
901         regfree(&mod_regex);
902         regfree(&sym_regex);
903         return TRUE;
904     }
905     pair.requested = module_find_by_addr(pair.pcs, BaseOfDll, DMT_UNKNOWN);
906     if (!module_get_debug(&pair))
907         return FALSE;
908
909     /* we always ignore module name from Mask when BaseOfDll is defined */
910     if (Mask && (bang = strchr(Mask, '!')))
911     {
912         if (bang == Mask) return FALSE;
913         Mask = bang + 1;
914     }
915
916     compile_regex(Mask ? Mask : "*", -1, &sym_regex, 
917                   dbghelp_options & SYMOPT_CASE_INSENSITIVE);
918     symt_enum_module(&pair, &sym_regex, se);
919     regfree(&sym_regex);
920
921     return TRUE;
922 }
923
924 /******************************************************************
925  *              SymEnumSymbols (DBGHELP.@)
926  *
927  * cases BaseOfDll = 0
928  *      !foo fails always (despite what MSDN states)
929  *      RE1!RE2 looks up all modules matching RE1, and in all these modules, lookup RE2
930  *      no ! in Mask, lookup in local Context
931  * cases BaseOfDll != 0
932  *      !foo fails always (despite what MSDN states)
933  *      RE1!RE2 gets RE2 from BaseOfDll (whatever RE1 is)
934  */
935 BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
936                            PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
937                            PVOID UserContext)
938 {
939     struct sym_enum     se;
940
941     TRACE("(%p %s %s %p %p)\n", 
942           hProcess, wine_dbgstr_longlong(BaseOfDll), debugstr_a(Mask),
943           EnumSymbolsCallback, UserContext);
944
945     se.cb = EnumSymbolsCallback;
946     se.user = UserContext;
947     se.index = 0;
948     se.tag = 0;
949     se.addr = 0;
950     se.sym_info = (PSYMBOL_INFO)se.buffer;
951
952     return sym_enum(hProcess, BaseOfDll, Mask, &se);
953 }
954
955 struct sym_enumW
956 {
957     PSYM_ENUMERATESYMBOLS_CALLBACKW     cb;
958     void*                               ctx;
959     PSYMBOL_INFOW                       sym_info;
960     char                                buffer[sizeof(SYMBOL_INFOW) + MAX_SYM_NAME];
961
962 };
963     
964 static BOOL CALLBACK sym_enumW(PSYMBOL_INFO si, ULONG size, PVOID ctx)
965 {
966     struct sym_enumW*   sew = ctx;
967
968     copy_symbolW(sew->sym_info, si);
969
970     return (sew->cb)(sew->sym_info, size, sew->ctx);
971 }
972
973 /******************************************************************
974  *              SymEnumSymbolsW (DBGHELP.@)
975  *
976  */
977 BOOL WINAPI SymEnumSymbolsW(HANDLE hProcess, ULONG64 BaseOfDll, PCWSTR Mask,
978                             PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
979                             PVOID UserContext)
980 {
981     struct sym_enumW    sew;
982     BOOL                ret = FALSE;
983     char*               maskA = NULL;
984
985     sew.ctx = UserContext;
986     sew.cb = EnumSymbolsCallback;
987     sew.sym_info = (PSYMBOL_INFOW)sew.buffer;
988
989     if (Mask)
990     {
991         unsigned len = WideCharToMultiByte(CP_ACP, 0, Mask, -1, NULL, 0, NULL, NULL);
992         maskA = HeapAlloc(GetProcessHeap(), 0, len);
993         if (!maskA) return FALSE;
994         WideCharToMultiByte(CP_ACP, 0, Mask, -1, maskA, len, NULL, NULL);
995     }
996     ret = SymEnumSymbols(hProcess, BaseOfDll, maskA, sym_enumW, &sew);
997     HeapFree(GetProcessHeap(), 0, maskA);
998
999     return ret;
1000 }
1001
1002 struct sym_enumerate
1003 {
1004     void*                       ctx;
1005     PSYM_ENUMSYMBOLS_CALLBACK   cb;
1006 };
1007
1008 static BOOL CALLBACK sym_enumerate_cb(PSYMBOL_INFO syminfo, ULONG size, void* ctx)
1009 {
1010     struct sym_enumerate*       se = (struct sym_enumerate*)ctx;
1011     return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx);
1012 }
1013
1014 /***********************************************************************
1015  *              SymEnumerateSymbols (DBGHELP.@)
1016  */
1017 BOOL WINAPI SymEnumerateSymbols(HANDLE hProcess, DWORD BaseOfDll,
1018                                 PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, 
1019                                 PVOID UserContext)
1020 {
1021     struct sym_enumerate        se;
1022
1023     se.ctx = UserContext;
1024     se.cb  = EnumSymbolsCallback;
1025     
1026     return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb, &se);
1027 }
1028
1029 /******************************************************************
1030  *              SymFromAddr (DBGHELP.@)
1031  *
1032  */
1033 BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, 
1034                         DWORD64* Displacement, PSYMBOL_INFO Symbol)
1035 {
1036     struct module_pair  pair;
1037     struct symt_ht*     sym;
1038
1039     pair.pcs = process_find_by_handle(hProcess);
1040     if (!pair.pcs) return FALSE;
1041     pair.requested = module_find_by_addr(pair.pcs, Address, DMT_UNKNOWN);
1042     if (!module_get_debug(&pair)) return FALSE;
1043     if ((sym = symt_find_nearest(pair.effective, Address)) == NULL) return FALSE;
1044
1045     symt_fill_sym_info(&pair, NULL, &sym->symt, Symbol);
1046     *Displacement = Address - Symbol->Address;
1047     return TRUE;
1048 }
1049
1050 /******************************************************************
1051  *              SymFromAddrW (DBGHELP.@)
1052  *
1053  */
1054 BOOL WINAPI SymFromAddrW(HANDLE hProcess, DWORD64 Address, 
1055                          DWORD64* Displacement, PSYMBOL_INFOW Symbol)
1056 {
1057     PSYMBOL_INFO        si;
1058     unsigned            len;
1059     BOOL                ret;
1060
1061     len = sizeof(*si) + Symbol->MaxNameLen * sizeof(WCHAR);
1062     si = HeapAlloc(GetProcessHeap(), 0, len);
1063     if (!si) return FALSE;
1064
1065     si->SizeOfStruct = sizeof(*si);
1066     si->MaxNameLen = Symbol->MaxNameLen;
1067     if ((ret = SymFromAddr(hProcess, Address, Displacement, si)))
1068     {
1069         copy_symbolW(Symbol, si);
1070     }
1071     HeapFree(GetProcessHeap(), 0, si);
1072     return ret;
1073 }
1074
1075 /******************************************************************
1076  *              SymGetSymFromAddr (DBGHELP.@)
1077  *
1078  */
1079 BOOL WINAPI SymGetSymFromAddr(HANDLE hProcess, DWORD Address,
1080                               PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol)
1081 {
1082     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
1083     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
1084     size_t      len;
1085     DWORD64     Displacement64;
1086
1087     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
1088     si->SizeOfStruct = sizeof(*si);
1089     si->MaxNameLen = MAX_SYM_NAME;
1090     if (!SymFromAddr(hProcess, Address, &Displacement64, si))
1091         return FALSE;
1092
1093     if (Displacement)
1094         *Displacement = Displacement64;
1095     Symbol->Address = si->Address;
1096     Symbol->Size    = si->Size;
1097     Symbol->Flags   = si->Flags;
1098     len = min(Symbol->MaxNameLength, si->MaxNameLen);
1099     lstrcpynA(Symbol->Name, si->Name, len);
1100     return TRUE;
1101 }
1102
1103 /******************************************************************
1104  *              SymGetSymFromAddr64 (DBGHELP.@)
1105  *
1106  */
1107 BOOL WINAPI SymGetSymFromAddr64(HANDLE hProcess, DWORD64 Address,
1108                                 PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol)
1109 {
1110     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
1111     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
1112     size_t      len;
1113     DWORD64     Displacement64;
1114
1115     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
1116     si->SizeOfStruct = sizeof(*si);
1117     si->MaxNameLen = MAX_SYM_NAME;
1118     if (!SymFromAddr(hProcess, Address, &Displacement64, si))
1119         return FALSE;
1120
1121     if (Displacement)
1122         *Displacement = Displacement64;
1123     Symbol->Address = si->Address;
1124     Symbol->Size    = si->Size;
1125     Symbol->Flags   = si->Flags;
1126     len = min(Symbol->MaxNameLength, si->MaxNameLen);
1127     lstrcpynA(Symbol->Name, si->Name, len);
1128     return TRUE;
1129 }
1130
1131 static BOOL find_name(struct process* pcs, struct module* module, const char* name,
1132                       SYMBOL_INFO* symbol)
1133 {
1134     struct hash_table_iter      hti;
1135     void*                       ptr;
1136     struct symt_ht*             sym = NULL;
1137     struct module_pair          pair;
1138
1139     pair.pcs = pcs;
1140     if (!(pair.requested = module)) return FALSE;
1141     if (!module_get_debug(&pair)) return FALSE;
1142
1143     hash_table_iter_init(&pair.effective->ht_symbols, &hti, name);
1144     while ((ptr = hash_table_iter_up(&hti)))
1145     {
1146         sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
1147
1148         if (!strcmp(sym->hash_elt.name, name))
1149         {
1150             symt_fill_sym_info(&pair, NULL, &sym->symt, symbol);
1151             return TRUE;
1152         }
1153     }
1154     return FALSE;
1155
1156 }
1157 /******************************************************************
1158  *              SymFromName (DBGHELP.@)
1159  *
1160  */
1161 BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol)
1162 {
1163     struct process*             pcs = process_find_by_handle(hProcess);
1164     struct module*              module;
1165     const char*                 name;
1166
1167     TRACE("(%p, %s, %p)\n", hProcess, Name, Symbol);
1168     if (!pcs) return FALSE;
1169     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
1170     name = strchr(Name, '!');
1171     if (name)
1172     {
1173         char    tmp[128];
1174         assert(name - Name < sizeof(tmp));
1175         memcpy(tmp, Name, name - Name);
1176         tmp[name - Name] = '\0';
1177         module = module_find_by_name(pcs, tmp, DMT_UNKNOWN);
1178         return find_name(pcs, module, name + 1, Symbol);
1179     }
1180     for (module = pcs->lmodules; module; module = module->next)
1181     {
1182         if (module->type == DMT_PE && find_name(pcs, module, Name, Symbol))
1183             return TRUE;
1184     }
1185     /* not found in PE modules, retry on the ELF ones
1186      */
1187     if (dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES)
1188     {
1189         for (module = pcs->lmodules; module; module = module->next)
1190         {
1191             if (module->type == DMT_ELF && !module_get_containee(pcs, module) &&
1192                 find_name(pcs, module, Name, Symbol))
1193                 return TRUE;
1194         }
1195     }
1196     return FALSE;
1197 }
1198
1199 /***********************************************************************
1200  *              SymGetSymFromName (DBGHELP.@)
1201  */
1202 BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symbol)
1203 {
1204     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
1205     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
1206     size_t      len;
1207
1208     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
1209     si->SizeOfStruct = sizeof(*si);
1210     si->MaxNameLen = MAX_SYM_NAME;
1211     if (!SymFromName(hProcess, Name, si)) return FALSE;
1212
1213     Symbol->Address = si->Address;
1214     Symbol->Size    = si->Size;
1215     Symbol->Flags   = si->Flags;
1216     len = min(Symbol->MaxNameLength, si->MaxNameLen);
1217     lstrcpynA(Symbol->Name, si->Name, len);
1218     return TRUE;
1219 }
1220
1221 /******************************************************************
1222  *              sym_fill_func_line_info
1223  *
1224  * fills information about a file
1225  */
1226 BOOL symt_fill_func_line_info(struct module* module, struct symt_function* func, 
1227                               DWORD addr, IMAGEHLP_LINE* line)
1228 {
1229     struct line_info*   dli = NULL;
1230     BOOL                found = FALSE;
1231
1232     assert(func->symt.tag == SymTagFunction);
1233
1234     while ((dli = vector_iter_down(&func->vlines, dli)))
1235     {
1236         if (!dli->is_source_file)
1237         {
1238             if (found || dli->u.pc_offset > addr) continue;
1239             line->LineNumber = dli->line_number;
1240             line->Address    = dli->u.pc_offset;
1241             line->Key        = dli;
1242             found = TRUE;
1243             continue;
1244         }
1245         if (found)
1246         {
1247             line->FileName = (char*)source_get(module, dli->u.source_file);
1248             return TRUE;
1249         }
1250     }
1251     return FALSE;
1252 }
1253
1254 /***********************************************************************
1255  *              SymGetSymNext (DBGHELP.@)
1256  */
1257 BOOL WINAPI SymGetSymNext(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
1258 {
1259     /* algo:
1260      * get module from Symbol.Address
1261      * get index in module.addr_sorttab of Symbol.Address
1262      * increment index
1263      * if out of module bounds, move to next module in process address space
1264      */
1265     FIXME("(%p, %p): stub\n", hProcess, Symbol);
1266     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1267     return FALSE;
1268 }
1269
1270 /***********************************************************************
1271  *              SymGetSymPrev (DBGHELP.@)
1272  */
1273
1274 BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
1275 {
1276     FIXME("(%p, %p): stub\n", hProcess, Symbol);
1277     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1278     return FALSE;
1279 }
1280
1281 /******************************************************************
1282  *              SymGetLineFromAddr (DBGHELP.@)
1283  *
1284  */
1285 BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, 
1286                                PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
1287 {
1288     struct module_pair  pair;
1289     struct symt_ht*     symt;
1290
1291     TRACE("%p %08x %p %p\n", hProcess, dwAddr, pdwDisplacement, Line);
1292
1293     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
1294
1295     pair.pcs = process_find_by_handle(hProcess);
1296     if (!pair.pcs) return FALSE;
1297     pair.requested = module_find_by_addr(pair.pcs, dwAddr, DMT_UNKNOWN);
1298     if (!module_get_debug(&pair)) return FALSE;
1299     if ((symt = symt_find_nearest(pair.effective, dwAddr)) == NULL) return FALSE;
1300
1301     if (symt->symt.tag != SymTagFunction) return FALSE;
1302     if (!symt_fill_func_line_info(pair.effective, (struct symt_function*)symt,
1303                                   dwAddr, Line)) return FALSE;
1304     *pdwDisplacement = dwAddr - Line->Address;
1305     return TRUE;
1306 }
1307
1308 /******************************************************************
1309  *              copy_line_64_from_32 (internal)
1310  *
1311  */
1312 static void copy_line_64_from_32(IMAGEHLP_LINE64* l64, const IMAGEHLP_LINE* l32)
1313
1314 {
1315     l64->Key = l32->Key;
1316     l64->LineNumber = l32->LineNumber;
1317     l64->FileName = l32->FileName;
1318     l64->Address = l32->Address;
1319 }
1320
1321 /******************************************************************
1322  *              copy_line_W64_from_32 (internal)
1323  *
1324  */
1325 static void copy_line_W64_from_32(struct process* pcs, IMAGEHLP_LINEW64* l64, const IMAGEHLP_LINE* l32)
1326 {
1327     unsigned len;
1328
1329     l64->Key = l32->Key;
1330     l64->LineNumber = l32->LineNumber;
1331     len = MultiByteToWideChar(CP_ACP, 0, l32->FileName, -1, NULL, 0);
1332     if ((l64->FileName = fetch_buffer(pcs, len * sizeof(WCHAR))))
1333         MultiByteToWideChar(CP_ACP, 0, l32->FileName, -1, l64->FileName, len);
1334     l64->Address = l32->Address;
1335 }
1336
1337 /******************************************************************
1338  *              copy_line_32_from_64 (internal)
1339  *
1340  */
1341 static void copy_line_32_from_64(IMAGEHLP_LINE* l32, const IMAGEHLP_LINE64* l64)
1342
1343 {
1344     l32->Key = l64->Key;
1345     l32->LineNumber = l64->LineNumber;
1346     l32->FileName = l64->FileName;
1347     l32->Address = l64->Address;
1348 }
1349
1350 /******************************************************************
1351  *              SymGetLineFromAddr64 (DBGHELP.@)
1352  *
1353  */
1354 BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, 
1355                                  PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line)
1356 {
1357     IMAGEHLP_LINE       line32;
1358
1359     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
1360     if (!validate_addr64(dwAddr)) return FALSE;
1361     line32.SizeOfStruct = sizeof(line32);
1362     if (!SymGetLineFromAddr(hProcess, (DWORD)dwAddr, pdwDisplacement, &line32))
1363         return FALSE;
1364     copy_line_64_from_32(Line, &line32);
1365     return TRUE;
1366 }
1367
1368 /******************************************************************
1369  *              SymGetLineFromAddrW64 (DBGHELP.@)
1370  *
1371  */
1372 BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr, 
1373                                   PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line)
1374 {
1375     struct process*     pcs = process_find_by_handle(hProcess);
1376     IMAGEHLP_LINE       line32;
1377
1378     if (!pcs) return FALSE;
1379     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
1380     if (!validate_addr64(dwAddr)) return FALSE;
1381     line32.SizeOfStruct = sizeof(line32);
1382     if (!SymGetLineFromAddr(hProcess, (DWORD)dwAddr, pdwDisplacement, &line32))
1383         return FALSE;
1384     copy_line_W64_from_32(pcs, Line, &line32);
1385     return TRUE;
1386 }
1387
1388 /******************************************************************
1389  *              SymGetLinePrev (DBGHELP.@)
1390  *
1391  */
1392 BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
1393 {
1394     struct module_pair  pair;
1395     struct line_info*   li;
1396     BOOL                in_search = FALSE;
1397
1398     TRACE("(%p %p)\n", hProcess, Line);
1399
1400     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
1401
1402     pair.pcs = process_find_by_handle(hProcess);
1403     if (!pair.pcs) return FALSE;
1404     pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN);
1405     if (!module_get_debug(&pair)) return FALSE;
1406
1407     if (Line->Key == 0) return FALSE;
1408     li = (struct line_info*)Line->Key;
1409     /* things are a bit complicated because when we encounter a DLIT_SOURCEFILE
1410      * element we have to go back until we find the prev one to get the real
1411      * source file name for the DLIT_OFFSET element just before 
1412      * the first DLIT_SOURCEFILE
1413      */
1414     while (!li->is_first)
1415     {
1416         li--;
1417         if (!li->is_source_file)
1418         {
1419             Line->LineNumber = li->line_number;
1420             Line->Address    = li->u.pc_offset;
1421             Line->Key        = li;
1422             if (!in_search) return TRUE;
1423         }
1424         else
1425         {
1426             if (in_search)
1427             {
1428                 Line->FileName = (char*)source_get(pair.effective, li->u.source_file);
1429                 return TRUE;
1430             }
1431             in_search = TRUE;
1432         }
1433     }
1434     SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */
1435     return FALSE;
1436 }
1437
1438 /******************************************************************
1439  *              SymGetLinePrev64 (DBGHELP.@)
1440  *
1441  */
1442 BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
1443 {
1444     IMAGEHLP_LINE       line32;
1445
1446     line32.SizeOfStruct = sizeof(line32);
1447     copy_line_32_from_64(&line32, Line);
1448     if (!SymGetLinePrev(hProcess, &line32)) return FALSE;
1449     copy_line_64_from_32(Line, &line32);
1450     return TRUE;
1451 }
1452     
1453 BOOL symt_get_func_line_next(struct module* module, PIMAGEHLP_LINE line)
1454 {
1455     struct line_info*   li;
1456
1457     if (line->Key == 0) return FALSE;
1458     li = (struct line_info*)line->Key;
1459     while (!li->is_last)
1460     {
1461         li++;
1462         if (!li->is_source_file)
1463         {
1464             line->LineNumber = li->line_number;
1465             line->Address    = li->u.pc_offset;
1466             line->Key        = li;
1467             return TRUE;
1468         }
1469         line->FileName = (char*)source_get(module, li->u.source_file);
1470     }
1471     return FALSE;
1472 }
1473
1474 /******************************************************************
1475  *              SymGetLineNext (DBGHELP.@)
1476  *
1477  */
1478 BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
1479 {
1480     struct module_pair  pair;
1481
1482     TRACE("(%p %p)\n", hProcess, Line);
1483
1484     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
1485     pair.pcs = process_find_by_handle(hProcess);
1486     if (!pair.pcs) return FALSE;
1487     pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN);
1488     if (!module_get_debug(&pair)) return FALSE;
1489
1490     if (symt_get_func_line_next(pair.effective, Line)) return TRUE;
1491     SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */
1492     return FALSE;
1493 }
1494
1495 /******************************************************************
1496  *              SymGetLineNext64 (DBGHELP.@)
1497  *
1498  */
1499 BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
1500 {
1501     IMAGEHLP_LINE       line32;
1502
1503     line32.SizeOfStruct = sizeof(line32);
1504     copy_line_32_from_64(&line32, Line);
1505     if (!SymGetLineNext(hProcess, &line32)) return FALSE;
1506     copy_line_64_from_32(Line, &line32);
1507     return TRUE;
1508 }
1509     
1510 /***********************************************************************
1511  *              SymFunctionTableAccess (DBGHELP.@)
1512  */
1513 PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
1514 {
1515     WARN("(%p, 0x%08x): stub\n", hProcess, AddrBase);
1516     return NULL;
1517 }
1518
1519 /***********************************************************************
1520  *              SymFunctionTableAccess64 (DBGHELP.@)
1521  */
1522 PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
1523 {
1524     WARN("(%p, %s): stub\n", hProcess, wine_dbgstr_longlong(AddrBase));
1525     return NULL;
1526 }
1527
1528 /***********************************************************************
1529  *              SymUnDName (DBGHELP.@)
1530  */
1531 BOOL WINAPI SymUnDName(PIMAGEHLP_SYMBOL sym, LPSTR UnDecName, DWORD UnDecNameLength)
1532 {
1533     TRACE("(%p %s %u)\n", sym, UnDecName, UnDecNameLength);
1534     return UnDecorateSymbolName(sym->Name, UnDecName, UnDecNameLength,
1535                                 UNDNAME_COMPLETE) != 0;
1536 }
1537
1538 static void* und_alloc(size_t len) { return HeapAlloc(GetProcessHeap(), 0, len); }
1539 static void  und_free (void* ptr)  { HeapFree(GetProcessHeap(), 0, ptr); }
1540
1541 /***********************************************************************
1542  *              UnDecorateSymbolName (DBGHELP.@)
1543  */
1544 DWORD WINAPI UnDecorateSymbolName(LPCSTR DecoratedName, LPSTR UnDecoratedName,
1545                                   DWORD UndecoratedLength, DWORD Flags)
1546 {
1547     /* undocumented from msvcrt */
1548     static char* (*p_undname)(char*, const char*, int, void* (*)(size_t), void (*)(void*), unsigned short);
1549     static const WCHAR szMsvcrt[] = {'m','s','v','c','r','t','.','d','l','l',0};
1550
1551     TRACE("(%s, %p, %d, 0x%08x)\n",
1552           debugstr_a(DecoratedName), UnDecoratedName, UndecoratedLength, Flags);
1553
1554     if (!p_undname)
1555     {
1556         if (!hMsvcrt) hMsvcrt = LoadLibraryW(szMsvcrt);
1557         if (hMsvcrt) p_undname = (void*)GetProcAddress(hMsvcrt, "__unDName");
1558         if (!p_undname) return 0;
1559     }
1560
1561     if (!UnDecoratedName) return 0;
1562     if (!p_undname(UnDecoratedName, DecoratedName, UndecoratedLength, 
1563                    und_alloc, und_free, Flags))
1564         return 0;
1565     return strlen(UnDecoratedName);
1566 }
1567
1568 /******************************************************************
1569  *              SymMatchString (DBGHELP.@)
1570  *
1571  */
1572 BOOL WINAPI SymMatchString(PCSTR string, PCSTR re, BOOL _case)
1573 {
1574     regex_t     preg;
1575     BOOL        ret;
1576
1577     TRACE("%s %s %c\n", string, re, _case ? 'Y' : 'N');
1578
1579     compile_regex(re, -1, &preg, _case);
1580     ret = regexec(&preg, string, 0, NULL, 0) == 0;
1581     regfree(&preg);
1582     return ret;
1583 }
1584
1585 /******************************************************************
1586  *              SymSearch (DBGHELP.@)
1587  */
1588 BOOL WINAPI SymSearch(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index,
1589                       DWORD SymTag, PCSTR Mask, DWORD64 Address,
1590                       PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
1591                       PVOID UserContext, DWORD Options)
1592 {
1593     struct sym_enum     se;
1594
1595     TRACE("(%p %s %u %u %s %s %p %p %x)\n",
1596           hProcess, wine_dbgstr_longlong(BaseOfDll), Index, SymTag, Mask,
1597           wine_dbgstr_longlong(Address), EnumSymbolsCallback,
1598           UserContext, Options);
1599
1600     if (Options != SYMSEARCH_GLOBALSONLY)
1601     {
1602         FIXME("Unsupported searching with options (%x)\n", Options);
1603         SetLastError(ERROR_INVALID_PARAMETER);
1604         return FALSE;
1605     }
1606
1607     se.cb = EnumSymbolsCallback;
1608     se.user = UserContext;
1609     se.index = Index;
1610     se.tag = SymTag;
1611     se.addr = Address;
1612     se.sym_info = (PSYMBOL_INFO)se.buffer;
1613
1614     return sym_enum(hProcess, BaseOfDll, Mask, &se);
1615 }
1616
1617 /******************************************************************
1618  *              SymSearchW (DBGHELP.@)
1619  */
1620 BOOL WINAPI SymSearchW(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index,
1621                        DWORD SymTag, PCWSTR Mask, DWORD64 Address,
1622                        PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
1623                        PVOID UserContext, DWORD Options)
1624 {
1625     struct sym_enumW    sew;
1626     BOOL                ret = FALSE;
1627     char*               maskA = NULL;
1628
1629     TRACE("(%p %s %u %u %s %s %p %p %x)\n",
1630           hProcess, wine_dbgstr_longlong(BaseOfDll), Index, SymTag, debugstr_w(Mask),
1631           wine_dbgstr_longlong(Address), EnumSymbolsCallback,
1632           UserContext, Options);
1633
1634     sew.ctx = UserContext;
1635     sew.cb = EnumSymbolsCallback;
1636     sew.sym_info = (PSYMBOL_INFOW)sew.buffer;
1637
1638     if (Mask)
1639     {
1640         unsigned len = WideCharToMultiByte(CP_ACP, 0, Mask, -1, NULL, 0, NULL, NULL);
1641         maskA = HeapAlloc(GetProcessHeap(), 0, len);
1642         if (!maskA) return FALSE;
1643         WideCharToMultiByte(CP_ACP, 0, Mask, -1, maskA, len, NULL, NULL);
1644     }
1645     ret = SymSearch(hProcess, BaseOfDll, Index, SymTag, maskA, Address,
1646                     sym_enumW, &sew, Options);
1647     HeapFree(GetProcessHeap(), 0, maskA);
1648
1649     return ret;
1650 }