module.c 30.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * File module.c - module handling for the wine debugger
 *
 * Copyright (C) 1993,      Eric Youngdale.
 * 		 2000-2004, Eric Pouech
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 23 24 25 26 27 28 29 30 31 32
 */

#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#include "dbghelp_private.h"
#include "psapi.h"
#include "winreg.h"
#include "winternl.h"
#include "wine/debug.h"
33
#include "winnls.h"
34 35 36

WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);

37
static const char * const ext[] = {".acm", ".dll", ".drv", ".exe", ".ocx", ".vxd", NULL};
38 39 40

static int match_ext(const char* ptr, size_t len)
{
41
    const char * const *e;
42 43 44 45 46 47 48 49 50 51 52 53 54
    size_t      l;

    for (e = ext; *e; e++)
    {
        l = strlen(*e);
        if (l >= len) return FALSE;
        if (strncasecmp(&ptr[len - l], *e, l)) continue;
        return l;
    }
    return 0;
}
        
static void module_fill_module(const char* in, char* out, size_t size)
55
{
56 57
    const char  *ptr,*endptr;
    size_t      len, l;
58

59 60 61
    endptr = in + strlen(in);
    for (ptr = endptr - 1;
         ptr >= in && *ptr != '/' && *ptr != '\\';
62
         ptr--);
63 64 65 66
    ptr++;
    len = min(endptr-ptr,size-1);
    memcpy(out, ptr, len);
    out[len] = '\0';
67 68 69
    if (len > 4 && (l = match_ext(out, len)))
        out[len - l] = '\0';
    else if (len > 12 &&
70 71
             (!strcasecmp(out + len - 12, "wine-pthread") || 
              !strcasecmp(out + len - 12, "wine-kthread")))
72
        lstrcpynA(out, "<wine-loader>", size);
73 74
    else
    {
75 76 77
        if (len > 3 && !strcasecmp(&out[len - 3], ".so") &&
            (l = match_ext(out, len - 3)))
            strcpy(&out[len - l - 3], "<elf>");
78
    }
79 80 81
    while ((*out = tolower(*out))) out++;
}

Eric Pouech's avatar
Eric Pouech committed
82
static const char*      get_module_type(enum module_type type, BOOL virtual)
83 84 85
{
    switch (type)
    {
Eric Pouech's avatar
Eric Pouech committed
86 87
    case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
    case DMT_PE: return virtual ? "Virtual PE" : "PE";
88 89 90 91
    default: return "---";
    }
}

92 93 94 95
/***********************************************************************
 * Creates and links a new module to a process 
 */
struct module* module_new(struct process* pcs, const char* name, 
Eric Pouech's avatar
Eric Pouech committed
96
                          enum module_type type, BOOL virtual,
97 98 99 100 101
                          unsigned long mod_addr, unsigned long size,
                          unsigned long stamp, unsigned long checksum) 
{
    struct module*      module;

Eric Pouech's avatar
Eric Pouech committed
102
    assert(type == DMT_ELF || type == DMT_PE);
103 104 105 106 107 108 109 110 111
    if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
	return NULL;

    memset(module, 0, sizeof(*module));

    module->next = pcs->lmodules;
    pcs->lmodules = module;

    TRACE("=> %s %08lx-%08lx %s\n", 
Eric Pouech's avatar
Eric Pouech committed
112
          get_module_type(type, virtual), mod_addr, mod_addr + size, name);
113 114 115 116 117 118

    pool_init(&module->pool, 65536);
    
    module->module.SizeOfStruct = sizeof(module->module);
    module->module.BaseOfImage = mod_addr;
    module->module.ImageSize = size;
119 120
    module_fill_module(name, module->module.ModuleName,
                       sizeof(module->module.ModuleName));
121
    module->module.ImageName[0] = '\0';
122
    lstrcpynA(module->module.LoadedImageName, name, sizeof(module->module.LoadedImageName));
123 124 125 126 127
    module->module.SymType = SymNone;
    module->module.NumSyms = 0;
    module->module.TimeDateStamp = stamp;
    module->module.CheckSum = checksum;

Eric Pouech's avatar
Eric Pouech committed
128 129 130 131 132 133 134 135 136 137 138
    memset(module->module.LoadedPdbName, 0, sizeof(module->module.CVData));
    module->module.CVSig = 0;
    memset(module->module.CVData, 0, sizeof(module->module.CVData));
    module->module.PdbSig = 0;
    memset(&module->module.PdbSig70, 0, sizeof(module->module.PdbSig70));
    module->module.PdbAge = 0;
    module->module.PdbUnmatched = FALSE;
    module->module.DbgUnmatched = FALSE;
    module->module.LineNumbers = FALSE;
    module->module.GlobalSymbols = FALSE;
    module->module.TypeInfo = FALSE;
139 140
    module->module.SourceIndexed = FALSE;
    module->module.Publics = FALSE;
Eric Pouech's avatar
Eric Pouech committed
141

142
    module->type              = type;
Eric Pouech's avatar
Eric Pouech committed
143
    module->is_virtual        = virtual ? TRUE : FALSE;
144 145 146 147 148 149 150
    module->sortlist_valid    = FALSE;
    module->addr_sorttab      = NULL;
    /* FIXME: this seems a bit too high (on a per module basis)
     * need some statistics about this
     */
    hash_table_init(&module->pool, &module->ht_symbols, 4096);
    hash_table_init(&module->pool, &module->ht_types,   4096);
151
    vector_init(&module->vtypes, sizeof(struct symt*),  32);
152 153 154 155 156 157 158 159 160 161 162 163 164

    module->sources_used      = 0;
    module->sources_alloc     = 0;
    module->sources           = 0;

    return module;
}

