Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensymbol.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
1.7.6.1
|