Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ d084469c

History | View | Annotate | Download (42.1 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 e58ffeb3 malc
#ifdef _ARCH_PPC64
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
static int load_aout_interp(void * exptr, int interp_fd);
549 31e31b8a bellard
550 31e31b8a bellard
#ifdef BSWAP_NEEDED
551 92a31b1f bellard
static void bswap_ehdr(struct elfhdr *ehdr)
552 31e31b8a bellard
{
553 31e31b8a bellard
    bswap16s(&ehdr->e_type);                        /* Object file type */
554 31e31b8a bellard
    bswap16s(&ehdr->e_machine);                /* Architecture */
555 31e31b8a bellard
    bswap32s(&ehdr->e_version);                /* Object file version */
556 92a31b1f bellard
    bswaptls(&ehdr->e_entry);                /* Entry point virtual address */
557 92a31b1f bellard
    bswaptls(&ehdr->e_phoff);                /* Program header table file offset */
558 92a31b1f bellard
    bswaptls(&ehdr->e_shoff);                /* Section header table file offset */
559 31e31b8a bellard
    bswap32s(&ehdr->e_flags);                /* Processor-specific flags */
560 31e31b8a bellard
    bswap16s(&ehdr->e_ehsize);                /* ELF header size in bytes */
561 31e31b8a bellard
    bswap16s(&ehdr->e_phentsize);                /* Program header table entry size */
562 31e31b8a bellard
    bswap16s(&ehdr->e_phnum);                /* Program header table entry count */
563 31e31b8a bellard
    bswap16s(&ehdr->e_shentsize);                /* Section header table entry size */
564 31e31b8a bellard
    bswap16s(&ehdr->e_shnum);                /* Section header table entry count */
565 31e31b8a bellard
    bswap16s(&ehdr->e_shstrndx);                /* Section header string table index */
566 31e31b8a bellard
}
567 31e31b8a bellard
568 92a31b1f bellard
static void bswap_phdr(struct elf_phdr *phdr)
569 31e31b8a bellard
{
570 31e31b8a bellard
    bswap32s(&phdr->p_type);                        /* Segment type */
571 92a31b1f bellard
    bswaptls(&phdr->p_offset);                /* Segment file offset */
572 92a31b1f bellard
    bswaptls(&phdr->p_vaddr);                /* Segment virtual address */
573 92a31b1f bellard
    bswaptls(&phdr->p_paddr);                /* Segment physical address */
574 92a31b1f bellard
    bswaptls(&phdr->p_filesz);                /* Segment size in file */
575 92a31b1f bellard
    bswaptls(&phdr->p_memsz);                /* Segment size in memory */
576 31e31b8a bellard
    bswap32s(&phdr->p_flags);                /* Segment flags */
577 92a31b1f bellard
    bswaptls(&phdr->p_align);                /* Segment alignment */
578 31e31b8a bellard
}
579 689f936f bellard
580 92a31b1f bellard
static void bswap_shdr(struct elf_shdr *shdr)
581 689f936f bellard
{
582 689f936f bellard
    bswap32s(&shdr->sh_name);
583 689f936f bellard
    bswap32s(&shdr->sh_type);
584 92a31b1f bellard
    bswaptls(&shdr->sh_flags);
585 92a31b1f bellard
    bswaptls(&shdr->sh_addr);
586 92a31b1f bellard
    bswaptls(&shdr->sh_offset);
587 92a31b1f bellard
    bswaptls(&shdr->sh_size);
588 689f936f bellard
    bswap32s(&shdr->sh_link);
589 689f936f bellard
    bswap32s(&shdr->sh_info);
590 92a31b1f bellard
    bswaptls(&shdr->sh_addralign);
591 92a31b1f bellard
    bswaptls(&shdr->sh_entsize);
592 689f936f bellard
}
593 689f936f bellard
594 7a3148a9 j_mayer
static void bswap_sym(struct elf_sym *sym)
595 689f936f bellard
{
596 689f936f bellard
    bswap32s(&sym->st_name);
597 7a3148a9 j_mayer
    bswaptls(&sym->st_value);
598 7a3148a9 j_mayer
    bswaptls(&sym->st_size);
599 689f936f bellard
    bswap16s(&sym->st_shndx);
600 689f936f bellard
}
601 31e31b8a bellard
#endif
602 31e31b8a bellard
603 31e31b8a bellard
/*
604 e5fe0c52 pbrook
 * 'copy_elf_strings()' copies argument/envelope strings from user
605 31e31b8a bellard
 * memory to free pages in kernel mem. These are in a format ready
606 31e31b8a bellard
 * to be put directly into the top of new user memory.
607 31e31b8a bellard
 *
608 31e31b8a bellard
 */
609 992f48a0 blueswir1
static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
610 992f48a0 blueswir1
                                  abi_ulong p)
611 31e31b8a bellard
{
612 31e31b8a bellard
    char *tmp, *tmp1, *pag = NULL;
613 31e31b8a bellard
    int len, offset = 0;
614 31e31b8a bellard
615 31e31b8a bellard
    if (!p) {
616 31e31b8a bellard
        return 0;       /* bullet-proofing */
617 31e31b8a bellard
    }
618 31e31b8a bellard
    while (argc-- > 0) {
619 edf779ff bellard
        tmp = argv[argc];
620 edf779ff bellard
        if (!tmp) {
621 31e31b8a bellard
            fprintf(stderr, "VFS: argc is wrong");
622 31e31b8a bellard
            exit(-1);
623 31e31b8a bellard
        }
624 edf779ff bellard
        tmp1 = tmp;
625 edf779ff bellard
        while (*tmp++);
626 31e31b8a bellard
        len = tmp - tmp1;
627 31e31b8a bellard
        if (p < len) {  /* this shouldn't happen - 128kB */
628 31e31b8a bellard
                return 0;
629 31e31b8a bellard
        }
630 31e31b8a bellard
        while (len) {
631 31e31b8a bellard
            --p; --tmp; --len;
632 31e31b8a bellard
            if (--offset < 0) {
633 54936004 bellard
                offset = p % TARGET_PAGE_SIZE;
634 53a5960a pbrook
                pag = (char *)page[p/TARGET_PAGE_SIZE];
635 44a91cae bellard
                if (!pag) {
636 53a5960a pbrook
                    pag = (char *)malloc(TARGET_PAGE_SIZE);
637 4118a970 j_mayer
                    memset(pag, 0, TARGET_PAGE_SIZE);
638 53a5960a pbrook
                    page[p/TARGET_PAGE_SIZE] = pag;
639 44a91cae bellard
                    if (!pag)
640 44a91cae bellard
                        return 0;
641 31e31b8a bellard
                }
642 31e31b8a bellard
            }
643 31e31b8a bellard
            if (len == 0 || offset == 0) {
644 edf779ff bellard
                *(pag + offset) = *tmp;
645 31e31b8a bellard
            }
646 31e31b8a bellard
            else {
647 31e31b8a bellard
              int bytes_to_copy = (len > offset) ? offset : len;
648 31e31b8a bellard
              tmp -= bytes_to_copy;
649 31e31b8a bellard
              p -= bytes_to_copy;
650 31e31b8a bellard
              offset -= bytes_to_copy;
651 31e31b8a bellard
              len -= bytes_to_copy;
652 31e31b8a bellard
              memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
653 31e31b8a bellard
            }
654 31e31b8a bellard
        }
655 31e31b8a bellard
    }
656 31e31b8a bellard
    return p;
657 31e31b8a bellard
}
658 31e31b8a bellard
659 992f48a0 blueswir1
static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
660 992f48a0 blueswir1
                                 struct image_info *info)
