/[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 40 - (show annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 21236 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26