1 /* 2 * File module.c - module handling for the wine debugger 3 * 4 * Copyright (C) 1993, Eric Youngdale. 5 * 2000-2007, 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 #include <stdlib.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include <assert.h> 26 27 #include "dbghelp_private.h" 28 #include "image_private.h" 29 #ifndef DBGHELP_STATIC_LIB 30 #include "psapi.h" 31 #include "winternl.h" 32 #include "wine/debug.h" 33 #include "wine/heap.h" 34 #endif 35 36 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp); 37 38 #define NOTE_GNU_BUILD_ID 3 39 40 const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'}; 41 #ifndef __REACTOS__ 42 const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'}; 43 #endif 44 static const WCHAR S_DotSoW[] = {'.','s','o','\0'}; 45 const WCHAR S_SlashW[] = {'/','\0'}; 46 47 static const WCHAR S_AcmW[] = {'.','a','c','m','\0'}; 48 static const WCHAR S_DllW[] = {'.','d','l','l','\0'}; 49 static const WCHAR S_DrvW[] = {'.','d','r','v','\0'}; 50 static const WCHAR S_ExeW[] = {'.','e','x','e','\0'}; 51 static const WCHAR S_OcxW[] = {'.','o','c','x','\0'}; 52 static const WCHAR S_VxdW[] = {'.','v','x','d','\0'}; 53 static const WCHAR * const ext[] = {S_AcmW, S_DllW, S_DrvW, S_ExeW, S_OcxW, S_VxdW, NULL}; 54 55 static int match_ext(const WCHAR* ptr, size_t len) 56 { 57 const WCHAR* const *e; 58 size_t l; 59 60 for (e = ext; *e; e++) 61 { 62 l = lstrlenW(*e); 63 if (l >= len) return 0; 64 if (wcsnicmp(&ptr[len - l], *e, l)) continue; 65 return l; 66 } 67 return 0; 68 } 69 70 static const WCHAR* get_filename(const WCHAR* name, const WCHAR* endptr) 71 { 72 const WCHAR* ptr; 73 74 if (!endptr) endptr = name + lstrlenW(name); 75 for (ptr = endptr - 1; ptr >= name; ptr--) 76 { 77 if (*ptr == '/' || *ptr == '\\') break; 78 } 79 return ++ptr; 80 } 81 82 #ifndef __REACTOS__ 83 static BOOL is_wine_loader(const WCHAR *module) 84 { 85 static const WCHAR wineW[] = {'w','i','n','e',0}; 86 static const WCHAR suffixW[] = {'6','4',0}; 87 const WCHAR *filename = get_filename(module, NULL); 88 const char *ptr; 89 BOOL ret = FALSE; 90 WCHAR *buffer; 91 DWORD len; 92 93 if ((ptr = getenv("WINELOADER"))) 94 { 95 ptr = file_nameA(ptr); 96 len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, NULL, 0 ); 97 buffer = heap_alloc( len * sizeof(WCHAR) ); 98 MultiByteToWideChar( CP_UNIXCP, 0, ptr, -1, buffer, len ); 99 } 100 else 101 { 102 buffer = heap_alloc( sizeof(wineW) + 2 * sizeof(WCHAR) ); 103 lstrcpyW( buffer, wineW ); 104 } 105 106 if (!wcscmp( filename, buffer )) 107 ret = TRUE; 108 109 lstrcatW( buffer, suffixW ); 110 if (!wcscmp( filename, buffer )) 111 ret = TRUE; 112 113 heap_free( buffer ); 114 return ret; 115 } 116 #endif 117 118 static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size) 119 { 120 const WCHAR *ptr, *endptr; 121 size_t len, l; 122 123 ptr = get_filename(in, endptr = in + lstrlenW(in)); 124 len = min(endptr - ptr, size - 1); 125 memcpy(out, ptr, len * sizeof(WCHAR)); 126 out[len] = '\0'; 127 if (len > 4 && (l = match_ext(out, len))) 128 out[len - l] = '\0'; 129 #ifndef __REACTOS__ 130 else if (is_wine_loader(out)) 131 lstrcpynW(out, S_WineLoaderW, size); 132 #endif 133 else 134 { 135 if (len > 3 && !wcsicmp(&out[len - 3], S_DotSoW) && 136 (l = match_ext(out, len - 3))) 137 lstrcpyW(&out[len - l - 3], S_ElfW); 138 } 139 while ((*out = towlower(*out))) out++; 140 } 141 142 void module_set_module(struct module* module, const WCHAR* name) 143 { 144 module_fill_module(name, module->module.ModuleName, ARRAY_SIZE(module->module.ModuleName)); 145 module_fill_module(name, module->modulename, ARRAY_SIZE(module->modulename)); 146 } 147 148 #ifndef __REACTOS__ 149 /* Returned string must be freed by caller */ 150 WCHAR *get_wine_loader_name(struct process *pcs) 151 { 152 static const WCHAR wineW[] = {'w','i','n','e',0}; 153 static const WCHAR suffixW[] = {'6','4',0}; 154 WCHAR *buffer, *p; 155 const char *env; 156 157 /* All binaries are loaded with WINELOADER (if run from tree) or by the 158 * main executable 159 */ 160 if ((env = getenv("WINELOADER"))) 161 { 162 DWORD len = 2 + MultiByteToWideChar( CP_UNIXCP, 0, env, -1, NULL, 0 ); 163 buffer = heap_alloc( len * sizeof(WCHAR) ); 164 MultiByteToWideChar( CP_UNIXCP, 0, env, -1, buffer, len ); 165 } 166 else 167 { 168 buffer = heap_alloc( sizeof(wineW) + 2 * sizeof(WCHAR) ); 169 lstrcpyW( buffer, wineW ); 170 } 171 172 p = buffer + lstrlenW( buffer ) - lstrlenW( suffixW ); 173 if (p > buffer && !wcscmp( p, suffixW )) 174 *p = 0; 175 176 if (pcs->is_64bit) 177 lstrcatW(buffer, suffixW); 178 179 TRACE( "returning %s\n", debugstr_w(buffer) ); 180 return buffer; 181 } 182 #endif 183 184 static const char* get_module_type(enum module_type type, BOOL virtual) 185 { 186 switch (type) 187 { 188 case DMT_ELF: return virtual ? "Virtual ELF" : "ELF"; 189 case DMT_PE: return virtual ? "Virtual PE" : "PE"; 190 case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O"; 191 default: return "---"; 192 } 193 } 194 195 /*********************************************************************** 196 * Creates and links a new module to a process 197 */ 198 struct module* module_new(struct process* pcs, const WCHAR* name, 199 enum module_type type, BOOL virtual, 200 DWORD64 mod_addr, DWORD64 size, 201 ULONG_PTR stamp, ULONG_PTR checksum) 202 { 203 struct module* module; 204 unsigned i; 205 206 assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO); 207 if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module)))) 208 return NULL; 209 210 module->next = pcs->lmodules; 211 pcs->lmodules = module; 212 213 TRACE("=> %s %s-%s %s\n", 214 get_module_type(type, virtual), 215 wine_dbgstr_longlong(mod_addr), wine_dbgstr_longlong(mod_addr + size), 216 debugstr_w(name)); 217 218 pool_init(&module->pool, 65536); 219 220 module->process = pcs; 221 module->module.SizeOfStruct = sizeof(module->module); 222 module->module.BaseOfImage = mod_addr; 223 module->module.ImageSize = size; 224 module_set_module(module, name); 225 module->module.ImageName[0] = '\0'; 226 lstrcpynW(module->module.LoadedImageName, name, ARRAY_SIZE(module->module.LoadedImageName)); 227 module->module.SymType = SymNone; 228 module->module.NumSyms = 0; 229 module->module.TimeDateStamp = stamp; 230 module->module.CheckSum = checksum; 231 232 memset(module->module.LoadedPdbName, 0, sizeof(module->module.LoadedPdbName)); 233 module->module.CVSig = 0; 234 memset(module->module.CVData, 0, sizeof(module->module.CVData)); 235 module->module.PdbSig = 0; 236 memset(&module->module.PdbSig70, 0, sizeof(module->module.PdbSig70)); 237 module->module.PdbAge = 0; 238 module->module.PdbUnmatched = FALSE; 239 module->module.DbgUnmatched = FALSE; 240 module->module.LineNumbers = FALSE; 241 module->module.GlobalSymbols = FALSE; 242 module->module.TypeInfo = FALSE; 243 module->module.SourceIndexed = FALSE; 244 module->module.Publics = FALSE; 245 246 module->reloc_delta = 0; 247 module->type = type; 248 module->is_virtual = virtual; 249 for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL; 250 module->sortlist_valid = FALSE; 251 module->sorttab_size = 0; 252 module->addr_sorttab = NULL; 253 module->num_sorttab = 0; 254 module->num_symbols = 0; 255 256 vector_init(&module->vsymt, sizeof(struct symt*), 128); 257 /* FIXME: this seems a bit too high (on a per module basis) 258 * need some statistics about this 259 */ 260 hash_table_init(&module->pool, &module->ht_symbols, 4096); 261 hash_table_init(&module->pool, &module->ht_types, 4096); 262 #ifdef __x86_64__ 263 hash_table_init(&module->pool, &module->ht_symaddr, 4096); 264 #endif 265 vector_init(&module->vtypes, sizeof(struct symt*), 32); 266 267 module->sources_used = 0; 268 module->sources_alloc = 0; 269 module->sources = 0; 270 wine_rb_init(&module->sources_offsets_tree, source_rb_compare); 271 272 return module; 273 } 274 275 /*********************************************************************** 276 * module_find_by_nameW 277 * 278 */ 279 struct module* module_find_by_nameW(const struct process* pcs, const WCHAR* name) 280 { 281 struct module* module; 282 283 for (module = pcs->lmodules; module; module = module->next) 284 { 285 if (!wcsicmp(name, module->module.ModuleName)) return module; 286 } 287 SetLastError(ERROR_INVALID_NAME); 288 return NULL; 289 } 290 291 struct module* module_find_by_nameA(const struct process* pcs, const char* name) 292 { 293 WCHAR wname[MAX_PATH]; 294 295 MultiByteToWideChar(CP_ACP, 0, name, -1, wname, ARRAY_SIZE(wname)); 296 return module_find_by_nameW(pcs, wname); 297 } 298 299 /*********************************************************************** 300 * module_is_already_loaded 301 * 302 */ 303 struct module* module_is_already_loaded(const struct process* pcs, const WCHAR* name) 304 { 305 struct module* module; 306 const WCHAR* filename; 307 308 /* first compare the loaded image name... */ 309 for (module = pcs->lmodules; module; module = module->next) 310 { 311 if (!wcsicmp(name, module->module.LoadedImageName)) 312 return module; 313 } 314 /* then compare the standard filenames (without the path) ... */ 315 filename = get_filename(name, NULL); 316 for (module = pcs->lmodules; module; module = module->next) 317 { 318 if (!wcsicmp(filename, get_filename(module->module.LoadedImageName, NULL))) 319 return module; 320 } 321 SetLastError(ERROR_INVALID_NAME); 322 return NULL; 323 } 324 325 /*********************************************************************** 326 * module_get_container 327 * 328 */ 329 static struct module* module_get_container(const struct process* pcs, 330 const struct module* inner) 331 { 332 struct module* module; 333 334 for (module = pcs->lmodules; module; module = module->next) 335 { 336 if (module != inner && 337 module->module.BaseOfImage <= inner->module.BaseOfImage && 338 module->module.BaseOfImage + module->module.ImageSize >= 339 inner->module.BaseOfImage + inner->module.ImageSize) 340 return module; 341 } 342 return NULL; 343 } 344 345 /*********************************************************************** 346 * module_get_containee 347 * 348 */ 349 struct module* module_get_containee(const struct process* pcs, const struct module* outer) 350 { 351 struct module* module; 352 353 for (module = pcs->lmodules; module; module = module->next) 354 { 355 if (module != outer && 356 outer->module.BaseOfImage <= module->module.BaseOfImage && 357 outer->module.BaseOfImage + outer->module.ImageSize >= 358 module->module.BaseOfImage + module->module.ImageSize) 359 return module; 360 } 361 return NULL; 362 } 363 364 /****************************************************************** 365 * module_get_debug 366 * 367 * get the debug information from a module: 368 * - if the module's type is deferred, then force loading of debug info (and return 369 * the module itself) 370 * - if the module has no debug info and has an ELF container, then return the ELF 371 * container (and also force the ELF container's debug info loading if deferred) 372 * - otherwise return the module itself if it has some debug info 373 */ 374 BOOL module_get_debug(struct module_pair* pair) 375 { 376 IMAGEHLP_DEFERRED_SYMBOL_LOADW64 idslW64; 377 378 if (!pair->requested) return FALSE; 379 /* for a PE builtin, always get info from container */ 380 if (!(pair->effective = module_get_container(pair->pcs, pair->requested))) 381 pair->effective = pair->requested; 382 /* if deferred, force loading */ 383 if (pair->effective->module.SymType == SymDeferred) 384 { 385 BOOL ret; 386 387 if (pair->effective->is_virtual) ret = FALSE; 388 else if (pair->effective->type == DMT_PE) 389 { 390 idslW64.SizeOfStruct = sizeof(idslW64); 391 idslW64.BaseOfImage = pair->effective->module.BaseOfImage; 392 idslW64.CheckSum = pair->effective->module.CheckSum; 393 idslW64.TimeDateStamp = pair->effective->module.TimeDateStamp; 394 memcpy(idslW64.FileName, pair->effective->module.ImageName, 395 sizeof(pair->effective->module.ImageName)); 396 idslW64.Reparse = FALSE; 397 idslW64.hFile = INVALID_HANDLE_VALUE; 398 399 pcs_callback(pair->pcs, CBA_DEFERRED_SYMBOL_LOAD_START, &idslW64); 400 ret = pe_load_debug_info(pair->pcs, pair->effective); 401 pcs_callback(pair->pcs, 402 ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE, 403 &idslW64); 404 } 405 else ret = pair->pcs->loader->load_debug_info(pair->pcs, pair->effective); 406 407 if (!ret) pair->effective->module.SymType = SymNone; 408 assert(pair->effective->module.SymType != SymDeferred); 409 pair->effective->module.NumSyms = pair->effective->ht_symbols.num_elts; 410 } 411 return pair->effective->module.SymType != SymNone; 412 } 413 414 /*********************************************************************** 415 * module_find_by_addr 416 * 417 * either the addr where module is loaded, or any address inside the 418 * module 419 */ 420 struct module* module_find_by_addr(const struct process* pcs, DWORD64 addr, 421 enum module_type type) 422 { 423 struct module* module; 424 425 if (type == DMT_UNKNOWN) 426 { 427 if ((module = module_find_by_addr(pcs, addr, DMT_PE)) || 428 (module = module_find_by_addr(pcs, addr, DMT_ELF)) || 429 (module = module_find_by_addr(pcs, addr, DMT_MACHO))) 430 return module; 431 } 432 else 433 { 434 for (module = pcs->lmodules; module; module = module->next) 435 { 436 if (type == module->type && addr >= module->module.BaseOfImage && 437 addr < module->module.BaseOfImage + module->module.ImageSize) 438 return module; 439 } 440 } 441 SetLastError(ERROR_MOD_NOT_FOUND); 442 return module; 443 } 444 445 /****************************************************************** 446 * module_is_container_loaded 447 * 448 * checks whether the native container, for a (supposed) PE builtin is 449 * already loaded 450 */ 451 static BOOL module_is_container_loaded(const struct process* pcs, 452 const WCHAR* ImageName, DWORD64 base) 453 { 454 size_t len; 455 struct module* module; 456 PCWSTR filename, modname; 457 458 if (!base) return FALSE; 459 filename = get_filename(ImageName, NULL); 460 len = lstrlenW(filename); 461 462 for (module = pcs->lmodules; module; module = module->next) 463 { 464 if ((module->type == DMT_ELF || module->type == DMT_MACHO) && 465 base >= module->module.BaseOfImage && 466 base < module->module.BaseOfImage + module->module.ImageSize) 467 { 468 modname = get_filename(module->module.LoadedImageName, NULL); 469 if (!wcsnicmp(modname, filename, len) && 470 !memcmp(modname + len, S_DotSoW, 3 * sizeof(WCHAR))) 471 { 472 return TRUE; 473 } 474 } 475 } 476 /* likely a native PE module */ 477 WARN("Couldn't find container for %s\n", debugstr_w(ImageName)); 478 return FALSE; 479 } 480 481 static BOOL image_check_debug_link(const WCHAR* file, struct image_file_map* fmap, DWORD link_crc) 482 { 483 DWORD read_bytes; 484 HANDLE handle; 485 #ifndef DBGHELP_STATIC_LIB 486 WCHAR *path; 487 #endif 488 WORD magic; 489 BOOL ret; 490 491 #ifndef DBGHELP_STATIC_LIB 492 path = get_dos_file_name(file); 493 handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 494 heap_free(path); 495 #else 496 handle = CreateFileW(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); 497 #endif 498 if (handle == INVALID_HANDLE_VALUE) return FALSE; 499 500 if (link_crc) 501 { 502 DWORD crc = calc_crc32(handle); 503 if (crc != link_crc) 504 { 505 WARN("Bad CRC for file %s (got %08x while expecting %08x)\n", debugstr_w(file), crc, link_crc); 506 CloseHandle(handle); 507 return FALSE; 508 } 509 } 510 511 SetFilePointer(handle, 0, 0, FILE_BEGIN); 512 if (ReadFile(handle, &magic, sizeof(magic), &read_bytes, NULL) && magic == IMAGE_DOS_SIGNATURE) 513 ret = pe_map_file(handle, fmap, DMT_PE); 514 else 515 #ifndef __REACTOS__ 516 ret = elf_map_handle(handle, fmap); 517 #else 518 ret = FALSE; 519 #endif 520 CloseHandle(handle); 521 return ret; 522 } 523 524 /****************************************************************** 525 * image_locate_debug_link 526 * 527 * Locate a filename from a .gnu_debuglink section, using the same 528 * strategy as gdb: 529 * "If the full name of the directory containing the executable is 530 * execdir, and the executable has a debug link that specifies the 531 * name debugfile, then GDB will automatically search for the 532 * debugging information file in three places: 533 * - the directory containing the executable file (that is, it 534 * will look for a file named `execdir/debugfile', 535 * - a subdirectory of that directory named `.debug' (that is, the 536 * file `execdir/.debug/debugfile', and 537 * - a subdirectory of the global debug file directory that includes 538 * the executable's full path, and the name from the link (that is, 539 * the file `globaldebugdir/execdir/debugfile', where globaldebugdir 540 * is the global debug file directory, and execdir has been turned 541 * into a relative path)." (from GDB manual) 542 */ 543 static BOOL image_locate_debug_link(const struct module* module, struct image_file_map* fmap, const char* filename, DWORD crc) 544 { 545 #ifndef __REACTOS__ 546 static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'}; 547 #else 548 static const WCHAR globalDebugDirW[] = {'\0'}; 549 #endif 550 static const WCHAR dotDebugW[] = {'.','d','e','b','u','g','/'}; 551 const size_t globalDebugDirLen = ARRAY_SIZE(globalDebugDirW); 552 size_t filename_len, path_len; 553 WCHAR* p = NULL; 554 WCHAR* slash; 555 WCHAR* slash2; 556 struct image_file_map* fmap_link = NULL; 557 558 fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link)); 559 if (!fmap_link) return FALSE; 560 561 filename_len = MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, NULL, 0); 562 path_len = lstrlenW(module->module.LoadedImageName); 563 if (module->real_path) path_len = max(path_len, lstrlenW(module->real_path)); 564 p = HeapAlloc(GetProcessHeap(), 0, 565 (globalDebugDirLen + path_len + 6 + 1 + filename_len + 1) * sizeof(WCHAR)); 566 if (!p) goto found; 567 568 /* we prebuild the string with "execdir" */ 569 lstrcpyW(p, module->module.LoadedImageName); 570 slash = p; 571 if ((slash2 = wcsrchr(slash, '/'))) slash = slash2 + 1; 572 if ((slash2 = wcsrchr(slash, '\\'))) slash = slash2 + 1; 573 574 /* testing execdir/filename */ 575 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); 576 if (image_check_debug_link(p, fmap_link, crc)) goto found; 577 578 /* testing execdir/.debug/filename */ 579 memcpy(slash, dotDebugW, sizeof(dotDebugW)); 580 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash + ARRAY_SIZE(dotDebugW), filename_len); 581 if (image_check_debug_link(p, fmap_link, crc)) goto found; 582 583 if (module->real_path) 584 { 585 lstrcpyW(p, module->real_path); 586 slash = p; 587 if ((slash2 = wcsrchr(slash, '/'))) slash = slash2 + 1; 588 if ((slash2 = wcsrchr(slash, '\\'))) slash = slash2 + 1; 589 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); 590 if (image_check_debug_link(p, fmap_link, crc)) goto found; 591 } 592 593 /* testing globaldebugdir/execdir/filename */ 594 memmove(p + globalDebugDirLen, p, (slash - p) * sizeof(WCHAR)); 595 memcpy(p, globalDebugDirW, globalDebugDirLen * sizeof(WCHAR)); 596 slash += globalDebugDirLen; 597 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); 598 if (image_check_debug_link(p, fmap_link, crc)) goto found; 599 600 /* finally testing filename */ 601 if (image_check_debug_link(slash, fmap_link, crc)) goto found; 602 603 604 WARN("Couldn't locate or map %s\n", filename); 605 HeapFree(GetProcessHeap(), 0, p); 606 HeapFree(GetProcessHeap(), 0, fmap_link); 607 return FALSE; 608 609 found: 610 TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p)); 611 HeapFree(GetProcessHeap(), 0, p); 612 fmap->alternate = fmap_link; 613 return TRUE; 614 } 615 616 /****************************************************************** 617 * image_locate_build_id_target 618 * 619 * Try to find the .so file containing the debug info out of the build-id note information 620 */ 621 static BOOL image_locate_build_id_target(struct image_file_map* fmap, const BYTE* id, unsigned idlen) 622 { 623 static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'}; 624 static const WCHAR buildidW[] = {'.','b','u','i','l','d','-','i','d','/'}; 625 static const WCHAR dotDebug0W[] = {'.','d','e','b','u','g',0}; 626 struct image_file_map* fmap_link = NULL; 627 WCHAR* p; 628 WCHAR* z; 629 const BYTE* idend = id + idlen; 630 631 fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link)); 632 if (!fmap_link) return FALSE; 633 634 p = HeapAlloc(GetProcessHeap(), 0, 635 sizeof(globalDebugDirW) + sizeof(buildidW) + 636 (idlen * 2 + 1) * sizeof(WCHAR) + sizeof(dotDebug0W)); 637 z = p; 638 memcpy(z, globalDebugDirW, sizeof(globalDebugDirW)); 639 z += ARRAY_SIZE(globalDebugDirW); 640 memcpy(z, buildidW, sizeof(buildidW)); 641 z += ARRAY_SIZE(buildidW); 642 643 if (id < idend) 644 { 645 *z++ = "0123456789abcdef"[*id >> 4 ]; 646 *z++ = "0123456789abcdef"[*id & 0x0F]; 647 id++; 648 } 649 if (id < idend) 650 *z++ = '/'; 651 while (id < idend) 652 { 653 *z++ = "0123456789abcdef"[*id >> 4 ]; 654 *z++ = "0123456789abcdef"[*id & 0x0F]; 655 id++; 656 } 657 memcpy(z, dotDebug0W, sizeof(dotDebug0W)); 658 TRACE("checking %s\n", wine_dbgstr_w(p)); 659 660 if (image_check_debug_link(p, fmap_link, 0)) 661 { 662 struct image_section_map buildid_sect; 663 if (image_find_section(fmap_link, ".note.gnu.build-id", &buildid_sect)) 664 { 665 const UINT32* note; 666 667 note = (const UINT32*)image_map_section(&buildid_sect); 668 if (note != IMAGE_NO_MAP) 669 { 670 /* the usual ELF note structure: name-size desc-size type <name> <desc> */ 671 if (note[2] == NOTE_GNU_BUILD_ID) 672 { 673 if (note[1] == idlen && 674 !memcmp(note + 3 + ((note[0] + 3) >> 2), idend - idlen, idlen)) 675 { 676 TRACE("Located debug information file at %s\n", debugstr_w(p)); 677 HeapFree(GetProcessHeap(), 0, p); 678 fmap->alternate = fmap_link; 679 return TRUE; 680 } 681 WARN("mismatch in buildid information for %s\n", wine_dbgstr_w(p)); 682 } 683 } 684 image_unmap_section(&buildid_sect); 685 } 686 image_unmap_file(fmap_link); 687 } 688 689 TRACE("not found\n"); 690 HeapFree(GetProcessHeap(), 0, p); 691 HeapFree(GetProcessHeap(), 0, fmap_link); 692 return FALSE; 693 } 694 695 /****************************************************************** 696 * image_check_alternate 697 * 698 * Load alternate files for a given image file, looking at either .note.gnu_build-id 699 * or .gnu_debuglink sections. 700 */ 701 BOOL image_check_alternate(struct image_file_map* fmap, const struct module* module) 702 { 703 BOOL ret = FALSE; 704 BOOL found = FALSE; 705 struct image_section_map buildid_sect, debuglink_sect; 706 707 /* if present, add the .gnu_debuglink file as an alternate to current one */ 708 if (image_find_section(fmap, ".note.gnu.build-id", &buildid_sect)) 709 { 710 const UINT32* note; 711 712 found = TRUE; 713 note = (const UINT32*)image_map_section(&buildid_sect); 714 if (note != IMAGE_NO_MAP) 715 { 716 /* the usual ELF note structure: name-size desc-size type <name> <desc> */ 717 if (note[2] == NOTE_GNU_BUILD_ID) 718 { 719 ret = image_locate_build_id_target(fmap, (const BYTE*)(note + 3 + ((note[0] + 3) >> 2)), note[1]); 720 } 721 } 722 image_unmap_section(&buildid_sect); 723 } 724 /* if present, add the .gnu_debuglink file as an alternate to current one */ 725 if (!ret && image_find_section(fmap, ".gnu_debuglink", &debuglink_sect)) 726 { 727 const char* dbg_link; 728 729 found = TRUE; 730 dbg_link = (const char*)image_map_section(&debuglink_sect); 731 if (dbg_link != IMAGE_NO_MAP) 732 { 733 /* The content of a debug link section is: 734 * 1/ a NULL terminated string, containing the file name for the 735 * debug info 736 * 2/ padding on 4 byte boundary 737 * 3/ CRC of the linked file 738 */ 739 DWORD crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3)); 740 ret = image_locate_debug_link(module, fmap, dbg_link, crc); 741 if (!ret) 742 WARN("Couldn't load linked debug file for %s\n", 743 debugstr_w(module->module.ModuleName)); 744 } 745 image_unmap_section(&debuglink_sect); 746 } 747 return found ? ret : TRUE; 748 } 749 750 /*********************************************************************** 751 * SymLoadModule (DBGHELP.@) 752 */ 753 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 754 PCSTR ModuleName, DWORD BaseOfDll, DWORD SizeOfDll) 755 { 756 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, 757 SizeOfDll, NULL, 0); 758 } 759 760 /*********************************************************************** 761 * SymLoadModuleEx (DBGHELP.@) 762 */ 763 DWORD64 WINAPI SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 764 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize, 765 PMODLOAD_DATA Data, DWORD Flags) 766 { 767 PWSTR wImageName, wModuleName; 768 unsigned len; 769 DWORD64 ret; 770 771 TRACE("(%p %p %s %s %s %08x %p %08x)\n", 772 hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName), 773 wine_dbgstr_longlong(BaseOfDll), DllSize, Data, Flags); 774 775 if (ImageName) 776 { 777 len = MultiByteToWideChar(CP_ACP, 0, ImageName, -1, NULL, 0); 778 wImageName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 779 MultiByteToWideChar(CP_ACP, 0, ImageName, -1, wImageName, len); 780 } 781 else wImageName = NULL; 782 if (ModuleName) 783 { 784 len = MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, NULL, 0); 785 wModuleName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 786 MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, wModuleName, len); 787 } 788 else wModuleName = NULL; 789 790 ret = SymLoadModuleExW(hProcess, hFile, wImageName, wModuleName, 791 BaseOfDll, DllSize, Data, Flags); 792 HeapFree(GetProcessHeap(), 0, wImageName); 793 HeapFree(GetProcessHeap(), 0, wModuleName); 794 return ret; 795 } 796 797 /*********************************************************************** 798 * SymLoadModuleExW (DBGHELP.@) 799 */ 800 DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName, 801 PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll, 802 PMODLOAD_DATA Data, DWORD Flags) 803 { 804 struct process* pcs; 805 struct module* module = NULL; 806 807 TRACE("(%p %p %s %s %s %08x %p %08x)\n", 808 hProcess, hFile, debugstr_w(wImageName), debugstr_w(wModuleName), 809 wine_dbgstr_longlong(BaseOfDll), SizeOfDll, Data, Flags); 810 811 if (Data) 812 FIXME("Unsupported load data parameter %p for %s\n", 813 Data, debugstr_w(wImageName)); 814 if (!validate_addr64(BaseOfDll)) return FALSE; 815 816 if (!(pcs = process_find_by_handle(hProcess))) return FALSE; 817 818 if (Flags & SLMFLAG_VIRTUAL) 819 { 820 if (!wImageName) return FALSE; 821 module = module_new(pcs, wImageName, DMT_PE, TRUE, BaseOfDll, SizeOfDll, 0, 0); 822 if (!module) return FALSE; 823 if (wModuleName) module_set_module(module, wModuleName); 824 module->module.SymType = SymVirtual; 825 826 return TRUE; 827 } 828 if (Flags & ~(SLMFLAG_VIRTUAL)) 829 FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName)); 830 831 pcs->loader->synchronize_module_list(pcs); 832 833 /* this is a Wine extension to the API just to redo the synchronisation */ 834 if (!wImageName && !hFile) return 0; 835 836 /* check if the module is already loaded, or if it's a builtin PE module with 837 * an containing ELF module 838 */ 839 if (wImageName) 840 { 841 module = module_is_already_loaded(pcs, wImageName); 842 if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll)) 843 { 844 /* force the loading of DLL as builtin */ 845 module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll); 846 } 847 } 848 if (!module) 849 { 850 /* otherwise, try a regular PE module */ 851 if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) && 852 wImageName) 853 { 854 /* and finally an ELF or Mach-O module */ 855 module = pcs->loader->load_module(pcs, wImageName, BaseOfDll); 856 } 857 } 858 if (!module) 859 { 860 WARN("Couldn't locate %s\n", debugstr_w(wImageName)); 861 return 0; 862 } 863 module->module.NumSyms = module->ht_symbols.num_elts; 864 /* by default module_new fills module.ModuleName from a derivation 865 * of LoadedImageName. Overwrite it, if we have better information 866 */ 867 if (wModuleName) 868 module_set_module(module, wModuleName); 869 if (wImageName) 870 lstrcpynW(module->module.ImageName, wImageName, ARRAY_SIZE(module->module.ImageName)); 871 872 return module->module.BaseOfImage; 873 } 874 875 /*********************************************************************** 876 * SymLoadModule64 (DBGHELP.@) 877 */ 878 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 879 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) 880 { 881 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll, 882 NULL, 0); 883 } 884 885 /****************************************************************** 886 * module_remove 887 * 888 */ 889 BOOL module_remove(struct process* pcs, struct module* module) 890 { 891 struct module_format*modfmt; 892 struct module** p; 893 unsigned i; 894 895 TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module); 896 897 for (i = 0; i < DFI_LAST; i++) 898 { 899 if ((modfmt = module->format_info[i]) && modfmt->remove) 900 modfmt->remove(pcs, module->format_info[i]); 901 } 902 hash_table_destroy(&module->ht_symbols); 903 hash_table_destroy(&module->ht_types); 904 HeapFree(GetProcessHeap(), 0, module->sources); 905 HeapFree(GetProcessHeap(), 0, module->addr_sorttab); 906 HeapFree(GetProcessHeap(), 0, module->real_path); 907 pool_destroy(&module->pool); 908 /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here 909 * so do we 910 */ 911 for (p = &pcs->lmodules; *p; p = &(*p)->next) 912 { 913 if (*p == module) 914 { 915 *p = module->next; 916 HeapFree(GetProcessHeap(), 0, module); 917 return TRUE; 918 } 919 } 920 FIXME("This shouldn't happen\n"); 921 return FALSE; 922 } 923 924 /****************************************************************** 925 * SymUnloadModule (DBGHELP.@) 926 * 927 */ 928 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll) 929 { 930 struct process* pcs; 931 struct module* module; 932 933 pcs = process_find_by_handle(hProcess); 934 if (!pcs) return FALSE; 935 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); 936 if (!module) return FALSE; 937 return module_remove(pcs, module); 938 } 939 940 /****************************************************************** 941 * SymUnloadModule64 (DBGHELP.@) 942 * 943 */ 944 BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll) 945 { 946 struct process* pcs; 947 struct module* module; 948 949 pcs = process_find_by_handle(hProcess); 950 if (!pcs) return FALSE; 951 if (!validate_addr64(BaseOfDll)) return FALSE; 952 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); 953 if (!module) return FALSE; 954 return module_remove(pcs, module); 955 } 956 957 /****************************************************************** 958 * SymEnumerateModules (DBGHELP.@) 959 * 960 */ 961 struct enum_modW64_32 962 { 963 PSYM_ENUMMODULES_CALLBACK cb; 964 PVOID user; 965 char module[MAX_PATH]; 966 }; 967 968 static BOOL CALLBACK enum_modW64_32(PCWSTR name, DWORD64 base, PVOID user) 969 { 970 struct enum_modW64_32* x = user; 971 972 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 973 return x->cb(x->module, (DWORD)base, x->user); 974 } 975 976 BOOL WINAPI SymEnumerateModules(HANDLE hProcess, 977 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, 978 PVOID UserContext) 979 { 980 struct enum_modW64_32 x; 981 982 x.cb = EnumModulesCallback; 983 x.user = UserContext; 984 985 return SymEnumerateModulesW64(hProcess, enum_modW64_32, &x); 986 } 987 988 /****************************************************************** 989 * SymEnumerateModules64 (DBGHELP.@) 990 * 991 */ 992 struct enum_modW64_64 993 { 994 PSYM_ENUMMODULES_CALLBACK64 cb; 995 PVOID user; 996 char module[MAX_PATH]; 997 }; 998 999 static BOOL CALLBACK enum_modW64_64(PCWSTR name, DWORD64 base, PVOID user) 1000 { 1001 struct enum_modW64_64* x = user; 1002 1003 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 1004 return x->cb(x->module, base, x->user); 1005 } 1006 1007 BOOL WINAPI SymEnumerateModules64(HANDLE hProcess, 1008 PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, 1009 PVOID UserContext) 1010 { 1011 struct enum_modW64_64 x; 1012 1013 x.cb = EnumModulesCallback; 1014 x.user = UserContext; 1015 1016 return SymEnumerateModulesW64(hProcess, enum_modW64_64, &x); 1017 } 1018 1019 /****************************************************************** 1020 * SymEnumerateModulesW64 (DBGHELP.@) 1021 * 1022 */ 1023 BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess, 1024 PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback, 1025 PVOID UserContext) 1026 { 1027 struct process* pcs = process_find_by_handle(hProcess); 1028 struct module* module; 1029 1030 if (!pcs) return FALSE; 1031 1032 for (module = pcs->lmodules; module; module = module->next) 1033 { 1034 if (!dbghelp_opt_native && 1035 (module->type == DMT_ELF || module->type == DMT_MACHO)) 1036 continue; 1037 if (!EnumModulesCallback(module->modulename, 1038 module->module.BaseOfImage, UserContext)) 1039 break; 1040 } 1041 return TRUE; 1042 } 1043 1044 #ifndef DBGHELP_STATIC_LIB 1045 /****************************************************************** 1046 * EnumerateLoadedModules64 (DBGHELP.@) 1047 * 1048 */ 1049 struct enum_load_modW64_64 1050 { 1051 PENUMLOADED_MODULES_CALLBACK64 cb; 1052 PVOID user; 1053 char module[MAX_PATH]; 1054 }; 1055 1056 static BOOL CALLBACK enum_load_modW64_64(PCWSTR name, DWORD64 base, ULONG size, 1057 PVOID user) 1058 { 1059 struct enum_load_modW64_64* x = user; 1060 1061 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 1062 return x->cb(x->module, base, size, x->user); 1063 } 1064 1065 BOOL WINAPI EnumerateLoadedModules64(HANDLE hProcess, 1066 PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, 1067 PVOID UserContext) 1068 { 1069 struct enum_load_modW64_64 x; 1070 1071 x.cb = EnumLoadedModulesCallback; 1072 x.user = UserContext; 1073 1074 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_64, &x); 1075 } 1076 1077 /****************************************************************** 1078 * EnumerateLoadedModules (DBGHELP.@) 1079 * 1080 */ 1081 struct enum_load_modW64_32 1082 { 1083 PENUMLOADED_MODULES_CALLBACK cb; 1084 PVOID user; 1085 char module[MAX_PATH]; 1086 }; 1087 1088 static BOOL CALLBACK enum_load_modW64_32(PCWSTR name, DWORD64 base, ULONG size, 1089 PVOID user) 1090 { 1091 struct enum_load_modW64_32* x = user; 1092 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 1093 return x->cb(x->module, (DWORD)base, size, x->user); 1094 } 1095 1096 BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess, 1097 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback, 1098 PVOID UserContext) 1099 { 1100 struct enum_load_modW64_32 x; 1101 1102 x.cb = EnumLoadedModulesCallback; 1103 x.user = UserContext; 1104 1105 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_32, &x); 1106 } 1107 1108 /****************************************************************** 1109 * EnumerateLoadedModulesW64 (DBGHELP.@) 1110 * 1111 */ 1112 BOOL WINAPI EnumerateLoadedModulesW64(HANDLE hProcess, 1113 PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, 1114 PVOID UserContext) 1115 { 1116 HMODULE* hMods; 1117 WCHAR baseW[256], modW[256]; 1118 DWORD i, sz; 1119 MODULEINFO mi; 1120 1121 hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0])); 1122 if (!hMods) return FALSE; 1123 1124 if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz)) 1125 { 1126 /* hProcess should also be a valid process handle !! */ 1127 FIXME("If this happens, bump the number in mod\n"); 1128 HeapFree(GetProcessHeap(), 0, hMods); 1129 return FALSE; 1130 } 1131 sz /= sizeof(HMODULE); 1132 for (i = 0; i < sz; i++) 1133 { 1134 if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) || 1135 !GetModuleBaseNameW(hProcess, hMods[i], baseW, ARRAY_SIZE(baseW))) 1136 continue; 1137 module_fill_module(baseW, modW, ARRAY_SIZE(modW)); 1138 EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage, 1139 UserContext); 1140 } 1141 HeapFree(GetProcessHeap(), 0, hMods); 1142 1143 return sz != 0 && i == sz; 1144 } 1145 1146 #endif /* DBGHELP_STATIC_LIB */ 1147 1148 static void dbghelp_str_WtoA(const WCHAR *src, char *dst, int dst_len) 1149 { 1150 WideCharToMultiByte(CP_ACP, 0, src, -1, dst, dst_len - 1, NULL, NULL); 1151 dst[dst_len - 1] = 0; 1152 } 1153 1154 /****************************************************************** 1155 * SymGetModuleInfo (DBGHELP.@) 1156 * 1157 */ 1158 BOOL WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 1159 PIMAGEHLP_MODULE ModuleInfo) 1160 { 1161 IMAGEHLP_MODULE mi; 1162 IMAGEHLP_MODULEW64 miw64; 1163 1164 if (sizeof(mi) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n"); 1165 1166 miw64.SizeOfStruct = sizeof(miw64); 1167 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 1168 1169 mi.SizeOfStruct = ModuleInfo->SizeOfStruct; 1170 mi.BaseOfImage = miw64.BaseOfImage; 1171 mi.ImageSize = miw64.ImageSize; 1172 mi.TimeDateStamp = miw64.TimeDateStamp; 1173 mi.CheckSum = miw64.CheckSum; 1174 mi.NumSyms = miw64.NumSyms; 1175 mi.SymType = miw64.SymType; 1176 dbghelp_str_WtoA(miw64.ModuleName, mi.ModuleName, sizeof(mi.ModuleName)); 1177 dbghelp_str_WtoA(miw64.ImageName, mi.ImageName, sizeof(mi.ImageName)); 1178 dbghelp_str_WtoA(miw64.LoadedImageName, mi.LoadedImageName, sizeof(mi.LoadedImageName)); 1179 1180 memcpy(ModuleInfo, &mi, ModuleInfo->SizeOfStruct); 1181 1182 return TRUE; 1183 } 1184 1185 /****************************************************************** 1186 * SymGetModuleInfoW (DBGHELP.@) 1187 * 1188 */ 1189 BOOL WINAPI SymGetModuleInfoW(HANDLE hProcess, DWORD dwAddr, 1190 PIMAGEHLP_MODULEW ModuleInfo) 1191 { 1192 IMAGEHLP_MODULEW64 miw64; 1193 IMAGEHLP_MODULEW miw; 1194 1195 if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n"); 1196 1197 miw64.SizeOfStruct = sizeof(miw64); 1198 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 1199 1200 miw.SizeOfStruct = ModuleInfo->SizeOfStruct; 1201 miw.BaseOfImage = miw64.BaseOfImage; 1202 miw.ImageSize = miw64.ImageSize; 1203 miw.TimeDateStamp = miw64.TimeDateStamp; 1204 miw.CheckSum = miw64.CheckSum; 1205 miw.NumSyms = miw64.NumSyms; 1206 miw.SymType = miw64.SymType; 1207 lstrcpyW(miw.ModuleName, miw64.ModuleName); 1208 lstrcpyW(miw.ImageName, miw64.ImageName); 1209 lstrcpyW(miw.LoadedImageName, miw64.LoadedImageName); 1210 memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct); 1211 1212 return TRUE; 1213 } 1214 1215 /****************************************************************** 1216 * SymGetModuleInfo64 (DBGHELP.@) 1217 * 1218 */ 1219 BOOL WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr, 1220 PIMAGEHLP_MODULE64 ModuleInfo) 1221 { 1222 IMAGEHLP_MODULE64 mi64; 1223 IMAGEHLP_MODULEW64 miw64; 1224 1225 if (sizeof(mi64) < ModuleInfo->SizeOfStruct) 1226 { 1227 SetLastError(ERROR_MOD_NOT_FOUND); /* NOTE: native returns this error */ 1228 WARN("Wrong size %u\n", ModuleInfo->SizeOfStruct); 1229 return FALSE; 1230 } 1231 1232 miw64.SizeOfStruct = sizeof(miw64); 1233 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 1234 1235 mi64.SizeOfStruct = ModuleInfo->SizeOfStruct; 1236 mi64.BaseOfImage = miw64.BaseOfImage; 1237 mi64.ImageSize = miw64.ImageSize; 1238 mi64.TimeDateStamp = miw64.TimeDateStamp; 1239 mi64.CheckSum = miw64.CheckSum; 1240 mi64.NumSyms = miw64.NumSyms; 1241 mi64.SymType = miw64.SymType; 1242 dbghelp_str_WtoA(miw64.ModuleName, mi64.ModuleName, sizeof(mi64.ModuleName)); 1243 dbghelp_str_WtoA(miw64.ImageName, mi64.ImageName, sizeof(mi64.ImageName)); 1244 dbghelp_str_WtoA(miw64.LoadedImageName, mi64.LoadedImageName, sizeof(mi64.LoadedImageName)); 1245 dbghelp_str_WtoA(miw64.LoadedPdbName, mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName)); 1246 1247 mi64.CVSig = miw64.CVSig; 1248 dbghelp_str_WtoA(miw64.CVData, mi64.CVData, sizeof(mi64.CVData)); 1249 mi64.PdbSig = miw64.PdbSig; 1250 mi64.PdbSig70 = miw64.PdbSig70; 1251 mi64.PdbAge = miw64.PdbAge; 1252 mi64.PdbUnmatched = miw64.PdbUnmatched; 1253 mi64.DbgUnmatched = miw64.DbgUnmatched; 1254 mi64.LineNumbers = miw64.LineNumbers; 1255 mi64.GlobalSymbols = miw64.GlobalSymbols; 1256 mi64.TypeInfo = miw64.TypeInfo; 1257 mi64.SourceIndexed = miw64.SourceIndexed; 1258 mi64.Publics = miw64.Publics; 1259 1260 memcpy(ModuleInfo, &mi64, ModuleInfo->SizeOfStruct); 1261 1262 return TRUE; 1263 } 1264 1265 /****************************************************************** 1266 * SymGetModuleInfoW64 (DBGHELP.@) 1267 * 1268 */ 1269 BOOL WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr, 1270 PIMAGEHLP_MODULEW64 ModuleInfo) 1271 { 1272 struct process* pcs = process_find_by_handle(hProcess); 1273 struct module* module; 1274 IMAGEHLP_MODULEW64 miw64; 1275 1276 TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo); 1277 1278 if (!pcs) return FALSE; 1279 if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE; 1280 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN); 1281 if (!module) return FALSE; 1282 1283 miw64 = module->module; 1284 1285 /* update debug information from container if any */ 1286 if (module->module.SymType == SymNone) 1287 { 1288 module = module_get_container(pcs, module); 1289 if (module && module->module.SymType != SymNone) 1290 { 1291 miw64.SymType = module->module.SymType; 1292 miw64.NumSyms = module->module.NumSyms; 1293 } 1294 } 1295 memcpy(ModuleInfo, &miw64, ModuleInfo->SizeOfStruct); 1296 return TRUE; 1297 } 1298 1299 /*********************************************************************** 1300 * SymGetModuleBase (DBGHELP.@) 1301 */ 1302 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr) 1303 { 1304 DWORD64 ret; 1305 1306 ret = SymGetModuleBase64(hProcess, dwAddr); 1307 return validate_addr64(ret) ? ret : 0; 1308 } 1309 1310 /*********************************************************************** 1311 * SymGetModuleBase64 (DBGHELP.@) 1312 */ 1313 DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) 1314 { 1315 struct process* pcs = process_find_by_handle(hProcess); 1316 struct module* module; 1317 1318 if (!pcs) return 0; 1319 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN); 1320 if (!module) return 0; 1321 return module->module.BaseOfImage; 1322 } 1323 1324 /****************************************************************** 1325 * module_reset_debug_info 1326 * Removes any debug information linked to a given module. 1327 */ 1328 void module_reset_debug_info(struct module* module) 1329 { 1330 module->sortlist_valid = TRUE; 1331 module->sorttab_size = 0; 1332 module->addr_sorttab = NULL; 1333 module->num_sorttab = module->num_symbols = 0; 1334 hash_table_destroy(&module->ht_symbols); 1335 module->ht_symbols.num_buckets = 0; 1336 module->ht_symbols.buckets = NULL; 1337 hash_table_destroy(&module->ht_types); 1338 module->ht_types.num_buckets = 0; 1339 module->ht_types.buckets = NULL; 1340 module->vtypes.num_elts = 0; 1341 hash_table_destroy(&module->ht_symbols); 1342 module->sources_used = module->sources_alloc = 0; 1343 module->sources = NULL; 1344 } 1345 1346 /****************************************************************** 1347 * SymRefreshModuleList (DBGHELP.@) 1348 */ 1349 BOOL WINAPI SymRefreshModuleList(HANDLE hProcess) 1350 { 1351 struct process* pcs; 1352 1353 TRACE("(%p)\n", hProcess); 1354 1355 if (!(pcs = process_find_by_handle(hProcess))) return FALSE; 1356 1357 return pcs->loader->synchronize_module_list(pcs); 1358 } 1359 1360 /*********************************************************************** 1361 * SymFunctionTableAccess (DBGHELP.@) 1362 */ 1363 PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase) 1364 { 1365 return SymFunctionTableAccess64(hProcess, AddrBase); 1366 } 1367 1368 /*********************************************************************** 1369 * SymFunctionTableAccess64 (DBGHELP.@) 1370 */ 1371 PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) 1372 { 1373 struct process* pcs = process_find_by_handle(hProcess); 1374 struct module* module; 1375 1376 if (!pcs || !dbghelp_current_cpu->find_runtime_function) return NULL; 1377 module = module_find_by_addr(pcs, AddrBase, DMT_UNKNOWN); 1378 if (!module) return NULL; 1379 1380 return dbghelp_current_cpu->find_runtime_function(module, AddrBase); 1381 } 1382 1383 static BOOL native_synchronize_module_list(struct process* pcs) 1384 { 1385 return FALSE; 1386 } 1387 1388 static struct module* native_load_module(struct process* pcs, const WCHAR* name, ULONG_PTR addr) 1389 { 1390 return NULL; 1391 } 1392 1393 static BOOL native_load_debug_info(struct process* process, struct module* module) 1394 { 1395 return FALSE; 1396 } 1397 1398 static BOOL native_enum_modules(struct process *process, enum_modules_cb cb, void* user) 1399 { 1400 return FALSE; 1401 } 1402 1403 static BOOL native_fetch_file_info(struct process* process, const WCHAR* name, ULONG_PTR load_addr, DWORD_PTR* base, 1404 DWORD* size, DWORD* checksum) 1405 { 1406 return FALSE; 1407 } 1408 1409 const struct loader_ops no_loader_ops = 1410 { 1411 native_synchronize_module_list, 1412 native_load_module, 1413 native_load_debug_info, 1414 native_enum_modules, 1415 native_fetch_file_info, 1416 }; 1417