661 53a5960a pbrook
{
662 992f48a0 blueswir1
    abi_ulong stack_base, size, error;
663 31e31b8a bellard
    int i;
664 31e31b8a bellard
665 09bfb054 bellard
    /* Create enough stack to hold everything.  If we don't use
666 09bfb054 bellard
     * it for args, we'll use it for something else...
667 09bfb054 bellard
     */
668 09bfb054 bellard
    size = x86_stack_size;
669 54936004 bellard
    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
670 54936004 bellard
        size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
671 5fafdf24 ths
    error = target_mmap(0,
672 83fb7adf bellard
                        size + qemu_host_page_size,
673 54936004 bellard
                        PROT_READ | PROT_WRITE,
674 54936004 bellard
                        MAP_PRIVATE | MAP_ANONYMOUS,
675 54936004 bellard
                        -1, 0);
676 09bfb054 bellard
    if (error == -1) {
677 09bfb054 bellard
        perror("stk mmap");
678 09bfb054 bellard
        exit(-1);
679 09bfb054 bellard
    }
680 09bfb054 bellard
    /* we reserve one extra page at the top of the stack as guard */
681 83fb7adf bellard
    target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
682 31e31b8a bellard
683 54936004 bellard
    stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
684 31e31b8a bellard
    p += stack_base;
685 09bfb054 bellard
686 31e31b8a bellard
    for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
687 31e31b8a bellard
        if (bprm->page[i]) {
688 31e31b8a bellard
            info->rss++;
689 579a97f7 bellard
            /* FIXME - check return value of memcpy_to_target() for failure */
690 53a5960a pbrook
            memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
691 53a5960a pbrook
            free(bprm->page[i]);
692 31e31b8a bellard
        }
693 53a5960a pbrook
        stack_base += TARGET_PAGE_SIZE;
694 31e31b8a bellard
    }
695 31e31b8a bellard
    return p;
696 31e31b8a bellard
}
697 31e31b8a bellard
698 992f48a0 blueswir1
static void set_brk(abi_ulong start, abi_ulong end)
699 31e31b8a bellard
{
700 31e31b8a bellard
        /* page-align the start and end addresses... */
701 54936004 bellard
        start = HOST_PAGE_ALIGN(start);
702 54936004 bellard
        end = HOST_PAGE_ALIGN(end);
703 31e31b8a bellard
        if (end <= start)
704 31e31b8a bellard
                return;
705 54936004 bellard
        if(target_mmap(start, end - start,
706 54936004 bellard
                       PROT_READ | PROT_WRITE | PROT_EXEC,
707 54936004 bellard
                       MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
708 31e31b8a bellard
            perror("cannot mmap brk");
709 31e31b8a bellard
            exit(-1);
710 31e31b8a bellard
        }
711 31e31b8a bellard
}
712 31e31b8a bellard
713 31e31b8a bellard
714 853d6f7a bellard
/* We need to explicitly zero any fractional pages after the data
715 853d6f7a bellard
   section (i.e. bss).  This would contain the junk from the file that
716 853d6f7a bellard
   should not be in memory. */
717 992f48a0 blueswir1
static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
718 31e31b8a bellard
{
719 992f48a0 blueswir1
        abi_ulong nbyte;
720 31e31b8a bellard
721 768a4a36 ths
        if (elf_bss >= last_bss)
722 768a4a36 ths
                return;
723 768a4a36 ths
724 853d6f7a bellard
        /* XXX: this is really a hack : if the real host page size is
725 853d6f7a bellard
           smaller than the target page size, some pages after the end
726 853d6f7a bellard
           of the file may not be mapped. A better fix would be to
727 853d6f7a bellard
           patch target_mmap(), but it is more complicated as the file
728 853d6f7a bellard
           size must be known */
729 83fb7adf bellard
        if (qemu_real_host_page_size < qemu_host_page_size) {
730 992f48a0 blueswir1
            abi_ulong end_addr, end_addr1;
731 5fafdf24 ths
            end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
732 83fb7adf bellard
                ~(qemu_real_host_page_size - 1);
733 853d6f7a bellard
            end_addr = HOST_PAGE_ALIGN(elf_bss);
734 853d6f7a bellard
            if (end_addr1 < end_addr) {
735 863cf0b7 j_mayer
                mmap((void *)g2h(end_addr1), end_addr - end_addr1,
736 853d6f7a bellard
                     PROT_READ|PROT_WRITE|PROT_EXEC,
737 853d6f7a bellard
                     MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
738 853d6f7a bellard
            }
739 853d6f7a bellard
        }
740 853d6f7a bellard
741 83fb7adf bellard
        nbyte = elf_bss & (qemu_host_page_size-1);
742 31e31b8a bellard
        if (nbyte) {
743 83fb7adf bellard
            nbyte = qemu_host_page_size - nbyte;
744 31e31b8a bellard
            do {
745 2f619698 bellard
                /* FIXME - what to do if put_user() fails? */
746 2f619698 bellard
                put_user_u8(0, elf_bss);
747 53a5960a pbrook
                elf_bss++;
748 31e31b8a bellard
            } while (--nbyte);
749 31e31b8a bellard
        }
750 31e31b8a bellard
}
751 31e31b8a bellard
752 53a5960a pbrook
753 992f48a0 blueswir1
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
754 992f48a0 blueswir1
                                   struct elfhdr * exec,
755 992f48a0 blueswir1
                                   abi_ulong load_addr,
756 992f48a0 blueswir1
                                   abi_ulong load_bias,
757 992f48a0 blueswir1
                                   abi_ulong interp_load_addr, int ibcs,
758 992f48a0 blueswir1
                                   struct image_info *info)
759 31e31b8a bellard
{
760 992f48a0 blueswir1
        abi_ulong sp;
761 53a5960a pbrook
        int size;
762 992f48a0 blueswir1
        abi_ulong u_platform;
763 15338fd7 bellard
        const char *k_platform;
764 863cf0b7 j_mayer
        const int n = sizeof(elf_addr_t);
765 edf779ff bellard
766 53a5960a pbrook
        sp = p;
767 53a5960a pbrook
        u_platform = 0;
768 15338fd7 bellard
        k_platform = ELF_PLATFORM;
769 15338fd7 bellard
        if (k_platform) {
770 15338fd7 bellard
            size_t len = strlen(k_platform) + 1;
771 53a5960a pbrook
            sp -= (len + n - 1) & ~(n - 1);
772 53a5960a pbrook
            u_platform = sp;
773 579a97f7 bellard
            /* FIXME - check return value of memcpy_to_target() for failure */
774 53a5960a pbrook
            memcpy_to_target(sp, k_platform, len);
775 15338fd7 bellard
        }
776 53a5960a pbrook
        /*
777 53a5960a pbrook
         * Force 16 byte _final_ alignment here for generality.
778 53a5960a pbrook
         */
779 992f48a0 blueswir1
        sp = sp &~ (abi_ulong)15;
780 53a5960a pbrook
        size = (DLINFO_ITEMS + 1) * 2;
781 15338fd7 bellard
        if (k_platform)
782 53a5960a pbrook
          size += 2;
783 f5155289 bellard
#ifdef DLINFO_ARCH_ITEMS
784 53a5960a pbrook
        size += DLINFO_ARCH_ITEMS * 2;
785 f5155289 bellard
#endif
786 53a5960a pbrook
        size += envc + argc + 2;
787 53a5960a pbrook
        size += (!ibcs ? 3 : 1);        /* argc itself */
788 53a5960a pbrook
        size *= n;
789 53a5960a pbrook
        if (size & 15)
790 53a5960a pbrook
            sp -= 16 - (size & 15);
791 3b46e624 ths
792 863cf0b7 j_mayer
        /* This is correct because Linux defines
793 863cf0b7 j_mayer
         * elf_addr_t as Elf32_Off / Elf64_Off
794 863cf0b7 j_mayer
         */
795 2f619698 bellard
#define NEW_AUX_ENT(id, val) do {                \
796 2f619698 bellard
            sp -= n; put_user_ual(val, sp);        \
797 2f619698 bellard
            sp -= n; put_user_ual(id, sp);        \
798 53a5960a pbrook
          } while(0)
799 2f619698 bellard
800 0bccf03d bellard
        NEW_AUX_ENT (AT_NULL, 0);
801 0bccf03d bellard
802 0bccf03d bellard
        /* There must be exactly DLINFO_ITEMS entries here.  */
803 992f48a0 blueswir1
        NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
804 992f48a0 blueswir1
        NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
805 992f48a0 blueswir1
        NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
806 992f48a0 blueswir1
        NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
807 992f48a0 blueswir1
        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
808 992f48a0 blueswir1
        NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
809 0bccf03d bellard
        NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
810 992f48a0 blueswir1
        NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
811 992f48a0 blueswir1
        NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
812 992f48a0 blueswir1
        NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
813 992f48a0 blueswir1
        NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
814 992f48a0 blueswir1
        NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
815 a07c67df pbrook
        NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
816 15338fd7 bellard
        if (k_platform)
817 53a5960a pbrook
            NEW_AUX_ENT(AT_PLATFORM, u_platform);
818 f5155289 bellard
#ifdef ARCH_DLINFO
819 5fafdf24 ths
        /*
820 f5155289 bellard
         * ARCH_DLINFO must come last so platform specific code can enforce
821 f5155289 bellard
         * special alignment requirements on the AUXV if necessary (eg. PPC).
822 f5155289 bellard
         */
823 f5155289 bellard
        ARCH_DLINFO;
824 f5155289 bellard
#endif
825 f5155289 bellard
#undef NEW_AUX_ENT
826 f5155289 bellard
827 e5fe0c52 pbrook
        sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
828 31e31b8a bellard
        return sp;
829 31e31b8a bellard
}
830 31e31b8a bellard
831 31e31b8a bellard
832 992f48a0 blueswir1
static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
833 992f48a0 blueswir1
                                 int interpreter_fd,