/***********************************************************************
 *	module_find_by_name
 *
 */
struct module* module_find_by_name(const struct process* pcs, 
165
                                   const char* name, enum module_type type)
166 167 168 169 170 171
{
    struct module*      module;

    if (type == DMT_UNKNOWN)
    {
        if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
Eric Pouech's avatar
Eric Pouech committed
172
            (module = module_find_by_name(pcs, name, DMT_ELF)))
173 174 175 176
            return module;
    }
    else
    {
177 178
        char                modname[MAX_PATH];

179 180
        for (module = pcs->lmodules; module; module = module->next)
        {
181 182
            if (type == module->type &&
                !strcasecmp(name, module->module.LoadedImageName)) 
183 184
                return module;
        }
185
        module_fill_module(name, modname, sizeof(modname));
186 187
        for (module = pcs->lmodules; module; module = module->next)
        {
188 189
            if (type == module->type &&
                !strcasecmp(modname, module->module.ModuleName)) 
190 191 192 193 194 195 196 197
                return module;
        }
    }
    SetLastError(ERROR_INVALID_NAME);
    return NULL;
}

/***********************************************************************
198
 *           module_get_container
199 200
 *
 */
201 202
struct module* module_get_container(const struct process* pcs, 
                                    const struct module* inner)
203 204 205 206 207 208 209 210 211 212 213 214 215 216
{
    struct module*      module;
     
    for (module = pcs->lmodules; module; module = module->next)
    {
        if (module != inner &&
            module->module.BaseOfImage <= inner->module.BaseOfImage &&
            module->module.BaseOfImage + module->module.ImageSize >=
            inner->module.BaseOfImage + inner->module.ImageSize)
            return module;
    }
    return NULL;
}

217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
/***********************************************************************
 *           module_get_containee
 *
 */
struct module* module_get_containee(const struct process* pcs, 
                                    const struct module* outter)
{
    struct module*      module;
     
    for (module = pcs->lmodules; module; module = module->next)
    {
        if (module != outter &&
            outter->module.BaseOfImage <= module->module.BaseOfImage &&
            outter->module.BaseOfImage + outter->module.ImageSize >=
            module->module.BaseOfImage + module->module.ImageSize)
            return module;
    }
    return NULL;
}

237 238 239 240 241 242 243 244 245 246
/******************************************************************
 *		module_get_debug
 *
 * get the debug information from a module:
 * - if the module's type is deferred, then force loading of debug info (and return
 *   the module itself)
 * - if the module has no debug info and has an ELF container, then return the ELF
 *   container (and also force the ELF container's debug info loading if deferred)
 * - otherwise return the module itself if it has some debug info
 */
