blob: 6b57a91a3eace32759b4b84a514b7b076ca293c3 [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/* This is the Linux kernel elf-loading code, ported into user space */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002#include <sys/time.h>
3#include <sys/param.h>
bellard31e31b82003-02-18 22:55:36 +00004
5#include <stdio.h>
6#include <sys/types.h>
7#include <fcntl.h>
bellard31e31b82003-02-18 22:55:36 +00008#include <errno.h>
9#include <unistd.h>
10#include <sys/mman.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030011#include <sys/resource.h>
bellard31e31b82003-02-18 22:55:36 +000012#include <stdlib.h>
13#include <string.h>
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030014#include <time.h>
bellard31e31b82003-02-18 22:55:36 +000015
bellard3ef693a2003-03-23 20:17:16 +000016#include "qemu.h"
bellard689f9362003-04-29 20:40:07 +000017#include "disas.h"
bellard31e31b82003-02-18 22:55:36 +000018
malce58ffeb2009-01-14 18:39:49 +000019#ifdef _ARCH_PPC64
malca6cc84f2008-08-20 22:39:28 +000020#undef ARCH_DLINFO
21#undef ELF_PLATFORM
22#undef ELF_HWCAP
23#undef ELF_CLASS
24#undef ELF_DATA
25#undef ELF_ARCH
26#endif
27
Mika Westerbergedf8e2a2009-04-07 09:57:11 +030028#define ELF_OSABI ELFOSABI_SYSV
29
blueswir1cb33da52007-10-09 16:34:29 +000030/* from personality.h */
31
32/*
33 * Flags for bug emulation.
34 *
35 * These occupy the top three bytes.
36 */
37enum {
Richard Hendersond97ef722010-07-27 10:25:29 -070038 ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
39 FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to
40 descriptors (signal handling) */
41 MMAP_PAGE_ZERO = 0x0100000,
42 ADDR_COMPAT_LAYOUT = 0x0200000,
43 READ_IMPLIES_EXEC = 0x0400000,
44 ADDR_LIMIT_32BIT = 0x0800000,
45 SHORT_INODE = 0x1000000,
46 WHOLE_SECONDS = 0x2000000,
47 STICKY_TIMEOUTS = 0x4000000,
48 ADDR_LIMIT_3GB = 0x8000000,
blueswir1cb33da52007-10-09 16:34:29 +000049};
50
51/*
52 * Personality types.
53 *
54 * These go in the low byte. Avoid using the top bit, it will
55 * conflict with error returns.
56 */
57enum {
Richard Hendersond97ef722010-07-27 10:25:29 -070058 PER_LINUX = 0x0000,
59 PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
60 PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
61 PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
62 PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
63 PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
64 PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
65 PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
66 PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
67 PER_BSD = 0x0006,
68 PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
69 PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
70 PER_LINUX32 = 0x0008,
71 PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
72 PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
73 PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
74 PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
75 PER_RISCOS = 0x000c,
76 PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
77 PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
78 PER_OSF4 = 0x000f, /* OSF/1 v4 */
79 PER_HPUX = 0x0010,
80 PER_MASK = 0x00ff,
blueswir1cb33da52007-10-09 16:34:29 +000081};
82
83/*
84 * Return the base personality without flags.
85 */
Richard Hendersond97ef722010-07-27 10:25:29 -070086#define personality(pers) (pers & PER_MASK)
blueswir1cb33da52007-10-09 16:34:29 +000087
bellard83fb7ad2004-07-05 21:25:26 +000088/* this flag is uneffective under linux too, should be deleted */
89#ifndef MAP_DENYWRITE
90#define MAP_DENYWRITE 0
91#endif
92
93/* should probably go in elf.h */
94#ifndef ELIBBAD
95#define ELIBBAD 80
96#endif
97
Richard Henderson28490232010-07-27 10:25:31 -070098#ifdef TARGET_WORDS_BIGENDIAN
99#define ELF_DATA ELFDATA2MSB
100#else
101#define ELF_DATA ELFDATA2LSB
102#endif
103
Richard Hendersond97ef722010-07-27 10:25:29 -0700104typedef target_ulong target_elf_greg_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800105#ifdef USE_UID16
Richard Hendersond97ef722010-07-27 10:25:29 -0700106typedef uint16_t target_uid_t;
107typedef uint16_t target_gid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800108#else
Richard Hendersond97ef722010-07-27 10:25:29 -0700109typedef uint32_t target_uid_t;
110typedef uint32_t target_gid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800111#endif
Richard Hendersond97ef722010-07-27 10:25:29 -0700112typedef int32_t target_pid_t;
Nathan Froyd21e807f2009-12-11 09:04:46 -0800113
bellard30ac07d2003-04-07 21:33:03 +0000114#ifdef TARGET_I386
115
bellard15338fd2005-11-26 11:41:16 +0000116#define ELF_PLATFORM get_elf_platform()
117
118static const char *get_elf_platform(void)
119{
120 static char elf_platform[] = "i386";
pbrookd5975362008-06-07 20:50:51 +0000121 int family = (thread_env->cpuid_version >> 8) & 0xff;
bellard15338fd2005-11-26 11:41:16 +0000122 if (family > 6)
123 family = 6;
124 if (family >= 3)
125 elf_platform[1] = '0' + family;
126 return elf_platform;
127}
128
129#define ELF_HWCAP get_elf_hwcap()
130
131static uint32_t get_elf_hwcap(void)
132{
Richard Hendersond97ef722010-07-27 10:25:29 -0700133 return thread_env->cpuid_features;
bellard15338fd2005-11-26 11:41:16 +0000134}
135
j_mayer84409dd2007-04-06 08:56:50 +0000136#ifdef TARGET_X86_64
137#define ELF_START_MMAP 0x2aaaaab000ULL
138#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
139
140#define ELF_CLASS ELFCLASS64
j_mayer84409dd2007-04-06 08:56:50 +0000141#define ELF_ARCH EM_X86_64
142
143static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
144{
145 regs->rax = 0;
146 regs->rsp = infop->start_stack;
147 regs->rip = infop->entry;
148}
149
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300150#define ELF_NREG 27
Anthony Liguoric227f092009-10-01 16:12:16 -0500151typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300152
153/*
154 * Note that ELF_NREG should be 29 as there should be place for
155 * TRAPNO and ERR "registers" as well but linux doesn't dump
156 * those.
157 *
158 * See linux kernel: arch/x86/include/asm/elf.h
159 */
Anthony Liguoric227f092009-10-01 16:12:16 -0500160static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300161{
162 (*regs)[0] = env->regs[15];
163 (*regs)[1] = env->regs[14];
164 (*regs)[2] = env->regs[13];
165 (*regs)[3] = env->regs[12];
166 (*regs)[4] = env->regs[R_EBP];
167 (*regs)[5] = env->regs[R_EBX];
168 (*regs)[6] = env->regs[11];
169 (*regs)[7] = env->regs[10];
170 (*regs)[8] = env->regs[9];
171 (*regs)[9] = env->regs[8];
172 (*regs)[10] = env->regs[R_EAX];
173 (*regs)[11] = env->regs[R_ECX];
174 (*regs)[12] = env->regs[R_EDX];
175 (*regs)[13] = env->regs[R_ESI];
176 (*regs)[14] = env->regs[R_EDI];
177 (*regs)[15] = env->regs[R_EAX]; /* XXX */
178 (*regs)[16] = env->eip;
179 (*regs)[17] = env->segs[R_CS].selector & 0xffff;
180 (*regs)[18] = env->eflags;
181 (*regs)[19] = env->regs[R_ESP];
182 (*regs)[20] = env->segs[R_SS].selector & 0xffff;
183 (*regs)[21] = env->segs[R_FS].selector & 0xffff;
184 (*regs)[22] = env->segs[R_GS].selector & 0xffff;
185 (*regs)[23] = env->segs[R_DS].selector & 0xffff;
186 (*regs)[24] = env->segs[R_ES].selector & 0xffff;
187 (*regs)[25] = env->segs[R_FS].selector & 0xffff;
188 (*regs)[26] = env->segs[R_GS].selector & 0xffff;
189}
190
j_mayer84409dd2007-04-06 08:56:50 +0000191#else
192
bellard30ac07d2003-04-07 21:33:03 +0000193#define ELF_START_MMAP 0x80000000
194
bellard30ac07d2003-04-07 21:33:03 +0000195/*
196 * This is used to ensure we don't load something for the wrong architecture.
197 */
198#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
199
200/*
201 * These are used to set parameters in the core dumps.
202 */
Richard Hendersond97ef722010-07-27 10:25:29 -0700203#define ELF_CLASS ELFCLASS32
Richard Hendersond97ef722010-07-27 10:25:29 -0700204#define ELF_ARCH EM_386
bellard30ac07d2003-04-07 21:33:03 +0000205
Richard Hendersond97ef722010-07-27 10:25:29 -0700206static inline void init_thread(struct target_pt_regs *regs,
207 struct image_info *infop)
bellardb346ff42003-06-15 20:05:50 +0000208{
209 regs->esp = infop->start_stack;
210 regs->eip = infop->entry;
pbrooke5fe0c52006-06-11 13:32:59 +0000211
212 /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
213 starts %edx contains a pointer to a function which might be
214 registered using `atexit'. This provides a mean for the
215 dynamic linker to call DT_FINI functions for shared libraries
216 that have been loaded before the code runs.
217
218 A value of 0 tells we have no such handler. */
219 regs->edx = 0;
bellardb346ff42003-06-15 20:05:50 +0000220}
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300221
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300222#define ELF_NREG 17
Anthony Liguoric227f092009-10-01 16:12:16 -0500223typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300224
225/*
226 * Note that ELF_NREG should be 19 as there should be place for
227 * TRAPNO and ERR "registers" as well but linux doesn't dump
228 * those.
229 *
230 * See linux kernel: arch/x86/include/asm/elf.h
231 */
Anthony Liguoric227f092009-10-01 16:12:16 -0500232static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300233{
234 (*regs)[0] = env->regs[R_EBX];
235 (*regs)[1] = env->regs[R_ECX];
236 (*regs)[2] = env->regs[R_EDX];
237 (*regs)[3] = env->regs[R_ESI];
238 (*regs)[4] = env->regs[R_EDI];
239 (*regs)[5] = env->regs[R_EBP];
240 (*regs)[6] = env->regs[R_EAX];
241 (*regs)[7] = env->segs[R_DS].selector & 0xffff;
242 (*regs)[8] = env->segs[R_ES].selector & 0xffff;
243 (*regs)[9] = env->segs[R_FS].selector & 0xffff;
244 (*regs)[10] = env->segs[R_GS].selector & 0xffff;
245 (*regs)[11] = env->regs[R_EAX]; /* XXX */
246 (*regs)[12] = env->eip;
247 (*regs)[13] = env->segs[R_CS].selector & 0xffff;
248 (*regs)[14] = env->eflags;
249 (*regs)[15] = env->regs[R_ESP];
250 (*regs)[16] = env->segs[R_SS].selector & 0xffff;
251}
j_mayer84409dd2007-04-06 08:56:50 +0000252#endif
bellardb346ff42003-06-15 20:05:50 +0000253
Mika Westerberg9edc5d72009-04-07 09:57:59 +0300254#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700255#define ELF_EXEC_PAGESIZE 4096
bellardb346ff42003-06-15 20:05:50 +0000256
257#endif
258
259#ifdef TARGET_ARM
260
261#define ELF_START_MMAP 0x80000000
262
263#define elf_check_arch(x) ( (x) == EM_ARM )
264
Richard Hendersond97ef722010-07-27 10:25:29 -0700265#define ELF_CLASS ELFCLASS32
Richard Hendersond97ef722010-07-27 10:25:29 -0700266#define ELF_ARCH EM_ARM
bellardb346ff42003-06-15 20:05:50 +0000267
Richard Hendersond97ef722010-07-27 10:25:29 -0700268static inline void init_thread(struct target_pt_regs *regs,
269 struct image_info *infop)
bellardb346ff42003-06-15 20:05:50 +0000270{
blueswir1992f48a2007-10-14 16:27:31 +0000271 abi_long stack = infop->start_stack;
bellardb346ff42003-06-15 20:05:50 +0000272 memset(regs, 0, sizeof(*regs));
273 regs->ARM_cpsr = 0x10;
pbrook0240ded2006-02-04 19:30:51 +0000274 if (infop->entry & 1)
Richard Hendersond97ef722010-07-27 10:25:29 -0700275 regs->ARM_cpsr |= CPSR_T;
pbrook0240ded2006-02-04 19:30:51 +0000276 regs->ARM_pc = infop->entry & 0xfffffffe;
bellardb346ff42003-06-15 20:05:50 +0000277 regs->ARM_sp = infop->start_stack;
bellard2f619692007-11-16 10:46:05 +0000278 /* FIXME - what to for failure of get_user()? */
279 get_user_ual(regs->ARM_r2, stack + 8); /* envp */
280 get_user_ual(regs->ARM_r1, stack + 4); /* envp */
bellarda1516e92003-07-09 17:13:37 +0000281 /* XXX: it seems that r0 is zeroed after ! */
pbrooke5fe0c52006-06-11 13:32:59 +0000282 regs->ARM_r0 = 0;
283 /* For uClinux PIC binaries. */
j_mayer863cf0b2007-10-07 15:59:45 +0000284 /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
pbrooke5fe0c52006-06-11 13:32:59 +0000285 regs->ARM_r10 = infop->start_data;
bellardb346ff42003-06-15 20:05:50 +0000286}
287
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300288#define ELF_NREG 18
Anthony Liguoric227f092009-10-01 16:12:16 -0500289typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300290
Anthony Liguoric227f092009-10-01 16:12:16 -0500291static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300292{
Nathan Froydd049e622009-12-11 09:04:47 -0800293 (*regs)[0] = tswapl(env->regs[0]);
294 (*regs)[1] = tswapl(env->regs[1]);
295 (*regs)[2] = tswapl(env->regs[2]);
296 (*regs)[3] = tswapl(env->regs[3]);
297 (*regs)[4] = tswapl(env->regs[4]);
298 (*regs)[5] = tswapl(env->regs[5]);
299 (*regs)[6] = tswapl(env->regs[6]);
300 (*regs)[7] = tswapl(env->regs[7]);
301 (*regs)[8] = tswapl(env->regs[8]);
302 (*regs)[9] = tswapl(env->regs[9]);
303 (*regs)[10] = tswapl(env->regs[10]);
304 (*regs)[11] = tswapl(env->regs[11]);
305 (*regs)[12] = tswapl(env->regs[12]);
306 (*regs)[13] = tswapl(env->regs[13]);
307 (*regs)[14] = tswapl(env->regs[14]);
308 (*regs)[15] = tswapl(env->regs[15]);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300309
Nathan Froydd049e622009-12-11 09:04:47 -0800310 (*regs)[16] = tswapl(cpsr_read((CPUState *)env));
311 (*regs)[17] = tswapl(env->regs[0]); /* XXX */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300312}
313
bellard30ac07d2003-04-07 21:33:03 +0000314#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700315#define ELF_EXEC_PAGESIZE 4096
bellard30ac07d2003-04-07 21:33:03 +0000316
bellardafce2922005-10-30 20:58:30 +0000317enum
318{
Richard Hendersond97ef722010-07-27 10:25:29 -0700319 ARM_HWCAP_ARM_SWP = 1 << 0,
320 ARM_HWCAP_ARM_HALF = 1 << 1,
321 ARM_HWCAP_ARM_THUMB = 1 << 2,
322 ARM_HWCAP_ARM_26BIT = 1 << 3,
323 ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
324 ARM_HWCAP_ARM_FPA = 1 << 5,
325 ARM_HWCAP_ARM_VFP = 1 << 6,
326 ARM_HWCAP_ARM_EDSP = 1 << 7,
327 ARM_HWCAP_ARM_JAVA = 1 << 8,
328 ARM_HWCAP_ARM_IWMMXT = 1 << 9,
329 ARM_HWCAP_ARM_THUMBEE = 1 << 10,
330 ARM_HWCAP_ARM_NEON = 1 << 11,
331 ARM_HWCAP_ARM_VFPv3 = 1 << 12,
332 ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
bellardafce2922005-10-30 20:58:30 +0000333};
334
Richard Hendersond97ef722010-07-27 10:25:29 -0700335#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \
336 | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \
337 | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
338 | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
bellardafce2922005-10-30 20:58:30 +0000339
bellard30ac07d2003-04-07 21:33:03 +0000340#endif
341
bellard853d6f72003-09-30 20:58:32 +0000342#ifdef TARGET_SPARC
bellarda315a142005-01-30 22:59:18 +0000343#ifdef TARGET_SPARC64
bellard853d6f72003-09-30 20:58:32 +0000344
345#define ELF_START_MMAP 0x80000000
346
blueswir1992f48a2007-10-14 16:27:31 +0000347#ifndef TARGET_ABI32
blueswir1cb33da52007-10-09 16:34:29 +0000348#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
blueswir1992f48a2007-10-14 16:27:31 +0000349#else
350#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
351#endif
bellard853d6f72003-09-30 20:58:32 +0000352
bellarda315a142005-01-30 22:59:18 +0000353#define ELF_CLASS ELFCLASS64
bellard5ef54112006-07-18 21:14:09 +0000354#define ELF_ARCH EM_SPARCV9
355
Richard Hendersond97ef722010-07-27 10:25:29 -0700356#define STACK_BIAS 2047
bellarda315a142005-01-30 22:59:18 +0000357
Richard Hendersond97ef722010-07-27 10:25:29 -0700358static inline void init_thread(struct target_pt_regs *regs,
359 struct image_info *infop)
bellarda315a142005-01-30 22:59:18 +0000360{
blueswir1992f48a2007-10-14 16:27:31 +0000361#ifndef TARGET_ABI32
bellarda315a142005-01-30 22:59:18 +0000362 regs->tstate = 0;
blueswir1992f48a2007-10-14 16:27:31 +0000363#endif
bellarda315a142005-01-30 22:59:18 +0000364 regs->pc = infop->entry;
365 regs->npc = regs->pc + 4;
366 regs->y = 0;
blueswir1992f48a2007-10-14 16:27:31 +0000367#ifdef TARGET_ABI32
368 regs->u_regs[14] = infop->start_stack - 16 * 4;
369#else
blueswir1cb33da52007-10-09 16:34:29 +0000370 if (personality(infop->personality) == PER_LINUX32)
371 regs->u_regs[14] = infop->start_stack - 16 * 4;
372 else
373 regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
blueswir1992f48a2007-10-14 16:27:31 +0000374#endif
bellarda315a142005-01-30 22:59:18 +0000375}
376
377#else
378#define ELF_START_MMAP 0x80000000
379
380#define elf_check_arch(x) ( (x) == EM_SPARC )
381
bellard853d6f72003-09-30 20:58:32 +0000382#define ELF_CLASS ELFCLASS32
bellard853d6f72003-09-30 20:58:32 +0000383#define ELF_ARCH EM_SPARC
384
Richard Hendersond97ef722010-07-27 10:25:29 -0700385static inline void init_thread(struct target_pt_regs *regs,
386 struct image_info *infop)
bellard853d6f72003-09-30 20:58:32 +0000387{
bellardf5155282004-01-04 15:46:50 +0000388 regs->psr = 0;
389 regs->pc = infop->entry;
390 regs->npc = regs->pc + 4;
391 regs->y = 0;
392 regs->u_regs[14] = infop->start_stack - 16 * 4;
bellard853d6f72003-09-30 20:58:32 +0000393}
394
395#endif
bellarda315a142005-01-30 22:59:18 +0000396#endif
bellard853d6f72003-09-30 20:58:32 +0000397
bellard67867302003-11-23 17:05:30 +0000398#ifdef TARGET_PPC
399
400#define ELF_START_MMAP 0x80000000
401
j_mayere85e7c62007-10-18 19:59:49 +0000402#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
j_mayer84409dd2007-04-06 08:56:50 +0000403
404#define elf_check_arch(x) ( (x) == EM_PPC64 )
405
Richard Hendersond97ef722010-07-27 10:25:29 -0700406#define ELF_CLASS ELFCLASS64
j_mayer84409dd2007-04-06 08:56:50 +0000407
408#else
409
bellard67867302003-11-23 17:05:30 +0000410#define elf_check_arch(x) ( (x) == EM_PPC )
411
Richard Hendersond97ef722010-07-27 10:25:29 -0700412#define ELF_CLASS ELFCLASS32
j_mayer84409dd2007-04-06 08:56:50 +0000413
414#endif
415
Richard Hendersond97ef722010-07-27 10:25:29 -0700416#define ELF_ARCH EM_PPC
bellard67867302003-11-23 17:05:30 +0000417
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700418/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
419 See arch/powerpc/include/asm/cputable.h. */
420enum {
malc3efa9a62009-07-18 13:10:12 +0400421 QEMU_PPC_FEATURE_32 = 0x80000000,
422 QEMU_PPC_FEATURE_64 = 0x40000000,
423 QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
424 QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
425 QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
426 QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
427 QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
428 QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
429 QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
430 QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
431 QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
432 QEMU_PPC_FEATURE_NO_TB = 0x00100000,
433 QEMU_PPC_FEATURE_POWER4 = 0x00080000,
434 QEMU_PPC_FEATURE_POWER5 = 0x00040000,
435 QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
436 QEMU_PPC_FEATURE_CELL = 0x00010000,
437 QEMU_PPC_FEATURE_BOOKE = 0x00008000,
438 QEMU_PPC_FEATURE_SMT = 0x00004000,
439 QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
440 QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
441 QEMU_PPC_FEATURE_PA6T = 0x00000800,
442 QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
443 QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
444 QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
445 QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
446 QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700447
malc3efa9a62009-07-18 13:10:12 +0400448 QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
449 QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700450};
451
452#define ELF_HWCAP get_elf_hwcap()
453
454static uint32_t get_elf_hwcap(void)
455{
456 CPUState *e = thread_env;
457 uint32_t features = 0;
458
459 /* We don't have to be terribly complete here; the high points are
460 Altivec/FP/SPE support. Anything else is just a bonus. */
Richard Hendersond97ef722010-07-27 10:25:29 -0700461#define GET_FEATURE(flag, feature) \
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700462 do {if (e->insns_flags & flag) features |= feature; } while(0)
malc3efa9a62009-07-18 13:10:12 +0400463 GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
464 GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
465 GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
466 GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
467 GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
468 GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
469 GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
470 GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
Nathan Froyddf84e4f2009-05-12 12:26:59 -0700471#undef GET_FEATURE
472
473 return features;
474}
475
bellardf5155282004-01-04 15:46:50 +0000476/*
bellardf5155282004-01-04 15:46:50 +0000477 * The requirements here are:
478 * - keep the final alignment of sp (sp & 0xf)
479 * - make sure the 32-bit value at the first 16 byte aligned position of
480 * AUXV is greater than 16 for glibc compatibility.
481 * AT_IGNOREPPC is used for that.
482 * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
483 * even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
484 */
bellard0bccf032005-08-21 10:12:28 +0000485#define DLINFO_ARCH_ITEMS 5
Richard Hendersond97ef722010-07-27 10:25:29 -0700486#define ARCH_DLINFO \
487 do { \
488 NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \
489 NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \
490 NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \
491 /* \
492 * Now handle glibc compatibility. \
493 */ \
494 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
495 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \
496 } while (0)
bellardf5155282004-01-04 15:46:50 +0000497
bellard67867302003-11-23 17:05:30 +0000498static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
499{
bellard67867302003-11-23 17:05:30 +0000500 _regs->gpr[1] = infop->start_stack;
j_mayere85e7c62007-10-18 19:59:49 +0000501#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
Rob Landley7983f432010-03-28 16:51:43 +0200502 _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_addr;
503 infop->entry = ldq_raw(infop->entry) + infop->load_addr;
j_mayer84409dd2007-04-06 08:56:50 +0000504#endif
bellard67867302003-11-23 17:05:30 +0000505 _regs->nip = infop->entry;
506}
507
Nathan Froyde2f3e742009-12-11 09:04:48 -0800508/* See linux kernel: arch/powerpc/include/asm/elf.h. */
509#define ELF_NREG 48
510typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
511
512static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
513{
514 int i;
515 target_ulong ccr = 0;
516
517 for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
518 (*regs)[i] = tswapl(env->gpr[i]);
519 }
520
521 (*regs)[32] = tswapl(env->nip);
522 (*regs)[33] = tswapl(env->msr);
523 (*regs)[35] = tswapl(env->ctr);
524 (*regs)[36] = tswapl(env->lr);
525 (*regs)[37] = tswapl(env->xer);
526
527 for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
528 ccr |= env->crf[i] << (32 - ((i + 1) * 4));
529 }
530 (*regs)[38] = tswapl(ccr);
531}
532
533#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700534#define ELF_EXEC_PAGESIZE 4096
bellard67867302003-11-23 17:05:30 +0000535
536#endif
537
bellard048f6b42005-11-26 18:47:20 +0000538#ifdef TARGET_MIPS
539
540#define ELF_START_MMAP 0x80000000
541
542#define elf_check_arch(x) ( (x) == EM_MIPS )
543
ths388bb212007-05-13 13:58:00 +0000544#ifdef TARGET_MIPS64
545#define ELF_CLASS ELFCLASS64
546#else
bellard048f6b42005-11-26 18:47:20 +0000547#define ELF_CLASS ELFCLASS32
ths388bb212007-05-13 13:58:00 +0000548#endif
bellard048f6b42005-11-26 18:47:20 +0000549#define ELF_ARCH EM_MIPS
550
Richard Hendersond97ef722010-07-27 10:25:29 -0700551static inline void init_thread(struct target_pt_regs *regs,
552 struct image_info *infop)
bellard048f6b42005-11-26 18:47:20 +0000553{
ths623a9302007-10-28 19:45:05 +0000554 regs->cp0_status = 2 << CP0St_KSU;
bellard048f6b42005-11-26 18:47:20 +0000555 regs->cp0_epc = infop->entry;
556 regs->regs[29] = infop->start_stack;
557}
558
Nathan Froyd51e52602009-12-11 09:04:49 -0800559/* See linux kernel: arch/mips/include/asm/elf.h. */
560#define ELF_NREG 45
561typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
562
563/* See linux kernel: arch/mips/include/asm/reg.h. */
564enum {
565#ifdef TARGET_MIPS64
566 TARGET_EF_R0 = 0,
567#else
568 TARGET_EF_R0 = 6,
569#endif
570 TARGET_EF_R26 = TARGET_EF_R0 + 26,
571 TARGET_EF_R27 = TARGET_EF_R0 + 27,
572 TARGET_EF_LO = TARGET_EF_R0 + 32,
573 TARGET_EF_HI = TARGET_EF_R0 + 33,
574 TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
575 TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
576 TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
577 TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
578};
579
580/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
581static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
582{
583 int i;
584
585 for (i = 0; i < TARGET_EF_R0; i++) {
586 (*regs)[i] = 0;
587 }
588 (*regs)[TARGET_EF_R0] = 0;
589
590 for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
591 (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]);
592 }
593
594 (*regs)[TARGET_EF_R26] = 0;
595 (*regs)[TARGET_EF_R27] = 0;
596 (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]);
597 (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]);
598 (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC);
599 (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr);
600 (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status);
601 (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause);
602}
603
604#define USE_ELF_CORE_DUMP
ths388bb212007-05-13 13:58:00 +0000605#define ELF_EXEC_PAGESIZE 4096
606
bellard048f6b42005-11-26 18:47:20 +0000607#endif /* TARGET_MIPS */
608
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200609#ifdef TARGET_MICROBLAZE
610
611#define ELF_START_MMAP 0x80000000
612
Edgar E. Iglesias0d5d4692010-05-19 15:24:17 +0200613#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200614
615#define ELF_CLASS ELFCLASS32
Edgar E. Iglesias0d5d4692010-05-19 15:24:17 +0200616#define ELF_ARCH EM_MICROBLAZE
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200617
Richard Hendersond97ef722010-07-27 10:25:29 -0700618static inline void init_thread(struct target_pt_regs *regs,
619 struct image_info *infop)
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200620{
621 regs->pc = infop->entry;
622 regs->r1 = infop->start_stack;
623
624}
625
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200626#define ELF_EXEC_PAGESIZE 4096
627
Edgar E. Iglesiase4cbd442010-05-19 15:09:28 +0200628#define USE_ELF_CORE_DUMP
629#define ELF_NREG 38
630typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
631
632/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
633static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
634{
635 int i, pos = 0;
636
637 for (i = 0; i < 32; i++) {
638 (*regs)[pos++] = tswapl(env->regs[i]);
639 }
640
641 for (i = 0; i < 6; i++) {
642 (*regs)[pos++] = tswapl(env->sregs[i]);
643 }
644}
645
Edgar E. Iglesiasb779e292009-05-20 21:31:33 +0200646#endif /* TARGET_MICROBLAZE */
647
bellardfdf9b3e2006-04-27 21:07:38 +0000648#ifdef TARGET_SH4
649
650#define ELF_START_MMAP 0x80000000
651
652#define elf_check_arch(x) ( (x) == EM_SH )
653
654#define ELF_CLASS ELFCLASS32
bellardfdf9b3e2006-04-27 21:07:38 +0000655#define ELF_ARCH EM_SH
656
Richard Hendersond97ef722010-07-27 10:25:29 -0700657static inline void init_thread(struct target_pt_regs *regs,
658 struct image_info *infop)
bellardfdf9b3e2006-04-27 21:07:38 +0000659{
Richard Hendersond97ef722010-07-27 10:25:29 -0700660 /* Check other registers XXXXX */
661 regs->pc = infop->entry;
662 regs->regs[15] = infop->start_stack;
bellardfdf9b3e2006-04-27 21:07:38 +0000663}
664
Nathan Froyd7631c972009-12-11 09:04:51 -0800665/* See linux kernel: arch/sh/include/asm/elf.h. */
666#define ELF_NREG 23
667typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
668
669/* See linux kernel: arch/sh/include/asm/ptrace.h. */
670enum {
671 TARGET_REG_PC = 16,
672 TARGET_REG_PR = 17,
673 TARGET_REG_SR = 18,
674 TARGET_REG_GBR = 19,
675 TARGET_REG_MACH = 20,
676 TARGET_REG_MACL = 21,
677 TARGET_REG_SYSCALL = 22
678};
679
Richard Hendersond97ef722010-07-27 10:25:29 -0700680static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
681 const CPUState *env)
Nathan Froyd7631c972009-12-11 09:04:51 -0800682{
683 int i;
684
685 for (i = 0; i < 16; i++) {
686 (*regs[i]) = tswapl(env->gregs[i]);
687 }
688
689 (*regs)[TARGET_REG_PC] = tswapl(env->pc);
690 (*regs)[TARGET_REG_PR] = tswapl(env->pr);
691 (*regs)[TARGET_REG_SR] = tswapl(env->sr);
692 (*regs)[TARGET_REG_GBR] = tswapl(env->gbr);
693 (*regs)[TARGET_REG_MACH] = tswapl(env->mach);
694 (*regs)[TARGET_REG_MACL] = tswapl(env->macl);
695 (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
696}
697
698#define USE_ELF_CORE_DUMP
bellardfdf9b3e2006-04-27 21:07:38 +0000699#define ELF_EXEC_PAGESIZE 4096
700
701#endif
702
ths48733d12007-10-08 13:36:46 +0000703#ifdef TARGET_CRIS
704
705#define ELF_START_MMAP 0x80000000
706
707#define elf_check_arch(x) ( (x) == EM_CRIS )
708
709#define ELF_CLASS ELFCLASS32
ths48733d12007-10-08 13:36:46 +0000710#define ELF_ARCH EM_CRIS
711
Richard Hendersond97ef722010-07-27 10:25:29 -0700712static inline void init_thread(struct target_pt_regs *regs,
713 struct image_info *infop)
ths48733d12007-10-08 13:36:46 +0000714{
Richard Hendersond97ef722010-07-27 10:25:29 -0700715 regs->erp = infop->entry;
ths48733d12007-10-08 13:36:46 +0000716}
717
ths48733d12007-10-08 13:36:46 +0000718#define ELF_EXEC_PAGESIZE 8192
719
720#endif
721
pbrooke6e59062006-10-22 00:18:54 +0000722#ifdef TARGET_M68K
723
724#define ELF_START_MMAP 0x80000000
725
726#define elf_check_arch(x) ( (x) == EM_68K )
727
Richard Hendersond97ef722010-07-27 10:25:29 -0700728#define ELF_CLASS ELFCLASS32
Richard Hendersond97ef722010-07-27 10:25:29 -0700729#define ELF_ARCH EM_68K
pbrooke6e59062006-10-22 00:18:54 +0000730
731/* ??? Does this need to do anything?
Richard Hendersond97ef722010-07-27 10:25:29 -0700732 #define ELF_PLAT_INIT(_r) */
pbrooke6e59062006-10-22 00:18:54 +0000733
Richard Hendersond97ef722010-07-27 10:25:29 -0700734static inline void init_thread(struct target_pt_regs *regs,
735 struct image_info *infop)
pbrooke6e59062006-10-22 00:18:54 +0000736{
737 regs->usp = infop->start_stack;
738 regs->sr = 0;
739 regs->pc = infop->entry;
740}
741
Nathan Froyd7a93cc52009-12-11 09:04:50 -0800742/* See linux kernel: arch/m68k/include/asm/elf.h. */
743#define ELF_NREG 20
744typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
745
746static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
747{
748 (*regs)[0] = tswapl(env->dregs[1]);
749 (*regs)[1] = tswapl(env->dregs[2]);
750 (*regs)[2] = tswapl(env->dregs[3]);
751 (*regs)[3] = tswapl(env->dregs[4]);
752 (*regs)[4] = tswapl(env->dregs[5]);
753 (*regs)[5] = tswapl(env->dregs[6]);
754 (*regs)[6] = tswapl(env->dregs[7]);
755 (*regs)[7] = tswapl(env->aregs[0]);
756 (*regs)[8] = tswapl(env->aregs[1]);
757 (*regs)[9] = tswapl(env->aregs[2]);
758 (*regs)[10] = tswapl(env->aregs[3]);
759 (*regs)[11] = tswapl(env->aregs[4]);
760 (*regs)[12] = tswapl(env->aregs[5]);
761 (*regs)[13] = tswapl(env->aregs[6]);
762 (*regs)[14] = tswapl(env->dregs[0]);
763 (*regs)[15] = tswapl(env->aregs[7]);
764 (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */
765 (*regs)[17] = tswapl(env->sr);
766 (*regs)[18] = tswapl(env->pc);
767 (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */
768}
769
770#define USE_ELF_CORE_DUMP
Richard Hendersond97ef722010-07-27 10:25:29 -0700771#define ELF_EXEC_PAGESIZE 8192
pbrooke6e59062006-10-22 00:18:54 +0000772
773#endif
774
j_mayer7a3148a2007-04-05 07:13:51 +0000775#ifdef TARGET_ALPHA
776
777#define ELF_START_MMAP (0x30000000000ULL)
778
779#define elf_check_arch(x) ( (x) == ELF_ARCH )
780
781#define ELF_CLASS ELFCLASS64
j_mayer7a3148a2007-04-05 07:13:51 +0000782#define ELF_ARCH EM_ALPHA
783
Richard Hendersond97ef722010-07-27 10:25:29 -0700784static inline void init_thread(struct target_pt_regs *regs,
785 struct image_info *infop)
j_mayer7a3148a2007-04-05 07:13:51 +0000786{
787 regs->pc = infop->entry;
788 regs->ps = 8;
789 regs->usp = infop->start_stack;
j_mayer7a3148a2007-04-05 07:13:51 +0000790}
791
j_mayer7a3148a2007-04-05 07:13:51 +0000792#define ELF_EXEC_PAGESIZE 8192
793
794#endif /* TARGET_ALPHA */
795
bellard15338fd2005-11-26 11:41:16 +0000796#ifndef ELF_PLATFORM
797#define ELF_PLATFORM (NULL)
798#endif
799
800#ifndef ELF_HWCAP
801#define ELF_HWCAP 0
802#endif
803
blueswir1992f48a2007-10-14 16:27:31 +0000804#ifdef TARGET_ABI32
blueswir1cb33da52007-10-09 16:34:29 +0000805#undef ELF_CLASS
blueswir1992f48a2007-10-14 16:27:31 +0000806#define ELF_CLASS ELFCLASS32
blueswir1cb33da52007-10-09 16:34:29 +0000807#undef bswaptls
808#define bswaptls(ptr) bswap32s(ptr)
809#endif
810
bellard31e31b82003-02-18 22:55:36 +0000811#include "elf.h"
bellard09bfb052003-04-10 00:03:40 +0000812
bellard09bfb052003-04-10 00:03:40 +0000813struct exec
814{
Richard Hendersond97ef722010-07-27 10:25:29 -0700815 unsigned int a_info; /* Use macros N_MAGIC, etc for access */
816 unsigned int a_text; /* length of text, in bytes */
817 unsigned int a_data; /* length of data, in bytes */
818 unsigned int a_bss; /* length of uninitialized data area, in bytes */
819 unsigned int a_syms; /* length of symbol table data in file, in bytes */
820 unsigned int a_entry; /* start address */
821 unsigned int a_trsize; /* length of relocation info for text, in bytes */
822 unsigned int a_drsize; /* length of relocation info for data, in bytes */
bellard09bfb052003-04-10 00:03:40 +0000823};
824
825
826#define N_MAGIC(exec) ((exec).a_info & 0xffff)
827#define OMAGIC 0407
828#define NMAGIC 0410
829#define ZMAGIC 0413
830#define QMAGIC 0314
831
bellard09bfb052003-04-10 00:03:40 +0000832/* max code+data+bss+brk space allocated to ET_DYN executables */
833#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
834
bellard31e31b82003-02-18 22:55:36 +0000835/* Necessary parameters */
bellard54936002003-05-13 00:25:15 +0000836#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
837#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
838#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
bellard31e31b82003-02-18 22:55:36 +0000839
840#define INTERPRETER_NONE 0
841#define INTERPRETER_AOUT 1
842#define INTERPRETER_ELF 2
843
bellard15338fd2005-11-26 11:41:16 +0000844#define DLINFO_ITEMS 12
bellard31e31b82003-02-18 22:55:36 +0000845
bellard09bfb052003-04-10 00:03:40 +0000846static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
847{
Richard Hendersond97ef722010-07-27 10:25:29 -0700848 memcpy(to, from, n);
bellard09bfb052003-04-10 00:03:40 +0000849}
850
bellard31e31b82003-02-18 22:55:36 +0000851static int load_aout_interp(void * exptr, int interp_fd);
852
853#ifdef BSWAP_NEEDED
bellard92a31b12005-02-10 22:00:52 +0000854static void bswap_ehdr(struct elfhdr *ehdr)
bellard31e31b82003-02-18 22:55:36 +0000855{
Richard Hendersond97ef722010-07-27 10:25:29 -0700856 bswap16s(&ehdr->e_type); /* Object file type */
857 bswap16s(&ehdr->e_machine); /* Architecture */
858 bswap32s(&ehdr->e_version); /* Object file version */
859 bswaptls(&ehdr->e_entry); /* Entry point virtual address */
860 bswaptls(&ehdr->e_phoff); /* Program header table file offset */
861 bswaptls(&ehdr->e_shoff); /* Section header table file offset */
862 bswap32s(&ehdr->e_flags); /* Processor-specific flags */
863 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
864 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
865 bswap16s(&ehdr->e_phnum); /* Program header table entry count */
866 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
867 bswap16s(&ehdr->e_shnum); /* Section header table entry count */
868 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
bellard31e31b82003-02-18 22:55:36 +0000869}
870
Richard Henderson991f8f02010-07-27 10:25:32 -0700871static void bswap_phdr(struct elf_phdr *phdr, int phnum)
bellard31e31b82003-02-18 22:55:36 +0000872{
Richard Henderson991f8f02010-07-27 10:25:32 -0700873 int i;
874 for (i = 0; i < phnum; ++i, ++phdr) {
875 bswap32s(&phdr->p_type); /* Segment type */
876 bswap32s(&phdr->p_flags); /* Segment flags */
877 bswaptls(&phdr->p_offset); /* Segment file offset */
878 bswaptls(&phdr->p_vaddr); /* Segment virtual address */
879 bswaptls(&phdr->p_paddr); /* Segment physical address */
880 bswaptls(&phdr->p_filesz); /* Segment size in file */
881 bswaptls(&phdr->p_memsz); /* Segment size in memory */
882 bswaptls(&phdr->p_align); /* Segment alignment */
883 }
bellard31e31b82003-02-18 22:55:36 +0000884}
bellard689f9362003-04-29 20:40:07 +0000885
Richard Henderson991f8f02010-07-27 10:25:32 -0700886static void bswap_shdr(struct elf_shdr *shdr, int shnum)
bellard689f9362003-04-29 20:40:07 +0000887{
Richard Henderson991f8f02010-07-27 10:25:32 -0700888 int i;
889 for (i = 0; i < shnum; ++i, ++shdr) {
890 bswap32s(&shdr->sh_name);
891 bswap32s(&shdr->sh_type);
892 bswaptls(&shdr->sh_flags);
893 bswaptls(&shdr->sh_addr);
894 bswaptls(&shdr->sh_offset);
895 bswaptls(&shdr->sh_size);
896 bswap32s(&shdr->sh_link);
897 bswap32s(&shdr->sh_info);
898 bswaptls(&shdr->sh_addralign);
899 bswaptls(&shdr->sh_entsize);
900 }
bellard689f9362003-04-29 20:40:07 +0000901}
902
j_mayer7a3148a2007-04-05 07:13:51 +0000903static void bswap_sym(struct elf_sym *sym)
bellard689f9362003-04-29 20:40:07 +0000904{
905 bswap32s(&sym->st_name);
j_mayer7a3148a2007-04-05 07:13:51 +0000906 bswaptls(&sym->st_value);
907 bswaptls(&sym->st_size);
bellard689f9362003-04-29 20:40:07 +0000908 bswap16s(&sym->st_shndx);
909}
Richard Henderson991f8f02010-07-27 10:25:32 -0700910#else
911static inline void bswap_ehdr(struct elfhdr *ehdr) { }
912static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
913static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
914static inline void bswap_sym(struct elf_sym *sym) { }
bellard31e31b82003-02-18 22:55:36 +0000915#endif
916
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300917#ifdef USE_ELF_CORE_DUMP
918static int elf_core_dump(int, const CPUState *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300919#endif /* USE_ELF_CORE_DUMP */
Richard Henderson682674b2010-07-27 10:25:33 -0700920static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +0300921
bellard31e31b82003-02-18 22:55:36 +0000922/*
pbrooke5fe0c52006-06-11 13:32:59 +0000923 * 'copy_elf_strings()' copies argument/envelope strings from user
bellard31e31b82003-02-18 22:55:36 +0000924 * memory to free pages in kernel mem. These are in a format ready
925 * to be put directly into the top of new user memory.
926 *
927 */
blueswir1992f48a2007-10-14 16:27:31 +0000928static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
929 abi_ulong p)
bellard31e31b82003-02-18 22:55:36 +0000930{
931 char *tmp, *tmp1, *pag = NULL;
932 int len, offset = 0;
933
934 if (!p) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700935 return 0; /* bullet-proofing */
bellard31e31b82003-02-18 22:55:36 +0000936 }
937 while (argc-- > 0) {
bellardedf779f2004-02-22 13:40:13 +0000938 tmp = argv[argc];
939 if (!tmp) {
Richard Hendersond97ef722010-07-27 10:25:29 -0700940 fprintf(stderr, "VFS: argc is wrong");
941 exit(-1);
942 }
bellardedf779f2004-02-22 13:40:13 +0000943 tmp1 = tmp;
Richard Hendersond97ef722010-07-27 10:25:29 -0700944 while (*tmp++);
945 len = tmp - tmp1;
946 if (p < len) { /* this shouldn't happen - 128kB */
947 return 0;
948 }
949 while (len) {
950 --p; --tmp; --len;
951 if (--offset < 0) {
952 offset = p % TARGET_PAGE_SIZE;
pbrook53a59602006-03-25 19:31:22 +0000953 pag = (char *)page[p/TARGET_PAGE_SIZE];
bellard44a91ca2004-01-18 22:05:44 +0000954 if (!pag) {
pbrook53a59602006-03-25 19:31:22 +0000955 pag = (char *)malloc(TARGET_PAGE_SIZE);
j_mayer4118a972007-09-27 04:10:43 +0000956 memset(pag, 0, TARGET_PAGE_SIZE);
pbrook53a59602006-03-25 19:31:22 +0000957 page[p/TARGET_PAGE_SIZE] = pag;
bellard44a91ca2004-01-18 22:05:44 +0000958 if (!pag)
959 return 0;
Richard Hendersond97ef722010-07-27 10:25:29 -0700960 }
961 }
962 if (len == 0 || offset == 0) {
963 *(pag + offset) = *tmp;
964 }
965 else {
966 int bytes_to_copy = (len > offset) ? offset : len;
967 tmp -= bytes_to_copy;
968 p -= bytes_to_copy;
969 offset -= bytes_to_copy;
970 len -= bytes_to_copy;
971 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
972 }
973 }
bellard31e31b82003-02-18 22:55:36 +0000974 }
975 return p;
976}
977
blueswir1992f48a2007-10-14 16:27:31 +0000978static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
979 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +0000980{
blueswir1992f48a2007-10-14 16:27:31 +0000981 abi_ulong stack_base, size, error;
bellard31e31b82003-02-18 22:55:36 +0000982 int i;
bellard31e31b82003-02-18 22:55:36 +0000983
984 /* Create enough stack to hold everything. If we don't use
985 * it for args, we'll use it for something else...
986 */
Richard Henderson703e0e82010-03-19 14:21:13 -0700987 size = guest_stack_size;
bellard54936002003-05-13 00:25:15 +0000988 if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
989 size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
ths5fafdf22007-09-16 21:08:06 +0000990 error = target_mmap(0,
bellard83fb7ad2004-07-05 21:25:26 +0000991 size + qemu_host_page_size,
bellard54936002003-05-13 00:25:15 +0000992 PROT_READ | PROT_WRITE,
993 MAP_PRIVATE | MAP_ANONYMOUS,
994 -1, 0);
bellard09bfb052003-04-10 00:03:40 +0000995 if (error == -1) {
996 perror("stk mmap");
997 exit(-1);
bellard31e31b82003-02-18 22:55:36 +0000998 }
bellard09bfb052003-04-10 00:03:40 +0000999 /* we reserve one extra page at the top of the stack as guard */
bellard83fb7ad2004-07-05 21:25:26 +00001000 target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
bellard09bfb052003-04-10 00:03:40 +00001001
Paul Brook97374d32010-06-16 13:03:51 +01001002 info->stack_limit = error;
bellard54936002003-05-13 00:25:15 +00001003 stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
bellard09bfb052003-04-10 00:03:40 +00001004 p += stack_base;
1005
bellard31e31b82003-02-18 22:55:36 +00001006 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001007 if (bprm->page[i]) {
1008 info->rss++;
bellard579a97f2007-11-11 14:26:47 +00001009 /* FIXME - check return value of memcpy_to_target() for failure */
Richard Hendersond97ef722010-07-27 10:25:29 -07001010 memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
1011 free(bprm->page[i]);
1012 }
pbrook53a59602006-03-25 19:31:22 +00001013 stack_base += TARGET_PAGE_SIZE;
bellard31e31b82003-02-18 22:55:36 +00001014 }
1015 return p;
1016}
1017
Richard Hendersoncf129f32010-07-27 10:25:27 -07001018/* Map and zero the bss. We need to explicitly zero any fractional pages
1019 after the data section (i.e. bss). */
1020static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
bellard31e31b82003-02-18 22:55:36 +00001021{
Richard Hendersoncf129f32010-07-27 10:25:27 -07001022 uintptr_t host_start, host_map_start, host_end;
bellard31e31b82003-02-18 22:55:36 +00001023
Richard Hendersoncf129f32010-07-27 10:25:27 -07001024 last_bss = TARGET_PAGE_ALIGN(last_bss);
bellard31e31b82003-02-18 22:55:36 +00001025
Richard Hendersoncf129f32010-07-27 10:25:27 -07001026 /* ??? There is confusion between qemu_real_host_page_size and
1027 qemu_host_page_size here and elsewhere in target_mmap, which
1028 may lead to the end of the data section mapping from the file
1029 not being mapped. At least there was an explicit test and
1030 comment for that here, suggesting that "the file size must
1031 be known". The comment probably pre-dates the introduction
1032 of the fstat system call in target_mmap which does in fact
1033 find out the size. What isn't clear is if the workaround
1034 here is still actually needed. For now, continue with it,
1035 but merge it with the "normal" mmap that would allocate the bss. */
bellard31e31b82003-02-18 22:55:36 +00001036
Richard Hendersoncf129f32010-07-27 10:25:27 -07001037 host_start = (uintptr_t) g2h(elf_bss);
1038 host_end = (uintptr_t) g2h(last_bss);
1039 host_map_start = (host_start + qemu_real_host_page_size - 1);
1040 host_map_start &= -qemu_real_host_page_size;
ths768a4a32006-12-14 13:32:11 +00001041
Richard Hendersoncf129f32010-07-27 10:25:27 -07001042 if (host_map_start < host_end) {
1043 void *p = mmap((void *)host_map_start, host_end - host_map_start,
1044 prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1045 if (p == MAP_FAILED) {
1046 perror("cannot mmap brk");
1047 exit(-1);
bellard853d6f72003-09-30 20:58:32 +00001048 }
1049
Richard Hendersoncf129f32010-07-27 10:25:27 -07001050 /* Since we didn't use target_mmap, make sure to record
1051 the validity of the pages with qemu. */
1052 page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
1053 }
bellard31e31b82003-02-18 22:55:36 +00001054
Richard Hendersoncf129f32010-07-27 10:25:27 -07001055 if (host_start < host_map_start) {
1056 memset((void *)host_start, 0, host_map_start - host_start);
1057 }
1058}
bellardedf779f2004-02-22 13:40:13 +00001059
blueswir1992f48a2007-10-14 16:27:31 +00001060static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
1061 struct elfhdr * exec,
1062 abi_ulong load_addr,
1063 abi_ulong load_bias,
1064 abi_ulong interp_load_addr, int ibcs,
1065 struct image_info *info)
pbrook53a59602006-03-25 19:31:22 +00001066{
Richard Hendersond97ef722010-07-27 10:25:29 -07001067 abi_ulong sp;
1068 int size;
1069 abi_ulong u_platform;
1070 const char *k_platform;
1071 const int n = sizeof(elf_addr_t);
pbrook53a59602006-03-25 19:31:22 +00001072
Richard Hendersond97ef722010-07-27 10:25:29 -07001073 sp = p;
1074 u_platform = 0;
1075 k_platform = ELF_PLATFORM;
1076 if (k_platform) {
1077 size_t len = strlen(k_platform) + 1;
1078 sp -= (len + n - 1) & ~(n - 1);
1079 u_platform = sp;
1080 /* FIXME - check return value of memcpy_to_target() for failure */
1081 memcpy_to_target(sp, k_platform, len);
1082 }
1083 /*
1084 * Force 16 byte _final_ alignment here for generality.
1085 */
1086 sp = sp &~ (abi_ulong)15;
1087 size = (DLINFO_ITEMS + 1) * 2;
1088 if (k_platform)
1089 size += 2;
bellardf5155282004-01-04 15:46:50 +00001090#ifdef DLINFO_ARCH_ITEMS
Richard Hendersond97ef722010-07-27 10:25:29 -07001091 size += DLINFO_ARCH_ITEMS * 2;
bellardf5155282004-01-04 15:46:50 +00001092#endif
Richard Hendersond97ef722010-07-27 10:25:29 -07001093 size += envc + argc + 2;
1094 size += (!ibcs ? 3 : 1); /* argc itself */
1095 size *= n;
1096 if (size & 15)
1097 sp -= 16 - (size & 15);
ths3b46e622007-09-17 08:09:54 +00001098
Richard Hendersond97ef722010-07-27 10:25:29 -07001099 /* This is correct because Linux defines
1100 * elf_addr_t as Elf32_Off / Elf64_Off
1101 */
1102#define NEW_AUX_ENT(id, val) do { \
1103 sp -= n; put_user_ual(val, sp); \
1104 sp -= n; put_user_ual(id, sp); \
1105 } while(0)
bellard2f619692007-11-16 10:46:05 +00001106
Richard Hendersond97ef722010-07-27 10:25:29 -07001107 NEW_AUX_ENT (AT_NULL, 0);
bellardf5155282004-01-04 15:46:50 +00001108
Richard Hendersond97ef722010-07-27 10:25:29 -07001109 /* There must be exactly DLINFO_ITEMS entries here. */
1110 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
1111 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1112 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1113 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
1114 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
1115 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
1116 NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
1117 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1118 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1119 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1120 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1121 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1122 NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
1123 if (k_platform)
1124 NEW_AUX_ENT(AT_PLATFORM, u_platform);
bellardf5155282004-01-04 15:46:50 +00001125#ifdef ARCH_DLINFO
Richard Hendersond97ef722010-07-27 10:25:29 -07001126 /*
1127 * ARCH_DLINFO must come last so platform specific code can enforce
1128 * special alignment requirements on the AUXV if necessary (eg. PPC).
1129 */
1130 ARCH_DLINFO;
bellardf5155282004-01-04 15:46:50 +00001131#endif
1132#undef NEW_AUX_ENT
1133
Richard Hendersond97ef722010-07-27 10:25:29 -07001134 info->saved_auxv = sp;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001135
Richard Hendersond97ef722010-07-27 10:25:29 -07001136 sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
1137 return sp;
bellard31e31b82003-02-18 22:55:36 +00001138}
1139
1140
blueswir1992f48a2007-10-14 16:27:31 +00001141static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
1142 int interpreter_fd,
Richard Henderson9955ffa2010-07-27 10:25:30 -07001143 abi_ulong *interp_load_addr,
1144 char bprm_buf[BPRM_BUF_SIZE])
bellard31e31b82003-02-18 22:55:36 +00001145{
Richard Hendersond97ef722010-07-27 10:25:29 -07001146 struct elf_phdr *elf_phdata = NULL;
Richard Henderson682674b2010-07-27 10:25:33 -07001147 abi_ulong load_addr, load_bias, loaddr, hiaddr;
Richard Hendersond97ef722010-07-27 10:25:29 -07001148 int retval;
1149 abi_ulong error;
1150 int i;
ths5fafdf22007-09-16 21:08:06 +00001151
Richard Hendersond97ef722010-07-27 10:25:29 -07001152 bswap_ehdr(interp_elf_ex);
Richard Hendersond97ef722010-07-27 10:25:29 -07001153 /* First of all, some simple consistency checks */
1154 if ((interp_elf_ex->e_type != ET_EXEC &&
1155 interp_elf_ex->e_type != ET_DYN) ||
1156 !elf_check_arch(interp_elf_ex->e_machine)) {
1157 return ~((abi_ulong)0UL);
1158 }
ths5fafdf22007-09-16 21:08:06 +00001159
Richard Hendersond97ef722010-07-27 10:25:29 -07001160 /* Now read in all of the header information */
ths5fafdf22007-09-16 21:08:06 +00001161
Richard Hendersond97ef722010-07-27 10:25:29 -07001162 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
1163 return ~(abi_ulong)0UL;
ths5fafdf22007-09-16 21:08:06 +00001164
Richard Hendersond97ef722010-07-27 10:25:29 -07001165 elf_phdata = (struct elf_phdr *)
1166 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
bellard31e31b82003-02-18 22:55:36 +00001167
Richard Hendersond97ef722010-07-27 10:25:29 -07001168 if (!elf_phdata)
1169 return ~((abi_ulong)0UL);
ths5fafdf22007-09-16 21:08:06 +00001170
Richard Hendersond97ef722010-07-27 10:25:29 -07001171 /*
1172 * If the size of this structure has changed, then punt, since
1173 * we will be doing the wrong thing.
1174 */
1175 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
1176 free(elf_phdata);
1177 return ~((abi_ulong)0UL);
1178 }
bellard31e31b82003-02-18 22:55:36 +00001179
Richard Henderson9955ffa2010-07-27 10:25:30 -07001180 i = interp_elf_ex->e_phnum * sizeof(struct elf_phdr);
1181 if (interp_elf_ex->e_phoff + i <= BPRM_BUF_SIZE) {
1182 memcpy(elf_phdata, bprm_buf + interp_elf_ex->e_phoff, i);
1183 } else {
1184 retval = pread(interpreter_fd, elf_phdata, i, interp_elf_ex->e_phoff);
1185 if (retval != i) {
1186 perror("load_elf_interp");
1187 exit(-1);
1188 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001189 }
Richard Henderson991f8f02010-07-27 10:25:32 -07001190 bswap_phdr(elf_phdata, interp_elf_ex->e_phnum);
bellard09bfb052003-04-10 00:03:40 +00001191
Richard Henderson682674b2010-07-27 10:25:33 -07001192 /* Find the maximum size of the image and allocate an appropriate
1193 amount of memory to handle that. */
1194 loaddr = -1, hiaddr = 0;
1195 for (i = 0; i < interp_elf_ex->e_phnum; ++i) {
1196 if (elf_phdata[i].p_type == PT_LOAD) {
1197 abi_ulong a = elf_phdata[i].p_vaddr;
1198 if (a < loaddr) {
1199 loaddr = a;
1200 }
1201 a += elf_phdata[i].p_memsz;
1202 if (a > hiaddr) {
1203 hiaddr = a;
1204 }
1205 }
1206 }
1207
1208 load_addr = loaddr;
Richard Hendersond97ef722010-07-27 10:25:29 -07001209 if (interp_elf_ex->e_type == ET_DYN) {
Richard Henderson682674b2010-07-27 10:25:33 -07001210 /* The image indicates that it can be loaded anywhere. Find a
1211 location that can hold the memory space required. If the
1212 image is pre-linked, LOADDR will be non-zero. Since we do
1213 not supply MAP_FIXED here we'll use that address if and
1214 only if it remains available. */
1215 load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
1216 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
1217 -1, 0);
1218 if (load_addr == -1) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001219 perror("mmap");
1220 exit(-1);
1221 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001222 }
Richard Henderson682674b2010-07-27 10:25:33 -07001223 load_bias = load_addr - loaddr;
Richard Hendersond97ef722010-07-27 10:25:29 -07001224
Richard Henderson682674b2010-07-27 10:25:33 -07001225 for (i = 0; i < interp_elf_ex->e_phnum; i++) {
1226 struct elf_phdr *eppnt = elf_phdata + i;
Richard Hendersond97ef722010-07-27 10:25:29 -07001227 if (eppnt->p_type == PT_LOAD) {
Richard Henderson682674b2010-07-27 10:25:33 -07001228 abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
Richard Hendersond97ef722010-07-27 10:25:29 -07001229 int elf_prot = 0;
Richard Hendersond97ef722010-07-27 10:25:29 -07001230
1231 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
1232 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1233 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
bellard09bfb052003-04-10 00:03:40 +00001234
Richard Henderson682674b2010-07-27 10:25:33 -07001235 vaddr = load_bias + eppnt->p_vaddr;
1236 vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
1237 vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
1238
1239 error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
1240 elf_prot, MAP_PRIVATE | MAP_FIXED,
1241 interpreter_fd, eppnt->p_offset - vaddr_po);
Richard Hendersond97ef722010-07-27 10:25:29 -07001242 if (error == -1) {
1243 /* Real error */
1244 close(interpreter_fd);
1245 free(elf_phdata);
1246 return ~((abi_ulong)0UL);
1247 }
bellard31e31b82003-02-18 22:55:36 +00001248
Richard Henderson682674b2010-07-27 10:25:33 -07001249 vaddr_ef = vaddr + eppnt->p_filesz;
1250 vaddr_em = vaddr + eppnt->p_memsz;
bellard31e31b82003-02-18 22:55:36 +00001251
Richard Hendersoncf129f32010-07-27 10:25:27 -07001252 /* If the load segment requests extra zeros (e.g. bss), map it. */
Richard Henderson682674b2010-07-27 10:25:33 -07001253 if (vaddr_ef < vaddr_em) {
1254 zero_bss(vaddr_ef, vaddr_em, elf_prot);
Richard Hendersoncf129f32010-07-27 10:25:27 -07001255 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001256 }
Richard Henderson682674b2010-07-27 10:25:33 -07001257 }
ths5fafdf22007-09-16 21:08:06 +00001258
Richard Henderson682674b2010-07-27 10:25:33 -07001259 if (qemu_log_enabled()) {
1260 load_symbols(interp_elf_ex, interpreter_fd, load_bias);
1261 }
bellard31e31b82003-02-18 22:55:36 +00001262
Richard Hendersond97ef722010-07-27 10:25:29 -07001263 close(interpreter_fd);
1264 free(elf_phdata);
bellard31e31b82003-02-18 22:55:36 +00001265
Richard Hendersond97ef722010-07-27 10:25:29 -07001266 *interp_load_addr = load_addr;
Richard Henderson682674b2010-07-27 10:25:33 -07001267 return ((abi_ulong) interp_elf_ex->e_entry) + load_bias;
bellard31e31b82003-02-18 22:55:36 +00001268}
1269
pbrook49918a72008-10-22 15:11:31 +00001270static int symfind(const void *s0, const void *s1)
1271{
1272 struct elf_sym *key = (struct elf_sym *)s0;
1273 struct elf_sym *sym = (struct elf_sym *)s1;
1274 int result = 0;
1275 if (key->st_value < sym->st_value) {
1276 result = -1;
Laurent Desnoguesec822002009-07-30 19:23:49 +02001277 } else if (key->st_value >= sym->st_value + sym->st_size) {
pbrook49918a72008-10-22 15:11:31 +00001278 result = 1;
1279 }
1280 return result;
1281}
1282
1283static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
1284{
1285#if ELF_CLASS == ELFCLASS32
1286 struct elf_sym *syms = s->disas_symtab.elf32;
1287#else
1288 struct elf_sym *syms = s->disas_symtab.elf64;
1289#endif
1290
1291 // binary search
1292 struct elf_sym key;
1293 struct elf_sym *sym;
1294
1295 key.st_value = orig_addr;
1296
1297 sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
Blue Swirl7cba04f2009-08-01 10:13:20 +00001298 if (sym != NULL) {
pbrook49918a72008-10-22 15:11:31 +00001299 return s->disas_strtab + sym->st_name;
1300 }
1301
1302 return "";
1303}
1304
1305/* FIXME: This should use elf_ops.h */
1306static int symcmp(const void *s0, const void *s1)
1307{
1308 struct elf_sym *sym0 = (struct elf_sym *)s0;
1309 struct elf_sym *sym1 = (struct elf_sym *)s1;
1310 return (sym0->st_value < sym1->st_value)
1311 ? -1
1312 : ((sym0->st_value > sym1->st_value) ? 1 : 0);
1313}
1314
bellard689f9362003-04-29 20:40:07 +00001315/* Best attempt to load symbols from this ELF object. */
Richard Henderson682674b2010-07-27 10:25:33 -07001316static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
bellard689f9362003-04-29 20:40:07 +00001317{
Richard Henderson682674b2010-07-27 10:25:33 -07001318 int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
1319 struct elf_shdr *shdr;
bellard689f9362003-04-29 20:40:07 +00001320 char *strings;
bellarde80cfcf2004-12-19 23:18:01 +00001321 struct syminfo *s;
pbrook49918a72008-10-22 15:11:31 +00001322 struct elf_sym *syms;
bellard31e31b82003-02-18 22:55:36 +00001323
Richard Henderson682674b2010-07-27 10:25:33 -07001324 shnum = hdr->e_shnum;
1325 i = shnum * sizeof(struct elf_shdr);
1326 shdr = (struct elf_shdr *)alloca(i);
1327 if (pread(fd, shdr, i, hdr->e_shoff) != i) {
1328 return;
1329 }
1330
1331 bswap_shdr(shdr, shnum);
1332 for (i = 0; i < shnum; ++i) {
1333 if (shdr[i].sh_type == SHT_SYMTAB) {
1334 sym_idx = i;
1335 str_idx = shdr[i].sh_link;
pbrook49918a72008-10-22 15:11:31 +00001336 goto found;
1337 }
bellard689f9362003-04-29 20:40:07 +00001338 }
Richard Henderson682674b2010-07-27 10:25:33 -07001339
1340 /* There will be no symbol table if the file was stripped. */
1341 return;
bellard689f9362003-04-29 20:40:07 +00001342
1343 found:
Richard Henderson682674b2010-07-27 10:25:33 -07001344 /* Now know where the strtab and symtab are. Snarf them. */
bellarde80cfcf2004-12-19 23:18:01 +00001345 s = malloc(sizeof(*s));
Richard Henderson682674b2010-07-27 10:25:33 -07001346 if (!s) {
pbrook49918a72008-10-22 15:11:31 +00001347 return;
Richard Henderson682674b2010-07-27 10:25:33 -07001348 }
1349
1350 i = shdr[str_idx].sh_size;
1351 s->disas_strtab = strings = malloc(i);
1352 if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
1353 free(s);
1354 free(strings);
pbrook49918a72008-10-22 15:11:31 +00001355 return;
Richard Henderson682674b2010-07-27 10:25:33 -07001356 }
ths5fafdf22007-09-16 21:08:06 +00001357
Richard Henderson682674b2010-07-27 10:25:33 -07001358 i = shdr[sym_idx].sh_size;
1359 syms = malloc(i);
1360 if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
1361 free(s);
1362 free(strings);
1363 free(syms);
pbrook49918a72008-10-22 15:11:31 +00001364 return;
Richard Henderson682674b2010-07-27 10:25:33 -07001365 }
bellard689f9362003-04-29 20:40:07 +00001366
Richard Henderson682674b2010-07-27 10:25:33 -07001367 nsyms = i / sizeof(struct elf_sym);
1368 for (i = 0; i < nsyms; ) {
pbrook49918a72008-10-22 15:11:31 +00001369 bswap_sym(syms + i);
Richard Henderson682674b2010-07-27 10:25:33 -07001370 /* Throw away entries which we do not need. */
1371 if (syms[i].st_shndx == SHN_UNDEF
1372 || syms[i].st_shndx >= SHN_LORESERVE
1373 || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
1374 if (i < --nsyms) {
pbrook49918a72008-10-22 15:11:31 +00001375 syms[i] = syms[nsyms];
1376 }
Richard Henderson682674b2010-07-27 10:25:33 -07001377 } else {
pbrook49918a72008-10-22 15:11:31 +00001378#if defined(TARGET_ARM) || defined (TARGET_MIPS)
Richard Henderson682674b2010-07-27 10:25:33 -07001379 /* The bottom address bit marks a Thumb or MIPS16 symbol. */
1380 syms[i].st_value &= ~(target_ulong)1;
blueswir10774bed2007-07-05 13:23:29 +00001381#endif
Richard Henderson682674b2010-07-27 10:25:33 -07001382 syms[i].st_value += load_bias;
1383 i++;
1384 }
blueswir10774bed2007-07-05 13:23:29 +00001385 }
bellard689f9362003-04-29 20:40:07 +00001386
Richard Henderson682674b2010-07-27 10:25:33 -07001387 syms = realloc(syms, nsyms * sizeof(*syms));
pbrook49918a72008-10-22 15:11:31 +00001388 qsort(syms, nsyms, sizeof(*syms), symcmp);
1389
pbrook49918a72008-10-22 15:11:31 +00001390 s->disas_num_syms = nsyms;
1391#if ELF_CLASS == ELFCLASS32
1392 s->disas_symtab.elf32 = syms;
pbrook49918a72008-10-22 15:11:31 +00001393#else
1394 s->disas_symtab.elf64 = syms;
pbrook49918a72008-10-22 15:11:31 +00001395#endif
Richard Henderson682674b2010-07-27 10:25:33 -07001396 s->lookup_symbol = lookup_symbolxx;
bellarde80cfcf2004-12-19 23:18:01 +00001397 s->next = syminfos;
1398 syminfos = s;
bellard689f9362003-04-29 20:40:07 +00001399}
bellard31e31b82003-02-18 22:55:36 +00001400
pbrooke5fe0c52006-06-11 13:32:59 +00001401int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1402 struct image_info * info)
bellard31e31b82003-02-18 22:55:36 +00001403{
1404 struct elfhdr elf_ex;
1405 struct elfhdr interp_elf_ex;
1406 struct exec interp_ex;
1407 int interpreter_fd = -1; /* avoid warning */
blueswir1992f48a2007-10-14 16:27:31 +00001408 abi_ulong load_addr, load_bias;
bellard31e31b82003-02-18 22:55:36 +00001409 int load_addr_set = 0;
1410 unsigned int interpreter_type = INTERPRETER_NONE;
1411 unsigned char ibcs2_interpreter;
1412 int i;
blueswir1992f48a2007-10-14 16:27:31 +00001413 abi_ulong mapped_addr;
bellard31e31b82003-02-18 22:55:36 +00001414 struct elf_phdr * elf_ppnt;
1415 struct elf_phdr *elf_phdata;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001416 abi_ulong k, elf_brk;
bellard31e31b82003-02-18 22:55:36 +00001417 int retval;
1418 char * elf_interpreter;
blueswir1992f48a2007-10-14 16:27:31 +00001419 abi_ulong elf_entry, interp_load_addr = 0;
bellard31e31b82003-02-18 22:55:36 +00001420 int status;
blueswir1992f48a2007-10-14 16:27:31 +00001421 abi_ulong start_code, end_code, start_data, end_data;
1422 abi_ulong reloc_func_desc = 0;
1423 abi_ulong elf_stack;
bellard31e31b82003-02-18 22:55:36 +00001424 char passed_fileno[6];
1425
1426 ibcs2_interpreter = 0;
1427 status = 0;
1428 load_addr = 0;
bellard09bfb052003-04-10 00:03:40 +00001429 load_bias = 0;
bellard31e31b82003-02-18 22:55:36 +00001430 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
bellard31e31b82003-02-18 22:55:36 +00001431 bswap_ehdr(&elf_ex);
bellard31e31b82003-02-18 22:55:36 +00001432
bellard31e31b82003-02-18 22:55:36 +00001433 /* First of all, some simple consistency checks */
1434 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
Richard Hendersond97ef722010-07-27 10:25:29 -07001435 (! elf_check_arch(elf_ex.e_machine))) {
1436 return -ENOEXEC;
bellard31e31b82003-02-18 22:55:36 +00001437 }
1438
pbrooke5fe0c52006-06-11 13:32:59 +00001439 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1440 bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1441 bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1442 if (!bprm->p) {
1443 retval = -E2BIG;
1444 }
1445
bellard31e31b82003-02-18 22:55:36 +00001446 /* Now read in all of the header information */
bellard31e31b82003-02-18 22:55:36 +00001447 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
1448 if (elf_phdata == NULL) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001449 return -ENOMEM;
bellard31e31b82003-02-18 22:55:36 +00001450 }
1451
Richard Henderson9955ffa2010-07-27 10:25:30 -07001452 i = elf_ex.e_phnum * sizeof(struct elf_phdr);
1453 if (elf_ex.e_phoff + i <= BPRM_BUF_SIZE) {
1454 memcpy(elf_phdata, bprm->buf + elf_ex.e_phoff, i);
1455 } else {
1456 retval = pread(bprm->fd, (char *) elf_phdata, i, elf_ex.e_phoff);
1457 if (retval != i) {
1458 perror("load_elf_binary");
1459 exit(-1);
1460 }
bellard31e31b82003-02-18 22:55:36 +00001461 }
Richard Henderson991f8f02010-07-27 10:25:32 -07001462 bswap_phdr(elf_phdata, elf_ex.e_phnum);
bellard31e31b82003-02-18 22:55:36 +00001463
bellard31e31b82003-02-18 22:55:36 +00001464 elf_brk = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001465 elf_stack = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001466 elf_interpreter = NULL;
blueswir1992f48a2007-10-14 16:27:31 +00001467 start_code = ~((abi_ulong)0UL);
bellard31e31b82003-02-18 22:55:36 +00001468 end_code = 0;
j_mayer863cf0b2007-10-07 15:59:45 +00001469 start_data = 0;
bellard31e31b82003-02-18 22:55:36 +00001470 end_data = 0;
blueswir198448f52008-09-30 18:16:09 +00001471 interp_ex.a_info = 0;
bellard31e31b82003-02-18 22:55:36 +00001472
Richard Henderson991f8f02010-07-27 10:25:32 -07001473 elf_ppnt = elf_phdata;
bellard31e31b82003-02-18 22:55:36 +00001474 for(i=0;i < elf_ex.e_phnum; i++) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001475 if (elf_ppnt->p_type == PT_INTERP) {
1476 if ( elf_interpreter != NULL )
1477 {
1478 free (elf_phdata);
1479 free(elf_interpreter);
1480 close(bprm->fd);
1481 return -EINVAL;
1482 }
bellard31e31b82003-02-18 22:55:36 +00001483
Richard Hendersond97ef722010-07-27 10:25:29 -07001484 /* This is the program interpreter used for
1485 * shared libraries - for now assume that this
1486 * is an a.out format binary
1487 */
bellard31e31b82003-02-18 22:55:36 +00001488
Richard Hendersond97ef722010-07-27 10:25:29 -07001489 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
bellard31e31b82003-02-18 22:55:36 +00001490
Richard Hendersond97ef722010-07-27 10:25:29 -07001491 if (elf_interpreter == NULL) {
1492 free (elf_phdata);
1493 close(bprm->fd);
1494 return -ENOMEM;
1495 }
bellard31e31b82003-02-18 22:55:36 +00001496
Richard Henderson9955ffa2010-07-27 10:25:30 -07001497 if (elf_ppnt->p_offset + elf_ppnt->p_filesz <= BPRM_BUF_SIZE) {
1498 memcpy(elf_interpreter, bprm->buf + elf_ppnt->p_offset,
1499 elf_ppnt->p_filesz);
1500 } else {
1501 retval = pread(bprm->fd, elf_interpreter, elf_ppnt->p_filesz,
1502 elf_ppnt->p_offset);
1503 if (retval != elf_ppnt->p_filesz) {
1504 perror("load_elf_binary2");
1505 exit(-1);
1506 }
Richard Hendersond97ef722010-07-27 10:25:29 -07001507 }
bellard31e31b82003-02-18 22:55:36 +00001508
Richard Hendersond97ef722010-07-27 10:25:29 -07001509 /* If the program interpreter is one of these two,
1510 then assume an iBCS2 image. Otherwise assume
1511 a native linux image. */
bellard31e31b82003-02-18 22:55:36 +00001512
Richard Hendersond97ef722010-07-27 10:25:29 -07001513 /* JRP - Need to add X86 lib dir stuff here... */
bellard31e31b82003-02-18 22:55:36 +00001514
Richard Hendersond97ef722010-07-27 10:25:29 -07001515 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
1516 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
1517 ibcs2_interpreter = 1;
1518 }
bellard31e31b82003-02-18 22:55:36 +00001519
Richard Henderson9955ffa2010-07-27 10:25:30 -07001520 retval = open(path(elf_interpreter), O_RDONLY);
1521 if (retval < 0) {
1522 perror(elf_interpreter);
1523 exit(-1);
Richard Hendersond97ef722010-07-27 10:25:29 -07001524 }
Richard Henderson9955ffa2010-07-27 10:25:30 -07001525 interpreter_fd = retval;
bellard31e31b82003-02-18 22:55:36 +00001526
Richard Henderson9955ffa2010-07-27 10:25:30 -07001527 retval = read(interpreter_fd, bprm->buf, BPRM_BUF_SIZE);
Richard Hendersond97ef722010-07-27 10:25:29 -07001528 if (retval < 0) {
1529 perror("load_elf_binary3");
1530 exit(-1);
Richard Hendersond97ef722010-07-27 10:25:29 -07001531 }
Richard Henderson9955ffa2010-07-27 10:25:30 -07001532 if (retval < BPRM_BUF_SIZE) {
1533 memset(bprm->buf, 0, BPRM_BUF_SIZE - retval);
1534 }
1535
1536 interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
1537 interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
Richard Hendersond97ef722010-07-27 10:25:29 -07001538 }
1539 elf_ppnt++;
bellard31e31b82003-02-18 22:55:36 +00001540 }
1541
1542 /* Some simple consistency checks for the interpreter */
1543 if (elf_interpreter){
Richard Hendersond97ef722010-07-27 10:25:29 -07001544 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
bellard31e31b82003-02-18 22:55:36 +00001545
Richard Hendersond97ef722010-07-27 10:25:29 -07001546 /* Now figure out which format our binary is */
1547 if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
1548 (N_MAGIC(interp_ex) != QMAGIC)) {
1549 interpreter_type = INTERPRETER_ELF;
1550 }
bellard31e31b82003-02-18 22:55:36 +00001551
Richard Hendersond97ef722010-07-27 10:25:29 -07001552 if (interp_elf_ex.e_ident[0] != 0x7f ||
blueswir1b55266b2008-09-20 08:07:15 +00001553 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001554 interpreter_type &= ~INTERPRETER_ELF;
1555 }
bellard31e31b82003-02-18 22:55:36 +00001556
Richard Hendersond97ef722010-07-27 10:25:29 -07001557 if (!interpreter_type) {
1558 free(elf_interpreter);
1559 free(elf_phdata);
1560 close(bprm->fd);
1561 return -ELIBBAD;
1562 }
bellard31e31b82003-02-18 22:55:36 +00001563 }
1564
1565 /* OK, we are done with that, now set up the arg stuff,
1566 and then start this sucker up */
1567
pbrooke5fe0c52006-06-11 13:32:59 +00001568 {
Richard Hendersond97ef722010-07-27 10:25:29 -07001569 char * passed_p;
bellard31e31b82003-02-18 22:55:36 +00001570
Richard Hendersond97ef722010-07-27 10:25:29 -07001571 if (interpreter_type == INTERPRETER_AOUT) {
1572 snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
1573 passed_p = passed_fileno;
bellard31e31b82003-02-18 22:55:36 +00001574
Richard Hendersond97ef722010-07-27 10:25:29 -07001575 if (elf_interpreter) {
1576 bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
1577 bprm->argc++;
1578 }
1579 }
1580 if (!bprm->p) {
1581 if (elf_interpreter) {
1582 free(elf_interpreter);
1583 }
1584 free (elf_phdata);
1585 close(bprm->fd);
1586 return -E2BIG;
1587 }
bellard31e31b82003-02-18 22:55:36 +00001588 }
1589
1590 /* OK, This is the point of no return */
1591 info->end_data = 0;
1592 info->end_code = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001593 info->start_mmap = (abi_ulong)ELF_START_MMAP;
bellard31e31b82003-02-18 22:55:36 +00001594 info->mmap = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001595 elf_entry = (abi_ulong) elf_ex.e_entry;
bellard31e31b82003-02-18 22:55:36 +00001596
Paul Brook379f6692009-07-17 12:48:08 +01001597#if defined(CONFIG_USE_GUEST_BASE)
1598 /*
1599 * In case where user has not explicitly set the guest_base, we
1600 * probe here that should we set it automatically.
1601 */
Paul Brook68a1c812010-05-29 02:27:35 +01001602 if (!(have_guest_base || reserved_va)) {
Paul Brook379f6692009-07-17 12:48:08 +01001603 /*
Paul Brookc581ded2010-05-05 16:32:59 +01001604 * Go through ELF program header table and find the address
1605 * range used by loadable segments. Check that this is available on
1606 * the host, and if not find a suitable value for guest_base. */
1607 abi_ulong app_start = ~0;
1608 abi_ulong app_end = 0;
1609 abi_ulong addr;
1610 unsigned long host_start;
1611 unsigned long real_start;
1612 unsigned long host_size;
Paul Brook379f6692009-07-17 12:48:08 +01001613 for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
Richard Hendersond97ef722010-07-27 10:25:29 -07001614 i++, elf_ppnt++) {
Paul Brook379f6692009-07-17 12:48:08 +01001615 if (elf_ppnt->p_type != PT_LOAD)
1616 continue;
Paul Brookc581ded2010-05-05 16:32:59 +01001617 addr = elf_ppnt->p_vaddr;
1618 if (addr < app_start) {
1619 app_start = addr;
1620 }
1621 addr += elf_ppnt->p_memsz;
1622 if (addr > app_end) {
1623 app_end = addr;
Paul Brook379f6692009-07-17 12:48:08 +01001624 }
1625 }
Paul Brookc581ded2010-05-05 16:32:59 +01001626
1627 /* If we don't have any loadable segments then something
1628 is very wrong. */
1629 assert(app_start < app_end);
1630
1631 /* Round addresses to page boundaries. */
1632 app_start = app_start & qemu_host_page_mask;
1633 app_end = HOST_PAGE_ALIGN(app_end);
1634 if (app_start < mmap_min_addr) {
1635 host_start = HOST_PAGE_ALIGN(mmap_min_addr);
1636 } else {
1637 host_start = app_start;
1638 if (host_start != app_start) {
1639 fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
1640 abort();
1641 }
1642 }
1643 host_size = app_end - app_start;
1644 while (1) {
1645 /* Do not use mmap_find_vma here because that is limited to the
1646 guest address space. We are going to make the
1647 guest address space fit whatever we're given. */
1648 real_start = (unsigned long)mmap((void *)host_start, host_size,
1649 PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
1650 if (real_start == (unsigned long)-1) {
1651 fprintf(stderr, "qemu: Virtual memory exausted\n");
1652 abort();
1653 }
1654 if (real_start == host_start) {
1655 break;
1656 }
1657 /* That address didn't work. Unmap and try a different one.
1658 The address the host picked because is typically
1659 right at the top of the host address space and leaves the
1660 guest with no usable address space. Resort to a linear search.
1661 We already compensated for mmap_min_addr, so this should not
1662 happen often. Probably means we got unlucky and host address
1663 space randomization put a shared library somewhere
1664 inconvenient. */
1665 munmap((void *)real_start, host_size);
1666 host_start += qemu_host_page_size;
1667 if (host_start == app_start) {
1668 /* Theoretically possible if host doesn't have any
1669 suitably aligned areas. Normally the first mmap will
1670 fail. */
1671 fprintf(stderr, "qemu: Unable to find space for application\n");
1672 abort();
1673 }
1674 }
1675 qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
1676 " to 0x%lx\n", app_start, real_start);
1677 guest_base = real_start - app_start;
Paul Brook379f6692009-07-17 12:48:08 +01001678 }
1679#endif /* CONFIG_USE_GUEST_BASE */
1680
bellard31e31b82003-02-18 22:55:36 +00001681 /* Do this so that we can load the interpreter, if need be. We will
1682 change some of these later */
1683 info->rss = 0;
1684 bprm->p = setup_arg_pages(bprm->p, bprm, info);
1685 info->start_stack = bprm->p;
1686
1687 /* Now we do a little grungy work by mmaping the ELF image into
1688 * the correct location in memory. At this point, we assume that
1689 * the image should be loaded at fixed address, not at a variable
1690 * address.
1691 */
1692
bellard31e31b82003-02-18 22:55:36 +00001693 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
bellard09bfb052003-04-10 00:03:40 +00001694 int elf_prot = 0;
1695 int elf_flags = 0;
blueswir1992f48a2007-10-14 16:27:31 +00001696 abi_ulong error;
ths3b46e622007-09-17 08:09:54 +00001697
Richard Hendersond97ef722010-07-27 10:25:29 -07001698 if (elf_ppnt->p_type != PT_LOAD)
bellard09bfb052003-04-10 00:03:40 +00001699 continue;
ths3b46e622007-09-17 08:09:54 +00001700
bellard09bfb052003-04-10 00:03:40 +00001701 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
1702 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1703 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1704 elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
1705 if (elf_ex.e_type == ET_EXEC || load_addr_set) {
1706 elf_flags |= MAP_FIXED;
1707 } else if (elf_ex.e_type == ET_DYN) {
1708 /* Try and get dynamic programs out of the way of the default mmap
1709 base, as well as whatever program they might try to exec. This
1710 is because the brk will follow the loader, and is not movable. */
1711 /* NOTE: for qemu, we do a big mmap to get enough space
thse91c8a72007-06-03 13:35:16 +00001712 without hardcoding any address */
bellard54936002003-05-13 00:25:15 +00001713 error = target_mmap(0, ET_DYN_MAP_SIZE,
ths5fafdf22007-09-16 21:08:06 +00001714 PROT_NONE, MAP_PRIVATE | MAP_ANON,
bellard54936002003-05-13 00:25:15 +00001715 -1, 0);
bellard09bfb052003-04-10 00:03:40 +00001716 if (error == -1) {
1717 perror("mmap");
1718 exit(-1);
1719 }
bellard54936002003-05-13 00:25:15 +00001720 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001721 }
ths3b46e622007-09-17 08:09:54 +00001722
bellard54936002003-05-13 00:25:15 +00001723 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
1724 (elf_ppnt->p_filesz +
1725 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
1726 elf_prot,
1727 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
1728 bprm->fd,
ths5fafdf22007-09-16 21:08:06 +00001729 (elf_ppnt->p_offset -
bellard54936002003-05-13 00:25:15 +00001730 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
bellard09bfb052003-04-10 00:03:40 +00001731 if (error == -1) {
1732 perror("mmap");
1733 exit(-1);
1734 }
bellard31e31b82003-02-18 22:55:36 +00001735
1736#ifdef LOW_ELF_STACK
bellard54936002003-05-13 00:25:15 +00001737 if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
1738 elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
bellard31e31b82003-02-18 22:55:36 +00001739#endif
ths3b46e622007-09-17 08:09:54 +00001740
bellard09bfb052003-04-10 00:03:40 +00001741 if (!load_addr_set) {
1742 load_addr_set = 1;
1743 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1744 if (elf_ex.e_type == ET_DYN) {
1745 load_bias += error -
bellard54936002003-05-13 00:25:15 +00001746 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
bellard09bfb052003-04-10 00:03:40 +00001747 load_addr += load_bias;
j_mayer84409dd2007-04-06 08:56:50 +00001748 reloc_func_desc = load_bias;
bellard09bfb052003-04-10 00:03:40 +00001749 }
1750 }
1751 k = elf_ppnt->p_vaddr;
ths5fafdf22007-09-16 21:08:06 +00001752 if (k < start_code)
bellard09bfb052003-04-10 00:03:40 +00001753 start_code = k;
j_mayer863cf0b2007-10-07 15:59:45 +00001754 if (start_data < k)
1755 start_data = k;
bellard09bfb052003-04-10 00:03:40 +00001756 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
bellard09bfb052003-04-10 00:03:40 +00001757 if ((elf_ppnt->p_flags & PF_X) && end_code < k)
1758 end_code = k;
ths5fafdf22007-09-16 21:08:06 +00001759 if (end_data < k)
bellard09bfb052003-04-10 00:03:40 +00001760 end_data = k;
1761 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
Richard Hendersoncf129f32010-07-27 10:25:27 -07001762 if (k > elf_brk) {
1763 elf_brk = TARGET_PAGE_ALIGN(k);
1764 }
1765
1766 /* If the load segment requests extra zeros (e.g. bss), map it. */
1767 if (elf_ppnt->p_filesz < elf_ppnt->p_memsz) {
1768 abi_ulong base = load_bias + elf_ppnt->p_vaddr;
1769 zero_bss(base + elf_ppnt->p_filesz,
1770 base + elf_ppnt->p_memsz, elf_prot);
1771 }
bellard31e31b82003-02-18 22:55:36 +00001772 }
1773
bellard09bfb052003-04-10 00:03:40 +00001774 elf_entry += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001775 elf_brk += load_bias;
1776 start_code += load_bias;
1777 end_code += load_bias;
j_mayer863cf0b2007-10-07 15:59:45 +00001778 start_data += load_bias;
bellard09bfb052003-04-10 00:03:40 +00001779 end_data += load_bias;
1780
bellard31e31b82003-02-18 22:55:36 +00001781 if (elf_interpreter) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001782 if (interpreter_type & 1) {
1783 elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
Richard Henderson9955ffa2010-07-27 10:25:30 -07001784 } else if (interpreter_type & 2) {
Richard Hendersond97ef722010-07-27 10:25:29 -07001785 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
Richard Henderson9955ffa2010-07-27 10:25:30 -07001786 &interp_load_addr, bprm->buf);
Richard Hendersond97ef722010-07-27 10:25:29 -07001787 }
j_mayer84409dd2007-04-06 08:56:50 +00001788 reloc_func_desc = interp_load_addr;
bellard31e31b82003-02-18 22:55:36 +00001789
Richard Hendersond97ef722010-07-27 10:25:29 -07001790 close(interpreter_fd);
1791 free(elf_interpreter);
bellard31e31b82003-02-18 22:55:36 +00001792
Richard Hendersond97ef722010-07-27 10:25:29 -07001793 if (elf_entry == ~((abi_ulong)0UL)) {
1794 printf("Unable to load interpreter\n");
1795 free(elf_phdata);
1796 exit(-1);
1797 return 0;
1798 }
bellard31e31b82003-02-18 22:55:36 +00001799 }
1800
1801 free(elf_phdata);
1802
Richard Henderson682674b2010-07-27 10:25:33 -07001803 if (qemu_log_enabled()) {
1804 load_symbols(&elf_ex, bprm->fd, load_bias);
1805 }
bellard689f9362003-04-29 20:40:07 +00001806
bellard31e31b82003-02-18 22:55:36 +00001807 if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
1808 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
1809
1810#ifdef LOW_ELF_STACK
1811 info->start_stack = bprm->p = elf_stack - 4;
1812#endif
pbrook53a59602006-03-25 19:31:22 +00001813 bprm->p = create_elf_tables(bprm->p,
Richard Hendersond97ef722010-07-27 10:25:29 -07001814 bprm->argc,
1815 bprm->envc,
1816 &elf_ex,
1817 load_addr, load_bias,
1818 interp_load_addr,
1819 (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
1820 info);
j_mayer92a343d2007-09-27 01:14:15 +00001821 info->load_addr = reloc_func_desc;
bellard31e31b82003-02-18 22:55:36 +00001822 info->start_brk = info->brk = elf_brk;
1823 info->end_code = end_code;
1824 info->start_code = start_code;
j_mayer863cf0b2007-10-07 15:59:45 +00001825 info->start_data = start_data;
bellard31e31b82003-02-18 22:55:36 +00001826 info->end_data = end_data;
1827 info->start_stack = bprm->p;
1828
bellard31e31b82003-02-18 22:55:36 +00001829#if 0
1830 printf("(start_brk) %x\n" , info->start_brk);
1831 printf("(end_code) %x\n" , info->end_code);
1832 printf("(start_code) %x\n" , info->start_code);
1833 printf("(end_data) %x\n" , info->end_data);
1834 printf("(start_stack) %x\n" , info->start_stack);
1835 printf("(brk) %x\n" , info->brk);
1836#endif
1837
1838 if ( info->personality == PER_SVR4 )
1839 {
Richard Hendersond97ef722010-07-27 10:25:29 -07001840 /* Why this, you ask??? Well SVr4 maps page 0 as read-only,
1841 and some applications "depend" upon this behavior.
1842 Since we do not have the power to recompile these, we
1843 emulate the SVr4 behavior. Sigh. */
1844 mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
1845 MAP_FIXED | MAP_PRIVATE, -1, 0);
bellard31e31b82003-02-18 22:55:36 +00001846 }
1847
bellard31e31b82003-02-18 22:55:36 +00001848 info->entry = elf_entry;
1849
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001850#ifdef USE_ELF_CORE_DUMP
1851 bprm->core_dump = &elf_core_dump;
1852#endif
1853
bellard31e31b82003-02-18 22:55:36 +00001854 return 0;
1855}
1856
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001857#ifdef USE_ELF_CORE_DUMP
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001858/*
1859 * Definitions to generate Intel SVR4-like core files.
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001860 * These mostly have the same names as the SVR4 types with "target_elf_"
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001861 * tacked on the front to prevent clashes with linux definitions,
1862 * and the typedef forms have been avoided. This is mostly like
1863 * the SVR4 structure, but more Linuxy, with things that Linux does
1864 * not support and which gdb doesn't really use excluded.
1865 *
1866 * Fields we don't dump (their contents is zero) in linux-user qemu
1867 * are marked with XXX.
1868 *
1869 * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
1870 *
1871 * Porting ELF coredump for target is (quite) simple process. First you
Nathan Froyddd0a3652009-12-11 09:04:45 -08001872 * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001873 * the target resides):
1874 *
1875 * #define USE_ELF_CORE_DUMP
1876 *
1877 * Next you define type of register set used for dumping. ELF specification
1878 * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
1879 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001880 * typedef <target_regtype> target_elf_greg_t;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001881 * #define ELF_NREG <number of registers>
Anthony Liguoric227f092009-10-01 16:12:16 -05001882 * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001883 *
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001884 * Last step is to implement target specific function that copies registers
1885 * from given cpu into just specified register set. Prototype is:
1886 *
Anthony Liguoric227f092009-10-01 16:12:16 -05001887 * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001888 * const CPUState *env);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001889 *
1890 * Parameters:
1891 * regs - copy register values into here (allocated and zeroed by caller)
1892 * env - copy registers from here
1893 *
1894 * Example for ARM target is provided in this file.
1895 */
1896
1897/* An ELF note in memory */
1898struct memelfnote {
1899 const char *name;
1900 size_t namesz;
1901 size_t namesz_rounded;
1902 int type;
1903 size_t datasz;
1904 void *data;
1905 size_t notesz;
1906};
1907
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001908struct target_elf_siginfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001909 int si_signo; /* signal number */
1910 int si_code; /* extra code */
1911 int si_errno; /* errno */
1912};
1913
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001914struct target_elf_prstatus {
1915 struct target_elf_siginfo pr_info; /* Info associated with signal */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001916 short pr_cursig; /* Current signal */
1917 target_ulong pr_sigpend; /* XXX */
1918 target_ulong pr_sighold; /* XXX */
Anthony Liguoric227f092009-10-01 16:12:16 -05001919 target_pid_t pr_pid;
1920 target_pid_t pr_ppid;
1921 target_pid_t pr_pgrp;
1922 target_pid_t pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001923 struct target_timeval pr_utime; /* XXX User time */
1924 struct target_timeval pr_stime; /* XXX System time */
1925 struct target_timeval pr_cutime; /* XXX Cumulative user time */
1926 struct target_timeval pr_cstime; /* XXX Cumulative system time */
Anthony Liguoric227f092009-10-01 16:12:16 -05001927 target_elf_gregset_t pr_reg; /* GP registers */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001928 int pr_fpvalid; /* XXX */
1929};
1930
1931#define ELF_PRARGSZ (80) /* Number of chars for args */
1932
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001933struct target_elf_prpsinfo {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001934 char pr_state; /* numeric process state */
1935 char pr_sname; /* char for pr_state */
1936 char pr_zomb; /* zombie */
1937 char pr_nice; /* nice val */
1938 target_ulong pr_flag; /* flags */
Anthony Liguoric227f092009-10-01 16:12:16 -05001939 target_uid_t pr_uid;
1940 target_gid_t pr_gid;
1941 target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001942 /* Lots missing */
1943 char pr_fname[16]; /* filename of executable */
1944 char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
1945};
1946
1947/* Here is the structure in which status of each thread is captured. */
1948struct elf_thread_status {
Blue Swirl72cf2d42009-09-12 07:36:22 +00001949 QTAILQ_ENTRY(elf_thread_status) ets_link;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001950 struct target_elf_prstatus prstatus; /* NT_PRSTATUS */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001951#if 0
1952 elf_fpregset_t fpu; /* NT_PRFPREG */
1953 struct task_struct *thread;
1954 elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */
1955#endif
1956 struct memelfnote notes[1];
1957 int num_notes;
1958};
1959
1960struct elf_note_info {
1961 struct memelfnote *notes;
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01001962 struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */
1963 struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001964
Blue Swirl72cf2d42009-09-12 07:36:22 +00001965 QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001966#if 0
1967 /*
1968 * Current version of ELF coredump doesn't support
1969 * dumping fp regs etc.
1970 */
1971 elf_fpregset_t *fpu;
1972 elf_fpxregset_t *xfpu;
1973 int thread_status_size;
1974#endif
1975 int notes_size;
1976 int numnote;
1977};
1978
1979struct vm_area_struct {
1980 abi_ulong vma_start; /* start vaddr of memory region */
1981 abi_ulong vma_end; /* end vaddr of memory region */
1982 abi_ulong vma_flags; /* protection etc. flags for the region */
Blue Swirl72cf2d42009-09-12 07:36:22 +00001983 QTAILQ_ENTRY(vm_area_struct) vma_link;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001984};
1985
1986struct mm_struct {
Blue Swirl72cf2d42009-09-12 07:36:22 +00001987 QTAILQ_HEAD(, vm_area_struct) mm_mmap;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001988 int mm_count; /* number of mappings */
1989};
1990
1991static struct mm_struct *vma_init(void);
1992static void vma_delete(struct mm_struct *);
1993static int vma_add_mapping(struct mm_struct *, abi_ulong,
Richard Hendersond97ef722010-07-27 10:25:29 -07001994 abi_ulong, abi_ulong);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03001995static int vma_get_mapping_count(const struct mm_struct *);
1996static struct vm_area_struct *vma_first(const struct mm_struct *);
1997static struct vm_area_struct *vma_next(struct vm_area_struct *);
1998static abi_ulong vma_dump_size(const struct vm_area_struct *);
Paul Brookb480d9b2010-03-12 23:23:29 +00001999static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07002000 unsigned long flags);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002001
2002static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
2003static void fill_note(struct memelfnote *, const char *, int,
Richard Hendersond97ef722010-07-27 10:25:29 -07002004 unsigned int, void *);
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002005static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
2006static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002007static void fill_auxv_note(struct memelfnote *, const TaskState *);
2008static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
2009static size_t note_size(const struct memelfnote *);
2010static void free_note_info(struct elf_note_info *);
2011static int fill_note_info(struct elf_note_info *, long, const CPUState *);
2012static void fill_thread_info(struct elf_note_info *, const CPUState *);
2013static int core_dump_filename(const TaskState *, char *, size_t);
2014
2015static int dump_write(int, const void *, size_t);
2016static int write_note(struct memelfnote *, int);
2017static int write_note_info(struct elf_note_info *, int);
2018
2019#ifdef BSWAP_NEEDED
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002020static void bswap_prstatus(struct target_elf_prstatus *prstatus)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002021{
2022 prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
2023 prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
2024 prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
2025 prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
2026 prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
2027 prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
2028 prstatus->pr_pid = tswap32(prstatus->pr_pid);
2029 prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
2030 prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
2031 prstatus->pr_sid = tswap32(prstatus->pr_sid);
2032 /* cpu times are not filled, so we skip them */
2033 /* regs should be in correct format already */
2034 prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
2035}
2036
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002037static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002038{
2039 psinfo->pr_flag = tswapl(psinfo->pr_flag);
2040 psinfo->pr_uid = tswap16(psinfo->pr_uid);
2041 psinfo->pr_gid = tswap16(psinfo->pr_gid);
2042 psinfo->pr_pid = tswap32(psinfo->pr_pid);
2043 psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
2044 psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
2045 psinfo->pr_sid = tswap32(psinfo->pr_sid);
2046}
Richard Henderson991f8f02010-07-27 10:25:32 -07002047
2048static void bswap_note(struct elf_note *en)
2049{
2050 bswap32s(&en->n_namesz);
2051 bswap32s(&en->n_descsz);
2052 bswap32s(&en->n_type);
2053}
2054#else
2055static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
2056static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
2057static inline void bswap_note(struct elf_note *en) { }
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002058#endif /* BSWAP_NEEDED */
2059
2060/*
2061 * Minimal support for linux memory regions. These are needed
2062 * when we are finding out what memory exactly belongs to
2063 * emulated process. No locks needed here, as long as
2064 * thread that received the signal is stopped.
2065 */
2066
2067static struct mm_struct *vma_init(void)
2068{
2069 struct mm_struct *mm;
2070
2071 if ((mm = qemu_malloc(sizeof (*mm))) == NULL)
2072 return (NULL);
2073
2074 mm->mm_count = 0;
Blue Swirl72cf2d42009-09-12 07:36:22 +00002075 QTAILQ_INIT(&mm->mm_mmap);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002076
2077 return (mm);
2078}
2079
2080static void vma_delete(struct mm_struct *mm)
2081{
2082 struct vm_area_struct *vma;
2083
2084 while ((vma = vma_first(mm)) != NULL) {
Blue Swirl72cf2d42009-09-12 07:36:22 +00002085 QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002086 qemu_free(vma);
2087 }
2088 qemu_free(mm);
2089}
2090
2091static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
Richard Hendersond97ef722010-07-27 10:25:29 -07002092 abi_ulong end, abi_ulong flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002093{
2094 struct vm_area_struct *vma;
2095
2096 if ((vma = qemu_mallocz(sizeof (*vma))) == NULL)
2097 return (-1);
2098
2099 vma->vma_start = start;
2100 vma->vma_end = end;
2101 vma->vma_flags = flags;
2102
Blue Swirl72cf2d42009-09-12 07:36:22 +00002103 QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002104 mm->mm_count++;
2105
2106 return (0);
2107}
2108
2109static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2110{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002111 return (QTAILQ_FIRST(&mm->mm_mmap));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002112}
2113
2114static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2115{
Blue Swirl72cf2d42009-09-12 07:36:22 +00002116 return (QTAILQ_NEXT(vma, vma_link));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002117}
2118
2119static int vma_get_mapping_count(const struct mm_struct *mm)
2120{
2121 return (mm->mm_count);
2122}
2123
2124/*
2125 * Calculate file (dump) size of given memory region.
2126 */
2127static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2128{
2129 /* if we cannot even read the first page, skip it */
2130 if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2131 return (0);
2132
2133 /*
2134 * Usually we don't dump executable pages as they contain
2135 * non-writable code that debugger can read directly from
2136 * target library etc. However, thread stacks are marked
2137 * also executable so we read in first page of given region
2138 * and check whether it contains elf header. If there is
2139 * no elf header, we dump it.
2140 */
2141 if (vma->vma_flags & PROT_EXEC) {
2142 char page[TARGET_PAGE_SIZE];
2143
2144 copy_from_user(page, vma->vma_start, sizeof (page));
2145 if ((page[EI_MAG0] == ELFMAG0) &&
2146 (page[EI_MAG1] == ELFMAG1) &&
2147 (page[EI_MAG2] == ELFMAG2) &&
2148 (page[EI_MAG3] == ELFMAG3)) {
2149 /*
2150 * Mappings are possibly from ELF binary. Don't dump
2151 * them.
2152 */
2153 return (0);
2154 }
2155 }
2156
2157 return (vma->vma_end - vma->vma_start);
2158}
2159
Paul Brookb480d9b2010-03-12 23:23:29 +00002160static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
Richard Hendersond97ef722010-07-27 10:25:29 -07002161 unsigned long flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002162{
2163 struct mm_struct *mm = (struct mm_struct *)priv;
2164
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002165 vma_add_mapping(mm, start, end, flags);
2166 return (0);
2167}
2168
2169static void fill_note(struct memelfnote *note, const char *name, int type,
Richard Hendersond97ef722010-07-27 10:25:29 -07002170 unsigned int sz, void *data)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002171{
2172 unsigned int namesz;
2173
2174 namesz = strlen(name) + 1;
2175 note->name = name;
2176 note->namesz = namesz;
2177 note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2178 note->type = type;
2179 note->datasz = roundup(sz, sizeof (int32_t));;
2180 note->data = data;
2181
2182 /*
2183 * We calculate rounded up note size here as specified by
2184 * ELF document.
2185 */
2186 note->notesz = sizeof (struct elf_note) +
2187 note->namesz_rounded + note->datasz;
2188}
2189
2190static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
Richard Hendersond97ef722010-07-27 10:25:29 -07002191 uint32_t flags)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002192{
2193 (void) memset(elf, 0, sizeof(*elf));
2194
2195 (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2196 elf->e_ident[EI_CLASS] = ELF_CLASS;
2197 elf->e_ident[EI_DATA] = ELF_DATA;
2198 elf->e_ident[EI_VERSION] = EV_CURRENT;
2199 elf->e_ident[EI_OSABI] = ELF_OSABI;
2200
2201 elf->e_type = ET_CORE;
2202 elf->e_machine = machine;
2203 elf->e_version = EV_CURRENT;
2204 elf->e_phoff = sizeof(struct elfhdr);
2205 elf->e_flags = flags;
2206 elf->e_ehsize = sizeof(struct elfhdr);
2207 elf->e_phentsize = sizeof(struct elf_phdr);
2208 elf->e_phnum = segs;
2209
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002210 bswap_ehdr(elf);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002211}
2212
2213static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2214{
2215 phdr->p_type = PT_NOTE;
2216 phdr->p_offset = offset;
2217 phdr->p_vaddr = 0;
2218 phdr->p_paddr = 0;
2219 phdr->p_filesz = sz;
2220 phdr->p_memsz = 0;
2221 phdr->p_flags = 0;
2222 phdr->p_align = 0;
2223
Richard Henderson991f8f02010-07-27 10:25:32 -07002224 bswap_phdr(phdr, 1);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002225}
2226
2227static size_t note_size(const struct memelfnote *note)
2228{
2229 return (note->notesz);
2230}
2231
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002232static void fill_prstatus(struct target_elf_prstatus *prstatus,
Richard Hendersond97ef722010-07-27 10:25:29 -07002233 const TaskState *ts, int signr)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002234{
2235 (void) memset(prstatus, 0, sizeof (*prstatus));
2236 prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2237 prstatus->pr_pid = ts->ts_tid;
2238 prstatus->pr_ppid = getppid();
2239 prstatus->pr_pgrp = getpgrp();
2240 prstatus->pr_sid = getsid(0);
2241
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002242 bswap_prstatus(prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002243}
2244
Laurent Desnoguesa2547a12009-07-17 13:33:41 +01002245static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002246{
2247 char *filename, *base_filename;
2248 unsigned int i, len;
2249
2250 (void) memset(psinfo, 0, sizeof (*psinfo));
2251
2252 len = ts->info->arg_end - ts->info->arg_start;
2253 if (len >= ELF_PRARGSZ)
2254 len = ELF_PRARGSZ - 1;
2255 if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2256 return -EFAULT;
2257 for (i = 0; i < len; i++)
2258 if (psinfo->pr_psargs[i] == 0)
2259 psinfo->pr_psargs[i] = ' ';
2260 psinfo->pr_psargs[len] = 0;
2261
2262 psinfo->pr_pid = getpid();
2263 psinfo->pr_ppid = getppid();
2264 psinfo->pr_pgrp = getpgrp();
2265 psinfo->pr_sid = getsid(0);
2266 psinfo->pr_uid = getuid();
2267 psinfo->pr_gid = getgid();
2268
2269 filename = strdup(ts->bprm->filename);
2270 base_filename = strdup(basename(filename));
2271 (void) strncpy(psinfo->pr_fname, base_filename,
Richard Hendersond97ef722010-07-27 10:25:29 -07002272 sizeof(psinfo->pr_fname));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002273 free(base_filename);
2274 free(filename);
2275
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002276 bswap_psinfo(psinfo);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002277 return (0);
2278}
2279
2280static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2281{
2282 elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2283 elf_addr_t orig_auxv = auxv;
2284 abi_ulong val;
2285 void *ptr;
2286 int i, len;
2287
2288 /*
2289 * Auxiliary vector is stored in target process stack. It contains
2290 * {type, value} pairs that we need to dump into note. This is not
2291 * strictly necessary but we do it here for sake of completeness.
2292 */
2293
2294 /* find out lenght of the vector, AT_NULL is terminator */
2295 i = len = 0;
2296 do {
2297 get_user_ual(val, auxv);
2298 i += 2;
2299 auxv += 2 * sizeof (elf_addr_t);
2300 } while (val != AT_NULL);
2301 len = i * sizeof (elf_addr_t);
2302
2303 /* read in whole auxv vector and copy it to memelfnote */
2304 ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2305 if (ptr != NULL) {
2306 fill_note(note, "CORE", NT_AUXV, len, ptr);
2307 unlock_user(ptr, auxv, len);
2308 }
2309}
2310
2311/*
2312 * Constructs name of coredump file. We have following convention
2313 * for the name:
2314 * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2315 *
2316 * Returns 0 in case of success, -1 otherwise (errno is set).
2317 */
2318static int core_dump_filename(const TaskState *ts, char *buf,
Richard Hendersond97ef722010-07-27 10:25:29 -07002319 size_t bufsize)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002320{
2321 char timestamp[64];
2322 char *filename = NULL;
2323 char *base_filename = NULL;
2324 struct timeval tv;
2325 struct tm tm;
2326
2327 assert(bufsize >= PATH_MAX);
2328
2329 if (gettimeofday(&tv, NULL) < 0) {
2330 (void) fprintf(stderr, "unable to get current timestamp: %s",
Richard Hendersond97ef722010-07-27 10:25:29 -07002331 strerror(errno));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002332 return (-1);
2333 }
2334
2335 filename = strdup(ts->bprm->filename);
2336 base_filename = strdup(basename(filename));
2337 (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
Richard Hendersond97ef722010-07-27 10:25:29 -07002338 localtime_r(&tv.tv_sec, &tm));
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002339 (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
Richard Hendersond97ef722010-07-27 10:25:29 -07002340 base_filename, timestamp, (int)getpid());
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002341 free(base_filename);
2342 free(filename);
2343
2344 return (0);
2345}
2346
2347static int dump_write(int fd, const void *ptr, size_t size)
2348{
2349 const char *bufp = (const char *)ptr;
2350 ssize_t bytes_written, bytes_left;
2351 struct rlimit dumpsize;
2352 off_t pos;
2353
2354 bytes_written = 0;
2355 getrlimit(RLIMIT_CORE, &dumpsize);
2356 if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2357 if (errno == ESPIPE) { /* not a seekable stream */
2358 bytes_left = size;
2359 } else {
2360 return pos;
2361 }
2362 } else {
2363 if (dumpsize.rlim_cur <= pos) {
2364 return -1;
2365 } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2366 bytes_left = size;
2367 } else {
2368 size_t limit_left=dumpsize.rlim_cur - pos;
2369 bytes_left = limit_left >= size ? size : limit_left ;
2370 }
2371 }
2372
2373 /*
2374 * In normal conditions, single write(2) should do but
2375 * in case of socket etc. this mechanism is more portable.
2376 */
2377 do {
2378 bytes_written = write(fd, bufp, bytes_left);
2379 if (bytes_written < 0) {
2380 if (errno == EINTR)
2381 continue;
2382 return (-1);
2383 } else if (bytes_written == 0) { /* eof */
2384 return (-1);
2385 }
2386 bufp += bytes_written;
2387 bytes_left -= bytes_written;
2388 } while (bytes_left > 0);
2389
2390 return (0);
2391}
2392
2393static int write_note(struct memelfnote *men, int fd)
2394{
2395 struct elf_note en;
2396
2397 en.n_namesz = men->namesz;
2398 en.n_type = men->type;
2399 en.n_descsz = men->datasz;
2400
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002401 bswap_note(&en);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002402
2403 if (dump_write(fd, &en, sizeof(en)) != 0)
2404 return (-1);
2405 if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2406 return (-1);
2407 if (dump_write(fd, men->data, men->datasz) != 0)
2408 return (-1);
2409
2410 return (0);
2411}
2412
2413static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
2414{
2415 TaskState *ts = (TaskState *)env->opaque;
2416 struct elf_thread_status *ets;
2417
2418 ets = qemu_mallocz(sizeof (*ets));
2419 ets->num_notes = 1; /* only prstatus is dumped */
2420 fill_prstatus(&ets->prstatus, ts, 0);
2421 elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2422 fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
Richard Hendersond97ef722010-07-27 10:25:29 -07002423 &ets->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002424
Blue Swirl72cf2d42009-09-12 07:36:22 +00002425 QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002426
2427 info->notes_size += note_size(&ets->notes[0]);
2428}
2429
2430static int fill_note_info(struct elf_note_info *info,
Richard Hendersond97ef722010-07-27 10:25:29 -07002431 long signr, const CPUState *env)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002432{
2433#define NUMNOTES 3
2434 CPUState *cpu = NULL;
2435 TaskState *ts = (TaskState *)env->opaque;
2436 int i;
2437
2438 (void) memset(info, 0, sizeof (*info));
2439
Blue Swirl72cf2d42009-09-12 07:36:22 +00002440 QTAILQ_INIT(&info->thread_list);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002441
2442 info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote));
2443 if (info->notes == NULL)
2444 return (-ENOMEM);
2445 info->prstatus = qemu_mallocz(sizeof (*info->prstatus));
2446 if (info->prstatus == NULL)
2447 return (-ENOMEM);
2448 info->psinfo = qemu_mallocz(sizeof (*info->psinfo));
2449 if (info->prstatus == NULL)
2450 return (-ENOMEM);
2451
2452 /*
2453 * First fill in status (and registers) of current thread
2454 * including process info & aux vector.
2455 */
2456 fill_prstatus(info->prstatus, ts, signr);
2457 elf_core_copy_regs(&info->prstatus->pr_reg, env);
2458 fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
Richard Hendersond97ef722010-07-27 10:25:29 -07002459 sizeof (*info->prstatus), info->prstatus);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002460 fill_psinfo(info->psinfo, ts);
2461 fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
Richard Hendersond97ef722010-07-27 10:25:29 -07002462 sizeof (*info->psinfo), info->psinfo);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002463 fill_auxv_note(&info->notes[2], ts);
2464 info->numnote = 3;
2465
2466 info->notes_size = 0;
2467 for (i = 0; i < info->numnote; i++)
2468 info->notes_size += note_size(&info->notes[i]);
2469
2470 /* read and fill status of all threads */
2471 cpu_list_lock();
2472 for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2473 if (cpu == thread_env)
2474 continue;
2475 fill_thread_info(info, cpu);
2476 }
2477 cpu_list_unlock();
2478
2479 return (0);
2480}
2481
2482static void free_note_info(struct elf_note_info *info)
2483{
2484 struct elf_thread_status *ets;
2485
Blue Swirl72cf2d42009-09-12 07:36:22 +00002486 while (!QTAILQ_EMPTY(&info->thread_list)) {
2487 ets = QTAILQ_FIRST(&info->thread_list);
2488 QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002489 qemu_free(ets);
2490 }
2491
2492 qemu_free(info->prstatus);
2493 qemu_free(info->psinfo);
2494 qemu_free(info->notes);
2495}
2496
2497static int write_note_info(struct elf_note_info *info, int fd)
2498{
2499 struct elf_thread_status *ets;
2500 int i, error = 0;
2501
2502 /* write prstatus, psinfo and auxv for current thread */
2503 for (i = 0; i < info->numnote; i++)
2504 if ((error = write_note(&info->notes[i], fd)) != 0)
2505 return (error);
2506
2507 /* write prstatus for each thread */
2508 for (ets = info->thread_list.tqh_first; ets != NULL;
Richard Hendersond97ef722010-07-27 10:25:29 -07002509 ets = ets->ets_link.tqe_next) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002510 if ((error = write_note(&ets->notes[0], fd)) != 0)
2511 return (error);
2512 }
2513
2514 return (0);
2515}
2516
2517/*
2518 * Write out ELF coredump.
2519 *
2520 * See documentation of ELF object file format in:
2521 * http://www.caldera.com/developers/devspecs/gabi41.pdf
2522 *
2523 * Coredump format in linux is following:
2524 *
2525 * 0 +----------------------+ \
2526 * | ELF header | ET_CORE |
2527 * +----------------------+ |
2528 * | ELF program headers | |--- headers
2529 * | - NOTE section | |
2530 * | - PT_LOAD sections | |
2531 * +----------------------+ /
2532 * | NOTEs: |
2533 * | - NT_PRSTATUS |
2534 * | - NT_PRSINFO |
2535 * | - NT_AUXV |
2536 * +----------------------+ <-- aligned to target page
2537 * | Process memory dump |
2538 * : :
2539 * . .
2540 * : :
2541 * | |
2542 * +----------------------+
2543 *
2544 * NT_PRSTATUS -> struct elf_prstatus (per thread)
2545 * NT_PRSINFO -> struct elf_prpsinfo
2546 * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2547 *
2548 * Format follows System V format as close as possible. Current
2549 * version limitations are as follows:
2550 * - no floating point registers are dumped
2551 *
2552 * Function returns 0 in case of success, negative errno otherwise.
2553 *
2554 * TODO: make this work also during runtime: it should be
2555 * possible to force coredump from running process and then
2556 * continue processing. For example qemu could set up SIGUSR2
2557 * handler (provided that target process haven't registered
2558 * handler for that) that does the dump when signal is received.
2559 */
2560static int elf_core_dump(int signr, const CPUState *env)
2561{
2562 const TaskState *ts = (const TaskState *)env->opaque;
2563 struct vm_area_struct *vma = NULL;
2564 char corefile[PATH_MAX];
2565 struct elf_note_info info;
2566 struct elfhdr elf;
2567 struct elf_phdr phdr;
2568 struct rlimit dumpsize;
2569 struct mm_struct *mm = NULL;
2570 off_t offset = 0, data_offset = 0;
2571 int segs = 0;
2572 int fd = -1;
2573
2574 errno = 0;
2575 getrlimit(RLIMIT_CORE, &dumpsize);
2576 if (dumpsize.rlim_cur == 0)
Richard Hendersond97ef722010-07-27 10:25:29 -07002577 return 0;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002578
2579 if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2580 return (-errno);
2581
2582 if ((fd = open(corefile, O_WRONLY | O_CREAT,
Richard Hendersond97ef722010-07-27 10:25:29 -07002583 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002584 return (-errno);
2585
2586 /*
2587 * Walk through target process memory mappings and
2588 * set up structure containing this information. After
2589 * this point vma_xxx functions can be used.
2590 */
2591 if ((mm = vma_init()) == NULL)
2592 goto out;
2593
2594 walk_memory_regions(mm, vma_walker);
2595 segs = vma_get_mapping_count(mm);
2596
2597 /*
2598 * Construct valid coredump ELF header. We also
2599 * add one more segment for notes.
2600 */
2601 fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2602 if (dump_write(fd, &elf, sizeof (elf)) != 0)
2603 goto out;
2604
2605 /* fill in in-memory version of notes */
2606 if (fill_note_info(&info, signr, env) < 0)
2607 goto out;
2608
2609 offset += sizeof (elf); /* elf header */
2610 offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */
2611
2612 /* write out notes program header */
2613 fill_elf_note_phdr(&phdr, info.notes_size, offset);
2614
2615 offset += info.notes_size;
2616 if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2617 goto out;
2618
2619 /*
2620 * ELF specification wants data to start at page boundary so
2621 * we align it here.
2622 */
2623 offset = roundup(offset, ELF_EXEC_PAGESIZE);
2624
2625 /*
2626 * Write program headers for memory regions mapped in
2627 * the target process.
2628 */
2629 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2630 (void) memset(&phdr, 0, sizeof (phdr));
2631
2632 phdr.p_type = PT_LOAD;
2633 phdr.p_offset = offset;
2634 phdr.p_vaddr = vma->vma_start;
2635 phdr.p_paddr = 0;
2636 phdr.p_filesz = vma_dump_size(vma);
2637 offset += phdr.p_filesz;
2638 phdr.p_memsz = vma->vma_end - vma->vma_start;
2639 phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2640 if (vma->vma_flags & PROT_WRITE)
2641 phdr.p_flags |= PF_W;
2642 if (vma->vma_flags & PROT_EXEC)
2643 phdr.p_flags |= PF_X;
2644 phdr.p_align = ELF_EXEC_PAGESIZE;
2645
2646 dump_write(fd, &phdr, sizeof (phdr));
2647 }
2648
2649 /*
2650 * Next we write notes just after program headers. No
2651 * alignment needed here.
2652 */
2653 if (write_note_info(&info, fd) < 0)
2654 goto out;
2655
2656 /* align data to page boundary */
2657 data_offset = lseek(fd, 0, SEEK_CUR);
2658 data_offset = TARGET_PAGE_ALIGN(data_offset);
2659 if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2660 goto out;
2661
2662 /*
2663 * Finally we can dump process memory into corefile as well.
2664 */
2665 for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2666 abi_ulong addr;
2667 abi_ulong end;
2668
2669 end = vma->vma_start + vma_dump_size(vma);
2670
2671 for (addr = vma->vma_start; addr < end;
Richard Hendersond97ef722010-07-27 10:25:29 -07002672 addr += TARGET_PAGE_SIZE) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002673 char page[TARGET_PAGE_SIZE];
2674 int error;
2675
2676 /*
2677 * Read in page from target process memory and
2678 * write it to coredump file.
2679 */
2680 error = copy_from_user(page, addr, sizeof (page));
2681 if (error != 0) {
Aurelien Jarno49995e12009-12-19 20:28:23 +01002682 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
Richard Hendersond97ef722010-07-27 10:25:29 -07002683 addr);
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002684 errno = -error;
2685 goto out;
2686 }
2687 if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2688 goto out;
2689 }
2690 }
2691
Richard Hendersond97ef722010-07-27 10:25:29 -07002692 out:
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03002693 free_note_info(&info);
2694 if (mm != NULL)
2695 vma_delete(mm);
2696 (void) close(fd);
2697
2698 if (errno != 0)
2699 return (-errno);
2700 return (0);
2701}
2702
2703#endif /* USE_ELF_CORE_DUMP */
2704
bellard31e31b82003-02-18 22:55:36 +00002705static int load_aout_interp(void * exptr, int interp_fd)
2706{
2707 printf("a.out interpreter not yet supported\n");
2708 return(0);
2709}
2710
pbrooke5fe0c52006-06-11 13:32:59 +00002711void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2712{
2713 init_thread(regs, infop);
2714}