834 992f48a0 blueswir1
                                 abi_ulong *interp_load_addr)
835 31e31b8a bellard
{
836 31e31b8a bellard
        struct elf_phdr *elf_phdata  =  NULL;
837 31e31b8a bellard
        struct elf_phdr *eppnt;
838 992f48a0 blueswir1
        abi_ulong load_addr = 0;
839 31e31b8a bellard
        int load_addr_set = 0;
840 31e31b8a bellard
        int retval;
841 992f48a0 blueswir1
        abi_ulong last_bss, elf_bss;
842 992f48a0 blueswir1
        abi_ulong error;
843 31e31b8a bellard
        int i;
844 5fafdf24 ths
845 31e31b8a bellard
        elf_bss = 0;
846 31e31b8a bellard
        last_bss = 0;
847 31e31b8a bellard
        error = 0;
848 31e31b8a bellard
849 644c433c bellard
#ifdef BSWAP_NEEDED
850 644c433c bellard
        bswap_ehdr(interp_elf_ex);
851 644c433c bellard
#endif
852 31e31b8a bellard
        /* First of all, some simple consistency checks */
853 5fafdf24 ths
        if ((interp_elf_ex->e_type != ET_EXEC &&
854 5fafdf24 ths
             interp_elf_ex->e_type != ET_DYN) ||
855 31e31b8a bellard
           !elf_check_arch(interp_elf_ex->e_machine)) {
856 992f48a0 blueswir1
                return ~((abi_ulong)0UL);
857 31e31b8a bellard
        }
858 5fafdf24 ths
859 644c433c bellard
860 31e31b8a bellard
        /* Now read in all of the header information */
861 5fafdf24 ths
862 54936004 bellard
        if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
863 992f48a0 blueswir1
            return ~(abi_ulong)0UL;
864 5fafdf24 ths
865 5fafdf24 ths
        elf_phdata =  (struct elf_phdr *)
866 31e31b8a bellard
                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
867 31e31b8a bellard
868 31e31b8a bellard
        if (!elf_phdata)
869 992f48a0 blueswir1
          return ~((abi_ulong)0UL);
870 5fafdf24 ths
871 31e31b8a bellard
        /*
872 31e31b8a bellard
         * If the size of this structure has changed, then punt, since
873 31e31b8a bellard
         * we will be doing the wrong thing.
874 31e31b8a bellard
         */
875 09bfb054 bellard
        if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
876 31e31b8a bellard
            free(elf_phdata);
877 992f48a0 blueswir1
            return ~((abi_ulong)0UL);
878 09bfb054 bellard
        }
879 31e31b8a bellard
880 31e31b8a bellard
        retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
881 31e31b8a bellard
        if(retval >= 0) {
882 31e31b8a bellard
            retval = read(interpreter_fd,
883 31e31b8a bellard
                           (char *) elf_phdata,
884 31e31b8a bellard
                           sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
885 31e31b8a bellard
        }
886 31e31b8a bellard
        if (retval < 0) {
887 31e31b8a bellard
                perror("load_elf_interp");
888 31e31b8a bellard
                exit(-1);
889 31e31b8a bellard
                free (elf_phdata);
890 31e31b8a bellard
                return retval;
891 31e31b8a bellard
         }
892 31e31b8a bellard
#ifdef BSWAP_NEEDED
893 31e31b8a bellard
        eppnt = elf_phdata;
894 31e31b8a bellard
        for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
895 31e31b8a bellard
            bswap_phdr(eppnt);
896 31e31b8a bellard
        }