247
BOOL module_get_debug(struct module_pair* pair)
248
{
249
    IMAGEHLP_DEFERRED_SYMBOL_LOAD64     idsl64;
250

Eric Pouech's avatar
Eric Pouech committed
251 252
    if (!pair->requested) return FALSE;
    /* for a PE builtin, always get info from container */
253
    if (!(pair->effective = module_get_container(pair->pcs, pair->requested)))
Eric Pouech's avatar
Eric Pouech committed
254
        pair->effective = pair->requested;
255
    /* if deferred, force loading */
Eric Pouech's avatar
Eric Pouech committed
256
    if (pair->effective->module.SymType == SymDeferred)
257
    {
258
        BOOL ret;
Eric Pouech's avatar
Eric Pouech committed
259
        
Eric Pouech's avatar
Eric Pouech committed
260 261
        if (pair->effective->is_virtual) ret = FALSE;
        else switch (pair->effective->type)
262
        {
263
        case DMT_ELF:
Eric Pouech's avatar
Eric Pouech committed
264
            ret = elf_load_debug_info(pair->effective, NULL);
265 266 267
            break;
        case DMT_PE:
            idsl64.SizeOfStruct = sizeof(idsl64);
Eric Pouech's avatar
Eric Pouech committed
268 269 270 271
            idsl64.BaseOfImage = pair->effective->module.BaseOfImage;
            idsl64.CheckSum = pair->effective->module.CheckSum;
            idsl64.TimeDateStamp = pair->effective->module.TimeDateStamp;
            strcpy(idsl64.FileName, pair->effective->module.ImageName);
272 273 274
            idsl64.Reparse = FALSE;
            idsl64.hFile = INVALID_HANDLE_VALUE;

275 276 277
            pcs_callback(pair->pcs, CBA_DEFERRED_SYMBOL_LOAD_START, &idsl64);
            ret = pe_load_debug_info(pair->pcs, pair->effective);
            pcs_callback(pair->pcs,
278 279 280 281 282 283
                         ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
                         &idsl64);
            break;
        default:
            ret = FALSE;
            break;
284
        }
Eric Pouech's avatar
Eric Pouech committed
285 286
        if (!ret) pair->effective->module.SymType = SymNone;
        assert(pair->effective->module.SymType != SymDeferred);
287
        pair->effective->module.NumSyms = pair->effective->ht_symbols.num_elts;
288
    }
Eric Pouech's avatar
Eric Pouech committed
289
    return pair->effective->module.SymType != SymNone;
290 291 292 293 294 295 296 297 298
}

/***********************************************************************
 *	module_find_by_addr
 *
 * either the addr where module is loaded, or any address inside the 
 * module
 */
struct module* module_find_by_addr(const struct process* pcs, unsigned long addr, 
299
                                   enum module_type type)
300 301 302 303 304 305
{
    struct module*      module;
    
    if (type == DMT_UNKNOWN)
    {
        if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
Eric Pouech's avatar
Eric Pouech committed
306
            (module = module_find_by_addr(pcs, addr, DMT_ELF)))
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
            return module;
    }
    else
    {
        for (module = pcs->lmodules; module; module = module->next)
        {
            if (type == module->type && addr >= module->module.BaseOfImage &&
                addr < module->module.BaseOfImage + module->module.ImageSize) 
                return module;
        }
    }
    SetLastError(ERROR_INVALID_ADDRESS);
    return module;
}

322
static BOOL module_is_elf_container_loaded(struct process* pcs, const char* ImageName,
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
                                           const char* ModuleName)
{
    char                buffer[MAX_PATH];
    size_t              len;
    struct module*      module;

    if (!ModuleName)
    {
        module_fill_module(ImageName, buffer, sizeof(buffer));
        ModuleName = buffer;
    }
    len = strlen(ModuleName);
    for (module = pcs->lmodules; module; module = module->next)
    {
        if (!strncasecmp(module->module.ModuleName, ModuleName, len) &&
            module->type == DMT_ELF &&
            !strcmp(module->module.ModuleName + len, "<elf>"))
            return TRUE;
    }
    return FALSE;
}

345 346 347 348 349 350
/******************************************************************
 *		module_get_type_by_name
 *
 * Guesses a filename type from its extension
 */
enum module_type module_get_type_by_name(const char* name)
351 352 353 354
{
    const char* ptr;
    int         len = strlen(name);

355 356 357
    /* check for terminating .so or .so.[digit] */
    ptr = strrchr(name, '.');
    if (ptr)
358
    {
359 360 361 362 363
        if (!strcmp(ptr, ".so") ||
            (isdigit(ptr[1]) && !ptr[2] && ptr >= name + 3 && !memcmp(ptr - 3, ".so", 3)))
            return DMT_ELF;
        else if (!strcasecmp(ptr, ".pdb"))
            return DMT_PDB;
364
    }
365 366
    /* wine-[kp]thread is also an ELF module */
    else if (((len > 12 && name[len - 13] == '/') || len == 12) && 
367 368
             (!strcasecmp(name + len - 12, "wine-pthread") || 
              !strcasecmp(name + len - 12, "wine-kthread")))
369 370 371 372
    {
        return DMT_ELF;
    }
    return DMT_PE;
373 374
}

