ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

elf_module.c
Go to the documentation of this file.
00001 /*
00002  * File elf.c - processing of ELF files
00003  *
00004  * Copyright (C) 1996, Eric Youngdale.
00005  *       1999-2007 Eric Pouech
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #include "config.h"
00023 #include "wine/port.h"
00024 
00025 #if defined(__svr4__) || defined(__sun)
00026 #define __ELF__ 1
00027 /* large files are not supported by libelf */
00028 #undef _FILE_OFFSET_BITS
00029 #define _FILE_OFFSET_BITS 32
00030 #endif
00031 
00032 #include <assert.h>
00033 #include <stdio.h>
00034 #include <stdlib.h>
00035 #ifdef HAVE_SYS_STAT_H
00036 # include <sys/stat.h>
00037 #endif
00038 #include <fcntl.h>
00039 #ifdef HAVE_SYS_MMAN_H
00040 #include <sys/mman.h>
00041 #endif
00042 #ifdef HAVE_UNISTD_H
00043 # include <unistd.h>
00044 #endif
00045 
00046 #include "dbghelp_private.h"
00047 
00048 #include "image_private.h"
00049 
00050 #include "wine/library.h"
00051 #include "wine/debug.h"
00052 
00053 #ifdef __ELF__
00054 
00055 #define ELF_INFO_DEBUG_HEADER   0x0001
00056 #define ELF_INFO_MODULE         0x0002
00057 #define ELF_INFO_NAME           0x0004
00058 
00059 WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
00060 
00061 struct elf_info
00062 {
00063     unsigned                    flags;          /* IN  one (or several) of the ELF_INFO constants */
00064     DWORD_PTR                   dbg_hdr_addr;   /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
00065     struct module*              module;         /* OUT loaded module (if ELF_INFO_MODULE is set) */
00066     const WCHAR*                module_name;    /* OUT found module name (if ELF_INFO_NAME is set) */
00067 };
00068 
00069 struct symtab_elt
00070 {
00071     struct hash_table_elt       ht_elt;
00072     const Elf_Sym*              symp;
00073     struct symt_compiland*      compiland;
00074     unsigned                    used;
00075 };
00076 
00077 struct elf_thunk_area
00078 {
00079     const char*                 symname;
00080     THUNK_ORDINAL               ordinal;
00081     unsigned long               rva_start;
00082     unsigned long               rva_end;
00083 };
00084 
00085 struct elf_module_info
00086 {
00087     unsigned long               elf_addr;
00088     unsigned short          elf_mark : 1,
00089                                 elf_loader : 1;
00090     struct image_file_map       file_map;
00091 };
00092 
00093 /******************************************************************
00094  *      elf_map_section
00095  *
00096  * Maps a single section into memory from an ELF file
00097  */
00098 const char* elf_map_section(struct image_section_map* ism)
00099 {
00100     struct elf_file_map*        fmap = &ism->fmap->u.elf;
00101 
00102     unsigned long pgsz = getpagesize();
00103     unsigned long ofst, size;
00104 
00105     assert(ism->fmap->modtype == DMT_ELF);
00106     if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum ||
00107         fmap->sect[ism->sidx].shdr.sh_type == SHT_NOBITS)
00108         return IMAGE_NO_MAP;
00109 
00110     if (fmap->target_copy)
00111     {
00112         return fmap->target_copy + fmap->sect[ism->sidx].shdr.sh_offset;
00113     }
00114     /* align required information on page size (we assume pagesize is a power of 2) */
00115     ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1);
00116     size = ((fmap->sect[ism->sidx].shdr.sh_offset +
00117              fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
00118     fmap->sect[ism->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE,
00119                                         fmap->fd, ofst);
00120     if (fmap->sect[ism->sidx].mapped == IMAGE_NO_MAP) return IMAGE_NO_MAP;
00121     return fmap->sect[ism->sidx].mapped + (fmap->sect[ism->sidx].shdr.sh_offset & (pgsz - 1));
00122 }
00123 
00124 /******************************************************************
00125  *      elf_find_section
00126  *
00127  * Finds a section by name (and type) into memory from an ELF file
00128  * or its alternate if any
00129  */
00130 BOOL elf_find_section(struct image_file_map* _fmap, const char* name,
00131                       unsigned sht, struct image_section_map* ism)
00132 {
00133     struct elf_file_map*        fmap;
00134     unsigned i;
00135 
00136     while (_fmap)
00137     {
00138         fmap = &_fmap->u.elf;
00139         if (fmap->shstrtab == IMAGE_NO_MAP)
00140         {
00141             struct image_section_map  hdr_ism = {_fmap, fmap->elfhdr.e_shstrndx};
00142             if ((fmap->shstrtab = elf_map_section(&hdr_ism)) == IMAGE_NO_MAP) break;
00143         }
00144         for (i = 0; i < fmap->elfhdr.e_shnum; i++)
00145         {
00146             if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 &&
00147                 (sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type))
00148             {
00149                 ism->fmap = _fmap;
00150                 ism->sidx = i;
00151                 return TRUE;
00152             }
00153         }
00154         _fmap = fmap->alternate;
00155     }
00156     ism->fmap = NULL;
00157     ism->sidx = -1;
00158     return FALSE;
00159 }
00160 
00161 /******************************************************************
00162  *      elf_unmap_section
00163  *
00164  * Unmaps a single section from memory
00165  */
00166 void elf_unmap_section(struct image_section_map* ism)
00167 {
00168     struct elf_file_map*        fmap = &ism->fmap->u.elf;
00169 
00170     if (ism->sidx >= 0 && ism->sidx < fmap->elfhdr.e_shnum && !fmap->target_copy &&
00171         fmap->sect[ism->sidx].mapped != IMAGE_NO_MAP)
00172     {
00173         unsigned long pgsz = getpagesize();
00174         unsigned long ofst, size;
00175 
00176         ofst = fmap->sect[ism->sidx].shdr.sh_offset & ~(pgsz - 1);
00177         size = ((fmap->sect[ism->sidx].shdr.sh_offset +
00178              fmap->sect[ism->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
00179         if (munmap((char*)fmap->sect[ism->sidx].mapped, size) < 0)
00180             WARN("Couldn't unmap the section\n");
00181         fmap->sect[ism->sidx].mapped = IMAGE_NO_MAP;
00182     }
00183 }
00184 
00185 static void elf_end_find(struct image_file_map* fmap)
00186 {
00187     struct image_section_map      ism;
00188 
00189     while (fmap)
00190     {
00191         ism.fmap = fmap;
00192         ism.sidx = fmap->u.elf.elfhdr.e_shstrndx;
00193         elf_unmap_section(&ism);
00194         fmap->u.elf.shstrtab = IMAGE_NO_MAP;
00195         fmap = fmap->u.elf.alternate;
00196     }
00197 }
00198 
00199 /******************************************************************
00200  *      elf_get_map_rva
00201  *
00202  * Get the RVA of an ELF section
00203  */
00204 DWORD_PTR elf_get_map_rva(const struct image_section_map* ism)
00205 {
00206     if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum)
00207         return 0;
00208     return ism->fmap->u.elf.sect[ism->sidx].shdr.sh_addr - ism->fmap->u.elf.elf_start;
00209 }
00210 
00211 /******************************************************************
00212  *      elf_get_map_size
00213  *
00214  * Get the size of an ELF section
00215  */
00216 unsigned elf_get_map_size(const struct image_section_map* ism)
00217 {
00218     if (ism->sidx < 0 || ism->sidx >= ism->fmap->u.elf.elfhdr.e_shnum)
00219         return 0;
00220     return ism->fmap->u.elf.sect[ism->sidx].shdr.sh_size;
00221 }
00222 
00223 static inline void elf_reset_file_map(struct image_file_map* fmap)
00224 {
00225     fmap->u.elf.fd = -1;
00226     fmap->u.elf.shstrtab = IMAGE_NO_MAP;
00227     fmap->u.elf.alternate = NULL;
00228     fmap->u.elf.target_copy = NULL;
00229 }
00230 
00231 struct elf_map_file_data
00232 {
00233     enum {from_file, from_process}      kind;
00234     union
00235     {
00236         struct
00237         {
00238             const WCHAR* filename;
00239         } file;
00240         struct
00241         {
00242             HANDLE      handle;
00243             void*       load_addr;
00244         } process;
00245     } u;
00246 };
00247 
00248 static BOOL elf_map_file_read(struct image_file_map* fmap, struct elf_map_file_data* emfd,
00249                               void* buf, size_t len, off_t off)
00250 {
00251     SIZE_T dw;
00252 
00253     switch (emfd->kind)
00254     {
00255     case from_file:
00256         return pread(fmap->u.elf.fd, buf, len, off) == len;
00257     case from_process:
00258         return ReadProcessMemory(emfd->u.process.handle,
00259                                  (void*)((unsigned long)emfd->u.process.load_addr + (unsigned long)off),
00260                                  buf, len, &dw) && dw == len;
00261     default:
00262         assert(0);
00263         return FALSE;
00264     }
00265 }
00266 
00267 /******************************************************************
00268  *      elf_map_file
00269  *
00270  * Maps an ELF file into memory (and checks it's a real ELF file)
00271  */
00272 static BOOL elf_map_file(struct elf_map_file_data* emfd, struct image_file_map* fmap)
00273 {
00274     static const BYTE   elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
00275     struct stat         statbuf;
00276     int                 i;
00277     Elf_Phdr            phdr;
00278     unsigned long       tmp, page_mask = getpagesize() - 1;
00279     char*               filename;
00280     unsigned            len;
00281     BOOL                ret = FALSE;
00282 
00283     switch (emfd->kind)
00284     {
00285     case from_file:
00286         len = WideCharToMultiByte(CP_UNIXCP, 0, emfd->u.file.filename, -1, NULL, 0, NULL, NULL);
00287         if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE;
00288         WideCharToMultiByte(CP_UNIXCP, 0, emfd->u.file.filename, -1, filename, len, NULL, NULL);
00289         break;
00290     case from_process:
00291         filename = NULL;
00292         break;
00293     default: assert(0);
00294         return FALSE;
00295     }
00296 
00297     elf_reset_file_map(fmap);
00298 
00299     fmap->modtype = DMT_ELF;
00300     fmap->u.elf.fd = -1;
00301     fmap->u.elf.target_copy = NULL;
00302 
00303     switch (emfd->kind)
00304     {
00305     case from_file:
00306         /* check that the file exists, and that the module hasn't been loaded yet */
00307         if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done;
00308 
00309         /* Now open the file, so that we can mmap() it. */
00310         if ((fmap->u.elf.fd = open(filename, O_RDONLY)) == -1) goto done;
00311         break;
00312     case from_process:
00313         break;
00314     }
00315     if (!elf_map_file_read(fmap, emfd, &fmap->u.elf.elfhdr, sizeof(fmap->u.elf.elfhdr), 0))
00316         goto done;
00317 
00318     /* and check for an ELF header */
00319     if (memcmp(fmap->u.elf.elfhdr.e_ident,
00320                elf_signature, sizeof(elf_signature))) goto done;
00321     /* and check 32 vs 64 size according to current machine */
00322 #ifdef _WIN64
00323     if (fmap->u.elf.elfhdr.e_ident[EI_CLASS] != ELFCLASS64) goto done;
00324 #else
00325     if (fmap->u.elf.elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done;
00326 #endif
00327     fmap->u.elf.sect = HeapAlloc(GetProcessHeap(), 0,
00328                                  fmap->u.elf.elfhdr.e_shnum * sizeof(fmap->u.elf.sect[0]));
00329     if (!fmap->u.elf.sect) goto done;
00330 
00331     for (i = 0; i < fmap->u.elf.elfhdr.e_shnum; i++)
00332     {
00333         if (!elf_map_file_read(fmap, emfd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr),
00334                                fmap->u.elf.elfhdr.e_shoff + i * sizeof(fmap->u.elf.sect[i].shdr)))
00335         {
00336             HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect);
00337             fmap->u.elf.sect = NULL;
00338             goto done;
00339         }
00340         fmap->u.elf.sect[i].mapped = IMAGE_NO_MAP;
00341     }
00342 
00343     /* grab size of module once loaded in memory */
00344     fmap->u.elf.elf_size = 0;
00345     fmap->u.elf.elf_start = ~0L;
00346     for (i = 0; i < fmap->u.elf.elfhdr.e_phnum; i++)
00347     {
00348         if (elf_map_file_read(fmap, emfd, &phdr, sizeof(phdr),
00349                               fmap->u.elf.elfhdr.e_phoff + i * sizeof(phdr)) &&
00350             phdr.p_type == PT_LOAD)
00351         {
00352             tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask;
00353             if (fmap->u.elf.elf_size < tmp) fmap->u.elf.elf_size = tmp;
00354             if (phdr.p_vaddr < fmap->u.elf.elf_start) fmap->u.elf.elf_start = phdr.p_vaddr;
00355         }
00356     }
00357     /* if non relocatable ELF, then remove fixed address from computation
00358      * otherwise, all addresses are zero based and start has no effect
00359      */
00360     fmap->u.elf.elf_size -= fmap->u.elf.elf_start;
00361 
00362     switch (emfd->kind)
00363     {
00364     case from_file: break;
00365     case from_process:
00366         if (!(fmap->u.elf.target_copy = HeapAlloc(GetProcessHeap(), 0, fmap->u.elf.elf_size)))
00367         {
00368             HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect);
00369             goto done;
00370         }
00371         if (!ReadProcessMemory(emfd->u.process.handle, emfd->u.process.load_addr, fmap->u.elf.target_copy,
00372                                fmap->u.elf.elf_size, NULL))
00373         {
00374             HeapFree(GetProcessHeap(), 0, fmap->u.elf.target_copy);
00375             HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect);
00376             goto done;
00377         }
00378         break;
00379     }
00380     ret = TRUE;
00381 done:
00382     HeapFree(GetProcessHeap(), 0, filename);
00383     return ret;
00384 }
00385 
00386 /******************************************************************
00387  *      elf_unmap_file
00388  *
00389  * Unmaps an ELF file from memory (previously mapped with elf_map_file)
00390  */
00391 static void elf_unmap_file(struct image_file_map* fmap)
00392 {
00393     while (fmap)
00394     {
00395         if (fmap->u.elf.fd != -1)
00396         {
00397             struct image_section_map  ism;
00398             ism.fmap = fmap;
00399             for (ism.sidx = 0; ism.sidx < fmap->u.elf.elfhdr.e_shnum; ism.sidx++)
00400             {
00401                 elf_unmap_section(&ism);
00402             }
00403             HeapFree(GetProcessHeap(), 0, fmap->u.elf.sect);
00404             close(fmap->u.elf.fd);
00405         }
00406         HeapFree(GetProcessHeap(), 0, fmap->u.elf.target_copy);
00407         fmap = fmap->u.elf.alternate;
00408     }
00409 }
00410 
00411 static void elf_module_remove(struct process* pcs, struct module_format* modfmt)
00412 {
00413     elf_unmap_file(&modfmt->u.elf_info->file_map);
00414     HeapFree(GetProcessHeap(), 0, modfmt);
00415 }
00416 
00417 /******************************************************************
00418  *      elf_is_in_thunk_area
00419  *
00420  * Check whether an address lies within one of the thunk area we
00421  * know of.
00422  */
00423 int elf_is_in_thunk_area(unsigned long addr,
00424                          const struct elf_thunk_area* thunks)
00425 {
00426     unsigned i;
00427 
00428     if (thunks) for (i = 0; thunks[i].symname; i++)
00429     {
00430         if (addr >= thunks[i].rva_start && addr < thunks[i].rva_end)
00431             return i;
00432     }
00433     return -1;
00434 }
00435 
00436 /******************************************************************
00437  *      elf_hash_symtab
00438  *
00439  * creating an internal hash table to ease use ELF symtab information lookup
00440  */
00441 static void elf_hash_symtab(struct module* module, struct pool* pool,
00442                             struct hash_table* ht_symtab, struct image_file_map* fmap,
00443                             struct elf_thunk_area* thunks)
00444 {
00445     int                     i, j, nsym;
00446     const char*                 strp;
00447     const char*                 symname;
00448     struct symt_compiland*      compiland = NULL;
00449     const char*                 ptr;
00450     const Elf_Sym*              symp;
00451     struct symtab_elt*          ste;
00452     struct image_section_map    ism, ism_str;
00453 
00454     if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &ism) &&
00455         !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &ism)) return;
00456     if ((symp = (const Elf_Sym*)image_map_section(&ism)) == IMAGE_NO_MAP) return;
00457     ism_str.fmap = ism.fmap;
00458     ism_str.sidx = fmap->u.elf.sect[ism.sidx].shdr.sh_link;
00459     if ((strp = image_map_section(&ism_str)) == IMAGE_NO_MAP)
00460     {
00461         image_unmap_section(&ism);
00462         return;
00463     }
00464 
00465     nsym = image_get_map_size(&ism) / sizeof(*symp);
00466 
00467     for (j = 0; thunks[j].symname; j++)
00468         thunks[j].rva_start = thunks[j].rva_end = 0;
00469 
00470     for (i = 0; i < nsym; i++, symp++)
00471     {
00472         /* Ignore certain types of entries which really aren't of that much
00473          * interest.
00474          */
00475         if ((ELF32_ST_TYPE(symp->st_info) != STT_NOTYPE &&
00476              ELF32_ST_TYPE(symp->st_info) != STT_FILE &&
00477              ELF32_ST_TYPE(symp->st_info) != STT_OBJECT &&
00478              ELF32_ST_TYPE(symp->st_info) != STT_FUNC) ||
00479             symp->st_shndx == SHN_UNDEF)
00480         {
00481             continue;
00482         }
00483 
00484         symname = strp + symp->st_name;
00485 
00486         /* handle some specific symtab (that we'll throw away when done) */
00487         switch (ELF32_ST_TYPE(symp->st_info))
00488         {
00489         case STT_FILE:
00490             if (symname)
00491                 compiland = symt_new_compiland(module, symp->st_value,
00492                                                source_new(module, NULL, symname));
00493             else
00494                 compiland = NULL;
00495             continue;
00496         case STT_NOTYPE:
00497             /* we are only interested in wine markers inserted by winebuild */
00498             for (j = 0; thunks[j].symname; j++)
00499             {
00500                 if (!strcmp(symname, thunks[j].symname))
00501                 {
00502                     thunks[j].rva_start = symp->st_value;
00503                     thunks[j].rva_end   = symp->st_value + symp->st_size;
00504                     break;
00505                 }
00506             }
00507             continue;
00508         }
00509 
00510         /* FIXME: we don't need to handle them (GCC internals)
00511          * Moreover, they screw up our symbol lookup :-/
00512          */
00513         if (symname[0] == '.' && symname[1] == 'L' && isdigit(symname[2]))
00514             continue;
00515 
00516         ste = pool_alloc(pool, sizeof(*ste));
00517         ste->ht_elt.name = symname;
00518         /* GCC emits, in some cases, a .<digit>+ suffix.
00519          * This is used for static variable inside functions, so
00520          * that we can have several such variables with same name in
00521          * the same compilation unit
00522          * We simply ignore that suffix when present (we also get rid
00523          * of it in stabs parsing)
00524          */
00525         ptr = symname + strlen(symname) - 1;
00526         if (isdigit(*ptr))
00527         {
00528             while (isdigit(*ptr) && ptr >= symname) ptr--;
00529             if (ptr > symname && *ptr == '.')
00530             {
00531                 char* n = pool_alloc(pool, ptr - symname + 1);
00532                 memcpy(n, symname, ptr - symname + 1);
00533                 n[ptr - symname] = '\0';
00534                 ste->ht_elt.name = n;
00535             }
00536         }
00537         ste->symp        = symp;
00538         ste->compiland   = compiland;
00539         ste->used        = 0;
00540         hash_table_add(ht_symtab, &ste->ht_elt);
00541     }
00542     /* as we added in the ht_symtab pointers to the symbols themselves,
00543      * we cannot unmap yet the sections, it will be done when we're over
00544      * with this ELF file
00545      */
00546 }
00547 
00548 /******************************************************************
00549  *      elf_lookup_symtab
00550  *
00551  * lookup a symbol by name in our internal hash table for the symtab
00552  */
00553 static const Elf_Sym* elf_lookup_symtab(const struct module* module,
00554                                           const struct hash_table* ht_symtab,
00555                                           const char* name, const struct symt* compiland)
00556 {
00557     struct symtab_elt*          weak_result = NULL; /* without compiland name */
00558     struct symtab_elt*          result = NULL;
00559     struct hash_table_iter      hti;
00560     struct symtab_elt*          ste;
00561     const char*                 compiland_name;
00562     const char*                 compiland_basename;
00563     const char*                 base;
00564 
00565     /* we need weak match up (at least) when symbols of same name, 
00566      * defined several times in different compilation units,
00567      * are merged in a single one (hence a different filename for c.u.)
00568      */
00569     if (compiland)
00570     {
00571         compiland_name = source_get(module,
00572                                     ((const struct symt_compiland*)compiland)->source);
00573         compiland_basename = strrchr(compiland_name, '/');
00574         if (!compiland_basename++) compiland_basename = compiland_name;
00575     }
00576     else compiland_name = compiland_basename = NULL;
00577     
00578     hash_table_iter_init(ht_symtab, &hti, name);
00579     while ((ste = hash_table_iter_up(&hti)))
00580     {
00581         if (ste->used || strcmp(ste->ht_elt.name, name)) continue;
00582 
00583         weak_result = ste;
00584         if ((ste->compiland && !compiland_name) || (!ste->compiland && compiland_name))
00585             continue;
00586         if (ste->compiland && compiland_name)
00587         {
00588             const char* filename = source_get(module, ste->compiland->source);
00589             if (strcmp(filename, compiland_name))
00590             {
00591                 base = strrchr(filename, '/');
00592                 if (!base++) base = filename;
00593                 if (strcmp(base, compiland_basename)) continue;
00594             }
00595         }
00596         if (result)
00597         {
00598             FIXME("Already found symbol %s (%s) in symtab %s @%08x and %s @%08x\n",
00599                   name, compiland_name,
00600                   source_get(module, result->compiland->source), (unsigned int)result->symp->st_value,
00601                   source_get(module, ste->compiland->source), (unsigned int)ste->symp->st_value);
00602         }
00603         else
00604         {
00605             result = ste;
00606             ste->used = 1;
00607         }
00608     }
00609     if (!result && !(result = weak_result))
00610     {
00611         FIXME("Couldn't find symbol %s!%s in symtab\n",
00612               debugstr_w(module->module.ModuleName), name);
00613         return NULL;
00614     }
00615     return result->symp;
00616 }
00617 
00618 /******************************************************************
00619  *      elf_finish_stabs_info
00620  *
00621  * - get any relevant information (address & size) from the bits we got from the
00622  *   stabs debugging information
00623  */
00624 static void elf_finish_stabs_info(struct module* module, const struct hash_table* symtab)
00625 {
00626     struct hash_table_iter      hti;
00627     void*                       ptr;
00628     struct symt_ht*             sym;
00629     const Elf_Sym*              symp;
00630     struct elf_module_info*     elf_info = module->format_info[DFI_ELF]->u.elf_info;
00631 
00632     hash_table_iter_init(&module->ht_symbols, &hti, NULL);
00633     while ((ptr = hash_table_iter_up(&hti)))
00634     {
00635         sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
00636         switch (sym->symt.tag)
00637         {
00638         case SymTagFunction:
00639             if (((struct symt_function*)sym)->address != elf_info->elf_addr &&
00640                 ((struct symt_function*)sym)->size)
00641             {
00642                 break;
00643             }
00644             symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, 
00645                                      ((struct symt_function*)sym)->container);
00646             if (symp)
00647             {
00648                 if (((struct symt_function*)sym)->address != elf_info->elf_addr &&
00649                     ((struct symt_function*)sym)->address != elf_info->elf_addr + symp->st_value)
00650                     FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n",
00651                           sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
00652                           ((struct symt_function*)sym)->address, elf_info->elf_addr + symp->st_value);
00653                 if (((struct symt_function*)sym)->size && ((struct symt_function*)sym)->size != symp->st_size)
00654                     FIXME("Changing size for %p/%s!%s from %08lx to %08x\n",
00655                           sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
00656                           ((struct symt_function*)sym)->size, (unsigned int)symp->st_size);
00657 
00658                 ((struct symt_function*)sym)->address = elf_info->elf_addr + symp->st_value;
00659                 ((struct symt_function*)sym)->size    = symp->st_size;
00660             } else
00661                 FIXME("Couldn't find %s!%s\n",
00662                       debugstr_w(module->module.ModuleName), sym->hash_elt.name);
00663             break;
00664         case SymTagData:
00665             switch (((struct symt_data*)sym)->kind)
00666             {
00667             case DataIsGlobal:
00668             case DataIsFileStatic:
00669                 if (((struct symt_data*)sym)->u.var.kind != loc_absolute ||
00670                     ((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr)
00671                     break;
00672                 symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name, 
00673                                          ((struct symt_data*)sym)->container);
00674                 if (symp)
00675                 {
00676                 if (((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr &&
00677                     ((struct symt_data*)sym)->u.var.offset != elf_info->elf_addr + symp->st_value)
00678                     FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n",
00679                           sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
00680                           ((struct symt_function*)sym)->address, elf_info->elf_addr + symp->st_value);
00681                     ((struct symt_data*)sym)->u.var.offset = elf_info->elf_addr + symp->st_value;
00682                     ((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ?
00683                         DataIsFileStatic : DataIsGlobal;
00684                 } else
00685                     FIXME("Couldn't find %s!%s\n",
00686                           debugstr_w(module->module.ModuleName), sym->hash_elt.name);
00687                 break;
00688             default:;
00689             }
00690             break;
00691         default:
00692             FIXME("Unsupported tag %u\n", sym->symt.tag);
00693             break;
00694         }
00695     }
00696     /* since we may have changed some addresses & sizes, mark the module to be resorted */
00697     module->sortlist_valid = FALSE;
00698 }
00699 
00700 /******************************************************************
00701  *      elf_load_wine_thunks
00702  *
00703  * creating the thunk objects for a wine native DLL
00704  */
00705 static int elf_new_wine_thunks(struct module* module, const struct hash_table* ht_symtab,
00706                                const struct elf_thunk_area* thunks)
00707 {
00708     int                     j;
00709     struct hash_table_iter      hti;
00710     struct symtab_elt*          ste;
00711     DWORD_PTR                   addr;
00712     struct symt_ht*             symt;
00713 
00714     hash_table_iter_init(ht_symtab, &hti, NULL);
00715     while ((ste = hash_table_iter_up(&hti)))
00716     {
00717         if (ste->used) continue;
00718 
00719         addr = module->reloc_delta + ste->symp->st_value;
00720 
00721         j = elf_is_in_thunk_area(ste->symp->st_value, thunks);
00722         if (j >= 0) /* thunk found */
00723         {
00724             symt_new_thunk(module, ste->compiland, ste->ht_elt.name, thunks[j].ordinal,
00725                            addr, ste->symp->st_size);
00726         }
00727         else
00728         {
00729             ULONG64     ref_addr;
00730             struct location loc;
00731 
00732             symt = symt_find_nearest(module, addr);
00733             if (symt && !symt_get_address(&symt->symt, &ref_addr))
00734                 ref_addr = addr;
00735             if (!symt || addr != ref_addr)
00736             {
00737                 /* creating public symbols for all the ELF symbols which haven't been
00738                  * used yet (ie we have no debug information on them)
00739                  * That's the case, for example, of the .spec.c files
00740                  */
00741                 switch (ELF32_ST_TYPE(ste->symp->st_info))
00742                 {
00743                 case STT_FUNC:
00744                     symt_new_function(module, ste->compiland, ste->ht_elt.name,
00745                                       addr, ste->symp->st_size, NULL);
00746                     break;
00747                 case STT_OBJECT:
00748                     loc.kind = loc_absolute;
00749                     loc.reg = 0;
00750                     loc.offset = addr;
00751                     symt_new_global_variable(module, ste->compiland, ste->ht_elt.name,
00752                                              ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL,
00753                                              loc, ste->symp->st_size, NULL);
00754                     break;
00755                 default:
00756                     FIXME("Shouldn't happen\n");
00757                     break;
00758                 }
00759                 /* FIXME: this is a hack !!!
00760                  * we are adding new symbols, but as we're parsing a symbol table
00761                  * (hopefully without duplicate symbols) we delay rebuilding the sorted
00762                  * module table until we're done with the symbol table
00763                  * Otherwise, as we intertwine symbols' add and lookup, performance
00764                  * is rather bad
00765                  */
00766                 module->sortlist_valid = TRUE;
00767             }
00768         }
00769     }
00770     /* see comment above */
00771     module->sortlist_valid = FALSE;
00772     return TRUE;
00773 }
00774 
00775 /******************************************************************
00776  *      elf_new_public_symbols
00777  *
00778  * Creates a set of public symbols from an ELF symtab
00779  */
00780 static int elf_new_public_symbols(struct module* module, const struct hash_table* symtab)
00781 {
00782     struct hash_table_iter      hti;
00783     struct symtab_elt*          ste;
00784 
00785     if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE;
00786 
00787     /* FIXME: we're missing the ELF entry point here */
00788 
00789     hash_table_iter_init(symtab, &hti, NULL);
00790     while ((ste = hash_table_iter_up(&hti)))
00791     {
00792         symt_new_public(module, ste->compiland, ste->ht_elt.name,
00793                         module->reloc_delta + ste->symp->st_value,
00794                         ste->symp->st_size);
00795     }
00796     return TRUE;
00797 }
00798 
00799 static BOOL elf_check_debug_link(const WCHAR* file, struct image_file_map* fmap, DWORD crc)
00800 {
00801     BOOL        ret;
00802     struct elf_map_file_data    emfd;
00803 
00804     emfd.kind = from_file;
00805     emfd.u.file.filename = file;
00806     if (!elf_map_file(&emfd, fmap)) return FALSE;
00807     if (!(ret = crc == calc_crc32(fmap->u.elf.fd)))
00808     {
00809         WARN("Bad CRC for file %s (got %08x while expecting %08x)\n",
00810              debugstr_w(file), calc_crc32(fmap->u.elf.fd), crc);
00811         elf_unmap_file(fmap);
00812     }
00813     return ret;
00814 }
00815 
00816 /******************************************************************
00817  *      elf_locate_debug_link
00818  *
00819  * Locate a filename from a .gnu_debuglink section, using the same
00820  * strategy as gdb:
00821  * "If the full name of the directory containing the executable is
00822  * execdir, and the executable has a debug link that specifies the
00823  * name debugfile, then GDB will automatically search for the
00824  * debugging information file in three places:
00825  *  - the directory containing the executable file (that is, it
00826  *    will look for a file named `execdir/debugfile',
00827  *  - a subdirectory of that directory named `.debug' (that is, the
00828  *    file `execdir/.debug/debugfile', and
00829  *  - a subdirectory of the global debug file directory that includes
00830  *    the executable's full path, and the name from the link (that is,
00831  *    the file `globaldebugdir/execdir/debugfile', where globaldebugdir
00832  *    is the global debug file directory, and execdir has been turned
00833  *    into a relative path)." (from GDB manual)
00834  */
00835 static BOOL elf_locate_debug_link(struct image_file_map* fmap, const char* filename,
00836                                   const WCHAR* loaded_file, DWORD crc)
00837 {
00838     static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'};
00839     static const WCHAR dotDebugW[] = {'.','d','e','b','u','g','/'};
00840     const size_t globalDebugDirLen = sizeof(globalDebugDirW) / sizeof(WCHAR);
00841     size_t filename_len;
00842     WCHAR* p = NULL;
00843     WCHAR* slash;
00844     struct image_file_map* fmap_link = NULL;
00845 
00846     fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link));
00847     if (!fmap_link) return FALSE;
00848 
00849     filename_len = MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, NULL, 0);
00850     p = HeapAlloc(GetProcessHeap(), 0,
00851                   (globalDebugDirLen + strlenW(loaded_file) + 6 + 1 + filename_len + 1) * sizeof(WCHAR));
00852     if (!p) goto found;
00853 
00854     /* we prebuild the string with "execdir" */
00855     strcpyW(p, loaded_file);
00856     slash = strrchrW(p, '/');
00857     if (slash == NULL) slash = p; else slash++;
00858 
00859     /* testing execdir/filename */
00860     MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len);
00861     if (elf_check_debug_link(p, fmap_link, crc)) goto found;
00862 
00863     /* testing execdir/.debug/filename */
00864     memcpy(slash, dotDebugW, sizeof(dotDebugW));
00865     MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash + sizeof(dotDebugW) / sizeof(WCHAR), filename_len);
00866     if (elf_check_debug_link(p, fmap_link, crc)) goto found;
00867 
00868     /* testing globaldebugdir/execdir/filename */
00869     memmove(p + globalDebugDirLen, p, (slash - p) * sizeof(WCHAR));
00870     memcpy(p, globalDebugDirW, globalDebugDirLen * sizeof(WCHAR));
00871     slash += globalDebugDirLen;
00872     MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len);
00873     if (elf_check_debug_link(p, fmap_link, crc)) goto found;
00874 
00875     /* finally testing filename */
00876     if (elf_check_debug_link(slash, fmap_link, crc)) goto found;
00877 
00878 
00879     WARN("Couldn't locate or map %s\n", filename);
00880     HeapFree(GetProcessHeap(), 0, p);
00881     HeapFree(GetProcessHeap(), 0, fmap_link);
00882     return FALSE;
00883 
00884 found:
00885     TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p));
00886     HeapFree(GetProcessHeap(), 0, p);
00887     fmap->u.elf.alternate = fmap_link;
00888     return TRUE;
00889 }
00890 
00891 /******************************************************************
00892  *      elf_debuglink_parse
00893  *
00894  * Parses a .gnu_debuglink section and loads the debug info from
00895  * the external file specified there.
00896  */
00897 static BOOL elf_debuglink_parse(struct image_file_map* fmap, const struct module* module,
00898                                 const BYTE* debuglink)
00899 {
00900     /* The content of a debug link section is:
00901      * 1/ a NULL terminated string, containing the file name for the
00902      *    debug info
00903      * 2/ padding on 4 byte boundary
00904      * 3/ CRC of the linked ELF file
00905      */
00906     const char* dbg_link = (const char*)debuglink;
00907     DWORD crc;
00908 
00909     crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3));
00910     return elf_locate_debug_link(fmap, dbg_link, module->module.LoadedImageName, crc);
00911 }
00912 
00913 /******************************************************************
00914  *      elf_load_debug_info_from_map
00915  *
00916  * Loads the symbolic information from ELF module which mapping is described
00917  * in fmap
00918  * the module has been loaded at 'load_offset' address, so symbols' address
00919  * relocation is performed.
00920  * CRC is checked if fmap->with_crc is TRUE
00921  * returns
00922  *  0 if the file doesn't contain symbolic info (or this info cannot be
00923  *  read or parsed)
00924  *  1 on success
00925  */
00926 static BOOL elf_load_debug_info_from_map(struct module* module,
00927                                          struct image_file_map* fmap,
00928                                          struct pool* pool,
00929                                          struct hash_table* ht_symtab)
00930 {
00931     BOOL                ret = FALSE, lret;
00932     struct elf_thunk_area thunks[] = 
00933     {
00934         {"__wine_spec_import_thunks",           THUNK_ORDINAL_NOTYPE, 0, 0},    /* inter DLL calls */
00935         {"__wine_spec_delayed_import_loaders",  THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
00936         {"__wine_spec_delayed_import_thunks",   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
00937         {"__wine_delay_load",                   THUNK_ORDINAL_LOAD,   0, 0},    /* delayed inter DLL calls */
00938         {"__wine_spec_thunk_text_16",           -16,                  0, 0},    /* 16 => 32 thunks */
00939         {"__wine_spec_thunk_text_32",           -32,                  0, 0},    /* 32 => 16 thunks */
00940         {NULL,                                  0,                    0, 0}
00941     };
00942 
00943     module->module.SymType = SymExport;
00944 
00945     /* create a hash table for the symtab */
00946     elf_hash_symtab(module, pool, ht_symtab, fmap, thunks);
00947 
00948     if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
00949     {
00950         struct image_section_map stab_sect, stabstr_sect;
00951         struct image_section_map debuglink_sect;
00952 
00953         /* if present, add the .gnu_debuglink file as an alternate to current one */
00954     if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect))
00955         {
00956             const BYTE* dbg_link;
00957 
00958             dbg_link = (const BYTE*)image_map_section(&debuglink_sect);
00959             if (dbg_link != IMAGE_NO_MAP)
00960             {
00961                 lret = elf_debuglink_parse(fmap, module, dbg_link);
00962                 if (!lret)
00963             WARN("Couldn't load linked debug file for %s\n",
00964                          debugstr_w(module->module.ModuleName));
00965                 ret = ret || lret;
00966             }
00967             image_unmap_section(&debuglink_sect);
00968         }
00969         if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) &&
00970             elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect))
00971         {
00972             const char* stab;
00973             const char* stabstr;
00974 
00975             stab = image_map_section(&stab_sect);
00976             stabstr = image_map_section(&stabstr_sect);
00977             if (stab != IMAGE_NO_MAP && stabstr != IMAGE_NO_MAP)
00978             {
00979                 /* OK, now just parse all of the stabs. */
00980                 lret = stabs_parse(module, module->format_info[DFI_ELF]->u.elf_info->elf_addr,
00981                                    stab, image_get_map_size(&stab_sect),
00982                                    stabstr, image_get_map_size(&stabstr_sect),
00983                                    NULL, NULL);
00984                 if (lret)
00985                     /* and fill in the missing information for stabs */
00986                     elf_finish_stabs_info(module, ht_symtab);
00987                 else
00988                     WARN("Couldn't correctly read stabs\n");
00989                 ret = ret || lret;
00990             }
00991             image_unmap_section(&stab_sect);
00992             image_unmap_section(&stabstr_sect);
00993         }
00994         lret = dwarf2_parse(module, module->reloc_delta, thunks, fmap);
00995         ret = ret || lret;
00996     }
00997     if (strstrW(module->module.ModuleName, S_ElfW) ||
00998         !strcmpW(module->module.ModuleName, S_WineLoaderW))
00999     {
01000         /* add the thunks for native libraries */
01001         if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
01002             elf_new_wine_thunks(module, ht_symtab, thunks);
01003     }
01004     /* add all the public symbols from symtab */
01005     if (elf_new_public_symbols(module, ht_symtab) && !ret) ret = TRUE;
01006 
01007     return ret;
01008 }
01009 
01010 /******************************************************************
01011  *      elf_load_debug_info
01012  *
01013  * Loads ELF debugging information from the module image file.
01014  */
01015 BOOL elf_load_debug_info(struct module* module)
01016 {
01017     BOOL                        ret = TRUE;
01018     struct pool                 pool;
01019     struct hash_table           ht_symtab;
01020     struct module_format*       modfmt;
01021 
01022     if (module->type != DMT_ELF || !(modfmt = module->format_info[DFI_ELF]) || !modfmt->u.elf_info)
01023     {
01024     ERR("Bad elf module '%s'\n", debugstr_w(module->module.LoadedImageName));
01025     return FALSE;
01026     }
01027 
01028     pool_init(&pool, 65536);
01029     hash_table_init(&pool, &ht_symtab, 256);
01030 
01031     ret = elf_load_debug_info_from_map(module, &modfmt->u.elf_info->file_map, &pool, &ht_symtab);
01032 
01033     pool_destroy(&pool);
01034     return ret;
01035 }
01036 
01037 /******************************************************************
01038  *      elf_fetch_file_info
01039  *
01040  * Gathers some more information for an ELF module from a given file
01041  */
01042 BOOL elf_fetch_file_info(const WCHAR* name, DWORD_PTR* base,
01043                          DWORD* size, DWORD* checksum)
01044 {
01045     struct image_file_map fmap;
01046 
01047     struct elf_map_file_data    emfd;
01048 
01049     emfd.kind = from_file;
01050     emfd.u.file.filename = name;
01051     if (!elf_map_file(&emfd, &fmap)) return FALSE;
01052     if (base) *base = fmap.u.elf.elf_start;
01053     *size = fmap.u.elf.elf_size;
01054     *checksum = calc_crc32(fmap.u.elf.fd);
01055     elf_unmap_file(&fmap);
01056     return TRUE;
01057 }
01058 
01059 static BOOL elf_load_file_from_fmap(struct process* pcs, const WCHAR* filename,
01060                                     struct image_file_map* fmap, unsigned long load_offset,
01061                                     unsigned long dyn_addr, struct elf_info* elf_info)
01062 {
01063     BOOL        ret = FALSE;
01064 
01065     if (elf_info->flags & ELF_INFO_DEBUG_HEADER)
01066     {
01067         struct image_section_map        ism;
01068 
01069         if (elf_find_section(fmap, ".dynamic", SHT_DYNAMIC, &ism))
01070         {
01071             Elf_Dyn         dyn;
01072             char*           ptr = (char*)fmap->u.elf.sect[ism.sidx].shdr.sh_addr;
01073             unsigned long   len;
01074 
01075             do
01076             {
01077                 if (!ReadProcessMemory(pcs->handle, ptr, &dyn, sizeof(dyn), &len) ||
01078                     len != sizeof(dyn))
01079                     return ret;
01080                 if (dyn.d_tag == DT_DEBUG)
01081                 {
01082                     elf_info->dbg_hdr_addr = dyn.d_un.d_ptr;
01083                     if (load_offset == 0 && dyn_addr == 0) /* likely the case */
01084                         /* Assume this module (the Wine loader) has been loaded at its preferred address */
01085                         dyn_addr = ism.fmap->u.elf.sect[ism.sidx].shdr.sh_addr;
01086                     break;
01087                 }
01088                 ptr += sizeof(dyn);
01089             } while (dyn.d_tag != DT_NULL);
01090             if (dyn.d_tag == DT_NULL) return ret;
01091     }
01092         elf_end_find(fmap);
01093     }
01094 
01095     if (elf_info->flags & ELF_INFO_MODULE)
01096     {
01097         struct elf_module_info *elf_module_info;
01098         struct module_format*   modfmt;
01099         struct image_section_map ism;
01100         unsigned long           modbase = load_offset;
01101 
01102         if (elf_find_section(fmap, ".dynamic", SHT_DYNAMIC, &ism))
01103         {
01104             unsigned long rva_dyn = elf_get_map_rva(&ism);
01105 
01106             TRACE("For module %s, got ELF (start=%lx dyn=%lx), link_map (start=%lx dyn=%lx)\n",
01107                   debugstr_w(filename), (unsigned long)fmap->u.elf.elf_start, rva_dyn,
01108                   load_offset, dyn_addr);
01109             if (dyn_addr && load_offset + rva_dyn != dyn_addr)
01110             {
01111                 WARN("\thave to relocate: %lx\n", dyn_addr - rva_dyn);
01112                 modbase = dyn_addr - rva_dyn;
01113             }
01114     } else WARN("For module %s, no .dynamic section\n", debugstr_w(filename));
01115         elf_end_find(fmap);
01116 
01117         modfmt = HeapAlloc(GetProcessHeap(), 0,
01118                           sizeof(struct module_format) + sizeof(struct elf_module_info));
01119         if (!modfmt) return FALSE;
01120         elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE, modbase,
01121                                       fmap->u.elf.elf_size, 0, calc_crc32(fmap->u.elf.fd));
01122         if (!elf_info->module)
01123         {
01124             HeapFree(GetProcessHeap(), 0, modfmt);
01125             return FALSE;
01126         }
01127         elf_info->module->reloc_delta = elf_info->module->module.BaseOfImage - fmap->u.elf.elf_start;
01128         elf_module_info = (void*)(modfmt + 1);
01129         elf_info->module->format_info[DFI_ELF] = modfmt;
01130         modfmt->module      = elf_info->module;
01131         modfmt->remove      = elf_module_remove;
01132         modfmt->loc_compute = NULL;
01133         modfmt->u.elf_info  = elf_module_info;
01134 
01135         elf_module_info->elf_addr = load_offset;
01136 
01137         elf_module_info->file_map = *fmap;
01138         elf_reset_file_map(fmap);
01139         if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
01140         {
01141             elf_info->module->module.SymType = SymDeferred;
01142             ret = TRUE;
01143         }
01144         else ret = elf_load_debug_info(elf_info->module);
01145 
01146         elf_module_info->elf_mark = 1;
01147         elf_module_info->elf_loader = 0;
01148     } else ret = TRUE;
01149 
01150     if (elf_info->flags & ELF_INFO_NAME)
01151     {
01152         WCHAR*  ptr;
01153         ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR));
01154         if (ptr)
01155         {
01156             strcpyW(ptr, filename);
01157             elf_info->module_name = ptr;
01158         }
01159         else ret = FALSE;
01160     }
01161 
01162     return ret;
01163 }
01164 
01165 /******************************************************************
01166  *      elf_load_file
01167  *
01168  * Loads the information for ELF module stored in 'filename'
01169  * the module has been loaded at 'load_offset' address
01170  * returns
01171  *  -1 if the file cannot be found/opened
01172  *  0 if the file doesn't contain symbolic info (or this info cannot be
01173  *  read or parsed)
01174  *  1 on success
01175  */
01176 static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
01177                           unsigned long load_offset, unsigned long dyn_addr,
01178                           struct elf_info* elf_info)
01179 {
01180     BOOL                        ret = FALSE;
01181     struct image_file_map       fmap;
01182     struct elf_map_file_data    emfd;
01183 
01184     TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
01185 
01186     emfd.kind = from_file;
01187     emfd.u.file.filename = filename;
01188     if (!elf_map_file(&emfd, &fmap)) return ret;
01189 
01190     /* Next, we need to find a few of the internal ELF headers within
01191      * this thing.  We need the main executable header, and the section
01192      * table.
01193      */
01194     if (!fmap.u.elf.elf_start && !load_offset)
01195         ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n",
01196             debugstr_w(filename));
01197 
01198     ret = elf_load_file_from_fmap(pcs, filename, &fmap, load_offset, dyn_addr, elf_info);
01199 
01200     elf_unmap_file(&fmap);
01201 
01202     return ret;
01203 }
01204 
01205 /******************************************************************
01206  *      elf_load_file_from_path
01207  * tries to load an ELF file from a set of paths (separated by ':')
01208  */
01209 static BOOL elf_load_file_from_path(HANDLE hProcess,
01210                                     const WCHAR* filename,
01211                                     unsigned long load_offset,
01212                                     unsigned long dyn_addr,
01213                                     const char* path,
01214                                     struct elf_info* elf_info)
01215 {
01216     BOOL                ret = FALSE;
01217     WCHAR               *s, *t, *fn;
01218     WCHAR*          pathW = NULL;
01219     unsigned            len;
01220 
01221     if (!path) return FALSE;
01222 
01223     len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
01224     pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
01225     if (!pathW) return FALSE;
01226     MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len);
01227 
01228     for (s = pathW; s && *s; s = (t) ? (t+1) : NULL)
01229     {
01230     t = strchrW(s, ':');
01231     if (t) *t = '\0';
01232     fn = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1 + lstrlenW(s) + 1) * sizeof(WCHAR));
01233     if (!fn) break;
01234     strcpyW(fn, s);
01235     strcatW(fn, S_SlashW);
01236     strcatW(fn, filename);
01237     ret = elf_load_file(hProcess, fn, load_offset, dyn_addr, elf_info);
01238     HeapFree(GetProcessHeap(), 0, fn);
01239     if (ret) break;
01240     }
01241 
01242     HeapFree(GetProcessHeap(), 0, pathW);
01243     return ret;
01244 }
01245 
01246 /******************************************************************
01247  *      elf_load_file_from_dll_path
01248  *
01249  * Tries to load an ELF file from the dll path
01250  */
01251 static BOOL elf_load_file_from_dll_path(HANDLE hProcess,
01252                                         const WCHAR* filename,
01253                                         unsigned long load_offset,
01254                                         unsigned long dyn_addr,
01255                                         struct elf_info* elf_info)
01256 {
01257     BOOL ret = FALSE;
01258     unsigned int index = 0;
01259     const char *path;
01260 
01261     while (!ret && (path = wine_dll_enum_load_path( index++ )))
01262     {
01263         WCHAR *name;
01264         unsigned len;
01265 
01266         len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
01267 
01268         name = HeapAlloc( GetProcessHeap(), 0,
01269                           (len + lstrlenW(filename) + 2) * sizeof(WCHAR) );
01270 
01271         if (!name) break;
01272         MultiByteToWideChar(CP_UNIXCP, 0, path, -1, name, len);
01273         strcatW( name, S_SlashW );
01274         strcatW( name, filename );
01275         ret = elf_load_file(hProcess, name, load_offset, dyn_addr, elf_info);
01276         HeapFree( GetProcessHeap(), 0, name );
01277     }
01278     return ret;
01279 }
01280 
01281 #ifdef AT_SYSINFO_EHDR
01282 /******************************************************************
01283  *      elf_search_auxv
01284  *
01285  * locate some a value from the debuggee auxiliary vector
01286  */
01287 static BOOL elf_search_auxv(const struct process* pcs, unsigned type, unsigned long* val)
01288 {
01289     char        buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
01290     SYMBOL_INFO*si = (SYMBOL_INFO*)buffer;
01291     void*       addr;
01292     void*       str;
01293     void*       str_max;
01294     Elf_auxv_t  auxv;
01295 
01296     si->SizeOfStruct = sizeof(*si);
01297     si->MaxNameLen = MAX_SYM_NAME;
01298     if (!SymFromName(pcs->handle, "libwine.so.1!__wine_main_environ", si) ||
01299         !(addr = (void*)(DWORD_PTR)si->Address) ||
01300         !ReadProcessMemory(pcs->handle, addr, &addr, sizeof(addr), NULL) ||
01301         !addr)
01302     {
01303         FIXME("can't find symbol in module\n");
01304         return FALSE;
01305     }
01306     /* walk through envp[] */
01307     /* envp[] strings are located after the auxiliary vector, so protect the walk */
01308     str_max = (void*)(DWORD_PTR)~0L;
01309     while (ReadProcessMemory(pcs->handle, addr, &str, sizeof(str), NULL) &&
01310            (addr = (void*)((DWORD_PTR)addr + sizeof(str))) != NULL && str != NULL)
01311         str_max = min(str_max, str);
01312 
01313     /* Walk through the end of envp[] array.
01314      * Actually, there can be several NULLs at the end of envp[]. This happens when an env variable is
01315      * deleted, the last entry is replaced by an extra NULL.
01316      */
01317     while (addr < str_max && ReadProcessMemory(pcs->handle, addr, &str, sizeof(str), NULL) && str == NULL)
01318         addr = (void*)((DWORD_PTR)addr + sizeof(str));
01319 
01320     while (ReadProcessMemory(pcs->handle, addr, &auxv, sizeof(auxv), NULL) && auxv.a_type != AT_NULL)
01321     {
01322         if (auxv.a_type == type)
01323         {
01324             *val = auxv.a_un.a_val;
01325             return TRUE;
01326         }
01327         addr = (void*)((DWORD_PTR)addr + sizeof(auxv));
01328     }
01329 
01330     return FALSE;
01331 }
01332 #endif
01333 
01334 /******************************************************************
01335  *      elf_search_and_load_file
01336  *
01337  * lookup a file in standard ELF locations, and if found, load it
01338  */
01339 static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename,
01340                                      unsigned long load_offset, unsigned long dyn_addr,
01341                                      struct elf_info* elf_info)
01342 {
01343     BOOL                ret = FALSE;
01344     struct module*      module;
01345     static WCHAR        S_libstdcPPW[] = {'l','i','b','s','t','d','c','+','+','\0'};
01346 
01347     if (filename == NULL || *filename == '\0') return FALSE;
01348     if ((module = module_is_already_loaded(pcs, filename)))
01349     {
01350         elf_info->module = module;
01351         elf_info->module->format_info[DFI_ELF]->u.elf_info->elf_mark = 1;
01352         return module->module.SymType;
01353     }
01354 
01355     if (strstrW(filename, S_libstdcPPW)) return FALSE; /* We know we can't do it */
01356     ret = elf_load_file(pcs, filename, load_offset, dyn_addr, elf_info);
01357     /* if relative pathname, try some absolute base dirs */
01358     if (!ret && !strchrW(filename, '/'))
01359     {
01360         ret = elf_load_file_from_path(pcs, filename, load_offset, dyn_addr,
01361                                       getenv("PATH"), elf_info) ||
01362             elf_load_file_from_path(pcs, filename, load_offset, dyn_addr,
01363                                     getenv("LD_LIBRARY_PATH"), elf_info);
01364         if (!ret) ret = elf_load_file_from_dll_path(pcs, filename,
01365                                                     load_offset, dyn_addr, elf_info);
01366     }
01367 
01368     return ret;
01369 }
01370 
01371 typedef BOOL (*enum_elf_modules_cb)(const WCHAR*, unsigned long load_addr,
01372                                     unsigned long dyn_addr, BOOL is_system, void* user);
01373 
01374 /******************************************************************
01375  *      elf_enum_modules_internal
01376  *
01377  * Enumerate ELF modules from a running process
01378  */
01379 static BOOL elf_enum_modules_internal(const struct process* pcs,
01380                                       const WCHAR* main_name,
01381                                       enum_elf_modules_cb cb, void* user)
01382 {
01383     struct r_debug      dbg_hdr;
01384     void*               lm_addr;
01385     struct link_map     lm;
01386     char        bufstr[256];
01387     WCHAR               bufstrW[MAX_PATH];
01388 
01389     if (!pcs->dbg_hdr_addr ||
01390         !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr,
01391                            &dbg_hdr, sizeof(dbg_hdr), NULL))
01392         return FALSE;
01393 
01394     /* Now walk the linked list.  In all known ELF implementations,
01395      * the dynamic loader maintains this linked list for us.  In some
01396      * cases the first entry doesn't appear with a name, in other cases it
01397      * does.
01398      */
01399     for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next)
01400     {
01401     if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL))
01402         return FALSE;
01403 
01404     if (lm.l_prev != NULL && /* skip first entry, normally debuggee itself */
01405         lm.l_name != NULL &&
01406         ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL))
01407         {
01408         bufstr[sizeof(bufstr) - 1] = '\0';
01409             MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, sizeof(bufstrW) / sizeof(WCHAR));
01410             if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name);
01411             if (!cb(bufstrW, (unsigned long)lm.l_addr, (unsigned long)lm.l_ld, FALSE, user)) break;
01412     }
01413     }
01414 
01415 #ifdef AT_SYSINFO_EHDR
01416     if (!lm_addr)
01417     {
01418         unsigned long ehdr_addr;
01419 
01420         if (elf_search_auxv(pcs, AT_SYSINFO_EHDR, &ehdr_addr))
01421         {
01422             static const WCHAR vdsoW[] = {'[','v','d','s','o',']','.','s','o',0};
01423             cb(vdsoW, ehdr_addr, 0, TRUE, user);
01424         }
01425     }
01426 #endif
01427     return TRUE;
01428 }
01429 
01430 /******************************************************************
01431  *      elf_search_loader
01432  *
01433  * Lookup in a running ELF process the loader, and sets its ELF link
01434  * address (for accessing the list of loaded .so libs) in pcs.
01435  * If flags is ELF_INFO_MODULE, the module for the loader is also
01436  * added as a module into pcs.
01437  */
01438 static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
01439 {
01440     return elf_search_and_load_file(pcs, get_wine_loader_name(), 0, 0, elf_info);
01441 }
01442 
01443 /******************************************************************
01444  *      elf_read_wine_loader_dbg_info
01445  *
01446  * Try to find a decent wine executable which could have loaded the debuggee
01447  */
01448 BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
01449 {
01450     struct elf_info     elf_info;
01451 
01452     elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
01453     if (!elf_search_loader(pcs, &elf_info)) return FALSE;
01454     elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_loader = 1;
01455     module_set_module(elf_info.module, S_WineLoaderW);
01456     return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
01457 }
01458 
01459 struct elf_enum_user
01460 {
01461     enum_modules_cb     cb;
01462     void*               user;
01463 };
01464 
01465 static BOOL elf_enum_modules_translate(const WCHAR* name, unsigned long load_addr,
01466                                        unsigned long dyn_addr, BOOL is_system, void* user)
01467 {
01468     struct elf_enum_user*       eeu = user;
01469     return eeu->cb(name, load_addr, eeu->user);
01470 }
01471 
01472 /******************************************************************
01473  *      elf_enum_modules
01474  *
01475  * Enumerates the ELF loaded modules from a running target (hProc)
01476  * This function doesn't require that someone has called SymInitialize
01477  * on this very process.
01478  */
01479 BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
01480 {
01481     struct process      pcs;
01482     struct elf_info     elf_info;
01483     BOOL                ret;
01484     struct elf_enum_user eeu;
01485 
01486     memset(&pcs, 0, sizeof(pcs));
01487     pcs.handle = hProc;
01488     elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_NAME;
01489     if (!elf_search_loader(&pcs, &elf_info)) return FALSE;
01490     pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr;
01491     eeu.cb = cb;
01492     eeu.user = user;
01493     ret = elf_enum_modules_internal(&pcs, elf_info.module_name, elf_enum_modules_translate, &eeu);
01494     HeapFree(GetProcessHeap(), 0, (char*)elf_info.module_name);
01495     return ret;
01496 }
01497 
01498 struct elf_load
01499 {
01500     struct process*     pcs;
01501     struct elf_info     elf_info;
01502     const WCHAR*        name;
01503     BOOL                ret;
01504 };
01505 
01506 /******************************************************************
01507  *      elf_load_cb
01508  *
01509  * Callback for elf_load_module, used to walk the list of loaded
01510  * modules.
01511  */
01512 static BOOL elf_load_cb(const WCHAR* name, unsigned long load_addr,
01513                         unsigned long dyn_addr, BOOL is_system, void* user)
01514 {
01515     struct elf_load*    el = user;
01516     BOOL                ret = TRUE;
01517     const WCHAR*        p;
01518 
01519     if (is_system) /* virtual ELF module, created by system. handle it from memory */
01520     {
01521         struct module*                  module;
01522         struct elf_map_file_data        emfd;
01523         struct image_file_map           fmap;
01524 
01525         if ((module = module_is_already_loaded(el->pcs, name)))
01526         {
01527             el->elf_info.module = module;
01528             el->elf_info.module->format_info[DFI_ELF]->u.elf_info->elf_mark = 1;
01529             return module->module.SymType;
01530         }
01531 
01532         emfd.kind = from_process;
01533         emfd.u.process.handle = el->pcs->handle;
01534         emfd.u.process.load_addr = (void*)load_addr;
01535 
01536         if (elf_map_file(&emfd, &fmap))
01537             el->ret = elf_load_file_from_fmap(el->pcs, name, &fmap, load_addr, 0, &el->elf_info);
01538         return TRUE;
01539     }
01540     if (el->name)
01541     {
01542         /* memcmp is needed for matches when bufstr contains also version information
01543          * el->name: libc.so, name: libc.so.6.0
01544          */
01545         p = strrchrW(name, '/');
01546         if (!p++) p = name;
01547     }
01548 
01549     if (!el->name || !memcmp(p, el->name, lstrlenW(el->name) * sizeof(WCHAR)))
01550     {
01551         el->ret = elf_search_and_load_file(el->pcs, name, load_addr, dyn_addr, &el->elf_info);
01552         if (el->name) ret = FALSE;
01553     }
01554 
01555     return ret;
01556 }
01557 
01558 /******************************************************************
01559  *      elf_load_module
01560  *
01561  * loads an ELF module and stores it in process' module list
01562  * Also, find module real name and load address from
01563  * the real loaded modules list in pcs address space
01564  */
01565 struct module*  elf_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
01566 {
01567     struct elf_load     el;
01568 
01569     TRACE("(%p %s %08lx)\n", pcs, debugstr_w(name), addr);
01570 
01571     el.elf_info.flags = ELF_INFO_MODULE;
01572     el.ret = FALSE;
01573 
01574     if (pcs->dbg_hdr_addr) /* we're debugging a life target */
01575     {
01576         el.pcs = pcs;
01577         /* do only the lookup from the filename, not the path (as we lookup module
01578          * name in the process' loaded module list)
01579          */
01580         el.name = strrchrW(name, '/');
01581         if (!el.name++) el.name = name;
01582         el.ret = FALSE;
01583 
01584         if (!elf_enum_modules_internal(pcs, NULL, elf_load_cb, &el))
01585             return NULL;
01586     }
01587     else if (addr)
01588     {
01589         el.name = name;
01590         el.ret = elf_search_and_load_file(pcs, el.name, addr, 0, &el.elf_info);
01591     }
01592     if (!el.ret) return NULL;
01593     assert(el.elf_info.module);
01594     return el.elf_info.module;
01595 }
01596 
01597 /******************************************************************
01598  *      elf_synchronize_module_list
01599  *
01600  * this functions rescans the debuggee module's list and synchronizes it with
01601  * the one from 'pcs', ie:
01602  * - if a module is in debuggee and not in pcs, it's loaded into pcs
01603  * - if a module is in pcs and not in debuggee, it's unloaded from pcs
01604  */
01605 BOOL    elf_synchronize_module_list(struct process* pcs)
01606 {
01607     struct module*      module;
01608     struct elf_load     el;
01609 
01610     for (module = pcs->lmodules; module; module = module->next)
01611     {
01612         if (module->type == DMT_ELF && !module->is_virtual)
01613             module->format_info[DFI_ELF]->u.elf_info->elf_mark = 0;
01614     }
01615 
01616     el.pcs = pcs;
01617     el.elf_info.flags = ELF_INFO_MODULE;
01618     el.ret = FALSE;
01619     el.name = NULL; /* fetch all modules */
01620 
01621     if (!elf_enum_modules_internal(pcs, NULL, elf_load_cb, &el))
01622         return FALSE;
01623 
01624     module = pcs->lmodules;
01625     while (module)
01626     {
01627         if (module->type == DMT_ELF && !module->is_virtual)
01628         {
01629             struct elf_module_info* elf_info = module->format_info[DFI_ELF]->u.elf_info;
01630 
01631             if (!elf_info->elf_mark && !elf_info->elf_loader)
01632             {
01633                 module_remove(pcs, module);
01634                 /* restart all over */
01635                 module = pcs->lmodules;
01636                 continue;
01637             }
01638         }
01639         module = module->next;
01640     }
01641     return TRUE;
01642 }
01643 
01644 #else   /* !__ELF__ */
01645 
01646 BOOL         elf_find_section(struct image_file_map* fmap, const char* name,
01647                               unsigned sht, struct image_section_map* ism)
01648 {
01649     return FALSE;
01650 }
01651 
01652 const char*  elf_map_section(struct image_section_map* ism)
01653 {
01654     return NULL;
01655 }
01656 
01657 void         elf_unmap_section(struct image_section_map* ism)
01658 {}
01659 
01660 unsigned     elf_get_map_size(const struct image_section_map* ism)
01661 {
01662     return 0;
01663 }
01664 
01665 DWORD_PTR elf_get_map_rva(const struct image_section_map* ism)
01666 {
01667     return 0;
01668 }
01669 
01670 BOOL    elf_synchronize_module_list(struct process* pcs)
01671 {
01672     return FALSE;
01673 }
01674 
01675 BOOL elf_fetch_file_info(const WCHAR* name, DWORD_PTR* base,
01676                          DWORD* size, DWORD* checksum)
01677 {
01678     return FALSE;
01679 }
01680 
01681 BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
01682 {
01683     return FALSE;
01684 }
01685 
01686 BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
01687 {
01688     return FALSE;
01689 }
01690 
01691 struct module*  elf_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
01692 {
01693     return NULL;
01694 }
01695 
01696 BOOL elf_load_debug_info(struct module* module)
01697 {
01698     return FALSE;
01699 }
01700 
01701 int elf_is_in_thunk_area(unsigned long addr,
01702                          const struct elf_thunk_area* thunks)
01703 {
01704     return -1;
01705 }
01706 #endif  /* __ELF__ */

Generated on Sat May 26 2012 04:21:58 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.