897 31e31b8a bellard
#endif
898 09bfb054 bellard
899 09bfb054 bellard
        if (interp_elf_ex->e_type == ET_DYN) {
900 e91c8a77 ths
            /* in order to avoid hardcoding the interpreter load
901 09bfb054 bellard
               address in qemu, we allocate a big enough memory zone */
902 54936004 bellard
            error = target_mmap(0, INTERP_MAP_SIZE,
903 5fafdf24 ths
                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
904 54936004 bellard
                                -1, 0);
905 09bfb054 bellard
            if (error == -1) {
906 09bfb054 bellard
                perror("mmap");
907 09bfb054 bellard
                exit(-1);
908 09bfb054 bellard
            }
909 09bfb054 bellard
            load_addr = error;
910 09bfb054 bellard
            load_addr_set = 1;
911 09bfb054 bellard
        }
912 09bfb054 bellard
913 31e31b8a bellard
        eppnt = elf_phdata;
914 31e31b8a bellard
        for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
915 31e31b8a bellard
          if (eppnt->p_type == PT_LOAD) {
916 31e31b8a bellard
            int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
917 31e31b8a bellard
            int elf_prot = 0;
918 992f48a0 blueswir1
            abi_ulong vaddr = 0;
919 992f48a0 blueswir1
            abi_ulong k;
920 31e31b8a bellard
921 31e31b8a bellard
            if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
922 31e31b8a bellard
            if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
923 31e31b8a bellard
            if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
924 31e31b8a bellard
            if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
925 31e31b8a bellard
                    elf_type |= MAP_FIXED;
926 31e31b8a bellard
                    vaddr = eppnt->p_vaddr;
927 31e31b8a bellard
            }
928 54936004 bellard
            error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
929 54936004 bellard
                 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
930 31e31b8a bellard
                 elf_prot,
931 31e31b8a bellard
                 elf_type,
932 31e31b8a bellard
                 interpreter_fd,
933 54936004 bellard
                 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
934 3b46e624 ths
935 e89f07d3 pbrook
            if (error == -1) {
936 31e31b8a bellard
              /* Real error */
937 31e31b8a bellard
              close(interpreter_fd);
938 31e31b8a bellard
              free(elf_phdata);
939 992f48a0 blueswir1
              return ~((abi_ulong)0UL);
940 31e31b8a bellard
            }
941 31e31b8a bellard
942 31e31b8a bellard
            if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
943 31e31b8a bellard
              load_addr = error;
944 31e31b8a bellard
              load_addr_set = 1;
945 31e31b8a bellard
            }
946 31e31b8a bellard
947 31e31b8a bellard
            /*
948 31e31b8a bellard
             * Find the end of the file  mapping for this phdr, and keep
949 31e31b8a bellard
             * track of the largest address we see for this.
950 31e31b8a bellard
             */
951 31e31b8a bellard
            k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
952 31e31b8a bellard
            if (k > elf_bss) elf_bss = k;
953 31e31b8a bellard
954 31e31b8a bellard
            /*
955 31e31b8a bellard
             * Do the same thing for the memory mapping - between
956 31e31b8a bellard
             * elf_bss and last_bss is the bss section.
957 31e31b8a bellard
             */
958 31e31b8a bellard
            k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
959 31e31b8a bellard
            if (k > last_bss) last_bss = k;
960 31e31b8a bellard
          }
961 5fafdf24 ths
962 31e31b8a bellard
        /* Now use mmap to map the library into memory. */
963 31e31b8a bellard
964 31e31b8a bellard
        close(interpreter_fd);
965 31e31b8a bellard
966 31e31b8a bellard
        /*
967 31e31b8a bellard
         * Now fill out the bss section.  First pad the last page up
968 31e31b8a bellard
         * to the page boundary, and then perform a mmap to make sure
969 31e31b8a bellard
         * that there are zeromapped pages up to and including the last
970 31e31b8a bellard
         * bss page.
971 31e31b8a bellard
         */
972 768a4a36 ths
        padzero(elf_bss, last_bss);
973 83fb7adf bellard
        elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
974 31e31b8a bellard
975 31e31b8a bellard
        /* Map the last of the bss segment */
