Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ b1f9be31

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