elf_module.c 61.3 KB
Newer Older
1 2 3 4
/*
 * File elf.c - processing of ELF files
 *
 * Copyright (C) 1996, Eric Youngdale.
5
 *		 1999-2007 Eric Pouech
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
 */

#include "config.h"
23
#include "wine/port.h"
24

25
#if defined(__svr4__) || defined(__sun)
26
#define __ELF__ 1
27 28 29 30 31
/* large files are not supported by libelf */
#undef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 32
#endif

32 33 34
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
35 36 37
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
#include <fcntl.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifndef PATH_MAX
#define PATH_MAX MAX_PATH
#endif

#include "dbghelp_private.h"

#ifdef HAVE_ELF_H
# include <elf.h>
#endif
#ifdef HAVE_SYS_ELF32_H
# include <sys/elf32.h>
#endif
#ifdef HAVE_SYS_EXEC_ELF_H
# include <sys/exec_elf.h>
#endif
#if !defined(DT_NUM)
# if defined(DT_COUNT)
#  define DT_NUM DT_COUNT
# else
/* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */
#  define DT_NUM 24
# endif
#endif
#ifdef HAVE_LINK_H
# include <link.h>
#endif
#ifdef HAVE_SYS_LINK_H
# include <sys/link.h>
#endif

75
#include "wine/library.h"
76 77
#include "wine/debug.h"

78
struct elf_module_info
79
{
80 81 82 83
    unsigned long               elf_addr;
    unsigned short	        elf_mark : 1,
                                elf_loader : 1;
};
84 85 86 87 88

#ifdef __ELF__

#define ELF_INFO_DEBUG_HEADER   0x0001
#define ELF_INFO_MODULE         0x0002
89
#define ELF_INFO_NAME           0x0004
90

91 92
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);

93 94
struct elf_info
{
95 96 97
    unsigned                    flags;          /* IN  one (or several) of the ELF_INFO constants */
    unsigned long               dbg_hdr_addr;   /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
    struct module*              module;         /* OUT loaded module (if ELF_INFO_MODULE is set) */
98
    const WCHAR*                module_name;    /* OUT found module name (if ELF_INFO_NAME is set) */
99 100
};

101 102 103 104 105 106 107 108 109 110 111 112 113 114
/* structure holding information while handling an ELF image
 * allows one by one section mapping for memory savings
 */
struct elf_file_map
{
    Elf32_Ehdr                  elfhdr;
    size_t                      elf_size;
    size_t                      elf_start;
    struct
    {
        Elf32_Shdr                      shdr;
        const char*                     mapped;
    }*                          sect;
    int                         fd;
115
    const char*	                shstrtab;
116
    struct elf_file_map*        alternate;      /* another ELF file (linked to this one) */
117 118 119 120 121
};

struct elf_section_map
{
    struct elf_file_map*        fmap;
122
    long                        sidx;
123 124
};

125 126 127 128
struct symtab_elt
{
    struct hash_table_elt       ht_elt;
    const Elf32_Sym*            symp;
129
    struct symt_compiland*      compiland;
130 131 132
    unsigned                    used;
};

Eric Pouech's avatar
Eric Pouech committed
133
struct elf_thunk_area
134 135 136 137 138
{
    const char*                 symname;
    THUNK_ORDINAL               ordinal;
    unsigned long               rva_start;
    unsigned long               rva_end;
139 140
};

141 142 143
/******************************************************************
 *		elf_map_section
 *
144
 * Maps a single section into memory from an ELF file
145
 */
146
static const char* elf_map_section(struct elf_section_map* esm)
147 148 149 150
{
    unsigned pgsz = getpagesize();
    unsigned ofst, size;

151 152
    if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum ||
        esm->fmap->sect[esm->sidx].shdr.sh_type == SHT_NOBITS)
153
        return ELF_NO_MAP;
154

155
    /* align required information on page size (we assume pagesize is a power of 2) */
156 157 158 159 160 161 162 163 164 165 166 167 168
    ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1);
    size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset +
             esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
    esm->fmap->sect[esm->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE,
                                             esm->fmap->fd, ofst);
    if (esm->fmap->sect[esm->sidx].mapped == ELF_NO_MAP) return ELF_NO_MAP;
    return esm->fmap->sect[esm->sidx].mapped + (esm->fmap->sect[esm->sidx].shdr.sh_offset & (pgsz - 1));
}

/******************************************************************
 *		elf_find_section
 *
 * Finds a section by name (and type) into memory from an ELF file
169
 * or its alternate if any
170 171 172 173 174 175
 */
static BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
                             unsigned sht, struct elf_section_map* esm)
{
    unsigned i;

176
    while (fmap)
177
    {
178 179 180
        if (fmap->shstrtab == ELF_NO_MAP)
        {
            struct elf_section_map  hdr_esm = {fmap, fmap->elfhdr.e_shstrndx};
181
            if ((fmap->shstrtab = elf_map_section(&hdr_esm)) == ELF_NO_MAP) break;
182 183
        }
        for (i = 0; i < fmap->elfhdr.e_shnum; i++)
184
        {
185 186 187 188 189 190 191
            if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 &&
                (sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type))
            {
                esm->fmap = fmap;
                esm->sidx = i;
                return TRUE;
            }
192
        }
193
        fmap = fmap->alternate;
194
    }
195 196
    esm->fmap = NULL;
    esm->sidx = -1;
197
    return FALSE;
198 199 200 201 202 203 204
}

/******************************************************************
 *		elf_unmap_section
 *
 * Unmaps a single section from memory
 */
205
static void elf_unmap_section(struct elf_section_map* esm)
206
{
207
    if (esm->sidx >= 0 && esm->sidx < esm->fmap->elfhdr.e_shnum && esm->fmap->sect[esm->sidx].mapped != ELF_NO_MAP)
208
    {
209 210 211
        unsigned pgsz = getpagesize();
        unsigned ofst, size;

212 213 214 215
        ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1);
        size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset +
             esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
        if (munmap((char*)esm->fmap->sect[esm->sidx].mapped, size) < 0)
216
            WARN("Couldn't unmap the section\n");
217
        esm->fmap->sect[esm->sidx].mapped = ELF_NO_MAP;
218 219 220
    }
}

221 222 223 224
static void elf_end_find(struct elf_file_map* fmap)
{
    struct elf_section_map      esm;

225 226 227 228 229 230 231 232
    while (fmap)
    {
        esm.fmap = fmap;
        esm.sidx = fmap->elfhdr.e_shstrndx;
        elf_unmap_section(&esm);
        fmap->shstrtab = ELF_NO_MAP;
        fmap = fmap->alternate;
    }
233 234
}

235 236 237 238 239
/******************************************************************
 *		elf_get_map_size
 *
 * Get the size of an ELF section
 */
240
static inline unsigned elf_get_map_size(struct elf_section_map* esm)
241
{
242
    if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum)
243
        return 0;
244
    return esm->fmap->sect[esm->sidx].shdr.sh_size;
245 246
}

247 248 249
/******************************************************************
 *		elf_map_file
 *
250
 * Maps an ELF file into memory (and checks it's a real ELF file)
251
 */
252
static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
253 254 255 256 257 258
{
    static const BYTE   elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
    struct stat	        statbuf;
    int                 i;
    Elf32_Phdr          phdr;
    unsigned            tmp, page_mask = getpagesize() - 1;
259 260 261
    char*               filename;
    unsigned            len;
    BOOL                ret = FALSE;
262

263 264 265
    len = WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, NULL, 0, NULL, NULL);
    if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE;
    WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL);