976 31e31b8a bellard
        if (last_bss > elf_bss) {
977 54936004 bellard
            target_mmap(elf_bss, last_bss-elf_bss,
978 54936004 bellard
                        PROT_READ|PROT_WRITE|PROT_EXEC,
979 54936004 bellard
                        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
980 31e31b8a bellard
        }
981 31e31b8a bellard
        free(elf_phdata);
982 31e31b8a bellard
983 31e31b8a bellard
        *interp_load_addr = load_addr;
984 992f48a0 blueswir1
        return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
985 31e31b8a bellard
}
986 31e31b8a bellard
987 49918a75 pbrook
static int symfind(const void *s0, const void *s1)
988 49918a75 pbrook
{
989 49918a75 pbrook
    struct elf_sym *key = (struct elf_sym *)s0;
990 49918a75 pbrook
    struct elf_sym *sym = (struct elf_sym *)s1;
991 49918a75 pbrook
    int result = 0;
992 49918a75 pbrook
    if (key->st_value < sym->st_value) {
993 49918a75 pbrook
        result = -1;
994 49918a75 pbrook
    } else if (key->st_value > sym->st_value + sym->st_size) {
995 49918a75 pbrook
        result = 1;
996 49918a75 pbrook
    }
997 49918a75 pbrook
    return result;
998 49918a75 pbrook
}
999 49918a75 pbrook
1000 49918a75 pbrook
static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
1001 49918a75 pbrook
{
1002 49918a75 pbrook
#if ELF_CLASS == ELFCLASS32
1003 49918a75 pbrook
    struct elf_sym *syms = s->disas_symtab.elf32;
1004 49918a75 pbrook
#else
1005 49918a75 pbrook
    struct elf_sym *syms = s->disas_symtab.elf64;
1006 49918a75 pbrook
#endif
1007 49918a75 pbrook
1008 49918a75 pbrook
    // binary search
1009 49918a75 pbrook
    struct elf_sym key;
1010 49918a75 pbrook
    struct elf_sym *sym;
1011 49918a75 pbrook
1012 49918a75 pbrook
    key.st_value = orig_addr;
1013 49918a75 pbrook
1014 49918a75 pbrook
    sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
1015 49918a75 pbrook
    if (sym != 0) {
1016 49918a75 pbrook
        return s->disas_strtab + sym->st_name;
1017 49918a75 pbrook
    }
1018 49918a75 pbrook
1019 49918a75 pbrook
    return "";
1020 49918a75 pbrook
}
1021 49918a75 pbrook
1022 49918a75 pbrook
/* FIXME: This should use elf_ops.h  */
1023 49918a75 pbrook
static int symcmp(const void *s0, const void *s1)
1024 49918a75 pbrook
{
1025 49918a75 pbrook
    struct elf_sym *sym0 = (struct elf_sym *)s0;
1026 49918a75 pbrook
    struct elf_sym *sym1 = (struct elf_sym *)s1;
1027 49918a75 pbrook
    return (sym0->st_value < sym1->st_value)
1028 49918a75 pbrook
        ? -1
1029 49918a75 pbrook
        : ((sym0->st_value > sym1->st_value) ? 1 : 0);
1030 49918a75 pbrook
}
1031 49918a75 pbrook
1032 689f936f bellard
/* Best attempt to load symbols from this ELF object. */
1033 689f936f bellard
static void load_symbols(struct elfhdr *hdr, int fd)
1034 689f936f bellard
{
1035 49918a75 pbrook
    unsigned int i, nsyms;
1036 689f936f bellard
    struct elf_shdr sechdr, symtab, strtab;
1037 689f936f bellard
    char *strings;
1038 e80cfcfc bellard
    struct syminfo *s;
1039 49918a75 pbrook
    struct elf_sym *syms;
1040 689f936f bellard
1041 689f936f bellard
    lseek(fd, hdr->e_shoff, SEEK_SET);
1042 689f936f bellard
    for (i = 0; i < hdr->e_shnum; i++) {
1043 49918a75 pbrook
        if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
1044 49918a75 pbrook
            return;
1045 689f936f bellard
#ifdef BSWAP_NEEDED
1046 49918a75 pbrook
        bswap_shdr(&sechdr);
1047 689f936f bellard
#endif
1048 49918a75 pbrook
        if (sechdr.sh_type == SHT_SYMTAB) {
1049 49918a75 pbrook
            symtab = sechdr;
1050 49918a75 pbrook
            lseek(fd, hdr->e_shoff
1051 49918a75 pbrook
                  + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
1052 49918a75 pbrook
            if (read(fd, &strtab, sizeof(strtab))
1053 49918a75 pbrook
                != sizeof(strtab))
1054 49918a75 pbrook
                return;
1055 689f936f bellard
#ifdef BSWAP_NEEDED
1056 49918a75 pbrook
            bswap_shdr(&strtab);
1057 689f936f bellard
#endif
1058 49918a75 pbrook
            goto found;
1059 49918a75 pbrook
        }
1060 689f936f bellard
    }
1061 689f936f bellard
    return; /* Shouldn't happen... */
1062 689f936f bellard
1063 689f936f bellard
 found:
1064 689f936f bellard
    /* Now know where the strtab and symtab are.  Snarf them. */
1065 e80cfcfc bellard
    s = malloc(sizeof(*s));
1066 49918a75 pbrook
    syms = malloc(symtab.sh_size);
1067 49918a75 pbrook
    if (!syms)
1068 49918a75 pbrook
        return;
1069 e80cfcfc bellard
    s->disas_strtab = strings = malloc(strtab.sh_size);
1070 49918a75 pbrook
    if (!s->disas_strtab)
1071 49918a75 pbrook
        return;
1072 5fafdf24 ths
1073 689f936f bellard
    lseek(fd, symtab.sh_offset, SEEK_SET);
1074 49918a75 pbrook
    if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
1075 49918a75 pbrook
        return;
1076 49918a75 pbrook
1077 49918a75 pbrook
    nsyms = symtab.sh_size / sizeof(struct elf_sym);
1078 31e31b8a bellard
1079 49918a75 pbrook
    i = 0;
1080 49918a75 pbrook
    while (i < nsyms) {
1081 689f936f bellard
#ifdef BSWAP_NEEDED
1082 49918a75 pbrook
        bswap_sym(syms + i);
1083 689f936f bellard
#endif
1084 49918a75 pbrook
        // Throw away entries which we do not need.
1085 49918a75 pbrook
        if (syms[i].st_shndx == SHN_UNDEF ||
1086 49918a75 pbrook
                syms[i].st_shndx >= SHN_LORESERVE ||
1087 49918a75 pbrook
                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
1088 49918a75 pbrook
            nsyms--;
1089 49918a75 pbrook
            if (i < nsyms) {
1090 49918a75 pbrook
                syms[i] = syms[nsyms];
1091 49918a75 pbrook
            }
1092 49918a75 pbrook
            continue;
1093 49918a75 pbrook
        }
1094 49918a75 pbrook
#if defined(TARGET_ARM) || defined (TARGET_MIPS)
1095 49918a75 pbrook
        /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
1096 49918a75 pbrook
        syms[i].st_value &= ~(target_ulong)1;
1097 0774bed1 blueswir1
#endif
1098 49918a75 pbrook
        i++;
1099 0774bed1 blueswir1
    }
1100 49918a75 pbrook
    syms = realloc(syms, nsyms * sizeof(*syms));
1101 49918a75 pbrook
1102 49918a75 pbrook
    qsort(syms, nsyms, sizeof(*syms), symcmp);
1103 689f936f bellard
1104 689f936f bellard
    lseek(fd, strtab.sh_offset, SEEK_SET);
1105 689f936f bellard
    if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
1106 49918a75 pbrook
        return;
1107 49918a75 pbrook
    s->disas_num_syms = nsyms;
1108 49918a75 pbrook
#if ELF_CLASS == ELFCLASS32
1109 49918a75 pbrook
    s->disas_symtab.elf32 = syms;
1110 49918a75 pbrook
    s->lookup_symbol = lookup_symbolxx;
1111 49918a75 pbrook
#else
1112 49918a75 pbrook
    s->disas_symtab.elf64 = syms;
1113 49918a75 pbrook
    s->lookup_symbol = lookup_symbolxx;
1114 49918a75 pbrook
#endif
1115 e80cfcfc bellard
    s->next = syminfos;
1116 e80cfcfc bellard
    syminfos = s;
1117 689f936f bellard
}
1118 31e31b8a bellard
1119 e5fe0c52 pbrook
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1120 e5fe0c52 pbrook
                    struct image_info * info)
1121 31e31b8a bellard
{
1122 31e31b8a bellard
    struct elfhdr elf_ex;
1123 31e31b8a bellard
    struct elfhdr interp_elf_ex;
1124 31e31b8a bellard
    struct exec interp_ex;
1125 31e31b8a bellard
    int interpreter_fd = -1; /* avoid warning */
1126 992f48a0 blueswir1
    abi_ulong load_addr, load_bias;
1127 31e31b8a bellard
    int load_addr_set = 0;
1128 31e31b8a bellard
    unsigned int interpreter_type = INTERPRETER_NONE;
1129 31e31b8a bellard
    unsigned char ibcs2_interpreter;
1130 31e31b8a bellard
    int i;
1131 992f48a0 blueswir1
    abi_ulong mapped_addr;
1132 31e31b8a bellard
    struct elf_phdr * elf_ppnt;
1133 31e31b8a bellard
    struct elf_phdr *elf_phdata;
1134 992f48a0 blueswir1
    abi_ulong elf_bss, k, elf_brk;
1135 31e31b8a bellard
    int retval;
1136 31e31b8a bellard
    char * elf_interpreter;
1137 992f48a0 blueswir1
    abi_ulong elf_entry, interp_load_addr = 0;
1138 31e31b8a bellard
    int status;
1139 992f48a0 blueswir1
    abi_ulong start_code, end_code, start_data, end_data;
1140 992f48a0 blueswir1
    abi_ulong reloc_func_desc = 0;
1141 992f48a0 blueswir1
    abi_ulong elf_stack;
1142 31e31b8a bellard
    char passed_fileno[6];
1143 31e31b8a bellard
1144 31e31b8a bellard
    ibcs2_interpreter = 0;
1145 31e31b8a bellard
    status = 0;
1146 31e31b8a bellard
    load_addr = 0;
1147 09bfb054 bellard
    load_bias = 0;
1148 31e31b8a bellard
    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
1149 31e31b8a bellard
#ifdef BSWAP_NEEDED
1150 31e31b8a bellard
    bswap_ehdr(&elf_ex);
1151 31e31b8a bellard
#endif
1152 31e31b8a bellard
1153 31e31b8a bellard
    /* First of all, some simple consistency checks */
1154 31e31b8a bellard
    if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
1155 31e31b8a bellard
                                       (! elf_check_arch(elf_ex.e_machine))) {
1156 31e31b8a bellard
            return -ENOEXEC;
1157 31e31b8a bellard
    }
