blob: 61167cdcb82b6be4601d2290f126eae54893c81d [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/* This is the Linux kernel elf-loading code, ported into user space */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002#include <sys/time.h>
3#include <sys/param.h>
bellard31e31b82003-02-18 22:55:36 +00004
5#include <stdio.h>
6#include <sys/types.h>
7#include <fcntl.h>
bellard31e31b82003-02-18 22:55:36 +00008#include <errno.h>
9#include <unistd.h>
10#include <sys/mman.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030011#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000012#include <stdlib.h>
13#include <string.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030014#include <time.h>
bellard31e31b82003-02-18 22:55:36 +000015
bellard3ef693a2003-03-23 20:17:16 +000016#include "qemu.h"
bellard689f9362003-04-29 20:40:07 +000017#include "disas.h"
bellard31e31b82003-02-18 22:55:36 +000018
malce58ffeb2009-01-14 18:39:49 +000019#ifdef _ARCH_PPC64
malca6cc84f2008-08-20 22:39:28 +000020#undef ARCH_DLINFO
21#undef ELF_PLATFORM
22#undef ELF_HWCAP
23#undef ELF_CLASS
24#undef ELF_DATA
25#undef ELF_ARCH
26#endif
27
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030028#define ELF_OSABI ELFOSABI_SYSV
29
blueswir1cb33da52007-10-09 16:34:29 +000030/* from personality.h */
31
32/*
33 * Flags for bug emulation.
34 *
35 * These occupy the top three bytes.
36 */
37enum {
Richard Hendersond97ef722010-07-27 10:25:29 -070038 ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
39 FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to
40 descriptors (signal handling) */
41 MMAP_PAGE_ZERO = 0x0100000,
42 ADDR_COMPAT_LAYOUT = 0x0200000,
43 READ_IMPLIES_EXEC = 0x0400000,
44 ADDR_LIMIT_32BIT = 0x0800000,
45 SHORT_INODE = 0x1000000,
46 WHOLE_SECONDS = 0x2000000,
47 STICKY_TIMEOUTS = 0x4000000,
48 ADDR_LIMIT_3GB = 0x8000000,
blueswir1cb33da52007-10-09 16:34:29 +000049};
50
51/*
52 * Personality types.
53 *
54 * These go in the low byte. Avoid using the top bit, it will
55 * conflict with error returns.
56 */
57enum {
Richard Hendersond97ef722010-07-27 10:25:29 -070058 PER_LINUX = 0x0000,
59 PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
60 PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
61 PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
62 PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
63 PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
64 PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
65 PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
66 PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
67 PER_BSD = 0x0006,
68 PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
69 PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
70 PER_LINUX32 = 0x0008,
71 PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
72 PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
73 PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
74 PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
75 PER_RISCOS = 0x000c,
76 PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
77 PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
78 PER_OSF4 = 0x000f, /* OSF/1 v4 */
79 PER_HPUX = 0x0010,
80 PER_MASK = 0x00ff,
blueswir1cb33da52007-10-09 16:34:29 +000081};
82
83/*
84 * Return the base personality without flags.
85 */
Richard Hendersond97ef722010-07-27 10:25:29 -070086#define personality(pers) (pers & PER_MASK)
blueswir1cb33da52007-10-09 16:34:29 +000087
bellard83fb7ad2004-07-05 21:25:26 +000088/* this flag is uneffective under linux too, should be deleted */
89#ifndef MAP_DENYWRITE
90#define MAP_DENYWRITE 0
91#endif
92
93/* should probably go in elf.h */
94#ifndef ELIBBAD
95#define ELIBBAD 80
96#endif
97
Richard Henderson28490232010-07-27 10:25:31 -070098#ifdef TARGET_WORDS_BIGENDIAN
99#define ELF_DATA ELFDATA2MSB
100#else
101#define ELF_DATA ELFDATA2LSB
102#endif
103
Richard Hendersond97ef722010-07-27 10:25:29 -0700104typedef target_ulong target_elf_greg_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800105#ifdef USE_UID16
Richard Hendersond97ef722010-07-27 10:25:29 -0700106typedef uint16_t target_uid_t;
107typedef uint16_t target_gid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800108#else
Richard Hendersond97ef722010-07-27 10:25:29 -0700109typedef uint32_t target_uid_t;
110typedef uint32_t target_gid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800111#endif
Richard Hendersond97ef722010-07-27 10:25:29 -0700112typedef int32_t target_pid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800113
bellard30ac07d2003-04-07 21:33:03 +0000114#ifdef TARGET_I386
115
bellard15338fd2005-11-26 11:41:16 +0000116#define ELF_PLATFORM get_elf_platform()
117
118static const char *get_elf_platform(void)
119{
120 static char elf_platform[] = "i386";
pbrookd5975362008-06-07 20:50:51 +0000121 int family = (thread_env->cpuid_version >> 8) & 0xff;
bellard15338fd2005-11-26 11:41:16 +0000122 if (family > 6)
123 family = 6;
124 if (family >= 3)
125 elf_platform[1] = '0' + family;
126 return elf_platform;
127}
128
129#define ELF_HWCAP get_elf_hwcap()
130
131static uint32_t get_elf_hwcap(void)
132{
Richard Hendersond97ef722010-07-27 10:25:29 -0700133 return thread_env->cpuid_features;
bellard15338fd2005-11-26 11:41:16 +0000134}
135
j_mayer84409dd2007-04-06 08:56:50 +0000136#ifdef TARGET_X86_64
137#define ELF_START_MMAP 0x2aaaaab000ULL
138#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
139
140#define ELF_CLASS ELFCLASS64
j_mayer84409dd2007-04-06 08:56:50 +0000141#define ELF_ARCH EM_X86_64
142
143static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
144{
145 regs->rax = 0;
146 regs->rsp = infop->start_stack;
147 regs->rip = infop->entry;
148}
149
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300150#define ELF_NREG 27
Anthony Liguoric227f092009-10-01 16:12:16 -0500151typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300152
153/*
154 * Note that ELF_NREG should be 29 as there should be place for
155 * TRAPNO and ERR "registers" as well but linux doesn't dump
156 * those.
157 *
158 * See linux kernel: arch/x86/include/asm/elf.h
159 */
Anthony Liguoric227f092009-10-01 16:12:16 -0500160static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300161{
162 (*regs)[0] = env->regs[15];
163 (*regs)[1] = env->regs[14];
164 (*regs)[2] = env->regs[13];
165 (*regs)[3] = env->regs[12];
166 (*regs)[4] = env->regs[R_EBP];
167 (*regs)[5] = env->regs[R_EBX];
168 (*regs)[6] = env->regs[11];
169 (*regs)[7] = env->regs[10];
170 (*regs)[8] = env->regs[9];
171 (*regs)[9] = env->regs[8];
172 (*regs)[10] = env->regs[R_EAX];
173 (*regs)[11] = env->regs[R_ECX];
174 (*regs)[12] = env->regs[R_EDX];
175 (*regs)[13] = env->regs[R_ESI];
176 (*regs)[14] = env->regs[R_EDI];
177 (*regs)[15] = env->regs[R_EAX]; /* XXX */
178 (*regs)[16] = env->eip;
179 (*regs)[17] = env->segs[R_CS].selector & 0xffff;
180 (*regs)[18] = env->eflags;
181 (*regs)[19] = env->regs[R_ESP];
182 (*regs)[20] = env->segs[R_SS].selector & 0xffff;
183 (*regs)[21] = env->segs[R_FS].selector & 0xffff;
184 (*regs)[22] = env->segs[R_GS].selector & 0xffff;
185 (*regs)[23] = env->segs[R_DS].selector & 0xffff;
186 (*regs)[24] = env->segs[R_ES].selector & 0xffff;
187 (*regs)[25] = env->segs[R_FS].selector & 0xffff;
188 (*regs)[26] = env->segs[R_GS].selector & 0xffff;
189}
190
j_mayer84409dd2007-04-06 08:56:50 +0000191#else
192
bellard30ac07d2003-04-07 21:33:03 +0000193#define ELF_START_MMAP 0x80000000
194
bellard30ac07d2003-04-07 21:33:03 +0000195/*
196 * This is used to ensure we don't load something for the wrong architecture.
197 */
198#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
199
200/*
201 * These are used to set parameters in the core dumps.
202 */
Richard Hendersond97ef722010-07-27 10:25:29 -0700203#define ELF_CLASS ELFCLASS32
Richard Hendersond97ef722010-07-27 10:25:29 -0700204#define ELF_ARCH EM_386
bellard30ac07d2003-04-07 21:33:03 +0000205
Richard Hendersond97ef722010-07-27 10:25:29 -0700206static inline void init_thread(struct target_pt_regs *regs,
207 struct image_info *infop)
bellardb346ff42003-06-15 20:05:50 +0000208{
209 regs->esp = infop->start_stack;
210 regs->eip = infop->entry;
pbrooke5fe0c52006-06-11 13:32:59 +0000211
212 /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
213 starts %edx contains a pointer to a function which might be
214 registered using `atexit'. This provides a mean for the
215 dynamic linker to call DT_FINI functions for shared libraries
216 that have been loaded before the code runs.
217
218 A value of 0 tells we have no such handler. */
219 regs->edx = 0;
bellardb346ff42003-06-15 20:05:50 +0000220}
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300221
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300222#define ELF_NREG 17
Anthony Liguoric227f092009-10-01 16:12:16 -0500223typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300224
225/*
226 * Note that ELF_NREG should be 19 as there should be place for
227 * TRAPNO and ERR "registers" as well but linux doesn't dump
228 * those.
229 *
230 * See linux kernel: arch/x86/include/asm/elf.h
231 */
Anthony Liguoric227f092009-10-01 16:12:16 -0500232static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300233{
234 (*regs)[0] = env->regs[R_EBX];
235 (*regs)[1] = env->regs[R_ECX];
236 (*regs)[2] = env->regs[R_EDX];
237 (*regs)[3] = env->regs[R_ESI];
238 (*regs)[4] = env->regs[R_EDI];
239 (*regs)[5] = env->regs[R_EBP];
240 (*regs)[6] = env->regs[R_EAX];
241 (*regs)[7] = env->segs[R_DS].selector & 0xffff;
242 (*regs)[8] = env->segs[R_ES].selector & 0xffff;
243 (*regs)[9] = env->segs[R_FS].selector & 0xffff;
244 (*regs)[10] = env->segs[R_GS].selector & 0xffff;
245 (*regs)[11] = env->regs[R_EAX]; /* XXX */
246 (*regs)[12] = env->eip;
247 (*regs)[13] = env->segs[R_CS].selector & 0xffff;
248 (*regs)[14] = env->eflags;
249 (*regs)[15] = env->regs[R_ESP];
250 (*regs)[16] = env->segs[R_SS].selector & 0xffff;
251}
j_mayer84409dd2007-04-06 08:56:50 +0000252#endif
bellardb346ff42003-06-15 20:05:50 +0000253
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300254#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700255#define ELF_EXEC_PAGESIZE 4096
bellardb346ff42003-06-15 20:05:50 +0000256
257#endif
258
259#ifdef TARGET_ARM
260
261#define ELF_START_MMAP 0x80000000
262
263#define elf_check_arch(x) ( (x) == EM_ARM )
264
Richard Hendersond97ef722010-07-27 10:25:29 -0700265#define ELF_CLASS ELFCLASS32
Richard Hendersond97ef722010-07-27 10:25:29 -0700266#define ELF_ARCH EM_ARM
bellardb346ff42003-06-15 20:05:50 +0000267
Richard Hendersond97ef722010-07-27 10:25:29 -0700268static inline void init_thread(struct target_pt_regs *regs,
269 struct image_info *infop)
bellardb346ff42003-06-15 20:05:50 +0000270{
blueswir1992f48a2007-10-14 16:27:31 +0000271 abi_long stack = infop->start_stack;
bellardb346ff42003-06-15 20:05:50 +0000272 memset(regs, 0, sizeof(*regs));
273 regs->ARM_cpsr = 0x10;
pbrook0240ded2006-02-04 19:30:51 +0000274 if (infop->entry & 1)
Richard Hendersond97ef722010-07-27 10:25:29 -0700275 regs->ARM_cpsr |= CPSR_T;
pbrook0240ded2006-02-04 19:30:51 +0000276 regs->ARM_pc = infop->entry & 0xfffffffe;
bellardb346ff42003-06-15 20:05:50 +0000277 regs->ARM_sp = infop->start_stack;
bellard2f619692007-11-16 10:46:05 +0000278 /* FIXME - what to for failure of get_user()? */
279 get_user_ual(regs->ARM_r2, stack + 8); /* envp */
280 get_user_ual(regs->ARM_r1, stack + 4); /* envp */
bellarda1516e92003-07-09 17:13:37 +0000281 /* XXX: it seems that r0 is zeroed after ! */
pbrooke5fe0c52006-06-11 13:32:59 +0000282 regs->ARM_r0 = 0;
283 /* For uClinux PIC binaries. */
j_mayer863cf0b2007-10-07 15:59:45 +0000284 /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
pbrooke5fe0c52006-06-11 13:32:59 +0000285 regs->ARM_r10 = infop->start_data;
bellardb346ff42003-06-15 20:05:50 +0000286}
287
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300288#define ELF_NREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -0500289typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300290
Anthony Liguoric227f092009-10-01 16:12:16 -0500291static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300292{
Nathan Froydd049e622009-12-11 09:04:47 -0800293 (*regs)[0] = tswapl(env->regs[0]);
294 (*regs)[1] = tswapl(env->regs[1]);
295 (*regs)[2] = tswapl(env->regs[2]);
296 (*regs)[3] = tswapl(env->regs[3]);
297 (*regs)[4] = tswapl(env->regs[4]);
298 (*regs)[5] = tswapl(env->regs[5]);
299 (*regs)[6] = tswapl(env->regs[6]);
300 (*regs)[7] = tswapl(env->regs[7]);
301 (*regs)[8] = tswapl(env->regs[8]);
302 (*regs)[9] = tswapl(env->regs[9]);
303 (*regs)[10] = tswapl(env->regs[10]);
304 (*regs)[11] = tswapl(env->regs[11]);
305 (*regs)[12] = tswapl(env->regs[12]);
306 (*regs)[13] = tswapl(env->regs[13]);
307 (*regs)[14] = tswapl(env->regs[14]);
308 (*regs)[15] = tswapl(env->regs[15]);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300309
Nathan Froydd049e622009-12-11 09:04:47 -0800310 (*regs)[16] = tswapl(cpsr_read((CPUState *)env));
311 (*regs)[17] = tswapl(env->regs[0]); /* XXX */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300312}
313
bellard30ac07d2003-04-07 21:33:03 +0000314#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700315#define ELF_EXEC_PAGESIZE 4096
bellard30ac07d2003-04-07 21:33:03 +0000316
bellardafce2922005-10-30 20:58:30 +0000317enum
318{
Richard Hendersond97ef722010-07-27 10:25:29 -0700319 ARM_HWCAP_ARM_SWP = 1 << 0,
320 ARM_HWCAP_ARM_HALF = 1 << 1,
321 ARM_HWCAP_ARM_THUMB = 1 << 2,
322 ARM_HWCAP_ARM_26BIT = 1 << 3,
323 ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
324 ARM_HWCAP_ARM_FPA = 1 << 5,
325 ARM_HWCAP_ARM_VFP = 1 << 6,
326 ARM_HWCAP_ARM_EDSP = 1 << 7,
327 ARM_HWCAP_ARM_JAVA = 1 << 8,
328 ARM_HWCAP_ARM_IWMMXT = 1 << 9,
329 ARM_HWCAP_ARM_THUMBEE = 1 << 10,
330 ARM_HWCAP_ARM_NEON = 1 << 11,
331 ARM_HWCAP_ARM_VFPv3 = 1 << 12,
332 ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
bellardafce2922005-10-30 20:58:30 +0000333};
334
Richard Hendersond97ef722010-07-27 10:25:29 -0700335#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
336 | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
337 | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
338 | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
bellardafce2922005-10-30 20:58:30 +0000339
bellard30ac07d2003-04-07 21:33:03 +0000340#endif
341
bellard853d6f72003-09-30 20:58:32 +0000342#ifdef TARGET_SPARC
bellarda315a142005-01-30 22:59:18 +0000343#ifdef TARGET_SPARC64
bellard853d6f72003-09-30 20:58:32 +0000344
345#define ELF_START_MMAP 0x80000000
346
blueswir1992f48a2007-10-14 16:27:31 +0000347#ifndef TARGET_ABI32
blueswir1cb33da52007-10-09 16:34:29 +0000348#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
blueswir1992f48a2007-10-14 16:27:31 +0000349#else
350#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
351#endif
bellard853d6f72003-09-30 20:58:32 +0000352
bellarda315a142005-01-30 22:59:18 +0000353#define ELF_CLASS ELFCLASS64
bellard5ef54112006-07-18 21:14:09 +0000354#define ELF_ARCH EM_SPARCV9
355
Richard Hendersond97ef722010-07-27 10:25:29 -0700356#define STACK_BIAS 2047
bellarda315a142005-01-30 22:59:18 +0000357
Richard Hendersond97ef722010-07-27 10:25:29 -0700358static inline void init_thread(struct target_pt_regs *regs,
359 struct image_info *infop)
bellarda315a142005-01-30 22:59:18 +0000360{
blueswir1992f48a2007-10-14 16:27:31 +0000361#ifndef TARGET_ABI32
bellarda315a142005-01-30 22:59:18 +0000362 regs->tstate = 0;
blueswir1992f48a2007-10-14 16:27:31 +0000363#endif
bellarda315a142005-01-30 22:59:18 +0000364 regs->pc = infop->entry;
365 regs->npc = regs->pc + 4;
366 regs->y = 0;
blueswir1992f48a2007-10-14 16:27:31 +0000367#ifdef TARGET_ABI32
368 regs->u_regs[14] = infop->start_stack - 16 * 4;
369#else
blueswir1cb33da52007-10-09 16:34:29 +0000370 if (personality(infop->personality) == PER_LINUX32)
371 regs->u_regs[14] = infop->start_stack - 16 * 4;
372 else
373 regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
blueswir1992f48a2007-10-14 16:27:31 +0000374#endif
bellarda315a142005-01-30 22:59:18 +0000375}
376
377#else
378#define ELF_START_MMAP 0x80000000
379
380#define elf_check_arch(x) ( (x) == EM_SPARC )
381
bellard853d6f72003-09-30 20:58:32 +0000382#define ELF_CLASS ELFCLASS32
bellard853d6f72003-09-30 20:58:32 +0000383#define ELF_ARCH EM_SPARC
384
Richard Hendersond97ef722010-07-27 10:25:29 -0700385static inline void init_thread(struct target_pt_regs *regs,
386 struct image_info *infop)
bellard853d6f72003-09-30 20:58:32 +0000387{
bellardf5155282004-01-04 15:46:50 +0000388 regs->psr = 0;
389 regs->pc = infop->entry;
390 regs->npc = regs->pc + 4;
391 regs->y = 0;
392 regs->u_regs[14] = infop->start_stack - 16 * 4;
bellard853d6f72003-09-30 20:58:32 +0000393}
394
395#endif
bellarda315a142005-01-30 22:59:18 +0000396#endif
bellard853d6f72003-09-30 20:58:32 +0000397
bellard67867302003-11-23 17:05:30 +0000398#ifdef TARGET_PPC
399
400#define ELF_START_MMAP 0x80000000
401
j_mayere85e7c62007-10-18 19:59:49 +0000402#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
j_mayer84409dd2007-04-06 08:56:50 +0000403
404#define elf_check_arch(x) ( (x) == EM_PPC64 )
405
Richard Hendersond97ef722010-07-27 10:25:29 -0700406#define ELF_CLASS ELFCLASS64
j_mayer84409dd2007-04-06 08:56:50 +0000407
408#else
409
bellard67867302003-11-23 17:05:30 +0000410#define elf_check_arch(x) ( (x) == EM_PPC )
411
Richard Hendersond97ef722010-07-27 10:25:29 -0700412#define ELF_CLASS ELFCLASS32
j_mayer84409dd2007-04-06 08:56:50 +0000413
414#endif
415
Richard Hendersond97ef722010-07-27 10:25:29 -0700416#define ELF_ARCH EM_PPC
bellard67867302003-11-23 17:05:30 +0000417
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700418/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
419 See arch/powerpc/include/asm/cputable.h. */
420enum {
malc3efa9a62009-07-18 13:10:12 +0400421 QEMU_PPC_FEATURE_32 = 0x80000000,
422 QEMU_PPC_FEATURE_64 = 0x40000000,
423 QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
424 QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
425 QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
426 QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
427 QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
428 QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
429 QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
430 QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
431 QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
432 QEMU_PPC_FEATURE_NO_TB = 0x00100000,
433 QEMU_PPC_FEATURE_POWER4 = 0x00080000,
434 QEMU_PPC_FEATURE_POWER5 = 0x00040000,
435 QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
436 QEMU_PPC_FEATURE_CELL = 0x00010000,
437 QEMU_PPC_FEATURE_BOOKE = 0x00008000,
438 QEMU_PPC_FEATURE_SMT = 0x00004000,
439 QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
440 QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
441 QEMU_PPC_FEATURE_PA6T = 0x00000800,
442 QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
443 QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
444 QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
445 QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
446 QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700447
malc3efa9a62009-07-18 13:10:12 +0400448 QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
449 QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700450};
451
452#define ELF_HWCAP get_elf_hwcap()
453
454static uint32_t get_elf_hwcap(void)
455{
456 CPUState *e = thread_env;
457 uint32_t features = 0;
458
459 /* We don't have to be terribly complete here; the high points are
460 Altivec/FP/SPE support. Anything else is just a bonus. */
Richard Hendersond97ef722010-07-27 10:25:29 -0700461#define GET_FEATURE(flag, feature) \
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700462 do {if (e->insns_flags & flag) features |= feature; } while(0)
malc3efa9a62009-07-18 13:10:12 +0400463 GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
464 GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
465 GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
466 GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
467 GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
468 GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
469 GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
470 GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700471#undef GET_FEATURE
472
473 return features;
474}
475
bellardf5155282004-01-04 15:46:50 +0000476/*
bellardf5155282004-01-04 15:46:50 +0000477 * The requirements here are:
478 * - keep the final alignment of sp (sp & 0xf)
479 * - make sure the 32-bit value at the first 16 byte aligned position of
480 * AUXV is greater than 16 for glibc compatibility.
481 * AT_IGNOREPPC is used for that.
482 * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
483 * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
484 */
bellard0bccf032005-08-21 10:12:28 +0000485#define DLINFO_ARCH_ITEMS 5
Richard Hendersond97ef722010-07-27 10:25:29 -0700486#define ARCH_DLINFO \
487 do { \
488 NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
489 NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
490 NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
491 /* \
492 * Now handle glibc compatibility. \
493 */ \
494 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
495 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
496 } while (0)
bellardf5155282004-01-04 15:46:50 +0000497
bellard67867302003-11-23 17:05:30 +0000498static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
499{
bellard67867302003-11-23 17:05:30 +0000500 _regs->gpr[1] = infop->start_stack;
j_mayere85e7c62007-10-18 19:59:49 +0000501#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
Rob Landley7983f432010-03-28 16:51:43 +0200502 _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_addr;
503 infop->entry = ldq_raw(infop->entry) + infop->load_addr;
j_mayer84409dd2007-04-06 08:56:50 +0000504#endif
bellard67867302003-11-23 17:05:30 +0000505 _regs->nip = infop->entry;
506}
507
Nathan Froyde2f3e742009-12-11 09:04:48 -0800508/* See linux kernel: arch/powerpc/include/asm/elf.h. */
509#define ELF_NREG 48
510typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
511
512static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
513{
514 int i;
515 target_ulong ccr = 0;
516
517 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
518 (*regs)[i] = tswapl(env->gpr[i]);
519 }
520
521 (*regs)[32] = tswapl(env->nip);
522 (*regs)[33] = tswapl(env->msr);
523 (*regs)[35] = tswapl(env->ctr);
524 (*regs)[36] = tswapl(env->lr);
525 (*regs)[37] = tswapl(env->xer);
526
527 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
528 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
529 }
530 (*regs)[38] = tswapl(ccr);
531}
532
533#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700534#define ELF_EXEC_PAGESIZE 4096
bellard67867302003-11-23 17:05:30 +0000535
536#endif
537
bellard048f6b42005-11-26 18:47:20 +0000538#ifdef TARGET_MIPS
539
540#define ELF_START_MMAP 0x80000000
541
542#define elf_check_arch(x) ( (x) == EM_MIPS )
543
ths388bb212007-05-13 13:58:00 +0000544#ifdef TARGET_MIPS64
545#define ELF_CLASS ELFCLASS64
546#else
bellard048f6b42005-11-26 18:47:20 +0000547#define ELF_CLASS ELFCLASS32
ths388bb212007-05-13 13:58:00 +0000548#endif
bellard048f6b42005-11-26 18:47:20 +0000549#define ELF_ARCH EM_MIPS
550
Richard Hendersond97ef722010-07-27 10:25:29 -0700551static inline void init_thread(struct target_pt_regs *regs,
552 struct image_info *infop)
bellard048f6b42005-11-26 18:47:20 +0000553{
ths623a9302007-10-28 19:45:05 +0000554 regs->cp0_status = 2 << CP0St_KSU;
bellard048f6b42005-11-26 18:47:20 +0000555 regs->cp0_epc = infop->entry;
556 regs->regs[29] = infop->start_stack;
557}
558
Nathan Froyd51e52602009-12-11 09:04:49 -0800559/* See linux kernel: arch/mips/include/asm/elf.h. */
560#define ELF_NREG 45
561typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
562
563/* See linux kernel: arch/mips/include/asm/reg.h. */
564enum {
565#ifdef TARGET_MIPS64
566 TARGET_EF_R0 = 0,
567#else
568 TARGET_EF_R0 = 6,
569#endif
570 TARGET_EF_R26 = TARGET_EF_R0 + 26,
571 TARGET_EF_R27 = TARGET_EF_R0 + 27,
572 TARGET_EF_LO = TARGET_EF_R0 + 32,
573 TARGET_EF_HI = TARGET_EF_R0 + 33,
574 TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
575 TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
576 TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
577 TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
578};
579
580/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
581static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
582{
583 int i;
584
585 for (i = 0; i < TARGET_EF_R0; i++) {
586 (*regs)[i] = 0;
587 }
588 (*regs)[TARGET_EF_R0] = 0;
589
590 for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
591 (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]);
592 }
593
594 (*regs)[TARGET_EF_R26] = 0;
595 (*regs)[TARGET_EF_R27] = 0;
596 (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]);
597 (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]);
598 (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC);
599 (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr);
600 (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status);
601 (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause);
602}
603
604#define USE_ELF_CORE_DUMP
ths388bb212007-05-13 13:58:00 +0000605#define ELF_EXEC_PAGESIZE 4096
606
bellard048f6b42005-11-26 18:47:20 +0000607#endif /* TARGET_MIPS */
608
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200609#ifdef TARGET_MICROBLAZE
610
611#define ELF_START_MMAP 0x80000000
612
Edgar E. Iglesias0d5d4692010-05-19 15:24:17 +0200613#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200614
615#define ELF_CLASS ELFCLASS32
Edgar E. Iglesias0d5d4692010-05-19 15:24:17 +0200616#define ELF_ARCH EM_MICROBLAZE
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200617
Richard Hendersond97ef722010-07-27 10:25:29 -0700618static inline void init_thread(struct target_pt_regs *regs,
619 struct image_info *infop)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200620{
621 regs->pc = infop->entry;
622 regs->r1 = infop->start_stack;
623
624}
625
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200626#define ELF_EXEC_PAGESIZE 4096
627
Edgar E. Iglesiase4cbd442010-05-19 15:09:28 +0200628#define USE_ELF_CORE_DUMP
629#define ELF_NREG 38
630typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
631
632/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
633static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
634{
635 int i, pos = 0;
636
637 for (i = 0; i < 32; i++) {
638 (*regs)[pos++] = tswapl(env->regs[i]);
639 }
640
641 for (i = 0; i < 6; i++) {
642 (*regs)[pos++] = tswapl(env->sregs[i]);
643 }
644}
645
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200646#endif /* TARGET_MICROBLAZE */
647
bellardfdf9b3e2006-04-27 21:07:38 +0000648#ifdef TARGET_SH4
649
650#define ELF_START_MMAP 0x80000000
651
652#define elf_check_arch(x) ( (x) == EM_SH )
653
654#define ELF_CLASS ELFCLASS32
bellardfdf9b3e2006-04-27 21:07:38 +0000655#define ELF_ARCH EM_SH
656
Richard Hendersond97ef722010-07-27 10:25:29 -0700657static inline void init_thread(struct target_pt_regs *regs,
658 struct image_info *infop)
bellardfdf9b3e2006-04-27 21:07:38 +0000659{
Richard Hendersond97ef722010-07-27 10:25:29 -0700660 /* Check other registers XXXXX */
661 regs->pc = infop->entry;
662 regs->regs[15] = infop->start_stack;
bellardfdf9b3e2006-04-27 21:07:38 +0000663}
664
Nathan Froyd7631c972009-12-11 09:04:51 -0800665/* See linux kernel: arch/sh/include/asm/elf.h. */
666#define ELF_NREG 23
667typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
668
669/* See linux kernel: arch/sh/include/asm/ptrace.h. */
670enum {
671 TARGET_REG_PC = 16,
672 TARGET_REG_PR = 17,
673 TARGET_REG_SR = 18,
674 TARGET_REG_GBR = 19,
675 TARGET_REG_MACH = 20,
676 TARGET_REG_MACL = 21,
677 TARGET_REG_SYSCALL = 22
678};
679
Richard Hendersond97ef722010-07-27 10:25:29 -0700680static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
681 const CPUState *env)
Nathan Froyd7631c972009-12-11 09:04:51 -0800682{
683 int i;
684
685 for (i = 0; i < 16; i++) {
686 (*regs[i]) = tswapl(env->gregs[i]);
687 }
688
689 (*regs)[TARGET_REG_PC] = tswapl(env->pc);
690 (*regs)[TARGET_REG_PR] = tswapl(env->pr);
691 (*regs)[TARGET_REG_SR] = tswapl(env->sr);
692 (*regs)[TARGET_REG_GBR] = tswapl(env->gbr);
693 (*regs)[TARGET_REG_MACH] = tswapl(env->mach);
694 (*regs)[TARGET_REG_MACL] = tswapl(env->macl);
695 (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
696}
697
698#define USE_ELF_CORE_DUMP
bellardfdf9b3e2006-04-27 21:07:38 +0000699#define ELF_EXEC_PAGESIZE 4096
700
701#endif
702
ths48733d12007-10-08 13:36:46 +0000703#ifdef TARGET_CRIS
704
705#define ELF_START_MMAP 0x80000000
706
707#define elf_check_arch(x) ( (x) == EM_CRIS )
708
709#define ELF_CLASS ELFCLASS32
ths48733d12007-10-08 13:36:46 +0000710#define ELF_ARCH EM_CRIS
711
Richard Hendersond97ef722010-07-27 10:25:29 -0700712static inline void init_thread(struct target_pt_regs *regs,
713 struct image_info *infop)
ths48733d12007-10-08 13:36:46 +0000714{
Richard Hendersond97ef722010-07-27 10:25:29 -0700715 regs->erp = infop->entry;
ths48733d12007-10-08 13:36:46 +0000716}
717
ths48733d12007-10-08 13:36:46 +0000718#define ELF_EXEC_PAGESIZE 8192
719
720#endif
721
pbrooke6e59062006-10-22 00:18:54 +0000722#ifdef TARGET_M68K
723
724#define ELF_START_MMAP 0x80000000
725
726#define elf_check_arch(x) ( (x) == EM_68K )
727
Richard Hendersond97ef722010-07-27 10:25:29 -0700728#define ELF_CLASS ELFCLASS32
Richard Hendersond97ef722010-07-27 10:25:29 -0700729#define ELF_ARCH EM_68K
pbrooke6e59062006-10-22 00:18:54 +0000730
731/* ??? Does this need to do anything?
Richard Hendersond97ef722010-07-27 10:25:29 -0700732 #define ELF_PLAT_INIT(_r) */
pbrooke6e59062006-10-22 00:18:54 +0000733
Richard Hendersond97ef722010-07-27 10:25:29 -0700734static inline void init_thread(struct target_pt_regs *regs,
735 struct image_info *infop)
pbrooke6e59062006-10-22 00:18:54 +0000736{
737 regs->usp = infop->start_stack;
738 regs->sr = 0;
739 regs->pc = infop->entry;
740}
741
Nathan Froyd7a93cc52009-12-11 09:04:50 -0800742/* See linux kernel: arch/m68k/include/asm/elf.h. */
743#define ELF_NREG 20
744typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
745
746static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
747{
748 (*regs)[0] = tswapl(env->dregs[1]);
749 (*regs)[1] = tswapl(env->dregs[2]);
750 (*regs)[2] = tswapl(env->dregs[3]);
751 (*regs)[3] = tswapl(env->dregs[4]);
752 (*regs)[4] = tswapl(env->dregs[5]);
753 (*regs)[5] = tswapl(env->dregs[6]);
754 (*regs)[6] = tswapl(env->dregs[7]);
755 (*regs)[7] = tswapl(env->aregs[0]);
756 (*regs)[8] = tswapl(env->aregs[1]);
757 (*regs)[9] = tswapl(env->aregs[2]);
758 (*regs)[10] = tswapl(env->aregs[3]);
759 (*regs)[11] = tswapl(env->aregs[4]);
760 (*regs)[12] = tswapl(env->aregs[5]);
761 (*regs)[13] = tswapl(env->aregs[6]);
762 (*regs)[14] = tswapl(env->dregs[0]);
763 (*regs)[15] = tswapl(env->aregs[7]);
764 (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */
765 (*regs)[17] = tswapl(env->sr);
766 (*regs)[18] = tswapl(env->pc);
767 (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */
768}
769
770#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700771#define ELF_EXEC_PAGESIZE 8192
pbrooke6e59062006-10-22 00:18:54 +0000772
773#endif
774
j_mayer7a3148a2007-04-05 07:13:51 +0000775#ifdef TARGET_ALPHA
776
777#define ELF_START_MMAP (0x30000000000ULL)
778
779#define elf_check_arch(x) ( (x) == ELF_ARCH )
780
781#define ELF_CLASS ELFCLASS64
j_mayer7a3148a2007-04-05 07:13:51 +0000782#define ELF_ARCH EM_ALPHA
783
Richard Hendersond97ef722010-07-27 10:25:29 -0700784static inline void init_thread(struct target_pt_regs *regs,
785 struct image_info *infop)
j_mayer7a3148a2007-04-05 07:13:51 +0000786{
787 regs->pc = infop->entry;
788 regs->ps = 8;
789 regs->usp = infop->start_stack;
j_mayer7a3148a2007-04-05 07:13:51 +0000790}
791
j_mayer7a3148a2007-04-05 07:13:51 +0000792#define ELF_EXEC_PAGESIZE 8192
793
794#endif /* TARGET_ALPHA */
795
bellard15338fd2005-11-26 11:41:16 +0000796#ifndef ELF_PLATFORM
797#define ELF_PLATFORM (NULL)
798#endif
799
800#ifndef ELF_HWCAP
801#define ELF_HWCAP 0
802#endif
803
blueswir1992f48a2007-10-14 16:27:31 +0000804#ifdef TARGET_ABI32
blueswir1cb33da52007-10-09 16:34:29 +0000805#undef ELF_CLASS
blueswir1992f48a2007-10-14 16:27:31 +0000806#define ELF_CLASS ELFCLASS32
blueswir1cb33da52007-10-09 16:34:29 +0000807#undef bswaptls
808#define bswaptls(ptr) bswap32s(ptr)
809#endif
810
bellard31e31b82003-02-18 22:55:36 +0000811#include "elf.h"
bellard09bfb052003-04-10 00:03:40 +0000812
bellard09bfb052003-04-10 00:03:40 +0000813struct exec
814{
Richard Hendersond97ef722010-07-27 10:25:29 -0700815 unsigned int a_info; /* Use macros N_MAGIC, etc for access */
816 unsigned int a_text; /* length of text, in bytes */
817 unsigned int a_data; /* length of data, in bytes */
818 unsigned int a_bss; /* length of uninitialized data area, in bytes */
819 unsigned int a_syms; /* length of symbol table data in file, in bytes */
820 unsigned int a_entry; /* start address */
821 unsigned int a_trsize; /* length of relocation info for text, in bytes */
822 unsigned int a_drsize; /* length of relocation info for data, in bytes */
bellard09bfb052003-04-10 00:03:40 +0000823};
824
825
826#define N_MAGIC(exec) ((exec).a_info & 0xffff)
827#define OMAGIC 0407
828#define NMAGIC 0410
829#define ZMAGIC 0413
830#define QMAGIC 0314
831
bellard09bfb052003-04-10 00:03:40 +0000832/* max code+data+bss+brk space allocated to ET_DYN executables */
833#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
834
bellard31e31b82003-02-18 22:55:36 +0000835/* Necessary parameters */
bellard54936002003-05-13 00:25:15 +0000836#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
837#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
838#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
bellard31e31b82003-02-18 22:55:36 +0000839
bellard15338fd2005-11-26 11:41:16 +0000840#define DLINFO_ITEMS 12
bellard31e31b82003-02-18 22:55:36 +0000841
bellard09bfb052003-04-10 00:03:40 +0000842static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
843{
Richard Hendersond97ef722010-07-27 10:25:29 -0700844 memcpy(to, from, n);
bellard09bfb052003-04-10 00:03:40 +0000845}
846
bellard31e31b82003-02-18 22:55:36 +0000847#ifdef BSWAP_NEEDED
bellard92a31b12005-02-10 22:00:52 +0000848static void bswap_ehdr(struct elfhdr *ehdr)
bellard31e31b82003-02-18 22:55:36 +0000849{
Richard Hendersond97ef722010-07-27 10:25:29 -0700850 bswap16s(&ehdr->e_type); /* Object file type */
851 bswap16s(&ehdr->e_machine); /* Architecture */
852 bswap32s(&ehdr->e_version); /* Object file version */
853 bswaptls(&ehdr->e_entry); /* Entry point virtual address */
854 bswaptls(&ehdr->e_phoff); /* Program header table file offset */
855 bswaptls(&ehdr->e_shoff); /* Section header table file offset */
856 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
857 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
858 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
859 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
860 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
861 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
862 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
bellard31e31b82003-02-18 22:55:36 +0000863}
864
Richard Henderson991f8f02010-07-27 10:25:32 -0700865static void bswap_phdr(struct elf_phdr *phdr, int phnum)
bellard31e31b82003-02-18 22:55:36 +0000866{
Richard Henderson991f8f02010-07-27 10:25:32 -0700867 int i;
868 for (i = 0; i < phnum; ++i, ++phdr) {
869 bswap32s(&phdr->p_type); /* Segment type */
870 bswap32s(&phdr->p_flags); /* Segment flags */
871 bswaptls(&phdr->p_offset); /* Segment file offset */
872 bswaptls(&phdr->p_vaddr); /* Segment virtual address */
873 bswaptls(&phdr->p_paddr); /* Segment physical address */
874 bswaptls(&phdr->p_filesz); /* Segment size in file */
875 bswaptls(&phdr->p_memsz); /* Segment size in memory */
876 bswaptls(&phdr->p_align); /* Segment alignment */
877 }
bellard31e31b82003-02-18 22:55:36 +0000878}
bellard689f9362003-04-29 20:40:07 +0000879
Richard Henderson991f8f02010-07-27 10:25:32 -0700880static void bswap_shdr(struct elf_shdr *shdr, int shnum)
bellard689f9362003-04-29 20:40:07 +0000881{
Richard Henderson991f8f02010-07-27 10:25:32 -0700882 int i;
883 for (i = 0; i < shnum; ++i, ++shdr) {
884 bswap32s(&shdr->sh_name);
885 bswap32s(&shdr->sh_type);
886 bswaptls(&shdr->sh_flags);
887 bswaptls(&shdr->sh_addr);
888 bswaptls(&shdr->sh_offset);
889 bswaptls(&shdr->sh_size);
890 bswap32s(&shdr->sh_link);
891 bswap32s(&shdr->sh_info);
892 bswaptls(&shdr->sh_addralign);
893 bswaptls(&shdr->sh_entsize);
894 }
bellard689f9362003-04-29 20:40:07 +0000895}
896
j_mayer7a3148a2007-04-05 07:13:51 +0000897static void bswap_sym(struct elf_sym *sym)
bellard689f9362003-04-29 20:40:07 +0000898{
899 bswap32s(&sym->st_name);
j_mayer7a3148a2007-04-05 07:13:51 +0000900 bswaptls(&sym->st_value);
901 bswaptls(&sym->st_size);
bellard689f9362003-04-29 20:40:07 +0000902 bswap16s(&sym->st_shndx);
903}
Richard Henderson991f8f02010-07-27 10:25:32 -0700904#else
905static inline void bswap_ehdr(struct elfhdr *ehdr) { }
906static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
907static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
908static inline void bswap_sym(struct elf_sym *sym) { }
bellard31e31b82003-02-18 22:55:36 +0000909#endif
910
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300911#ifdef USE_ELF_CORE_DUMP
912static int elf_core_dump(int, const CPUState *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300913#endif /* USE_ELF_CORE_DUMP */
Richard Henderson682674b2010-07-27 10:25:33 -0700914static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300915
Richard Henderson9058abd2010-07-27 10:25:34 -0700916/* Verify the portions of EHDR within E_IDENT for the target.
917 This can be performed before bswapping the entire header. */
918static bool elf_check_ident(struct elfhdr *ehdr)
919{
920 return (ehdr->e_ident[EI_MAG0] == ELFMAG0
921 && ehdr->e_ident[EI_MAG1] == ELFMAG1
922 && ehdr->e_ident[EI_MAG2] == ELFMAG2
923 && ehdr->e_ident[EI_MAG3] == ELFMAG3
924 && ehdr->e_ident[EI_CLASS] == ELF_CLASS
925 && ehdr->e_ident[EI_DATA] == ELF_DATA
926 && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
927}
928
929/* Verify the portions of EHDR outside of E_IDENT for the target.
930 This has to wait until after bswapping the header. */
931static bool elf_check_ehdr(struct elfhdr *ehdr)
932{
933 return (elf_check_arch(ehdr->e_machine)
934 && ehdr->e_ehsize == sizeof(struct elfhdr)
935 && ehdr->e_phentsize == sizeof(struct elf_phdr)
936 && ehdr->e_shentsize == sizeof(struct elf_shdr)
937 && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
938}
939
bellard31e31b82003-02-18 22:55:36 +0000940/*
pbrooke5fe0c52006-06-11 13:32:59 +0000941 * 'copy_elf_strings()' copies argument/envelope strings from user
bellard31e31b82003-02-18 22:55:36 +0000942 * memory to free pages in kernel mem. These are in a format ready
943 * to be put directly into the top of new user memory.
944 *
945 */
blueswir1992f48a2007-10-14 16:27:31 +0000946static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
947 abi_ulong p)
bellard31e31b82003-02-18 22:55:36 +0000948{
949 char *tmp, *tmp1, *pag = NULL;
950 int len, offset = 0;
951
952 if (!p) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700953 return 0; /* bullet-proofing */
bellard31e31b82003-02-18 22:55:36 +0000954 }
955 while (argc-- > 0) {
bellardedf779f2004-02-22 13:40:13 +0000956 tmp = argv[argc];
957 if (!tmp) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700958 fprintf(stderr, "VFS: argc is wrong");
959 exit(-1);
960 }
bellardedf779f2004-02-22 13:40:13 +0000961 tmp1 = tmp;
Richard Hendersond97ef722010-07-27 10:25:29 -0700962 while (*tmp++);
963 len = tmp - tmp1;
964 if (p < len) { /* this shouldn't happen - 128kB */
965 return 0;
966 }
967 while (len) {
968 --p; --tmp; --len;
969 if (--offset < 0) {
970 offset = p % TARGET_PAGE_SIZE;
pbrook53a59602006-03-25 19:31:22 +0000971 pag = (char *)page[p/TARGET_PAGE_SIZE];
bellard44a91ca2004-01-18 22:05:44 +0000972 if (!pag) {
pbrook53a59602006-03-25 19:31:22 +0000973 pag = (char *)malloc(TARGET_PAGE_SIZE);
j_mayer4118a972007-09-27 04:10:43 +0000974 memset(pag, 0, TARGET_PAGE_SIZE);
pbrook53a59602006-03-25 19:31:22 +0000975 page[p/TARGET_PAGE_SIZE] = pag;
bellard44a91ca2004-01-18 22:05:44 +0000976 if (!pag)
977 return 0;
Richard Hendersond97ef722010-07-27 10:25:29 -0700978 }
979 }
980 if (len == 0 || offset == 0) {
981 *(pag + offset) = *tmp;
982 }
983 else {
984 int bytes_to_copy = (len > offset) ? offset : len;
985 tmp -= bytes_to_copy;
986 p -= bytes_to_copy;
987 offset -= bytes_to_copy;
988 len -= bytes_to_copy;
989 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
990 }
991 }
bellard31e31b82003-02-18 22:55:36 +0000992 }
993 return p;
994}
995
blueswir1992f48a2007-10-14 16:27:31 +0000996static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
997 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +0000998{
Richard Henderson60dcbcb2010-07-27 10:25:35 -0700999 abi_ulong stack_base, size, error, guard;
bellard31e31b82003-02-18 22:55:36 +00001000 int i;
bellard31e31b82003-02-18 22:55:36 +00001001
1002 /* Create enough stack to hold everything. If we don't use
Richard Henderson60dcbcb2010-07-27 10:25:35 -07001003 it for args, we'll use it for something else. */
Richard Henderson703e0e82010-03-19 14:21:13 -07001004 size = guest_stack_size;
Richard Henderson60dcbcb2010-07-27 10:25:35 -07001005 if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) {
bellard54936002003-05-13 00:25:15 +00001006 size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
Richard Henderson60dcbcb2010-07-27 10:25:35 -07001007 }
1008 guard = TARGET_PAGE_SIZE;
1009 if (guard < qemu_real_host_page_size) {
1010 guard = qemu_real_host_page_size;
1011 }
1012
1013 error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
1014 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
bellard09bfb052003-04-10 00:03:40 +00001015 if (error == -1) {
Richard Henderson60dcbcb2010-07-27 10:25:35 -07001016 perror("mmap stack");
bellard09bfb052003-04-10 00:03:40 +00001017 exit(-1);
bellard31e31b82003-02-18 22:55:36 +00001018 }
bellard09bfb052003-04-10 00:03:40 +00001019
Richard Henderson60dcbcb2010-07-27 10:25:35 -07001020 /* We reserve one extra page at the top of the stack as guard. */
1021 target_mprotect(error, guard, PROT_NONE);
1022
1023 info->stack_limit = error + guard;
1024 stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
bellard09bfb052003-04-10 00:03:40 +00001025 p += stack_base;
1026
bellard31e31b82003-02-18 22:55:36 +00001027 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001028 if (bprm->page[i]) {
1029 info->rss++;
bellard579a97f2007-11-11 14:26:47 +00001030 /* FIXME - check return value of memcpy_to_target() for failure */
Richard Hendersond97ef722010-07-27 10:25:29 -07001031 memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
1032 free(bprm->page[i]);
1033 }
pbrook53a59602006-03-25 19:31:22 +00001034 stack_base += TARGET_PAGE_SIZE;
bellard31e31b82003-02-18 22:55:36 +00001035 }
1036 return p;
1037}
1038
Richard Hendersoncf129f32010-07-27 10:25:27 -07001039/* Map and zero the bss. We need to explicitly zero any fractional pages
1040 after the data section (i.e. bss). */
1041static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
bellard31e31b82003-02-18 22:55:36 +00001042{
Richard Hendersoncf129f32010-07-27 10:25:27 -07001043 uintptr_t host_start, host_map_start, host_end;
bellard31e31b82003-02-18 22:55:36 +00001044
Richard Hendersoncf129f32010-07-27 10:25:27 -07001045 last_bss = TARGET_PAGE_ALIGN(last_bss);
bellard31e31b82003-02-18 22:55:36 +00001046
Richard Hendersoncf129f32010-07-27 10:25:27 -07001047 /* ??? There is confusion between qemu_real_host_page_size and
1048 qemu_host_page_size here and elsewhere in target_mmap, which
1049 may lead to the end of the data section mapping from the file
1050 not being mapped. At least there was an explicit test and
1051 comment for that here, suggesting that "the file size must
1052 be known". The comment probably pre-dates the introduction
1053 of the fstat system call in target_mmap which does in fact
1054 find out the size. What isn't clear is if the workaround
1055 here is still actually needed. For now, continue with it,
1056 but merge it with the "normal" mmap that would allocate the bss. */
bellard31e31b82003-02-18 22:55:36 +00001057
Richard Hendersoncf129f32010-07-27 10:25:27 -07001058 host_start = (uintptr_t) g2h(elf_bss);
1059 host_end = (uintptr_t) g2h(last_bss);
1060 host_map_start = (host_start + qemu_real_host_page_size - 1);
1061 host_map_start &= -qemu_real_host_page_size;
ths768a4a32006-12-14 13:32:11 +00001062
Richard Hendersoncf129f32010-07-27 10:25:27 -07001063 if (host_map_start < host_end) {
1064 void *p = mmap((void *)host_map_start, host_end - host_map_start,
1065 prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1066 if (p == MAP_FAILED) {
1067 perror("cannot mmap brk");
1068 exit(-1);
bellard853d6f72003-09-30 20:58:32 +00001069 }
1070
Richard Hendersoncf129f32010-07-27 10:25:27 -07001071 /* Since we didn't use target_mmap, make sure to record
1072 the validity of the pages with qemu. */
1073 page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
1074 }
bellard31e31b82003-02-18 22:55:36 +00001075
Richard Hendersoncf129f32010-07-27 10:25:27 -07001076 if (host_start < host_map_start) {
1077 memset((void *)host_start, 0, host_map_start - host_start);
1078 }
1079}
bellardedf779f2004-02-22 13:40:13 +00001080
blueswir1992f48a2007-10-14 16:27:31 +00001081static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
1082 struct elfhdr * exec,
1083 abi_ulong load_addr,
1084 abi_ulong load_bias,
Richard Hendersonb9329d42010-07-27 10:25:36 -07001085 abi_ulong interp_load_addr,
blueswir1992f48a2007-10-14 16:27:31 +00001086 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +00001087{
Richard Hendersond97ef722010-07-27 10:25:29 -07001088 abi_ulong sp;
1089 int size;
1090 abi_ulong u_platform;
1091 const char *k_platform;
1092 const int n = sizeof(elf_addr_t);
pbrook53a59602006-03-25 19:31:22 +00001093
Richard Hendersond97ef722010-07-27 10:25:29 -07001094 sp = p;
1095 u_platform = 0;
1096 k_platform = ELF_PLATFORM;
1097 if (k_platform) {
1098 size_t len = strlen(k_platform) + 1;
1099 sp -= (len + n - 1) & ~(n - 1);
1100 u_platform = sp;
1101 /* FIXME - check return value of memcpy_to_target() for failure */
1102 memcpy_to_target(sp, k_platform, len);
1103 }
1104 /*
1105 * Force 16 byte _final_ alignment here for generality.
1106 */
1107 sp = sp &~ (abi_ulong)15;
1108 size = (DLINFO_ITEMS + 1) * 2;
1109 if (k_platform)
1110 size += 2;
bellardf5155282004-01-04 15:46:50 +00001111#ifdef DLINFO_ARCH_ITEMS
Richard Hendersond97ef722010-07-27 10:25:29 -07001112 size += DLINFO_ARCH_ITEMS * 2;
bellardf5155282004-01-04 15:46:50 +00001113#endif
Richard Hendersond97ef722010-07-27 10:25:29 -07001114 size += envc + argc + 2;
Richard Hendersonb9329d42010-07-27 10:25:36 -07001115 size += 1; /* argc itself */
Richard Hendersond97ef722010-07-27 10:25:29 -07001116 size *= n;
1117 if (size & 15)
1118 sp -= 16 - (size & 15);
ths3b46e622007-09-17 08:09:54 +00001119
Richard Hendersond97ef722010-07-27 10:25:29 -07001120 /* This is correct because Linux defines
1121 * elf_addr_t as Elf32_Off / Elf64_Off
1122 */
1123#define NEW_AUX_ENT(id, val) do { \
1124 sp -= n; put_user_ual(val, sp); \
1125 sp -= n; put_user_ual(id, sp); \
1126 } while(0)
bellard2f619692007-11-16 10:46:05 +00001127
Richard Hendersond97ef722010-07-27 10:25:29 -07001128 NEW_AUX_ENT (AT_NULL, 0);
bellardf5155282004-01-04 15:46:50 +00001129
Richard Hendersond97ef722010-07-27 10:25:29 -07001130 /* There must be exactly DLINFO_ITEMS entries here. */
1131 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
1132 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1133 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1134 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
1135 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
1136 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
1137 NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
1138 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1139 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1140 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1141 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1142 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1143 NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
1144 if (k_platform)
1145 NEW_AUX_ENT(AT_PLATFORM, u_platform);
bellardf5155282004-01-04 15:46:50 +00001146#ifdef ARCH_DLINFO
Richard Hendersond97ef722010-07-27 10:25:29 -07001147 /*
1148 * ARCH_DLINFO must come last so platform specific code can enforce
1149 * special alignment requirements on the AUXV if necessary (eg. PPC).
1150 */
1151 ARCH_DLINFO;
bellardf5155282004-01-04 15:46:50 +00001152#endif
1153#undef NEW_AUX_ENT
1154
Richard Hendersond97ef722010-07-27 10:25:29 -07001155 info->saved_auxv = sp;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001156
Richard Hendersonb9329d42010-07-27 10:25:36 -07001157 sp = loader_build_argptr(envc, argc, sp, p, 0);
Richard Hendersond97ef722010-07-27 10:25:29 -07001158 return sp;
bellard31e31b82003-02-18 22:55:36 +00001159}
1160
1161
blueswir1992f48a2007-10-14 16:27:31 +00001162static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
1163 int interpreter_fd,
Richard Henderson9955ffa2010-07-27 10:25:30 -07001164 abi_ulong *interp_load_addr,
1165 char bprm_buf[BPRM_BUF_SIZE])
bellard31e31b82003-02-18 22:55:36 +00001166{
Richard Hendersond97ef722010-07-27 10:25:29 -07001167 struct elf_phdr *elf_phdata = NULL;
Richard Henderson682674b2010-07-27 10:25:33 -07001168 abi_ulong load_addr, load_bias, loaddr, hiaddr;
Richard Hendersond97ef722010-07-27 10:25:29 -07001169 int retval;
1170 abi_ulong error;
1171 int i;
ths5fafdf22007-09-16 21:08:06 +00001172
Richard Hendersond97ef722010-07-27 10:25:29 -07001173 bswap_ehdr(interp_elf_ex);
Richard Henderson9058abd2010-07-27 10:25:34 -07001174 if (!elf_check_ehdr(interp_elf_ex)) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001175 return ~((abi_ulong)0UL);
1176 }
ths5fafdf22007-09-16 21:08:06 +00001177
Richard Hendersond97ef722010-07-27 10:25:29 -07001178 /* Now read in all of the header information */
Richard Hendersond97ef722010-07-27 10:25:29 -07001179 elf_phdata = (struct elf_phdr *)
1180 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
Richard Hendersond97ef722010-07-27 10:25:29 -07001181 if (!elf_phdata)
1182 return ~((abi_ulong)0UL);
ths5fafdf22007-09-16 21:08:06 +00001183
Richard Henderson9955ffa2010-07-27 10:25:30 -07001184 i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
1185 if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
1186 memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
1187 } else {
1188 retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
1189 if (retval != i) {
1190 perror("load_elf_interp");
1191 exit(-1);
1192 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001193 }
Richard Henderson991f8f02010-07-27 10:25:32 -07001194 bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
bellard09bfb052003-04-10 00:03:40 +00001195
Richard Henderson682674b2010-07-27 10:25:33 -07001196 /* Find the maximum size of the image and allocate an appropriate
1197 amount of memory to handle that. */
1198 loaddr = -1, hiaddr = 0;
1199 for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
1200 if (elf_phdata[i].p_type == PT_LOAD) {
1201 abi_ulong a = elf_phdata[i].p_vaddr;
1202 if (a < loaddr) {
1203 loaddr = a;
1204 }
1205 a += elf_phdata[i].p_memsz;
1206 if (a > hiaddr) {
1207 hiaddr = a;
1208 }
1209 }
1210 }
1211
1212 load_addr = loaddr;
Richard Hendersond97ef722010-07-27 10:25:29 -07001213 if (interp_elf_ex->e_type == ET_DYN) {
Richard Henderson682674b2010-07-27 10:25:33 -07001214 /* The image indicates that it can be loaded anywhere. Find a
1215 location that can hold the memory space required. If the
1216 image is pre-linked, LOADDR will be non-zero. Since we do
1217 not supply MAP_FIXED here we'll use that address if and
1218 only if it remains available. */
1219 load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
1220 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
1221 -1, 0);
1222 if (load_addr == -1) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001223 perror("mmap");
1224 exit(-1);
1225 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001226 }
Richard Henderson682674b2010-07-27 10:25:33 -07001227 load_bias = load_addr - loaddr;
Richard Hendersond97ef722010-07-27 10:25:29 -07001228
Richard Henderson682674b2010-07-27 10:25:33 -07001229 for (i = 0; i < interp_elf_ex->e_phnum; i++) {
1230 struct elf_phdr *eppnt = elf_phdata + i;
Richard Hendersond97ef722010-07-27 10:25:29 -07001231 if (eppnt->p_type == PT_LOAD) {
Richard Henderson682674b2010-07-27 10:25:33 -07001232 abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
Richard Hendersond97ef722010-07-27 10:25:29 -07001233 int elf_prot = 0;
Richard Hendersond97ef722010-07-27 10:25:29 -07001234
1235 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
1236 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1237 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
bellard09bfb052003-04-10 00:03:40 +00001238
Richard Henderson682674b2010-07-27 10:25:33 -07001239 vaddr = load_bias + eppnt->p_vaddr;
1240 vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
1241 vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
1242
1243 error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
1244 elf_prot, MAP_PRIVATE | MAP_FIXED,
1245 interpreter_fd, eppnt->p_offset - vaddr_po);
Richard Hendersond97ef722010-07-27 10:25:29 -07001246 if (error == -1) {
1247 /* Real error */
1248 close(interpreter_fd);
1249 free(elf_phdata);
1250 return ~((abi_ulong)0UL);
1251 }
bellard31e31b82003-02-18 22:55:36 +00001252
Richard Henderson682674b2010-07-27 10:25:33 -07001253 vaddr_ef = vaddr + eppnt->p_filesz;
1254 vaddr_em = vaddr + eppnt->p_memsz;
bellard31e31b82003-02-18 22:55:36 +00001255
Richard Hendersoncf129f32010-07-27 10:25:27 -07001256 /* If the load segment requests extra zeros (e.g. bss), map it. */
Richard Henderson682674b2010-07-27 10:25:33 -07001257 if (vaddr_ef < vaddr_em) {
1258 zero_bss(vaddr_ef, vaddr_em, elf_prot);
Richard Hendersoncf129f32010-07-27 10:25:27 -07001259 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001260 }
Richard Henderson682674b2010-07-27 10:25:33 -07001261 }
ths5fafdf22007-09-16 21:08:06 +00001262
Richard Henderson682674b2010-07-27 10:25:33 -07001263 if (qemu_log_enabled()) {
1264 load_symbols(interp_elf_ex, interpreter_fd, load_bias);
1265 }
bellard31e31b82003-02-18 22:55:36 +00001266
Richard Hendersond97ef722010-07-27 10:25:29 -07001267 close(interpreter_fd);
1268 free(elf_phdata);
bellard31e31b82003-02-18 22:55:36 +00001269
Richard Hendersond97ef722010-07-27 10:25:29 -07001270 *interp_load_addr = load_addr;
Richard Henderson682674b2010-07-27 10:25:33 -07001271 return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
bellard31e31b82003-02-18 22:55:36 +00001272}
1273
pbrook49918a72008-10-22 15:11:31 +00001274static int symfind(const void *s0, const void *s1)
1275{
1276 struct elf_sym *key = (struct elf_sym *)s0;
1277 struct elf_sym *sym = (struct elf_sym *)s1;
1278 int result = 0;
1279 if (key->st_value < sym->st_value) {
1280 result = -1;
Laurent Desnoguesec822002009-07-30 19:23:49 +02001281 } else if (key->st_value >= sym->st_value + sym->st_size) {
pbrook49918a72008-10-22 15:11:31 +00001282 result = 1;
1283 }
1284 return result;
1285}
1286
1287static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
1288{
1289#if ELF_CLASS == ELFCLASS32
1290 struct elf_sym *syms = s->disas_symtab.elf32;
1291#else
1292 struct elf_sym *syms = s->disas_symtab.elf64;
1293#endif
1294
1295 // binary search
1296 struct elf_sym key;
1297 struct elf_sym *sym;
1298
1299 key.st_value = orig_addr;
1300
1301 sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
Blue Swirl7cba04f2009-08-01 10:13:20 +00001302 if (sym != NULL) {
pbrook49918a72008-10-22 15:11:31 +00001303 return s->disas_strtab + sym->st_name;
1304 }
1305
1306 return "";
1307}
1308
1309/* FIXME: This should use elf_ops.h */
1310static int symcmp(const void *s0, const void *s1)
1311{
1312 struct elf_sym *sym0 = (struct elf_sym *)s0;
1313 struct elf_sym *sym1 = (struct elf_sym *)s1;
1314 return (sym0->st_value < sym1->st_value)
1315 ? -1
1316 : ((sym0->st_value > sym1->st_value) ? 1 : 0);
1317}
1318
bellard689f9362003-04-29 20:40:07 +00001319/* Best attempt to load symbols from this ELF object. */
Richard Henderson682674b2010-07-27 10:25:33 -07001320static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
bellard689f9362003-04-29 20:40:07 +00001321{
Richard Henderson682674b2010-07-27 10:25:33 -07001322 int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
1323 struct elf_shdr *shdr;
bellard689f9362003-04-29 20:40:07 +00001324 char *strings;
bellarde80cfcf2004-12-19 23:18:01 +00001325 struct syminfo *s;
pbrook49918a72008-10-22 15:11:31 +00001326 struct elf_sym *syms;
bellard31e31b82003-02-18 22:55:36 +00001327
Richard Henderson682674b2010-07-27 10:25:33 -07001328 shnum = hdr->e_shnum;
1329 i = shnum * sizeof(struct elf_shdr);
1330 shdr = (struct elf_shdr *)alloca(i);
1331 if (pread(fd, shdr, i, hdr->e_shoff) != i) {
1332 return;
1333 }
1334
1335 bswap_shdr(shdr, shnum);
1336 for (i = 0; i < shnum; ++i) {
1337 if (shdr[i].sh_type == SHT_SYMTAB) {
1338 sym_idx = i;
1339 str_idx = shdr[i].sh_link;
pbrook49918a72008-10-22 15:11:31 +00001340 goto found;
1341 }
bellard689f9362003-04-29 20:40:07 +00001342 }
Richard Henderson682674b2010-07-27 10:25:33 -07001343
1344 /* There will be no symbol table if the file was stripped. */
1345 return;
bellard689f9362003-04-29 20:40:07 +00001346
1347 found:
Richard Henderson682674b2010-07-27 10:25:33 -07001348 /* Now know where the strtab and symtab are. Snarf them. */
bellarde80cfcf2004-12-19 23:18:01 +00001349 s = malloc(sizeof(*s));
Richard Henderson682674b2010-07-27 10:25:33 -07001350 if (!s) {
pbrook49918a72008-10-22 15:11:31 +00001351 return;
Richard Henderson682674b2010-07-27 10:25:33 -07001352 }
1353
1354 i = shdr[str_idx].sh_size;
1355 s->disas_strtab = strings = malloc(i);
1356 if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
1357 free(s);
1358 free(strings);
pbrook49918a72008-10-22 15:11:31 +00001359 return;
Richard Henderson682674b2010-07-27 10:25:33 -07001360 }
ths5fafdf22007-09-16 21:08:06 +00001361
Richard Henderson682674b2010-07-27 10:25:33 -07001362 i = shdr[sym_idx].sh_size;
1363 syms = malloc(i);
1364 if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
1365 free(s);
1366 free(strings);
1367 free(syms);
pbrook49918a72008-10-22 15:11:31 +00001368 return;
Richard Henderson682674b2010-07-27 10:25:33 -07001369 }
bellard689f9362003-04-29 20:40:07 +00001370
Richard Henderson682674b2010-07-27 10:25:33 -07001371 nsyms = i / sizeof(struct elf_sym);
1372 for (i = 0; i < nsyms; ) {
pbrook49918a72008-10-22 15:11:31 +00001373 bswap_sym(syms + i);
Richard Henderson682674b2010-07-27 10:25:33 -07001374 /* Throw away entries which we do not need. */
1375 if (syms[i].st_shndx == SHN_UNDEF
1376 || syms[i].st_shndx >= SHN_LORESERVE
1377 || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
1378 if (i < --nsyms) {
pbrook49918a72008-10-22 15:11:31 +00001379 syms[i] = syms[nsyms];
1380 }
Richard Henderson682674b2010-07-27 10:25:33 -07001381 } else {
pbrook49918a72008-10-22 15:11:31 +00001382#if defined(TARGET_ARM) || defined (TARGET_MIPS)
Richard Henderson682674b2010-07-27 10:25:33 -07001383 /* The bottom address bit marks a Thumb or MIPS16 symbol. */
1384 syms[i].st_value &= ~(target_ulong)1;
blueswir10774bed2007-07-05 13:23:29 +00001385#endif
Richard Henderson682674b2010-07-27 10:25:33 -07001386 syms[i].st_value += load_bias;
1387 i++;
1388 }
blueswir10774bed2007-07-05 13:23:29 +00001389 }
bellard689f9362003-04-29 20:40:07 +00001390
Richard Henderson682674b2010-07-27 10:25:33 -07001391 syms = realloc(syms, nsyms * sizeof(*syms));
pbrook49918a72008-10-22 15:11:31 +00001392 qsort(syms, nsyms, sizeof(*syms), symcmp);
1393
pbrook49918a72008-10-22 15:11:31 +00001394 s->disas_num_syms = nsyms;
1395#if ELF_CLASS == ELFCLASS32
1396 s->disas_symtab.elf32 = syms;
pbrook49918a72008-10-22 15:11:31 +00001397#else
1398 s->disas_symtab.elf64 = syms;
pbrook49918a72008-10-22 15:11:31 +00001399#endif
Richard Henderson682674b2010-07-27 10:25:33 -07001400 s->lookup_symbol = lookup_symbolxx;
bellarde80cfcf2004-12-19 23:18:01 +00001401 s->next = syminfos;
1402 syminfos = s;
bellard689f9362003-04-29 20:40:07 +00001403}
bellard31e31b82003-02-18 22:55:36 +00001404
pbrooke5fe0c52006-06-11 13:32:59 +00001405int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1406 struct image_info * info)
bellard31e31b82003-02-18 22:55:36 +00001407{
1408 struct elfhdr elf_ex;
1409 struct elfhdr interp_elf_ex;
bellard31e31b82003-02-18 22:55:36 +00001410 int interpreter_fd = -1; /* avoid warning */
blueswir1992f48a2007-10-14 16:27:31 +00001411 abi_ulong load_addr, load_bias;
bellard31e31b82003-02-18 22:55:36 +00001412 int load_addr_set = 0;
bellard31e31b82003-02-18 22:55:36 +00001413 unsigned char ibcs2_interpreter;
1414 int i;
blueswir1992f48a2007-10-14 16:27:31 +00001415 abi_ulong mapped_addr;
bellard31e31b82003-02-18 22:55:36 +00001416 struct elf_phdr * elf_ppnt;
1417 struct elf_phdr *elf_phdata;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001418 abi_ulong k, elf_brk;
bellard31e31b82003-02-18 22:55:36 +00001419 int retval;
1420 char * elf_interpreter;
blueswir1992f48a2007-10-14 16:27:31 +00001421 abi_ulong elf_entry, interp_load_addr = 0;
bellard31e31b82003-02-18 22:55:36 +00001422 int status;
blueswir1992f48a2007-10-14 16:27:31 +00001423 abi_ulong start_code, end_code, start_data, end_data;
1424 abi_ulong reloc_func_desc = 0;
1425 abi_ulong elf_stack;
bellard31e31b82003-02-18 22:55:36 +00001426
1427 ibcs2_interpreter = 0;
1428 status = 0;
1429 load_addr = 0;
bellard09bfb052003-04-10 00:03:40 +00001430 load_bias = 0;
bellard31e31b82003-02-18 22:55:36 +00001431 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
bellard31e31b82003-02-18 22:55:36 +00001432
bellard31e31b82003-02-18 22:55:36 +00001433 /* First of all, some simple consistency checks */
Richard Henderson9058abd2010-07-27 10:25:34 -07001434 if (!elf_check_ident(&elf_ex)) {
1435 return -ENOEXEC;
1436 }
1437 bswap_ehdr(&elf_ex);
1438 if (!elf_check_ehdr(&elf_ex)) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001439 return -ENOEXEC;
bellard31e31b82003-02-18 22:55:36 +00001440 }
1441
pbrooke5fe0c52006-06-11 13:32:59 +00001442 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1443 bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1444 bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1445 if (!bprm->p) {
1446 retval = -E2BIG;
1447 }
1448
bellard31e31b82003-02-18 22:55:36 +00001449 /* Now read in all of the header information */
Richard Henderson9058abd2010-07-27 10:25:34 -07001450 elf_phdata = (struct elf_phdr *)
1451 malloc(elf_ex.e_phnum * sizeof(struct elf_phdr));
bellard31e31b82003-02-18 22:55:36 +00001452 if (elf_phdata == NULL) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001453 return -ENOMEM;
bellard31e31b82003-02-18 22:55:36 +00001454 }
1455
Richard Henderson9955ffa2010-07-27 10:25:30 -07001456 i = elf_ex.e_phnum * sizeof(struct elf_phdr);
1457 if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
1458 memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
1459 } else {
1460 retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
1461 if (retval != i) {
1462 perror("load_elf_binary");
1463 exit(-1);
1464 }
bellard31e31b82003-02-18 22:55:36 +00001465 }
Richard Henderson991f8f02010-07-27 10:25:32 -07001466 bswap_phdr(elf_phdata, elf_ex.e_phnum);
bellard31e31b82003-02-18 22:55:36 +00001467
bellard31e31b82003-02-18 22:55:36 +00001468 elf_brk = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001469 elf_stack = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001470 elf_interpreter = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00001471 start_code = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001472 end_code = 0;
j_mayer863cf0b2007-10-07 15:59:45 +00001473 start_data = 0;
bellard31e31b82003-02-18 22:55:36 +00001474 end_data = 0;
1475
Richard Henderson991f8f02010-07-27 10:25:32 -07001476 elf_ppnt = elf_phdata;
bellard31e31b82003-02-18 22:55:36 +00001477 for(i=0;i < elf_ex.e_phnum; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001478 if (elf_ppnt->p_type == PT_INTERP) {
1479 if ( elf_interpreter != NULL )
1480 {
1481 free (elf_phdata);
1482 free(elf_interpreter);
1483 close(bprm->fd);
1484 return -EINVAL;
1485 }
bellard31e31b82003-02-18 22:55:36 +00001486
Richard Hendersond97ef722010-07-27 10:25:29 -07001487 /* This is the program interpreter used for
1488 * shared libraries - for now assume that this
1489 * is an a.out format binary
1490 */
bellard31e31b82003-02-18 22:55:36 +00001491
Richard Hendersond97ef722010-07-27 10:25:29 -07001492 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
bellard31e31b82003-02-18 22:55:36 +00001493
Richard Hendersond97ef722010-07-27 10:25:29 -07001494 if (elf_interpreter == NULL) {
1495 free (elf_phdata);
1496 close(bprm->fd);
1497 return -ENOMEM;
1498 }
bellard31e31b82003-02-18 22:55:36 +00001499
Richard Henderson9955ffa2010-07-27 10:25:30 -07001500 if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
1501 memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
1502 elf_ppnt->p_filesz);
1503 } else {
1504 retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
1505 elf_ppnt->p_offset);
1506 if (retval != elf_ppnt->p_filesz) {
1507 perror("load_elf_binary2");
1508 exit(-1);
1509 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001510 }
bellard31e31b82003-02-18 22:55:36 +00001511
Richard Hendersond97ef722010-07-27 10:25:29 -07001512 /* If the program interpreter is one of these two,
1513 then assume an iBCS2 image. Otherwise assume
1514 a native linux image. */
bellard31e31b82003-02-18 22:55:36 +00001515
Richard Hendersond97ef722010-07-27 10:25:29 -07001516 /* JRP - Need to add X86 lib dir stuff here... */
bellard31e31b82003-02-18 22:55:36 +00001517
Richard Hendersond97ef722010-07-27 10:25:29 -07001518 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
1519 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
1520 ibcs2_interpreter = 1;
1521 }
bellard31e31b82003-02-18 22:55:36 +00001522
Richard Henderson9955ffa2010-07-27 10:25:30 -07001523 retval = open(path(elf_interpreter), O_RDONLY);
1524 if (retval < 0) {
1525 perror(elf_interpreter);
1526 exit(-1);
Richard Hendersond97ef722010-07-27 10:25:29 -07001527 }
Richard Henderson9955ffa2010-07-27 10:25:30 -07001528 interpreter_fd = retval;
bellard31e31b82003-02-18 22:55:36 +00001529
Richard Henderson9955ffa2010-07-27 10:25:30 -07001530 retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
Richard Hendersond97ef722010-07-27 10:25:29 -07001531 if (retval < 0) {
1532 perror("load_elf_binary3");
1533 exit(-1);
Richard Hendersond97ef722010-07-27 10:25:29 -07001534 }
Richard Henderson9955ffa2010-07-27 10:25:30 -07001535 if (retval < BPRM_BUF_SIZE) {
1536 memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
1537 }
1538
Richard Hendersonb9329d42010-07-27 10:25:36 -07001539 interp_elf_ex = *((struct elfhdr *) bprm->buf);
Richard Hendersond97ef722010-07-27 10:25:29 -07001540 }
1541 elf_ppnt++;
bellard31e31b82003-02-18 22:55:36 +00001542 }
1543
1544 /* Some simple consistency checks for the interpreter */
Richard Hendersonb9329d42010-07-27 10:25:36 -07001545 if (elf_interpreter) {
Richard Henderson9058abd2010-07-27 10:25:34 -07001546 if (!elf_check_ident(&interp_elf_ex)) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001547 free(elf_interpreter);
1548 free(elf_phdata);
1549 close(bprm->fd);
Richard Hendersonb9329d42010-07-27 10:25:36 -07001550 close(interpreter_fd);
Richard Hendersond97ef722010-07-27 10:25:29 -07001551 return -ELIBBAD;
1552 }
bellard31e31b82003-02-18 22:55:36 +00001553 }
1554
bellard31e31b82003-02-18 22:55:36 +00001555 /* OK, This is the point of no return */
1556 info->end_data = 0;
1557 info->end_code = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001558 info->start_mmap = (abi_ulong)ELF_START_MMAP;
bellard31e31b82003-02-18 22:55:36 +00001559 info->mmap = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001560 elf_entry = (abi_ulong) elf_ex.e_entry;
bellard31e31b82003-02-18 22:55:36 +00001561
Paul Brook379f6692009-07-17 12:48:08 +01001562#if defined(CONFIG_USE_GUEST_BASE)
1563 /*
1564 * In case where user has not explicitly set the guest_base, we
1565 * probe here that should we set it automatically.
1566 */
Paul Brook68a1c812010-05-29 02:27:35 +01001567 if (!(have_guest_base || reserved_va)) {
Paul Brook379f6692009-07-17 12:48:08 +01001568 /*
Paul Brookc581ded2010-05-05 16:32:59 +01001569 * Go through ELF program header table and find the address
1570 * range used by loadable segments. Check that this is available on
1571 * the host, and if not find a suitable value for guest_base. */
1572 abi_ulong app_start = ~0;
1573 abi_ulong app_end = 0;
1574 abi_ulong addr;
1575 unsigned long host_start;
1576 unsigned long real_start;
1577 unsigned long host_size;
Paul Brook379f6692009-07-17 12:48:08 +01001578 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
Richard Hendersond97ef722010-07-27 10:25:29 -07001579 i++, elf_ppnt++) {
Paul Brook379f6692009-07-17 12:48:08 +01001580 if (elf_ppnt->p_type != PT_LOAD)
1581 continue;
Paul Brookc581ded2010-05-05 16:32:59 +01001582 addr = elf_ppnt->p_vaddr;
1583 if (addr < app_start) {
1584 app_start = addr;
1585 }
1586 addr += elf_ppnt->p_memsz;
1587 if (addr > app_end) {
1588 app_end = addr;
Paul Brook379f6692009-07-17 12:48:08 +01001589 }
1590 }
Paul Brookc581ded2010-05-05 16:32:59 +01001591
1592 /* If we don't have any loadable segments then something
1593 is very wrong. */
1594 assert(app_start < app_end);
1595
1596 /* Round addresses to page boundaries. */
1597 app_start = app_start & qemu_host_page_mask;
1598 app_end = HOST_PAGE_ALIGN(app_end);
1599 if (app_start < mmap_min_addr) {
1600 host_start = HOST_PAGE_ALIGN(mmap_min_addr);
1601 } else {
1602 host_start = app_start;
1603 if (host_start != app_start) {
1604 fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
1605 abort();
1606 }
1607 }
1608 host_size = app_end - app_start;
1609 while (1) {
1610 /* Do not use mmap_find_vma here because that is limited to the
1611 guest address space. We are going to make the
1612 guest address space fit whatever we're given. */
1613 real_start = (unsigned long)mmap((void *)host_start, host_size,
1614 PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
1615 if (real_start == (unsigned long)-1) {
1616 fprintf(stderr, "qemu: Virtual memory exausted\n");
1617 abort();
1618 }
1619 if (real_start == host_start) {
1620 break;
1621 }
1622 /* That address didn't work. Unmap and try a different one.
1623 The address the host picked because is typically
1624 right at the top of the host address space and leaves the
1625 guest with no usable address space. Resort to a linear search.
1626 We already compensated for mmap_min_addr, so this should not
1627 happen often. Probably means we got unlucky and host address
1628 space randomization put a shared library somewhere
1629 inconvenient. */
1630 munmap((void *)real_start, host_size);
1631 host_start += qemu_host_page_size;
1632 if (host_start == app_start) {
1633 /* Theoretically possible if host doesn't have any
1634 suitably aligned areas. Normally the first mmap will
1635 fail. */
1636 fprintf(stderr, "qemu: Unable to find space for application\n");
1637 abort();
1638 }
1639 }
1640 qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
1641 " to 0x%lx\n", app_start, real_start);
1642 guest_base = real_start - app_start;
Paul Brook379f6692009-07-17 12:48:08 +01001643 }
1644#endif /* CONFIG_USE_GUEST_BASE */
1645
bellard31e31b82003-02-18 22:55:36 +00001646 /* Do this so that we can load the interpreter, if need be. We will
1647 change some of these later */
1648 info->rss = 0;
1649 bprm->p = setup_arg_pages(bprm->p, bprm, info);
1650 info->start_stack = bprm->p;
1651
1652 /* Now we do a little grungy work by mmaping the ELF image into
1653 * the correct location in memory. At this point, we assume that
1654 * the image should be loaded at fixed address, not at a variable
1655 * address.
1656 */
1657
bellard31e31b82003-02-18 22:55:36 +00001658 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
bellard09bfb052003-04-10 00:03:40 +00001659 int elf_prot = 0;
1660 int elf_flags = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001661 abi_ulong error;
ths3b46e622007-09-17 08:09:54 +00001662
Richard Hendersond97ef722010-07-27 10:25:29 -07001663 if (elf_ppnt->p_type != PT_LOAD)
bellard09bfb052003-04-10 00:03:40 +00001664 continue;
ths3b46e622007-09-17 08:09:54 +00001665
bellard09bfb052003-04-10 00:03:40 +00001666 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
1667 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1668 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1669 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
1670 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
1671 elf_flags |= MAP_FIXED;
1672 } else if (elf_ex.e_type == ET_DYN) {
1673 /* Try and get dynamic programs out of the way of the default mmap
1674 base, as well as whatever program they might try to exec. This
1675 is because the brk will follow the loader, and is not movable. */
1676 /* NOTE: for qemu, we do a big mmap to get enough space
thse91c8a72007-06-03 13:35:16 +00001677 without hardcoding any address */
bellard54936002003-05-13 00:25:15 +00001678 error = target_mmap(0, ET_DYN_MAP_SIZE,
ths5fafdf22007-09-16 21:08:06 +00001679 PROT_NONE, MAP_PRIVATE | MAP_ANON,
bellard54936002003-05-13 00:25:15 +00001680 -1, 0);
bellard09bfb052003-04-10 00:03:40 +00001681 if (error == -1) {
1682 perror("mmap");
1683 exit(-1);
1684 }
bellard54936002003-05-13 00:25:15 +00001685 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001686 }
ths3b46e622007-09-17 08:09:54 +00001687
bellard54936002003-05-13 00:25:15 +00001688 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
1689 (elf_ppnt->p_filesz +
1690 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
1691 elf_prot,
1692 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
1693 bprm->fd,
ths5fafdf22007-09-16 21:08:06 +00001694 (elf_ppnt->p_offset -
bellard54936002003-05-13 00:25:15 +00001695 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
bellard09bfb052003-04-10 00:03:40 +00001696 if (error == -1) {
1697 perror("mmap");
1698 exit(-1);
1699 }
bellard31e31b82003-02-18 22:55:36 +00001700
1701#ifdef LOW_ELF_STACK
bellard54936002003-05-13 00:25:15 +00001702 if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
1703 elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
bellard31e31b82003-02-18 22:55:36 +00001704#endif
ths3b46e622007-09-17 08:09:54 +00001705
bellard09bfb052003-04-10 00:03:40 +00001706 if (!load_addr_set) {
1707 load_addr_set = 1;
1708 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1709 if (elf_ex.e_type == ET_DYN) {
1710 load_bias += error -
bellard54936002003-05-13 00:25:15 +00001711 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001712 load_addr += load_bias;
j_mayer84409dd2007-04-06 08:56:50 +00001713 reloc_func_desc = load_bias;
bellard09bfb052003-04-10 00:03:40 +00001714 }
1715 }
1716 k = elf_ppnt->p_vaddr;
ths5fafdf22007-09-16 21:08:06 +00001717 if (k < start_code)
bellard09bfb052003-04-10 00:03:40 +00001718 start_code = k;
j_mayer863cf0b2007-10-07 15:59:45 +00001719 if (start_data < k)
1720 start_data = k;
bellard09bfb052003-04-10 00:03:40 +00001721 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
bellard09bfb052003-04-10 00:03:40 +00001722 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
1723 end_code = k;
ths5fafdf22007-09-16 21:08:06 +00001724 if (end_data < k)
bellard09bfb052003-04-10 00:03:40 +00001725 end_data = k;
1726 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001727 if (k > elf_brk) {
1728 elf_brk = TARGET_PAGE_ALIGN(k);
1729 }
1730
1731 /* If the load segment requests extra zeros (e.g. bss), map it. */
1732 if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
1733 abi_ulong base = load_bias + elf_ppnt->p_vaddr;
1734 zero_bss(base + elf_ppnt->p_filesz,
1735 base + elf_ppnt->p_memsz, elf_prot);
1736 }
bellard31e31b82003-02-18 22:55:36 +00001737 }
1738
bellard09bfb052003-04-10 00:03:40 +00001739 elf_entry += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001740 elf_brk += load_bias;
1741 start_code += load_bias;
1742 end_code += load_bias;
j_mayer863cf0b2007-10-07 15:59:45 +00001743 start_data += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001744 end_data += load_bias;
1745
bellard31e31b82003-02-18 22:55:36 +00001746 if (elf_interpreter) {
Richard Hendersonb9329d42010-07-27 10:25:36 -07001747 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
1748 &interp_load_addr, bprm->buf);
j_mayer84409dd2007-04-06 08:56:50 +00001749 reloc_func_desc = interp_load_addr;
Richard Hendersond97ef722010-07-27 10:25:29 -07001750 free(elf_interpreter);
bellard31e31b82003-02-18 22:55:36 +00001751
Richard Hendersond97ef722010-07-27 10:25:29 -07001752 if (elf_entry == ~((abi_ulong)0UL)) {
1753 printf("Unable to load interpreter\n");
1754 free(elf_phdata);
1755 exit(-1);
1756 return 0;
1757 }
bellard31e31b82003-02-18 22:55:36 +00001758 }
1759
1760 free(elf_phdata);
1761
Richard Henderson682674b2010-07-27 10:25:33 -07001762 if (qemu_log_enabled()) {
1763 load_symbols(&elf_ex, bprm->fd, load_bias);
1764 }
bellard689f9362003-04-29 20:40:07 +00001765
Richard Hendersonb9329d42010-07-27 10:25:36 -07001766 close(bprm->fd);
bellard31e31b82003-02-18 22:55:36 +00001767 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
1768
1769#ifdef LOW_ELF_STACK
1770 info->start_stack = bprm->p = elf_stack - 4;
1771#endif
pbrook53a59602006-03-25 19:31:22 +00001772 bprm->p = create_elf_tables(bprm->p,
Richard Hendersond97ef722010-07-27 10:25:29 -07001773 bprm->argc,
1774 bprm->envc,
1775 &elf_ex,
1776 load_addr, load_bias,
1777 interp_load_addr,
Richard Hendersond97ef722010-07-27 10:25:29 -07001778 info);
j_mayer92a343d2007-09-27 01:14:15 +00001779 info->load_addr = reloc_func_desc;
bellard31e31b82003-02-18 22:55:36 +00001780 info->start_brk = info->brk = elf_brk;
1781 info->end_code = end_code;
1782 info->start_code = start_code;
j_mayer863cf0b2007-10-07 15:59:45 +00001783 info->start_data = start_data;
bellard31e31b82003-02-18 22:55:36 +00001784 info->end_data = end_data;
1785 info->start_stack = bprm->p;
1786
bellard31e31b82003-02-18 22:55:36 +00001787#if 0
1788 printf("(start_brk) %x\n" , info->start_brk);
1789 printf("(end_code) %x\n" , info->end_code);
1790 printf("(start_code) %x\n" , info->start_code);
1791 printf("(end_data) %x\n" , info->end_data);
1792 printf("(start_stack) %x\n" , info->start_stack);
1793 printf("(brk) %x\n" , info->brk);
1794#endif
1795
1796 if ( info->personality == PER_SVR4 )
1797 {
Richard Hendersond97ef722010-07-27 10:25:29 -07001798 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
1799 and some applications "depend" upon this behavior.
1800 Since we do not have the power to recompile these, we
1801 emulate the SVr4 behavior. Sigh. */
1802 mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
1803 MAP_FIXED | MAP_PRIVATE, -1, 0);
bellard31e31b82003-02-18 22:55:36 +00001804 }
1805
bellard31e31b82003-02-18 22:55:36 +00001806 info->entry = elf_entry;
1807
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001808#ifdef USE_ELF_CORE_DUMP
1809 bprm->core_dump = &elf_core_dump;
1810#endif
1811
bellard31e31b82003-02-18 22:55:36 +00001812 return 0;
1813}
1814
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001815#ifdef USE_ELF_CORE_DUMP
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001816/*
1817 * Definitions to generate Intel SVR4-like core files.
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001818 * These mostly have the same names as the SVR4 types with "target_elf_"
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001819 * tacked on the front to prevent clashes with linux definitions,
1820 * and the typedef forms have been avoided. This is mostly like
1821 * the SVR4 structure, but more Linuxy, with things that Linux does
1822 * not support and which gdb doesn't really use excluded.
1823 *
1824 * Fields we don't dump (their contents is zero) in linux-user qemu
1825 * are marked with XXX.
1826 *
1827 * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
1828 *
1829 * Porting ELF coredump for target is (quite) simple process. First you
Nathan Froyddd0a3652009-12-11 09:04:45 -08001830 * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001831 * the target resides):
1832 *
1833 * #define USE_ELF_CORE_DUMP
1834 *
1835 * Next you define type of register set used for dumping. ELF specification
1836 * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
1837 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001838 * typedef <target_regtype> target_elf_greg_t;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001839 * #define ELF_NREG <number of registers>
Anthony Liguoric227f092009-10-01 16:12:16 -05001840 * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001841 *
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001842 * Last step is to implement target specific function that copies registers
1843 * from given cpu into just specified register set. Prototype is:
1844 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001845 * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001846 * const CPUState *env);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001847 *
1848 * Parameters:
1849 * regs - copy register values into here (allocated and zeroed by caller)
1850 * env - copy registers from here
1851 *
1852 * Example for ARM target is provided in this file.
1853 */
1854
1855/* An ELF note in memory */
1856struct memelfnote {
1857 const char *name;
1858 size_t namesz;
1859 size_t namesz_rounded;
1860 int type;
1861 size_t datasz;
1862 void *data;
1863 size_t notesz;
1864};
1865
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001866struct target_elf_siginfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001867 int si_signo; /* signal number */
1868 int si_code; /* extra code */
1869 int si_errno; /* errno */
1870};
1871
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001872struct target_elf_prstatus {
1873 struct target_elf_siginfo pr_info; /* Info associated with signal */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001874 short pr_cursig; /* Current signal */
1875 target_ulong pr_sigpend; /* XXX */
1876 target_ulong pr_sighold; /* XXX */
Anthony Liguoric227f092009-10-01 16:12:16 -05001877 target_pid_t pr_pid;
1878 target_pid_t pr_ppid;
1879 target_pid_t pr_pgrp;
1880 target_pid_t pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001881 struct target_timeval pr_utime; /* XXX User time */
1882 struct target_timeval pr_stime; /* XXX System time */
1883 struct target_timeval pr_cutime; /* XXX Cumulative user time */
1884 struct target_timeval pr_cstime; /* XXX Cumulative system time */
Anthony Liguoric227f092009-10-01 16:12:16 -05001885 target_elf_gregset_t pr_reg; /* GP registers */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001886 int pr_fpvalid; /* XXX */
1887};
1888
1889#define ELF_PRARGSZ (80) /* Number of chars for args */
1890
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001891struct target_elf_prpsinfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001892 char pr_state; /* numeric process state */
1893 char pr_sname; /* char for pr_state */
1894 char pr_zomb; /* zombie */
1895 char pr_nice; /* nice val */
1896 target_ulong pr_flag; /* flags */
Anthony Liguoric227f092009-10-01 16:12:16 -05001897 target_uid_t pr_uid;
1898 target_gid_t pr_gid;
1899 target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001900 /* Lots missing */
1901 char pr_fname[16]; /* filename of executable */
1902 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
1903};
1904
1905/* Here is the structure in which status of each thread is captured. */
1906struct elf_thread_status {
Blue Swirl72cf2d42009-09-12 07:36:22 +00001907 QTAILQ_ENTRY(elf_thread_status) ets_link;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001908 struct target_elf_prstatus prstatus; /* NT_PRSTATUS */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001909#if 0
1910 elf_fpregset_t fpu; /* NT_PRFPREG */
1911 struct task_struct *thread;
1912 elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
1913#endif
1914 struct memelfnote notes[1];
1915 int num_notes;
1916};
1917
1918struct elf_note_info {
1919 struct memelfnote *notes;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001920 struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */
1921 struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001922
Blue Swirl72cf2d42009-09-12 07:36:22 +00001923 QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001924#if 0
1925 /*
1926 * Current version of ELF coredump doesn't support
1927 * dumping fp regs etc.
1928 */
1929 elf_fpregset_t *fpu;
1930 elf_fpxregset_t *xfpu;
1931 int thread_status_size;
1932#endif
1933 int notes_size;
1934 int numnote;
1935};
1936
1937struct vm_area_struct {
1938 abi_ulong vma_start; /* start vaddr of memory region */
1939 abi_ulong vma_end; /* end vaddr of memory region */
1940 abi_ulong vma_flags; /* protection etc. flags for the region */
Blue Swirl72cf2d42009-09-12 07:36:22 +00001941 QTAILQ_ENTRY(vm_area_struct) vma_link;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001942};
1943
1944struct mm_struct {
Blue Swirl72cf2d42009-09-12 07:36:22 +00001945 QTAILQ_HEAD(, vm_area_struct) mm_mmap;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001946 int mm_count; /* number of mappings */
1947};
1948
1949static struct mm_struct *vma_init(void);
1950static void vma_delete(struct mm_struct *);
1951static int vma_add_mapping(struct mm_struct *, abi_ulong,
Richard Hendersond97ef722010-07-27 10:25:29 -07001952 abi_ulong, abi_ulong);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001953static int vma_get_mapping_count(const struct mm_struct *);
1954static struct vm_area_struct *vma_first(const struct mm_struct *);
1955static struct vm_area_struct *vma_next(struct vm_area_struct *);
1956static abi_ulong vma_dump_size(const struct vm_area_struct *);
Paul Brookb480d9b2010-03-12 23:23:29 +00001957static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07001958 unsigned long flags);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001959
1960static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
1961static void fill_note(struct memelfnote *, const char *, int,
Richard Hendersond97ef722010-07-27 10:25:29 -07001962 unsigned int, void *);
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001963static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
1964static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001965static void fill_auxv_note(struct memelfnote *, const TaskState *);
1966static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
1967static size_t note_size(const struct memelfnote *);
1968static void free_note_info(struct elf_note_info *);
1969static int fill_note_info(struct elf_note_info *, long, const CPUState *);
1970static void fill_thread_info(struct elf_note_info *, const CPUState *);
1971static int core_dump_filename(const TaskState *, char *, size_t);
1972
1973static int dump_write(int, const void *, size_t);
1974static int write_note(struct memelfnote *, int);
1975static int write_note_info(struct elf_note_info *, int);
1976
1977#ifdef BSWAP_NEEDED
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001978static void bswap_prstatus(struct target_elf_prstatus *prstatus)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001979{
1980 prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
1981 prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
1982 prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
1983 prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
1984 prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
1985 prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
1986 prstatus->pr_pid = tswap32(prstatus->pr_pid);
1987 prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
1988 prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
1989 prstatus->pr_sid = tswap32(prstatus->pr_sid);
1990 /* cpu times are not filled, so we skip them */
1991 /* regs should be in correct format already */
1992 prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
1993}
1994
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001995static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001996{
1997 psinfo->pr_flag = tswapl(psinfo->pr_flag);
1998 psinfo->pr_uid = tswap16(psinfo->pr_uid);
1999 psinfo->pr_gid = tswap16(psinfo->pr_gid);
2000 psinfo->pr_pid = tswap32(psinfo->pr_pid);
2001 psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
2002 psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
2003 psinfo->pr_sid = tswap32(psinfo->pr_sid);
2004}
Richard Henderson991f8f02010-07-27 10:25:32 -07002005
2006static void bswap_note(struct elf_note *en)
2007{
2008 bswap32s(&en->n_namesz);
2009 bswap32s(&en->n_descsz);
2010 bswap32s(&en->n_type);
2011}
2012#else
2013static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
2014static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
2015static inline void bswap_note(struct elf_note *en) { }
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002016#endif /* BSWAP_NEEDED */
2017
2018/*
2019 * Minimal support for linux memory regions. These are needed
2020 * when we are finding out what memory exactly belongs to
2021 * emulated process. No locks needed here, as long as
2022 * thread that received the signal is stopped.
2023 */
2024
2025static struct mm_struct *vma_init(void)
2026{
2027 struct mm_struct *mm;
2028
2029 if ((mm = qemu_malloc(sizeof (*mm))) == NULL)
2030 return (NULL);
2031
2032 mm->mm_count = 0;
Blue Swirl72cf2d42009-09-12 07:36:22 +00002033 QTAILQ_INIT(&mm->mm_mmap);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002034
2035 return (mm);
2036}
2037
2038static void vma_delete(struct mm_struct *mm)
2039{
2040 struct vm_area_struct *vma;
2041
2042 while ((vma = vma_first(mm)) != NULL) {
Blue Swirl72cf2d42009-09-12 07:36:22 +00002043 QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002044 qemu_free(vma);
2045 }
2046 qemu_free(mm);
2047}
2048
2049static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
Richard Hendersond97ef722010-07-27 10:25:29 -07002050 abi_ulong end, abi_ulong flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002051{
2052 struct vm_area_struct *vma;
2053
2054 if ((vma = qemu_mallocz(sizeof (*vma))) == NULL)
2055 return (-1);
2056
2057 vma->vma_start = start;
2058 vma->vma_end = end;
2059 vma->vma_flags = flags;
2060
Blue Swirl72cf2d42009-09-12 07:36:22 +00002061 QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002062 mm->mm_count++;
2063
2064 return (0);
2065}
2066
2067static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2068{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002069 return (QTAILQ_FIRST(&mm->mm_mmap));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002070}
2071
2072static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2073{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002074 return (QTAILQ_NEXT(vma, vma_link));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002075}
2076
2077static int vma_get_mapping_count(const struct mm_struct *mm)
2078{
2079 return (mm->mm_count);
2080}
2081
2082/*
2083 * Calculate file (dump) size of given memory region.
2084 */
2085static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2086{
2087 /* if we cannot even read the first page, skip it */
2088 if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2089 return (0);
2090
2091 /*
2092 * Usually we don't dump executable pages as they contain
2093 * non-writable code that debugger can read directly from
2094 * target library etc. However, thread stacks are marked
2095 * also executable so we read in first page of given region
2096 * and check whether it contains elf header. If there is
2097 * no elf header, we dump it.
2098 */
2099 if (vma->vma_flags & PROT_EXEC) {
2100 char page[TARGET_PAGE_SIZE];
2101
2102 copy_from_user(page, vma->vma_start, sizeof (page));
2103 if ((page[EI_MAG0] == ELFMAG0) &&
2104 (page[EI_MAG1] == ELFMAG1) &&
2105 (page[EI_MAG2] == ELFMAG2) &&
2106 (page[EI_MAG3] == ELFMAG3)) {
2107 /*
2108 * Mappings are possibly from ELF binary. Don't dump
2109 * them.
2110 */
2111 return (0);
2112 }
2113 }
2114
2115 return (vma->vma_end - vma->vma_start);
2116}
2117
Paul Brookb480d9b2010-03-12 23:23:29 +00002118static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07002119 unsigned long flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002120{
2121 struct mm_struct *mm = (struct mm_struct *)priv;
2122
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002123 vma_add_mapping(mm, start, end, flags);
2124 return (0);
2125}
2126
2127static void fill_note(struct memelfnote *note, const char *name, int type,
Richard Hendersond97ef722010-07-27 10:25:29 -07002128 unsigned int sz, void *data)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002129{
2130 unsigned int namesz;
2131
2132 namesz = strlen(name) + 1;
2133 note->name = name;
2134 note->namesz = namesz;
2135 note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2136 note->type = type;
2137 note->datasz = roundup(sz, sizeof (int32_t));;
2138 note->data = data;
2139
2140 /*
2141 * We calculate rounded up note size here as specified by
2142 * ELF document.
2143 */
2144 note->notesz = sizeof (struct elf_note) +
2145 note->namesz_rounded + note->datasz;
2146}
2147
2148static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
Richard Hendersond97ef722010-07-27 10:25:29 -07002149 uint32_t flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002150{
2151 (void) memset(elf, 0, sizeof(*elf));
2152
2153 (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2154 elf->e_ident[EI_CLASS] = ELF_CLASS;
2155 elf->e_ident[EI_DATA] = ELF_DATA;
2156 elf->e_ident[EI_VERSION] = EV_CURRENT;
2157 elf->e_ident[EI_OSABI] = ELF_OSABI;
2158
2159 elf->e_type = ET_CORE;
2160 elf->e_machine = machine;
2161 elf->e_version = EV_CURRENT;
2162 elf->e_phoff = sizeof(struct elfhdr);
2163 elf->e_flags = flags;
2164 elf->e_ehsize = sizeof(struct elfhdr);
2165 elf->e_phentsize = sizeof(struct elf_phdr);
2166 elf->e_phnum = segs;
2167
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002168 bswap_ehdr(elf);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002169}
2170
2171static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2172{
2173 phdr->p_type = PT_NOTE;
2174 phdr->p_offset = offset;
2175 phdr->p_vaddr = 0;
2176 phdr->p_paddr = 0;
2177 phdr->p_filesz = sz;
2178 phdr->p_memsz = 0;
2179 phdr->p_flags = 0;
2180 phdr->p_align = 0;
2181
Richard Henderson991f8f02010-07-27 10:25:32 -07002182 bswap_phdr(phdr, 1);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002183}
2184
2185static size_t note_size(const struct memelfnote *note)
2186{
2187 return (note->notesz);
2188}
2189
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002190static void fill_prstatus(struct target_elf_prstatus *prstatus,
Richard Hendersond97ef722010-07-27 10:25:29 -07002191 const TaskState *ts, int signr)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002192{
2193 (void) memset(prstatus, 0, sizeof (*prstatus));
2194 prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2195 prstatus->pr_pid = ts->ts_tid;
2196 prstatus->pr_ppid = getppid();
2197 prstatus->pr_pgrp = getpgrp();
2198 prstatus->pr_sid = getsid(0);
2199
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002200 bswap_prstatus(prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002201}
2202
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002203static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002204{
2205 char *filename, *base_filename;
2206 unsigned int i, len;
2207
2208 (void) memset(psinfo, 0, sizeof (*psinfo));
2209
2210 len = ts->info->arg_end - ts->info->arg_start;
2211 if (len >= ELF_PRARGSZ)
2212 len = ELF_PRARGSZ - 1;
2213 if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2214 return -EFAULT;
2215 for (i = 0; i < len; i++)
2216 if (psinfo->pr_psargs[i] == 0)
2217 psinfo->pr_psargs[i] = ' ';
2218 psinfo->pr_psargs[len] = 0;
2219
2220 psinfo->pr_pid = getpid();
2221 psinfo->pr_ppid = getppid();
2222 psinfo->pr_pgrp = getpgrp();
2223 psinfo->pr_sid = getsid(0);
2224 psinfo->pr_uid = getuid();
2225 psinfo->pr_gid = getgid();
2226
2227 filename = strdup(ts->bprm->filename);
2228 base_filename = strdup(basename(filename));
2229 (void) strncpy(psinfo->pr_fname, base_filename,
Richard Hendersond97ef722010-07-27 10:25:29 -07002230 sizeof(psinfo->pr_fname));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002231 free(base_filename);
2232 free(filename);
2233
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002234 bswap_psinfo(psinfo);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002235 return (0);
2236}
2237
2238static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2239{
2240 elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2241 elf_addr_t orig_auxv = auxv;
2242 abi_ulong val;
2243 void *ptr;
2244 int i, len;
2245
2246 /*
2247 * Auxiliary vector is stored in target process stack. It contains
2248 * {type, value} pairs that we need to dump into note. This is not
2249 * strictly necessary but we do it here for sake of completeness.
2250 */
2251
2252 /* find out lenght of the vector, AT_NULL is terminator */
2253 i = len = 0;
2254 do {
2255 get_user_ual(val, auxv);
2256 i += 2;
2257 auxv += 2 * sizeof (elf_addr_t);
2258 } while (val != AT_NULL);
2259 len = i * sizeof (elf_addr_t);
2260
2261 /* read in whole auxv vector and copy it to memelfnote */
2262 ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2263 if (ptr != NULL) {
2264 fill_note(note, "CORE", NT_AUXV, len, ptr);
2265 unlock_user(ptr, auxv, len);
2266 }
2267}
2268
2269/*
2270 * Constructs name of coredump file. We have following convention
2271 * for the name:
2272 * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2273 *
2274 * Returns 0 in case of success, -1 otherwise (errno is set).
2275 */
2276static int core_dump_filename(const TaskState *ts, char *buf,
Richard Hendersond97ef722010-07-27 10:25:29 -07002277 size_t bufsize)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002278{
2279 char timestamp[64];
2280 char *filename = NULL;
2281 char *base_filename = NULL;
2282 struct timeval tv;
2283 struct tm tm;
2284
2285 assert(bufsize >= PATH_MAX);
2286
2287 if (gettimeofday(&tv, NULL) < 0) {
2288 (void) fprintf(stderr, "unable to get current timestamp: %s",
Richard Hendersond97ef722010-07-27 10:25:29 -07002289 strerror(errno));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002290 return (-1);
2291 }
2292
2293 filename = strdup(ts->bprm->filename);
2294 base_filename = strdup(basename(filename));
2295 (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
Richard Hendersond97ef722010-07-27 10:25:29 -07002296 localtime_r(&tv.tv_sec, &tm));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002297 (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
Richard Hendersond97ef722010-07-27 10:25:29 -07002298 base_filename, timestamp, (int)getpid());
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002299 free(base_filename);
2300 free(filename);
2301
2302 return (0);
2303}
2304
2305static int dump_write(int fd, const void *ptr, size_t size)
2306{
2307 const char *bufp = (const char *)ptr;
2308 ssize_t bytes_written, bytes_left;
2309 struct rlimit dumpsize;
2310 off_t pos;
2311
2312 bytes_written = 0;
2313 getrlimit(RLIMIT_CORE, &dumpsize);
2314 if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2315 if (errno == ESPIPE) { /* not a seekable stream */
2316 bytes_left = size;
2317 } else {
2318 return pos;
2319 }
2320 } else {
2321 if (dumpsize.rlim_cur <= pos) {
2322 return -1;
2323 } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2324 bytes_left = size;
2325 } else {
2326 size_t limit_left=dumpsize.rlim_cur - pos;
2327 bytes_left = limit_left >= size ? size : limit_left ;
2328 }
2329 }
2330
2331 /*
2332 * In normal conditions, single write(2) should do but
2333 * in case of socket etc. this mechanism is more portable.
2334 */
2335 do {
2336 bytes_written = write(fd, bufp, bytes_left);
2337 if (bytes_written < 0) {
2338 if (errno == EINTR)
2339 continue;
2340 return (-1);
2341 } else if (bytes_written == 0) { /* eof */
2342 return (-1);
2343 }
2344 bufp += bytes_written;
2345 bytes_left -= bytes_written;
2346 } while (bytes_left > 0);
2347
2348 return (0);
2349}
2350
2351static int write_note(struct memelfnote *men, int fd)
2352{
2353 struct elf_note en;
2354
2355 en.n_namesz = men->namesz;
2356 en.n_type = men->type;
2357 en.n_descsz = men->datasz;
2358
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002359 bswap_note(&en);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002360
2361 if (dump_write(fd, &en, sizeof(en)) != 0)
2362 return (-1);
2363 if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2364 return (-1);
2365 if (dump_write(fd, men->data, men->datasz) != 0)
2366 return (-1);
2367
2368 return (0);
2369}
2370
2371static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
2372{
2373 TaskState *ts = (TaskState *)env->opaque;
2374 struct elf_thread_status *ets;
2375
2376 ets = qemu_mallocz(sizeof (*ets));
2377 ets->num_notes = 1; /* only prstatus is dumped */
2378 fill_prstatus(&ets->prstatus, ts, 0);
2379 elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2380 fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
Richard Hendersond97ef722010-07-27 10:25:29 -07002381 &ets->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002382
Blue Swirl72cf2d42009-09-12 07:36:22 +00002383 QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002384
2385 info->notes_size += note_size(&ets->notes[0]);
2386}
2387
2388static int fill_note_info(struct elf_note_info *info,
Richard Hendersond97ef722010-07-27 10:25:29 -07002389 long signr, const CPUState *env)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002390{
2391#define NUMNOTES 3
2392 CPUState *cpu = NULL;
2393 TaskState *ts = (TaskState *)env->opaque;
2394 int i;
2395
2396 (void) memset(info, 0, sizeof (*info));
2397
Blue Swirl72cf2d42009-09-12 07:36:22 +00002398 QTAILQ_INIT(&info->thread_list);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002399
2400 info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote));
2401 if (info->notes == NULL)
2402 return (-ENOMEM);
2403 info->prstatus = qemu_mallocz(sizeof (*info->prstatus));
2404 if (info->prstatus == NULL)
2405 return (-ENOMEM);
2406 info->psinfo = qemu_mallocz(sizeof (*info->psinfo));
2407 if (info->prstatus == NULL)
2408 return (-ENOMEM);
2409
2410 /*
2411 * First fill in status (and registers) of current thread
2412 * including process info & aux vector.
2413 */
2414 fill_prstatus(info->prstatus, ts, signr);
2415 elf_core_copy_regs(&info->prstatus->pr_reg, env);
2416 fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
Richard Hendersond97ef722010-07-27 10:25:29 -07002417 sizeof (*info->prstatus), info->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002418 fill_psinfo(info->psinfo, ts);
2419 fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
Richard Hendersond97ef722010-07-27 10:25:29 -07002420 sizeof (*info->psinfo), info->psinfo);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002421 fill_auxv_note(&info->notes[2], ts);
2422 info->numnote = 3;
2423
2424 info->notes_size = 0;
2425 for (i = 0; i < info->numnote; i++)
2426 info->notes_size += note_size(&info->notes[i]);
2427
2428 /* read and fill status of all threads */
2429 cpu_list_lock();
2430 for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2431 if (cpu == thread_env)
2432 continue;
2433 fill_thread_info(info, cpu);
2434 }
2435 cpu_list_unlock();
2436
2437 return (0);
2438}
2439
2440static void free_note_info(struct elf_note_info *info)
2441{
2442 struct elf_thread_status *ets;
2443
Blue Swirl72cf2d42009-09-12 07:36:22 +00002444 while (!QTAILQ_EMPTY(&info->thread_list)) {
2445 ets = QTAILQ_FIRST(&info->thread_list);
2446 QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002447 qemu_free(ets);
2448 }
2449
2450 qemu_free(info->prstatus);
2451 qemu_free(info->psinfo);
2452 qemu_free(info->notes);
2453}
2454
2455static int write_note_info(struct elf_note_info *info, int fd)
2456{
2457 struct elf_thread_status *ets;
2458 int i, error = 0;
2459
2460 /* write prstatus, psinfo and auxv for current thread */
2461 for (i = 0; i < info->numnote; i++)
2462 if ((error = write_note(&info->notes[i], fd)) != 0)
2463 return (error);
2464
2465 /* write prstatus for each thread */
2466 for (ets = info->thread_list.tqh_first; ets != NULL;
Richard Hendersond97ef722010-07-27 10:25:29 -07002467 ets = ets->ets_link.tqe_next) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002468 if ((error = write_note(&ets->notes[0], fd)) != 0)
2469 return (error);
2470 }
2471
2472 return (0);
2473}
2474
2475/*
2476 * Write out ELF coredump.
2477 *
2478 * See documentation of ELF object file format in:
2479 * http://www.caldera.com/developers/devspecs/gabi41.pdf
2480 *
2481 * Coredump format in linux is following:
2482 *
2483 * 0 +----------------------+ \
2484 * | ELF header | ET_CORE |
2485 * +----------------------+ |
2486 * | ELF program headers | |--- headers
2487 * | - NOTE section | |
2488 * | - PT_LOAD sections | |
2489 * +----------------------+ /
2490 * | NOTEs: |
2491 * | - NT_PRSTATUS |
2492 * | - NT_PRSINFO |
2493 * | - NT_AUXV |
2494 * +----------------------+ <-- aligned to target page
2495 * | Process memory dump |
2496 * : :
2497 * . .
2498 * : :
2499 * | |
2500 * +----------------------+
2501 *
2502 * NT_PRSTATUS -> struct elf_prstatus (per thread)
2503 * NT_PRSINFO -> struct elf_prpsinfo
2504 * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2505 *
2506 * Format follows System V format as close as possible. Current
2507 * version limitations are as follows:
2508 * - no floating point registers are dumped
2509 *
2510 * Function returns 0 in case of success, negative errno otherwise.
2511 *
2512 * TODO: make this work also during runtime: it should be
2513 * possible to force coredump from running process and then
2514 * continue processing. For example qemu could set up SIGUSR2
2515 * handler (provided that target process haven't registered
2516 * handler for that) that does the dump when signal is received.
2517 */
2518static int elf_core_dump(int signr, const CPUState *env)
2519{
2520 const TaskState *ts = (const TaskState *)env->opaque;
2521 struct vm_area_struct *vma = NULL;
2522 char corefile[PATH_MAX];
2523 struct elf_note_info info;
2524 struct elfhdr elf;
2525 struct elf_phdr phdr;
2526 struct rlimit dumpsize;
2527 struct mm_struct *mm = NULL;
2528 off_t offset = 0, data_offset = 0;
2529 int segs = 0;
2530 int fd = -1;
2531
2532 errno = 0;
2533 getrlimit(RLIMIT_CORE, &dumpsize);
2534 if (dumpsize.rlim_cur == 0)
Richard Hendersond97ef722010-07-27 10:25:29 -07002535 return 0;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002536
2537 if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2538 return (-errno);
2539
2540 if ((fd = open(corefile, O_WRONLY | O_CREAT,
Richard Hendersond97ef722010-07-27 10:25:29 -07002541 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002542 return (-errno);
2543
2544 /*
2545 * Walk through target process memory mappings and
2546 * set up structure containing this information. After
2547 * this point vma_xxx functions can be used.
2548 */
2549 if ((mm = vma_init()) == NULL)
2550 goto out;
2551
2552 walk_memory_regions(mm, vma_walker);
2553 segs = vma_get_mapping_count(mm);
2554
2555 /*
2556 * Construct valid coredump ELF header. We also
2557 * add one more segment for notes.
2558 */
2559 fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2560 if (dump_write(fd, &elf, sizeof (elf)) != 0)
2561 goto out;
2562
2563 /* fill in in-memory version of notes */
2564 if (fill_note_info(&info, signr, env) < 0)
2565 goto out;
2566
2567 offset += sizeof (elf); /* elf header */
2568 offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */
2569
2570 /* write out notes program header */
2571 fill_elf_note_phdr(&phdr, info.notes_size, offset);
2572
2573 offset += info.notes_size;
2574 if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2575 goto out;
2576
2577 /*
2578 * ELF specification wants data to start at page boundary so
2579 * we align it here.
2580 */
2581 offset = roundup(offset, ELF_EXEC_PAGESIZE);
2582
2583 /*
2584 * Write program headers for memory regions mapped in
2585 * the target process.
2586 */
2587 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2588 (void) memset(&phdr, 0, sizeof (phdr));
2589
2590 phdr.p_type = PT_LOAD;
2591 phdr.p_offset = offset;
2592 phdr.p_vaddr = vma->vma_start;
2593 phdr.p_paddr = 0;
2594 phdr.p_filesz = vma_dump_size(vma);
2595 offset += phdr.p_filesz;
2596 phdr.p_memsz = vma->vma_end - vma->vma_start;
2597 phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2598 if (vma->vma_flags & PROT_WRITE)
2599 phdr.p_flags |= PF_W;
2600 if (vma->vma_flags & PROT_EXEC)
2601 phdr.p_flags |= PF_X;
2602 phdr.p_align = ELF_EXEC_PAGESIZE;
2603
2604 dump_write(fd, &phdr, sizeof (phdr));
2605 }
2606
2607 /*
2608 * Next we write notes just after program headers. No
2609 * alignment needed here.
2610 */
2611 if (write_note_info(&info, fd) < 0)
2612 goto out;
2613
2614 /* align data to page boundary */
2615 data_offset = lseek(fd, 0, SEEK_CUR);
2616 data_offset = TARGET_PAGE_ALIGN(data_offset);
2617 if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2618 goto out;
2619
2620 /*
2621 * Finally we can dump process memory into corefile as well.
2622 */
2623 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2624 abi_ulong addr;
2625 abi_ulong end;
2626
2627 end = vma->vma_start + vma_dump_size(vma);
2628
2629 for (addr = vma->vma_start; addr < end;
Richard Hendersond97ef722010-07-27 10:25:29 -07002630 addr += TARGET_PAGE_SIZE) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002631 char page[TARGET_PAGE_SIZE];
2632 int error;
2633
2634 /*
2635 * Read in page from target process memory and
2636 * write it to coredump file.
2637 */
2638 error = copy_from_user(page, addr, sizeof (page));
2639 if (error != 0) {
Aurelien Jarno49995e12009-12-19 20:28:23 +01002640 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
Richard Hendersond97ef722010-07-27 10:25:29 -07002641 addr);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002642 errno = -error;
2643 goto out;
2644 }
2645 if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2646 goto out;
2647 }
2648 }
2649
Richard Hendersond97ef722010-07-27 10:25:29 -07002650 out:
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002651 free_note_info(&info);
2652 if (mm != NULL)
2653 vma_delete(mm);
2654 (void) close(fd);
2655
2656 if (errno != 0)
2657 return (-errno);
2658 return (0);
2659}
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002660#endif /* USE_ELF_CORE_DUMP */
2661
pbrooke5fe0c52006-06-11 13:32:59 +00002662void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2663{
2664 init_thread(regs, infop);
2665}