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 |
// XXX force load address to 0 |
323 |
eentry -= 0xc0000000; |
324 |
|
325 |
if (elf64) |
326 |
debug("%016"PRIx64"\n", (uint64_t) eentry); |
327 |
else |
328 |
debug("%08"PRIx32"\n", (uint32_t) eentry); |
329 |
|
330 |
/* |
331 |
* SH64: 32-bit instruction encoding? |
332 |
*/ |
333 |
if (arch == ARCH_SH && (eentry & 1)) { |
334 |
fatal("SH64: 32-bit instruction encoding: TODO\n"); |
335 |
/* m->cpus[0]->cd.sh.compact = 0; */ |
336 |
m->cpus[0]->cd.sh.cpu_type.bits = 64; |
337 |
exit(1); |
338 |
} |
339 |
|
340 |
/* Read the program headers: */ |
341 |
|
342 |
for (i=0; i<ephnum; i++) { |
343 |
int p_type; |
344 |
uint64_t p_offset; |
345 |
uint64_t p_vaddr; |
346 |
uint64_t p_paddr; |
347 |
uint64_t p_filesz; |
348 |
uint64_t p_memsz; |
349 |
int p_flags; |
350 |
int p_align; |
351 |
|
352 |
fseek(f, ephoff + i * ephentsize, SEEK_SET); |
353 |
|
354 |
if (elf64) { |
355 |
fread(&phdr64, 1, sizeof(Elf64_Phdr), f); |
356 |
unencode(p_type, &phdr64.p_type, Elf64_Half); |
357 |
unencode(p_flags, &phdr64.p_flags, Elf64_Half); |
358 |
unencode(p_offset, &phdr64.p_offset, Elf64_Off); |
359 |
unencode(p_vaddr, &phdr64.p_vaddr, Elf64_Addr); |
360 |
unencode(p_paddr, &phdr64.p_paddr, Elf64_Addr); |
361 |
unencode(p_filesz, &phdr64.p_filesz, Elf64_Xword); |
362 |
unencode(p_memsz, &phdr64.p_memsz, Elf64_Xword); |
363 |
unencode(p_align, &phdr64.p_align, Elf64_Xword); |
364 |
} else { |
365 |
fread(&phdr32, 1, sizeof(Elf32_Phdr), f); |
366 |
unencode(p_type, &phdr32.p_type, Elf32_Word); |
367 |
unencode(p_offset, &phdr32.p_offset, Elf32_Off); |
368 |
unencode(p_vaddr, &phdr32.p_vaddr, Elf32_Addr); |
369 |
unencode(p_paddr, &phdr32.p_paddr, Elf32_Addr); |
370 |
unencode(p_filesz, &phdr32.p_filesz, Elf32_Word); |
371 |
unencode(p_memsz, &phdr32.p_memsz, Elf32_Word); |
372 |
unencode(p_flags, &phdr32.p_flags, Elf32_Word); |
373 |
unencode(p_align, &phdr32.p_align, Elf32_Word); |
374 |
} |
375 |
|
376 |
/* |
377 |
* Hack for loading PPC kernels that are linked to high |
378 |
* addresses. (This requires enabling of instruction and |
379 |
* data virtual address translation.) |
380 |
*/ |
381 |
if (arch == ARCH_PPC) { |
382 |
if ( (elf64 && (p_vaddr >> 60) != 0) || |
383 |
(!elf64 && (p_vaddr >> 28) != 0) ) |
384 |
m->cpus[m->bootstrap_cpu]-> |
385 |
cd.ppc.msr |= PPC_MSR_IR | PPC_MSR_DR; |
386 |
} |
387 |
|
388 |
if (p_memsz != 0 && (p_type == PT_LOAD || |
389 |
(p_type & PF_MASKPROC) == PT_MIPS_REGINFO)) { |
390 |
debug("chunk %i (", i); |
391 |
if (p_type == PT_LOAD) |
392 |
debug("load"); |
393 |
else |
394 |
debug("0x%08"PRIx32, (uint32_t) p_type); |
395 |
|
396 |
debug(") @ 0x%"PRIx64", vaddr 0x", (uint64_t) p_offset); |
397 |
|
398 |
if (elf64) |
399 |
debug("%016"PRIx64, (uint64_t) p_vaddr); |
400 |
else |
401 |
debug("%08"PRIx32, (uint32_t) p_vaddr); |
402 |
|
403 |
debug(" len=0x%"PRIx64"\n", (uint64_t) p_memsz); |
404 |
|
405 |
if (p_vaddr != p_paddr) { |
406 |
if (elf64) |
407 |
debug("NOTE: vaddr (0x%"PRIx64") and " |
408 |
"paddr (0x%"PRIx64") differ; using " |
409 |
"vaddr\n", (uint64_t) p_vaddr, |
410 |
(uint64_t) p_paddr); |
411 |
else |
412 |
debug("NOTE: vaddr (0x%08"PRIx32") and " |
413 |
"paddr (0x%08"PRIx32") differ; usin" |
414 |
"g vaddr\n", (uint32_t) p_vaddr, |
415 |
(uint32_t)p_paddr); |
416 |
} |
417 |
|
418 |
if (p_memsz < p_filesz) { |
419 |
fprintf(stderr, "%s: memsz < filesz. TODO: how" |
420 |
" to handle this? memsz=%016"PRIx64 |
421 |
" filesz=%016"PRIx64"\n", filename, |
422 |
(uint64_t) p_memsz, (uint64_t) p_filesz); |
423 |
exit(1); |
424 |
} |
425 |
|
426 |
fseek(f, p_offset, SEEK_SET); |
427 |
align_len = 1; |
428 |
if ((p_vaddr & 0xf)==0) align_len = 0x10; |
429 |
if ((p_vaddr & 0x3f)==0) align_len = 0x40; |
430 |
if ((p_vaddr & 0xff)==0) align_len = 0x100; |
431 |
if ((p_vaddr & 0xfff)==0) align_len = 0x1000; |
432 |
if ((p_vaddr & 0x3fff)==0) align_len = 0x4000; |
433 |
if ((p_vaddr & 0xffff)==0) align_len = 0x10000; |
434 |
ofs = 0; len = chunk_len = align_len; |
435 |
while (ofs < (int64_t)p_filesz && len==chunk_len) { |
436 |
unsigned char *ch; |
437 |
int i = 0; |
438 |
|
439 |
CHECK_ALLOCATION(ch = malloc(chunk_len)); |
440 |
|
441 |
/* Switch to larger size, if possible: */ |
442 |
if (align_len < 0x10000 && |
443 |
((p_vaddr + ofs) & 0xffff)==0) { |
444 |
align_len = 0x10000; |
445 |
len = chunk_len = align_len; |
446 |
free(ch); |
447 |
CHECK_ALLOCATION(ch=malloc(chunk_len)); |
448 |
} else if (align_len < 0x1000 && |
449 |
((p_vaddr + ofs) & 0xfff)==0) { |
450 |
align_len = 0x1000; |
451 |
len = chunk_len = align_len; |
452 |
free(ch); |
453 |
CHECK_ALLOCATION(ch=malloc(chunk_len)); |
454 |
} |
455 |
|
456 |
len = fread(&ch[0], 1, chunk_len, f); |
457 |
if (ofs + len > (int64_t)p_filesz) |
458 |
len = p_filesz - ofs; |
459 |
|
460 |
while (i < len) { |
461 |
size_t len_to_copy; |
462 |
len_to_copy = (i + align_len) <= len? |
463 |
align_len : len - i; |
464 |
m->cpus[0]->memory_rw(m->cpus[0], mem, |
465 |
p_vaddr + ofs, &ch[i], len_to_copy, |
466 |
MEM_WRITE, NO_EXCEPTIONS); |
467 |
ofs += align_len; |
468 |
i += align_len; |
469 |
} |
470 |
|
471 |
free(ch); |
472 |
} |
473 |
} |
474 |
} |
475 |
|
476 |
/* |
477 |
* Read the section headers to find the address of the _gp |
478 |
* symbol (for MIPS): |
479 |
*/ |
480 |
|
481 |
for (i=0; i<eshnum; i++) { |
482 |
int sh_name, sh_type, sh_flags, sh_link, sh_info, sh_entsize; |
483 |
uint64_t sh_addr, sh_size, sh_addralign; |
484 |
off_t sh_offset; |
485 |
int n_entries; /* for reading the symbol / string tables */ |
486 |
|
487 |
/* debug("section header %i at %016"PRIx64"\n", i, |
488 |
(uint64_t) eshoff+i*eshentsize); */ |
489 |
|
490 |
fseek(f, eshoff + i * eshentsize, SEEK_SET); |
491 |
|
492 |
if (elf64) { |
493 |
len = fread(&shdr64, 1, sizeof(Elf64_Shdr), f); |
494 |
if (len != sizeof(Elf64_Shdr)) { |
495 |
fprintf(stderr, "couldn't read header\n"); |
496 |
exit(1); |
497 |
} |
498 |
unencode(sh_name, &shdr64.sh_name, Elf64_Half); |
499 |
unencode(sh_type, &shdr64.sh_type, Elf64_Half); |
500 |
unencode(sh_flags, &shdr64.sh_flags, Elf64_Xword); |
501 |
unencode(sh_addr, &shdr64.sh_addr, Elf64_Addr); |
502 |
unencode(sh_offset, &shdr64.sh_offset, Elf64_Off); |
503 |
unencode(sh_size, &shdr64.sh_size, Elf64_Xword); |
504 |
unencode(sh_link, &shdr64.sh_link, Elf64_Half); |
505 |
unencode(sh_info, &shdr64.sh_info, Elf64_Half); |
506 |
unencode(sh_addralign, &shdr64.sh_addralign, |
507 |
Elf64_Xword); |
508 |
unencode(sh_entsize, &shdr64.sh_entsize, Elf64_Xword); |
509 |
} else { |
510 |
len = fread(&shdr32, 1, sizeof(Elf32_Shdr), f); |
511 |
if (len != sizeof(Elf32_Shdr)) { |
512 |
fprintf(stderr, "couldn't read header\n"); |
513 |
exit(1); |
514 |
} |
515 |
unencode(sh_name, &shdr32.sh_name, Elf32_Word); |
516 |
unencode(sh_type, &shdr32.sh_type, Elf32_Word); |
517 |
unencode(sh_flags, &shdr32.sh_flags, Elf32_Word); |
518 |
unencode(sh_addr, &shdr32.sh_addr, Elf32_Addr); |
519 |
unencode(sh_offset, &shdr32.sh_offset, Elf32_Off); |
520 |
unencode(sh_size, &shdr32.sh_size, Elf32_Word); |
521 |
unencode(sh_link, &shdr32.sh_link, Elf32_Word); |
522 |
unencode(sh_info, &shdr32.sh_info, Elf32_Word); |
523 |
unencode(sh_addralign, &shdr32.sh_addralign,Elf32_Word); |
524 |
unencode(sh_entsize, &shdr32.sh_entsize, Elf32_Word); |
525 |
} |
526 |
|
527 |
/* debug("sh_name=%04lx, sh_type=%08lx, sh_flags=%08lx" |
528 |
" sh_size=%06lx sh_entsize=%03lx\n", |
529 |
(long)sh_name, (long)sh_type, (long)sh_flags, |
530 |
(long)sh_size, (long)sh_entsize); */ |
531 |
|
532 |
/* Perhaps it is bad to reuse sh_entsize like this? TODO */ |
533 |
if (elf64) |
534 |
sh_entsize = sizeof(Elf64_Sym); |
535 |
else |
536 |
sh_entsize = sizeof(Elf32_Sym); |
537 |
|
538 |
if (sh_type == SHT_SYMTAB) { |
539 |
size_t len; |
540 |
n_entries = sh_size / sh_entsize; |
541 |
|
542 |
fseek(f, sh_offset, SEEK_SET); |
543 |
|
544 |
if (elf64) { |
545 |
if (symbols_sym64 != NULL) |
546 |
free(symbols_sym64); |
547 |
|
548 |
CHECK_ALLOCATION(symbols_sym64 = |
549 |
malloc(sh_size)); |
550 |
|
551 |
len = fread(symbols_sym64, 1, sh_entsize * |
552 |
n_entries, f); |
553 |
} else { |
554 |
if (symbols_sym32 != NULL) |
555 |
free(symbols_sym32); |
556 |
|
557 |
CHECK_ALLOCATION(symbols_sym32 = |
558 |
malloc(sh_size)); |
559 |
|
560 |
len = fread(symbols_sym32, 1, |
561 |
sh_entsize * n_entries, f); |
562 |
} |
563 |
|
564 |
if (len != sh_size) { |
565 |
fprintf(stderr, "could not read symbols from " |
566 |
"%s\n", filename); |
567 |
exit(1); |
568 |
} |
569 |
|
570 |
debug("%i symbol entries at 0x%"PRIx64"\n", |
571 |
(int) n_entries, (uint64_t) sh_offset); |
572 |
|
573 |
n_symbols = n_entries; |
574 |
} |
575 |
|
576 |
/* |
577 |
* TODO: This is incorrect, there may be several strtab |
578 |
* sections. |
579 |
* |
580 |
* For now, the simple/stupid guess that the largest string |
581 |
* table is the one to use seems to be good enough. |
582 |
*/ |
583 |
|
584 |
if (sh_type == SHT_STRTAB && sh_size > symbol_length) { |
585 |
size_t len; |
586 |
|
587 |
if (symbol_strings != NULL) |
588 |
free(symbol_strings); |
589 |
|
590 |
CHECK_ALLOCATION(symbol_strings = malloc(sh_size + 1)); |
591 |
|
592 |
fseek(f, sh_offset, SEEK_SET); |
593 |
len = fread(symbol_strings, 1, sh_size, f); |
594 |
if (len != sh_size) { |
595 |
fprintf(stderr, "could not read symbols from " |
596 |
"%s\n", filename); |
597 |
exit(1); |
598 |
} |
599 |
|
600 |
debug("%i bytes of symbol strings at 0x%"PRIx64"\n", |
601 |
(int) sh_size, (uint64_t) sh_offset); |
602 |
|
603 |
symbol_strings[sh_size] = '\0'; |
604 |
symbol_length = sh_size; |
605 |
} |
606 |
} |
607 |
|
608 |
fclose(f); |
609 |
|
610 |
/* Decode symbols: */ |
611 |
if (symbol_strings != NULL) { |
612 |
for (i=0; i<n_symbols; i++) { |
613 |
uint64_t st_name, addr, size; |
614 |
int st_info; |
615 |
|
616 |
if (elf64) { |
617 |
sym64 = symbols_sym64[i]; |
618 |
unencode(st_name, &sym64.st_name, Elf64_Half); |
619 |
unencode(st_info, &sym64.st_info, Elf_Byte); |
620 |
unencode(addr, &sym64.st_value, Elf64_Addr); |
621 |
unencode(size, &sym64.st_size, Elf64_Xword); |
622 |
} else { |
623 |
sym32 = symbols_sym32[i]; |
624 |
unencode(st_name, &sym32.st_name, Elf32_Word); |
625 |
unencode(st_info, &sym32.st_info, Elf_Byte); |
626 |
unencode(addr, &sym32.st_value, Elf32_Word); |
627 |
unencode(size, &sym32.st_size, Elf32_Word); |
628 |
} |
629 |
|
630 |
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
631 |
" (%i) '%s'\n", st_info, (uint64_t) addr, |
632 |
st_name, symbol_strings + st_name); */ |
633 |
|
634 |
if (size == 0) |
635 |
size ++; |
636 |
|
637 |
if (addr != 0) /* && ((st_info >> 4) & 0xf) |
638 |
>= STB_GLOBAL) */ { |
639 |
/* debug("symbol info=0x%02x addr=0x%016"PRIx64 |
640 |
" '%s'\n", st_info, (uint64_t) addr, |
641 |
symbol_strings + st_name); */ |
642 |
add_symbol_name(&m->symbol_context, |
643 |
addr, size, symbol_strings + st_name, |
644 |
0, -1); |
645 |
} |
646 |
|
647 |
if (strcmp(symbol_strings + st_name, "_gp") == 0) { |
648 |
debug("found _gp address: 0x"); |
649 |
if (elf64) |
650 |
debug("%016"PRIx64"\n", (uint64_t)addr); |
651 |
else |
652 |
debug("%08"PRIx32"\n", (uint32_t)addr); |
653 |
*gpp = addr; |
654 |
} |
655 |
} |
656 |
} |
657 |
|
658 |
*entrypointp = eentry; |
659 |
|
660 |
if (encoding == ELFDATA2LSB) |
661 |
*byte_order = EMUL_LITTLE_ENDIAN; |
662 |
else |
663 |
*byte_order = EMUL_BIG_ENDIAN; |
664 |
|
665 |
if (elf64 && arch == ARCH_PPC) { |
666 |
/* |
667 |
* Special case for 64-bit PPC ELFs: |
668 |
* |
669 |
* The ELF starting symbol points to a ".opd" section |
670 |
* which contains a function descriptor: |
671 |
* |
672 |
* uint64_t start; |
673 |
* uint64_t toc_base; |
674 |
* uint64_t something_else; (?) |
675 |
*/ |
676 |
int res; |
677 |
unsigned char b[sizeof(uint64_t)]; |
678 |
uint64_t toc_base; |
679 |
|
680 |
debug("PPC64: "); |
681 |
|
682 |
res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry, b, |
683 |
sizeof(b), MEM_READ, NO_EXCEPTIONS); |
684 |
if (!res) |
685 |
debug(" [WARNING: could not read memory?] "); |
686 |
|
687 |
/* PPC are always big-endian: */ |
688 |
*entrypointp = ((uint64_t)b[0] << 56) + |
689 |
((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) + |
690 |
((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) + |
691 |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
692 |
(uint64_t)b[7]; |
693 |
|
694 |
res = m->cpus[0]->memory_rw(m->cpus[0], mem, eentry + 8, |
695 |
b, sizeof(b), MEM_READ, NO_EXCEPTIONS); |
696 |
if (!res) |
697 |
fatal(" [WARNING: could not read memory?] "); |
698 |
|
699 |
toc_base = ((uint64_t)b[0] << 56) + |
700 |
((uint64_t)b[1] << 48) + ((uint64_t)b[2] << 40) + |
701 |
((uint64_t)b[3] << 32) + ((uint64_t)b[4] << 24) + |
702 |
((uint64_t)b[5] << 16) + ((uint64_t)b[6] << 8) + |
703 |
(uint64_t)b[7]; |
704 |
|
705 |
debug("entrypoint 0x%016"PRIx64", toc_base 0x%016"PRIx64"\n", |
706 |
(uint64_t) *entrypointp, (uint64_t) toc_base); |
707 |
if (tocp != NULL) |
708 |
*tocp = toc_base; |
709 |
} |
710 |
|
711 |
n_executables_loaded ++; |
712 |
} |
713 |
|