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 static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'}; 546 static const WCHAR dotDebugW[] = {'.','d','e','b','u','g','/'}; 547 const size_t globalDebugDirLen = ARRAY_SIZE(globalDebugDirW); 548 size_t filename_len, path_len; 549 WCHAR* p = NULL; 550 WCHAR* slash; 551 WCHAR* slash2; 552 struct image_file_map* fmap_link = NULL; 553 554 fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link)); 555 if (!fmap_link) return FALSE; 556 557 filename_len = MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, NULL, 0); 558 path_len = lstrlenW(module->module.LoadedImageName); 559 if (module->real_path) path_len = max(path_len, lstrlenW(module->real_path)); 560 p = HeapAlloc(GetProcessHeap(), 0, 561 (globalDebugDirLen + path_len + 6 + 1 + filename_len + 1) * sizeof(WCHAR)); 562 if (!p) goto found; 563 564 /* we prebuild the string with "execdir" */ 565 lstrcpyW(p, module->module.LoadedImageName); 566 slash = p; 567 if ((slash2 = wcsrchr(slash, '/'))) slash = slash2 + 1; 568 if ((slash2 = wcsrchr(slash, '\\'))) slash = slash2 + 1; 569 570 /* testing execdir/filename */ 571 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); 572 if (image_check_debug_link(p, fmap_link, crc)) goto found; 573 574 /* testing execdir/.debug/filename */ 575 memcpy(slash, dotDebugW, sizeof(dotDebugW)); 576 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash + ARRAY_SIZE(dotDebugW), filename_len); 577 if (image_check_debug_link(p, fmap_link, crc)) goto found; 578 579 if (module->real_path) 580 { 581 lstrcpyW(p, module->real_path); 582 slash = p; 583 if ((slash2 = wcsrchr(slash, '/'))) slash = slash2 + 1; 584 if ((slash2 = wcsrchr(slash, '\\'))) slash = slash2 + 1; 585 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); 586 if (image_check_debug_link(p, fmap_link, crc)) goto found; 587 } 588 589 /* testing globaldebugdir/execdir/filename */ 590 memmove(p + globalDebugDirLen, p, (slash - p) * sizeof(WCHAR)); 591 memcpy(p, globalDebugDirW, globalDebugDirLen * sizeof(WCHAR)); 592 slash += globalDebugDirLen; 593 MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len); 594 if (image_check_debug_link(p, fmap_link, crc)) goto found; 595 596 /* finally testing filename */ 597 if (image_check_debug_link(slash, fmap_link, crc)) goto found; 598 599 600 WARN("Couldn't locate or map %s\n", filename); 601 HeapFree(GetProcessHeap(), 0, p); 602 HeapFree(GetProcessHeap(), 0, fmap_link); 603 return FALSE; 604 605 found: 606 TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p)); 607 HeapFree(GetProcessHeap(), 0, p); 608 fmap->alternate = fmap_link; 609 return TRUE; 610 } 611 612 /****************************************************************** 613 * image_locate_build_id_target 614 * 615 * Try to find the .so file containing the debug info out of the build-id note information 616 */ 617 static BOOL image_locate_build_id_target(struct image_file_map* fmap, const BYTE* id, unsigned idlen) 618 { 619 static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'}; 620 static const WCHAR buildidW[] = {'.','b','u','i','l','d','-','i','d','/'}; 621 static const WCHAR dotDebug0W[] = {'.','d','e','b','u','g',0}; 622 struct image_file_map* fmap_link = NULL; 623 WCHAR* p; 624 WCHAR* z; 625 const BYTE* idend = id + idlen; 626 627 fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link)); 628 if (!fmap_link) return FALSE; 629 630 p = HeapAlloc(GetProcessHeap(), 0, 631 sizeof(globalDebugDirW) + sizeof(buildidW) + 632 (idlen * 2 + 1) * sizeof(WCHAR) + sizeof(dotDebug0W)); 633 z = p; 634 memcpy(z, globalDebugDirW, sizeof(globalDebugDirW)); 635 z += ARRAY_SIZE(globalDebugDirW); 636 memcpy(z, buildidW, sizeof(buildidW)); 637 z += ARRAY_SIZE(buildidW); 638 639 if (id < idend) 640 { 641 *z++ = "0123456789abcdef"[*id >> 4 ]; 642 *z++ = "0123456789abcdef"[*id & 0x0F]; 643 id++; 644 } 645 if (id < idend) 646 *z++ = '/'; 647 while (id < idend) 648 { 649 *z++ = "0123456789abcdef"[*id >> 4 ]; 650 *z++ = "0123456789abcdef"[*id & 0x0F]; 651 id++; 652 } 653 memcpy(z, dotDebug0W, sizeof(dotDebug0W)); 654 TRACE("checking %s\n", wine_dbgstr_w(p)); 655 656 if (image_check_debug_link(p, fmap_link, 0)) 657 { 658 struct image_section_map buildid_sect; 659 if (image_find_section(fmap_link, ".note.gnu.build-id", &buildid_sect)) 660 { 661 const UINT32* note; 662 663 note = (const UINT32*)image_map_section(&buildid_sect); 664 if (note != IMAGE_NO_MAP) 665 { 666 /* the usual ELF note structure: name-size desc-size type <name> <desc> */ 667 if (note[2] == NOTE_GNU_BUILD_ID) 668 { 669 if (note[1] == idlen && 670 !memcmp(note + 3 + ((note[0] + 3) >> 2), idend - idlen, idlen)) 671 { 672 TRACE("Located debug information file at %s\n", debugstr_w(p)); 673 HeapFree(GetProcessHeap(), 0, p); 674 fmap->alternate = fmap_link; 675 return TRUE; 676 } 677 WARN("mismatch in buildid information for %s\n", wine_dbgstr_w(p)); 678 } 679 } 680 image_unmap_section(&buildid_sect); 681 } 682 image_unmap_file(fmap_link); 683 } 684 685 TRACE("not found\n"); 686 HeapFree(GetProcessHeap(), 0, p); 687 HeapFree(GetProcessHeap(), 0, fmap_link); 688 return FALSE; 689 } 690 691 /****************************************************************** 692 * image_check_alternate 693 * 694 * Load alternate files for a given image file, looking at either .note.gnu_build-id 695 * or .gnu_debuglink sections. 696 */ 697 BOOL image_check_alternate(struct image_file_map* fmap, const struct module* module) 698 { 699 BOOL ret = FALSE; 700 BOOL found = FALSE; 701 struct image_section_map buildid_sect, debuglink_sect; 702 703 /* if present, add the .gnu_debuglink file as an alternate to current one */ 704 if (image_find_section(fmap, ".note.gnu.build-id", &buildid_sect)) 705 { 706 const UINT32* note; 707 708 found = TRUE; 709 note = (const UINT32*)image_map_section(&buildid_sect); 710 if (note != IMAGE_NO_MAP) 711 { 712 /* the usual ELF note structure: name-size desc-size type <name> <desc> */ 713 if (note[2] == NOTE_GNU_BUILD_ID) 714 { 715 ret = image_locate_build_id_target(fmap, (const BYTE*)(note + 3 + ((note[0] + 3) >> 2)), note[1]); 716 } 717 } 718 image_unmap_section(&buildid_sect); 719 } 720 /* if present, add the .gnu_debuglink file as an alternate to current one */ 721 if (!ret && image_find_section(fmap, ".gnu_debuglink", &debuglink_sect)) 722 { 723 const char* dbg_link; 724 725 found = TRUE; 726 dbg_link = (const char*)image_map_section(&debuglink_sect); 727 if (dbg_link != IMAGE_NO_MAP) 728 { 729 /* The content of a debug link section is: 730 * 1/ a NULL terminated string, containing the file name for the 731 * debug info 732 * 2/ padding on 4 byte boundary 733 * 3/ CRC of the linked file 734 */ 735 DWORD crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3)); 736 ret = image_locate_debug_link(module, fmap, dbg_link, crc); 737 if (!ret) 738 WARN("Couldn't load linked debug file for %s\n", 739 debugstr_w(module->module.ModuleName)); 740 } 741 image_unmap_section(&debuglink_sect); 742 } 743 return found ? ret : TRUE; 744 } 745 746 /*********************************************************************** 747 * SymLoadModule (DBGHELP.@) 748 */ 749 DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 750 PCSTR ModuleName, DWORD BaseOfDll, DWORD SizeOfDll) 751 { 752 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, 753 SizeOfDll, NULL, 0); 754 } 755 756 /*********************************************************************** 757 * SymLoadModuleEx (DBGHELP.@) 758 */ 759 DWORD64 WINAPI SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 760 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize, 761 PMODLOAD_DATA Data, DWORD Flags) 762 { 763 PWSTR wImageName, wModuleName; 764 unsigned len; 765 DWORD64 ret; 766 767 TRACE("(%p %p %s %s %s %08x %p %08x)\n", 768 hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName), 769 wine_dbgstr_longlong(BaseOfDll), DllSize, Data, Flags); 770 771 if (ImageName) 772 { 773 len = MultiByteToWideChar(CP_ACP, 0, ImageName, -1, NULL, 0); 774 wImageName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 775 MultiByteToWideChar(CP_ACP, 0, ImageName, -1, wImageName, len); 776 } 777 else wImageName = NULL; 778 if (ModuleName) 779 { 780 len = MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, NULL, 0); 781 wModuleName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 782 MultiByteToWideChar(CP_ACP, 0, ModuleName, -1, wModuleName, len); 783 } 784 else wModuleName = NULL; 785 786 ret = SymLoadModuleExW(hProcess, hFile, wImageName, wModuleName, 787 BaseOfDll, DllSize, Data, Flags); 788 HeapFree(GetProcessHeap(), 0, wImageName); 789 HeapFree(GetProcessHeap(), 0, wModuleName); 790 return ret; 791 } 792 793 /*********************************************************************** 794 * SymLoadModuleExW (DBGHELP.@) 795 */ 796 DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName, 797 PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll, 798 PMODLOAD_DATA Data, DWORD Flags) 799 { 800 struct process* pcs; 801 struct module* module = NULL; 802 803 TRACE("(%p %p %s %s %s %08x %p %08x)\n", 804 hProcess, hFile, debugstr_w(wImageName), debugstr_w(wModuleName), 805 wine_dbgstr_longlong(BaseOfDll), SizeOfDll, Data, Flags); 806 807 if (Data) 808 FIXME("Unsupported load data parameter %p for %s\n", 809 Data, debugstr_w(wImageName)); 810 if (!validate_addr64(BaseOfDll)) return FALSE; 811 812 if (!(pcs = process_find_by_handle(hProcess))) return FALSE; 813 814 if (Flags & SLMFLAG_VIRTUAL) 815 { 816 if (!wImageName) return FALSE; 817 module = module_new(pcs, wImageName, DMT_PE, TRUE, BaseOfDll, SizeOfDll, 0, 0); 818 if (!module) return FALSE; 819 if (wModuleName) module_set_module(module, wModuleName); 820 module->module.SymType = SymVirtual; 821 822 return TRUE; 823 } 824 if (Flags & ~(SLMFLAG_VIRTUAL)) 825 FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName)); 826 827 pcs->loader->synchronize_module_list(pcs); 828 829 /* this is a Wine extension to the API just to redo the synchronisation */ 830 if (!wImageName && !hFile) return 0; 831 832 /* check if the module is already loaded, or if it's a builtin PE module with 833 * an containing ELF module 834 */ 835 if (wImageName) 836 { 837 module = module_is_already_loaded(pcs, wImageName); 838 if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll)) 839 { 840 /* force the loading of DLL as builtin */ 841 module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll); 842 } 843 } 844 if (!module) 845 { 846 /* otherwise, try a regular PE module */ 847 if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) && 848 wImageName) 849 { 850 /* and finally an ELF or Mach-O module */ 851 module = pcs->loader->load_module(pcs, wImageName, BaseOfDll); 852 } 853 } 854 if (!module) 855 { 856 WARN("Couldn't locate %s\n", debugstr_w(wImageName)); 857 return 0; 858 } 859 module->module.NumSyms = module->ht_symbols.num_elts; 860 /* by default module_new fills module.ModuleName from a derivation 861 * of LoadedImageName. Overwrite it, if we have better information 862 */ 863 if (wModuleName) 864 module_set_module(module, wModuleName); 865 if (wImageName) 866 lstrcpynW(module->module.ImageName, wImageName, ARRAY_SIZE(module->module.ImageName)); 867 868 return module->module.BaseOfImage; 869 } 870 871 /*********************************************************************** 872 * SymLoadModule64 (DBGHELP.@) 873 */ 874 DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName, 875 PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll) 876 { 877 return SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll, 878 NULL, 0); 879 } 880 881 /****************************************************************** 882 * module_remove 883 * 884 */ 885 BOOL module_remove(struct process* pcs, struct module* module) 886 { 887 struct module_format*modfmt; 888 struct module** p; 889 unsigned i; 890 891 TRACE("%s (%p)\n", debugstr_w(module->module.ModuleName), module); 892 893 for (i = 0; i < DFI_LAST; i++) 894 { 895 if ((modfmt = module->format_info[i]) && modfmt->remove) 896 modfmt->remove(pcs, module->format_info[i]); 897 } 898 hash_table_destroy(&module->ht_symbols); 899 hash_table_destroy(&module->ht_types); 900 HeapFree(GetProcessHeap(), 0, module->sources); 901 HeapFree(GetProcessHeap(), 0, module->addr_sorttab); 902 HeapFree(GetProcessHeap(), 0, module->real_path); 903 pool_destroy(&module->pool); 904 /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here 905 * so do we 906 */ 907 for (p = &pcs->lmodules; *p; p = &(*p)->next) 908 { 909 if (*p == module) 910 { 911 *p = module->next; 912 HeapFree(GetProcessHeap(), 0, module); 913 return TRUE; 914 } 915 } 916 FIXME("This shouldn't happen\n"); 917 return FALSE; 918 } 919 920 /****************************************************************** 921 * SymUnloadModule (DBGHELP.@) 922 * 923 */ 924 BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll) 925 { 926 struct process* pcs; 927 struct module* module; 928 929 pcs = process_find_by_handle(hProcess); 930 if (!pcs) return FALSE; 931 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); 932 if (!module) return FALSE; 933 return module_remove(pcs, module); 934 } 935 936 /****************************************************************** 937 * SymUnloadModule64 (DBGHELP.@) 938 * 939 */ 940 BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll) 941 { 942 struct process* pcs; 943 struct module* module; 944 945 pcs = process_find_by_handle(hProcess); 946 if (!pcs) return FALSE; 947 if (!validate_addr64(BaseOfDll)) return FALSE; 948 module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN); 949 if (!module) return FALSE; 950 return module_remove(pcs, module); 951 } 952 953 /****************************************************************** 954 * SymEnumerateModules (DBGHELP.@) 955 * 956 */ 957 struct enum_modW64_32 958 { 959 PSYM_ENUMMODULES_CALLBACK cb; 960 PVOID user; 961 char module[MAX_PATH]; 962 }; 963 964 static BOOL CALLBACK enum_modW64_32(PCWSTR name, DWORD64 base, PVOID user) 965 { 966 struct enum_modW64_32* x = user; 967 968 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 969 return x->cb(x->module, (DWORD)base, x->user); 970 } 971 972 BOOL WINAPI SymEnumerateModules(HANDLE hProcess, 973 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, 974 PVOID UserContext) 975 { 976 struct enum_modW64_32 x; 977 978 x.cb = EnumModulesCallback; 979 x.user = UserContext; 980 981 return SymEnumerateModulesW64(hProcess, enum_modW64_32, &x); 982 } 983 984 /****************************************************************** 985 * SymEnumerateModules64 (DBGHELP.@) 986 * 987 */ 988 struct enum_modW64_64 989 { 990 PSYM_ENUMMODULES_CALLBACK64 cb; 991 PVOID user; 992 char module[MAX_PATH]; 993 }; 994 995 static BOOL CALLBACK enum_modW64_64(PCWSTR name, DWORD64 base, PVOID user) 996 { 997 struct enum_modW64_64* x = user; 998 999 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 1000 return x->cb(x->module, base, x->user); 1001 } 1002 1003 BOOL WINAPI SymEnumerateModules64(HANDLE hProcess, 1004 PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback, 1005 PVOID UserContext) 1006 { 1007 struct enum_modW64_64 x; 1008 1009 x.cb = EnumModulesCallback; 1010 x.user = UserContext; 1011 1012 return SymEnumerateModulesW64(hProcess, enum_modW64_64, &x); 1013 } 1014 1015 /****************************************************************** 1016 * SymEnumerateModulesW64 (DBGHELP.@) 1017 * 1018 */ 1019 BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess, 1020 PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback, 1021 PVOID UserContext) 1022 { 1023 struct process* pcs = process_find_by_handle(hProcess); 1024 struct module* module; 1025 1026 if (!pcs) return FALSE; 1027 1028 for (module = pcs->lmodules; module; module = module->next) 1029 { 1030 if (!dbghelp_opt_native && 1031 (module->type == DMT_ELF || module->type == DMT_MACHO)) 1032 continue; 1033 if (!EnumModulesCallback(module->modulename, 1034 module->module.BaseOfImage, UserContext)) 1035 break; 1036 } 1037 return TRUE; 1038 } 1039 1040 #ifndef DBGHELP_STATIC_LIB 1041 /****************************************************************** 1042 * EnumerateLoadedModules64 (DBGHELP.@) 1043 * 1044 */ 1045 struct enum_load_modW64_64 1046 { 1047 PENUMLOADED_MODULES_CALLBACK64 cb; 1048 PVOID user; 1049 char module[MAX_PATH]; 1050 }; 1051 1052 static BOOL CALLBACK enum_load_modW64_64(PCWSTR name, DWORD64 base, ULONG size, 1053 PVOID user) 1054 { 1055 struct enum_load_modW64_64* x = user; 1056 1057 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 1058 return x->cb(x->module, base, size, x->user); 1059 } 1060 1061 BOOL WINAPI EnumerateLoadedModules64(HANDLE hProcess, 1062 PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback, 1063 PVOID UserContext) 1064 { 1065 struct enum_load_modW64_64 x; 1066 1067 x.cb = EnumLoadedModulesCallback; 1068 x.user = UserContext; 1069 1070 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_64, &x); 1071 } 1072 1073 /****************************************************************** 1074 * EnumerateLoadedModules (DBGHELP.@) 1075 * 1076 */ 1077 struct enum_load_modW64_32 1078 { 1079 PENUMLOADED_MODULES_CALLBACK cb; 1080 PVOID user; 1081 char module[MAX_PATH]; 1082 }; 1083 1084 static BOOL CALLBACK enum_load_modW64_32(PCWSTR name, DWORD64 base, ULONG size, 1085 PVOID user) 1086 { 1087 struct enum_load_modW64_32* x = user; 1088 WideCharToMultiByte(CP_ACP, 0, name, -1, x->module, sizeof(x->module), NULL, NULL); 1089 return x->cb(x->module, (DWORD)base, size, x->user); 1090 } 1091 1092 BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess, 1093 PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback, 1094 PVOID UserContext) 1095 { 1096 struct enum_load_modW64_32 x; 1097 1098 x.cb = EnumLoadedModulesCallback; 1099 x.user = UserContext; 1100 1101 return EnumerateLoadedModulesW64(hProcess, enum_load_modW64_32, &x); 1102 } 1103 1104 /****************************************************************** 1105 * EnumerateLoadedModulesW64 (DBGHELP.@) 1106 * 1107 */ 1108 BOOL WINAPI EnumerateLoadedModulesW64(HANDLE hProcess, 1109 PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback, 1110 PVOID UserContext) 1111 { 1112 HMODULE* hMods; 1113 WCHAR baseW[256], modW[256]; 1114 DWORD i, sz; 1115 MODULEINFO mi; 1116 1117 hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0])); 1118 if (!hMods) return FALSE; 1119 1120 if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz)) 1121 { 1122 /* hProcess should also be a valid process handle !! */ 1123 FIXME("If this happens, bump the number in mod\n"); 1124 HeapFree(GetProcessHeap(), 0, hMods); 1125 return FALSE; 1126 } 1127 sz /= sizeof(HMODULE); 1128 for (i = 0; i < sz; i++) 1129 { 1130 if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) || 1131 !GetModuleBaseNameW(hProcess, hMods[i], baseW, ARRAY_SIZE(baseW))) 1132 continue; 1133 module_fill_module(baseW, modW, ARRAY_SIZE(modW)); 1134 EnumLoadedModulesCallback(modW, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage, 1135 UserContext); 1136 } 1137 HeapFree(GetProcessHeap(), 0, hMods); 1138 1139 return sz != 0 && i == sz; 1140 } 1141 1142 #endif /* DBGHELP_STATIC_LIB */ 1143 1144 static void dbghelp_str_WtoA(const WCHAR *src, char *dst, int dst_len) 1145 { 1146 WideCharToMultiByte(CP_ACP, 0, src, -1, dst, dst_len - 1, NULL, NULL); 1147 dst[dst_len - 1] = 0; 1148 } 1149 1150 /****************************************************************** 1151 * SymGetModuleInfo (DBGHELP.@) 1152 * 1153 */ 1154 BOOL WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 1155 PIMAGEHLP_MODULE ModuleInfo) 1156 { 1157 IMAGEHLP_MODULE mi; 1158 IMAGEHLP_MODULEW64 miw64; 1159 1160 if (sizeof(mi) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n"); 1161 1162 miw64.SizeOfStruct = sizeof(miw64); 1163 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 1164 1165 mi.SizeOfStruct = ModuleInfo->SizeOfStruct; 1166 mi.BaseOfImage = miw64.BaseOfImage; 1167 mi.ImageSize = miw64.ImageSize; 1168 mi.TimeDateStamp = miw64.TimeDateStamp; 1169 mi.CheckSum = miw64.CheckSum; 1170 mi.NumSyms = miw64.NumSyms; 1171 mi.SymType = miw64.SymType; 1172 dbghelp_str_WtoA(miw64.ModuleName, mi.ModuleName, sizeof(mi.ModuleName)); 1173 dbghelp_str_WtoA(miw64.ImageName, mi.ImageName, sizeof(mi.ImageName)); 1174 dbghelp_str_WtoA(miw64.LoadedImageName, mi.LoadedImageName, sizeof(mi.LoadedImageName)); 1175 1176 memcpy(ModuleInfo, &mi, ModuleInfo->SizeOfStruct); 1177 1178 return TRUE; 1179 } 1180 1181 /****************************************************************** 1182 * SymGetModuleInfoW (DBGHELP.@) 1183 * 1184 */ 1185 BOOL WINAPI SymGetModuleInfoW(HANDLE hProcess, DWORD dwAddr, 1186 PIMAGEHLP_MODULEW ModuleInfo) 1187 { 1188 IMAGEHLP_MODULEW64 miw64; 1189 IMAGEHLP_MODULEW miw; 1190 1191 if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n"); 1192 1193 miw64.SizeOfStruct = sizeof(miw64); 1194 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 1195 1196 miw.SizeOfStruct = ModuleInfo->SizeOfStruct; 1197 miw.BaseOfImage = miw64.BaseOfImage; 1198 miw.ImageSize = miw64.ImageSize; 1199 miw.TimeDateStamp = miw64.TimeDateStamp; 1200 miw.CheckSum = miw64.CheckSum; 1201 miw.NumSyms = miw64.NumSyms; 1202 miw.SymType = miw64.SymType; 1203 lstrcpyW(miw.ModuleName, miw64.ModuleName); 1204 lstrcpyW(miw.ImageName, miw64.ImageName); 1205 lstrcpyW(miw.LoadedImageName, miw64.LoadedImageName); 1206 memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct); 1207 1208 return TRUE; 1209 } 1210 1211 /****************************************************************** 1212 * SymGetModuleInfo64 (DBGHELP.@) 1213 * 1214 */ 1215 BOOL WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr, 1216 PIMAGEHLP_MODULE64 ModuleInfo) 1217 { 1218 IMAGEHLP_MODULE64 mi64; 1219 IMAGEHLP_MODULEW64 miw64; 1220 1221 if (sizeof(mi64) < ModuleInfo->SizeOfStruct) 1222 { 1223 SetLastError(ERROR_MOD_NOT_FOUND); /* NOTE: native returns this error */ 1224 WARN("Wrong size %u\n", ModuleInfo->SizeOfStruct); 1225 return FALSE; 1226 } 1227 1228 miw64.SizeOfStruct = sizeof(miw64); 1229 if (!SymGetModuleInfoW64(hProcess, dwAddr, &miw64)) return FALSE; 1230 1231 mi64.SizeOfStruct = ModuleInfo->SizeOfStruct; 1232 mi64.BaseOfImage = miw64.BaseOfImage; 1233 mi64.ImageSize = miw64.ImageSize; 1234 mi64.TimeDateStamp = miw64.TimeDateStamp; 1235 mi64.CheckSum = miw64.CheckSum; 1236 mi64.NumSyms = miw64.NumSyms; 1237 mi64.SymType = miw64.SymType; 1238 dbghelp_str_WtoA(miw64.ModuleName, mi64.ModuleName, sizeof(mi64.ModuleName)); 1239 dbghelp_str_WtoA(miw64.ImageName, mi64.ImageName, sizeof(mi64.ImageName)); 1240 dbghelp_str_WtoA(miw64.LoadedImageName, mi64.LoadedImageName, sizeof(mi64.LoadedImageName)); 1241 dbghelp_str_WtoA(miw64.LoadedPdbName, mi64.LoadedPdbName, sizeof(mi64.LoadedPdbName)); 1242 1243 mi64.CVSig = miw64.CVSig; 1244 dbghelp_str_WtoA(miw64.CVData, mi64.CVData, sizeof(mi64.CVData)); 1245 mi64.PdbSig = miw64.PdbSig; 1246 mi64.PdbSig70 = miw64.PdbSig70; 1247 mi64.PdbAge = miw64.PdbAge; 1248 mi64.PdbUnmatched = miw64.PdbUnmatched; 1249 mi64.DbgUnmatched = miw64.DbgUnmatched; 1250 mi64.LineNumbers = miw64.LineNumbers; 1251 mi64.GlobalSymbols = miw64.GlobalSymbols; 1252 mi64.TypeInfo = miw64.TypeInfo; 1253 mi64.SourceIndexed = miw64.SourceIndexed; 1254 mi64.Publics = miw64.Publics; 1255 1256 memcpy(ModuleInfo, &mi64, ModuleInfo->SizeOfStruct); 1257 1258 return TRUE; 1259 } 1260 1261 /****************************************************************** 1262 * SymGetModuleInfoW64 (DBGHELP.@) 1263 * 1264 */ 1265 BOOL WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr, 1266 PIMAGEHLP_MODULEW64 ModuleInfo) 1267 { 1268 struct process* pcs = process_find_by_handle(hProcess); 1269 struct module* module; 1270 IMAGEHLP_MODULEW64 miw64; 1271 1272 TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo); 1273 1274 if (!pcs) return FALSE; 1275 if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE; 1276 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN); 1277 if (!module) return FALSE; 1278 1279 miw64 = module->module; 1280 1281 /* update debug information from container if any */ 1282 if (module->module.SymType == SymNone) 1283 { 1284 module = module_get_container(pcs, module); 1285 if (module && module->module.SymType != SymNone) 1286 { 1287 miw64.SymType = module->module.SymType; 1288 miw64.NumSyms = module->module.NumSyms; 1289 } 1290 } 1291 memcpy(ModuleInfo, &miw64, ModuleInfo->SizeOfStruct); 1292 return TRUE; 1293 } 1294 1295 /*********************************************************************** 1296 * SymGetModuleBase (DBGHELP.@) 1297 */ 1298 DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr) 1299 { 1300 DWORD64 ret; 1301 1302 ret = SymGetModuleBase64(hProcess, dwAddr); 1303 return validate_addr64(ret) ? ret : 0; 1304 } 1305 1306 /*********************************************************************** 1307 * SymGetModuleBase64 (DBGHELP.@) 1308 */ 1309 DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr) 1310 { 1311 struct process* pcs = process_find_by_handle(hProcess); 1312 struct module* module; 1313 1314 if (!pcs) return 0; 1315 module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN); 1316 if (!module) return 0; 1317 return module->module.BaseOfImage; 1318 } 1319 1320 /****************************************************************** 1321 * module_reset_debug_info 1322 * Removes any debug information linked to a given module. 1323 */ 1324 void module_reset_debug_info(struct module* module) 1325 { 1326 module->sortlist_valid = TRUE; 1327 module->sorttab_size = 0; 1328 module->addr_sorttab = NULL; 1329 module->num_sorttab = module->num_symbols = 0; 1330 hash_table_destroy(&module->ht_symbols); 1331 module->ht_symbols.num_buckets = 0; 1332 module->ht_symbols.buckets = NULL; 1333 hash_table_destroy(&module->ht_types); 1334 module->ht_types.num_buckets = 0; 1335 module->ht_types.buckets = NULL; 1336 module->vtypes.num_elts = 0; 1337 hash_table_destroy(&module->ht_symbols); 1338 module->sources_used = module->sources_alloc = 0; 1339 module->sources = NULL; 1340 } 1341 1342 /****************************************************************** 1343 * SymRefreshModuleList (DBGHELP.@) 1344 */ 1345 BOOL WINAPI SymRefreshModuleList(HANDLE hProcess) 1346 { 1347 struct process* pcs; 1348 1349 TRACE("(%p)\n", hProcess); 1350 1351 if (!(pcs = process_find_by_handle(hProcess))) return FALSE; 1352 1353 return pcs->loader->synchronize_module_list(pcs); 1354 } 1355 1356 /*********************************************************************** 1357 * SymFunctionTableAccess (DBGHELP.@) 1358 */ 1359 PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase) 1360 { 1361 return SymFunctionTableAccess64(hProcess, AddrBase); 1362 } 1363 1364 /*********************************************************************** 1365 * SymFunctionTableAccess64 (DBGHELP.@) 1366 */ 1367 PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) 1368 { 1369 struct process* pcs = process_find_by_handle(hProcess); 1370 struct module* module; 1371 1372 if (!pcs || !dbghelp_current_cpu->find_runtime_function) return NULL; 1373 module = module_find_by_addr(pcs, AddrBase, DMT_UNKNOWN); 1374 if (!module) return NULL; 1375 1376 return dbghelp_current_cpu->find_runtime_function(module, AddrBase); 1377 } 1378 1379 static BOOL native_synchronize_module_list(struct process* pcs) 1380 { 1381 return FALSE; 1382 } 1383 1384 static struct module* native_load_module(struct process* pcs, const WCHAR* name, ULONG_PTR addr) 1385 { 1386 return NULL; 1387 } 1388 1389 static BOOL native_load_debug_info(struct process* process, struct module* module) 1390 { 1391 return FALSE; 1392 } 1393 1394 static BOOL native_enum_modules(struct process *process, enum_modules_cb cb, void* user) 1395 { 1396 return FALSE; 1397 } 1398 1399 static BOOL native_fetch_file_info(struct process* process, const WCHAR* name, ULONG_PTR load_addr, DWORD_PTR* base, 1400 DWORD* size, DWORD* checksum) 1401 { 1402 return FALSE; 1403 } 1404 1405 const struct loader_ops no_loader_ops = 1406 { 1407 native_synchronize_module_list, 1408 native_load_module, 1409 native_load_debug_info, 1410 native_enum_modules, 1411 native_fetch_file_info, 1412 }; 1413