Statistics
| Branch: | Revision:

root / bsd-user / elfload.c @ 2ae144c9

History | View | Annotate | Download (46.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 78cfb07f Juergen Lock
    if (bsd_type == target_freebsd) {
130 78cfb07f Juergen Lock
        regs->rdi = infop->start_stack;
131 78cfb07f Juergen Lock
    }
132 84778508 blueswir1
}
133 84778508 blueswir1
134 84778508 blueswir1
#else
135 84778508 blueswir1
136 84778508 blueswir1
#define ELF_START_MMAP 0x80000000
137 84778508 blueswir1
138 84778508 blueswir1
/*
139 84778508 blueswir1
 * This is used to ensure we don't load something for the wrong architecture.
140 84778508 blueswir1
 */
141 84778508 blueswir1
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
142 84778508 blueswir1
143 84778508 blueswir1
/*
144 84778508 blueswir1
 * These are used to set parameters in the core dumps.
145 84778508 blueswir1
 */
146 84778508 blueswir1
#define ELF_CLASS       ELFCLASS32
147 84778508 blueswir1
#define ELF_DATA        ELFDATA2LSB
148 84778508 blueswir1
#define ELF_ARCH        EM_386
149 84778508 blueswir1
150 84778508 blueswir1
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
151 84778508 blueswir1
{
152 84778508 blueswir1
    regs->esp = infop->start_stack;
153 84778508 blueswir1
    regs->eip = infop->entry;
154 84778508 blueswir1
155 84778508 blueswir1
    /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
156 84778508 blueswir1
       starts %edx contains a pointer to a function which might be
157 84778508 blueswir1
       registered using `atexit'.  This provides a mean for the
158 84778508 blueswir1
       dynamic linker to call DT_FINI functions for shared libraries
159 84778508 blueswir1
       that have been loaded before the code runs.
160 84778508 blueswir1

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