266 267

    fmap->fd = -1;
268
    fmap->shstrtab = ELF_NO_MAP;
269
    fmap->alternate = NULL;
270 271

    /* check that the file exists, and that the module hasn't been loaded yet */
272
    if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done;
273 274

    /* Now open the file, so that we can mmap() it. */
275
    if ((fmap->fd = open(filename, O_RDONLY)) == -1) goto done;
276 277

    if (read(fmap->fd, &fmap->elfhdr, sizeof(fmap->elfhdr)) != sizeof(fmap->elfhdr))
278
        goto done;
279 280
    /* and check for an ELF header */
    if (memcmp(fmap->elfhdr.e_ident, 
281
               elf_signature, sizeof(elf_signature))) goto done;
282

283 284
    fmap->sect = HeapAlloc(GetProcessHeap(), 0,
                           fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
285
    if (!fmap->sect) goto done;
286 287 288 289 290

    lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET);
    for (i = 0; i < fmap->elfhdr.e_shnum; i++)
    {
        read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr));
291
        fmap->sect[i].mapped = ELF_NO_MAP;
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
    }

    /* grab size of module once loaded in memory */
    lseek(fmap->fd, fmap->elfhdr.e_phoff, SEEK_SET);
    fmap->elf_size = 0; 
    fmap->elf_start = ~0L;
    for (i = 0; i < fmap->elfhdr.e_phnum; i++)
    {
        if (read(fmap->fd, &phdr, sizeof(phdr)) == sizeof(phdr) && 
            phdr.p_type == PT_LOAD)
        {
            tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask;
            if (fmap->elf_size < tmp) fmap->elf_size = tmp;
            if (phdr.p_vaddr < fmap->elf_start) fmap->elf_start = phdr.p_vaddr;
        }
    }
    /* if non relocatable ELF, then remove fixed address from computation
     * otherwise, all addresses are zero based and start has no effect
     */
    fmap->elf_size -= fmap->elf_start;
312 313
    ret = TRUE;
done:
314 315 316 317
    HeapFree(GetProcessHeap(), 0, filename);
    return ret;
}

318 319 320
/******************************************************************
 *		elf_unmap_file
 *
321
 * Unmaps an ELF file from memory (previously mapped with elf_map_file)
322 323 324
 */
static void elf_unmap_file(struct elf_file_map* fmap)
{
325
    while (fmap)
326
    {
327
        if (fmap->fd != -1)
328
        {
329 330 331 332 333 334 335 336
            struct elf_section_map  esm;
            esm.fmap = fmap;
            for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++)
            {
                elf_unmap_section(&esm);
            }
            HeapFree(GetProcessHeap(), 0, fmap->sect);
            close(fmap->fd);
337
        }
338
        fmap = fmap->alternate;
339 340 341
    }
}

Eric Pouech's avatar
Eric Pouech committed
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
/******************************************************************
 *		elf_is_in_thunk_area
 *
 * Check whether an address lies within one of the thunk area we
 * know of.
 */
int elf_is_in_thunk_area(unsigned long addr,
                         const struct elf_thunk_area* thunks)
{
    unsigned i;

    for (i = 0; thunks[i].symname; i++)
    {
        if (addr >= thunks[i].rva_start && addr < thunks[i].rva_end)
            return i;
    }
    return -1;
}

361
/******************************************************************
362
 *		elf_hash_symtab
363
 *
364
 * creating an internal hash table to ease use ELF symtab information lookup
365
 */
366
static void elf_hash_symtab(struct module* module, struct pool* pool, 
367
                            struct hash_table* ht_symtab, struct elf_file_map* fmap,
368
                            struct elf_thunk_area* thunks)
