Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ 89fc88da

History | View | Annotate | Download (40.4 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 cb33da57 blueswir1
/* from personality.h */
16 cb33da57 blueswir1
17 cb33da57 blueswir1
/*
18 cb33da57 blueswir1
 * Flags for bug emulation.
19 cb33da57 blueswir1
 *
20 cb33da57 blueswir1
 * These occupy the top three bytes.
21 cb33da57 blueswir1
 */
22 cb33da57 blueswir1
enum {
23 cb33da57 blueswir1
        ADDR_NO_RANDOMIZE =         0x0040000,        /* disable randomization of VA space */
24 cb33da57 blueswir1
        FDPIC_FUNCPTRS =        0x0080000,        /* userspace function ptrs point to descriptors
25 cb33da57 blueswir1
                                                 * (signal handling)
26 cb33da57 blueswir1
                                                 */
27 cb33da57 blueswir1
        MMAP_PAGE_ZERO =        0x0100000,
28 cb33da57 blueswir1
        ADDR_COMPAT_LAYOUT =        0x0200000,
29 cb33da57 blueswir1
        READ_IMPLIES_EXEC =        0x0400000,
30 cb33da57 blueswir1
        ADDR_LIMIT_32BIT =        0x0800000,
31 cb33da57 blueswir1
        SHORT_INODE =                0x1000000,
32 cb33da57 blueswir1
        WHOLE_SECONDS =                0x2000000,
33 cb33da57 blueswir1
        STICKY_TIMEOUTS        =        0x4000000,
34 cb33da57 blueswir1
        ADDR_LIMIT_3GB =         0x8000000,
35 cb33da57 blueswir1
};
36 cb33da57 blueswir1
37 cb33da57 blueswir1
/*
38 cb33da57 blueswir1
 * Personality types.
39 cb33da57 blueswir1
 *
40 cb33da57 blueswir1
 * These go in the low byte.  Avoid using the top bit, it will
41 cb33da57 blueswir1
 * conflict with error returns.
42 cb33da57 blueswir1
 */
43 cb33da57 blueswir1
enum {
44 cb33da57 blueswir1
        PER_LINUX =                0x0000,
45 cb33da57 blueswir1
        PER_LINUX_32BIT =        0x0000 | ADDR_LIMIT_32BIT,
46 cb33da57 blueswir1
        PER_LINUX_FDPIC =        0x0000 | FDPIC_FUNCPTRS,
47 cb33da57 blueswir1
        PER_SVR4 =                0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
48 cb33da57 blueswir1
        PER_SVR3 =                0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
49 cb33da57 blueswir1
        PER_SCOSVR3 =                0x0003 | STICKY_TIMEOUTS |
50 cb33da57 blueswir1
                                         WHOLE_SECONDS | SHORT_INODE,
51 cb33da57 blueswir1
        PER_OSR5 =                0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
52 cb33da57 blueswir1
        PER_WYSEV386 =                0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
53 cb33da57 blueswir1
        PER_ISCR4 =                0x0005 | STICKY_TIMEOUTS,
54 cb33da57 blueswir1
        PER_BSD =                0x0006,
55 cb33da57 blueswir1
        PER_SUNOS =                0x0006 | STICKY_TIMEOUTS,
56 cb33da57 blueswir1
        PER_XENIX =                0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
57 cb33da57 blueswir1
        PER_LINUX32 =                0x0008,
58 cb33da57 blueswir1
        PER_LINUX32_3GB =        0x0008 | ADDR_LIMIT_3GB,
59 cb33da57 blueswir1
        PER_IRIX32 =                0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
60 cb33da57 blueswir1
        PER_IRIXN32 =                0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
61 cb33da57 blueswir1
        PER_IRIX64 =                0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
62 cb33da57 blueswir1
        PER_RISCOS =                0x000c,
63 cb33da57 blueswir1
        PER_SOLARIS =                0x000d | STICKY_TIMEOUTS,
64 cb33da57 blueswir1
        PER_UW7 =                0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
65 cb33da57 blueswir1
        PER_OSF4 =                0x000f,                         /* OSF/1 v4 */
66 cb33da57 blueswir1
        PER_HPUX =                0x0010,
67 cb33da57 blueswir1
        PER_MASK =                0x00ff,
68 cb33da57 blueswir1
};
69 cb33da57 blueswir1
70 cb33da57 blueswir1
/*
71 cb33da57 blueswir1
 * Return the base personality without flags.
72 cb33da57 blueswir1
 */
73 cb33da57 blueswir1
#define personality(pers)        (pers & PER_MASK)
74 cb33da57 blueswir1
75 83fb7adf bellard
/* this flag is uneffective under linux too, should be deleted */
76 83fb7adf bellard
#ifndef MAP_DENYWRITE
77 83fb7adf bellard
#define MAP_DENYWRITE 0
78 83fb7adf bellard
#endif
79 83fb7adf bellard
80 83fb7adf bellard
/* should probably go in elf.h */
81 83fb7adf bellard
#ifndef ELIBBAD
82 83fb7adf bellard
#define ELIBBAD 80
83 83fb7adf bellard
#endif
84 83fb7adf bellard
85 30ac07d4 bellard
#ifdef TARGET_I386
86 30ac07d4 bellard
87 15338fd7 bellard
#define ELF_PLATFORM get_elf_platform()
88 15338fd7 bellard
89 15338fd7 bellard
static const char *get_elf_platform(void)
90 15338fd7 bellard
{
91 15338fd7 bellard
    static char elf_platform[] = "i386";
92 15338fd7 bellard
    int family = (global_env->cpuid_version >> 8) & 0xff;
93 15338fd7 bellard
    if (family > 6)
94 15338fd7 bellard
        family = 6;
95 15338fd7 bellard
    if (family >= 3)
96 15338fd7 bellard
        elf_platform[1] = '0' + family;
97 15338fd7 bellard
    return elf_platform;
98 15338fd7 bellard
}
99 15338fd7 bellard
100 15338fd7 bellard
#define ELF_HWCAP get_elf_hwcap()
101 15338fd7 bellard
102 15338fd7 bellard
static uint32_t get_elf_hwcap(void)
103 15338fd7 bellard
{
104 15338fd7 bellard
  return global_env->cpuid_features;
105 15338fd7 bellard
}
106 15338fd7 bellard
107 84409ddb j_mayer
#ifdef TARGET_X86_64
108 84409ddb j_mayer
#define ELF_START_MMAP 0x2aaaaab000ULL
109 84409ddb j_mayer
#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
110 84409ddb j_mayer
111 84409ddb j_mayer
#define ELF_CLASS      ELFCLASS64
112 84409ddb j_mayer
#define ELF_DATA       ELFDATA2LSB
113 84409ddb j_mayer
#define ELF_ARCH       EM_X86_64
114 84409ddb j_mayer
115 84409ddb j_mayer
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
116 84409ddb j_mayer
{
117 84409ddb j_mayer
    regs->rax = 0;
118 84409ddb j_mayer
    regs->rsp = infop->start_stack;
119 84409ddb j_mayer
    regs->rip = infop->entry;
120 84409ddb j_mayer
}
121 84409ddb j_mayer
122 84409ddb j_mayer
#else
123 84409ddb j_mayer
124 30ac07d4 bellard
#define ELF_START_MMAP 0x80000000
125 30ac07d4 bellard
126 30ac07d4 bellard
/*
127 30ac07d4 bellard
 * This is used to ensure we don't load something for the wrong architecture.
128 30ac07d4 bellard
 */
129 30ac07d4 bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
130 30ac07d4 bellard
131 30ac07d4 bellard
/*
132 30ac07d4 bellard
 * These are used to set parameters in the core dumps.
133 30ac07d4 bellard
 */
134 30ac07d4 bellard
#define ELF_CLASS        ELFCLASS32
135 30ac07d4 bellard
#define ELF_DATA        ELFDATA2LSB
136 30ac07d4 bellard
#define ELF_ARCH        EM_386
137 30ac07d4 bellard
138 b346ff46 bellard
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
139 b346ff46 bellard
{
140 b346ff46 bellard
    regs->esp = infop->start_stack;
141 b346ff46 bellard
    regs->eip = infop->entry;
142 e5fe0c52 pbrook
143 e5fe0c52 pbrook
    /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
144 e5fe0c52 pbrook
       starts %edx contains a pointer to a function which might be
145 e5fe0c52 pbrook
       registered using `atexit'.  This provides a mean for the
146 e5fe0c52 pbrook
       dynamic linker to call DT_FINI functions for shared libraries
147 e5fe0c52 pbrook
       that have been loaded before the code runs.
148 e5fe0c52 pbrook

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