Statistics
| Branch: | Revision:

root / linux-user / elfload.c @ 26ca8c06

History | View | Annotate | Download (87 kB)

1 31e31b8a bellard
/* This is the Linux kernel elf-loading code, ported into user space */
2 edf8e2af Mika Westerberg
#include <sys/time.h>
3 edf8e2af Mika Westerberg
#include <sys/param.h>
4 31e31b8a bellard
5 31e31b8a bellard
#include <stdio.h>
6 31e31b8a bellard
#include <sys/types.h>
7 31e31b8a bellard
#include <fcntl.h>
8 31e31b8a bellard
#include <errno.h>
9 31e31b8a bellard
#include <unistd.h>
10 31e31b8a bellard
#include <sys/mman.h>
11 edf8e2af Mika Westerberg
#include <sys/resource.h>
12 31e31b8a bellard
#include <stdlib.h>
13 31e31b8a bellard
#include <string.h>
14 edf8e2af Mika Westerberg
#include <time.h>
15 31e31b8a bellard
16 3ef693a0 bellard
#include "qemu.h"
17 76cad711 Paolo Bonzini
#include "disas/disas.h"
18 31e31b8a bellard
19 e58ffeb3 malc
#ifdef _ARCH_PPC64
20 a6cc84f4 malc
#undef ARCH_DLINFO
21 a6cc84f4 malc
#undef ELF_PLATFORM
22 a6cc84f4 malc
#undef ELF_HWCAP
23 a6cc84f4 malc
#undef ELF_CLASS
24 a6cc84f4 malc
#undef ELF_DATA
25 a6cc84f4 malc
#undef ELF_ARCH
26 a6cc84f4 malc
#endif
27 a6cc84f4 malc
28 edf8e2af Mika Westerberg
#define ELF_OSABI   ELFOSABI_SYSV
29 edf8e2af Mika Westerberg
30 cb33da57 blueswir1
/* from personality.h */
31 cb33da57 blueswir1
32 cb33da57 blueswir1
/*
33 cb33da57 blueswir1
 * Flags for bug emulation.
34 cb33da57 blueswir1
 *
35 cb33da57 blueswir1
 * These occupy the top three bytes.
36 cb33da57 blueswir1
 */
37 cb33da57 blueswir1
enum {
38 d97ef72e Richard Henderson
    ADDR_NO_RANDOMIZE = 0x0040000,      /* disable randomization of VA space */
39 d97ef72e Richard Henderson
    FDPIC_FUNCPTRS =    0x0080000,      /* userspace function ptrs point to
40 d97ef72e Richard Henderson
                                           descriptors (signal handling) */
41 d97ef72e Richard Henderson
    MMAP_PAGE_ZERO =    0x0100000,
42 d97ef72e Richard Henderson
    ADDR_COMPAT_LAYOUT = 0x0200000,
43 d97ef72e Richard Henderson
    READ_IMPLIES_EXEC = 0x0400000,
44 d97ef72e Richard Henderson
    ADDR_LIMIT_32BIT =  0x0800000,
45 d97ef72e Richard Henderson
    SHORT_INODE =       0x1000000,
46 d97ef72e Richard Henderson
    WHOLE_SECONDS =     0x2000000,
47 d97ef72e Richard Henderson
    STICKY_TIMEOUTS =   0x4000000,
48 d97ef72e Richard Henderson
    ADDR_LIMIT_3GB =    0x8000000,
49 cb33da57 blueswir1
};
50 cb33da57 blueswir1
51 cb33da57 blueswir1
/*
52 cb33da57 blueswir1
 * Personality types.
53 cb33da57 blueswir1
 *
54 cb33da57 blueswir1
 * These go in the low byte.  Avoid using the top bit, it will
55 cb33da57 blueswir1
 * conflict with error returns.
56 cb33da57 blueswir1
 */
57 cb33da57 blueswir1
enum {
58 d97ef72e Richard Henderson
    PER_LINUX =         0x0000,
59 d97ef72e Richard Henderson
    PER_LINUX_32BIT =   0x0000 | ADDR_LIMIT_32BIT,
60 d97ef72e Richard Henderson
    PER_LINUX_FDPIC =   0x0000 | FDPIC_FUNCPTRS,
61 d97ef72e Richard Henderson
    PER_SVR4 =          0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
62 d97ef72e Richard Henderson
    PER_SVR3 =          0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
63 d97ef72e Richard Henderson
    PER_SCOSVR3 =       0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
64 d97ef72e Richard Henderson
    PER_OSR5 =          0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
65 d97ef72e Richard Henderson
    PER_WYSEV386 =      0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
66 d97ef72e Richard Henderson
    PER_ISCR4 =         0x0005 | STICKY_TIMEOUTS,
67 d97ef72e Richard Henderson
    PER_BSD =           0x0006,
68 d97ef72e Richard Henderson
    PER_SUNOS =         0x0006 | STICKY_TIMEOUTS,
69 d97ef72e Richard Henderson
    PER_XENIX =         0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
70 d97ef72e Richard Henderson
    PER_LINUX32 =       0x0008,
71 d97ef72e Richard Henderson
    PER_LINUX32_3GB =   0x0008 | ADDR_LIMIT_3GB,
72 d97ef72e Richard Henderson
    PER_IRIX32 =        0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
73 d97ef72e Richard Henderson
    PER_IRIXN32 =       0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
74 d97ef72e Richard Henderson
    PER_IRIX64 =        0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
75 d97ef72e Richard Henderson
    PER_RISCOS =        0x000c,
76 d97ef72e Richard Henderson
    PER_SOLARIS =       0x000d | STICKY_TIMEOUTS,
77 d97ef72e Richard Henderson
    PER_UW7 =           0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
78 d97ef72e Richard Henderson
    PER_OSF4 =          0x000f,                  /* OSF/1 v4 */
79 d97ef72e Richard Henderson
    PER_HPUX =          0x0010,
80 d97ef72e Richard Henderson
    PER_MASK =          0x00ff,
81 cb33da57 blueswir1
};
82 cb33da57 blueswir1
83 cb33da57 blueswir1
/*
84 cb33da57 blueswir1
 * Return the base personality without flags.
85 cb33da57 blueswir1
 */
86 d97ef72e Richard Henderson
#define personality(pers)       (pers & PER_MASK)
87 cb33da57 blueswir1
88 83fb7adf bellard
/* this flag is uneffective under linux too, should be deleted */
89 83fb7adf bellard
#ifndef MAP_DENYWRITE
90 83fb7adf bellard
#define MAP_DENYWRITE 0
91 83fb7adf bellard
#endif
92 83fb7adf bellard
93 83fb7adf bellard
/* should probably go in elf.h */
94 83fb7adf bellard
#ifndef ELIBBAD
95 83fb7adf bellard
#define ELIBBAD 80
96 83fb7adf bellard
#endif
97 83fb7adf bellard
98 28490231 Richard Henderson
#ifdef TARGET_WORDS_BIGENDIAN
99 28490231 Richard Henderson
#define ELF_DATA        ELFDATA2MSB
100 28490231 Richard Henderson
#else
101 28490231 Richard Henderson
#define ELF_DATA        ELFDATA2LSB
102 28490231 Richard Henderson
#endif
103 28490231 Richard Henderson
104 d97ef72e Richard Henderson
typedef target_ulong    target_elf_greg_t;
105 21e807fa Nathan Froyd
#ifdef USE_UID16
106 80f5ce75 Laurent Vivier
typedef target_ushort   target_uid_t;
107 80f5ce75 Laurent Vivier
typedef target_ushort   target_gid_t;
108 21e807fa Nathan Froyd
#else
109 80f5ce75 Laurent Vivier
typedef target_uint     target_uid_t;
110 80f5ce75 Laurent Vivier
typedef target_uint     target_gid_t;
111 21e807fa Nathan Froyd
#endif
112 80f5ce75 Laurent Vivier
typedef target_int      target_pid_t;
113 21e807fa Nathan Froyd
114 30ac07d4 bellard
#ifdef TARGET_I386
115 30ac07d4 bellard
116 15338fd7 bellard
#define ELF_PLATFORM get_elf_platform()
117 15338fd7 bellard
118 15338fd7 bellard
static const char *get_elf_platform(void)
119 15338fd7 bellard
{
120 15338fd7 bellard
    static char elf_platform[] = "i386";
121 d5975363 pbrook
    int family = (thread_env->cpuid_version >> 8) & 0xff;
122 15338fd7 bellard
    if (family > 6)
123 15338fd7 bellard
        family = 6;
124 15338fd7 bellard
    if (family >= 3)
125 15338fd7 bellard
        elf_platform[1] = '0' + family;
126 15338fd7 bellard
    return elf_platform;
127 15338fd7 bellard
}
128 15338fd7 bellard
129 15338fd7 bellard
#define ELF_HWCAP get_elf_hwcap()
130 15338fd7 bellard
131 15338fd7 bellard
static uint32_t get_elf_hwcap(void)
132 15338fd7 bellard
{
133 d97ef72e Richard Henderson
    return thread_env->cpuid_features;
134 15338fd7 bellard
}
135 15338fd7 bellard
136 84409ddb j_mayer
#ifdef TARGET_X86_64
137 84409ddb j_mayer
#define ELF_START_MMAP 0x2aaaaab000ULL
138 84409ddb j_mayer
#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
139 84409ddb j_mayer
140 84409ddb j_mayer
#define ELF_CLASS      ELFCLASS64
141 84409ddb j_mayer
#define ELF_ARCH       EM_X86_64
142 84409ddb j_mayer
143 84409ddb j_mayer
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
144 84409ddb j_mayer
{
145 84409ddb j_mayer
    regs->rax = 0;
146 84409ddb j_mayer
    regs->rsp = infop->start_stack;
147 84409ddb j_mayer
    regs->rip = infop->entry;
148 84409ddb j_mayer
}
149 84409ddb j_mayer
150 9edc5d79 Mika Westerberg
#define ELF_NREG    27
151 c227f099 Anthony Liguori
typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
152 9edc5d79 Mika Westerberg
153 9edc5d79 Mika Westerberg
/*
154 9edc5d79 Mika Westerberg
 * Note that ELF_NREG should be 29 as there should be place for
155 9edc5d79 Mika Westerberg
 * TRAPNO and ERR "registers" as well but linux doesn't dump
156 9edc5d79 Mika Westerberg
 * those.
157 9edc5d79 Mika Westerberg
 *
158 9edc5d79 Mika Westerberg
 * See linux kernel: arch/x86/include/asm/elf.h
159 9edc5d79 Mika Westerberg
 */
160 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
161 9edc5d79 Mika Westerberg
{
162 9edc5d79 Mika Westerberg
    (*regs)[0] = env->regs[15];
163 9edc5d79 Mika Westerberg
    (*regs)[1] = env->regs[14];
164 9edc5d79 Mika Westerberg
    (*regs)[2] = env->regs[13];
165 9edc5d79 Mika Westerberg
    (*regs)[3] = env->regs[12];
166 9edc5d79 Mika Westerberg
    (*regs)[4] = env->regs[R_EBP];
167 9edc5d79 Mika Westerberg
    (*regs)[5] = env->regs[R_EBX];
168 9edc5d79 Mika Westerberg
    (*regs)[6] = env->regs[11];
169 9edc5d79 Mika Westerberg
    (*regs)[7] = env->regs[10];
170 9edc5d79 Mika Westerberg
    (*regs)[8] = env->regs[9];
171 9edc5d79 Mika Westerberg
    (*regs)[9] = env->regs[8];
172 9edc5d79 Mika Westerberg
    (*regs)[10] = env->regs[R_EAX];
173 9edc5d79 Mika Westerberg
    (*regs)[11] = env->regs[R_ECX];
174 9edc5d79 Mika Westerberg
    (*regs)[12] = env->regs[R_EDX];
175 9edc5d79 Mika Westerberg
    (*regs)[13] = env->regs[R_ESI];
176 9edc5d79 Mika Westerberg
    (*regs)[14] = env->regs[R_EDI];
177 9edc5d79 Mika Westerberg
    (*regs)[15] = env->regs[R_EAX]; /* XXX */
178 9edc5d79 Mika Westerberg
    (*regs)[16] = env->eip;
179 9edc5d79 Mika Westerberg
    (*regs)[17] = env->segs[R_CS].selector & 0xffff;
180 9edc5d79 Mika Westerberg
    (*regs)[18] = env->eflags;
181 9edc5d79 Mika Westerberg
    (*regs)[19] = env->regs[R_ESP];
182 9edc5d79 Mika Westerberg
    (*regs)[20] = env->segs[R_SS].selector & 0xffff;
183 9edc5d79 Mika Westerberg
    (*regs)[21] = env->segs[R_FS].selector & 0xffff;
184 9edc5d79 Mika Westerberg
    (*regs)[22] = env->segs[R_GS].selector & 0xffff;
185 9edc5d79 Mika Westerberg
    (*regs)[23] = env->segs[R_DS].selector & 0xffff;
186 9edc5d79 Mika Westerberg
    (*regs)[24] = env->segs[R_ES].selector & 0xffff;
187 9edc5d79 Mika Westerberg
    (*regs)[25] = env->segs[R_FS].selector & 0xffff;
188 9edc5d79 Mika Westerberg
    (*regs)[26] = env->segs[R_GS].selector & 0xffff;
189 9edc5d79 Mika Westerberg
}
190 9edc5d79 Mika Westerberg
191 84409ddb j_mayer
#else
192 84409ddb j_mayer
193 30ac07d4 bellard
#define ELF_START_MMAP 0x80000000
194 30ac07d4 bellard
195 30ac07d4 bellard
/*
196 30ac07d4 bellard
 * This is used to ensure we don't load something for the wrong architecture.
197 30ac07d4 bellard
 */
198 30ac07d4 bellard
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
199 30ac07d4 bellard
200 30ac07d4 bellard
/*
201 30ac07d4 bellard
 * These are used to set parameters in the core dumps.
202 30ac07d4 bellard
 */
203 d97ef72e Richard Henderson
#define ELF_CLASS       ELFCLASS32
204 d97ef72e Richard Henderson
#define ELF_ARCH        EM_386
205 30ac07d4 bellard
206 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
207 d97ef72e Richard Henderson
                               struct image_info *infop)
