/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 21228 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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.1 2007/04/10 16:33:44 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