Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ e85e7c6e

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