1158 31e31b8a bellard
1159 e5fe0c52 pbrook
    bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1160 e5fe0c52 pbrook
    bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1161 e5fe0c52 pbrook
    bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1162 e5fe0c52 pbrook
    if (!bprm->p) {
1163 e5fe0c52 pbrook
        retval = -E2BIG;
1164 e5fe0c52 pbrook
    }
1165 e5fe0c52 pbrook
1166 31e31b8a bellard
    /* Now read in all of the header information */
1167 31e31b8a bellard
    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
1168 31e31b8a bellard
    if (elf_phdata == NULL) {
1169 31e31b8a bellard
        return -ENOMEM;
1170 31e31b8a bellard
    }
1171 31e31b8a bellard
1172 31e31b8a bellard
    retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
1173 31e31b8a bellard
    if(retval > 0) {
1174 5fafdf24 ths
        retval = read(bprm->fd, (char *) elf_phdata,
1175 31e31b8a bellard
                                elf_ex.e_phentsize * elf_ex.e_phnum);
1176 31e31b8a bellard
    }
1177 31e31b8a bellard
1178 31e31b8a bellard
    if (retval < 0) {
1179 31e31b8a bellard
        perror("load_elf_binary");
1180 31e31b8a bellard
        exit(-1);
1181 31e31b8a bellard
        free (elf_phdata);
1182 31e31b8a bellard
        return -errno;
1183 31e31b8a bellard
    }
1184 31e31b8a bellard
1185 b17780d5 bellard
#ifdef BSWAP_NEEDED
1186 b17780d5 bellard
    elf_ppnt = elf_phdata;
1187 b17780d5 bellard
    for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
1188 b17780d5 bellard
        bswap_phdr(elf_ppnt);
1189 b17780d5 bellard
    }
1190 b17780d5 bellard
#endif
1191 31e31b8a bellard
    elf_ppnt = elf_phdata;
1192 31e31b8a bellard
1193 31e31b8a bellard
    elf_bss = 0;
1194 31e31b8a bellard
    elf_brk = 0;
1195 31e31b8a bellard
1196 31e31b8a bellard
1197 992f48a0 blueswir1
    elf_stack = ~((abi_ulong)0UL);
1198 31e31b8a bellard
    elf_interpreter = NULL;
1199 992f48a0 blueswir1
    start_code = ~((abi_ulong)0UL);
1200 31e31b8a bellard
    end_code = 0;
1201 863cf0b7 j_mayer
    start_data = 0;
1202 31e31b8a bellard
    end_data = 0;
1203 98448f58 blueswir1
    interp_ex.a_info = 0;
1204 31e31b8a bellard
1205 31e31b8a bellard
    for(i=0;i < elf_ex.e_phnum; i++) {
1206 31e31b8a bellard
        if (elf_ppnt->p_type == PT_INTERP) {
1207 31e31b8a bellard
            if ( elf_interpreter != NULL )
1208 31e31b8a bellard
            {
1209 31e31b8a bellard
                free (elf_phdata);
1210 31e31b8a bellard
                free(elf_interpreter);
1211 31e31b8a bellard
                close(bprm->fd);
1212 31e31b8a bellard
                return -EINVAL;
1213 31e31b8a bellard
            }
1214 31e31b8a bellard
1215 31e31b8a bellard
            /* This is the program interpreter used for
1216 31e31b8a bellard
             * shared libraries - for now assume that this
1217 31e31b8a bellard
             * is an a.out format binary
1218 31e31b8a bellard
             */
1219 31e31b8a bellard
1220 32ce6337 bellard
            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
1221 31e31b8a bellard
1222 31e31b8a bellard
            if (elf_interpreter == NULL) {
1223 31e31b8a bellard
                free (elf_phdata);
1224 31e31b8a bellard
                close(bprm->fd);
1225 31e31b8a bellard
                return -ENOMEM;
1226 31e31b8a bellard
            }
1227 31e31b8a bellard
1228 31e31b8a bellard
            retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
1229 31e31b8a bellard
            if(retval >= 0) {
1230 32ce6337 bellard
                retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
1231 31e31b8a bellard
            }
1232 31e31b8a bellard
            if(retval < 0) {
1233 31e31b8a bellard
                 perror("load_elf_binary2");
1234 31e31b8a bellard
                exit(-1);
1235 5fafdf24 ths
            }
1236 31e31b8a bellard
1237 31e31b8a bellard
            /* If the program interpreter is one of these two,
1238 31e31b8a bellard
               then assume an iBCS2 image. Otherwise assume
1239 31e31b8a bellard
               a native linux image. */
1240 31e31b8a bellard
1241 31e31b8a bellard
            /* JRP - Need to add X86 lib dir stuff here... */
1242 31e31b8a bellard
1243 31e31b8a bellard
            if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
1244 31e31b8a bellard
                strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
1245 31e31b8a bellard
              ibcs2_interpreter = 1;
1246 31e31b8a bellard
            }
1247 31e31b8a bellard
1248 31e31b8a bellard
#if 0
1249 31e31b8a bellard
            printf("Using ELF interpreter %s\n", elf_interpreter);
1250 31e31b8a bellard
#endif
1251 31e31b8a bellard
            if (retval >= 0) {
1252 32ce6337 bellard
                retval = open(path(elf_interpreter), O_RDONLY);
1253 31e31b8a bellard
                if(retval >= 0) {
1254 31e31b8a bellard
                    interpreter_fd = retval;
1255 31e31b8a bellard
                }
1256 31e31b8a bellard
                else {
1257 31e31b8a bellard
                    perror(elf_interpreter);
1258 31e31b8a bellard
                    exit(-1);
1259 31e31b8a bellard
                    /* retval = -errno; */
1260 31e31b8a bellard
                }
1261 31e31b8a bellard
            }
1262 31e31b8a bellard
1263 31e31b8a bellard
            if (retval >= 0) {
1264 31e31b8a bellard
                retval = lseek(interpreter_fd, 0, SEEK_SET);
1265 31e31b8a bellard
                if(retval >= 0) {
1266 31e31b8a bellard
                    retval = read(interpreter_fd,bprm->buf,128);
1267 31e31b8a bellard
                }
1268 31e31b8a bellard
            }
1269 31e31b8a bellard
            if (retval >= 0) {
1270 31e31b8a bellard
                interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
1271 31e31b8a bellard
                interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
1272 31e31b8a bellard
            }
1273 31e31b8a bellard
            if (retval < 0) {
1274 31e31b8a bellard
                perror("load_elf_binary3");
1275 31e31b8a bellard
                exit(-1);
1276 31e31b8a bellard
                free (elf_phdata);
1277 31e31b8a bellard
                free(elf_interpreter);
1278 31e31b8a bellard
                close(bprm->fd);
1279 31e31b8a bellard
                return retval;
1280 31e31b8a bellard
            }
1281 31e31b8a bellard
        }