375 376 377
/***********************************************************************
 *			SymLoadModule (DBGHELP.@)
 */
378 379
DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, const char* ImageName,
                           const char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
380 381 382 383
{
    struct process*     pcs;
    struct module*	module = NULL;

384 385
    TRACE("(%p %p %s %s %08x %08x)\n",
          hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName),
386 387 388 389 390
          BaseOfDll, SizeOfDll);

    pcs = process_find_by_handle(hProcess);
    if (!pcs) return FALSE;

391 392 393 394 395 396 397
    /* force transparent ELF loading / unloading */
    elf_synchronize_module_list(pcs);

    /* this is a Wine extension to the API just to redo the synchronisation */
    if (!ImageName && !hFile) return 0;

    if (module_is_elf_container_loaded(pcs, ImageName, ModuleName))
398
    {
399
        /* force the loading of DLL as builtin */
400 401
        if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
                                              BaseOfDll, SizeOfDll)))
402 403
            goto done;
        WARN("Couldn't locate %s\n", ImageName);
404 405
        return 0;
    }
406
    TRACE("Assuming %s as native DLL\n", ImageName);
407 408
    if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
    {
409
        if (module_get_type_by_name(ImageName) == DMT_ELF &&
410 411 412 413
            (module = elf_load_module(pcs, ImageName, BaseOfDll)))
            goto done;
        FIXME("Should have successfully loaded debug information for image %s\n",
              ImageName);
414 415
        if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName,
                                              BaseOfDll, SizeOfDll)))
416 417 418 419
            goto done;
        WARN("Couldn't locate %s\n", ImageName);
        return 0;
    }
420
    module->module.NumSyms = module->ht_symbols.num_elts;
421 422 423 424 425
done:
    /* by default pe_load_module fills module.ModuleName from a derivation 
     * of ImageName. Overwrite it, if we have better information
     */
    if (ModuleName)
426 427
        lstrcpynA(module->module.ModuleName, ModuleName, sizeof(module->module.ModuleName));
    lstrcpynA(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
428 429 430 431

    return module->module.BaseOfImage;
}

432 433 434 435 436 437 438
/***********************************************************************
 *			SymLoadModuleEx (DBGHELP.@)
 */
DWORD64 WINAPI  SymLoadModuleEx(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
                                PCSTR ModuleName, DWORD64 BaseOfDll, DWORD DllSize,
                                PMODLOAD_DATA Data, DWORD Flags)
{
439 440
    TRACE("(%p %p %s %s %s %08x %p %08x)\n",
          hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName),
Eric Pouech's avatar
Eric Pouech committed
441 442
          wine_dbgstr_longlong(BaseOfDll), DllSize, Data, Flags);

443 444 445 446
    if (Data)
        FIXME("Unsupported load data parameter %p for %s\n", Data, ImageName);
    if (!validate_addr64(BaseOfDll)) return FALSE;
    if (Flags & SLMFLAG_VIRTUAL)
447
    {
448 449 450 451
        struct process* pcs = process_find_by_handle(hProcess);
        struct module* module;
        if (!pcs) return FALSE;

Eric Pouech's avatar
Eric Pouech committed
452 453
        module = module_new(pcs, ImageName, module_get_type_by_name(ImageName), TRUE, 
                            (DWORD)BaseOfDll, DllSize, 0, 0);
454 455 456
        if (!module) return FALSE;
        if (ModuleName)
            lstrcpynA(module->module.ModuleName, ModuleName, sizeof(module->module.ModuleName));
457
        module->module.SymType = SymVirtual;
458 459

        return TRUE;
460
    }
461
    if (Flags & ~(SLMFLAG_VIRTUAL))
462
        FIXME("Unsupported Flags %08x for %s\n", Flags, ImageName);
463

464
    return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, DllSize);
465 466
}

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
/***********************************************************************
 *			SymLoadModuleExW (DBGHELP.@)
 */