369
{
370
    int		                i, j, nsym;
371 372
    const char*                 strp;
    const char*                 symname;
373
    struct symt_compiland*      compiland = NULL;
374
    const char*                 ptr;
375
    const Elf32_Sym*            symp;
376
    struct symtab_elt*          ste;
377
    struct elf_section_map      esm, esm_str;
378

379 380 381 382 383 384
    if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) &&
        !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return;
    if ((symp = (const Elf32_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return;
    esm_str.fmap = fmap;
    esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link;
    if ((strp = elf_map_section(&esm_str)) == ELF_NO_MAP) return;
385

386
    nsym = elf_get_map_size(&esm) / sizeof(*symp);
387

388
    for (j = 0; thunks[j].symname; j++)
389
        thunks[j].rva_start = thunks[j].rva_end = 0;
390 391 392 393 394 395

    for (i = 0; i < nsym; i++, symp++)
    {
        /* Ignore certain types of entries which really aren't of that much
         * interest.
         */
396 397
        if ((ELF32_ST_TYPE(symp->st_info) != STT_NOTYPE &&
             ELF32_ST_TYPE(symp->st_info) != STT_FILE &&
398 399 400
             ELF32_ST_TYPE(symp->st_info) != STT_OBJECT &&
             ELF32_ST_TYPE(symp->st_info) != STT_FUNC) ||
            symp->st_shndx == SHN_UNDEF)
401 402 403 404 405 406
        {
            continue;
        }

        symname = strp + symp->st_name;

407 408
        /* handle some specific symtab (that we'll throw away when done) */
        switch (ELF32_ST_TYPE(symp->st_info))
409
        {
410
        case STT_FILE:
411 412 413 414 415
            if (symname)
                compiland = symt_new_compiland(module, symp->st_value,
                                               source_new(module, NULL, symname));
            else
                compiland = NULL;
416
            continue;
417 418 419
        case STT_NOTYPE:
            /* we are only interested in wine markers inserted by winebuild */
            for (j = 0; thunks[j].symname; j++)
420
            {
421 422 423 424 425 426
                if (!strcmp(symname, thunks[j].symname))
                {
                    thunks[j].rva_start = symp->st_value;
                    thunks[j].rva_end   = symp->st_value + symp->st_size;
                    break;
                }
427
            }
428
            continue;
429
        }
430

431 432 433 434 435 436
        /* FIXME: we don't need to handle them (GCC internals)
         * Moreover, they screw up our symbol lookup :-/
         */
        if (symname[0] == '.' && symname[1] == 'L' && isdigit(symname[2]))
            continue;

437
        ste = pool_alloc(pool, sizeof(*ste));
438 439
        ste->ht_elt.name = symname;
        /* GCC emits, in some cases, a .<digit>+ suffix.
440 441 442 443 444 445 446 447 448
         * This is used for static variable inside functions, so
         * that we can have several such variables with same name in
         * the same compilation unit
         * We simply ignore that suffix when present (we also get rid
         * of it in stabs parsing)
         */
        ptr = symname + strlen(symname) - 1;
        if (isdigit(*ptr))
        {
449
            while (isdigit(*ptr) && ptr >= symname) ptr--;
450 451 452 453 454 455 456 457
            if (ptr > symname && *ptr == '.')
            {
                char* n = pool_alloc(pool, ptr - symname + 1);
                memcpy(n, symname, ptr - symname + 1);
                n[ptr - symname] = '\0';
                ste->ht_elt.name = n;
            }
        }
458
        ste->symp        = symp;
459
        ste->compiland   = compiland;
460 461 462
        ste->used        = 0;
        hash_table_add(ht_symtab, &ste->ht_elt);
    }
463 464 465 466
    /* as we added in the ht_symtab pointers to the symbols themselves,
     * we cannot unmap yet the sections, it will be done when we're over
     * with this ELF file
     */
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 500 501 502 503 504
}

/******************************************************************
 *		elf_lookup_symtab
 *
 * lookup a symbol by name in our internal hash table for the symtab
 */
static const Elf32_Sym* elf_lookup_symtab(const struct module* module,        
                                          const struct hash_table* ht_symtab,
                                          const char* name, struct symt* compiland)
{
    struct symtab_elt*          weak_result = NULL; /* without compiland name */
    struct symtab_elt*          result = NULL;
    struct hash_table_iter      hti;
    struct symtab_elt*          ste;
    const char*                 compiland_name;
    const char*                 compiland_basename;
    const char*                 base;

    /* we need weak match up (at least) when symbols of same name, 
     * defined several times in different compilation units,
     * are merged in a single one (hence a different filename for c.u.)
     */
    if (compiland)
    {
        compiland_name = source_get(module,
                                    ((struct symt_compiland*)compiland)->source);
        compiland_basename = strrchr(compiland_name, '/');
        if (!compiland_basename++) compiland_basename = compiland_name;
    }
    else compiland_name = compiland_basename = NULL;
    
    hash_table_iter_init(ht_symtab, &hti, name);
    while ((ste = hash_table_iter_up(&hti)))
    {
        if (ste->used || strcmp(ste->ht_elt.name, name)) continue;

        weak_result = ste;
505
        if ((ste->compiland && !compiland_name) || (!ste->compiland && compiland_name))
506
            continue;
507
        if (ste->compiland && compiland_name)
508
        {
509 510
            const char* filename = source_get(module, ste->compiland->source);
            if (strcmp(filename, compiland_name))
511
            {
512 513
                base = strrchr(filename, '/');
                if (!base++) base = filename;
514 515 516 517 518
                if (strcmp(base, compiland_basename)) continue;
            }
        }
        if (result)
        {
519
            FIXME("Already found symbol %s (%s) in symtab %s @%08x and %s @%08x\n",
520
                  name, compiland_name,
521 522
                  source_get(module, result->compiland->source), (unsigned int)result->symp->st_value,
                  source_get(module, ste->compiland->source), (unsigned int)ste->symp->st_value);
523 524 525 526 527 528 529 530 531
        }
        else
        {
            result = ste;
            ste->used = 1;
        }
    }
    if (!result && !(result = weak_result))
    {
532
        FIXME("Couldn't find symbol %s!%s in symtab\n",
533
              debugstr_w(module->module.ModuleName), name);
534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
        return NULL;
    }
    return result->symp;
}

/******************************************************************
 *		elf_finish_stabs_info
 *
 * - get any relevant information (address & size) from the bits we got from the
 *   stabs debugging information
 */
static void elf_finish_stabs_info(struct module* module, struct hash_table* symtab)
{
    struct hash_table_iter      hti;
    void*                       ptr;
    struct symt_ht*             sym;
    const Elf32_Sym*            symp;

    hash_table_iter_init(&module->ht_symbols, &hti, NULL);
    while ((ptr = hash_table_iter_up(&hti)))
    {
        sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
        switch (sym->symt.tag)
        {
        case SymTagFunction:
559 560 561
            if (((struct symt_function*)sym)->address != module->elf_info->elf_addr &&
                ((struct symt_function*)sym)->size)
            {
562
                break;
563
            }
564 565 566 567
            symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, 
                                     ((struct symt_function*)sym)->container);
            if (symp)
            {
568 569
                if (((struct symt_function*)sym)->address != module->elf_info->elf_addr &&
                    ((struct symt_function*)sym)->address != module->elf_info->elf_addr + symp->st_value)
570
                    FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n",
571
                          sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
572 573
                          ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value);
                if (((struct symt_function*)sym)->size && ((struct symt_function*)sym)->size != symp->st_size)
574
                    FIXME("Changing size for %p/%s!%s from %08lx to %08x\n",
575
                          sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
576
                          ((struct symt_function*)sym)->size, (unsigned int)symp->st_size);
577

578 579 580
                ((struct symt_function*)sym)->address = module->elf_info->elf_addr +
                                                        symp->st_value;
                ((struct symt_function*)sym)->size    = symp->st_size;
581 582 583
            } else
                FIXME("Couldn't find %s!%s\n",
                      debugstr_w(module->module.ModuleName), sym->hash_elt.name);
584 585 586 587 588 589
            break;
        case SymTagData:
            switch (((struct symt_data*)sym)->kind)
            {
            case DataIsGlobal:
            case DataIsFileStatic:
590
                if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr)
591 592 593 594
                    break;
                symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, 
                                         ((struct symt_data*)sym)->container);
                if (symp)
595
                {
596 597
                if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr &&
                    ((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr + symp->st_value)
598
                    FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n",
599
                          sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
600
                          ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value);
601
                    ((struct symt_data*)sym)->u.var.offset = module->elf_info->elf_addr +
602
                                                          symp->st_value;
603 604
                    ((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ?
                        DataIsFileStatic : DataIsGlobal;
605 606 607
                } else
                    FIXME("Couldn't find %s!%s\n",
                          debugstr_w(module->module.ModuleName), sym->hash_elt.name);
608 609 610 611 612 613 614 615 616
                break;
            default:;
            }
            break;
        default:
            FIXME("Unsupported tag %u\n", sym->symt.tag);
            break;
        }
    }
617 618
    /* since we may have changed some addresses & sizes, mark the module to be resorted */
    module->sortlist_valid = FALSE;
619 620 621 622 623 624 625 626
}

/******************************************************************
 *		elf_load_wine_thunks
 *
 * creating the thunk objects for a wine native DLL
 */
static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symtab,
Eric Pouech's avatar
Eric Pouech committed
627
                               const struct elf_thunk_area* thunks)
