Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ 6a24a778

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

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