DWORD64 WINAPI  SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageName,
                                 PCWSTR wModuleName, DWORD64 BaseOfDll, DWORD DllSize,
                                 PMODLOAD_DATA Data, DWORD Flags)
{
    LPSTR       ImageName, ModuleName;
    unsigned    len;
    BOOL        ret;

    if (wImageName)
    {
        len = WideCharToMultiByte(CP_ACP,0, wImageName, -1, NULL, 0, NULL, NULL);
        ImageName = HeapAlloc(GetProcessHeap(), 0, len);
        WideCharToMultiByte(CP_ACP,0, wImageName, -1, ImageName, len, NULL, NULL);
    }
    else ImageName = NULL;
    if (wModuleName)
    {
        len = WideCharToMultiByte(CP_ACP,0, wModuleName, -1, NULL, 0, NULL, NULL);
        ModuleName = HeapAlloc(GetProcessHeap(), 0, len);
        WideCharToMultiByte(CP_ACP,0, wModuleName, -1, ModuleName, len, NULL, NULL);
    }
    else ModuleName = NULL;

    ret = SymLoadModuleEx(hProcess, hFile, ImageName, ModuleName,
                          BaseOfDll, DllSize, Data, Flags);
    HeapFree(GetProcessHeap(), 0, ImageName);
    HeapFree(GetProcessHeap(), 0, ModuleName);
    return ret;
}

Paul Vriens's avatar
Paul Vriens committed
500 501 502
/***********************************************************************
 *                     SymLoadModule64 (DBGHELP.@)
 */
503 504
DWORD64 WINAPI SymLoadModule64(HANDLE hProcess, HANDLE hFile, PCSTR ImageName,
                               PCSTR ModuleName, DWORD64 BaseOfDll, DWORD SizeOfDll)
Paul Vriens's avatar
Paul Vriens committed
505
{
506
    if (!validate_addr64(BaseOfDll)) return FALSE;
Paul Vriens's avatar
Paul Vriens committed
507 508 509
    return SymLoadModule(hProcess, hFile, ImageName, ModuleName, (DWORD)BaseOfDll, SizeOfDll);
}

510 511 512 513 514 515 516 517 518 519 520 521 522
/******************************************************************
 *		module_remove
 *
 */
BOOL module_remove(struct process* pcs, struct module* module)
{
    struct module**     p;

    TRACE("%s (%p)\n", module->module.ModuleName, module);
    hash_table_destroy(&module->ht_symbols);
    hash_table_destroy(&module->ht_types);
    HeapFree(GetProcessHeap(), 0, (char*)module->sources);
    HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
523
    HeapFree(GetProcessHeap(), 0, module->dwarf2_info);
524
    pool_destroy(&module->pool);
525 526 527
    /* native dbghelp doesn't invoke registered callback(,CBA_SYMBOLS_UNLOADED,) here
     * so do we
     */
528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
    for (p = &pcs->lmodules; *p; p = &(*p)->next)
    {
        if (*p == module)
        {
            *p = module->next;
            HeapFree(GetProcessHeap(), 0, module);
            return TRUE;
        }
    }
    FIXME("This shouldn't happen\n");
    return FALSE;
}

/******************************************************************
 *		SymUnloadModule (DBGHELP.@)
 *
 */
BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
{
    struct process*     pcs;
    struct module*      module;

    pcs = process_find_by_handle(hProcess);
    if (!pcs) return FALSE;
    module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
    if (!module) return FALSE;
    return module_remove(pcs, module);
}

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
/******************************************************************
 *		SymUnloadModule64 (DBGHELP.@)
 *
 */
BOOL WINAPI SymUnloadModule64(HANDLE hProcess, DWORD64 BaseOfDll)
{
    struct process*     pcs;
    struct module*      module;

    pcs = process_find_by_handle(hProcess);
    if (!pcs) return FALSE;
    if (!validate_addr64(BaseOfDll)) return FALSE;
    module = module_find_by_addr(pcs, (DWORD)BaseOfDll, DMT_UNKNOWN);
    if (!module) return FALSE;
    return module_remove(pcs, module);
}

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
/******************************************************************
 *		SymEnumerateModules (DBGHELP.@)
 *
 */
