blob: 6ea1e8db02846e7dd0359a0879ed6c9399b9872e [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 Hendersond97ef722010-07-27 10:25:29 -070098typedef target_ulong target_elf_greg_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -080099#ifdef USE_UID16
Richard Hendersond97ef722010-07-27 10:25:29 -0700100typedef uint16_t target_uid_t;
101typedef uint16_t target_gid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800102#else
Richard Hendersond97ef722010-07-27 10:25:29 -0700103typedef uint32_t target_uid_t;
104typedef uint32_t target_gid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800105#endif
Richard Hendersond97ef722010-07-27 10:25:29 -0700106typedef int32_t target_pid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800107
bellard30ac07d2003-04-07 21:33:03 +0000108#ifdef TARGET_I386
109
bellard15338fd2005-11-26 11:41:16 +0000110#define ELF_PLATFORM get_elf_platform()
111
112static const char *get_elf_platform(void)
113{
114 static char elf_platform[] = "i386";
pbrookd5975362008-06-07 20:50:51 +0000115 int family = (thread_env->cpuid_version >> 8) & 0xff;
bellard15338fd2005-11-26 11:41:16 +0000116 if (family > 6)
117 family = 6;
118 if (family >= 3)
119 elf_platform[1] = '0' + family;
120 return elf_platform;
121}
122
123#define ELF_HWCAP get_elf_hwcap()
124
125static uint32_t get_elf_hwcap(void)
126{
Richard Hendersond97ef722010-07-27 10:25:29 -0700127 return thread_env->cpuid_features;
bellard15338fd2005-11-26 11:41:16 +0000128}
129
j_mayer84409dd2007-04-06 08:56:50 +0000130#ifdef TARGET_X86_64
131#define ELF_START_MMAP 0x2aaaaab000ULL
132#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
133
134#define ELF_CLASS ELFCLASS64
135#define ELF_DATA ELFDATA2LSB
136#define ELF_ARCH EM_X86_64
137
138static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
139{
140 regs->rax = 0;
141 regs->rsp = infop->start_stack;
142 regs->rip = infop->entry;
143}
144
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300145#define ELF_NREG 27
Anthony Liguoric227f092009-10-01 16:12:16 -0500146typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300147
148/*
149 * Note that ELF_NREG should be 29 as there should be place for
150 * TRAPNO and ERR "registers" as well but linux doesn't dump
151 * those.
152 *
153 * See linux kernel: arch/x86/include/asm/elf.h
154 */
Anthony Liguoric227f092009-10-01 16:12:16 -0500155static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300156{
157 (*regs)[0] = env->regs[15];
158 (*regs)[1] = env->regs[14];
159 (*regs)[2] = env->regs[13];
160 (*regs)[3] = env->regs[12];
161 (*regs)[4] = env->regs[R_EBP];
162 (*regs)[5] = env->regs[R_EBX];
163 (*regs)[6] = env->regs[11];
164 (*regs)[7] = env->regs[10];
165 (*regs)[8] = env->regs[9];
166 (*regs)[9] = env->regs[8];
167 (*regs)[10] = env->regs[R_EAX];
168 (*regs)[11] = env->regs[R_ECX];
169 (*regs)[12] = env->regs[R_EDX];
170 (*regs)[13] = env->regs[R_ESI];
171 (*regs)[14] = env->regs[R_EDI];
172 (*regs)[15] = env->regs[R_EAX]; /* XXX */
173 (*regs)[16] = env->eip;
174 (*regs)[17] = env->segs[R_CS].selector & 0xffff;
175 (*regs)[18] = env->eflags;
176 (*regs)[19] = env->regs[R_ESP];
177 (*regs)[20] = env->segs[R_SS].selector & 0xffff;
178 (*regs)[21] = env->segs[R_FS].selector & 0xffff;
179 (*regs)[22] = env->segs[R_GS].selector & 0xffff;
180 (*regs)[23] = env->segs[R_DS].selector & 0xffff;
181 (*regs)[24] = env->segs[R_ES].selector & 0xffff;
182 (*regs)[25] = env->segs[R_FS].selector & 0xffff;
183 (*regs)[26] = env->segs[R_GS].selector & 0xffff;
184}
185
j_mayer84409dd2007-04-06 08:56:50 +0000186#else
187
bellard30ac07d2003-04-07 21:33:03 +0000188#define ELF_START_MMAP 0x80000000
189
bellard30ac07d2003-04-07 21:33:03 +0000190/*
191 * This is used to ensure we don't load something for the wrong architecture.
192 */
193#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
194
195/*
196 * These are used to set parameters in the core dumps.
197 */
Richard Hendersond97ef722010-07-27 10:25:29 -0700198#define ELF_CLASS ELFCLASS32
199#define ELF_DATA ELFDATA2LSB
200#define ELF_ARCH EM_386
bellard30ac07d2003-04-07 21:33:03 +0000201
Richard Hendersond97ef722010-07-27 10:25:29 -0700202static inline void init_thread(struct target_pt_regs *regs,
203 struct image_info *infop)
bellardb346ff42003-06-15 20:05:50 +0000204{
205 regs->esp = infop->start_stack;
206 regs->eip = infop->entry;
pbrooke5fe0c52006-06-11 13:32:59 +0000207
208 /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
209 starts %edx contains a pointer to a function which might be
210 registered using `atexit'. This provides a mean for the
211 dynamic linker to call DT_FINI functions for shared libraries
212 that have been loaded before the code runs.
213
214 A value of 0 tells we have no such handler. */
215 regs->edx = 0;
bellardb346ff42003-06-15 20:05:50 +0000216}
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300217
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300218#define ELF_NREG 17
Anthony Liguoric227f092009-10-01 16:12:16 -0500219typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300220
221/*
222 * Note that ELF_NREG should be 19 as there should be place for
223 * TRAPNO and ERR "registers" as well but linux doesn't dump
224 * those.
225 *
226 * See linux kernel: arch/x86/include/asm/elf.h
227 */
Anthony Liguoric227f092009-10-01 16:12:16 -0500228static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300229{
230 (*regs)[0] = env->regs[R_EBX];
231 (*regs)[1] = env->regs[R_ECX];
232 (*regs)[2] = env->regs[R_EDX];
233 (*regs)[3] = env->regs[R_ESI];
234 (*regs)[4] = env->regs[R_EDI];
235 (*regs)[5] = env->regs[R_EBP];
236 (*regs)[6] = env->regs[R_EAX];
237 (*regs)[7] = env->segs[R_DS].selector & 0xffff;
238 (*regs)[8] = env->segs[R_ES].selector & 0xffff;
239 (*regs)[9] = env->segs[R_FS].selector & 0xffff;
240 (*regs)[10] = env->segs[R_GS].selector & 0xffff;
241 (*regs)[11] = env->regs[R_EAX]; /* XXX */
242 (*regs)[12] = env->eip;
243 (*regs)[13] = env->segs[R_CS].selector & 0xffff;
244 (*regs)[14] = env->eflags;
245 (*regs)[15] = env->regs[R_ESP];
246 (*regs)[16] = env->segs[R_SS].selector & 0xffff;
247}
j_mayer84409dd2007-04-06 08:56:50 +0000248#endif
bellardb346ff42003-06-15 20:05:50 +0000249
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300250#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700251#define ELF_EXEC_PAGESIZE 4096
bellardb346ff42003-06-15 20:05:50 +0000252
253#endif
254
255#ifdef TARGET_ARM
256
257#define ELF_START_MMAP 0x80000000
258
259#define elf_check_arch(x) ( (x) == EM_ARM )
260
Richard Hendersond97ef722010-07-27 10:25:29 -0700261#define ELF_CLASS ELFCLASS32
bellardb346ff42003-06-15 20:05:50 +0000262#ifdef TARGET_WORDS_BIGENDIAN
Richard Hendersond97ef722010-07-27 10:25:29 -0700263#define ELF_DATA ELFDATA2MSB
bellardb346ff42003-06-15 20:05:50 +0000264#else
Richard Hendersond97ef722010-07-27 10:25:29 -0700265#define ELF_DATA ELFDATA2LSB
bellardb346ff42003-06-15 20:05:50 +0000266#endif
Richard Hendersond97ef722010-07-27 10:25:29 -0700267#define ELF_ARCH EM_ARM
bellardb346ff42003-06-15 20:05:50 +0000268
Richard Hendersond97ef722010-07-27 10:25:29 -0700269static inline void init_thread(struct target_pt_regs *regs,
270 struct image_info *infop)
bellardb346ff42003-06-15 20:05:50 +0000271{
blueswir1992f48a2007-10-14 16:27:31 +0000272 abi_long stack = infop->start_stack;
bellardb346ff42003-06-15 20:05:50 +0000273 memset(regs, 0, sizeof(*regs));
274 regs->ARM_cpsr = 0x10;
pbrook0240ded2006-02-04 19:30:51 +0000275 if (infop->entry & 1)
Richard Hendersond97ef722010-07-27 10:25:29 -0700276 regs->ARM_cpsr |= CPSR_T;
pbrook0240ded2006-02-04 19:30:51 +0000277 regs->ARM_pc = infop->entry & 0xfffffffe;
bellardb346ff42003-06-15 20:05:50 +0000278 regs->ARM_sp = infop->start_stack;
bellard2f619692007-11-16 10:46:05 +0000279 /* FIXME - what to for failure of get_user()? */
280 get_user_ual(regs->ARM_r2, stack + 8); /* envp */
281 get_user_ual(regs->ARM_r1, stack + 4); /* envp */
bellarda1516e92003-07-09 17:13:37 +0000282 /* XXX: it seems that r0 is zeroed after ! */
pbrooke5fe0c52006-06-11 13:32:59 +0000283 regs->ARM_r0 = 0;
284 /* For uClinux PIC binaries. */
j_mayer863cf0b2007-10-07 15:59:45 +0000285 /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
pbrooke5fe0c52006-06-11 13:32:59 +0000286 regs->ARM_r10 = infop->start_data;
bellardb346ff42003-06-15 20:05:50 +0000287}
288
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300289#define ELF_NREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -0500290typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300291
Anthony Liguoric227f092009-10-01 16:12:16 -0500292static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300293{
Nathan Froydd049e622009-12-11 09:04:47 -0800294 (*regs)[0] = tswapl(env->regs[0]);
295 (*regs)[1] = tswapl(env->regs[1]);
296 (*regs)[2] = tswapl(env->regs[2]);
297 (*regs)[3] = tswapl(env->regs[3]);
298 (*regs)[4] = tswapl(env->regs[4]);
299 (*regs)[5] = tswapl(env->regs[5]);
300 (*regs)[6] = tswapl(env->regs[6]);
301 (*regs)[7] = tswapl(env->regs[7]);
302 (*regs)[8] = tswapl(env->regs[8]);
303 (*regs)[9] = tswapl(env->regs[9]);
304 (*regs)[10] = tswapl(env->regs[10]);
305 (*regs)[11] = tswapl(env->regs[11]);
306 (*regs)[12] = tswapl(env->regs[12]);
307 (*regs)[13] = tswapl(env->regs[13]);
308 (*regs)[14] = tswapl(env->regs[14]);
309 (*regs)[15] = tswapl(env->regs[15]);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300310
Nathan Froydd049e622009-12-11 09:04:47 -0800311 (*regs)[16] = tswapl(cpsr_read((CPUState *)env));
312 (*regs)[17] = tswapl(env->regs[0]); /* XXX */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300313}
314
bellard30ac07d2003-04-07 21:33:03 +0000315#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700316#define ELF_EXEC_PAGESIZE 4096
bellard30ac07d2003-04-07 21:33:03 +0000317
bellardafce2922005-10-30 20:58:30 +0000318enum
319{
Richard Hendersond97ef722010-07-27 10:25:29 -0700320 ARM_HWCAP_ARM_SWP = 1 << 0,
321 ARM_HWCAP_ARM_HALF = 1 << 1,
322 ARM_HWCAP_ARM_THUMB = 1 << 2,
323 ARM_HWCAP_ARM_26BIT = 1 << 3,
324 ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
325 ARM_HWCAP_ARM_FPA = 1 << 5,
326 ARM_HWCAP_ARM_VFP = 1 << 6,
327 ARM_HWCAP_ARM_EDSP = 1 << 7,
328 ARM_HWCAP_ARM_JAVA = 1 << 8,
329 ARM_HWCAP_ARM_IWMMXT = 1 << 9,
330 ARM_HWCAP_ARM_THUMBEE = 1 << 10,
331 ARM_HWCAP_ARM_NEON = 1 << 11,
332 ARM_HWCAP_ARM_VFPv3 = 1 << 12,
333 ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
bellardafce2922005-10-30 20:58:30 +0000334};
335
Richard Hendersond97ef722010-07-27 10:25:29 -0700336#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
337 | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
338 | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
339 | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
bellardafce2922005-10-30 20:58:30 +0000340
bellard30ac07d2003-04-07 21:33:03 +0000341#endif
342
bellard853d6f72003-09-30 20:58:32 +0000343#ifdef TARGET_SPARC
bellarda315a142005-01-30 22:59:18 +0000344#ifdef TARGET_SPARC64
bellard853d6f72003-09-30 20:58:32 +0000345
346#define ELF_START_MMAP 0x80000000
347
blueswir1992f48a2007-10-14 16:27:31 +0000348#ifndef TARGET_ABI32
blueswir1cb33da52007-10-09 16:34:29 +0000349#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
blueswir1992f48a2007-10-14 16:27:31 +0000350#else
351#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
352#endif
bellard853d6f72003-09-30 20:58:32 +0000353
bellarda315a142005-01-30 22:59:18 +0000354#define ELF_CLASS ELFCLASS64
355#define ELF_DATA ELFDATA2MSB
bellard5ef54112006-07-18 21:14:09 +0000356#define ELF_ARCH EM_SPARCV9
357
Richard Hendersond97ef722010-07-27 10:25:29 -0700358#define STACK_BIAS 2047
bellarda315a142005-01-30 22:59:18 +0000359
Richard Hendersond97ef722010-07-27 10:25:29 -0700360static inline void init_thread(struct target_pt_regs *regs,
361 struct image_info *infop)
bellarda315a142005-01-30 22:59:18 +0000362{
blueswir1992f48a2007-10-14 16:27:31 +0000363#ifndef TARGET_ABI32
bellarda315a142005-01-30 22:59:18 +0000364 regs->tstate = 0;
blueswir1992f48a2007-10-14 16:27:31 +0000365#endif
bellarda315a142005-01-30 22:59:18 +0000366 regs->pc = infop->entry;
367 regs->npc = regs->pc + 4;
368 regs->y = 0;
blueswir1992f48a2007-10-14 16:27:31 +0000369#ifdef TARGET_ABI32
370 regs->u_regs[14] = infop->start_stack - 16 * 4;
371#else
blueswir1cb33da52007-10-09 16:34:29 +0000372 if (personality(infop->personality) == PER_LINUX32)
373 regs->u_regs[14] = infop->start_stack - 16 * 4;
374 else
375 regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
blueswir1992f48a2007-10-14 16:27:31 +0000376#endif
bellarda315a142005-01-30 22:59:18 +0000377}
378
379#else
380#define ELF_START_MMAP 0x80000000
381
382#define elf_check_arch(x) ( (x) == EM_SPARC )
383
bellard853d6f72003-09-30 20:58:32 +0000384#define ELF_CLASS ELFCLASS32
385#define ELF_DATA ELFDATA2MSB
386#define ELF_ARCH EM_SPARC
387
Richard Hendersond97ef722010-07-27 10:25:29 -0700388static inline void init_thread(struct target_pt_regs *regs,
389 struct image_info *infop)
bellard853d6f72003-09-30 20:58:32 +0000390{
bellardf5155282004-01-04 15:46:50 +0000391 regs->psr = 0;
392 regs->pc = infop->entry;
393 regs->npc = regs->pc + 4;
394 regs->y = 0;
395 regs->u_regs[14] = infop->start_stack - 16 * 4;
bellard853d6f72003-09-30 20:58:32 +0000396}
397
398#endif
bellarda315a142005-01-30 22:59:18 +0000399#endif
bellard853d6f72003-09-30 20:58:32 +0000400
bellard67867302003-11-23 17:05:30 +0000401#ifdef TARGET_PPC
402
403#define ELF_START_MMAP 0x80000000
404
j_mayere85e7c62007-10-18 19:59:49 +0000405#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
j_mayer84409dd2007-04-06 08:56:50 +0000406
407#define elf_check_arch(x) ( (x) == EM_PPC64 )
408
Richard Hendersond97ef722010-07-27 10:25:29 -0700409#define ELF_CLASS ELFCLASS64
j_mayer84409dd2007-04-06 08:56:50 +0000410
411#else
412
bellard67867302003-11-23 17:05:30 +0000413#define elf_check_arch(x) ( (x) == EM_PPC )
414
Richard Hendersond97ef722010-07-27 10:25:29 -0700415#define ELF_CLASS ELFCLASS32
j_mayer84409dd2007-04-06 08:56:50 +0000416
417#endif
418
bellard67867302003-11-23 17:05:30 +0000419#ifdef TARGET_WORDS_BIGENDIAN
Richard Hendersond97ef722010-07-27 10:25:29 -0700420#define ELF_DATA ELFDATA2MSB
bellard67867302003-11-23 17:05:30 +0000421#else
Richard Hendersond97ef722010-07-27 10:25:29 -0700422#define ELF_DATA ELFDATA2LSB
bellard67867302003-11-23 17:05:30 +0000423#endif
Richard Hendersond97ef722010-07-27 10:25:29 -0700424#define ELF_ARCH EM_PPC
bellard67867302003-11-23 17:05:30 +0000425
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700426/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
427 See arch/powerpc/include/asm/cputable.h. */
428enum {
malc3efa9a62009-07-18 13:10:12 +0400429 QEMU_PPC_FEATURE_32 = 0x80000000,
430 QEMU_PPC_FEATURE_64 = 0x40000000,
431 QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
432 QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
433 QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
434 QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
435 QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
436 QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
437 QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
438 QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
439 QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
440 QEMU_PPC_FEATURE_NO_TB = 0x00100000,
441 QEMU_PPC_FEATURE_POWER4 = 0x00080000,
442 QEMU_PPC_FEATURE_POWER5 = 0x00040000,
443 QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
444 QEMU_PPC_FEATURE_CELL = 0x00010000,
445 QEMU_PPC_FEATURE_BOOKE = 0x00008000,
446 QEMU_PPC_FEATURE_SMT = 0x00004000,
447 QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
448 QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
449 QEMU_PPC_FEATURE_PA6T = 0x00000800,
450 QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
451 QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
452 QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
453 QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
454 QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700455
malc3efa9a62009-07-18 13:10:12 +0400456 QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
457 QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700458};
459
460#define ELF_HWCAP get_elf_hwcap()
461
462static uint32_t get_elf_hwcap(void)
463{
464 CPUState *e = thread_env;
465 uint32_t features = 0;
466
467 /* We don't have to be terribly complete here; the high points are
468 Altivec/FP/SPE support. Anything else is just a bonus. */
Richard Hendersond97ef722010-07-27 10:25:29 -0700469#define GET_FEATURE(flag, feature) \
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700470 do {if (e->insns_flags & flag) features |= feature; } while(0)
malc3efa9a62009-07-18 13:10:12 +0400471 GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
472 GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
473 GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
474 GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
475 GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
476 GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
477 GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
478 GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700479#undef GET_FEATURE
480
481 return features;
482}
483
bellardf5155282004-01-04 15:46:50 +0000484/*
bellardf5155282004-01-04 15:46:50 +0000485 * The requirements here are:
486 * - keep the final alignment of sp (sp & 0xf)
487 * - make sure the 32-bit value at the first 16 byte aligned position of
488 * AUXV is greater than 16 for glibc compatibility.
489 * AT_IGNOREPPC is used for that.
490 * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
491 * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
492 */
bellard0bccf032005-08-21 10:12:28 +0000493#define DLINFO_ARCH_ITEMS 5
Richard Hendersond97ef722010-07-27 10:25:29 -0700494#define ARCH_DLINFO \
495 do { \
496 NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
497 NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
498 NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
499 /* \
500 * Now handle glibc compatibility. \
501 */ \
502 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
503 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
504 } while (0)
bellardf5155282004-01-04 15:46:50 +0000505
bellard67867302003-11-23 17:05:30 +0000506static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
507{
bellard67867302003-11-23 17:05:30 +0000508 _regs->gpr[1] = infop->start_stack;
j_mayere85e7c62007-10-18 19:59:49 +0000509#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
Rob Landley7983f432010-03-28 16:51:43 +0200510 _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_addr;
511 infop->entry = ldq_raw(infop->entry) + infop->load_addr;
j_mayer84409dd2007-04-06 08:56:50 +0000512#endif
bellard67867302003-11-23 17:05:30 +0000513 _regs->nip = infop->entry;
514}
515
Nathan Froyde2f3e742009-12-11 09:04:48 -0800516/* See linux kernel: arch/powerpc/include/asm/elf.h. */
517#define ELF_NREG 48
518typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
519
520static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
521{
522 int i;
523 target_ulong ccr = 0;
524
525 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
526 (*regs)[i] = tswapl(env->gpr[i]);
527 }
528
529 (*regs)[32] = tswapl(env->nip);
530 (*regs)[33] = tswapl(env->msr);
531 (*regs)[35] = tswapl(env->ctr);
532 (*regs)[36] = tswapl(env->lr);
533 (*regs)[37] = tswapl(env->xer);
534
535 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
536 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
537 }
538 (*regs)[38] = tswapl(ccr);
539}
540
541#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700542#define ELF_EXEC_PAGESIZE 4096
bellard67867302003-11-23 17:05:30 +0000543
544#endif
545
bellard048f6b42005-11-26 18:47:20 +0000546#ifdef TARGET_MIPS
547
548#define ELF_START_MMAP 0x80000000
549
550#define elf_check_arch(x) ( (x) == EM_MIPS )
551
ths388bb212007-05-13 13:58:00 +0000552#ifdef TARGET_MIPS64
553#define ELF_CLASS ELFCLASS64
554#else
bellard048f6b42005-11-26 18:47:20 +0000555#define ELF_CLASS ELFCLASS32
ths388bb212007-05-13 13:58:00 +0000556#endif
bellard048f6b42005-11-26 18:47:20 +0000557#ifdef TARGET_WORDS_BIGENDIAN
Richard Hendersond97ef722010-07-27 10:25:29 -0700558#define ELF_DATA ELFDATA2MSB
bellard048f6b42005-11-26 18:47:20 +0000559#else
Richard Hendersond97ef722010-07-27 10:25:29 -0700560#define ELF_DATA ELFDATA2LSB
bellard048f6b42005-11-26 18:47:20 +0000561#endif
562#define ELF_ARCH EM_MIPS
563
Richard Hendersond97ef722010-07-27 10:25:29 -0700564static inline void init_thread(struct target_pt_regs *regs,
565 struct image_info *infop)
bellard048f6b42005-11-26 18:47:20 +0000566{
ths623a9302007-10-28 19:45:05 +0000567 regs->cp0_status = 2 << CP0St_KSU;
bellard048f6b42005-11-26 18:47:20 +0000568 regs->cp0_epc = infop->entry;
569 regs->regs[29] = infop->start_stack;
570}
571
Nathan Froyd51e52602009-12-11 09:04:49 -0800572/* See linux kernel: arch/mips/include/asm/elf.h. */
573#define ELF_NREG 45
574typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
575
576/* See linux kernel: arch/mips/include/asm/reg.h. */
577enum {
578#ifdef TARGET_MIPS64
579 TARGET_EF_R0 = 0,
580#else
581 TARGET_EF_R0 = 6,
582#endif
583 TARGET_EF_R26 = TARGET_EF_R0 + 26,
584 TARGET_EF_R27 = TARGET_EF_R0 + 27,
585 TARGET_EF_LO = TARGET_EF_R0 + 32,
586 TARGET_EF_HI = TARGET_EF_R0 + 33,
587 TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
588 TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
589 TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
590 TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
591};
592
593/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
594static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
595{
596 int i;
597
598 for (i = 0; i < TARGET_EF_R0; i++) {
599 (*regs)[i] = 0;
600 }
601 (*regs)[TARGET_EF_R0] = 0;
602
603 for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
604 (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]);
605 }
606
607 (*regs)[TARGET_EF_R26] = 0;
608 (*regs)[TARGET_EF_R27] = 0;
609 (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]);
610 (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]);
611 (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC);
612 (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr);
613 (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status);
614 (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause);
615}
616
617#define USE_ELF_CORE_DUMP
ths388bb212007-05-13 13:58:00 +0000618#define ELF_EXEC_PAGESIZE 4096
619
bellard048f6b42005-11-26 18:47:20 +0000620#endif /* TARGET_MIPS */
621
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200622#ifdef TARGET_MICROBLAZE
623
624#define ELF_START_MMAP 0x80000000
625
Edgar E. Iglesias0d5d4692010-05-19 15:24:17 +0200626#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200627
628#define ELF_CLASS ELFCLASS32
Richard Hendersond97ef722010-07-27 10:25:29 -0700629#define ELF_DATA ELFDATA2MSB
Edgar E. Iglesias0d5d4692010-05-19 15:24:17 +0200630#define ELF_ARCH EM_MICROBLAZE
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200631
Richard Hendersond97ef722010-07-27 10:25:29 -0700632static inline void init_thread(struct target_pt_regs *regs,
633 struct image_info *infop)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200634{
635 regs->pc = infop->entry;
636 regs->r1 = infop->start_stack;
637
638}
639
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200640#define ELF_EXEC_PAGESIZE 4096
641
Edgar E. Iglesiase4cbd442010-05-19 15:09:28 +0200642#define USE_ELF_CORE_DUMP
643#define ELF_NREG 38
644typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
645
646/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
647static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
648{
649 int i, pos = 0;
650
651 for (i = 0; i < 32; i++) {
652 (*regs)[pos++] = tswapl(env->regs[i]);
653 }
654
655 for (i = 0; i < 6; i++) {
656 (*regs)[pos++] = tswapl(env->sregs[i]);
657 }
658}
659
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200660#endif /* TARGET_MICROBLAZE */
661
bellardfdf9b3e2006-04-27 21:07:38 +0000662#ifdef TARGET_SH4
663
664#define ELF_START_MMAP 0x80000000
665
666#define elf_check_arch(x) ( (x) == EM_SH )
667
668#define ELF_CLASS ELFCLASS32
669#define ELF_DATA ELFDATA2LSB
670#define ELF_ARCH EM_SH
671
Richard Hendersond97ef722010-07-27 10:25:29 -0700672static inline void init_thread(struct target_pt_regs *regs,
673 struct image_info *infop)
bellardfdf9b3e2006-04-27 21:07:38 +0000674{
Richard Hendersond97ef722010-07-27 10:25:29 -0700675 /* Check other registers XXXXX */
676 regs->pc = infop->entry;
677 regs->regs[15] = infop->start_stack;
bellardfdf9b3e2006-04-27 21:07:38 +0000678}
679
Nathan Froyd7631c972009-12-11 09:04:51 -0800680/* See linux kernel: arch/sh/include/asm/elf.h. */
681#define ELF_NREG 23
682typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
683
684/* See linux kernel: arch/sh/include/asm/ptrace.h. */
685enum {
686 TARGET_REG_PC = 16,
687 TARGET_REG_PR = 17,
688 TARGET_REG_SR = 18,
689 TARGET_REG_GBR = 19,
690 TARGET_REG_MACH = 20,
691 TARGET_REG_MACL = 21,
692 TARGET_REG_SYSCALL = 22
693};
694
Richard Hendersond97ef722010-07-27 10:25:29 -0700695static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
696 const CPUState *env)
Nathan Froyd7631c972009-12-11 09:04:51 -0800697{
698 int i;
699
700 for (i = 0; i < 16; i++) {
701 (*regs[i]) = tswapl(env->gregs[i]);
702 }
703
704 (*regs)[TARGET_REG_PC] = tswapl(env->pc);
705 (*regs)[TARGET_REG_PR] = tswapl(env->pr);
706 (*regs)[TARGET_REG_SR] = tswapl(env->sr);
707 (*regs)[TARGET_REG_GBR] = tswapl(env->gbr);
708 (*regs)[TARGET_REG_MACH] = tswapl(env->mach);
709 (*regs)[TARGET_REG_MACL] = tswapl(env->macl);
710 (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
711}
712
713#define USE_ELF_CORE_DUMP
bellardfdf9b3e2006-04-27 21:07:38 +0000714#define ELF_EXEC_PAGESIZE 4096
715
716#endif
717
ths48733d12007-10-08 13:36:46 +0000718#ifdef TARGET_CRIS
719
720#define ELF_START_MMAP 0x80000000
721
722#define elf_check_arch(x) ( (x) == EM_CRIS )
723
724#define ELF_CLASS ELFCLASS32
725#define ELF_DATA ELFDATA2LSB
726#define ELF_ARCH EM_CRIS
727
Richard Hendersond97ef722010-07-27 10:25:29 -0700728static inline void init_thread(struct target_pt_regs *regs,
729 struct image_info *infop)
ths48733d12007-10-08 13:36:46 +0000730{
Richard Hendersond97ef722010-07-27 10:25:29 -0700731 regs->erp = infop->entry;
ths48733d12007-10-08 13:36:46 +0000732}
733
ths48733d12007-10-08 13:36:46 +0000734#define ELF_EXEC_PAGESIZE 8192
735
736#endif
737
pbrooke6e59062006-10-22 00:18:54 +0000738#ifdef TARGET_M68K
739
740#define ELF_START_MMAP 0x80000000
741
742#define elf_check_arch(x) ( (x) == EM_68K )
743
Richard Hendersond97ef722010-07-27 10:25:29 -0700744#define ELF_CLASS ELFCLASS32
745#define ELF_DATA ELFDATA2MSB
746#define ELF_ARCH EM_68K
pbrooke6e59062006-10-22 00:18:54 +0000747
748/* ??? Does this need to do anything?
Richard Hendersond97ef722010-07-27 10:25:29 -0700749 #define ELF_PLAT_INIT(_r) */
pbrooke6e59062006-10-22 00:18:54 +0000750
Richard Hendersond97ef722010-07-27 10:25:29 -0700751static inline void init_thread(struct target_pt_regs *regs,
752 struct image_info *infop)
pbrooke6e59062006-10-22 00:18:54 +0000753{
754 regs->usp = infop->start_stack;
755 regs->sr = 0;
756 regs->pc = infop->entry;
757}
758
Nathan Froyd7a93cc52009-12-11 09:04:50 -0800759/* See linux kernel: arch/m68k/include/asm/elf.h. */
760#define ELF_NREG 20
761typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
762
763static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
764{
765 (*regs)[0] = tswapl(env->dregs[1]);
766 (*regs)[1] = tswapl(env->dregs[2]);
767 (*regs)[2] = tswapl(env->dregs[3]);
768 (*regs)[3] = tswapl(env->dregs[4]);
769 (*regs)[4] = tswapl(env->dregs[5]);
770 (*regs)[5] = tswapl(env->dregs[6]);
771 (*regs)[6] = tswapl(env->dregs[7]);
772 (*regs)[7] = tswapl(env->aregs[0]);
773 (*regs)[8] = tswapl(env->aregs[1]);
774 (*regs)[9] = tswapl(env->aregs[2]);
775 (*regs)[10] = tswapl(env->aregs[3]);
776 (*regs)[11] = tswapl(env->aregs[4]);
777 (*regs)[12] = tswapl(env->aregs[5]);
778 (*regs)[13] = tswapl(env->aregs[6]);
779 (*regs)[14] = tswapl(env->dregs[0]);
780 (*regs)[15] = tswapl(env->aregs[7]);
781 (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */
782 (*regs)[17] = tswapl(env->sr);
783 (*regs)[18] = tswapl(env->pc);
784 (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */
785}
786
787#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700788#define ELF_EXEC_PAGESIZE 8192
pbrooke6e59062006-10-22 00:18:54 +0000789
790#endif
791
j_mayer7a3148a2007-04-05 07:13:51 +0000792#ifdef TARGET_ALPHA
793
794#define ELF_START_MMAP (0x30000000000ULL)
795
796#define elf_check_arch(x) ( (x) == ELF_ARCH )
797
798#define ELF_CLASS ELFCLASS64
799#define ELF_DATA ELFDATA2MSB
800#define ELF_ARCH EM_ALPHA
801
Richard Hendersond97ef722010-07-27 10:25:29 -0700802static inline void init_thread(struct target_pt_regs *regs,
803 struct image_info *infop)
j_mayer7a3148a2007-04-05 07:13:51 +0000804{
805 regs->pc = infop->entry;
806 regs->ps = 8;
807 regs->usp = infop->start_stack;
j_mayer7a3148a2007-04-05 07:13:51 +0000808}
809
j_mayer7a3148a2007-04-05 07:13:51 +0000810#define ELF_EXEC_PAGESIZE 8192
811
812#endif /* TARGET_ALPHA */
813
bellard15338fd2005-11-26 11:41:16 +0000814#ifndef ELF_PLATFORM
815#define ELF_PLATFORM (NULL)
816#endif
817
818#ifndef ELF_HWCAP
819#define ELF_HWCAP 0
820#endif
821
blueswir1992f48a2007-10-14 16:27:31 +0000822#ifdef TARGET_ABI32
blueswir1cb33da52007-10-09 16:34:29 +0000823#undef ELF_CLASS
blueswir1992f48a2007-10-14 16:27:31 +0000824#define ELF_CLASS ELFCLASS32
blueswir1cb33da52007-10-09 16:34:29 +0000825#undef bswaptls
826#define bswaptls(ptr) bswap32s(ptr)
827#endif
828
bellard31e31b82003-02-18 22:55:36 +0000829#include "elf.h"
bellard09bfb052003-04-10 00:03:40 +0000830
bellard09bfb052003-04-10 00:03:40 +0000831struct exec
832{
Richard Hendersond97ef722010-07-27 10:25:29 -0700833 unsigned int a_info; /* Use macros N_MAGIC, etc for access */
834 unsigned int a_text; /* length of text, in bytes */
835 unsigned int a_data; /* length of data, in bytes */
836 unsigned int a_bss; /* length of uninitialized data area, in bytes */
837 unsigned int a_syms; /* length of symbol table data in file, in bytes */
838 unsigned int a_entry; /* start address */
839 unsigned int a_trsize; /* length of relocation info for text, in bytes */
840 unsigned int a_drsize; /* length of relocation info for data, in bytes */
bellard09bfb052003-04-10 00:03:40 +0000841};
842
843
844#define N_MAGIC(exec) ((exec).a_info & 0xffff)
845#define OMAGIC 0407
846#define NMAGIC 0410
847#define ZMAGIC 0413
848#define QMAGIC 0314
849
bellard09bfb052003-04-10 00:03:40 +0000850/* max code+data+bss space allocated to elf interpreter */
851#define INTERP_MAP_SIZE (32 * 1024 * 1024)
852
853/* max code+data+bss+brk space allocated to ET_DYN executables */
854#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
855
bellard31e31b82003-02-18 22:55:36 +0000856/* Necessary parameters */
bellard54936002003-05-13 00:25:15 +0000857#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
858#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
859#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
bellard31e31b82003-02-18 22:55:36 +0000860
861#define INTERPRETER_NONE 0
862#define INTERPRETER_AOUT 1
863#define INTERPRETER_ELF 2
864
bellard15338fd2005-11-26 11:41:16 +0000865#define DLINFO_ITEMS 12
bellard31e31b82003-02-18 22:55:36 +0000866
bellard09bfb052003-04-10 00:03:40 +0000867static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
868{
Richard Hendersond97ef722010-07-27 10:25:29 -0700869 memcpy(to, from, n);
bellard09bfb052003-04-10 00:03:40 +0000870}
871
bellard31e31b82003-02-18 22:55:36 +0000872static int load_aout_interp(void * exptr, int interp_fd);
873
874#ifdef BSWAP_NEEDED
bellard92a31b12005-02-10 22:00:52 +0000875static void bswap_ehdr(struct elfhdr *ehdr)
bellard31e31b82003-02-18 22:55:36 +0000876{
Richard Hendersond97ef722010-07-27 10:25:29 -0700877 bswap16s(&ehdr->e_type); /* Object file type */
878 bswap16s(&ehdr->e_machine); /* Architecture */
879 bswap32s(&ehdr->e_version); /* Object file version */
880 bswaptls(&ehdr->e_entry); /* Entry point virtual address */
881 bswaptls(&ehdr->e_phoff); /* Program header table file offset */
882 bswaptls(&ehdr->e_shoff); /* Section header table file offset */
883 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
884 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
885 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
886 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
887 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
888 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
889 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
bellard31e31b82003-02-18 22:55:36 +0000890}
891
bellard92a31b12005-02-10 22:00:52 +0000892static void bswap_phdr(struct elf_phdr *phdr)
bellard31e31b82003-02-18 22:55:36 +0000893{
Richard Hendersond97ef722010-07-27 10:25:29 -0700894 bswap32s(&phdr->p_type); /* Segment type */
895 bswaptls(&phdr->p_offset); /* Segment file offset */
896 bswaptls(&phdr->p_vaddr); /* Segment virtual address */
897 bswaptls(&phdr->p_paddr); /* Segment physical address */
898 bswaptls(&phdr->p_filesz); /* Segment size in file */
899 bswaptls(&phdr->p_memsz); /* Segment size in memory */
900 bswap32s(&phdr->p_flags); /* Segment flags */
901 bswaptls(&phdr->p_align); /* Segment alignment */
bellard31e31b82003-02-18 22:55:36 +0000902}
bellard689f9362003-04-29 20:40:07 +0000903
bellard92a31b12005-02-10 22:00:52 +0000904static void bswap_shdr(struct elf_shdr *shdr)
bellard689f9362003-04-29 20:40:07 +0000905{
906 bswap32s(&shdr->sh_name);
907 bswap32s(&shdr->sh_type);
bellard92a31b12005-02-10 22:00:52 +0000908 bswaptls(&shdr->sh_flags);
909 bswaptls(&shdr->sh_addr);
910 bswaptls(&shdr->sh_offset);
911 bswaptls(&shdr->sh_size);
bellard689f9362003-04-29 20:40:07 +0000912 bswap32s(&shdr->sh_link);
913 bswap32s(&shdr->sh_info);
bellard92a31b12005-02-10 22:00:52 +0000914 bswaptls(&shdr->sh_addralign);
915 bswaptls(&shdr->sh_entsize);
bellard689f9362003-04-29 20:40:07 +0000916}
917
j_mayer7a3148a2007-04-05 07:13:51 +0000918static void bswap_sym(struct elf_sym *sym)
bellard689f9362003-04-29 20:40:07 +0000919{
920 bswap32s(&sym->st_name);
j_mayer7a3148a2007-04-05 07:13:51 +0000921 bswaptls(&sym->st_value);
922 bswaptls(&sym->st_size);
bellard689f9362003-04-29 20:40:07 +0000923 bswap16s(&sym->st_shndx);
924}
bellard31e31b82003-02-18 22:55:36 +0000925#endif
926
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300927#ifdef USE_ELF_CORE_DUMP
928static int elf_core_dump(int, const CPUState *);
929
930#ifdef BSWAP_NEEDED
931static void bswap_note(struct elf_note *en)
932{
malc9fdca5a2009-07-18 13:12:20 +0400933 bswap32s(&en->n_namesz);
934 bswap32s(&en->n_descsz);
935 bswap32s(&en->n_type);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300936}
937#endif /* BSWAP_NEEDED */
938
939#endif /* USE_ELF_CORE_DUMP */
940
bellard31e31b82003-02-18 22:55:36 +0000941/*
pbrooke5fe0c52006-06-11 13:32:59 +0000942 * 'copy_elf_strings()' copies argument/envelope strings from user
bellard31e31b82003-02-18 22:55:36 +0000943 * memory to free pages in kernel mem. These are in a format ready
944 * to be put directly into the top of new user memory.
945 *
946 */
blueswir1992f48a2007-10-14 16:27:31 +0000947static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
948 abi_ulong p)
bellard31e31b82003-02-18 22:55:36 +0000949{
950 char *tmp, *tmp1, *pag = NULL;
951 int len, offset = 0;
952
953 if (!p) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700954 return 0; /* bullet-proofing */
bellard31e31b82003-02-18 22:55:36 +0000955 }
956 while (argc-- > 0) {
bellardedf779f2004-02-22 13:40:13 +0000957 tmp = argv[argc];
958 if (!tmp) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700959 fprintf(stderr, "VFS: argc is wrong");
960 exit(-1);
961 }
bellardedf779f2004-02-22 13:40:13 +0000962 tmp1 = tmp;
Richard Hendersond97ef722010-07-27 10:25:29 -0700963 while (*tmp++);
964 len = tmp - tmp1;
965 if (p < len) { /* this shouldn't happen - 128kB */
966 return 0;
967 }
968 while (len) {
969 --p; --tmp; --len;
970 if (--offset < 0) {
971 offset = p % TARGET_PAGE_SIZE;
pbrook53a59602006-03-25 19:31:22 +0000972 pag = (char *)page[p/TARGET_PAGE_SIZE];
bellard44a91ca2004-01-18 22:05:44 +0000973 if (!pag) {
pbrook53a59602006-03-25 19:31:22 +0000974 pag = (char *)malloc(TARGET_PAGE_SIZE);
j_mayer4118a972007-09-27 04:10:43 +0000975 memset(pag, 0, TARGET_PAGE_SIZE);
pbrook53a59602006-03-25 19:31:22 +0000976 page[p/TARGET_PAGE_SIZE] = pag;
bellard44a91ca2004-01-18 22:05:44 +0000977 if (!pag)
978 return 0;
Richard Hendersond97ef722010-07-27 10:25:29 -0700979 }
980 }
981 if (len == 0 || offset == 0) {
982 *(pag + offset) = *tmp;
983 }
984 else {
985 int bytes_to_copy = (len > offset) ? offset : len;
986 tmp -= bytes_to_copy;
987 p -= bytes_to_copy;
988 offset -= bytes_to_copy;
989 len -= bytes_to_copy;
990 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
991 }
992 }
bellard31e31b82003-02-18 22:55:36 +0000993 }
994 return p;
995}
996
blueswir1992f48a2007-10-14 16:27:31 +0000997static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
998 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +0000999{
blueswir1992f48a2007-10-14 16:27:31 +00001000 abi_ulong stack_base, size, error;
bellard31e31b82003-02-18 22:55:36 +00001001 int i;
bellard31e31b82003-02-18 22:55:36 +00001002
1003 /* Create enough stack to hold everything. If we don't use
1004 * it for args, we'll use it for something else...
1005 */
Richard Henderson703e0e82010-03-19 14:21:13 -07001006 size = guest_stack_size;
bellard54936002003-05-13 00:25:15 +00001007 if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
1008 size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
ths5fafdf22007-09-16 21:08:06 +00001009 error = target_mmap(0,
bellard83fb7ad2004-07-05 21:25:26 +00001010 size + qemu_host_page_size,
bellard54936002003-05-13 00:25:15 +00001011 PROT_READ | PROT_WRITE,
1012 MAP_PRIVATE | MAP_ANONYMOUS,
1013 -1, 0);
bellard09bfb052003-04-10 00:03:40 +00001014 if (error == -1) {
1015 perror("stk mmap");
1016 exit(-1);
bellard31e31b82003-02-18 22:55:36 +00001017 }
bellard09bfb052003-04-10 00:03:40 +00001018 /* we reserve one extra page at the top of the stack as guard */
bellard83fb7ad2004-07-05 21:25:26 +00001019 target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
bellard09bfb052003-04-10 00:03:40 +00001020
Paul Brook97374d32010-06-16 13:03:51 +01001021 info->stack_limit = error;
bellard54936002003-05-13 00:25:15 +00001022 stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
bellard09bfb052003-04-10 00:03:40 +00001023 p += stack_base;
1024
bellard31e31b82003-02-18 22:55:36 +00001025 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001026 if (bprm->page[i]) {
1027 info->rss++;
bellard579a97f2007-11-11 14:26:47 +00001028 /* FIXME - check return value of memcpy_to_target() for failure */
Richard Hendersond97ef722010-07-27 10:25:29 -07001029 memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
1030 free(bprm->page[i]);
1031 }
pbrook53a59602006-03-25 19:31:22 +00001032 stack_base += TARGET_PAGE_SIZE;
bellard31e31b82003-02-18 22:55:36 +00001033 }
1034 return p;
1035}
1036
Richard Hendersoncf129f32010-07-27 10:25:27 -07001037/* Map and zero the bss. We need to explicitly zero any fractional pages
1038 after the data section (i.e. bss). */
1039static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
bellard31e31b82003-02-18 22:55:36 +00001040{
Richard Hendersoncf129f32010-07-27 10:25:27 -07001041 uintptr_t host_start, host_map_start, host_end;
bellard31e31b82003-02-18 22:55:36 +00001042
Richard Hendersoncf129f32010-07-27 10:25:27 -07001043 last_bss = TARGET_PAGE_ALIGN(last_bss);
bellard31e31b82003-02-18 22:55:36 +00001044
Richard Hendersoncf129f32010-07-27 10:25:27 -07001045 /* ??? There is confusion between qemu_real_host_page_size and
1046 qemu_host_page_size here and elsewhere in target_mmap, which
1047 may lead to the end of the data section mapping from the file
1048 not being mapped. At least there was an explicit test and
1049 comment for that here, suggesting that "the file size must
1050 be known". The comment probably pre-dates the introduction
1051 of the fstat system call in target_mmap which does in fact
1052 find out the size. What isn't clear is if the workaround
1053 here is still actually needed. For now, continue with it,
1054 but merge it with the "normal" mmap that would allocate the bss. */
bellard31e31b82003-02-18 22:55:36 +00001055
Richard Hendersoncf129f32010-07-27 10:25:27 -07001056 host_start = (uintptr_t) g2h(elf_bss);
1057 host_end = (uintptr_t) g2h(last_bss);
1058 host_map_start = (host_start + qemu_real_host_page_size - 1);
1059 host_map_start &= -qemu_real_host_page_size;
ths768a4a32006-12-14 13:32:11 +00001060
Richard Hendersoncf129f32010-07-27 10:25:27 -07001061 if (host_map_start < host_end) {
1062 void *p = mmap((void *)host_map_start, host_end - host_map_start,
1063 prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1064 if (p == MAP_FAILED) {
1065 perror("cannot mmap brk");
1066 exit(-1);
bellard853d6f72003-09-30 20:58:32 +00001067 }
1068
Richard Hendersoncf129f32010-07-27 10:25:27 -07001069 /* Since we didn't use target_mmap, make sure to record
1070 the validity of the pages with qemu. */
1071 page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
1072 }
bellard31e31b82003-02-18 22:55:36 +00001073
Richard Hendersoncf129f32010-07-27 10:25:27 -07001074 if (host_start < host_map_start) {
1075 memset((void *)host_start, 0, host_map_start - host_start);
1076 }
1077}
bellardedf779f2004-02-22 13:40:13 +00001078
blueswir1992f48a2007-10-14 16:27:31 +00001079static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
1080 struct elfhdr * exec,
1081 abi_ulong load_addr,
1082 abi_ulong load_bias,
1083 abi_ulong interp_load_addr, int ibcs,
1084 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +00001085{
Richard Hendersond97ef722010-07-27 10:25:29 -07001086 abi_ulong sp;
1087 int size;
1088 abi_ulong u_platform;
1089 const char *k_platform;
1090 const int n = sizeof(elf_addr_t);
pbrook53a59602006-03-25 19:31:22 +00001091
Richard Hendersond97ef722010-07-27 10:25:29 -07001092 sp = p;
1093 u_platform = 0;
1094 k_platform = ELF_PLATFORM;
1095 if (k_platform) {
1096 size_t len = strlen(k_platform) + 1;
1097 sp -= (len + n - 1) & ~(n - 1);
1098 u_platform = sp;
1099 /* FIXME - check return value of memcpy_to_target() for failure */
1100 memcpy_to_target(sp, k_platform, len);
1101 }
1102 /*
1103 * Force 16 byte _final_ alignment here for generality.
1104 */
1105 sp = sp &~ (abi_ulong)15;
1106 size = (DLINFO_ITEMS + 1) * 2;
1107 if (k_platform)
1108 size += 2;
bellardf5155282004-01-04 15:46:50 +00001109#ifdef DLINFO_ARCH_ITEMS
Richard Hendersond97ef722010-07-27 10:25:29 -07001110 size += DLINFO_ARCH_ITEMS * 2;
bellardf5155282004-01-04 15:46:50 +00001111#endif
Richard Hendersond97ef722010-07-27 10:25:29 -07001112 size += envc + argc + 2;
1113 size += (!ibcs ? 3 : 1); /* argc itself */
1114 size *= n;
1115 if (size & 15)
1116 sp -= 16 - (size & 15);
ths3b46e622007-09-17 08:09:54 +00001117
Richard Hendersond97ef722010-07-27 10:25:29 -07001118 /* This is correct because Linux defines
1119 * elf_addr_t as Elf32_Off / Elf64_Off
1120 */
1121#define NEW_AUX_ENT(id, val) do { \
1122 sp -= n; put_user_ual(val, sp); \
1123 sp -= n; put_user_ual(id, sp); \
1124 } while(0)
bellard2f619692007-11-16 10:46:05 +00001125
Richard Hendersond97ef722010-07-27 10:25:29 -07001126 NEW_AUX_ENT (AT_NULL, 0);
bellardf5155282004-01-04 15:46:50 +00001127
Richard Hendersond97ef722010-07-27 10:25:29 -07001128 /* There must be exactly DLINFO_ITEMS entries here. */
1129 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
1130 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1131 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1132 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
1133 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
1134 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
1135 NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
1136 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1137 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1138 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1139 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1140 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1141 NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
1142 if (k_platform)
1143 NEW_AUX_ENT(AT_PLATFORM, u_platform);
bellardf5155282004-01-04 15:46:50 +00001144#ifdef ARCH_DLINFO
Richard Hendersond97ef722010-07-27 10:25:29 -07001145 /*
1146 * ARCH_DLINFO must come last so platform specific code can enforce
1147 * special alignment requirements on the AUXV if necessary (eg. PPC).
1148 */
1149 ARCH_DLINFO;
bellardf5155282004-01-04 15:46:50 +00001150#endif
1151#undef NEW_AUX_ENT
1152
Richard Hendersond97ef722010-07-27 10:25:29 -07001153 info->saved_auxv = sp;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001154
Richard Hendersond97ef722010-07-27 10:25:29 -07001155 sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
1156 return sp;
bellard31e31b82003-02-18 22:55:36 +00001157}
1158
1159
blueswir1992f48a2007-10-14 16:27:31 +00001160static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
1161 int interpreter_fd,
1162 abi_ulong *interp_load_addr)
bellard31e31b82003-02-18 22:55:36 +00001163{
Richard Hendersond97ef722010-07-27 10:25:29 -07001164 struct elf_phdr *elf_phdata = NULL;
1165 struct elf_phdr *eppnt;
1166 abi_ulong load_addr = 0;
1167 int load_addr_set = 0;
1168 int retval;
1169 abi_ulong error;
1170 int i;
ths5fafdf22007-09-16 21:08:06 +00001171
Richard Hendersond97ef722010-07-27 10:25:29 -07001172 error = 0;
bellard31e31b82003-02-18 22:55:36 +00001173
bellard644c4332003-03-24 23:00:36 +00001174#ifdef BSWAP_NEEDED
Richard Hendersond97ef722010-07-27 10:25:29 -07001175 bswap_ehdr(interp_elf_ex);
bellard644c4332003-03-24 23:00:36 +00001176#endif
Richard Hendersond97ef722010-07-27 10:25:29 -07001177 /* First of all, some simple consistency checks */
1178 if ((interp_elf_ex->e_type != ET_EXEC &&
1179 interp_elf_ex->e_type != ET_DYN) ||
1180 !elf_check_arch(interp_elf_ex->e_machine)) {
1181 return ~((abi_ulong)0UL);
1182 }
ths5fafdf22007-09-16 21:08:06 +00001183
bellard644c4332003-03-24 23:00:36 +00001184
Richard Hendersond97ef722010-07-27 10:25:29 -07001185 /* Now read in all of the header information */
ths5fafdf22007-09-16 21:08:06 +00001186
Richard Hendersond97ef722010-07-27 10:25:29 -07001187 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
1188 return ~(abi_ulong)0UL;
ths5fafdf22007-09-16 21:08:06 +00001189
Richard Hendersond97ef722010-07-27 10:25:29 -07001190 elf_phdata = (struct elf_phdr *)
1191 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
bellard31e31b82003-02-18 22:55:36 +00001192
Richard Hendersond97ef722010-07-27 10:25:29 -07001193 if (!elf_phdata)
1194 return ~((abi_ulong)0UL);
ths5fafdf22007-09-16 21:08:06 +00001195
Richard Hendersond97ef722010-07-27 10:25:29 -07001196 /*
1197 * If the size of this structure has changed, then punt, since
1198 * we will be doing the wrong thing.
1199 */
1200 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
1201 free(elf_phdata);
1202 return ~((abi_ulong)0UL);
1203 }
bellard31e31b82003-02-18 22:55:36 +00001204
Richard Hendersond97ef722010-07-27 10:25:29 -07001205 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
1206 if(retval >= 0) {
1207 retval = read(interpreter_fd,
1208 (char *) elf_phdata,
1209 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
1210 }
1211 if (retval < 0) {
1212 perror("load_elf_interp");
1213 exit(-1);
1214 free (elf_phdata);
1215 return retval;
1216 }
bellard31e31b82003-02-18 22:55:36 +00001217#ifdef BSWAP_NEEDED
Richard Hendersond97ef722010-07-27 10:25:29 -07001218 eppnt = elf_phdata;
1219 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
1220 bswap_phdr(eppnt);
1221 }
bellard31e31b82003-02-18 22:55:36 +00001222#endif
bellard09bfb052003-04-10 00:03:40 +00001223
Richard Hendersond97ef722010-07-27 10:25:29 -07001224 if (interp_elf_ex->e_type == ET_DYN) {
1225 /* in order to avoid hardcoding the interpreter load
1226 address in qemu, we allocate a big enough memory zone */
1227 error = target_mmap(0, INTERP_MAP_SIZE,
1228 PROT_NONE, MAP_PRIVATE | MAP_ANON,
1229 -1, 0);
1230 if (error == -1) {
1231 perror("mmap");
1232 exit(-1);
1233 }
1234 load_addr = error;
1235 load_addr_set = 1;
1236 }
1237
1238 eppnt = elf_phdata;
1239 for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
1240 if (eppnt->p_type == PT_LOAD) {
1241 int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
1242 int elf_prot = 0;
1243 abi_ulong vaddr = 0;
1244
1245 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
1246 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1247 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1248 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
1249 elf_type |= MAP_FIXED;
1250 vaddr = eppnt->p_vaddr;
bellard09bfb052003-04-10 00:03:40 +00001251 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001252 error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
1253 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
1254 elf_prot,
1255 elf_type,
1256 interpreter_fd,
1257 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
bellard09bfb052003-04-10 00:03:40 +00001258
Richard Hendersond97ef722010-07-27 10:25:29 -07001259 if (error == -1) {
1260 /* Real error */
1261 close(interpreter_fd);
1262 free(elf_phdata);
1263 return ~((abi_ulong)0UL);
1264 }
bellard31e31b82003-02-18 22:55:36 +00001265
Richard Hendersond97ef722010-07-27 10:25:29 -07001266 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
1267 load_addr = error;
1268 load_addr_set = 1;
1269 }
bellard31e31b82003-02-18 22:55:36 +00001270
Richard Hendersoncf129f32010-07-27 10:25:27 -07001271 /* If the load segment requests extra zeros (e.g. bss), map it. */
1272 if (eppnt->p_filesz < eppnt->p_memsz) {
1273 abi_ulong base = load_addr + eppnt->p_vaddr;
1274 zero_bss(base + eppnt->p_filesz,
1275 base + eppnt->p_memsz, elf_prot);
1276 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001277 }
ths5fafdf22007-09-16 21:08:06 +00001278
Richard Hendersond97ef722010-07-27 10:25:29 -07001279 /* Now use mmap to map the library into memory. */
bellard31e31b82003-02-18 22:55:36 +00001280
Richard Hendersond97ef722010-07-27 10:25:29 -07001281 close(interpreter_fd);
1282 free(elf_phdata);
bellard31e31b82003-02-18 22:55:36 +00001283
Richard Hendersond97ef722010-07-27 10:25:29 -07001284 *interp_load_addr = load_addr;
1285 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
bellard31e31b82003-02-18 22:55:36 +00001286}
1287
pbrook49918a72008-10-22 15:11:31 +00001288static int symfind(const void *s0, const void *s1)
1289{
1290 struct elf_sym *key = (struct elf_sym *)s0;
1291 struct elf_sym *sym = (struct elf_sym *)s1;
1292 int result = 0;
1293 if (key->st_value < sym->st_value) {
1294 result = -1;
Laurent Desnoguesec822002009-07-30 19:23:49 +02001295 } else if (key->st_value >= sym->st_value + sym->st_size) {
pbrook49918a72008-10-22 15:11:31 +00001296 result = 1;
1297 }
1298 return result;
1299}
1300
1301static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
1302{
1303#if ELF_CLASS == ELFCLASS32
1304 struct elf_sym *syms = s->disas_symtab.elf32;
1305#else
1306 struct elf_sym *syms = s->disas_symtab.elf64;
1307#endif
1308
1309 // binary search
1310 struct elf_sym key;
1311 struct elf_sym *sym;
1312
1313 key.st_value = orig_addr;
1314
1315 sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
Blue Swirl7cba04f2009-08-01 10:13:20 +00001316 if (sym != NULL) {
pbrook49918a72008-10-22 15:11:31 +00001317 return s->disas_strtab + sym->st_name;
1318 }
1319
1320 return "";
1321}
1322
1323/* FIXME: This should use elf_ops.h */
1324static int symcmp(const void *s0, const void *s1)
1325{
1326 struct elf_sym *sym0 = (struct elf_sym *)s0;
1327 struct elf_sym *sym1 = (struct elf_sym *)s1;
1328 return (sym0->st_value < sym1->st_value)
1329 ? -1
1330 : ((sym0->st_value > sym1->st_value) ? 1 : 0);
1331}
1332
bellard689f9362003-04-29 20:40:07 +00001333/* Best attempt to load symbols from this ELF object. */
1334static void load_symbols(struct elfhdr *hdr, int fd)
1335{
pbrook49918a72008-10-22 15:11:31 +00001336 unsigned int i, nsyms;
bellard689f9362003-04-29 20:40:07 +00001337 struct elf_shdr sechdr, symtab, strtab;
1338 char *strings;
bellarde80cfcf2004-12-19 23:18:01 +00001339 struct syminfo *s;
pbrook49918a72008-10-22 15:11:31 +00001340 struct elf_sym *syms;
bellard31e31b82003-02-18 22:55:36 +00001341
bellard689f9362003-04-29 20:40:07 +00001342 lseek(fd, hdr->e_shoff, SEEK_SET);
1343 for (i = 0; i < hdr->e_shnum; i++) {
pbrook49918a72008-10-22 15:11:31 +00001344 if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
1345 return;
bellard689f9362003-04-29 20:40:07 +00001346#ifdef BSWAP_NEEDED
pbrook49918a72008-10-22 15:11:31 +00001347 bswap_shdr(&sechdr);
bellard689f9362003-04-29 20:40:07 +00001348#endif
pbrook49918a72008-10-22 15:11:31 +00001349 if (sechdr.sh_type == SHT_SYMTAB) {
1350 symtab = sechdr;
1351 lseek(fd, hdr->e_shoff
1352 + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
1353 if (read(fd, &strtab, sizeof(strtab))
1354 != sizeof(strtab))
1355 return;
bellard689f9362003-04-29 20:40:07 +00001356#ifdef BSWAP_NEEDED
pbrook49918a72008-10-22 15:11:31 +00001357 bswap_shdr(&strtab);
bellard689f9362003-04-29 20:40:07 +00001358#endif
pbrook49918a72008-10-22 15:11:31 +00001359 goto found;
1360 }
bellard689f9362003-04-29 20:40:07 +00001361 }
1362 return; /* Shouldn't happen... */
1363
1364 found:
1365 /* Now know where the strtab and symtab are. Snarf them. */
bellarde80cfcf2004-12-19 23:18:01 +00001366 s = malloc(sizeof(*s));
pbrook49918a72008-10-22 15:11:31 +00001367 syms = malloc(symtab.sh_size);
1368 if (!syms)
1369 return;
bellarde80cfcf2004-12-19 23:18:01 +00001370 s->disas_strtab = strings = malloc(strtab.sh_size);
pbrook49918a72008-10-22 15:11:31 +00001371 if (!s->disas_strtab)
1372 return;
ths5fafdf22007-09-16 21:08:06 +00001373
bellard689f9362003-04-29 20:40:07 +00001374 lseek(fd, symtab.sh_offset, SEEK_SET);
pbrook49918a72008-10-22 15:11:31 +00001375 if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
1376 return;
bellard689f9362003-04-29 20:40:07 +00001377
pbrook49918a72008-10-22 15:11:31 +00001378 nsyms = symtab.sh_size / sizeof(struct elf_sym);
1379
1380 i = 0;
1381 while (i < nsyms) {
bellard689f9362003-04-29 20:40:07 +00001382#ifdef BSWAP_NEEDED
pbrook49918a72008-10-22 15:11:31 +00001383 bswap_sym(syms + i);
bellard689f9362003-04-29 20:40:07 +00001384#endif
pbrook49918a72008-10-22 15:11:31 +00001385 // Throw away entries which we do not need.
1386 if (syms[i].st_shndx == SHN_UNDEF ||
Richard Hendersond97ef722010-07-27 10:25:29 -07001387 syms[i].st_shndx >= SHN_LORESERVE ||
1388 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
pbrook49918a72008-10-22 15:11:31 +00001389 nsyms--;
1390 if (i < nsyms) {
1391 syms[i] = syms[nsyms];
1392 }
1393 continue;
1394 }
1395#if defined(TARGET_ARM) || defined (TARGET_MIPS)
1396 /* The bottom address bit marks a Thumb or MIPS16 symbol. */
1397 syms[i].st_value &= ~(target_ulong)1;
blueswir10774bed2007-07-05 13:23:29 +00001398#endif
pbrook49918a72008-10-22 15:11:31 +00001399 i++;
blueswir10774bed2007-07-05 13:23:29 +00001400 }
pbrook49918a72008-10-22 15:11:31 +00001401 syms = realloc(syms, nsyms * sizeof(*syms));
bellard689f9362003-04-29 20:40:07 +00001402
pbrook49918a72008-10-22 15:11:31 +00001403 qsort(syms, nsyms, sizeof(*syms), symcmp);
1404
bellard689f9362003-04-29 20:40:07 +00001405 lseek(fd, strtab.sh_offset, SEEK_SET);
1406 if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
pbrook49918a72008-10-22 15:11:31 +00001407 return;
1408 s->disas_num_syms = nsyms;
1409#if ELF_CLASS == ELFCLASS32
1410 s->disas_symtab.elf32 = syms;
Paul Brook9f9f0302010-03-01 03:55:48 +00001411 s->lookup_symbol = lookup_symbolxx;
pbrook49918a72008-10-22 15:11:31 +00001412#else
1413 s->disas_symtab.elf64 = syms;
Paul Brook9f9f0302010-03-01 03:55:48 +00001414 s->lookup_symbol = lookup_symbolxx;
pbrook49918a72008-10-22 15:11:31 +00001415#endif
bellarde80cfcf2004-12-19 23:18:01 +00001416 s->next = syminfos;
1417 syminfos = s;
bellard689f9362003-04-29 20:40:07 +00001418}
bellard31e31b82003-02-18 22:55:36 +00001419
pbrooke5fe0c52006-06-11 13:32:59 +00001420int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1421 struct image_info * info)
bellard31e31b82003-02-18 22:55:36 +00001422{
1423 struct elfhdr elf_ex;
1424 struct elfhdr interp_elf_ex;
1425 struct exec interp_ex;
1426 int interpreter_fd = -1; /* avoid warning */
blueswir1992f48a2007-10-14 16:27:31 +00001427 abi_ulong load_addr, load_bias;
bellard31e31b82003-02-18 22:55:36 +00001428 int load_addr_set = 0;
1429 unsigned int interpreter_type = INTERPRETER_NONE;
1430 unsigned char ibcs2_interpreter;
1431 int i;
blueswir1992f48a2007-10-14 16:27:31 +00001432 abi_ulong mapped_addr;
bellard31e31b82003-02-18 22:55:36 +00001433 struct elf_phdr * elf_ppnt;
1434 struct elf_phdr *elf_phdata;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001435 abi_ulong k, elf_brk;
bellard31e31b82003-02-18 22:55:36 +00001436 int retval;
1437 char * elf_interpreter;
blueswir1992f48a2007-10-14 16:27:31 +00001438 abi_ulong elf_entry, interp_load_addr = 0;
bellard31e31b82003-02-18 22:55:36 +00001439 int status;
blueswir1992f48a2007-10-14 16:27:31 +00001440 abi_ulong start_code, end_code, start_data, end_data;
1441 abi_ulong reloc_func_desc = 0;
1442 abi_ulong elf_stack;
bellard31e31b82003-02-18 22:55:36 +00001443 char passed_fileno[6];
1444
1445 ibcs2_interpreter = 0;
1446 status = 0;
1447 load_addr = 0;
bellard09bfb052003-04-10 00:03:40 +00001448 load_bias = 0;
bellard31e31b82003-02-18 22:55:36 +00001449 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
1450#ifdef BSWAP_NEEDED
1451 bswap_ehdr(&elf_ex);
1452#endif
1453
bellard31e31b82003-02-18 22:55:36 +00001454 /* First of all, some simple consistency checks */
1455 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
Richard Hendersond97ef722010-07-27 10:25:29 -07001456 (! elf_check_arch(elf_ex.e_machine))) {
1457 return -ENOEXEC;
bellard31e31b82003-02-18 22:55:36 +00001458 }
1459
pbrooke5fe0c52006-06-11 13:32:59 +00001460 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1461 bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1462 bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1463 if (!bprm->p) {
1464 retval = -E2BIG;
1465 }
1466
bellard31e31b82003-02-18 22:55:36 +00001467 /* Now read in all of the header information */
bellard31e31b82003-02-18 22:55:36 +00001468 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
1469 if (elf_phdata == NULL) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001470 return -ENOMEM;
bellard31e31b82003-02-18 22:55:36 +00001471 }
1472
1473 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
1474 if(retval > 0) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001475 retval = read(bprm->fd, (char *) elf_phdata,
1476 elf_ex.e_phentsize * elf_ex.e_phnum);
bellard31e31b82003-02-18 22:55:36 +00001477 }
1478
1479 if (retval < 0) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001480 perror("load_elf_binary");
1481 exit(-1);
1482 free (elf_phdata);
1483 return -errno;
bellard31e31b82003-02-18 22:55:36 +00001484 }
1485
bellardb17780d2003-02-18 23:32:15 +00001486#ifdef BSWAP_NEEDED
1487 elf_ppnt = elf_phdata;
1488 for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
1489 bswap_phdr(elf_ppnt);
1490 }
1491#endif
bellard31e31b82003-02-18 22:55:36 +00001492 elf_ppnt = elf_phdata;
1493
bellard31e31b82003-02-18 22:55:36 +00001494 elf_brk = 0;
1495
blueswir1992f48a2007-10-14 16:27:31 +00001496 elf_stack = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001497 elf_interpreter = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00001498 start_code = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001499 end_code = 0;
j_mayer863cf0b2007-10-07 15:59:45 +00001500 start_data = 0;
bellard31e31b82003-02-18 22:55:36 +00001501 end_data = 0;
blueswir198448f52008-09-30 18:16:09 +00001502 interp_ex.a_info = 0;
bellard31e31b82003-02-18 22:55:36 +00001503
1504 for(i=0;i < elf_ex.e_phnum; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001505 if (elf_ppnt->p_type == PT_INTERP) {
1506 if ( elf_interpreter != NULL )
1507 {
1508 free (elf_phdata);
1509 free(elf_interpreter);
1510 close(bprm->fd);
1511 return -EINVAL;
1512 }
bellard31e31b82003-02-18 22:55:36 +00001513
Richard Hendersond97ef722010-07-27 10:25:29 -07001514 /* This is the program interpreter used for
1515 * shared libraries - for now assume that this
1516 * is an a.out format binary
1517 */
bellard31e31b82003-02-18 22:55:36 +00001518
Richard Hendersond97ef722010-07-27 10:25:29 -07001519 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
bellard31e31b82003-02-18 22:55:36 +00001520
Richard Hendersond97ef722010-07-27 10:25:29 -07001521 if (elf_interpreter == NULL) {
1522 free (elf_phdata);
1523 close(bprm->fd);
1524 return -ENOMEM;
1525 }
bellard31e31b82003-02-18 22:55:36 +00001526
Richard Hendersond97ef722010-07-27 10:25:29 -07001527 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
1528 if(retval >= 0) {
1529 retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
1530 }
1531 if(retval < 0) {
1532 perror("load_elf_binary2");
1533 exit(-1);
1534 }
bellard31e31b82003-02-18 22:55:36 +00001535
Richard Hendersond97ef722010-07-27 10:25:29 -07001536 /* If the program interpreter is one of these two,
1537 then assume an iBCS2 image. Otherwise assume
1538 a native linux image. */
bellard31e31b82003-02-18 22:55:36 +00001539
Richard Hendersond97ef722010-07-27 10:25:29 -07001540 /* JRP - Need to add X86 lib dir stuff here... */
bellard31e31b82003-02-18 22:55:36 +00001541
Richard Hendersond97ef722010-07-27 10:25:29 -07001542 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
1543 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
1544 ibcs2_interpreter = 1;
1545 }
bellard31e31b82003-02-18 22:55:36 +00001546
1547#if 0
Richard Hendersond97ef722010-07-27 10:25:29 -07001548 printf("Using ELF interpreter %s\n", path(elf_interpreter));
bellard31e31b82003-02-18 22:55:36 +00001549#endif
Richard Hendersond97ef722010-07-27 10:25:29 -07001550 if (retval >= 0) {
1551 retval = open(path(elf_interpreter), O_RDONLY);
1552 if(retval >= 0) {
1553 interpreter_fd = retval;
1554 }
1555 else {
1556 perror(elf_interpreter);
1557 exit(-1);
1558 /* retval = -errno; */
1559 }
1560 }
bellard31e31b82003-02-18 22:55:36 +00001561
Richard Hendersond97ef722010-07-27 10:25:29 -07001562 if (retval >= 0) {
1563 retval = lseek(interpreter_fd, 0, SEEK_SET);
1564 if(retval >= 0) {
1565 retval = read(interpreter_fd,bprm->buf,128);
1566 }
1567 }
1568 if (retval >= 0) {
1569 interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
1570 interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
1571 }
1572 if (retval < 0) {
1573 perror("load_elf_binary3");
1574 exit(-1);
1575 free (elf_phdata);
1576 free(elf_interpreter);
1577 close(bprm->fd);
1578 return retval;
1579 }
1580 }
1581 elf_ppnt++;
bellard31e31b82003-02-18 22:55:36 +00001582 }
1583
1584 /* Some simple consistency checks for the interpreter */
1585 if (elf_interpreter){
Richard Hendersond97ef722010-07-27 10:25:29 -07001586 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
bellard31e31b82003-02-18 22:55:36 +00001587
Richard Hendersond97ef722010-07-27 10:25:29 -07001588 /* Now figure out which format our binary is */
1589 if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
1590 (N_MAGIC(interp_ex) != QMAGIC)) {
1591 interpreter_type = INTERPRETER_ELF;
1592 }
bellard31e31b82003-02-18 22:55:36 +00001593
Richard Hendersond97ef722010-07-27 10:25:29 -07001594 if (interp_elf_ex.e_ident[0] != 0x7f ||
blueswir1b55266b2008-09-20 08:07:15 +00001595 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001596 interpreter_type &= ~INTERPRETER_ELF;
1597 }
bellard31e31b82003-02-18 22:55:36 +00001598
Richard Hendersond97ef722010-07-27 10:25:29 -07001599 if (!interpreter_type) {
1600 free(elf_interpreter);
1601 free(elf_phdata);
1602 close(bprm->fd);
1603 return -ELIBBAD;
1604 }
bellard31e31b82003-02-18 22:55:36 +00001605 }
1606
1607 /* OK, we are done with that, now set up the arg stuff,
1608 and then start this sucker up */
1609
pbrooke5fe0c52006-06-11 13:32:59 +00001610 {
Richard Hendersond97ef722010-07-27 10:25:29 -07001611 char * passed_p;
bellard31e31b82003-02-18 22:55:36 +00001612
Richard Hendersond97ef722010-07-27 10:25:29 -07001613 if (interpreter_type == INTERPRETER_AOUT) {
1614 snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
1615 passed_p = passed_fileno;
bellard31e31b82003-02-18 22:55:36 +00001616
Richard Hendersond97ef722010-07-27 10:25:29 -07001617 if (elf_interpreter) {
1618 bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
1619 bprm->argc++;
1620 }
1621 }
1622 if (!bprm->p) {
1623 if (elf_interpreter) {
1624 free(elf_interpreter);
1625 }
1626 free (elf_phdata);
1627 close(bprm->fd);
1628 return -E2BIG;
1629 }
bellard31e31b82003-02-18 22:55:36 +00001630 }
1631
1632 /* OK, This is the point of no return */
1633 info->end_data = 0;
1634 info->end_code = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001635 info->start_mmap = (abi_ulong)ELF_START_MMAP;
bellard31e31b82003-02-18 22:55:36 +00001636 info->mmap = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001637 elf_entry = (abi_ulong) elf_ex.e_entry;
bellard31e31b82003-02-18 22:55:36 +00001638
Paul Brook379f6692009-07-17 12:48:08 +01001639#if defined(CONFIG_USE_GUEST_BASE)
1640 /*
1641 * In case where user has not explicitly set the guest_base, we
1642 * probe here that should we set it automatically.
1643 */
Paul Brook68a1c812010-05-29 02:27:35 +01001644 if (!(have_guest_base || reserved_va)) {
Paul Brook379f6692009-07-17 12:48:08 +01001645 /*
Paul Brookc581ded2010-05-05 16:32:59 +01001646 * Go through ELF program header table and find the address
1647 * range used by loadable segments. Check that this is available on
1648 * the host, and if not find a suitable value for guest_base. */
1649 abi_ulong app_start = ~0;
1650 abi_ulong app_end = 0;
1651 abi_ulong addr;
1652 unsigned long host_start;
1653 unsigned long real_start;
1654 unsigned long host_size;
Paul Brook379f6692009-07-17 12:48:08 +01001655 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
Richard Hendersond97ef722010-07-27 10:25:29 -07001656 i++, elf_ppnt++) {
Paul Brook379f6692009-07-17 12:48:08 +01001657 if (elf_ppnt->p_type != PT_LOAD)
1658 continue;
Paul Brookc581ded2010-05-05 16:32:59 +01001659 addr = elf_ppnt->p_vaddr;
1660 if (addr < app_start) {
1661 app_start = addr;
1662 }
1663 addr += elf_ppnt->p_memsz;
1664 if (addr > app_end) {
1665 app_end = addr;
Paul Brook379f6692009-07-17 12:48:08 +01001666 }
1667 }
Paul Brookc581ded2010-05-05 16:32:59 +01001668
1669 /* If we don't have any loadable segments then something
1670 is very wrong. */
1671 assert(app_start < app_end);
1672
1673 /* Round addresses to page boundaries. */
1674 app_start = app_start & qemu_host_page_mask;
1675 app_end = HOST_PAGE_ALIGN(app_end);
1676 if (app_start < mmap_min_addr) {
1677 host_start = HOST_PAGE_ALIGN(mmap_min_addr);
1678 } else {
1679 host_start = app_start;
1680 if (host_start != app_start) {
1681 fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
1682 abort();
1683 }
1684 }
1685 host_size = app_end - app_start;
1686 while (1) {
1687 /* Do not use mmap_find_vma here because that is limited to the
1688 guest address space. We are going to make the
1689 guest address space fit whatever we're given. */
1690 real_start = (unsigned long)mmap((void *)host_start, host_size,
1691 PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
1692 if (real_start == (unsigned long)-1) {
1693 fprintf(stderr, "qemu: Virtual memory exausted\n");
1694 abort();
1695 }
1696 if (real_start == host_start) {
1697 break;
1698 }
1699 /* That address didn't work. Unmap and try a different one.
1700 The address the host picked because is typically
1701 right at the top of the host address space and leaves the
1702 guest with no usable address space. Resort to a linear search.
1703 We already compensated for mmap_min_addr, so this should not
1704 happen often. Probably means we got unlucky and host address
1705 space randomization put a shared library somewhere
1706 inconvenient. */
1707 munmap((void *)real_start, host_size);
1708 host_start += qemu_host_page_size;
1709 if (host_start == app_start) {
1710 /* Theoretically possible if host doesn't have any
1711 suitably aligned areas. Normally the first mmap will
1712 fail. */
1713 fprintf(stderr, "qemu: Unable to find space for application\n");
1714 abort();
1715 }
1716 }
1717 qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
1718 " to 0x%lx\n", app_start, real_start);
1719 guest_base = real_start - app_start;
Paul Brook379f6692009-07-17 12:48:08 +01001720 }
1721#endif /* CONFIG_USE_GUEST_BASE */
1722
bellard31e31b82003-02-18 22:55:36 +00001723 /* Do this so that we can load the interpreter, if need be. We will
1724 change some of these later */
1725 info->rss = 0;
1726 bprm->p = setup_arg_pages(bprm->p, bprm, info);
1727 info->start_stack = bprm->p;
1728
1729 /* Now we do a little grungy work by mmaping the ELF image into
1730 * the correct location in memory. At this point, we assume that
1731 * the image should be loaded at fixed address, not at a variable
1732 * address.
1733 */
1734
bellard31e31b82003-02-18 22:55:36 +00001735 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
bellard09bfb052003-04-10 00:03:40 +00001736 int elf_prot = 0;
1737 int elf_flags = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001738 abi_ulong error;
ths3b46e622007-09-17 08:09:54 +00001739
Richard Hendersond97ef722010-07-27 10:25:29 -07001740 if (elf_ppnt->p_type != PT_LOAD)
bellard09bfb052003-04-10 00:03:40 +00001741 continue;
ths3b46e622007-09-17 08:09:54 +00001742
bellard09bfb052003-04-10 00:03:40 +00001743 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
1744 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1745 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1746 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
1747 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
1748 elf_flags |= MAP_FIXED;
1749 } else if (elf_ex.e_type == ET_DYN) {
1750 /* Try and get dynamic programs out of the way of the default mmap
1751 base, as well as whatever program they might try to exec. This
1752 is because the brk will follow the loader, and is not movable. */
1753 /* NOTE: for qemu, we do a big mmap to get enough space
thse91c8a72007-06-03 13:35:16 +00001754 without hardcoding any address */
bellard54936002003-05-13 00:25:15 +00001755 error = target_mmap(0, ET_DYN_MAP_SIZE,
ths5fafdf22007-09-16 21:08:06 +00001756 PROT_NONE, MAP_PRIVATE | MAP_ANON,
bellard54936002003-05-13 00:25:15 +00001757 -1, 0);
bellard09bfb052003-04-10 00:03:40 +00001758 if (error == -1) {
1759 perror("mmap");
1760 exit(-1);
1761 }
bellard54936002003-05-13 00:25:15 +00001762 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001763 }
ths3b46e622007-09-17 08:09:54 +00001764
bellard54936002003-05-13 00:25:15 +00001765 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
1766 (elf_ppnt->p_filesz +
1767 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
1768 elf_prot,
1769 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
1770 bprm->fd,
ths5fafdf22007-09-16 21:08:06 +00001771 (elf_ppnt->p_offset -
bellard54936002003-05-13 00:25:15 +00001772 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
bellard09bfb052003-04-10 00:03:40 +00001773 if (error == -1) {
1774 perror("mmap");
1775 exit(-1);
1776 }
bellard31e31b82003-02-18 22:55:36 +00001777
1778#ifdef LOW_ELF_STACK
bellard54936002003-05-13 00:25:15 +00001779 if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
1780 elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
bellard31e31b82003-02-18 22:55:36 +00001781#endif
ths3b46e622007-09-17 08:09:54 +00001782
bellard09bfb052003-04-10 00:03:40 +00001783 if (!load_addr_set) {
1784 load_addr_set = 1;
1785 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1786 if (elf_ex.e_type == ET_DYN) {
1787 load_bias += error -
bellard54936002003-05-13 00:25:15 +00001788 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001789 load_addr += load_bias;
j_mayer84409dd2007-04-06 08:56:50 +00001790 reloc_func_desc = load_bias;
bellard09bfb052003-04-10 00:03:40 +00001791 }
1792 }
1793 k = elf_ppnt->p_vaddr;
ths5fafdf22007-09-16 21:08:06 +00001794 if (k < start_code)
bellard09bfb052003-04-10 00:03:40 +00001795 start_code = k;
j_mayer863cf0b2007-10-07 15:59:45 +00001796 if (start_data < k)
1797 start_data = k;
bellard09bfb052003-04-10 00:03:40 +00001798 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
bellard09bfb052003-04-10 00:03:40 +00001799 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
1800 end_code = k;
ths5fafdf22007-09-16 21:08:06 +00001801 if (end_data < k)
bellard09bfb052003-04-10 00:03:40 +00001802 end_data = k;
1803 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001804 if (k > elf_brk) {
1805 elf_brk = TARGET_PAGE_ALIGN(k);
1806 }
1807
1808 /* If the load segment requests extra zeros (e.g. bss), map it. */
1809 if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
1810 abi_ulong base = load_bias + elf_ppnt->p_vaddr;
1811 zero_bss(base + elf_ppnt->p_filesz,
1812 base + elf_ppnt->p_memsz, elf_prot);
1813 }
bellard31e31b82003-02-18 22:55:36 +00001814 }
1815
bellard09bfb052003-04-10 00:03:40 +00001816 elf_entry += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001817 elf_brk += load_bias;
1818 start_code += load_bias;
1819 end_code += load_bias;
j_mayer863cf0b2007-10-07 15:59:45 +00001820 start_data += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001821 end_data += load_bias;
1822
bellard31e31b82003-02-18 22:55:36 +00001823 if (elf_interpreter) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001824 if (interpreter_type & 1) {
1825 elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
1826 }
1827 else if (interpreter_type & 2) {
1828 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
1829 &interp_load_addr);
1830 }
j_mayer84409dd2007-04-06 08:56:50 +00001831 reloc_func_desc = interp_load_addr;
bellard31e31b82003-02-18 22:55:36 +00001832
Richard Hendersond97ef722010-07-27 10:25:29 -07001833 close(interpreter_fd);
1834 free(elf_interpreter);
bellard31e31b82003-02-18 22:55:36 +00001835
Richard Hendersond97ef722010-07-27 10:25:29 -07001836 if (elf_entry == ~((abi_ulong)0UL)) {
1837 printf("Unable to load interpreter\n");
1838 free(elf_phdata);
1839 exit(-1);
1840 return 0;
1841 }
bellard31e31b82003-02-18 22:55:36 +00001842 }
1843
1844 free(elf_phdata);
1845
aliguori93fcfe32009-01-15 22:34:14 +00001846 if (qemu_log_enabled())
Richard Hendersond97ef722010-07-27 10:25:29 -07001847 load_symbols(&elf_ex, bprm->fd);
bellard689f9362003-04-29 20:40:07 +00001848
bellard31e31b82003-02-18 22:55:36 +00001849 if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
1850 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
1851
1852#ifdef LOW_ELF_STACK
1853 info->start_stack = bprm->p = elf_stack - 4;
1854#endif
pbrook53a59602006-03-25 19:31:22 +00001855 bprm->p = create_elf_tables(bprm->p,
Richard Hendersond97ef722010-07-27 10:25:29 -07001856 bprm->argc,
1857 bprm->envc,
1858 &elf_ex,
1859 load_addr, load_bias,
1860 interp_load_addr,
1861 (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
1862 info);
j_mayer92a343d2007-09-27 01:14:15 +00001863 info->load_addr = reloc_func_desc;
bellard31e31b82003-02-18 22:55:36 +00001864 info->start_brk = info->brk = elf_brk;
1865 info->end_code = end_code;
1866 info->start_code = start_code;
j_mayer863cf0b2007-10-07 15:59:45 +00001867 info->start_data = start_data;
bellard31e31b82003-02-18 22:55:36 +00001868 info->end_data = end_data;
1869 info->start_stack = bprm->p;
1870
bellard31e31b82003-02-18 22:55:36 +00001871#if 0
1872 printf("(start_brk) %x\n" , info->start_brk);
1873 printf("(end_code) %x\n" , info->end_code);
1874 printf("(start_code) %x\n" , info->start_code);
1875 printf("(end_data) %x\n" , info->end_data);
1876 printf("(start_stack) %x\n" , info->start_stack);
1877 printf("(brk) %x\n" , info->brk);
1878#endif
1879
1880 if ( info->personality == PER_SVR4 )
1881 {
Richard Hendersond97ef722010-07-27 10:25:29 -07001882 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
1883 and some applications "depend" upon this behavior.
1884 Since we do not have the power to recompile these, we
1885 emulate the SVr4 behavior. Sigh. */
1886 mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
1887 MAP_FIXED | MAP_PRIVATE, -1, 0);
bellard31e31b82003-02-18 22:55:36 +00001888 }
1889
bellard31e31b82003-02-18 22:55:36 +00001890 info->entry = elf_entry;
1891
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001892#ifdef USE_ELF_CORE_DUMP
1893 bprm->core_dump = &elf_core_dump;
1894#endif
1895
bellard31e31b82003-02-18 22:55:36 +00001896 return 0;
1897}
1898
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001899#ifdef USE_ELF_CORE_DUMP
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001900/*
1901 * Definitions to generate Intel SVR4-like core files.
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001902 * These mostly have the same names as the SVR4 types with "target_elf_"
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001903 * tacked on the front to prevent clashes with linux definitions,
1904 * and the typedef forms have been avoided. This is mostly like
1905 * the SVR4 structure, but more Linuxy, with things that Linux does
1906 * not support and which gdb doesn't really use excluded.
1907 *
1908 * Fields we don't dump (their contents is zero) in linux-user qemu
1909 * are marked with XXX.
1910 *
1911 * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
1912 *
1913 * Porting ELF coredump for target is (quite) simple process. First you
Nathan Froyddd0a3652009-12-11 09:04:45 -08001914 * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001915 * the target resides):
1916 *
1917 * #define USE_ELF_CORE_DUMP
1918 *
1919 * Next you define type of register set used for dumping. ELF specification
1920 * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
1921 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001922 * typedef <target_regtype> target_elf_greg_t;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001923 * #define ELF_NREG <number of registers>
Anthony Liguoric227f092009-10-01 16:12:16 -05001924 * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001925 *
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001926 * Last step is to implement target specific function that copies registers
1927 * from given cpu into just specified register set. Prototype is:
1928 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001929 * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001930 * const CPUState *env);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001931 *
1932 * Parameters:
1933 * regs - copy register values into here (allocated and zeroed by caller)
1934 * env - copy registers from here
1935 *
1936 * Example for ARM target is provided in this file.
1937 */
1938
1939/* An ELF note in memory */
1940struct memelfnote {
1941 const char *name;
1942 size_t namesz;
1943 size_t namesz_rounded;
1944 int type;
1945 size_t datasz;
1946 void *data;
1947 size_t notesz;
1948};
1949
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001950struct target_elf_siginfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001951 int si_signo; /* signal number */
1952 int si_code; /* extra code */
1953 int si_errno; /* errno */
1954};
1955
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001956struct target_elf_prstatus {
1957 struct target_elf_siginfo pr_info; /* Info associated with signal */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001958 short pr_cursig; /* Current signal */
1959 target_ulong pr_sigpend; /* XXX */
1960 target_ulong pr_sighold; /* XXX */
Anthony Liguoric227f092009-10-01 16:12:16 -05001961 target_pid_t pr_pid;
1962 target_pid_t pr_ppid;
1963 target_pid_t pr_pgrp;
1964 target_pid_t pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001965 struct target_timeval pr_utime; /* XXX User time */
1966 struct target_timeval pr_stime; /* XXX System time */
1967 struct target_timeval pr_cutime; /* XXX Cumulative user time */
1968 struct target_timeval pr_cstime; /* XXX Cumulative system time */
Anthony Liguoric227f092009-10-01 16:12:16 -05001969 target_elf_gregset_t pr_reg; /* GP registers */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001970 int pr_fpvalid; /* XXX */
1971};
1972
1973#define ELF_PRARGSZ (80) /* Number of chars for args */
1974
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001975struct target_elf_prpsinfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001976 char pr_state; /* numeric process state */
1977 char pr_sname; /* char for pr_state */
1978 char pr_zomb; /* zombie */
1979 char pr_nice; /* nice val */
1980 target_ulong pr_flag; /* flags */
Anthony Liguoric227f092009-10-01 16:12:16 -05001981 target_uid_t pr_uid;
1982 target_gid_t pr_gid;
1983 target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001984 /* Lots missing */
1985 char pr_fname[16]; /* filename of executable */
1986 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
1987};
1988
1989/* Here is the structure in which status of each thread is captured. */
1990struct elf_thread_status {
Blue Swirl72cf2d42009-09-12 07:36:22 +00001991 QTAILQ_ENTRY(elf_thread_status) ets_link;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001992 struct target_elf_prstatus prstatus; /* NT_PRSTATUS */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001993#if 0
1994 elf_fpregset_t fpu; /* NT_PRFPREG */
1995 struct task_struct *thread;
1996 elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
1997#endif
1998 struct memelfnote notes[1];
1999 int num_notes;
2000};
2001
2002struct elf_note_info {
2003 struct memelfnote *notes;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002004 struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */
2005 struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002006
Blue Swirl72cf2d42009-09-12 07:36:22 +00002007 QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002008#if 0
2009 /*
2010 * Current version of ELF coredump doesn't support
2011 * dumping fp regs etc.
2012 */
2013 elf_fpregset_t *fpu;
2014 elf_fpxregset_t *xfpu;
2015 int thread_status_size;
2016#endif
2017 int notes_size;
2018 int numnote;
2019};
2020
2021struct vm_area_struct {
2022 abi_ulong vma_start; /* start vaddr of memory region */
2023 abi_ulong vma_end; /* end vaddr of memory region */
2024 abi_ulong vma_flags; /* protection etc. flags for the region */
Blue Swirl72cf2d42009-09-12 07:36:22 +00002025 QTAILQ_ENTRY(vm_area_struct) vma_link;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002026};
2027
2028struct mm_struct {
Blue Swirl72cf2d42009-09-12 07:36:22 +00002029 QTAILQ_HEAD(, vm_area_struct) mm_mmap;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002030 int mm_count; /* number of mappings */
2031};
2032
2033static struct mm_struct *vma_init(void);
2034static void vma_delete(struct mm_struct *);
2035static int vma_add_mapping(struct mm_struct *, abi_ulong,
Richard Hendersond97ef722010-07-27 10:25:29 -07002036 abi_ulong, abi_ulong);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002037static int vma_get_mapping_count(const struct mm_struct *);
2038static struct vm_area_struct *vma_first(const struct mm_struct *);
2039static struct vm_area_struct *vma_next(struct vm_area_struct *);
2040static abi_ulong vma_dump_size(const struct vm_area_struct *);
Paul Brookb480d9b2010-03-12 23:23:29 +00002041static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07002042 unsigned long flags);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002043
2044static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
2045static void fill_note(struct memelfnote *, const char *, int,
Richard Hendersond97ef722010-07-27 10:25:29 -07002046 unsigned int, void *);
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002047static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
2048static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002049static void fill_auxv_note(struct memelfnote *, const TaskState *);
2050static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
2051static size_t note_size(const struct memelfnote *);
2052static void free_note_info(struct elf_note_info *);
2053static int fill_note_info(struct elf_note_info *, long, const CPUState *);
2054static void fill_thread_info(struct elf_note_info *, const CPUState *);
2055static int core_dump_filename(const TaskState *, char *, size_t);
2056
2057static int dump_write(int, const void *, size_t);
2058static int write_note(struct memelfnote *, int);
2059static int write_note_info(struct elf_note_info *, int);
2060
2061#ifdef BSWAP_NEEDED
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002062static void bswap_prstatus(struct target_elf_prstatus *);
2063static void bswap_psinfo(struct target_elf_prpsinfo *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002064
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002065static void bswap_prstatus(struct target_elf_prstatus *prstatus)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002066{
2067 prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
2068 prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
2069 prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
2070 prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
2071 prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
2072 prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
2073 prstatus->pr_pid = tswap32(prstatus->pr_pid);
2074 prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
2075 prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
2076 prstatus->pr_sid = tswap32(prstatus->pr_sid);
2077 /* cpu times are not filled, so we skip them */
2078 /* regs should be in correct format already */
2079 prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
2080}
2081
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002082static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002083{
2084 psinfo->pr_flag = tswapl(psinfo->pr_flag);
2085 psinfo->pr_uid = tswap16(psinfo->pr_uid);
2086 psinfo->pr_gid = tswap16(psinfo->pr_gid);
2087 psinfo->pr_pid = tswap32(psinfo->pr_pid);
2088 psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
2089 psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
2090 psinfo->pr_sid = tswap32(psinfo->pr_sid);
2091}
2092#endif /* BSWAP_NEEDED */
2093
2094/*
2095 * Minimal support for linux memory regions. These are needed
2096 * when we are finding out what memory exactly belongs to
2097 * emulated process. No locks needed here, as long as
2098 * thread that received the signal is stopped.
2099 */
2100
2101static struct mm_struct *vma_init(void)
2102{
2103 struct mm_struct *mm;
2104
2105 if ((mm = qemu_malloc(sizeof (*mm))) == NULL)
2106 return (NULL);
2107
2108 mm->mm_count = 0;
Blue Swirl72cf2d42009-09-12 07:36:22 +00002109 QTAILQ_INIT(&mm->mm_mmap);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002110
2111 return (mm);
2112}
2113
2114static void vma_delete(struct mm_struct *mm)
2115{
2116 struct vm_area_struct *vma;
2117
2118 while ((vma = vma_first(mm)) != NULL) {
Blue Swirl72cf2d42009-09-12 07:36:22 +00002119 QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002120 qemu_free(vma);
2121 }
2122 qemu_free(mm);
2123}
2124
2125static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
Richard Hendersond97ef722010-07-27 10:25:29 -07002126 abi_ulong end, abi_ulong flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002127{
2128 struct vm_area_struct *vma;
2129
2130 if ((vma = qemu_mallocz(sizeof (*vma))) == NULL)
2131 return (-1);
2132
2133 vma->vma_start = start;
2134 vma->vma_end = end;
2135 vma->vma_flags = flags;
2136
Blue Swirl72cf2d42009-09-12 07:36:22 +00002137 QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002138 mm->mm_count++;
2139
2140 return (0);
2141}
2142
2143static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2144{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002145 return (QTAILQ_FIRST(&mm->mm_mmap));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002146}
2147
2148static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2149{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002150 return (QTAILQ_NEXT(vma, vma_link));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002151}
2152
2153static int vma_get_mapping_count(const struct mm_struct *mm)
2154{
2155 return (mm->mm_count);
2156}
2157
2158/*
2159 * Calculate file (dump) size of given memory region.
2160 */
2161static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2162{
2163 /* if we cannot even read the first page, skip it */
2164 if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2165 return (0);
2166
2167 /*
2168 * Usually we don't dump executable pages as they contain
2169 * non-writable code that debugger can read directly from
2170 * target library etc. However, thread stacks are marked
2171 * also executable so we read in first page of given region
2172 * and check whether it contains elf header. If there is
2173 * no elf header, we dump it.
2174 */
2175 if (vma->vma_flags & PROT_EXEC) {
2176 char page[TARGET_PAGE_SIZE];
2177
2178 copy_from_user(page, vma->vma_start, sizeof (page));
2179 if ((page[EI_MAG0] == ELFMAG0) &&
2180 (page[EI_MAG1] == ELFMAG1) &&
2181 (page[EI_MAG2] == ELFMAG2) &&
2182 (page[EI_MAG3] == ELFMAG3)) {
2183 /*
2184 * Mappings are possibly from ELF binary. Don't dump
2185 * them.
2186 */
2187 return (0);
2188 }
2189 }
2190
2191 return (vma->vma_end - vma->vma_start);
2192}
2193
Paul Brookb480d9b2010-03-12 23:23:29 +00002194static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07002195 unsigned long flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002196{
2197 struct mm_struct *mm = (struct mm_struct *)priv;
2198
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002199 vma_add_mapping(mm, start, end, flags);
2200 return (0);
2201}
2202
2203static void fill_note(struct memelfnote *note, const char *name, int type,
Richard Hendersond97ef722010-07-27 10:25:29 -07002204 unsigned int sz, void *data)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002205{
2206 unsigned int namesz;
2207
2208 namesz = strlen(name) + 1;
2209 note->name = name;
2210 note->namesz = namesz;
2211 note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2212 note->type = type;
2213 note->datasz = roundup(sz, sizeof (int32_t));;
2214 note->data = data;
2215
2216 /*
2217 * We calculate rounded up note size here as specified by
2218 * ELF document.
2219 */
2220 note->notesz = sizeof (struct elf_note) +
2221 note->namesz_rounded + note->datasz;
2222}
2223
2224static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
Richard Hendersond97ef722010-07-27 10:25:29 -07002225 uint32_t flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002226{
2227 (void) memset(elf, 0, sizeof(*elf));
2228
2229 (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2230 elf->e_ident[EI_CLASS] = ELF_CLASS;
2231 elf->e_ident[EI_DATA] = ELF_DATA;
2232 elf->e_ident[EI_VERSION] = EV_CURRENT;
2233 elf->e_ident[EI_OSABI] = ELF_OSABI;
2234
2235 elf->e_type = ET_CORE;
2236 elf->e_machine = machine;
2237 elf->e_version = EV_CURRENT;
2238 elf->e_phoff = sizeof(struct elfhdr);
2239 elf->e_flags = flags;
2240 elf->e_ehsize = sizeof(struct elfhdr);
2241 elf->e_phentsize = sizeof(struct elf_phdr);
2242 elf->e_phnum = segs;
2243
2244#ifdef BSWAP_NEEDED
2245 bswap_ehdr(elf);
2246#endif
2247}
2248
2249static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2250{
2251 phdr->p_type = PT_NOTE;
2252 phdr->p_offset = offset;
2253 phdr->p_vaddr = 0;
2254 phdr->p_paddr = 0;
2255 phdr->p_filesz = sz;
2256 phdr->p_memsz = 0;
2257 phdr->p_flags = 0;
2258 phdr->p_align = 0;
2259
2260#ifdef BSWAP_NEEDED
2261 bswap_phdr(phdr);
2262#endif
2263}
2264
2265static size_t note_size(const struct memelfnote *note)
2266{
2267 return (note->notesz);
2268}
2269
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002270static void fill_prstatus(struct target_elf_prstatus *prstatus,
Richard Hendersond97ef722010-07-27 10:25:29 -07002271 const TaskState *ts, int signr)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002272{
2273 (void) memset(prstatus, 0, sizeof (*prstatus));
2274 prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2275 prstatus->pr_pid = ts->ts_tid;
2276 prstatus->pr_ppid = getppid();
2277 prstatus->pr_pgrp = getpgrp();
2278 prstatus->pr_sid = getsid(0);
2279
2280#ifdef BSWAP_NEEDED
2281 bswap_prstatus(prstatus);
2282#endif
2283}
2284
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002285static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002286{
2287 char *filename, *base_filename;
2288 unsigned int i, len;
2289
2290 (void) memset(psinfo, 0, sizeof (*psinfo));
2291
2292 len = ts->info->arg_end - ts->info->arg_start;
2293 if (len >= ELF_PRARGSZ)
2294 len = ELF_PRARGSZ - 1;
2295 if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2296 return -EFAULT;
2297 for (i = 0; i < len; i++)
2298 if (psinfo->pr_psargs[i] == 0)
2299 psinfo->pr_psargs[i] = ' ';
2300 psinfo->pr_psargs[len] = 0;
2301
2302 psinfo->pr_pid = getpid();
2303 psinfo->pr_ppid = getppid();
2304 psinfo->pr_pgrp = getpgrp();
2305 psinfo->pr_sid = getsid(0);
2306 psinfo->pr_uid = getuid();
2307 psinfo->pr_gid = getgid();
2308
2309 filename = strdup(ts->bprm->filename);
2310 base_filename = strdup(basename(filename));
2311 (void) strncpy(psinfo->pr_fname, base_filename,
Richard Hendersond97ef722010-07-27 10:25:29 -07002312 sizeof(psinfo->pr_fname));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002313 free(base_filename);
2314 free(filename);
2315
2316#ifdef BSWAP_NEEDED
2317 bswap_psinfo(psinfo);
2318#endif
2319 return (0);
2320}
2321
2322static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2323{
2324 elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2325 elf_addr_t orig_auxv = auxv;
2326 abi_ulong val;
2327 void *ptr;
2328 int i, len;
2329
2330 /*
2331 * Auxiliary vector is stored in target process stack. It contains
2332 * {type, value} pairs that we need to dump into note. This is not
2333 * strictly necessary but we do it here for sake of completeness.
2334 */
2335
2336 /* find out lenght of the vector, AT_NULL is terminator */
2337 i = len = 0;
2338 do {
2339 get_user_ual(val, auxv);
2340 i += 2;
2341 auxv += 2 * sizeof (elf_addr_t);
2342 } while (val != AT_NULL);
2343 len = i * sizeof (elf_addr_t);
2344
2345 /* read in whole auxv vector and copy it to memelfnote */
2346 ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2347 if (ptr != NULL) {
2348 fill_note(note, "CORE", NT_AUXV, len, ptr);
2349 unlock_user(ptr, auxv, len);
2350 }
2351}
2352
2353/*
2354 * Constructs name of coredump file. We have following convention
2355 * for the name:
2356 * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2357 *
2358 * Returns 0 in case of success, -1 otherwise (errno is set).
2359 */
2360static int core_dump_filename(const TaskState *ts, char *buf,
Richard Hendersond97ef722010-07-27 10:25:29 -07002361 size_t bufsize)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002362{
2363 char timestamp[64];
2364 char *filename = NULL;
2365 char *base_filename = NULL;
2366 struct timeval tv;
2367 struct tm tm;
2368
2369 assert(bufsize >= PATH_MAX);
2370
2371 if (gettimeofday(&tv, NULL) < 0) {
2372 (void) fprintf(stderr, "unable to get current timestamp: %s",
Richard Hendersond97ef722010-07-27 10:25:29 -07002373 strerror(errno));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002374 return (-1);
2375 }
2376
2377 filename = strdup(ts->bprm->filename);
2378 base_filename = strdup(basename(filename));
2379 (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
Richard Hendersond97ef722010-07-27 10:25:29 -07002380 localtime_r(&tv.tv_sec, &tm));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002381 (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
Richard Hendersond97ef722010-07-27 10:25:29 -07002382 base_filename, timestamp, (int)getpid());
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002383 free(base_filename);
2384 free(filename);
2385
2386 return (0);
2387}
2388
2389static int dump_write(int fd, const void *ptr, size_t size)
2390{
2391 const char *bufp = (const char *)ptr;
2392 ssize_t bytes_written, bytes_left;
2393 struct rlimit dumpsize;
2394 off_t pos;
2395
2396 bytes_written = 0;
2397 getrlimit(RLIMIT_CORE, &dumpsize);
2398 if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2399 if (errno == ESPIPE) { /* not a seekable stream */
2400 bytes_left = size;
2401 } else {
2402 return pos;
2403 }
2404 } else {
2405 if (dumpsize.rlim_cur <= pos) {
2406 return -1;
2407 } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2408 bytes_left = size;
2409 } else {
2410 size_t limit_left=dumpsize.rlim_cur - pos;
2411 bytes_left = limit_left >= size ? size : limit_left ;
2412 }
2413 }
2414
2415 /*
2416 * In normal conditions, single write(2) should do but
2417 * in case of socket etc. this mechanism is more portable.
2418 */
2419 do {
2420 bytes_written = write(fd, bufp, bytes_left);
2421 if (bytes_written < 0) {
2422 if (errno == EINTR)
2423 continue;
2424 return (-1);
2425 } else if (bytes_written == 0) { /* eof */
2426 return (-1);
2427 }
2428 bufp += bytes_written;
2429 bytes_left -= bytes_written;
2430 } while (bytes_left > 0);
2431
2432 return (0);
2433}
2434
2435static int write_note(struct memelfnote *men, int fd)
2436{
2437 struct elf_note en;
2438
2439 en.n_namesz = men->namesz;
2440 en.n_type = men->type;
2441 en.n_descsz = men->datasz;
2442
2443#ifdef BSWAP_NEEDED
2444 bswap_note(&en);
2445#endif
2446
2447 if (dump_write(fd, &en, sizeof(en)) != 0)
2448 return (-1);
2449 if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2450 return (-1);
2451 if (dump_write(fd, men->data, men->datasz) != 0)
2452 return (-1);
2453
2454 return (0);
2455}
2456
2457static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
2458{
2459 TaskState *ts = (TaskState *)env->opaque;
2460 struct elf_thread_status *ets;
2461
2462 ets = qemu_mallocz(sizeof (*ets));
2463 ets->num_notes = 1; /* only prstatus is dumped */
2464 fill_prstatus(&ets->prstatus, ts, 0);
2465 elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2466 fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
Richard Hendersond97ef722010-07-27 10:25:29 -07002467 &ets->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002468
Blue Swirl72cf2d42009-09-12 07:36:22 +00002469 QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002470
2471 info->notes_size += note_size(&ets->notes[0]);
2472}
2473
2474static int fill_note_info(struct elf_note_info *info,
Richard Hendersond97ef722010-07-27 10:25:29 -07002475 long signr, const CPUState *env)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002476{
2477#define NUMNOTES 3
2478 CPUState *cpu = NULL;
2479 TaskState *ts = (TaskState *)env->opaque;
2480 int i;
2481
2482 (void) memset(info, 0, sizeof (*info));
2483
Blue Swirl72cf2d42009-09-12 07:36:22 +00002484 QTAILQ_INIT(&info->thread_list);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002485
2486 info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote));
2487 if (info->notes == NULL)
2488 return (-ENOMEM);
2489 info->prstatus = qemu_mallocz(sizeof (*info->prstatus));
2490 if (info->prstatus == NULL)
2491 return (-ENOMEM);
2492 info->psinfo = qemu_mallocz(sizeof (*info->psinfo));
2493 if (info->prstatus == NULL)
2494 return (-ENOMEM);
2495
2496 /*
2497 * First fill in status (and registers) of current thread
2498 * including process info & aux vector.
2499 */
2500 fill_prstatus(info->prstatus, ts, signr);
2501 elf_core_copy_regs(&info->prstatus->pr_reg, env);
2502 fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
Richard Hendersond97ef722010-07-27 10:25:29 -07002503 sizeof (*info->prstatus), info->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002504 fill_psinfo(info->psinfo, ts);
2505 fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
Richard Hendersond97ef722010-07-27 10:25:29 -07002506 sizeof (*info->psinfo), info->psinfo);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002507 fill_auxv_note(&info->notes[2], ts);
2508 info->numnote = 3;
2509
2510 info->notes_size = 0;
2511 for (i = 0; i < info->numnote; i++)
2512 info->notes_size += note_size(&info->notes[i]);
2513
2514 /* read and fill status of all threads */
2515 cpu_list_lock();
2516 for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2517 if (cpu == thread_env)
2518 continue;
2519 fill_thread_info(info, cpu);
2520 }
2521 cpu_list_unlock();
2522
2523 return (0);
2524}
2525
2526static void free_note_info(struct elf_note_info *info)
2527{
2528 struct elf_thread_status *ets;
2529
Blue Swirl72cf2d42009-09-12 07:36:22 +00002530 while (!QTAILQ_EMPTY(&info->thread_list)) {
2531 ets = QTAILQ_FIRST(&info->thread_list);
2532 QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002533 qemu_free(ets);
2534 }
2535
2536 qemu_free(info->prstatus);
2537 qemu_free(info->psinfo);
2538 qemu_free(info->notes);
2539}
2540
2541static int write_note_info(struct elf_note_info *info, int fd)
2542{
2543 struct elf_thread_status *ets;
2544 int i, error = 0;
2545
2546 /* write prstatus, psinfo and auxv for current thread */
2547 for (i = 0; i < info->numnote; i++)
2548 if ((error = write_note(&info->notes[i], fd)) != 0)
2549 return (error);
2550
2551 /* write prstatus for each thread */
2552 for (ets = info->thread_list.tqh_first; ets != NULL;
Richard Hendersond97ef722010-07-27 10:25:29 -07002553 ets = ets->ets_link.tqe_next) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002554 if ((error = write_note(&ets->notes[0], fd)) != 0)
2555 return (error);
2556 }
2557
2558 return (0);
2559}
2560
2561/*
2562 * Write out ELF coredump.
2563 *
2564 * See documentation of ELF object file format in:
2565 * http://www.caldera.com/developers/devspecs/gabi41.pdf
2566 *
2567 * Coredump format in linux is following:
2568 *
2569 * 0 +----------------------+ \
2570 * | ELF header | ET_CORE |
2571 * +----------------------+ |
2572 * | ELF program headers | |--- headers
2573 * | - NOTE section | |
2574 * | - PT_LOAD sections | |
2575 * +----------------------+ /
2576 * | NOTEs: |
2577 * | - NT_PRSTATUS |
2578 * | - NT_PRSINFO |
2579 * | - NT_AUXV |
2580 * +----------------------+ <-- aligned to target page
2581 * | Process memory dump |
2582 * : :
2583 * . .
2584 * : :
2585 * | |
2586 * +----------------------+
2587 *
2588 * NT_PRSTATUS -> struct elf_prstatus (per thread)
2589 * NT_PRSINFO -> struct elf_prpsinfo
2590 * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2591 *
2592 * Format follows System V format as close as possible. Current
2593 * version limitations are as follows:
2594 * - no floating point registers are dumped
2595 *
2596 * Function returns 0 in case of success, negative errno otherwise.
2597 *
2598 * TODO: make this work also during runtime: it should be
2599 * possible to force coredump from running process and then
2600 * continue processing. For example qemu could set up SIGUSR2
2601 * handler (provided that target process haven't registered
2602 * handler for that) that does the dump when signal is received.
2603 */
2604static int elf_core_dump(int signr, const CPUState *env)
2605{
2606 const TaskState *ts = (const TaskState *)env->opaque;
2607 struct vm_area_struct *vma = NULL;
2608 char corefile[PATH_MAX];
2609 struct elf_note_info info;
2610 struct elfhdr elf;
2611 struct elf_phdr phdr;
2612 struct rlimit dumpsize;
2613 struct mm_struct *mm = NULL;
2614 off_t offset = 0, data_offset = 0;
2615 int segs = 0;
2616 int fd = -1;
2617
2618 errno = 0;
2619 getrlimit(RLIMIT_CORE, &dumpsize);
2620 if (dumpsize.rlim_cur == 0)
Richard Hendersond97ef722010-07-27 10:25:29 -07002621 return 0;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002622
2623 if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2624 return (-errno);
2625
2626 if ((fd = open(corefile, O_WRONLY | O_CREAT,
Richard Hendersond97ef722010-07-27 10:25:29 -07002627 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002628 return (-errno);
2629
2630 /*
2631 * Walk through target process memory mappings and
2632 * set up structure containing this information. After
2633 * this point vma_xxx functions can be used.
2634 */
2635 if ((mm = vma_init()) == NULL)
2636 goto out;
2637
2638 walk_memory_regions(mm, vma_walker);
2639 segs = vma_get_mapping_count(mm);
2640
2641 /*
2642 * Construct valid coredump ELF header. We also
2643 * add one more segment for notes.
2644 */
2645 fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2646 if (dump_write(fd, &elf, sizeof (elf)) != 0)
2647 goto out;
2648
2649 /* fill in in-memory version of notes */
2650 if (fill_note_info(&info, signr, env) < 0)
2651 goto out;
2652
2653 offset += sizeof (elf); /* elf header */
2654 offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */
2655
2656 /* write out notes program header */
2657 fill_elf_note_phdr(&phdr, info.notes_size, offset);
2658
2659 offset += info.notes_size;
2660 if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2661 goto out;
2662
2663 /*
2664 * ELF specification wants data to start at page boundary so
2665 * we align it here.
2666 */
2667 offset = roundup(offset, ELF_EXEC_PAGESIZE);
2668
2669 /*
2670 * Write program headers for memory regions mapped in
2671 * the target process.
2672 */
2673 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2674 (void) memset(&phdr, 0, sizeof (phdr));
2675
2676 phdr.p_type = PT_LOAD;
2677 phdr.p_offset = offset;
2678 phdr.p_vaddr = vma->vma_start;
2679 phdr.p_paddr = 0;
2680 phdr.p_filesz = vma_dump_size(vma);
2681 offset += phdr.p_filesz;
2682 phdr.p_memsz = vma->vma_end - vma->vma_start;
2683 phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2684 if (vma->vma_flags & PROT_WRITE)
2685 phdr.p_flags |= PF_W;
2686 if (vma->vma_flags & PROT_EXEC)
2687 phdr.p_flags |= PF_X;
2688 phdr.p_align = ELF_EXEC_PAGESIZE;
2689
2690 dump_write(fd, &phdr, sizeof (phdr));
2691 }
2692
2693 /*
2694 * Next we write notes just after program headers. No
2695 * alignment needed here.
2696 */
2697 if (write_note_info(&info, fd) < 0)
2698 goto out;
2699
2700 /* align data to page boundary */
2701 data_offset = lseek(fd, 0, SEEK_CUR);
2702 data_offset = TARGET_PAGE_ALIGN(data_offset);
2703 if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2704 goto out;
2705
2706 /*
2707 * Finally we can dump process memory into corefile as well.
2708 */
2709 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2710 abi_ulong addr;
2711 abi_ulong end;
2712
2713 end = vma->vma_start + vma_dump_size(vma);
2714
2715 for (addr = vma->vma_start; addr < end;
Richard Hendersond97ef722010-07-27 10:25:29 -07002716 addr += TARGET_PAGE_SIZE) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002717 char page[TARGET_PAGE_SIZE];
2718 int error;
2719
2720 /*
2721 * Read in page from target process memory and
2722 * write it to coredump file.
2723 */
2724 error = copy_from_user(page, addr, sizeof (page));
2725 if (error != 0) {
Aurelien Jarno49995e12009-12-19 20:28:23 +01002726 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
Richard Hendersond97ef722010-07-27 10:25:29 -07002727 addr);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002728 errno = -error;
2729 goto out;
2730 }
2731 if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2732 goto out;
2733 }
2734 }
2735
Richard Hendersond97ef722010-07-27 10:25:29 -07002736 out:
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002737 free_note_info(&info);
2738 if (mm != NULL)
2739 vma_delete(mm);
2740 (void) close(fd);
2741
2742 if (errno != 0)
2743 return (-errno);
2744 return (0);
2745}
2746
2747#endif /* USE_ELF_CORE_DUMP */
2748
bellard31e31b82003-02-18 22:55:36 +00002749static int load_aout_interp(void * exptr, int interp_fd)
2750{
2751 printf("a.out interpreter not yet supported\n");
2752 return(0);
2753}
2754
pbrooke5fe0c52006-06-11 13:32:59 +00002755void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2756{
2757 init_thread(regs, infop);
2758}