Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ 5a91de8c

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