BOOL  WINAPI SymEnumerateModules(HANDLE hProcess,
                                 PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,  
                                 PVOID UserContext)
{
    struct process*     pcs = process_find_by_handle(hProcess);
    struct module*      module;

    if (!pcs) return FALSE;
    
    for (module = pcs->lmodules; module; module = module->next)
    {
589
        if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
590
            continue;
591 592 593 594 595 596 597
        if (!EnumModulesCallback(module->module.ModuleName, 
                                 module->module.BaseOfImage, UserContext))
            break;
    }
    return TRUE;
}

598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
/******************************************************************
 *		SymEnumerateModules64 (DBGHELP.@)
 *
 */
BOOL  WINAPI SymEnumerateModules64(HANDLE hProcess,
                                   PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,  
                                   PVOID UserContext)
{
    struct process*     pcs = process_find_by_handle(hProcess);
    struct module*      module;

    if (!pcs) return FALSE;
    
    for (module = pcs->lmodules; module; module = module->next)
    {
        if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
            continue;
        if (!EnumModulesCallback(module->module.ModuleName, 
                                 module->module.BaseOfImage, UserContext))
            break;
    }
    return TRUE;
}

622
/******************************************************************
623
 *		EnumerateLoadedModules64 (DBGHELP.@)
624 625
 *
 */
626 627 628
BOOL  WINAPI EnumerateLoadedModules64(HANDLE hProcess,
                                      PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,
                                      PVOID UserContext)
629 630
{
    HMODULE*    hMods;
631
    char        base[256], mod[256];
632 633 634
    DWORD       i, sz;
    MODULEINFO  mi;

635
    hMods = HeapAlloc(GetProcessHeap(), 0, 256 * sizeof(hMods[0]));
636 637 638 639 640 641 642 643 644 645 646 647 648
    if (!hMods) return FALSE;

    if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
    {
        /* hProcess should also be a valid process handle !! */
        FIXME("If this happens, bump the number in mod\n");
        HeapFree(GetProcessHeap(), 0, hMods);
        return FALSE;
    }
    sz /= sizeof(HMODULE);
    for (i = 0; i < sz; i++)
    {
        if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
649 650 651
            !GetModuleBaseNameA(hProcess, hMods[i], base, sizeof(base)))
            continue;
        module_fill_module(base, mod, sizeof(mod));
652
        EnumLoadedModulesCallback(mod, (DWORD_PTR)mi.lpBaseOfDll, mi.SizeOfImage,
653 654 655 656 657 658 659
                                  UserContext);
    }
    HeapFree(GetProcessHeap(), 0, hMods);

    return sz != 0 && i == sz;
}

660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
/******************************************************************
 *		EnumerateLoadedModules (DBGHELP.@)
 *
 */
struct enum_load_mod64_32
{
    PENUMLOADED_MODULES_CALLBACK        cb;
    PVOID                               user;
};

static BOOL CALLBACK enum_load_mod64_32(PSTR name, DWORD64 base, ULONG size,
                                        PVOID user)
{
    struct enum_load_mod64_32*  x = user;
    return x->cb(name, (DWORD)base, size, x->user);
}

BOOL  WINAPI EnumerateLoadedModules(HANDLE hProcess,
                                    PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
                                    PVOID UserContext)
{
    struct enum_load_mod64_32   x;

    x.cb = EnumLoadedModulesCallback;
    x.user = UserContext;

    return EnumerateLoadedModules64(hProcess, enum_load_mod64_32, &x);
}

/******************************************************************
 *		EnumerateLoadedModulesW64 (DBGHELP.@)
 *
 */
struct enum_load_mod64_W64
{
    PENUMLOADED_MODULES_CALLBACKW64     cb;
    PVOID                               user;
    WCHAR                               module[MAX_PATH];
};

static BOOL CALLBACK enum_load_mod64_W64(PSTR name, DWORD64 base, ULONG size,
                                         PVOID user)
{
    struct enum_load_mod64_W64* x = user;

    MultiByteToWideChar(CP_ACP, 0, name, -1,
                        x->module, sizeof(x->module) / sizeof(WCHAR));
    return x->cb(x->module, base, size, x->user);
}

BOOL  WINAPI EnumerateLoadedModulesW64(HANDLE hProcess,
                                       PENUMLOADED_MODULES_CALLBACKW64 EnumLoadedModulesCallback,
                                       PVOID UserContext)
{
    struct enum_load_mod64_W64  x;

    x.cb = EnumLoadedModulesCallback;
    x.user = UserContext;

    return EnumerateLoadedModules64(hProcess, enum_load_mod64_W64, &x);
}

