Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ d3c61721

History | View | Annotate | Download (37.8 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 83fb7adf bellard
/* this flag is uneffective under linux too, should be deleted */
17 83fb7adf bellard
#ifndef MAP_DENYWRITE
18 83fb7adf bellard
#define MAP_DENYWRITE 0
19 83fb7adf bellard
#endif
20 83fb7adf bellard
21 83fb7adf bellard
/* should probably go in elf.h */
22 83fb7adf bellard
#ifndef ELIBBAD
23 83fb7adf bellard
#define ELIBBAD 80
24 83fb7adf bellard
#endif
25 83fb7adf bellard
26 30ac07d4 bellard
#ifdef TARGET_I386
27 30ac07d4 bellard
28 30ac07d4 bellard
#define ELF_START_MMAP 0x80000000
29 30ac07d4 bellard
30 30ac07d4 bellard
/*
31 30ac07d4 bellard
 * This is used to ensure we don't load something for the wrong architecture.
32 30ac07d4 bellard
 */
33 30ac07d4 bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
34 30ac07d4 bellard
35 30ac07d4 bellard
/*
36 30ac07d4 bellard
 * These are used to set parameters in the core dumps.
37 30ac07d4 bellard
 */
38 30ac07d4 bellard
#define ELF_CLASS        ELFCLASS32
39 30ac07d4 bellard
#define ELF_DATA        ELFDATA2LSB
40 30ac07d4 bellard
#define ELF_ARCH        EM_386
41 30ac07d4 bellard
42 30ac07d4 bellard
        /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
43 30ac07d4 bellard
           starts %edx contains a pointer to a function which might be
44 30ac07d4 bellard
           registered using `atexit'.  This provides a mean for the
45 30ac07d4 bellard
           dynamic linker to call DT_FINI functions for shared libraries
46 30ac07d4 bellard
           that have been loaded before the code runs.
47 30ac07d4 bellard

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