Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ 3ef693a0

History | View | Annotate | Download (25.9 kB)

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