628 629 630 631 632
{
    int		                j;
    struct hash_table_iter      hti;
    struct symtab_elt*          ste;
    DWORD                       addr;
633
    struct symt_ht*             symt;
634 635 636 637 638 639 640 641

    hash_table_iter_init(ht_symtab, &hti, NULL);
    while ((ste = hash_table_iter_up(&hti)))
    {
        if (ste->used) continue;

        addr = module->elf_info->elf_addr + ste->symp->st_value;

Eric Pouech's avatar
Eric Pouech committed
642 643
        j = elf_is_in_thunk_area(ste->symp->st_value, thunks);
        if (j >= 0) /* thunk found */
644
        {
645
            symt_new_thunk(module, ste->compiland, ste->ht_elt.name, thunks[j].ordinal,
646 647
                           addr, ste->symp->st_size);
        }
648
        else
649
        {
650
            ULONG64     ref_addr;
651

652 653 654 655
            symt = symt_find_nearest(module, addr);
            if (symt)
                symt_get_info(&symt->symt, TI_GET_ADDRESS, &ref_addr);
            if (!symt || addr != ref_addr)
656
            {
657 658 659 660
                /* creating public symbols for all the ELF symbols which haven't been
                 * used yet (ie we have no debug information on them)
                 * That's the case, for example, of the .spec.c files
                 */
661
                switch (ELF32_ST_TYPE(ste->symp->st_info))
662
                {
663
                case STT_FUNC:
664
                    symt_new_function(module, ste->compiland, ste->ht_elt.name,
665
                                      addr, ste->symp->st_size, NULL);
666 667
                    break;
                case STT_OBJECT:
668
                    symt_new_global_variable(module, ste->compiland, ste->ht_elt.name,
669 670
                                             ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL,
                                             addr, ste->symp->st_size, NULL);
671 672 673 674
                    break;
                default:
                    FIXME("Shouldn't happen\n");
                    break;
675 676 677 678 679 680 681 682 683
                }
                /* FIXME: this is a hack !!!
                 * we are adding new symbols, but as we're parsing a symbol table
                 * (hopefully without duplicate symbols) we delay rebuilding the sorted
                 * module table until we're done with the symbol table
                 * Otherwise, as we intertwine symbols's add and lookup, performance
                 * is rather bad
                 */
                module->sortlist_valid = TRUE;
684
            }
685
            else if (strcmp(ste->ht_elt.name, symt->hash_elt.name))
686
            {
687 688
                ULONG64 xaddr = 0, xsize = 0;
                DWORD   kind = -1;
689

690 691 692
                symt_get_info(&symt->symt, TI_GET_ADDRESS,  &xaddr);
                symt_get_info(&symt->symt, TI_GET_LENGTH,   &xsize);
                symt_get_info(&symt->symt, TI_GET_DATAKIND, &kind);
693

694
                /* If none of symbols has a correct size, we consider they are both markers
695
                 * Hence, we can silence this warning
696 697
                 * Also, we check that we don't have two symbols, one local, the other 
                 * global which is legal
698
                 */
699
                if ((xsize || ste->symp->st_size) &&
700
                    (kind == (ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal))
701
                    FIXME("Duplicate in %s: %s<%08x-%08x> %s<%s-%s>\n",
702
                          debugstr_w(module->module.ModuleName),
703
                          ste->ht_elt.name, addr, (unsigned int)ste->symp->st_size,
704
                          symt->hash_elt.name,
705
                          wine_dbgstr_longlong(xaddr), wine_dbgstr_longlong(xsize));
706 707
            }
        }
708
    }
709 710
    /* see comment above */
    module->sortlist_valid = FALSE;
711 712 713 714 715 716 717 718
    return TRUE;
}

/******************************************************************
 *		elf_new_public_symbols
 *
 * Creates a set of public symbols from an ELF symtab
 */
719
static int elf_new_public_symbols(struct module* module, struct hash_table* symtab)
720 721 722 723
{
    struct hash_table_iter      hti;
    struct symtab_elt*          ste;

724
    if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE;
725

726 727
    /* FIXME: we're missing the ELF entry point here */

728 729 730
    hash_table_iter_init(symtab, &hti, NULL);
    while ((ste = hash_table_iter_up(&hti)))
    {
731 732 733 734
        symt_new_public(module, ste->compiland, ste->ht_elt.name,
                        module->elf_info->elf_addr + ste->symp->st_value,
                        ste->symp->st_size, TRUE /* FIXME */, 
                        ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC);
735
    }
736 737 738
    return TRUE;
}

739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 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 795 796 797 798
/* Copyright (C) 1986 Gary S. Brown. Modified by Robert Shearman. You may use
   the following calc_crc32 code or tables extracted from it, as desired without
   restriction. */

/**********************************************************************\
|* Demonstration program to compute the 32-bit CRC used as the frame  *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71     *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level     *|
|* protocol).  The 32-bit FCS was added via the Federal Register,     *|
|* 1 June 1982, p.23798.  I presume but don't know for certain that   *|
|* this polynomial is or will be included in CCITT V.41, which        *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial.  FIPS  *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected       *|
|* errors by a factor of 10^-5 over 16-bit FCS.                       *|
\**********************************************************************/

/* First, the polynomial itself and its table of feedback terms.  The  */
/* polynomial is                                                       */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in  */
/* the lowest-order bit.  The X^32 term is "implied"; the LSB is the   */
/* X^31 term, etc.  The X^0 term (usually shown as "+1") results in    */
/* the MSB being 1.                                                    */

/* Note that the usual hardware shift register implementation, which   */
/* is what we're using (we're merely optimizing it by doing eight-bit  */
/* chunks at a time) shifts bits into the lowest-order term.  In our   */
/* implementation, that means shifting towards the right.  Why do we   */
/* do it this way?  Because the calculated CRC must be transmitted in  */
/* order from highest-order term to lowest-order term.  UARTs transmit */
/* characters in order from LSB to MSB.  By storing the CRC this way,  */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part.  Reception works similarly.                  */

/* The feedback terms table consists of 256, 32-bit entries.  Notes:   */
/*                                                                     */
/*  1. The table can be generated at runtime if desired; code to do so */
/*     is shown later.  It might not be obvious, but the feedback      */
/*     terms simply represent the results of eight shift/xor opera-    */
/*     tions for all combinations of data and CRC register values.     */
/*                                                                     */
/*  2. The CRC accumulation logic is the same for all CRC polynomials, */
/*     be they sixteen or thirty-two bits wide.  You simply choose the */
/*     appropriate table.  Alternatively, because the table can be     */
/*     generated at runtime, you can start by generating the table for */
/*     the polynomial in question and use exactly the same "updcrc",   */
/*     if your application needn't simultaneously handle two CRC       */
/*     polynomials.  (Note, however, that XMODEM is strange.)          */
/*                                                                     */
/*  3. For 16-bit CRCs, the table entries need be only 16 bits wide;   */
/*     of course, 32-bit entries work OK if the high 16 bits are zero. */
/*                                                                     */
/*  4. The values must be right-shifted by eight bits by the "updcrc"  */
/*     logic; the shift must be unsigned (bring in zeroes).  On some   */
/*     hardware you could probably optimize the shift in assembler by  */
/*     using byte-swap instructions.                                   */


799
static DWORD calc_crc32(struct elf_file_map* fmap)
800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847
{
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
    static const DWORD crc_32_tab[] =
    { /* CRC polynomial 0xedb88320 */
        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
        0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
        0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
        0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
        0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
        0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
        0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
        0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
        0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
        0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
        0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
        0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
        0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
        0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
        0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
        0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
        0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
        0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
        0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
    };
848 849 850 851 852 853 854 855 856
    int                 i, r;
    unsigned char       buffer[256];
    DWORD               crc = ~0;

    lseek(fmap->fd, 0, SEEK_SET);
    while ((r = read(fmap->fd, buffer, sizeof(buffer))) > 0)
    {
        for (i = 0; i < r; i++) crc = UPDC32(buffer[i], crc);
    }
857 858 859 860
    return ~crc;
#undef UPDC32
}

861 862 863 864 865 866 867 868 869 870 871 872
static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, DWORD crc)
{
    BOOL        ret;
    if (!elf_map_file(file, fmap)) return FALSE;
    if (!(ret = crc == calc_crc32(fmap)))
    {
        WARN("Bad CRC for file %s (got %08x while expecting %08x)\n",
             debugstr_w(file), calc_crc32(fmap), crc);
        elf_unmap_file(fmap);
    }
    return ret;
}
873

874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892
/******************************************************************
 *		elf_locate_debug_link
 *
 * Locate a filename from a .gnu_debuglink section, using the same
 * strategy as gdb:
 * "If the full name of the directory containing the executable is
 * execdir, and the executable has a debug link that specifies the
 * name debugfile, then GDB will automatically search for the
 * debugging information file in three places:
 *  - the directory containing the executable file (that is, it
 *    will look for a file named `execdir/debugfile',
 *  - a subdirectory of that directory named `.debug' (that is, the
 *    file `execdir/.debug/debugfile', and
 *  - a subdirectory of the global debug file directory that includes
 *    the executable's full path, and the name from the link (that is,
 *    the file `globaldebugdir/execdir/debugfile', where globaldebugdir
 *    is the global debug file directory, and execdir has been turned
 *    into a relative path)." (from GDB manual)
 */
