Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ a062e36c

History | View | Annotate | Download (38 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 84409ddb j_mayer
#ifdef TARGET_X86_64
48 84409ddb j_mayer
#define ELF_START_MMAP 0x2aaaaab000ULL
49 84409ddb j_mayer
#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
50 84409ddb j_mayer
51 84409ddb j_mayer
#define ELF_CLASS      ELFCLASS64
52 84409ddb j_mayer
#define ELF_DATA       ELFDATA2LSB
53 84409ddb j_mayer
#define ELF_ARCH       EM_X86_64
54 84409ddb j_mayer
55 84409ddb j_mayer
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
56 84409ddb j_mayer
{
57 84409ddb j_mayer
    regs->rax = 0;
58 84409ddb j_mayer
    regs->rsp = infop->start_stack;
59 84409ddb j_mayer
    regs->rip = infop->entry;
60 84409ddb j_mayer
}
61 84409ddb j_mayer
62 84409ddb j_mayer
#else
63 84409ddb j_mayer
64 30ac07d4 bellard
#define ELF_START_MMAP 0x80000000
65 30ac07d4 bellard
66 30ac07d4 bellard
/*
67 30ac07d4 bellard
 * This is used to ensure we don't load something for the wrong architecture.
68 30ac07d4 bellard
 */
69 30ac07d4 bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
70 30ac07d4 bellard
71 30ac07d4 bellard
/*
72 30ac07d4 bellard
 * These are used to set parameters in the core dumps.
73 30ac07d4 bellard
 */
74 30ac07d4 bellard
#define ELF_CLASS        ELFCLASS32
75 30ac07d4 bellard
#define ELF_DATA        ELFDATA2LSB
76 30ac07d4 bellard
#define ELF_ARCH        EM_386
77 30ac07d4 bellard
78 b346ff46 bellard
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
79 b346ff46 bellard
{
80 b346ff46 bellard
    regs->esp = infop->start_stack;
81 b346ff46 bellard
    regs->eip = infop->entry;
82 e5fe0c52 pbrook
83 e5fe0c52 pbrook
    /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
84 e5fe0c52 pbrook
       starts %edx contains a pointer to a function which might be
85 e5fe0c52 pbrook
       registered using `atexit'.  This provides a mean for the
86 e5fe0c52 pbrook
       dynamic linker to call DT_FINI functions for shared libraries
87 e5fe0c52 pbrook
       that have been loaded before the code runs.
88 e5fe0c52 pbrook

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