]> git.proxmox.com Git - mirror_qemu.git/blame - bsd-user/elfload.c
bsd-user: elfload.c style catch up patch
[mirror_qemu.git] / bsd-user / elfload.c
CommitLineData
310df056
WL
1/*
2 * ELF loading code
3 *
4 * Copyright (c) 2013 Stacey D. Son
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
84778508 19
2231197c 20#include "qemu/osdep.h"
84778508
BS
21
22#include "qemu.h"
76cad711 23#include "disas/disas.h"
f348b6d1 24#include "qemu/path.h"
84778508 25
98b34d35
WL
26static abi_ulong target_auxents; /* Where the AUX entries are in target */
27static size_t target_auxents_sz; /* Size of AUX entries including AT_NULL */
84778508 28
0475f8fa 29#include "target_arch_reg.h"
98b34d35
WL
30#include "target_os_elf.h"
31#include "target_os_stack.h"
32#include "target_os_thread.h"
0475f8fa 33#include "target_os_user.h"
84778508 34
98b34d35
WL
35abi_ulong target_stksiz;
36abi_ulong target_stkbas;
84778508 37
0475f8fa
WL
38static int elf_core_dump(int signr, CPUArchState *env);
39
b4bebeee 40static inline void memcpy_fromfs(void *to, const void *from, unsigned long n)
84778508 41{
b62f790c 42 memcpy(to, from, n);
84778508
BS
43}
44
84778508
BS
45#ifdef BSWAP_NEEDED
46static void bswap_ehdr(struct elfhdr *ehdr)
47{
b62f790c 48 bswap16s(&ehdr->e_type); /* Object file type */
84778508
BS
49 bswap16s(&ehdr->e_machine); /* Architecture */
50 bswap32s(&ehdr->e_version); /* Object file version */
51 bswaptls(&ehdr->e_entry); /* Entry point virtual address */
52 bswaptls(&ehdr->e_phoff); /* Program header table file offset */
53 bswaptls(&ehdr->e_shoff); /* Section header table file offset */
54 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
55 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
b62f790c 56 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
84778508 57 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
b62f790c 58 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
84778508 59 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
b62f790c 60 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
84778508
BS
61}
62
b62f790c 63static void bswap_phdr(struct elf_phdr *phdr, int phnum)
84778508 64{
b62f790c
WL
65 int i;
66
67 for (i = 0; i < phnum; i++, phdr++) {
68 bswap32s(&phdr->p_type); /* Segment type */
69 bswap32s(&phdr->p_flags); /* Segment flags */
70 bswaptls(&phdr->p_offset); /* Segment file offset */
71 bswaptls(&phdr->p_vaddr); /* Segment virtual address */
72 bswaptls(&phdr->p_paddr); /* Segment physical address */
73 bswaptls(&phdr->p_filesz); /* Segment size in file */
74 bswaptls(&phdr->p_memsz); /* Segment size in memory */
75 bswaptls(&phdr->p_align); /* Segment alignment */
76 }
84778508
BS
77}
78
b62f790c 79static void bswap_shdr(struct elf_shdr *shdr, int shnum)
84778508 80{
b62f790c
WL
81 int i;
82
83 for (i = 0; i < shnum; i++, shdr++) {
84 bswap32s(&shdr->sh_name);
85 bswap32s(&shdr->sh_type);
86 bswaptls(&shdr->sh_flags);
87 bswaptls(&shdr->sh_addr);
88 bswaptls(&shdr->sh_offset);
89 bswaptls(&shdr->sh_size);
90 bswap32s(&shdr->sh_link);
91 bswap32s(&shdr->sh_info);
92 bswaptls(&shdr->sh_addralign);
93 bswaptls(&shdr->sh_entsize);
94 }
84778508
BS
95}
96
97static void bswap_sym(struct elf_sym *sym)
98{
99 bswap32s(&sym->st_name);
100 bswaptls(&sym->st_value);
101 bswaptls(&sym->st_size);
102 bswap16s(&sym->st_shndx);
103}
b62f790c 104
0475f8fa
WL
105static void bswap_note(struct elf_note *en)
106{
107 bswap32s(&en->n_namesz);
108 bswap32s(&en->n_descsz);
109 bswap32s(&en->n_type);
110}
111
b62f790c
WL
112#else /* ! BSWAP_NEEDED */
113
114static void bswap_ehdr(struct elfhdr *ehdr) { }
115static void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
116static void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
117static void bswap_sym(struct elf_sym *sym) { }
0475f8fa 118static void bswap_note(struct elf_note *en) { }
b62f790c
WL
119
120#endif /* ! BSWAP_NEEDED */
84778508 121
0475f8fa
WL
122#include "elfcore.c"
123
84778508
BS
124/*
125 * 'copy_elf_strings()' copies argument/envelope strings from user
126 * memory to free pages in kernel mem. These are in a format ready
127 * to be put directly into the top of new user memory.
128 *
129 */
b4bebeee 130static abi_ulong copy_elf_strings(int argc, char **argv, void **page,
84778508
BS
131 abi_ulong p)
132{
133 char *tmp, *tmp1, *pag = NULL;
134 int len, offset = 0;
135
136 if (!p) {
137 return 0; /* bullet-proofing */
138 }
139 while (argc-- > 0) {
140 tmp = argv[argc];
141 if (!tmp) {
9bb93180 142 fprintf(stderr, "VFS: argc is wrong");
84778508
BS
143 exit(-1);
144 }
145 tmp1 = tmp;
0456a177
WL
146 while (*tmp++) {
147 continue;
148 }
84778508
BS
149 len = tmp - tmp1;
150 if (p < len) { /* this shouldn't happen - 128kB */
0456a177 151 return 0;
84778508
BS
152 }
153 while (len) {
154 --p; --tmp; --len;
155 if (--offset < 0) {
156 offset = p % TARGET_PAGE_SIZE;
b4bebeee 157 pag = (char *)page[p / TARGET_PAGE_SIZE];
84778508 158 if (!pag) {
c580dee4 159 pag = g_try_malloc0(TARGET_PAGE_SIZE);
b4bebeee 160 page[p / TARGET_PAGE_SIZE] = pag;
0456a177 161 if (!pag) {
84778508 162 return 0;
0456a177 163 }
84778508
BS
164 }
165 }
166 if (len == 0 || offset == 0) {
167 *(pag + offset) = *tmp;
0456a177 168 } else {
84778508
BS
169 int bytes_to_copy = (len > offset) ? offset : len;
170 tmp -= bytes_to_copy;
171 p -= bytes_to_copy;
172 offset -= bytes_to_copy;
173 len -= bytes_to_copy;
174 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
175 }
176 }
177 }
178 return p;
179}
180
98b34d35
WL
181static void setup_arg_pages(struct bsd_binprm *bprm, struct image_info *info,
182 abi_ulong *stackp, abi_ulong *stringp)
84778508 183{
98b34d35
WL
184 abi_ulong stack_base, size;
185 abi_long addr;
84778508 186
0456a177
WL
187 /*
188 * Create enough stack to hold everything. If we don't use it for args,
189 * we'll use it for something else...
84778508 190 */
312a0b1c 191 size = target_dflssiz;
98b34d35 192 stack_base = TARGET_USRSTACK - size;
0456a177
WL
193 addr = target_mmap(stack_base , size + qemu_host_page_size,
194 PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
98b34d35 195 if (addr == -1) {
84778508
BS
196 perror("stk mmap");
197 exit(-1);
198 }
199 /* we reserve one extra page at the top of the stack as guard */
98b34d35 200 target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
84778508 201
98b34d35
WL
202 target_stksiz = size;
203 target_stkbas = addr;
84778508 204
98b34d35
WL
205 if (setup_initial_stack(bprm, stackp, stringp) != 0) {
206 perror("stk setup");
207 exit(-1);
84778508 208 }
84778508
BS
209}
210
211static void set_brk(abi_ulong start, abi_ulong end)
212{
0456a177
WL
213 /* page-align the start and end addresses... */
214 start = HOST_PAGE_ALIGN(start);
215 end = HOST_PAGE_ALIGN(end);
216 if (end <= start) {
217 return;
218 }
219 if (target_mmap(start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC,
220 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == -1) {
221 perror("cannot mmap brk");
222 exit(-1);
223 }
84778508
BS
224}
225
226
0456a177
WL
227/*
228 * We need to explicitly zero any fractional pages after the data
229 * section (i.e. bss). This would contain the junk from the file that
230 * should not be in memory.
231 */
84778508
BS
232static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
233{
0456a177 234 abi_ulong nbyte;
84778508 235
0456a177
WL
236 if (elf_bss >= last_bss) {
237 return;
238 }
84778508 239
0456a177
WL
240 /*
241 * XXX: this is really a hack : if the real host page size is
242 * smaller than the target page size, some pages after the end
243 * of the file may not be mapped. A better fix would be to
244 * patch target_mmap(), but it is more complicated as the file
245 * size must be known.
246 */
247 if (qemu_real_host_page_size < qemu_host_page_size) {
248 abi_ulong end_addr, end_addr1;
249 end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
250 end_addr = HOST_PAGE_ALIGN(elf_bss);
251 if (end_addr1 < end_addr) {
252 mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
253 PROT_READ | PROT_WRITE | PROT_EXEC,
254 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
84778508 255 }
0456a177 256 }
84778508 257
0456a177
WL
258 nbyte = elf_bss & (qemu_host_page_size - 1);
259 if (nbyte) {
260 nbyte = qemu_host_page_size - nbyte;
261 do {
262 /* FIXME - what to do if put_user() fails? */
263 put_user_u8(0, elf_bss);
264 elf_bss++;
265 } while (--nbyte);
266 }
84778508
BS
267}
268
b4bebeee 269static abi_ulong load_elf_interp(struct elfhdr *interp_elf_ex,
84778508
BS
270 int interpreter_fd,
271 abi_ulong *interp_load_addr)
272{
b4bebeee
WL
273 struct elf_phdr *elf_phdata = NULL;
274 struct elf_phdr *eppnt;
275 abi_ulong load_addr = 0;
276 int load_addr_set = 0;
277 int retval;
278 abi_ulong last_bss, elf_bss;
279 abi_ulong error;
280 int i;
84778508 281
b4bebeee
WL
282 elf_bss = 0;
283 last_bss = 0;
284 error = 0;
84778508 285
b4bebeee 286 bswap_ehdr(interp_elf_ex);
b4bebeee 287 /* First of all, some simple consistency checks */
0456a177
WL
288 if ((interp_elf_ex->e_type != ET_EXEC && interp_elf_ex->e_type != ET_DYN) ||
289 !elf_check_arch(interp_elf_ex->e_machine)) {
b4bebeee
WL
290 return ~((abi_ulong)0UL);
291 }
84778508
BS
292
293
b4bebeee 294 /* Now read in all of the header information */
0456a177 295 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE) {
b4bebeee 296 return ~(abi_ulong)0UL;
0456a177 297 }
84778508 298
0456a177
WL
299 elf_phdata = (struct elf_phdr *) malloc(sizeof(struct elf_phdr) *
300 interp_elf_ex->e_phnum);
84778508 301
0456a177 302 if (!elf_phdata) {
b4bebeee 303 return ~((abi_ulong)0UL);
0456a177 304 }
84778508 305
b4bebeee
WL
306 /*
307 * If the size of this structure has changed, then punt, since
308 * we will be doing the wrong thing.
309 */
310 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
311 free(elf_phdata);
312 return ~((abi_ulong)0UL);
313 }
84778508 314
b4bebeee
WL
315 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
316 if (retval >= 0) {
0456a177
WL
317 retval = read(interpreter_fd, (char *) elf_phdata,
318 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
b4bebeee
WL
319 }
320 if (retval < 0) {
321 perror("load_elf_interp");
322 exit(-1);
ffa03665 323 free(elf_phdata);
b4bebeee
WL
324 return retval;
325 }
b62f790c 326 bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
84778508 327
b4bebeee 328 if (interp_elf_ex->e_type == ET_DYN) {
0456a177
WL
329 /*
330 * In order to avoid hardcoding the interpreter load
331 * address in qemu, we allocate a big enough memory zone.
332 */
333 error = target_mmap(0, INTERP_MAP_SIZE, PROT_NONE,
334 MAP_PRIVATE | MAP_ANON, -1, 0);
b4bebeee
WL
335 if (error == -1) {
336 perror("mmap");
337 exit(-1);
84778508 338 }
b4bebeee
WL
339 load_addr = error;
340 load_addr_set = 1;
341 }
84778508 342
b4bebeee
WL
343 eppnt = elf_phdata;
344 for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++)
345 if (eppnt->p_type == PT_LOAD) {
84778508
BS
346 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
347 int elf_prot = 0;
348 abi_ulong vaddr = 0;
349 abi_ulong k;
350
351 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
352 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
353 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
354 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
355 elf_type |= MAP_FIXED;
356 vaddr = eppnt->p_vaddr;
357 }
b4bebeee
WL
358 error = target_mmap(load_addr + TARGET_ELF_PAGESTART(vaddr),
359 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
360 elf_prot,
361 elf_type,
362 interpreter_fd,
363 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
84778508
BS
364
365 if (error == -1) {
b4bebeee
WL
366 /* Real error */
367 close(interpreter_fd);
368 free(elf_phdata);
369 return ~((abi_ulong)0UL);
84778508
BS
370 }
371
372 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
b4bebeee
WL
373 load_addr = error;
374 load_addr_set = 1;
84778508
BS
375 }
376
377 /*
378 * Find the end of the file mapping for this phdr, and keep
379 * track of the largest address we see for this.
380 */
381 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
382 if (k > elf_bss) elf_bss = k;
383
384 /*
385 * Do the same thing for the memory mapping - between
386 * elf_bss and last_bss is the bss section.
387 */
388 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
389 if (k > last_bss) last_bss = k;
b4bebeee 390 }
84778508 391
b4bebeee 392 /* Now use mmap to map the library into memory. */
84778508 393
b4bebeee 394 close(interpreter_fd);
84778508 395
b4bebeee
WL
396 /*
397 * Now fill out the bss section. First pad the last page up
398 * to the page boundary, and then perform a mmap to make sure
399 * that there are zeromapped pages up to and including the last
400 * bss page.
401 */
402 padzero(elf_bss, last_bss);
403 elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
404
405 /* Map the last of the bss segment */
406 if (last_bss > elf_bss) {
407 target_mmap(elf_bss, last_bss - elf_bss,
408 PROT_READ | PROT_WRITE | PROT_EXEC,
409 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
410 }
411 free(elf_phdata);
84778508 412
b4bebeee
WL
413 *interp_load_addr = load_addr;
414 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
84778508
BS
415}
416
417static int symfind(const void *s0, const void *s1)
418{
c7c530cd 419 target_ulong addr = *(target_ulong *)s0;
84778508
BS
420 struct elf_sym *sym = (struct elf_sym *)s1;
421 int result = 0;
c7c530cd 422 if (addr < sym->st_value) {
84778508 423 result = -1;
c7c530cd 424 } else if (addr >= sym->st_value + sym->st_size) {
84778508
BS
425 result = 1;
426 }
427 return result;
428}
429
430static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
431{
432#if ELF_CLASS == ELFCLASS32
433 struct elf_sym *syms = s->disas_symtab.elf32;
434#else
435 struct elf_sym *syms = s->disas_symtab.elf64;
436#endif
437
0456a177 438 /* binary search */
84778508
BS
439 struct elf_sym *sym;
440
c7c530cd 441 sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
7cba04f6 442 if (sym != NULL) {
84778508
BS
443 return s->disas_strtab + sym->st_name;
444 }
445
446 return "";
447}
448
449/* FIXME: This should use elf_ops.h */
450static int symcmp(const void *s0, const void *s1)
451{
452 struct elf_sym *sym0 = (struct elf_sym *)s0;
453 struct elf_sym *sym1 = (struct elf_sym *)s1;
0456a177
WL
454 return (sym0->st_value < sym1->st_value) ? -1 :
455 ((sym0->st_value > sym1->st_value) ? 1 : 0);
84778508
BS
456}
457
458/* Best attempt to load symbols from this ELF object. */
459static void load_symbols(struct elfhdr *hdr, int fd)
460{
461 unsigned int i, nsyms;
462 struct elf_shdr sechdr, symtab, strtab;
463 char *strings;
464 struct syminfo *s;
29718712 465 struct elf_sym *syms, *new_syms;
84778508
BS
466
467 lseek(fd, hdr->e_shoff, SEEK_SET);
468 for (i = 0; i < hdr->e_shnum; i++) {
0456a177 469 if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) {
84778508 470 return;
0456a177 471 }
b62f790c 472 bswap_shdr(&sechdr, 1);
84778508
BS
473 if (sechdr.sh_type == SHT_SYMTAB) {
474 symtab = sechdr;
0456a177
WL
475 lseek(fd, hdr->e_shoff + sizeof(sechdr) * sechdr.sh_link,
476 SEEK_SET);
477 if (read(fd, &strtab, sizeof(strtab)) != sizeof(strtab)) {
84778508 478 return;
0456a177 479 }
b62f790c 480 bswap_shdr(&strtab, 1);
84778508
BS
481 goto found;
482 }
483 }
484 return; /* Shouldn't happen... */
485
0456a177 486found:
84778508
BS
487 /* Now know where the strtab and symtab are. Snarf them. */
488 s = malloc(sizeof(*s));
489 syms = malloc(symtab.sh_size);
29718712
SW
490 if (!syms) {
491 free(s);
84778508 492 return;
29718712 493 }
84778508 494 s->disas_strtab = strings = malloc(strtab.sh_size);
29718712
SW
495 if (!s->disas_strtab) {
496 free(s);
497 free(syms);
84778508 498 return;
29718712 499 }
84778508
BS
500
501 lseek(fd, symtab.sh_offset, SEEK_SET);
29718712
SW
502 if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {
503 free(s);
504 free(syms);
505 free(strings);
84778508 506 return;
29718712 507 }
84778508
BS
508
509 nsyms = symtab.sh_size / sizeof(struct elf_sym);
510
511 i = 0;
512 while (i < nsyms) {
84778508 513 bswap_sym(syms + i);
0456a177 514 /* Throw away entries which we do not need. */
84778508
BS
515 if (syms[i].st_shndx == SHN_UNDEF ||
516 syms[i].st_shndx >= SHN_LORESERVE ||
517 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
518 nsyms--;
519 if (i < nsyms) {
520 syms[i] = syms[nsyms];
521 }
522 continue;
523 }
84778508
BS
524 i++;
525 }
29718712 526
0456a177
WL
527 /*
528 * Attempt to free the storage associated with the local symbols
529 * that we threw away. Whether or not this has any effect on the
530 * memory allocation depends on the malloc implementation and how
531 * many symbols we managed to discard.
532 */
29718712
SW
533 new_syms = realloc(syms, nsyms * sizeof(*syms));
534 if (new_syms == NULL) {
535 free(s);
536 free(syms);
537 free(strings);
538 return;
539 }
540 syms = new_syms;
84778508
BS
541
542 qsort(syms, nsyms, sizeof(*syms), symcmp);
543
544 lseek(fd, strtab.sh_offset, SEEK_SET);
29718712
SW
545 if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {
546 free(s);
547 free(syms);
548 free(strings);
84778508 549 return;
29718712 550 }
84778508
BS
551 s->disas_num_syms = nsyms;
552#if ELF_CLASS == ELFCLASS32
553 s->disas_symtab.elf32 = syms;
032e51d7 554 s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
84778508
BS
555#else
556 s->disas_symtab.elf64 = syms;
032e51d7 557 s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
84778508
BS
558#endif
559 s->next = syminfos;
560 syminfos = s;
561}
562
afcbcff8 563int load_elf_binary(struct bsd_binprm *bprm, struct target_pt_regs *regs,
b4bebeee 564 struct image_info *info)
84778508
BS
565{
566 struct elfhdr elf_ex;
567 struct elfhdr interp_elf_ex;
84778508
BS
568 int interpreter_fd = -1; /* avoid warning */
569 abi_ulong load_addr, load_bias;
570 int load_addr_set = 0;
84778508 571 int i;
84778508
BS
572 struct elf_phdr * elf_ppnt;
573 struct elf_phdr *elf_phdata;
574 abi_ulong elf_bss, k, elf_brk;
575 int retval;
576 char * elf_interpreter;
577 abi_ulong elf_entry, interp_load_addr = 0;
84778508
BS
578 abi_ulong start_code, end_code, start_data, end_data;
579 abi_ulong reloc_func_desc = 0;
84778508 580
84778508
BS
581 load_addr = 0;
582 load_bias = 0;
583 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
84778508 584 bswap_ehdr(&elf_ex);
84778508
BS
585
586 /* First of all, some simple consistency checks */
587 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
0456a177 588 (!elf_check_arch(elf_ex.e_machine))) {
84778508
BS
589 return -ENOEXEC;
590 }
591
592 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
0456a177
WL
593 bprm->p = copy_elf_strings(bprm->envc, bprm->envp, bprm->page, bprm->p);
594 bprm->p = copy_elf_strings(bprm->argc, bprm->argv, bprm->page, bprm->p);
84778508
BS
595 if (!bprm->p) {
596 retval = -E2BIG;
597 }
598
599 /* Now read in all of the header information */
0456a177 600 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize * elf_ex.e_phnum);
84778508
BS
601 if (elf_phdata == NULL) {
602 return -ENOMEM;
603 }
604
605 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
b4bebeee
WL
606 if (retval > 0) {
607 retval = read(bprm->fd, (char *)elf_phdata,
84778508
BS
608 elf_ex.e_phentsize * elf_ex.e_phnum);
609 }
610
611 if (retval < 0) {
612 perror("load_elf_binary");
613 exit(-1);
b4bebeee 614 free(elf_phdata);
84778508
BS
615 return -errno;
616 }
617
b62f790c 618 bswap_phdr(elf_phdata, elf_ex.e_phnum);
84778508
BS
619 elf_ppnt = elf_phdata;
620
621 elf_bss = 0;
622 elf_brk = 0;
623
624
84778508
BS
625 elf_interpreter = NULL;
626 start_code = ~((abi_ulong)0UL);
627 end_code = 0;
628 start_data = 0;
629 end_data = 0;
84778508 630
0456a177 631 for (i = 0; i < elf_ex.e_phnum; i++) {
84778508 632 if (elf_ppnt->p_type == PT_INTERP) {
0456a177 633 if (elf_interpreter != NULL) {
b4bebeee 634 free(elf_phdata);
84778508
BS
635 free(elf_interpreter);
636 close(bprm->fd);
637 return -EINVAL;
638 }
639
84778508 640 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
84778508 641 if (elf_interpreter == NULL) {
b4bebeee 642 free(elf_phdata);
84778508
BS
643 close(bprm->fd);
644 return -ENOMEM;
645 }
646
647 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
b4bebeee 648 if (retval >= 0) {
84778508
BS
649 retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
650 }
b4bebeee 651 if (retval < 0) {
84778508
BS
652 perror("load_elf_binary2");
653 exit(-1);
654 }
655
84778508
BS
656 if (retval >= 0) {
657 retval = open(path(elf_interpreter), O_RDONLY);
b4bebeee 658 if (retval >= 0) {
84778508 659 interpreter_fd = retval;
0456a177 660 } else {
84778508
BS
661 perror(elf_interpreter);
662 exit(-1);
663 /* retval = -errno; */
664 }
665 }
666
667 if (retval >= 0) {
668 retval = lseek(interpreter_fd, 0, SEEK_SET);
b4bebeee
WL
669 if (retval >= 0) {
670 retval = read(interpreter_fd, bprm->buf, 128);
84778508
BS
671 }
672 }
673 if (retval >= 0) {
0456a177 674 interp_elf_ex = *((struct elfhdr *) bprm->buf);
84778508
BS
675 }
676 if (retval < 0) {
677 perror("load_elf_binary3");
678 exit(-1);
b4bebeee 679 free(elf_phdata);
84778508
BS
680 free(elf_interpreter);
681 close(bprm->fd);
682 return retval;
683 }
684 }
685 elf_ppnt++;
686 }
687
688 /* Some simple consistency checks for the interpreter */
b4bebeee 689 if (elf_interpreter) {
84778508 690 if (interp_elf_ex.e_ident[0] != 0x7f ||
ffa03665 691 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF", 3) != 0) {
84778508
BS
692 free(elf_interpreter);
693 free(elf_phdata);
694 close(bprm->fd);
695 return -ELIBBAD;
696 }
697 }
698
0456a177
WL
699 /*
700 * OK, we are done with that, now set up the arg stuff, and then start this
701 * sucker up
702 */
ffa03665
WL
703 if (!bprm->p) {
704 free(elf_interpreter);
705 free(elf_phdata);
706 close(bprm->fd);
707 return -E2BIG;
84778508
BS
708 }
709
710 /* OK, This is the point of no return */
711 info->end_data = 0;
712 info->end_code = 0;
713 info->start_mmap = (abi_ulong)ELF_START_MMAP;
714 info->mmap = 0;
715 elf_entry = (abi_ulong) elf_ex.e_entry;
716
717 /* Do this so that we can load the interpreter, if need be. We will
718 change some of these later */
719 info->rss = 0;
98b34d35 720 setup_arg_pages(bprm, info, &bprm->p, &bprm->stringp);
84778508
BS
721 info->start_stack = bprm->p;
722
723 /* Now we do a little grungy work by mmaping the ELF image into
724 * the correct location in memory. At this point, we assume that
725 * the image should be loaded at fixed address, not at a variable
726 * address.
727 */
728
b4bebeee 729 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
84778508
BS
730 int elf_prot = 0;
731 int elf_flags = 0;
732 abi_ulong error;
733
734 if (elf_ppnt->p_type != PT_LOAD)
735 continue;
736
737 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
738 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
739 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
740 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
741 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
742 elf_flags |= MAP_FIXED;
743 } else if (elf_ex.e_type == ET_DYN) {
744 /* Try and get dynamic programs out of the way of the default mmap
745 base, as well as whatever program they might try to exec. This
746 is because the brk will follow the loader, and is not movable. */
747 /* NOTE: for qemu, we do a big mmap to get enough space
748 without hardcoding any address */
749 error = target_mmap(0, ET_DYN_MAP_SIZE,
750 PROT_NONE, MAP_PRIVATE | MAP_ANON,
751 -1, 0);
752 if (error == -1) {
753 perror("mmap");
754 exit(-1);
755 }
756 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
757 }
758
759 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
760 (elf_ppnt->p_filesz +
761 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
762 elf_prot,
763 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
764 bprm->fd,
765 (elf_ppnt->p_offset -
766 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
767 if (error == -1) {
768 perror("mmap");
769 exit(-1);
770 }
771
84778508
BS
772 if (!load_addr_set) {
773 load_addr_set = 1;
774 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
775 if (elf_ex.e_type == ET_DYN) {
776 load_bias += error -
777 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
778 load_addr += load_bias;
779 reloc_func_desc = load_bias;
780 }
781 }
782 k = elf_ppnt->p_vaddr;
783 if (k < start_code)
784 start_code = k;
785 if (start_data < k)
786 start_data = k;
787 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
788 if (k > elf_bss)
789 elf_bss = k;
790 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
791 end_code = k;
792 if (end_data < k)
793 end_data = k;
794 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
795 if (k > elf_brk) elf_brk = k;
796 }
797
798 elf_entry += load_bias;
799 elf_bss += load_bias;
800 elf_brk += load_bias;
801 start_code += load_bias;
802 end_code += load_bias;
803 start_data += load_bias;
804 end_data += load_bias;
805
806 if (elf_interpreter) {
ffa03665
WL
807 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
808 &interp_load_addr);
84778508
BS
809 reloc_func_desc = interp_load_addr;
810
811 close(interpreter_fd);
812 free(elf_interpreter);
813
814 if (elf_entry == ~((abi_ulong)0UL)) {
815 printf("Unable to load interpreter\n");
816 free(elf_phdata);
817 exit(-1);
818 return 0;
819 }
820 }
821
822 free(elf_phdata);
823
0456a177 824 if (qemu_log_enabled()) {
84778508 825 load_symbols(&elf_ex, bprm->fd);
0456a177 826 }
84778508 827
ffa03665 828 close(bprm->fd);
84778508 829
98b34d35
WL
830 bprm->p = target_create_elf_tables(bprm->p, bprm->argc, bprm->envc,
831 bprm->stringp, &elf_ex, load_addr,
832 load_bias, interp_load_addr, info);
84778508
BS
833 info->load_addr = reloc_func_desc;
834 info->start_brk = info->brk = elf_brk;
835 info->end_code = end_code;
836 info->start_code = start_code;
837 info->start_data = start_data;
838 info->end_data = end_data;
839 info->start_stack = bprm->p;
840
841 /* Calling set_brk effectively mmaps the pages that we need for the bss and break
842 sections */
843 set_brk(elf_bss, elf_brk);
844
845 padzero(elf_bss, elf_brk);
846
84778508
BS
847 info->entry = elf_entry;
848
0475f8fa
WL
849#ifdef USE_ELF_CORE_DUMP
850 bprm->core_dump = &elf_core_dump;
851#else
852 bprm->core_dump = NULL;
853#endif
854
84778508
BS
855 return 0;
856}
857
84778508
BS
858void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
859{
a8fe6d5d
WL
860
861 target_thread_init(regs, infop);
84778508 862}