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