/[gxemul]/trunk/src/file/file_elf.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/file/file_elf.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 44 - (show annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 20993 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

1 /*
2 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: file_elf.c,v 1.7 2007/07/20 09:03:33 debug Exp $
29 *
30 * COMMENT: ELF file support
31 */
32
33 /* Note: Included from file.c. */
34
35
36 #include "exec_elf.h"
37
38 /* ELF machine types as strings: (same as exec_elf.h) */
39 #define N_ELF_MACHINE_TYPES 89
40 static char *elf_machine_type[N_ELF_MACHINE_TYPES] = {
41 "NONE", "M32", "SPARC", "386", /* 0..3 */
42 "68K", "88K", "486", "860", /* 4..7 */
43 "MIPS", "S370", "MIPS_RS3_LE", "RS6000", /* 8..11 */
44 "unknown12", "unknown13", "unknown14", "PARISC", /* 12..15 */
45 "NCUBE", "VPP500", "SPARC32PLUS", "960", /* 16..19 */
46 "PPC", "PPC64", "unknown22", "unknown23", /* 20..23 */
47 "unknown24", "unknown25", "unknown26", "unknown27", /* 24..27 */
48 "unknown28", "unknown29", "unknown30", "unknown31", /* 28..31 */
49 "unknown32", "unknown33", "unknown34", "unknown35", /* 32..35 */
50 "V800", "FR20", "RH32", "RCE", /* 36..39 */
51 "ARM", "ALPHA", "SH", "SPARCV9", /* 40..43 */
52 "TRICORE", "ARC", "H8_300", "H8_300H", /* 44..47 */
53 "H8S", "H8_500", "IA_64", "MIPS_X", /* 48..51 */
54 "COLDFIRE", "68HC12", "unknown54", "unknown55", /* 52..55 */
55 "unknown56", "unknown57", "unknown58", "unknown59", /* 56..59 */
56 "unknown60", "unknown61", "AMD64", "unknown63", /* 60..63 */
57 "unknown64", "unknown65", "unknown66", "unknown67", /* 64..67 */
58 "unknown68", "unknown69", "unknown70", "unknown71", /* 68..71 */
59 "unknown72", "unknown73", "unknown74", "unknown75", /* 72..75 */
60 "unknown76", "unknown77", "unknown78", "unknown79", /* 76..79 */
61 "unknown80", "unknown81", "unknown82", "AVR", /* 80..83 */
62 "unknown84", "unknown85", "unknown86", "unknown87", /* 84..87 */
63 "M32R" /* 88 */
64 };
65
66
67 /*
68 * file_load_elf():
69 *
70 * Loads an ELF image into the emulated memory. The entry point (read from
71 * the ELF header) and the initial value of the gp register (read from the
72 * ELF symbol table) are stored in the specified CPU's registers.
73 *
74 * This is pretty heavy stuff, but is needed because of the heaviness of
75 * ELF files. :-/ Hopefully it will be able to recognize most valid ELFs.
76 */
77 static void file_load_elf(struct machine *m, struct memory *mem,
78 char *filename, uint64_t *entrypointp, int arch, uint64_t *gpp,
79 int *byte_order, uint64_t *tocp)
80 {
81 Elf32_Ehdr hdr32;
82 Elf64_Ehdr hdr64;
83 FILE *f;
84 uint64_t eentry;
85 int len, i, ok;
86 int elf64, encoding, eflags;
87 int etype, emachine;
88 int ephnum, ephentsize, eshnum, eshentsize;
89 off_t ephoff, eshoff;
90 Elf32_Phdr phdr32;
91 Elf64_Phdr phdr64;
92 Elf32_Shdr shdr32;
93 Elf64_Shdr shdr64;
94 Elf32_Sym sym32;
95 Elf64_Sym sym64;
96 int ofs;
97 int chunk_len = 1024, align_len;
98 char *symbol_strings = NULL; size_t symbol_length = 0;
99 char *s;
100 Elf32_Sym *symbols_sym32 = NULL; int n_symbols = 0;
101 Elf64_Sym *symbols_sym64 = NULL;
102
103 f = fopen(filename, "r");
104 if (f == NULL) {
105 perror(filename);
106 exit(1);
107 }
108
109 len = fread(&hdr32, 1, sizeof(Elf32_Ehdr), f);
110 if (len < (signed int)sizeof(Elf32_Ehdr)) {
111 fprintf(stderr, "%s: not an ELF file image\n", filename);
112 exit(1);
113 }
114
115 if (memcmp(&hdr32.e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0) {
116 fprintf(stderr, "%s: not an ELF file image\n", filename);
117 exit(1);
118 }
119
120 switch (hdr32.e_ident[EI_CLASS]) {
121 case ELFCLASS32:
122 elf64 = 0;
123 break;
124 case ELFCLASS64:
125 elf64 = 1;
126 fseek(f, 0, SEEK_SET);
127 len = fread(&hdr64, 1, sizeof(Elf64_Ehdr), f);
128 if (len < (signed int)sizeof(Elf64_Ehdr)) {
129 fprintf(stderr, "%s: not an ELF64 file image\n",
130 filename);
131 exit(1);
132 }
133 break;
134 default:
135 fprintf(stderr, "%s: unknown ELF class '%i'\n",
136 filename, hdr32.e_ident[EI_CLASS]);
137 exit(1);
138 }
139
140 encoding = hdr32.e_ident[EI_DATA];
141 if (encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) {
142 fprintf(stderr, "%s: unknown data encoding '%i'\n",
143 filename, hdr32.e_ident[EI_DATA]);
144 exit(1);
145 }
146
147 if (elf64) {
148 unencode(etype, &hdr64.e_type, Elf64_Quarter);
149 unencode(eflags, &hdr64.e_flags, Elf64_Half);
150 unencode(emachine, &hdr64.e_machine, Elf64_Quarter);
151 unencode(eentry, &hdr64.e_entry, Elf64_Addr);
152 unencode(ephnum, &hdr64.e_phnum, Elf64_Quarter);
153 unencode(ephentsize, &hdr64.e_phentsize, Elf64_Quarter);
154 unencode(ephoff, &hdr64.e_phoff, Elf64_Off);
155 unencode(eshnum, &hdr64.e_shnum, Elf64_Quarter);
156 unencode(eshentsize, &hdr64.e_shentsize, Elf64_Quarter);
157 unencode(eshoff, &hdr64.e_shoff, Elf64_Off);
158 if (ephentsize != sizeof(Elf64_Phdr)) {
159 fprintf(stderr, "%s: incorrect phentsize? %i, should "
160 "be %i\nPerhaps this is a dynamically linked "
161 "binary (which isn't supported yet).\n", filename,
162 (int)ephentsize, (int)sizeof(Elf64_Phdr));
163 exit(1);
164 }
165 if (eshentsize != sizeof(Elf64_Shdr)) {
166 fprintf(stderr, "%s: incorrect shentsize? %i, should "
167 "be %i\nPerhaps this is a dynamically linked "
168 "binary (which isn't supported yet).\n", filename,
169 (int)eshentsize, (int)sizeof(Elf64_Shdr));
170 exit(1);
171 }
172 } else {
173 unencode(etype, &hdr32.e_type, Elf32_Half);
174 unencode(eflags, &hdr32.e_flags, Elf32_Word);
175 unencode(emachine, &hdr32.e_machine, Elf32_Half);
176 unencode(eentry, &hdr32.e_entry, Elf32_Addr);
177 unencode(ephnum, &hdr32.e_phnum, Elf32_Half);
178 unencode(ephentsize, &hdr32.e_phentsize, Elf32_Half);
179 unencode(ephoff, &hdr32.e_phoff, Elf32_Off);
180 unencode(eshnum, &hdr32.e_shnum, Elf32_Half);
181 unencode(eshentsize, &hdr32.e_shentsize, Elf32_Half);
182 unencode(eshoff, &hdr32.e_shoff, Elf32_Off);
183 if (ephentsize != sizeof(Elf32_Phdr)) {
184 fprintf(stderr, "%s: incorrect phentsize? %i, should "
185 "be %i\nPerhaps this is a dynamically linked "
186 "binary (which isn't supported yet).\n", filename,
187 (int)ephentsize, (int)sizeof(Elf32_Phdr));
188 exit(1);
189 }
190 if (eshentsize != sizeof(Elf32_Shdr)) {
191 fprintf(stderr, "%s: incorrect shentsize? %i, should "
192 "be %i\nPerhaps this is a dynamically linked "
193 "binary (which isn't supported yet).\n", filename,
194 (int)eshentsize, (int)sizeof(Elf32_Shdr));
195 exit(1);
196 }
197 }
198
199 if ( etype != ET_EXEC ) {
200 fprintf(stderr, "%s is not an ELF Executable file, type = %i\n",
201 filename, etype);
202 exit(1);
203 }
204
205 ok = 0;
206 switch (arch) {
207 case ARCH_ALPHA:
208 switch (emachine) {
209 case EM_ALPHA:
210 case -28634:
211 ok = 1;
212 }
213 break;
214 case ARCH_ARM:
215 switch (emachine) {
216 case EM_ARM:
217 ok = 1;
218 }
219 break;
220 /* case ARCH_AVR:
221 switch (emachine) {
222 case EM_AVR:
223 ok = 1;
224 }
225 break;
226 case ARCH_AVR32:
227 switch (emachine) {
228 case 6317:
229 ok = 1;
230 }
231 break;
232 case ARCH_HPPA:
233 switch (emachine) {
234 case EM_PARISC:
235 ok = 1;
236 }
237 break;
238 case ARCH_I960:
239 switch (emachine) {
240 case EM_960:
241 ok = 1;
242 }
243 break;
244 case ARCH_IA64:
245 switch (emachine) {
246 case EM_IA_64:
247 ok = 1;
248 }
249 break;
250 case ARCH_M68K:
251 switch (emachine) {
252 case EM_68K:
253 ok = 1;
254 }
255 break; */
256 case ARCH_M32R:
257 switch (emachine) {
258 case EM_M32R:
259 ok = 1;
260 }
261 break;
262 case ARCH_MIPS:
263 switch (emachine) {
264 case EM_MIPS:
265 case EM_MIPS_RS3_LE:
266 ok = 1;
267 }
268 break;
269 case ARCH_PPC:
270 switch (emachine) {
271 case EM_PPC:
272 case EM_PPC64:
273 ok = 1;
274 }
275 break;
276 case ARCH_SH:
277 switch (emachine) {
278 case EM_SH:
279 ok = 1;
280 }
281 break;
282 case ARCH_SPARC:
283 switch (emachine) {
284 case EM_SPARC:
285 case EM_SPARCV9:
286 ok = 1;
287 }
288 break;
289 /* case ARCH_X86:
290 switch (emachine) {
291 case EM_386:
292 case EM_486:
293 *tocp = 1;
294 ok = 1;
295 break;
296 case EM_AMD64:
297 *tocp = 2;
298 ok = 1;
299 break;
300 }
301 break; */
302 default:
303 fatal("file.c: INTERNAL ERROR: Unimplemented arch!\n");
304 }
305 if (!ok) {
306 fprintf(stderr, "%s: this is a ", filename);
307 if (emachine >= 0 && emachine < N_ELF_MACHINE_TYPES)
308 fprintf(stderr, elf_machine_type[emachine]);
309 else
310 fprintf(stderr, "machine type '%i'", emachine);
311 fprintf(stderr, " ELF binary!\n");
312 exit(1);
313 }
314
315 s = "entry point";
316 if (elf64 && arch == ARCH_PPC)
317 s = "function descriptor at";
318
319 debug("ELF%i %s, %s 0x", elf64? 64 : 32,
320 encoding == ELFDATA2LSB? "LSB (LE)" : "MSB (BE)", s);
321
322 if (elf64)
323 debug("%016"PRIx64"\n", (uint64_t) eentry);
324 else
325 debug("%08"PRIx32"\n", (uint32_t) eentry);
326
327 /*
328 * SH64: 32-bit instruction encoding?
329 */
330 if (arch == ARCH_SH && (eentry & 1)) {
331 fatal("SH64: 32-bit instruction encoding: TODO\n");
332 /* m->cpus[0]->cd.sh.compact = 0; */
333 m->cpus[0]->cd.sh.cpu_type.bits = 64;
334 exit(1);
335 }
336
337 /* Read the program headers: */
338
339 for (i=0; i<ephnum; i++) {
340 int p_type;
341 uint64_t p_offset;
342 uint64_t p_vaddr;
343 uint64_t p_paddr;
344 uint64_t p_filesz;
345 uint64_t p_memsz;
346 int p_flags;
347 int p_align;
348
349 fseek(f, ephoff + i * ephentsize, SEEK_SET);
350
351 if (elf64) {
352 fread(&phdr64, 1, sizeof(Elf64_Phdr), f);
353 unencode(p_type, &phdr64.p_type, Elf64_Half);
354 unencode(p_flags, &phdr64.p_flags, Elf64_Half);
355 unencode(p_offset, &phdr64.p_offset, Elf64_Off);
356 unencode(p_vaddr, &phdr64.p_vaddr, Elf64_Addr);
357 unencode(p_paddr, &phdr64.p_paddr, Elf64_Addr);
358 unencode(p_filesz, &phdr64.p_filesz, Elf64_Xword);
359 unencode(p_memsz, &phdr64.p_memsz, Elf64_Xword);
360 unencode(p_align, &phdr64.p_align, Elf64_Xword);
361 } else {
362 fread(&phdr32, 1, sizeof(Elf32_Phdr), f);
363 unencode(p_type, &phdr32.p_type, Elf32_Word);
364 unencode(p_offset, &phdr32.p_offset, Elf32_Off);
365 unencode(p_vaddr, &phdr32.p_vaddr, Elf32_Addr);
366 unencode(p_paddr, &phdr32.p_paddr, Elf32_Addr);
367 unencode(p_filesz, &phdr32.p_filesz, Elf32_Word);
368 unencode(p_memsz, &phdr32.p_memsz, Elf32_Word);
369 unencode(p_flags, &phdr32.p_flags, Elf32_Word);
370 unencode(p_align, &phdr32.p_align, Elf32_Word);
371 }
372
373 /*
374 * Hack for loading PPC kernels that are linked to high
375 * addresses. (This requires enabling of instruction and
376 * data virtual address translation.)
377 */
378 if (arch == ARCH_PPC) {
379 if ( (elf64 && (p_vaddr >> 60) != 0) ||
380 (!elf64 && (p_vaddr >> 28) != 0) )
381 m->cpus[m->bootstrap_cpu]->
382 cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR;
383 }
384
385 if (p_memsz != 0 && (p_type == PT_LOAD ||
386 (p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) {
387 debug("chunk %i (", i);
388 if (p_type == PT_LOAD)
389 debug("load");
390 else
391 debug("0x%08"PRIx32, (uint32_t) p_type);
392
393 debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset);
394
395 if (elf64)
396 debug("%016"PRIx64, (uint64_t) p_vaddr);
397 else
398 debug("%08"PRIx32, (uint32_t) p_vaddr);
399
400 debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz);
401
402 if (p_vaddr != p_paddr) {
403 if (elf64)
404 debug("NOTE: vaddr (0x%"PRIx64") and "
405 "paddr (0x%"PRIx64") differ; using "
406 "vaddr\n", (uint64_t) p_vaddr,
407 (uint64_t) p_paddr);
408 else
409 debug("NOTE: vaddr (0x%08"PRIx32") and "
410 "paddr (0x%08"PRIx32") differ; usin"
411 "g vaddr\n", (uint32_t) p_vaddr,
412 (uint32_t)p_paddr);
413 }
414
415 if (p_memsz < p_filesz) {
416 fprintf(stderr, "%s: memsz < filesz. TODO: how"
417 " to handle this? memsz=%016"PRIx64
418 " filesz=%016"PRIx64"\n", filename,
419 (uint64_t) p_memsz, (uint64_t) p_filesz);
420 exit(1);
421 }
422
423 fseek(f, p_offset, SEEK_SET);
424 align_len = 1;
425 if ((p_vaddr & 0xf)==0) align_len = 0x10;
426 if ((p_vaddr & 0x3f)==0) align_len = 0x40;
427 if ((p_vaddr & 0xff)==0) align_len = 0x100;
428 if ((p_vaddr & 0xfff)==0) align_len = 0x1000;
429 if ((p_vaddr & 0x3fff)==0) align_len = 0x4000;
430 if ((p_vaddr & 0xffff)==0) align_len = 0x10000;
431 ofs = 0; len = chunk_len = align_len;
432 while (ofs < (int64_t)p_filesz && len==chunk_len) {
433 unsigned char *ch;
434 int i = 0;
435
436 CHECK_ALLOCATION(ch = malloc(chunk_len));
437
438 /* Switch to larger size, if possible: */
439 if (align_len < 0x10000 &&
440 ((p_vaddr + ofs) & 0xffff)==0) {
441 align_len = 0x10000;
442 len = chunk_len = align_len;
443 free(ch);
444 CHECK_ALLOCATION(ch=malloc(chunk_len));
445 } else if (align_len < 0x1000 &&
446 ((p_vaddr + ofs) & 0xfff)==0) {
447 align_len = 0x1000;
448 len = chunk_len = align_len;
449 free(ch);
450 CHECK_ALLOCATION(ch=malloc(chunk_len));
451 }
452
453 len = fread(&ch[0], 1, chunk_len, f);
454 if (ofs + len > (int64_t)p_filesz)
455 len = p_filesz - ofs;
456
457 while (i < len) {
458 size_t len_to_copy;
459 len_to_copy = (i + align_len) <= len?
460 align_len : len - i;
461 m->cpus[0]->memory_rw(m->cpus[0], mem,
462 p_vaddr + ofs, &ch[i], len_to_copy,
463 MEM_WRITE, NO_EXCEPTIONS);
464 ofs += align_len;
465 i += align_len;
466 }
467
468 free(ch);
469 }
470 }
471 }
472
473 /*
474 * Read the section headers to find the address of the _gp
475 * symbol (for MIPS):
476 */
477
478 for (i=0; i<eshnum; i++) {
479 int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize;
480 uint64_t sh_addr, sh_size, sh_addralign;
481 off_t sh_offset;
482 int n_entries; /* for reading the symbol / string tables */
483
484 /* debug("section header %i at %016"PRIx64"\n", i,
485 (uint64_t) eshoff+i*eshentsize); */
486
487 fseek(f, eshoff + i * eshentsize, SEEK_SET);
488
489 if (elf64) {
490 len = fread(&shdr64, 1, sizeof(Elf64_Shdr), f);
491 if (len != sizeof(Elf64_Shdr)) {
492 fprintf(stderr, "couldn't read header\n");
493 exit(1);
494 }
495 unencode(sh_name, &shdr64.sh_name, Elf64_Half);
496 unencode(sh_type, &shdr64.sh_type, Elf64_Half);
497 unencode(sh_flags, &shdr64.sh_flags, Elf64_Xword);
498 unencode(sh_addr, &shdr64.sh_addr, Elf64_Addr);
499 unencode(sh_offset, &shdr64.sh_offset, Elf64_Off);
500 unencode(sh_size, &shdr64.sh_size, Elf64_Xword);
501 unencode(sh_link, &shdr64.sh_link, Elf64_Half);
502 unencode(sh_info, &shdr64.sh_info, Elf64_Half);
503 unencode(sh_addralign, &shdr64.sh_addralign,
504 Elf64_Xword);
505 unencode(sh_entsize, &shdr64.sh_entsize, Elf64_Xword);
506 } else {
507 len = fread(&shdr32, 1, sizeof(Elf32_Shdr), f);
508 if (len != sizeof(Elf32_Shdr)) {
509 fprintf(stderr, "couldn't read header\n");
510 exit(1);
511 }
512 unencode(sh_name, &shdr32.sh_name, Elf32_Word);
513 unencode(sh_type, &shdr32.sh_type, Elf32_Word);
514 unencode(sh_flags, &shdr32.sh_flags, Elf32_Word);
515 unencode(sh_addr, &shdr32.sh_addr, Elf32_Addr);
516 unencode(sh_offset, &shdr32.sh_offset, Elf32_Off);
517 unencode(sh_size, &shdr32.sh_size, Elf32_Word);
518 unencode(sh_link, &shdr32.sh_link, Elf32_Word);
519 unencode(sh_info, &shdr32.sh_info, Elf32_Word);
520 unencode(sh_addralign, &shdr32.sh_addralign,Elf32_Word);
521 unencode(sh_entsize, &shdr32.sh_entsize, Elf32_Word);
522 }
523
524 /* debug("sh_name=%04lx, sh_type=%08lx, sh_flags=%08lx"
525 " sh_size=%06lx sh_entsize=%03lx\n",
526 (long)sh_name, (long)sh_type, (long)sh_flags,
527 (long)sh_size, (long)sh_entsize); */
528
529 /* Perhaps it is bad to reuse sh_entsize like this? TODO */
530 if (elf64)
531 sh_entsize = sizeof(Elf64_Sym);
532 else
533 sh_entsize = sizeof(Elf32_Sym);
534
535 if (sh_type == SHT_SYMTAB) {
536 size_t len;
537 n_entries = sh_size / sh_entsize;
538
539 fseek(f, sh_offset, SEEK_SET);
540
541 if (elf64) {
542 if (symbols_sym64 != NULL)
543 free(symbols_sym64);
544
545 CHECK_ALLOCATION(symbols_sym64 =
546 malloc(sh_size));
547
548 len = fread(symbols_sym64, 1, sh_entsize *
549 n_entries, f);
550 } else {
551 if (symbols_sym32 != NULL)
552 free(symbols_sym32);
553
554 CHECK_ALLOCATION(symbols_sym32 =
555 malloc(sh_size));
556
557 len = fread(symbols_sym32, 1,
558 sh_entsize * n_entries, f);
559 }
560
561 if (len != sh_size) {
562 fprintf(stderr, "could not read symbols from "
563 "%s\n", filename);
564 exit(1);
565 }
566
567 debug("%i symbol entries at 0x%"PRIx64"\n",
568 (int) n_entries, (uint64_t) sh_offset);
569
570 n_symbols = n_entries;
571 }
572
573 /*
574 * TODO: This is incorrect, there may be several strtab
575 * sections.
576 *
577 * For now, the simple/stupid guess that the largest string
578 * table is the one to use seems to be good enough.
579 */
580
581 if (sh_type == SHT_STRTAB && sh_size > symbol_length) {
582 size_t len;
583
584 if (symbol_strings != NULL)
585 free(symbol_strings);
586
587 CHECK_ALLOCATION(symbol_strings = malloc(sh_size + 1));
588
589 fseek(f, sh_offset, SEEK_SET);
590 len = fread(symbol_strings, 1, sh_size, f);
591 if (len != sh_size) {
592 fprintf(stderr, "could not read symbols from "
593 "%s\n", filename);
594 exit(1);
595 }
596
597 debug("%i bytes of symbol strings at 0x%"PRIx64"\n",
598 (int) sh_size, (uint64_t) sh_offset);
599
600 symbol_strings[sh_size] = '\0';
601 symbol_length = sh_size;
602 }
603 }
604
605 fclose(f);
606
607 /* Decode symbols: */
608 if (symbol_strings != NULL) {
609 for (i=0; i<n_symbols; i++) {
610 uint64_t st_name, addr, size;
611 int st_info;
612
613 if (elf64) {
614 sym64 = symbols_sym64[i];
615 unencode(st_name, &sym64.st_name, Elf64_Half);
616 unencode(st_info, &sym64.st_info, Elf_Byte);
617 unencode(addr, &sym64.st_value, Elf64_Addr);
618 unencode(size, &sym64.st_size, Elf64_Xword);
619 } else {
620 sym32 = symbols_sym32[i];
621 unencode(st_name, &sym32.st_name, Elf32_Word);
622 unencode(st_info, &sym32.st_info, Elf_Byte);
623 unencode(addr, &sym32.st_value, Elf32_Word);
624 unencode(size, &sym32.st_size, Elf32_Word);
625 }
626
627 /* debug("symbol info=0x%02x addr=0x%016"PRIx64
628 " (%i) '%s'\n", st_info, (uint64_t) addr,
629 st_name, symbol_strings + st_name); */
630
631 if (size == 0)
632 size ++;
633
634 if (addr != 0) /* && ((st_info >> 4) & 0xf)
635 >= STB_GLOBAL) */ {
636 /* debug("symbol info=0x%02x addr=0x%016"PRIx64
637 " '%s'\n", st_info, (uint64_t) addr,
638 symbol_strings + st_name); */
639 add_symbol_name(&m->symbol_context,
640 addr, size, symbol_strings + st_name,
641 0, -1);
642 }
643
644 if (strcmp(symbol_strings + st_name, "_gp") == 0) {
645 debug("found _gp address: 0x");
646 if (elf64)
647 debug("%016"PRIx64"\n", (uint64_t)addr);
648 else
649 debug("%08"PRIx32"\n", (uint32_t)addr);
650 *gpp = addr;
651 }
652 }
653 }
654
655 *entrypointp = eentry;
656
657 if (encoding == ELFDATA2LSB)
658 *byte_order = EMUL_LITTLE_ENDIAN;
659 else
660 *byte_order = EMUL_BIG_ENDIAN;
661
662 if (elf64 && arch == ARCH_PPC) {
663 /*
664 * Special case for 64-bit PPC ELFs:
665 *
666 * The ELF starting symbol points to a ".opd" section
667 * which contains a function descriptor:
668 *
669 * uint64_t start;
670 * uint64_t toc_base;
671 * uint64_t something_else; (?)
672 */
673 int res;
674 unsigned char b[sizeof(uint64_t)];
675 uint64_t toc_base;
676
677 debug("PPC64: ");
678
679 res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b,
680 sizeof(b), MEM_READ, NO_EXCEPTIONS);
681 if (!res)
682 debug(" [WARNING: could not read memory?] ");
683
684 /* PPC are always big-endian: */
685 *entrypointp = ((uint64_t)b[0] << 56) +
686 ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
687 ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
688 ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
689 (uint64_t)b[7];
690
691 res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8,
692 b, sizeof(b), MEM_READ, NO_EXCEPTIONS);
693 if (!res)
694 fatal(" [WARNING: could not read memory?] ");
695
696 toc_base = ((uint64_t)b[0] << 56) +
697 ((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) +
698 ((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) +
699 ((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) +
700 (uint64_t)b[7];
701
702 debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n",
703 (uint64_t) *entrypointp, (uint64_t) toc_base);
704 if (tocp != NULL)
705 *tocp = toc_base;
706 }
707
708 n_executables_loaded ++;
709 }
710

  ViewVC Help
Powered by ViewVC 1.1.26