208 b346ff46 bellard
{
209 b346ff46 bellard
    regs->esp = infop->start_stack;
210 b346ff46 bellard
    regs->eip = infop->entry;
211 e5fe0c52 pbrook
212 e5fe0c52 pbrook
    /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
213 e5fe0c52 pbrook
       starts %edx contains a pointer to a function which might be
214 e5fe0c52 pbrook
       registered using `atexit'.  This provides a mean for the
215 e5fe0c52 pbrook
       dynamic linker to call DT_FINI functions for shared libraries
216 e5fe0c52 pbrook
       that have been loaded before the code runs.
217 e5fe0c52 pbrook

218 e5fe0c52 pbrook
       A value of 0 tells we have no such handler.  */
219 e5fe0c52 pbrook
    regs->edx = 0;
220 b346ff46 bellard
}
221 9edc5d79 Mika Westerberg
222 9edc5d79 Mika Westerberg
#define ELF_NREG    17
223 c227f099 Anthony Liguori
typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
224 9edc5d79 Mika Westerberg
225 9edc5d79 Mika Westerberg
/*
226 9edc5d79 Mika Westerberg
 * Note that ELF_NREG should be 19 as there should be place for
227 9edc5d79 Mika Westerberg
 * TRAPNO and ERR "registers" as well but linux doesn't dump
228 9edc5d79 Mika Westerberg
 * those.
229 9edc5d79 Mika Westerberg
 *
230 9edc5d79 Mika Westerberg
 * See linux kernel: arch/x86/include/asm/elf.h
231 9edc5d79 Mika Westerberg
 */
232 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
233 9edc5d79 Mika Westerberg
{
234 9edc5d79 Mika Westerberg
    (*regs)[0] = env->regs[R_EBX];
235 9edc5d79 Mika Westerberg
    (*regs)[1] = env->regs[R_ECX];
236 9edc5d79 Mika Westerberg
    (*regs)[2] = env->regs[R_EDX];
237 9edc5d79 Mika Westerberg
    (*regs)[3] = env->regs[R_ESI];
238 9edc5d79 Mika Westerberg
    (*regs)[4] = env->regs[R_EDI];
239 9edc5d79 Mika Westerberg
    (*regs)[5] = env->regs[R_EBP];
240 9edc5d79 Mika Westerberg
    (*regs)[6] = env->regs[R_EAX];
241 9edc5d79 Mika Westerberg
    (*regs)[7] = env->segs[R_DS].selector & 0xffff;
242 9edc5d79 Mika Westerberg
    (*regs)[8] = env->segs[R_ES].selector & 0xffff;
243 9edc5d79 Mika Westerberg
    (*regs)[9] = env->segs[R_FS].selector & 0xffff;
244 9edc5d79 Mika Westerberg
    (*regs)[10] = env->segs[R_GS].selector & 0xffff;
245 9edc5d79 Mika Westerberg
    (*regs)[11] = env->regs[R_EAX]; /* XXX */
246 9edc5d79 Mika Westerberg
    (*regs)[12] = env->eip;
247 9edc5d79 Mika Westerberg
    (*regs)[13] = env->segs[R_CS].selector & 0xffff;
248 9edc5d79 Mika Westerberg
    (*regs)[14] = env->eflags;
249 9edc5d79 Mika Westerberg
    (*regs)[15] = env->regs[R_ESP];
250 9edc5d79 Mika Westerberg
    (*regs)[16] = env->segs[R_SS].selector & 0xffff;
251 9edc5d79 Mika Westerberg
}
252 84409ddb j_mayer
#endif
253 b346ff46 bellard
254 9edc5d79 Mika Westerberg
#define USE_ELF_CORE_DUMP
255 d97ef72e Richard Henderson
#define ELF_EXEC_PAGESIZE       4096
256 b346ff46 bellard
257 b346ff46 bellard
#endif
258 b346ff46 bellard
259 b346ff46 bellard
#ifdef TARGET_ARM
260 b346ff46 bellard
261 b346ff46 bellard
#define ELF_START_MMAP 0x80000000
262 b346ff46 bellard
263 b346ff46 bellard
#define elf_check_arch(x) ( (x) == EM_ARM )
264 b346ff46 bellard
265 d97ef72e Richard Henderson
#define ELF_CLASS       ELFCLASS32
266 d97ef72e Richard Henderson
#define ELF_ARCH        EM_ARM
267 b346ff46 bellard
268 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
269 d97ef72e Richard Henderson
                               struct image_info *infop)
270 b346ff46 bellard
{
271 992f48a0 blueswir1
    abi_long stack = infop->start_stack;
272 b346ff46 bellard
    memset(regs, 0, sizeof(*regs));
273 b346ff46 bellard
    regs->ARM_cpsr = 0x10;
274 0240ded8 pbrook
    if (infop->entry & 1)
275 d97ef72e Richard Henderson
        regs->ARM_cpsr |= CPSR_T;
276 0240ded8 pbrook
    regs->ARM_pc = infop->entry & 0xfffffffe;
277 b346ff46 bellard
    regs->ARM_sp = infop->start_stack;
278 2f619698 bellard
    /* FIXME - what to for failure of get_user()? */
279 2f619698 bellard
    get_user_ual(regs->ARM_r2, stack + 8); /* envp */
280 2f619698 bellard
    get_user_ual(regs->ARM_r1, stack + 4); /* envp */
281 a1516e92 bellard
    /* XXX: it seems that r0 is zeroed after ! */
282 e5fe0c52 pbrook
    regs->ARM_r0 = 0;
283 e5fe0c52 pbrook
    /* For uClinux PIC binaries.  */
284 863cf0b7 j_mayer
    /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
285 e5fe0c52 pbrook
    regs->ARM_r10 = infop->start_data;
286 b346ff46 bellard
}
287 b346ff46 bellard
288 edf8e2af Mika Westerberg
#define ELF_NREG    18
289 c227f099 Anthony Liguori
typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
290 edf8e2af Mika Westerberg
291 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env)
292 edf8e2af Mika Westerberg
{
293 d049e626 Nathan Froyd
    (*regs)[0] = tswapl(env->regs[0]);
294 d049e626 Nathan Froyd
    (*regs)[1] = tswapl(env->regs[1]);
295 d049e626 Nathan Froyd
    (*regs)[2] = tswapl(env->regs[2]);
296 d049e626 Nathan Froyd
    (*regs)[3] = tswapl(env->regs[3]);
297 d049e626 Nathan Froyd
    (*regs)[4] = tswapl(env->regs[4]);
298 d049e626 Nathan Froyd
    (*regs)[5] = tswapl(env->regs[5]);
299 d049e626 Nathan Froyd
    (*regs)[6] = tswapl(env->regs[6]);
300 d049e626 Nathan Froyd
    (*regs)[7] = tswapl(env->regs[7]);
301 d049e626 Nathan Froyd
    (*regs)[8] = tswapl(env->regs[8]);
302 d049e626 Nathan Froyd
    (*regs)[9] = tswapl(env->regs[9]);
303 d049e626 Nathan Froyd
    (*regs)[10] = tswapl(env->regs[10]);
304 d049e626 Nathan Froyd
    (*regs)[11] = tswapl(env->regs[11]);
305 d049e626 Nathan Froyd
    (*regs)[12] = tswapl(env->regs[12]);
306 d049e626 Nathan Froyd
    (*regs)[13] = tswapl(env->regs[13]);
307 d049e626 Nathan Froyd
    (*regs)[14] = tswapl(env->regs[14]);
308 d049e626 Nathan Froyd
    (*regs)[15] = tswapl(env->regs[15]);
309 d049e626 Nathan Froyd
310 05390248 Andreas Fรคrber
    (*regs)[16] = tswapl(cpsr_read((CPUARMState *)env));
311 d049e626 Nathan Froyd
    (*regs)[17] = tswapl(env->regs[0]); /* XXX */
312 edf8e2af Mika Westerberg
}
313 edf8e2af Mika Westerberg
314 30ac07d4 bellard
#define USE_ELF_CORE_DUMP
315 d97ef72e Richard Henderson
#define ELF_EXEC_PAGESIZE       4096
316 30ac07d4 bellard
317 afce2927 bellard
enum
318 afce2927 bellard
{
319 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_SWP       = 1 << 0,
320 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_HALF      = 1 << 1,
321 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_THUMB     = 1 << 2,
322 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_26BIT     = 1 << 3,
323 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
324 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_FPA       = 1 << 5,
325 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_VFP       = 1 << 6,
326 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_EDSP      = 1 << 7,
327 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_JAVA      = 1 << 8,
328 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
329 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
330 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_NEON      = 1 << 11,
331 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_VFPv3     = 1 << 12,
332 d97ef72e Richard Henderson
    ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
333 afce2927 bellard
};
334 afce2927 bellard
335 806d1021 Meador Inge
#define TARGET_HAS_VALIDATE_GUEST_SPACE
336 806d1021 Meador Inge
/* Return 1 if the proposed guest space is suitable for the guest.
337 806d1021 Meador Inge
 * Return 0 if the proposed guest space isn't suitable, but another
338 806d1021 Meador Inge
 * address space should be tried.
339 806d1021 Meador Inge
 * Return -1 if there is no way the proposed guest space can be
340 806d1021 Meador Inge
 * valid regardless of the base.
341 806d1021 Meador Inge
 * The guest code may leave a page mapped and populate it if the
342 806d1021 Meador Inge
 * address is suitable.
343 806d1021 Meador Inge
 */
344 806d1021 Meador Inge
static int validate_guest_space(unsigned long guest_base,
345 806d1021 Meador Inge
                                unsigned long guest_size)
346 97cc7560 Dr. David Alan Gilbert
{
347 97cc7560 Dr. David Alan Gilbert
    unsigned long real_start, test_page_addr;
348 97cc7560 Dr. David Alan Gilbert
349 97cc7560 Dr. David Alan Gilbert
    /* We need to check that we can force a fault on access to the
350 97cc7560 Dr. David Alan Gilbert
     * commpage at 0xffff0fxx
351 97cc7560 Dr. David Alan Gilbert
     */
352 97cc7560 Dr. David Alan Gilbert
    test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask);
353 806d1021 Meador Inge
354 806d1021 Meador Inge
    /* If the commpage lies within the already allocated guest space,
355 806d1021 Meador Inge
     * then there is no way we can allocate it.
356 806d1021 Meador Inge
     */
357 806d1021 Meador Inge
    if (test_page_addr >= guest_base
358 806d1021 Meador Inge
        && test_page_addr <= (guest_base + guest_size)) {
359 806d1021 Meador Inge
        return -1;
360 806d1021 Meador Inge
    }
361 806d1021 Meador Inge
362 97cc7560 Dr. David Alan Gilbert
    /* Note it needs to be writeable to let us initialise it */
363 97cc7560 Dr. David Alan Gilbert
    real_start = (unsigned long)
364 97cc7560 Dr. David Alan Gilbert
                 mmap((void *)test_page_addr, qemu_host_page_size,
365 97cc7560 Dr. David Alan Gilbert
                     PROT_READ | PROT_WRITE,
366 97cc7560 Dr. David Alan Gilbert
                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
367 97cc7560 Dr. David Alan Gilbert
368 97cc7560 Dr. David Alan Gilbert
    /* If we can't map it then try another address */
369 97cc7560 Dr. David Alan Gilbert
    if (real_start == -1ul) {
370 97cc7560 Dr. David Alan Gilbert
        return 0;
371 97cc7560 Dr. David Alan Gilbert
    }
372 97cc7560 Dr. David Alan Gilbert
373 97cc7560 Dr. David Alan Gilbert
    if (real_start != test_page_addr) {
374 97cc7560 Dr. David Alan Gilbert
        /* OS didn't put the page where we asked - unmap and reject */
375 97cc7560 Dr. David Alan Gilbert
        munmap((void *)real_start, qemu_host_page_size);
376 97cc7560 Dr. David Alan Gilbert
        return 0;
377 97cc7560 Dr. David Alan Gilbert
    }
378 97cc7560 Dr. David Alan Gilbert
379 97cc7560 Dr. David Alan Gilbert
    /* Leave the page mapped
380 97cc7560 Dr. David Alan Gilbert
     * Populate it (mmap should have left it all 0'd)
381 97cc7560 Dr. David Alan Gilbert
     */
382 97cc7560 Dr. David Alan Gilbert
383 97cc7560 Dr. David Alan Gilbert
    /* Kernel helper versions */
384 97cc7560 Dr. David Alan Gilbert
    __put_user(5, (uint32_t *)g2h(0xffff0ffcul));
385 97cc7560 Dr. David Alan Gilbert
386 97cc7560 Dr. David Alan Gilbert
    /* Now it's populated make it RO */
387 97cc7560 Dr. David Alan Gilbert
    if (mprotect((void *)test_page_addr, qemu_host_page_size, PROT_READ)) {
388 97cc7560 Dr. David Alan Gilbert
        perror("Protecting guest commpage");
389 97cc7560 Dr. David Alan Gilbert
        exit(-1);
390 97cc7560 Dr. David Alan Gilbert
    }
391 97cc7560 Dr. David Alan Gilbert
392 97cc7560 Dr. David Alan Gilbert
    return 1; /* All good */
393 97cc7560 Dr. David Alan Gilbert
}
394 97cc7560 Dr. David Alan Gilbert
395 adf050b1 Benoit Canet
396 adf050b1 Benoit Canet
#define ELF_HWCAP get_elf_hwcap()
397 adf050b1 Benoit Canet
398 adf050b1 Benoit Canet
static uint32_t get_elf_hwcap(void)
399 adf050b1 Benoit Canet
{
400 adf050b1 Benoit Canet
    CPUARMState *e = thread_env;
401 adf050b1 Benoit Canet
    uint32_t hwcaps = 0;
402 adf050b1 Benoit Canet
403 adf050b1 Benoit Canet
    hwcaps |= ARM_HWCAP_ARM_SWP;
404 adf050b1 Benoit Canet
    hwcaps |= ARM_HWCAP_ARM_HALF;
405 adf050b1 Benoit Canet
    hwcaps |= ARM_HWCAP_ARM_THUMB;
406 adf050b1 Benoit Canet
    hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
407 adf050b1 Benoit Canet
    hwcaps |= ARM_HWCAP_ARM_FPA;
408 adf050b1 Benoit Canet
409 adf050b1 Benoit Canet
    /* probe for the extra features */
410 adf050b1 Benoit Canet
#define GET_FEATURE(feat, hwcap) \
411 adf050b1 Benoit Canet
    do {if (arm_feature(e, feat)) { hwcaps |= hwcap; } } while (0)
412 adf050b1 Benoit Canet
    GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP);
413 adf050b1 Benoit Canet
    GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
414 adf050b1 Benoit Canet
    GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
415 adf050b1 Benoit Canet
    GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
416 adf050b1 Benoit Canet
    GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3);
417 adf050b1 Benoit Canet
    GET_FEATURE(ARM_FEATURE_VFP_FP16, ARM_HWCAP_ARM_VFPv3D16);
418 adf050b1 Benoit Canet
#undef GET_FEATURE
419 adf050b1 Benoit Canet
420 adf050b1 Benoit Canet
    return hwcaps;
421 adf050b1 Benoit Canet
}
422 afce2927 bellard
423 30ac07d4 bellard
#endif
424 30ac07d4 bellard
425 d2fbca94 Guan Xuetao
#ifdef TARGET_UNICORE32
426 d2fbca94 Guan Xuetao
427 d2fbca94 Guan Xuetao
#define ELF_START_MMAP          0x80000000
428 d2fbca94 Guan Xuetao
429 d2fbca94 Guan Xuetao
#define elf_check_arch(x)       ((x) == EM_UNICORE32)
430 d2fbca94 Guan Xuetao
431 d2fbca94 Guan Xuetao
#define ELF_CLASS               ELFCLASS32
432 d2fbca94 Guan Xuetao
#define ELF_DATA                ELFDATA2LSB
433 d2fbca94 Guan Xuetao
#define ELF_ARCH                EM_UNICORE32
434 d2fbca94 Guan Xuetao
435 d2fbca94 Guan Xuetao
static inline void init_thread(struct target_pt_regs *regs,
436 d2fbca94 Guan Xuetao
        struct image_info *infop)
437 d2fbca94 Guan Xuetao
{
438 d2fbca94 Guan Xuetao
    abi_long stack = infop->start_stack;
439 d2fbca94 Guan Xuetao
    memset(regs, 0, sizeof(*regs));
440 d2fbca94 Guan Xuetao
    regs->UC32_REG_asr = 0x10;
441 d2fbca94 Guan Xuetao
    regs->UC32_REG_pc = infop->entry & 0xfffffffe;
442 d2fbca94 Guan Xuetao
    regs->UC32_REG_sp = infop->start_stack;
443 d2fbca94 Guan Xuetao
    /* FIXME - what to for failure of get_user()? */
444 d2fbca94 Guan Xuetao
    get_user_ual(regs->UC32_REG_02, stack + 8); /* envp */
445 d2fbca94 Guan Xuetao
    get_user_ual(regs->UC32_REG_01, stack + 4); /* envp */
446 d2fbca94 Guan Xuetao
    /* XXX: it seems that r0 is zeroed after ! */
447 d2fbca94 Guan Xuetao
    regs->UC32_REG_00 = 0;
448 d2fbca94 Guan Xuetao
}
449 d2fbca94 Guan Xuetao
450 d2fbca94 Guan Xuetao
#define ELF_NREG    34
451 d2fbca94 Guan Xuetao
typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
452 d2fbca94 Guan Xuetao
453 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUUniCore32State *env)
454 d2fbca94 Guan Xuetao
{
455 d2fbca94 Guan Xuetao
    (*regs)[0] = env->regs[0];
456 d2fbca94 Guan Xuetao
    (*regs)[1] = env->regs[1];
457 d2fbca94 Guan Xuetao
    (*regs)[2] = env->regs[2];
458 d2fbca94 Guan Xuetao
    (*regs)[3] = env->regs[3];
459 d2fbca94 Guan Xuetao
    (*regs)[4] = env->regs[4];
460 d2fbca94 Guan Xuetao
    (*regs)[5] = env->regs[5];
461 d2fbca94 Guan Xuetao
    (*regs)[6] = env->regs[6];
462 d2fbca94 Guan Xuetao
    (*regs)[7] = env->regs[7];
463 d2fbca94 Guan Xuetao
    (*regs)[8] = env->regs[8];
464 d2fbca94 Guan Xuetao
    (*regs)[9] = env->regs[9];
465 d2fbca94 Guan Xuetao
    (*regs)[10] = env->regs[10];
466 d2fbca94 Guan Xuetao
    (*regs)[11] = env->regs[11];
467 d2fbca94 Guan Xuetao
    (*regs)[12] = env->regs[12];
468 d2fbca94 Guan Xuetao
    (*regs)[13] = env->regs[13];
469 d2fbca94 Guan Xuetao
    (*regs)[14] = env->regs[14];
470 d2fbca94 Guan Xuetao
    (*regs)[15] = env->regs[15];
471 d2fbca94 Guan Xuetao
    (*regs)[16] = env->regs[16];
472 d2fbca94 Guan Xuetao
    (*regs)[17] = env->regs[17];
473 d2fbca94 Guan Xuetao
    (*regs)[18] = env->regs[18];
474 d2fbca94 Guan Xuetao
    (*regs)[19] = env->regs[19];
475 d2fbca94 Guan Xuetao
    (*regs)[20] = env->regs[20];
476 d2fbca94 Guan Xuetao
    (*regs)[21] = env->regs[21];
477 d2fbca94 Guan Xuetao
    (*regs)[22] = env->regs[22];
478 d2fbca94 Guan Xuetao
    (*regs)[23] = env->regs[23];
479 d2fbca94 Guan Xuetao
    (*regs)[24] = env->regs[24];
480 d2fbca94 Guan Xuetao
    (*regs)[25] = env->regs[25];
481 d2fbca94 Guan Xuetao
    (*regs)[26] = env->regs[26];
482 d2fbca94 Guan Xuetao
    (*regs)[27] = env->regs[27];
483 d2fbca94 Guan Xuetao
    (*regs)[28] = env->regs[28];
484 d2fbca94 Guan Xuetao
    (*regs)[29] = env->regs[29];
485 d2fbca94 Guan Xuetao
    (*regs)[30] = env->regs[30];
486 d2fbca94 Guan Xuetao
    (*regs)[31] = env->regs[31];
487 d2fbca94 Guan Xuetao
488 05390248 Andreas Fรคrber
    (*regs)[32] = cpu_asr_read((CPUUniCore32State *)env);
489 d2fbca94 Guan Xuetao
    (*regs)[33] = env->regs[0]; /* XXX */
490 d2fbca94 Guan Xuetao
}
491 d2fbca94 Guan Xuetao
492 d2fbca94 Guan Xuetao
#define USE_ELF_CORE_DUMP
493 d2fbca94 Guan Xuetao
#define ELF_EXEC_PAGESIZE               4096
494 d2fbca94 Guan Xuetao
495 d2fbca94 Guan Xuetao
#define ELF_HWCAP                       (UC32_HWCAP_CMOV | UC32_HWCAP_UCF64)
496 d2fbca94 Guan Xuetao
497 d2fbca94 Guan Xuetao
#endif
498 d2fbca94 Guan Xuetao
499 853d6f7a bellard
#ifdef TARGET_SPARC
500 a315a145 bellard
#ifdef TARGET_SPARC64
501 853d6f7a bellard
502 853d6f7a bellard
#define ELF_START_MMAP 0x80000000
503 cf973e46 Artyom Tarasenko
#define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
504 cf973e46 Artyom Tarasenko
                    | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9)
505 992f48a0 blueswir1
#ifndef TARGET_ABI32
506 cb33da57 blueswir1
#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
507 992f48a0 blueswir1
#else
508 992f48a0 blueswir1
#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
509 992f48a0 blueswir1
#endif
510 853d6f7a bellard
511 a315a145 bellard
#define ELF_CLASS   ELFCLASS64
512 5ef54116 bellard
#define ELF_ARCH    EM_SPARCV9
513 5ef54116 bellard
514 d97ef72e Richard Henderson
#define STACK_BIAS              2047
515 a315a145 bellard
516 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
517 d97ef72e Richard Henderson
                               struct image_info *infop)
518 a315a145 bellard
{
519 992f48a0 blueswir1
#ifndef TARGET_ABI32
520 a315a145 bellard
    regs->tstate = 0;
521 992f48a0 blueswir1
#endif
522 a315a145 bellard
    regs->pc = infop->entry;
523 a315a145 bellard
    regs->npc = regs->pc + 4;
524 a315a145 bellard
    regs->y = 0;
525 992f48a0 blueswir1
#ifdef TARGET_ABI32
526 992f48a0 blueswir1
    regs->u_regs[14] = infop->start_stack - 16 * 4;
527 992f48a0 blueswir1
#else
528 cb33da57 blueswir1
    if (personality(infop->personality) == PER_LINUX32)
529 cb33da57 blueswir1
        regs->u_regs[14] = infop->start_stack - 16 * 4;
530 cb33da57 blueswir1
    else
531 cb33da57 blueswir1
        regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
532 992f48a0 blueswir1
#endif
533 a315a145 bellard
}
534 a315a145 bellard
535 a315a145 bellard
#else
536 a315a145 bellard
#define ELF_START_MMAP 0x80000000
537 cf973e46 Artyom Tarasenko
#define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
538 cf973e46 Artyom Tarasenko
                    | HWCAP_SPARC_MULDIV)
539 a315a145 bellard
#define elf_check_arch(x) ( (x) == EM_SPARC )
540 a315a145 bellard
541 853d6f7a bellard
#define ELF_CLASS   ELFCLASS32
542 853d6f7a bellard
#define ELF_ARCH    EM_SPARC
543 853d6f7a bellard
544 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
545 d97ef72e Richard Henderson
                               struct image_info *infop)
546 853d6f7a bellard
{
547 f5155289 bellard
    regs->psr = 0;
548 f5155289 bellard
    regs->pc = infop->entry;
549 f5155289 bellard
    regs->npc = regs->pc + 4;
550 f5155289 bellard
    regs->y = 0;
551 f5155289 bellard
    regs->u_regs[14] = infop->start_stack - 16 * 4;
552 853d6f7a bellard
}
553 853d6f7a bellard
554 853d6f7a bellard
#endif
555 a315a145 bellard
#endif
556 853d6f7a bellard
557 67867308 bellard
#ifdef TARGET_PPC
558 67867308 bellard
559 67867308 bellard
#define ELF_START_MMAP 0x80000000
560 67867308 bellard
561 e85e7c6e j_mayer
#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
562 84409ddb j_mayer
563 84409ddb j_mayer
#define elf_check_arch(x) ( (x) == EM_PPC64 )
564 84409ddb j_mayer
565 d97ef72e Richard Henderson
#define ELF_CLASS       ELFCLASS64
566 84409ddb j_mayer
567 84409ddb j_mayer
#else
568 84409ddb j_mayer
569 67867308 bellard
#define elf_check_arch(x) ( (x) == EM_PPC )
570 67867308 bellard
571 d97ef72e Richard Henderson
#define ELF_CLASS       ELFCLASS32
572 84409ddb j_mayer
573 84409ddb j_mayer
#endif
574 84409ddb j_mayer
575 d97ef72e Richard Henderson
#define ELF_ARCH        EM_PPC
576 67867308 bellard
577 df84e4f3 Nathan Froyd
/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
578 df84e4f3 Nathan Froyd
   See arch/powerpc/include/asm/cputable.h.  */
579 df84e4f3 Nathan Froyd
enum {
580 3efa9a67 malc
    QEMU_PPC_FEATURE_32 = 0x80000000,
581 3efa9a67 malc
    QEMU_PPC_FEATURE_64 = 0x40000000,
582 3efa9a67 malc
    QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
583 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
584 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
585 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
586 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
587 3efa9a67 malc
    QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
588 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
589 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
590 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
591 3efa9a67 malc
    QEMU_PPC_FEATURE_NO_TB = 0x00100000,
592 3efa9a67 malc
    QEMU_PPC_FEATURE_POWER4 = 0x00080000,
593 3efa9a67 malc
    QEMU_PPC_FEATURE_POWER5 = 0x00040000,
594 3efa9a67 malc
    QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
595 3efa9a67 malc
    QEMU_PPC_FEATURE_CELL = 0x00010000,
596 3efa9a67 malc
    QEMU_PPC_FEATURE_BOOKE = 0x00008000,
597 3efa9a67 malc
    QEMU_PPC_FEATURE_SMT = 0x00004000,
598 3efa9a67 malc
    QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
599 3efa9a67 malc
    QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
600 3efa9a67 malc
    QEMU_PPC_FEATURE_PA6T = 0x00000800,
601 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
602 3efa9a67 malc
    QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
603 3efa9a67 malc
    QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
604 3efa9a67 malc
    QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
605 3efa9a67 malc
    QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
606 3efa9a67 malc
607 3efa9a67 malc
    QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
608 3efa9a67 malc
    QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
609 df84e4f3 Nathan Froyd
};
610 df84e4f3 Nathan Froyd
611 df84e4f3 Nathan Froyd
#define ELF_HWCAP get_elf_hwcap()
612 df84e4f3 Nathan Froyd
613 df84e4f3 Nathan Froyd
static uint32_t get_elf_hwcap(void)
614 df84e4f3 Nathan Froyd
{
615 05390248 Andreas Fรคrber
    CPUPPCState *e = thread_env;
616 df84e4f3 Nathan Froyd
    uint32_t features = 0;
617 df84e4f3 Nathan Froyd
618 df84e4f3 Nathan Froyd
    /* We don't have to be terribly complete here; the high points are
619 df84e4f3 Nathan Froyd
       Altivec/FP/SPE support.  Anything else is just a bonus.  */
620 d97ef72e Richard Henderson
#define GET_FEATURE(flag, feature)                                      \
621 df84e4f3 Nathan Froyd
    do {if (e->insns_flags & flag) features |= feature; } while(0)
622 3efa9a67 malc
    GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
623 3efa9a67 malc
    GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
624 3efa9a67 malc
    GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
625 3efa9a67 malc
    GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
626 3efa9a67 malc
    GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
627 3efa9a67 malc
    GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
628 3efa9a67 malc
    GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
629 3efa9a67 malc
    GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
630 df84e4f3 Nathan Froyd
#undef GET_FEATURE
631 df84e4f3 Nathan Froyd
632 df84e4f3 Nathan Froyd
    return features;
633 df84e4f3 Nathan Froyd
}
634 df84e4f3 Nathan Froyd
635 f5155289 bellard
/*
636 f5155289 bellard
 * The requirements here are:
637 f5155289 bellard
 * - keep the final alignment of sp (sp & 0xf)
638 f5155289 bellard
 * - make sure the 32-bit value at the first 16 byte aligned position of
639 f5155289 bellard
 *   AUXV is greater than 16 for glibc compatibility.
640 f5155289 bellard
 *   AT_IGNOREPPC is used for that.
641 f5155289 bellard
 * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
642 f5155289 bellard
 *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
643 f5155289 bellard
 */
644 0bccf03d bellard
#define DLINFO_ARCH_ITEMS       5
645 d97ef72e Richard Henderson
#define ARCH_DLINFO                                     \
646 d97ef72e Richard Henderson
    do {                                                \
647 d97ef72e Richard Henderson
        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);              \
648 d97ef72e Richard Henderson
        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);              \
649 d97ef72e Richard Henderson
        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
650 d97ef72e Richard Henderson
        /*                                              \
651 d97ef72e Richard Henderson
         * Now handle glibc compatibility.              \
652 d97ef72e Richard Henderson
         */                                             \
653 d97ef72e Richard Henderson
        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
654 d97ef72e Richard Henderson
        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
655 d97ef72e Richard Henderson
    } while (0)
656 f5155289 bellard
657 67867308 bellard
static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
658 67867308 bellard
{
659 67867308 bellard
    _regs->gpr[1] = infop->start_stack;
660 e85e7c6e j_mayer
#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
661 8e78064e Richard Henderson
    _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias;
662 8e78064e Richard Henderson
    infop->entry = ldq_raw(infop->entry) + infop->load_bias;
663 84409ddb j_mayer
#endif
664 67867308 bellard
    _regs->nip = infop->entry;
665 67867308 bellard
}
666 67867308 bellard
667 e2f3e741 Nathan Froyd
/* See linux kernel: arch/powerpc/include/asm/elf.h.  */
668 e2f3e741 Nathan Froyd
#define ELF_NREG 48
669 e2f3e741 Nathan Froyd
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
670 e2f3e741 Nathan Froyd
671 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env)
672 e2f3e741 Nathan Froyd
{
673 e2f3e741 Nathan Froyd
    int i;
674 e2f3e741 Nathan Froyd
    target_ulong ccr = 0;
675 e2f3e741 Nathan Froyd
676 e2f3e741 Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
677 e2f3e741 Nathan Froyd
        (*regs)[i] = tswapl(env->gpr[i]);
678 e2f3e741 Nathan Froyd
    }
679 e2f3e741 Nathan Froyd
680 e2f3e741 Nathan Froyd
    (*regs)[32] = tswapl(env->nip);
681 e2f3e741 Nathan Froyd
    (*regs)[33] = tswapl(env->msr);
682 e2f3e741 Nathan Froyd
    (*regs)[35] = tswapl(env->ctr);
683 e2f3e741 Nathan Froyd
    (*regs)[36] = tswapl(env->lr);
684 e2f3e741 Nathan Froyd
    (*regs)[37] = tswapl(env->xer);
685 e2f3e741 Nathan Froyd
686 e2f3e741 Nathan Froyd
    for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
687 e2f3e741 Nathan Froyd
        ccr |= env->crf[i] << (32 - ((i + 1) * 4));
688 e2f3e741 Nathan Froyd
    }
689 e2f3e741 Nathan Froyd
    (*regs)[38] = tswapl(ccr);
690 e2f3e741 Nathan Froyd
}
691 e2f3e741 Nathan Froyd
692 e2f3e741 Nathan Froyd
#define USE_ELF_CORE_DUMP
693 d97ef72e Richard Henderson
#define ELF_EXEC_PAGESIZE       4096
694 67867308 bellard
695 67867308 bellard
#endif
696 67867308 bellard
697 048f6b4d bellard
#ifdef TARGET_MIPS
698 048f6b4d bellard
699 048f6b4d bellard
#define ELF_START_MMAP 0x80000000
700 048f6b4d bellard
701 048f6b4d bellard
#define elf_check_arch(x) ( (x) == EM_MIPS )
702 048f6b4d bellard
703 388bb21a ths
#ifdef TARGET_MIPS64
704 388bb21a ths
#define ELF_CLASS   ELFCLASS64
705 388bb21a ths
#else
706 048f6b4d bellard
#define ELF_CLASS   ELFCLASS32
707 388bb21a ths
#endif
708 048f6b4d bellard
#define ELF_ARCH    EM_MIPS
709 048f6b4d bellard
710 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
711 d97ef72e Richard Henderson
                               struct image_info *infop)
712 048f6b4d bellard
{
713 623a930e ths
    regs->cp0_status = 2 << CP0St_KSU;
714 048f6b4d bellard
    regs->cp0_epc = infop->entry;
715 048f6b4d bellard
    regs->regs[29] = infop->start_stack;
716 048f6b4d bellard
}
717 048f6b4d bellard
718 51e52606 Nathan Froyd
/* See linux kernel: arch/mips/include/asm/elf.h.  */
719 51e52606 Nathan Froyd
#define ELF_NREG 45
720 51e52606 Nathan Froyd
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
721 51e52606 Nathan Froyd
722 51e52606 Nathan Froyd
/* See linux kernel: arch/mips/include/asm/reg.h.  */
723 51e52606 Nathan Froyd
enum {
724 51e52606 Nathan Froyd
#ifdef TARGET_MIPS64
725 51e52606 Nathan Froyd
    TARGET_EF_R0 = 0,
726 51e52606 Nathan Froyd
#else
727 51e52606 Nathan Froyd
    TARGET_EF_R0 = 6,
728 51e52606 Nathan Froyd
#endif
729 51e52606 Nathan Froyd
    TARGET_EF_R26 = TARGET_EF_R0 + 26,
730 51e52606 Nathan Froyd
    TARGET_EF_R27 = TARGET_EF_R0 + 27,
731 51e52606 Nathan Froyd
    TARGET_EF_LO = TARGET_EF_R0 + 32,
732 51e52606 Nathan Froyd
    TARGET_EF_HI = TARGET_EF_R0 + 33,
733 51e52606 Nathan Froyd
    TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
734 51e52606 Nathan Froyd
    TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
735 51e52606 Nathan Froyd
    TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
736 51e52606 Nathan Froyd
    TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
737 51e52606 Nathan Froyd
};
738 51e52606 Nathan Froyd
739 51e52606 Nathan Froyd
/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
740 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env)
741 51e52606 Nathan Froyd
{
742 51e52606 Nathan Froyd
    int i;
743 51e52606 Nathan Froyd
744 51e52606 Nathan Froyd
    for (i = 0; i < TARGET_EF_R0; i++) {
745 51e52606 Nathan Froyd
        (*regs)[i] = 0;
746 51e52606 Nathan Froyd
    }
747 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_R0] = 0;
748 51e52606 Nathan Froyd
749 51e52606 Nathan Froyd
    for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
750 51e52606 Nathan Froyd
        (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]);
751 51e52606 Nathan Froyd
    }
752 51e52606 Nathan Froyd
753 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_R26] = 0;
754 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_R27] = 0;
755 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]);
756 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]);
757 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC);
758 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr);
759 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status);
760 51e52606 Nathan Froyd
    (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause);
761 51e52606 Nathan Froyd
}
762 51e52606 Nathan Froyd
763 51e52606 Nathan Froyd
#define USE_ELF_CORE_DUMP
764 388bb21a ths
#define ELF_EXEC_PAGESIZE        4096
765 388bb21a ths
766 048f6b4d bellard
#endif /* TARGET_MIPS */
767 048f6b4d bellard
768 b779e29e Edgar E. Iglesias
#ifdef TARGET_MICROBLAZE
769 b779e29e Edgar E. Iglesias
770 b779e29e Edgar E. Iglesias
#define ELF_START_MMAP 0x80000000
771 b779e29e Edgar E. Iglesias
772 0d5d4699 Edgar E. Iglesias
#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
773 b779e29e Edgar E. Iglesias
774 b779e29e Edgar E. Iglesias
#define ELF_CLASS   ELFCLASS32
775 0d5d4699 Edgar E. Iglesias
#define ELF_ARCH    EM_MICROBLAZE
776 b779e29e Edgar E. Iglesias
777 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
778 d97ef72e Richard Henderson
                               struct image_info *infop)
779 b779e29e Edgar E. Iglesias
{
780 b779e29e Edgar E. Iglesias
    regs->pc = infop->entry;
781 b779e29e Edgar E. Iglesias
    regs->r1 = infop->start_stack;
782 b779e29e Edgar E. Iglesias
783 b779e29e Edgar E. Iglesias
}
784 b779e29e Edgar E. Iglesias
785 b779e29e Edgar E. Iglesias
#define ELF_EXEC_PAGESIZE        4096
786 b779e29e Edgar E. Iglesias
787 e4cbd44d Edgar E. Iglesias
#define USE_ELF_CORE_DUMP
788 e4cbd44d Edgar E. Iglesias
#define ELF_NREG 38
789 e4cbd44d Edgar E. Iglesias
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
790 e4cbd44d Edgar E. Iglesias
791 e4cbd44d Edgar E. Iglesias
/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
792 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env)
793 e4cbd44d Edgar E. Iglesias
{
794 e4cbd44d Edgar E. Iglesias
    int i, pos = 0;
795 e4cbd44d Edgar E. Iglesias
796 e4cbd44d Edgar E. Iglesias
    for (i = 0; i < 32; i++) {
797 e4cbd44d Edgar E. Iglesias
        (*regs)[pos++] = tswapl(env->regs[i]);
798 e4cbd44d Edgar E. Iglesias
    }
799 e4cbd44d Edgar E. Iglesias
800 e4cbd44d Edgar E. Iglesias
    for (i = 0; i < 6; i++) {
801 e4cbd44d Edgar E. Iglesias
        (*regs)[pos++] = tswapl(env->sregs[i]);
802 e4cbd44d Edgar E. Iglesias
    }
803 e4cbd44d Edgar E. Iglesias
}
804 e4cbd44d Edgar E. Iglesias
805 b779e29e Edgar E. Iglesias
#endif /* TARGET_MICROBLAZE */
806 b779e29e Edgar E. Iglesias
807 d962783e Jia Liu
#ifdef TARGET_OPENRISC
808 d962783e Jia Liu
809 d962783e Jia Liu
#define ELF_START_MMAP 0x08000000
810 d962783e Jia Liu
811 d962783e Jia Liu
#define elf_check_arch(x) ((x) == EM_OPENRISC)
812 d962783e Jia Liu
813 d962783e Jia Liu
#define ELF_ARCH EM_OPENRISC
814 d962783e Jia Liu
#define ELF_CLASS ELFCLASS32
815 d962783e Jia Liu
#define ELF_DATA  ELFDATA2MSB
816 d962783e Jia Liu
817 d962783e Jia Liu
static inline void init_thread(struct target_pt_regs *regs,
818 d962783e Jia Liu
                               struct image_info *infop)
819 d962783e Jia Liu
{
820 d962783e Jia Liu
    regs->pc = infop->entry;
821 d962783e Jia Liu
    regs->gpr[1] = infop->start_stack;
822 d962783e Jia Liu
}
823 d962783e Jia Liu
824 d962783e Jia Liu
#define USE_ELF_CORE_DUMP
825 d962783e Jia Liu
#define ELF_EXEC_PAGESIZE 8192
826 d962783e Jia Liu
827 d962783e Jia Liu
/* See linux kernel arch/openrisc/include/asm/elf.h.  */
828 d962783e Jia Liu
#define ELF_NREG 34 /* gprs and pc, sr */
829 d962783e Jia Liu
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
830 d962783e Jia Liu
831 d962783e Jia Liu
static void elf_core_copy_regs(target_elf_gregset_t *regs,
832 d962783e Jia Liu
                               const CPUOpenRISCState *env)
833 d962783e Jia Liu
{
834 d962783e Jia Liu
    int i;
835 d962783e Jia Liu
836 d962783e Jia Liu
    for (i = 0; i < 32; i++) {
837 d962783e Jia Liu
        (*regs)[i] = tswapl(env->gpr[i]);
838 d962783e Jia Liu
    }
839 d962783e Jia Liu
840 d962783e Jia Liu
    (*regs)[32] = tswapl(env->pc);
841 d962783e Jia Liu
    (*regs)[33] = tswapl(env->sr);
842 d962783e Jia Liu
}
843 d962783e Jia Liu
#define ELF_HWCAP 0
844 d962783e Jia Liu
#define ELF_PLATFORM NULL
845 d962783e Jia Liu
846 d962783e Jia Liu
#endif /* TARGET_OPENRISC */
847 d962783e Jia Liu
848 fdf9b3e8 bellard
#ifdef TARGET_SH4
849 fdf9b3e8 bellard
850 fdf9b3e8 bellard
#define ELF_START_MMAP 0x80000000
851 fdf9b3e8 bellard
852 fdf9b3e8 bellard
#define elf_check_arch(x) ( (x) == EM_SH )
853 fdf9b3e8 bellard
854 fdf9b3e8 bellard
#define ELF_CLASS ELFCLASS32
855 fdf9b3e8 bellard
#define ELF_ARCH  EM_SH
856 fdf9b3e8 bellard
857 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
858 d97ef72e Richard Henderson
                               struct image_info *infop)
859 fdf9b3e8 bellard
{
860 d97ef72e Richard Henderson
    /* Check other registers XXXXX */
861 d97ef72e Richard Henderson
    regs->pc = infop->entry;
862 d97ef72e Richard Henderson
    regs->regs[15] = infop->start_stack;
863 fdf9b3e8 bellard
}
864 fdf9b3e8 bellard
865 7631c97e Nathan Froyd
/* See linux kernel: arch/sh/include/asm/elf.h.  */
866 7631c97e Nathan Froyd
#define ELF_NREG 23
867 7631c97e Nathan Froyd
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
868 7631c97e Nathan Froyd
869 7631c97e Nathan Froyd
/* See linux kernel: arch/sh/include/asm/ptrace.h.  */
870 7631c97e Nathan Froyd
enum {
871 7631c97e Nathan Froyd
    TARGET_REG_PC = 16,
872 7631c97e Nathan Froyd
    TARGET_REG_PR = 17,
873 7631c97e Nathan Froyd
    TARGET_REG_SR = 18,
874 7631c97e Nathan Froyd
    TARGET_REG_GBR = 19,
875 7631c97e Nathan Froyd
    TARGET_REG_MACH = 20,
876 7631c97e Nathan Froyd
    TARGET_REG_MACL = 21,
877 7631c97e Nathan Froyd
    TARGET_REG_SYSCALL = 22
878 7631c97e Nathan Froyd
};
879 7631c97e Nathan Froyd
880 d97ef72e Richard Henderson
static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
881 05390248 Andreas Fรคrber
                                      const CPUSH4State *env)
882 7631c97e Nathan Froyd
{
883 7631c97e Nathan Froyd
    int i;
884 7631c97e Nathan Froyd
885 7631c97e Nathan Froyd
    for (i = 0; i < 16; i++) {
886 7631c97e Nathan Froyd
        (*regs[i]) = tswapl(env->gregs[i]);
887 7631c97e Nathan Froyd
    }
888 7631c97e Nathan Froyd
889 7631c97e Nathan Froyd
    (*regs)[TARGET_REG_PC] = tswapl(env->pc);
890 7631c97e Nathan Froyd
    (*regs)[TARGET_REG_PR] = tswapl(env->pr);
891 7631c97e Nathan Froyd
    (*regs)[TARGET_REG_SR] = tswapl(env->sr);
892 7631c97e Nathan Froyd
    (*regs)[TARGET_REG_GBR] = tswapl(env->gbr);
893 7631c97e Nathan Froyd
    (*regs)[TARGET_REG_MACH] = tswapl(env->mach);
894 7631c97e Nathan Froyd
    (*regs)[TARGET_REG_MACL] = tswapl(env->macl);
895 7631c97e Nathan Froyd
    (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
896 7631c97e Nathan Froyd
}
897 7631c97e Nathan Froyd
898 7631c97e Nathan Froyd
#define USE_ELF_CORE_DUMP
899 fdf9b3e8 bellard
#define ELF_EXEC_PAGESIZE        4096
900 fdf9b3e8 bellard
901 fdf9b3e8 bellard
#endif
902 fdf9b3e8 bellard
903 48733d19 ths
#ifdef TARGET_CRIS
904 48733d19 ths
905 48733d19 ths
#define ELF_START_MMAP 0x80000000
906 48733d19 ths
907 48733d19 ths
#define elf_check_arch(x) ( (x) == EM_CRIS )
908 48733d19 ths
909 48733d19 ths
#define ELF_CLASS ELFCLASS32
910 48733d19 ths
#define ELF_ARCH  EM_CRIS
911 48733d19 ths
912 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
913 d97ef72e Richard Henderson
                               struct image_info *infop)
914 48733d19 ths
{
915 d97ef72e Richard Henderson
    regs->erp = infop->entry;
916 48733d19 ths
}
917 48733d19 ths
918 48733d19 ths
#define ELF_EXEC_PAGESIZE        8192
919 48733d19 ths
920 48733d19 ths
#endif
921 48733d19 ths
922 e6e5906b pbrook
#ifdef TARGET_M68K
923 e6e5906b pbrook
924 e6e5906b pbrook
#define ELF_START_MMAP 0x80000000
925 e6e5906b pbrook
926 e6e5906b pbrook
#define elf_check_arch(x) ( (x) == EM_68K )
927 e6e5906b pbrook
928 d97ef72e Richard Henderson
#define ELF_CLASS       ELFCLASS32
929 d97ef72e Richard Henderson
#define ELF_ARCH        EM_68K
930 e6e5906b pbrook
931 e6e5906b pbrook
/* ??? Does this need to do anything?
932 d97ef72e Richard Henderson
   #define ELF_PLAT_INIT(_r) */
933 e6e5906b pbrook
934 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
935 d97ef72e Richard Henderson
                               struct image_info *infop)
936 e6e5906b pbrook
{
937 e6e5906b pbrook
    regs->usp = infop->start_stack;
938 e6e5906b pbrook
    regs->sr = 0;
939 e6e5906b pbrook
    regs->pc = infop->entry;
940 e6e5906b pbrook
}
941 e6e5906b pbrook
942 7a93cc55 Nathan Froyd
/* See linux kernel: arch/m68k/include/asm/elf.h.  */
943 7a93cc55 Nathan Froyd
#define ELF_NREG 20
944 7a93cc55 Nathan Froyd
typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
945 7a93cc55 Nathan Froyd
946 05390248 Andreas Fรคrber
static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env)
947 7a93cc55 Nathan Froyd
{
948 7a93cc55 Nathan Froyd
    (*regs)[0] = tswapl(env->dregs[1]);
949 7a93cc55 Nathan Froyd
    (*regs)[1] = tswapl(env->dregs[2]);
950 7a93cc55 Nathan Froyd
    (*regs)[2] = tswapl(env->dregs[3]);
951 7a93cc55 Nathan Froyd
    (*regs)[3] = tswapl(env->dregs[4]);
952 7a93cc55 Nathan Froyd
    (*regs)[4] = tswapl(env->dregs[5]);
953 7a93cc55 Nathan Froyd
    (*regs)[5] = tswapl(env->dregs[6]);
954 7a93cc55 Nathan Froyd
    (*regs)[6] = tswapl(env->dregs[7]);
955 7a93cc55 Nathan Froyd
    (*regs)[7] = tswapl(env->aregs[0]);
956 7a93cc55 Nathan Froyd
    (*regs)[8] = tswapl(env->aregs[1]);
957 7a93cc55 Nathan Froyd
    (*regs)[9] = tswapl(env->aregs[2]);
958 7a93cc55 Nathan Froyd
    (*regs)[10] = tswapl(env->aregs[3]);
959 7a93cc55 Nathan Froyd
    (*regs)[11] = tswapl(env->aregs[4]);
960 7a93cc55 Nathan Froyd
    (*regs)[12] = tswapl(env->aregs[5]);
961 7a93cc55 Nathan Froyd
    (*regs)[13] = tswapl(env->aregs[6]);
962 7a93cc55 Nathan Froyd
    (*regs)[14] = tswapl(env->dregs[0]);
963 7a93cc55 Nathan Froyd
    (*regs)[15] = tswapl(env->aregs[7]);
964 7a93cc55 Nathan Froyd
    (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */
965 7a93cc55 Nathan Froyd
    (*regs)[17] = tswapl(env->sr);
966 7a93cc55 Nathan Froyd
    (*regs)[18] = tswapl(env->pc);
967 7a93cc55 Nathan Froyd
    (*regs)[19] = 0;  /* FIXME: regs->format | regs->vector */
968 7a93cc55 Nathan Froyd
}
969 7a93cc55 Nathan Froyd
970 7a93cc55 Nathan Froyd
#define USE_ELF_CORE_DUMP
971 d97ef72e Richard Henderson
#define ELF_EXEC_PAGESIZE       8192
972 e6e5906b pbrook
973 e6e5906b pbrook
#endif
974 e6e5906b pbrook
975 7a3148a9 j_mayer
#ifdef TARGET_ALPHA
976 7a3148a9 j_mayer
977 7a3148a9 j_mayer
#define ELF_START_MMAP (0x30000000000ULL)
978 7a3148a9 j_mayer
979 7a3148a9 j_mayer
#define elf_check_arch(x) ( (x) == ELF_ARCH )
980 7a3148a9 j_mayer
981 7a3148a9 j_mayer
#define ELF_CLASS      ELFCLASS64
982 7a3148a9 j_mayer
#define ELF_ARCH       EM_ALPHA
983 7a3148a9 j_mayer
984 d97ef72e Richard Henderson
static inline void init_thread(struct target_pt_regs *regs,
985 d97ef72e Richard Henderson
                               struct image_info *infop)
986 7a3148a9 j_mayer
{
987 7a3148a9 j_mayer
    regs->pc = infop->entry;
988 7a3148a9 j_mayer
    regs->ps = 8;
989 7a3148a9 j_mayer
    regs->usp = infop->start_stack;
990 7a3148a9 j_mayer
}
991 7a3148a9 j_mayer
992 7a3148a9 j_mayer
#define ELF_EXEC_PAGESIZE        8192
993 7a3148a9 j_mayer
994 7a3148a9 j_mayer
#endif /* TARGET_ALPHA */
995 7a3148a9 j_mayer
996 a4c075f1 Ulrich Hecht
#ifdef TARGET_S390X
997 a4c075f1 Ulrich Hecht
998 a4c075f1 Ulrich Hecht
#define ELF_START_MMAP (0x20000000000ULL)
999 a4c075f1 Ulrich Hecht
1000 a4c075f1 Ulrich Hecht
#define elf_check_arch(x) ( (x) == ELF_ARCH )
1001 a4c075f1 Ulrich Hecht
1002 a4c075f1 Ulrich Hecht
#define ELF_CLASS        ELFCLASS64
1003 a4c075f1 Ulrich Hecht
#define ELF_DATA        ELFDATA2MSB
1004 a4c075f1 Ulrich Hecht
#define ELF_ARCH        EM_S390
1005 a4c075f1 Ulrich Hecht
1006 a4c075f1 Ulrich Hecht
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
1007 a4c075f1 Ulrich Hecht
{
1008 a4c075f1 Ulrich Hecht
    regs->psw.addr = infop->entry;
1009 a4c075f1 Ulrich Hecht
    regs->psw.mask = PSW_MASK_64 | PSW_MASK_32;
1010 a4c075f1 Ulrich Hecht
    regs->gprs[15] = infop->start_stack;
1011 a4c075f1 Ulrich Hecht
}
1012 a4c075f1 Ulrich Hecht
1013 a4c075f1 Ulrich Hecht
#endif /* TARGET_S390X */
1014 a4c075f1 Ulrich Hecht
1015 15338fd7 bellard
#ifndef ELF_PLATFORM
1016 15338fd7 bellard
#define ELF_PLATFORM (NULL)
1017 15338fd7 bellard
#endif
1018 15338fd7 bellard
1019 15338fd7 bellard
#ifndef ELF_HWCAP
1020 15338fd7 bellard
#define ELF_HWCAP 0
1021 15338fd7 bellard
#endif
1022 15338fd7 bellard
1023 992f48a0 blueswir1
#ifdef TARGET_ABI32
1024 cb33da57 blueswir1
#undef ELF_CLASS
1025 992f48a0 blueswir1
#define ELF_CLASS ELFCLASS32
1026 cb33da57 blueswir1
#undef bswaptls
1027 cb33da57 blueswir1
#define bswaptls(ptr) bswap32s(ptr)
1028 cb33da57 blueswir1
#endif
1029 cb33da57 blueswir1
1030 31e31b8a bellard
#include "elf.h"
1031 09bfb054 bellard
1032 09bfb054 bellard
struct exec
1033 09bfb054 bellard
{
1034 d97ef72e Richard Henderson
    unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
1035 d97ef72e Richard Henderson
    unsigned int a_text;   /* length of text, in bytes */
1036 d97ef72e Richard Henderson
    unsigned int a_data;   /* length of data, in bytes */
1037 d97ef72e Richard Henderson
    unsigned int a_bss;    /* length of uninitialized data area, in bytes */
1038 d97ef72e Richard Henderson
    unsigned int a_syms;   /* length of symbol table data in file, in bytes */
1039 d97ef72e Richard Henderson
    unsigned int a_entry;  /* start address */
1040 d97ef72e Richard Henderson
    unsigned int a_trsize; /* length of relocation info for text, in bytes */
1041 d97ef72e Richard Henderson
    unsigned int a_drsize; /* length of relocation info for data, in bytes */
1042 09bfb054 bellard
};
1043 09bfb054 bellard
1044 09bfb054 bellard
1045 09bfb054 bellard
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
1046 09bfb054 bellard
#define OMAGIC 0407
1047 09bfb054 bellard
#define NMAGIC 0410
1048 09bfb054 bellard
#define ZMAGIC 0413
1049 09bfb054 bellard
#define QMAGIC 0314
1050 09bfb054 bellard
1051 31e31b8a bellard
/* Necessary parameters */
1052 54936004 bellard
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
1053 54936004 bellard
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
1054 54936004 bellard
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
1055 31e31b8a bellard
1056 14322bad Laurent ALFONSI
#define DLINFO_ITEMS 13
1057 31e31b8a bellard
1058 09bfb054 bellard
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
1059 09bfb054 bellard
{
1060 d97ef72e Richard Henderson
    memcpy(to, from, n);
1061 09bfb054 bellard
}
1062 d691f669 bellard
1063 31e31b8a bellard
#ifdef BSWAP_NEEDED
1064 92a31b1f bellard
static void bswap_ehdr(struct elfhdr *ehdr)
1065 31e31b8a bellard
{
1066 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_type);            /* Object file type */
1067 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_machine);         /* Architecture */
1068 d97ef72e Richard Henderson
    bswap32s(&ehdr->e_version);         /* Object file version */
1069 d97ef72e Richard Henderson
    bswaptls(&ehdr->e_entry);           /* Entry point virtual address */
1070 d97ef72e Richard Henderson
    bswaptls(&ehdr->e_phoff);           /* Program header table file offset */
1071 d97ef72e Richard Henderson
    bswaptls(&ehdr->e_shoff);           /* Section header table file offset */
1072 d97ef72e Richard Henderson
    bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
1073 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
1074 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_phentsize);       /* Program header table entry size */
1075 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
1076 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_shentsize);       /* Section header table entry size */
1077 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
1078 d97ef72e Richard Henderson
    bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */
1079 31e31b8a bellard
}
1080 31e31b8a bellard
1081 991f8f0c Richard Henderson
static void bswap_phdr(struct elf_phdr *phdr, int phnum)
1082 31e31b8a bellard
{
1083 991f8f0c Richard Henderson
    int i;
1084 991f8f0c Richard Henderson
    for (i = 0; i < phnum; ++i, ++phdr) {
1085 991f8f0c Richard Henderson
        bswap32s(&phdr->p_type);        /* Segment type */
1086 991f8f0c Richard Henderson
        bswap32s(&phdr->p_flags);       /* Segment flags */
1087 991f8f0c Richard Henderson
        bswaptls(&phdr->p_offset);      /* Segment file offset */
1088 991f8f0c Richard Henderson
        bswaptls(&phdr->p_vaddr);       /* Segment virtual address */
1089 991f8f0c Richard Henderson
        bswaptls(&phdr->p_paddr);       /* Segment physical address */
1090 991f8f0c Richard Henderson
        bswaptls(&phdr->p_filesz);      /* Segment size in file */
1091 991f8f0c Richard Henderson
        bswaptls(&phdr->p_memsz);       /* Segment size in memory */
1092 991f8f0c Richard Henderson
        bswaptls(&phdr->p_align);       /* Segment alignment */
1093 991f8f0c Richard Henderson
    }
1094 31e31b8a bellard
}
1095 689f936f bellard
1096 991f8f0c Richard Henderson
static void bswap_shdr(struct elf_shdr *shdr, int shnum)
1097 689f936f bellard
{
1098 991f8f0c Richard Henderson
    int i;
1099 991f8f0c Richard Henderson
    for (i = 0; i < shnum; ++i, ++shdr) {
1100 991f8f0c Richard Henderson
        bswap32s(&shdr->sh_name);
1101 991f8f0c Richard Henderson
        bswap32s(&shdr->sh_type);
1102 991f8f0c Richard Henderson
        bswaptls(&shdr->sh_flags);
1103 991f8f0c Richard Henderson
        bswaptls(&shdr->sh_addr);
1104 991f8f0c Richard Henderson
        bswaptls(&shdr->sh_offset);
1105 991f8f0c Richard Henderson
        bswaptls(&shdr->sh_size);
1106 991f8f0c Richard Henderson
        bswap32s(&shdr->sh_link);
1107 991f8f0c Richard Henderson
        bswap32s(&shdr->sh_info);
1108 991f8f0c Richard Henderson
        bswaptls(&shdr->sh_addralign);
1109 991f8f0c Richard Henderson
        bswaptls(&shdr->sh_entsize);
1110 991f8f0c Richard Henderson
    }
1111 689f936f bellard
}
1112 689f936f bellard
1113 7a3148a9 j_mayer
static void bswap_sym(struct elf_sym *sym)
1114 689f936f bellard
{
1115 689f936f bellard
    bswap32s(&sym->st_name);
1116 7a3148a9 j_mayer
    bswaptls(&sym->st_value);
1117 7a3148a9 j_mayer
    bswaptls(&sym->st_size);
1118 689f936f bellard
    bswap16s(&sym->st_shndx);
1119 689f936f bellard
}
1120 991f8f0c Richard Henderson
#else
1121 991f8f0c Richard Henderson
static inline void bswap_ehdr(struct elfhdr *ehdr) { }
1122 991f8f0c Richard Henderson
static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
1123 991f8f0c Richard Henderson
static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
1124 991f8f0c Richard Henderson
static inline void bswap_sym(struct elf_sym *sym) { }
1125 31e31b8a bellard
#endif
1126 31e31b8a bellard
1127 edf8e2af Mika Westerberg
#ifdef USE_ELF_CORE_DUMP
1128 9349b4f9 Andreas Fรคrber
static int elf_core_dump(int, const CPUArchState *);
1129 edf8e2af Mika Westerberg
#endif /* USE_ELF_CORE_DUMP */
1130 682674b8 Richard Henderson
static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
1131 edf8e2af Mika Westerberg
1132 9058abdd Richard Henderson
/* Verify the portions of EHDR within E_IDENT for the target.
1133 9058abdd Richard Henderson
   This can be performed before bswapping the entire header.  */
1134 9058abdd Richard Henderson
static bool elf_check_ident(struct elfhdr *ehdr)
1135 9058abdd Richard Henderson
{
1136 9058abdd Richard Henderson
    return (ehdr->e_ident[EI_MAG0] == ELFMAG0
1137 9058abdd Richard Henderson
            && ehdr->e_ident[EI_MAG1] == ELFMAG1
1138 9058abdd Richard Henderson
            && ehdr->e_ident[EI_MAG2] == ELFMAG2
1139 9058abdd Richard Henderson
            && ehdr->e_ident[EI_MAG3] == ELFMAG3
1140 9058abdd Richard Henderson
            && ehdr->e_ident[EI_CLASS] == ELF_CLASS
1141 9058abdd Richard Henderson
            && ehdr->e_ident[EI_DATA] == ELF_DATA
1142 9058abdd Richard Henderson
            && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
1143 9058abdd Richard Henderson
}
1144 9058abdd Richard Henderson
1145 9058abdd Richard Henderson
/* Verify the portions of EHDR outside of E_IDENT for the target.
1146 9058abdd Richard Henderson
   This has to wait until after bswapping the header.  */
1147 9058abdd Richard Henderson
static bool elf_check_ehdr(struct elfhdr *ehdr)
1148 9058abdd Richard Henderson
{
1149 9058abdd Richard Henderson
    return (elf_check_arch(ehdr->e_machine)
1150 9058abdd Richard Henderson
            && ehdr->e_ehsize == sizeof(struct elfhdr)
1151 9058abdd Richard Henderson
            && ehdr->e_phentsize == sizeof(struct elf_phdr)
1152 9058abdd Richard Henderson
            && ehdr->e_shentsize == sizeof(struct elf_shdr)
1153 9058abdd Richard Henderson
            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
1154 9058abdd Richard Henderson
}
1155 9058abdd Richard Henderson
1156 31e31b8a bellard
/*
1157 e5fe0c52 pbrook
 * 'copy_elf_strings()' copies argument/envelope strings from user
1158 31e31b8a bellard
 * memory to free pages in kernel mem. These are in a format ready
1159 31e31b8a bellard
 * to be put directly into the top of new user memory.
1160 31e31b8a bellard
 *
1161 31e31b8a bellard
 */
1162 992f48a0 blueswir1
static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
1163 992f48a0 blueswir1
                                  abi_ulong p)
1164 31e31b8a bellard
{
1165 31e31b8a bellard
    char *tmp, *tmp1, *pag = NULL;
1166 31e31b8a bellard
    int len, offset = 0;
1167 31e31b8a bellard
1168 31e31b8a bellard
    if (!p) {
1169 d97ef72e Richard Henderson
        return 0;       /* bullet-proofing */
1170 31e31b8a bellard
    }
1171 31e31b8a bellard
    while (argc-- > 0) {
1172 edf779ff bellard
        tmp = argv[argc];
1173 edf779ff bellard
        if (!tmp) {
1174 d97ef72e Richard Henderson
            fprintf(stderr, "VFS: argc is wrong");
1175 d97ef72e Richard Henderson
            exit(-1);
1176 d97ef72e Richard Henderson
        }
1177 edf779ff bellard
        tmp1 = tmp;
1178 d97ef72e Richard Henderson
        while (*tmp++);
1179 d97ef72e Richard Henderson
        len = tmp - tmp1;
1180 d97ef72e Richard Henderson
        if (p < len) {  /* this shouldn't happen - 128kB */
1181 d97ef72e Richard Henderson
            return 0;
1182 d97ef72e Richard Henderson
        }
1183 d97ef72e Richard Henderson
        while (len) {
1184 d97ef72e Richard Henderson
            --p; --tmp; --len;
1185 d97ef72e Richard Henderson
            if (--offset < 0) {
1186 d97ef72e Richard Henderson
                offset = p % TARGET_PAGE_SIZE;
1187 53a5960a pbrook
                pag = (char *)page[p/TARGET_PAGE_SIZE];
1188 44a91cae bellard
                if (!pag) {
1189 7dd47667 Peter Maydell
                    pag = g_try_malloc0(TARGET_PAGE_SIZE);
1190 53a5960a pbrook
                    page[p/TARGET_PAGE_SIZE] = pag;
1191 44a91cae bellard
                    if (!pag)
1192 44a91cae bellard
                        return 0;
1193 d97ef72e Richard Henderson
                }
1194 d97ef72e Richard Henderson
            }
1195 d97ef72e Richard Henderson
            if (len == 0 || offset == 0) {
1196 d97ef72e Richard Henderson
                *(pag + offset) = *tmp;
1197 d97ef72e Richard Henderson
            }
1198 d97ef72e Richard Henderson
            else {
1199 d97ef72e Richard Henderson
                int bytes_to_copy = (len > offset) ? offset : len;
1200 d97ef72e Richard Henderson
                tmp -= bytes_to_copy;
1201 d97ef72e Richard Henderson
                p -= bytes_to_copy;
1202 d97ef72e Richard Henderson
                offset -= bytes_to_copy;
1203 d97ef72e Richard Henderson
                len -= bytes_to_copy;
1204 d97ef72e Richard Henderson
                memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
1205 d97ef72e Richard Henderson
            }
1206 d97ef72e Richard Henderson
        }
1207 31e31b8a bellard
    }
1208 31e31b8a bellard
    return p;
1209 31e31b8a bellard
}
1210 31e31b8a bellard
1211 992f48a0 blueswir1
static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
1212 992f48a0 blueswir1
                                 struct image_info *info)
1213 53a5960a pbrook
{
1214 60dcbcb5 Richard Henderson
    abi_ulong stack_base, size, error, guard;
1215 31e31b8a bellard
    int i;
1216 31e31b8a bellard
1217 09bfb054 bellard
    /* Create enough stack to hold everything.  If we don't use
1218 60dcbcb5 Richard Henderson
       it for args, we'll use it for something else.  */
1219 703e0e89 Richard Henderson
    size = guest_stack_size;
1220 60dcbcb5 Richard Henderson
    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) {
1221 54936004 bellard
        size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
1222 60dcbcb5 Richard Henderson
    }
1223 60dcbcb5 Richard Henderson
    guard = TARGET_PAGE_SIZE;
1224 60dcbcb5 Richard Henderson
    if (guard < qemu_real_host_page_size) {
1225 60dcbcb5 Richard Henderson
        guard = qemu_real_host_page_size;
1226 60dcbcb5 Richard Henderson
    }
1227 60dcbcb5 Richard Henderson
1228 60dcbcb5 Richard Henderson
    error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
1229 60dcbcb5 Richard Henderson
                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1230 09bfb054 bellard
    if (error == -1) {
1231 60dcbcb5 Richard Henderson
        perror("mmap stack");
1232 09bfb054 bellard
        exit(-1);
1233 09bfb054 bellard
    }
1234 31e31b8a bellard
1235 60dcbcb5 Richard Henderson
    /* We reserve one extra page at the top of the stack as guard.  */
1236 60dcbcb5 Richard Henderson
    target_mprotect(error, guard, PROT_NONE);
1237 60dcbcb5 Richard Henderson
1238 60dcbcb5 Richard Henderson
    info->stack_limit = error + guard;
1239 60dcbcb5 Richard Henderson
    stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
1240 31e31b8a bellard
    p += stack_base;
1241 09bfb054 bellard
1242 31e31b8a bellard
    for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
1243 d97ef72e Richard Henderson
        if (bprm->page[i]) {
1244 d97ef72e Richard Henderson
            info->rss++;
1245 579a97f7 bellard
            /* FIXME - check return value of memcpy_to_target() for failure */
1246 d97ef72e Richard Henderson
            memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
1247 7dd47667 Peter Maydell
            g_free(bprm->page[i]);
1248 d97ef72e Richard Henderson
        }
1249 53a5960a pbrook
        stack_base += TARGET_PAGE_SIZE;
1250 31e31b8a bellard
    }
1251 31e31b8a bellard
    return p;
1252 31e31b8a bellard
}
1253 31e31b8a bellard
1254 cf129f3a Richard Henderson
/* Map and zero the bss.  We need to explicitly zero any fractional pages
1255 cf129f3a Richard Henderson
   after the data section (i.e. bss).  */
1256 cf129f3a Richard Henderson
static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
1257 31e31b8a bellard
{
1258 cf129f3a Richard Henderson
    uintptr_t host_start, host_map_start, host_end;
1259 cf129f3a Richard Henderson
1260 cf129f3a Richard Henderson
    last_bss = TARGET_PAGE_ALIGN(last_bss);
1261 cf129f3a Richard Henderson
1262 cf129f3a Richard Henderson
    /* ??? There is confusion between qemu_real_host_page_size and
1263 cf129f3a Richard Henderson
       qemu_host_page_size here and elsewhere in target_mmap, which
1264 cf129f3a Richard Henderson
       may lead to the end of the data section mapping from the file
1265 cf129f3a Richard Henderson
       not being mapped.  At least there was an explicit test and
1266 cf129f3a Richard Henderson
       comment for that here, suggesting that "the file size must
1267 cf129f3a Richard Henderson
       be known".  The comment probably pre-dates the introduction
1268 cf129f3a Richard Henderson
       of the fstat system call in target_mmap which does in fact
1269 cf129f3a Richard Henderson
       find out the size.  What isn't clear is if the workaround
1270 cf129f3a Richard Henderson
       here is still actually needed.  For now, continue with it,
1271 cf129f3a Richard Henderson
       but merge it with the "normal" mmap that would allocate the bss.  */
1272 cf129f3a Richard Henderson
1273 cf129f3a Richard Henderson
    host_start = (uintptr_t) g2h(elf_bss);
1274 cf129f3a Richard Henderson
    host_end = (uintptr_t) g2h(last_bss);
1275 cf129f3a Richard Henderson
    host_map_start = (host_start + qemu_real_host_page_size - 1);
1276 cf129f3a Richard Henderson
    host_map_start &= -qemu_real_host_page_size;
1277 cf129f3a Richard Henderson
1278 cf129f3a Richard Henderson
    if (host_map_start < host_end) {
1279 cf129f3a Richard Henderson
        void *p = mmap((void *)host_map_start, host_end - host_map_start,
1280 cf129f3a Richard Henderson
                       prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1281 cf129f3a Richard Henderson
        if (p == MAP_FAILED) {
1282 cf129f3a Richard Henderson
            perror("cannot mmap brk");
1283 cf129f3a Richard Henderson
            exit(-1);
1284 853d6f7a bellard
        }
1285 853d6f7a bellard
1286 cf129f3a Richard Henderson
        /* Since we didn't use target_mmap, make sure to record
1287 cf129f3a Richard Henderson
           the validity of the pages with qemu.  */
1288 cf129f3a Richard Henderson
        page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
1289 cf129f3a Richard Henderson
    }
1290 31e31b8a bellard
1291 cf129f3a Richard Henderson
    if (host_start < host_map_start) {
1292 cf129f3a Richard Henderson
        memset((void *)host_start, 0, host_map_start - host_start);
1293 cf129f3a Richard Henderson
    }
1294 cf129f3a Richard Henderson
}
1295 53a5960a pbrook
1296 1af02e83 Mike Frysinger
#ifdef CONFIG_USE_FDPIC
1297 1af02e83 Mike Frysinger
static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
1298 1af02e83 Mike Frysinger
{
1299 1af02e83 Mike Frysinger
    uint16_t n;
1300 1af02e83 Mike Frysinger
    struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
1301 1af02e83 Mike Frysinger
1302 1af02e83 Mike Frysinger
    /* elf32_fdpic_loadseg */
1303 1af02e83 Mike Frysinger
    n = info->nsegs;
1304 1af02e83 Mike Frysinger
    while (n--) {
1305 1af02e83 Mike Frysinger
        sp -= 12;
1306 1af02e83 Mike Frysinger
        put_user_u32(loadsegs[n].addr, sp+0);
1307 1af02e83 Mike Frysinger
        put_user_u32(loadsegs[n].p_vaddr, sp+4);
1308 1af02e83 Mike Frysinger
        put_user_u32(loadsegs[n].p_memsz, sp+8);
1309 1af02e83 Mike Frysinger
    }
1310 1af02e83 Mike Frysinger
1311 1af02e83 Mike Frysinger
    /* elf32_fdpic_loadmap */
1312 1af02e83 Mike Frysinger
    sp -= 4;
1313 1af02e83 Mike Frysinger
    put_user_u16(0, sp+0); /* version */
1314 1af02e83 Mike Frysinger
    put_user_u16(info->nsegs, sp+2); /* nsegs */
1315 1af02e83 Mike Frysinger
1316 1af02e83 Mike Frysinger
    info->personality = PER_LINUX_FDPIC;
1317 1af02e83 Mike Frysinger
    info->loadmap_addr = sp;
1318 1af02e83 Mike Frysinger
1319 1af02e83 Mike Frysinger
    return sp;
1320 1af02e83 Mike Frysinger
}
1321 1af02e83 Mike Frysinger
#endif
1322 1af02e83 Mike Frysinger
1323 992f48a0 blueswir1
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
1324 8e62a717 Richard Henderson
                                   struct elfhdr *exec,
1325 8e62a717 Richard Henderson
                                   struct image_info *info,
1326 8e62a717 Richard Henderson
                                   struct image_info *interp_info)
1327 31e31b8a bellard
{
1328 d97ef72e Richard Henderson
    abi_ulong sp;
1329 125b0f55 Alexander Graf
    abi_ulong sp_auxv;
1330 d97ef72e Richard Henderson
    int size;
1331 14322bad Laurent ALFONSI
    int i;
1332 14322bad Laurent ALFONSI
    abi_ulong u_rand_bytes;
1333 14322bad Laurent ALFONSI
    uint8_t k_rand_bytes[16];
1334 d97ef72e Richard Henderson
    abi_ulong u_platform;
1335 d97ef72e Richard Henderson
    const char *k_platform;
1336 d97ef72e Richard Henderson
    const int n = sizeof(elf_addr_t);
1337 d97ef72e Richard Henderson
1338 d97ef72e Richard Henderson
    sp = p;
1339 1af02e83 Mike Frysinger
1340 1af02e83 Mike Frysinger
#ifdef CONFIG_USE_FDPIC
1341 1af02e83 Mike Frysinger
    /* Needs to be before we load the env/argc/... */
1342 1af02e83 Mike Frysinger
    if (elf_is_fdpic(exec)) {
1343 1af02e83 Mike Frysinger
        /* Need 4 byte alignment for these structs */
1344 1af02e83 Mike Frysinger
        sp &= ~3;
1345 1af02e83 Mike Frysinger
        sp = loader_build_fdpic_loadmap(info, sp);
1346 1af02e83 Mike Frysinger
        info->other_info = interp_info;
1347 1af02e83 Mike Frysinger
        if (interp_info) {
1348 1af02e83 Mike Frysinger
            interp_info->other_info = info;
1349 1af02e83 Mike Frysinger
            sp = loader_build_fdpic_loadmap(interp_info, sp);
1350 1af02e83 Mike Frysinger
        }
1351 1af02e83 Mike Frysinger
    }
1352 1af02e83 Mike Frysinger
#endif
1353 1af02e83 Mike Frysinger
1354 d97ef72e Richard Henderson
    u_platform = 0;
1355 d97ef72e Richard Henderson
    k_platform = ELF_PLATFORM;
1356 d97ef72e Richard Henderson
    if (k_platform) {
1357 d97ef72e Richard Henderson
        size_t len = strlen(k_platform) + 1;
1358 d97ef72e Richard Henderson
        sp -= (len + n - 1) & ~(n - 1);
1359 d97ef72e Richard Henderson
        u_platform = sp;
1360 d97ef72e Richard Henderson
        /* FIXME - check return value of memcpy_to_target() for failure */
1361 d97ef72e Richard Henderson
        memcpy_to_target(sp, k_platform, len);
1362 d97ef72e Richard Henderson
    }
1363 14322bad Laurent ALFONSI
1364 14322bad Laurent ALFONSI
    /*
1365 14322bad Laurent ALFONSI
     * Generate 16 random bytes for userspace PRNG seeding (not
1366 14322bad Laurent ALFONSI
     * cryptically secure but it's not the aim of QEMU).
1367 14322bad Laurent ALFONSI
     */
1368 14322bad Laurent ALFONSI
    srand((unsigned int) time(NULL));
1369 14322bad Laurent ALFONSI
    for (i = 0; i < 16; i++) {
1370 14322bad Laurent ALFONSI
        k_rand_bytes[i] = rand();
1371 14322bad Laurent ALFONSI
    }
1372 14322bad Laurent ALFONSI
    sp -= 16;
1373 14322bad Laurent ALFONSI
    u_rand_bytes = sp;
1374 14322bad Laurent ALFONSI
    /* FIXME - check return value of memcpy_to_target() for failure */
1375 14322bad Laurent ALFONSI
    memcpy_to_target(sp, k_rand_bytes, 16);
1376 14322bad Laurent ALFONSI
1377 d97ef72e Richard Henderson
    /*
1378 d97ef72e Richard Henderson
     * Force 16 byte _final_ alignment here for generality.
1379 d97ef72e Richard Henderson
     */
1380 d97ef72e Richard Henderson
    sp = sp &~ (abi_ulong)15;
1381 d97ef72e Richard Henderson
    size = (DLINFO_ITEMS + 1) * 2;
1382 d97ef72e Richard Henderson
    if (k_platform)
1383 d97ef72e Richard Henderson
        size += 2;
1384 f5155289 bellard
#ifdef DLINFO_ARCH_ITEMS
1385 d97ef72e Richard Henderson
    size += DLINFO_ARCH_ITEMS * 2;
1386 f5155289 bellard
#endif
1387 d97ef72e Richard Henderson
    size += envc + argc + 2;
1388 b9329d4b Richard Henderson
    size += 1;  /* argc itself */
1389 d97ef72e Richard Henderson
    size *= n;
1390 d97ef72e Richard Henderson
    if (size & 15)
1391 d97ef72e Richard Henderson
        sp -= 16 - (size & 15);
1392 d97ef72e Richard Henderson
1393 d97ef72e Richard Henderson
    /* This is correct because Linux defines
1394 d97ef72e Richard Henderson
     * elf_addr_t as Elf32_Off / Elf64_Off
1395 d97ef72e Richard Henderson
     */
1396 d97ef72e Richard Henderson
#define NEW_AUX_ENT(id, val) do {               \
1397 d97ef72e Richard Henderson
        sp -= n; put_user_ual(val, sp);         \
1398 d97ef72e Richard Henderson
        sp -= n; put_user_ual(id, sp);          \
1399 d97ef72e Richard Henderson
    } while(0)
1400 d97ef72e Richard Henderson
1401 125b0f55 Alexander Graf
    sp_auxv = sp;
1402 d97ef72e Richard Henderson
    NEW_AUX_ENT (AT_NULL, 0);
1403 d97ef72e Richard Henderson
1404 d97ef72e Richard Henderson
    /* There must be exactly DLINFO_ITEMS entries here.  */
1405 8e62a717 Richard Henderson
    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
1406 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1407 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1408 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
1409 8e62a717 Richard Henderson
    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0));
1410 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
1411 8e62a717 Richard Henderson
    NEW_AUX_ENT(AT_ENTRY, info->entry);
1412 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1413 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1414 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1415 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1416 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1417 d97ef72e Richard Henderson
    NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
1418 14322bad Laurent ALFONSI
    NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
1419 14322bad Laurent ALFONSI
1420 d97ef72e Richard Henderson
    if (k_platform)
1421 d97ef72e Richard Henderson
        NEW_AUX_ENT(AT_PLATFORM, u_platform);
1422 f5155289 bellard
#ifdef ARCH_DLINFO
1423 d97ef72e Richard Henderson
    /*
1424 d97ef72e Richard Henderson
     * ARCH_DLINFO must come last so platform specific code can enforce
1425 d97ef72e Richard Henderson
     * special alignment requirements on the AUXV if necessary (eg. PPC).
1426 d97ef72e Richard Henderson
     */
1427 d97ef72e Richard Henderson
    ARCH_DLINFO;
1428 f5155289 bellard
#endif
1429 f5155289 bellard
#undef NEW_AUX_ENT
1430 f5155289 bellard
1431 d97ef72e Richard Henderson
    info->saved_auxv = sp;
1432 125b0f55 Alexander Graf
    info->auxv_len = sp_auxv - sp;
1433 edf8e2af Mika Westerberg
1434 b9329d4b Richard Henderson
    sp = loader_build_argptr(envc, argc, sp, p, 0);
1435 d97ef72e Richard Henderson
    return sp;
1436 31e31b8a bellard
}
1437 31e31b8a bellard
1438 806d1021 Meador Inge
#ifndef TARGET_HAS_VALIDATE_GUEST_SPACE
1439 97cc7560 Dr. David Alan Gilbert
/* If the guest doesn't have a validation function just agree */
1440 806d1021 Meador Inge
static int validate_guest_space(unsigned long guest_base,
1441 806d1021 Meador Inge
                                unsigned long guest_size)
1442 97cc7560 Dr. David Alan Gilbert
{
1443 97cc7560 Dr. David Alan Gilbert
    return 1;
1444 97cc7560 Dr. David Alan Gilbert
}
1445 97cc7560 Dr. David Alan Gilbert
#endif
1446 97cc7560 Dr. David Alan Gilbert
1447 dce10401 Meador Inge
unsigned long init_guest_space(unsigned long host_start,
1448 dce10401 Meador Inge
                               unsigned long host_size,
1449 dce10401 Meador Inge
                               unsigned long guest_start,
1450 dce10401 Meador Inge
                               bool fixed)
1451 dce10401 Meador Inge
{
1452 dce10401 Meador Inge
    unsigned long current_start, real_start;
1453 dce10401 Meador Inge
    int flags;
1454 dce10401 Meador Inge
1455 dce10401 Meador Inge
    assert(host_start || host_size);
1456 dce10401 Meador Inge
1457 dce10401 Meador Inge
    /* If just a starting address is given, then just verify that
1458 dce10401 Meador Inge
     * address.  */
1459 dce10401 Meador Inge
    if (host_start && !host_size) {
1460 806d1021 Meador Inge
        if (validate_guest_space(host_start, host_size) == 1) {
1461 dce10401 Meador Inge
            return host_start;
1462 dce10401 Meador Inge
        } else {
1463 dce10401 Meador Inge
            return (unsigned long)-1;
1464 dce10401 Meador Inge
        }
1465 dce10401 Meador Inge
    }
1466 dce10401 Meador Inge
1467 dce10401 Meador Inge
    /* Setup the initial flags and start address.  */
1468 dce10401 Meador Inge
    current_start = host_start & qemu_host_page_mask;
1469 dce10401 Meador Inge
    flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
1470 dce10401 Meador Inge
    if (fixed) {
1471 dce10401 Meador Inge
        flags |= MAP_FIXED;
1472 dce10401 Meador Inge
    }
1473 dce10401 Meador Inge
1474 dce10401 Meador Inge
    /* Otherwise, a non-zero size region of memory needs to be mapped
1475 dce10401 Meador Inge
     * and validated.  */
1476 dce10401 Meador Inge
    while (1) {
1477 806d1021 Meador Inge
        unsigned long real_size = host_size;
1478 806d1021 Meador Inge
1479 dce10401 Meador Inge
        /* Do not use mmap_find_vma here because that is limited to the
1480 dce10401 Meador Inge
         * guest address space.  We are going to make the
1481 dce10401 Meador Inge
         * guest address space fit whatever we're given.
1482 dce10401 Meador Inge
         */
1483 dce10401 Meador Inge
        real_start = (unsigned long)
1484 dce10401 Meador Inge
            mmap((void *)current_start, host_size, PROT_NONE, flags, -1, 0);
1485 dce10401 Meador Inge
        if (real_start == (unsigned long)-1) {
1486 dce10401 Meador Inge
            return (unsigned long)-1;
1487 dce10401 Meador Inge
        }
1488 dce10401 Meador Inge
1489 806d1021 Meador Inge
        /* Ensure the address is properly aligned.  */
1490 806d1021 Meador Inge
        if (real_start & ~qemu_host_page_mask) {
1491 806d1021 Meador Inge
            munmap((void *)real_start, host_size);
1492 806d1021 Meador Inge
            real_size = host_size + qemu_host_page_size;
1493 806d1021 Meador Inge
            real_start = (unsigned long)
1494 806d1021 Meador Inge
                mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0);
1495 806d1021 Meador Inge
            if (real_start == (unsigned long)-1) {
1496 806d1021 Meador Inge
                return (unsigned long)-1;
1497 806d1021 Meador Inge
            }
1498 806d1021 Meador Inge
            real_start = HOST_PAGE_ALIGN(real_start);
1499 806d1021 Meador Inge
        }
1500 806d1021 Meador Inge
1501 806d1021 Meador Inge
        /* Check to see if the address is valid.  */
1502 806d1021 Meador Inge
        if (!host_start || real_start == current_start) {
1503 806d1021 Meador Inge
            int valid = validate_guest_space(real_start - guest_start,
1504 806d1021 Meador Inge
                                             real_size);
1505 806d1021 Meador Inge
            if (valid == 1) {
1506 806d1021 Meador Inge
                break;
1507 806d1021 Meador Inge
            } else if (valid == -1) {
1508 806d1021 Meador Inge
                return (unsigned long)-1;
1509 806d1021 Meador Inge
            }
1510 806d1021 Meador Inge
            /* valid == 0, so try again. */
1511 dce10401 Meador Inge
        }
1512 dce10401 Meador Inge
1513 dce10401 Meador Inge
        /* That address didn't work.  Unmap and try a different one.
1514 dce10401 Meador Inge
         * The address the host picked because is typically right at
1515 dce10401 Meador Inge
         * the top of the host address space and leaves the guest with
1516 dce10401 Meador Inge
         * no usable address space.  Resort to a linear search.  We
1517 dce10401 Meador Inge
         * already compensated for mmap_min_addr, so this should not
1518 dce10401 Meador Inge
         * happen often.  Probably means we got unlucky and host
1519 dce10401 Meador Inge
         * address space randomization put a shared library somewhere
1520 dce10401 Meador Inge
         * inconvenient.
1521 dce10401 Meador Inge
         */
1522 dce10401 Meador Inge
        munmap((void *)real_start, host_size);
1523 dce10401 Meador Inge
        current_start += qemu_host_page_size;
1524 dce10401 Meador Inge
        if (host_start == current_start) {
1525 dce10401 Meador Inge
            /* Theoretically possible if host doesn't have any suitably
1526 dce10401 Meador Inge
             * aligned areas.  Normally the first mmap will fail.
1527 dce10401 Meador Inge
             */
1528 dce10401 Meador Inge
            return (unsigned long)-1;
1529 dce10401 Meador Inge
        }
1530 dce10401 Meador Inge
    }
1531 dce10401 Meador Inge
1532 806d1021 Meador Inge
    qemu_log("Reserved 0x%lx bytes of guest address space\n", host_size);
1533 806d1021 Meador Inge
1534 dce10401 Meador Inge
    return real_start;
1535 dce10401 Meador Inge
}
1536 dce10401 Meador Inge
1537 f3ed1f5d Peter Maydell
static void probe_guest_base(const char *image_name,
1538 f3ed1f5d Peter Maydell
                             abi_ulong loaddr, abi_ulong hiaddr)
1539 f3ed1f5d Peter Maydell
{
1540 f3ed1f5d Peter Maydell
    /* Probe for a suitable guest base address, if the user has not set
1541 f3ed1f5d Peter Maydell
     * it explicitly, and set guest_base appropriately.
1542 f3ed1f5d Peter Maydell
     * In case of error we will print a suitable message and exit.
1543 f3ed1f5d Peter Maydell
     */
1544 f3ed1f5d Peter Maydell
#if defined(CONFIG_USE_GUEST_BASE)
1545 f3ed1f5d Peter Maydell
    const char *errmsg;
1546 f3ed1f5d Peter Maydell
    if (!have_guest_base && !reserved_va) {
1547 f3ed1f5d Peter Maydell
        unsigned long host_start, real_start, host_size;
1548 f3ed1f5d Peter Maydell
1549 f3ed1f5d Peter Maydell
        /* Round addresses to page boundaries.  */
1550 f3ed1f5d Peter Maydell
        loaddr &= qemu_host_page_mask;
1551 f3ed1f5d Peter Maydell
        hiaddr = HOST_PAGE_ALIGN(hiaddr);
1552 f3ed1f5d Peter Maydell
1553 f3ed1f5d Peter Maydell
        if (loaddr < mmap_min_addr) {
1554 f3ed1f5d Peter Maydell
            host_start = HOST_PAGE_ALIGN(mmap_min_addr);
1555 f3ed1f5d Peter Maydell
        } else {
1556 f3ed1f5d Peter Maydell
            host_start = loaddr;
1557 f3ed1f5d Peter Maydell
            if (host_start != loaddr) {
1558 f3ed1f5d Peter Maydell
                errmsg = "Address overflow loading ELF binary";
1559 f3ed1f5d Peter Maydell
                goto exit_errmsg;
1560 f3ed1f5d Peter Maydell
            }
1561 f3ed1f5d Peter Maydell
        }
1562 f3ed1f5d Peter Maydell
        host_size = hiaddr - loaddr;
1563 dce10401 Meador Inge
1564 dce10401 Meador Inge
        /* Setup the initial guest memory space with ranges gleaned from
1565 dce10401 Meador Inge
         * the ELF image that is being loaded.
1566 dce10401 Meador Inge
         */
1567 dce10401 Meador Inge
        real_start = init_guest_space(host_start, host_size, loaddr, false);
1568 dce10401 Meador Inge
        if (real_start == (unsigned long)-1) {
1569 dce10401 Meador Inge
            errmsg = "Unable to find space for application";
1570 dce10401 Meador Inge
            goto exit_errmsg;
1571 f3ed1f5d Peter Maydell
        }
1572 dce10401 Meador Inge
        guest_base = real_start - loaddr;
1573 dce10401 Meador Inge
1574 f3ed1f5d Peter Maydell
        qemu_log("Relocating guest address space from 0x"
1575 f3ed1f5d Peter Maydell
                 TARGET_ABI_FMT_lx " to 0x%lx\n",
1576 f3ed1f5d Peter Maydell
                 loaddr, real_start);
1577 f3ed1f5d Peter Maydell
    }
1578 f3ed1f5d Peter Maydell
    return;
1579 f3ed1f5d Peter Maydell
1580 f3ed1f5d Peter Maydell
exit_errmsg:
1581 f3ed1f5d Peter Maydell
    fprintf(stderr, "%s: %s\n", image_name, errmsg);
1582 f3ed1f5d Peter Maydell
    exit(-1);
1583 f3ed1f5d Peter Maydell
#endif
1584 f3ed1f5d Peter Maydell
}
1585 f3ed1f5d Peter Maydell
1586 f3ed1f5d Peter Maydell
1587 8e62a717 Richard Henderson
/* Load an ELF image into the address space.
1588 31e31b8a bellard

1589 8e62a717 Richard Henderson
   IMAGE_NAME is the filename of the image, to use in error messages.
1590 8e62a717 Richard Henderson
   IMAGE_FD is the open file descriptor for the image.
1591 8e62a717 Richard Henderson

1592 8e62a717 Richard Henderson
   BPRM_BUF is a copy of the beginning of the file; this of course
1593 8e62a717 Richard Henderson
   contains the elf file header at offset 0.  It is assumed that this
1594 8e62a717 Richard Henderson
   buffer is sufficiently aligned to present no problems to the host
1595 8e62a717 Richard Henderson
   in accessing data at aligned offsets within the buffer.
1596 8e62a717 Richard Henderson

1597 8e62a717 Richard Henderson
   On return: INFO values will be filled in, as necessary or available.  */
1598 8e62a717 Richard Henderson
1599 8e62a717 Richard Henderson
static void load_elf_image(const char *image_name, int image_fd,
1600 bf858897 Richard Henderson
                           struct image_info *info, char **pinterp_name,
1601 8e62a717 Richard Henderson
                           char bprm_buf[BPRM_BUF_SIZE])
1602 31e31b8a bellard
{
1603 8e62a717 Richard Henderson
    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
1604 8e62a717 Richard Henderson
    struct elf_phdr *phdr;
1605 8e62a717 Richard Henderson
    abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
1606 8e62a717 Richard Henderson
    int i, retval;
1607 8e62a717 Richard Henderson
    const char *errmsg;
1608 5fafdf24 ths
1609 8e62a717 Richard Henderson
    /* First of all, some simple consistency checks */
1610 8e62a717 Richard Henderson
    errmsg = "Invalid ELF image for this architecture";
1611 8e62a717 Richard Henderson
    if (!elf_check_ident(ehdr)) {
1612 8e62a717 Richard Henderson
        goto exit_errmsg;
1613 8e62a717 Richard Henderson
    }
1614 8e62a717 Richard Henderson
    bswap_ehdr(ehdr);
1615 8e62a717 Richard Henderson
    if (!elf_check_ehdr(ehdr)) {
1616 8e62a717 Richard Henderson
        goto exit_errmsg;
1617 d97ef72e Richard Henderson
    }
1618 5fafdf24 ths
1619 8e62a717 Richard Henderson
    i = ehdr->e_phnum * sizeof(struct elf_phdr);
1620 8e62a717 Richard Henderson
    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
1621 8e62a717 Richard Henderson
        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
1622 9955ffac Richard Henderson
    } else {
1623 8e62a717 Richard Henderson
        phdr = (struct elf_phdr *) alloca(i);
1624 8e62a717 Richard Henderson
        retval = pread(image_fd, phdr, i, ehdr->e_phoff);
1625 9955ffac Richard Henderson
        if (retval != i) {
1626 8e62a717 Richard Henderson
            goto exit_read;
1627 9955ffac Richard Henderson
        }
1628 d97ef72e Richard Henderson
    }
1629 8e62a717 Richard Henderson
    bswap_phdr(phdr, ehdr->e_phnum);
1630 09bfb054 bellard
1631 1af02e83 Mike Frysinger
#ifdef CONFIG_USE_FDPIC
1632 1af02e83 Mike Frysinger
    info->nsegs = 0;
1633 1af02e83 Mike Frysinger
    info->pt_dynamic_addr = 0;
1634 1af02e83 Mike Frysinger
#endif
1635 1af02e83 Mike Frysinger
1636 682674b8 Richard Henderson
    /* Find the maximum size of the image and allocate an appropriate
1637 682674b8 Richard Henderson
       amount of memory to handle that.  */
1638 682674b8 Richard Henderson
    loaddr = -1, hiaddr = 0;
1639 8e62a717 Richard Henderson
    for (i = 0; i < ehdr->e_phnum; ++i) {
1640 8e62a717 Richard Henderson
        if (phdr[i].p_type == PT_LOAD) {
1641 8e62a717 Richard Henderson
            abi_ulong a = phdr[i].p_vaddr;
1642 682674b8 Richard Henderson
            if (a < loaddr) {
1643 682674b8 Richard Henderson
                loaddr = a;
1644 682674b8 Richard Henderson
            }
1645 8e62a717 Richard Henderson
            a += phdr[i].p_memsz;
1646 682674b8 Richard Henderson
            if (a > hiaddr) {
1647 682674b8 Richard Henderson
                hiaddr = a;
1648 682674b8 Richard Henderson
            }
1649 1af02e83 Mike Frysinger
#ifdef CONFIG_USE_FDPIC
1650 1af02e83 Mike Frysinger
            ++info->nsegs;
1651 1af02e83 Mike Frysinger
#endif
1652 682674b8 Richard Henderson
        }
1653 682674b8 Richard Henderson
    }
1654 682674b8 Richard Henderson
1655 682674b8 Richard Henderson
    load_addr = loaddr;
1656 8e62a717 Richard Henderson
    if (ehdr->e_type == ET_DYN) {
1657 682674b8 Richard Henderson
        /* The image indicates that it can be loaded anywhere.  Find a
1658 682674b8 Richard Henderson
           location that can hold the memory space required.  If the
1659 682674b8 Richard Henderson
           image is pre-linked, LOADDR will be non-zero.  Since we do
1660 682674b8 Richard Henderson
           not supply MAP_FIXED here we'll use that address if and
1661 682674b8 Richard Henderson
           only if it remains available.  */
1662 682674b8 Richard Henderson
        load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
1663 682674b8 Richard Henderson
                                MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
1664 682674b8 Richard Henderson
                                -1, 0);
1665 682674b8 Richard Henderson
        if (load_addr == -1) {
1666 8e62a717 Richard Henderson
            goto exit_perror;
1667 d97ef72e Richard Henderson
        }
1668 bf858897 Richard Henderson
    } else if (pinterp_name != NULL) {
1669 bf858897 Richard Henderson
        /* This is the main executable.  Make sure that the low
1670 bf858897 Richard Henderson
           address does not conflict with MMAP_MIN_ADDR or the
1671 bf858897 Richard Henderson
           QEMU application itself.  */
1672 f3ed1f5d Peter Maydell
        probe_guest_base(image_name, loaddr, hiaddr);
1673 d97ef72e Richard Henderson
    }
1674 682674b8 Richard Henderson
    load_bias = load_addr - loaddr;
1675 d97ef72e Richard Henderson
1676 1af02e83 Mike Frysinger
#ifdef CONFIG_USE_FDPIC
1677 1af02e83 Mike Frysinger
    {
1678 1af02e83 Mike Frysinger
        struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
1679 7267c094 Anthony Liguori
            g_malloc(sizeof(*loadsegs) * info->nsegs);
1680 1af02e83 Mike Frysinger
1681 1af02e83 Mike Frysinger
        for (i = 0; i < ehdr->e_phnum; ++i) {
1682 1af02e83 Mike Frysinger
            switch (phdr[i].p_type) {
1683 1af02e83 Mike Frysinger
            case PT_DYNAMIC:
1684 1af02e83 Mike Frysinger
                info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
1685 1af02e83 Mike Frysinger
                break;
1686 1af02e83 Mike Frysinger
            case PT_LOAD:
1687 1af02e83 Mike Frysinger
                loadsegs->addr = phdr[i].p_vaddr + load_bias;
1688 1af02e83 Mike Frysinger
                loadsegs->p_vaddr = phdr[i].p_vaddr;
1689 1af02e83 Mike Frysinger
                loadsegs->p_memsz = phdr[i].p_memsz;
1690 1af02e83 Mike Frysinger
                ++loadsegs;
1691 1af02e83 Mike Frysinger
                break;
1692 1af02e83 Mike Frysinger
            }
1693 1af02e83 Mike Frysinger
        }
1694 1af02e83 Mike Frysinger
    }
1695 1af02e83 Mike Frysinger
#endif
1696 1af02e83 Mike Frysinger
1697 8e62a717 Richard Henderson
    info->load_bias = load_bias;
1698 8e62a717 Richard Henderson
    info->load_addr = load_addr;
1699 8e62a717 Richard Henderson
    info->entry = ehdr->e_entry + load_bias;
1700 8e62a717 Richard Henderson
    info->start_code = -1;
1701 8e62a717 Richard Henderson
    info->end_code = 0;
1702 8e62a717 Richard Henderson
    info->start_data = -1;
1703 8e62a717 Richard Henderson
    info->end_data = 0;
1704 8e62a717 Richard Henderson
    info->brk = 0;
1705 d8fd2954 Paul Brook
    info->elf_flags = ehdr->e_flags;
1706 8e62a717 Richard Henderson
1707 8e62a717 Richard Henderson
    for (i = 0; i < ehdr->e_phnum; i++) {
1708 8e62a717 Richard Henderson
        struct elf_phdr *eppnt = phdr + i;
1709 d97ef72e Richard Henderson
        if (eppnt->p_type == PT_LOAD) {
1710 682674b8 Richard Henderson
            abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
1711 d97ef72e Richard Henderson
            int elf_prot = 0;
1712 d97ef72e Richard Henderson
1713 d97ef72e Richard Henderson
            if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
1714 d97ef72e Richard Henderson
            if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1715 d97ef72e Richard Henderson
            if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1716 d97ef72e Richard Henderson
1717 682674b8 Richard Henderson
            vaddr = load_bias + eppnt->p_vaddr;
1718 682674b8 Richard Henderson
            vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
1719 682674b8 Richard Henderson
            vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
1720 682674b8 Richard Henderson
1721 682674b8 Richard Henderson
            error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
1722 682674b8 Richard Henderson
                                elf_prot, MAP_PRIVATE | MAP_FIXED,
1723 8e62a717 Richard Henderson
                                image_fd, eppnt->p_offset - vaddr_po);
1724 09bfb054 bellard
            if (error == -1) {
1725 8e62a717 Richard Henderson
                goto exit_perror;
1726 09bfb054 bellard
            }
1727 09bfb054 bellard
1728 682674b8 Richard Henderson
            vaddr_ef = vaddr + eppnt->p_filesz;
1729 682674b8 Richard Henderson
            vaddr_em = vaddr + eppnt->p_memsz;
1730 31e31b8a bellard
1731 cf129f3a Richard Henderson
            /* If the load segment requests extra zeros (e.g. bss), map it.  */
1732 682674b8 Richard Henderson
            if (vaddr_ef < vaddr_em) {
1733 682674b8 Richard Henderson
                zero_bss(vaddr_ef, vaddr_em, elf_prot);
1734 cf129f3a Richard Henderson
            }
1735 8e62a717 Richard Henderson
1736 8e62a717 Richard Henderson
            /* Find the full program boundaries.  */
1737 8e62a717 Richard Henderson
            if (elf_prot & PROT_EXEC) {
1738 8e62a717 Richard Henderson
                if (vaddr < info->start_code) {
1739 8e62a717 Richard Henderson
                    info->start_code = vaddr;
1740 8e62a717 Richard Henderson
                }
1741 8e62a717 Richard Henderson
                if (vaddr_ef > info->end_code) {
1742 8e62a717 Richard Henderson
                    info->end_code = vaddr_ef;
1743 8e62a717 Richard Henderson
                }
1744 8e62a717 Richard Henderson
            }
1745 8e62a717 Richard Henderson
            if (elf_prot & PROT_WRITE) {
1746 8e62a717 Richard Henderson
                if (vaddr < info->start_data) {
1747 8e62a717 Richard Henderson
                    info->start_data = vaddr;
1748 8e62a717 Richard Henderson
                }
1749 8e62a717 Richard Henderson
                if (vaddr_ef > info->end_data) {
1750 8e62a717 Richard Henderson
                    info->end_data = vaddr_ef;
1751 8e62a717 Richard Henderson
                }
1752 8e62a717 Richard Henderson
                if (vaddr_em > info->brk) {
1753 8e62a717 Richard Henderson
                    info->brk = vaddr_em;
1754 8e62a717 Richard Henderson
                }
1755 8e62a717 Richard Henderson
            }
1756 bf858897 Richard Henderson
        } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
1757 bf858897 Richard Henderson
            char *interp_name;
1758 bf858897 Richard Henderson
1759 bf858897 Richard Henderson
            if (*pinterp_name) {
1760 bf858897 Richard Henderson
                errmsg = "Multiple PT_INTERP entries";
1761 bf858897 Richard Henderson
                goto exit_errmsg;
1762 bf858897 Richard Henderson
            }
1763 bf858897 Richard Henderson
            interp_name = malloc(eppnt->p_filesz);
1764 bf858897 Richard Henderson
            if (!interp_name) {
1765 bf858897 Richard Henderson
                goto exit_perror;
1766 bf858897 Richard Henderson
            }
1767 bf858897 Richard Henderson
1768 bf858897 Richard Henderson
            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
1769 bf858897 Richard Henderson
                memcpy(interp_name, bprm_buf + eppnt->p_offset,
1770 bf858897 Richard Henderson
                       eppnt->p_filesz);
1771 bf858897 Richard Henderson
            } else {
1772 bf858897 Richard Henderson
                retval = pread(image_fd, interp_name, eppnt->p_filesz,
1773 bf858897 Richard Henderson
                               eppnt->p_offset);
1774 bf858897 Richard Henderson
                if (retval != eppnt->p_filesz) {
1775 bf858897 Richard Henderson
                    goto exit_perror;
1776 bf858897 Richard Henderson
                }
1777 bf858897 Richard Henderson
            }
1778 bf858897 Richard Henderson
            if (interp_name[eppnt->p_filesz - 1] != 0) {
1779 bf858897 Richard Henderson
                errmsg = "Invalid PT_INTERP entry";
1780 bf858897 Richard Henderson
                goto exit_errmsg;
1781 bf858897 Richard Henderson
            }
1782 bf858897 Richard Henderson
            *pinterp_name = interp_name;
1783 d97ef72e Richard Henderson
        }
1784 682674b8 Richard Henderson
    }
1785 5fafdf24 ths
1786 8e62a717 Richard Henderson
    if (info->end_data == 0) {
1787 8e62a717 Richard Henderson
        info->start_data = info->end_code;
1788 8e62a717 Richard Henderson
        info->end_data = info->end_code;
1789 8e62a717 Richard Henderson
        info->brk = info->end_code;
1790 8e62a717 Richard Henderson
    }
1791 8e62a717 Richard Henderson
1792 682674b8 Richard Henderson
    if (qemu_log_enabled()) {
1793 8e62a717 Richard Henderson
        load_symbols(ehdr, image_fd, load_bias);
1794 682674b8 Richard Henderson
    }
1795 31e31b8a bellard
1796 8e62a717 Richard Henderson
    close(image_fd);
1797 8e62a717 Richard Henderson
    return;
1798 8e62a717 Richard Henderson
1799 8e62a717 Richard Henderson
 exit_read:
1800 8e62a717 Richard Henderson
    if (retval >= 0) {
1801 8e62a717 Richard Henderson
        errmsg = "Incomplete read of file header";
1802 8e62a717 Richard Henderson
        goto exit_errmsg;
1803 8e62a717 Richard Henderson
    }
1804 8e62a717 Richard Henderson
 exit_perror:
1805 8e62a717 Richard Henderson
    errmsg = strerror(errno);
1806 8e62a717 Richard Henderson
 exit_errmsg:
1807 8e62a717 Richard Henderson
    fprintf(stderr, "%s: %s\n", image_name, errmsg);
1808 8e62a717 Richard Henderson
    exit(-1);
1809 8e62a717 Richard Henderson
}
1810 8e62a717 Richard Henderson
1811 8e62a717 Richard Henderson
static void load_elf_interp(const char *filename, struct image_info *info,
1812 8e62a717 Richard Henderson
                            char bprm_buf[BPRM_BUF_SIZE])
1813 8e62a717 Richard Henderson
{
1814 8e62a717 Richard Henderson
    int fd, retval;
1815 8e62a717 Richard Henderson
1816 8e62a717 Richard Henderson
    fd = open(path(filename), O_RDONLY);
1817 8e62a717 Richard Henderson
    if (fd < 0) {
1818 8e62a717 Richard Henderson
        goto exit_perror;
1819 8e62a717 Richard Henderson
    }
1820 31e31b8a bellard
1821 8e62a717 Richard Henderson
    retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
1822 8e62a717 Richard Henderson
    if (retval < 0) {
1823 8e62a717 Richard Henderson
        goto exit_perror;
1824 8e62a717 Richard Henderson
    }
1825 8e62a717 Richard Henderson
    if (retval < BPRM_BUF_SIZE) {
1826 8e62a717 Richard Henderson
        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
1827 8e62a717 Richard Henderson
    }
1828 8e62a717 Richard Henderson
1829 bf858897 Richard Henderson
    load_elf_image(filename, fd, info, NULL, bprm_buf);
1830 8e62a717 Richard Henderson
    return;
1831 8e62a717 Richard Henderson
1832 8e62a717 Richard Henderson
 exit_perror:
1833 8e62a717 Richard Henderson
    fprintf(stderr, "%s: %s\n", filename, strerror(errno));
1834 8e62a717 Richard Henderson
    exit(-1);
1835 31e31b8a bellard
}
1836 31e31b8a bellard
1837 49918a75 pbrook
static int symfind(const void *s0, const void *s1)
1838 49918a75 pbrook
{
1839 c7c530cd Stefan Weil
    target_ulong addr = *(target_ulong *)s0;
1840 49918a75 pbrook
    struct elf_sym *sym = (struct elf_sym *)s1;
1841 49918a75 pbrook
    int result = 0;
1842 c7c530cd Stefan Weil
    if (addr < sym->st_value) {
1843 49918a75 pbrook
        result = -1;
1844 c7c530cd Stefan Weil
    } else if (addr >= sym->st_value + sym->st_size) {
1845 49918a75 pbrook
        result = 1;
1846 49918a75 pbrook
    }
1847 49918a75 pbrook
    return result;
1848 49918a75 pbrook
}
1849 49918a75 pbrook
1850 49918a75 pbrook
static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
1851 49918a75 pbrook
{
1852 49918a75 pbrook
#if ELF_CLASS == ELFCLASS32
1853 49918a75 pbrook
    struct elf_sym *syms = s->disas_symtab.elf32;
1854 49918a75 pbrook
#else
1855 49918a75 pbrook
    struct elf_sym *syms = s->disas_symtab.elf64;
1856 49918a75 pbrook
#endif
1857 49918a75 pbrook
1858 49918a75 pbrook
    // binary search
1859 49918a75 pbrook
    struct elf_sym *sym;
1860 49918a75 pbrook
1861 c7c530cd Stefan Weil
    sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
1862 7cba04f6 Blue Swirl
    if (sym != NULL) {
1863 49918a75 pbrook
        return s->disas_strtab + sym->st_name;
1864 49918a75 pbrook
    }
1865 49918a75 pbrook
1866 49918a75 pbrook
    return "";
1867 49918a75 pbrook
}
1868 49918a75 pbrook
1869 49918a75 pbrook
/* FIXME: This should use elf_ops.h  */
1870 49918a75 pbrook
static int symcmp(const void *s0, const void *s1)
1871 49918a75 pbrook
{
1872 49918a75 pbrook
    struct elf_sym *sym0 = (struct elf_sym *)s0;
1873 49918a75 pbrook
    struct elf_sym *sym1 = (struct elf_sym *)s1;
1874 49918a75 pbrook
    return (sym0->st_value < sym1->st_value)
1875 49918a75 pbrook
        ? -1
1876 49918a75 pbrook
        : ((sym0->st_value > sym1->st_value) ? 1 : 0);
1877 49918a75 pbrook
}
1878 49918a75 pbrook
1879 689f936f bellard
/* Best attempt to load symbols from this ELF object. */
1880 682674b8 Richard Henderson
static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
1881 689f936f bellard
{
1882 682674b8 Richard Henderson
    int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
1883 682674b8 Richard Henderson
    struct elf_shdr *shdr;
1884 b9475279 Cรฉdric VINCENT
    char *strings = NULL;
1885 b9475279 Cรฉdric VINCENT
    struct syminfo *s = NULL;
1886 b9475279 Cรฉdric VINCENT
    struct elf_sym *new_syms, *syms = NULL;
1887 689f936f bellard
1888 682674b8 Richard Henderson
    shnum = hdr->e_shnum;
1889 682674b8 Richard Henderson
    i = shnum * sizeof(struct elf_shdr);
1890 682674b8 Richard Henderson
    shdr = (struct elf_shdr *)alloca(i);
1891 682674b8 Richard Henderson
    if (pread(fd, shdr, i, hdr->e_shoff) != i) {
1892 682674b8 Richard Henderson
        return;
1893 682674b8 Richard Henderson
    }
1894 682674b8 Richard Henderson
1895 682674b8 Richard Henderson
    bswap_shdr(shdr, shnum);
1896 682674b8 Richard Henderson
    for (i = 0; i < shnum; ++i) {
1897 682674b8 Richard Henderson
        if (shdr[i].sh_type == SHT_SYMTAB) {
1898 682674b8 Richard Henderson
            sym_idx = i;
1899 682674b8 Richard Henderson
            str_idx = shdr[i].sh_link;
1900 49918a75 pbrook
            goto found;
1901 49918a75 pbrook
        }
1902 689f936f bellard
    }
1903 682674b8 Richard Henderson
1904 682674b8 Richard Henderson
    /* There will be no symbol table if the file was stripped.  */
1905 682674b8 Richard Henderson
    return;
1906 689f936f bellard
1907 689f936f bellard
 found:
1908 682674b8 Richard Henderson
    /* Now know where the strtab and symtab are.  Snarf them.  */
1909 e80cfcfc bellard
    s = malloc(sizeof(*s));
1910 682674b8 Richard Henderson
    if (!s) {
1911 b9475279 Cรฉdric VINCENT
        goto give_up;
1912 682674b8 Richard Henderson
    }
1913 5fafdf24 ths
1914 682674b8 Richard Henderson
    i = shdr[str_idx].sh_size;
1915 682674b8 Richard Henderson
    s->disas_strtab = strings = malloc(i);
1916 682674b8 Richard Henderson
    if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
1917 b9475279 Cรฉdric VINCENT
        goto give_up;
1918 682674b8 Richard Henderson
    }
1919 49918a75 pbrook
1920 682674b8 Richard Henderson
    i = shdr[sym_idx].sh_size;
1921 682674b8 Richard Henderson
    syms = malloc(i);
1922 682674b8 Richard Henderson
    if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
1923 b9475279 Cรฉdric VINCENT
        goto give_up;
1924 682674b8 Richard Henderson
    }
1925 31e31b8a bellard
1926 682674b8 Richard Henderson
    nsyms = i / sizeof(struct elf_sym);
1927 682674b8 Richard Henderson
    for (i = 0; i < nsyms; ) {
1928 49918a75 pbrook
        bswap_sym(syms + i);
1929 682674b8 Richard Henderson
        /* Throw away entries which we do not need.  */
1930 682674b8 Richard Henderson
        if (syms[i].st_shndx == SHN_UNDEF
1931 682674b8 Richard Henderson
            || syms[i].st_shndx >= SHN_LORESERVE
1932 682674b8 Richard Henderson
            || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
1933 682674b8 Richard Henderson
            if (i < --nsyms) {
1934 49918a75 pbrook
                syms[i] = syms[nsyms];
1935 49918a75 pbrook
            }
1936 682674b8 Richard Henderson
        } else {
1937 49918a75 pbrook
#if defined(TARGET_ARM) || defined (TARGET_MIPS)
1938 682674b8 Richard Henderson
            /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
1939 682674b8 Richard Henderson
            syms[i].st_value &= ~(target_ulong)1;
1940 0774bed1 blueswir1
#endif
1941 682674b8 Richard Henderson
            syms[i].st_value += load_bias;
1942 682674b8 Richard Henderson
            i++;
1943 682674b8 Richard Henderson
        }
1944 0774bed1 blueswir1
    }
1945 49918a75 pbrook
1946 b9475279 Cรฉdric VINCENT
    /* No "useful" symbol.  */
1947 b9475279 Cรฉdric VINCENT
    if (nsyms == 0) {
1948 b9475279 Cรฉdric VINCENT
        goto give_up;
1949 b9475279 Cรฉdric VINCENT
    }
1950 b9475279 Cรฉdric VINCENT
1951 5d5c9930 Richard Henderson
    /* Attempt to free the storage associated with the local symbols
1952 5d5c9930 Richard Henderson
       that we threw away.  Whether or not this has any effect on the
1953 5d5c9930 Richard Henderson
       memory allocation depends on the malloc implementation and how
1954 5d5c9930 Richard Henderson
       many symbols we managed to discard.  */
1955 8d79de6e Stefan Weil
    new_syms = realloc(syms, nsyms * sizeof(*syms));
1956 8d79de6e Stefan Weil
    if (new_syms == NULL) {
1957 b9475279 Cรฉdric VINCENT
        goto give_up;
1958 5d5c9930 Richard Henderson
    }
1959 8d79de6e Stefan Weil
    syms = new_syms;
1960 5d5c9930 Richard Henderson
1961 49918a75 pbrook
    qsort(syms, nsyms, sizeof(*syms), symcmp);
1962 689f936f bellard
1963 49918a75 pbrook
    s->disas_num_syms = nsyms;
1964 49918a75 pbrook
#if ELF_CLASS == ELFCLASS32
1965 49918a75 pbrook
    s->disas_symtab.elf32 = syms;
1966 49918a75 pbrook
#else
1967 49918a75 pbrook
    s->disas_symtab.elf64 = syms;
1968 49918a75 pbrook
#endif
1969 682674b8 Richard Henderson
    s->lookup_symbol = lookup_symbolxx;
1970 e80cfcfc bellard
    s->next = syminfos;
1971 e80cfcfc bellard
    syminfos = s;
1972 b9475279 Cรฉdric VINCENT
1973 b9475279 Cรฉdric VINCENT
    return;
1974 b9475279 Cรฉdric VINCENT
1975 b9475279 Cรฉdric VINCENT
give_up:
1976 b9475279 Cรฉdric VINCENT
    free(s);
1977 b9475279 Cรฉdric VINCENT
    free(strings);
1978 b9475279 Cรฉdric VINCENT
    free(syms);
1979 689f936f bellard
}
1980 31e31b8a bellard
1981 e5fe0c52 pbrook
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1982 e5fe0c52 pbrook
                    struct image_info * info)
1983 31e31b8a bellard
{
1984 8e62a717 Richard Henderson
    struct image_info interp_info;
1985 31e31b8a bellard
    struct elfhdr elf_ex;
1986 8e62a717 Richard Henderson
    char *elf_interpreter = NULL;
1987 31e31b8a bellard
1988 bf858897 Richard Henderson
    info->start_mmap = (abi_ulong)ELF_START_MMAP;
1989 bf858897 Richard Henderson
    info->mmap = 0;
1990 bf858897 Richard Henderson
    info->rss = 0;
1991 bf858897 Richard Henderson
1992 bf858897 Richard Henderson
    load_elf_image(bprm->filename, bprm->fd, info,
1993 bf858897 Richard Henderson
                   &elf_interpreter, bprm->buf);
1994 31e31b8a bellard
1995 bf858897 Richard Henderson
    /* ??? We need a copy of the elf header for passing to create_elf_tables.
1996 bf858897 Richard Henderson
       If we do nothing, we'll have overwritten this when we re-use bprm->buf
1997 bf858897 Richard Henderson
       when we load the interpreter.  */
1998 bf858897 Richard Henderson
    elf_ex = *(struct elfhdr *)bprm->buf;
1999 31e31b8a bellard
2000 e5fe0c52 pbrook
    bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
2001 e5fe0c52 pbrook
    bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
2002 e5fe0c52 pbrook
    bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
2003 e5fe0c52 pbrook
    if (!bprm->p) {
2004 bf858897 Richard Henderson
        fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
2005 bf858897 Richard Henderson
        exit(-1);
2006 379f6698 Paul Brook
    }
2007 379f6698 Paul Brook
2008 31e31b8a bellard
    /* Do this so that we can load the interpreter, if need be.  We will
2009 31e31b8a bellard
       change some of these later */
2010 31e31b8a bellard
    bprm->p = setup_arg_pages(bprm->p, bprm, info);
2011 31e31b8a bellard
2012 8e62a717 Richard Henderson
    if (elf_interpreter) {
2013 8e62a717 Richard Henderson
        load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
2014 31e31b8a bellard
2015 8e62a717 Richard Henderson
        /* If the program interpreter is one of these two, then assume
2016 8e62a717 Richard Henderson
           an iBCS2 image.  Otherwise assume a native linux image.  */
2017 8e62a717 Richard Henderson
2018 8e62a717 Richard Henderson
        if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
2019 8e62a717 Richard Henderson
            || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
2020 8e62a717 Richard Henderson
            info->personality = PER_SVR4;
2021 31e31b8a bellard
2022 8e62a717 Richard Henderson
            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
2023 8e62a717 Richard Henderson
               and some applications "depend" upon this behavior.  Since
2024 8e62a717 Richard Henderson
               we do not have the power to recompile these, we emulate
2025 8e62a717 Richard Henderson
               the SVr4 behavior.  Sigh.  */
2026 8e62a717 Richard Henderson
            target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
2027 8e62a717 Richard Henderson
                        MAP_FIXED | MAP_PRIVATE, -1, 0);
2028 8e62a717 Richard Henderson
        }
2029 31e31b8a bellard
    }
2030 31e31b8a bellard
2031 8e62a717 Richard Henderson
    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
2032 8e62a717 Richard Henderson
                                info, (elf_interpreter ? &interp_info : NULL));
2033 8e62a717 Richard Henderson
    info->start_stack = bprm->p;
2034 8e62a717 Richard Henderson
2035 8e62a717 Richard Henderson
    /* If we have an interpreter, set that as the program's entry point.
2036 8e78064e Richard Henderson
       Copy the load_bias as well, to help PPC64 interpret the entry
2037 8e62a717 Richard Henderson
       point as a function descriptor.  Do this after creating elf tables
2038 8e62a717 Richard Henderson
       so that we copy the original program entry point into the AUXV.  */
2039 8e62a717 Richard Henderson
    if (elf_interpreter) {
2040 8e78064e Richard Henderson
        info->load_bias = interp_info.load_bias;
2041 8e62a717 Richard Henderson
        info->entry = interp_info.entry;
2042 bf858897 Richard Henderson
        free(elf_interpreter);
2043 8e62a717 Richard Henderson
    }
2044 31e31b8a bellard
2045 edf8e2af Mika Westerberg
#ifdef USE_ELF_CORE_DUMP
2046 edf8e2af Mika Westerberg
    bprm->core_dump = &elf_core_dump;
2047 edf8e2af Mika Westerberg
#endif
2048 edf8e2af Mika Westerberg
2049 31e31b8a bellard
    return 0;
2050 31e31b8a bellard
}
2051 31e31b8a bellard
2052 edf8e2af Mika Westerberg
#ifdef USE_ELF_CORE_DUMP
2053 edf8e2af Mika Westerberg
/*
2054 edf8e2af Mika Westerberg
 * Definitions to generate Intel SVR4-like core files.
2055 a2547a13 Laurent Desnogues
 * These mostly have the same names as the SVR4 types with "target_elf_"
2056 edf8e2af Mika Westerberg
 * tacked on the front to prevent clashes with linux definitions,
2057 edf8e2af Mika Westerberg
 * and the typedef forms have been avoided.  This is mostly like
2058 edf8e2af Mika Westerberg
 * the SVR4 structure, but more Linuxy, with things that Linux does
2059 edf8e2af Mika Westerberg
 * not support and which gdb doesn't really use excluded.
2060 edf8e2af Mika Westerberg
 *
2061 edf8e2af Mika Westerberg
 * Fields we don't dump (their contents is zero) in linux-user qemu
2062 edf8e2af Mika Westerberg
 * are marked with XXX.
2063 edf8e2af Mika Westerberg
 *
2064 edf8e2af Mika Westerberg
 * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
2065 edf8e2af Mika Westerberg
 *
2066 edf8e2af Mika Westerberg
 * Porting ELF coredump for target is (quite) simple process.  First you
2067 dd0a3651 Nathan Froyd
 * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
2068 edf8e2af Mika Westerberg
 * the target resides):
2069 edf8e2af Mika Westerberg
 *
2070 edf8e2af Mika Westerberg
 * #define USE_ELF_CORE_DUMP
2071 edf8e2af Mika Westerberg
 *
2072 edf8e2af Mika Westerberg
 * Next you define type of register set used for dumping.  ELF specification
2073 edf8e2af Mika Westerberg
 * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
2074 edf8e2af Mika Westerberg
 *
2075 c227f099 Anthony Liguori
 * typedef <target_regtype> target_elf_greg_t;
2076 edf8e2af Mika Westerberg
 * #define ELF_NREG <number of registers>
2077 c227f099 Anthony Liguori
 * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
2078 edf8e2af Mika Westerberg
 *
2079 edf8e2af Mika Westerberg
 * Last step is to implement target specific function that copies registers
2080 edf8e2af Mika Westerberg
 * from given cpu into just specified register set.  Prototype is:
2081 edf8e2af Mika Westerberg
 *
2082 c227f099 Anthony Liguori
 * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
2083 9349b4f9 Andreas Fรคrber
 *                                const CPUArchState *env);
2084 edf8e2af Mika Westerberg
 *
2085 edf8e2af Mika Westerberg
 * Parameters:
2086 edf8e2af Mika Westerberg
 *     regs - copy register values into here (allocated and zeroed by caller)
2087 edf8e2af Mika Westerberg
 *     env - copy registers from here
2088 edf8e2af Mika Westerberg
 *
2089 edf8e2af Mika Westerberg
 * Example for ARM target is provided in this file.
2090 edf8e2af Mika Westerberg
 */
2091 edf8e2af Mika Westerberg
2092 edf8e2af Mika Westerberg
/* An ELF note in memory */
2093 edf8e2af Mika Westerberg
struct memelfnote {
2094 edf8e2af Mika Westerberg
    const char *name;
2095 edf8e2af Mika Westerberg
    size_t     namesz;
2096 edf8e2af Mika Westerberg
    size_t     namesz_rounded;
2097 edf8e2af Mika Westerberg
    int        type;
2098 edf8e2af Mika Westerberg
    size_t     datasz;
2099 80f5ce75 Laurent Vivier
    size_t     datasz_rounded;
2100 edf8e2af Mika Westerberg
    void       *data;
2101 edf8e2af Mika Westerberg
    size_t     notesz;
2102 edf8e2af Mika Westerberg
};
2103 edf8e2af Mika Westerberg
2104 a2547a13 Laurent Desnogues
struct target_elf_siginfo {
2105 80f5ce75 Laurent Vivier
    target_int  si_signo; /* signal number */
2106 80f5ce75 Laurent Vivier
    target_int  si_code;  /* extra code */
2107 80f5ce75 Laurent Vivier
    target_int  si_errno; /* errno */
2108 edf8e2af Mika Westerberg
};
2109 edf8e2af Mika Westerberg
2110 a2547a13 Laurent Desnogues
struct target_elf_prstatus {
2111 a2547a13 Laurent Desnogues
    struct target_elf_siginfo pr_info;      /* Info associated with signal */
2112 80f5ce75 Laurent Vivier
    target_short       pr_cursig;    /* Current signal */
2113 edf8e2af Mika Westerberg
    target_ulong       pr_sigpend;   /* XXX */
2114 edf8e2af Mika Westerberg
    target_ulong       pr_sighold;   /* XXX */
2115 c227f099 Anthony Liguori
    target_pid_t       pr_pid;
2116 c227f099 Anthony Liguori
    target_pid_t       pr_ppid;
2117 c227f099 Anthony Liguori
    target_pid_t       pr_pgrp;
2118 c227f099 Anthony Liguori
    target_pid_t       pr_sid;
2119 edf8e2af Mika Westerberg
    struct target_timeval pr_utime;  /* XXX User time */
2120 edf8e2af Mika Westerberg
    struct target_timeval pr_stime;  /* XXX System time */
2121 edf8e2af Mika Westerberg
    struct target_timeval pr_cutime; /* XXX Cumulative user time */
2122 edf8e2af Mika Westerberg
    struct target_timeval pr_cstime; /* XXX Cumulative system time */
2123 c227f099 Anthony Liguori
    target_elf_gregset_t      pr_reg;       /* GP registers */
2124 80f5ce75 Laurent Vivier
    target_int         pr_fpvalid;   /* XXX */
2125 edf8e2af Mika Westerberg
};
2126 edf8e2af Mika Westerberg
2127 edf8e2af Mika Westerberg
#define ELF_PRARGSZ     (80) /* Number of chars for args */
2128 edf8e2af Mika Westerberg
2129 a2547a13 Laurent Desnogues
struct target_elf_prpsinfo {
2130 edf8e2af Mika Westerberg
    char         pr_state;       /* numeric process state */
2131 edf8e2af Mika Westerberg
    char         pr_sname;       /* char for pr_state */
2132 edf8e2af Mika Westerberg
    char         pr_zomb;        /* zombie */
2133 edf8e2af Mika Westerberg
    char         pr_nice;        /* nice val */
2134 edf8e2af Mika Westerberg
    target_ulong pr_flag;        /* flags */
2135 c227f099 Anthony Liguori
    target_uid_t pr_uid;
2136 c227f099 Anthony Liguori
    target_gid_t pr_gid;
2137 c227f099 Anthony Liguori
    target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
2138 edf8e2af Mika Westerberg
    /* Lots missing */
2139 edf8e2af Mika Westerberg
    char    pr_fname[16];           /* filename of executable */
2140 edf8e2af Mika Westerberg
    char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
2141 edf8e2af Mika Westerberg
};
2142 edf8e2af Mika Westerberg
2143 edf8e2af Mika Westerberg
/* Here is the structure in which status of each thread is captured. */
2144 edf8e2af Mika Westerberg
struct elf_thread_status {
2145 72cf2d4f Blue Swirl
    QTAILQ_ENTRY(elf_thread_status)  ets_link;
2146 a2547a13 Laurent Desnogues
    struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
2147 edf8e2af Mika Westerberg
#if 0
2148 edf8e2af Mika Westerberg
    elf_fpregset_t fpu;             /* NT_PRFPREG */
2149 edf8e2af Mika Westerberg
    struct task_struct *thread;
2150 edf8e2af Mika Westerberg
    elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */
2151 edf8e2af Mika Westerberg
#endif
2152 edf8e2af Mika Westerberg
    struct memelfnote notes[1];
2153 edf8e2af Mika Westerberg
    int num_notes;
2154 edf8e2af Mika Westerberg
};
2155 edf8e2af Mika Westerberg
2156 edf8e2af Mika Westerberg
struct elf_note_info {
2157 edf8e2af Mika Westerberg
    struct memelfnote   *notes;
2158 a2547a13 Laurent Desnogues
    struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
2159 a2547a13 Laurent Desnogues
    struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
2160 edf8e2af Mika Westerberg
2161 72cf2d4f Blue Swirl
    QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
2162 edf8e2af Mika Westerberg
#if 0
2163 edf8e2af Mika Westerberg
    /*
2164 edf8e2af Mika Westerberg
     * Current version of ELF coredump doesn't support
2165 edf8e2af Mika Westerberg
     * dumping fp regs etc.
2166 edf8e2af Mika Westerberg
     */
2167 edf8e2af Mika Westerberg
    elf_fpregset_t *fpu;
2168 edf8e2af Mika Westerberg
    elf_fpxregset_t *xfpu;
2169 edf8e2af Mika Westerberg
    int thread_status_size;
2170 edf8e2af Mika Westerberg
#endif
2171 edf8e2af Mika Westerberg
    int notes_size;
2172 edf8e2af Mika Westerberg
    int numnote;
2173 edf8e2af Mika Westerberg
};
2174 edf8e2af Mika Westerberg
2175 edf8e2af Mika Westerberg
struct vm_area_struct {
2176 edf8e2af Mika Westerberg
    abi_ulong   vma_start;  /* start vaddr of memory region */
2177 edf8e2af Mika Westerberg
    abi_ulong   vma_end;    /* end vaddr of memory region */
2178 edf8e2af Mika Westerberg
    abi_ulong   vma_flags;  /* protection etc. flags for the region */
2179 72cf2d4f Blue Swirl
    QTAILQ_ENTRY(vm_area_struct) vma_link;
2180 edf8e2af Mika Westerberg
};
2181 edf8e2af Mika Westerberg
2182 edf8e2af Mika Westerberg
struct mm_struct {
2183 72cf2d4f Blue Swirl
    QTAILQ_HEAD(, vm_area_struct) mm_mmap;
2184 edf8e2af Mika Westerberg
    int mm_count;           /* number of mappings */
2185 edf8e2af Mika Westerberg
};
2186 edf8e2af Mika Westerberg
2187 edf8e2af Mika Westerberg
static struct mm_struct *vma_init(void);
2188 edf8e2af Mika Westerberg
static void vma_delete(struct mm_struct *);
2189 edf8e2af Mika Westerberg
static int vma_add_mapping(struct mm_struct *, abi_ulong,
2190 d97ef72e Richard Henderson
                           abi_ulong, abi_ulong);
2191 edf8e2af Mika Westerberg
static int vma_get_mapping_count(const struct mm_struct *);
2192 edf8e2af Mika Westerberg
static struct vm_area_struct *vma_first(const struct mm_struct *);
2193 edf8e2af Mika Westerberg
static struct vm_area_struct *vma_next(struct vm_area_struct *);
2194 edf8e2af Mika Westerberg
static abi_ulong vma_dump_size(const struct vm_area_struct *);
2195 b480d9b7 Paul Brook
static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
2196 d97ef72e Richard Henderson
                      unsigned long flags);
2197 edf8e2af Mika Westerberg
2198 edf8e2af Mika Westerberg
static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
2199 edf8e2af Mika Westerberg
static void fill_note(struct memelfnote *, const char *, int,
2200 d97ef72e Richard Henderson
                      unsigned int, void *);
2201 a2547a13 Laurent Desnogues
static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
2202 a2547a13 Laurent Desnogues
static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
2203 edf8e2af Mika Westerberg
static void fill_auxv_note(struct memelfnote *, const TaskState *);
2204 edf8e2af Mika Westerberg
static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
2205 edf8e2af Mika Westerberg
static size_t note_size(const struct memelfnote *);
2206 edf8e2af Mika Westerberg
static void free_note_info(struct elf_note_info *);
2207 9349b4f9 Andreas Fรคrber
static int fill_note_info(struct elf_note_info *, long, const CPUArchState *);
2208 9349b4f9 Andreas Fรคrber
static void fill_thread_info(struct elf_note_info *, const CPUArchState *);
2209 edf8e2af Mika Westerberg
static int core_dump_filename(const TaskState *, char *, size_t);
2210 edf8e2af Mika Westerberg
2211 edf8e2af Mika Westerberg
static int dump_write(int, const void *, size_t);
2212 edf8e2af Mika Westerberg
static int write_note(struct memelfnote *, int);
2213 edf8e2af Mika Westerberg
static int write_note_info(struct elf_note_info *, int);
2214 edf8e2af Mika Westerberg
2215 edf8e2af Mika Westerberg
#ifdef BSWAP_NEEDED
2216 a2547a13 Laurent Desnogues
static void bswap_prstatus(struct target_elf_prstatus *prstatus)
2217 edf8e2af Mika Westerberg
{
2218 edf8e2af Mika Westerberg
    prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
2219 edf8e2af Mika Westerberg
    prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
2220 edf8e2af Mika Westerberg
    prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
2221 edf8e2af Mika Westerberg
    prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
2222 edf8e2af Mika Westerberg
    prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
2223 edf8e2af Mika Westerberg
    prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
2224 edf8e2af Mika Westerberg
    prstatus->pr_pid = tswap32(prstatus->pr_pid);
2225 edf8e2af Mika Westerberg
    prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
2226 edf8e2af Mika Westerberg
    prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
2227 edf8e2af Mika Westerberg
    prstatus->pr_sid = tswap32(prstatus->pr_sid);
2228 edf8e2af Mika Westerberg
    /* cpu times are not filled, so we skip them */
2229 edf8e2af Mika Westerberg
    /* regs should be in correct format already */
2230 edf8e2af Mika Westerberg
    prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
2231 edf8e2af Mika Westerberg
}
2232 edf8e2af Mika Westerberg
2233 a2547a13 Laurent Desnogues
static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
2234 edf8e2af Mika Westerberg
{
2235 edf8e2af Mika Westerberg
    psinfo->pr_flag = tswapl(psinfo->pr_flag);
2236 edf8e2af Mika Westerberg
    psinfo->pr_uid = tswap16(psinfo->pr_uid);
2237 edf8e2af Mika Westerberg
    psinfo->pr_gid = tswap16(psinfo->pr_gid);
2238 edf8e2af Mika Westerberg
    psinfo->pr_pid = tswap32(psinfo->pr_pid);
2239 edf8e2af Mika Westerberg
    psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
2240 edf8e2af Mika Westerberg
    psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
2241 edf8e2af Mika Westerberg
    psinfo->pr_sid = tswap32(psinfo->pr_sid);
2242 edf8e2af Mika Westerberg
}
2243 991f8f0c Richard Henderson
2244 991f8f0c Richard Henderson
static void bswap_note(struct elf_note *en)
2245 991f8f0c Richard Henderson
{
2246 991f8f0c Richard Henderson
    bswap32s(&en->n_namesz);
2247 991f8f0c Richard Henderson
    bswap32s(&en->n_descsz);
2248 991f8f0c Richard Henderson
    bswap32s(&en->n_type);
2249 991f8f0c Richard Henderson
}
2250 991f8f0c Richard Henderson
#else
2251 991f8f0c Richard Henderson
static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
2252 991f8f0c Richard Henderson
static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
2253 991f8f0c Richard Henderson
static inline void bswap_note(struct elf_note *en) { }
2254 edf8e2af Mika Westerberg
#endif /* BSWAP_NEEDED */
2255 edf8e2af Mika Westerberg
2256 edf8e2af Mika Westerberg
/*
2257 edf8e2af Mika Westerberg
 * Minimal support for linux memory regions.  These are needed
2258 edf8e2af Mika Westerberg
 * when we are finding out what memory exactly belongs to
2259 edf8e2af Mika Westerberg
 * emulated process.  No locks needed here, as long as
2260 edf8e2af Mika Westerberg
 * thread that received the signal is stopped.
2261 edf8e2af Mika Westerberg
 */
2262 edf8e2af Mika Westerberg
2263 edf8e2af Mika Westerberg
static struct mm_struct *vma_init(void)
2264 edf8e2af Mika Westerberg
{
2265 edf8e2af Mika Westerberg
    struct mm_struct *mm;
2266 edf8e2af Mika Westerberg
2267 7267c094 Anthony Liguori
    if ((mm = g_malloc(sizeof (*mm))) == NULL)
2268 edf8e2af Mika Westerberg
        return (NULL);
2269 edf8e2af Mika Westerberg
2270 edf8e2af Mika Westerberg
    mm->mm_count = 0;
2271 72cf2d4f Blue Swirl
    QTAILQ_INIT(&mm->mm_mmap);
2272 edf8e2af Mika Westerberg
2273 edf8e2af Mika Westerberg
    return (mm);
2274 edf8e2af Mika Westerberg
}
2275 edf8e2af Mika Westerberg
2276 edf8e2af Mika Westerberg
static void vma_delete(struct mm_struct *mm)
2277 edf8e2af Mika Westerberg
{
2278 edf8e2af Mika Westerberg
    struct vm_area_struct *vma;
2279 edf8e2af Mika Westerberg
2280 edf8e2af Mika Westerberg
    while ((vma = vma_first(mm)) != NULL) {
2281 72cf2d4f Blue Swirl
        QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
2282 7267c094 Anthony Liguori
        g_free(vma);
2283 edf8e2af Mika Westerberg
    }
2284 7267c094 Anthony Liguori
    g_free(mm);
2285 edf8e2af Mika Westerberg
}
2286 edf8e2af Mika Westerberg
2287 edf8e2af Mika Westerberg
static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
2288 d97ef72e Richard Henderson
                           abi_ulong end, abi_ulong flags)
2289 edf8e2af Mika Westerberg
{
2290 edf8e2af Mika Westerberg
    struct vm_area_struct *vma;
2291 edf8e2af Mika Westerberg
2292 7267c094 Anthony Liguori
    if ((vma = g_malloc0(sizeof (*vma))) == NULL)
2293 edf8e2af Mika Westerberg
        return (-1);
2294 edf8e2af Mika Westerberg
2295 edf8e2af Mika Westerberg
    vma->vma_start = start;
2296 edf8e2af Mika Westerberg
    vma->vma_end = end;
2297 edf8e2af Mika Westerberg
    vma->vma_flags = flags;
2298 edf8e2af Mika Westerberg
2299 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
2300 edf8e2af Mika Westerberg
    mm->mm_count++;
2301 edf8e2af Mika Westerberg
2302 edf8e2af Mika Westerberg
    return (0);
2303 edf8e2af Mika Westerberg
}
2304 edf8e2af Mika Westerberg
2305 edf8e2af Mika Westerberg
static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2306 edf8e2af Mika Westerberg
{
2307 72cf2d4f Blue Swirl
    return (QTAILQ_FIRST(&mm->mm_mmap));
2308 edf8e2af Mika Westerberg
}
2309 edf8e2af Mika Westerberg
2310 edf8e2af Mika Westerberg
static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2311 edf8e2af Mika Westerberg
{
2312 72cf2d4f Blue Swirl
    return (QTAILQ_NEXT(vma, vma_link));
2313 edf8e2af Mika Westerberg
}
2314 edf8e2af Mika Westerberg
2315 edf8e2af Mika Westerberg
static int vma_get_mapping_count(const struct mm_struct *mm)
2316 edf8e2af Mika Westerberg
{
2317 edf8e2af Mika Westerberg
    return (mm->mm_count);
2318 edf8e2af Mika Westerberg
}
2319 edf8e2af Mika Westerberg
2320 edf8e2af Mika Westerberg
/*
2321 edf8e2af Mika Westerberg
 * Calculate file (dump) size of given memory region.
2322 edf8e2af Mika Westerberg
 */
2323 edf8e2af Mika Westerberg
static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2324 edf8e2af Mika Westerberg
{
2325 edf8e2af Mika Westerberg
    /* if we cannot even read the first page, skip it */
2326 edf8e2af Mika Westerberg
    if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2327 edf8e2af Mika Westerberg
        return (0);
2328 edf8e2af Mika Westerberg
2329 edf8e2af Mika Westerberg
    /*
2330 edf8e2af Mika Westerberg
     * Usually we don't dump executable pages as they contain
2331 edf8e2af Mika Westerberg
     * non-writable code that debugger can read directly from
2332 edf8e2af Mika Westerberg
     * target library etc.  However, thread stacks are marked
2333 edf8e2af Mika Westerberg
     * also executable so we read in first page of given region
2334 edf8e2af Mika Westerberg
     * and check whether it contains elf header.  If there is
2335 edf8e2af Mika Westerberg
     * no elf header, we dump it.
2336 edf8e2af Mika Westerberg
     */
2337 edf8e2af Mika Westerberg
    if (vma->vma_flags & PROT_EXEC) {
2338 edf8e2af Mika Westerberg
        char page[TARGET_PAGE_SIZE];
2339 edf8e2af Mika Westerberg
2340 edf8e2af Mika Westerberg
        copy_from_user(page, vma->vma_start, sizeof (page));
2341 edf8e2af Mika Westerberg
        if ((page[EI_MAG0] == ELFMAG0) &&
2342 edf8e2af Mika Westerberg
            (page[EI_MAG1] == ELFMAG1) &&
2343 edf8e2af Mika Westerberg
            (page[EI_MAG2] == ELFMAG2) &&
2344 edf8e2af Mika Westerberg
            (page[EI_MAG3] == ELFMAG3)) {
2345 edf8e2af Mika Westerberg
            /*
2346 edf8e2af Mika Westerberg
             * Mappings are possibly from ELF binary.  Don't dump
2347 edf8e2af Mika Westerberg
             * them.
2348 edf8e2af Mika Westerberg
             */
2349 edf8e2af Mika Westerberg
            return (0);
2350 edf8e2af Mika Westerberg
        }
2351 edf8e2af Mika Westerberg
    }
2352 edf8e2af Mika Westerberg
2353 edf8e2af Mika Westerberg
    return (vma->vma_end - vma->vma_start);
2354 edf8e2af Mika Westerberg
}
2355 edf8e2af Mika Westerberg
2356 b480d9b7 Paul Brook
static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
2357 d97ef72e Richard Henderson
                      unsigned long flags)
2358 edf8e2af Mika Westerberg
{
2359 edf8e2af Mika Westerberg
    struct mm_struct *mm = (struct mm_struct *)priv;
2360 edf8e2af Mika Westerberg
2361 edf8e2af Mika Westerberg
    vma_add_mapping(mm, start, end, flags);
2362 edf8e2af Mika Westerberg
    return (0);
2363 edf8e2af Mika Westerberg
}
2364 edf8e2af Mika Westerberg
2365 edf8e2af Mika Westerberg
static void fill_note(struct memelfnote *note, const char *name, int type,
2366 d97ef72e Richard Henderson
                      unsigned int sz, void *data)
2367 edf8e2af Mika Westerberg
{
2368 edf8e2af Mika Westerberg
    unsigned int namesz;
2369 edf8e2af Mika Westerberg
2370 edf8e2af Mika Westerberg
    namesz = strlen(name) + 1;
2371 edf8e2af Mika Westerberg
    note->name = name;
2372 edf8e2af Mika Westerberg
    note->namesz = namesz;
2373 edf8e2af Mika Westerberg
    note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2374 edf8e2af Mika Westerberg
    note->type = type;
2375 80f5ce75 Laurent Vivier
    note->datasz = sz;
2376 80f5ce75 Laurent Vivier
    note->datasz_rounded = roundup(sz, sizeof (int32_t));
2377 80f5ce75 Laurent Vivier
2378 edf8e2af Mika Westerberg
    note->data = data;
2379 edf8e2af Mika Westerberg
2380 edf8e2af Mika Westerberg
    /*
2381 edf8e2af Mika Westerberg
     * We calculate rounded up note size here as specified by
2382 edf8e2af Mika Westerberg
     * ELF document.
2383 edf8e2af Mika Westerberg
     */
2384 edf8e2af Mika Westerberg
    note->notesz = sizeof (struct elf_note) +
2385 80f5ce75 Laurent Vivier
        note->namesz_rounded + note->datasz_rounded;
2386 edf8e2af Mika Westerberg
}
2387 edf8e2af Mika Westerberg
2388 edf8e2af Mika Westerberg
static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
2389 d97ef72e Richard Henderson
                            uint32_t flags)
2390 edf8e2af Mika Westerberg
{
2391 edf8e2af Mika Westerberg
    (void) memset(elf, 0, sizeof(*elf));
2392 edf8e2af Mika Westerberg
2393 edf8e2af Mika Westerberg
    (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2394 edf8e2af Mika Westerberg
    elf->e_ident[EI_CLASS] = ELF_CLASS;
2395 edf8e2af Mika Westerberg
    elf->e_ident[EI_DATA] = ELF_DATA;
2396 edf8e2af Mika Westerberg
    elf->e_ident[EI_VERSION] = EV_CURRENT;
2397 edf8e2af Mika Westerberg
    elf->e_ident[EI_OSABI] = ELF_OSABI;
2398 edf8e2af Mika Westerberg
2399 edf8e2af Mika Westerberg
    elf->e_type = ET_CORE;
2400 edf8e2af Mika Westerberg
    elf->e_machine = machine;
2401 edf8e2af Mika Westerberg
    elf->e_version = EV_CURRENT;
2402 edf8e2af Mika Westerberg
    elf->e_phoff = sizeof(struct elfhdr);
2403 edf8e2af Mika Westerberg
    elf->e_flags = flags;
2404 edf8e2af Mika Westerberg
    elf->e_ehsize = sizeof(struct elfhdr);
2405 edf8e2af Mika Westerberg
    elf->e_phentsize = sizeof(struct elf_phdr);
2406 edf8e2af Mika Westerberg
    elf->e_phnum = segs;
2407 edf8e2af Mika Westerberg
2408 edf8e2af Mika Westerberg
    bswap_ehdr(elf);
2409 edf8e2af Mika Westerberg
}
2410 edf8e2af Mika Westerberg
2411 edf8e2af Mika Westerberg
static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2412 edf8e2af Mika Westerberg
{
2413 edf8e2af Mika Westerberg
    phdr->p_type = PT_NOTE;
2414 edf8e2af Mika Westerberg
    phdr->p_offset = offset;
2415 edf8e2af Mika Westerberg
    phdr->p_vaddr = 0;
2416 edf8e2af Mika Westerberg
    phdr->p_paddr = 0;
2417 edf8e2af Mika Westerberg
    phdr->p_filesz = sz;
2418 edf8e2af Mika Westerberg
    phdr->p_memsz = 0;
2419 edf8e2af Mika Westerberg
    phdr->p_flags = 0;
2420 edf8e2af Mika Westerberg
    phdr->p_align = 0;
2421 edf8e2af Mika Westerberg
2422 991f8f0c Richard Henderson
    bswap_phdr(phdr, 1);
2423 edf8e2af Mika Westerberg
}
2424 edf8e2af Mika Westerberg
2425 edf8e2af Mika Westerberg
static size_t note_size(const struct memelfnote *note)
2426 edf8e2af Mika Westerberg
{
2427 edf8e2af Mika Westerberg
    return (note->notesz);
2428 edf8e2af Mika Westerberg
}
2429 edf8e2af Mika Westerberg
2430 a2547a13 Laurent Desnogues
static void fill_prstatus(struct target_elf_prstatus *prstatus,
2431 d97ef72e Richard Henderson
                          const TaskState *ts, int signr)
2432 edf8e2af Mika Westerberg
{
2433 edf8e2af Mika Westerberg
    (void) memset(prstatus, 0, sizeof (*prstatus));
2434 edf8e2af Mika Westerberg
    prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2435 edf8e2af Mika Westerberg
    prstatus->pr_pid = ts->ts_tid;
2436 edf8e2af Mika Westerberg
    prstatus->pr_ppid = getppid();
2437 edf8e2af Mika Westerberg
    prstatus->pr_pgrp = getpgrp();
2438 edf8e2af Mika Westerberg
    prstatus->pr_sid = getsid(0);
2439 edf8e2af Mika Westerberg
2440 edf8e2af Mika Westerberg
    bswap_prstatus(prstatus);
2441 edf8e2af Mika Westerberg
}
2442 edf8e2af Mika Westerberg
2443 a2547a13 Laurent Desnogues
static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
2444 edf8e2af Mika Westerberg
{
2445 900cfbca Jim Meyering
    char *base_filename;
2446 edf8e2af Mika Westerberg
    unsigned int i, len;
2447 edf8e2af Mika Westerberg
2448 edf8e2af Mika Westerberg
    (void) memset(psinfo, 0, sizeof (*psinfo));
2449 edf8e2af Mika Westerberg
2450 edf8e2af Mika Westerberg
    len = ts->info->arg_end - ts->info->arg_start;
2451 edf8e2af Mika Westerberg
    if (len >= ELF_PRARGSZ)
2452 edf8e2af Mika Westerberg
        len = ELF_PRARGSZ - 1;
2453 edf8e2af Mika Westerberg
    if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2454 edf8e2af Mika Westerberg
        return -EFAULT;
2455 edf8e2af Mika Westerberg
    for (i = 0; i < len; i++)
2456 edf8e2af Mika Westerberg
        if (psinfo->pr_psargs[i] == 0)
2457 edf8e2af Mika Westerberg
            psinfo->pr_psargs[i] = ' ';
2458 edf8e2af Mika Westerberg
    psinfo->pr_psargs[len] = 0;
2459 edf8e2af Mika Westerberg
2460 edf8e2af Mika Westerberg
    psinfo->pr_pid = getpid();
2461 edf8e2af Mika Westerberg
    psinfo->pr_ppid = getppid();
2462 edf8e2af Mika Westerberg
    psinfo->pr_pgrp = getpgrp();
2463 edf8e2af Mika Westerberg
    psinfo->pr_sid = getsid(0);
2464 edf8e2af Mika Westerberg
    psinfo->pr_uid = getuid();
2465 edf8e2af Mika Westerberg
    psinfo->pr_gid = getgid();
2466 edf8e2af Mika Westerberg
2467 900cfbca Jim Meyering
    base_filename = g_path_get_basename(ts->bprm->filename);
2468 900cfbca Jim Meyering
    /*
2469 900cfbca Jim Meyering
     * Using strncpy here is fine: at max-length,
2470 900cfbca Jim Meyering
     * this field is not NUL-terminated.
2471 900cfbca Jim Meyering
     */
2472 edf8e2af Mika Westerberg
    (void) strncpy(psinfo->pr_fname, base_filename,
2473 d97ef72e Richard Henderson
                   sizeof(psinfo->pr_fname));
2474 edf8e2af Mika Westerberg
2475 900cfbca Jim Meyering
    g_free(base_filename);
2476 edf8e2af Mika Westerberg
    bswap_psinfo(psinfo);
2477 edf8e2af Mika Westerberg
    return (0);
2478 edf8e2af Mika Westerberg
}
2479 edf8e2af Mika Westerberg
2480 edf8e2af Mika Westerberg
static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2481 edf8e2af Mika Westerberg
{
2482 edf8e2af Mika Westerberg
    elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2483 edf8e2af Mika Westerberg
    elf_addr_t orig_auxv = auxv;
2484 edf8e2af Mika Westerberg
    void *ptr;
2485 125b0f55 Alexander Graf
    int len = ts->info->auxv_len;
2486 edf8e2af Mika Westerberg
2487 edf8e2af Mika Westerberg
    /*
2488 edf8e2af Mika Westerberg
     * Auxiliary vector is stored in target process stack.  It contains
2489 edf8e2af Mika Westerberg
     * {type, value} pairs that we need to dump into note.  This is not
2490 edf8e2af Mika Westerberg
     * strictly necessary but we do it here for sake of completeness.
2491 edf8e2af Mika Westerberg
     */
2492 edf8e2af Mika Westerberg
2493 edf8e2af Mika Westerberg
    /* read in whole auxv vector and copy it to memelfnote */
2494 edf8e2af Mika Westerberg
    ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2495 edf8e2af Mika Westerberg
    if (ptr != NULL) {
2496 edf8e2af Mika Westerberg
        fill_note(note, "CORE", NT_AUXV, len, ptr);
2497 edf8e2af Mika Westerberg
        unlock_user(ptr, auxv, len);
2498 edf8e2af Mika Westerberg
    }
2499 edf8e2af Mika Westerberg
}
2500 edf8e2af Mika Westerberg
2501 edf8e2af Mika Westerberg
/*
2502 edf8e2af Mika Westerberg
 * Constructs name of coredump file.  We have following convention
2503 edf8e2af Mika Westerberg
 * for the name:
2504 edf8e2af Mika Westerberg
 *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2505 edf8e2af Mika Westerberg
 *
2506 edf8e2af Mika Westerberg
 * Returns 0 in case of success, -1 otherwise (errno is set).
2507 edf8e2af Mika Westerberg
 */
2508 edf8e2af Mika Westerberg
static int core_dump_filename(const TaskState *ts, char *buf,
2509 d97ef72e Richard Henderson
                              size_t bufsize)
2510 edf8e2af Mika Westerberg
{
2511 edf8e2af Mika Westerberg
    char timestamp[64];
2512 edf8e2af Mika Westerberg
    char *filename = NULL;
2513 edf8e2af Mika Westerberg
    char *base_filename = NULL;
2514 edf8e2af Mika Westerberg
    struct timeval tv;
2515 edf8e2af Mika Westerberg
    struct tm tm;
2516 edf8e2af Mika Westerberg
2517 edf8e2af Mika Westerberg
    assert(bufsize >= PATH_MAX);
2518 edf8e2af Mika Westerberg
2519 edf8e2af Mika Westerberg
    if (gettimeofday(&tv, NULL) < 0) {
2520 edf8e2af Mika Westerberg
        (void) fprintf(stderr, "unable to get current timestamp: %s",
2521 d97ef72e Richard Henderson
                       strerror(errno));
2522 edf8e2af Mika Westerberg
        return (-1);
2523 edf8e2af Mika Westerberg
    }
2524 edf8e2af Mika Westerberg
2525 edf8e2af Mika Westerberg
    filename = strdup(ts->bprm->filename);
2526 edf8e2af Mika Westerberg
    base_filename = strdup(basename(filename));
2527 edf8e2af Mika Westerberg
    (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
2528 d97ef72e Richard Henderson
                    localtime_r(&tv.tv_sec, &tm));
2529 edf8e2af Mika Westerberg
    (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
2530 d97ef72e Richard Henderson
                    base_filename, timestamp, (int)getpid());
2531 edf8e2af Mika Westerberg
    free(base_filename);
2532 edf8e2af Mika Westerberg
    free(filename);
2533 edf8e2af Mika Westerberg
2534 edf8e2af Mika Westerberg
    return (0);
2535 edf8e2af Mika Westerberg
}
2536 edf8e2af Mika Westerberg
2537 edf8e2af Mika Westerberg
static int dump_write(int fd, const void *ptr, size_t size)
2538 edf8e2af Mika Westerberg
{
2539 edf8e2af Mika Westerberg
    const char *bufp = (const char *)ptr;
2540 edf8e2af Mika Westerberg
    ssize_t bytes_written, bytes_left;
2541 edf8e2af Mika Westerberg
    struct rlimit dumpsize;
2542 edf8e2af Mika Westerberg
    off_t pos;
2543 edf8e2af Mika Westerberg
2544 edf8e2af Mika Westerberg
    bytes_written = 0;
2545 edf8e2af Mika Westerberg
    getrlimit(RLIMIT_CORE, &dumpsize);
2546 edf8e2af Mika Westerberg
    if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2547 edf8e2af Mika Westerberg
        if (errno == ESPIPE) { /* not a seekable stream */
2548 edf8e2af Mika Westerberg
            bytes_left = size;
2549 edf8e2af Mika Westerberg
        } else {
2550 edf8e2af Mika Westerberg
            return pos;
2551 edf8e2af Mika Westerberg
        }
2552 edf8e2af Mika Westerberg
    } else {
2553 edf8e2af Mika Westerberg
        if (dumpsize.rlim_cur <= pos) {
2554 edf8e2af Mika Westerberg
            return -1;
2555 edf8e2af Mika Westerberg
        } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2556 edf8e2af Mika Westerberg
            bytes_left = size;
2557 edf8e2af Mika Westerberg
        } else {
2558 edf8e2af Mika Westerberg
            size_t limit_left=dumpsize.rlim_cur - pos;
2559 edf8e2af Mika Westerberg
            bytes_left = limit_left >= size ? size : limit_left ;
2560 edf8e2af Mika Westerberg
        }
2561 edf8e2af Mika Westerberg
    }
2562 edf8e2af Mika Westerberg
2563 edf8e2af Mika Westerberg
    /*
2564 edf8e2af Mika Westerberg
     * In normal conditions, single write(2) should do but
2565 edf8e2af Mika Westerberg
     * in case of socket etc. this mechanism is more portable.
2566 edf8e2af Mika Westerberg
     */
2567 edf8e2af Mika Westerberg
    do {
2568 edf8e2af Mika Westerberg
        bytes_written = write(fd, bufp, bytes_left);
2569 edf8e2af Mika Westerberg
        if (bytes_written < 0) {
2570 edf8e2af Mika Westerberg
            if (errno == EINTR)
2571 edf8e2af Mika Westerberg
                continue;
2572 edf8e2af Mika Westerberg
            return (-1);
2573 edf8e2af Mika Westerberg
        } else if (bytes_written == 0) { /* eof */
2574 edf8e2af Mika Westerberg
            return (-1);
2575 edf8e2af Mika Westerberg
        }
2576 edf8e2af Mika Westerberg
        bufp += bytes_written;
2577 edf8e2af Mika Westerberg
        bytes_left -= bytes_written;
2578 edf8e2af Mika Westerberg
    } while (bytes_left > 0);
2579 edf8e2af Mika Westerberg
2580 edf8e2af Mika Westerberg
    return (0);
2581 edf8e2af Mika Westerberg
}
2582 edf8e2af Mika Westerberg
2583 edf8e2af Mika Westerberg
static int write_note(struct memelfnote *men, int fd)
2584 edf8e2af Mika Westerberg
{
2585 edf8e2af Mika Westerberg
    struct elf_note en;
2586 edf8e2af Mika Westerberg
2587 edf8e2af Mika Westerberg
    en.n_namesz = men->namesz;
2588 edf8e2af Mika Westerberg
    en.n_type = men->type;
2589 edf8e2af Mika Westerberg
    en.n_descsz = men->datasz;
2590 edf8e2af Mika Westerberg
2591 edf8e2af Mika Westerberg
    bswap_note(&en);
2592 edf8e2af Mika Westerberg
2593 edf8e2af Mika Westerberg
    if (dump_write(fd, &en, sizeof(en)) != 0)
2594 edf8e2af Mika Westerberg
        return (-1);
2595 edf8e2af Mika Westerberg
    if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2596 edf8e2af Mika Westerberg
        return (-1);
2597 80f5ce75 Laurent Vivier
    if (dump_write(fd, men->data, men->datasz_rounded) != 0)
2598 edf8e2af Mika Westerberg
        return (-1);
2599 edf8e2af Mika Westerberg
2600 edf8e2af Mika Westerberg
    return (0);
2601 edf8e2af Mika Westerberg
}
2602 edf8e2af Mika Westerberg
2603 9349b4f9 Andreas Fรคrber
static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env)
2604 edf8e2af Mika Westerberg
{
2605 edf8e2af Mika Westerberg
    TaskState *ts = (TaskState *)env->opaque;
2606 edf8e2af Mika Westerberg
    struct elf_thread_status *ets;
2607 edf8e2af Mika Westerberg
2608 7267c094 Anthony Liguori
    ets = g_malloc0(sizeof (*ets));
2609 edf8e2af Mika Westerberg
    ets->num_notes = 1; /* only prstatus is dumped */
2610 edf8e2af Mika Westerberg
    fill_prstatus(&ets->prstatus, ts, 0);
2611 edf8e2af Mika Westerberg
    elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2612 edf8e2af Mika Westerberg
    fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
2613 d97ef72e Richard Henderson
              &ets->prstatus);
2614 edf8e2af Mika Westerberg
2615 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
2616 edf8e2af Mika Westerberg
2617 edf8e2af Mika Westerberg
    info->notes_size += note_size(&ets->notes[0]);
2618 edf8e2af Mika Westerberg
}
2619 edf8e2af Mika Westerberg
2620 edf8e2af Mika Westerberg
static int fill_note_info(struct elf_note_info *info,
2621 9349b4f9 Andreas Fรคrber
                          long signr, const CPUArchState *env)
2622 edf8e2af Mika Westerberg
{
2623 edf8e2af Mika Westerberg
#define NUMNOTES 3
2624 9349b4f9 Andreas Fรคrber
    CPUArchState *cpu = NULL;
2625 edf8e2af Mika Westerberg
    TaskState *ts = (TaskState *)env->opaque;
2626 edf8e2af Mika Westerberg
    int i;
2627 edf8e2af Mika Westerberg
2628 edf8e2af Mika Westerberg
    (void) memset(info, 0, sizeof (*info));
2629 edf8e2af Mika Westerberg
2630 72cf2d4f Blue Swirl
    QTAILQ_INIT(&info->thread_list);
2631 edf8e2af Mika Westerberg
2632 7267c094 Anthony Liguori
    info->notes = g_malloc0(NUMNOTES * sizeof (struct memelfnote));
2633 edf8e2af Mika Westerberg
    if (info->notes == NULL)
2634 edf8e2af Mika Westerberg
        return (-ENOMEM);
2635 7267c094 Anthony Liguori
    info->prstatus = g_malloc0(sizeof (*info->prstatus));
2636 edf8e2af Mika Westerberg
    if (info->prstatus == NULL)
2637 edf8e2af Mika Westerberg
        return (-ENOMEM);
2638 7267c094 Anthony Liguori
    info->psinfo = g_malloc0(sizeof (*info->psinfo));
2639 edf8e2af Mika Westerberg
    if (info->prstatus == NULL)
2640 edf8e2af Mika Westerberg
        return (-ENOMEM);
2641 edf8e2af Mika Westerberg
2642 edf8e2af Mika Westerberg
    /*
2643 edf8e2af Mika Westerberg
     * First fill in status (and registers) of current thread
2644 edf8e2af Mika Westerberg
     * including process info & aux vector.
2645 edf8e2af Mika Westerberg
     */
2646 edf8e2af Mika Westerberg
    fill_prstatus(info->prstatus, ts, signr);
2647 edf8e2af Mika Westerberg
    elf_core_copy_regs(&info->prstatus->pr_reg, env);
2648 edf8e2af Mika Westerberg
    fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
2649 d97ef72e Richard Henderson
              sizeof (*info->prstatus), info->prstatus);
2650 edf8e2af Mika Westerberg
    fill_psinfo(info->psinfo, ts);
2651 edf8e2af Mika Westerberg
    fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
2652 d97ef72e Richard Henderson
              sizeof (*info->psinfo), info->psinfo);
2653 edf8e2af Mika Westerberg
    fill_auxv_note(&info->notes[2], ts);
2654 edf8e2af Mika Westerberg
    info->numnote = 3;
2655 edf8e2af Mika Westerberg
2656 edf8e2af Mika Westerberg
    info->notes_size = 0;
2657 edf8e2af Mika Westerberg
    for (i = 0; i < info->numnote; i++)
2658 edf8e2af Mika Westerberg
        info->notes_size += note_size(&info->notes[i]);
2659 edf8e2af Mika Westerberg
2660 edf8e2af Mika Westerberg
    /* read and fill status of all threads */
2661 edf8e2af Mika Westerberg
    cpu_list_lock();
2662 edf8e2af Mika Westerberg
    for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2663 edf8e2af Mika Westerberg
        if (cpu == thread_env)
2664 edf8e2af Mika Westerberg
            continue;
2665 edf8e2af Mika Westerberg
        fill_thread_info(info, cpu);
2666 edf8e2af Mika Westerberg
    }
2667 edf8e2af Mika Westerberg
    cpu_list_unlock();
2668 edf8e2af Mika Westerberg
2669 edf8e2af Mika Westerberg
    return (0);
2670 edf8e2af Mika Westerberg
}
2671 edf8e2af Mika Westerberg
2672 edf8e2af Mika Westerberg
static void free_note_info(struct elf_note_info *info)
2673 edf8e2af Mika Westerberg
{
2674 edf8e2af Mika Westerberg
    struct elf_thread_status *ets;
2675 edf8e2af Mika Westerberg
2676 72cf2d4f Blue Swirl
    while (!QTAILQ_EMPTY(&info->thread_list)) {
2677 72cf2d4f Blue Swirl
        ets = QTAILQ_FIRST(&info->thread_list);
2678 72cf2d4f Blue Swirl
        QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
2679 7267c094 Anthony Liguori
        g_free(ets);
2680 edf8e2af Mika Westerberg
    }
2681 edf8e2af Mika Westerberg
2682 7267c094 Anthony Liguori
    g_free(info->prstatus);
2683 7267c094 Anthony Liguori
    g_free(info->psinfo);
2684 7267c094 Anthony Liguori
    g_free(info->notes);
2685 edf8e2af Mika Westerberg
}
2686 edf8e2af Mika Westerberg
2687 edf8e2af Mika Westerberg
static int write_note_info(struct elf_note_info *info, int fd)
2688 edf8e2af Mika Westerberg
{
2689 edf8e2af Mika Westerberg
    struct elf_thread_status *ets;
2690 edf8e2af Mika Westerberg
    int i, error = 0;
2691 edf8e2af Mika Westerberg
2692 edf8e2af Mika Westerberg
    /* write prstatus, psinfo and auxv for current thread */
2693 edf8e2af Mika Westerberg
    for (i = 0; i < info->numnote; i++)
2694 edf8e2af Mika Westerberg
        if ((error = write_note(&info->notes[i], fd)) != 0)
2695 edf8e2af Mika Westerberg
            return (error);
2696 edf8e2af Mika Westerberg
2697 edf8e2af Mika Westerberg
    /* write prstatus for each thread */
2698 edf8e2af Mika Westerberg
    for (ets = info->thread_list.tqh_first; ets != NULL;
2699 d97ef72e Richard Henderson
         ets = ets->ets_link.tqe_next) {
2700 edf8e2af Mika Westerberg
        if ((error = write_note(&ets->notes[0], fd)) != 0)
2701 edf8e2af Mika Westerberg
            return (error);
2702 edf8e2af Mika Westerberg
    }
2703 edf8e2af Mika Westerberg
2704 edf8e2af Mika Westerberg
    return (0);
2705 edf8e2af Mika Westerberg
}
2706 edf8e2af Mika Westerberg
2707 edf8e2af Mika Westerberg
/*
2708 edf8e2af Mika Westerberg
 * Write out ELF coredump.
2709 edf8e2af Mika Westerberg
 *
2710 edf8e2af Mika Westerberg
 * See documentation of ELF object file format in:
2711 edf8e2af Mika Westerberg
 * http://www.caldera.com/developers/devspecs/gabi41.pdf
2712 edf8e2af Mika Westerberg
 *
2713 edf8e2af Mika Westerberg
 * Coredump format in linux is following:
2714 edf8e2af Mika Westerberg
 *
2715 edf8e2af Mika Westerberg
 * 0   +----------------------+         \
2716 edf8e2af Mika Westerberg
 *     | ELF header           | ET_CORE  |
2717 edf8e2af Mika Westerberg
 *     +----------------------+          |
2718 edf8e2af Mika Westerberg
 *     | ELF program headers  |          |--- headers
2719 edf8e2af Mika Westerberg
 *     | - NOTE section       |          |
2720 edf8e2af Mika Westerberg
 *     | - PT_LOAD sections   |          |
2721 edf8e2af Mika Westerberg
 *     +----------------------+         /
2722 edf8e2af Mika Westerberg
 *     | NOTEs:               |
2723 edf8e2af Mika Westerberg
 *     | - NT_PRSTATUS        |
2724 edf8e2af Mika Westerberg
 *     | - NT_PRSINFO         |
2725 edf8e2af Mika Westerberg
 *     | - NT_AUXV            |
2726 edf8e2af Mika Westerberg
 *     +----------------------+ <-- aligned to target page
2727 edf8e2af Mika Westerberg
 *     | Process memory dump  |
2728 edf8e2af Mika Westerberg
 *     :                      :
2729 edf8e2af Mika Westerberg
 *     .                      .
2730 edf8e2af Mika Westerberg
 *     :                      :
2731 edf8e2af Mika Westerberg
 *     |                      |
2732 edf8e2af Mika Westerberg
 *     +----------------------+
2733 edf8e2af Mika Westerberg
 *
2734 edf8e2af Mika Westerberg
 * NT_PRSTATUS -> struct elf_prstatus (per thread)
2735 edf8e2af Mika Westerberg
 * NT_PRSINFO  -> struct elf_prpsinfo
2736 edf8e2af Mika Westerberg
 * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2737 edf8e2af Mika Westerberg
 *
2738 edf8e2af Mika Westerberg
 * Format follows System V format as close as possible.  Current
2739 edf8e2af Mika Westerberg
 * version limitations are as follows:
2740 edf8e2af Mika Westerberg
 *     - no floating point registers are dumped
2741 edf8e2af Mika Westerberg
 *
2742 edf8e2af Mika Westerberg
 * Function returns 0 in case of success, negative errno otherwise.
2743 edf8e2af Mika Westerberg
 *
2744 edf8e2af Mika Westerberg
 * TODO: make this work also during runtime: it should be
2745 edf8e2af Mika Westerberg
 * possible to force coredump from running process and then
2746 edf8e2af Mika Westerberg
 * continue processing.  For example qemu could set up SIGUSR2
2747 edf8e2af Mika Westerberg
 * handler (provided that target process haven't registered
2748 edf8e2af Mika Westerberg
 * handler for that) that does the dump when signal is received.
2749 edf8e2af Mika Westerberg
 */
2750 9349b4f9 Andreas Fรคrber
static int elf_core_dump(int signr, const CPUArchState *env)
2751 edf8e2af Mika Westerberg
{
2752 edf8e2af Mika Westerberg
    const TaskState *ts = (const TaskState *)env->opaque;
2753 edf8e2af Mika Westerberg
    struct vm_area_struct *vma = NULL;
2754 edf8e2af Mika Westerberg
    char corefile[PATH_MAX];
2755 edf8e2af Mika Westerberg
    struct elf_note_info info;
2756 edf8e2af Mika Westerberg
    struct elfhdr elf;
2757 edf8e2af Mika Westerberg
    struct elf_phdr phdr;
2758 edf8e2af Mika Westerberg
    struct rlimit dumpsize;
2759 edf8e2af Mika Westerberg
    struct mm_struct *mm = NULL;
2760 edf8e2af Mika Westerberg
    off_t offset = 0, data_offset = 0;
2761 edf8e2af Mika Westerberg
    int segs = 0;
2762 edf8e2af Mika Westerberg
    int fd = -1;
2763 edf8e2af Mika Westerberg
2764 edf8e2af Mika Westerberg
    errno = 0;
2765 edf8e2af Mika Westerberg
    getrlimit(RLIMIT_CORE, &dumpsize);
2766 edf8e2af Mika Westerberg
    if (dumpsize.rlim_cur == 0)
2767 d97ef72e Richard Henderson
        return 0;
2768 edf8e2af Mika Westerberg
2769 edf8e2af Mika Westerberg
    if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2770 edf8e2af Mika Westerberg
        return (-errno);
2771 edf8e2af Mika Westerberg
2772 edf8e2af Mika Westerberg
    if ((fd = open(corefile, O_WRONLY | O_CREAT,
2773 d97ef72e Richard Henderson
                   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
2774 edf8e2af Mika Westerberg
        return (-errno);
2775 edf8e2af Mika Westerberg
2776 edf8e2af Mika Westerberg
    /*
2777 edf8e2af Mika Westerberg
     * Walk through target process memory mappings and
2778 edf8e2af Mika Westerberg
     * set up structure containing this information.  After
2779 edf8e2af Mika Westerberg
     * this point vma_xxx functions can be used.
2780 edf8e2af Mika Westerberg
     */
2781 edf8e2af Mika Westerberg
    if ((mm = vma_init()) == NULL)
2782 edf8e2af Mika Westerberg
        goto out;
2783 edf8e2af Mika Westerberg
2784 edf8e2af Mika Westerberg
    walk_memory_regions(mm, vma_walker);
2785 edf8e2af Mika Westerberg
    segs = vma_get_mapping_count(mm);
2786 edf8e2af Mika Westerberg
2787 edf8e2af Mika Westerberg
    /*
2788 edf8e2af Mika Westerberg
     * Construct valid coredump ELF header.  We also
2789 edf8e2af Mika Westerberg
     * add one more segment for notes.
2790 edf8e2af Mika Westerberg
     */
2791 edf8e2af Mika Westerberg
    fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2792 edf8e2af Mika Westerberg
    if (dump_write(fd, &elf, sizeof (elf)) != 0)
2793 edf8e2af Mika Westerberg
        goto out;
2794 edf8e2af Mika Westerberg
2795 edf8e2af Mika Westerberg
    /* fill in in-memory version of notes */
2796 edf8e2af Mika Westerberg
    if (fill_note_info(&info, signr, env) < 0)
2797 edf8e2af Mika Westerberg
        goto out;
2798 edf8e2af Mika Westerberg
2799 edf8e2af Mika Westerberg
    offset += sizeof (elf);                             /* elf header */
2800 edf8e2af Mika Westerberg
    offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */
2801 edf8e2af Mika Westerberg
2802 edf8e2af Mika Westerberg
    /* write out notes program header */
2803 edf8e2af Mika Westerberg
    fill_elf_note_phdr(&phdr, info.notes_size, offset);
2804 edf8e2af Mika Westerberg
2805 edf8e2af Mika Westerberg
    offset += info.notes_size;
2806 edf8e2af Mika Westerberg
    if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2807 edf8e2af Mika Westerberg
        goto out;
2808 edf8e2af Mika Westerberg
2809 edf8e2af Mika Westerberg
    /*
2810 edf8e2af Mika Westerberg
     * ELF specification wants data to start at page boundary so
2811 edf8e2af Mika Westerberg
     * we align it here.
2812 edf8e2af Mika Westerberg
     */
2813 80f5ce75 Laurent Vivier
    data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
2814 edf8e2af Mika Westerberg
2815 edf8e2af Mika Westerberg
    /*
2816 edf8e2af Mika Westerberg
     * Write program headers for memory regions mapped in
2817 edf8e2af Mika Westerberg
     * the target process.
2818 edf8e2af Mika Westerberg
     */
2819 edf8e2af Mika Westerberg
    for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2820 edf8e2af Mika Westerberg
        (void) memset(&phdr, 0, sizeof (phdr));
2821 edf8e2af Mika Westerberg
2822 edf8e2af Mika Westerberg
        phdr.p_type = PT_LOAD;
2823 edf8e2af Mika Westerberg
        phdr.p_offset = offset;
2824 edf8e2af Mika Westerberg
        phdr.p_vaddr = vma->vma_start;
2825 edf8e2af Mika Westerberg
        phdr.p_paddr = 0;
2826 edf8e2af Mika Westerberg
        phdr.p_filesz = vma_dump_size(vma);
2827 edf8e2af Mika Westerberg
        offset += phdr.p_filesz;
2828 edf8e2af Mika Westerberg
        phdr.p_memsz = vma->vma_end - vma->vma_start;
2829 edf8e2af Mika Westerberg
        phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2830 edf8e2af Mika Westerberg
        if (vma->vma_flags & PROT_WRITE)
2831 edf8e2af Mika Westerberg
            phdr.p_flags |= PF_W;
2832 edf8e2af Mika Westerberg
        if (vma->vma_flags & PROT_EXEC)
2833 edf8e2af Mika Westerberg
            phdr.p_flags |= PF_X;
2834 edf8e2af Mika Westerberg
        phdr.p_align = ELF_EXEC_PAGESIZE;
2835 edf8e2af Mika Westerberg
2836 80f5ce75 Laurent Vivier
        bswap_phdr(&phdr, 1);
2837 edf8e2af Mika Westerberg
        dump_write(fd, &phdr, sizeof (phdr));
2838 edf8e2af Mika Westerberg
    }
2839 edf8e2af Mika Westerberg
2840 edf8e2af Mika Westerberg
    /*
2841 edf8e2af Mika Westerberg
     * Next we write notes just after program headers.  No
2842 edf8e2af Mika Westerberg
     * alignment needed here.
2843 edf8e2af Mika Westerberg
     */
2844 edf8e2af Mika Westerberg
    if (write_note_info(&info, fd) < 0)
2845 edf8e2af Mika Westerberg
        goto out;
2846 edf8e2af Mika Westerberg
2847 edf8e2af Mika Westerberg
    /* align data to page boundary */
2848 edf8e2af Mika Westerberg
    if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2849 edf8e2af Mika Westerberg
        goto out;
2850 edf8e2af Mika Westerberg
2851 edf8e2af Mika Westerberg
    /*
2852 edf8e2af Mika Westerberg
     * Finally we can dump process memory into corefile as well.
2853 edf8e2af Mika Westerberg
     */
2854 edf8e2af Mika Westerberg
    for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2855 edf8e2af Mika Westerberg
        abi_ulong addr;
2856 edf8e2af Mika Westerberg
        abi_ulong end;
2857 edf8e2af Mika Westerberg
2858 edf8e2af Mika Westerberg
        end = vma->vma_start + vma_dump_size(vma);
2859 edf8e2af Mika Westerberg
2860 edf8e2af Mika Westerberg
        for (addr = vma->vma_start; addr < end;
2861 d97ef72e Richard Henderson
             addr += TARGET_PAGE_SIZE) {
2862 edf8e2af Mika Westerberg
            char page[TARGET_PAGE_SIZE];
2863 edf8e2af Mika Westerberg
            int error;
2864 edf8e2af Mika Westerberg
2865 edf8e2af Mika Westerberg
            /*
2866 edf8e2af Mika Westerberg
             *  Read in page from target process memory and
2867 edf8e2af Mika Westerberg
             *  write it to coredump file.
2868 edf8e2af Mika Westerberg
             */
2869 edf8e2af Mika Westerberg
            error = copy_from_user(page, addr, sizeof (page));
2870 edf8e2af Mika Westerberg
            if (error != 0) {
2871 49995e17 Aurelien Jarno
                (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
2872 d97ef72e Richard Henderson
                               addr);
2873 edf8e2af Mika Westerberg
                errno = -error;
2874 edf8e2af Mika Westerberg
                goto out;
2875 edf8e2af Mika Westerberg
            }
2876 edf8e2af Mika Westerberg
            if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2877 edf8e2af Mika Westerberg
                goto out;
2878 edf8e2af Mika Westerberg
        }
2879 edf8e2af Mika Westerberg
    }
2880 edf8e2af Mika Westerberg
2881 d97ef72e Richard Henderson
 out:
2882 edf8e2af Mika Westerberg
    free_note_info(&info);
2883 edf8e2af Mika Westerberg
    if (mm != NULL)
2884 edf8e2af Mika Westerberg
        vma_delete(mm);
2885 edf8e2af Mika Westerberg
    (void) close(fd);
2886 edf8e2af Mika Westerberg
2887 edf8e2af Mika Westerberg
    if (errno != 0)
2888 edf8e2af Mika Westerberg
        return (-errno);
2889 edf8e2af Mika Westerberg
    return (0);
2890 edf8e2af Mika Westerberg
}
2891 edf8e2af Mika Westerberg
#endif /* USE_ELF_CORE_DUMP */
2892 edf8e2af Mika Westerberg
2893 e5fe0c52 pbrook
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2894 e5fe0c52 pbrook
{
2895 e5fe0c52 pbrook
    init_thread(regs, infop);
2896 e5fe0c52 pbrook
}