1282 31e31b8a bellard
        elf_ppnt++;
1283 31e31b8a bellard
    }
1284 31e31b8a bellard
1285 31e31b8a bellard
    /* Some simple consistency checks for the interpreter */
1286 31e31b8a bellard
    if (elf_interpreter){
1287 31e31b8a bellard
        interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
1288 31e31b8a bellard
1289 31e31b8a bellard
        /* Now figure out which format our binary is */
1290 31e31b8a bellard
        if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
1291 31e31b8a bellard
                    (N_MAGIC(interp_ex) != QMAGIC)) {
1292 31e31b8a bellard
          interpreter_type = INTERPRETER_ELF;
1293 31e31b8a bellard
        }
1294 31e31b8a bellard
1295 31e31b8a bellard
        if (interp_elf_ex.e_ident[0] != 0x7f ||
1296 b55266b5 blueswir1
            strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
1297 31e31b8a bellard
            interpreter_type &= ~INTERPRETER_ELF;
1298 31e31b8a bellard
        }
1299 31e31b8a bellard
1300 31e31b8a bellard
        if (!interpreter_type) {
1301 31e31b8a bellard
            free(elf_interpreter);
1302 31e31b8a bellard
            free(elf_phdata);
1303 31e31b8a bellard
            close(bprm->fd);
1304 31e31b8a bellard
            return -ELIBBAD;
1305 31e31b8a bellard
        }
1306 31e31b8a bellard
    }
1307 31e31b8a bellard
1308 31e31b8a bellard
    /* OK, we are done with that, now set up the arg stuff,
1309 31e31b8a bellard
       and then start this sucker up */
1310 31e31b8a bellard
1311 e5fe0c52 pbrook
    {
1312 31e31b8a bellard
        char * passed_p;
1313 31e31b8a bellard
1314 31e31b8a bellard
        if (interpreter_type == INTERPRETER_AOUT) {
1315 eba2af63 bellard
            snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
1316 31e31b8a bellard
            passed_p = passed_fileno;
1317 31e31b8a bellard
1318 31e31b8a bellard
            if (elf_interpreter) {
1319 e5fe0c52 pbrook
                bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
1320 31e31b8a bellard
                bprm->argc++;
1321 31e31b8a bellard
            }
1322 31e31b8a bellard
        }
1323 31e31b8a bellard
        if (!bprm->p) {
1324 31e31b8a bellard
            if (elf_interpreter) {
1325 31e31b8a bellard
                free(elf_interpreter);
1326 31e31b8a bellard
            }
1327 31e31b8a bellard
            free (elf_phdata);
1328 31e31b8a bellard
            close(bprm->fd);
1329 31e31b8a bellard
            return -E2BIG;
1330 31e31b8a bellard
        }
1331 31e31b8a bellard
    }
1332 31e31b8a bellard
1333 31e31b8a bellard
    /* OK, This is the point of no return */
1334 31e31b8a bellard
    info->end_data = 0;
1335 31e31b8a bellard
    info->end_code = 0;
1336 992f48a0 blueswir1
    info->start_mmap = (abi_ulong)ELF_START_MMAP;
1337 31e31b8a bellard
    info->mmap = 0;
1338 992f48a0 blueswir1
    elf_entry = (abi_ulong) elf_ex.e_entry;
1339 31e31b8a bellard
1340 31e31b8a bellard
    /* Do this so that we can load the interpreter, if need be.  We will
1341 31e31b8a bellard
       change some of these later */
1342 31e31b8a bellard
    info->rss = 0;
1343 31e31b8a bellard
    bprm->p = setup_arg_pages(bprm->p, bprm, info);
1344 31e31b8a bellard
    info->start_stack = bprm->p;
1345 31e31b8a bellard
1346 31e31b8a bellard
    /* Now we do a little grungy work by mmaping the ELF image into
1347 31e31b8a bellard
     * the correct location in memory.  At this point, we assume that
1348 31e31b8a bellard
     * the image should be loaded at fixed address, not at a variable
1349 31e31b8a bellard
     * address.
1350 31e31b8a bellard
     */
1351 31e31b8a bellard
1352 31e31b8a bellard
    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
1353 09bfb054 bellard
        int elf_prot = 0;
1354 09bfb054 bellard
        int elf_flags = 0;
1355 992f48a0 blueswir1
        abi_ulong error;
1356 3b46e624 ths
1357 09bfb054 bellard
        if (elf_ppnt->p_type != PT_LOAD)
1358 09bfb054 bellard
            continue;
1359 3b46e624 ths
1360 09bfb054 bellard
        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
1361 09bfb054 bellard
        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1362 09bfb054 bellard
        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1363 09bfb054 bellard
        elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
1364 09bfb054 bellard
        if (elf_ex.e_type == ET_EXEC || load_addr_set) {
1365 09bfb054 bellard
            elf_flags |= MAP_FIXED;
1366 09bfb054 bellard
        } else if (elf_ex.e_type == ET_DYN) {
1367 09bfb054 bellard
            /* Try and get dynamic programs out of the way of the default mmap
1368 09bfb054 bellard
               base, as well as whatever program they might try to exec.  This
1369 09bfb054 bellard
               is because the brk will follow the loader, and is not movable.  */
1370 09bfb054 bellard
            /* NOTE: for qemu, we do a big mmap to get enough space
1371 e91c8a77 ths
               without hardcoding any address */
1372 54936004 bellard
            error = target_mmap(0, ET_DYN_MAP_SIZE,
1373 5fafdf24 ths
                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
1374 54936004 bellard
                                -1, 0);
1375 09bfb054 bellard
            if (error == -1) {
1376 09bfb054 bellard
                perror("mmap");
1377 09bfb054 bellard
                exit(-1);
1378 09bfb054 bellard
            }
1379 54936004 bellard
            load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
1380 09bfb054 bellard
        }
1381 3b46e624 ths
1382 54936004 bellard
        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
