Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ a32ff1ad

History | View | Annotate | Download (40.4 kB)

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

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