Statistics
| Branch: | Revision:

root / bsd-user / elfload.c @ 82b11662

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