1383 54936004 bellard
                            (elf_ppnt->p_filesz +
1384 54936004 bellard
                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
1385 54936004 bellard
                            elf_prot,
1386 54936004 bellard
                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
1387 54936004 bellard
                            bprm->fd,
1388 5fafdf24 ths
                            (elf_ppnt->p_offset -
1389 54936004 bellard
                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
1390 09bfb054 bellard
        if (error == -1) {
1391 09bfb054 bellard
            perror("mmap");
1392 09bfb054 bellard
            exit(-1);
1393 09bfb054 bellard
        }
1394 31e31b8a bellard
1395 31e31b8a bellard
#ifdef LOW_ELF_STACK
1396 54936004 bellard
        if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
1397 54936004 bellard
            elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
1398 31e31b8a bellard
#endif
1399 3b46e624 ths
1400 09bfb054 bellard
        if (!load_addr_set) {
1401 09bfb054 bellard
            load_addr_set = 1;
1402 09bfb054 bellard
            load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1403 09bfb054 bellard
            if (elf_ex.e_type == ET_DYN) {
1404 09bfb054 bellard
                load_bias += error -
1405 54936004 bellard
                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
1406 09bfb054 bellard
                load_addr += load_bias;
1407 84409ddb j_mayer
                reloc_func_desc = load_bias;
1408 09bfb054 bellard
            }
1409 09bfb054 bellard
        }
1410 09bfb054 bellard
        k = elf_ppnt->p_vaddr;
1411 5fafdf24 ths
        if (k < start_code)
1412 09bfb054 bellard
            start_code = k;
1413 863cf0b7 j_mayer
        if (start_data < k)
1414 863cf0b7 j_mayer
            start_data = k;
1415 09bfb054 bellard
        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
1416 5fafdf24 ths
        if (k > elf_bss)
1417 09bfb054 bellard
            elf_bss = k;
1418 09bfb054 bellard
        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
1419 09bfb054 bellard
            end_code = k;
1420 5fafdf24 ths
        if (end_data < k)
1421 09bfb054 bellard
            end_data = k;
1422 09bfb054 bellard
        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
1423 09bfb054 bellard
        if (k > elf_brk) elf_brk = k;
1424 31e31b8a bellard
    }
1425 31e31b8a bellard
1426 09bfb054 bellard
    elf_entry += load_bias;
1427 09bfb054 bellard
    elf_bss += load_bias;
1428 09bfb054 bellard
    elf_brk += load_bias;
1429 09bfb054 bellard
    start_code += load_bias;
1430 09bfb054 bellard
    end_code += load_bias;
1431 863cf0b7 j_mayer
    start_data += load_bias;
1432 09bfb054 bellard
    end_data += load_bias;
1433 09bfb054 bellard
1434 31e31b8a bellard
    if (elf_interpreter) {
1435 31e31b8a bellard
        if (interpreter_type & 1) {
1436 31e31b8a bellard
            elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
1437 31e31b8a bellard
        }
1438 31e31b8a bellard
        else if (interpreter_type & 2) {
1439 31e31b8a bellard
            elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
1440 31e31b8a bellard
                                            &interp_load_addr);
1441 31e31b8a bellard
        }
1442 84409ddb j_mayer
        reloc_func_desc = interp_load_addr;
1443 31e31b8a bellard
1444 31e31b8a bellard
        close(interpreter_fd);
1445 31e31b8a bellard
        free(elf_interpreter);
1446 31e31b8a bellard
1447 992f48a0 blueswir1
        if (elf_entry == ~((abi_ulong)0UL)) {
1448 31e31b8a bellard
            printf("Unable to load interpreter\n");
1449 31e31b8a bellard
            free(elf_phdata);
1450 31e31b8a bellard
            exit(-1);
1451 31e31b8a bellard
            return 0;
1452 31e31b8a bellard
        }
1453 31e31b8a bellard
    }
1454 31e31b8a bellard
1455 31e31b8a bellard
    free(elf_phdata);
1456 31e31b8a bellard
1457 93fcfe39 aliguori
    if (qemu_log_enabled())
1458 689f936f bellard
        load_symbols(&elf_ex, bprm->fd);
1459 689f936f bellard
1460 31e31b8a bellard
    if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
1461 31e31b8a bellard
    info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
1462 31e31b8a bellard
1463 31e31b8a bellard
#ifdef LOW_ELF_STACK
1464 31e31b8a bellard
    info->start_stack = bprm->p = elf_stack - 4;
1465 31e31b8a bellard
#endif
1466 53a5960a pbrook
    bprm->p = create_elf_tables(bprm->p,
1467 31e31b8a bellard
                    bprm->argc,
1468 31e31b8a bellard
                    bprm->envc,
1469 a1516e92 bellard
                    &elf_ex,
1470 09bfb054 bellard
                    load_addr, load_bias,
1471 31e31b8a bellard
                    interp_load_addr,
1472 31e31b8a bellard
                    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
1473 31e31b8a bellard
                    info);
1474 92a343da j_mayer
    info->load_addr = reloc_func_desc;
1475 31e31b8a bellard
    info->start_brk = info->brk = elf_brk;
1476 31e31b8a bellard
    info->end_code = end_code;
1477 31e31b8a bellard
    info->start_code = start_code;
1478 863cf0b7 j_mayer
    info->start_data = start_data;
1479 31e31b8a bellard
    info->end_data = end_data;
1480 31e31b8a bellard
    info->start_stack = bprm->p;
1481 31e31b8a bellard
1482 31e31b8a bellard
    /* Calling set_brk effectively mmaps the pages that we need for the bss and break
1483 31e31b8a bellard
       sections */
1484 31e31b8a bellard
    set_brk(elf_bss, elf_brk);
1485 31e31b8a bellard
1486 768a4a36 ths
    padzero(elf_bss, elf_brk);
1487 31e31b8a bellard
1488 31e31b8a bellard
#if 0
1489 31e31b8a bellard
    printf("(start_brk) %x\n" , info->start_brk);
1490 31e31b8a bellard
    printf("(end_code) %x\n" , info->end_code);
1491 31e31b8a bellard
    printf("(start_code) %x\n" , info->start_code);
1492 31e31b8a bellard
    printf("(end_data) %x\n" , info->end_data);
1493 31e31b8a bellard
    printf("(start_stack) %x\n" , info->start_stack);
1494 31e31b8a bellard
    printf("(brk) %x\n" , info->brk);
1495 31e31b8a bellard
#endif
1496 31e31b8a bellard
1497 31e31b8a bellard
    if ( info->personality == PER_SVR4 )
1498 31e31b8a bellard
    {
1499 31e31b8a bellard
            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
1500 31e31b8a bellard
               and some applications "depend" upon this behavior.
1501 31e31b8a bellard
               Since we do not have the power to recompile these, we
1502 31e31b8a bellard
               emulate the SVr4 behavior.  Sigh.  */
1503 83fb7adf bellard
            mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
1504 54936004 bellard
                                      MAP_FIXED | MAP_PRIVATE, -1, 0);
1505 31e31b8a bellard
    }
1506 31e31b8a bellard
1507 31e31b8a bellard
    info->entry = elf_entry;
1508 31e31b8a bellard
1509 31e31b8a bellard
    return 0;
1510 31e31b8a bellard
}
1511 31e31b8a bellard
1512 31e31b8a bellard
static int load_aout_interp(void * exptr, int interp_fd)
1513 31e31b8a bellard
{
1514 31e31b8a bellard
    printf("a.out interpreter not yet supported\n");
1515 31e31b8a bellard
    return(0);
1516 31e31b8a bellard
}
1517 31e31b8a bellard
1518 e5fe0c52 pbrook
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
1519 e5fe0c52 pbrook
{
1520 e5fe0c52 pbrook
    init_thread(regs, infop);
1521 e5fe0c52 pbrook
}