Statistics
| Branch: | Revision:

root / bsd-user / elfload.c @ 3f4cb3d3

History | View | Annotate | Download (45.7 kB)

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

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