Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ f68c781c

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