1 /* This is the Linux kernel elf-loading code, ported into user space */
17 #define ELF_START_MMAP 0x80000000
19 typedef uint32_t elf_greg_t;
21 #define ELF_NGREG (sizeof (struct target_pt_regs) / sizeof(elf_greg_t))
22 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
24 typedef struct user_i387_struct elf_fpregset_t;
27 * This is used to ensure we don't load something for the wrong architecture.
29 #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
32 * These are used to set parameters in the core dumps.
34 #define ELF_CLASS ELFCLASS32
35 #define ELF_DATA ELFDATA2LSB
36 #define ELF_ARCH EM_386
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.
44 A value of 0 tells we have no such handler. */
45 #define ELF_PLAT_INIT(_r) _r->edx = 0
47 #define USE_ELF_CORE_DUMP
48 #define ELF_EXEC_PAGESIZE 4096
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!
59 #define MAX_ARG_PAGES 32
62 * This structure is used to hold the arguments that are
63 * used when loading binaries.
67 unsigned long page[MAX_ARG_PAGES];
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 */
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 */
92 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
98 #define X86_STACK_TOP 0x7d000000
100 /* max code+data+bss space allocated to elf interpreter */
101 #define INTERP_MAP_SIZE (32 * 1024 * 1024)
103 /* max code+data+bss+brk space allocated to ET_DYN executables */
104 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
106 /* from personality.h */
108 /* Flags for bug emulation. These occupy the top three bytes. */
109 #define STICKY_TIMEOUTS 0x4000000
110 #define WHOLE_SECONDS 0x2000000
112 /* Personality types. These go in the low byte. Avoid using the top bit,
113 * it will conflict with error returns.
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)
125 /* Necessary parameters */
126 #define ALPHA_PAGE_SIZE 4096
127 #define X86_PAGE_SIZE 4096
129 #define ALPHA_PAGE_MASK (~(ALPHA_PAGE_SIZE-1))
130 #define X86_PAGE_MASK (~(X86_PAGE_SIZE-1))
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)
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))
141 #define ALPHA_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ALPHA_PAGE_SIZE-1))
142 #define ALPHA_ELF_PAGEOFFSET(_v) ((_v) & (ALPHA_PAGE_SIZE-1))
144 #define INTERPRETER_NONE 0
145 #define INTERPRETER_AOUT 1
146 #define INTERPRETER_ELF 2
148 #define DLINFO_ITEMS 12
150 #define put_user(x,ptr) (void)(*(ptr) = (typeof(*ptr))(x))
151 #define get_user(ptr) (typeof(*ptr))(*(ptr))
153 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
158 static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
163 //extern void * mmap4k();
164 #define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
166 extern unsigned long x86_stack_size;
168 static int load_aout_interp(void * exptr, int interp_fd);
171 static void bswap_ehdr(Elf32_Ehdr *ehdr)
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 */
188 static void bswap_phdr(Elf32_Phdr *phdr)
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 */
201 static void * get_free_page(void)
205 /* User-space version of kernel get_free_page. Returns a page-aligned
206 * page-sized chunk of memory.
208 retval = mmap4k(0, ALPHA_PAGE_SIZE, PROT_READ|PROT_WRITE,
209 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
211 if((long)retval == -1) {
212 perror("get_free_page");
220 static void free_page(void * pageaddr)
222 (void)munmap(pageaddr, ALPHA_PAGE_SIZE);
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.
231 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
234 char *tmp, *tmp1, *pag = NULL;
238 return 0; /* bullet-proofing */
241 if (!(tmp1 = tmp = get_user(argv+argc))) {
242 fprintf(stderr, "VFS: argc is wrong");
245 while (get_user(tmp++));
247 if (p < len) { /* this shouldn't happen - 128kB */
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())) {
260 if (len == 0 || offset == 0) {
261 *(pag + offset) = get_user(tmp);
264 int bytes_to_copy = (len > offset) ? offset : len;
265 tmp -= bytes_to_copy;
267 offset -= bytes_to_copy;
268 len -= bytes_to_copy;
269 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
276 static int in_group_p(gid_t g)
278 /* return TRUE if we're in the specified group, FALSE otherwise */
281 gid_t grouplist[NGROUPS];
283 ngroup = getgroups(NGROUPS, grouplist);
284 for(i = 0; i < ngroup; i++) {
285 if(grouplist[i] == g) {
292 static int count(char ** vec)
296 for(i = 0; *vec; i++) {
303 static int prepare_binprm(struct linux_binprm *bprm)
307 int retval, id_change;
309 if(fstat(bprm->fd, &st) < 0) {
314 if(!S_ISREG(mode)) { /* Must be regular file */
317 if(!(mode & 0111)) { /* Must have at least one execute bit set */
321 bprm->e_uid = geteuid();
322 bprm->e_gid = getegid();
327 bprm->e_uid = st.st_uid;
328 if(bprm->e_uid != geteuid()) {
335 * If setgid is set but no group execute bit then this
336 * is a candidate for mandatory locking, not a setgid
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)) {
346 memset(bprm->buf, 0, sizeof(bprm->buf));
347 retval = lseek(bprm->fd, 0L, SEEK_SET);
349 retval = read(bprm->fd, bprm->buf, 128);
352 perror("prepare_binprm");
354 /* return(-errno); */
361 unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
362 struct image_info * info)
364 unsigned long stack_base, size, error;
367 /* Create enough stack to hold everything. If we don't use
368 * it for args, we'll use it for something else...
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,
382 /* we reserve one extra page at the top of the stack as guard */
383 mprotect((void *)(error + size), X86_PAGE_SIZE, PROT_NONE);
385 stack_base = error + size - MAX_ARG_PAGES*X86_PAGE_SIZE;
389 bprm->loader += stack_base;
391 bprm->exec += stack_base;
393 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
397 memcpy((void *)stack_base, (void *)bprm->page[i], X86_PAGE_SIZE);
398 free_page((void *)bprm->page[i]);
400 stack_base += X86_PAGE_SIZE;
405 static void set_brk(unsigned long start, unsigned long end)
407 /* page-align the start and end addresses... */
408 start = ALPHA_PAGE_ALIGN(start);
409 end = ALPHA_PAGE_ALIGN(end);
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");
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
427 static void padzero(unsigned long elf_bss)
432 nbyte = elf_bss & (ALPHA_PAGE_SIZE-1); /* was X86_PAGE_SIZE - JRP */
434 nbyte = ALPHA_PAGE_SIZE - nbyte;
435 fpnt = (char *) elf_bss;
442 static unsigned int * create_elf_tables(char *p, int argc, int envc,
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)
449 target_ulong *argv, *envp, *dlinfo;
453 * Force 16 byte alignment here for generality.
455 sp = (unsigned int *) (~15UL & (unsigned long) p);
456 sp -= exec ? DLINFO_ITEMS*2 : 2;
463 put_user(tswapl((target_ulong)envp),--sp);
464 put_user(tswapl((target_ulong)argv),--sp);
467 #define NEW_AUX_ENT(id, val) \
468 put_user (tswapl(id), dlinfo++); \
469 put_user (tswapl(val), dlinfo++)
471 if (exec) { /* Put this here for an ELF program interpreter */
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());
484 NEW_AUX_ENT (AT_NULL, 0);
486 put_user(tswapl(argc),--sp);
487 info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
489 put_user(tswapl((target_ulong)p),argv++);
490 while (get_user(p++)) /* nothing */ ;
493 info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
495 put_user(tswapl((target_ulong)p),envp++);
496 while (get_user(p++)) /* nothing */ ;
499 info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
505 static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
507 unsigned long *interp_load_addr)
509 struct elf_phdr *elf_phdata = NULL;
510 struct elf_phdr *eppnt;
511 unsigned long load_addr = 0;
512 int load_addr_set = 0;
514 unsigned long last_bss, elf_bss;
523 bswap_ehdr(interp_elf_ex);
525 /* First of all, some simple consistency checks */
526 if ((interp_elf_ex->e_type != ET_EXEC &&
527 interp_elf_ex->e_type != ET_DYN) ||
528 !elf_check_arch(interp_elf_ex->e_machine)) {
533 /* Now read in all of the header information */
535 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > X86_PAGE_SIZE)
538 elf_phdata = (struct elf_phdr *)
539 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
545 * If the size of this structure has changed, then punt, since
546 * we will be doing the wrong thing.
548 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
553 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
555 retval = read(interpreter_fd,
557 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
560 perror("load_elf_interp");
567 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
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,
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;
591 unsigned long vaddr = 0;
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;
601 error = (unsigned long)mmap4k(load_addr+X86_ELF_PAGESTART(vaddr),
602 eppnt->p_filesz + X86_ELF_PAGEOFFSET(eppnt->p_vaddr),
606 eppnt->p_offset - X86_ELF_PAGEOFFSET(eppnt->p_vaddr));
608 if (error > -1024UL) {
610 close(interpreter_fd);
615 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
621 * Find the end of the file mapping for this phdr, and keep
622 * track of the largest address we see for this.
624 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
625 if (k > elf_bss) elf_bss = k;
628 * Do the same thing for the memory mapping - between
629 * elf_bss and last_bss is the bss section.
631 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
632 if (k > last_bss) last_bss = k;
635 /* Now use mmap to map the library into memory. */
637 close(interpreter_fd);
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
646 elf_bss = X86_ELF_PAGESTART(elf_bss + ALPHA_PAGE_SIZE - 1); /* What we have mapped so far */
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);
656 *interp_load_addr = load_addr;
657 return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
662 static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
663 struct image_info * info)
665 struct elfhdr elf_ex;
666 struct elfhdr interp_elf_ex;
667 struct exec interp_ex;
668 int interpreter_fd = -1; /* avoid warning */
669 unsigned long load_addr, load_bias;
670 int load_addr_set = 0;
671 unsigned int interpreter_type = INTERPRETER_NONE;
672 unsigned char ibcs2_interpreter;
675 struct elf_phdr * elf_ppnt;
676 struct elf_phdr *elf_phdata;
677 unsigned long elf_bss, k, elf_brk;
679 char * elf_interpreter;
680 unsigned long elf_entry, interp_load_addr = 0;
682 unsigned long start_code, end_code, end_data;
683 unsigned long elf_stack;
684 char passed_fileno[6];
686 ibcs2_interpreter = 0;
690 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
695 if (elf_ex.e_ident[0] != 0x7f ||
696 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
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))) {
706 /* Now read in all of the header information */
708 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
709 if (elf_phdata == NULL) {
713 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
715 retval = read(bprm->fd, (char *) elf_phdata,
716 elf_ex.e_phentsize * elf_ex.e_phnum);
720 perror("load_elf_binary");
727 elf_ppnt = elf_phdata;
728 for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
729 bswap_phdr(elf_ppnt);
732 elf_ppnt = elf_phdata;
739 elf_interpreter = NULL;
744 for(i=0;i < elf_ex.e_phnum; i++) {
745 if (elf_ppnt->p_type == PT_INTERP) {
746 if ( elf_interpreter != NULL )
749 free(elf_interpreter);
754 /* This is the program interpreter used for
755 * shared libraries - for now assume that this
756 * is an a.out format binary
759 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+
760 strlen(bprm->interp_prefix));
762 if (elf_interpreter == NULL) {
768 strcpy(elf_interpreter, bprm->interp_prefix);
769 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
771 retval = read(bprm->fd,
772 elf_interpreter+strlen(bprm->interp_prefix),
776 perror("load_elf_binary2");
780 /* If the program interpreter is one of these two,
781 then assume an iBCS2 image. Otherwise assume
782 a native linux image. */
784 /* JRP - Need to add X86 lib dir stuff here... */
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;
792 printf("Using ELF interpreter %s\n", elf_interpreter);
795 retval = open(elf_interpreter, O_RDONLY);
797 interpreter_fd = retval;
800 perror(elf_interpreter);
802 /* retval = -errno; */
807 retval = lseek(interpreter_fd, 0, SEEK_SET);
809 retval = read(interpreter_fd,bprm->buf,128);
813 interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
814 interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
817 perror("load_elf_binary3");
820 free(elf_interpreter);
828 /* Some simple consistency checks for the interpreter */
829 if (elf_interpreter){
830 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
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;
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;
843 if (!interpreter_type) {
844 free(elf_interpreter);
851 /* OK, we are done with that, now set up the arg stuff,
852 and then start this sucker up */
854 if (!bprm->sh_bang) {
857 if (interpreter_type == INTERPRETER_AOUT) {
858 sprintf(passed_fileno, "%d", bprm->fd);
859 passed_p = passed_fileno;
861 if (elf_interpreter) {
862 bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
867 if (elf_interpreter) {
868 free(elf_interpreter);
876 /* OK, This is the point of no return */
879 info->start_mmap = (unsigned long)ELF_START_MMAP;
881 elf_entry = (unsigned long) elf_ex.e_entry;
883 /* Do this so that we can load the interpreter, if need be. We will
884 change some of these later */
886 bprm->p = setup_arg_pages(bprm->p, bprm, info);
887 info->start_stack = bprm->p;
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
895 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
900 if (elf_ppnt->p_type != PT_LOAD)
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,
922 load_bias = X86_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
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)),
930 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
932 (elf_ppnt->p_offset -
933 X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
940 if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
941 elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr);
944 if (!load_addr_set) {
946 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
947 if (elf_ex.e_type == ET_DYN) {
949 X86_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
950 load_addr += load_bias;
953 k = elf_ppnt->p_vaddr;
956 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
959 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
963 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
964 if (k > elf_brk) elf_brk = k;
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;
975 if (elf_interpreter) {
976 if (interpreter_type & 1) {
977 elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
979 else if (interpreter_type & 2) {
980 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
984 close(interpreter_fd);
985 free(elf_interpreter);
987 if (elf_entry == ~0UL) {
988 printf("Unable to load interpreter\n");
997 if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
998 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
1000 #ifdef LOW_ELF_STACK
1001 info->start_stack = bprm->p = elf_stack - 4;
1003 bprm->p = (unsigned long)
1004 create_elf_tables((char *)bprm->p,
1007 (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
1008 load_addr, load_bias,
1010 (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
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;
1020 /* Calling set_brk effectively mmaps the pages that we need for the bss and break
1022 set_brk(elf_bss, elf_brk);
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);
1035 if ( info->personality == PER_SVR4 )
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);
1045 #ifdef ELF_PLAT_INIT
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.
1052 ELF_PLAT_INIT(regs);
1056 info->entry = elf_entry;
1063 int elf_exec(const char *interp_prefix,
1064 const char * filename, char ** argv, char ** envp,
1065 struct target_pt_regs * regs, struct image_info *infop)
1067 struct linux_binprm bprm;
1071 bprm.p = X86_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
1072 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
1074 retval = open(filename, O_RDONLY);
1078 /* return retval; */
1083 bprm.interp_prefix = (char *)interp_prefix;
1084 bprm.filename = (char *)filename;
1089 bprm.argc = count(argv);
1090 bprm.envc = count(envp);
1092 retval = prepare_binprm(&bprm);
1095 bprm.p = copy_strings(1, &bprm.filename, bprm.page, 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);
1105 retval = load_elf_binary(&bprm,regs,infop);
1108 /* success. Initialize important registers */
1109 regs->esp = infop->start_stack;
1110 regs->eip = infop->entry;
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]);
1122 static int load_aout_interp(void * exptr, int interp_fd)
1124 printf("a.out interpreter not yet supported\n");