Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ b5dc7732

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