]> Git Repo - qemu.git/blame - linux-user/elfload.c
stat patches - path patches - added exit_group() syscall
[qemu.git] / linux-user / elfload.c
CommitLineData
31e31b8a
FB
1/* This is the Linux kernel elf-loading code, ported into user space */
2
3#include <stdio.h>
4#include <sys/types.h>
5#include <fcntl.h>
6#include <sys/stat.h>
7#include <errno.h>
8#include <unistd.h>
9#include <sys/mman.h>
10#include <stdlib.h>
11#include <string.h>
12
3ef693a0 13#include "qemu.h"
31e31b8a 14
30ac07d4
FB
15#ifdef TARGET_I386
16
17#define ELF_START_MMAP 0x80000000
18
19typedef uint32_t elf_greg_t;
20
21#define ELF_NGREG (sizeof (struct target_pt_regs) / sizeof(elf_greg_t))
22typedef elf_greg_t elf_gregset_t[ELF_NGREG];
23
24typedef struct user_i387_struct elf_fpregset_t;
25
26/*
27 * This is used to ensure we don't load something for the wrong architecture.
28 */
29#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
30
31/*
32 * These are used to set parameters in the core dumps.
33 */
34#define ELF_CLASS ELFCLASS32
35#define ELF_DATA ELFDATA2LSB
36#define ELF_ARCH EM_386
37
38 /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
39 starts %edx contains a pointer to a function which might be
40 registered using `atexit'. This provides a mean for the
41 dynamic linker to call DT_FINI functions for shared libraries
42 that have been loaded before the code runs.
43
44 A value of 0 tells we have no such handler. */
45#define ELF_PLAT_INIT(_r) _r->edx = 0
46
47#define USE_ELF_CORE_DUMP
48#define ELF_EXEC_PAGESIZE 4096
49
50#endif
51
31e31b8a 52#include "elf.h"
09bfb054
FB
53
54/*
55 * MAX_ARG_PAGES defines the number of pages allocated for arguments
56 * and envelope for the new program. 32 should suffice, this gives
57 * a maximum env+arg of 128kB w/4KB pages!
58 */
59#define MAX_ARG_PAGES 32
60
61/*
62 * This structure is used to hold the arguments that are
63 * used when loading binaries.
64 */
65struct linux_binprm {
66 char buf[128];
67 unsigned long page[MAX_ARG_PAGES];
68 unsigned long p;
69 int sh_bang;
70 int fd;
71 int e_uid, e_gid;
72 int argc, envc;
73 char * interp_prefix; /* prefix for interpreter */
74 char * filename; /* Name of binary */
75 unsigned long loader, exec;
76 int dont_iput; /* binfmt handler has put inode */
77};
78
79struct exec
80{
81 unsigned int a_info; /* Use macros N_MAGIC, etc for access */
82 unsigned int a_text; /* length of text, in bytes */
83 unsigned int a_data; /* length of data, in bytes */
84 unsigned int a_bss; /* length of uninitialized data area, in bytes */
85 unsigned int a_syms; /* length of symbol table data in file, in bytes */
86 unsigned int a_entry; /* start address */
87 unsigned int a_trsize; /* length of relocation info for text, in bytes */
88 unsigned int a_drsize; /* length of relocation info for data, in bytes */
89};
90
91
92#define N_MAGIC(exec) ((exec).a_info & 0xffff)
93#define OMAGIC 0407
94#define NMAGIC 0410
95#define ZMAGIC 0413
96#define QMAGIC 0314
97
98#define X86_STACK_TOP 0x7d000000
99
100/* max code+data+bss space allocated to elf interpreter */
101#define INTERP_MAP_SIZE (32 * 1024 * 1024)
102
103/* max code+data+bss+brk space allocated to ET_DYN executables */
104#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
105
106/* from personality.h */
107
108/* Flags for bug emulation. These occupy the top three bytes. */
109#define STICKY_TIMEOUTS 0x4000000
110#define WHOLE_SECONDS 0x2000000
111
112/* Personality types. These go in the low byte. Avoid using the top bit,
113 * it will conflict with error returns.
114 */
115#define PER_MASK (0x00ff)
116#define PER_LINUX (0x0000)
117#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS)
118#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS)
119#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
120#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS)
121#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
122#define PER_BSD (0x0006)
123#define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
31e31b8a
FB
124
125/* Necessary parameters */
126#define ALPHA_PAGE_SIZE 4096
127#define X86_PAGE_SIZE 4096
128
129#define ALPHA_PAGE_MASK (~(ALPHA_PAGE_SIZE-1))
130#define X86_PAGE_MASK (~(X86_PAGE_SIZE-1))
131
132#define ALPHA_PAGE_ALIGN(addr) ((((addr)+ALPHA_PAGE_SIZE)-1)&ALPHA_PAGE_MASK)
133#define X86_PAGE_ALIGN(addr) ((((addr)+X86_PAGE_SIZE)-1)&X86_PAGE_MASK)
134
135#define NGROUPS 32
136
137#define X86_ELF_EXEC_PAGESIZE X86_PAGE_SIZE
138#define X86_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(X86_ELF_EXEC_PAGESIZE-1))
139#define X86_ELF_PAGEOFFSET(_v) ((_v) & (X86_ELF_EXEC_PAGESIZE-1))
140
141#define ALPHA_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ALPHA_PAGE_SIZE-1))
142#define ALPHA_ELF_PAGEOFFSET(_v) ((_v) & (ALPHA_PAGE_SIZE-1))
143
144#define INTERPRETER_NONE 0
145#define INTERPRETER_AOUT 1
146#define INTERPRETER_ELF 2
147
148#define DLINFO_ITEMS 12
149
09bfb054
FB
150#define put_user(x,ptr) (void)(*(ptr) = (typeof(*ptr))(x))
151#define get_user(ptr) (typeof(*ptr))(*(ptr))
152
153static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
154{
155 memcpy(to, from, n);
156}
d691f669 157
09bfb054
FB
158static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
159{
160 memcpy(to, from, n);
161}
31e31b8a
FB
162
163//extern void * mmap4k();
164#define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
165
166extern unsigned long x86_stack_size;
167
168static int load_aout_interp(void * exptr, int interp_fd);
169
170#ifdef BSWAP_NEEDED
171static void bswap_ehdr(Elf32_Ehdr *ehdr)
172{
173 bswap16s(&ehdr->e_type); /* Object file type */
174 bswap16s(&ehdr->e_machine); /* Architecture */
175 bswap32s(&ehdr->e_version); /* Object file version */
176 bswap32s(&ehdr->e_entry); /* Entry point virtual address */
177 bswap32s(&ehdr->e_phoff); /* Program header table file offset */
178 bswap32s(&ehdr->e_shoff); /* Section header table file offset */
179 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
180 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
181 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
182 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
183 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
184 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
185 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
186}
187
188static void bswap_phdr(Elf32_Phdr *phdr)
189{
190 bswap32s(&phdr->p_type); /* Segment type */
191 bswap32s(&phdr->p_offset); /* Segment file offset */
192 bswap32s(&phdr->p_vaddr); /* Segment virtual address */
193 bswap32s(&phdr->p_paddr); /* Segment physical address */
194 bswap32s(&phdr->p_filesz); /* Segment size in file */
195 bswap32s(&phdr->p_memsz); /* Segment size in memory */
196 bswap32s(&phdr->p_flags); /* Segment flags */
197 bswap32s(&phdr->p_align); /* Segment alignment */
198}
199#endif
200
201static void * get_free_page(void)
202{
203 void * retval;
204
205 /* User-space version of kernel get_free_page. Returns a page-aligned
206 * page-sized chunk of memory.
207 */
208 retval = mmap4k(0, ALPHA_PAGE_SIZE, PROT_READ|PROT_WRITE,
209 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
210
211 if((long)retval == -1) {
212 perror("get_free_page");
213 exit(-1);
214 }
215 else {
216 return(retval);
217 }
218}
219
220static void free_page(void * pageaddr)
221{
222 (void)munmap(pageaddr, ALPHA_PAGE_SIZE);
223}
224
225/*
226 * 'copy_string()' copies argument/envelope strings from user
227 * memory to free pages in kernel mem. These are in a format ready
228 * to be put directly into the top of new user memory.
229 *
230 */
231static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
232 unsigned long p)
233{
234 char *tmp, *tmp1, *pag = NULL;
235 int len, offset = 0;
236
237 if (!p) {
238 return 0; /* bullet-proofing */
239 }
240 while (argc-- > 0) {
241 if (!(tmp1 = tmp = get_user(argv+argc))) {
242 fprintf(stderr, "VFS: argc is wrong");
243 exit(-1);
244 }
245 while (get_user(tmp++));
246 len = tmp - tmp1;
247 if (p < len) { /* this shouldn't happen - 128kB */
248 return 0;
249 }
250 while (len) {
251 --p; --tmp; --len;
252 if (--offset < 0) {
253 offset = p % X86_PAGE_SIZE;
254 if (!(pag = (char *) page[p/X86_PAGE_SIZE]) &&
255 !(pag = (char *) page[p/X86_PAGE_SIZE] =
256 (unsigned long *) get_free_page())) {
257 return 0;
258 }
259 }
260 if (len == 0 || offset == 0) {
261 *(pag + offset) = get_user(tmp);
262 }
263 else {
264 int bytes_to_copy = (len > offset) ? offset : len;
265 tmp -= bytes_to_copy;
266 p -= bytes_to_copy;
267 offset -= bytes_to_copy;
268 len -= bytes_to_copy;
269 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
270 }
271 }
272 }
273 return p;
274}
275
276static int in_group_p(gid_t g)
277{
278 /* return TRUE if we're in the specified group, FALSE otherwise */
279 int ngroup;
280 int i;
281 gid_t grouplist[NGROUPS];
282
283 ngroup = getgroups(NGROUPS, grouplist);
284 for(i = 0; i < ngroup; i++) {
285 if(grouplist[i] == g) {
286 return 1;
287 }
288 }
289 return 0;
290}
291
292static int count(char ** vec)
293{
294 int i;
295
296 for(i = 0; *vec; i++) {
297 vec++;
298 }
299
300 return(i);
301}
302
303static int prepare_binprm(struct linux_binprm *bprm)
304{
305 struct stat st;
306 int mode;
307 int retval, id_change;
308
309 if(fstat(bprm->fd, &st) < 0) {
310 return(-errno);
311 }
312
313 mode = st.st_mode;
314 if(!S_ISREG(mode)) { /* Must be regular file */
315 return(-EACCES);
316 }
317 if(!(mode & 0111)) { /* Must have at least one execute bit set */
318 return(-EACCES);
319 }
320
321 bprm->e_uid = geteuid();
322 bprm->e_gid = getegid();
323 id_change = 0;
324
325 /* Set-uid? */
326 if(mode & S_ISUID) {
327 bprm->e_uid = st.st_uid;
328 if(bprm->e_uid != geteuid()) {
329 id_change = 1;
330 }
331 }
332
333 /* Set-gid? */
334 /*
335 * If setgid is set but no group execute bit then this
336 * is a candidate for mandatory locking, not a setgid
337 * executable.
338 */
339 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
340 bprm->e_gid = st.st_gid;
341 if (!in_group_p(bprm->e_gid)) {
342 id_change = 1;
343 }
344 }
345
346 memset(bprm->buf, 0, sizeof(bprm->buf));
347 retval = lseek(bprm->fd, 0L, SEEK_SET);
348 if(retval >= 0) {
349 retval = read(bprm->fd, bprm->buf, 128);
350 }
351 if(retval < 0) {
352 perror("prepare_binprm");
353 exit(-1);
354 /* return(-errno); */
355 }
356 else {
357 return(retval);
358 }
359}
360
361unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
362 struct image_info * info)
363{
09bfb054 364 unsigned long stack_base, size, error;
31e31b8a 365 int i;
31e31b8a 366
09bfb054
FB
367 /* Create enough stack to hold everything. If we don't use
368 * it for args, we'll use it for something else...
369 */
370 size = x86_stack_size;
371 if (size < MAX_ARG_PAGES*X86_PAGE_SIZE)
372 size = MAX_ARG_PAGES*X86_PAGE_SIZE;
373 error = (unsigned long)mmap4k(NULL,
374 size + X86_PAGE_SIZE,
375 PROT_READ | PROT_WRITE,
376 MAP_PRIVATE | MAP_ANONYMOUS,
377 -1, 0);
378 if (error == -1) {
379 perror("stk mmap");
380 exit(-1);
381 }
382 /* we reserve one extra page at the top of the stack as guard */
383 mprotect((void *)(error + size), X86_PAGE_SIZE, PROT_NONE);
31e31b8a 384
09bfb054 385 stack_base = error + size - MAX_ARG_PAGES*X86_PAGE_SIZE;
31e31b8a 386 p += stack_base;
09bfb054 387
31e31b8a
FB
388 if (bprm->loader) {
389 bprm->loader += stack_base;
390 }
391 bprm->exec += stack_base;
392
31e31b8a
FB
393 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
394 if (bprm->page[i]) {
395 info->rss++;
396
397 memcpy((void *)stack_base, (void *)bprm->page[i], X86_PAGE_SIZE);
398 free_page((void *)bprm->page[i]);
399 }
400 stack_base += X86_PAGE_SIZE;
401 }
402 return p;
403}
404
405static void set_brk(unsigned long start, unsigned long end)
406{
407 /* page-align the start and end addresses... */
408 start = ALPHA_PAGE_ALIGN(start);
409 end = ALPHA_PAGE_ALIGN(end);
410 if (end <= start)
411 return;
412 if((long)mmap4k(start, end - start,
413 PROT_READ | PROT_WRITE | PROT_EXEC,
414 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
415 perror("cannot mmap brk");
416 exit(-1);
417 }
418}
419
420
421/* We need to explicitly zero any fractional pages
422 after the data section (i.e. bss). This would
423 contain the junk from the file that should not
424 be in memory */
425
426
427static void padzero(unsigned long elf_bss)
428{
429 unsigned long nbyte;
430 char * fpnt;
431
432 nbyte = elf_bss & (ALPHA_PAGE_SIZE-1); /* was X86_PAGE_SIZE - JRP */
433 if (nbyte) {
434 nbyte = ALPHA_PAGE_SIZE - nbyte;
435 fpnt = (char *) elf_bss;
436 do {
437 *fpnt++ = 0;
438 } while (--nbyte);
439 }
440}
441
442static unsigned int * create_elf_tables(char *p, int argc, int envc,
09bfb054
FB
443 struct elfhdr * exec,
444 unsigned long load_addr,
445 unsigned long load_bias,
446 unsigned long interp_load_addr, int ibcs,
447 struct image_info *info)
31e31b8a 448{
b17780d5
FB
449 target_ulong *argv, *envp, *dlinfo;
450 target_ulong *sp;
31e31b8a
FB
451
452 /*
453 * Force 16 byte alignment here for generality.
454 */
455 sp = (unsigned int *) (~15UL & (unsigned long) p);
456 sp -= exec ? DLINFO_ITEMS*2 : 2;
457 dlinfo = sp;
458 sp -= envc+1;
459 envp = sp;
460 sp -= argc+1;
461 argv = sp;
462 if (!ibcs) {
b17780d5
FB
463 put_user(tswapl((target_ulong)envp),--sp);
464 put_user(tswapl((target_ulong)argv),--sp);
31e31b8a 465 }
31e31b8a
FB
466
467#define NEW_AUX_ENT(id, val) \
b17780d5
FB
468 put_user (tswapl(id), dlinfo++); \
469 put_user (tswapl(val), dlinfo++)
31e31b8a
FB
470
471 if (exec) { /* Put this here for an ELF program interpreter */
09bfb054
FB
472 NEW_AUX_ENT (AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
473 NEW_AUX_ENT (AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
474 NEW_AUX_ENT (AT_PHNUM, (target_ulong)(exec->e_phnum));
475 NEW_AUX_ENT (AT_PAGESZ, (target_ulong)(ALPHA_PAGE_SIZE));
476 NEW_AUX_ENT (AT_BASE, (target_ulong)(interp_load_addr));
477 NEW_AUX_ENT (AT_FLAGS, (target_ulong)0);
478 NEW_AUX_ENT (AT_ENTRY, load_bias + exec->e_entry);
479 NEW_AUX_ENT (AT_UID, (target_ulong) getuid());
480 NEW_AUX_ENT (AT_EUID, (target_ulong) geteuid());
481 NEW_AUX_ENT (AT_GID, (target_ulong) getgid());
482 NEW_AUX_ENT (AT_EGID, (target_ulong) getegid());
31e31b8a
FB
483 }
484 NEW_AUX_ENT (AT_NULL, 0);
485#undef NEW_AUX_ENT
b17780d5 486 put_user(tswapl(argc),--sp);
31e31b8a
FB
487 info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
488 while (argc-->0) {
b17780d5 489 put_user(tswapl((target_ulong)p),argv++);
31e31b8a
FB
490 while (get_user(p++)) /* nothing */ ;
491 }
492 put_user(0,argv);
493 info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
31e31b8a 494 while (envc-->0) {
b17780d5 495 put_user(tswapl((target_ulong)p),envp++);
31e31b8a
FB
496 while (get_user(p++)) /* nothing */ ;
497 }
498 put_user(0,envp);
31e31b8a
FB
499 info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
500 return sp;
501}
502
503
504
505static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
506 int interpreter_fd,
507 unsigned long *interp_load_addr)
508{
509 struct elf_phdr *elf_phdata = NULL;
510 struct elf_phdr *eppnt;
09bfb054 511 unsigned long load_addr = 0;
31e31b8a
FB
512 int load_addr_set = 0;
513 int retval;
514 unsigned long last_bss, elf_bss;
515 unsigned long error;
516 int i;
517
518 elf_bss = 0;
519 last_bss = 0;
520 error = 0;
521
644c433c
FB
522#ifdef BSWAP_NEEDED
523 bswap_ehdr(interp_elf_ex);
524#endif
31e31b8a
FB
525 /* First of all, some simple consistency checks */
526 if ((interp_elf_ex->e_type != ET_EXEC &&
09bfb054 527 interp_elf_ex->e_type != ET_DYN) ||
31e31b8a
FB
528 !elf_check_arch(interp_elf_ex->e_machine)) {
529 return ~0UL;
530 }
531
644c433c 532
31e31b8a
FB
533 /* Now read in all of the header information */
534
535 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > X86_PAGE_SIZE)
536 return ~0UL;
537
538 elf_phdata = (struct elf_phdr *)
539 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
540
541 if (!elf_phdata)
542 return ~0UL;
543
544 /*
545 * If the size of this structure has changed, then punt, since
546 * we will be doing the wrong thing.
547 */
09bfb054 548 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
31e31b8a
FB
549 free(elf_phdata);
550 return ~0UL;
09bfb054 551 }
31e31b8a
FB
552
553 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
554 if(retval >= 0) {
555 retval = read(interpreter_fd,
556 (char *) elf_phdata,
557 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
558 }
31e31b8a
FB
559 if (retval < 0) {
560 perror("load_elf_interp");
561 exit(-1);
562 free (elf_phdata);
563 return retval;
564 }
565#ifdef BSWAP_NEEDED
566 eppnt = elf_phdata;
567 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
568 bswap_phdr(eppnt);
569 }
570#endif
09bfb054
FB
571
572 if (interp_elf_ex->e_type == ET_DYN) {
573 /* in order to avoid harcoding the interpreter load
574 address in qemu, we allocate a big enough memory zone */
575 error = (unsigned long)mmap4k(NULL, INTERP_MAP_SIZE,
576 PROT_NONE, MAP_PRIVATE | MAP_ANON,
577 -1, 0);
578 if (error == -1) {
579 perror("mmap");
580 exit(-1);
581 }
582 load_addr = error;
583 load_addr_set = 1;
584 }
585
31e31b8a
FB
586 eppnt = elf_phdata;
587 for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
588 if (eppnt->p_type == PT_LOAD) {
589 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
590 int elf_prot = 0;
591 unsigned long vaddr = 0;
592 unsigned long k;
593
594 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
595 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
596 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
597 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
598 elf_type |= MAP_FIXED;
599 vaddr = eppnt->p_vaddr;
600 }
601 error = (unsigned long)mmap4k(load_addr+X86_ELF_PAGESTART(vaddr),
602 eppnt->p_filesz + X86_ELF_PAGEOFFSET(eppnt->p_vaddr),
603 elf_prot,
604 elf_type,
605 interpreter_fd,
606 eppnt->p_offset - X86_ELF_PAGEOFFSET(eppnt->p_vaddr));
607
608 if (error > -1024UL) {
609 /* Real error */
610 close(interpreter_fd);
611 free(elf_phdata);
612 return ~0UL;
613 }
614
615 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
616 load_addr = error;
617 load_addr_set = 1;
618 }
619
620 /*
621 * Find the end of the file mapping for this phdr, and keep
622 * track of the largest address we see for this.
623 */
624 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
625 if (k > elf_bss) elf_bss = k;
626
627 /*
628 * Do the same thing for the memory mapping - between
629 * elf_bss and last_bss is the bss section.
630 */
631 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
632 if (k > last_bss) last_bss = k;
633 }
634
635 /* Now use mmap to map the library into memory. */
636
637 close(interpreter_fd);
638
639 /*
640 * Now fill out the bss section. First pad the last page up
641 * to the page boundary, and then perform a mmap to make sure
642 * that there are zeromapped pages up to and including the last
643 * bss page.
644 */
645 padzero(elf_bss);
646 elf_bss = X86_ELF_PAGESTART(elf_bss + ALPHA_PAGE_SIZE - 1); /* What we have mapped so far */
647
648 /* Map the last of the bss segment */
649 if (last_bss > elf_bss) {
650 mmap4k(elf_bss, last_bss-elf_bss,
651 PROT_READ|PROT_WRITE|PROT_EXEC,
652 MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
653 }
654 free(elf_phdata);
655
656 *interp_load_addr = load_addr;
657 return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
658}
659
660
661
b17780d5
FB
662static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
663 struct image_info * info)
31e31b8a
FB
664{
665 struct elfhdr elf_ex;
666 struct elfhdr interp_elf_ex;
667 struct exec interp_ex;
668 int interpreter_fd = -1; /* avoid warning */
09bfb054 669 unsigned long load_addr, load_bias;
31e31b8a
FB
670 int load_addr_set = 0;
671 unsigned int interpreter_type = INTERPRETER_NONE;
672 unsigned char ibcs2_interpreter;
673 int i;
674 void * mapped_addr;
675 struct elf_phdr * elf_ppnt;
676 struct elf_phdr *elf_phdata;
677 unsigned long elf_bss, k, elf_brk;
678 int retval;
679 char * elf_interpreter;
680 unsigned long elf_entry, interp_load_addr = 0;
681 int status;
682 unsigned long start_code, end_code, end_data;
683 unsigned long elf_stack;
684 char passed_fileno[6];
685
686 ibcs2_interpreter = 0;
687 status = 0;
688 load_addr = 0;
09bfb054 689 load_bias = 0;
31e31b8a
FB
690 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
691#ifdef BSWAP_NEEDED
692 bswap_ehdr(&elf_ex);
693#endif
694
695 if (elf_ex.e_ident[0] != 0x7f ||
696 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
697 return -ENOEXEC;
698 }
699
31e31b8a
FB
700 /* First of all, some simple consistency checks */
701 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
702 (! elf_check_arch(elf_ex.e_machine))) {
703 return -ENOEXEC;
704 }
705
706 /* Now read in all of the header information */
707
708 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
709 if (elf_phdata == NULL) {
710 return -ENOMEM;
711 }
712
713 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
714 if(retval > 0) {
715 retval = read(bprm->fd, (char *) elf_phdata,
716 elf_ex.e_phentsize * elf_ex.e_phnum);
717 }
718
719 if (retval < 0) {
720 perror("load_elf_binary");
721 exit(-1);
722 free (elf_phdata);
723 return -errno;
724 }
725
b17780d5
FB
726#ifdef BSWAP_NEEDED
727 elf_ppnt = elf_phdata;
728 for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
729 bswap_phdr(elf_ppnt);
730 }
731#endif
31e31b8a
FB
732 elf_ppnt = elf_phdata;
733
734 elf_bss = 0;
735 elf_brk = 0;
736
737
738 elf_stack = ~0UL;
739 elf_interpreter = NULL;
740 start_code = ~0UL;
741 end_code = 0;
742 end_data = 0;
743
744 for(i=0;i < elf_ex.e_phnum; i++) {
745 if (elf_ppnt->p_type == PT_INTERP) {
746 if ( elf_interpreter != NULL )
747 {
748 free (elf_phdata);
749 free(elf_interpreter);
750 close(bprm->fd);
751 return -EINVAL;
752 }
753
754 /* This is the program interpreter used for
755 * shared libraries - for now assume that this
756 * is an a.out format binary
757 */
758
d691f669
FB
759 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+
760 strlen(bprm->interp_prefix));
31e31b8a
FB
761
762 if (elf_interpreter == NULL) {
763 free (elf_phdata);
764 close(bprm->fd);
765 return -ENOMEM;
766 }
767
d691f669 768 strcpy(elf_interpreter, bprm->interp_prefix);
31e31b8a
FB
769 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
770 if(retval >= 0) {
771 retval = read(bprm->fd,
d691f669 772 elf_interpreter+strlen(bprm->interp_prefix),
31e31b8a
FB
773 elf_ppnt->p_filesz);
774 }
775 if(retval < 0) {
776 perror("load_elf_binary2");
777 exit(-1);
778 }
779
780 /* If the program interpreter is one of these two,
781 then assume an iBCS2 image. Otherwise assume
782 a native linux image. */
783
784 /* JRP - Need to add X86 lib dir stuff here... */
785
786 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
787 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
788 ibcs2_interpreter = 1;
789 }
790
791#if 0
792 printf("Using ELF interpreter %s\n", elf_interpreter);
793#endif
794 if (retval >= 0) {
795 retval = open(elf_interpreter, O_RDONLY);
796 if(retval >= 0) {
797 interpreter_fd = retval;
798 }
799 else {
800 perror(elf_interpreter);
801 exit(-1);
802 /* retval = -errno; */
803 }
804 }
805
806 if (retval >= 0) {
807 retval = lseek(interpreter_fd, 0, SEEK_SET);
808 if(retval >= 0) {
809 retval = read(interpreter_fd,bprm->buf,128);
810 }
811 }
812 if (retval >= 0) {
813 interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
814 interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
815 }
816 if (retval < 0) {
817 perror("load_elf_binary3");
818 exit(-1);
819 free (elf_phdata);
820 free(elf_interpreter);
821 close(bprm->fd);
822 return retval;
823 }
824 }
825 elf_ppnt++;
826 }
827
828 /* Some simple consistency checks for the interpreter */
829 if (elf_interpreter){
830 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
831
832 /* Now figure out which format our binary is */
833 if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
834 (N_MAGIC(interp_ex) != QMAGIC)) {
835 interpreter_type = INTERPRETER_ELF;
836 }
837
838 if (interp_elf_ex.e_ident[0] != 0x7f ||
839 strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
840 interpreter_type &= ~INTERPRETER_ELF;
841 }
842
843 if (!interpreter_type) {
844 free(elf_interpreter);
845 free(elf_phdata);
846 close(bprm->fd);
847 return -ELIBBAD;
848 }
849 }
850
851 /* OK, we are done with that, now set up the arg stuff,
852 and then start this sucker up */
853
854 if (!bprm->sh_bang) {
855 char * passed_p;
856
857 if (interpreter_type == INTERPRETER_AOUT) {
858 sprintf(passed_fileno, "%d", bprm->fd);
859 passed_p = passed_fileno;
860
861 if (elf_interpreter) {
862 bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
863 bprm->argc++;
864 }
865 }
866 if (!bprm->p) {
867 if (elf_interpreter) {
868 free(elf_interpreter);
869 }
870 free (elf_phdata);
871 close(bprm->fd);
872 return -E2BIG;
873 }
874 }
875
876 /* OK, This is the point of no return */
877 info->end_data = 0;
878 info->end_code = 0;
879 info->start_mmap = (unsigned long)ELF_START_MMAP;
880 info->mmap = 0;
881 elf_entry = (unsigned long) elf_ex.e_entry;
882
883 /* Do this so that we can load the interpreter, if need be. We will
884 change some of these later */
885 info->rss = 0;
886 bprm->p = setup_arg_pages(bprm->p, bprm, info);
887 info->start_stack = bprm->p;
888
889 /* Now we do a little grungy work by mmaping the ELF image into
890 * the correct location in memory. At this point, we assume that
891 * the image should be loaded at fixed address, not at a variable
892 * address.
893 */
894
31e31b8a 895 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
09bfb054
FB
896 int elf_prot = 0;
897 int elf_flags = 0;
898 unsigned long error;
899
900 if (elf_ppnt->p_type != PT_LOAD)
901 continue;
902
903 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
904 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
905 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
906 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
907 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
908 elf_flags |= MAP_FIXED;
909 } else if (elf_ex.e_type == ET_DYN) {
910 /* Try and get dynamic programs out of the way of the default mmap
911 base, as well as whatever program they might try to exec. This
912 is because the brk will follow the loader, and is not movable. */
913 /* NOTE: for qemu, we do a big mmap to get enough space
914 without harcoding any address */
915 error = (unsigned long)mmap4k(NULL, ET_DYN_MAP_SIZE,
916 PROT_NONE, MAP_PRIVATE | MAP_ANON,
917 -1, 0);
918 if (error == -1) {
919 perror("mmap");
920 exit(-1);
921 }
922 load_bias = X86_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
923 }
924
925 error = (unsigned long)mmap4k(
926 X86_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
927 (elf_ppnt->p_filesz +
928 X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
929 elf_prot,
930 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
931 bprm->fd,
932 (elf_ppnt->p_offset -
933 X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
934 if (error == -1) {
935 perror("mmap");
936 exit(-1);
937 }
31e31b8a
FB
938
939#ifdef LOW_ELF_STACK
09bfb054
FB
940 if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
941 elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr);
31e31b8a 942#endif
09bfb054
FB
943
944 if (!load_addr_set) {
945 load_addr_set = 1;
946 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
947 if (elf_ex.e_type == ET_DYN) {
948 load_bias += error -
949 X86_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
950 load_addr += load_bias;
951 }
952 }
953 k = elf_ppnt->p_vaddr;
954 if (k < start_code)
955 start_code = k;
956 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
957 if (k > elf_bss)
958 elf_bss = k;
959 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
960 end_code = k;
961 if (end_data < k)
962 end_data = k;
963 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
964 if (k > elf_brk) elf_brk = k;
31e31b8a
FB
965 }
966
09bfb054
FB
967 elf_entry += load_bias;
968 elf_bss += load_bias;
969 elf_brk += load_bias;
970 start_code += load_bias;
971 end_code += load_bias;
972 // start_data += load_bias;
973 end_data += load_bias;
974
31e31b8a
FB
975 if (elf_interpreter) {
976 if (interpreter_type & 1) {
977 elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
978 }
979 else if (interpreter_type & 2) {
980 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
981 &interp_load_addr);
982 }
983
984 close(interpreter_fd);
985 free(elf_interpreter);
986
987 if (elf_entry == ~0UL) {
988 printf("Unable to load interpreter\n");
989 free(elf_phdata);
990 exit(-1);
991 return 0;
992 }
993 }
994
995 free(elf_phdata);
996
997 if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
998 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
999
1000#ifdef LOW_ELF_STACK
1001 info->start_stack = bprm->p = elf_stack - 4;
1002#endif
1003 bprm->p = (unsigned long)
1004 create_elf_tables((char *)bprm->p,
1005 bprm->argc,
1006 bprm->envc,
1007 (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
09bfb054 1008 load_addr, load_bias,
31e31b8a
FB
1009 interp_load_addr,
1010 (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
1011 info);
1012 if (interpreter_type == INTERPRETER_AOUT)
1013 info->arg_start += strlen(passed_fileno) + 1;
1014 info->start_brk = info->brk = elf_brk;
1015 info->end_code = end_code;
1016 info->start_code = start_code;
1017 info->end_data = end_data;
1018 info->start_stack = bprm->p;
1019
1020 /* Calling set_brk effectively mmaps the pages that we need for the bss and break
1021 sections */
1022 set_brk(elf_bss, elf_brk);
1023
1024 padzero(elf_bss);
1025
1026#if 0
1027 printf("(start_brk) %x\n" , info->start_brk);
1028 printf("(end_code) %x\n" , info->end_code);
1029 printf("(start_code) %x\n" , info->start_code);
1030 printf("(end_data) %x\n" , info->end_data);
1031 printf("(start_stack) %x\n" , info->start_stack);
1032 printf("(brk) %x\n" , info->brk);
1033#endif
1034
1035 if ( info->personality == PER_SVR4 )
1036 {
1037 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
1038 and some applications "depend" upon this behavior.
1039 Since we do not have the power to recompile these, we
1040 emulate the SVr4 behavior. Sigh. */
1041 mapped_addr = mmap4k(NULL, ALPHA_PAGE_SIZE, PROT_READ | PROT_EXEC,
1042 MAP_FIXED | MAP_PRIVATE, -1, 0);
1043 }
1044
1045#ifdef ELF_PLAT_INIT
1046 /*
1047 * The ABI may specify that certain registers be set up in special
1048 * ways (on i386 %edx is the address of a DT_FINI function, for
1049 * example. This macro performs whatever initialization to
1050 * the regs structure is required.
1051 */
1052 ELF_PLAT_INIT(regs);
1053#endif
1054
1055
1056 info->entry = elf_entry;
1057
1058 return 0;
1059}
1060
1061
1062
d691f669
FB
1063int elf_exec(const char *interp_prefix,
1064 const char * filename, char ** argv, char ** envp,
b17780d5 1065 struct target_pt_regs * regs, struct image_info *infop)
31e31b8a
FB
1066{
1067 struct linux_binprm bprm;
1068 int retval;
1069 int i;
1070
1071 bprm.p = X86_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
1072 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
1073 bprm.page[i] = 0;
1074 retval = open(filename, O_RDONLY);
1075 if (retval == -1) {
1076 perror(filename);
1077 exit(-1);
1078 /* return retval; */
1079 }
1080 else {
1081 bprm.fd = retval;
1082 }
d691f669 1083 bprm.interp_prefix = (char *)interp_prefix;
31e31b8a
FB
1084 bprm.filename = (char *)filename;
1085 bprm.sh_bang = 0;
1086 bprm.loader = 0;
1087 bprm.exec = 0;
1088 bprm.dont_iput = 0;
1089 bprm.argc = count(argv);
1090 bprm.envc = count(envp);
1091
1092 retval = prepare_binprm(&bprm);
1093
1094 if(retval>=0) {
1095 bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p);
1096 bprm.exec = bprm.p;
1097 bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p);
1098 bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p);
1099 if (!bprm.p) {
1100 retval = -E2BIG;
1101 }
1102 }
1103
1104 if(retval>=0) {
1105 retval = load_elf_binary(&bprm,regs,infop);
1106 }
1107 if(retval>=0) {
1108 /* success. Initialize important registers */
1109 regs->esp = infop->start_stack;
1110 regs->eip = infop->entry;
1111 return retval;
1112 }
1113
1114 /* Something went wrong, return the inode and free the argument pages*/
1115 for (i=0 ; i<MAX_ARG_PAGES ; i++) {
1116 free_page((void *)bprm.page[i]);
1117 }
1118 return(retval);
1119}
1120
1121
1122static int load_aout_interp(void * exptr, int interp_fd)
1123{
1124 printf("a.out interpreter not yet supported\n");
1125 return(0);
1126}
1127
This page took 0.197267 seconds and 4 git commands to generate.