blob: 3cbb1f4bb87679f7cec71509adf390ecd19f8689 [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 space allocated to elf interpreter */
833#define INTERP_MAP_SIZE (32 * 1024 * 1024)
834
835/* max code+data+bss+brk space allocated to ET_DYN executables */
836#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
837
bellard31e31b82003-02-18 22:55:36 +0000838/* Necessary parameters */
bellard54936002003-05-13 00:25:15 +0000839#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
840#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
841#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
bellard31e31b82003-02-18 22:55:36 +0000842
843#define INTERPRETER_NONE 0
844#define INTERPRETER_AOUT 1
845#define INTERPRETER_ELF 2
846
bellard15338fd2005-11-26 11:41:16 +0000847#define DLINFO_ITEMS 12
bellard31e31b82003-02-18 22:55:36 +0000848
bellard09bfb052003-04-10 00:03:40 +0000849static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
850{
Richard Hendersond97ef722010-07-27 10:25:29 -0700851 memcpy(to, from, n);
bellard09bfb052003-04-10 00:03:40 +0000852}
853
bellard31e31b82003-02-18 22:55:36 +0000854static int load_aout_interp(void * exptr, int interp_fd);
855
856#ifdef BSWAP_NEEDED
bellard92a31b12005-02-10 22:00:52 +0000857static void bswap_ehdr(struct elfhdr *ehdr)
bellard31e31b82003-02-18 22:55:36 +0000858{
Richard Hendersond97ef722010-07-27 10:25:29 -0700859 bswap16s(&ehdr->e_type); /* Object file type */
860 bswap16s(&ehdr->e_machine); /* Architecture */
861 bswap32s(&ehdr->e_version); /* Object file version */
862 bswaptls(&ehdr->e_entry); /* Entry point virtual address */
863 bswaptls(&ehdr->e_phoff); /* Program header table file offset */
864 bswaptls(&ehdr->e_shoff); /* Section header table file offset */
865 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
866 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
867 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
868 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
869 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
870 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
871 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
bellard31e31b82003-02-18 22:55:36 +0000872}
873
Richard Henderson991f8f02010-07-27 10:25:32 -0700874static void bswap_phdr(struct elf_phdr *phdr, int phnum)
bellard31e31b82003-02-18 22:55:36 +0000875{
Richard Henderson991f8f02010-07-27 10:25:32 -0700876 int i;
877 for (i = 0; i < phnum; ++i, ++phdr) {
878 bswap32s(&phdr->p_type); /* Segment type */
879 bswap32s(&phdr->p_flags); /* Segment flags */
880 bswaptls(&phdr->p_offset); /* Segment file offset */
881 bswaptls(&phdr->p_vaddr); /* Segment virtual address */
882 bswaptls(&phdr->p_paddr); /* Segment physical address */
883 bswaptls(&phdr->p_filesz); /* Segment size in file */
884 bswaptls(&phdr->p_memsz); /* Segment size in memory */
885 bswaptls(&phdr->p_align); /* Segment alignment */
886 }
bellard31e31b82003-02-18 22:55:36 +0000887}
bellard689f9362003-04-29 20:40:07 +0000888
Richard Henderson991f8f02010-07-27 10:25:32 -0700889static void bswap_shdr(struct elf_shdr *shdr, int shnum)
bellard689f9362003-04-29 20:40:07 +0000890{
Richard Henderson991f8f02010-07-27 10:25:32 -0700891 int i;
892 for (i = 0; i < shnum; ++i, ++shdr) {
893 bswap32s(&shdr->sh_name);
894 bswap32s(&shdr->sh_type);
895 bswaptls(&shdr->sh_flags);
896 bswaptls(&shdr->sh_addr);
897 bswaptls(&shdr->sh_offset);
898 bswaptls(&shdr->sh_size);
899 bswap32s(&shdr->sh_link);
900 bswap32s(&shdr->sh_info);
901 bswaptls(&shdr->sh_addralign);
902 bswaptls(&shdr->sh_entsize);
903 }
bellard689f9362003-04-29 20:40:07 +0000904}
905
j_mayer7a3148a2007-04-05 07:13:51 +0000906static void bswap_sym(struct elf_sym *sym)
bellard689f9362003-04-29 20:40:07 +0000907{
908 bswap32s(&sym->st_name);
j_mayer7a3148a2007-04-05 07:13:51 +0000909 bswaptls(&sym->st_value);
910 bswaptls(&sym->st_size);
bellard689f9362003-04-29 20:40:07 +0000911 bswap16s(&sym->st_shndx);
912}
Richard Henderson991f8f02010-07-27 10:25:32 -0700913#else
914static inline void bswap_ehdr(struct elfhdr *ehdr) { }
915static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
916static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
917static inline void bswap_sym(struct elf_sym *sym) { }
bellard31e31b82003-02-18 22:55:36 +0000918#endif
919
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300920#ifdef USE_ELF_CORE_DUMP
921static int elf_core_dump(int, const CPUState *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300922#endif /* USE_ELF_CORE_DUMP */
923
bellard31e31b82003-02-18 22:55:36 +0000924/*
pbrooke5fe0c52006-06-11 13:32:59 +0000925 * 'copy_elf_strings()' copies argument/envelope strings from user
bellard31e31b82003-02-18 22:55:36 +0000926 * memory to free pages in kernel mem. These are in a format ready
927 * to be put directly into the top of new user memory.
928 *
929 */
blueswir1992f48a2007-10-14 16:27:31 +0000930static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
931 abi_ulong p)
bellard31e31b82003-02-18 22:55:36 +0000932{
933 char *tmp, *tmp1, *pag = NULL;
934 int len, offset = 0;
935
936 if (!p) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700937 return 0; /* bullet-proofing */
bellard31e31b82003-02-18 22:55:36 +0000938 }
939 while (argc-- > 0) {
bellardedf779f2004-02-22 13:40:13 +0000940 tmp = argv[argc];
941 if (!tmp) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700942 fprintf(stderr, "VFS: argc is wrong");
943 exit(-1);
944 }
bellardedf779f2004-02-22 13:40:13 +0000945 tmp1 = tmp;
Richard Hendersond97ef722010-07-27 10:25:29 -0700946 while (*tmp++);
947 len = tmp - tmp1;
948 if (p < len) { /* this shouldn't happen - 128kB */
949 return 0;
950 }
951 while (len) {
952 --p; --tmp; --len;
953 if (--offset < 0) {
954 offset = p % TARGET_PAGE_SIZE;
pbrook53a59602006-03-25 19:31:22 +0000955 pag = (char *)page[p/TARGET_PAGE_SIZE];
bellard44a91ca2004-01-18 22:05:44 +0000956 if (!pag) {
pbrook53a59602006-03-25 19:31:22 +0000957 pag = (char *)malloc(TARGET_PAGE_SIZE);
j_mayer4118a972007-09-27 04:10:43 +0000958 memset(pag, 0, TARGET_PAGE_SIZE);
pbrook53a59602006-03-25 19:31:22 +0000959 page[p/TARGET_PAGE_SIZE] = pag;
bellard44a91ca2004-01-18 22:05:44 +0000960 if (!pag)
961 return 0;
Richard Hendersond97ef722010-07-27 10:25:29 -0700962 }
963 }
964 if (len == 0 || offset == 0) {
965 *(pag + offset) = *tmp;
966 }
967 else {
968 int bytes_to_copy = (len > offset) ? offset : len;
969 tmp -= bytes_to_copy;
970 p -= bytes_to_copy;
971 offset -= bytes_to_copy;
972 len -= bytes_to_copy;
973 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
974 }
975 }
bellard31e31b82003-02-18 22:55:36 +0000976 }
977 return p;
978}
979
blueswir1992f48a2007-10-14 16:27:31 +0000980static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
981 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +0000982{
blueswir1992f48a2007-10-14 16:27:31 +0000983 abi_ulong stack_base, size, error;
bellard31e31b82003-02-18 22:55:36 +0000984 int i;
bellard31e31b82003-02-18 22:55:36 +0000985
986 /* Create enough stack to hold everything. If we don't use
987 * it for args, we'll use it for something else...
988 */
Richard Henderson703e0e82010-03-19 14:21:13 -0700989 size = guest_stack_size;
bellard54936002003-05-13 00:25:15 +0000990 if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
991 size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
ths5fafdf22007-09-16 21:08:06 +0000992 error = target_mmap(0,
bellard83fb7ad2004-07-05 21:25:26 +0000993 size + qemu_host_page_size,
bellard54936002003-05-13 00:25:15 +0000994 PROT_READ | PROT_WRITE,
995 MAP_PRIVATE | MAP_ANONYMOUS,
996 -1, 0);
bellard09bfb052003-04-10 00:03:40 +0000997 if (error == -1) {
998 perror("stk mmap");
999 exit(-1);
bellard31e31b82003-02-18 22:55:36 +00001000 }
bellard09bfb052003-04-10 00:03:40 +00001001 /* we reserve one extra page at the top of the stack as guard */
bellard83fb7ad2004-07-05 21:25:26 +00001002 target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
bellard09bfb052003-04-10 00:03:40 +00001003
Paul Brook97374d32010-06-16 13:03:51 +01001004 info->stack_limit = error;
bellard54936002003-05-13 00:25:15 +00001005 stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
bellard09bfb052003-04-10 00:03:40 +00001006 p += stack_base;
1007
bellard31e31b82003-02-18 22:55:36 +00001008 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001009 if (bprm->page[i]) {
1010 info->rss++;
bellard579a97f2007-11-11 14:26:47 +00001011 /* FIXME - check return value of memcpy_to_target() for failure */
Richard Hendersond97ef722010-07-27 10:25:29 -07001012 memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
1013 free(bprm->page[i]);
1014 }
pbrook53a59602006-03-25 19:31:22 +00001015 stack_base += TARGET_PAGE_SIZE;
bellard31e31b82003-02-18 22:55:36 +00001016 }
1017 return p;
1018}
1019
Richard Hendersoncf129f32010-07-27 10:25:27 -07001020/* Map and zero the bss. We need to explicitly zero any fractional pages
1021 after the data section (i.e. bss). */
1022static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
bellard31e31b82003-02-18 22:55:36 +00001023{
Richard Hendersoncf129f32010-07-27 10:25:27 -07001024 uintptr_t host_start, host_map_start, host_end;
bellard31e31b82003-02-18 22:55:36 +00001025
Richard Hendersoncf129f32010-07-27 10:25:27 -07001026 last_bss = TARGET_PAGE_ALIGN(last_bss);
bellard31e31b82003-02-18 22:55:36 +00001027
Richard Hendersoncf129f32010-07-27 10:25:27 -07001028 /* ??? There is confusion between qemu_real_host_page_size and
1029 qemu_host_page_size here and elsewhere in target_mmap, which
1030 may lead to the end of the data section mapping from the file
1031 not being mapped. At least there was an explicit test and
1032 comment for that here, suggesting that "the file size must
1033 be known". The comment probably pre-dates the introduction
1034 of the fstat system call in target_mmap which does in fact
1035 find out the size. What isn't clear is if the workaround
1036 here is still actually needed. For now, continue with it,
1037 but merge it with the "normal" mmap that would allocate the bss. */
bellard31e31b82003-02-18 22:55:36 +00001038
Richard Hendersoncf129f32010-07-27 10:25:27 -07001039 host_start = (uintptr_t) g2h(elf_bss);
1040 host_end = (uintptr_t) g2h(last_bss);
1041 host_map_start = (host_start + qemu_real_host_page_size - 1);
1042 host_map_start &= -qemu_real_host_page_size;
ths768a4a32006-12-14 13:32:11 +00001043
Richard Hendersoncf129f32010-07-27 10:25:27 -07001044 if (host_map_start < host_end) {
1045 void *p = mmap((void *)host_map_start, host_end - host_map_start,
1046 prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1047 if (p == MAP_FAILED) {
1048 perror("cannot mmap brk");
1049 exit(-1);
bellard853d6f72003-09-30 20:58:32 +00001050 }
1051
Richard Hendersoncf129f32010-07-27 10:25:27 -07001052 /* Since we didn't use target_mmap, make sure to record
1053 the validity of the pages with qemu. */
1054 page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
1055 }
bellard31e31b82003-02-18 22:55:36 +00001056
Richard Hendersoncf129f32010-07-27 10:25:27 -07001057 if (host_start < host_map_start) {
1058 memset((void *)host_start, 0, host_map_start - host_start);
1059 }
1060}
bellardedf779f2004-02-22 13:40:13 +00001061
blueswir1992f48a2007-10-14 16:27:31 +00001062static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
1063 struct elfhdr * exec,
1064 abi_ulong load_addr,
1065 abi_ulong load_bias,
1066 abi_ulong interp_load_addr, int ibcs,
1067 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +00001068{
Richard Hendersond97ef722010-07-27 10:25:29 -07001069 abi_ulong sp;
1070 int size;
1071 abi_ulong u_platform;
1072 const char *k_platform;
1073 const int n = sizeof(elf_addr_t);
pbrook53a59602006-03-25 19:31:22 +00001074
Richard Hendersond97ef722010-07-27 10:25:29 -07001075 sp = p;
1076 u_platform = 0;
1077 k_platform = ELF_PLATFORM;
1078 if (k_platform) {
1079 size_t len = strlen(k_platform) + 1;
1080 sp -= (len + n - 1) & ~(n - 1);
1081 u_platform = sp;
1082 /* FIXME - check return value of memcpy_to_target() for failure */
1083 memcpy_to_target(sp, k_platform, len);
1084 }
1085 /*
1086 * Force 16 byte _final_ alignment here for generality.
1087 */
1088 sp = sp &~ (abi_ulong)15;
1089 size = (DLINFO_ITEMS + 1) * 2;
1090 if (k_platform)
1091 size += 2;
bellardf5155282004-01-04 15:46:50 +00001092#ifdef DLINFO_ARCH_ITEMS
Richard Hendersond97ef722010-07-27 10:25:29 -07001093 size += DLINFO_ARCH_ITEMS * 2;
bellardf5155282004-01-04 15:46:50 +00001094#endif
Richard Hendersond97ef722010-07-27 10:25:29 -07001095 size += envc + argc + 2;
1096 size += (!ibcs ? 3 : 1); /* argc itself */
1097 size *= n;
1098 if (size & 15)
1099 sp -= 16 - (size & 15);
ths3b46e622007-09-17 08:09:54 +00001100
Richard Hendersond97ef722010-07-27 10:25:29 -07001101 /* This is correct because Linux defines
1102 * elf_addr_t as Elf32_Off / Elf64_Off
1103 */
1104#define NEW_AUX_ENT(id, val) do { \
1105 sp -= n; put_user_ual(val, sp); \
1106 sp -= n; put_user_ual(id, sp); \
1107 } while(0)
bellard2f619692007-11-16 10:46:05 +00001108
Richard Hendersond97ef722010-07-27 10:25:29 -07001109 NEW_AUX_ENT (AT_NULL, 0);
bellardf5155282004-01-04 15:46:50 +00001110
Richard Hendersond97ef722010-07-27 10:25:29 -07001111 /* There must be exactly DLINFO_ITEMS entries here. */
1112 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
1113 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1114 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1115 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
1116 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
1117 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
1118 NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
1119 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1120 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1121 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1122 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1123 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1124 NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
1125 if (k_platform)
1126 NEW_AUX_ENT(AT_PLATFORM, u_platform);
bellardf5155282004-01-04 15:46:50 +00001127#ifdef ARCH_DLINFO
Richard Hendersond97ef722010-07-27 10:25:29 -07001128 /*
1129 * ARCH_DLINFO must come last so platform specific code can enforce
1130 * special alignment requirements on the AUXV if necessary (eg. PPC).
1131 */
1132 ARCH_DLINFO;
bellardf5155282004-01-04 15:46:50 +00001133#endif
1134#undef NEW_AUX_ENT
1135
Richard Hendersond97ef722010-07-27 10:25:29 -07001136 info->saved_auxv = sp;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001137
Richard Hendersond97ef722010-07-27 10:25:29 -07001138 sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
1139 return sp;
bellard31e31b82003-02-18 22:55:36 +00001140}
1141
1142
blueswir1992f48a2007-10-14 16:27:31 +00001143static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
1144 int interpreter_fd,
Richard Henderson9955ffa2010-07-27 10:25:30 -07001145 abi_ulong *interp_load_addr,
1146 char bprm_buf[BPRM_BUF_SIZE])
bellard31e31b82003-02-18 22:55:36 +00001147{
Richard Hendersond97ef722010-07-27 10:25:29 -07001148 struct elf_phdr *elf_phdata = NULL;
1149 struct elf_phdr *eppnt;
1150 abi_ulong load_addr = 0;
1151 int load_addr_set = 0;
1152 int retval;
1153 abi_ulong error;
1154 int i;
ths5fafdf22007-09-16 21:08:06 +00001155
Richard Hendersond97ef722010-07-27 10:25:29 -07001156 error = 0;
bellard31e31b82003-02-18 22:55:36 +00001157
Richard Hendersond97ef722010-07-27 10:25:29 -07001158 bswap_ehdr(interp_elf_ex);
Richard Hendersond97ef722010-07-27 10:25:29 -07001159 /* First of all, some simple consistency checks */
1160 if ((interp_elf_ex->e_type != ET_EXEC &&
1161 interp_elf_ex->e_type != ET_DYN) ||
1162 !elf_check_arch(interp_elf_ex->e_machine)) {
1163 return ~((abi_ulong)0UL);
1164 }
ths5fafdf22007-09-16 21:08:06 +00001165
bellard644c4332003-03-24 23:00:36 +00001166
Richard Hendersond97ef722010-07-27 10:25:29 -07001167 /* Now read in all of the header information */
ths5fafdf22007-09-16 21:08:06 +00001168
Richard Hendersond97ef722010-07-27 10:25:29 -07001169 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
1170 return ~(abi_ulong)0UL;
ths5fafdf22007-09-16 21:08:06 +00001171
Richard Hendersond97ef722010-07-27 10:25:29 -07001172 elf_phdata = (struct elf_phdr *)
1173 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
bellard31e31b82003-02-18 22:55:36 +00001174
Richard Hendersond97ef722010-07-27 10:25:29 -07001175 if (!elf_phdata)
1176 return ~((abi_ulong)0UL);
ths5fafdf22007-09-16 21:08:06 +00001177
Richard Hendersond97ef722010-07-27 10:25:29 -07001178 /*
1179 * If the size of this structure has changed, then punt, since
1180 * we will be doing the wrong thing.
1181 */
1182 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
1183 free(elf_phdata);
1184 return ~((abi_ulong)0UL);
1185 }
bellard31e31b82003-02-18 22:55:36 +00001186
Richard Henderson9955ffa2010-07-27 10:25:30 -07001187 i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
1188 if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
1189 memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
1190 } else {
1191 retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
1192 if (retval != i) {
1193 perror("load_elf_interp");
1194 exit(-1);
1195 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001196 }
Richard Henderson991f8f02010-07-27 10:25:32 -07001197 bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
bellard09bfb052003-04-10 00:03:40 +00001198
Richard Hendersond97ef722010-07-27 10:25:29 -07001199 if (interp_elf_ex->e_type == ET_DYN) {
1200 /* in order to avoid hardcoding the interpreter load
1201 address in qemu, we allocate a big enough memory zone */
1202 error = target_mmap(0, INTERP_MAP_SIZE,
1203 PROT_NONE, MAP_PRIVATE | MAP_ANON,
1204 -1, 0);
1205 if (error == -1) {
1206 perror("mmap");
1207 exit(-1);
1208 }
1209 load_addr = error;
1210 load_addr_set = 1;
1211 }
1212
1213 eppnt = elf_phdata;
1214 for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
1215 if (eppnt->p_type == PT_LOAD) {
1216 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
1217 int elf_prot = 0;
1218 abi_ulong vaddr = 0;
1219
1220 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
1221 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1222 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1223 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
1224 elf_type |= MAP_FIXED;
1225 vaddr = eppnt->p_vaddr;
bellard09bfb052003-04-10 00:03:40 +00001226 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001227 error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
1228 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
1229 elf_prot,
1230 elf_type,
1231 interpreter_fd,
1232 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
bellard09bfb052003-04-10 00:03:40 +00001233
Richard Hendersond97ef722010-07-27 10:25:29 -07001234 if (error == -1) {
1235 /* Real error */
1236 close(interpreter_fd);
1237 free(elf_phdata);
1238 return ~((abi_ulong)0UL);
1239 }
bellard31e31b82003-02-18 22:55:36 +00001240
Richard Hendersond97ef722010-07-27 10:25:29 -07001241 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
1242 load_addr = error;
1243 load_addr_set = 1;
1244 }
bellard31e31b82003-02-18 22:55:36 +00001245
Richard Hendersoncf129f32010-07-27 10:25:27 -07001246 /* If the load segment requests extra zeros (e.g. bss), map it. */
1247 if (eppnt->p_filesz < eppnt->p_memsz) {
1248 abi_ulong base = load_addr + eppnt->p_vaddr;
1249 zero_bss(base + eppnt->p_filesz,
1250 base + eppnt->p_memsz, elf_prot);
1251 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001252 }
ths5fafdf22007-09-16 21:08:06 +00001253
Richard Hendersond97ef722010-07-27 10:25:29 -07001254 /* Now use mmap to map the library into memory. */
bellard31e31b82003-02-18 22:55:36 +00001255
Richard Hendersond97ef722010-07-27 10:25:29 -07001256 close(interpreter_fd);
1257 free(elf_phdata);
bellard31e31b82003-02-18 22:55:36 +00001258
Richard Hendersond97ef722010-07-27 10:25:29 -07001259 *interp_load_addr = load_addr;
1260 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
bellard31e31b82003-02-18 22:55:36 +00001261}
1262
pbrook49918a72008-10-22 15:11:31 +00001263static int symfind(const void *s0, const void *s1)
1264{
1265 struct elf_sym *key = (struct elf_sym *)s0;
1266 struct elf_sym *sym = (struct elf_sym *)s1;
1267 int result = 0;
1268 if (key->st_value < sym->st_value) {
1269 result = -1;
Laurent Desnoguesec822002009-07-30 19:23:49 +02001270 } else if (key->st_value >= sym->st_value + sym->st_size) {
pbrook49918a72008-10-22 15:11:31 +00001271 result = 1;
1272 }
1273 return result;
1274}
1275
1276static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
1277{
1278#if ELF_CLASS == ELFCLASS32
1279 struct elf_sym *syms = s->disas_symtab.elf32;
1280#else
1281 struct elf_sym *syms = s->disas_symtab.elf64;
1282#endif
1283
1284 // binary search
1285 struct elf_sym key;
1286 struct elf_sym *sym;
1287
1288 key.st_value = orig_addr;
1289
1290 sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
Blue Swirl7cba04f2009-08-01 10:13:20 +00001291 if (sym != NULL) {
pbrook49918a72008-10-22 15:11:31 +00001292 return s->disas_strtab + sym->st_name;
1293 }
1294
1295 return "";
1296}
1297
1298/* FIXME: This should use elf_ops.h */
1299static int symcmp(const void *s0, const void *s1)
1300{
1301 struct elf_sym *sym0 = (struct elf_sym *)s0;
1302 struct elf_sym *sym1 = (struct elf_sym *)s1;
1303 return (sym0->st_value < sym1->st_value)
1304 ? -1
1305 : ((sym0->st_value > sym1->st_value) ? 1 : 0);
1306}
1307
bellard689f9362003-04-29 20:40:07 +00001308/* Best attempt to load symbols from this ELF object. */
1309static void load_symbols(struct elfhdr *hdr, int fd)
1310{
pbrook49918a72008-10-22 15:11:31 +00001311 unsigned int i, nsyms;
bellard689f9362003-04-29 20:40:07 +00001312 struct elf_shdr sechdr, symtab, strtab;
1313 char *strings;
bellarde80cfcf2004-12-19 23:18:01 +00001314 struct syminfo *s;
pbrook49918a72008-10-22 15:11:31 +00001315 struct elf_sym *syms;
bellard31e31b82003-02-18 22:55:36 +00001316
bellard689f9362003-04-29 20:40:07 +00001317 lseek(fd, hdr->e_shoff, SEEK_SET);
1318 for (i = 0; i < hdr->e_shnum; i++) {
pbrook49918a72008-10-22 15:11:31 +00001319 if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
1320 return;
Richard Henderson991f8f02010-07-27 10:25:32 -07001321 bswap_shdr(&sechdr, 1);
pbrook49918a72008-10-22 15:11:31 +00001322 if (sechdr.sh_type == SHT_SYMTAB) {
1323 symtab = sechdr;
1324 lseek(fd, hdr->e_shoff
1325 + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
1326 if (read(fd, &strtab, sizeof(strtab))
1327 != sizeof(strtab))
1328 return;
Richard Henderson991f8f02010-07-27 10:25:32 -07001329 bswap_shdr(&strtab, 1);
pbrook49918a72008-10-22 15:11:31 +00001330 goto found;
1331 }
bellard689f9362003-04-29 20:40:07 +00001332 }
1333 return; /* Shouldn't happen... */
1334
1335 found:
1336 /* Now know where the strtab and symtab are. Snarf them. */
bellarde80cfcf2004-12-19 23:18:01 +00001337 s = malloc(sizeof(*s));
pbrook49918a72008-10-22 15:11:31 +00001338 syms = malloc(symtab.sh_size);
1339 if (!syms)
1340 return;
bellarde80cfcf2004-12-19 23:18:01 +00001341 s->disas_strtab = strings = malloc(strtab.sh_size);
pbrook49918a72008-10-22 15:11:31 +00001342 if (!s->disas_strtab)
1343 return;
ths5fafdf22007-09-16 21:08:06 +00001344
bellard689f9362003-04-29 20:40:07 +00001345 lseek(fd, symtab.sh_offset, SEEK_SET);
pbrook49918a72008-10-22 15:11:31 +00001346 if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
1347 return;
bellard689f9362003-04-29 20:40:07 +00001348
pbrook49918a72008-10-22 15:11:31 +00001349 nsyms = symtab.sh_size / sizeof(struct elf_sym);
1350
1351 i = 0;
1352 while (i < nsyms) {
pbrook49918a72008-10-22 15:11:31 +00001353 bswap_sym(syms + i);
pbrook49918a72008-10-22 15:11:31 +00001354 // Throw away entries which we do not need.
1355 if (syms[i].st_shndx == SHN_UNDEF ||
Richard Hendersond97ef722010-07-27 10:25:29 -07001356 syms[i].st_shndx >= SHN_LORESERVE ||
1357 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
pbrook49918a72008-10-22 15:11:31 +00001358 nsyms--;
1359 if (i < nsyms) {
1360 syms[i] = syms[nsyms];
1361 }
1362 continue;
1363 }
1364#if defined(TARGET_ARM) || defined (TARGET_MIPS)
1365 /* The bottom address bit marks a Thumb or MIPS16 symbol. */
1366 syms[i].st_value &= ~(target_ulong)1;
blueswir10774bed2007-07-05 13:23:29 +00001367#endif
pbrook49918a72008-10-22 15:11:31 +00001368 i++;
blueswir10774bed2007-07-05 13:23:29 +00001369 }
pbrook49918a72008-10-22 15:11:31 +00001370 syms = realloc(syms, nsyms * sizeof(*syms));
bellard689f9362003-04-29 20:40:07 +00001371
pbrook49918a72008-10-22 15:11:31 +00001372 qsort(syms, nsyms, sizeof(*syms), symcmp);
1373
bellard689f9362003-04-29 20:40:07 +00001374 lseek(fd, strtab.sh_offset, SEEK_SET);
1375 if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
pbrook49918a72008-10-22 15:11:31 +00001376 return;
1377 s->disas_num_syms = nsyms;
1378#if ELF_CLASS == ELFCLASS32
1379 s->disas_symtab.elf32 = syms;
Paul Brook9f9f0302010-03-01 03:55:48 +00001380 s->lookup_symbol = lookup_symbolxx;
pbrook49918a72008-10-22 15:11:31 +00001381#else
1382 s->disas_symtab.elf64 = syms;
Paul Brook9f9f0302010-03-01 03:55:48 +00001383 s->lookup_symbol = lookup_symbolxx;
pbrook49918a72008-10-22 15:11:31 +00001384#endif
bellarde80cfcf2004-12-19 23:18:01 +00001385 s->next = syminfos;
1386 syminfos = s;
bellard689f9362003-04-29 20:40:07 +00001387}
bellard31e31b82003-02-18 22:55:36 +00001388
pbrooke5fe0c52006-06-11 13:32:59 +00001389int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1390 struct image_info * info)
bellard31e31b82003-02-18 22:55:36 +00001391{
1392 struct elfhdr elf_ex;
1393 struct elfhdr interp_elf_ex;
1394 struct exec interp_ex;
1395 int interpreter_fd = -1; /* avoid warning */
blueswir1992f48a2007-10-14 16:27:31 +00001396 abi_ulong load_addr, load_bias;
bellard31e31b82003-02-18 22:55:36 +00001397 int load_addr_set = 0;
1398 unsigned int interpreter_type = INTERPRETER_NONE;
1399 unsigned char ibcs2_interpreter;
1400 int i;
blueswir1992f48a2007-10-14 16:27:31 +00001401 abi_ulong mapped_addr;
bellard31e31b82003-02-18 22:55:36 +00001402 struct elf_phdr * elf_ppnt;
1403 struct elf_phdr *elf_phdata;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001404 abi_ulong k, elf_brk;
bellard31e31b82003-02-18 22:55:36 +00001405 int retval;
1406 char * elf_interpreter;
blueswir1992f48a2007-10-14 16:27:31 +00001407 abi_ulong elf_entry, interp_load_addr = 0;
bellard31e31b82003-02-18 22:55:36 +00001408 int status;
blueswir1992f48a2007-10-14 16:27:31 +00001409 abi_ulong start_code, end_code, start_data, end_data;
1410 abi_ulong reloc_func_desc = 0;
1411 abi_ulong elf_stack;
bellard31e31b82003-02-18 22:55:36 +00001412 char passed_fileno[6];
1413
1414 ibcs2_interpreter = 0;
1415 status = 0;
1416 load_addr = 0;
bellard09bfb052003-04-10 00:03:40 +00001417 load_bias = 0;
bellard31e31b82003-02-18 22:55:36 +00001418 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
bellard31e31b82003-02-18 22:55:36 +00001419 bswap_ehdr(&elf_ex);
bellard31e31b82003-02-18 22:55:36 +00001420
bellard31e31b82003-02-18 22:55:36 +00001421 /* First of all, some simple consistency checks */
1422 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
Richard Hendersond97ef722010-07-27 10:25:29 -07001423 (! elf_check_arch(elf_ex.e_machine))) {
1424 return -ENOEXEC;
bellard31e31b82003-02-18 22:55:36 +00001425 }
1426
pbrooke5fe0c52006-06-11 13:32:59 +00001427 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1428 bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1429 bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1430 if (!bprm->p) {
1431 retval = -E2BIG;
1432 }
1433
bellard31e31b82003-02-18 22:55:36 +00001434 /* Now read in all of the header information */
bellard31e31b82003-02-18 22:55:36 +00001435 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
1436 if (elf_phdata == NULL) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001437 return -ENOMEM;
bellard31e31b82003-02-18 22:55:36 +00001438 }
1439
Richard Henderson9955ffa2010-07-27 10:25:30 -07001440 i = elf_ex.e_phnum * sizeof(struct elf_phdr);
1441 if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
1442 memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
1443 } else {
1444 retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
1445 if (retval != i) {
1446 perror("load_elf_binary");
1447 exit(-1);
1448 }
bellard31e31b82003-02-18 22:55:36 +00001449 }
Richard Henderson991f8f02010-07-27 10:25:32 -07001450 bswap_phdr(elf_phdata, elf_ex.e_phnum);
bellard31e31b82003-02-18 22:55:36 +00001451
bellard31e31b82003-02-18 22:55:36 +00001452 elf_brk = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001453 elf_stack = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001454 elf_interpreter = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00001455 start_code = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001456 end_code = 0;
j_mayer863cf0b2007-10-07 15:59:45 +00001457 start_data = 0;
bellard31e31b82003-02-18 22:55:36 +00001458 end_data = 0;
blueswir198448f52008-09-30 18:16:09 +00001459 interp_ex.a_info = 0;
bellard31e31b82003-02-18 22:55:36 +00001460
Richard Henderson991f8f02010-07-27 10:25:32 -07001461 elf_ppnt = elf_phdata;
bellard31e31b82003-02-18 22:55:36 +00001462 for(i=0;i < elf_ex.e_phnum; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001463 if (elf_ppnt->p_type == PT_INTERP) {
1464 if ( elf_interpreter != NULL )
1465 {
1466 free (elf_phdata);
1467 free(elf_interpreter);
1468 close(bprm->fd);
1469 return -EINVAL;
1470 }
bellard31e31b82003-02-18 22:55:36 +00001471
Richard Hendersond97ef722010-07-27 10:25:29 -07001472 /* This is the program interpreter used for
1473 * shared libraries - for now assume that this
1474 * is an a.out format binary
1475 */
bellard31e31b82003-02-18 22:55:36 +00001476
Richard Hendersond97ef722010-07-27 10:25:29 -07001477 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
bellard31e31b82003-02-18 22:55:36 +00001478
Richard Hendersond97ef722010-07-27 10:25:29 -07001479 if (elf_interpreter == NULL) {
1480 free (elf_phdata);
1481 close(bprm->fd);
1482 return -ENOMEM;
1483 }
bellard31e31b82003-02-18 22:55:36 +00001484
Richard Henderson9955ffa2010-07-27 10:25:30 -07001485 if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
1486 memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
1487 elf_ppnt->p_filesz);
1488 } else {
1489 retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
1490 elf_ppnt->p_offset);
1491 if (retval != elf_ppnt->p_filesz) {
1492 perror("load_elf_binary2");
1493 exit(-1);
1494 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001495 }
bellard31e31b82003-02-18 22:55:36 +00001496
Richard Hendersond97ef722010-07-27 10:25:29 -07001497 /* If the program interpreter is one of these two,
1498 then assume an iBCS2 image. Otherwise assume
1499 a native linux image. */
bellard31e31b82003-02-18 22:55:36 +00001500
Richard Hendersond97ef722010-07-27 10:25:29 -07001501 /* JRP - Need to add X86 lib dir stuff here... */
bellard31e31b82003-02-18 22:55:36 +00001502
Richard Hendersond97ef722010-07-27 10:25:29 -07001503 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
1504 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
1505 ibcs2_interpreter = 1;
1506 }
bellard31e31b82003-02-18 22:55:36 +00001507
Richard Henderson9955ffa2010-07-27 10:25:30 -07001508 retval = open(path(elf_interpreter), O_RDONLY);
1509 if (retval < 0) {
1510 perror(elf_interpreter);
1511 exit(-1);
Richard Hendersond97ef722010-07-27 10:25:29 -07001512 }
Richard Henderson9955ffa2010-07-27 10:25:30 -07001513 interpreter_fd = retval;
bellard31e31b82003-02-18 22:55:36 +00001514
Richard Henderson9955ffa2010-07-27 10:25:30 -07001515 retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
Richard Hendersond97ef722010-07-27 10:25:29 -07001516 if (retval < 0) {
1517 perror("load_elf_binary3");
1518 exit(-1);
Richard Hendersond97ef722010-07-27 10:25:29 -07001519 }
Richard Henderson9955ffa2010-07-27 10:25:30 -07001520 if (retval < BPRM_BUF_SIZE) {
1521 memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
1522 }
1523
1524 interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
1525 interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
Richard Hendersond97ef722010-07-27 10:25:29 -07001526 }
1527 elf_ppnt++;
bellard31e31b82003-02-18 22:55:36 +00001528 }
1529
1530 /* Some simple consistency checks for the interpreter */
1531 if (elf_interpreter){
Richard Hendersond97ef722010-07-27 10:25:29 -07001532 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
bellard31e31b82003-02-18 22:55:36 +00001533
Richard Hendersond97ef722010-07-27 10:25:29 -07001534 /* Now figure out which format our binary is */
1535 if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
1536 (N_MAGIC(interp_ex) != QMAGIC)) {
1537 interpreter_type = INTERPRETER_ELF;
1538 }
bellard31e31b82003-02-18 22:55:36 +00001539
Richard Hendersond97ef722010-07-27 10:25:29 -07001540 if (interp_elf_ex.e_ident[0] != 0x7f ||
blueswir1b55266b2008-09-20 08:07:15 +00001541 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001542 interpreter_type &= ~INTERPRETER_ELF;
1543 }
bellard31e31b82003-02-18 22:55:36 +00001544
Richard Hendersond97ef722010-07-27 10:25:29 -07001545 if (!interpreter_type) {
1546 free(elf_interpreter);
1547 free(elf_phdata);
1548 close(bprm->fd);
1549 return -ELIBBAD;
1550 }
bellard31e31b82003-02-18 22:55:36 +00001551 }
1552
1553 /* OK, we are done with that, now set up the arg stuff,
1554 and then start this sucker up */
1555
pbrooke5fe0c52006-06-11 13:32:59 +00001556 {
Richard Hendersond97ef722010-07-27 10:25:29 -07001557 char * passed_p;
bellard31e31b82003-02-18 22:55:36 +00001558
Richard Hendersond97ef722010-07-27 10:25:29 -07001559 if (interpreter_type == INTERPRETER_AOUT) {
1560 snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
1561 passed_p = passed_fileno;
bellard31e31b82003-02-18 22:55:36 +00001562
Richard Hendersond97ef722010-07-27 10:25:29 -07001563 if (elf_interpreter) {
1564 bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
1565 bprm->argc++;
1566 }
1567 }
1568 if (!bprm->p) {
1569 if (elf_interpreter) {
1570 free(elf_interpreter);
1571 }
1572 free (elf_phdata);
1573 close(bprm->fd);
1574 return -E2BIG;
1575 }
bellard31e31b82003-02-18 22:55:36 +00001576 }
1577
1578 /* OK, This is the point of no return */
1579 info->end_data = 0;
1580 info->end_code = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001581 info->start_mmap = (abi_ulong)ELF_START_MMAP;
bellard31e31b82003-02-18 22:55:36 +00001582 info->mmap = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001583 elf_entry = (abi_ulong) elf_ex.e_entry;
bellard31e31b82003-02-18 22:55:36 +00001584
Paul Brook379f6692009-07-17 12:48:08 +01001585#if defined(CONFIG_USE_GUEST_BASE)
1586 /*
1587 * In case where user has not explicitly set the guest_base, we
1588 * probe here that should we set it automatically.
1589 */
Paul Brook68a1c812010-05-29 02:27:35 +01001590 if (!(have_guest_base || reserved_va)) {
Paul Brook379f6692009-07-17 12:48:08 +01001591 /*
Paul Brookc581ded2010-05-05 16:32:59 +01001592 * Go through ELF program header table and find the address
1593 * range used by loadable segments. Check that this is available on
1594 * the host, and if not find a suitable value for guest_base. */
1595 abi_ulong app_start = ~0;
1596 abi_ulong app_end = 0;
1597 abi_ulong addr;
1598 unsigned long host_start;
1599 unsigned long real_start;
1600 unsigned long host_size;
Paul Brook379f6692009-07-17 12:48:08 +01001601 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
Richard Hendersond97ef722010-07-27 10:25:29 -07001602 i++, elf_ppnt++) {
Paul Brook379f6692009-07-17 12:48:08 +01001603 if (elf_ppnt->p_type != PT_LOAD)
1604 continue;
Paul Brookc581ded2010-05-05 16:32:59 +01001605 addr = elf_ppnt->p_vaddr;
1606 if (addr < app_start) {
1607 app_start = addr;
1608 }
1609 addr += elf_ppnt->p_memsz;
1610 if (addr > app_end) {
1611 app_end = addr;
Paul Brook379f6692009-07-17 12:48:08 +01001612 }
1613 }
Paul Brookc581ded2010-05-05 16:32:59 +01001614
1615 /* If we don't have any loadable segments then something
1616 is very wrong. */
1617 assert(app_start < app_end);
1618
1619 /* Round addresses to page boundaries. */
1620 app_start = app_start & qemu_host_page_mask;
1621 app_end = HOST_PAGE_ALIGN(app_end);
1622 if (app_start < mmap_min_addr) {
1623 host_start = HOST_PAGE_ALIGN(mmap_min_addr);
1624 } else {
1625 host_start = app_start;
1626 if (host_start != app_start) {
1627 fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
1628 abort();
1629 }
1630 }
1631 host_size = app_end - app_start;
1632 while (1) {
1633 /* Do not use mmap_find_vma here because that is limited to the
1634 guest address space. We are going to make the
1635 guest address space fit whatever we're given. */
1636 real_start = (unsigned long)mmap((void *)host_start, host_size,
1637 PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
1638 if (real_start == (unsigned long)-1) {
1639 fprintf(stderr, "qemu: Virtual memory exausted\n");
1640 abort();
1641 }
1642 if (real_start == host_start) {
1643 break;
1644 }
1645 /* That address didn't work. Unmap and try a different one.
1646 The address the host picked because is typically
1647 right at the top of the host address space and leaves the
1648 guest with no usable address space. Resort to a linear search.
1649 We already compensated for mmap_min_addr, so this should not
1650 happen often. Probably means we got unlucky and host address
1651 space randomization put a shared library somewhere
1652 inconvenient. */
1653 munmap((void *)real_start, host_size);
1654 host_start += qemu_host_page_size;
1655 if (host_start == app_start) {
1656 /* Theoretically possible if host doesn't have any
1657 suitably aligned areas. Normally the first mmap will
1658 fail. */
1659 fprintf(stderr, "qemu: Unable to find space for application\n");
1660 abort();
1661 }
1662 }
1663 qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
1664 " to 0x%lx\n", app_start, real_start);
1665 guest_base = real_start - app_start;
Paul Brook379f6692009-07-17 12:48:08 +01001666 }
1667#endif /* CONFIG_USE_GUEST_BASE */
1668
bellard31e31b82003-02-18 22:55:36 +00001669 /* Do this so that we can load the interpreter, if need be. We will
1670 change some of these later */
1671 info->rss = 0;
1672 bprm->p = setup_arg_pages(bprm->p, bprm, info);
1673 info->start_stack = bprm->p;
1674
1675 /* Now we do a little grungy work by mmaping the ELF image into
1676 * the correct location in memory. At this point, we assume that
1677 * the image should be loaded at fixed address, not at a variable
1678 * address.
1679 */
1680
bellard31e31b82003-02-18 22:55:36 +00001681 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
bellard09bfb052003-04-10 00:03:40 +00001682 int elf_prot = 0;
1683 int elf_flags = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001684 abi_ulong error;
ths3b46e622007-09-17 08:09:54 +00001685
Richard Hendersond97ef722010-07-27 10:25:29 -07001686 if (elf_ppnt->p_type != PT_LOAD)
bellard09bfb052003-04-10 00:03:40 +00001687 continue;
ths3b46e622007-09-17 08:09:54 +00001688
bellard09bfb052003-04-10 00:03:40 +00001689 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
1690 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1691 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1692 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
1693 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
1694 elf_flags |= MAP_FIXED;
1695 } else if (elf_ex.e_type == ET_DYN) {
1696 /* Try and get dynamic programs out of the way of the default mmap
1697 base, as well as whatever program they might try to exec. This
1698 is because the brk will follow the loader, and is not movable. */
1699 /* NOTE: for qemu, we do a big mmap to get enough space
thse91c8a72007-06-03 13:35:16 +00001700 without hardcoding any address */
bellard54936002003-05-13 00:25:15 +00001701 error = target_mmap(0, ET_DYN_MAP_SIZE,
ths5fafdf22007-09-16 21:08:06 +00001702 PROT_NONE, MAP_PRIVATE | MAP_ANON,
bellard54936002003-05-13 00:25:15 +00001703 -1, 0);
bellard09bfb052003-04-10 00:03:40 +00001704 if (error == -1) {
1705 perror("mmap");
1706 exit(-1);
1707 }
bellard54936002003-05-13 00:25:15 +00001708 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001709 }
ths3b46e622007-09-17 08:09:54 +00001710
bellard54936002003-05-13 00:25:15 +00001711 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
1712 (elf_ppnt->p_filesz +
1713 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
1714 elf_prot,
1715 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
1716 bprm->fd,
ths5fafdf22007-09-16 21:08:06 +00001717 (elf_ppnt->p_offset -
bellard54936002003-05-13 00:25:15 +00001718 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
bellard09bfb052003-04-10 00:03:40 +00001719 if (error == -1) {
1720 perror("mmap");
1721 exit(-1);
1722 }
bellard31e31b82003-02-18 22:55:36 +00001723
1724#ifdef LOW_ELF_STACK
bellard54936002003-05-13 00:25:15 +00001725 if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
1726 elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
bellard31e31b82003-02-18 22:55:36 +00001727#endif
ths3b46e622007-09-17 08:09:54 +00001728
bellard09bfb052003-04-10 00:03:40 +00001729 if (!load_addr_set) {
1730 load_addr_set = 1;
1731 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1732 if (elf_ex.e_type == ET_DYN) {
1733 load_bias += error -
bellard54936002003-05-13 00:25:15 +00001734 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001735 load_addr += load_bias;
j_mayer84409dd2007-04-06 08:56:50 +00001736 reloc_func_desc = load_bias;
bellard09bfb052003-04-10 00:03:40 +00001737 }
1738 }
1739 k = elf_ppnt->p_vaddr;
ths5fafdf22007-09-16 21:08:06 +00001740 if (k < start_code)
bellard09bfb052003-04-10 00:03:40 +00001741 start_code = k;
j_mayer863cf0b2007-10-07 15:59:45 +00001742 if (start_data < k)
1743 start_data = k;
bellard09bfb052003-04-10 00:03:40 +00001744 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
bellard09bfb052003-04-10 00:03:40 +00001745 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
1746 end_code = k;
ths5fafdf22007-09-16 21:08:06 +00001747 if (end_data < k)
bellard09bfb052003-04-10 00:03:40 +00001748 end_data = k;
1749 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001750 if (k > elf_brk) {
1751 elf_brk = TARGET_PAGE_ALIGN(k);
1752 }
1753
1754 /* If the load segment requests extra zeros (e.g. bss), map it. */
1755 if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
1756 abi_ulong base = load_bias + elf_ppnt->p_vaddr;
1757 zero_bss(base + elf_ppnt->p_filesz,
1758 base + elf_ppnt->p_memsz, elf_prot);
1759 }
bellard31e31b82003-02-18 22:55:36 +00001760 }
1761
bellard09bfb052003-04-10 00:03:40 +00001762 elf_entry += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001763 elf_brk += load_bias;
1764 start_code += load_bias;
1765 end_code += load_bias;
j_mayer863cf0b2007-10-07 15:59:45 +00001766 start_data += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001767 end_data += load_bias;
1768
bellard31e31b82003-02-18 22:55:36 +00001769 if (elf_interpreter) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001770 if (interpreter_type & 1) {
1771 elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
Richard Henderson9955ffa2010-07-27 10:25:30 -07001772 } else if (interpreter_type & 2) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001773 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
Richard Henderson9955ffa2010-07-27 10:25:30 -07001774 &interp_load_addr, bprm->buf);
Richard Hendersond97ef722010-07-27 10:25:29 -07001775 }
j_mayer84409dd2007-04-06 08:56:50 +00001776 reloc_func_desc = interp_load_addr;
bellard31e31b82003-02-18 22:55:36 +00001777
Richard Hendersond97ef722010-07-27 10:25:29 -07001778 close(interpreter_fd);
1779 free(elf_interpreter);
bellard31e31b82003-02-18 22:55:36 +00001780
Richard Hendersond97ef722010-07-27 10:25:29 -07001781 if (elf_entry == ~((abi_ulong)0UL)) {
1782 printf("Unable to load interpreter\n");
1783 free(elf_phdata);
1784 exit(-1);
1785 return 0;
1786 }
bellard31e31b82003-02-18 22:55:36 +00001787 }
1788
1789 free(elf_phdata);
1790
aliguori93fcfe32009-01-15 22:34:14 +00001791 if (qemu_log_enabled())
Richard Hendersond97ef722010-07-27 10:25:29 -07001792 load_symbols(&elf_ex, bprm->fd);
bellard689f9362003-04-29 20:40:07 +00001793
bellard31e31b82003-02-18 22:55:36 +00001794 if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
1795 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
1796
1797#ifdef LOW_ELF_STACK
1798 info->start_stack = bprm->p = elf_stack - 4;
1799#endif
pbrook53a59602006-03-25 19:31:22 +00001800 bprm->p = create_elf_tables(bprm->p,
Richard Hendersond97ef722010-07-27 10:25:29 -07001801 bprm->argc,
1802 bprm->envc,
1803 &elf_ex,
1804 load_addr, load_bias,
1805 interp_load_addr,
1806 (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
1807 info);
j_mayer92a343d2007-09-27 01:14:15 +00001808 info->load_addr = reloc_func_desc;
bellard31e31b82003-02-18 22:55:36 +00001809 info->start_brk = info->brk = elf_brk;
1810 info->end_code = end_code;
1811 info->start_code = start_code;
j_mayer863cf0b2007-10-07 15:59:45 +00001812 info->start_data = start_data;
bellard31e31b82003-02-18 22:55:36 +00001813 info->end_data = end_data;
1814 info->start_stack = bprm->p;
1815
bellard31e31b82003-02-18 22:55:36 +00001816#if 0
1817 printf("(start_brk) %x\n" , info->start_brk);
1818 printf("(end_code) %x\n" , info->end_code);
1819 printf("(start_code) %x\n" , info->start_code);
1820 printf("(end_data) %x\n" , info->end_data);
1821 printf("(start_stack) %x\n" , info->start_stack);
1822 printf("(brk) %x\n" , info->brk);
1823#endif
1824
1825 if ( info->personality == PER_SVR4 )
1826 {
Richard Hendersond97ef722010-07-27 10:25:29 -07001827 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
1828 and some applications "depend" upon this behavior.
1829 Since we do not have the power to recompile these, we
1830 emulate the SVr4 behavior. Sigh. */
1831 mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
1832 MAP_FIXED | MAP_PRIVATE, -1, 0);
bellard31e31b82003-02-18 22:55:36 +00001833 }
1834
bellard31e31b82003-02-18 22:55:36 +00001835 info->entry = elf_entry;
1836
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001837#ifdef USE_ELF_CORE_DUMP
1838 bprm->core_dump = &elf_core_dump;
1839#endif
1840
bellard31e31b82003-02-18 22:55:36 +00001841 return 0;
1842}
1843
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001844#ifdef USE_ELF_CORE_DUMP
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001845/*
1846 * Definitions to generate Intel SVR4-like core files.
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001847 * These mostly have the same names as the SVR4 types with "target_elf_"
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001848 * tacked on the front to prevent clashes with linux definitions,
1849 * and the typedef forms have been avoided. This is mostly like
1850 * the SVR4 structure, but more Linuxy, with things that Linux does
1851 * not support and which gdb doesn't really use excluded.
1852 *
1853 * Fields we don't dump (their contents is zero) in linux-user qemu
1854 * are marked with XXX.
1855 *
1856 * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
1857 *
1858 * Porting ELF coredump for target is (quite) simple process. First you
Nathan Froyddd0a3652009-12-11 09:04:45 -08001859 * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001860 * the target resides):
1861 *
1862 * #define USE_ELF_CORE_DUMP
1863 *
1864 * Next you define type of register set used for dumping. ELF specification
1865 * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
1866 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001867 * typedef <target_regtype> target_elf_greg_t;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001868 * #define ELF_NREG <number of registers>
Anthony Liguoric227f092009-10-01 16:12:16 -05001869 * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001870 *
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001871 * Last step is to implement target specific function that copies registers
1872 * from given cpu into just specified register set. Prototype is:
1873 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001874 * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001875 * const CPUState *env);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001876 *
1877 * Parameters:
1878 * regs - copy register values into here (allocated and zeroed by caller)
1879 * env - copy registers from here
1880 *
1881 * Example for ARM target is provided in this file.
1882 */
1883
1884/* An ELF note in memory */
1885struct memelfnote {
1886 const char *name;
1887 size_t namesz;
1888 size_t namesz_rounded;
1889 int type;
1890 size_t datasz;
1891 void *data;
1892 size_t notesz;
1893};
1894
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001895struct target_elf_siginfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001896 int si_signo; /* signal number */
1897 int si_code; /* extra code */
1898 int si_errno; /* errno */
1899};
1900
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001901struct target_elf_prstatus {
1902 struct target_elf_siginfo pr_info; /* Info associated with signal */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001903 short pr_cursig; /* Current signal */
1904 target_ulong pr_sigpend; /* XXX */
1905 target_ulong pr_sighold; /* XXX */
Anthony Liguoric227f092009-10-01 16:12:16 -05001906 target_pid_t pr_pid;
1907 target_pid_t pr_ppid;
1908 target_pid_t pr_pgrp;
1909 target_pid_t pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001910 struct target_timeval pr_utime; /* XXX User time */
1911 struct target_timeval pr_stime; /* XXX System time */
1912 struct target_timeval pr_cutime; /* XXX Cumulative user time */
1913 struct target_timeval pr_cstime; /* XXX Cumulative system time */
Anthony Liguoric227f092009-10-01 16:12:16 -05001914 target_elf_gregset_t pr_reg; /* GP registers */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001915 int pr_fpvalid; /* XXX */
1916};
1917
1918#define ELF_PRARGSZ (80) /* Number of chars for args */
1919
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001920struct target_elf_prpsinfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001921 char pr_state; /* numeric process state */
1922 char pr_sname; /* char for pr_state */
1923 char pr_zomb; /* zombie */
1924 char pr_nice; /* nice val */
1925 target_ulong pr_flag; /* flags */
Anthony Liguoric227f092009-10-01 16:12:16 -05001926 target_uid_t pr_uid;
1927 target_gid_t pr_gid;
1928 target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001929 /* Lots missing */
1930 char pr_fname[16]; /* filename of executable */
1931 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
1932};
1933
1934/* Here is the structure in which status of each thread is captured. */
1935struct elf_thread_status {
Blue Swirl72cf2d42009-09-12 07:36:22 +00001936 QTAILQ_ENTRY(elf_thread_status) ets_link;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001937 struct target_elf_prstatus prstatus; /* NT_PRSTATUS */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001938#if 0
1939 elf_fpregset_t fpu; /* NT_PRFPREG */
1940 struct task_struct *thread;
1941 elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
1942#endif
1943 struct memelfnote notes[1];
1944 int num_notes;
1945};
1946
1947struct elf_note_info {
1948 struct memelfnote *notes;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001949 struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */
1950 struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001951
Blue Swirl72cf2d42009-09-12 07:36:22 +00001952 QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001953#if 0
1954 /*
1955 * Current version of ELF coredump doesn't support
1956 * dumping fp regs etc.
1957 */
1958 elf_fpregset_t *fpu;
1959 elf_fpxregset_t *xfpu;
1960 int thread_status_size;
1961#endif
1962 int notes_size;
1963 int numnote;
1964};
1965
1966struct vm_area_struct {
1967 abi_ulong vma_start; /* start vaddr of memory region */
1968 abi_ulong vma_end; /* end vaddr of memory region */
1969 abi_ulong vma_flags; /* protection etc. flags for the region */
Blue Swirl72cf2d42009-09-12 07:36:22 +00001970 QTAILQ_ENTRY(vm_area_struct) vma_link;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001971};
1972
1973struct mm_struct {
Blue Swirl72cf2d42009-09-12 07:36:22 +00001974 QTAILQ_HEAD(, vm_area_struct) mm_mmap;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001975 int mm_count; /* number of mappings */
1976};
1977
1978static struct mm_struct *vma_init(void);
1979static void vma_delete(struct mm_struct *);
1980static int vma_add_mapping(struct mm_struct *, abi_ulong,
Richard Hendersond97ef722010-07-27 10:25:29 -07001981 abi_ulong, abi_ulong);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001982static int vma_get_mapping_count(const struct mm_struct *);
1983static struct vm_area_struct *vma_first(const struct mm_struct *);
1984static struct vm_area_struct *vma_next(struct vm_area_struct *);
1985static abi_ulong vma_dump_size(const struct vm_area_struct *);
Paul Brookb480d9b2010-03-12 23:23:29 +00001986static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07001987 unsigned long flags);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001988
1989static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
1990static void fill_note(struct memelfnote *, const char *, int,
Richard Hendersond97ef722010-07-27 10:25:29 -07001991 unsigned int, void *);
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001992static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
1993static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001994static void fill_auxv_note(struct memelfnote *, const TaskState *);
1995static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
1996static size_t note_size(const struct memelfnote *);
1997static void free_note_info(struct elf_note_info *);
1998static int fill_note_info(struct elf_note_info *, long, const CPUState *);
1999static void fill_thread_info(struct elf_note_info *, const CPUState *);
2000static int core_dump_filename(const TaskState *, char *, size_t);
2001
2002static int dump_write(int, const void *, size_t);
2003static int write_note(struct memelfnote *, int);
2004static int write_note_info(struct elf_note_info *, int);
2005
2006#ifdef BSWAP_NEEDED
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002007static void bswap_prstatus(struct target_elf_prstatus *prstatus)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002008{
2009 prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
2010 prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
2011 prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
2012 prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
2013 prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
2014 prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
2015 prstatus->pr_pid = tswap32(prstatus->pr_pid);
2016 prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
2017 prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
2018 prstatus->pr_sid = tswap32(prstatus->pr_sid);
2019 /* cpu times are not filled, so we skip them */
2020 /* regs should be in correct format already */
2021 prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
2022}
2023
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002024static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002025{
2026 psinfo->pr_flag = tswapl(psinfo->pr_flag);
2027 psinfo->pr_uid = tswap16(psinfo->pr_uid);
2028 psinfo->pr_gid = tswap16(psinfo->pr_gid);
2029 psinfo->pr_pid = tswap32(psinfo->pr_pid);
2030 psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
2031 psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
2032 psinfo->pr_sid = tswap32(psinfo->pr_sid);
2033}
Richard Henderson991f8f02010-07-27 10:25:32 -07002034
2035static void bswap_note(struct elf_note *en)
2036{
2037 bswap32s(&en->n_namesz);
2038 bswap32s(&en->n_descsz);
2039 bswap32s(&en->n_type);
2040}
2041#else
2042static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
2043static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
2044static inline void bswap_note(struct elf_note *en) { }
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002045#endif /* BSWAP_NEEDED */
2046
2047/*
2048 * Minimal support for linux memory regions. These are needed
2049 * when we are finding out what memory exactly belongs to
2050 * emulated process. No locks needed here, as long as
2051 * thread that received the signal is stopped.
2052 */
2053
2054static struct mm_struct *vma_init(void)
2055{
2056 struct mm_struct *mm;
2057
2058 if ((mm = qemu_malloc(sizeof (*mm))) == NULL)
2059 return (NULL);
2060
2061 mm->mm_count = 0;
Blue Swirl72cf2d42009-09-12 07:36:22 +00002062 QTAILQ_INIT(&mm->mm_mmap);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002063
2064 return (mm);
2065}
2066
2067static void vma_delete(struct mm_struct *mm)
2068{
2069 struct vm_area_struct *vma;
2070
2071 while ((vma = vma_first(mm)) != NULL) {
Blue Swirl72cf2d42009-09-12 07:36:22 +00002072 QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002073 qemu_free(vma);
2074 }
2075 qemu_free(mm);
2076}
2077
2078static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
Richard Hendersond97ef722010-07-27 10:25:29 -07002079 abi_ulong end, abi_ulong flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002080{
2081 struct vm_area_struct *vma;
2082
2083 if ((vma = qemu_mallocz(sizeof (*vma))) == NULL)
2084 return (-1);
2085
2086 vma->vma_start = start;
2087 vma->vma_end = end;
2088 vma->vma_flags = flags;
2089
Blue Swirl72cf2d42009-09-12 07:36:22 +00002090 QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002091 mm->mm_count++;
2092
2093 return (0);
2094}
2095
2096static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2097{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002098 return (QTAILQ_FIRST(&mm->mm_mmap));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002099}
2100
2101static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2102{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002103 return (QTAILQ_NEXT(vma, vma_link));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002104}
2105
2106static int vma_get_mapping_count(const struct mm_struct *mm)
2107{
2108 return (mm->mm_count);
2109}
2110
2111/*
2112 * Calculate file (dump) size of given memory region.
2113 */
2114static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2115{
2116 /* if we cannot even read the first page, skip it */
2117 if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2118 return (0);
2119
2120 /*
2121 * Usually we don't dump executable pages as they contain
2122 * non-writable code that debugger can read directly from
2123 * target library etc. However, thread stacks are marked
2124 * also executable so we read in first page of given region
2125 * and check whether it contains elf header. If there is
2126 * no elf header, we dump it.
2127 */
2128 if (vma->vma_flags & PROT_EXEC) {
2129 char page[TARGET_PAGE_SIZE];
2130
2131 copy_from_user(page, vma->vma_start, sizeof (page));
2132 if ((page[EI_MAG0] == ELFMAG0) &&
2133 (page[EI_MAG1] == ELFMAG1) &&
2134 (page[EI_MAG2] == ELFMAG2) &&
2135 (page[EI_MAG3] == ELFMAG3)) {
2136 /*
2137 * Mappings are possibly from ELF binary. Don't dump
2138 * them.
2139 */
2140 return (0);
2141 }
2142 }
2143
2144 return (vma->vma_end - vma->vma_start);
2145}
2146
Paul Brookb480d9b2010-03-12 23:23:29 +00002147static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07002148 unsigned long flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002149{
2150 struct mm_struct *mm = (struct mm_struct *)priv;
2151
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002152 vma_add_mapping(mm, start, end, flags);
2153 return (0);
2154}
2155
2156static void fill_note(struct memelfnote *note, const char *name, int type,
Richard Hendersond97ef722010-07-27 10:25:29 -07002157 unsigned int sz, void *data)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002158{
2159 unsigned int namesz;
2160
2161 namesz = strlen(name) + 1;
2162 note->name = name;
2163 note->namesz = namesz;
2164 note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2165 note->type = type;
2166 note->datasz = roundup(sz, sizeof (int32_t));;
2167 note->data = data;
2168
2169 /*
2170 * We calculate rounded up note size here as specified by
2171 * ELF document.
2172 */
2173 note->notesz = sizeof (struct elf_note) +
2174 note->namesz_rounded + note->datasz;
2175}
2176
2177static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
Richard Hendersond97ef722010-07-27 10:25:29 -07002178 uint32_t flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002179{
2180 (void) memset(elf, 0, sizeof(*elf));
2181
2182 (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2183 elf->e_ident[EI_CLASS] = ELF_CLASS;
2184 elf->e_ident[EI_DATA] = ELF_DATA;
2185 elf->e_ident[EI_VERSION] = EV_CURRENT;
2186 elf->e_ident[EI_OSABI] = ELF_OSABI;
2187
2188 elf->e_type = ET_CORE;
2189 elf->e_machine = machine;
2190 elf->e_version = EV_CURRENT;
2191 elf->e_phoff = sizeof(struct elfhdr);
2192 elf->e_flags = flags;
2193 elf->e_ehsize = sizeof(struct elfhdr);
2194 elf->e_phentsize = sizeof(struct elf_phdr);
2195 elf->e_phnum = segs;
2196
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002197 bswap_ehdr(elf);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002198}
2199
2200static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2201{
2202 phdr->p_type = PT_NOTE;
2203 phdr->p_offset = offset;
2204 phdr->p_vaddr = 0;
2205 phdr->p_paddr = 0;
2206 phdr->p_filesz = sz;
2207 phdr->p_memsz = 0;
2208 phdr->p_flags = 0;
2209 phdr->p_align = 0;
2210
Richard Henderson991f8f02010-07-27 10:25:32 -07002211 bswap_phdr(phdr, 1);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002212}
2213
2214static size_t note_size(const struct memelfnote *note)
2215{
2216 return (note->notesz);
2217}
2218
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002219static void fill_prstatus(struct target_elf_prstatus *prstatus,
Richard Hendersond97ef722010-07-27 10:25:29 -07002220 const TaskState *ts, int signr)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002221{
2222 (void) memset(prstatus, 0, sizeof (*prstatus));
2223 prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2224 prstatus->pr_pid = ts->ts_tid;
2225 prstatus->pr_ppid = getppid();
2226 prstatus->pr_pgrp = getpgrp();
2227 prstatus->pr_sid = getsid(0);
2228
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002229 bswap_prstatus(prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002230}
2231
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002232static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002233{
2234 char *filename, *base_filename;
2235 unsigned int i, len;
2236
2237 (void) memset(psinfo, 0, sizeof (*psinfo));
2238
2239 len = ts->info->arg_end - ts->info->arg_start;
2240 if (len >= ELF_PRARGSZ)
2241 len = ELF_PRARGSZ - 1;
2242 if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2243 return -EFAULT;
2244 for (i = 0; i < len; i++)
2245 if (psinfo->pr_psargs[i] == 0)
2246 psinfo->pr_psargs[i] = ' ';
2247 psinfo->pr_psargs[len] = 0;
2248
2249 psinfo->pr_pid = getpid();
2250 psinfo->pr_ppid = getppid();
2251 psinfo->pr_pgrp = getpgrp();
2252 psinfo->pr_sid = getsid(0);
2253 psinfo->pr_uid = getuid();
2254 psinfo->pr_gid = getgid();
2255
2256 filename = strdup(ts->bprm->filename);
2257 base_filename = strdup(basename(filename));
2258 (void) strncpy(psinfo->pr_fname, base_filename,
Richard Hendersond97ef722010-07-27 10:25:29 -07002259 sizeof(psinfo->pr_fname));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002260 free(base_filename);
2261 free(filename);
2262
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002263 bswap_psinfo(psinfo);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002264 return (0);
2265}
2266
2267static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2268{
2269 elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2270 elf_addr_t orig_auxv = auxv;
2271 abi_ulong val;
2272 void *ptr;
2273 int i, len;
2274
2275 /*
2276 * Auxiliary vector is stored in target process stack. It contains
2277 * {type, value} pairs that we need to dump into note. This is not
2278 * strictly necessary but we do it here for sake of completeness.
2279 */
2280
2281 /* find out lenght of the vector, AT_NULL is terminator */
2282 i = len = 0;
2283 do {
2284 get_user_ual(val, auxv);
2285 i += 2;
2286 auxv += 2 * sizeof (elf_addr_t);
2287 } while (val != AT_NULL);
2288 len = i * sizeof (elf_addr_t);
2289
2290 /* read in whole auxv vector and copy it to memelfnote */
2291 ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2292 if (ptr != NULL) {
2293 fill_note(note, "CORE", NT_AUXV, len, ptr);
2294 unlock_user(ptr, auxv, len);
2295 }
2296}
2297
2298/*
2299 * Constructs name of coredump file. We have following convention
2300 * for the name:
2301 * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2302 *
2303 * Returns 0 in case of success, -1 otherwise (errno is set).
2304 */
2305static int core_dump_filename(const TaskState *ts, char *buf,
Richard Hendersond97ef722010-07-27 10:25:29 -07002306 size_t bufsize)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002307{
2308 char timestamp[64];
2309 char *filename = NULL;
2310 char *base_filename = NULL;
2311 struct timeval tv;
2312 struct tm tm;
2313
2314 assert(bufsize >= PATH_MAX);
2315
2316 if (gettimeofday(&tv, NULL) < 0) {
2317 (void) fprintf(stderr, "unable to get current timestamp: %s",
Richard Hendersond97ef722010-07-27 10:25:29 -07002318 strerror(errno));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002319 return (-1);
2320 }
2321
2322 filename = strdup(ts->bprm->filename);
2323 base_filename = strdup(basename(filename));
2324 (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
Richard Hendersond97ef722010-07-27 10:25:29 -07002325 localtime_r(&tv.tv_sec, &tm));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002326 (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
Richard Hendersond97ef722010-07-27 10:25:29 -07002327 base_filename, timestamp, (int)getpid());
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002328 free(base_filename);
2329 free(filename);
2330
2331 return (0);
2332}
2333
2334static int dump_write(int fd, const void *ptr, size_t size)
2335{
2336 const char *bufp = (const char *)ptr;
2337 ssize_t bytes_written, bytes_left;
2338 struct rlimit dumpsize;
2339 off_t pos;
2340
2341 bytes_written = 0;
2342 getrlimit(RLIMIT_CORE, &dumpsize);
2343 if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2344 if (errno == ESPIPE) { /* not a seekable stream */
2345 bytes_left = size;
2346 } else {
2347 return pos;
2348 }
2349 } else {
2350 if (dumpsize.rlim_cur <= pos) {
2351 return -1;
2352 } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2353 bytes_left = size;
2354 } else {
2355 size_t limit_left=dumpsize.rlim_cur - pos;
2356 bytes_left = limit_left >= size ? size : limit_left ;
2357 }
2358 }
2359
2360 /*
2361 * In normal conditions, single write(2) should do but
2362 * in case of socket etc. this mechanism is more portable.
2363 */
2364 do {
2365 bytes_written = write(fd, bufp, bytes_left);
2366 if (bytes_written < 0) {
2367 if (errno == EINTR)
2368 continue;
2369 return (-1);
2370 } else if (bytes_written == 0) { /* eof */
2371 return (-1);
2372 }
2373 bufp += bytes_written;
2374 bytes_left -= bytes_written;
2375 } while (bytes_left > 0);
2376
2377 return (0);
2378}
2379
2380static int write_note(struct memelfnote *men, int fd)
2381{
2382 struct elf_note en;
2383
2384 en.n_namesz = men->namesz;
2385 en.n_type = men->type;
2386 en.n_descsz = men->datasz;
2387
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002388 bswap_note(&en);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002389
2390 if (dump_write(fd, &en, sizeof(en)) != 0)
2391 return (-1);
2392 if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2393 return (-1);
2394 if (dump_write(fd, men->data, men->datasz) != 0)
2395 return (-1);
2396
2397 return (0);
2398}
2399
2400static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
2401{
2402 TaskState *ts = (TaskState *)env->opaque;
2403 struct elf_thread_status *ets;
2404
2405 ets = qemu_mallocz(sizeof (*ets));
2406 ets->num_notes = 1; /* only prstatus is dumped */
2407 fill_prstatus(&ets->prstatus, ts, 0);
2408 elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2409 fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
Richard Hendersond97ef722010-07-27 10:25:29 -07002410 &ets->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002411
Blue Swirl72cf2d42009-09-12 07:36:22 +00002412 QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002413
2414 info->notes_size += note_size(&ets->notes[0]);
2415}
2416
2417static int fill_note_info(struct elf_note_info *info,
Richard Hendersond97ef722010-07-27 10:25:29 -07002418 long signr, const CPUState *env)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002419{
2420#define NUMNOTES 3
2421 CPUState *cpu = NULL;
2422 TaskState *ts = (TaskState *)env->opaque;
2423 int i;
2424
2425 (void) memset(info, 0, sizeof (*info));
2426
Blue Swirl72cf2d42009-09-12 07:36:22 +00002427 QTAILQ_INIT(&info->thread_list);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002428
2429 info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote));
2430 if (info->notes == NULL)
2431 return (-ENOMEM);
2432 info->prstatus = qemu_mallocz(sizeof (*info->prstatus));
2433 if (info->prstatus == NULL)
2434 return (-ENOMEM);
2435 info->psinfo = qemu_mallocz(sizeof (*info->psinfo));
2436 if (info->prstatus == NULL)
2437 return (-ENOMEM);
2438
2439 /*
2440 * First fill in status (and registers) of current thread
2441 * including process info & aux vector.
2442 */
2443 fill_prstatus(info->prstatus, ts, signr);
2444 elf_core_copy_regs(&info->prstatus->pr_reg, env);
2445 fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
Richard Hendersond97ef722010-07-27 10:25:29 -07002446 sizeof (*info->prstatus), info->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002447 fill_psinfo(info->psinfo, ts);
2448 fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
Richard Hendersond97ef722010-07-27 10:25:29 -07002449 sizeof (*info->psinfo), info->psinfo);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002450 fill_auxv_note(&info->notes[2], ts);
2451 info->numnote = 3;
2452
2453 info->notes_size = 0;
2454 for (i = 0; i < info->numnote; i++)
2455 info->notes_size += note_size(&info->notes[i]);
2456
2457 /* read and fill status of all threads */
2458 cpu_list_lock();
2459 for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2460 if (cpu == thread_env)
2461 continue;
2462 fill_thread_info(info, cpu);
2463 }
2464 cpu_list_unlock();
2465
2466 return (0);
2467}
2468
2469static void free_note_info(struct elf_note_info *info)
2470{
2471 struct elf_thread_status *ets;
2472
Blue Swirl72cf2d42009-09-12 07:36:22 +00002473 while (!QTAILQ_EMPTY(&info->thread_list)) {
2474 ets = QTAILQ_FIRST(&info->thread_list);
2475 QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002476 qemu_free(ets);
2477 }
2478
2479 qemu_free(info->prstatus);
2480 qemu_free(info->psinfo);
2481 qemu_free(info->notes);
2482}
2483
2484static int write_note_info(struct elf_note_info *info, int fd)
2485{
2486 struct elf_thread_status *ets;
2487 int i, error = 0;
2488
2489 /* write prstatus, psinfo and auxv for current thread */
2490 for (i = 0; i < info->numnote; i++)
2491 if ((error = write_note(&info->notes[i], fd)) != 0)
2492 return (error);
2493
2494 /* write prstatus for each thread */
2495 for (ets = info->thread_list.tqh_first; ets != NULL;
Richard Hendersond97ef722010-07-27 10:25:29 -07002496 ets = ets->ets_link.tqe_next) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002497 if ((error = write_note(&ets->notes[0], fd)) != 0)
2498 return (error);
2499 }
2500
2501 return (0);
2502}
2503
2504/*
2505 * Write out ELF coredump.
2506 *
2507 * See documentation of ELF object file format in:
2508 * http://www.caldera.com/developers/devspecs/gabi41.pdf
2509 *
2510 * Coredump format in linux is following:
2511 *
2512 * 0 +----------------------+ \
2513 * | ELF header | ET_CORE |
2514 * +----------------------+ |
2515 * | ELF program headers | |--- headers
2516 * | - NOTE section | |
2517 * | - PT_LOAD sections | |
2518 * +----------------------+ /
2519 * | NOTEs: |
2520 * | - NT_PRSTATUS |
2521 * | - NT_PRSINFO |
2522 * | - NT_AUXV |
2523 * +----------------------+ <-- aligned to target page
2524 * | Process memory dump |
2525 * : :
2526 * . .
2527 * : :
2528 * | |
2529 * +----------------------+
2530 *
2531 * NT_PRSTATUS -> struct elf_prstatus (per thread)
2532 * NT_PRSINFO -> struct elf_prpsinfo
2533 * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2534 *
2535 * Format follows System V format as close as possible. Current
2536 * version limitations are as follows:
2537 * - no floating point registers are dumped
2538 *
2539 * Function returns 0 in case of success, negative errno otherwise.
2540 *
2541 * TODO: make this work also during runtime: it should be
2542 * possible to force coredump from running process and then
2543 * continue processing. For example qemu could set up SIGUSR2
2544 * handler (provided that target process haven't registered
2545 * handler for that) that does the dump when signal is received.
2546 */
2547static int elf_core_dump(int signr, const CPUState *env)
2548{
2549 const TaskState *ts = (const TaskState *)env->opaque;
2550 struct vm_area_struct *vma = NULL;
2551 char corefile[PATH_MAX];
2552 struct elf_note_info info;
2553 struct elfhdr elf;
2554 struct elf_phdr phdr;
2555 struct rlimit dumpsize;
2556 struct mm_struct *mm = NULL;
2557 off_t offset = 0, data_offset = 0;
2558 int segs = 0;
2559 int fd = -1;
2560
2561 errno = 0;
2562 getrlimit(RLIMIT_CORE, &dumpsize);
2563 if (dumpsize.rlim_cur == 0)
Richard Hendersond97ef722010-07-27 10:25:29 -07002564 return 0;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002565
2566 if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2567 return (-errno);
2568
2569 if ((fd = open(corefile, O_WRONLY | O_CREAT,
Richard Hendersond97ef722010-07-27 10:25:29 -07002570 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002571 return (-errno);
2572
2573 /*
2574 * Walk through target process memory mappings and
2575 * set up structure containing this information. After
2576 * this point vma_xxx functions can be used.
2577 */
2578 if ((mm = vma_init()) == NULL)
2579 goto out;
2580
2581 walk_memory_regions(mm, vma_walker);
2582 segs = vma_get_mapping_count(mm);
2583
2584 /*
2585 * Construct valid coredump ELF header. We also
2586 * add one more segment for notes.
2587 */
2588 fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2589 if (dump_write(fd, &elf, sizeof (elf)) != 0)
2590 goto out;
2591
2592 /* fill in in-memory version of notes */
2593 if (fill_note_info(&info, signr, env) < 0)
2594 goto out;
2595
2596 offset += sizeof (elf); /* elf header */
2597 offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */
2598
2599 /* write out notes program header */
2600 fill_elf_note_phdr(&phdr, info.notes_size, offset);
2601
2602 offset += info.notes_size;
2603 if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2604 goto out;
2605
2606 /*
2607 * ELF specification wants data to start at page boundary so
2608 * we align it here.
2609 */
2610 offset = roundup(offset, ELF_EXEC_PAGESIZE);
2611
2612 /*
2613 * Write program headers for memory regions mapped in
2614 * the target process.
2615 */
2616 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2617 (void) memset(&phdr, 0, sizeof (phdr));
2618
2619 phdr.p_type = PT_LOAD;
2620 phdr.p_offset = offset;
2621 phdr.p_vaddr = vma->vma_start;
2622 phdr.p_paddr = 0;
2623 phdr.p_filesz = vma_dump_size(vma);
2624 offset += phdr.p_filesz;
2625 phdr.p_memsz = vma->vma_end - vma->vma_start;
2626 phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2627 if (vma->vma_flags & PROT_WRITE)
2628 phdr.p_flags |= PF_W;
2629 if (vma->vma_flags & PROT_EXEC)
2630 phdr.p_flags |= PF_X;
2631 phdr.p_align = ELF_EXEC_PAGESIZE;
2632
2633 dump_write(fd, &phdr, sizeof (phdr));
2634 }
2635
2636 /*
2637 * Next we write notes just after program headers. No
2638 * alignment needed here.
2639 */
2640 if (write_note_info(&info, fd) < 0)
2641 goto out;
2642
2643 /* align data to page boundary */
2644 data_offset = lseek(fd, 0, SEEK_CUR);
2645 data_offset = TARGET_PAGE_ALIGN(data_offset);
2646 if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2647 goto out;
2648
2649 /*
2650 * Finally we can dump process memory into corefile as well.
2651 */
2652 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2653 abi_ulong addr;
2654 abi_ulong end;
2655
2656 end = vma->vma_start + vma_dump_size(vma);
2657
2658 for (addr = vma->vma_start; addr < end;
Richard Hendersond97ef722010-07-27 10:25:29 -07002659 addr += TARGET_PAGE_SIZE) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002660 char page[TARGET_PAGE_SIZE];
2661 int error;
2662
2663 /*
2664 * Read in page from target process memory and
2665 * write it to coredump file.
2666 */
2667 error = copy_from_user(page, addr, sizeof (page));
2668 if (error != 0) {
Aurelien Jarno49995e12009-12-19 20:28:23 +01002669 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
Richard Hendersond97ef722010-07-27 10:25:29 -07002670 addr);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002671 errno = -error;
2672 goto out;
2673 }
2674 if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2675 goto out;
2676 }
2677 }
2678
Richard Hendersond97ef722010-07-27 10:25:29 -07002679 out:
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002680 free_note_info(&info);
2681 if (mm != NULL)
2682 vma_delete(mm);
2683 (void) close(fd);
2684
2685 if (errno != 0)
2686 return (-errno);
2687 return (0);
2688}
2689
2690#endif /* USE_ELF_CORE_DUMP */
2691
bellard31e31b82003-02-18 22:55:36 +00002692static int load_aout_interp(void * exptr, int interp_fd)
2693{
2694 printf("a.out interpreter not yet supported\n");
2695 return(0);
2696}
2697
pbrooke5fe0c52006-06-11 13:32:59 +00002698void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2699{
2700 init_thread(regs, infop);
2701}