722 723 724 725 726 727 728 729 730
/******************************************************************
 *		SymGetModuleInfo (DBGHELP.@)
 *
 */
BOOL  WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr, 
                              PIMAGEHLP_MODULE ModuleInfo)
{
    struct process*     pcs = process_find_by_handle(hProcess);
    struct module*      module;
Eric Pouech's avatar
Eric Pouech committed
731
    IMAGEHLP_MODULE     mod;
732 733 734 735 736 737

    if (!pcs) return FALSE;
    if (ModuleInfo->SizeOfStruct < sizeof(*ModuleInfo)) return FALSE;
    module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
    if (!module) return FALSE;

Eric Pouech's avatar
Eric Pouech committed
738 739 740 741 742 743 744 745 746 747 748
    mod.SizeOfStruct = ModuleInfo->SizeOfStruct;
    mod.BaseOfImage = module->module.BaseOfImage;
    mod.ImageSize = module->module.ImageSize;
    mod.TimeDateStamp = module->module.TimeDateStamp;
    mod.CheckSum = module->module.CheckSum;
    mod.NumSyms = module->module.NumSyms;
    mod.SymType = module->module.SymType;
    strcpy(mod.ModuleName, module->module.ModuleName);
    strcpy(mod.ImageName, module->module.ImageName);
    strcpy(mod.LoadedImageName, module->module.LoadedImageName);

749
    if (module->module.SymType == SymNone)
750 751
    {
        module = module_get_container(pcs, module);
752
        if (module && module->module.SymType != SymNone)
753
        {
Eric Pouech's avatar
Eric Pouech committed
754 755
            mod.SymType = module->module.SymType;
            mod.NumSyms = module->module.NumSyms;
756
        }
757
    }
Eric Pouech's avatar
Eric Pouech committed
758
    memcpy(ModuleInfo, &mod, ModuleInfo->SizeOfStruct);
759 760 761
    return TRUE;
}

762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794
/******************************************************************
 *		SymGetModuleInfoW (DBGHELP.@)
 *
 */
BOOL  WINAPI SymGetModuleInfoW(HANDLE hProcess, DWORD dwAddr, 
                               PIMAGEHLP_MODULEW ModuleInfo)
{
    IMAGEHLP_MODULE     mi;
    IMAGEHLP_MODULEW    miw;

    if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");

    mi.SizeOfStruct = sizeof(mi);
    if (!SymGetModuleInfo(hProcess, dwAddr, &mi)) return FALSE;

    miw.SizeOfStruct  = mi.SizeOfStruct;
    miw.BaseOfImage   = mi.BaseOfImage;
    miw.ImageSize     = mi.ImageSize;
    miw.TimeDateStamp = mi.TimeDateStamp;
    miw.CheckSum      = mi.CheckSum;
    miw.NumSyms       = mi.NumSyms;
    miw.SymType       = mi.SymType;
    MultiByteToWideChar(CP_ACP, 0, mi.ModuleName, -1,   
                        miw.ModuleName, sizeof(miw.ModuleName) / sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, mi.ImageName, -1,   
                        miw.ImageName, sizeof(miw.ImageName) / sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, mi.LoadedImageName, -1,   
                        miw.LoadedImageName, sizeof(miw.LoadedImageName) / sizeof(WCHAR));
    memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct);

    return TRUE;
}

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
/******************************************************************
 *		SymGetModuleInfo64 (DBGHELP.@)
 *
 */
BOOL  WINAPI SymGetModuleInfo64(HANDLE hProcess, DWORD64 dwAddr, 
                                PIMAGEHLP_MODULE64 ModuleInfo)
{
    struct process*     pcs = process_find_by_handle(hProcess);
    struct module*      module;

    TRACE("%p %s %p\n", hProcess, wine_dbgstr_longlong(dwAddr), ModuleInfo);

    if (!pcs) return FALSE;
    if (ModuleInfo->SizeOfStruct > sizeof(*ModuleInfo)) return FALSE;
    module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
    if (!module) return FALSE;

Eric Pouech's avatar
Eric Pouech committed
812
    memcpy(ModuleInfo, &module->module, ModuleInfo->SizeOfStruct);
813 814 815 816 817

    if (module->module.SymType == SymNone)
    {
        module = module_get_container(pcs, module);
        if (module && module->module.SymType != SymNone)
818
        {
Eric Pouech's avatar
Eric Pouech committed
819 820
            ModuleInfo->SymType = module->module.SymType;
            ModuleInfo->NumSyms = module->module.NumSyms;
821
        }
822 823 824 825
    }
    return TRUE;
}

