Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ 480c1cdb

History | View | Annotate | Download (35 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 <errno.h>
7 31e31b8a bellard
#include <unistd.h>
8 31e31b8a bellard
#include <sys/mman.h>
9 31e31b8a bellard
#include <stdlib.h>
10 31e31b8a bellard
#include <string.h>
11 31e31b8a bellard
12 3ef693a0 bellard
#include "qemu.h"
13 689f936f bellard
#include "disas.h"
14 31e31b8a bellard
15 83fb7adf bellard
/* this flag is uneffective under linux too, should be deleted */
16 83fb7adf bellard
#ifndef MAP_DENYWRITE
17 83fb7adf bellard
#define MAP_DENYWRITE 0
18 83fb7adf bellard
#endif
19 83fb7adf bellard
20 83fb7adf bellard
/* should probably go in elf.h */
21 83fb7adf bellard
#ifndef ELIBBAD
22 83fb7adf bellard
#define ELIBBAD 80
23 83fb7adf bellard
#endif
24 83fb7adf bellard
25 30ac07d4 bellard
#ifdef TARGET_I386
26 30ac07d4 bellard
27 15338fd7 bellard
#define ELF_PLATFORM get_elf_platform()
28 15338fd7 bellard
29 15338fd7 bellard
static const char *get_elf_platform(void)
30 15338fd7 bellard
{
31 15338fd7 bellard
    static char elf_platform[] = "i386";
32 15338fd7 bellard
    int family = (global_env->cpuid_version >> 8) & 0xff;
33 15338fd7 bellard
    if (family > 6)
34 15338fd7 bellard
        family = 6;
35 15338fd7 bellard
    if (family >= 3)
36 15338fd7 bellard
        elf_platform[1] = '0' + family;
37 15338fd7 bellard
    return elf_platform;
38 15338fd7 bellard
}
39 15338fd7 bellard
40 15338fd7 bellard
#define ELF_HWCAP get_elf_hwcap()
41 15338fd7 bellard
42 15338fd7 bellard
static uint32_t get_elf_hwcap(void)
43 15338fd7 bellard
{
44 15338fd7 bellard
  return global_env->cpuid_features;
45 15338fd7 bellard
}
46 15338fd7 bellard
47 30ac07d4 bellard
#define ELF_START_MMAP 0x80000000
48 30ac07d4 bellard
49 30ac07d4 bellard
/*
50 30ac07d4 bellard
 * This is used to ensure we don't load something for the wrong architecture.
51 30ac07d4 bellard
 */
52 30ac07d4 bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
53 30ac07d4 bellard
54 30ac07d4 bellard
/*
55 30ac07d4 bellard
 * These are used to set parameters in the core dumps.
56 30ac07d4 bellard
 */
57 30ac07d4 bellard
#define ELF_CLASS        ELFCLASS32
58 30ac07d4 bellard
#define ELF_DATA        ELFDATA2LSB
59 30ac07d4 bellard
#define ELF_ARCH        EM_386
60 30ac07d4 bellard
61 b346ff46 bellard
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
62 b346ff46 bellard
{
63 b346ff46 bellard
    regs->esp = infop->start_stack;
64 b346ff46 bellard
    regs->eip = infop->entry;
65 e5fe0c52 pbrook
66 e5fe0c52 pbrook
    /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
67 e5fe0c52 pbrook
       starts %edx contains a pointer to a function which might be
68 e5fe0c52 pbrook
       registered using `atexit'.  This provides a mean for the
69 e5fe0c52 pbrook
       dynamic linker to call DT_FINI functions for shared libraries
70 e5fe0c52 pbrook
       that have been loaded before the code runs.
71 e5fe0c52 pbrook

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