1 /* 2 * File symbol.c - management of symbols (lexical tree) 3 * 4 * Copyright (C) 1993, Eric Youngdale. 5 * 2004, Eric Pouech 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #define NONAMELESSUNION 23 24 #include <stdlib.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <limits.h> 28 #include <sys/types.h> 29 #include <assert.h> 30 #ifndef DBGHELP_STATIC_LIB 31 #include "wine/debug.h" 32 #endif 33 #include "dbghelp_private.h" 34 #ifndef DBGHELP_STATIC_LIB 35 #include "winnls.h" 36 #endif 37 38 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); 39 WINE_DECLARE_DEBUG_CHANNEL(dbghelp_symt); 40 41 static const WCHAR starW[] = {'*','\0'}; 42 43 static inline int cmp_addr(ULONG64 a1, ULONG64 a2) 44 { 45 if (a1 > a2) return 1; 46 if (a1 < a2) return -1; 47 return 0; 48 } 49 50 static inline int cmp_sorttab_addr(struct module* module, int idx, ULONG64 addr) 51 { 52 ULONG64 ref; 53 symt_get_address(&module->addr_sorttab[idx]->symt, &ref); 54 return cmp_addr(ref, addr); 55 } 56 57 int __cdecl symt_cmp_addr(const void* p1, const void* p2) 58 { 59 const struct symt* sym1 = *(const struct symt* const *)p1; 60 const struct symt* sym2 = *(const struct symt* const *)p2; 61 ULONG64 a1, a2; 62 63 symt_get_address(sym1, &a1); 64 symt_get_address(sym2, &a2); 65 return cmp_addr(a1, a2); 66 } 67 68 DWORD symt_ptr2index(struct module* module, const struct symt* sym) 69 { 70 #ifdef __x86_64__ 71 const struct symt** c; 72 int len = vector_length(&module->vsymt); 73 struct hash_table_iter hti; 74 void *ptr; 75 struct symt_idx_to_ptr *idx_to_ptr; 76 /* place enough storage on the stack to represent a pointer in %p form */ 77 char ptrbuf[3 + (sizeof(void *) * 2)]; 78 79 /* make a string representation of the pointer to use as a hash key */ 80 sprintf(ptrbuf, "%p", sym); 81 hash_table_iter_init(&module->ht_symaddr, &hti, ptrbuf); 82 83 /* try to find the pointer in our ht */ 84 while ((ptr = hash_table_iter_up(&hti))) { 85 idx_to_ptr = CONTAINING_RECORD(ptr, struct symt_idx_to_ptr, hash_elt); 86 if (idx_to_ptr->sym == sym) 87 return idx_to_ptr->idx; 88 } 89 90 /* not found */ 91 /* add the symbol to our symbol vector */ 92 c = vector_add(&module->vsymt, &module->pool); 93 94 /* add an idx to ptr mapping so we can find it again by address */ 95 if ((idx_to_ptr = pool_alloc(&module->pool, sizeof(*idx_to_ptr)))) 96 { 97 idx_to_ptr->hash_elt.name = pool_strdup(&module->pool, ptrbuf); 98 idx_to_ptr->sym = sym; 99 idx_to_ptr->idx = len + 1; 100 hash_table_add(&module->ht_symaddr, &idx_to_ptr->hash_elt); 101 } 102 103 if (c) *c = sym; 104 return len + 1; 105 #else 106 return (DWORD)sym; 107 #endif 108 } 109 110 struct symt* symt_index2ptr(struct module* module, DWORD id) 111 { 112 #if defined(__x86_64__) || defined(__arm64__) 113 if (!id-- || id >= vector_length(&module->vsymt)) return NULL; 114 return *(struct symt**)vector_at(&module->vsymt, id); 115 #else 116 return (struct symt*)id; 117 #endif 118 } 119 120 static BOOL symt_grow_sorttab(struct module* module, unsigned sz) 121 { 122 struct symt_ht** new; 123 unsigned int size; 124 125 if (sz <= module->sorttab_size) return TRUE; 126 if (module->addr_sorttab) 127 { 128 size = module->sorttab_size * 2; 129 new = HeapReAlloc(GetProcessHeap(), 0, module->addr_sorttab, 130 size * sizeof(struct symt_ht*)); 131 } 132 else 133 { 134 size = 64; 135 new = HeapAlloc(GetProcessHeap(), 0, size * sizeof(struct symt_ht*)); 136 } 137 if (!new) return FALSE; 138 module->sorttab_size = size; 139 module->addr_sorttab = new; 140 return TRUE; 141 } 142 143 static void symt_add_module_ht(struct module* module, struct symt_ht* ht) 144 { 145 ULONG64 addr; 146 147 hash_table_add(&module->ht_symbols, &ht->hash_elt); 148 /* Don't store in sorttab a symbol without address, they are of 149 * no use here (e.g. constant values) 150 */ 151 if (symt_get_address(&ht->symt, &addr) && 152 symt_grow_sorttab(module, module->num_symbols + 1)) 153 { 154 module->addr_sorttab[module->num_symbols++] = ht; 155 module->sortlist_valid = FALSE; 156 } 157 } 158 159 static WCHAR* file_regex(const char* srcfile) 160 { 161 WCHAR* mask; 162 WCHAR* p; 163 164 if (!srcfile || !*srcfile) 165 { 166 if (!(p = mask = HeapAlloc(GetProcessHeap(), 0, 3 * sizeof(WCHAR)))) return NULL; 167 *p++ = '?'; 168 *p++ = '#'; 169 } 170 else 171 { 172 DWORD sz = MultiByteToWideChar(CP_ACP, 0, srcfile, -1, NULL, 0); 173 WCHAR* srcfileW; 174 175 /* FIXME: we use here the largest conversion for every char... could be optimized */ 176 p = mask = HeapAlloc(GetProcessHeap(), 0, (5 * strlen(srcfile) + 1 + sz) * sizeof(WCHAR)); 177 if (!mask) return NULL; 178 srcfileW = mask + 5 * strlen(srcfile) + 1; 179 MultiByteToWideChar(CP_ACP, 0, srcfile, -1, srcfileW, sz); 180 181 while (*srcfileW) 182 { 183 switch (*srcfileW) 184 { 185 case '\\': 186 case '/': 187 *p++ = '['; 188 *p++ = '\\'; 189 *p++ = '\\'; 190 *p++ = '/'; 191 *p++ = ']'; 192 break; 193 case '.': 194 *p++ = '?'; 195 break; 196 default: 197 *p++ = *srcfileW; 198 break; 199 } 200 srcfileW++; 201 } 202 } 203 *p = 0; 204 return mask; 205 } 206 207 struct symt_compiland* symt_new_compiland(struct module* module, 208 ULONG_PTR address, unsigned src_idx) 209 { 210 struct symt_compiland* sym; 211 212 TRACE_(dbghelp_symt)("Adding compiland symbol %s:%s\n", 213 debugstr_w(module->module.ModuleName), source_get(module, src_idx)); 214 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 215 { 216 sym->symt.tag = SymTagCompiland; 217 sym->address = address; 218 sym->source = src_idx; 219 vector_init(&sym->vchildren, sizeof(struct symt*), 32); 220 } 221 return sym; 222 } 223 224 struct symt_public* symt_new_public(struct module* module, 225 struct symt_compiland* compiland, 226 const char* name, 227 BOOL is_function, 228 ULONG_PTR address, unsigned size) 229 { 230 struct symt_public* sym; 231 struct symt** p; 232 233 TRACE_(dbghelp_symt)("Adding public symbol %s:%s @%lx\n", 234 debugstr_w(module->module.ModuleName), name, address); 235 if ((dbghelp_options & SYMOPT_AUTO_PUBLICS) && 236 symt_find_nearest(module, address) != NULL) 237 return NULL; 238 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 239 { 240 sym->symt.tag = SymTagPublicSymbol; 241 sym->hash_elt.name = pool_strdup(&module->pool, name); 242 sym->container = compiland ? &compiland->symt : NULL; 243 sym->is_function = is_function; 244 sym->address = address; 245 sym->size = size; 246 symt_add_module_ht(module, (struct symt_ht*)sym); 247 if (compiland) 248 { 249 p = vector_add(&compiland->vchildren, &module->pool); 250 *p = &sym->symt; 251 } 252 } 253 return sym; 254 } 255 256 struct symt_data* symt_new_global_variable(struct module* module, 257 struct symt_compiland* compiland, 258 const char* name, unsigned is_static, 259 struct location loc, ULONG_PTR size, 260 struct symt* type) 261 { 262 struct symt_data* sym; 263 struct symt** p; 264 DWORD64 tsz; 265 266 TRACE_(dbghelp_symt)("Adding global symbol %s:%s %d@%lx %p\n", 267 debugstr_w(module->module.ModuleName), name, loc.kind, loc.offset, type); 268 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 269 { 270 sym->symt.tag = SymTagData; 271 sym->hash_elt.name = pool_strdup(&module->pool, name); 272 sym->kind = is_static ? DataIsFileStatic : DataIsGlobal; 273 sym->container = compiland ? &compiland->symt : NULL; 274 sym->type = type; 275 sym->u.var = loc; 276 if (type && size && symt_get_info(module, type, TI_GET_LENGTH, &tsz)) 277 { 278 if (tsz != size) 279 FIXME("Size mismatch for %s.%s between type (%s) and src (%lu)\n", 280 debugstr_w(module->module.ModuleName), name, 281 wine_dbgstr_longlong(tsz), size); 282 } 283 symt_add_module_ht(module, (struct symt_ht*)sym); 284 if (compiland) 285 { 286 p = vector_add(&compiland->vchildren, &module->pool); 287 *p = &sym->symt; 288 } 289 } 290 return sym; 291 } 292 293 struct symt_function* symt_new_function(struct module* module, 294 struct symt_compiland* compiland, 295 const char* name, 296 ULONG_PTR addr, ULONG_PTR size, 297 struct symt* sig_type) 298 { 299 struct symt_function* sym; 300 struct symt** p; 301 302 TRACE_(dbghelp_symt)("Adding global function %s:%s @%lx-%lx\n", 303 debugstr_w(module->module.ModuleName), name, addr, addr + size - 1); 304 305 assert(!sig_type || sig_type->tag == SymTagFunctionType); 306 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 307 { 308 sym->symt.tag = SymTagFunction; 309 sym->hash_elt.name = pool_strdup(&module->pool, name); 310 sym->container = &compiland->symt; 311 sym->address = addr; 312 sym->type = sig_type; 313 sym->size = size; 314 vector_init(&sym->vlines, sizeof(struct line_info), 64); 315 vector_init(&sym->vchildren, sizeof(struct symt*), 8); 316 symt_add_module_ht(module, (struct symt_ht*)sym); 317 if (compiland) 318 { 319 p = vector_add(&compiland->vchildren, &module->pool); 320 *p = &sym->symt; 321 } 322 } 323 return sym; 324 } 325 326 void symt_add_func_line(struct module* module, struct symt_function* func, 327 unsigned source_idx, int line_num, ULONG_PTR offset) 328 { 329 struct line_info* dli; 330 BOOL last_matches = FALSE; 331 int i; 332 333 if (func == NULL || !(dbghelp_options & SYMOPT_LOAD_LINES)) return; 334 335 TRACE_(dbghelp_symt)("(%p)%s:%lx %s:%u\n", 336 func, func->hash_elt.name, offset, 337 source_get(module, source_idx), line_num); 338 339 assert(func->symt.tag == SymTagFunction); 340 341 for (i=vector_length(&func->vlines)-1; i>=0; i--) 342 { 343 dli = vector_at(&func->vlines, i); 344 if (dli->is_source_file) 345 { 346 last_matches = (source_idx == dli->u.source_file); 347 break; 348 } 349 } 350 351 if (!last_matches) 352 { 353 /* we shouldn't have line changes on first line of function */ 354 dli = vector_add(&func->vlines, &module->pool); 355 dli->is_source_file = 1; 356 dli->is_first = dli->is_last = 0; 357 dli->line_number = 0; 358 dli->u.source_file = source_idx; 359 } 360 dli = vector_add(&func->vlines, &module->pool); 361 dli->is_source_file = 0; 362 dli->is_first = dli->is_last = 0; 363 dli->line_number = line_num; 364 dli->u.pc_offset = func->address + offset; 365 } 366 367 /****************************************************************** 368 * symt_add_func_local 369 * 370 * Adds a new local/parameter to a given function: 371 * In any cases, dt tells whether it's a local variable or a parameter 372 * If regno it's not 0: 373 * - then variable is stored in a register 374 * - otherwise, value is referenced by register + offset 375 * Otherwise, the variable is stored on the stack: 376 * - offset is then the offset from the frame register 377 */ 378 struct symt_data* symt_add_func_local(struct module* module, 379 struct symt_function* func, 380 enum DataKind dt, 381 const struct location* loc, 382 struct symt_block* block, 383 struct symt* type, const char* name) 384 { 385 struct symt_data* locsym; 386 struct symt** p; 387 388 TRACE_(dbghelp_symt)("Adding local symbol (%s:%s): %s %p\n", 389 debugstr_w(module->module.ModuleName), func->hash_elt.name, 390 name, type); 391 392 assert(func); 393 assert(func->symt.tag == SymTagFunction); 394 assert(dt == DataIsParam || dt == DataIsLocal); 395 396 locsym = pool_alloc(&module->pool, sizeof(*locsym)); 397 locsym->symt.tag = SymTagData; 398 locsym->hash_elt.name = pool_strdup(&module->pool, name); 399 locsym->hash_elt.next = NULL; 400 locsym->kind = dt; 401 locsym->container = block ? &block->symt : &func->symt; 402 locsym->type = type; 403 locsym->u.var = *loc; 404 if (block) 405 p = vector_add(&block->vchildren, &module->pool); 406 else 407 p = vector_add(&func->vchildren, &module->pool); 408 *p = &locsym->symt; 409 return locsym; 410 } 411 412 413 struct symt_block* symt_open_func_block(struct module* module, 414 struct symt_function* func, 415 struct symt_block* parent_block, 416 unsigned pc, unsigned len) 417 { 418 struct symt_block* block; 419 struct symt** p; 420 421 assert(func); 422 assert(func->symt.tag == SymTagFunction); 423 424 assert(!parent_block || parent_block->symt.tag == SymTagBlock); 425 block = pool_alloc(&module->pool, sizeof(*block)); 426 block->symt.tag = SymTagBlock; 427 block->address = func->address + pc; 428 block->size = len; 429 block->container = parent_block ? &parent_block->symt : &func->symt; 430 vector_init(&block->vchildren, sizeof(struct symt*), 4); 431 if (parent_block) 432 p = vector_add(&parent_block->vchildren, &module->pool); 433 else 434 p = vector_add(&func->vchildren, &module->pool); 435 *p = &block->symt; 436 437 return block; 438 } 439 440 struct symt_block* symt_close_func_block(struct module* module, 441 const struct symt_function* func, 442 struct symt_block* block, unsigned pc) 443 { 444 assert(func); 445 assert(func->symt.tag == SymTagFunction); 446 447 if (pc) block->size = func->address + pc - block->address; 448 return (block->container->tag == SymTagBlock) ? 449 CONTAINING_RECORD(block->container, struct symt_block, symt) : NULL; 450 } 451 452 struct symt_hierarchy_point* symt_add_function_point(struct module* module, 453 struct symt_function* func, 454 enum SymTagEnum point, 455 const struct location* loc, 456 const char* name) 457 { 458 struct symt_hierarchy_point*sym; 459 struct symt** p; 460 461 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 462 { 463 sym->symt.tag = point; 464 sym->parent = &func->symt; 465 sym->loc = *loc; 466 sym->hash_elt.name = name ? pool_strdup(&module->pool, name) : NULL; 467 p = vector_add(&func->vchildren, &module->pool); 468 *p = &sym->symt; 469 } 470 return sym; 471 } 472 473 BOOL symt_normalize_function(struct module* module, const struct symt_function* func) 474 { 475 unsigned len; 476 struct line_info* dli; 477 478 assert(func); 479 /* We aren't adding any more locals or line numbers to this function. 480 * Free any spare memory that we might have allocated. 481 */ 482 assert(func->symt.tag == SymTagFunction); 483 484 /* EPP vector_pool_normalize(&func->vlines, &module->pool); */ 485 /* EPP vector_pool_normalize(&func->vchildren, &module->pool); */ 486 487 len = vector_length(&func->vlines); 488 if (len--) 489 { 490 dli = vector_at(&func->vlines, 0); dli->is_first = 1; 491 dli = vector_at(&func->vlines, len); dli->is_last = 1; 492 } 493 return TRUE; 494 } 495 496 struct symt_thunk* symt_new_thunk(struct module* module, 497 struct symt_compiland* compiland, 498 const char* name, THUNK_ORDINAL ord, 499 ULONG_PTR addr, ULONG_PTR size) 500 { 501 struct symt_thunk* sym; 502 503 TRACE_(dbghelp_symt)("Adding global thunk %s:%s @%lx-%lx\n", 504 debugstr_w(module->module.ModuleName), name, addr, addr + size - 1); 505 506 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 507 { 508 sym->symt.tag = SymTagThunk; 509 sym->hash_elt.name = pool_strdup(&module->pool, name); 510 sym->container = &compiland->symt; 511 sym->address = addr; 512 sym->size = size; 513 sym->ordinal = ord; 514 symt_add_module_ht(module, (struct symt_ht*)sym); 515 if (compiland) 516 { 517 struct symt** p; 518 p = vector_add(&compiland->vchildren, &module->pool); 519 *p = &sym->symt; 520 } 521 } 522 return sym; 523 } 524 525 struct symt_data* symt_new_constant(struct module* module, 526 struct symt_compiland* compiland, 527 const char* name, struct symt* type, 528 const VARIANT* v) 529 { 530 struct symt_data* sym; 531 532 TRACE_(dbghelp_symt)("Adding constant value %s:%s\n", 533 debugstr_w(module->module.ModuleName), name); 534 535 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 536 { 537 sym->symt.tag = SymTagData; 538 sym->hash_elt.name = pool_strdup(&module->pool, name); 539 sym->kind = DataIsConstant; 540 sym->container = compiland ? &compiland->symt : NULL; 541 sym->type = type; 542 sym->u.value = *v; 543 symt_add_module_ht(module, (struct symt_ht*)sym); 544 if (compiland) 545 { 546 struct symt** p; 547 p = vector_add(&compiland->vchildren, &module->pool); 548 *p = &sym->symt; 549 } 550 } 551 return sym; 552 } 553 554 struct symt_hierarchy_point* symt_new_label(struct module* module, 555 struct symt_compiland* compiland, 556 const char* name, ULONG_PTR address) 557 { 558 struct symt_hierarchy_point* sym; 559 560 TRACE_(dbghelp_symt)("Adding global label value %s:%s\n", 561 debugstr_w(module->module.ModuleName), name); 562 563 if ((sym = pool_alloc(&module->pool, sizeof(*sym)))) 564 { 565 sym->symt.tag = SymTagLabel; 566 sym->hash_elt.name = pool_strdup(&module->pool, name); 567 sym->loc.kind = loc_absolute; 568 sym->loc.offset = address; 569 sym->parent = compiland ? &compiland->symt : NULL; 570 symt_add_module_ht(module, (struct symt_ht*)sym); 571 if (compiland) 572 { 573 struct symt** p; 574 p = vector_add(&compiland->vchildren, &module->pool); 575 *p = &sym->symt; 576 } 577 } 578 return sym; 579 } 580 581 /* expect sym_info->MaxNameLen to be set before being called */ 582 static void symt_fill_sym_info(struct module_pair* pair, 583 const struct symt_function* func, 584 const struct symt* sym, SYMBOL_INFO* sym_info) 585 { 586 const char* name; 587 DWORD64 size; 588 589 if (!symt_get_info(pair->effective, sym, TI_GET_TYPE, &sym_info->TypeIndex)) 590 sym_info->TypeIndex = 0; 591 sym_info->Index = symt_ptr2index(pair->effective, sym); 592 sym_info->Reserved[0] = sym_info->Reserved[1] = 0; 593 if (!symt_get_info(pair->effective, sym, TI_GET_LENGTH, &size) && 594 (!sym_info->TypeIndex || 595 !symt_get_info(pair->effective, symt_index2ptr(pair->effective, sym_info->TypeIndex), 596 TI_GET_LENGTH, &size))) 597 size = 0; 598 sym_info->Size = (DWORD)size; 599 sym_info->ModBase = pair->requested->module.BaseOfImage; 600 sym_info->Flags = 0; 601 sym_info->Value = 0; 602 603 switch (sym->tag) 604 { 605 case SymTagData: 606 { 607 const struct symt_data* data = (const struct symt_data*)sym; 608 switch (data->kind) 609 { 610 case DataIsParam: 611 sym_info->Flags |= SYMFLAG_PARAMETER; 612 /* fall through */ 613 case DataIsLocal: 614 sym_info->Flags |= SYMFLAG_LOCAL; 615 { 616 struct location loc = data->u.var; 617 618 if (loc.kind >= loc_user) 619 { 620 unsigned i; 621 struct module_format* modfmt; 622 623 for (i = 0; i < DFI_LAST; i++) 624 { 625 modfmt = pair->effective->format_info[i]; 626 if (modfmt && modfmt->loc_compute) 627 { 628 modfmt->loc_compute(pair->pcs, modfmt, func, &loc); 629 break; 630 } 631 } 632 } 633 switch (loc.kind) 634 { 635 case loc_error: 636 /* for now we report error cases as a negative register number */ 637 /* fall through */ 638 case loc_register: 639 sym_info->Flags |= SYMFLAG_REGISTER; 640 sym_info->Register = loc.reg; 641 sym_info->Address = 0; 642 break; 643 case loc_regrel: 644 sym_info->Flags |= SYMFLAG_REGREL; 645 sym_info->Register = loc.reg; 646 if (loc.reg == CV_REG_NONE || (int)loc.reg < 0 /* error */) 647 FIXME("suspicious register value %x\n", loc.reg); 648 sym_info->Address = loc.offset; 649 break; 650 case loc_absolute: 651 sym_info->Flags |= SYMFLAG_VALUEPRESENT; 652 sym_info->Value = loc.offset; 653 break; 654 default: 655 FIXME("Shouldn't happen (kind=%d), debug reader backend is broken\n", loc.kind); 656 assert(0); 657 } 658 } 659 break; 660 case DataIsGlobal: 661 case DataIsFileStatic: 662 switch (data->u.var.kind) 663 { 664 case loc_tlsrel: 665 sym_info->Flags |= SYMFLAG_TLSREL; 666 /* fall through */ 667 case loc_absolute: 668 symt_get_address(sym, &sym_info->Address); 669 sym_info->Register = 0; 670 break; 671 default: 672 FIXME("Shouldn't happen (kind=%d), debug reader backend is broken\n", data->u.var.kind); 673 assert(0); 674 } 675 break; 676 case DataIsConstant: 677 sym_info->Flags |= SYMFLAG_VALUEPRESENT; 678 switch (data->u.value.n1.n2.vt) 679 { 680 case VT_I4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.lVal; break; 681 case VT_I2: sym_info->Value = (ULONG)(LONG_PTR)data->u.value.n1.n2.n3.iVal; break; 682 case VT_I1: sym_info->Value = (ULONG)(LONG_PTR)data->u.value.n1.n2.n3.cVal; break; 683 case VT_UI4: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.ulVal; break; 684 case VT_UI2: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.uiVal; break; 685 case VT_UI1: sym_info->Value = (ULONG)data->u.value.n1.n2.n3.bVal; break; 686 case VT_I1 | VT_BYREF: sym_info->Value = (ULONG64)(DWORD_PTR)data->u.value.n1.n2.n3.byref; break; 687 case VT_EMPTY: sym_info->Value = 0; break; 688 default: 689 FIXME("Unsupported variant type (%u)\n", data->u.value.n1.n2.vt); 690 sym_info->Value = 0; 691 break; 692 } 693 break; 694 default: 695 FIXME("Unhandled kind (%u) in sym data\n", data->kind); 696 } 697 } 698 break; 699 case SymTagPublicSymbol: 700 { 701 const struct symt_public* pub = (const struct symt_public*)sym; 702 if (pub->is_function) 703 sym_info->Flags |= SYMFLAG_PUBLIC_CODE; 704 else 705 sym_info->Flags |= SYMFLAG_EXPORT; 706 symt_get_address(sym, &sym_info->Address); 707 } 708 break; 709 case SymTagFunction: 710 symt_get_address(sym, &sym_info->Address); 711 break; 712 case SymTagThunk: 713 sym_info->Flags |= SYMFLAG_THUNK; 714 symt_get_address(sym, &sym_info->Address); 715 break; 716 default: 717 symt_get_address(sym, &sym_info->Address); 718 sym_info->Register = 0; 719 break; 720 } 721 sym_info->Scope = 0; /* FIXME */ 722 sym_info->Tag = sym->tag; 723 name = symt_get_name(sym); 724 if (sym_info->MaxNameLen) 725 { 726 if (sym->tag != SymTagPublicSymbol || !(dbghelp_options & SYMOPT_UNDNAME) || 727 ((sym_info->NameLen = UnDecorateSymbolName(name, sym_info->Name, 728 sym_info->MaxNameLen, UNDNAME_NAME_ONLY)) == 0)) 729 { 730 sym_info->NameLen = min(strlen(name), sym_info->MaxNameLen - 1); 731 memcpy(sym_info->Name, name, sym_info->NameLen); 732 sym_info->Name[sym_info->NameLen] = '\0'; 733 } 734 } 735 TRACE_(dbghelp_symt)("%p => %s %u %s\n", 736 sym, sym_info->Name, sym_info->Size, 737 wine_dbgstr_longlong(sym_info->Address)); 738 } 739 740 struct sym_enum 741 { 742 PSYM_ENUMERATESYMBOLS_CALLBACK cb; 743 PVOID user; 744 SYMBOL_INFO* sym_info; 745 DWORD index; 746 DWORD tag; 747 DWORD64 addr; 748 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; 749 }; 750 751 static BOOL send_symbol(const struct sym_enum* se, struct module_pair* pair, 752 const struct symt_function* func, const struct symt* sym) 753 { 754 symt_fill_sym_info(pair, func, sym, se->sym_info); 755 if (se->index && se->sym_info->Index != se->index) return FALSE; 756 if (se->tag && se->sym_info->Tag != se->tag) return FALSE; 757 if (se->addr && !(se->addr >= se->sym_info->Address && se->addr < se->sym_info->Address + se->sym_info->Size)) return FALSE; 758 return !se->cb(se->sym_info, se->sym_info->Size, se->user); 759 } 760 761 static BOOL symt_enum_module(struct module_pair* pair, const WCHAR* match, 762 const struct sym_enum* se) 763 { 764 void* ptr; 765 struct symt_ht* sym = NULL; 766 struct hash_table_iter hti; 767 WCHAR* nameW; 768 BOOL ret; 769 770 hash_table_iter_init(&pair->effective->ht_symbols, &hti, NULL); 771 while ((ptr = hash_table_iter_up(&hti))) 772 { 773 sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt); 774 nameW = symt_get_nameW(&sym->symt); 775 ret = SymMatchStringW(nameW, match, FALSE); 776 HeapFree(GetProcessHeap(), 0, nameW); 777 if (ret) 778 { 779 se->sym_info->SizeOfStruct = sizeof(SYMBOL_INFO); 780 se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO); 781 if (send_symbol(se, pair, NULL, &sym->symt)) return TRUE; 782 } 783 } 784 return FALSE; 785 } 786 787 static inline unsigned where_to_insert(struct module* module, unsigned high, const struct symt_ht* elt) 788 { 789 unsigned low = 0, mid = high / 2; 790 ULONG64 addr; 791 792 if (!high) return 0; 793 symt_get_address(&elt->symt, &addr); 794 do 795 { 796 switch (cmp_sorttab_addr(module, mid, addr)) 797 { 798 case 0: return mid; 799 case -1: low = mid + 1; break; 800 case 1: high = mid; break; 801 } 802 mid = low + (high - low) / 2; 803 } while (low < high); 804 return mid; 805 } 806 807 /*********************************************************************** 808 * resort_symbols 809 * 810 * Rebuild sorted list of symbols for a module. 811 */ 812 static BOOL resort_symbols(struct module* module) 813 { 814 int delta; 815 816 if (!(module->module.NumSyms = module->num_symbols)) 817 return FALSE; 818 819 /* we know that set from 0 up to num_sorttab is already sorted 820 * so sort the remaining (new) symbols, and merge the two sets 821 * (unless the first set is empty) 822 */ 823 delta = module->num_symbols - module->num_sorttab; 824 qsort(&module->addr_sorttab[module->num_sorttab], delta, sizeof(struct symt_ht*), symt_cmp_addr); 825 if (module->num_sorttab) 826 { 827 int i, ins_idx = module->num_sorttab, prev_ins_idx; 828 static struct symt_ht** tmp; 829 static unsigned num_tmp; 830 831 if (num_tmp < delta) 832 { 833 static struct symt_ht** new; 834 if (tmp) 835 new = HeapReAlloc(GetProcessHeap(), 0, tmp, delta * sizeof(struct symt_ht*)); 836 else 837 new = HeapAlloc(GetProcessHeap(), 0, delta * sizeof(struct symt_ht*)); 838 if (!new) 839 { 840 module->num_sorttab = 0; 841 return resort_symbols(module); 842 } 843 tmp = new; 844 num_tmp = delta; 845 } 846 memcpy(tmp, &module->addr_sorttab[module->num_sorttab], delta * sizeof(struct symt_ht*)); 847 qsort(tmp, delta, sizeof(struct symt_ht*), symt_cmp_addr); 848 849 for (i = delta - 1; i >= 0; i--) 850 { 851 prev_ins_idx = ins_idx; 852 ins_idx = where_to_insert(module, ins_idx, tmp[i]); 853 memmove(&module->addr_sorttab[ins_idx + i + 1], 854 &module->addr_sorttab[ins_idx], 855 (prev_ins_idx - ins_idx) * sizeof(struct symt_ht*)); 856 module->addr_sorttab[ins_idx + i] = tmp[i]; 857 } 858 } 859 module->num_sorttab = module->num_symbols; 860 return module->sortlist_valid = TRUE; 861 } 862 863 static void symt_get_length(struct module* module, const struct symt* symt, ULONG64* size) 864 { 865 DWORD type_index; 866 867 if (symt_get_info(module, symt, TI_GET_LENGTH, size) && *size) 868 return; 869 870 if (symt_get_info(module, symt, TI_GET_TYPE, &type_index) && 871 symt_get_info(module, symt_index2ptr(module, type_index), TI_GET_LENGTH, size)) return; 872 *size = 0x1000; /* arbitrary value */ 873 } 874 875 /* needed by symt_find_nearest */ 876 static int symt_get_best_at(struct module* module, int idx_sorttab) 877 { 878 ULONG64 ref_addr; 879 int idx_sorttab_orig = idx_sorttab; 880 if (module->addr_sorttab[idx_sorttab]->symt.tag == SymTagPublicSymbol) 881 { 882 symt_get_address(&module->addr_sorttab[idx_sorttab]->symt, &ref_addr); 883 while (idx_sorttab > 0 && 884 module->addr_sorttab[idx_sorttab]->symt.tag == SymTagPublicSymbol && 885 !cmp_sorttab_addr(module, idx_sorttab - 1, ref_addr)) 886 idx_sorttab--; 887 if (module->addr_sorttab[idx_sorttab]->symt.tag == SymTagPublicSymbol) 888 { 889 idx_sorttab = idx_sorttab_orig; 890 while (idx_sorttab < module->num_sorttab - 1 && 891 module->addr_sorttab[idx_sorttab]->symt.tag == SymTagPublicSymbol && 892 !cmp_sorttab_addr(module, idx_sorttab + 1, ref_addr)) 893 idx_sorttab++; 894 } 895 /* if no better symbol was found restore the original */ 896 if (module->addr_sorttab[idx_sorttab]->symt.tag == SymTagPublicSymbol) 897 idx_sorttab = idx_sorttab_orig; 898 } 899 return idx_sorttab; 900 } 901 902 /* assume addr is in module */ 903 struct symt_ht* symt_find_nearest(struct module* module, DWORD_PTR addr) 904 { 905 int mid, high, low; 906 ULONG64 ref_addr, ref_size; 907 908 if (!module->sortlist_valid || !module->addr_sorttab) 909 { 910 if (!resort_symbols(module)) return NULL; 911 } 912 913 /* 914 * Binary search to find closest symbol. 915 */ 916 low = 0; 917 high = module->num_sorttab; 918 919 symt_get_address(&module->addr_sorttab[0]->symt, &ref_addr); 920 if (addr <= ref_addr) 921 { 922 low = symt_get_best_at(module, 0); 923 return module->addr_sorttab[low]; 924 } 925 926 if (high) 927 { 928 symt_get_address(&module->addr_sorttab[high - 1]->symt, &ref_addr); 929 symt_get_length(module, &module->addr_sorttab[high - 1]->symt, &ref_size); 930 if (addr >= ref_addr + ref_size) return NULL; 931 } 932 933 while (high > low + 1) 934 { 935 mid = (high + low) / 2; 936 if (cmp_sorttab_addr(module, mid, addr) < 0) 937 low = mid; 938 else 939 high = mid; 940 } 941 if (low != high && high != module->num_sorttab && 942 cmp_sorttab_addr(module, high, addr) <= 0) 943 low = high; 944 945 /* If found symbol is a public symbol, check if there are any other entries that 946 * might also have the same address, but would get better information 947 */ 948 low = symt_get_best_at(module, low); 949 950 return module->addr_sorttab[low]; 951 } 952 953 static BOOL symt_enum_locals_helper(struct module_pair* pair, 954 const WCHAR* match, const struct sym_enum* se, 955 struct symt_function* func, const struct vector* v) 956 { 957 struct symt* lsym = NULL; 958 DWORD pc = pair->pcs->ctx_frame.InstructionOffset; 959 unsigned int i; 960 WCHAR* nameW; 961 BOOL ret; 962 963 for (i=0; i<vector_length(v); i++) 964 { 965 lsym = *(struct symt**)vector_at(v, i); 966 switch (lsym->tag) 967 { 968 case SymTagBlock: 969 { 970 struct symt_block* block = (struct symt_block*)lsym; 971 if (pc < block->address || block->address + block->size <= pc) 972 continue; 973 if (!symt_enum_locals_helper(pair, match, se, func, &block->vchildren)) 974 return FALSE; 975 } 976 break; 977 case SymTagData: 978 nameW = symt_get_nameW(lsym); 979 ret = SymMatchStringW(nameW, match, 980 !(dbghelp_options & SYMOPT_CASE_INSENSITIVE)); 981 HeapFree(GetProcessHeap(), 0, nameW); 982 if (ret) 983 { 984 if (send_symbol(se, pair, func, lsym)) return FALSE; 985 } 986 break; 987 case SymTagLabel: 988 case SymTagFuncDebugStart: 989 case SymTagFuncDebugEnd: 990 case SymTagCustom: 991 break; 992 default: 993 FIXME("Unknown type: %u (%x)\n", lsym->tag, lsym->tag); 994 assert(0); 995 } 996 } 997 return TRUE; 998 } 999 1000 static BOOL symt_enum_locals(struct process* pcs, const WCHAR* mask, 1001 const struct sym_enum* se) 1002 { 1003 struct module_pair pair; 1004 struct symt_ht* sym; 1005 DWORD_PTR pc = pcs->ctx_frame.InstructionOffset; 1006 1007 se->sym_info->SizeOfStruct = sizeof(*se->sym_info); 1008 se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO); 1009 1010 pair.pcs = pcs; 1011 pair.requested = module_find_by_addr(pair.pcs, pc, DMT_UNKNOWN); 1012 if (!module_get_debug(&pair)) return FALSE; 1013 if ((sym = symt_find_nearest(pair.effective, pc)) == NULL) return FALSE; 1014 1015 if (sym->symt.tag == SymTagFunction) 1016 { 1017 return symt_enum_locals_helper(&pair, mask ? mask : starW, se, (struct symt_function*)sym, 1018 &((struct symt_function*)sym)->vchildren); 1019 } 1020 return FALSE; 1021 } 1022 1023 /****************************************************************** 1024 * copy_symbolW 1025 * 1026 * Helper for transforming an ANSI symbol info into a UNICODE one. 1027 * Assume that MaxNameLen is the same for both version (A & W). 1028 */ 1029 void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si) 1030 { 1031 siw->SizeOfStruct = si->SizeOfStruct; 1032 siw->TypeIndex = si->TypeIndex; 1033 siw->Reserved[0] = si->Reserved[0]; 1034 siw->Reserved[1] = si->Reserved[1]; 1035 siw->Index = si->Index; 1036 siw->Size = si->Size; 1037 siw->ModBase = si->ModBase; 1038 siw->Flags = si->Flags; 1039 siw->Value = si->Value; 1040 siw->Address = si->Address; 1041 siw->Register = si->Register; 1042 siw->Scope = si->Scope; 1043 siw->Tag = si->Tag; 1044 siw->NameLen = si->NameLen; 1045 siw->MaxNameLen = si->MaxNameLen; 1046 MultiByteToWideChar(CP_ACP, 0, si->Name, -1, siw->Name, siw->MaxNameLen); 1047 } 1048 1049 /****************************************************************** 1050 * sym_enum 1051 * 1052 * Core routine for most of the enumeration of symbols 1053 */ 1054 static BOOL sym_enum(HANDLE hProcess, ULONG64 BaseOfDll, PCWSTR Mask, 1055 const struct sym_enum* se) 1056 { 1057 struct module_pair pair; 1058 const WCHAR* bang; 1059 WCHAR* mod; 1060 1061 pair.pcs = process_find_by_handle(hProcess); 1062 if (!pair.pcs) return FALSE; 1063 if (BaseOfDll == 0) 1064 { 1065 /* do local variables ? */ 1066 if (!Mask || !(bang = wcschr(Mask, '!'))) 1067 return symt_enum_locals(pair.pcs, Mask, se); 1068 1069 if (bang == Mask) return FALSE; 1070 1071 mod = HeapAlloc(GetProcessHeap(), 0, (bang - Mask + 1) * sizeof(WCHAR)); 1072 if (!mod) return FALSE; 1073 memcpy(mod, Mask, (bang - Mask) * sizeof(WCHAR)); 1074 mod[bang - Mask] = 0; 1075 1076 for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next) 1077 { 1078 if (pair.requested->type == DMT_PE && module_get_debug(&pair)) 1079 { 1080 if (SymMatchStringW(pair.requested->module.ModuleName, mod, FALSE) && 1081 symt_enum_module(&pair, bang + 1, se)) 1082 break; 1083 } 1084 } 1085 /* not found in PE modules, retry on the ELF ones 1086 */ 1087 if (!pair.requested && dbghelp_opt_native) 1088 { 1089 for (pair.requested = pair.pcs->lmodules; pair.requested; pair.requested = pair.requested->next) 1090 { 1091 if ((pair.requested->type == DMT_ELF || pair.requested->type == DMT_MACHO) && 1092 !module_get_containee(pair.pcs, pair.requested) && 1093 module_get_debug(&pair)) 1094 { 1095 if (SymMatchStringW(pair.requested->module.ModuleName, mod, FALSE) && 1096 symt_enum_module(&pair, bang + 1, se)) 1097 break; 1098 } 1099 } 1100 } 1101 HeapFree(GetProcessHeap(), 0, mod); 1102 return TRUE; 1103 } 1104 pair.requested = module_find_by_addr(pair.pcs, BaseOfDll, DMT_UNKNOWN); 1105 if (!module_get_debug(&pair)) 1106 return FALSE; 1107 1108 /* we always ignore module name from Mask when BaseOfDll is defined */ 1109 if (Mask && (bang = wcschr(Mask, '!'))) 1110 { 1111 if (bang == Mask) return FALSE; 1112 Mask = bang + 1; 1113 } 1114 1115 symt_enum_module(&pair, Mask ? Mask : starW, se); 1116 1117 return TRUE; 1118 } 1119 1120 static inline BOOL doSymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCWSTR Mask, 1121 PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, 1122 PVOID UserContext) 1123 { 1124 struct sym_enum se; 1125 1126 se.cb = EnumSymbolsCallback; 1127 se.user = UserContext; 1128 se.index = 0; 1129 se.tag = 0; 1130 se.addr = 0; 1131 se.sym_info = (PSYMBOL_INFO)se.buffer; 1132 1133 return sym_enum(hProcess, BaseOfDll, Mask, &se); 1134 } 1135 1136 /****************************************************************** 1137 * SymEnumSymbols (DBGHELP.@) 1138 * 1139 * cases BaseOfDll = 0 1140 * !foo fails always (despite what MSDN states) 1141 * RE1!RE2 looks up all modules matching RE1, and in all these modules, lookup RE2 1142 * no ! in Mask, lookup in local Context 1143 * cases BaseOfDll != 0 1144 * !foo fails always (despite what MSDN states) 1145 * RE1!RE2 gets RE2 from BaseOfDll (whatever RE1 is) 1146 */ 1147 BOOL WINAPI SymEnumSymbols(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR Mask, 1148 PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, 1149 PVOID UserContext) 1150 { 1151 BOOL ret; 1152 PWSTR maskW = NULL; 1153 1154 TRACE("(%p %s %s %p %p)\n", 1155 hProcess, wine_dbgstr_longlong(BaseOfDll), debugstr_a(Mask), 1156 EnumSymbolsCallback, UserContext); 1157 1158 if (Mask) 1159 { 1160 DWORD sz = MultiByteToWideChar(CP_ACP, 0, Mask, -1, NULL, 0); 1161 if (!(maskW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 1162 return FALSE; 1163 MultiByteToWideChar(CP_ACP, 0, Mask, -1, maskW, sz); 1164 } 1165 ret = doSymEnumSymbols(hProcess, BaseOfDll, maskW, EnumSymbolsCallback, UserContext); 1166 HeapFree(GetProcessHeap(), 0, maskW); 1167 return ret; 1168 } 1169 1170 struct sym_enumW 1171 { 1172 PSYM_ENUMERATESYMBOLS_CALLBACKW cb; 1173 void* ctx; 1174 PSYMBOL_INFOW sym_info; 1175 char buffer[sizeof(SYMBOL_INFOW) + MAX_SYM_NAME]; 1176 1177 }; 1178 1179 static BOOL CALLBACK sym_enumW(PSYMBOL_INFO si, ULONG size, PVOID ctx) 1180 { 1181 struct sym_enumW* sew = ctx; 1182 1183 copy_symbolW(sew->sym_info, si); 1184 1185 return (sew->cb)(sew->sym_info, size, sew->ctx); 1186 } 1187 1188 /****************************************************************** 1189 * SymEnumSymbolsW (DBGHELP.@) 1190 * 1191 */ 1192 BOOL WINAPI SymEnumSymbolsW(HANDLE hProcess, ULONG64 BaseOfDll, PCWSTR Mask, 1193 PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, 1194 PVOID UserContext) 1195 { 1196 struct sym_enumW sew; 1197 1198 sew.ctx = UserContext; 1199 sew.cb = EnumSymbolsCallback; 1200 sew.sym_info = (PSYMBOL_INFOW)sew.buffer; 1201 1202 return doSymEnumSymbols(hProcess, BaseOfDll, Mask, sym_enumW, &sew); 1203 } 1204 1205 struct sym_enumerate 1206 { 1207 void* ctx; 1208 PSYM_ENUMSYMBOLS_CALLBACK cb; 1209 }; 1210 1211 static BOOL CALLBACK sym_enumerate_cb(PSYMBOL_INFO syminfo, ULONG size, void* ctx) 1212 { 1213 struct sym_enumerate* se = ctx; 1214 return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx); 1215 } 1216 1217 /*********************************************************************** 1218 * SymEnumerateSymbols (DBGHELP.@) 1219 */ 1220 BOOL WINAPI SymEnumerateSymbols(HANDLE hProcess, DWORD BaseOfDll, 1221 PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, 1222 PVOID UserContext) 1223 { 1224 struct sym_enumerate se; 1225 1226 se.ctx = UserContext; 1227 se.cb = EnumSymbolsCallback; 1228 1229 return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb, &se); 1230 } 1231 1232 struct sym_enumerate64 1233 { 1234 void* ctx; 1235 PSYM_ENUMSYMBOLS_CALLBACK64 cb; 1236 }; 1237 1238 static BOOL CALLBACK sym_enumerate_cb64(PSYMBOL_INFO syminfo, ULONG size, void* ctx) 1239 { 1240 struct sym_enumerate64* se = ctx; 1241 return (se->cb)(syminfo->Name, syminfo->Address, syminfo->Size, se->ctx); 1242 } 1243 1244 /*********************************************************************** 1245 * SymEnumerateSymbols64 (DBGHELP.@) 1246 */ 1247 BOOL WINAPI SymEnumerateSymbols64(HANDLE hProcess, DWORD64 BaseOfDll, 1248 PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback, 1249 PVOID UserContext) 1250 { 1251 struct sym_enumerate64 se; 1252 1253 se.ctx = UserContext; 1254 se.cb = EnumSymbolsCallback; 1255 1256 return SymEnumSymbols(hProcess, BaseOfDll, NULL, sym_enumerate_cb64, &se); 1257 } 1258 1259 /****************************************************************** 1260 * SymFromAddr (DBGHELP.@) 1261 * 1262 */ 1263 BOOL WINAPI SymFromAddr(HANDLE hProcess, DWORD64 Address, 1264 DWORD64* Displacement, PSYMBOL_INFO Symbol) 1265 { 1266 struct module_pair pair; 1267 struct symt_ht* sym; 1268 1269 pair.pcs = process_find_by_handle(hProcess); 1270 if (!pair.pcs) return FALSE; 1271 pair.requested = module_find_by_addr(pair.pcs, Address, DMT_UNKNOWN); 1272 if (!module_get_debug(&pair)) return FALSE; 1273 if ((sym = symt_find_nearest(pair.effective, Address)) == NULL) return FALSE; 1274 1275 symt_fill_sym_info(&pair, NULL, &sym->symt, Symbol); 1276 if (Displacement) 1277 *Displacement = (Address >= Symbol->Address) ? (Address - Symbol->Address) : (DWORD64)-1; 1278 return TRUE; 1279 } 1280 1281 /****************************************************************** 1282 * SymFromAddrW (DBGHELP.@) 1283 * 1284 */ 1285 BOOL WINAPI SymFromAddrW(HANDLE hProcess, DWORD64 Address, 1286 DWORD64* Displacement, PSYMBOL_INFOW Symbol) 1287 { 1288 PSYMBOL_INFO si; 1289 unsigned len; 1290 BOOL ret; 1291 1292 len = sizeof(*si) + Symbol->MaxNameLen * sizeof(WCHAR); 1293 si = HeapAlloc(GetProcessHeap(), 0, len); 1294 if (!si) return FALSE; 1295 1296 si->SizeOfStruct = sizeof(*si); 1297 si->MaxNameLen = Symbol->MaxNameLen; 1298 if ((ret = SymFromAddr(hProcess, Address, Displacement, si))) 1299 { 1300 copy_symbolW(Symbol, si); 1301 } 1302 HeapFree(GetProcessHeap(), 0, si); 1303 return ret; 1304 } 1305 1306 /****************************************************************** 1307 * SymGetSymFromAddr (DBGHELP.@) 1308 * 1309 */ 1310 BOOL WINAPI SymGetSymFromAddr(HANDLE hProcess, DWORD Address, 1311 PDWORD Displacement, PIMAGEHLP_SYMBOL Symbol) 1312 { 1313 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; 1314 SYMBOL_INFO*si = (SYMBOL_INFO*)buffer; 1315 size_t len; 1316 DWORD64 Displacement64; 1317 1318 if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE; 1319 si->SizeOfStruct = sizeof(*si); 1320 si->MaxNameLen = MAX_SYM_NAME; 1321 if (!SymFromAddr(hProcess, Address, &Displacement64, si)) 1322 return FALSE; 1323 1324 if (Displacement) 1325 *Displacement = Displacement64; 1326 Symbol->Address = si->Address; 1327 Symbol->Size = si->Size; 1328 Symbol->Flags = si->Flags; 1329 len = min(Symbol->MaxNameLength, si->MaxNameLen); 1330 lstrcpynA(Symbol->Name, si->Name, len); 1331 return TRUE; 1332 } 1333 1334 /****************************************************************** 1335 * SymGetSymFromAddr64 (DBGHELP.@) 1336 * 1337 */ 1338 BOOL WINAPI SymGetSymFromAddr64(HANDLE hProcess, DWORD64 Address, 1339 PDWORD64 Displacement, PIMAGEHLP_SYMBOL64 Symbol) 1340 { 1341 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; 1342 SYMBOL_INFO*si = (SYMBOL_INFO*)buffer; 1343 size_t len; 1344 DWORD64 Displacement64; 1345 1346 if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE; 1347 si->SizeOfStruct = sizeof(*si); 1348 si->MaxNameLen = MAX_SYM_NAME; 1349 if (!SymFromAddr(hProcess, Address, &Displacement64, si)) 1350 return FALSE; 1351 1352 if (Displacement) 1353 *Displacement = Displacement64; 1354 Symbol->Address = si->Address; 1355 Symbol->Size = si->Size; 1356 Symbol->Flags = si->Flags; 1357 len = min(Symbol->MaxNameLength, si->MaxNameLen); 1358 lstrcpynA(Symbol->Name, si->Name, len); 1359 return TRUE; 1360 } 1361 1362 static BOOL find_name(struct process* pcs, struct module* module, const char* name, 1363 SYMBOL_INFO* symbol) 1364 { 1365 struct hash_table_iter hti; 1366 void* ptr; 1367 struct symt_ht* sym = NULL; 1368 struct module_pair pair; 1369 1370 pair.pcs = pcs; 1371 if (!(pair.requested = module)) return FALSE; 1372 if (!module_get_debug(&pair)) return FALSE; 1373 1374 hash_table_iter_init(&pair.effective->ht_symbols, &hti, name); 1375 while ((ptr = hash_table_iter_up(&hti))) 1376 { 1377 sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt); 1378 1379 if (!strcmp(sym->hash_elt.name, name)) 1380 { 1381 symt_fill_sym_info(&pair, NULL, &sym->symt, symbol); 1382 return TRUE; 1383 } 1384 } 1385 return FALSE; 1386 1387 } 1388 /****************************************************************** 1389 * SymFromName (DBGHELP.@) 1390 * 1391 */ 1392 BOOL WINAPI SymFromName(HANDLE hProcess, PCSTR Name, PSYMBOL_INFO Symbol) 1393 { 1394 struct process* pcs = process_find_by_handle(hProcess); 1395 struct module* module; 1396 const char* name; 1397 1398 TRACE("(%p, %s, %p)\n", hProcess, Name, Symbol); 1399 if (!pcs) return FALSE; 1400 if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE; 1401 name = strchr(Name, '!'); 1402 if (name) 1403 { 1404 char tmp[128]; 1405 assert(name - Name < sizeof(tmp)); 1406 memcpy(tmp, Name, name - Name); 1407 tmp[name - Name] = '\0'; 1408 module = module_find_by_nameA(pcs, tmp); 1409 return find_name(pcs, module, name + 1, Symbol); 1410 } 1411 for (module = pcs->lmodules; module; module = module->next) 1412 { 1413 if (module->type == DMT_PE && find_name(pcs, module, Name, Symbol)) 1414 return TRUE; 1415 } 1416 /* not found in PE modules, retry on the ELF ones 1417 */ 1418 if (dbghelp_opt_native) 1419 { 1420 for (module = pcs->lmodules; module; module = module->next) 1421 { 1422 if ((module->type == DMT_ELF || module->type == DMT_MACHO) && 1423 !module_get_containee(pcs, module) && 1424 find_name(pcs, module, Name, Symbol)) 1425 return TRUE; 1426 } 1427 } 1428 return FALSE; 1429 } 1430 1431 /*********************************************************************** 1432 * SymGetSymFromName64 (DBGHELP.@) 1433 */ 1434 BOOL WINAPI SymGetSymFromName64(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL64 Symbol) 1435 { 1436 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; 1437 SYMBOL_INFO*si = (SYMBOL_INFO*)buffer; 1438 size_t len; 1439 1440 if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE; 1441 si->SizeOfStruct = sizeof(*si); 1442 si->MaxNameLen = MAX_SYM_NAME; 1443 if (!SymFromName(hProcess, Name, si)) return FALSE; 1444 1445 Symbol->Address = si->Address; 1446 Symbol->Size = si->Size; 1447 Symbol->Flags = si->Flags; 1448 len = min(Symbol->MaxNameLength, si->MaxNameLen); 1449 lstrcpynA(Symbol->Name, si->Name, len); 1450 return TRUE; 1451 } 1452 1453 /*********************************************************************** 1454 * SymGetSymFromName (DBGHELP.@) 1455 */ 1456 BOOL WINAPI SymGetSymFromName(HANDLE hProcess, PCSTR Name, PIMAGEHLP_SYMBOL Symbol) 1457 { 1458 char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; 1459 SYMBOL_INFO*si = (SYMBOL_INFO*)buffer; 1460 size_t len; 1461 1462 if (Symbol->SizeOfStruct < sizeof(*Symbol)) return FALSE; 1463 si->SizeOfStruct = sizeof(*si); 1464 si->MaxNameLen = MAX_SYM_NAME; 1465 if (!SymFromName(hProcess, Name, si)) return FALSE; 1466 1467 Symbol->Address = si->Address; 1468 Symbol->Size = si->Size; 1469 Symbol->Flags = si->Flags; 1470 len = min(Symbol->MaxNameLength, si->MaxNameLen); 1471 lstrcpynA(Symbol->Name, si->Name, len); 1472 return TRUE; 1473 } 1474 1475 /****************************************************************** 1476 * sym_fill_func_line_info 1477 * 1478 * fills information about a file 1479 */ 1480 BOOL symt_fill_func_line_info(const struct module* module, const struct symt_function* func, 1481 DWORD64 addr, IMAGEHLP_LINE64* line) 1482 { 1483 struct line_info* dli = NULL; 1484 BOOL found = FALSE; 1485 int i; 1486 1487 assert(func->symt.tag == SymTagFunction); 1488 1489 for (i=vector_length(&func->vlines)-1; i>=0; i--) 1490 { 1491 dli = vector_at(&func->vlines, i); 1492 if (!dli->is_source_file) 1493 { 1494 if (found || dli->u.pc_offset > addr) continue; 1495 line->LineNumber = dli->line_number; 1496 line->Address = dli->u.pc_offset; 1497 line->Key = dli; 1498 found = TRUE; 1499 continue; 1500 } 1501 if (found) 1502 { 1503 if (dbghelp_opt_native) 1504 { 1505 /* Return native file paths when using winedbg */ 1506 line->FileName = (char*)source_get(module, dli->u.source_file); 1507 } 1508 else 1509 { 1510 WCHAR *dospath = wine_get_dos_file_name(source_get(module, dli->u.source_file)); 1511 DWORD len = WideCharToMultiByte(CP_ACP, 0, dospath, -1, NULL, 0, NULL, NULL); 1512 line->FileName = fetch_buffer(module->process, len); 1513 WideCharToMultiByte(CP_ACP, 0, dospath, -1, line->FileName, len, NULL, NULL); 1514 HeapFree( GetProcessHeap(), 0, dospath ); 1515 } 1516 return TRUE; 1517 } 1518 } 1519 return FALSE; 1520 } 1521 1522 /*********************************************************************** 1523 * SymGetSymNext64 (DBGHELP.@) 1524 */ 1525 BOOL WINAPI SymGetSymNext64(HANDLE hProcess, PIMAGEHLP_SYMBOL64 Symbol) 1526 { 1527 /* algo: 1528 * get module from Symbol.Address 1529 * get index in module.addr_sorttab of Symbol.Address 1530 * increment index 1531 * if out of module bounds, move to next module in process address space 1532 */ 1533 FIXME("(%p, %p): stub\n", hProcess, Symbol); 1534 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1535 return FALSE; 1536 } 1537 1538 /*********************************************************************** 1539 * SymGetSymNext (DBGHELP.@) 1540 */ 1541 BOOL WINAPI SymGetSymNext(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol) 1542 { 1543 FIXME("(%p, %p): stub\n", hProcess, Symbol); 1544 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1545 return FALSE; 1546 } 1547 1548 /*********************************************************************** 1549 * SymGetSymPrev64 (DBGHELP.@) 1550 */ 1551 BOOL WINAPI SymGetSymPrev64(HANDLE hProcess, PIMAGEHLP_SYMBOL64 Symbol) 1552 { 1553 FIXME("(%p, %p): stub\n", hProcess, Symbol); 1554 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1555 return FALSE; 1556 } 1557 1558 /*********************************************************************** 1559 * SymGetSymPrev (DBGHELP.@) 1560 */ 1561 BOOL WINAPI SymGetSymPrev(HANDLE hProcess, PIMAGEHLP_SYMBOL Symbol) 1562 { 1563 FIXME("(%p, %p): stub\n", hProcess, Symbol); 1564 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1565 return FALSE; 1566 } 1567 1568 /****************************************************************** 1569 * copy_line_64_from_32 (internal) 1570 * 1571 */ 1572 static void copy_line_64_from_32(IMAGEHLP_LINE64* l64, const IMAGEHLP_LINE* l32) 1573 1574 { 1575 l64->Key = l32->Key; 1576 l64->LineNumber = l32->LineNumber; 1577 l64->FileName = l32->FileName; 1578 l64->Address = l32->Address; 1579 } 1580 1581 /****************************************************************** 1582 * copy_line_W64_from_32 (internal) 1583 * 1584 */ 1585 static void copy_line_W64_from_64(struct process* pcs, IMAGEHLP_LINEW64* l64w, const IMAGEHLP_LINE64* l64) 1586 { 1587 unsigned len; 1588 1589 l64w->Key = l64->Key; 1590 l64w->LineNumber = l64->LineNumber; 1591 len = MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, NULL, 0); 1592 if ((l64w->FileName = fetch_buffer(pcs, len * sizeof(WCHAR)))) 1593 MultiByteToWideChar(CP_ACP, 0, l64->FileName, -1, l64w->FileName, len); 1594 l64w->Address = l64->Address; 1595 } 1596 1597 /****************************************************************** 1598 * copy_line_32_from_64 (internal) 1599 * 1600 */ 1601 static void copy_line_32_from_64(IMAGEHLP_LINE* l32, const IMAGEHLP_LINE64* l64) 1602 1603 { 1604 l32->Key = l64->Key; 1605 l32->LineNumber = l64->LineNumber; 1606 l32->FileName = l64->FileName; 1607 l32->Address = l64->Address; 1608 } 1609 1610 /****************************************************************** 1611 * SymGetLineFromAddr (DBGHELP.@) 1612 * 1613 */ 1614 BOOL WINAPI SymGetLineFromAddr(HANDLE hProcess, DWORD dwAddr, 1615 PDWORD pdwDisplacement, PIMAGEHLP_LINE Line) 1616 { 1617 IMAGEHLP_LINE64 il64; 1618 1619 il64.SizeOfStruct = sizeof(il64); 1620 if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64)) 1621 return FALSE; 1622 copy_line_32_from_64(Line, &il64); 1623 return TRUE; 1624 } 1625 1626 /****************************************************************** 1627 * SymGetLineFromAddr64 (DBGHELP.@) 1628 * 1629 */ 1630 BOOL WINAPI SymGetLineFromAddr64(HANDLE hProcess, DWORD64 dwAddr, 1631 PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line) 1632 { 1633 struct module_pair pair; 1634 struct symt_ht* symt; 1635 1636 TRACE("%p %s %p %p\n", hProcess, wine_dbgstr_longlong(dwAddr), pdwDisplacement, Line); 1637 1638 if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; 1639 1640 pair.pcs = process_find_by_handle(hProcess); 1641 if (!pair.pcs) return FALSE; 1642 pair.requested = module_find_by_addr(pair.pcs, dwAddr, DMT_UNKNOWN); 1643 if (!module_get_debug(&pair)) return FALSE; 1644 if ((symt = symt_find_nearest(pair.effective, dwAddr)) == NULL) return FALSE; 1645 1646 if (symt->symt.tag != SymTagFunction) return FALSE; 1647 if (!symt_fill_func_line_info(pair.effective, (struct symt_function*)symt, 1648 dwAddr, Line)) return FALSE; 1649 *pdwDisplacement = dwAddr - Line->Address; 1650 return TRUE; 1651 } 1652 1653 /****************************************************************** 1654 * SymGetLineFromAddrW64 (DBGHELP.@) 1655 * 1656 */ 1657 BOOL WINAPI SymGetLineFromAddrW64(HANDLE hProcess, DWORD64 dwAddr, 1658 PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line) 1659 { 1660 IMAGEHLP_LINE64 il64; 1661 1662 il64.SizeOfStruct = sizeof(il64); 1663 if (!SymGetLineFromAddr64(hProcess, dwAddr, pdwDisplacement, &il64)) 1664 return FALSE; 1665 copy_line_W64_from_64(process_find_by_handle(hProcess), Line, &il64); 1666 return TRUE; 1667 } 1668 1669 /****************************************************************** 1670 * SymGetLinePrev64 (DBGHELP.@) 1671 * 1672 */ 1673 BOOL WINAPI SymGetLinePrev64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) 1674 { 1675 struct module_pair pair; 1676 struct line_info* li; 1677 BOOL in_search = FALSE; 1678 1679 TRACE("(%p %p)\n", hProcess, Line); 1680 1681 if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; 1682 1683 pair.pcs = process_find_by_handle(hProcess); 1684 if (!pair.pcs) return FALSE; 1685 pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN); 1686 if (!module_get_debug(&pair)) return FALSE; 1687 1688 if (Line->Key == 0) return FALSE; 1689 li = Line->Key; 1690 /* things are a bit complicated because when we encounter a DLIT_SOURCEFILE 1691 * element we have to go back until we find the prev one to get the real 1692 * source file name for the DLIT_OFFSET element just before 1693 * the first DLIT_SOURCEFILE 1694 */ 1695 while (!li->is_first) 1696 { 1697 li--; 1698 if (!li->is_source_file) 1699 { 1700 Line->LineNumber = li->line_number; 1701 Line->Address = li->u.pc_offset; 1702 Line->Key = li; 1703 if (!in_search) return TRUE; 1704 } 1705 else 1706 { 1707 if (in_search) 1708 { 1709 Line->FileName = (char*)source_get(pair.effective, li->u.source_file); 1710 return TRUE; 1711 } 1712 in_search = TRUE; 1713 } 1714 } 1715 SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */ 1716 return FALSE; 1717 } 1718 1719 /****************************************************************** 1720 * SymGetLinePrev (DBGHELP.@) 1721 * 1722 */ 1723 BOOL WINAPI SymGetLinePrev(HANDLE hProcess, PIMAGEHLP_LINE Line) 1724 { 1725 IMAGEHLP_LINE64 line64; 1726 1727 line64.SizeOfStruct = sizeof(line64); 1728 copy_line_64_from_32(&line64, Line); 1729 if (!SymGetLinePrev64(hProcess, &line64)) return FALSE; 1730 copy_line_32_from_64(Line, &line64); 1731 return TRUE; 1732 } 1733 1734 BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line) 1735 { 1736 struct line_info* li; 1737 1738 if (line->Key == 0) return FALSE; 1739 li = line->Key; 1740 while (!li->is_last) 1741 { 1742 li++; 1743 if (!li->is_source_file) 1744 { 1745 line->LineNumber = li->line_number; 1746 line->Address = li->u.pc_offset; 1747 line->Key = li; 1748 return TRUE; 1749 } 1750 line->FileName = (char*)source_get(module, li->u.source_file); 1751 } 1752 return FALSE; 1753 } 1754 1755 /****************************************************************** 1756 * SymGetLineNext64 (DBGHELP.@) 1757 * 1758 */ 1759 BOOL WINAPI SymGetLineNext64(HANDLE hProcess, PIMAGEHLP_LINE64 Line) 1760 { 1761 struct module_pair pair; 1762 1763 TRACE("(%p %p)\n", hProcess, Line); 1764 1765 if (Line->SizeOfStruct < sizeof(*Line)) return FALSE; 1766 pair.pcs = process_find_by_handle(hProcess); 1767 if (!pair.pcs) return FALSE; 1768 pair.requested = module_find_by_addr(pair.pcs, Line->Address, DMT_UNKNOWN); 1769 if (!module_get_debug(&pair)) return FALSE; 1770 1771 if (symt_get_func_line_next(pair.effective, Line)) return TRUE; 1772 SetLastError(ERROR_NO_MORE_ITEMS); /* FIXME */ 1773 return FALSE; 1774 } 1775 1776 /****************************************************************** 1777 * SymGetLineNext (DBGHELP.@) 1778 * 1779 */ 1780 BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line) 1781 { 1782 IMAGEHLP_LINE64 line64; 1783 1784 line64.SizeOfStruct = sizeof(line64); 1785 copy_line_64_from_32(&line64, Line); 1786 if (!SymGetLineNext64(hProcess, &line64)) return FALSE; 1787 copy_line_32_from_64(Line, &line64); 1788 return TRUE; 1789 } 1790 1791 /*********************************************************************** 1792 * SymUnDName (DBGHELP.@) 1793 */ 1794 BOOL WINAPI SymUnDName(PIMAGEHLP_SYMBOL sym, PSTR UnDecName, DWORD UnDecNameLength) 1795 { 1796 return UnDecorateSymbolName(sym->Name, UnDecName, UnDecNameLength, 1797 UNDNAME_COMPLETE) != 0; 1798 } 1799 1800 /*********************************************************************** 1801 * SymUnDName64 (DBGHELP.@) 1802 */ 1803 BOOL WINAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym, PSTR UnDecName, DWORD UnDecNameLength) 1804 { 1805 return UnDecorateSymbolName(sym->Name, UnDecName, UnDecNameLength, 1806 UNDNAME_COMPLETE) != 0; 1807 } 1808 1809 static void * CDECL und_alloc(size_t len) { return HeapAlloc(GetProcessHeap(), 0, len); } 1810 static void CDECL und_free (void* ptr) { HeapFree(GetProcessHeap(), 0, ptr); } 1811 1812 static char *und_name(char *buffer, const char *mangled, int buflen, unsigned short flags) 1813 { 1814 /* undocumented from msvcrt */ 1815 static HANDLE hMsvcrt; 1816 static char* (CDECL *p_undname)(char*, const char*, int, void* (CDECL*)(size_t), void (CDECL*)(void*), unsigned short); 1817 static const WCHAR szMsvcrt[] = {'m','s','v','c','r','t','.','d','l','l',0}; 1818 1819 if (!p_undname) 1820 { 1821 if (!hMsvcrt) hMsvcrt = LoadLibraryW(szMsvcrt); 1822 if (hMsvcrt) p_undname = (void*)GetProcAddress(hMsvcrt, "__unDName"); 1823 if (!p_undname) return NULL; 1824 } 1825 1826 return p_undname(buffer, mangled, buflen, und_alloc, und_free, flags); 1827 } 1828 1829 /*********************************************************************** 1830 * UnDecorateSymbolName (DBGHELP.@) 1831 */ 1832 DWORD WINAPI UnDecorateSymbolName(const char *decorated_name, char *undecorated_name, 1833 DWORD undecorated_length, DWORD flags) 1834 { 1835 TRACE("(%s, %p, %d, 0x%08x)\n", 1836 debugstr_a(decorated_name), undecorated_name, undecorated_length, flags); 1837 1838 if (!undecorated_name || !undecorated_length) 1839 return 0; 1840 if (!und_name(undecorated_name, decorated_name, undecorated_length, flags)) 1841 return 0; 1842 return strlen(undecorated_name); 1843 } 1844 1845 /*********************************************************************** 1846 * UnDecorateSymbolNameW (DBGHELP.@) 1847 */ 1848 DWORD WINAPI UnDecorateSymbolNameW(const WCHAR *decorated_name, WCHAR *undecorated_name, 1849 DWORD undecorated_length, DWORD flags) 1850 { 1851 char *buf, *ptr; 1852 int len, ret = 0; 1853 1854 TRACE("(%s, %p, %d, 0x%08x)\n", 1855 debugstr_w(decorated_name), undecorated_name, undecorated_length, flags); 1856 1857 if (!undecorated_name || !undecorated_length) 1858 return 0; 1859 1860 len = WideCharToMultiByte(CP_ACP, 0, decorated_name, -1, NULL, 0, NULL, NULL); 1861 if ((buf = HeapAlloc(GetProcessHeap(), 0, len))) 1862 { 1863 WideCharToMultiByte(CP_ACP, 0, decorated_name, -1, buf, len, NULL, NULL); 1864 if ((ptr = und_name(NULL, buf, 0, flags))) 1865 { 1866 MultiByteToWideChar(CP_ACP, 0, ptr, -1, undecorated_name, undecorated_length); 1867 undecorated_name[undecorated_length - 1] = 0; 1868 ret = lstrlenW(undecorated_name); 1869 und_free(ptr); 1870 } 1871 HeapFree(GetProcessHeap(), 0, buf); 1872 } 1873 1874 return ret; 1875 } 1876 1877 #define WILDCHAR(x) (-(x)) 1878 1879 static int re_fetch_char(const WCHAR** re) 1880 { 1881 switch (**re) 1882 { 1883 case '\\': (*re)++; return *(*re)++; 1884 case '*': case '[': case '?': case '+': case '#': case ']': return WILDCHAR(*(*re)++); 1885 default: return *(*re)++; 1886 } 1887 } 1888 1889 static inline int re_match_char(WCHAR ch1, WCHAR ch2, BOOL _case) 1890 { 1891 return _case ? ch1 - ch2 : towupper(ch1) - towupper(ch2); 1892 } 1893 1894 static const WCHAR* re_match_one(const WCHAR* string, const WCHAR* elt, BOOL _case) 1895 { 1896 int ch1, prev = 0; 1897 unsigned state = 0; 1898 1899 switch (ch1 = re_fetch_char(&elt)) 1900 { 1901 default: 1902 return (ch1 >= 0 && re_match_char(*string, ch1, _case) == 0) ? ++string : NULL; 1903 case WILDCHAR('?'): return *string ? ++string : NULL; 1904 case WILDCHAR('*'): assert(0); 1905 case WILDCHAR('['): break; 1906 } 1907 1908 for (;;) 1909 { 1910 ch1 = re_fetch_char(&elt); 1911 if (ch1 == WILDCHAR(']')) return NULL; 1912 if (state == 1 && ch1 == '-') state = 2; 1913 else 1914 { 1915 if (re_match_char(*string, ch1, _case) == 0) return ++string; 1916 switch (state) 1917 { 1918 case 0: 1919 state = 1; 1920 prev = ch1; 1921 break; 1922 case 1: 1923 state = 0; 1924 break; 1925 case 2: 1926 if (prev >= 0 && ch1 >= 0 && re_match_char(prev, *string, _case) <= 0 && 1927 re_match_char(*string, ch1, _case) <= 0) 1928 return ++string; 1929 state = 0; 1930 break; 1931 } 1932 } 1933 } 1934 } 1935 1936 /****************************************************************** 1937 * re_match_multi 1938 * 1939 * match a substring of *pstring according to *pre regular expression 1940 * pstring and pre are only updated in case of successful match 1941 */ 1942 static BOOL re_match_multi(const WCHAR** pstring, const WCHAR** pre, BOOL _case) 1943 { 1944 const WCHAR* re_end = *pre; 1945 const WCHAR* string_end = *pstring; 1946 const WCHAR* re_beg; 1947 const WCHAR* string_beg; 1948 const WCHAR* next; 1949 int ch; 1950 1951 while (*re_end && *string_end) 1952 { 1953 string_beg = string_end; 1954 re_beg = re_end; 1955 switch (ch = re_fetch_char(&re_end)) 1956 { 1957 case WILDCHAR(']'): case WILDCHAR('+'): case WILDCHAR('#'): return FALSE; 1958 case WILDCHAR('*'): 1959 /* transform '*' into '?#' */ 1960 {static const WCHAR qmW[] = {'?',0}; re_beg = qmW;} 1961 goto closure; 1962 case WILDCHAR('['): 1963 do 1964 { 1965 if (!(ch = re_fetch_char(&re_end))) return FALSE; 1966 } while (ch != WILDCHAR(']')); 1967 /* fall through */ 1968 case WILDCHAR('?'): 1969 default: 1970 break; 1971 } 1972 1973 switch (*re_end) 1974 { 1975 case '+': 1976 if (!(next = re_match_one(string_end, re_beg, _case))) return FALSE; 1977 string_beg++; 1978 /* fall through */ 1979 case '#': 1980 re_end++; 1981 closure: 1982 while ((next = re_match_one(string_end, re_beg, _case))) string_end = next; 1983 for ( ; string_end >= string_beg; string_end--) 1984 { 1985 if (re_match_multi(&string_end, &re_end, _case)) goto found; 1986 } 1987 return FALSE; 1988 default: 1989 if (!(next = re_match_one(string_end, re_beg, _case))) return FALSE; 1990 string_end = next; 1991 } 1992 } 1993 1994 if (*re_end || *string_end) return FALSE; 1995 1996 found: 1997 *pre = re_end; 1998 *pstring = string_end; 1999 return TRUE; 2000 } 2001 2002 /****************************************************************** 2003 * SymMatchStringA (DBGHELP.@) 2004 * 2005 */ 2006 BOOL WINAPI SymMatchStringA(PCSTR string, PCSTR re, BOOL _case) 2007 { 2008 WCHAR* strW; 2009 WCHAR* reW; 2010 BOOL ret = FALSE; 2011 DWORD sz; 2012 2013 if (!string || !re) 2014 { 2015 SetLastError(ERROR_INVALID_HANDLE); 2016 return FALSE; 2017 } 2018 TRACE("%s %s %c\n", string, re, _case ? 'Y' : 'N'); 2019 2020 sz = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0); 2021 if ((strW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 2022 MultiByteToWideChar(CP_ACP, 0, string, -1, strW, sz); 2023 sz = MultiByteToWideChar(CP_ACP, 0, re, -1, NULL, 0); 2024 if ((reW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 2025 MultiByteToWideChar(CP_ACP, 0, re, -1, reW, sz); 2026 2027 if (strW && reW) 2028 ret = SymMatchStringW(strW, reW, _case); 2029 HeapFree(GetProcessHeap(), 0, strW); 2030 HeapFree(GetProcessHeap(), 0, reW); 2031 return ret; 2032 } 2033 2034 /****************************************************************** 2035 * SymMatchStringW (DBGHELP.@) 2036 * 2037 */ 2038 BOOL WINAPI SymMatchStringW(PCWSTR string, PCWSTR re, BOOL _case) 2039 { 2040 TRACE("%s %s %c\n", debugstr_w(string), debugstr_w(re), _case ? 'Y' : 'N'); 2041 2042 if (!string || !re) 2043 { 2044 SetLastError(ERROR_INVALID_HANDLE); 2045 return FALSE; 2046 } 2047 return re_match_multi(&string, &re, _case); 2048 } 2049 2050 static inline BOOL doSymSearch(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index, 2051 DWORD SymTag, PCWSTR Mask, DWORD64 Address, 2052 PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, 2053 PVOID UserContext, DWORD Options) 2054 { 2055 struct sym_enum se; 2056 2057 if (Options != SYMSEARCH_GLOBALSONLY) 2058 { 2059 FIXME("Unsupported searching with options (%x)\n", Options); 2060 SetLastError(ERROR_INVALID_PARAMETER); 2061 return FALSE; 2062 } 2063 2064 se.cb = EnumSymbolsCallback; 2065 se.user = UserContext; 2066 se.index = Index; 2067 se.tag = SymTag; 2068 se.addr = Address; 2069 se.sym_info = (PSYMBOL_INFO)se.buffer; 2070 2071 return sym_enum(hProcess, BaseOfDll, Mask, &se); 2072 } 2073 2074 /****************************************************************** 2075 * SymSearch (DBGHELP.@) 2076 */ 2077 BOOL WINAPI SymSearch(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index, 2078 DWORD SymTag, PCSTR Mask, DWORD64 Address, 2079 PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, 2080 PVOID UserContext, DWORD Options) 2081 { 2082 LPWSTR maskW = NULL; 2083 BOOLEAN ret; 2084 2085 TRACE("(%p %s %u %u %s %s %p %p %x)\n", 2086 hProcess, wine_dbgstr_longlong(BaseOfDll), Index, SymTag, Mask, 2087 wine_dbgstr_longlong(Address), EnumSymbolsCallback, 2088 UserContext, Options); 2089 2090 if (Mask) 2091 { 2092 DWORD sz = MultiByteToWideChar(CP_ACP, 0, Mask, -1, NULL, 0); 2093 2094 if (!(maskW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 2095 return FALSE; 2096 MultiByteToWideChar(CP_ACP, 0, Mask, -1, maskW, sz); 2097 } 2098 ret = doSymSearch(hProcess, BaseOfDll, Index, SymTag, maskW, Address, 2099 EnumSymbolsCallback, UserContext, Options); 2100 HeapFree(GetProcessHeap(), 0, maskW); 2101 return ret; 2102 } 2103 2104 /****************************************************************** 2105 * SymSearchW (DBGHELP.@) 2106 */ 2107 BOOL WINAPI SymSearchW(HANDLE hProcess, ULONG64 BaseOfDll, DWORD Index, 2108 DWORD SymTag, PCWSTR Mask, DWORD64 Address, 2109 PSYM_ENUMERATESYMBOLS_CALLBACKW EnumSymbolsCallback, 2110 PVOID UserContext, DWORD Options) 2111 { 2112 struct sym_enumW sew; 2113 2114 TRACE("(%p %s %u %u %s %s %p %p %x)\n", 2115 hProcess, wine_dbgstr_longlong(BaseOfDll), Index, SymTag, debugstr_w(Mask), 2116 wine_dbgstr_longlong(Address), EnumSymbolsCallback, 2117 UserContext, Options); 2118 2119 sew.ctx = UserContext; 2120 sew.cb = EnumSymbolsCallback; 2121 sew.sym_info = (PSYMBOL_INFOW)sew.buffer; 2122 2123 return doSymSearch(hProcess, BaseOfDll, Index, SymTag, Mask, Address, 2124 sym_enumW, &sew, Options); 2125 } 2126 2127 /****************************************************************** 2128 * SymAddSymbol (DBGHELP.@) 2129 * 2130 */ 2131 BOOL WINAPI SymAddSymbol(HANDLE hProcess, ULONG64 BaseOfDll, PCSTR name, 2132 DWORD64 addr, DWORD size, DWORD flags) 2133 { 2134 WCHAR nameW[MAX_SYM_NAME]; 2135 2136 MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, ARRAY_SIZE(nameW)); 2137 return SymAddSymbolW(hProcess, BaseOfDll, nameW, addr, size, flags); 2138 } 2139 2140 /****************************************************************** 2141 * SymAddSymbolW (DBGHELP.@) 2142 * 2143 */ 2144 BOOL WINAPI SymAddSymbolW(HANDLE hProcess, ULONG64 BaseOfDll, PCWSTR name, 2145 DWORD64 addr, DWORD size, DWORD flags) 2146 { 2147 struct module_pair pair; 2148 2149 TRACE("(%p %s %s %u)\n", hProcess, wine_dbgstr_w(name), wine_dbgstr_longlong(addr), size); 2150 2151 pair.pcs = process_find_by_handle(hProcess); 2152 if (!pair.pcs) return FALSE; 2153 pair.requested = module_find_by_addr(pair.pcs, BaseOfDll, DMT_UNKNOWN); 2154 if (!module_get_debug(&pair)) return FALSE; 2155 2156 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 2157 return FALSE; 2158 } 2159 2160 /****************************************************************** 2161 * SymSetScopeFromAddr (DBGHELP.@) 2162 */ 2163 BOOL WINAPI SymSetScopeFromAddr(HANDLE hProcess, ULONG64 addr) 2164 { 2165 struct process* pcs; 2166 2167 FIXME("(%p %s): stub\n", hProcess, wine_dbgstr_longlong(addr)); 2168 2169 if (!(pcs = process_find_by_handle(hProcess))) return FALSE; 2170 return TRUE; 2171 } 2172 2173 /****************************************************************** 2174 * SymEnumLines (DBGHELP.@) 2175 * 2176 */ 2177 BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland, 2178 PCSTR srcfile, PSYM_ENUMLINES_CALLBACK cb, PVOID user) 2179 { 2180 struct module_pair pair; 2181 struct hash_table_iter hti; 2182 struct symt_ht* sym; 2183 WCHAR* srcmask; 2184 struct line_info* dli; 2185 void* ptr; 2186 SRCCODEINFO sci; 2187 const char* file; 2188 2189 if (!cb) return FALSE; 2190 if (!(dbghelp_options & SYMOPT_LOAD_LINES)) return TRUE; 2191 2192 pair.pcs = process_find_by_handle(hProcess); 2193 if (!pair.pcs) return FALSE; 2194 if (compiland) FIXME("Unsupported yet (filtering on compiland %s)\n", compiland); 2195 pair.requested = module_find_by_addr(pair.pcs, base, DMT_UNKNOWN); 2196 if (!module_get_debug(&pair)) return FALSE; 2197 if (!(srcmask = file_regex(srcfile))) return FALSE; 2198 2199 sci.SizeOfStruct = sizeof(sci); 2200 sci.ModBase = base; 2201 2202 hash_table_iter_init(&pair.effective->ht_symbols, &hti, NULL); 2203 while ((ptr = hash_table_iter_up(&hti))) 2204 { 2205 unsigned int i; 2206 2207 sym = CONTAINING_RECORD(ptr, struct symt_ht, hash_elt); 2208 if (sym->symt.tag != SymTagFunction) continue; 2209 2210 sci.FileName[0] = '\0'; 2211 for (i=0; i<vector_length(&((struct symt_function*)sym)->vlines); i++) 2212 { 2213 dli = vector_at(&((struct symt_function*)sym)->vlines, i); 2214 if (dli->is_source_file) 2215 { 2216 file = source_get(pair.effective, dli->u.source_file); 2217 if (!file) sci.FileName[0] = '\0'; 2218 else 2219 { 2220 DWORD sz = MultiByteToWideChar(CP_ACP, 0, file, -1, NULL, 0); 2221 WCHAR* fileW; 2222 2223 if ((fileW = HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR)))) 2224 MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, sz); 2225 if (SymMatchStringW(fileW, srcmask, FALSE)) 2226 strcpy(sci.FileName, file); 2227 else 2228 sci.FileName[0] = '\0'; 2229 HeapFree(GetProcessHeap(), 0, fileW); 2230 } 2231 } 2232 else if (sci.FileName[0]) 2233 { 2234 sci.Key = dli; 2235 sci.Obj[0] = '\0'; /* FIXME */ 2236 sci.LineNumber = dli->line_number; 2237 sci.Address = dli->u.pc_offset; 2238 if (!cb(&sci, user)) break; 2239 } 2240 } 2241 } 2242 HeapFree(GetProcessHeap(), 0, srcmask); 2243 return TRUE; 2244 } 2245 2246 BOOL WINAPI SymGetLineFromName(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName, 2247 DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINE Line) 2248 { 2249 FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, ModuleName, FileName, 2250 dwLineNumber, plDisplacement, Line); 2251 return FALSE; 2252 } 2253 2254 BOOL WINAPI SymGetLineFromName64(HANDLE hProcess, PCSTR ModuleName, PCSTR FileName, 2255 DWORD dwLineNumber, PLONG lpDisplacement, PIMAGEHLP_LINE64 Line) 2256 { 2257 FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, ModuleName, FileName, 2258 dwLineNumber, lpDisplacement, Line); 2259 return FALSE; 2260 } 2261 2262 BOOL WINAPI SymGetLineFromNameW64(HANDLE hProcess, PCWSTR ModuleName, PCWSTR FileName, 2263 DWORD dwLineNumber, PLONG plDisplacement, PIMAGEHLP_LINEW64 Line) 2264 { 2265 FIXME("(%p) (%s, %s, %d %p %p): stub\n", hProcess, debugstr_w(ModuleName), debugstr_w(FileName), 2266 dwLineNumber, plDisplacement, Line); 2267 return FALSE; 2268 } 2269 2270 /****************************************************************** 2271 * SymFromIndex (DBGHELP.@) 2272 * 2273 */ 2274 BOOL WINAPI SymFromIndex(HANDLE hProcess, ULONG64 BaseOfDll, DWORD index, PSYMBOL_INFO symbol) 2275 { 2276 FIXME("hProcess = %p, BaseOfDll = %s, index = %d, symbol = %p\n", 2277 hProcess, wine_dbgstr_longlong(BaseOfDll), index, symbol); 2278 2279 return FALSE; 2280 } 2281 2282 /****************************************************************** 2283 * SymFromIndexW (DBGHELP.@) 2284 * 2285 */ 2286 BOOL WINAPI SymFromIndexW(HANDLE hProcess, ULONG64 BaseOfDll, DWORD index, PSYMBOL_INFOW symbol) 2287 { 2288 FIXME("hProcess = %p, BaseOfDll = %s, index = %d, symbol = %p\n", 2289 hProcess, wine_dbgstr_longlong(BaseOfDll), index, symbol); 2290 2291 return FALSE; 2292 } 2293 2294 /****************************************************************** 2295 * SymSetHomeDirectory (DBGHELP.@) 2296 * 2297 */ 2298 PCHAR WINAPI SymSetHomeDirectory(HANDLE hProcess, PCSTR dir) 2299 { 2300 FIXME("(%p, %s): stub\n", hProcess, dir); 2301 2302 return NULL; 2303 } 2304 2305 /****************************************************************** 2306 * SymSetHomeDirectoryW (DBGHELP.@) 2307 * 2308 */ 2309 PWSTR WINAPI SymSetHomeDirectoryW(HANDLE hProcess, PCWSTR dir) 2310 { 2311 FIXME("(%p, %s): stub\n", hProcess, debugstr_w(dir)); 2312 2313 return NULL; 2314 } 2315