1 | /*
|
---|
2 | * File elf.c - processing of ELF files
|
---|
3 | *
|
---|
4 | * Copyright (C) 1996, Eric Youngdale.
|
---|
5 | * 1999-2007 Eric Pouech
|
---|
6 | *
|
---|
7 | * This library is free software; you can redistribute it and/or
|
---|
8 | * modify it under the terms of the GNU Lesser General Public
|
---|
9 | * License as published by the Free Software Foundation; either
|
---|
10 | * version 2.1 of the License, or (at your option) any later version.
|
---|
11 | *
|
---|
12 | * This library is distributed in the hope that it will be useful,
|
---|
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
15 | * Lesser General Public License for more details.
|
---|
16 | *
|
---|
17 | * You should have received a copy of the GNU Lesser General Public
|
---|
18 | * License along with this library; if not, write to the Free Software
|
---|
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
---|
20 | */
|
---|
21 |
|
---|
22 | #include "config.h"
|
---|
23 | #include "wine/port.h"
|
---|
24 |
|
---|
25 | #if defined(__svr4__) || defined(__sun)
|
---|
26 | #define __ELF__ 1
|
---|
27 | /* large files are not supported by libelf */
|
---|
28 | #undef _FILE_OFFSET_BITS
|
---|
29 | #define _FILE_OFFSET_BITS 32
|
---|
30 | #endif
|
---|
31 |
|
---|
32 | #include <assert.h>
|
---|
33 | #include <stdio.h>
|
---|
34 | #include <stdlib.h>
|
---|
35 | #ifdef HAVE_SYS_STAT_H
|
---|
36 | # include <sys/stat.h>
|
---|
37 | #endif
|
---|
38 | #include <fcntl.h>
|
---|
39 | #ifdef HAVE_SYS_MMAN_H
|
---|
40 | #include <sys/mman.h>
|
---|
41 | #endif
|
---|
42 | #ifdef HAVE_UNISTD_H
|
---|
43 | # include <unistd.h>
|
---|
44 | #endif
|
---|
45 | #ifndef PATH_MAX
|
---|
46 | #define PATH_MAX MAX_PATH
|
---|
47 | #endif
|
---|
48 |
|
---|
49 | #include "dbghelp_private.h"
|
---|
50 |
|
---|
51 | //#ifdef HAVE_ELF_H
|
---|
52 | # include <elf.h>
|
---|
53 | //#endif
|
---|
54 | #ifdef HAVE_SYS_ELF32_H
|
---|
55 | # include <sys/elf32.h>
|
---|
56 | #endif
|
---|
57 | #ifdef HAVE_SYS_EXEC_ELF_H
|
---|
58 | # include <sys/exec_elf.h>
|
---|
59 | #endif
|
---|
60 | #if !defined(DT_NUM)
|
---|
61 | # if defined(DT_COUNT)
|
---|
62 | # define DT_NUM DT_COUNT
|
---|
63 | # else
|
---|
64 | /* this seems to be a satisfactory value on Solaris, which doesn't support this AFAICT */
|
---|
65 | # define DT_NUM 24
|
---|
66 | # endif
|
---|
67 | #endif
|
---|
68 | //#ifdef HAVE_LINK_H
|
---|
69 | # include <link.h>
|
---|
70 | //#endif
|
---|
71 | #ifdef HAVE_SYS_LINK_H
|
---|
72 | # include <sys/link.h>
|
---|
73 | #endif
|
---|
74 |
|
---|
75 | #include "wine/library.h"
|
---|
76 | #include "wine/debug.h"
|
---|
77 |
|
---|
78 | struct elf_module_info
|
---|
79 | {
|
---|
80 | unsigned long elf_addr;
|
---|
81 | unsigned short elf_mark : 1,
|
---|
82 | elf_loader : 1;
|
---|
83 | };
|
---|
84 |
|
---|
85 | #ifdef __ELF__
|
---|
86 |
|
---|
87 | #define ELF_INFO_DEBUG_HEADER 0x0001
|
---|
88 | #define ELF_INFO_MODULE 0x0002
|
---|
89 | #define ELF_INFO_NAME 0x0004
|
---|
90 |
|
---|
91 | WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
---|
92 |
|
---|
93 | struct elf_info
|
---|
94 | {
|
---|
95 | unsigned flags; /* IN one (or several) of the ELF_INFO constants */
|
---|
96 | unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
|
---|
97 | struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
|
---|
98 | const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */
|
---|
99 | };
|
---|
100 |
|
---|
101 | /* structure holding information while handling an ELF image
|
---|
102 | * allows one by one section mapping for memory savings
|
---|
103 | */
|
---|
104 | struct elf_file_map
|
---|
105 | {
|
---|
106 | Elf32_Ehdr elfhdr;
|
---|
107 | size_t elf_size;
|
---|
108 | size_t elf_start;
|
---|
109 | struct
|
---|
110 | {
|
---|
111 | Elf32_Shdr shdr;
|
---|
112 | const char* mapped;
|
---|
113 | }* sect;
|
---|
114 | int fd;
|
---|
115 | const char* shstrtab;
|
---|
116 | struct elf_file_map* alternate; /* another ELF file (linked to this one) */
|
---|
117 | };
|
---|
118 |
|
---|
119 | struct elf_section_map
|
---|
120 | {
|
---|
121 | struct elf_file_map* fmap;
|
---|
122 | long sidx;
|
---|
123 | };
|
---|
124 |
|
---|
125 | struct symtab_elt
|
---|
126 | {
|
---|
127 | struct hash_table_elt ht_elt;
|
---|
128 | const Elf32_Sym* symp;
|
---|
129 | struct symt_compiland* compiland;
|
---|
130 | unsigned used;
|
---|
131 | };
|
---|
132 |
|
---|
133 | struct elf_thunk_area
|
---|
134 | {
|
---|
135 | const char* symname;
|
---|
136 | THUNK_ORDINAL ordinal;
|
---|
137 | unsigned long rva_start;
|
---|
138 | unsigned long rva_end;
|
---|
139 | };
|
---|
140 |
|
---|
141 | /******************************************************************
|
---|
142 | * elf_map_section
|
---|
143 | *
|
---|
144 | * Maps a single section into memory from an ELF file
|
---|
145 | */
|
---|
146 | static const char* elf_map_section(struct elf_section_map* esm)
|
---|
147 | {
|
---|
148 | unsigned pgsz = getpagesize();
|
---|
149 | unsigned ofst, size;
|
---|
150 |
|
---|
151 | if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum ||
|
---|
152 | esm->fmap->sect[esm->sidx].shdr.sh_type == SHT_NOBITS)
|
---|
153 | return ELF_NO_MAP;
|
---|
154 |
|
---|
155 | /* align required information on page size (we assume pagesize is a power of 2) */
|
---|
156 | ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1);
|
---|
157 | size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset +
|
---|
158 | esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
|
---|
159 | esm->fmap->sect[esm->sidx].mapped = mmap(NULL, size, PROT_READ, MAP_PRIVATE,
|
---|
160 | esm->fmap->fd, ofst);
|
---|
161 | if (esm->fmap->sect[esm->sidx].mapped == ELF_NO_MAP) return ELF_NO_MAP;
|
---|
162 | return esm->fmap->sect[esm->sidx].mapped + (esm->fmap->sect[esm->sidx].shdr.sh_offset & (pgsz - 1));
|
---|
163 | }
|
---|
164 |
|
---|
165 | /******************************************************************
|
---|
166 | * elf_find_section
|
---|
167 | *
|
---|
168 | * Finds a section by name (and type) into memory from an ELF file
|
---|
169 | * or its alternate if any
|
---|
170 | */
|
---|
171 | static BOOL elf_find_section(struct elf_file_map* fmap, const char* name,
|
---|
172 | unsigned sht, struct elf_section_map* esm)
|
---|
173 | {
|
---|
174 | unsigned i;
|
---|
175 |
|
---|
176 | while (fmap)
|
---|
177 | {
|
---|
178 | if (fmap->shstrtab == ELF_NO_MAP)
|
---|
179 | {
|
---|
180 | struct elf_section_map hdr_esm = {fmap, fmap->elfhdr.e_shstrndx};
|
---|
181 | if ((fmap->shstrtab = elf_map_section(&hdr_esm)) == ELF_NO_MAP) break;
|
---|
182 | }
|
---|
183 | for (i = 0; i < fmap->elfhdr.e_shnum; i++)
|
---|
184 | {
|
---|
185 | if (strcmp(fmap->shstrtab + fmap->sect[i].shdr.sh_name, name) == 0 &&
|
---|
186 | (sht == SHT_NULL || sht == fmap->sect[i].shdr.sh_type))
|
---|
187 | {
|
---|
188 | esm->fmap = fmap;
|
---|
189 | esm->sidx = i;
|
---|
190 | return TRUE;
|
---|
191 | }
|
---|
192 | }
|
---|
193 | fmap = fmap->alternate;
|
---|
194 | }
|
---|
195 | esm->fmap = NULL;
|
---|
196 | esm->sidx = -1;
|
---|
197 | return FALSE;
|
---|
198 | }
|
---|
199 |
|
---|
200 | /******************************************************************
|
---|
201 | * elf_unmap_section
|
---|
202 | *
|
---|
203 | * Unmaps a single section from memory
|
---|
204 | */
|
---|
205 | static void elf_unmap_section(struct elf_section_map* esm)
|
---|
206 | {
|
---|
207 | if (esm->sidx >= 0 && esm->sidx < esm->fmap->elfhdr.e_shnum && esm->fmap->sect[esm->sidx].mapped != ELF_NO_MAP)
|
---|
208 | {
|
---|
209 | unsigned pgsz = getpagesize();
|
---|
210 | unsigned ofst, size;
|
---|
211 |
|
---|
212 | ofst = esm->fmap->sect[esm->sidx].shdr.sh_offset & ~(pgsz - 1);
|
---|
213 | size = ((esm->fmap->sect[esm->sidx].shdr.sh_offset +
|
---|
214 | esm->fmap->sect[esm->sidx].shdr.sh_size + pgsz - 1) & ~(pgsz - 1)) - ofst;
|
---|
215 | if (munmap((char*)esm->fmap->sect[esm->sidx].mapped, size) < 0)
|
---|
216 | WARN("Couldn't unmap the section\n");
|
---|
217 | esm->fmap->sect[esm->sidx].mapped = ELF_NO_MAP;
|
---|
218 | }
|
---|
219 | }
|
---|
220 |
|
---|
221 | static void elf_end_find(struct elf_file_map* fmap)
|
---|
222 | {
|
---|
223 | struct elf_section_map esm;
|
---|
224 |
|
---|
225 | while (fmap)
|
---|
226 | {
|
---|
227 | esm.fmap = fmap;
|
---|
228 | esm.sidx = fmap->elfhdr.e_shstrndx;
|
---|
229 | elf_unmap_section(&esm);
|
---|
230 | fmap->shstrtab = ELF_NO_MAP;
|
---|
231 | fmap = fmap->alternate;
|
---|
232 | }
|
---|
233 | }
|
---|
234 |
|
---|
235 | /******************************************************************
|
---|
236 | * elf_get_map_size
|
---|
237 | *
|
---|
238 | * Get the size of an ELF section
|
---|
239 | */
|
---|
240 | static inline unsigned elf_get_map_size(struct elf_section_map* esm)
|
---|
241 | {
|
---|
242 | if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum)
|
---|
243 | return 0;
|
---|
244 | return esm->fmap->sect[esm->sidx].shdr.sh_size;
|
---|
245 | }
|
---|
246 |
|
---|
247 | /******************************************************************
|
---|
248 | * elf_map_file
|
---|
249 | *
|
---|
250 | * Maps an ELF file into memory (and checks it's a real ELF file)
|
---|
251 | */
|
---|
252 | static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
|
---|
253 | {
|
---|
254 | static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
|
---|
255 | struct stat statbuf;
|
---|
256 | int i;
|
---|
257 | Elf32_Phdr phdr;
|
---|
258 | unsigned tmp, page_mask = getpagesize() - 1;
|
---|
259 | char* filename;
|
---|
260 | unsigned len;
|
---|
261 | BOOL ret = FALSE;
|
---|
262 |
|
---|
263 | len = WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, NULL, 0, NULL, NULL);
|
---|
264 | if (!(filename = HeapAlloc(GetProcessHeap(), 0, len))) return FALSE;
|
---|
265 | WideCharToMultiByte(CP_UNIXCP, 0, filenameW, -1, filename, len, NULL, NULL);
|
---|
266 |
|
---|
267 | fmap->fd = -1;
|
---|
268 | fmap->shstrtab = ELF_NO_MAP;
|
---|
269 | fmap->alternate = NULL;
|
---|
270 |
|
---|
271 | /* check that the file exists, and that the module hasn't been loaded yet */
|
---|
272 | if (stat(filename, &statbuf) == -1 || S_ISDIR(statbuf.st_mode)) goto done;
|
---|
273 |
|
---|
274 | /* Now open the file, so that we can mmap() it. */
|
---|
275 | if ((fmap->fd = open(filename, O_RDONLY)) == -1) goto done;
|
---|
276 |
|
---|
277 | if (read(fmap->fd, &fmap->elfhdr, sizeof(fmap->elfhdr)) != sizeof(fmap->elfhdr))
|
---|
278 | goto done;
|
---|
279 | /* and check for an ELF header */
|
---|
280 | if (memcmp(fmap->elfhdr.e_ident,
|
---|
281 | elf_signature, sizeof(elf_signature))) goto done;
|
---|
282 |
|
---|
283 | fmap->sect = HeapAlloc(GetProcessHeap(), 0,
|
---|
284 | fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
|
---|
285 | if (!fmap->sect) goto done;
|
---|
286 |
|
---|
287 | lseek(fmap->fd, fmap->elfhdr.e_shoff, SEEK_SET);
|
---|
288 | for (i = 0; i < fmap->elfhdr.e_shnum; i++)
|
---|
289 | {
|
---|
290 | read(fmap->fd, &fmap->sect[i].shdr, sizeof(fmap->sect[i].shdr));
|
---|
291 | fmap->sect[i].mapped = ELF_NO_MAP;
|
---|
292 | }
|
---|
293 |
|
---|
294 | /* grab size of module once loaded in memory */
|
---|
295 | lseek(fmap->fd, fmap->elfhdr.e_phoff, SEEK_SET);
|
---|
296 | fmap->elf_size = 0;
|
---|
297 | fmap->elf_start = ~0L;
|
---|
298 | for (i = 0; i < fmap->elfhdr.e_phnum; i++)
|
---|
299 | {
|
---|
300 | if (read(fmap->fd, &phdr, sizeof(phdr)) == sizeof(phdr) &&
|
---|
301 | phdr.p_type == PT_LOAD)
|
---|
302 | {
|
---|
303 | tmp = (phdr.p_vaddr + phdr.p_memsz + page_mask) & ~page_mask;
|
---|
304 | if (fmap->elf_size < tmp) fmap->elf_size = tmp;
|
---|
305 | if (phdr.p_vaddr < fmap->elf_start) fmap->elf_start = phdr.p_vaddr;
|
---|
306 | }
|
---|
307 | }
|
---|
308 | /* if non relocatable ELF, then remove fixed address from computation
|
---|
309 | * otherwise, all addresses are zero based and start has no effect
|
---|
310 | */
|
---|
311 | fmap->elf_size -= fmap->elf_start;
|
---|
312 | ret = TRUE;
|
---|
313 | done:
|
---|
314 | HeapFree(GetProcessHeap(), 0, filename);
|
---|
315 | return ret;
|
---|
316 | }
|
---|
317 |
|
---|
318 | /******************************************************************
|
---|
319 | * elf_unmap_file
|
---|
320 | *
|
---|
321 | * Unmaps an ELF file from memory (previously mapped with elf_map_file)
|
---|
322 | */
|
---|
323 | static void elf_unmap_file(struct elf_file_map* fmap)
|
---|
324 | {
|
---|
325 | while (fmap)
|
---|
326 | {
|
---|
327 | if (fmap->fd != -1)
|
---|
328 | {
|
---|
329 | struct elf_section_map esm;
|
---|
330 | esm.fmap = fmap;
|
---|
331 | for (esm.sidx = 0; esm.sidx < fmap->elfhdr.e_shnum; esm.sidx++)
|
---|
332 | {
|
---|
333 | elf_unmap_section(&esm);
|
---|
334 | }
|
---|
335 | HeapFree(GetProcessHeap(), 0, fmap->sect);
|
---|
336 | close(fmap->fd);
|
---|
337 | }
|
---|
338 | fmap = fmap->alternate;
|
---|
339 | }
|
---|
340 | }
|
---|
341 |
|
---|
342 | /******************************************************************
|
---|
343 | * elf_is_in_thunk_area
|
---|
344 | *
|
---|
345 | * Check whether an address lies within one of the thunk area we
|
---|
346 | * know of.
|
---|
347 | */
|
---|
348 | int elf_is_in_thunk_area(unsigned long addr,
|
---|
349 | const struct elf_thunk_area* thunks)
|
---|
350 | {
|
---|
351 | unsigned i;
|
---|
352 |
|
---|
353 | for (i = 0; thunks[i].symname; i++)
|
---|
354 | {
|
---|
355 | if (addr >= thunks[i].rva_start && addr < thunks[i].rva_end)
|
---|
356 | return i;
|
---|
357 | }
|
---|
358 | return -1;
|
---|
359 | }
|
---|
360 |
|
---|
361 | /******************************************************************
|
---|
362 | * elf_hash_symtab
|
---|
363 | *
|
---|
364 | * creating an internal hash table to ease use ELF symtab information lookup
|
---|
365 | */
|
---|
366 | static void elf_hash_symtab(struct module* module, struct pool* pool,
|
---|
367 | struct hash_table* ht_symtab, struct elf_file_map* fmap,
|
---|
368 | struct elf_thunk_area* thunks)
|
---|
369 | {
|
---|
370 | int i, j, nsym;
|
---|
371 | const char* strp;
|
---|
372 | const char* symname;
|
---|
373 | struct symt_compiland* compiland = NULL;
|
---|
374 | const char* ptr;
|
---|
375 | const Elf32_Sym* symp;
|
---|
376 | struct symtab_elt* ste;
|
---|
377 | struct elf_section_map esm, esm_str;
|
---|
378 |
|
---|
379 | if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) &&
|
---|
380 | !elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return;
|
---|
381 | if ((symp = (const Elf32_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return;
|
---|
382 | esm_str.fmap = fmap;
|
---|
383 | esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link;
|
---|
384 | if ((strp = elf_map_section(&esm_str)) == ELF_NO_MAP) return;
|
---|
385 |
|
---|
386 | nsym = elf_get_map_size(&esm) / sizeof(*symp);
|
---|
387 |
|
---|
388 | for (j = 0; thunks[j].symname; j++)
|
---|
389 | thunks[j].rva_start = thunks[j].rva_end = 0;
|
---|
390 |
|
---|
391 | for (i = 0; i < nsym; i++, symp++)
|
---|
392 | {
|
---|
393 | /* Ignore certain types of entries which really aren't of that much
|
---|
394 | * interest.
|
---|
395 | */
|
---|
396 | if ((ELF32_ST_TYPE(symp->st_info) != STT_NOTYPE &&
|
---|
397 | ELF32_ST_TYPE(symp->st_info) != STT_FILE &&
|
---|
398 | ELF32_ST_TYPE(symp->st_info) != STT_OBJECT &&
|
---|
399 | ELF32_ST_TYPE(symp->st_info) != STT_FUNC) ||
|
---|
400 | symp->st_shndx == SHN_UNDEF)
|
---|
401 | {
|
---|
402 | continue;
|
---|
403 | }
|
---|
404 |
|
---|
405 | symname = strp + symp->st_name;
|
---|
406 |
|
---|
407 | /* handle some specific symtab (that we'll throw away when done) */
|
---|
408 | switch (ELF32_ST_TYPE(symp->st_info))
|
---|
409 | {
|
---|
410 | case STT_FILE:
|
---|
411 | if (symname)
|
---|
412 | compiland = symt_new_compiland(module, symp->st_value,
|
---|
413 | source_new(module, NULL, symname));
|
---|
414 | else
|
---|
415 | compiland = NULL;
|
---|
416 | continue;
|
---|
417 | case STT_NOTYPE:
|
---|
418 | /* we are only interested in wine markers inserted by winebuild */
|
---|
419 | for (j = 0; thunks[j].symname; j++)
|
---|
420 | {
|
---|
421 | if (!strcmp(symname, thunks[j].symname))
|
---|
422 | {
|
---|
423 | thunks[j].rva_start = symp->st_value;
|
---|
424 | thunks[j].rva_end = symp->st_value + symp->st_size;
|
---|
425 | break;
|
---|
426 | }
|
---|
427 | }
|
---|
428 | continue;
|
---|
429 | }
|
---|
430 |
|
---|
431 | /* FIXME: we don't need to handle them (GCC internals)
|
---|
432 | * Moreover, they screw up our symbol lookup :-/
|
---|
433 | */
|
---|
434 | if (symname[0] == '.' && symname[1] == 'L' && isdigit(symname[2]))
|
---|
435 | continue;
|
---|
436 |
|
---|
437 | ste = pool_alloc(pool, sizeof(*ste));
|
---|
438 | ste->ht_elt.name = symname;
|
---|
439 | /* GCC emits, in some cases, a .<digit>+ suffix.
|
---|
440 | * This is used for static variable inside functions, so
|
---|
441 | * that we can have several such variables with same name in
|
---|
442 | * the same compilation unit
|
---|
443 | * We simply ignore that suffix when present (we also get rid
|
---|
444 | * of it in stabs parsing)
|
---|
445 | */
|
---|
446 | ptr = symname + strlen(symname) - 1;
|
---|
447 | if (isdigit(*ptr))
|
---|
448 | {
|
---|
449 | while (isdigit(*ptr) && ptr >= symname) ptr--;
|
---|
450 | if (ptr > symname && *ptr == '.')
|
---|
451 | {
|
---|
452 | char* n = pool_alloc(pool, ptr - symname + 1);
|
---|
453 | memcpy(n, symname, ptr - symname + 1);
|
---|
454 | n[ptr - symname] = '\0';
|
---|
455 | ste->ht_elt.name = n;
|
---|
456 | }
|
---|
457 | }
|
---|
458 | ste->symp = symp;
|
---|
459 | ste->compiland = compiland;
|
---|
460 | ste->used = 0;
|
---|
461 | hash_table_add(ht_symtab, &ste->ht_elt);
|
---|
462 | }
|
---|
463 | /* as we added in the ht_symtab pointers to the symbols themselves,
|
---|
464 | * we cannot unmap yet the sections, it will be done when we're over
|
---|
465 | * with this ELF file
|
---|
466 | */
|
---|
467 | }
|
---|
468 |
|
---|
469 | /******************************************************************
|
---|
470 | * elf_lookup_symtab
|
---|
471 | *
|
---|
472 | * lookup a symbol by name in our internal hash table for the symtab
|
---|
473 | */
|
---|
474 | static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
|
---|
475 | const struct hash_table* ht_symtab,
|
---|
476 | const char* name, struct symt* compiland)
|
---|
477 | {
|
---|
478 | struct symtab_elt* weak_result = NULL; /* without compiland name */
|
---|
479 | struct symtab_elt* result = NULL;
|
---|
480 | struct hash_table_iter hti;
|
---|
481 | struct symtab_elt* ste;
|
---|
482 | const char* compiland_name;
|
---|
483 | const char* compiland_basename;
|
---|
484 | const char* base;
|
---|
485 |
|
---|
486 | /* we need weak match up (at least) when symbols of same name,
|
---|
487 | * defined several times in different compilation units,
|
---|
488 | * are merged in a single one (hence a different filename for c.u.)
|
---|
489 | */
|
---|
490 | if (compiland)
|
---|
491 | {
|
---|
492 | compiland_name = source_get(module,
|
---|
493 | ((struct symt_compiland*)compiland)->source);
|
---|
494 | compiland_basename = strrchr(compiland_name, '/');
|
---|
495 | if (!compiland_basename++) compiland_basename = compiland_name;
|
---|
496 | }
|
---|
497 | else compiland_name = compiland_basename = NULL;
|
---|
498 |
|
---|
499 | hash_table_iter_init(ht_symtab, &hti, name);
|
---|
500 | while ((ste = hash_table_iter_up(&hti)))
|
---|
501 | {
|
---|
502 | if (ste->used || strcmp(ste->ht_elt.name, name)) continue;
|
---|
503 |
|
---|
504 | weak_result = ste;
|
---|
505 | if ((ste->compiland && !compiland_name) || (!ste->compiland && compiland_name))
|
---|
506 | continue;
|
---|
507 | if (ste->compiland && compiland_name)
|
---|
508 | {
|
---|
509 | const char* filename = source_get(module, ste->compiland->source);
|
---|
510 | if (strcmp(filename, compiland_name))
|
---|
511 | {
|
---|
512 | base = strrchr(filename, '/');
|
---|
513 | if (!base++) base = filename;
|
---|
514 | if (strcmp(base, compiland_basename)) continue;
|
---|
515 | }
|
---|
516 | }
|
---|
517 | if (result)
|
---|
518 | {
|
---|
519 | FIXME("Already found symbol %s (%s) in symtab %s @%08x and %s @%08x\n",
|
---|
520 | name, compiland_name,
|
---|
521 | source_get(module, result->compiland->source), (unsigned int)result->symp->st_value,
|
---|
522 | source_get(module, ste->compiland->source), (unsigned int)ste->symp->st_value);
|
---|
523 | }
|
---|
524 | else
|
---|
525 | {
|
---|
526 | result = ste;
|
---|
527 | ste->used = 1;
|
---|
528 | }
|
---|
529 | }
|
---|
530 | if (!result && !(result = weak_result))
|
---|
531 | {
|
---|
532 | FIXME("Couldn't find symbol %s!%s in symtab\n",
|
---|
533 | debugstr_w(module->module.ModuleName), name);
|
---|
534 | return NULL;
|
---|
535 | }
|
---|
536 | return result->symp;
|
---|
537 | }
|
---|
538 |
|
---|
539 | /******************************************************************
|
---|
540 | * elf_finish_stabs_info
|
---|
541 | *
|
---|
542 | * - get any relevant information (address & size) from the bits we got from the
|
---|
543 | * stabs debugging information
|
---|
544 | */
|
---|
545 | static void elf_finish_stabs_info(struct module* module, struct hash_table* symtab)
|
---|
546 | {
|
---|
547 | struct hash_table_iter hti;
|
---|
548 | void* ptr;
|
---|
549 | struct symt_ht* sym;
|
---|
550 | const Elf32_Sym* symp;
|
---|
551 |
|
---|
552 | hash_table_iter_init(&module->ht_symbols, &hti, NULL);
|
---|
553 | while ((ptr = hash_table_iter_up(&hti)))
|
---|
554 | {
|
---|
555 | sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
|
---|
556 | switch (sym->symt.tag)
|
---|
557 | {
|
---|
558 | case SymTagFunction:
|
---|
559 | if (((struct symt_function*)sym)->address != module->elf_info->elf_addr &&
|
---|
560 | ((struct symt_function*)sym)->size)
|
---|
561 | {
|
---|
562 | break;
|
---|
563 | }
|
---|
564 | symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name,
|
---|
565 | ((struct symt_function*)sym)->container);
|
---|
566 | if (symp)
|
---|
567 | {
|
---|
568 | if (((struct symt_function*)sym)->address != module->elf_info->elf_addr &&
|
---|
569 | ((struct symt_function*)sym)->address != module->elf_info->elf_addr + symp->st_value)
|
---|
570 | FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n",
|
---|
571 | sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
|
---|
572 | ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value);
|
---|
573 | if (((struct symt_function*)sym)->size && ((struct symt_function*)sym)->size != symp->st_size)
|
---|
574 | FIXME("Changing size for %p/%s!%s from %08lx to %08x\n",
|
---|
575 | sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
|
---|
576 | ((struct symt_function*)sym)->size, (unsigned int)symp->st_size);
|
---|
577 |
|
---|
578 | ((struct symt_function*)sym)->address = module->elf_info->elf_addr +
|
---|
579 | symp->st_value;
|
---|
580 | ((struct symt_function*)sym)->size = symp->st_size;
|
---|
581 | } else
|
---|
582 | FIXME("Couldn't find %s!%s\n",
|
---|
583 | debugstr_w(module->module.ModuleName), sym->hash_elt.name);
|
---|
584 | break;
|
---|
585 | case SymTagData:
|
---|
586 | switch (((struct symt_data*)sym)->kind)
|
---|
587 | {
|
---|
588 | case DataIsGlobal:
|
---|
589 | case DataIsFileStatic:
|
---|
590 | if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr)
|
---|
591 | break;
|
---|
592 | symp = elf_lookup_symtab(module, symtab, sym->hash_elt.name,
|
---|
593 | ((struct symt_data*)sym)->container);
|
---|
594 | if (symp)
|
---|
595 | {
|
---|
596 | if (((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr &&
|
---|
597 | ((struct symt_data*)sym)->u.var.offset != module->elf_info->elf_addr + symp->st_value)
|
---|
598 | FIXME("Changing address for %p/%s!%s from %08lx to %08lx\n",
|
---|
599 | sym, debugstr_w(module->module.ModuleName), sym->hash_elt.name,
|
---|
600 | ((struct symt_function*)sym)->address, module->elf_info->elf_addr + symp->st_value);
|
---|
601 | ((struct symt_data*)sym)->u.var.offset = module->elf_info->elf_addr +
|
---|
602 | symp->st_value;
|
---|
603 | ((struct symt_data*)sym)->kind = (ELF32_ST_BIND(symp->st_info) == STB_LOCAL) ?
|
---|
604 | DataIsFileStatic : DataIsGlobal;
|
---|
605 | } else
|
---|
606 | FIXME("Couldn't find %s!%s\n",
|
---|
607 | debugstr_w(module->module.ModuleName), sym->hash_elt.name);
|
---|
608 | break;
|
---|
609 | default:;
|
---|
610 | }
|
---|
611 | break;
|
---|
612 | default:
|
---|
613 | FIXME("Unsupported tag %u\n", sym->symt.tag);
|
---|
614 | break;
|
---|
615 | }
|
---|
616 | }
|
---|
617 | /* since we may have changed some addresses & sizes, mark the module to be resorted */
|
---|
618 | module->sortlist_valid = FALSE;
|
---|
619 | }
|
---|
620 |
|
---|
621 | /******************************************************************
|
---|
622 | * elf_load_wine_thunks
|
---|
623 | *
|
---|
624 | * creating the thunk objects for a wine native DLL
|
---|
625 | */
|
---|
626 | static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symtab,
|
---|
627 | const struct elf_thunk_area* thunks)
|
---|
628 | {
|
---|
629 | int j;
|
---|
630 | struct hash_table_iter hti;
|
---|
631 | struct symtab_elt* ste;
|
---|
632 | DWORD addr;
|
---|
633 | struct symt_ht* symt;
|
---|
634 |
|
---|
635 | hash_table_iter_init(ht_symtab, &hti, NULL);
|
---|
636 | while ((ste = hash_table_iter_up(&hti)))
|
---|
637 | {
|
---|
638 | if (ste->used) continue;
|
---|
639 |
|
---|
640 | addr = module->elf_info->elf_addr + ste->symp->st_value;
|
---|
641 |
|
---|
642 | j = elf_is_in_thunk_area(ste->symp->st_value, thunks);
|
---|
643 | if (j >= 0) /* thunk found */
|
---|
644 | {
|
---|
645 | symt_new_thunk(module, ste->compiland, ste->ht_elt.name, thunks[j].ordinal,
|
---|
646 | addr, ste->symp->st_size);
|
---|
647 | }
|
---|
648 | else
|
---|
649 | {
|
---|
650 | ULONG64 ref_addr;
|
---|
651 |
|
---|
652 | symt = symt_find_nearest(module, addr);
|
---|
653 | if (symt)
|
---|
654 | symt_get_info(&symt->symt, TI_GET_ADDRESS, &ref_addr);
|
---|
655 | if (!symt || addr != ref_addr)
|
---|
656 | {
|
---|
657 | /* creating public symbols for all the ELF symbols which haven't been
|
---|
658 | * used yet (ie we have no debug information on them)
|
---|
659 | * That's the case, for example, of the .spec.c files
|
---|
660 | */
|
---|
661 | switch (ELF32_ST_TYPE(ste->symp->st_info))
|
---|
662 | {
|
---|
663 | case STT_FUNC:
|
---|
664 | symt_new_function(module, ste->compiland, ste->ht_elt.name,
|
---|
665 | addr, ste->symp->st_size, NULL);
|
---|
666 | break;
|
---|
667 | case STT_OBJECT:
|
---|
668 | symt_new_global_variable(module, ste->compiland, ste->ht_elt.name,
|
---|
669 | ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL,
|
---|
670 | addr, ste->symp->st_size, NULL);
|
---|
671 | break;
|
---|
672 | default:
|
---|
673 | FIXME("Shouldn't happen\n");
|
---|
674 | break;
|
---|
675 | }
|
---|
676 | /* FIXME: this is a hack !!!
|
---|
677 | * we are adding new symbols, but as we're parsing a symbol table
|
---|
678 | * (hopefully without duplicate symbols) we delay rebuilding the sorted
|
---|
679 | * module table until we're done with the symbol table
|
---|
680 | * Otherwise, as we intertwine symbols's add and lookup, performance
|
---|
681 | * is rather bad
|
---|
682 | */
|
---|
683 | module->sortlist_valid = TRUE;
|
---|
684 | }
|
---|
685 | else if (strcmp(ste->ht_elt.name, symt->hash_elt.name))
|
---|
686 | {
|
---|
687 | ULONG64 xaddr = 0, xsize = 0;
|
---|
688 | DWORD kind = -1;
|
---|
689 |
|
---|
690 | symt_get_info(&symt->symt, TI_GET_ADDRESS, &xaddr);
|
---|
691 | symt_get_info(&symt->symt, TI_GET_LENGTH, &xsize);
|
---|
692 | symt_get_info(&symt->symt, TI_GET_DATAKIND, &kind);
|
---|
693 |
|
---|
694 | /* If none of symbols has a correct size, we consider they are both markers
|
---|
695 | * Hence, we can silence this warning
|
---|
696 | * Also, we check that we don't have two symbols, one local, the other
|
---|
697 | * global which is legal
|
---|
698 | */
|
---|
699 | if ((xsize || ste->symp->st_size) &&
|
---|
700 | (kind == (ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal))
|
---|
701 | FIXME("Duplicate in %s: %s<%08x-%08x> %s<%s-%s>\n",
|
---|
702 | debugstr_w(module->module.ModuleName),
|
---|
703 | ste->ht_elt.name, addr, (unsigned int)ste->symp->st_size,
|
---|
704 | symt->hash_elt.name,
|
---|
705 | wine_dbgstr_longlong(xaddr), wine_dbgstr_longlong(xsize));
|
---|
706 | }
|
---|
707 | }
|
---|
708 | }
|
---|
709 | /* see comment above */
|
---|
710 | module->sortlist_valid = FALSE;
|
---|
711 | return TRUE;
|
---|
712 | }
|
---|
713 |
|
---|
714 | /******************************************************************
|
---|
715 | * elf_new_public_symbols
|
---|
716 | *
|
---|
717 | * Creates a set of public symbols from an ELF symtab
|
---|
718 | */
|
---|
719 | static int elf_new_public_symbols(struct module* module, struct hash_table* symtab)
|
---|
720 | {
|
---|
721 | struct hash_table_iter hti;
|
---|
722 | struct symtab_elt* ste;
|
---|
723 |
|
---|
724 | if (dbghelp_options & SYMOPT_NO_PUBLICS) return TRUE;
|
---|
725 |
|
---|
726 | /* FIXME: we're missing the ELF entry point here */
|
---|
727 |
|
---|
728 | hash_table_iter_init(symtab, &hti, NULL);
|
---|
729 | while ((ste = hash_table_iter_up(&hti)))
|
---|
730 | {
|
---|
731 | symt_new_public(module, ste->compiland, ste->ht_elt.name,
|
---|
732 | module->elf_info->elf_addr + ste->symp->st_value,
|
---|
733 | ste->symp->st_size, TRUE /* FIXME */,
|
---|
734 | ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC);
|
---|
735 | }
|
---|
736 | return TRUE;
|
---|
737 | }
|
---|
738 |
|
---|
739 | /* Copyright (C) 1986 Gary S. Brown. Modified by Robert Shearman. You may use
|
---|
740 | the following calc_crc32 code or tables extracted from it, as desired without
|
---|
741 | restriction. */
|
---|
742 |
|
---|
743 | /**********************************************************************\
|
---|
744 | |* Demonstration program to compute the 32-bit CRC used as the frame *|
|
---|
745 | |* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|
---|
746 | |* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|
---|
747 | |* protocol). The 32-bit FCS was added via the Federal Register, *|
|
---|
748 | |* 1 June 1982, p.23798. I presume but don't know for certain that *|
|
---|
749 | |* this polynomial is or will be included in CCITT V.41, which *|
|
---|
750 | |* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|
---|
751 | |* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|
---|
752 | |* errors by a factor of 10^-5 over 16-bit FCS. *|
|
---|
753 | \**********************************************************************/
|
---|
754 |
|
---|
755 | /* First, the polynomial itself and its table of feedback terms. The */
|
---|
756 | /* polynomial is */
|
---|
757 | /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
|
---|
758 | /* Note that we take it "backwards" and put the highest-order term in */
|
---|
759 | /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
|
---|
760 | /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
|
---|
761 | /* the MSB being 1. */
|
---|
762 |
|
---|
763 | /* Note that the usual hardware shift register implementation, which */
|
---|
764 | /* is what we're using (we're merely optimizing it by doing eight-bit */
|
---|
765 | /* chunks at a time) shifts bits into the lowest-order term. In our */
|
---|
766 | /* implementation, that means shifting towards the right. Why do we */
|
---|
767 | /* do it this way? Because the calculated CRC must be transmitted in */
|
---|
768 | /* order from highest-order term to lowest-order term. UARTs transmit */
|
---|
769 | /* characters in order from LSB to MSB. By storing the CRC this way, */
|
---|
770 | /* we hand it to the UART in the order low-byte to high-byte; the UART */
|
---|
771 | /* sends each low-bit to hight-bit; and the result is transmission bit */
|
---|
772 | /* by bit from highest- to lowest-order term without requiring any bit */
|
---|
773 | /* shuffling on our part. Reception works similarly. */
|
---|
774 |
|
---|
775 | /* The feedback terms table consists of 256, 32-bit entries. Notes: */
|
---|
776 | /* */
|
---|
777 | /* 1. The table can be generated at runtime if desired; code to do so */
|
---|
778 | /* is shown later. It might not be obvious, but the feedback */
|
---|
779 | /* terms simply represent the results of eight shift/xor opera- */
|
---|
780 | /* tions for all combinations of data and CRC register values. */
|
---|
781 | /* */
|
---|
782 | /* 2. The CRC accumulation logic is the same for all CRC polynomials, */
|
---|
783 | /* be they sixteen or thirty-two bits wide. You simply choose the */
|
---|
784 | /* appropriate table. Alternatively, because the table can be */
|
---|
785 | /* generated at runtime, you can start by generating the table for */
|
---|
786 | /* the polynomial in question and use exactly the same "updcrc", */
|
---|
787 | /* if your application needn't simultaneously handle two CRC */
|
---|
788 | /* polynomials. (Note, however, that XMODEM is strange.) */
|
---|
789 | /* */
|
---|
790 | /* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
|
---|
791 | /* of course, 32-bit entries work OK if the high 16 bits are zero. */
|
---|
792 | /* */
|
---|
793 | /* 4. The values must be right-shifted by eight bits by the "updcrc" */
|
---|
794 | /* logic; the shift must be unsigned (bring in zeroes). On some */
|
---|
795 | /* hardware you could probably optimize the shift in assembler by */
|
---|
796 | /* using byte-swap instructions. */
|
---|
797 |
|
---|
798 |
|
---|
799 | static DWORD calc_crc32(struct elf_file_map* fmap)
|
---|
800 | {
|
---|
801 | #define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
|
---|
802 | static const DWORD crc_32_tab[] =
|
---|
803 | { /* CRC polynomial 0xedb88320 */
|
---|
804 | 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
---|
805 | 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
---|
806 | 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
---|
807 | 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
---|
808 | 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
---|
809 | 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
---|
810 | 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
---|
811 | 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
---|
812 | 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
---|
813 | 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
---|
814 | 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
---|
815 | 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
---|
816 | 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
---|
817 | 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
---|
818 | 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
---|
819 | 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
---|
820 | 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
---|
821 | 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
---|
822 | 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
---|
823 | 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
---|
824 | 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
---|
825 | 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
---|
826 | 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
---|
827 | 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
---|
828 | 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
---|
829 | 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
---|
830 | 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
---|
831 | 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
---|
832 | 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
---|
833 | 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
---|
834 | 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
---|
835 | 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
---|
836 | 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
---|
837 | 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
---|
838 | 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
---|
839 | 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
---|
840 | 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
---|
841 | 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
---|
842 | 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
---|
843 | 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
---|
844 | 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
---|
845 | 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
---|
846 | 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
---|
847 | };
|
---|
848 | int i, r;
|
---|
849 | unsigned char buffer[256];
|
---|
850 | DWORD crc = ~0;
|
---|
851 |
|
---|
852 | lseek(fmap->fd, 0, SEEK_SET);
|
---|
853 | while ((r = read(fmap->fd, buffer, sizeof(buffer))) > 0)
|
---|
854 | {
|
---|
855 | for (i = 0; i < r; i++) crc = UPDC32(buffer[i], crc);
|
---|
856 | }
|
---|
857 | return ~crc;
|
---|
858 | #undef UPDC32
|
---|
859 | }
|
---|
860 |
|
---|
861 | static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, DWORD crc)
|
---|
862 | {
|
---|
863 | BOOL ret;
|
---|
864 | if (!elf_map_file(file, fmap)) return FALSE;
|
---|
865 | if (!(ret = crc == calc_crc32(fmap)))
|
---|
866 | {
|
---|
867 | WARN("Bad CRC for file %s (got %08x while expecting %08x)\n",
|
---|
868 | debugstr_w(file), calc_crc32(fmap), crc);
|
---|
869 | elf_unmap_file(fmap);
|
---|
870 | }
|
---|
871 | return ret;
|
---|
872 | }
|
---|
873 |
|
---|
874 | /******************************************************************
|
---|
875 | * elf_locate_debug_link
|
---|
876 | *
|
---|
877 | * Locate a filename from a .gnu_debuglink section, using the same
|
---|
878 | * strategy as gdb:
|
---|
879 | * "If the full name of the directory containing the executable is
|
---|
880 | * execdir, and the executable has a debug link that specifies the
|
---|
881 | * name debugfile, then GDB will automatically search for the
|
---|
882 | * debugging information file in three places:
|
---|
883 | * - the directory containing the executable file (that is, it
|
---|
884 | * will look for a file named `execdir/debugfile',
|
---|
885 | * - a subdirectory of that directory named `.debug' (that is, the
|
---|
886 | * file `execdir/.debug/debugfile', and
|
---|
887 | * - a subdirectory of the global debug file directory that includes
|
---|
888 | * the executable's full path, and the name from the link (that is,
|
---|
889 | * the file `globaldebugdir/execdir/debugfile', where globaldebugdir
|
---|
890 | * is the global debug file directory, and execdir has been turned
|
---|
891 | * into a relative path)." (from GDB manual)
|
---|
892 | */
|
---|
893 | static BOOL elf_locate_debug_link(struct elf_file_map* fmap, const char* filename,
|
---|
894 | const WCHAR* loaded_file, DWORD crc)
|
---|
895 | {
|
---|
896 | static const WCHAR globalDebugDirW[] = {'/','u','s','r','/','l','i','b','/','d','e','b','u','g','/'};
|
---|
897 | static const WCHAR dotDebugW[] = {'.','d','e','b','u','g','/'};
|
---|
898 | const size_t globalDebugDirLen = sizeof(globalDebugDirW) / sizeof(WCHAR);
|
---|
899 | size_t filename_len;
|
---|
900 | WCHAR* p = NULL;
|
---|
901 | WCHAR* slash;
|
---|
902 | struct elf_file_map* fmap_link = NULL;
|
---|
903 |
|
---|
904 | fmap_link = HeapAlloc(GetProcessHeap(), 0, sizeof(*fmap_link));
|
---|
905 | if (!fmap_link) return FALSE;
|
---|
906 |
|
---|
907 | filename_len = MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, NULL, 0);
|
---|
908 | p = HeapAlloc(GetProcessHeap(), 0,
|
---|
909 | (globalDebugDirLen + strlenW(loaded_file) + 6 + 1 + filename_len + 1) * sizeof(WCHAR));
|
---|
910 | if (!p) goto found;
|
---|
911 |
|
---|
912 | /* we prebuild the string with "execdir" */
|
---|
913 | strcpyW(p, loaded_file);
|
---|
914 | slash = strrchrW(p, '/');
|
---|
915 | if (slash == NULL) slash = p; else slash++;
|
---|
916 |
|
---|
917 | /* testing execdir/filename */
|
---|
918 | MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len);
|
---|
919 | if (elf_check_debug_link(p, fmap_link, crc)) goto found;
|
---|
920 |
|
---|
921 | /* testing execdir/.debug/filename */
|
---|
922 | memcpy(slash, dotDebugW, sizeof(dotDebugW));
|
---|
923 | MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash + sizeof(dotDebugW) / sizeof(WCHAR), filename_len);
|
---|
924 | if (elf_check_debug_link(p, fmap_link, crc)) goto found;
|
---|
925 |
|
---|
926 | /* testing globaldebugdir/execdir/filename */
|
---|
927 | memmove(p + globalDebugDirLen, p, (slash - p) * sizeof(WCHAR));
|
---|
928 | memcpy(p, globalDebugDirW, globalDebugDirLen * sizeof(WCHAR));
|
---|
929 | slash += globalDebugDirLen;
|
---|
930 | MultiByteToWideChar(CP_UNIXCP, 0, filename, -1, slash, filename_len);
|
---|
931 | if (elf_check_debug_link(p, fmap_link, crc)) goto found;
|
---|
932 |
|
---|
933 | /* finally testing filename */
|
---|
934 | if (elf_check_debug_link(slash, fmap_link, crc)) goto found;
|
---|
935 |
|
---|
936 |
|
---|
937 | WARN("Couldn't locate or map %s\n", filename);
|
---|
938 | HeapFree(GetProcessHeap(), 0, p);
|
---|
939 | HeapFree(GetProcessHeap(), 0, fmap_link);
|
---|
940 | return FALSE;
|
---|
941 |
|
---|
942 | found:
|
---|
943 | TRACE("Located debug information file %s at %s\n", filename, debugstr_w(p));
|
---|
944 | HeapFree(GetProcessHeap(), 0, p);
|
---|
945 | fmap->alternate = fmap_link;
|
---|
946 | return TRUE;
|
---|
947 | }
|
---|
948 |
|
---|
949 | /******************************************************************
|
---|
950 | * elf_debuglink_parse
|
---|
951 | *
|
---|
952 | * Parses a .gnu_debuglink section and loads the debug info from
|
---|
953 | * the external file specified there.
|
---|
954 | */
|
---|
955 | static BOOL elf_debuglink_parse(struct elf_file_map* fmap, struct module* module,
|
---|
956 | const BYTE* debuglink)
|
---|
957 | {
|
---|
958 | /* The content of a debug link section is:
|
---|
959 | * 1/ a NULL terminated string, containing the file name for the
|
---|
960 | * debug info
|
---|
961 | * 2/ padding on 4 byte boundary
|
---|
962 | * 3/ CRC of the linked ELF file
|
---|
963 | */
|
---|
964 | const char* dbg_link = (const char*)debuglink;
|
---|
965 | DWORD crc;
|
---|
966 |
|
---|
967 | crc = *(const DWORD*)(dbg_link + ((DWORD_PTR)(strlen(dbg_link) + 4) & ~3));
|
---|
968 | return elf_locate_debug_link(fmap, dbg_link, module->module.LoadedImageName, crc);
|
---|
969 | }
|
---|
970 |
|
---|
971 | /******************************************************************
|
---|
972 | * elf_load_debug_info_from_map
|
---|
973 | *
|
---|
974 | * Loads the symbolic information from ELF module which mapping is described
|
---|
975 | * in fmap
|
---|
976 | * the module has been loaded at 'load_offset' address, so symbols' address
|
---|
977 | * relocation is performed.
|
---|
978 | * CRC is checked if fmap->with_crc is TRUE
|
---|
979 | * returns
|
---|
980 | * 0 if the file doesn't contain symbolic info (or this info cannot be
|
---|
981 | * read or parsed)
|
---|
982 | * 1 on success
|
---|
983 | */
|
---|
984 | static BOOL elf_load_debug_info_from_map(struct module* module,
|
---|
985 | struct elf_file_map* fmap,
|
---|
986 | struct pool* pool,
|
---|
987 | struct hash_table* ht_symtab)
|
---|
988 | {
|
---|
989 | BOOL ret = FALSE, lret;
|
---|
990 | struct elf_thunk_area thunks[] =
|
---|
991 | {
|
---|
992 | {"__wine_spec_import_thunks", THUNK_ORDINAL_NOTYPE, 0, 0}, /* inter DLL calls */
|
---|
993 | {"__wine_spec_delayed_import_loaders", THUNK_ORDINAL_LOAD, 0, 0}, /* delayed inter DLL calls */
|
---|
994 | {"__wine_spec_delayed_import_thunks", THUNK_ORDINAL_LOAD, 0, 0}, /* delayed inter DLL calls */
|
---|
995 | {"__wine_delay_load", THUNK_ORDINAL_LOAD, 0, 0}, /* delayed inter DLL calls */
|
---|
996 | {"__wine_spec_thunk_text_16", -16, 0, 0}, /* 16 => 32 thunks */
|
---|
997 | {"__wine_spec_thunk_text_32", -32, 0, 0}, /* 32 => 16 thunks */
|
---|
998 | {NULL, 0, 0, 0}
|
---|
999 | };
|
---|
1000 |
|
---|
1001 | module->module.SymType = SymExport;
|
---|
1002 |
|
---|
1003 | /* create a hash table for the symtab */
|
---|
1004 | elf_hash_symtab(module, pool, ht_symtab, fmap, thunks);
|
---|
1005 |
|
---|
1006 | if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
|
---|
1007 | {
|
---|
1008 | struct elf_section_map stab_sect, stabstr_sect;
|
---|
1009 | struct elf_section_map debug_sect, debug_str_sect, debug_abbrev_sect,
|
---|
1010 | debug_line_sect, debug_loclist_sect;
|
---|
1011 | struct elf_section_map debuglink_sect;
|
---|
1012 |
|
---|
1013 | /* if present, add the .gnu_debuglink file as an alternate to current one */
|
---|
1014 | if (elf_find_section(fmap, ".gnu_debuglink", SHT_NULL, &debuglink_sect))
|
---|
1015 | {
|
---|
1016 | const BYTE* dbg_link;
|
---|
1017 |
|
---|
1018 | dbg_link = (const BYTE*)elf_map_section(&debuglink_sect);
|
---|
1019 | if (dbg_link != ELF_NO_MAP)
|
---|
1020 | {
|
---|
1021 | lret = elf_debuglink_parse(fmap, module, dbg_link);
|
---|
1022 | if (!lret)
|
---|
1023 | WARN("Couldn't load linked debug file for %s\n",
|
---|
1024 | debugstr_w(module->module.ModuleName));
|
---|
1025 | ret = ret || lret;
|
---|
1026 | }
|
---|
1027 | elf_unmap_section(&debuglink_sect);
|
---|
1028 | }
|
---|
1029 | if (elf_find_section(fmap, ".stab", SHT_NULL, &stab_sect) &&
|
---|
1030 | elf_find_section(fmap, ".stabstr", SHT_NULL, &stabstr_sect))
|
---|
1031 | {
|
---|
1032 | const char* stab;
|
---|
1033 | const char* stabstr;
|
---|
1034 |
|
---|
1035 | stab = elf_map_section(&stab_sect);
|
---|
1036 | stabstr = elf_map_section(&stabstr_sect);
|
---|
1037 | if (stab != ELF_NO_MAP && stabstr != ELF_NO_MAP)
|
---|
1038 | {
|
---|
1039 | /* OK, now just parse all of the stabs. */
|
---|
1040 | lret = stabs_parse(module, module->elf_info->elf_addr,
|
---|
1041 | stab, elf_get_map_size(&stab_sect),
|
---|
1042 | stabstr, elf_get_map_size(&stabstr_sect));
|
---|
1043 | if (lret)
|
---|
1044 | /* and fill in the missing information for stabs */
|
---|
1045 | elf_finish_stabs_info(module, ht_symtab);
|
---|
1046 | else
|
---|
1047 | WARN("Couldn't correctly read stabs\n");
|
---|
1048 | ret = ret || lret;
|
---|
1049 | }
|
---|
1050 | else lret = FALSE;
|
---|
1051 | elf_unmap_section(&stab_sect);
|
---|
1052 | elf_unmap_section(&stabstr_sect);
|
---|
1053 | }
|
---|
1054 | if (elf_find_section(fmap, ".debug_info", SHT_NULL, &debug_sect))
|
---|
1055 | {
|
---|
1056 | /* Dwarf 2 debug information */
|
---|
1057 | const BYTE* dw2_debug;
|
---|
1058 | const BYTE* dw2_debug_abbrev;
|
---|
1059 | const BYTE* dw2_debug_str;
|
---|
1060 | const BYTE* dw2_debug_line;
|
---|
1061 | const BYTE* dw2_debug_loclist;
|
---|
1062 |
|
---|
1063 | /* debug info might have a different base address than .so file
|
---|
1064 | * when elf file is prelinked after splitting off debug info
|
---|
1065 | * adjust symbol base addresses accordingly
|
---|
1066 | */
|
---|
1067 | unsigned long load_offset = module->elf_info->elf_addr +
|
---|
1068 | fmap->elf_start - debug_sect.fmap->elf_start;
|
---|
1069 |
|
---|
1070 | TRACE("Loading Dwarf2 information for %s\n", debugstr_w(module->module.ModuleName));
|
---|
1071 |
|
---|
1072 | elf_find_section(fmap, ".debug_str", SHT_NULL, &debug_str_sect);
|
---|
1073 | elf_find_section(fmap, ".debug_abbrev", SHT_NULL, &debug_abbrev_sect);
|
---|
1074 | elf_find_section(fmap, ".debug_line", SHT_NULL, &debug_line_sect);
|
---|
1075 | elf_find_section(fmap, ".debug_loc", SHT_NULL, &debug_loclist_sect);
|
---|
1076 |
|
---|
1077 | dw2_debug = (const BYTE*)elf_map_section(&debug_sect);
|
---|
1078 | dw2_debug_abbrev = (const BYTE*)elf_map_section(&debug_abbrev_sect);
|
---|
1079 | dw2_debug_str = (const BYTE*)elf_map_section(&debug_str_sect);
|
---|
1080 | dw2_debug_line = (const BYTE*)elf_map_section(&debug_line_sect);
|
---|
1081 | dw2_debug_loclist = (const BYTE*)elf_map_section(&debug_loclist_sect);
|
---|
1082 | if (dw2_debug != ELF_NO_MAP && dw2_debug_abbrev != ELF_NO_MAP && dw2_debug_str != ELF_NO_MAP)
|
---|
1083 | {
|
---|
1084 | /* OK, now just parse dwarf2 debug infos. */
|
---|
1085 | lret = dwarf2_parse(module, load_offset, thunks,
|
---|
1086 | dw2_debug, elf_get_map_size(&debug_sect),
|
---|
1087 | dw2_debug_abbrev, elf_get_map_size(&debug_abbrev_sect),
|
---|
1088 | dw2_debug_str, elf_get_map_size(&debug_str_sect),
|
---|
1089 | dw2_debug_line, elf_get_map_size(&debug_line_sect),
|
---|
1090 | dw2_debug_loclist, elf_get_map_size(&debug_loclist_sect));
|
---|
1091 |
|
---|
1092 | if (!lret)
|
---|
1093 | WARN("Couldn't correctly read dwarf2\n");
|
---|
1094 | ret = ret || lret;
|
---|
1095 | }
|
---|
1096 | elf_unmap_section(&debug_sect);
|
---|
1097 | elf_unmap_section(&debug_abbrev_sect);
|
---|
1098 | elf_unmap_section(&debug_str_sect);
|
---|
1099 | elf_unmap_section(&debug_line_sect);
|
---|
1100 | elf_unmap_section(&debug_loclist_sect);
|
---|
1101 | }
|
---|
1102 | }
|
---|
1103 | if (strstrW(module->module.ModuleName, S_ElfW) ||
|
---|
1104 | !strcmpW(module->module.ModuleName, S_WineLoaderW))
|
---|
1105 | {
|
---|
1106 | /* add the thunks for native libraries */
|
---|
1107 | if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
|
---|
1108 | elf_new_wine_thunks(module, ht_symtab, thunks);
|
---|
1109 | }
|
---|
1110 | /* add all the public symbols from symtab */
|
---|
1111 | if (elf_new_public_symbols(module, ht_symtab) && !ret) ret = TRUE;
|
---|
1112 |
|
---|
1113 | return ret;
|
---|
1114 | }
|
---|
1115 |
|
---|
1116 | /******************************************************************
|
---|
1117 | * elf_load_debug_info
|
---|
1118 | *
|
---|
1119 | * Loads ELF debugging information from the module image file.
|
---|
1120 | */
|
---|
1121 | BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap)
|
---|
1122 | {
|
---|
1123 | BOOL ret = TRUE;
|
---|
1124 | struct pool pool;
|
---|
1125 | struct hash_table ht_symtab;
|
---|
1126 | struct elf_file_map my_fmap;
|
---|
1127 |
|
---|
1128 | if (module->type != DMT_ELF || !module->elf_info)
|
---|
1129 | {
|
---|
1130 | ERR("Bad elf module '%s'\n", debugstr_w(module->module.LoadedImageName));
|
---|
1131 | return FALSE;
|
---|
1132 | }
|
---|
1133 |
|
---|
1134 | pool_init(&pool, 65536);
|
---|
1135 | hash_table_init(&pool, &ht_symtab, 256);
|
---|
1136 |
|
---|
1137 | if (!fmap)
|
---|
1138 | {
|
---|
1139 | fmap = &my_fmap;
|
---|
1140 | ret = elf_map_file(module->module.LoadedImageName, fmap);
|
---|
1141 | }
|
---|
1142 | if (ret)
|
---|
1143 | ret = elf_load_debug_info_from_map(module, fmap, &pool, &ht_symtab);
|
---|
1144 |
|
---|
1145 | pool_destroy(&pool);
|
---|
1146 | if (fmap == &my_fmap) elf_unmap_file(fmap);
|
---|
1147 | return ret;
|
---|
1148 | }
|
---|
1149 |
|
---|
1150 | /******************************************************************
|
---|
1151 | * elf_fetch_file_info
|
---|
1152 | *
|
---|
1153 | * Gathers some more information for an ELF module from a given file
|
---|
1154 | */
|
---|
1155 | BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
|
---|
1156 | DWORD* size, DWORD* checksum)
|
---|
1157 | {
|
---|
1158 | struct elf_file_map fmap;
|
---|
1159 |
|
---|
1160 | if (!elf_map_file(name, &fmap)) return FALSE;
|
---|
1161 | if (base) *base = fmap.elf_start;
|
---|
1162 | *size = fmap.elf_size;
|
---|
1163 | *checksum = calc_crc32(&fmap);
|
---|
1164 | elf_unmap_file(&fmap);
|
---|
1165 | return TRUE;
|
---|
1166 | }
|
---|
1167 |
|
---|
1168 | /******************************************************************
|
---|
1169 | * elf_load_file
|
---|
1170 | *
|
---|
1171 | * Loads the information for ELF module stored in 'filename'
|
---|
1172 | * the module has been loaded at 'load_offset' address
|
---|
1173 | * returns
|
---|
1174 | * -1 if the file cannot be found/opened
|
---|
1175 | * 0 if the file doesn't contain symbolic info (or this info cannot be
|
---|
1176 | * read or parsed)
|
---|
1177 | * 1 on success
|
---|
1178 | */
|
---|
1179 | static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
|
---|
1180 | unsigned long load_offset, struct elf_info* elf_info)
|
---|
1181 | {
|
---|
1182 | BOOL ret = FALSE;
|
---|
1183 | struct elf_file_map fmap;
|
---|
1184 |
|
---|
1185 | TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
|
---|
1186 |
|
---|
1187 | if (!elf_map_file(filename, &fmap)) goto leave;
|
---|
1188 |
|
---|
1189 | /* Next, we need to find a few of the internal ELF headers within
|
---|
1190 | * this thing. We need the main executable header, and the section
|
---|
1191 | * table.
|
---|
1192 | */
|
---|
1193 | if (!fmap.elf_start && !load_offset)
|
---|
1194 | ERR("Relocatable ELF %s, but no load address. Loading at 0x0000000\n",
|
---|
1195 | debugstr_w(filename));
|
---|
1196 | if (fmap.elf_start && load_offset)
|
---|
1197 | {
|
---|
1198 | WARN("Non-relocatable ELF %s, but load address of 0x%08lx supplied. "
|
---|
1199 | "Assuming load address is corrupt\n", debugstr_w(filename), load_offset);
|
---|
1200 | load_offset = 0;
|
---|
1201 | }
|
---|
1202 |
|
---|
1203 | if (elf_info->flags & ELF_INFO_DEBUG_HEADER)
|
---|
1204 | {
|
---|
1205 | struct elf_section_map esm;
|
---|
1206 |
|
---|
1207 | if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm))
|
---|
1208 | {
|
---|
1209 | Elf32_Dyn dyn;
|
---|
1210 | char* ptr = (char*)fmap.sect[esm.sidx].shdr.sh_addr;
|
---|
1211 | unsigned long len;
|
---|
1212 |
|
---|
1213 | do
|
---|
1214 | {
|
---|
1215 | if (!ReadProcessMemory(pcs->handle, ptr, &dyn, sizeof(dyn), &len) ||
|
---|
1216 | len != sizeof(dyn))
|
---|
1217 | goto leave;
|
---|
1218 | if (dyn.d_tag == DT_DEBUG)
|
---|
1219 | {
|
---|
1220 | elf_info->dbg_hdr_addr = dyn.d_un.d_ptr;
|
---|
1221 | break;
|
---|
1222 | }
|
---|
1223 | ptr += sizeof(dyn);
|
---|
1224 | } while (dyn.d_tag != DT_NULL);
|
---|
1225 | if (dyn.d_tag == DT_NULL) goto leave;
|
---|
1226 | }
|
---|
1227 | elf_end_find(&fmap);
|
---|
1228 | }
|
---|
1229 |
|
---|
1230 | if (elf_info->flags & ELF_INFO_MODULE)
|
---|
1231 | {
|
---|
1232 | struct elf_module_info *elf_module_info =
|
---|
1233 | HeapAlloc(GetProcessHeap(), 0, sizeof(struct elf_module_info));
|
---|
1234 | if (!elf_module_info) goto leave;
|
---|
1235 | elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE,
|
---|
1236 | (load_offset) ? load_offset : fmap.elf_start,
|
---|
1237 | fmap.elf_size, 0, calc_crc32(&fmap));
|
---|
1238 | if (!elf_info->module)
|
---|
1239 | {
|
---|
1240 | HeapFree(GetProcessHeap(), 0, elf_module_info);
|
---|
1241 | goto leave;
|
---|
1242 | }
|
---|
1243 | elf_info->module->elf_info = elf_module_info;
|
---|
1244 | elf_info->module->elf_info->elf_addr = load_offset;
|
---|
1245 |
|
---|
1246 | if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
|
---|
1247 | {
|
---|
1248 | elf_info->module->module.SymType = SymDeferred;
|
---|
1249 | ret = TRUE;
|
---|
1250 | }
|
---|
1251 | else ret = elf_load_debug_info(elf_info->module, &fmap);
|
---|
1252 |
|
---|
1253 | elf_info->module->elf_info->elf_mark = 1;
|
---|
1254 | elf_info->module->elf_info->elf_loader = 0;
|
---|
1255 | } else ret = TRUE;
|
---|
1256 |
|
---|
1257 | if (elf_info->flags & ELF_INFO_NAME)
|
---|
1258 | {
|
---|
1259 | WCHAR* ptr;
|
---|
1260 | ptr = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1) * sizeof(WCHAR));
|
---|
1261 | if (ptr)
|
---|
1262 | {
|
---|
1263 | strcpyW(ptr, filename);
|
---|
1264 | elf_info->module_name = ptr;
|
---|
1265 | }
|
---|
1266 | else ret = FALSE;
|
---|
1267 | }
|
---|
1268 | leave:
|
---|
1269 | elf_unmap_file(&fmap);
|
---|
1270 |
|
---|
1271 | return ret;
|
---|
1272 | }
|
---|
1273 |
|
---|
1274 | /******************************************************************
|
---|
1275 | * elf_load_file_from_path
|
---|
1276 | * tries to load an ELF file from a set of paths (separated by ':')
|
---|
1277 | */
|
---|
1278 | static BOOL elf_load_file_from_path(HANDLE hProcess,
|
---|
1279 | const WCHAR* filename,
|
---|
1280 | unsigned long load_offset,
|
---|
1281 | const char* path,
|
---|
1282 | struct elf_info* elf_info)
|
---|
1283 | {
|
---|
1284 | BOOL ret = FALSE;
|
---|
1285 | WCHAR *s, *t, *fn;
|
---|
1286 | WCHAR* pathW = NULL;
|
---|
1287 | unsigned len;
|
---|
1288 |
|
---|
1289 | if (!path) return FALSE;
|
---|
1290 |
|
---|
1291 | len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
|
---|
1292 | pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
---|
1293 | if (!pathW) return FALSE;
|
---|
1294 | MultiByteToWideChar(CP_UNIXCP, 0, path, -1, pathW, len);
|
---|
1295 |
|
---|
1296 | for (s = pathW; s && *s; s = (t) ? (t+1) : NULL)
|
---|
1297 | {
|
---|
1298 | t = strchrW(s, ':');
|
---|
1299 | if (t) *t = '\0';
|
---|
1300 | fn = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(filename) + 1 + lstrlenW(s) + 1) * sizeof(WCHAR));
|
---|
1301 | if (!fn) break;
|
---|
1302 | strcpyW(fn, s);
|
---|
1303 | strcatW(fn, S_SlashW);
|
---|
1304 | strcatW(fn, filename);
|
---|
1305 | ret = elf_load_file(hProcess, fn, load_offset, elf_info);
|
---|
1306 | HeapFree(GetProcessHeap(), 0, fn);
|
---|
1307 | if (ret) break;
|
---|
1308 | s = (t) ? (t+1) : NULL;
|
---|
1309 | }
|
---|
1310 |
|
---|
1311 | HeapFree(GetProcessHeap(), 0, pathW);
|
---|
1312 | return ret;
|
---|
1313 | }
|
---|
1314 |
|
---|
1315 | /******************************************************************
|
---|
1316 | * elf_load_file_from_dll_path
|
---|
1317 | *
|
---|
1318 | * Tries to load an ELF file from the dll path
|
---|
1319 | */
|
---|
1320 | static BOOL elf_load_file_from_dll_path(HANDLE hProcess,
|
---|
1321 | const WCHAR* filename,
|
---|
1322 | unsigned long load_offset,
|
---|
1323 | struct elf_info* elf_info)
|
---|
1324 | {
|
---|
1325 | BOOL ret = FALSE;
|
---|
1326 | unsigned int index = 0;
|
---|
1327 | const char *path;
|
---|
1328 |
|
---|
1329 | while (!ret && (path = wine_dll_enum_load_path( index++ )))
|
---|
1330 | {
|
---|
1331 | WCHAR *name;
|
---|
1332 | unsigned len;
|
---|
1333 |
|
---|
1334 | len = MultiByteToWideChar(CP_UNIXCP, 0, path, -1, NULL, 0);
|
---|
1335 |
|
---|
1336 | name = HeapAlloc( GetProcessHeap(), 0,
|
---|
1337 | (len + lstrlenW(filename) + 2) * sizeof(WCHAR) );
|
---|
1338 |
|
---|
1339 | if (!name) break;
|
---|
1340 | MultiByteToWideChar(CP_UNIXCP, 0, path, -1, name, len);
|
---|
1341 | strcatW( name, S_SlashW );
|
---|
1342 | strcatW( name, filename );
|
---|
1343 | ret = elf_load_file(hProcess, name, load_offset, elf_info);
|
---|
1344 | HeapFree( GetProcessHeap(), 0, name );
|
---|
1345 | }
|
---|
1346 | return ret;
|
---|
1347 | }
|
---|
1348 |
|
---|
1349 | /******************************************************************
|
---|
1350 | * elf_search_and_load_file
|
---|
1351 | *
|
---|
1352 | * lookup a file in standard ELF locations, and if found, load it
|
---|
1353 | */
|
---|
1354 | static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename,
|
---|
1355 | unsigned long load_offset,
|
---|
1356 | struct elf_info* elf_info)
|
---|
1357 | {
|
---|
1358 | BOOL ret = FALSE;
|
---|
1359 | struct module* module;
|
---|
1360 | static WCHAR S_libstdcPPW[] = {'l','i','b','s','t','d','c','+','+','\0'};
|
---|
1361 |
|
---|
1362 | if (filename == NULL || *filename == '\0') return FALSE;
|
---|
1363 | if ((module = module_is_already_loaded(pcs, filename)))
|
---|
1364 | {
|
---|
1365 | elf_info->module = module;
|
---|
1366 | module->elf_info->elf_mark = 1;
|
---|
1367 | return module->module.SymType;
|
---|
1368 | }
|
---|
1369 |
|
---|
1370 | if (strstrW(filename, S_libstdcPPW)) return FALSE; /* We know we can't do it */
|
---|
1371 | ret = elf_load_file(pcs, filename, load_offset, elf_info);
|
---|
1372 | /* if relative pathname, try some absolute base dirs */
|
---|
1373 | if (!ret && !strchrW(filename, '/'))
|
---|
1374 | {
|
---|
1375 | ret = elf_load_file_from_path(pcs, filename, load_offset,
|
---|
1376 | getenv("PATH"), elf_info) ||
|
---|
1377 | elf_load_file_from_path(pcs, filename, load_offset,
|
---|
1378 | getenv("LD_LIBRARY_PATH"), elf_info);
|
---|
1379 | if (!ret) ret = elf_load_file_from_dll_path(pcs, filename, load_offset, elf_info);
|
---|
1380 | }
|
---|
1381 |
|
---|
1382 | return ret;
|
---|
1383 | }
|
---|
1384 |
|
---|
1385 | /******************************************************************
|
---|
1386 | * elf_enum_modules_internal
|
---|
1387 | *
|
---|
1388 | * Enumerate ELF modules from a running process
|
---|
1389 | */
|
---|
1390 | static BOOL elf_enum_modules_internal(const struct process* pcs,
|
---|
1391 | const WCHAR* main_name,
|
---|
1392 | elf_enum_modules_cb cb, void* user)
|
---|
1393 | {
|
---|
1394 | struct r_debug dbg_hdr;
|
---|
1395 | void* lm_addr;
|
---|
1396 | struct link_map lm;
|
---|
1397 | char bufstr[256];
|
---|
1398 | WCHAR bufstrW[MAX_PATH];
|
---|
1399 |
|
---|
1400 | if (!pcs->dbg_hdr_addr ||
|
---|
1401 | !ReadProcessMemory(pcs->handle, (void*)pcs->dbg_hdr_addr,
|
---|
1402 | &dbg_hdr, sizeof(dbg_hdr), NULL))
|
---|
1403 | return FALSE;
|
---|
1404 |
|
---|
1405 | /* Now walk the linked list. In all known ELF implementations,
|
---|
1406 | * the dynamic loader maintains this linked list for us. In some
|
---|
1407 | * cases the first entry doesn't appear with a name, in other cases it
|
---|
1408 | * does.
|
---|
1409 | */
|
---|
1410 | for (lm_addr = (void*)dbg_hdr.r_map; lm_addr; lm_addr = (void*)lm.l_next)
|
---|
1411 | {
|
---|
1412 | if (!ReadProcessMemory(pcs->handle, lm_addr, &lm, sizeof(lm), NULL))
|
---|
1413 | return FALSE;
|
---|
1414 |
|
---|
1415 | if (lm.l_prev != NULL && /* skip first entry, normally debuggee itself */
|
---|
1416 | lm.l_name != NULL &&
|
---|
1417 | ReadProcessMemory(pcs->handle, lm.l_name, bufstr, sizeof(bufstr), NULL))
|
---|
1418 | {
|
---|
1419 | bufstr[sizeof(bufstr) - 1] = '\0';
|
---|
1420 | MultiByteToWideChar(CP_UNIXCP, 0, bufstr, -1, bufstrW, sizeof(bufstrW) / sizeof(WCHAR));
|
---|
1421 | if (main_name && !bufstrW[0]) strcpyW(bufstrW, main_name);
|
---|
1422 | if (!cb(bufstrW, (unsigned long)lm.l_addr, user)) break;
|
---|
1423 | }
|
---|
1424 | }
|
---|
1425 | return TRUE;
|
---|
1426 | }
|
---|
1427 |
|
---|
1428 | struct elf_sync
|
---|
1429 | {
|
---|
1430 | struct process* pcs;
|
---|
1431 | struct elf_info elf_info;
|
---|
1432 | };
|
---|
1433 |
|
---|
1434 | static BOOL elf_enum_sync_cb(const WCHAR* name, unsigned long addr, void* user)
|
---|
1435 | {
|
---|
1436 | struct elf_sync* es = user;
|
---|
1437 |
|
---|
1438 | elf_search_and_load_file(es->pcs, name, addr, &es->elf_info);
|
---|
1439 | return TRUE;
|
---|
1440 | }
|
---|
1441 |
|
---|
1442 | /******************************************************************
|
---|
1443 | * elf_synchronize_module_list
|
---|
1444 | *
|
---|
1445 | * this functions rescans the debuggee module's list and synchronizes it with
|
---|
1446 | * the one from 'pcs', ie:
|
---|
1447 | * - if a module is in debuggee and not in pcs, it's loaded into pcs
|
---|
1448 | * - if a module is in pcs and not in debuggee, it's unloaded from pcs
|
---|
1449 | */
|
---|
1450 | BOOL elf_synchronize_module_list(struct process* pcs)
|
---|
1451 | {
|
---|
1452 | struct module* module;
|
---|
1453 | struct elf_sync es;
|
---|
1454 |
|
---|
1455 | for (module = pcs->lmodules; module; module = module->next)
|
---|
1456 | {
|
---|
1457 | if (module->type == DMT_ELF && !module->is_virtual)
|
---|
1458 | module->elf_info->elf_mark = 0;
|
---|
1459 | }
|
---|
1460 |
|
---|
1461 | es.pcs = pcs;
|
---|
1462 | es.elf_info.flags = ELF_INFO_MODULE;
|
---|
1463 | if (!elf_enum_modules_internal(pcs, NULL, elf_enum_sync_cb, &es))
|
---|
1464 | return FALSE;
|
---|
1465 |
|
---|
1466 | module = pcs->lmodules;
|
---|
1467 | while (module)
|
---|
1468 | {
|
---|
1469 | if (module->type == DMT_ELF && !module->is_virtual &&
|
---|
1470 | !module->elf_info->elf_mark && !module->elf_info->elf_loader)
|
---|
1471 | {
|
---|
1472 | module_remove(pcs, module);
|
---|
1473 | /* restart all over */
|
---|
1474 | module = pcs->lmodules;
|
---|
1475 | }
|
---|
1476 | else module = module->next;
|
---|
1477 | }
|
---|
1478 | return TRUE;
|
---|
1479 | }
|
---|
1480 |
|
---|
1481 | /******************************************************************
|
---|
1482 | * elf_search_loader
|
---|
1483 | *
|
---|
1484 | * Lookup in a running ELF process the loader, and sets its ELF link
|
---|
1485 | * address (for accessing the list of loaded .so libs) in pcs.
|
---|
1486 | * If flags is ELF_INFO_MODULE, the module for the loader is also
|
---|
1487 | * added as a module into pcs.
|
---|
1488 | */
|
---|
1489 | static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
|
---|
1490 | {
|
---|
1491 | BOOL ret;
|
---|
1492 | const char* ptr;
|
---|
1493 |
|
---|
1494 | /* All binaries are loaded with WINELOADER (if run from tree) or by the
|
---|
1495 | * main executable (either wine-kthread or wine-pthread)
|
---|
1496 | * FIXME: the heuristic used to know whether we need to load wine-pthread
|
---|
1497 | * or wine-kthread is not 100% safe
|
---|
1498 | */
|
---|
1499 | if ((ptr = getenv("WINELOADER")))
|
---|
1500 | {
|
---|
1501 | WCHAR tmp[MAX_PATH];
|
---|
1502 | MultiByteToWideChar(CP_ACP, 0, ptr, -1, tmp, sizeof(tmp) / sizeof(WCHAR));
|
---|
1503 | ret = elf_search_and_load_file(pcs, tmp, 0, elf_info);
|
---|
1504 | }
|
---|
1505 | else
|
---|
1506 | {
|
---|
1507 | ret = elf_search_and_load_file(pcs, S_WineKThreadW, 0, elf_info) ||
|
---|
1508 | elf_search_and_load_file(pcs, S_WinePThreadW, 0, elf_info);
|
---|
1509 | }
|
---|
1510 | return ret;
|
---|
1511 | }
|
---|
1512 |
|
---|
1513 | /******************************************************************
|
---|
1514 | * elf_read_wine_loader_dbg_info
|
---|
1515 | *
|
---|
1516 | * Try to find a decent wine executable which could have loaded the debuggee
|
---|
1517 | */
|
---|
1518 | BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
|
---|
1519 | {
|
---|
1520 | struct elf_info elf_info;
|
---|
1521 |
|
---|
1522 | elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_MODULE;
|
---|
1523 | if (!elf_search_loader(pcs, &elf_info)) return FALSE;
|
---|
1524 | elf_info.module->elf_info->elf_loader = 1;
|
---|
1525 | module_set_module(elf_info.module, S_WineLoaderW);
|
---|
1526 | return (pcs->dbg_hdr_addr = elf_info.dbg_hdr_addr) != 0;
|
---|
1527 | }
|
---|
1528 |
|
---|
1529 | /******************************************************************
|
---|
1530 | * elf_enum_modules
|
---|
1531 | *
|
---|
1532 | * Enumerates the ELF loaded modules from a running target (hProc)
|
---|
1533 | * This function doesn't require that someone has called SymInitialize
|
---|
1534 | * on this very process.
|
---|
1535 | */
|
---|
1536 | BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
|
---|
1537 | {
|
---|
1538 | struct process pcs;
|
---|
1539 | struct elf_info elf_info;
|
---|
1540 | BOOL ret;
|
---|
1541 |
|
---|
1542 | memset(&pcs, 0, sizeof(pcs));
|
---|
1543 | pcs.handle = hProc;
|
---|
1544 | elf_info.flags = ELF_INFO_DEBUG_HEADER | ELF_INFO_NAME;
|
---|
1545 | if (!elf_search_loader(&pcs, &elf_info)) return FALSE;
|
---|
1546 | pcs.dbg_hdr_addr = elf_info.dbg_hdr_addr;
|
---|
1547 | ret = elf_enum_modules_internal(&pcs, elf_info.module_name, cb, user);
|
---|
1548 | HeapFree(GetProcessHeap(), 0, (char*)elf_info.module_name);
|
---|
1549 | return ret;
|
---|
1550 | }
|
---|
1551 |
|
---|
1552 | struct elf_load
|
---|
1553 | {
|
---|
1554 | struct process* pcs;
|
---|
1555 | struct elf_info elf_info;
|
---|
1556 | const WCHAR* name;
|
---|
1557 | BOOL ret;
|
---|
1558 | };
|
---|
1559 |
|
---|
1560 | /******************************************************************
|
---|
1561 | * elf_load_cb
|
---|
1562 | *
|
---|
1563 | * Callback for elf_load_module, used to walk the list of loaded
|
---|
1564 | * modules.
|
---|
1565 | */
|
---|
1566 | static BOOL elf_load_cb(const WCHAR* name, unsigned long addr, void* user)
|
---|
1567 | {
|
---|
1568 | struct elf_load* el = user;
|
---|
1569 | const WCHAR* p;
|
---|
1570 |
|
---|
1571 | /* memcmp is needed for matches when bufstr contains also version information
|
---|
1572 | * el->name: libc.so, name: libc.so.6.0
|
---|
1573 | */
|
---|
1574 | p = strrchrW(name, '/');
|
---|
1575 | if (!p++) p = name;
|
---|
1576 | if (!memcmp(p, el->name, lstrlenW(el->name) * sizeof(WCHAR)))
|
---|
1577 | {
|
---|
1578 | el->ret = elf_search_and_load_file(el->pcs, name, addr, &el->elf_info);
|
---|
1579 | return FALSE;
|
---|
1580 | }
|
---|
1581 | return TRUE;
|
---|
1582 | }
|
---|
1583 |
|
---|
1584 | /******************************************************************
|
---|
1585 | * elf_load_module
|
---|
1586 | *
|
---|
1587 | * loads an ELF module and stores it in process' module list
|
---|
1588 | * Also, find module real name and load address from
|
---|
1589 | * the real loaded modules list in pcs address space
|
---|
1590 | */
|
---|
1591 | struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
|
---|
1592 | {
|
---|
1593 | struct elf_load el;
|
---|
1594 |
|
---|
1595 | TRACE("(%p %s %08lx)\n", pcs, debugstr_w(name), addr);
|
---|
1596 |
|
---|
1597 | el.elf_info.flags = ELF_INFO_MODULE;
|
---|
1598 | el.ret = FALSE;
|
---|
1599 |
|
---|
1600 | if (pcs->dbg_hdr_addr) /* we're debugging a life target */
|
---|
1601 | {
|
---|
1602 | el.pcs = pcs;
|
---|
1603 | /* do only the lookup from the filename, not the path (as we lookup module
|
---|
1604 | * name in the process' loaded module list)
|
---|
1605 | */
|
---|
1606 | el.name = strrchrW(name, '/');
|
---|
1607 | if (!el.name++) el.name = name;
|
---|
1608 | el.ret = FALSE;
|
---|
1609 |
|
---|
1610 | if (!elf_enum_modules_internal(pcs, NULL, elf_load_cb, &el))
|
---|
1611 | return NULL;
|
---|
1612 | }
|
---|
1613 | else if (addr)
|
---|
1614 | {
|
---|
1615 | el.name = name;
|
---|
1616 | el.ret = elf_search_and_load_file(pcs, el.name, addr, &el.elf_info);
|
---|
1617 | }
|
---|
1618 | if (!el.ret) return NULL;
|
---|
1619 | assert(el.elf_info.module);
|
---|
1620 | return el.elf_info.module;
|
---|
1621 | }
|
---|
1622 |
|
---|
1623 | #else /* !__ELF__ */
|
---|
1624 |
|
---|
1625 | BOOL elf_synchronize_module_list(struct process* pcs)
|
---|
1626 | {
|
---|
1627 | return FALSE;
|
---|
1628 | }
|
---|
1629 |
|
---|
1630 | BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
|
---|
1631 | DWORD* size, DWORD* checksum)
|
---|
1632 | {
|
---|
1633 | return FALSE;
|
---|
1634 | }
|
---|
1635 |
|
---|
1636 | BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
|
---|
1637 | {
|
---|
1638 | return FALSE;
|
---|
1639 | }
|
---|
1640 |
|
---|
1641 | BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
|
---|
1642 | {
|
---|
1643 | return FALSE;
|
---|
1644 | }
|
---|
1645 |
|
---|
1646 | struct module* elf_load_module(struct process* pcs, const WCHAR* name, unsigned long addr)
|
---|
1647 | {
|
---|
1648 | return NULL;
|
---|
1649 | }
|
---|
1650 |
|
---|
1651 | BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap)
|
---|
1652 | {
|
---|
1653 | return FALSE;
|
---|
1654 | }
|
---|
1655 |
|
---|
1656 | int elf_is_in_thunk_area(unsigned long addr,
|
---|
1657 | const struct elf_thunk_area* thunks)
|
---|
1658 | {
|
---|
1659 | return -1;
|
---|
1660 | }
|
---|
1661 | #endif /* __ELF__ */
|
---|