893 894
static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filename,
                                  const WCHAR* loaded_file, DWORD crc)
895
{
896 897 898 899
    static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'};
    static const WCHAR dotDebugW[] = {'.','d','e','b','u','g','/'};
    const size_t globalDebugDirLen = sizeof(globalDebugDirW) / sizeof(WCHAR);
    size_t filename_len;
900
    WCHAR* p = NULL;
901
    WCHAR* slash;
902 903 904 905
    struct elf_file_map* fmap_link = NULL;

    fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link));
    if (!fmap_link) return FALSE;
906 907

    filename_len = MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, NULL, 0);
908
    p = HeapAlloc(GetProcessHeap(), 0,
909
                  (globalDebugDirLen + strlenW(loaded_file) + 6 + 1 + filename_len + 1) * sizeof(WCHAR));
910
    if (!p) goto found;
911 912

    /* we prebuild the string with "execdir" */
913 914
    strcpyW(p, loaded_file);
    slash = strrchrW(p, '/');
915 916 917
    if (slash == NULL) slash = p; else slash++;

    /* testing execdir/filename */
918
    MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len);
919
    if (elf_check_debug_link(p, fmap_link, crc)) goto found;
920

921
    /* testing execdir/.debug/filename */
922 923
    memcpy(slash, dotDebugW, sizeof(dotDebugW));
    MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash + sizeof(dotDebugW) / sizeof(WCHAR), filename_len);
924
    if (elf_check_debug_link(p, fmap_link, crc)) goto found;
925

926
    /* testing globaldebugdir/execdir/filename */
927 928
    memmove(p + globalDebugDirLen, p, (slash - p) * sizeof(WCHAR));
    memcpy(p, globalDebugDirW, globalDebugDirLen * sizeof(WCHAR));
929
    slash += globalDebugDirLen;
930
    MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len);
931
    if (elf_check_debug_link(p, fmap_link, crc)) goto found;
932

933
    /* finally testing filename */
934
    if (elf_check_debug_link(slash, fmap_link, crc)) goto found;
935 936


937
    WARN("Couldn't locate or map %s\n", filename);
938 939 940
    HeapFree(GetProcessHeap(), 0, p);
    HeapFree(GetProcessHeap(), 0, fmap_link);
    return FALSE;
941 942

found:
943
    TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p));
944 945 946
    HeapFree(GetProcessHeap(), 0, p);
    fmap->alternate = fmap_link;
    return TRUE;
947 948
}

949 950 951 952 953 954
/******************************************************************
 *		elf_debuglink_parse
 *
 * Parses a .gnu_debuglink section and loads the debug info from
 * the external file specified there.
 */
955 956
static BOOL elf_debuglink_parse(struct elf_file_map* fmap, struct module* module,
                                const BYTE* debuglink)
957 958 959 960 961 962 963
{
    /* The content of a debug link section is:
     * 1/ a NULL terminated string, containing the file name for the
     *    debug info
     * 2/ padding on 4 byte boundary
     * 3/ CRC of the linked ELF file
     */
964
    const char* dbg_link = (const char*)debuglink;
965
    DWORD crc;
966

967 968
    crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3));
    return elf_locate_debug_link(fmap, dbg_link, module->module.LoadedImageName, crc);
969 970
}

971
/******************************************************************
972
 *		elf_load_debug_info_from_map
973
 *
974 975
 * Loads the symbolic information from ELF module which mapping is described
 * in fmap
976
 * the module has been loaded at 'load_offset' address, so symbols' address
977 978
 * relocation is performed.
 * CRC is checked if fmap->with_crc is TRUE
979 980 981 982 983
 * returns
 *	0 if the file doesn't contain symbolic info (or this info cannot be
 *	read or parsed)
 *	1 on success
 */
984 985 986 987
static BOOL elf_load_debug_info_from_map(struct module* module, 
                                         struct elf_file_map* fmap,
                                         struct pool* pool,
                                         struct hash_table* ht_symtab)
988
{
989
    BOOL                ret = FALSE, lret;
Eric Pouech's avatar
Eric Pouech committed
990
    struct elf_thunk_area thunks[] = 
991 992 993 994 995 996 997
    {
        {"__wine_spec_import_thunks",           THUNK_ORDINAL_NOTYPE, 0, 0},    /* inter DLL calls */
        {"__wine_spec_delayed_import_loaders",  THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
        {"__wine_spec_delayed_import_thunks",   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
        {"__wine_delay_load",                   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
        {"__wine_spec_thunk_text_16",           -16,                  0, 0},    /* 16 => 32 thunks */
        {"__wine_spec_thunk_text_32",           -32,                  0, 0},    /* 32 => 16 thunks */
998
        {NULL,                                  0,                    0, 0}
999 1000
    };

1001
    module->module.SymType = SymExport;
1002 1003

    /* create a hash table for the symtab */
1004
    elf_hash_symtab(module, pool, ht_symtab, fmap, thunks);
1005

1006
    if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
1007
    {
1008 1009 1010 1011 1012
        struct elf_section_map  stab_sect, stabstr_sect;
        struct elf_section_map  debug_sect, debug_str_sect, debug_abbrev_sect,
                                debug_line_sect, debug_loclist_sect;
        struct elf_section_map  debuglink_sect;

1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
        /* if present, add the .gnu_debuglink file as an alternate to current one */
	if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect))
        {
            const BYTE* dbg_link;

            dbg_link = (const BYTE*)elf_map_section(&debuglink_sect);
            if (dbg_link != ELF_NO_MAP)
            {
                lret = elf_debuglink_parse(fmap, module, dbg_link);
                if (!lret)
		    WARN("Couldn't load linked debug file for %s\n",
                         debugstr_w(module->module.ModuleName));
                ret = ret || lret;
            }
            elf_unmap_section(&debuglink_sect);
        }
1029 1030
        if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) &&
            elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect))
1031
        {
1032 1033 1034
            const char* stab;
            const char* stabstr;

1035 1036
            stab = elf_map_section(&stab_sect);
            stabstr = elf_map_section(&stabstr_sect);
1037
            if (stab != ELF_NO_MAP && stabstr != ELF_NO_MAP)
1038 1039
            {
                /* OK, now just parse all of the stabs. */
1040
                lret = stabs_parse(module, module->elf_info->elf_addr,
1041 1042
                                   stab, elf_get_map_size(&stab_sect),
                                   stabstr, elf_get_map_size(&stabstr_sect));
1043 1044 1045 1046 1047 1048
                if (lret)
                    /* and fill in the missing information for stabs */
                    elf_finish_stabs_info(module, ht_symtab);
                else
                    WARN("Couldn't correctly read stabs\n");
                ret = ret || lret;
1049
            }
1050
            else lret = FALSE;
1051 1052
            elf_unmap_section(&stab_sect);
            elf_unmap_section(&stabstr_sect);
1053
        }
1054
	if (elf_find_section(fmap, ".debug_info", SHT_NULL, &debug_sect))
1055 1056
        {
            /* Dwarf 2 debug information */
Mike McCormack's avatar
Mike McCormack committed
1057 1058 1059
            const BYTE* dw2_debug;
            const BYTE* dw2_debug_abbrev;
            const BYTE* dw2_debug_str;
1060
            const BYTE* dw2_debug_line;
1061
            const BYTE* dw2_debug_loclist;
1062

1063 1064 1065 1066 1067 1068 1069
            /* debug info might have a different base address than .so file
             * when elf file is prelinked after splitting off debug info
             * adjust symbol base addresses accordingly
             */
            unsigned long load_offset = module->elf_info->elf_addr +
                          fmap->elf_start - debug_sect.fmap->elf_start;

1070
            TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName));
