Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ a69d83b6

History | View | Annotate | Download (33 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 689f936f bellard
#include "disas.h"
15 31e31b8a bellard
16 30ac07d4 bellard
#ifdef TARGET_I386
17 30ac07d4 bellard
18 30ac07d4 bellard
#define ELF_START_MMAP 0x80000000
19 30ac07d4 bellard
20 30ac07d4 bellard
typedef uint32_t  elf_greg_t;
21 30ac07d4 bellard
22 30ac07d4 bellard
#define ELF_NGREG (sizeof (struct target_pt_regs) / sizeof(elf_greg_t))
23 30ac07d4 bellard
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
24 30ac07d4 bellard
25 30ac07d4 bellard
typedef struct user_i387_struct elf_fpregset_t;
26 30ac07d4 bellard
27 30ac07d4 bellard
/*
28 30ac07d4 bellard
 * This is used to ensure we don't load something for the wrong architecture.
29 30ac07d4 bellard
 */
30 30ac07d4 bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
31 30ac07d4 bellard
32 30ac07d4 bellard
/*
33 30ac07d4 bellard
 * These are used to set parameters in the core dumps.
34 30ac07d4 bellard
 */
35 30ac07d4 bellard
#define ELF_CLASS        ELFCLASS32
36 30ac07d4 bellard
#define ELF_DATA        ELFDATA2LSB
37 30ac07d4 bellard
#define ELF_ARCH        EM_386
38 30ac07d4 bellard
39 30ac07d4 bellard
        /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
40 30ac07d4 bellard
           starts %edx contains a pointer to a function which might be
41 30ac07d4 bellard
           registered using `atexit'.  This provides a mean for the
42 30ac07d4 bellard
           dynamic linker to call DT_FINI functions for shared libraries
43 30ac07d4 bellard
           that have been loaded before the code runs.
44 30ac07d4 bellard

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