Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ 2c0262af

History | View | Annotate | Download (33.1 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
/*
21 30ac07d4 bellard
 * This is used to ensure we don't load something for the wrong architecture.
22 30ac07d4 bellard
 */
23 30ac07d4 bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
24 30ac07d4 bellard
25 30ac07d4 bellard
/*
26 30ac07d4 bellard
 * These are used to set parameters in the core dumps.
27 30ac07d4 bellard
 */
28 30ac07d4 bellard
#define ELF_CLASS        ELFCLASS32
29 30ac07d4 bellard
#define ELF_DATA        ELFDATA2LSB
30 30ac07d4 bellard
#define ELF_ARCH        EM_386
31 30ac07d4 bellard
32 30ac07d4 bellard
        /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
33 30ac07d4 bellard
           starts %edx contains a pointer to a function which might be
34 30ac07d4 bellard
           registered using `atexit'.  This provides a mean for the
35 30ac07d4 bellard
           dynamic linker to call DT_FINI functions for shared libraries
36 30ac07d4 bellard
           that have been loaded before the code runs.
37 30ac07d4 bellard

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