1071

1072 1073 1074 1075 1076 1077 1078 1079 1080 1081
	    elf_find_section(fmap, ".debug_str", SHT_NULL, &debug_str_sect);
	    elf_find_section(fmap, ".debug_abbrev", SHT_NULL, &debug_abbrev_sect);
	    elf_find_section(fmap, ".debug_line", SHT_NULL, &debug_line_sect);
	    elf_find_section(fmap, ".debug_loc", SHT_NULL, &debug_loclist_sect);

            dw2_debug = (const BYTE*)elf_map_section(&debug_sect);
            dw2_debug_abbrev = (const BYTE*)elf_map_section(&debug_abbrev_sect);
            dw2_debug_str = (const BYTE*)elf_map_section(&debug_str_sect);
            dw2_debug_line = (const BYTE*)elf_map_section(&debug_line_sect);
            dw2_debug_loclist = (const BYTE*)elf_map_section(&debug_loclist_sect);
1082
            if (dw2_debug != ELF_NO_MAP && dw2_debug_abbrev != ELF_NO_MAP && dw2_debug_str != ELF_NO_MAP)
1083 1084
            {
                /* OK, now just parse dwarf2 debug infos. */
1085
                lret = dwarf2_parse(module, load_offset, thunks,
1086 1087 1088 1089 1090
                                    dw2_debug, elf_get_map_size(&debug_sect),
                                    dw2_debug_abbrev, elf_get_map_size(&debug_abbrev_sect),
                                    dw2_debug_str, elf_get_map_size(&debug_str_sect),
                                    dw2_debug_line, elf_get_map_size(&debug_line_sect),
                                    dw2_debug_loclist, elf_get_map_size(&debug_loclist_sect));
1091

1092
                if (!lret)
1093
                    WARN("Couldn't correctly read dwarf2\n");
1094
                ret = ret || lret;
1095
            }
1096 1097 1098 1099 1100
            elf_unmap_section(&debug_sect);
            elf_unmap_section(&debug_abbrev_sect);
            elf_unmap_section(&debug_str_sect);
            elf_unmap_section(&debug_line_sect);
            elf_unmap_section(&debug_loclist_sect);
1101
        }
1102
    }
1103 1104
    if (strstrW(module->module.ModuleName, S_ElfW) ||
        !strcmpW(module->module.ModuleName, S_WineLoaderW))
1105 1106 1107
    {
        /* add the thunks for native libraries */
        if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
Eric Pouech's avatar
Eric Pouech committed
1108
            elf_new_wine_thunks(module, ht_symtab, thunks);
1109
    }
1110
    /* add all the public symbols from symtab */
1111
    if (elf_new_public_symbols(module, ht_symtab) && !ret) ret = TRUE;
1112

1113
    return ret;
1114 1115
}

1116 1117 1118 1119 1120
/******************************************************************
 *		elf_load_debug_info
 *
 * Loads ELF debugging information from the module image file.
 */
1121
BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap)
1122
{
1123 1124 1125 1126 1127 1128 1129
    BOOL                ret = TRUE;
    struct pool         pool;
    struct hash_table   ht_symtab;
    struct elf_file_map my_fmap;

    if (module->type != DMT_ELF || !module->elf_info)
    {
1130
	ERR("Bad elf module '%s'\n", debugstr_w(module->module.LoadedImageName));
1131 1132
	return FALSE;
    }
1133 1134 1135 1136

    pool_init(&pool, 65536);
    hash_table_init(&pool, &ht_symtab, 256);

1137 1138 1139
    if (!fmap)
    {
        fmap = &my_fmap;
1140
        ret = elf_map_file(module->module.LoadedImageName, fmap);
1141 1142 1143
    }
    if (ret)
        ret = elf_load_debug_info_from_map(module, fmap, &pool, &ht_symtab);
1144 1145

    pool_destroy(&pool);
1146
    if (fmap == &my_fmap) elf_unmap_file(fmap);
1147 1148 1149
    return ret;
}

1150 1151 1152 1153 1154
/******************************************************************
 *		elf_fetch_file_info
 *
 * Gathers some more information for an ELF module from a given file
 */
1155
BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
1156 1157 1158
                         DWORD* size, DWORD* checksum)
{
    struct elf_file_map fmap;
1159

1160
    if (!elf_map_file(name, &fmap)) return FALSE;
1161 1162 1163 1164 1165 1166
    if (base) *base = fmap.elf_start;
    *size = fmap.elf_size;
    *checksum = calc_crc32(&fmap);
    elf_unmap_file(&fmap);
    return TRUE;
}
1167

1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
/******************************************************************
 *		elf_load_file
 *
 * Loads the information for ELF module stored in 'filename'
 * the module has been loaded at 'load_offset' address
 * returns
 *	-1 if the file cannot be found/opened
 *	0 if the file doesn't contain symbolic info (or this info cannot be
 *	read or parsed)
 *	1 on success
 */
1179
static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
1180
                          unsigned long load_offset, struct elf_info* elf_info)
1181
{
1182
    BOOL                ret = FALSE;
1183
    struct elf_file_map fmap;
1184

1185
    TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
1186

1187
    if (!elf_map_file(filename, &fmap)) goto leave;
1188 1189 1190 1191 1192

    /* Next, we need to find a few of the internal ELF headers within
     * this thing.  We need the main executable header, and the section
     * table.
     */
1193
    if (!fmap.elf_start && !load_offset)
1194
        ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n",
1195
            debugstr_w(filename));
1196
    if (fmap.elf_start && load_offset)
1197 1198
    {
        WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. "
1199
             "Assuming load address is corrupt\n", debugstr_w(filename), load_offset);
1200 1201 1202
        load_offset = 0;
    }

1203 1204
    if (elf_info->flags & ELF_INFO_DEBUG_HEADER)
    {
1205 1206 1207
        struct elf_section_map  esm;

        if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm))
1208
        {
1209 1210 1211
            Elf32_Dyn       dyn;
            char*           ptr = (char*)fmap.sect[esm.sidx].shdr.sh_addr;
            unsigned long   len;
1212

1213 1214 1215 1216 1217 1218
            do
            {
                if (!ReadProcessMemory(pcs->handle, ptr, &dyn, sizeof(dyn), &len) ||
                    len != sizeof(dyn))
                    goto leave;
                if (dyn.d_tag == DT_DEBUG)
1219
                {
1220 1221 1222 1223 1224 1225
                    elf_info->dbg_hdr_addr = dyn.d_un.d_ptr;
                    break;
                }
                ptr += sizeof(dyn);
            } while (dyn.d_tag != DT_NULL);
            if (dyn.d_tag == DT_NULL) goto leave;
1226
	}
1227
        elf_end_find(&fmap);
1228 1229 1230 1231
    }

    if (elf_info->flags & ELF_INFO_MODULE)
    {
1232
        struct elf_module_info *elf_module_info =
1233 1234
            HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info));
        if (!elf_module_info) goto leave;
1235
        elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE,
1236 1237
                                      (load_offset) ? load_offset : fmap.elf_start,
                                      fmap.elf_size, 0, calc_crc32(&fmap));
1238
        if (!elf_info->module)
