Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenelf_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
1.7.6.1
|