ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

symbol.c
Go to the documentation of this file.
00001 /*
00002  * File symbol.c - management of symbols (lexical tree)
00003  *
00004  * Copyright (C) 1993, Eric Youngdale.
00005  *               2004, Eric Pouech
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #define NONAMELESSUNION
00023 #define NONAMELESSSTRUCT
00024 
00025 #include "config.h"
00026 
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <limits.h>
00031 #include <sys/types.h>
00032 #include <assert.h>
00033 #ifdef HAVE_REGEX_H
00034 # include <regex.h>
00035 #endif
00036 
00037 #include "wine/debug.h"
00038 #include "dbghelp_private.h"
00039 #include "winnls.h"
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
00042 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt);
00043 
00044 static inline int cmp_addr(ULONG64 a1, ULONG64 a2)
00045 {
00046     if (a1 > a2) return 1;
00047     if (a1 < a2) return -1;
00048     return 0;
00049 }
00050 
00051 static inline int cmp_sorttab_addr(struct module* module, int idx, ULONG64 addr)
00052 {
00053     ULONG64     ref;
00054     symt_get_address(&module->addr_sorttab[idx]->symt, &ref);
00055     return cmp_addr(ref, addr);
00056 }
00057 
00058 int symt_cmp_addr(const void* p1, const void* p2)
00059 {
00060     const struct symt*  sym1 = *(const struct symt* const *)p1;
00061     const struct symt*  sym2 = *(const struct symt* const *)p2;
00062     ULONG64     a1, a2;
00063 
00064     symt_get_address(sym1, &a1);
00065     symt_get_address(sym2, &a2);
00066     return cmp_addr(a1, a2);
00067 }
00068 
00069 DWORD             symt_ptr2index(struct module* module, const struct symt* sym)
00070 {
00071 #ifdef _WIN64
00072     const struct symt** c;
00073     int                 len = vector_length(&module->vsymt), i;
00074 
00075     /* FIXME: this is inefficient */
00076     for (i = 0; i < len; i++)
00077     {
00078         if (*(struct symt**)vector_at(&module->vsymt, i) == sym)
00079             return i + 1;
00080     }
00081     /* not found */
00082     c = vector_add(&module->vsymt, &module->pool);
00083     if (c) *c = sym;
00084     return len + 1;
00085 #else
00086     return (DWORD)sym;
00087 #endif
00088 }
00089 
00090 struct symt*      symt_index2ptr(struct module* module, DWORD id)
00091 {
00092 #ifdef _WIN64
00093     if (!id-- || id >= vector_length(&module->vsymt)) return NULL;
00094     return *(struct symt**)vector_at(&module->vsymt, id);
00095 #else
00096     return (struct symt*)id;
00097 #endif
00098 }
00099 
00100 static BOOL symt_grow_sorttab(struct module* module, unsigned sz)
00101 {
00102     struct symt_ht**    new;
00103     unsigned int size;
00104 
00105     if (sz <= module->sorttab_size) return TRUE;
00106     if (module->addr_sorttab)
00107     {
00108         size = module->sorttab_size * 2;
00109         new = HeapReAlloc(GetProcessHeap(), 0, module->addr_sorttab,
00110                           size * sizeof(struct symt_ht*));
00111     }
00112     else
00113     {
00114         size = 64;
00115         new = HeapAlloc(GetProcessHeap(), 0, size * sizeof(struct symt_ht*));
00116     }
00117     if (!new) return FALSE;
00118     module->sorttab_size = size;
00119     module->addr_sorttab = new;
00120     return TRUE;
00121 }
00122 
00123 static void symt_add_module_ht(struct module* module, struct symt_ht* ht)
00124 {
00125     ULONG64             addr;
00126 
00127     hash_table_add(&module->ht_symbols, &ht->hash_elt);
00128     /* Don't store in sorttab a symbol without address, they are of
00129      * no use here (e.g. constant values)
00130      */
00131     if (symt_get_address(&ht->symt, &addr) &&
00132         symt_grow_sorttab(module, module->num_symbols + 1))
00133     {
00134         module->addr_sorttab[module->num_symbols++] = ht;
00135         module->sortlist_valid = FALSE;
00136     }
00137 }
00138 
00139 #ifdef HAVE_REGEX_H
00140 
00141 /* transforms a dbghelp's regular expression into a POSIX one
00142  * Here are the valid dbghelp reg ex characters:
00143  *      *       0 or more characters
00144  *      ?       a single character
00145  *      []      list
00146  *      #       0 or more of preceding char
00147  *      +       1 or more of preceding char
00148  *      escapes \ on #, ?, [, ], *, +. don't work on -
00149  */
00150 static void compile_regex(const char* str, int numchar, regex_t* re, BOOL _case)
00151 {
00152     char *mask, *p;
00153     BOOL        in_escape = FALSE;
00154     unsigned    flags = REG_NOSUB;
00155 
00156     if (numchar == -1) numchar = strlen( str );
00157 
00158     p = mask = HeapAlloc( GetProcessHeap(), 0, 2 * numchar + 3 );
00159     *p++ = '^';
00160 
00161     while (*str && numchar--)
00162     {
00163         /* FIXME: this shouldn't be valid on '-' */
00164         if (in_escape)
00165         {
00166             *p++ = '\\';
00167             *p++ = *str;
00168             in_escape = FALSE;
00169         }
00170         else switch (*str)
00171         {
00172         case '\\': in_escape = TRUE; break;
00173         case '*':  *p++ = '.'; *p++ = '*'; break;
00174         case '?':  *p++ = '.'; break;
00175         case '#':  *p++ = '*'; break;
00176         /* escape some valid characters in dbghelp reg exp:s */
00177         case '$':  *p++ = '\\'; *p++ = '$'; break;
00178         /* +, [, ], - are the same in dbghelp & POSIX, use them as any other char */
00179         default:   *p++ = *str; break;
00180         }
00181         str++;
00182     }
00183     if (in_escape)
00184     {
00185         *p++ = '\\';
00186         *p++ = '\\';
00187     }
00188     *p++ = '$';
00189     *p = 0;
00190     if (_case) flags |= REG_ICASE;
00191     if (regcomp(re, mask, flags)) FIXME("Couldn't compile %s\n", mask);
00192     HeapFree(GetProcessHeap(), 0, mask);
00193 }
00194 
00195 static BOOL compile_file_regex(regex_t* re, const char* srcfile)
00196 {
00197     char *mask, *p;
00198     BOOL ret;
00199 
00200     if (!srcfile || !*srcfile) return regcomp(re, ".*", REG_NOSUB);
00201 
00202     p = mask = HeapAlloc(GetProcessHeap(), 0, 5 * strlen(srcfile) + 4);
00203     *p++ = '^';
00204     while (*srcfile)
00205     {
00206         switch (*srcfile)
00207         {
00208         case '\\':
00209         case '/':
00210             *p++ = '[';
00211             *p++ = '\\';
00212             *p++ = '\\';
00213             *p++ = '/';
00214             *p++ = ']';
00215             break;
00216         case '.':
00217             *p++ = '\\';
00218             *p++ = '.';
00219             break;
00220         case '*':
00221             *p++ = '.';
00222             *p++ = '*';
00223             break;
00224         default:
00225             *p++ = *srcfile;
00226             break;
00227         }
00228         srcfile++;
00229     }
00230     *p++ = '$';
00231     *p = 0;
00232     ret = !regcomp(re, mask, REG_NOSUB);
00233     HeapFree(GetProcessHeap(), 0, mask);
00234     if (!ret)
00235     {
00236         FIXME("Couldn't compile %s\n", mask);
00237         SetLastError(ERROR_INVALID_PARAMETER);
00238     }
00239     return ret;
00240 }
00241 
00242 static int match_regexp( const regex_t *re, const char *str )
00243 {
00244     return !regexec( re, str, 0, NULL, 0 );
00245 }
00246 
00247 #else /* HAVE_REGEX_H */
00248 
00249 /* if we don't have regexp support, fall back to a simple string comparison */
00250 
00251 typedef struct
00252 {
00253     char *str;
00254     BOOL  icase;
00255 } regex_t;
00256 
00257 static void compile_regex(const char* str, int numchar, regex_t* re, BOOL _case)
00258 {
00259     if (numchar == -1) numchar = strlen( str );
00260 
00261     re->str = HeapAlloc( GetProcessHeap(), 0, numchar + 1 );
00262     memcpy( re->str, str, numchar );
00263     re->str[numchar] = 0;
00264     re->icase = _case;
00265 }
00266 
00267 static BOOL compile_file_regex(regex_t* re, const char* srcfile)
00268 {
00269     if (!srcfile || !*srcfile) re->str = NULL;
00270     else compile_regex( srcfile, -1, re, FALSE );
00271     return TRUE;
00272 }
00273 
00274 static int match_regexp( const regex_t *re, const char *str )
00275 {
00276     if (!re->str) return 1;
00277     if (re->icase) return !lstrcmpiA( re->str, str );
00278     return !strcmp( re->str, str );
00279 }
00280 
00281 static void regfree( regex_t *re )
00282 {
00283     HeapFree( GetProcessHeap(), 0, re->str );
00284 }
00285 
00286 #endif /* HAVE_REGEX_H */
00287 
00288 struct symt_compiland* symt_new_compiland(struct module* module, 
00289                                           unsigned long address, unsigned src_idx)
00290 {
00291     struct symt_compiland*    sym;
00292 
00293     TRACE_(dbghelp_symt)("Adding compiland symbol %s:%s\n",
00294                          debugstr_w(module->module.ModuleName), source_get(module, src_idx));
00295     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00296     {
00297         sym->symt.tag = SymTagCompiland;
00298         sym->address  = address;
00299         sym->source   = src_idx;
00300         vector_init(&sym->vchildren, sizeof(struct symt*), 32);
00301     }
00302     return sym;
00303 }
00304 
00305 struct symt_public* symt_new_public(struct module* module, 
00306                                     struct symt_compiland* compiland,
00307                                     const char* name,
00308                                     unsigned long address, unsigned size)
00309 {
00310     struct symt_public* sym;
00311     struct symt**       p;
00312 
00313     TRACE_(dbghelp_symt)("Adding public symbol %s:%s @%lx\n",
00314                          debugstr_w(module->module.ModuleName), name, address);
00315     if ((dbghelp_options & SYMOPT_AUTO_PUBLICS) &&
00316         symt_find_nearest(module, address) != NULL)
00317         return NULL;
00318     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00319     {
00320         sym->symt.tag      = SymTagPublicSymbol;
00321         sym->hash_elt.name = pool_strdup(&module->pool, name);
00322         sym->container     = compiland ? &compiland->symt : NULL;
00323         sym->address       = address;
00324         sym->size          = size;
00325         symt_add_module_ht(module, (struct symt_ht*)sym);
00326         if (compiland)
00327         {
00328             p = vector_add(&compiland->vchildren, &module->pool);
00329             *p = &sym->symt;
00330         }
00331     }
00332     return sym;
00333 }
00334 
00335 struct symt_data* symt_new_global_variable(struct module* module, 
00336                                            struct symt_compiland* compiland, 
00337                                            const char* name, unsigned is_static,
00338                                            struct location loc, unsigned long size,
00339                                            struct symt* type)
00340 {
00341     struct symt_data*   sym;
00342     struct symt**       p;
00343     DWORD64             tsz;
00344 
00345     TRACE_(dbghelp_symt)("Adding global symbol %s:%s %d@%lx %p\n",
00346                          debugstr_w(module->module.ModuleName), name, loc.kind, loc.offset, type);
00347     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00348     {
00349         sym->symt.tag      = SymTagData;
00350         sym->hash_elt.name = pool_strdup(&module->pool, name);
00351         sym->kind          = is_static ? DataIsFileStatic : DataIsGlobal;
00352         sym->container     = compiland ? &compiland->symt : NULL;
00353         sym->type          = type;
00354         sym->u.var         = loc;
00355         if (type && size && symt_get_info(module, type, TI_GET_LENGTH, &tsz))
00356         {
00357             if (tsz != size)
00358                 FIXME("Size mismatch for %s.%s between type (%s) and src (%lu)\n",
00359                       debugstr_w(module->module.ModuleName), name,
00360                       wine_dbgstr_longlong(tsz), size);
00361         }
00362         symt_add_module_ht(module, (struct symt_ht*)sym);
00363         if (compiland)
00364         {
00365             p = vector_add(&compiland->vchildren, &module->pool);
00366             *p = &sym->symt;
00367         }
00368     }
00369     return sym;
00370 }
00371 
00372 struct symt_function* symt_new_function(struct module* module, 
00373                                         struct symt_compiland* compiland, 
00374                                         const char* name,
00375                                         unsigned long addr, unsigned long size,
00376                                         struct symt* sig_type)
00377 {
00378     struct symt_function*       sym;
00379     struct symt**               p;
00380 
00381     TRACE_(dbghelp_symt)("Adding global function %s:%s @%lx-%lx\n",
00382                          debugstr_w(module->module.ModuleName), name, addr, addr + size - 1);
00383 
00384     assert(!sig_type || sig_type->tag == SymTagFunctionType);
00385     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00386     {
00387         sym->symt.tag  = SymTagFunction;
00388         sym->hash_elt.name = pool_strdup(&module->pool, name);
00389         sym->container = &compiland->symt;
00390         sym->address   = addr;
00391         sym->type      = sig_type;
00392         sym->size      = size;
00393         vector_init(&sym->vlines,  sizeof(struct line_info), 64);
00394         vector_init(&sym->vchildren, sizeof(struct symt*), 8);
00395         symt_add_module_ht(module, (struct symt_ht*)sym);
00396         if (compiland)
00397         {
00398             p = vector_add(&compiland->vchildren, &module->pool);
00399             *p = &sym->symt;
00400         }
00401     }
00402     return sym;
00403 }
00404 
00405 void symt_add_func_line(struct module* module, struct symt_function* func,
00406                         unsigned source_idx, int line_num, unsigned long offset)
00407 {
00408     struct line_info*   dli;
00409     BOOL                last_matches = FALSE;
00410     int                 i;
00411 
00412     if (func == NULL || !(dbghelp_options & SYMOPT_LOAD_LINES)) return;
00413 
00414     TRACE_(dbghelp_symt)("(%p)%s:%lx %s:%u\n", 
00415                          func, func->hash_elt.name, offset, 
00416                          source_get(module, source_idx), line_num);
00417 
00418     assert(func->symt.tag == SymTagFunction);
00419 
00420     for (i=vector_length(&func->vlines)-1; i>=0; i--)
00421     {
00422         dli = vector_at(&func->vlines, i);
00423         if (dli->is_source_file)
00424         {
00425             last_matches = (source_idx == dli->u.source_file);
00426             break;
00427         }
00428     }
00429 
00430     if (!last_matches)
00431     {
00432         /* we shouldn't have line changes on first line of function */
00433         dli = vector_add(&func->vlines, &module->pool);
00434         dli->is_source_file = 1;
00435         dli->is_first       = dli->is_last = 0;
00436         dli->line_number    = 0;
00437         dli->u.source_file  = source_idx;
00438     }
00439     dli = vector_add(&func->vlines, &module->pool);
00440     dli->is_source_file = 0;
00441     dli->is_first       = dli->is_last = 0;
00442     dli->line_number    = line_num;
00443     dli->u.pc_offset    = func->address + offset;
00444 }
00445 
00446 /******************************************************************
00447  *             symt_add_func_local
00448  *
00449  * Adds a new local/parameter to a given function:
00450  * In any cases, dt tells whether it's a local variable or a parameter
00451  * If regno it's not 0:
00452  *      - then variable is stored in a register
00453  *      - otherwise, value is referenced by register + offset
00454  * Otherwise, the variable is stored on the stack:
00455  *      - offset is then the offset from the frame register
00456  */
00457 struct symt_data* symt_add_func_local(struct module* module, 
00458                                       struct symt_function* func, 
00459                                       enum DataKind dt,
00460                                       const struct location* loc,
00461                                       struct symt_block* block, 
00462                                       struct symt* type, const char* name)
00463 {
00464     struct symt_data*   locsym;
00465     struct symt**       p;
00466 
00467     TRACE_(dbghelp_symt)("Adding local symbol (%s:%s): %s %p\n",
00468                          debugstr_w(module->module.ModuleName), func->hash_elt.name,
00469                          name, type);
00470 
00471     assert(func);
00472     assert(func->symt.tag == SymTagFunction);
00473     assert(dt == DataIsParam || dt == DataIsLocal);
00474 
00475     locsym = pool_alloc(&module->pool, sizeof(*locsym));
00476     locsym->symt.tag      = SymTagData;
00477     locsym->hash_elt.name = pool_strdup(&module->pool, name);
00478     locsym->hash_elt.next = NULL;
00479     locsym->kind          = dt;
00480     locsym->container     = block ? &block->symt : &func->symt;
00481     locsym->type          = type;
00482     locsym->u.var         = *loc;
00483     if (block)
00484         p = vector_add(&block->vchildren, &module->pool);
00485     else
00486         p = vector_add(&func->vchildren, &module->pool);
00487     *p = &locsym->symt;
00488     return locsym;
00489 }
00490 
00491 
00492 struct symt_block* symt_open_func_block(struct module* module, 
00493                                         struct symt_function* func,
00494                                         struct symt_block* parent_block, 
00495                                         unsigned pc, unsigned len)
00496 {
00497     struct symt_block*  block;
00498     struct symt**       p;
00499 
00500     assert(func);
00501     assert(func->symt.tag == SymTagFunction);
00502 
00503     assert(!parent_block || parent_block->symt.tag == SymTagBlock);
00504     block = pool_alloc(&module->pool, sizeof(*block));
00505     block->symt.tag = SymTagBlock;
00506     block->address  = func->address + pc;
00507     block->size     = len;
00508     block->container = parent_block ? &parent_block->symt : &func->symt;
00509     vector_init(&block->vchildren, sizeof(struct symt*), 4);
00510     if (parent_block)
00511         p = vector_add(&parent_block->vchildren, &module->pool);
00512     else
00513         p = vector_add(&func->vchildren, &module->pool);
00514     *p = &block->symt;
00515 
00516     return block;
00517 }
00518 
00519 struct symt_block* symt_close_func_block(struct module* module, 
00520                                          const struct symt_function* func,
00521                                          struct symt_block* block, unsigned pc)
00522 {
00523     assert(func);
00524     assert(func->symt.tag == SymTagFunction);
00525 
00526     if (pc) block->size = func->address + pc - block->address;
00527     return (block->container->tag == SymTagBlock) ? 
00528         GET_ENTRY(block->container, struct symt_block, symt) : NULL;
00529 }
00530 
00531 struct symt_hierarchy_point* symt_add_function_point(struct module* module,
00532                                                      struct symt_function* func,
00533                                                      enum SymTagEnum point,
00534                                                      const struct location* loc,
00535                                                      const char* name)
00536 {
00537     struct symt_hierarchy_point*sym;
00538     struct symt**               p;
00539 
00540     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00541     {
00542         sym->symt.tag = point;
00543         sym->parent   = &func->symt;
00544         sym->loc      = *loc;
00545         sym->hash_elt.name = name ? pool_strdup(&module->pool, name) : NULL;
00546         p = vector_add(&func->vchildren, &module->pool);
00547         *p = &sym->symt;
00548     }
00549     return sym;
00550 }
00551 
00552 BOOL symt_normalize_function(struct module* module, const struct symt_function* func)
00553 {
00554     unsigned            len;
00555     struct line_info*   dli;
00556 
00557     assert(func);
00558     /* We aren't adding any more locals or line numbers to this function.
00559      * Free any spare memory that we might have allocated.
00560      */
00561     assert(func->symt.tag == SymTagFunction);
00562 
00563 /* EPP     vector_pool_normalize(&func->vlines,    &module->pool); */
00564 /* EPP     vector_pool_normalize(&func->vchildren, &module->pool); */
00565 
00566     len = vector_length(&func->vlines);
00567     if (len--)
00568     {
00569         dli = vector_at(&func->vlines,   0);  dli->is_first = 1;
00570         dli = vector_at(&func->vlines, len);  dli->is_last  = 1;
00571     }
00572     return TRUE;
00573 }
00574 
00575 struct symt_thunk* symt_new_thunk(struct module* module, 
00576                                   struct symt_compiland* compiland, 
00577                                   const char* name, THUNK_ORDINAL ord,
00578                                   unsigned long addr, unsigned long size)
00579 {
00580     struct symt_thunk*  sym;
00581 
00582     TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n",
00583                          debugstr_w(module->module.ModuleName), name, addr, addr + size - 1);
00584 
00585     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00586     {
00587         sym->symt.tag  = SymTagThunk;
00588         sym->hash_elt.name = pool_strdup(&module->pool, name);
00589         sym->container = &compiland->symt;
00590         sym->address   = addr;
00591         sym->size      = size;
00592         sym->ordinal   = ord;
00593         symt_add_module_ht(module, (struct symt_ht*)sym);
00594         if (compiland)
00595         {
00596             struct symt**       p;
00597             p = vector_add(&compiland->vchildren, &module->pool);
00598             *p = &sym->symt;
00599         }
00600     }
00601     return sym;
00602 }
00603 
00604 struct symt_data* symt_new_constant(struct module* module,
00605                                     struct symt_compiland* compiland,
00606                                     const char* name, struct symt* type,
00607                                     const VARIANT* v)
00608 {
00609     struct symt_data*  sym;
00610 
00611     TRACE_(dbghelp_symt)("Adding constant value %s:%s\n",
00612                          debugstr_w(module->module.ModuleName), name);
00613 
00614     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00615     {
00616         sym->symt.tag      = SymTagData;
00617         sym->hash_elt.name = pool_strdup(&module->pool, name);
00618         sym->kind          = DataIsConstant;
00619         sym->container     = compiland ? &compiland->symt : NULL;
00620         sym->type          = type;
00621         sym->u.value       = *v;
00622         symt_add_module_ht(module, (struct symt_ht*)sym);
00623         if (compiland)
00624         {
00625             struct symt**       p;
00626             p = vector_add(&compiland->vchildren, &module->pool);
00627             *p = &sym->symt;
00628         }
00629     }
00630     return sym;
00631 }
00632 
00633 struct symt_hierarchy_point* symt_new_label(struct module* module,
00634                                             struct symt_compiland* compiland,
00635                                             const char* name, unsigned long address)
00636 {
00637     struct symt_hierarchy_point*        sym;
00638 
00639     TRACE_(dbghelp_symt)("Adding global label value %s:%s\n",
00640                          debugstr_w(module->module.ModuleName), name);
00641 
00642     if ((sym = pool_alloc(&module->pool, sizeof(*sym))))
00643     {
00644         sym->symt.tag      = SymTagLabel;
00645         sym->hash_elt.name = pool_strdup(&module->pool, name);
00646         sym->loc.kind      = loc_absolute;
00647         sym->loc.offset    = address;
00648         sym->parent        = compiland ? &compiland->symt : NULL;
00649         symt_add_module_ht(module, (struct symt_ht*)sym);
00650         if (compiland)
00651         {
00652             struct symt**       p;
00653             p = vector_add(&compiland->vchildren, &module->pool);
00654             *p = &sym->symt;
00655         }
00656     }
00657     return sym;
00658 }
00659 
00660 /* expect sym_info->MaxNameLen to be set before being called */
00661 static void symt_fill_sym_info(struct module_pair* pair,
00662                                const struct symt_function* func,
00663                                const struct symt* sym, SYMBOL_INFO* sym_info)
00664 {
00665     const char* name;
00666     DWORD64 size;
00667 
00668     if (!symt_get_info(pair->effective, sym, TI_GET_TYPE, &sym_info->TypeIndex))
00669         sym_info->TypeIndex = 0;
00670     sym_info->info = symt_ptr2index(pair->effective, sym);
00671     sym_info->Reserved[0] = sym_info->Reserved[1] = 0;
00672     if (!symt_get_info(pair->effective, sym, TI_GET_LENGTH, &size) &&
00673         (!sym_info->TypeIndex ||
00674          !symt_get_info(pair->effective, symt_index2ptr(pair->effective, sym_info->TypeIndex),
00675                          TI_GET_LENGTH, &size)))
00676         size = 0;
00677     sym_info->Size = (DWORD)size;
00678     sym_info->ModBase = pair->requested->module.BaseOfImage;
00679     sym_info->Flags = 0;
00680     sym_info->Value = 0;
00681 
00682     switch (sym->tag)
00683     {
00684     case SymTagData:
00685         {
00686             const struct symt_data*  data = (const struct symt_data*)sym;
00687             switch (data->kind)
00688             {
00689             case DataIsParam:
00690                 sym_info->Flags |= SYMFLAG_PARAMETER;
00691                 /* fall through */
00692             case DataIsLocal:
00693                 sym_info->Flags |= SYMFLAG_LOCAL;
00694                 {
00695                     struct location loc = data->u.var;
00696 
00697                     if (loc.kind >= loc_user)
00698                     {
00699                         unsigned                i;
00700                         struct module_format*   modfmt;
00701 
00702                         for (i = 0; i < DFI_LAST; i++)
00703                         {
00704                             modfmt = pair->effective->format_info[i];
00705                             if (modfmt && modfmt->loc_compute)
00706                             {
00707                                 modfmt->loc_compute(pair->pcs, modfmt, func, &loc);
00708                                 break;
00709                             }
00710                         }
00711                     }
00712                     switch (loc.kind)
00713                     {
00714                     case loc_error:
00715                         /* for now we report error cases as a negative register number */
00716                         /* fall through */
00717                     case loc_register:
00718                         sym_info->Flags |= SYMFLAG_REGISTER;
00719                         sym_info->Register = loc.reg;
00720                         sym_info->Address = 0;
00721                         break;
00722                     case loc_regrel:
00723                         sym_info->Flags |= SYMFLAG_REGREL;
00724                         sym_info->Register = loc.reg;
00725                         if (loc.reg == CV_REG_NONE || (int)loc.reg < 0 /* error */)
00726                             FIXME("suspicious register value %x\n", loc.reg);
00727                         sym_info->Address = loc.offset;
00728                         break;
00729                     case loc_absolute:
00730                         sym_info->Flags |= SYMFLAG_VALUEPRESENT;
00731                         sym_info->Value = loc.offset;
00732                         break;
00733                     default:
00734                         FIXME("Shouldn't happen (kind=%d), debug reader backend is broken\n", loc.kind);
00735                         assert(0);
00736                     }
00737                 }
00738                 break;
00739             case DataIsGlobal:
00740             case DataIsFileStatic:
00741                 switch (data->u.var.kind)
00742                 {
00743                 case loc_tlsrel:
00744                     sym_info->Flags |= SYMFLAG_TLSREL;
00745                     /* fall through */
00746                 case loc_absolute:
00747                     symt_get_address(sym, &sym_info->Address);
00748                     sym_info->Register = 0;
00749                     break;
00750                 default:
00751                     FIXME("Shouldn't happen (kind=%d), debug reader backend is broken\n", data->u.var.kind);
00752                     assert(0);
00753                 }
00754                 break;
00755             case DataIsConstant:
00756                 sym_info->Flags |= SYMFLAG_VALUEPRESENT;
00757                 switch (data->u.value.n1.n2.vt)
00758                 {
00759                 case VT_I4:  sym_info->Value = (ULONG)data->u.value.n1.n2.n3.lVal; break;
00760                 case VT_I2:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.iVal; break;
00761                 case VT_I1:  sym_info->Value = (ULONG)(long)data->u.value.n1.n2.n3.cVal; break;
00762                 case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break;
00763                 case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break;
00764                 case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break;
00765                 case VT_I1 | VT_BYREF: sym_info->Value = (ULONG64)(DWORD_PTR)data->u.value.n1.n2.n3.byref; break;
00766                 case VT_EMPTY: sym_info->Value = 0; break;
00767                 default:
00768                     FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt);
00769                     sym_info->Value = 0;
00770                     break;
00771                 }
00772                 break;
00773             default:
00774                 FIXME("Unhandled kind (%u) in sym data\n", data->kind);
00775             }
00776         }
00777         break;
00778     case SymTagPublicSymbol:
00779         sym_info->Flags |= SYMFLAG_EXPORT;
00780         symt_get_address(sym, &sym_info->Address);
00781         break;
00782     case SymTagFunction:
00783         sym_info->Flags |= SYMFLAG_FUNCTION;
00784         symt_get_address(sym, &sym_info->Address);
00785         break;
00786     case SymTagThunk:
00787         sym_info->Flags |= SYMFLAG_THUNK;
00788         symt_get_address(sym, &sym_info->Address);
00789         break;
00790     default:
00791         symt_get_address(sym, &sym_info->Address);
00792         sym_info->Register = 0;
00793         break;
00794     }
00795     sym_info->Scope = 0; /* FIXME */
00796     sym_info->Tag = sym->tag;
00797     name = symt_get_name(sym);
00798     if (sym_info->MaxNameLen)
00799     {
00800         if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) ||
00801             (sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name,
00802                                                       sym_info->MaxNameLen, UNDNAME_NAME_ONLY) == 0))
00803         {
00804             sym_info->NameLen = min(strlen(name), sym_info->MaxNameLen - 1);
00805             memcpy(sym_info->Name, name, sym_info->NameLen);
00806             sym_info->Name[sym_info->NameLen] = '\0';
00807         }
00808     }
00809     TRACE_(dbghelp_symt)("%p => %s %u %s\n",
00810                          sym, sym_info->Name, sym_info->Size,
00811                          wine_dbgstr_longlong(sym_info->Address));
00812 }
00813 
00814 struct sym_enum
00815 {
00816     PSYM_ENUMERATESYMBOLS_CALLBACK      cb;
00817     PVOID                               user;
00818     SYMBOL_INFO*                        sym_info;
00819     DWORD                               index;
00820     DWORD                               tag;
00821     DWORD64                             addr;
00822     char                                buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
00823 };
00824 
00825 static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair,
00826                         const struct symt_function* func, const struct symt* sym)
00827 {
00828     symt_fill_sym_info(pair, func, sym, se->sym_info);
00829     if (se->index && se->sym_info->info != se->index) return FALSE;
00830     if (se->tag && se->sym_info->Tag != se->tag) return FALSE;
00831     if (se->addr && !(se->addr >= se->sym_info->Address && se->addr < se->sym_info->Address + se->sym_info->Size)) return FALSE;
00832     return !se->cb(se->sym_info, se->sym_info->Size, se->user);
00833 }
00834 
00835 static BOOL symt_enum_module(struct module_pair* pair, const regex_t* regex,
00836                              const struct sym_enum* se)
00837 {
00838     void*                       ptr;
00839     struct symt_ht*             sym = NULL;
00840     struct hash_table_iter      hti;
00841 
00842     hash_table_iter_init(&pair->effective->ht_symbols, &hti, NULL);
00843     while ((ptr = hash_table_iter_up(&hti)))
00844     {
00845         sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
00846         if (sym->hash_elt.name && match_regexp(regex, sym->hash_elt.name))
00847         {
00848             se->sym_info->SizeOfStruct = sizeof(SYMBOL_INFO);
00849             se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO);
00850             if (send_symbol(se, pair, NULL, &sym->symt)) return TRUE;
00851         }
00852     }   
00853     return FALSE;
00854 }
00855 
00856 static inline unsigned where_to_insert(struct module* module, unsigned high, const struct symt_ht* elt)
00857 {
00858     unsigned    low = 0, mid = high / 2;
00859     ULONG64     addr;
00860 
00861     if (!high) return 0;
00862     symt_get_address(&elt->symt, &addr);
00863     do
00864     {
00865         switch (cmp_sorttab_addr(module, mid, addr))
00866         {
00867         case 0: return mid;
00868         case -1: low = mid + 1; break;
00869         case 1: high = mid; break;
00870         }
00871         mid = low + (high - low) / 2;
00872     } while (low < high);
00873     return mid;
00874 }
00875 
00876 /***********************************************************************
00877  *              resort_symbols
00878  *
00879  * Rebuild sorted list of symbols for a module.
00880  */
00881 static BOOL resort_symbols(struct module* module)
00882 {
00883     int delta;
00884 
00885     if (!(module->module.NumSyms = module->num_symbols))
00886         return FALSE;
00887 
00888     /* we know that set from 0 up to num_sorttab is already sorted
00889      * so sort the remaining (new) symbols, and merge the two sets
00890      * (unless the first set is empty)
00891      */
00892     delta = module->num_symbols - module->num_sorttab;
00893     qsort(&module->addr_sorttab[module->num_sorttab], delta, sizeof(struct symt_ht*), symt_cmp_addr);
00894     if (module->num_sorttab)
00895     {
00896         int     i, ins_idx = module->num_sorttab, prev_ins_idx;
00897         static struct symt_ht** tmp;
00898         static unsigned num_tmp;
00899 
00900         if (num_tmp < delta)
00901         {
00902             static struct symt_ht** new;
00903             if (tmp)
00904                 new = HeapReAlloc(GetProcessHeap(), 0, tmp, delta * sizeof(struct symt_ht*));
00905             else
00906                 new = HeapAlloc(GetProcessHeap(), 0, delta * sizeof(struct symt_ht*));
00907             if (!new)
00908             {
00909                 module->num_sorttab = 0;
00910                 return resort_symbols(module);
00911             }
00912             tmp = new;
00913             num_tmp = delta;
00914         }
00915         memcpy(tmp, &module->addr_sorttab[module->num_sorttab], delta * sizeof(struct symt_ht*));
00916         qsort(tmp, delta, sizeof(struct symt_ht*), symt_cmp_addr);
00917 
00918         for (i = delta - 1; i >= 0; i--)
00919         {
00920             prev_ins_idx = ins_idx;
00921             ins_idx = where_to_insert(module, ins_idx, tmp[i]);
00922             memmove(&module->addr_sorttab[ins_idx + i + 1],
00923                     &module->addr_sorttab[ins_idx],
00924                     (prev_ins_idx - ins_idx) * sizeof(struct symt_ht*));
00925             module->addr_sorttab[ins_idx + i] = tmp[i];
00926         }
00927     }
00928     module->num_sorttab = module->num_symbols;
00929     return module->sortlist_valid = TRUE;
00930 }
00931 
00932 static void symt_get_length(struct module* module, const struct symt* symt, ULONG64* size)
00933 {
00934     DWORD       type_index;
00935 
00936     if (symt_get_info(module,  symt, TI_GET_LENGTH, size) && *size)
00937         return;
00938 
00939     if (symt_get_info(module, symt, TI_GET_TYPE, &type_index) &&
00940         symt_get_info(module, symt_index2ptr(module, type_index), TI_GET_LENGTH, size)) return;
00941     *size = 0x1000; /* arbitrary value */
00942 }
00943 
00944 /* assume addr is in module */
00945 struct symt_ht* symt_find_nearest(struct module* module, DWORD_PTR addr)
00946 {
00947     int         mid, high, low;
00948     ULONG64     ref_addr, ref_size;
00949 
00950     if (!module->sortlist_valid || !module->addr_sorttab)
00951     {
00952         if (!resort_symbols(module)) return NULL;
00953     }
00954 
00955     /*
00956      * Binary search to find closest symbol.
00957      */
00958     low = 0;
00959     high = module->num_sorttab;
00960 
00961     symt_get_address(&module->addr_sorttab[0]->symt, &ref_addr);
00962     if (addr < ref_addr) return NULL;
00963     if (high)
00964     {
00965         symt_get_address(&module->addr_sorttab[high - 1]->symt, &ref_addr);
00966         symt_get_length(module, &module->addr_sorttab[high - 1]->symt, &ref_size);
00967         if (addr >= ref_addr + ref_size) return NULL;
00968     }
00969     
00970     while (high > low + 1)
00971     {
00972         mid = (high + low) / 2;
00973         if (cmp_sorttab_addr(module, mid, addr) < 0)
00974             low = mid;
00975         else
00976             high = mid;
00977     }
00978     if (low != high && high != module->num_sorttab &&
00979         cmp_sorttab_addr(module, high, addr) <= 0)
00980         low = high;
00981 
00982     /* If found symbol is a public symbol, check if there are any other entries that
00983      * might also have the same address, but would get better information
00984      */
00985     if (module->addr_sorttab[low]->symt.tag == SymTagPublicSymbol)
00986     {
00987         symt_get_address(&module->addr_sorttab[low]->symt, &ref_addr);
00988         if (low > 0 &&
00989             module->addr_sorttab[low - 1]->symt.tag != SymTagPublicSymbol &&
00990             !cmp_sorttab_addr(module, low - 1, ref_addr))
00991             low--;
00992         else if (low < module->num_sorttab - 1 &&
00993                  module->addr_sorttab[low + 1]->symt.tag != SymTagPublicSymbol &&
00994                  !cmp_sorttab_addr(module, low + 1, ref_addr))
00995             low++;
00996     }
00997     /* finally check that we fit into the found symbol */
00998     symt_get_address(&module->addr_sorttab[low]->symt, &ref_addr);
00999     if (addr < ref_addr) return NULL;
01000     symt_get_length(module, &module->addr_sorttab[low]->symt, &ref_size);
01001     if (addr >= ref_addr + ref_size) return NULL;
01002 
01003     return module->addr_sorttab[low];
01004 }
01005 
01006 static BOOL symt_enum_locals_helper(struct module_pair* pair,
01007                                     regex_t* preg, const struct sym_enum* se,
01008                                     struct symt_function* func, const struct vector* v)
01009 {
01010     struct symt*        lsym = NULL;
01011     DWORD               pc = pair->pcs->ctx_frame.InstructionOffset;
01012     unsigned int        i;
01013 
01014     for (i=0; i<vector_length(v); i++)
01015     {
01016         lsym = *(struct symt**)vector_at(v, i);
01017         switch (lsym->tag)
01018         {
01019         case SymTagBlock:
01020             {
01021                 struct symt_block*  block = (struct symt_block*)lsym;
01022                 if (pc < block->address || block->address + block->size <= pc)
01023                     continue;
01024                 if (!symt_enum_locals_helper(pair, preg, se, func, &block->vchildren))
01025                     return FALSE;
01026             }
01027             break;
01028         case SymTagData:
01029             if (match_regexp(preg, symt_get_name(lsym)))
01030             {
01031                 if (send_symbol(se, pair, func, lsym)) return FALSE;
01032             }
01033             break;
01034         case SymTagLabel:
01035         case SymTagFuncDebugStart:
01036         case SymTagFuncDebugEnd:
01037         case SymTagCustom:
01038             break;
01039         default:
01040             FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag);
01041             assert(0);
01042         }
01043     }
01044     return TRUE;
01045 }
01046 
01047 static BOOL symt_enum_locals(struct process* pcs, const char* mask, 
01048                              const struct sym_enum* se)
01049 {
01050     struct module_pair  pair;
01051     struct symt_ht*     sym;
01052     DWORD_PTR           pc = pcs->ctx_frame.InstructionOffset;
01053 
01054     se->sym_info->SizeOfStruct = sizeof(*se->sym_info);
01055     se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO);
01056 
01057     pair.pcs = pcs;
01058     pair.requested = module_find_by_addr(pair.pcs, pc, DMT_UNKNOWN);
01059     if (!module_get_debug(&pair)) return FALSE;
01060     if ((sym = symt_find_nearest(pair.effective, pc)) == NULL) return FALSE;
01061 
01062     if (sym->symt.tag == SymTagFunction)
01063     {
01064         BOOL            ret;
01065         regex_t         preg;
01066 
01067         compile_regex(mask ? mask : "*", -1, &preg,
01068                       dbghelp_options & SYMOPT_CASE_INSENSITIVE);
01069         ret = symt_enum_locals_helper(&pair, &preg, se, (struct symt_function*)sym,
01070                                       &((struct symt_function*)sym)->vchildren);
01071         regfree(&preg);
01072         return ret;
01073     }
01074     return FALSE;
01075 }
01076 
01077 /******************************************************************
01078  *      copy_symbolW
01079  *
01080  * Helper for transforming an ANSI symbol info into a UNICODE one.
01081  * Assume that MaxNameLen is the same for both version (A & W).
01082  */
01083 void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si)
01084 {
01085     siw->SizeOfStruct = si->SizeOfStruct;
01086     siw->TypeIndex = si->TypeIndex; 
01087     siw->Reserved[0] = si->Reserved[0];
01088     siw->Reserved[1] = si->Reserved[1];
01089     siw->Index = si->info; /* FIXME: see dbghelp.h */
01090     siw->Size = si->Size;
01091     siw->ModBase = si->ModBase;
01092     siw->Flags = si->Flags;
01093     siw->Value = si->Value;
01094     siw->Address = si->Address;
01095     siw->Register = si->Register;
01096     siw->Scope = si->Scope;
01097     siw->Tag = si->Tag;
01098     siw->NameLen = si->NameLen;
01099     siw->MaxNameLen = si->MaxNameLen;
01100     MultiByteToWideChar(CP_ACP, 0, si->Name, -1, siw->Name, siw->MaxNameLen);
01101 }
01102 
01103 /******************************************************************
01104  *      sym_enum
01105  *
01106  * Core routine for most of the enumeration of symbols
01107  */
01108 static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
01109                      const struct sym_enum* se)
01110 {
01111     struct module_pair  pair;
01112     const char*         bang;
01113     regex_t             mod_regex, sym_regex;
01114 
01115     pair.pcs = process_find_by_handle(hProcess);
01116     if (!pair.pcs) return FALSE;
01117     if (BaseOfDll == 0)
01118     {
01119         /* do local variables ? */
01120         if (!Mask || !(bang = strchr(Mask, '!')))
01121             return symt_enum_locals(pair.pcs, Mask, se);
01122 
01123         if (bang == Mask) return FALSE;
01124 
01125         compile_regex(Mask, bang - Mask, &mod_regex, TRUE);
01126         compile_regex(bang + 1, -1, &sym_regex, 
01127                       dbghelp_options & SYMOPT_CASE_INSENSITIVE);
01128         
01129         for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next)
01130         {
01131             if (pair.requested->type == DMT_PE && module_get_debug(&pair))
01132             {
01133                 if (match_regexp(&mod_regex, pair.requested->module_name) &&
01134                     symt_enum_module(&pair, &sym_regex, se))
01135                     break;
01136             }
01137         }
01138         /* not found in PE modules, retry on the ELF ones
01139          */
01140         if (!pair.requested && (dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES))
01141         {
01142             for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next)
01143             {
01144                 if ((pair.requested->type == DMT_ELF || pair.requested->type == DMT_MACHO) &&
01145                     !module_get_containee(pair.pcs, pair.requested) &&
01146                     module_get_debug(&pair))
01147                 {
01148                     if (match_regexp(&mod_regex, pair.requested->module_name) &&
01149                         symt_enum_module(&pair, &sym_regex, se))
01150                     break;
01151                 }
01152             }
01153         }
01154         regfree(&mod_regex);
01155         regfree(&sym_regex);
01156         return TRUE;
01157     }
01158     pair.requested = module_find_by_addr(pair.pcs, BaseOfDll, DMT_UNKNOWN);
01159     if (!module_get_debug(&pair))
01160         return FALSE;
01161 
01162     /* we always ignore module name from Mask when BaseOfDll is defined */
01163     if (Mask && (bang = strchr(Mask, '!')))
01164     {
01165         if (bang == Mask) return FALSE;
01166         Mask = bang + 1;
01167     }
01168 
01169     compile_regex(Mask ? Mask : "*", -1, &sym_regex, 
01170                   dbghelp_options & SYMOPT_CASE_INSENSITIVE);
01171     symt_enum_module(&pair, &sym_regex, se);
01172     regfree(&sym_regex);
01173 
01174     return TRUE;
01175 }
01176 
01177 /******************************************************************
01178  *      SymEnumSymbols (DBGHELP.@)
01179  *
01180  * cases BaseOfDll = 0
01181  *      !foo fails always (despite what MSDN states)
01182  *      RE1!RE2 looks up all modules matching RE1, and in all these modules, lookup RE2
01183  *      no ! in Mask, lookup in local Context
01184  * cases BaseOfDll != 0
01185  *      !foo fails always (despite what MSDN states)
01186  *      RE1!RE2 gets RE2 from BaseOfDll (whatever RE1 is)
01187  */
01188 BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask,
01189                            PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
01190                            PVOID UserContext)
01191 {
01192     struct sym_enum     se;
01193 
01194     TRACE("(%p %s %s %p %p)\n", 
01195           hProcess, wine_dbgstr_longlong(BaseOfDll), debugstr_a(Mask),
01196           EnumSymbolsCallback, UserContext);
01197 
01198     se.cb = EnumSymbolsCallback;
01199     se.user = UserContext;
01200     se.index = 0;
01201     se.tag = 0;
01202     se.addr = 0;
01203     se.sym_info = (PSYMBOL_INFO)se.buffer;
01204 
01205     return sym_enum(hProcess, BaseOfDll, Mask, &se);
01206 }
01207 
01208 struct sym_enumW
01209 {
01210     PSYM_ENUMERATESYMBOLS_CALLBACKW     cb;
01211     void*                               ctx;
01212     PSYMBOL_INFOW                       sym_info;
01213     char                                buffer[sizeof(SYMBOL_INFOW) + MAX_SYM_NAME];
01214 
01215 };
01216     
01217 static BOOL CALLBACK sym_enumW(PSYMBOL_INFO si, ULONG size, PVOID ctx)
01218 {
01219     struct sym_enumW*   sew = ctx;
01220 
01221     copy_symbolW(sew->sym_info, si);
01222 
01223     return (sew->cb)(sew->sym_info, size, sew->ctx);
01224 }
01225 
01226 /******************************************************************
01227  *      SymEnumSymbolsW (DBGHELP.@)
01228  *
01229  */
01230 BOOL WINAPI SymEnumSymbolsW(HANDLE hProcess, ULONG64 BaseOfDll, PCWSTR Mask,
01231                             PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
01232                             PVOID UserContext)
01233 {
01234     struct sym_enumW    sew;
01235     BOOL                ret = FALSE;
01236     char*               maskA = NULL;
01237 
01238     sew.ctx = UserContext;
01239     sew.cb = EnumSymbolsCallback;
01240     sew.sym_info = (PSYMBOL_INFOW)sew.buffer;
01241 
01242     if (Mask)
01243     {
01244         unsigned len = WideCharToMultiByte(CP_ACP, 0, Mask, -1, NULL, 0, NULL, NULL);
01245         maskA = HeapAlloc(GetProcessHeap(), 0, len);
01246         if (!maskA) return FALSE;
01247         WideCharToMultiByte(CP_ACP, 0, Mask, -1, maskA, len, NULL, NULL);
01248     }
01249     ret = SymEnumSymbols(hProcess, BaseOfDll, maskA, sym_enumW, &sew);
01250     HeapFree(GetProcessHeap(), 0, maskA);
01251 
01252     return ret;
01253 }
01254 
01255 struct sym_enumerate
01256 {
01257     void*                       ctx;
01258     PSYM_ENUMSYMBOLS_CALLBACK   cb;
01259 };
01260 
01261 static BOOL CALLBACK sym_enumerate_cb(PSYMBOL_INFO syminfo, ULONG size, void* ctx)
01262 {
01263     struct sym_enumerate*       se = ctx;
01264     return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx);
01265 }
01266 
01267 /***********************************************************************
01268  *      SymEnumerateSymbols (DBGHELP.@)
01269  */
01270 BOOL WINAPI SymEnumerateSymbols(HANDLE hProcess, DWORD BaseOfDll,
01271                                 PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, 
01272                                 PVOID UserContext)
01273 {
01274     struct sym_enumerate        se;
01275 
01276     se.ctx = UserContext;
01277     se.cb  = EnumSymbolsCallback;
01278     
01279     return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb, &se);
01280 }
01281 
01282 struct sym_enumerate64
01283 {
01284     void*                       ctx;
01285     PSYM_ENUMSYMBOLS_CALLBACK64 cb;
01286 };
01287 
01288 static BOOL CALLBACK sym_enumerate_cb64(PSYMBOL_INFO syminfo, ULONG size, void* ctx)
01289 {
01290     struct sym_enumerate64*     se = ctx;
01291     return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx);
01292 }
01293 
01294 /***********************************************************************
01295  *              SymEnumerateSymbols64 (DBGHELP.@)
01296  */
01297 BOOL WINAPI SymEnumerateSymbols64(HANDLE hProcess, DWORD64 BaseOfDll,
01298                                   PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,
01299                                   PVOID UserContext)
01300 {
01301     struct sym_enumerate64      se;
01302 
01303     se.ctx = UserContext;
01304     se.cb  = EnumSymbolsCallback;
01305 
01306     return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb64, &se);
01307 }
01308 
01309 /******************************************************************
01310  *      SymFromAddr (DBGHELP.@)
01311  *
01312  */
01313 BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, 
01314                         DWORD64* Displacement, PSYMBOL_INFO Symbol)
01315 {
01316     struct module_pair  pair;
01317     struct symt_ht*     sym;
01318 
01319     pair.pcs = process_find_by_handle(hProcess);
01320     if (!pair.pcs) return FALSE;
01321     pair.requested = module_find_by_addr(pair.pcs, Address, DMT_UNKNOWN);
01322     if (!module_get_debug(&pair)) return FALSE;
01323     if ((sym = symt_find_nearest(pair.effective, Address)) == NULL) return FALSE;
01324 
01325     symt_fill_sym_info(&pair, NULL, &sym->symt, Symbol);
01326     *Displacement = Address - Symbol->Address;
01327     return TRUE;
01328 }
01329 
01330 /******************************************************************
01331  *      SymFromAddrW (DBGHELP.@)
01332  *
01333  */
01334 BOOL WINAPI SymFromAddrW(HANDLE hProcess, DWORD64 Address, 
01335                          DWORD64* Displacement, PSYMBOL_INFOW Symbol)
01336 {
01337     PSYMBOL_INFO        si;
01338     unsigned            len;
01339     BOOL                ret;
01340 
01341     len = sizeof(*si) + Symbol->MaxNameLen * sizeof(WCHAR);
01342     si = HeapAlloc(GetProcessHeap(), 0, len);
01343     if (!si) return FALSE;
01344 
01345     si->SizeOfStruct = sizeof(*si);
01346     si->MaxNameLen = Symbol->MaxNameLen;
01347     if ((ret = SymFromAddr(hProcess, Address, Displacement, si)))
01348     {
01349         copy_symbolW(Symbol, si);
01350     }
01351     HeapFree(GetProcessHeap(), 0, si);
01352     return ret;
01353 }
01354 
01355 /******************************************************************
01356  *      SymGetSymFromAddr (DBGHELP.@)
01357  *
01358  */
01359 BOOL WINAPI SymGetSymFromAddr(HANDLE hProcess, DWORD Address,
01360                               PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol)
01361 {
01362     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
01363     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
01364     size_t      len;
01365     DWORD64     Displacement64;
01366 
01367     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
01368     si->SizeOfStruct = sizeof(*si);
01369     si->MaxNameLen = MAX_SYM_NAME;
01370     if (!SymFromAddr(hProcess, Address, &Displacement64, si))
01371         return FALSE;
01372 
01373     if (Displacement)
01374         *Displacement = Displacement64;
01375     Symbol->Address = si->Address;
01376     Symbol->Size    = si->Size;
01377     Symbol->Flags   = si->Flags;
01378     len = min(Symbol->MaxNameLength, si->MaxNameLen);
01379     lstrcpynA(Symbol->Name, si->Name, len);
01380     return TRUE;
01381 }
01382 
01383 /******************************************************************
01384  *      SymGetSymFromAddr64 (DBGHELP.@)
01385  *
01386  */
01387 BOOL WINAPI SymGetSymFromAddr64(HANDLE hProcess, DWORD64 Address,
01388                                 PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol)
01389 {
01390     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
01391     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
01392     size_t      len;
01393     DWORD64     Displacement64;
01394 
01395     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
01396     si->SizeOfStruct = sizeof(*si);
01397     si->MaxNameLen = MAX_SYM_NAME;
01398     if (!SymFromAddr(hProcess, Address, &Displacement64, si))
01399         return FALSE;
01400 
01401     if (Displacement)
01402         *Displacement = Displacement64;
01403     Symbol->Address = si->Address;
01404     Symbol->Size    = si->Size;
01405     Symbol->Flags   = si->Flags;
01406     len = min(Symbol->MaxNameLength, si->MaxNameLen);
01407     lstrcpynA(Symbol->Name, si->Name, len);
01408     return TRUE;
01409 }
01410 
01411 static BOOL find_name(struct process* pcs, struct module* module, const char* name,
01412                       SYMBOL_INFO* symbol)
01413 {
01414     struct hash_table_iter      hti;
01415     void*                       ptr;
01416     struct symt_ht*             sym = NULL;
01417     struct module_pair          pair;
01418 
01419     pair.pcs = pcs;
01420     if (!(pair.requested = module)) return FALSE;
01421     if (!module_get_debug(&pair)) return FALSE;
01422 
01423     hash_table_iter_init(&pair.effective->ht_symbols, &hti, name);
01424     while ((ptr = hash_table_iter_up(&hti)))
01425     {
01426         sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
01427 
01428         if (!strcmp(sym->hash_elt.name, name))
01429         {
01430             symt_fill_sym_info(&pair, NULL, &sym->symt, symbol);
01431             return TRUE;
01432         }
01433     }
01434     return FALSE;
01435 
01436 }
01437 /******************************************************************
01438  *      SymFromName (DBGHELP.@)
01439  *
01440  */
01441 BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol)
01442 {
01443     struct process*             pcs = process_find_by_handle(hProcess);
01444     struct module*              module;
01445     const char*                 name;
01446 
01447     TRACE("(%p, %s, %p)\n", hProcess, Name, Symbol);
01448     if (!pcs) return FALSE;
01449     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
01450     name = strchr(Name, '!');
01451     if (name)
01452     {
01453         char    tmp[128];
01454         assert(name - Name < sizeof(tmp));
01455         memcpy(tmp, Name, name - Name);
01456         tmp[name - Name] = '\0';
01457         module = module_find_by_nameA(pcs, tmp);
01458         return find_name(pcs, module, name + 1, Symbol);
01459     }
01460     for (module = pcs->lmodules; module; module = module->next)
01461     {
01462         if (module->type == DMT_PE && find_name(pcs, module, Name, Symbol))
01463             return TRUE;
01464     }
01465     /* not found in PE modules, retry on the ELF ones
01466      */
01467     if (dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES)
01468     {
01469         for (module = pcs->lmodules; module; module = module->next)
01470         {
01471             if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
01472                 !module_get_containee(pcs, module) &&
01473                 find_name(pcs, module, Name, Symbol))
01474                 return TRUE;
01475         }
01476     }
01477     return FALSE;
01478 }
01479 
01480 /***********************************************************************
01481  *      SymGetSymFromName64 (DBGHELP.@)
01482  */
01483 BOOL WINAPI SymGetSymFromName64(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL64 Symbol)
01484 {
01485     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
01486     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
01487     size_t      len;
01488 
01489     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
01490     si->SizeOfStruct = sizeof(*si);
01491     si->MaxNameLen = MAX_SYM_NAME;
01492     if (!SymFromName(hProcess, Name, si)) return FALSE;
01493 
01494     Symbol->Address = si->Address;
01495     Symbol->Size    = si->Size;
01496     Symbol->Flags   = si->Flags;
01497     len = min(Symbol->MaxNameLength, si->MaxNameLen);
01498     lstrcpynA(Symbol->Name, si->Name, len);
01499     return TRUE;
01500 }
01501 
01502 /***********************************************************************
01503  *      SymGetSymFromName (DBGHELP.@)
01504  */
01505 BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symbol)
01506 {
01507     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
01508     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
01509     size_t      len;
01510 
01511     if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE;
01512     si->SizeOfStruct = sizeof(*si);
01513     si->MaxNameLen = MAX_SYM_NAME;
01514     if (!SymFromName(hProcess, Name, si)) return FALSE;
01515 
01516     Symbol->Address = si->Address;
01517     Symbol->Size    = si->Size;
01518     Symbol->Flags   = si->Flags;
01519     len = min(Symbol->MaxNameLength, si->MaxNameLen);
01520     lstrcpynA(Symbol->Name, si->Name, len);
01521     return TRUE;
01522 }
01523 
01524 /******************************************************************
01525  *      sym_fill_func_line_info
01526  *
01527  * fills information about a file
01528  */
01529 BOOL symt_fill_func_line_info(const struct module* module, const struct symt_function* func,
01530                               DWORD64 addr, IMAGEHLP_LINE64* line)
01531 {
01532     struct line_info*   dli = NULL;
01533     BOOL                found = FALSE;
01534     int                 i;
01535 
01536     assert(func->symt.tag == SymTagFunction);
01537 
01538     for (i=vector_length(&func->vlines)-1; i>=0; i--)
01539     {
01540         dli = vector_at(&func->vlines, i);
01541         if (!dli->is_source_file)
01542         {
01543             if (found || dli->u.pc_offset > addr) continue;
01544             line->LineNumber = dli->line_number;
01545             line->Address    = dli->u.pc_offset;
01546             line->Key        = dli;
01547             found = TRUE;
01548             continue;
01549         }
01550         if (found)
01551         {
01552             line->FileName = (char*)source_get(module, dli->u.source_file);
01553             return TRUE;
01554         }
01555     }
01556     return FALSE;
01557 }
01558 
01559 /***********************************************************************
01560  *      SymGetSymNext64 (DBGHELP.@)
01561  */
01562 BOOL WINAPI SymGetSymNext64(HANDLE hProcess, PIMAGEHLP_SYMBOL64 Symbol)
01563 {
01564     /* algo:
01565      * get module from Symbol.Address
01566      * get index in module.addr_sorttab of Symbol.Address
01567      * increment index
01568      * if out of module bounds, move to next module in process address space
01569      */
01570     FIXME("(%p, %p): stub\n", hProcess, Symbol);
01571     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
01572     return FALSE;
01573 }
01574 
01575 /***********************************************************************
01576  *      SymGetSymNext (DBGHELP.@)
01577  */
01578 BOOL WINAPI SymGetSymNext(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
01579 {
01580     FIXME("(%p, %p): stub\n", hProcess, Symbol);
01581     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
01582     return FALSE;
01583 }
01584 
01585 /***********************************************************************
01586  *      SymGetSymPrev64 (DBGHELP.@)
01587  */
01588 BOOL WINAPI SymGetSymPrev64(HANDLE hProcess, PIMAGEHLP_SYMBOL64 Symbol)
01589 {
01590     FIXME("(%p, %p): stub\n", hProcess, Symbol);
01591     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
01592     return FALSE;
01593 }
01594 
01595 /***********************************************************************
01596  *      SymGetSymPrev (DBGHELP.@)
01597  */
01598 BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol)
01599 {
01600     FIXME("(%p, %p): stub\n", hProcess, Symbol);
01601     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
01602     return FALSE;
01603 }
01604 
01605 /******************************************************************
01606  *      copy_line_64_from_32 (internal)
01607  *
01608  */
01609 static void copy_line_64_from_32(IMAGEHLP_LINE64* l64, const IMAGEHLP_LINE* l32)
01610 
01611 {
01612     l64->Key = l32->Key;
01613     l64->LineNumber = l32->LineNumber;
01614     l64->FileName = l32->FileName;
01615     l64->Address = l32->Address;
01616 }
01617 
01618 /******************************************************************
01619  *      copy_line_W64_from_32 (internal)
01620  *
01621  */
01622 static void copy_line_W64_from_64(struct process* pcs, IMAGEHLP_LINEW64* l64w, const IMAGEHLP_LINE64* l64)
01623 {
01624     unsigned len;
01625 
01626     l64w->Key = l64->Key;
01627     l64w->LineNumber = l64->LineNumber;
01628     len = MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, NULL, 0);
01629     if ((l64w->FileName = fetch_buffer(pcs, len * sizeof(WCHAR))))
01630         MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, l64w->FileName, len);
01631     l64w->Address = l64->Address;
01632 }
01633 
01634 /******************************************************************
01635  *      copy_line_32_from_64 (internal)
01636  *
01637  */
01638 static void copy_line_32_from_64(IMAGEHLP_LINE* l32, const IMAGEHLP_LINE64* l64)
01639 
01640 {
01641     l32->Key = l64->Key;
01642     l32->LineNumber = l64->LineNumber;
01643     l32->FileName = l64->FileName;
01644     l32->Address = l64->Address;
01645 }
01646 
01647 /******************************************************************
01648  *      SymGetLineFromAddr (DBGHELP.@)
01649  *
01650  */
01651 BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr,
01652                                PDWORD pdwDisplacement, PIMAGEHLP_LINE Line)
01653 {
01654     IMAGEHLP_LINE64     il64;
01655 
01656     il64.SizeOfStruct = sizeof(il64);
01657     if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64))
01658         return FALSE;
01659     copy_line_32_from_64(Line, &il64);
01660     return TRUE;
01661 }
01662 
01663 /******************************************************************
01664  *      SymGetLineFromAddr64 (DBGHELP.@)
01665  *
01666  */
01667 BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, 
01668                                  PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line)
01669 {
01670     struct module_pair  pair;
01671     struct symt_ht*     symt;
01672 
01673     TRACE("%p %s %p %p\n", hProcess, wine_dbgstr_longlong(dwAddr), pdwDisplacement, Line);
01674 
01675     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
01676 
01677     pair.pcs = process_find_by_handle(hProcess);
01678     if (!pair.pcs) return FALSE;
01679     pair.requested = module_find_by_addr(pair.pcs, dwAddr, DMT_UNKNOWN);
01680     if (!module_get_debug(&pair)) return FALSE;
01681     if ((symt = symt_find_nearest(pair.effective, dwAddr)) == NULL) return FALSE;
01682 
01683     if (symt->symt.tag != SymTagFunction) return FALSE;
01684     if (!symt_fill_func_line_info(pair.effective, (struct symt_function*)symt,
01685                                   dwAddr, Line)) return FALSE;
01686     *pdwDisplacement = dwAddr - Line->Address;
01687     return TRUE;
01688 }
01689 
01690 /******************************************************************
01691  *      SymGetLineFromAddrW64 (DBGHELP.@)
01692  *
01693  */
01694 BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr, 
01695                                   PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line)
01696 {
01697     IMAGEHLP_LINE64     il64;
01698 
01699     il64.SizeOfStruct = sizeof(il64);
01700     if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64))
01701         return FALSE;
01702     copy_line_W64_from_64(process_find_by_handle(hProcess), Line, &il64);
01703     return TRUE;
01704 }
01705 
01706 /******************************************************************
01707  *      SymGetLinePrev64 (DBGHELP.@)
01708  *
01709  */
01710 BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
01711 {
01712     struct module_pair  pair;
01713     struct line_info*   li;
01714     BOOL                in_search = FALSE;
01715 
01716     TRACE("(%p %p)\n", hProcess, Line);
01717 
01718     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
01719 
01720     pair.pcs = process_find_by_handle(hProcess);
01721     if (!pair.pcs) return FALSE;
01722     pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN);
01723     if (!module_get_debug(&pair)) return FALSE;
01724 
01725     if (Line->Key == 0) return FALSE;
01726     li = Line->Key;
01727     /* things are a bit complicated because when we encounter a DLIT_SOURCEFILE
01728      * element we have to go back until we find the prev one to get the real
01729      * source file name for the DLIT_OFFSET element just before 
01730      * the first DLIT_SOURCEFILE
01731      */
01732     while (!li->is_first)
01733     {
01734         li--;
01735         if (!li->is_source_file)
01736         {
01737             Line->LineNumber = li->line_number;
01738             Line->Address    = li->u.pc_offset;
01739             Line->Key        = li;
01740             if (!in_search) return TRUE;
01741         }
01742         else
01743         {
01744             if (in_search)
01745             {
01746                 Line->FileName = (char*)source_get(pair.effective, li->u.source_file);
01747                 return TRUE;
01748             }
01749             in_search = TRUE;
01750         }
01751     }
01752     SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */
01753     return FALSE;
01754 }
01755 
01756 /******************************************************************
01757  *      SymGetLinePrev (DBGHELP.@)
01758  *
01759  */
01760 BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line)
01761 {
01762     IMAGEHLP_LINE64     line64;
01763 
01764     line64.SizeOfStruct = sizeof(line64);
01765     copy_line_64_from_32(&line64, Line);
01766     if (!SymGetLinePrev64(hProcess, &line64)) return FALSE;
01767     copy_line_32_from_64(Line, &line64);
01768     return TRUE;
01769 }
01770 
01771 BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line)
01772 {
01773     struct line_info*   li;
01774 
01775     if (line->Key == 0) return FALSE;
01776     li = line->Key;
01777     while (!li->is_last)
01778     {
01779         li++;
01780         if (!li->is_source_file)
01781         {
01782             line->LineNumber = li->line_number;
01783             line->Address    = li->u.pc_offset;
01784             line->Key        = li;
01785             return TRUE;
01786         }
01787         line->FileName = (char*)source_get(module, li->u.source_file);
01788     }
01789     return FALSE;
01790 }
01791 
01792 /******************************************************************
01793  *      SymGetLineNext64 (DBGHELP.@)
01794  *
01795  */
01796 BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line)
01797 {
01798     struct module_pair  pair;
01799 
01800     TRACE("(%p %p)\n", hProcess, Line);
01801 
01802     if (Line->SizeOfStruct < sizeof(*Line)) return FALSE;
01803     pair.pcs = process_find_by_handle(hProcess);
01804     if (!pair.pcs) return FALSE;
01805     pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN);
01806     if (!module_get_debug(&pair)) return FALSE;
01807 
01808     if (symt_get_func_line_next(pair.effective, Line)) return TRUE;
01809     SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */
01810     return FALSE;
01811 }
01812 
01813 /******************************************************************
01814  *      SymGetLineNext (DBGHELP.@)
01815  *
01816  */
01817 BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
01818 {
01819     IMAGEHLP_LINE64     line64;
01820 
01821     line64.SizeOfStruct = sizeof(line64);
01822     copy_line_64_from_32(&line64, Line);
01823     if (!SymGetLineNext64(hProcess, &line64)) return FALSE;
01824     copy_line_32_from_64(Line, &line64);
01825     return TRUE;
01826 }
01827 
01828 /***********************************************************************
01829  *      SymUnDName (DBGHELP.@)
01830  */
01831 BOOL WINAPI SymUnDName(PIMAGEHLP_SYMBOL sym, PSTR UnDecName, DWORD UnDecNameLength)
01832 {
01833     return UnDecorateSymbolName(sym->Name, UnDecName, UnDecNameLength,
01834                                 UNDNAME_COMPLETE) != 0;
01835 }
01836 
01837 /***********************************************************************
01838  *      SymUnDName64 (DBGHELP.@)
01839  */
01840 BOOL WINAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym, PSTR UnDecName, DWORD UnDecNameLength)
01841 {
01842     return UnDecorateSymbolName(sym->Name, UnDecName, UnDecNameLength,
01843                                 UNDNAME_COMPLETE) != 0;
01844 }
01845 
01846 static void * CDECL und_alloc(size_t len) { return HeapAlloc(GetProcessHeap(), 0, len); }
01847 static void   CDECL und_free (void* ptr)  { HeapFree(GetProcessHeap(), 0, ptr); }
01848 
01849 /***********************************************************************
01850  *      UnDecorateSymbolName (DBGHELP.@)
01851  */
01852 DWORD WINAPI UnDecorateSymbolName(PCSTR DecoratedName, PSTR UnDecoratedName,
01853                                   DWORD UndecoratedLength, DWORD Flags)
01854 {
01855     /* undocumented from msvcrt */
01856     static char* (* CDECL p_undname)(char*, const char*, int, void* (* CDECL)(size_t), void (* CDECL)(void*), unsigned short);
01857     static const WCHAR szMsvcrt[] = {'m','s','v','c','r','t','.','d','l','l',0};
01858 
01859     TRACE("(%s, %p, %d, 0x%08x)\n",
01860           debugstr_a(DecoratedName), UnDecoratedName, UndecoratedLength, Flags);
01861 
01862     if (!p_undname)
01863     {
01864         if (!hMsvcrt) hMsvcrt = LoadLibraryW(szMsvcrt);
01865         if (hMsvcrt) p_undname = (void*)GetProcAddress(hMsvcrt, "__unDName");
01866         if (!p_undname) return 0;
01867     }
01868 
01869     if (!UnDecoratedName) return 0;
01870     if (!p_undname(UnDecoratedName, DecoratedName, UndecoratedLength, 
01871                    und_alloc, und_free, Flags))
01872         return 0;
01873     return strlen(UnDecoratedName);
01874 }
01875 
01876 /******************************************************************
01877  *      SymMatchStringA (DBGHELP.@)
01878  *
01879  */
01880 BOOL WINAPI SymMatchStringA(PCSTR string, PCSTR re, BOOL _case)
01881 {
01882     regex_t     preg;
01883     BOOL        ret;
01884 
01885     TRACE("%s %s %c\n", string, re, _case ? 'Y' : 'N');
01886 
01887     compile_regex(re, -1, &preg, _case);
01888     ret = match_regexp(&preg, string);
01889     regfree(&preg);
01890     return ret;
01891 }
01892 
01893 /******************************************************************
01894  *      SymMatchStringW (DBGHELP.@)
01895  *
01896  * FIXME: SymMatchStringA should convert and pass the strings to SymMatchStringW,
01897  *        but that needs a unicode RE library.
01898  */
01899 BOOL WINAPI SymMatchStringW(PCWSTR string, PCWSTR re, BOOL _case)
01900 {
01901     BOOL ret;
01902     LPSTR s, r;
01903     DWORD len;
01904 
01905     TRACE("%s %s %c\n", debugstr_w(string), debugstr_w(re), _case ? 'Y' : 'N');
01906 
01907     len = WideCharToMultiByte( CP_ACP, 0, string, -1, NULL, 0, NULL, NULL );
01908     s = HeapAlloc( GetProcessHeap(), 0, len );
01909     WideCharToMultiByte( CP_ACP, 0, string, -1, s, len, NULL, NULL );
01910 
01911     len = WideCharToMultiByte( CP_ACP, 0, re, -1, NULL, 0, NULL, NULL );
01912     r = HeapAlloc( GetProcessHeap(), 0, len );
01913     WideCharToMultiByte( CP_ACP, 0, re, -1, r, len, NULL, NULL );
01914 
01915     ret = SymMatchStringA(s, r, _case);
01916 
01917     HeapFree( GetProcessHeap(), 0, r );
01918     HeapFree( GetProcessHeap(), 0, s );
01919     return ret;
01920 }
01921 
01922 /******************************************************************
01923  *      SymSearch (DBGHELP.@)
01924  */
01925 BOOL WINAPI SymSearch(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index,
01926                       DWORD SymTag, PCSTR Mask, DWORD64 Address,
01927                       PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,
01928                       PVOID UserContext, DWORD Options)
01929 {
01930     struct sym_enum     se;
01931 
01932     TRACE("(%p %s %u %u %s %s %p %p %x)\n",
01933           hProcess, wine_dbgstr_longlong(BaseOfDll), Index, SymTag, Mask,
01934           wine_dbgstr_longlong(Address), EnumSymbolsCallback,
01935           UserContext, Options);
01936 
01937     if (Options != SYMSEARCH_GLOBALSONLY)
01938     {
01939         FIXME("Unsupported searching with options (%x)\n", Options);
01940         SetLastError(ERROR_INVALID_PARAMETER);
01941         return FALSE;
01942     }
01943 
01944     se.cb = EnumSymbolsCallback;
01945     se.user = UserContext;
01946     se.index = Index;
01947     se.tag = SymTag;
01948     se.addr = Address;
01949     se.sym_info = (PSYMBOL_INFO)se.buffer;
01950 
01951     return sym_enum(hProcess, BaseOfDll, Mask, &se);
01952 }
01953 
01954 /******************************************************************
01955  *      SymSearchW (DBGHELP.@)
01956  */
01957 BOOL WINAPI SymSearchW(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index,
01958                        DWORD SymTag, PCWSTR Mask, DWORD64 Address,
01959                        PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback,
01960                        PVOID UserContext, DWORD Options)
01961 {
01962     struct sym_enumW    sew;
01963     BOOL                ret = FALSE;
01964     char*               maskA = NULL;
01965 
01966     TRACE("(%p %s %u %u %s %s %p %p %x)\n",
01967           hProcess, wine_dbgstr_longlong(BaseOfDll), Index, SymTag, debugstr_w(Mask),
01968           wine_dbgstr_longlong(Address), EnumSymbolsCallback,
01969           UserContext, Options);
01970 
01971     sew.ctx = UserContext;
01972     sew.cb = EnumSymbolsCallback;
01973     sew.sym_info = (PSYMBOL_INFOW)sew.buffer;
01974 
01975     if (Mask)
01976     {
01977         unsigned len = WideCharToMultiByte(CP_ACP, 0, Mask, -1, NULL, 0, NULL, NULL);
01978         maskA = HeapAlloc(GetProcessHeap(), 0, len);
01979         if (!maskA) return FALSE;
01980         WideCharToMultiByte(CP_ACP, 0, Mask, -1, maskA, len, NULL, NULL);
01981     }
01982     ret = SymSearch(hProcess, BaseOfDll, Index, SymTag, maskA, Address,
01983                     sym_enumW, &sew, Options);
01984     HeapFree(GetProcessHeap(), 0, maskA);
01985 
01986     return ret;
01987 }
01988 
01989 /******************************************************************
01990  *      SymAddSymbol (DBGHELP.@)
01991  *
01992  */
01993 BOOL WINAPI SymAddSymbol(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR name,
01994                          DWORD64 addr, DWORD size, DWORD flags)
01995 {
01996     WCHAR       nameW[MAX_SYM_NAME];
01997 
01998     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, sizeof(nameW) / sizeof(WCHAR));
01999     return SymAddSymbolW(hProcess, BaseOfDll, nameW, addr, size, flags);
02000 }
02001 
02002 /******************************************************************
02003  *      SymAddSymbolW (DBGHELP.@)
02004  *
02005  */
02006 BOOL WINAPI SymAddSymbolW(HANDLE hProcess, ULONG64 BaseOfDll, PCWSTR name,
02007                           DWORD64 addr, DWORD size, DWORD flags)
02008 {
02009     struct module_pair  pair;
02010 
02011     TRACE("(%p %s %s %u)\n", hProcess, wine_dbgstr_w(name), wine_dbgstr_longlong(addr), size);
02012 
02013     pair.pcs = process_find_by_handle(hProcess);
02014     if (!pair.pcs) return FALSE;
02015     pair.requested = module_find_by_addr(pair.pcs, BaseOfDll, DMT_UNKNOWN);
02016     if (!module_get_debug(&pair)) return FALSE;
02017 
02018     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
02019     return FALSE;
02020 }
02021 
02022 /******************************************************************
02023  *      SymSetScopeFromAddr (DBGHELP.@)
02024  */
02025 BOOL WINAPI SymSetScopeFromAddr(HANDLE hProcess, ULONG64 addr)
02026 {
02027     struct process*     pcs;
02028 
02029     FIXME("(%p %s): stub\n", hProcess, wine_dbgstr_longlong(addr));
02030 
02031     if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
02032     return TRUE;
02033 }
02034 
02035 /******************************************************************
02036  *      SymEnumLines (DBGHELP.@)
02037  *
02038  */
02039 BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland,
02040                          PCSTR srcfile, PSYM_ENUMLINES_CALLBACK cb, PVOID user)
02041 {
02042     struct module_pair          pair;
02043     struct hash_table_iter      hti;
02044     struct symt_ht*             sym;
02045     regex_t                     re;
02046     struct line_info*           dli;
02047     void*                       ptr;
02048     SRCCODEINFO                 sci;
02049     const char*                 file;
02050 
02051     if (!cb) return FALSE;
02052     if (!(dbghelp_options & SYMOPT_LOAD_LINES)) return TRUE;
02053 
02054     pair.pcs = process_find_by_handle(hProcess);
02055     if (!pair.pcs) return FALSE;
02056     if (compiland) FIXME("Unsupported yet (filtering on compiland %s)\n", compiland);
02057     pair.requested = module_find_by_addr(pair.pcs, base, DMT_UNKNOWN);
02058     if (!module_get_debug(&pair)) return FALSE;
02059     if (!compile_file_regex(&re, srcfile)) return FALSE;
02060 
02061     sci.SizeOfStruct = sizeof(sci);
02062     sci.ModBase      = base;
02063 
02064     hash_table_iter_init(&pair.effective->ht_symbols, &hti, NULL);
02065     while ((ptr = hash_table_iter_up(&hti)))
02066     {
02067         unsigned int    i;
02068 
02069         sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
02070         if (sym->symt.tag != SymTagFunction) continue;
02071 
02072         sci.FileName[0] = '\0';
02073         for (i=0; i<vector_length(&((struct symt_function*)sym)->vlines); i++)
02074         {
02075             dli = vector_at(&((struct symt_function*)sym)->vlines, i);
02076             if (dli->is_source_file)
02077             {
02078                 file = source_get(pair.effective, dli->u.source_file);
02079                 if (!match_regexp(&re, file)) sci.FileName[0] = '\0';
02080                 else strcpy(sci.FileName, file);
02081             }
02082             else if (sci.FileName[0])
02083             {
02084                 sci.Key = dli;
02085                 sci.Obj[0] = '\0'; /* FIXME */
02086                 sci.LineNumber = dli->line_number;
02087                 sci.Address = dli->u.pc_offset;
02088                 if (!cb(&sci, user)) break;
02089             }
02090         }
02091     }
02092     regfree(&re);
02093     return TRUE;
02094 }
02095 
02096 BOOL WINAPI SymGetLineFromName(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName,
02097                 DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINE Line)
02098 {
02099     FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, ModuleName, FileName,
02100                 dwLineNumber, plDisplacement, Line);
02101     return FALSE;
02102 }
02103 
02104 BOOL WINAPI SymGetLineFromName64(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName,
02105                 DWORD dwLineNumber, PLONG lpDisplacement, PIMAGEHLP_LINE64 Line)
02106 {
02107     FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, ModuleName, FileName,
02108                 dwLineNumber, lpDisplacement, Line);
02109     return FALSE;
02110 }
02111 
02112 BOOL WINAPI SymGetLineFromNameW64(HANDLE hProcess, PCWSTR ModuleName, PCWSTR FileName,
02113                 DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINEW64 Line)
02114 {
02115     FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, debugstr_w(ModuleName), debugstr_w(FileName),
02116                 dwLineNumber, plDisplacement, Line);
02117     return FALSE;
02118 }
02119 
02120 /******************************************************************
02121  *      SymFromIndex (DBGHELP.@)
02122  *
02123  */
02124 BOOL WINAPI SymFromIndex(HANDLE hProcess, ULONG64 BaseOfDll, DWORD index, PSYMBOL_INFO symbol)
02125 {
02126     FIXME("hProcess = %p, BaseOfDll = %s, index = %d, symbol = %p\n",
02127           hProcess, wine_dbgstr_longlong(BaseOfDll), index, symbol);
02128 
02129     return FALSE;
02130 }
02131 
02132 /******************************************************************
02133  *      SymFromIndexW (DBGHELP.@)
02134  *
02135  */
02136 BOOL WINAPI SymFromIndexW(HANDLE hProcess, ULONG64 BaseOfDll, DWORD index, PSYMBOL_INFOW symbol)
02137 {
02138     FIXME("hProcess = %p, BaseOfDll = %s, index = %d, symbol = %p\n",
02139           hProcess, wine_dbgstr_longlong(BaseOfDll), index, symbol);
02140 
02141     return FALSE;
02142 }

Generated on Sun May 27 2012 04:23:25 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.