1239
        {
1240 1241
            HeapFree(GetProcessHeap(), 0, elf_module_info);
            goto leave;
1242
        }
1243 1244
        elf_info->module->elf_info = elf_module_info;
        elf_info->module->elf_info->elf_addr = load_offset;
1245 1246 1247 1248 1249

        if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
        {
            elf_info->module->module.SymType = SymDeferred;
            ret = TRUE;
1250
        }
1251
        else ret = elf_load_debug_info(elf_info->module, &fmap);
1252 1253 1254 1255

        elf_info->module->elf_info->elf_mark = 1;
        elf_info->module->elf_info->elf_loader = 0;
    } else ret = TRUE;
1256

1257 1258
    if (elf_info->flags & ELF_INFO_NAME)
    {
1259 1260 1261 1262 1263 1264 1265 1266
        WCHAR*  ptr;
        ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR));
        if (ptr)
        {
            strcpyW(ptr, filename);
            elf_info->module_name = ptr;
        }
        else ret = FALSE;
1267
    }
1268
leave:
1269
    elf_unmap_file(&fmap);
1270

1271
    return ret;
1272 1273 1274 1275 1276 1277
}

/******************************************************************
 *		elf_load_file_from_path
 * tries to load an ELF file from a set of paths (separated by ':')
 */
1278
static BOOL elf_load_file_from_path(HANDLE hProcess,
1279
                                    const WCHAR* filename,
1280 1281 1282
                                    unsigned long load_offset,
                                    const char* path,
                                    struct elf_info* elf_info)
1283
{
1284
    BOOL                ret = FALSE;
1285 1286 1287
    WCHAR               *s, *t, *fn;
    WCHAR*	        pathW = NULL;
    unsigned            len;
1288

1289
    if (!path) return FALSE;
1290

1291 1292 1293 1294 1295 1296
    len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
    pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
    if (!pathW) return FALSE;
    MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len);

    for (s = pathW; s && *s; s = (t) ? (t+1) : NULL)
1297
    {
1298
	t = strchrW(s, ':');
1299
	if (t) *t = '\0';
1300
	fn = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1 + lstrlenW(s) + 1) * sizeof(WCHAR));
1301
	if (!fn) break;
1302 1303 1304
	strcpyW(fn, s);
	strcatW(fn, S_SlashW);
	strcatW(fn, filename);
1305
	ret = elf_load_file(hProcess, fn, load_offset, elf_info);
1306
	HeapFree(GetProcessHeap(), 0, fn);
1307
	if (ret) break;
1308 1309
	s = (t) ? (t+1) : NULL;
    }
1310 1311

    HeapFree(GetProcessHeap(), 0, pathW);
1312
    return ret;
1313 1314
}

1315 1316 1317 1318 1319 1320
/******************************************************************
 *		elf_load_file_from_dll_path
 *
 * Tries to load an ELF file from the dll path
 */
static BOOL elf_load_file_from_dll_path(HANDLE hProcess,
1321
                                        const WCHAR* filename,
1322 1323 1324 1325 1326 1327 1328 1329 1330
                                        unsigned long load_offset,
                                        struct elf_info* elf_info)
{
    BOOL ret = FALSE;
    unsigned int index = 0;
    const char *path;

    while (!ret && (path = wine_dll_enum_load_path( index++ )))
    {
1331 1332 1333 1334 1335 1336 1337 1338
        WCHAR *name;
        unsigned len;

        len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);

        name = HeapAlloc( GetProcessHeap(), 0,
                          (len + lstrlenW(filename) + 2) * sizeof(WCHAR) );

1339
        if (!name) break;
1340 1341 1342
        MultiByteToWideChar(CP_UNIXCP, 0, path, -1, name, len);
        strcatW( name, S_SlashW );
        strcatW( name, filename );
1343 1344 1345 1346 1347 1348
        ret = elf_load_file(hProcess, name, load_offset, elf_info);
        HeapFree( GetProcessHeap(), 0, name );
    }
    return ret;
}

1349 1350 1351 1352 1353
/******************************************************************
 *		elf_search_and_load_file
 *
 * lookup a file in standard ELF locations, and if found, load it
 */
1354 1355
static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename,
                                     unsigned long load_offset,
1356
                                     struct elf_info* elf_info)
1357
{
1358
    BOOL                ret = FALSE;
1359
    struct module*      module;
1360
    static WCHAR        S_libstdcPPW[] = {'l','i','b','s','t','d','c','+','+','\0'};
1361

1362
    if (filename == NULL || *filename == '\0') return FALSE;
1363
    if ((module = module_is_already_loaded(pcs, filename)))
1364 1365
    {
        elf_info->module = module;
1366
        module->elf_info->elf_mark = 1;
1367 1368 1369
        return module->module.SymType;
    }

1370
    if (strstrW(filename, S_libstdcPPW)) return FALSE; /* We know we can't do it */
1371
    ret = elf_load_file(pcs, filename, load_offset, elf_info);
1372
    /* if relative pathname, try some absolute base dirs */
1373
    if (!ret && !strchrW(filename, '/'))
1374
    {
1375
        ret = elf_load_file_from_path(pcs, filename, load_offset,
1376 1377
                                      getenv("PATH"), elf_info) ||
            elf_load_file_from_path(pcs, filename, load_offset,
1378 1379
                                    getenv("LD_LIBRARY_PATH"), elf_info);
        if (!ret) ret = elf_load_file_from_dll_path(pcs, filename, load_offset, elf_info);
1380 1381
    }
    
1382
    return ret;
1383 1384 1385
}

/******************************************************************
1386
 *		elf_enum_modules_internal
1387
 *
1388
 * Enumerate ELF modules from a running process
1389
 */
1390
static BOOL elf_enum_modules_internal(const struct process* pcs,
1391
                                      const WCHAR* main_name,
1392
                                      elf_enum_modules_cb cb, void* user)
1393 1394 1395 1396 1397
{
    struct r_debug      dbg_hdr;
    void*               lm_addr;
    struct link_map     lm;
    char		bufstr[256];
1398
    WCHAR               bufstrW[MAX_PATH];
1399

1400
    if (!pcs->dbg_hdr_addr ||
1401
        !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr,
1402
                           &dbg_hdr, sizeof(dbg_hdr), NULL))
1403 1404 1405 1406 1407 1408 1409 1410 1411
        return FALSE;

    /* Now walk the linked list.  In all known ELF implementations,
     * the dynamic loader maintains this linked list for us.  In some
     * cases the first entry doesn't appear with a name, in other cases it
     * does.
     */
    for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next)
    {
1412
	if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL))
1413 1414 1415 1416
	    return FALSE;

	if (lm.l_prev != NULL && /* skip first entry, normally debuggee itself */
	    lm.l_name != NULL &&
1417
	    ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL))
1418 1419
        {
	    bufstr[sizeof(bufstr) - 1] = '\0';
1420
            MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, sizeof(bufstrW) / sizeof(WCHAR));
1421
            if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name);
1422
            if (!cb(bufstrW, (unsigned long)lm.l_addr, user)) break;
1423 1424
	}
    }
1425 1426 1427 1428 1429 1430 1431 1432 1433
    return TRUE;
}

struct elf_sync
{
    struct process*     pcs;
    struct elf_info     elf_info;
};

1434
static BOOL elf_enum_sync_cb(const WCHAR* name, unsigned long addr, void* user)
1435 1436 1437
{
    struct elf_sync*    es = user;

1438
    elf_search_and_load_file(es->pcs, name, addr, &es->elf_info);
1439 1440
    return TRUE;
}
1441

