xref: /openbmc/qemu/linux-user/elfload.c (revision 9de5e440b9f6a6c6305c0b81d1df4ddcc5a4b966)
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 
13 #include "gemu.h"
14 
15 #include "linux_bin.h"
16 #include "elf.h"
17 #include "segment.h"
18 
19 /* Necessary parameters */
20 #define	ALPHA_PAGE_SIZE 4096
21 #define	X86_PAGE_SIZE 4096
22 
23 #define ALPHA_PAGE_MASK (~(ALPHA_PAGE_SIZE-1))
24 #define X86_PAGE_MASK (~(X86_PAGE_SIZE-1))
25 
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)
28 
29 #define NGROUPS 32
30 
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))
34 
35 #define ALPHA_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ALPHA_PAGE_SIZE-1))
36 #define ALPHA_ELF_PAGEOFFSET(_v) ((_v) & (ALPHA_PAGE_SIZE-1))
37 
38 #define INTERPRETER_NONE 0
39 #define INTERPRETER_AOUT 1
40 #define INTERPRETER_ELF 2
41 
42 #define DLINFO_ITEMS 12
43 
44 /* Where we find X86 libraries... */
45 //#define X86_DEFAULT_LIB_DIR	"/usr/x86/"
46 #define X86_DEFAULT_LIB_DIR	"/"
47 
48 //extern void * mmap4k();
49 #define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
50 
51 extern unsigned long x86_stack_size;
52 
53 static int load_aout_interp(void * exptr, int interp_fd);
54 
55 #ifdef BSWAP_NEEDED
56 static void bswap_ehdr(Elf32_Ehdr *ehdr)
57 {
58     bswap16s(&ehdr->e_type);			/* Object file type */
59     bswap16s(&ehdr->e_machine);		/* Architecture */
60     bswap32s(&ehdr->e_version);		/* Object file version */
61     bswap32s(&ehdr->e_entry);		/* Entry point virtual address */
62     bswap32s(&ehdr->e_phoff);		/* Program header table file offset */
63     bswap32s(&ehdr->e_shoff);		/* Section header table file offset */
64     bswap32s(&ehdr->e_flags);		/* Processor-specific flags */
65     bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */
66     bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */
67     bswap16s(&ehdr->e_phnum);		/* Program header table entry count */
68     bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */
69     bswap16s(&ehdr->e_shnum);		/* Section header table entry count */
70     bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */
71 }
72 
73 static void bswap_phdr(Elf32_Phdr *phdr)
74 {
75     bswap32s(&phdr->p_type);			/* Segment type */
76     bswap32s(&phdr->p_offset);		/* Segment file offset */
77     bswap32s(&phdr->p_vaddr);		/* Segment virtual address */
78     bswap32s(&phdr->p_paddr);		/* Segment physical address */
79     bswap32s(&phdr->p_filesz);		/* Segment size in file */
80     bswap32s(&phdr->p_memsz);		/* Segment size in memory */
81     bswap32s(&phdr->p_flags);		/* Segment flags */
82     bswap32s(&phdr->p_align);		/* Segment alignment */
83 }
84 #endif
85 
86 static void * get_free_page(void)
87 {
88     void *	retval;
89 
90     /* User-space version of kernel get_free_page.  Returns a page-aligned
91      * page-sized chunk of memory.
92      */
93     retval = mmap4k(0, ALPHA_PAGE_SIZE, PROT_READ|PROT_WRITE,
94 			MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
95 
96     if((long)retval == -1) {
97 	perror("get_free_page");
98 	exit(-1);
99     }
100     else {
101 	return(retval);
102     }
103 }
104 
105 static void free_page(void * pageaddr)
106 {
107     (void)munmap(pageaddr, ALPHA_PAGE_SIZE);
108 }
109 
110 /*
111  * 'copy_string()' copies argument/envelope strings from user
112  * memory to free pages in kernel mem. These are in a format ready
113  * to be put directly into the top of new user memory.
114  *
115  */
116 static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
117                 unsigned long p)
118 {
119     char *tmp, *tmp1, *pag = NULL;
120     int len, offset = 0;
121 
122     if (!p) {
123 	return 0;       /* bullet-proofing */
124     }
125     while (argc-- > 0) {
126 	if (!(tmp1 = tmp = get_user(argv+argc))) {
127 	    fprintf(stderr, "VFS: argc is wrong");
128 	    exit(-1);
129 	}
130 	while (get_user(tmp++));
131 	len = tmp - tmp1;
132 	if (p < len) {  /* this shouldn't happen - 128kB */
133 		return 0;
134 	}
135 	while (len) {
136 	    --p; --tmp; --len;
137 	    if (--offset < 0) {
138 		offset = p % X86_PAGE_SIZE;
139 		if (!(pag = (char *) page[p/X86_PAGE_SIZE]) &&
140 		    !(pag = (char *) page[p/X86_PAGE_SIZE] =
141 		      (unsigned long *) get_free_page())) {
142 			return 0;
143 		}
144 	    }
145 	    if (len == 0 || offset == 0) {
146 	        *(pag + offset) = get_user(tmp);
147 	    }
148 	    else {
149 	      int bytes_to_copy = (len > offset) ? offset : len;
150 	      tmp -= bytes_to_copy;
151 	      p -= bytes_to_copy;
152 	      offset -= bytes_to_copy;
153 	      len -= bytes_to_copy;
154 	      memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
155 	    }
156 	}
157     }
158     return p;
159 }
160 
161 static int in_group_p(gid_t g)
162 {
163     /* return TRUE if we're in the specified group, FALSE otherwise */
164     int		ngroup;
165     int		i;
166     gid_t	grouplist[NGROUPS];
167 
168     ngroup = getgroups(NGROUPS, grouplist);
169     for(i = 0; i < ngroup; i++) {
170 	if(grouplist[i] == g) {
171 	    return 1;
172 	}
173     }
174     return 0;
175 }
176 
177 static int count(char ** vec)
178 {
179     int		i;
180 
181     for(i = 0; *vec; i++) {
182         vec++;
183     }
184 
185     return(i);
186 }
187 
188 static int prepare_binprm(struct linux_binprm *bprm)
189 {
190     struct stat		st;
191     int mode;
192     int retval, id_change;
193 
194     if(fstat(bprm->fd, &st) < 0) {
195 	return(-errno);
196     }
197 
198     mode = st.st_mode;
199     if(!S_ISREG(mode)) {	/* Must be regular file */
200 	return(-EACCES);
201     }
202     if(!(mode & 0111)) {	/* Must have at least one execute bit set */
203 	return(-EACCES);
204     }
205 
206     bprm->e_uid = geteuid();
207     bprm->e_gid = getegid();
208     id_change = 0;
209 
210     /* Set-uid? */
211     if(mode & S_ISUID) {
212     	bprm->e_uid = st.st_uid;
213 	if(bprm->e_uid != geteuid()) {
214 	    id_change = 1;
215 	}
216     }
217 
218     /* Set-gid? */
219     /*
220      * If setgid is set but no group execute bit then this
221      * is a candidate for mandatory locking, not a setgid
222      * executable.
223      */
224     if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
225 	bprm->e_gid = st.st_gid;
226 	if (!in_group_p(bprm->e_gid)) {
227 		id_change = 1;
228 	}
229     }
230 
231     memset(bprm->buf, 0, sizeof(bprm->buf));
232     retval = lseek(bprm->fd, 0L, SEEK_SET);
233     if(retval >= 0) {
234         retval = read(bprm->fd, bprm->buf, 128);
235     }
236     if(retval < 0) {
237 	perror("prepare_binprm");
238 	exit(-1);
239 	/* return(-errno); */
240     }
241     else {
242 	return(retval);
243     }
244 }
245 
246 unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
247 						struct image_info * info)
248 {
249     unsigned long stack_base;
250     int i;
251     extern unsigned long stktop;
252 
253     stack_base = X86_STACK_TOP - MAX_ARG_PAGES*X86_PAGE_SIZE;
254 
255     p += stack_base;
256     if (bprm->loader) {
257 	bprm->loader += stack_base;
258     }
259     bprm->exec += stack_base;
260 
261     /* Create enough stack to hold everything.  If we don't use
262      * it for args, we'll use it for something else...
263      */
264     /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
265        we allocate a bigger stack. Need a better solution, for example
266        by remapping the process stack directly at the right place */
267     if(x86_stack_size >  MAX_ARG_PAGES*X86_PAGE_SIZE) {
268         if((long)mmap4k((void *)(X86_STACK_TOP-x86_stack_size), x86_stack_size + X86_PAGE_SIZE,
269     		     PROT_READ | PROT_WRITE,
270 		     MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
271 	    perror("stk mmap");
272 	    exit(-1);
273 	}
274     }
275     else {
276         if((long)mmap4k((void *)stack_base, (MAX_ARG_PAGES+1)*X86_PAGE_SIZE,
277     		     PROT_READ | PROT_WRITE,
278 		     MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
279 	    perror("stk mmap");
280 	    exit(-1);
281 	}
282     }
283 
284     stktop = stack_base;
285 
286     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
287 	if (bprm->page[i]) {
288 	    info->rss++;
289 
290 	    memcpy((void *)stack_base, (void *)bprm->page[i], X86_PAGE_SIZE);
291 	    free_page((void *)bprm->page[i]);
292 	}
293 	stack_base += X86_PAGE_SIZE;
294     }
295     return p;
296 }
297 
298 static void set_brk(unsigned long start, unsigned long end)
299 {
300 	/* page-align the start and end addresses... */
301         start = ALPHA_PAGE_ALIGN(start);
302         end = ALPHA_PAGE_ALIGN(end);
303         if (end <= start)
304                 return;
305         if((long)mmap4k(start, end - start,
306                 PROT_READ | PROT_WRITE | PROT_EXEC,
307                 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
308 	    perror("cannot mmap brk");
309 	    exit(-1);
310 	}
311 }
312 
313 
314 /* We need to explicitly zero any fractional pages
315    after the data section (i.e. bss).  This would
316    contain the junk from the file that should not
317    be in memory */
318 
319 
320 static void padzero(unsigned long elf_bss)
321 {
322         unsigned long nbyte;
323         char * fpnt;
324 
325         nbyte = elf_bss & (ALPHA_PAGE_SIZE-1);	/* was X86_PAGE_SIZE - JRP */
326         if (nbyte) {
327 	    nbyte = ALPHA_PAGE_SIZE - nbyte;
328 	    fpnt = (char *) elf_bss;
329 	    do {
330 		*fpnt++ = 0;
331 	    } while (--nbyte);
332         }
333 }
334 
335 static unsigned int * create_elf_tables(char *p, int argc, int envc,
336                                   struct elfhdr * exec,
337                                   unsigned long load_addr,
338                                   unsigned long interp_load_addr, int ibcs,
339 				  struct image_info *info)
340 {
341         target_ulong *argv, *envp, *dlinfo;
342         target_ulong *sp;
343 
344         /*
345          * Force 16 byte alignment here for generality.
346          */
347         sp = (unsigned int *) (~15UL & (unsigned long) p);
348         sp -= exec ? DLINFO_ITEMS*2 : 2;
349         dlinfo = sp;
350         sp -= envc+1;
351         envp = sp;
352         sp -= argc+1;
353         argv = sp;
354         if (!ibcs) {
355                 put_user(tswapl((target_ulong)envp),--sp);
356                 put_user(tswapl((target_ulong)argv),--sp);
357         }
358 
359 #define NEW_AUX_ENT(id, val) \
360           put_user (tswapl(id), dlinfo++); \
361           put_user (tswapl(val), dlinfo++)
362 
363         if (exec) { /* Put this here for an ELF program interpreter */
364           struct elf_phdr * eppnt;
365           eppnt = (struct elf_phdr *)((unsigned long)exec->e_phoff);
366 
367           NEW_AUX_ENT (AT_PHDR, (unsigned int)(load_addr + exec->e_phoff));
368           NEW_AUX_ENT (AT_PHENT, (unsigned int)(sizeof (struct elf_phdr)));
369           NEW_AUX_ENT (AT_PHNUM, (unsigned int)(exec->e_phnum));
370           NEW_AUX_ENT (AT_PAGESZ, (unsigned int)(ALPHA_PAGE_SIZE));
371           NEW_AUX_ENT (AT_BASE, (unsigned int)(interp_load_addr));
372           NEW_AUX_ENT (AT_FLAGS, (unsigned int)0);
373           NEW_AUX_ENT (AT_ENTRY, (unsigned int) exec->e_entry);
374           NEW_AUX_ENT (AT_UID, (unsigned int) getuid());
375           NEW_AUX_ENT (AT_EUID, (unsigned int) geteuid());
376           NEW_AUX_ENT (AT_GID, (unsigned int) getgid());
377           NEW_AUX_ENT (AT_EGID, (unsigned int) getegid());
378         }
379         NEW_AUX_ENT (AT_NULL, 0);
380 #undef NEW_AUX_ENT
381         put_user(tswapl(argc),--sp);
382         info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
383         while (argc-->0) {
384                 put_user(tswapl((target_ulong)p),argv++);
385                 while (get_user(p++)) /* nothing */ ;
386         }
387         put_user(0,argv);
388         info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
389         while (envc-->0) {
390                 put_user(tswapl((target_ulong)p),envp++);
391                 while (get_user(p++)) /* nothing */ ;
392         }
393         put_user(0,envp);
394         info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
395         return sp;
396 }
397 
398 
399 
400 static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
401 				     int interpreter_fd,
402 				     unsigned long *interp_load_addr)
403 {
404 	struct elf_phdr *elf_phdata  =  NULL;
405 	struct elf_phdr *eppnt;
406 	unsigned long load_addr;
407 	int load_addr_set = 0;
408 	int retval;
409 	unsigned long last_bss, elf_bss;
410 	unsigned long error;
411 	int i;
412 
413 	elf_bss = 0;
414 	last_bss = 0;
415 	error = 0;
416 
417 	/* We put this here so that mmap will search for the *first*
418 	 * available memory...
419 	 */
420 	load_addr = INTERP_LOADADDR;
421 
422 	/* First of all, some simple consistency checks */
423 	if ((interp_elf_ex->e_type != ET_EXEC &&
424 	    interp_elf_ex->e_type != ET_DYN) ||
425 	   !elf_check_arch(interp_elf_ex->e_machine)) {
426 		return ~0UL;
427 	}
428 
429 	/* Now read in all of the header information */
430 
431 	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > X86_PAGE_SIZE)
432 	    return ~0UL;
433 
434 	elf_phdata =  (struct elf_phdr *)
435 		malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
436 
437 	if (!elf_phdata)
438 	  return ~0UL;
439 
440 	/*
441 	 * If the size of this structure has changed, then punt, since
442 	 * we will be doing the wrong thing.
443 	 */
444 	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
445 	  {
446 	    free(elf_phdata);
447 	    return ~0UL;
448 	  }
449 
450 	retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
451 	if(retval >= 0) {
452 	    retval = read(interpreter_fd,
453 			   (char *) elf_phdata,
454 			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
455 	}
456 
457 	if (retval < 0) {
458 		perror("load_elf_interp");
459 		exit(-1);
460 		free (elf_phdata);
461 		return retval;
462  	}
463 #ifdef BSWAP_NEEDED
464 	eppnt = elf_phdata;
465 	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
466             bswap_phdr(eppnt);
467         }
468 #endif
469 	eppnt = elf_phdata;
470 	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
471 	  if (eppnt->p_type == PT_LOAD) {
472 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
473 	    int elf_prot = 0;
474 	    unsigned long vaddr = 0;
475 	    unsigned long k;
476 
477 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
478 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
479 	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
480 	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
481 	    	elf_type |= MAP_FIXED;
482 	    	vaddr = eppnt->p_vaddr;
483 	    }
484 	    error = (unsigned long)mmap4k(load_addr+X86_ELF_PAGESTART(vaddr),
485 		 eppnt->p_filesz + X86_ELF_PAGEOFFSET(eppnt->p_vaddr),
486 		 elf_prot,
487 		 elf_type,
488 		 interpreter_fd,
489 		 eppnt->p_offset - X86_ELF_PAGEOFFSET(eppnt->p_vaddr));
490 
491 	    if (error > -1024UL) {
492 	      /* Real error */
493 	      close(interpreter_fd);
494 	      free(elf_phdata);
495 	      return ~0UL;
496 	    }
497 
498 	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
499 	      load_addr = error;
500 	      load_addr_set = 1;
501 	    }
502 
503 	    /*
504 	     * Find the end of the file  mapping for this phdr, and keep
505 	     * track of the largest address we see for this.
506 	     */
507 	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
508 	    if (k > elf_bss) elf_bss = k;
509 
510 	    /*
511 	     * Do the same thing for the memory mapping - between
512 	     * elf_bss and last_bss is the bss section.
513 	     */
514 	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
515 	    if (k > last_bss) last_bss = k;
516 	  }
517 
518 	/* Now use mmap to map the library into memory. */
519 
520 	close(interpreter_fd);
521 
522 	/*
523 	 * Now fill out the bss section.  First pad the last page up
524 	 * to the page boundary, and then perform a mmap to make sure
525 	 * that there are zeromapped pages up to and including the last
526 	 * bss page.
527 	 */
528 	padzero(elf_bss);
529 	elf_bss = X86_ELF_PAGESTART(elf_bss + ALPHA_PAGE_SIZE - 1); /* What we have mapped so far */
530 
531 	/* Map the last of the bss segment */
532 	if (last_bss > elf_bss) {
533 	  mmap4k(elf_bss, last_bss-elf_bss,
534 		  PROT_READ|PROT_WRITE|PROT_EXEC,
535 		  MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
536 	}
537 	free(elf_phdata);
538 
539 	*interp_load_addr = load_addr;
540 	return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
541 }
542 
543 
544 
545 static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
546                            struct image_info * info)
547 {
548     struct elfhdr elf_ex;
549     struct elfhdr interp_elf_ex;
550     struct exec interp_ex;
551     int interpreter_fd = -1; /* avoid warning */
552     unsigned long load_addr;
553     int load_addr_set = 0;
554     unsigned int interpreter_type = INTERPRETER_NONE;
555     unsigned char ibcs2_interpreter;
556     int i;
557     void * mapped_addr;
558     struct elf_phdr * elf_ppnt;
559     struct elf_phdr *elf_phdata;
560     unsigned long elf_bss, k, elf_brk;
561     int retval;
562     char * elf_interpreter;
563     unsigned long elf_entry, interp_load_addr = 0;
564     int status;
565     unsigned long start_code, end_code, end_data;
566     unsigned long elf_stack;
567     char passed_fileno[6];
568 
569     ibcs2_interpreter = 0;
570     status = 0;
571     load_addr = 0;
572     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
573 #ifdef BSWAP_NEEDED
574     bswap_ehdr(&elf_ex);
575 #endif
576 
577     if (elf_ex.e_ident[0] != 0x7f ||
578 	strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
579 	    return  -ENOEXEC;
580     }
581 
582     /* First of all, some simple consistency checks */
583     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
584        				(! elf_check_arch(elf_ex.e_machine))) {
585 	    return -ENOEXEC;
586     }
587 
588     /* Now read in all of the header information */
589 
590     elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
591     if (elf_phdata == NULL) {
592 	return -ENOMEM;
593     }
594 
595     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
596     if(retval > 0) {
597 	retval = read(bprm->fd, (char *) elf_phdata,
598 				elf_ex.e_phentsize * elf_ex.e_phnum);
599     }
600 
601     if (retval < 0) {
602 	perror("load_elf_binary");
603 	exit(-1);
604 	free (elf_phdata);
605 	return -errno;
606     }
607 
608 #ifdef BSWAP_NEEDED
609     elf_ppnt = elf_phdata;
610     for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
611         bswap_phdr(elf_ppnt);
612     }
613 #endif
614     elf_ppnt = elf_phdata;
615 
616     elf_bss = 0;
617     elf_brk = 0;
618 
619 
620     elf_stack = ~0UL;
621     elf_interpreter = NULL;
622     start_code = ~0UL;
623     end_code = 0;
624     end_data = 0;
625 
626     for(i=0;i < elf_ex.e_phnum; i++) {
627 	if (elf_ppnt->p_type == PT_INTERP) {
628 	    if ( elf_interpreter != NULL )
629 	    {
630 		free (elf_phdata);
631 		free(elf_interpreter);
632 		close(bprm->fd);
633 		return -EINVAL;
634 	    }
635 
636 	    /* This is the program interpreter used for
637 	     * shared libraries - for now assume that this
638 	     * is an a.out format binary
639 	     */
640 
641 	    elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+strlen(X86_DEFAULT_LIB_DIR));
642 
643 	    if (elf_interpreter == NULL) {
644 		free (elf_phdata);
645 		close(bprm->fd);
646 		return -ENOMEM;
647 	    }
648 
649 	    strcpy(elf_interpreter, X86_DEFAULT_LIB_DIR);
650 	    retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
651 	    if(retval >= 0) {
652 		retval = read(bprm->fd,
653 			      elf_interpreter+strlen(X86_DEFAULT_LIB_DIR),
654 			      elf_ppnt->p_filesz);
655 	    }
656 	    if(retval < 0) {
657 	 	perror("load_elf_binary2");
658 		exit(-1);
659 	    }
660 
661 	    /* If the program interpreter is one of these two,
662 	       then assume an iBCS2 image. Otherwise assume
663 	       a native linux image. */
664 
665 	    /* JRP - Need to add X86 lib dir stuff here... */
666 
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;
670 	    }
671 
672 #if 0
673 	    printf("Using ELF interpreter %s\n", elf_interpreter);
674 #endif
675 	    if (retval >= 0) {
676 		retval = open(elf_interpreter, O_RDONLY);
677 		if(retval >= 0) {
678 		    interpreter_fd = retval;
679 		}
680 		else {
681 		    perror(elf_interpreter);
682 		    exit(-1);
683 		    /* retval = -errno; */
684 		}
685 	    }
686 
687 	    if (retval >= 0) {
688 		retval = lseek(interpreter_fd, 0, SEEK_SET);
689 		if(retval >= 0) {
690 		    retval = read(interpreter_fd,bprm->buf,128);
691 		}
692 	    }
693 	    if (retval >= 0) {
694 		interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
695 		interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
696 	    }
697 	    if (retval < 0) {
698 		perror("load_elf_binary3");
699 		exit(-1);
700 		free (elf_phdata);
701 		free(elf_interpreter);
702 		close(bprm->fd);
703 		return retval;
704 	    }
705 	}
706 	elf_ppnt++;
707     }
708 
709     /* Some simple consistency checks for the interpreter */
710     if (elf_interpreter){
711 	interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
712 
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;
717 	}
718 
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;
722 	}
723 
724 	if (!interpreter_type) {
725 	    free(elf_interpreter);
726 	    free(elf_phdata);
727 	    close(bprm->fd);
728 	    return -ELIBBAD;
729 	}
730     }
731 
732     /* OK, we are done with that, now set up the arg stuff,
733        and then start this sucker up */
734 
735     if (!bprm->sh_bang) {
736 	char * passed_p;
737 
738 	if (interpreter_type == INTERPRETER_AOUT) {
739 	    sprintf(passed_fileno, "%d", bprm->fd);
740 	    passed_p = passed_fileno;
741 
742 	    if (elf_interpreter) {
743 		bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
744 		bprm->argc++;
745 	    }
746 	}
747 	if (!bprm->p) {
748 	    if (elf_interpreter) {
749 	        free(elf_interpreter);
750 	    }
751 	    free (elf_phdata);
752 	    close(bprm->fd);
753 	    return -E2BIG;
754 	}
755     }
756 
757     /* OK, This is the point of no return */
758     info->end_data = 0;
759     info->end_code = 0;
760     info->start_mmap = (unsigned long)ELF_START_MMAP;
761     info->mmap = 0;
762     elf_entry = (unsigned long) elf_ex.e_entry;
763 
764     /* Do this so that we can load the interpreter, if need be.  We will
765        change some of these later */
766     info->rss = 0;
767     bprm->p = setup_arg_pages(bprm->p, bprm, info);
768     info->start_stack = bprm->p;
769 
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
773      * address.
774      */
775 
776 
777 
778     for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
779 	if (elf_ppnt->p_type == PT_LOAD) {
780 	    int elf_prot = 0;
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;
784 
785 	    mapped_addr = mmap4k(X86_ELF_PAGESTART(elf_ppnt->p_vaddr),
786 		    (elf_ppnt->p_filesz +
787 			    X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
788 		    elf_prot,
789 		    (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
790 		    bprm->fd,
791 		    (elf_ppnt->p_offset -
792 			    X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
793 
794 	    if((unsigned long)mapped_addr == 0xffffffffffffffff) {
795 		perror("mmap");
796 		exit(-1);
797 	    }
798 
799 
800 
801 #ifdef LOW_ELF_STACK
802 	    if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
803 		    elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr);
804 #endif
805 
806 	    if (!load_addr_set) {
807 	        load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
808 	        load_addr_set = 1;
809 	    }
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;
814 #if 1
815 	    if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
816 #else
817 	    if ( !(elf_ppnt->p_flags & PF_W) && end_code <  k)
818 #endif
819 		    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;
823 	}
824     }
825 
826     if (elf_interpreter) {
827 	if (interpreter_type & 1) {
828 	    elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
829 	}
830 	else if (interpreter_type & 2) {
831 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
832 					    &interp_load_addr);
833 	}
834 
835 	close(interpreter_fd);
836 	free(elf_interpreter);
837 
838 	if (elf_entry == ~0UL) {
839 	    printf("Unable to load interpreter\n");
840 	    free(elf_phdata);
841 	    exit(-1);
842 	    return 0;
843 	}
844     }
845 
846     free(elf_phdata);
847 
848     if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
849     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
850 
851 #ifdef LOW_ELF_STACK
852     info->start_stack = bprm->p = elf_stack - 4;
853 #endif
854     bprm->p = (unsigned long)
855       create_elf_tables((char *)bprm->p,
856 		    bprm->argc,
857 		    bprm->envc,
858 		    (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
859 		    load_addr,
860 		    interp_load_addr,
861 		    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
862 		    info);
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;
870 
871     /* Calling set_brk effectively mmaps the pages that we need for the bss and break
872        sections */
873     set_brk(elf_bss, elf_brk);
874 
875     padzero(elf_bss);
876 
877 #if 0
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);
884 #endif
885 
886     if ( info->personality == PER_SVR4 )
887     {
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);
894     }
895 
896 #ifdef ELF_PLAT_INIT
897     /*
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.
902      */
903     ELF_PLAT_INIT(regs);
904 #endif
905 
906 
907     info->entry = elf_entry;
908 
909     return 0;
910 }
911 
912 
913 
914 int elf_exec(const char * filename, char ** argv, char ** envp,
915              struct target_pt_regs * regs, struct image_info *infop)
916 {
917         struct linux_binprm bprm;
918         int retval;
919         int i;
920 
921         bprm.p = X86_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
922         for (i=0 ; i<MAX_ARG_PAGES ; i++)       /* clear page-table */
923                 bprm.page[i] = 0;
924         retval = open(filename, O_RDONLY);
925         if (retval == -1) {
926 	    perror(filename);
927 	    exit(-1);
928             /* return retval; */
929 	}
930 	else {
931 	    bprm.fd = retval;
932 	}
933         bprm.filename = (char *)filename;
934         bprm.sh_bang = 0;
935         bprm.loader = 0;
936         bprm.exec = 0;
937         bprm.dont_iput = 0;
938 	bprm.argc = count(argv);
939 	bprm.envc = count(envp);
940 
941         retval = prepare_binprm(&bprm);
942 
943         if(retval>=0) {
944 	    bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p);
945 	    bprm.exec = bprm.p;
946 	    bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p);
947 	    bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p);
948 	    if (!bprm.p) {
949 		retval = -E2BIG;
950 	    }
951         }
952 
953         if(retval>=0) {
954 	    retval = load_elf_binary(&bprm,regs,infop);
955 	}
956         if(retval>=0) {
957 	    /* success.  Initialize important registers */
958 	    regs->esp = infop->start_stack;
959 	    regs->eip = infop->entry;
960 	    return retval;
961 	}
962 
963         /* Something went wrong, return the inode and free the argument pages*/
964         for (i=0 ; i<MAX_ARG_PAGES ; i++) {
965 	    free_page((void *)bprm.page[i]);
966 	}
967         return(retval);
968 }
969 
970 
971 static int load_aout_interp(void * exptr, int interp_fd)
972 {
973     printf("a.out interpreter not yet supported\n");
974     return(0);
975 }
976 
977