1 /* This is the Linux kernel elf-loading code, ported into user space */
15 #include "linux_bin.h"
19 /* Necessary parameters */
20 #define ALPHA_PAGE_SIZE 4096
21 #define X86_PAGE_SIZE 4096
23 #define ALPHA_PAGE_MASK (~(ALPHA_PAGE_SIZE-1))
24 #define X86_PAGE_MASK (~(X86_PAGE_SIZE-1))
26 #define ALPHA_PAGE_ALIGN(addr) ((((addr)+ALPHA_PAGE_SIZE)-1)&ALPHA_PAGE_MASK)
27 #define X86_PAGE_ALIGN(addr) ((((addr)+X86_PAGE_SIZE)-1)&X86_PAGE_MASK)
31 #define X86_ELF_EXEC_PAGESIZE X86_PAGE_SIZE
32 #define X86_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(X86_ELF_EXEC_PAGESIZE-1))
33 #define X86_ELF_PAGEOFFSET(_v) ((_v) & (X86_ELF_EXEC_PAGESIZE-1))
35 #define ALPHA_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ALPHA_PAGE_SIZE-1))
36 #define ALPHA_ELF_PAGEOFFSET(_v) ((_v) & (ALPHA_PAGE_SIZE-1))
38 #define INTERPRETER_NONE 0
39 #define INTERPRETER_AOUT 1
40 #define INTERPRETER_ELF 2
42 #define DLINFO_ITEMS 12
44 /* Where we find X86 libraries... */
47 //extern void * mmap4k();
48 #define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
50 extern unsigned long x86_stack_size;
52 static int load_aout_interp(void * exptr, int interp_fd);
55 static void bswap_ehdr(Elf32_Ehdr *ehdr)
57 bswap16s(&ehdr->e_type); /* Object file type */
58 bswap16s(&ehdr->e_machine); /* Architecture */
59 bswap32s(&ehdr->e_version); /* Object file version */
60 bswap32s(&ehdr->e_entry); /* Entry point virtual address */
61 bswap32s(&ehdr->e_phoff); /* Program header table file offset */
62 bswap32s(&ehdr->e_shoff); /* Section header table file offset */
63 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
64 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
65 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
66 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
67 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
68 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
69 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
72 static void bswap_phdr(Elf32_Phdr *phdr)
74 bswap32s(&phdr->p_type); /* Segment type */
75 bswap32s(&phdr->p_offset); /* Segment file offset */
76 bswap32s(&phdr->p_vaddr); /* Segment virtual address */
77 bswap32s(&phdr->p_paddr); /* Segment physical address */
78 bswap32s(&phdr->p_filesz); /* Segment size in file */
79 bswap32s(&phdr->p_memsz); /* Segment size in memory */
80 bswap32s(&phdr->p_flags); /* Segment flags */
81 bswap32s(&phdr->p_align); /* Segment alignment */
85 static void * get_free_page(void)
89 /* User-space version of kernel get_free_page. Returns a page-aligned
90 * page-sized chunk of memory.
92 retval = mmap4k(0, ALPHA_PAGE_SIZE, PROT_READ|PROT_WRITE,
93 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
95 if((long)retval == -1) {
96 perror("get_free_page");
104 static void free_page(void * pageaddr)
106 (void)munmap(pageaddr, ALPHA_PAGE_SIZE);
110 * 'copy_string()' copies argument/envelope strings from user
111 * memory to free pages in kernel mem. These are in a format ready
112 * to be put directly into the top of new user memory.
115 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
118 char *tmp, *tmp1, *pag = NULL;
122 return 0; /* bullet-proofing */
125 if (!(tmp1 = tmp = get_user(argv+argc))) {
126 fprintf(stderr, "VFS: argc is wrong");
129 while (get_user(tmp++));
131 if (p < len) { /* this shouldn't happen - 128kB */
137 offset = p % X86_PAGE_SIZE;
138 if (!(pag = (char *) page[p/X86_PAGE_SIZE]) &&
139 !(pag = (char *) page[p/X86_PAGE_SIZE] =
140 (unsigned long *) get_free_page())) {
144 if (len == 0 || offset == 0) {
145 *(pag + offset) = get_user(tmp);
148 int bytes_to_copy = (len > offset) ? offset : len;
149 tmp -= bytes_to_copy;
151 offset -= bytes_to_copy;
152 len -= bytes_to_copy;
153 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
160 static int in_group_p(gid_t g)
162 /* return TRUE if we're in the specified group, FALSE otherwise */
165 gid_t grouplist[NGROUPS];
167 ngroup = getgroups(NGROUPS, grouplist);
168 for(i = 0; i < ngroup; i++) {
169 if(grouplist[i] == g) {
176 static int count(char ** vec)
180 for(i = 0; *vec; i++) {
187 static int prepare_binprm(struct linux_binprm *bprm)
191 int retval, id_change;
193 if(fstat(bprm->fd, &st) < 0) {
198 if(!S_ISREG(mode)) { /* Must be regular file */
201 if(!(mode & 0111)) { /* Must have at least one execute bit set */
205 bprm->e_uid = geteuid();
206 bprm->e_gid = getegid();
211 bprm->e_uid = st.st_uid;
212 if(bprm->e_uid != geteuid()) {
219 * If setgid is set but no group execute bit then this
220 * is a candidate for mandatory locking, not a setgid
223 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
224 bprm->e_gid = st.st_gid;
225 if (!in_group_p(bprm->e_gid)) {
230 memset(bprm->buf, 0, sizeof(bprm->buf));
231 retval = lseek(bprm->fd, 0L, SEEK_SET);
233 retval = read(bprm->fd, bprm->buf, 128);
236 perror("prepare_binprm");
238 /* return(-errno); */
245 unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
246 struct image_info * info)
248 unsigned long stack_base;
250 extern unsigned long stktop;
252 stack_base = X86_STACK_TOP - MAX_ARG_PAGES*X86_PAGE_SIZE;
256 bprm->loader += stack_base;
258 bprm->exec += stack_base;
260 /* Create enough stack to hold everything. If we don't use
261 * it for args, we'll use it for something else...
263 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
264 we allocate a bigger stack. Need a better solution, for example
265 by remapping the process stack directly at the right place */
266 if(x86_stack_size > MAX_ARG_PAGES*X86_PAGE_SIZE) {
267 if((long)mmap4k((void *)(X86_STACK_TOP-x86_stack_size), x86_stack_size + X86_PAGE_SIZE,
268 PROT_READ | PROT_WRITE,
269 MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
275 if((long)mmap4k((void *)stack_base, (MAX_ARG_PAGES+1)*X86_PAGE_SIZE,
276 PROT_READ | PROT_WRITE,
277 MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
285 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
289 memcpy((void *)stack_base, (void *)bprm->page[i], X86_PAGE_SIZE);
290 free_page((void *)bprm->page[i]);
292 stack_base += X86_PAGE_SIZE;
297 static void set_brk(unsigned long start, unsigned long end)
299 /* page-align the start and end addresses... */
300 start = ALPHA_PAGE_ALIGN(start);
301 end = ALPHA_PAGE_ALIGN(end);
304 if((long)mmap4k(start, end - start,
305 PROT_READ | PROT_WRITE | PROT_EXEC,
306 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
307 perror("cannot mmap brk");
313 /* We need to explicitly zero any fractional pages
314 after the data section (i.e. bss). This would
315 contain the junk from the file that should not
319 static void padzero(unsigned long elf_bss)
324 nbyte = elf_bss & (ALPHA_PAGE_SIZE-1); /* was X86_PAGE_SIZE - JRP */
326 nbyte = ALPHA_PAGE_SIZE - nbyte;
327 fpnt = (char *) elf_bss;
334 static unsigned int * create_elf_tables(char *p, int argc, int envc,
335 struct elfhdr * exec,
336 unsigned long load_addr,
337 unsigned long interp_load_addr, int ibcs,
338 struct image_info *info)
340 target_ulong *argv, *envp, *dlinfo;
344 * Force 16 byte alignment here for generality.
346 sp = (unsigned int *) (~15UL & (unsigned long) p);
347 sp -= exec ? DLINFO_ITEMS*2 : 2;
354 put_user(tswapl((target_ulong)envp),--sp);
355 put_user(tswapl((target_ulong)argv),--sp);
358 #define NEW_AUX_ENT(id, val) \
359 put_user (tswapl(id), dlinfo++); \
360 put_user (tswapl(val), dlinfo++)
362 if (exec) { /* Put this here for an ELF program interpreter */
363 struct elf_phdr * eppnt;
364 eppnt = (struct elf_phdr *)((unsigned long)exec->e_phoff);
366 NEW_AUX_ENT (AT_PHDR, (unsigned int)(load_addr + exec->e_phoff));
367 NEW_AUX_ENT (AT_PHENT, (unsigned int)(sizeof (struct elf_phdr)));
368 NEW_AUX_ENT (AT_PHNUM, (unsigned int)(exec->e_phnum));
369 NEW_AUX_ENT (AT_PAGESZ, (unsigned int)(ALPHA_PAGE_SIZE));
370 NEW_AUX_ENT (AT_BASE, (unsigned int)(interp_load_addr));
371 NEW_AUX_ENT (AT_FLAGS, (unsigned int)0);
372 NEW_AUX_ENT (AT_ENTRY, (unsigned int) exec->e_entry);
373 NEW_AUX_ENT (AT_UID, (unsigned int) getuid());
374 NEW_AUX_ENT (AT_EUID, (unsigned int) geteuid());
375 NEW_AUX_ENT (AT_GID, (unsigned int) getgid());
376 NEW_AUX_ENT (AT_EGID, (unsigned int) getegid());
378 NEW_AUX_ENT (AT_NULL, 0);
380 put_user(tswapl(argc),--sp);
381 info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
383 put_user(tswapl((target_ulong)p),argv++);
384 while (get_user(p++)) /* nothing */ ;
387 info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
389 put_user(tswapl((target_ulong)p),envp++);
390 while (get_user(p++)) /* nothing */ ;
393 info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
399 static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
401 unsigned long *interp_load_addr)
403 struct elf_phdr *elf_phdata = NULL;
404 struct elf_phdr *eppnt;
405 unsigned long load_addr;
406 int load_addr_set = 0;
408 unsigned long last_bss, elf_bss;
416 /* We put this here so that mmap will search for the *first*
417 * available memory...
419 load_addr = INTERP_LOADADDR;
421 /* First of all, some simple consistency checks */
422 if ((interp_elf_ex->e_type != ET_EXEC &&
423 interp_elf_ex->e_type != ET_DYN) ||
424 !elf_check_arch(interp_elf_ex->e_machine)) {
428 /* Now read in all of the header information */
430 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > X86_PAGE_SIZE)
433 elf_phdata = (struct elf_phdr *)
434 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
440 * If the size of this structure has changed, then punt, since
441 * we will be doing the wrong thing.
443 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
449 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
451 retval = read(interpreter_fd,
453 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
457 perror("load_elf_interp");
464 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
469 for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
470 if (eppnt->p_type == PT_LOAD) {
471 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
473 unsigned long vaddr = 0;
476 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
477 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
478 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
479 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
480 elf_type |= MAP_FIXED;
481 vaddr = eppnt->p_vaddr;
483 error = (unsigned long)mmap4k(load_addr+X86_ELF_PAGESTART(vaddr),
484 eppnt->p_filesz + X86_ELF_PAGEOFFSET(eppnt->p_vaddr),
488 eppnt->p_offset - X86_ELF_PAGEOFFSET(eppnt->p_vaddr));
490 if (error > -1024UL) {
492 close(interpreter_fd);
497 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
503 * Find the end of the file mapping for this phdr, and keep
504 * track of the largest address we see for this.
506 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
507 if (k > elf_bss) elf_bss = k;
510 * Do the same thing for the memory mapping - between
511 * elf_bss and last_bss is the bss section.
513 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
514 if (k > last_bss) last_bss = k;
517 /* Now use mmap to map the library into memory. */
519 close(interpreter_fd);
522 * Now fill out the bss section. First pad the last page up
523 * to the page boundary, and then perform a mmap to make sure
524 * that there are zeromapped pages up to and including the last
528 elf_bss = X86_ELF_PAGESTART(elf_bss + ALPHA_PAGE_SIZE - 1); /* What we have mapped so far */
530 /* Map the last of the bss segment */
531 if (last_bss > elf_bss) {
532 mmap4k(elf_bss, last_bss-elf_bss,
533 PROT_READ|PROT_WRITE|PROT_EXEC,
534 MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
538 *interp_load_addr = load_addr;
539 return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
544 static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
545 struct image_info * info)
547 struct elfhdr elf_ex;
548 struct elfhdr interp_elf_ex;
549 struct exec interp_ex;
550 int interpreter_fd = -1; /* avoid warning */
551 unsigned long load_addr;
552 int load_addr_set = 0;
553 unsigned int interpreter_type = INTERPRETER_NONE;
554 unsigned char ibcs2_interpreter;
557 struct elf_phdr * elf_ppnt;
558 struct elf_phdr *elf_phdata;
559 unsigned long elf_bss, k, elf_brk;
561 char * elf_interpreter;
562 unsigned long elf_entry, interp_load_addr = 0;
564 unsigned long start_code, end_code, end_data;
565 unsigned long elf_stack;
566 char passed_fileno[6];
568 ibcs2_interpreter = 0;
571 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
576 if (elf_ex.e_ident[0] != 0x7f ||
577 strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
581 /* First of all, some simple consistency checks */
582 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
583 (! elf_check_arch(elf_ex.e_machine))) {
587 /* Now read in all of the header information */
589 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
590 if (elf_phdata == NULL) {
594 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
596 retval = read(bprm->fd, (char *) elf_phdata,
597 elf_ex.e_phentsize * elf_ex.e_phnum);
601 perror("load_elf_binary");
608 elf_ppnt = elf_phdata;
609 for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
610 bswap_phdr(elf_ppnt);
613 elf_ppnt = elf_phdata;
620 elf_interpreter = NULL;
625 for(i=0;i < elf_ex.e_phnum; i++) {
626 if (elf_ppnt->p_type == PT_INTERP) {
627 if ( elf_interpreter != NULL )
630 free(elf_interpreter);
635 /* This is the program interpreter used for
636 * shared libraries - for now assume that this
637 * is an a.out format binary
640 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+
641 strlen(bprm->interp_prefix));
643 if (elf_interpreter == NULL) {
649 strcpy(elf_interpreter, bprm->interp_prefix);
650 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
652 retval = read(bprm->fd,
653 elf_interpreter+strlen(bprm->interp_prefix),
657 perror("load_elf_binary2");
661 /* If the program interpreter is one of these two,
662 then assume an iBCS2 image. Otherwise assume
663 a native linux image. */
665 /* JRP - Need to add X86 lib dir stuff here... */
667 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
668 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
669 ibcs2_interpreter = 1;
673 printf("Using ELF interpreter %s\n", elf_interpreter);
676 retval = open(elf_interpreter, O_RDONLY);
678 interpreter_fd = retval;
681 perror(elf_interpreter);
683 /* retval = -errno; */
688 retval = lseek(interpreter_fd, 0, SEEK_SET);
690 retval = read(interpreter_fd,bprm->buf,128);
694 interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
695 interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
698 perror("load_elf_binary3");
701 free(elf_interpreter);
709 /* Some simple consistency checks for the interpreter */
710 if (elf_interpreter){
711 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
713 /* Now figure out which format our binary is */
714 if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
715 (N_MAGIC(interp_ex) != QMAGIC)) {
716 interpreter_type = INTERPRETER_ELF;
719 if (interp_elf_ex.e_ident[0] != 0x7f ||
720 strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
721 interpreter_type &= ~INTERPRETER_ELF;
724 if (!interpreter_type) {
725 free(elf_interpreter);
732 /* OK, we are done with that, now set up the arg stuff,
733 and then start this sucker up */
735 if (!bprm->sh_bang) {
738 if (interpreter_type == INTERPRETER_AOUT) {
739 sprintf(passed_fileno, "%d", bprm->fd);
740 passed_p = passed_fileno;
742 if (elf_interpreter) {
743 bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
748 if (elf_interpreter) {
749 free(elf_interpreter);
757 /* OK, This is the point of no return */
760 info->start_mmap = (unsigned long)ELF_START_MMAP;
762 elf_entry = (unsigned long) elf_ex.e_entry;
764 /* Do this so that we can load the interpreter, if need be. We will
765 change some of these later */
767 bprm->p = setup_arg_pages(bprm->p, bprm, info);
768 info->start_stack = bprm->p;
770 /* Now we do a little grungy work by mmaping the ELF image into
771 * the correct location in memory. At this point, we assume that
772 * the image should be loaded at fixed address, not at a variable
778 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
779 if (elf_ppnt->p_type == PT_LOAD) {
781 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
782 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
783 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
785 mapped_addr = mmap4k(X86_ELF_PAGESTART(elf_ppnt->p_vaddr),
786 (elf_ppnt->p_filesz +
787 X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
789 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
791 (elf_ppnt->p_offset -
792 X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
794 if((unsigned long)mapped_addr == 0xffffffffffffffff) {
802 if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
803 elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr);
806 if (!load_addr_set) {
807 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
810 k = elf_ppnt->p_vaddr;
811 if (k < start_code) start_code = k;
812 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
813 if (k > elf_bss) elf_bss = k;
815 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
817 if ( !(elf_ppnt->p_flags & PF_W) && end_code < k)
820 if (end_data < k) end_data = k;
821 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
822 if (k > elf_brk) elf_brk = k;
826 if (elf_interpreter) {
827 if (interpreter_type & 1) {
828 elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
830 else if (interpreter_type & 2) {
831 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
835 close(interpreter_fd);
836 free(elf_interpreter);
838 if (elf_entry == ~0UL) {
839 printf("Unable to load interpreter\n");
848 if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
849 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
852 info->start_stack = bprm->p = elf_stack - 4;
854 bprm->p = (unsigned long)
855 create_elf_tables((char *)bprm->p,
858 (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
861 (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
863 if (interpreter_type == INTERPRETER_AOUT)
864 info->arg_start += strlen(passed_fileno) + 1;
865 info->start_brk = info->brk = elf_brk;
866 info->end_code = end_code;
867 info->start_code = start_code;
868 info->end_data = end_data;
869 info->start_stack = bprm->p;
871 /* Calling set_brk effectively mmaps the pages that we need for the bss and break
873 set_brk(elf_bss, elf_brk);
878 printf("(start_brk) %x\n" , info->start_brk);
879 printf("(end_code) %x\n" , info->end_code);
880 printf("(start_code) %x\n" , info->start_code);
881 printf("(end_data) %x\n" , info->end_data);
882 printf("(start_stack) %x\n" , info->start_stack);
883 printf("(brk) %x\n" , info->brk);
886 if ( info->personality == PER_SVR4 )
888 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
889 and some applications "depend" upon this behavior.
890 Since we do not have the power to recompile these, we
891 emulate the SVr4 behavior. Sigh. */
892 mapped_addr = mmap4k(NULL, ALPHA_PAGE_SIZE, PROT_READ | PROT_EXEC,
893 MAP_FIXED | MAP_PRIVATE, -1, 0);
898 * The ABI may specify that certain registers be set up in special
899 * ways (on i386 %edx is the address of a DT_FINI function, for
900 * example. This macro performs whatever initialization to
901 * the regs structure is required.
907 info->entry = elf_entry;
914 int elf_exec(const char *interp_prefix,
915 const char * filename, char ** argv, char ** envp,
916 struct target_pt_regs * regs, struct image_info *infop)
918 struct linux_binprm bprm;
922 bprm.p = X86_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
923 for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
925 retval = open(filename, O_RDONLY);
934 bprm.interp_prefix = (char *)interp_prefix;
935 bprm.filename = (char *)filename;
940 bprm.argc = count(argv);
941 bprm.envc = count(envp);
943 retval = prepare_binprm(&bprm);
946 bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p);
948 bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p);
949 bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p);
956 retval = load_elf_binary(&bprm,regs,infop);
959 /* success. Initialize important registers */
960 regs->esp = infop->start_stack;
961 regs->eip = infop->entry;
965 /* Something went wrong, return the inode and free the argument pages*/
966 for (i=0 ; i<MAX_ARG_PAGES ; i++) {
967 free_page((void *)bprm.page[i]);
973 static int load_aout_interp(void * exptr, int interp_fd)
975 printf("a.out interpreter not yet supported\n");