1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
/******************************************************************
 *		elf_synchronize_module_list
 *
 * this functions rescans the debuggee module's list and synchronizes it with
 * the one from 'pcs', ie:
 * - if a module is in debuggee and not in pcs, it's loaded into pcs
 * - if a module is in pcs and not in debuggee, it's unloaded from pcs
 */
BOOL	elf_synchronize_module_list(struct process* pcs)
{
    struct module*      module;
    struct elf_sync     es;
1454 1455

    for (module = pcs->lmodules; module; module = module->next)
1456
    {
Eric Pouech's avatar
Eric Pouech committed
1457 1458
        if (module->type == DMT_ELF && !module->is_virtual)
            module->elf_info->elf_mark = 0;
1459 1460 1461 1462
    }

    es.pcs = pcs;
    es.elf_info.flags = ELF_INFO_MODULE;
1463
    if (!elf_enum_modules_internal(pcs, NULL, elf_enum_sync_cb, &es))
1464 1465 1466 1467
        return FALSE;

    module = pcs->lmodules;
    while (module)
1468
    {
Eric Pouech's avatar
Eric Pouech committed
1469 1470
        if (module->type == DMT_ELF && !module->is_virtual &&
            !module->elf_info->elf_mark && !module->elf_info->elf_loader)
1471 1472 1473 1474 1475
        {
            module_remove(pcs, module);
            /* restart all over */
            module = pcs->lmodules;
        }
1476
        else module = module->next;
1477 1478 1479 1480 1481
    }
    return TRUE;
}

/******************************************************************
1482
 *		elf_search_loader
1483
 *
1484 1485 1486 1487
 * Lookup in a running ELF process the loader, and sets its ELF link
 * address (for accessing the list of loaded .so libs) in pcs.
 * If flags is ELF_INFO_MODULE, the module for the loader is also
 * added as a module into pcs.
1488
 */
1489
static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
1490
{
1491
    BOOL                ret;
1492
    const char*         ptr;
1493 1494 1495

    /* All binaries are loaded with WINELOADER (if run from tree) or by the
     * main executable (either wine-kthread or wine-pthread)
1496 1497
     * FIXME: the heuristic used to know whether we need to load wine-pthread
     * or wine-kthread is not 100% safe
1498 1499 1500
     */
    if ((ptr = getenv("WINELOADER")))
    {
1501 1502 1503 1504 1505 1506 1507 1508
        WCHAR   tmp[MAX_PATH];
        MultiByteToWideChar(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp) / sizeof(WCHAR));
        ret = elf_search_and_load_file(pcs, tmp, 0, elf_info);
    }
    else
    {
        ret = elf_search_and_load_file(pcs, S_WineKThreadW, 0, elf_info) ||
            elf_search_and_load_file(pcs, S_WinePThreadW, 0, elf_info);
1509
    }
1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
    return ret;
}

/******************************************************************
 *		elf_read_wine_loader_dbg_info
 *
 * Try to find a decent wine executable which could have loaded the debuggee
 */
BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
{
    struct elf_info     elf_info;

    elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
    if (!elf_search_loader(pcs, &elf_info)) return FALSE;
1524
    elf_info.module->elf_info->elf_loader = 1;
1525
    module_set_module(elf_info.module, S_WineLoaderW);
1526
    return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
1527 1528
}

1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
/******************************************************************
 *		elf_enum_modules
 *
 * Enumerates the ELF loaded modules from a running target (hProc)
 * This function doesn't require that someone has called SymInitialize
 * on this very process.
 */
BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
{
    struct process      pcs;
    struct elf_info     elf_info;
1540
    BOOL                ret;
1541

1542
    memset(&pcs, 0, sizeof(pcs));
1543
    pcs.handle = hProc;
1544
    elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_NAME;
1545
    if (!elf_search_loader(&pcs, &elf_info)) return FALSE;
1546
    pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr;
1547 1548 1549
    ret = elf_enum_modules_internal(&pcs, elf_info.module_name, cb, user);
    HeapFree(GetProcessHeap(), 0, (char*)elf_info.module_name);
    return ret;
1550 1551 1552 1553 1554 1555
}

struct elf_load
{
    struct process*     pcs;
    struct elf_info     elf_info;
1556
    const WCHAR*        name;
1557 1558 1559 1560 1561 1562 1563 1564 1565
    BOOL                ret;
};

/******************************************************************
 *		elf_load_cb
 *
 * Callback for elf_load_module, used to walk the list of loaded
 * modules.
 */
1566
static BOOL elf_load_cb(const WCHAR* name, unsigned long addr, void* user)
1567 1568
{
    struct elf_load*    el = user;
1569
    const WCHAR*        p;
1570 1571 1572 1573

    /* memcmp is needed for matches when bufstr contains also version information
     * el->name: libc.so, name: libc.so.6.0
     */
1574
    p = strrchrW(name, '/');
1575
    if (!p++) p = name;
1576
    if (!memcmp(p, el->name, lstrlenW(el->name) * sizeof(WCHAR)))
1577
    {
1578
        el->ret = elf_search_and_load_file(el->pcs, name, addr, &el->elf_info);
1579 1580 1581 1582 1583
        return FALSE;
    }
    return TRUE;
}

1584 1585 1586 1587
/******************************************************************
 *		elf_load_module
 *
 * loads an ELF module and stores it in process' module list
1588
 * Also, find module real name and load address from
1589 1590
 * the real loaded modules list in pcs address space
 */
1591
struct module*  elf_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
1592
{
1593
    struct elf_load     el;
1594

1595
    TRACE("(%p %s %08lx)\n", pcs, debugstr_w(name), addr);
1596

1597 1598
    el.elf_info.flags = ELF_INFO_MODULE;
    el.ret = FALSE;
1599

1600
    if (pcs->dbg_hdr_addr) /* we're debugging a life target */
1601
    {
1602
        el.pcs = pcs;
1603 1604
        /* do only the lookup from the filename, not the path (as we lookup module
         * name in the process' loaded module list)
1605
         */
1606 1607
        el.name = strrchrW(name, '/');
        if (!el.name++) el.name = name;
1608
        el.ret = FALSE;
1609

1610
        if (!elf_enum_modules_internal(pcs, NULL, elf_load_cb, &el))
1611 1612 1613 1614
            return NULL;
    }
    else if (addr)
    {
1615
        el.name = name;
1616
        el.ret = elf_search_and_load_file(pcs, el.name, addr, &el.elf_info);
1617
    }
1618 1619 1620
    if (!el.ret) return NULL;
    assert(el.elf_info.module);
    return el.elf_info.module;
1621 1622 1623 1624 1625 1626 1627 1628 1629
}

#else	/* !__ELF__ */

BOOL	elf_synchronize_module_list(struct process* pcs)
{
    return FALSE;
}

1630
BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
1631 1632 1633 1634 1635
                         DWORD* size, DWORD* checksum)
{
    return FALSE;
}

1636
BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
1637
{
1638
    return FALSE;
1639 1640
}

1641 1642 1643 1644 1645
BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
{
    return FALSE;
}

1646
struct module*  elf_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
1647 1648 1649 1650
{
    return NULL;
}

1651
BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap)
1652
{
1653
    return FALSE;
1654
}
1655 1656 1657 1658 1659 1660

int elf_is_in_thunk_area(unsigned long addr,
                         const struct elf_thunk_area* thunks)
{
    return -1;
}
1661
#endif  /* __ELF__ */