826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853
/******************************************************************
 *		SymGetModuleInfoW64 (DBGHELP.@)
 *
 */
BOOL  WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr, 
                                 PIMAGEHLP_MODULEW64 ModuleInfo)
{
    IMAGEHLP_MODULE64   mi;
    IMAGEHLP_MODULEW64  miw;

    if (sizeof(miw) < ModuleInfo->SizeOfStruct) FIXME("Wrong size\n");

    mi.SizeOfStruct = sizeof(mi);
    if (!SymGetModuleInfo64(hProcess, dwAddr, &mi)) return FALSE;

    miw.SizeOfStruct  = mi.SizeOfStruct;
    miw.BaseOfImage   = mi.BaseOfImage;
    miw.ImageSize     = mi.ImageSize;
    miw.TimeDateStamp = mi.TimeDateStamp;
    miw.CheckSum      = mi.CheckSum;
    miw.NumSyms       = mi.NumSyms;
    miw.SymType       = mi.SymType;
    MultiByteToWideChar(CP_ACP, 0, mi.ModuleName, -1,   
                        miw.ModuleName, sizeof(miw.ModuleName) / sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, mi.ImageName, -1,   
                        miw.ImageName, sizeof(miw.ImageName) / sizeof(WCHAR));
    MultiByteToWideChar(CP_ACP, 0, mi.LoadedImageName, -1,   
                        miw.LoadedImageName, sizeof(miw.LoadedImageName) / sizeof(WCHAR));
Eric Pouech's avatar
Eric Pouech committed
854 855
    MultiByteToWideChar(CP_ACP, 0, mi.LoadedPdbName, -1,   
                        miw.LoadedPdbName, sizeof(miw.LoadedPdbName) / sizeof(WCHAR));
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875

    miw.CVSig         = mi.CVSig;
    MultiByteToWideChar(CP_ACP, 0, mi.CVData, -1,   
                        miw.CVData, sizeof(miw.CVData) / sizeof(WCHAR));
    miw.PdbSig        = mi.PdbSig;
    miw.PdbSig70      = mi.PdbSig70;
    miw.PdbAge        = mi.PdbAge;
    miw.PdbUnmatched  = mi.PdbUnmatched;
    miw.DbgUnmatched  = mi.DbgUnmatched;
    miw.LineNumbers   = mi.LineNumbers;
    miw.GlobalSymbols = mi.GlobalSymbols;
    miw.TypeInfo      = mi.TypeInfo;
    miw.SourceIndexed = mi.SourceIndexed;
    miw.Publics       = mi.Publics;

    memcpy(ModuleInfo, &miw, ModuleInfo->SizeOfStruct);

    return TRUE;
}

876
/***********************************************************************
877
 *		SymGetModuleBase (DBGHELP.@)
878 879 880 881 882 883 884 885 886 887 888
 */
DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
{
    struct process*     pcs = process_find_by_handle(hProcess);
    struct module*      module;

    if (!pcs) return 0;
    module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
    if (!module) return 0;
    return module->module.BaseOfImage;
}
889

890 891 892 893 894 895 896 897 898
/***********************************************************************
 *		SymGetModuleBase64 (DBGHELP.@)
 */
DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
{
    if (!validate_addr64(dwAddr)) return 0;
    return SymGetModuleBase(hProcess, (DWORD)dwAddr);
}

899 900 901 902 903 904 905 906 907 908 909 910 911 912
/******************************************************************
 *		module_reset_debug_info
 * Removes any debug information linked to a given module.
 */
void module_reset_debug_info(struct module* module)
{
    module->sortlist_valid = TRUE;
    module->addr_sorttab = NULL;
    hash_table_destroy(&module->ht_symbols);
    module->ht_symbols.num_buckets = 0;
    module->ht_symbols.buckets = NULL;
    hash_table_destroy(&module->ht_types);
    module->ht_types.num_buckets = 0;
    module->ht_types.buckets = NULL;
913
    module->vtypes.num_elts = 0;
914 915 916 917
    hash_table_destroy(&module->ht_symbols);
    module->sources_used = module->sources_alloc = 0;
    module->sources = NULL;
}