xref: /qemu/linux-user/elfload.c (revision 3efa9a672e4a5f7b2d35cf457ea277e997a0f8c6)
131e31b8aSbellard /* This is the Linux kernel elf-loading code, ported into user space */
2edf8e2afSMika Westerberg #include <sys/time.h>
3edf8e2afSMika Westerberg #include <sys/param.h>
431e31b8aSbellard 
531e31b8aSbellard #include <stdio.h>
631e31b8aSbellard #include <sys/types.h>
731e31b8aSbellard #include <fcntl.h>
831e31b8aSbellard #include <errno.h>
931e31b8aSbellard #include <unistd.h>
1031e31b8aSbellard #include <sys/mman.h>
11edf8e2afSMika Westerberg #include <sys/resource.h>
1231e31b8aSbellard #include <stdlib.h>
1331e31b8aSbellard #include <string.h>
14edf8e2afSMika Westerberg #include <time.h>
1531e31b8aSbellard 
163ef693a0Sbellard #include "qemu.h"
17689f936fSbellard #include "disas.h"
1831e31b8aSbellard 
19e58ffeb3Smalc #ifdef _ARCH_PPC64
20a6cc84f4Smalc #undef ARCH_DLINFO
21a6cc84f4Smalc #undef ELF_PLATFORM
22a6cc84f4Smalc #undef ELF_HWCAP
23a6cc84f4Smalc #undef ELF_CLASS
24a6cc84f4Smalc #undef ELF_DATA
25a6cc84f4Smalc #undef ELF_ARCH
26a6cc84f4Smalc #endif
27a6cc84f4Smalc 
28edf8e2afSMika Westerberg #define ELF_OSABI   ELFOSABI_SYSV
29edf8e2afSMika Westerberg 
30cb33da57Sblueswir1 /* from personality.h */
31cb33da57Sblueswir1 
32cb33da57Sblueswir1 /*
33cb33da57Sblueswir1  * Flags for bug emulation.
34cb33da57Sblueswir1  *
35cb33da57Sblueswir1  * These occupy the top three bytes.
36cb33da57Sblueswir1  */
37cb33da57Sblueswir1 enum {
38cb33da57Sblueswir1 	ADDR_NO_RANDOMIZE = 	0x0040000,	/* disable randomization of VA space */
39cb33da57Sblueswir1 	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
40cb33da57Sblueswir1 						 * (signal handling)
41cb33da57Sblueswir1 						 */
42cb33da57Sblueswir1 	MMAP_PAGE_ZERO =	0x0100000,
43cb33da57Sblueswir1 	ADDR_COMPAT_LAYOUT =	0x0200000,
44cb33da57Sblueswir1 	READ_IMPLIES_EXEC =	0x0400000,
45cb33da57Sblueswir1 	ADDR_LIMIT_32BIT =	0x0800000,
46cb33da57Sblueswir1 	SHORT_INODE =		0x1000000,
47cb33da57Sblueswir1 	WHOLE_SECONDS =		0x2000000,
48cb33da57Sblueswir1 	STICKY_TIMEOUTS	=	0x4000000,
49cb33da57Sblueswir1 	ADDR_LIMIT_3GB = 	0x8000000,
50cb33da57Sblueswir1 };
51cb33da57Sblueswir1 
52cb33da57Sblueswir1 /*
53cb33da57Sblueswir1  * Personality types.
54cb33da57Sblueswir1  *
55cb33da57Sblueswir1  * These go in the low byte.  Avoid using the top bit, it will
56cb33da57Sblueswir1  * conflict with error returns.
57cb33da57Sblueswir1  */
58cb33da57Sblueswir1 enum {
59cb33da57Sblueswir1 	PER_LINUX =		0x0000,
60cb33da57Sblueswir1 	PER_LINUX_32BIT =	0x0000 | ADDR_LIMIT_32BIT,
61cb33da57Sblueswir1 	PER_LINUX_FDPIC =	0x0000 | FDPIC_FUNCPTRS,
62cb33da57Sblueswir1 	PER_SVR4 =		0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
63cb33da57Sblueswir1 	PER_SVR3 =		0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
64cb33da57Sblueswir1 	PER_SCOSVR3 =		0x0003 | STICKY_TIMEOUTS |
65cb33da57Sblueswir1 					 WHOLE_SECONDS | SHORT_INODE,
66cb33da57Sblueswir1 	PER_OSR5 =		0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
67cb33da57Sblueswir1 	PER_WYSEV386 =		0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
68cb33da57Sblueswir1 	PER_ISCR4 =		0x0005 | STICKY_TIMEOUTS,
69cb33da57Sblueswir1 	PER_BSD =		0x0006,
70cb33da57Sblueswir1 	PER_SUNOS =		0x0006 | STICKY_TIMEOUTS,
71cb33da57Sblueswir1 	PER_XENIX =		0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
72cb33da57Sblueswir1 	PER_LINUX32 =		0x0008,
73cb33da57Sblueswir1 	PER_LINUX32_3GB =	0x0008 | ADDR_LIMIT_3GB,
74cb33da57Sblueswir1 	PER_IRIX32 =		0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
75cb33da57Sblueswir1 	PER_IRIXN32 =		0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
76cb33da57Sblueswir1 	PER_IRIX64 =		0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
77cb33da57Sblueswir1 	PER_RISCOS =		0x000c,
78cb33da57Sblueswir1 	PER_SOLARIS =		0x000d | STICKY_TIMEOUTS,
79cb33da57Sblueswir1 	PER_UW7 =		0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
80cb33da57Sblueswir1 	PER_OSF4 =		0x000f,			 /* OSF/1 v4 */
81cb33da57Sblueswir1 	PER_HPUX =		0x0010,
82cb33da57Sblueswir1 	PER_MASK =		0x00ff,
83cb33da57Sblueswir1 };
84cb33da57Sblueswir1 
85cb33da57Sblueswir1 /*
86cb33da57Sblueswir1  * Return the base personality without flags.
87cb33da57Sblueswir1  */
88cb33da57Sblueswir1 #define personality(pers)	(pers & PER_MASK)
89cb33da57Sblueswir1 
9083fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */
9183fb7adfSbellard #ifndef MAP_DENYWRITE
9283fb7adfSbellard #define MAP_DENYWRITE 0
9383fb7adfSbellard #endif
9483fb7adfSbellard 
9583fb7adfSbellard /* should probably go in elf.h */
9683fb7adfSbellard #ifndef ELIBBAD
9783fb7adfSbellard #define ELIBBAD 80
9883fb7adfSbellard #endif
9983fb7adfSbellard 
10030ac07d4Sbellard #ifdef TARGET_I386
10130ac07d4Sbellard 
10215338fd7Sbellard #define ELF_PLATFORM get_elf_platform()
10315338fd7Sbellard 
10415338fd7Sbellard static const char *get_elf_platform(void)
10515338fd7Sbellard {
10615338fd7Sbellard     static char elf_platform[] = "i386";
107d5975363Spbrook     int family = (thread_env->cpuid_version >> 8) & 0xff;
10815338fd7Sbellard     if (family > 6)
10915338fd7Sbellard         family = 6;
11015338fd7Sbellard     if (family >= 3)
11115338fd7Sbellard         elf_platform[1] = '0' + family;
11215338fd7Sbellard     return elf_platform;
11315338fd7Sbellard }
11415338fd7Sbellard 
11515338fd7Sbellard #define ELF_HWCAP get_elf_hwcap()
11615338fd7Sbellard 
11715338fd7Sbellard static uint32_t get_elf_hwcap(void)
11815338fd7Sbellard {
119d5975363Spbrook   return thread_env->cpuid_features;
12015338fd7Sbellard }
12115338fd7Sbellard 
12284409ddbSj_mayer #ifdef TARGET_X86_64
12384409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL
12484409ddbSj_mayer #define elf_check_arch(x) ( ((x) == ELF_ARCH) )
12584409ddbSj_mayer 
12684409ddbSj_mayer #define ELF_CLASS      ELFCLASS64
12784409ddbSj_mayer #define ELF_DATA       ELFDATA2LSB
12884409ddbSj_mayer #define ELF_ARCH       EM_X86_64
12984409ddbSj_mayer 
13084409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
13184409ddbSj_mayer {
13284409ddbSj_mayer     regs->rax = 0;
13384409ddbSj_mayer     regs->rsp = infop->start_stack;
13484409ddbSj_mayer     regs->rip = infop->entry;
13584409ddbSj_mayer }
13684409ddbSj_mayer 
137a2547a13SLaurent Desnogues typedef target_ulong    target_elf_greg_t;
1389edc5d79SMika Westerberg typedef uint32_t        target_uid_t;
1399edc5d79SMika Westerberg typedef uint32_t        target_gid_t;
1409edc5d79SMika Westerberg typedef int32_t         target_pid_t;
1419edc5d79SMika Westerberg 
1429edc5d79SMika Westerberg #define ELF_NREG    27
143a2547a13SLaurent Desnogues typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
1449edc5d79SMika Westerberg 
1459edc5d79SMika Westerberg /*
1469edc5d79SMika Westerberg  * Note that ELF_NREG should be 29 as there should be place for
1479edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
1489edc5d79SMika Westerberg  * those.
1499edc5d79SMika Westerberg  *
1509edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
1519edc5d79SMika Westerberg  */
152a2547a13SLaurent Desnogues static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
1539edc5d79SMika Westerberg {
1549edc5d79SMika Westerberg     (*regs)[0] = env->regs[15];
1559edc5d79SMika Westerberg     (*regs)[1] = env->regs[14];
1569edc5d79SMika Westerberg     (*regs)[2] = env->regs[13];
1579edc5d79SMika Westerberg     (*regs)[3] = env->regs[12];
1589edc5d79SMika Westerberg     (*regs)[4] = env->regs[R_EBP];
1599edc5d79SMika Westerberg     (*regs)[5] = env->regs[R_EBX];
1609edc5d79SMika Westerberg     (*regs)[6] = env->regs[11];
1619edc5d79SMika Westerberg     (*regs)[7] = env->regs[10];
1629edc5d79SMika Westerberg     (*regs)[8] = env->regs[9];
1639edc5d79SMika Westerberg     (*regs)[9] = env->regs[8];
1649edc5d79SMika Westerberg     (*regs)[10] = env->regs[R_EAX];
1659edc5d79SMika Westerberg     (*regs)[11] = env->regs[R_ECX];
1669edc5d79SMika Westerberg     (*regs)[12] = env->regs[R_EDX];
1679edc5d79SMika Westerberg     (*regs)[13] = env->regs[R_ESI];
1689edc5d79SMika Westerberg     (*regs)[14] = env->regs[R_EDI];
1699edc5d79SMika Westerberg     (*regs)[15] = env->regs[R_EAX]; /* XXX */
1709edc5d79SMika Westerberg     (*regs)[16] = env->eip;
1719edc5d79SMika Westerberg     (*regs)[17] = env->segs[R_CS].selector & 0xffff;
1729edc5d79SMika Westerberg     (*regs)[18] = env->eflags;
1739edc5d79SMika Westerberg     (*regs)[19] = env->regs[R_ESP];
1749edc5d79SMika Westerberg     (*regs)[20] = env->segs[R_SS].selector & 0xffff;
1759edc5d79SMika Westerberg     (*regs)[21] = env->segs[R_FS].selector & 0xffff;
1769edc5d79SMika Westerberg     (*regs)[22] = env->segs[R_GS].selector & 0xffff;
1779edc5d79SMika Westerberg     (*regs)[23] = env->segs[R_DS].selector & 0xffff;
1789edc5d79SMika Westerberg     (*regs)[24] = env->segs[R_ES].selector & 0xffff;
1799edc5d79SMika Westerberg     (*regs)[25] = env->segs[R_FS].selector & 0xffff;
1809edc5d79SMika Westerberg     (*regs)[26] = env->segs[R_GS].selector & 0xffff;
1819edc5d79SMika Westerberg }
1829edc5d79SMika Westerberg 
18384409ddbSj_mayer #else
18484409ddbSj_mayer 
18530ac07d4Sbellard #define ELF_START_MMAP 0x80000000
18630ac07d4Sbellard 
18730ac07d4Sbellard /*
18830ac07d4Sbellard  * This is used to ensure we don't load something for the wrong architecture.
18930ac07d4Sbellard  */
19030ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
19130ac07d4Sbellard 
19230ac07d4Sbellard /*
19330ac07d4Sbellard  * These are used to set parameters in the core dumps.
19430ac07d4Sbellard  */
19530ac07d4Sbellard #define ELF_CLASS	ELFCLASS32
19630ac07d4Sbellard #define ELF_DATA	ELFDATA2LSB
19730ac07d4Sbellard #define ELF_ARCH	EM_386
19830ac07d4Sbellard 
199e5fe0c52Spbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
200e5fe0c52Spbrook {
201e5fe0c52Spbrook     regs->esp = infop->start_stack;
202e5fe0c52Spbrook     regs->eip = infop->entry;
203e5fe0c52Spbrook 
20430ac07d4Sbellard     /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
20530ac07d4Sbellard        starts %edx contains a pointer to a function which might be
20630ac07d4Sbellard        registered using `atexit'.  This provides a mean for the
20730ac07d4Sbellard        dynamic linker to call DT_FINI functions for shared libraries
20830ac07d4Sbellard        that have been loaded before the code runs.
20930ac07d4Sbellard 
21030ac07d4Sbellard        A value of 0 tells we have no such handler.  */
211e5fe0c52Spbrook     regs->edx = 0;
212b346ff46Sbellard }
2139edc5d79SMika Westerberg 
214a2547a13SLaurent Desnogues typedef target_ulong    target_elf_greg_t;
2159edc5d79SMika Westerberg typedef uint16_t        target_uid_t;
2169edc5d79SMika Westerberg typedef uint16_t        target_gid_t;
2179edc5d79SMika Westerberg typedef int32_t         target_pid_t;
2189edc5d79SMika Westerberg 
2199edc5d79SMika Westerberg #define ELF_NREG    17
220a2547a13SLaurent Desnogues typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
2219edc5d79SMika Westerberg 
2229edc5d79SMika Westerberg /*
2239edc5d79SMika Westerberg  * Note that ELF_NREG should be 19 as there should be place for
2249edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
2259edc5d79SMika Westerberg  * those.
2269edc5d79SMika Westerberg  *
2279edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
2289edc5d79SMika Westerberg  */
229a2547a13SLaurent Desnogues static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
2309edc5d79SMika Westerberg {
2319edc5d79SMika Westerberg     (*regs)[0] = env->regs[R_EBX];
2329edc5d79SMika Westerberg     (*regs)[1] = env->regs[R_ECX];
2339edc5d79SMika Westerberg     (*regs)[2] = env->regs[R_EDX];
2349edc5d79SMika Westerberg     (*regs)[3] = env->regs[R_ESI];
2359edc5d79SMika Westerberg     (*regs)[4] = env->regs[R_EDI];
2369edc5d79SMika Westerberg     (*regs)[5] = env->regs[R_EBP];
2379edc5d79SMika Westerberg     (*regs)[6] = env->regs[R_EAX];
2389edc5d79SMika Westerberg     (*regs)[7] = env->segs[R_DS].selector & 0xffff;
2399edc5d79SMika Westerberg     (*regs)[8] = env->segs[R_ES].selector & 0xffff;
2409edc5d79SMika Westerberg     (*regs)[9] = env->segs[R_FS].selector & 0xffff;
2419edc5d79SMika Westerberg     (*regs)[10] = env->segs[R_GS].selector & 0xffff;
2429edc5d79SMika Westerberg     (*regs)[11] = env->regs[R_EAX]; /* XXX */
2439edc5d79SMika Westerberg     (*regs)[12] = env->eip;
2449edc5d79SMika Westerberg     (*regs)[13] = env->segs[R_CS].selector & 0xffff;
2459edc5d79SMika Westerberg     (*regs)[14] = env->eflags;
2469edc5d79SMika Westerberg     (*regs)[15] = env->regs[R_ESP];
2479edc5d79SMika Westerberg     (*regs)[16] = env->segs[R_SS].selector & 0xffff;
2489edc5d79SMika Westerberg }
24984409ddbSj_mayer #endif
250b346ff46Sbellard 
2519edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP
252b346ff46Sbellard #define ELF_EXEC_PAGESIZE	4096
253b346ff46Sbellard 
254b346ff46Sbellard #endif
255b346ff46Sbellard 
256b346ff46Sbellard #ifdef TARGET_ARM
257b346ff46Sbellard 
258b346ff46Sbellard #define ELF_START_MMAP 0x80000000
259b346ff46Sbellard 
260b346ff46Sbellard #define elf_check_arch(x) ( (x) == EM_ARM )
261b346ff46Sbellard 
262b346ff46Sbellard #define ELF_CLASS	ELFCLASS32
263b346ff46Sbellard #ifdef TARGET_WORDS_BIGENDIAN
264b346ff46Sbellard #define ELF_DATA	ELFDATA2MSB
265b346ff46Sbellard #else
266b346ff46Sbellard #define ELF_DATA	ELFDATA2LSB
267b346ff46Sbellard #endif
268b346ff46Sbellard #define ELF_ARCH	EM_ARM
269b346ff46Sbellard 
270b346ff46Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
271b346ff46Sbellard {
272992f48a0Sblueswir1     abi_long stack = infop->start_stack;
273b346ff46Sbellard     memset(regs, 0, sizeof(*regs));
274b346ff46Sbellard     regs->ARM_cpsr = 0x10;
2750240ded8Spbrook     if (infop->entry & 1)
2760240ded8Spbrook       regs->ARM_cpsr |= CPSR_T;
2770240ded8Spbrook     regs->ARM_pc = infop->entry & 0xfffffffe;
278b346ff46Sbellard     regs->ARM_sp = infop->start_stack;
2792f619698Sbellard     /* FIXME - what to for failure of get_user()? */
2802f619698Sbellard     get_user_ual(regs->ARM_r2, stack + 8); /* envp */
2812f619698Sbellard     get_user_ual(regs->ARM_r1, stack + 4); /* envp */
282a1516e92Sbellard     /* XXX: it seems that r0 is zeroed after ! */
283e5fe0c52Spbrook     regs->ARM_r0 = 0;
284e5fe0c52Spbrook     /* For uClinux PIC binaries.  */
285863cf0b7Sj_mayer     /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
286e5fe0c52Spbrook     regs->ARM_r10 = infop->start_data;
287b346ff46Sbellard }
288b346ff46Sbellard 
289a2547a13SLaurent Desnogues typedef uint32_t target_elf_greg_t;
290edf8e2afSMika Westerberg typedef uint16_t target_uid_t;
291edf8e2afSMika Westerberg typedef uint16_t target_gid_t;
292edf8e2afSMika Westerberg typedef int32_t  target_pid_t;
293edf8e2afSMika Westerberg 
294edf8e2afSMika Westerberg #define ELF_NREG    18
295a2547a13SLaurent Desnogues typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
296edf8e2afSMika Westerberg 
297a2547a13SLaurent Desnogues static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
298edf8e2afSMika Westerberg {
299edf8e2afSMika Westerberg     (*regs)[0] = env->regs[0];
300edf8e2afSMika Westerberg     (*regs)[1] = env->regs[1];
301edf8e2afSMika Westerberg     (*regs)[2] = env->regs[2];
302edf8e2afSMika Westerberg     (*regs)[3] = env->regs[3];
303edf8e2afSMika Westerberg     (*regs)[4] = env->regs[4];
304edf8e2afSMika Westerberg     (*regs)[5] = env->regs[5];
305edf8e2afSMika Westerberg     (*regs)[6] = env->regs[6];
306edf8e2afSMika Westerberg     (*regs)[7] = env->regs[7];
307edf8e2afSMika Westerberg     (*regs)[8] = env->regs[8];
308edf8e2afSMika Westerberg     (*regs)[9] = env->regs[9];
309edf8e2afSMika Westerberg     (*regs)[10] = env->regs[10];
310edf8e2afSMika Westerberg     (*regs)[11] = env->regs[11];
311edf8e2afSMika Westerberg     (*regs)[12] = env->regs[12];
312edf8e2afSMika Westerberg     (*regs)[13] = env->regs[13];
313edf8e2afSMika Westerberg     (*regs)[14] = env->regs[14];
314edf8e2afSMika Westerberg     (*regs)[15] = env->regs[15];
315edf8e2afSMika Westerberg 
316edf8e2afSMika Westerberg     (*regs)[16] = cpsr_read((CPUState *)env);
317edf8e2afSMika Westerberg     (*regs)[17] = env->regs[0]; /* XXX */
318edf8e2afSMika Westerberg }
319edf8e2afSMika Westerberg 
32030ac07d4Sbellard #define USE_ELF_CORE_DUMP
32130ac07d4Sbellard #define ELF_EXEC_PAGESIZE	4096
32230ac07d4Sbellard 
323afce2927Sbellard enum
324afce2927Sbellard {
325afce2927Sbellard   ARM_HWCAP_ARM_SWP       = 1 << 0,
326afce2927Sbellard   ARM_HWCAP_ARM_HALF      = 1 << 1,
327afce2927Sbellard   ARM_HWCAP_ARM_THUMB     = 1 << 2,
328afce2927Sbellard   ARM_HWCAP_ARM_26BIT     = 1 << 3,
329afce2927Sbellard   ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
330afce2927Sbellard   ARM_HWCAP_ARM_FPA       = 1 << 5,
331afce2927Sbellard   ARM_HWCAP_ARM_VFP       = 1 << 6,
332afce2927Sbellard   ARM_HWCAP_ARM_EDSP      = 1 << 7,
333afce2927Sbellard };
334afce2927Sbellard 
33515338fd7Sbellard #define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF              \
336afce2927Sbellard                     | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT     \
337afce2927Sbellard                     | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP)
338afce2927Sbellard 
33930ac07d4Sbellard #endif
34030ac07d4Sbellard 
341853d6f7aSbellard #ifdef TARGET_SPARC
342a315a145Sbellard #ifdef TARGET_SPARC64
343853d6f7aSbellard 
344853d6f7aSbellard #define ELF_START_MMAP 0x80000000
345853d6f7aSbellard 
346992f48a0Sblueswir1 #ifndef TARGET_ABI32
347cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
348992f48a0Sblueswir1 #else
349992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
350992f48a0Sblueswir1 #endif
351853d6f7aSbellard 
352a315a145Sbellard #define ELF_CLASS   ELFCLASS64
353a315a145Sbellard #define ELF_DATA    ELFDATA2MSB
3545ef54116Sbellard #define ELF_ARCH    EM_SPARCV9
3555ef54116Sbellard 
3565ef54116Sbellard #define STACK_BIAS		2047
357a315a145Sbellard 
358a315a145Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
359a315a145Sbellard {
360992f48a0Sblueswir1 #ifndef TARGET_ABI32
361a315a145Sbellard     regs->tstate = 0;
362992f48a0Sblueswir1 #endif
363a315a145Sbellard     regs->pc = infop->entry;
364a315a145Sbellard     regs->npc = regs->pc + 4;
365a315a145Sbellard     regs->y = 0;
366992f48a0Sblueswir1 #ifdef TARGET_ABI32
367992f48a0Sblueswir1     regs->u_regs[14] = infop->start_stack - 16 * 4;
368992f48a0Sblueswir1 #else
369cb33da57Sblueswir1     if (personality(infop->personality) == PER_LINUX32)
370cb33da57Sblueswir1         regs->u_regs[14] = infop->start_stack - 16 * 4;
371cb33da57Sblueswir1     else
3725ef54116Sbellard         regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
373992f48a0Sblueswir1 #endif
374a315a145Sbellard }
375a315a145Sbellard 
376a315a145Sbellard #else
377a315a145Sbellard #define ELF_START_MMAP 0x80000000
378a315a145Sbellard 
379a315a145Sbellard #define elf_check_arch(x) ( (x) == EM_SPARC )
380a315a145Sbellard 
381853d6f7aSbellard #define ELF_CLASS   ELFCLASS32
382853d6f7aSbellard #define ELF_DATA    ELFDATA2MSB
383853d6f7aSbellard #define ELF_ARCH    EM_SPARC
384853d6f7aSbellard 
385853d6f7aSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
386853d6f7aSbellard {
387f5155289Sbellard     regs->psr = 0;
388f5155289Sbellard     regs->pc = infop->entry;
389f5155289Sbellard     regs->npc = regs->pc + 4;
390f5155289Sbellard     regs->y = 0;
391f5155289Sbellard     regs->u_regs[14] = infop->start_stack - 16 * 4;
392853d6f7aSbellard }
393853d6f7aSbellard 
394853d6f7aSbellard #endif
395a315a145Sbellard #endif
396853d6f7aSbellard 
39767867308Sbellard #ifdef TARGET_PPC
39867867308Sbellard 
39967867308Sbellard #define ELF_START_MMAP 0x80000000
40067867308Sbellard 
401e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
40284409ddbSj_mayer 
40384409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 )
40484409ddbSj_mayer 
40584409ddbSj_mayer #define ELF_CLASS	ELFCLASS64
40684409ddbSj_mayer 
40784409ddbSj_mayer #else
40884409ddbSj_mayer 
40967867308Sbellard #define elf_check_arch(x) ( (x) == EM_PPC )
41067867308Sbellard 
41167867308Sbellard #define ELF_CLASS	ELFCLASS32
41284409ddbSj_mayer 
41384409ddbSj_mayer #endif
41484409ddbSj_mayer 
41567867308Sbellard #ifdef TARGET_WORDS_BIGENDIAN
41667867308Sbellard #define ELF_DATA	ELFDATA2MSB
41767867308Sbellard #else
41867867308Sbellard #define ELF_DATA	ELFDATA2LSB
41967867308Sbellard #endif
42067867308Sbellard #define ELF_ARCH	EM_PPC
42167867308Sbellard 
422df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
423df84e4f3SNathan Froyd    See arch/powerpc/include/asm/cputable.h.  */
424df84e4f3SNathan Froyd enum {
425*3efa9a67Smalc     QEMU_PPC_FEATURE_32 = 0x80000000,
426*3efa9a67Smalc     QEMU_PPC_FEATURE_64 = 0x40000000,
427*3efa9a67Smalc     QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
428*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
429*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
430*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
431*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
432*3efa9a67Smalc     QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
433*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
434*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
435*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
436*3efa9a67Smalc     QEMU_PPC_FEATURE_NO_TB = 0x00100000,
437*3efa9a67Smalc     QEMU_PPC_FEATURE_POWER4 = 0x00080000,
438*3efa9a67Smalc     QEMU_PPC_FEATURE_POWER5 = 0x00040000,
439*3efa9a67Smalc     QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
440*3efa9a67Smalc     QEMU_PPC_FEATURE_CELL = 0x00010000,
441*3efa9a67Smalc     QEMU_PPC_FEATURE_BOOKE = 0x00008000,
442*3efa9a67Smalc     QEMU_PPC_FEATURE_SMT = 0x00004000,
443*3efa9a67Smalc     QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
444*3efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
445*3efa9a67Smalc     QEMU_PPC_FEATURE_PA6T = 0x00000800,
446*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
447*3efa9a67Smalc     QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
448*3efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
449*3efa9a67Smalc     QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
450*3efa9a67Smalc     QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
451df84e4f3SNathan Froyd 
452*3efa9a67Smalc     QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
453*3efa9a67Smalc     QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
454df84e4f3SNathan Froyd };
455df84e4f3SNathan Froyd 
456df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap()
457df84e4f3SNathan Froyd 
458df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void)
459df84e4f3SNathan Froyd {
460df84e4f3SNathan Froyd     CPUState *e = thread_env;
461df84e4f3SNathan Froyd     uint32_t features = 0;
462df84e4f3SNathan Froyd 
463df84e4f3SNathan Froyd     /* We don't have to be terribly complete here; the high points are
464df84e4f3SNathan Froyd        Altivec/FP/SPE support.  Anything else is just a bonus.  */
465df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature)              \
466df84e4f3SNathan Froyd     do {if (e->insns_flags & flag) features |= feature; } while(0)
467*3efa9a67Smalc     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
468*3efa9a67Smalc     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
469*3efa9a67Smalc     GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
470*3efa9a67Smalc     GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
471*3efa9a67Smalc     GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
472*3efa9a67Smalc     GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
473*3efa9a67Smalc     GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
474*3efa9a67Smalc     GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
475df84e4f3SNathan Froyd #undef GET_FEATURE
476df84e4f3SNathan Froyd 
477df84e4f3SNathan Froyd     return features;
478df84e4f3SNathan Froyd }
479df84e4f3SNathan Froyd 
480f5155289Sbellard /*
481f5155289Sbellard  * We need to put in some extra aux table entries to tell glibc what
482f5155289Sbellard  * the cache block size is, so it can use the dcbz instruction safely.
483f5155289Sbellard  */
484f5155289Sbellard #define AT_DCACHEBSIZE          19
485f5155289Sbellard #define AT_ICACHEBSIZE          20
486f5155289Sbellard #define AT_UCACHEBSIZE          21
487f5155289Sbellard /* A special ignored type value for PPC, for glibc compatibility.  */
488f5155289Sbellard #define AT_IGNOREPPC            22
489f5155289Sbellard /*
490f5155289Sbellard  * The requirements here are:
491f5155289Sbellard  * - keep the final alignment of sp (sp & 0xf)
492f5155289Sbellard  * - make sure the 32-bit value at the first 16 byte aligned position of
493f5155289Sbellard  *   AUXV is greater than 16 for glibc compatibility.
494f5155289Sbellard  *   AT_IGNOREPPC is used for that.
495f5155289Sbellard  * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
496f5155289Sbellard  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
497f5155289Sbellard  */
4980bccf03dSbellard #define DLINFO_ARCH_ITEMS       5
499f5155289Sbellard #define ARCH_DLINFO                                                     \
500f5155289Sbellard do {                                                                    \
5010bccf03dSbellard         NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \
5020bccf03dSbellard         NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \
5030bccf03dSbellard         NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \
504f5155289Sbellard         /*                                                              \
505f5155289Sbellard          * Now handle glibc compatibility.                              \
506f5155289Sbellard          */                                                             \
5070bccf03dSbellard 	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
5080bccf03dSbellard 	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
509f5155289Sbellard  } while (0)
510f5155289Sbellard 
51167867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
51267867308Sbellard {
513992f48a0Sblueswir1     abi_ulong pos = infop->start_stack;
514992f48a0Sblueswir1     abi_ulong tmp;
515e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
516992f48a0Sblueswir1     abi_ulong entry, toc;
51784409ddbSj_mayer #endif
518e5fe0c52Spbrook 
51967867308Sbellard     _regs->gpr[1] = infop->start_stack;
520e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
52184409ddbSj_mayer     entry = ldq_raw(infop->entry) + infop->load_addr;
52284409ddbSj_mayer     toc = ldq_raw(infop->entry + 8) + infop->load_addr;
52384409ddbSj_mayer     _regs->gpr[2] = toc;
52484409ddbSj_mayer     infop->entry = entry;
52584409ddbSj_mayer #endif
52667867308Sbellard     _regs->nip = infop->entry;
527e5fe0c52Spbrook     /* Note that isn't exactly what regular kernel does
528e5fe0c52Spbrook      * but this is what the ABI wants and is needed to allow
529e5fe0c52Spbrook      * execution of PPC BSD programs.
530e5fe0c52Spbrook      */
5312f619698Sbellard     /* FIXME - what to for failure of get_user()? */
5322f619698Sbellard     get_user_ual(_regs->gpr[3], pos);
533992f48a0Sblueswir1     pos += sizeof(abi_ulong);
534e5fe0c52Spbrook     _regs->gpr[4] = pos;
535992f48a0Sblueswir1     for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong))
536e5fe0c52Spbrook         tmp = ldl(pos);
537e5fe0c52Spbrook     _regs->gpr[5] = pos;
53867867308Sbellard }
53967867308Sbellard 
54067867308Sbellard #define ELF_EXEC_PAGESIZE	4096
54167867308Sbellard 
54267867308Sbellard #endif
54367867308Sbellard 
544048f6b4dSbellard #ifdef TARGET_MIPS
545048f6b4dSbellard 
546048f6b4dSbellard #define ELF_START_MMAP 0x80000000
547048f6b4dSbellard 
548048f6b4dSbellard #define elf_check_arch(x) ( (x) == EM_MIPS )
549048f6b4dSbellard 
550388bb21aSths #ifdef TARGET_MIPS64
551388bb21aSths #define ELF_CLASS   ELFCLASS64
552388bb21aSths #else
553048f6b4dSbellard #define ELF_CLASS   ELFCLASS32
554388bb21aSths #endif
555048f6b4dSbellard #ifdef TARGET_WORDS_BIGENDIAN
556048f6b4dSbellard #define ELF_DATA	ELFDATA2MSB
557048f6b4dSbellard #else
558048f6b4dSbellard #define ELF_DATA	ELFDATA2LSB
559048f6b4dSbellard #endif
560048f6b4dSbellard #define ELF_ARCH    EM_MIPS
561048f6b4dSbellard 
562048f6b4dSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
563048f6b4dSbellard {
564623a930eSths     regs->cp0_status = 2 << CP0St_KSU;
565048f6b4dSbellard     regs->cp0_epc = infop->entry;
566048f6b4dSbellard     regs->regs[29] = infop->start_stack;
567048f6b4dSbellard }
568048f6b4dSbellard 
569388bb21aSths #define ELF_EXEC_PAGESIZE        4096
570388bb21aSths 
571048f6b4dSbellard #endif /* TARGET_MIPS */
572048f6b4dSbellard 
573b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE
574b779e29eSEdgar E. Iglesias 
575b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000
576b779e29eSEdgar E. Iglesias 
577b779e29eSEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE )
578b779e29eSEdgar E. Iglesias 
579b779e29eSEdgar E. Iglesias #define ELF_CLASS   ELFCLASS32
580b779e29eSEdgar E. Iglesias #define ELF_DATA	ELFDATA2MSB
581b779e29eSEdgar E. Iglesias #define ELF_ARCH    EM_MIPS
582b779e29eSEdgar E. Iglesias 
583b779e29eSEdgar E. Iglesias static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
584b779e29eSEdgar E. Iglesias {
585b779e29eSEdgar E. Iglesias     regs->pc = infop->entry;
586b779e29eSEdgar E. Iglesias     regs->r1 = infop->start_stack;
587b779e29eSEdgar E. Iglesias 
588b779e29eSEdgar E. Iglesias }
589b779e29eSEdgar E. Iglesias 
590b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE        4096
591b779e29eSEdgar E. Iglesias 
592b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */
593b779e29eSEdgar E. Iglesias 
594fdf9b3e8Sbellard #ifdef TARGET_SH4
595fdf9b3e8Sbellard 
596fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000
597fdf9b3e8Sbellard 
598fdf9b3e8Sbellard #define elf_check_arch(x) ( (x) == EM_SH )
599fdf9b3e8Sbellard 
600fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32
601fdf9b3e8Sbellard #define ELF_DATA  ELFDATA2LSB
602fdf9b3e8Sbellard #define ELF_ARCH  EM_SH
603fdf9b3e8Sbellard 
604fdf9b3e8Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
605fdf9b3e8Sbellard {
606fdf9b3e8Sbellard   /* Check other registers XXXXX */
607fdf9b3e8Sbellard   regs->pc = infop->entry;
608072ae847Sths   regs->regs[15] = infop->start_stack;
609fdf9b3e8Sbellard }
610fdf9b3e8Sbellard 
611fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE        4096
612fdf9b3e8Sbellard 
613fdf9b3e8Sbellard #endif
614fdf9b3e8Sbellard 
61548733d19Sths #ifdef TARGET_CRIS
61648733d19Sths 
61748733d19Sths #define ELF_START_MMAP 0x80000000
61848733d19Sths 
61948733d19Sths #define elf_check_arch(x) ( (x) == EM_CRIS )
62048733d19Sths 
62148733d19Sths #define ELF_CLASS ELFCLASS32
62248733d19Sths #define ELF_DATA  ELFDATA2LSB
62348733d19Sths #define ELF_ARCH  EM_CRIS
62448733d19Sths 
62548733d19Sths static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
62648733d19Sths {
62748733d19Sths   regs->erp = infop->entry;
62848733d19Sths }
62948733d19Sths 
63048733d19Sths #define ELF_EXEC_PAGESIZE        8192
63148733d19Sths 
63248733d19Sths #endif
63348733d19Sths 
634e6e5906bSpbrook #ifdef TARGET_M68K
635e6e5906bSpbrook 
636e6e5906bSpbrook #define ELF_START_MMAP 0x80000000
637e6e5906bSpbrook 
638e6e5906bSpbrook #define elf_check_arch(x) ( (x) == EM_68K )
639e6e5906bSpbrook 
640e6e5906bSpbrook #define ELF_CLASS	ELFCLASS32
641e6e5906bSpbrook #define ELF_DATA	ELFDATA2MSB
642e6e5906bSpbrook #define ELF_ARCH	EM_68K
643e6e5906bSpbrook 
644e6e5906bSpbrook /* ??? Does this need to do anything?
645e6e5906bSpbrook #define ELF_PLAT_INIT(_r) */
646e6e5906bSpbrook 
647e6e5906bSpbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
648e6e5906bSpbrook {
649e6e5906bSpbrook     regs->usp = infop->start_stack;
650e6e5906bSpbrook     regs->sr = 0;
651e6e5906bSpbrook     regs->pc = infop->entry;
652e6e5906bSpbrook }
653e6e5906bSpbrook 
654e6e5906bSpbrook #define ELF_EXEC_PAGESIZE	8192
655e6e5906bSpbrook 
656e6e5906bSpbrook #endif
657e6e5906bSpbrook 
6587a3148a9Sj_mayer #ifdef TARGET_ALPHA
6597a3148a9Sj_mayer 
6607a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL)
6617a3148a9Sj_mayer 
6627a3148a9Sj_mayer #define elf_check_arch(x) ( (x) == ELF_ARCH )
6637a3148a9Sj_mayer 
6647a3148a9Sj_mayer #define ELF_CLASS      ELFCLASS64
6657a3148a9Sj_mayer #define ELF_DATA       ELFDATA2MSB
6667a3148a9Sj_mayer #define ELF_ARCH       EM_ALPHA
6677a3148a9Sj_mayer 
6687a3148a9Sj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
6697a3148a9Sj_mayer {
6707a3148a9Sj_mayer     regs->pc = infop->entry;
6717a3148a9Sj_mayer     regs->ps = 8;
6727a3148a9Sj_mayer     regs->usp = infop->start_stack;
6737a3148a9Sj_mayer     regs->unique = infop->start_data; /* ? */
6747a3148a9Sj_mayer     printf("Set unique value to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n",
6757a3148a9Sj_mayer            regs->unique, infop->start_data);
6767a3148a9Sj_mayer }
6777a3148a9Sj_mayer 
6787a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE        8192
6797a3148a9Sj_mayer 
6807a3148a9Sj_mayer #endif /* TARGET_ALPHA */
6817a3148a9Sj_mayer 
68215338fd7Sbellard #ifndef ELF_PLATFORM
68315338fd7Sbellard #define ELF_PLATFORM (NULL)
68415338fd7Sbellard #endif
68515338fd7Sbellard 
68615338fd7Sbellard #ifndef ELF_HWCAP
68715338fd7Sbellard #define ELF_HWCAP 0
68815338fd7Sbellard #endif
68915338fd7Sbellard 
690992f48a0Sblueswir1 #ifdef TARGET_ABI32
691cb33da57Sblueswir1 #undef ELF_CLASS
692992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32
693cb33da57Sblueswir1 #undef bswaptls
694cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr)
695cb33da57Sblueswir1 #endif
696cb33da57Sblueswir1 
69731e31b8aSbellard #include "elf.h"
69809bfb054Sbellard 
69909bfb054Sbellard struct exec
70009bfb054Sbellard {
70109bfb054Sbellard   unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
70209bfb054Sbellard   unsigned int a_text;   /* length of text, in bytes */
70309bfb054Sbellard   unsigned int a_data;   /* length of data, in bytes */
70409bfb054Sbellard   unsigned int a_bss;    /* length of uninitialized data area, in bytes */
70509bfb054Sbellard   unsigned int a_syms;   /* length of symbol table data in file, in bytes */
70609bfb054Sbellard   unsigned int a_entry;  /* start address */
70709bfb054Sbellard   unsigned int a_trsize; /* length of relocation info for text, in bytes */
70809bfb054Sbellard   unsigned int a_drsize; /* length of relocation info for data, in bytes */
70909bfb054Sbellard };
71009bfb054Sbellard 
71109bfb054Sbellard 
71209bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff)
71309bfb054Sbellard #define OMAGIC 0407
71409bfb054Sbellard #define NMAGIC 0410
71509bfb054Sbellard #define ZMAGIC 0413
71609bfb054Sbellard #define QMAGIC 0314
71709bfb054Sbellard 
71809bfb054Sbellard /* max code+data+bss space allocated to elf interpreter */
71909bfb054Sbellard #define INTERP_MAP_SIZE (32 * 1024 * 1024)
72009bfb054Sbellard 
72109bfb054Sbellard /* max code+data+bss+brk space allocated to ET_DYN executables */
72209bfb054Sbellard #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
72309bfb054Sbellard 
72431e31b8aSbellard /* Necessary parameters */
72554936004Sbellard #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
72654936004Sbellard #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
72754936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
72831e31b8aSbellard 
72931e31b8aSbellard #define INTERPRETER_NONE 0
73031e31b8aSbellard #define INTERPRETER_AOUT 1
73131e31b8aSbellard #define INTERPRETER_ELF 2
73231e31b8aSbellard 
73315338fd7Sbellard #define DLINFO_ITEMS 12
73431e31b8aSbellard 
73509bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
73609bfb054Sbellard {
73709bfb054Sbellard 	memcpy(to, from, n);
73809bfb054Sbellard }
73909bfb054Sbellard 
74031e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd);
74131e31b8aSbellard 
74231e31b8aSbellard #ifdef BSWAP_NEEDED
74392a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr)
74431e31b8aSbellard {
74531e31b8aSbellard     bswap16s(&ehdr->e_type);			/* Object file type */
74631e31b8aSbellard     bswap16s(&ehdr->e_machine);		/* Architecture */
74731e31b8aSbellard     bswap32s(&ehdr->e_version);		/* Object file version */
74892a31b1fSbellard     bswaptls(&ehdr->e_entry);		/* Entry point virtual address */
74992a31b1fSbellard     bswaptls(&ehdr->e_phoff);		/* Program header table file offset */
75092a31b1fSbellard     bswaptls(&ehdr->e_shoff);		/* Section header table file offset */
75131e31b8aSbellard     bswap32s(&ehdr->e_flags);		/* Processor-specific flags */
75231e31b8aSbellard     bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */
75331e31b8aSbellard     bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */
75431e31b8aSbellard     bswap16s(&ehdr->e_phnum);		/* Program header table entry count */
75531e31b8aSbellard     bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */
75631e31b8aSbellard     bswap16s(&ehdr->e_shnum);		/* Section header table entry count */
75731e31b8aSbellard     bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */
75831e31b8aSbellard }
75931e31b8aSbellard 
76092a31b1fSbellard static void bswap_phdr(struct elf_phdr *phdr)
76131e31b8aSbellard {
76231e31b8aSbellard     bswap32s(&phdr->p_type);			/* Segment type */
76392a31b1fSbellard     bswaptls(&phdr->p_offset);		/* Segment file offset */
76492a31b1fSbellard     bswaptls(&phdr->p_vaddr);		/* Segment virtual address */
76592a31b1fSbellard     bswaptls(&phdr->p_paddr);		/* Segment physical address */
76692a31b1fSbellard     bswaptls(&phdr->p_filesz);		/* Segment size in file */
76792a31b1fSbellard     bswaptls(&phdr->p_memsz);		/* Segment size in memory */
76831e31b8aSbellard     bswap32s(&phdr->p_flags);		/* Segment flags */
76992a31b1fSbellard     bswaptls(&phdr->p_align);		/* Segment alignment */
77031e31b8aSbellard }
771689f936fSbellard 
77292a31b1fSbellard static void bswap_shdr(struct elf_shdr *shdr)
773689f936fSbellard {
774689f936fSbellard     bswap32s(&shdr->sh_name);
775689f936fSbellard     bswap32s(&shdr->sh_type);
77692a31b1fSbellard     bswaptls(&shdr->sh_flags);
77792a31b1fSbellard     bswaptls(&shdr->sh_addr);
77892a31b1fSbellard     bswaptls(&shdr->sh_offset);
77992a31b1fSbellard     bswaptls(&shdr->sh_size);
780689f936fSbellard     bswap32s(&shdr->sh_link);
781689f936fSbellard     bswap32s(&shdr->sh_info);
78292a31b1fSbellard     bswaptls(&shdr->sh_addralign);
78392a31b1fSbellard     bswaptls(&shdr->sh_entsize);
784689f936fSbellard }
785689f936fSbellard 
7867a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym)
787689f936fSbellard {
788689f936fSbellard     bswap32s(&sym->st_name);
7897a3148a9Sj_mayer     bswaptls(&sym->st_value);
7907a3148a9Sj_mayer     bswaptls(&sym->st_size);
791689f936fSbellard     bswap16s(&sym->st_shndx);
792689f936fSbellard }
79331e31b8aSbellard #endif
79431e31b8aSbellard 
795edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
796edf8e2afSMika Westerberg static int elf_core_dump(int, const CPUState *);
797edf8e2afSMika Westerberg 
798edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
799edf8e2afSMika Westerberg static void bswap_note(struct elf_note *en)
800edf8e2afSMika Westerberg {
801edf8e2afSMika Westerberg     bswaptls(&en->n_namesz);
802edf8e2afSMika Westerberg     bswaptls(&en->n_descsz);
803edf8e2afSMika Westerberg     bswaptls(&en->n_type);
804edf8e2afSMika Westerberg }
805edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
806edf8e2afSMika Westerberg 
807edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
808edf8e2afSMika Westerberg 
80931e31b8aSbellard /*
810e5fe0c52Spbrook  * 'copy_elf_strings()' copies argument/envelope strings from user
81131e31b8aSbellard  * memory to free pages in kernel mem. These are in a format ready
81231e31b8aSbellard  * to be put directly into the top of new user memory.
81331e31b8aSbellard  *
81431e31b8aSbellard  */
815992f48a0Sblueswir1 static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
816992f48a0Sblueswir1                                   abi_ulong p)
81731e31b8aSbellard {
81831e31b8aSbellard     char *tmp, *tmp1, *pag = NULL;
81931e31b8aSbellard     int len, offset = 0;
82031e31b8aSbellard 
82131e31b8aSbellard     if (!p) {
82231e31b8aSbellard 	return 0;       /* bullet-proofing */
82331e31b8aSbellard     }
82431e31b8aSbellard     while (argc-- > 0) {
825edf779ffSbellard         tmp = argv[argc];
826edf779ffSbellard         if (!tmp) {
82731e31b8aSbellard 	    fprintf(stderr, "VFS: argc is wrong");
82831e31b8aSbellard 	    exit(-1);
82931e31b8aSbellard 	}
830edf779ffSbellard         tmp1 = tmp;
831edf779ffSbellard 	while (*tmp++);
83231e31b8aSbellard 	len = tmp - tmp1;
83331e31b8aSbellard 	if (p < len) {  /* this shouldn't happen - 128kB */
83431e31b8aSbellard 		return 0;
83531e31b8aSbellard 	}
83631e31b8aSbellard 	while (len) {
83731e31b8aSbellard 	    --p; --tmp; --len;
83831e31b8aSbellard 	    if (--offset < 0) {
83954936004Sbellard 		offset = p % TARGET_PAGE_SIZE;
84044a91caeSbellard                 pag = (char *)page[p/TARGET_PAGE_SIZE];
84144a91caeSbellard                 if (!pag) {
84253a5960aSpbrook                     pag = (char *)malloc(TARGET_PAGE_SIZE);
8434118a970Sj_mayer                     memset(pag, 0, TARGET_PAGE_SIZE);
84453a5960aSpbrook                     page[p/TARGET_PAGE_SIZE] = pag;
84544a91caeSbellard                     if (!pag)
84631e31b8aSbellard                         return 0;
84731e31b8aSbellard 		}
84831e31b8aSbellard 	    }
84931e31b8aSbellard 	    if (len == 0 || offset == 0) {
850edf779ffSbellard 	        *(pag + offset) = *tmp;
85131e31b8aSbellard 	    }
85231e31b8aSbellard 	    else {
85331e31b8aSbellard 	      int bytes_to_copy = (len > offset) ? offset : len;
85431e31b8aSbellard 	      tmp -= bytes_to_copy;
85531e31b8aSbellard 	      p -= bytes_to_copy;
85631e31b8aSbellard 	      offset -= bytes_to_copy;
85731e31b8aSbellard 	      len -= bytes_to_copy;
85831e31b8aSbellard 	      memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
85931e31b8aSbellard 	    }
86031e31b8aSbellard 	}
86131e31b8aSbellard     }
86231e31b8aSbellard     return p;
86331e31b8aSbellard }
86431e31b8aSbellard 
865992f48a0Sblueswir1 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
86631e31b8aSbellard                                  struct image_info *info)
86731e31b8aSbellard {
868992f48a0Sblueswir1     abi_ulong stack_base, size, error;
86931e31b8aSbellard     int i;
87031e31b8aSbellard 
87131e31b8aSbellard     /* Create enough stack to hold everything.  If we don't use
87231e31b8aSbellard      * it for args, we'll use it for something else...
87331e31b8aSbellard      */
87409bfb054Sbellard     size = x86_stack_size;
87554936004Sbellard     if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
87654936004Sbellard         size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
87754936004Sbellard     error = target_mmap(0,
87883fb7adfSbellard                         size + qemu_host_page_size,
87931e31b8aSbellard                         PROT_READ | PROT_WRITE,
88009bfb054Sbellard                         MAP_PRIVATE | MAP_ANONYMOUS,
88109bfb054Sbellard                         -1, 0);
88209bfb054Sbellard     if (error == -1) {
88331e31b8aSbellard         perror("stk mmap");
88431e31b8aSbellard         exit(-1);
88531e31b8aSbellard     }
88609bfb054Sbellard     /* we reserve one extra page at the top of the stack as guard */
88783fb7adfSbellard     target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
88831e31b8aSbellard 
88954936004Sbellard     stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
89009bfb054Sbellard     p += stack_base;
89109bfb054Sbellard 
89231e31b8aSbellard     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
89331e31b8aSbellard 	if (bprm->page[i]) {
89431e31b8aSbellard 	    info->rss++;
895579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
89653a5960aSpbrook 	    memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
89753a5960aSpbrook 	    free(bprm->page[i]);
89831e31b8aSbellard 	}
89954936004Sbellard         stack_base += TARGET_PAGE_SIZE;
90031e31b8aSbellard     }
90131e31b8aSbellard     return p;
90231e31b8aSbellard }
90331e31b8aSbellard 
904992f48a0Sblueswir1 static void set_brk(abi_ulong start, abi_ulong end)
90531e31b8aSbellard {
90631e31b8aSbellard 	/* page-align the start and end addresses... */
90754936004Sbellard         start = HOST_PAGE_ALIGN(start);
90854936004Sbellard         end = HOST_PAGE_ALIGN(end);
90931e31b8aSbellard         if (end <= start)
91031e31b8aSbellard                 return;
91154936004Sbellard         if(target_mmap(start, end - start,
91231e31b8aSbellard                        PROT_READ | PROT_WRITE | PROT_EXEC,
91331e31b8aSbellard                        MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
91431e31b8aSbellard 	    perror("cannot mmap brk");
91531e31b8aSbellard 	    exit(-1);
91631e31b8aSbellard 	}
91731e31b8aSbellard }
91831e31b8aSbellard 
91931e31b8aSbellard 
920853d6f7aSbellard /* We need to explicitly zero any fractional pages after the data
921853d6f7aSbellard    section (i.e. bss).  This would contain the junk from the file that
922853d6f7aSbellard    should not be in memory. */
923992f48a0Sblueswir1 static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
92431e31b8aSbellard {
925992f48a0Sblueswir1         abi_ulong nbyte;
92631e31b8aSbellard 
927768a4a36Sths 	if (elf_bss >= last_bss)
928768a4a36Sths 		return;
929768a4a36Sths 
930853d6f7aSbellard         /* XXX: this is really a hack : if the real host page size is
931853d6f7aSbellard            smaller than the target page size, some pages after the end
932853d6f7aSbellard            of the file may not be mapped. A better fix would be to
933853d6f7aSbellard            patch target_mmap(), but it is more complicated as the file
934853d6f7aSbellard            size must be known */
93583fb7adfSbellard         if (qemu_real_host_page_size < qemu_host_page_size) {
936992f48a0Sblueswir1             abi_ulong end_addr, end_addr1;
93783fb7adfSbellard             end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
93883fb7adfSbellard                 ~(qemu_real_host_page_size - 1);
939853d6f7aSbellard             end_addr = HOST_PAGE_ALIGN(elf_bss);
940853d6f7aSbellard             if (end_addr1 < end_addr) {
941863cf0b7Sj_mayer                 mmap((void *)g2h(end_addr1), end_addr - end_addr1,
942853d6f7aSbellard                      PROT_READ|PROT_WRITE|PROT_EXEC,
943853d6f7aSbellard                      MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
944853d6f7aSbellard             }
945853d6f7aSbellard         }
946853d6f7aSbellard 
94783fb7adfSbellard         nbyte = elf_bss & (qemu_host_page_size-1);
94831e31b8aSbellard         if (nbyte) {
94983fb7adfSbellard 	    nbyte = qemu_host_page_size - nbyte;
95031e31b8aSbellard 	    do {
9512f619698Sbellard                 /* FIXME - what to do if put_user() fails? */
9522f619698Sbellard 		put_user_u8(0, elf_bss);
95353a5960aSpbrook                 elf_bss++;
95431e31b8aSbellard 	    } while (--nbyte);
95531e31b8aSbellard         }
95631e31b8aSbellard }
95731e31b8aSbellard 
95853a5960aSpbrook 
959992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
96031e31b8aSbellard                                    struct elfhdr * exec,
961992f48a0Sblueswir1                                    abi_ulong load_addr,
962992f48a0Sblueswir1                                    abi_ulong load_bias,
963992f48a0Sblueswir1                                    abi_ulong interp_load_addr, int ibcs,
96431e31b8aSbellard                                    struct image_info *info)
96531e31b8aSbellard {
966992f48a0Sblueswir1         abi_ulong sp;
96753a5960aSpbrook         int size;
968992f48a0Sblueswir1         abi_ulong u_platform;
96915338fd7Sbellard         const char *k_platform;
970863cf0b7Sj_mayer         const int n = sizeof(elf_addr_t);
97131e31b8aSbellard 
97253a5960aSpbrook         sp = p;
97353a5960aSpbrook         u_platform = 0;
97415338fd7Sbellard         k_platform = ELF_PLATFORM;
97515338fd7Sbellard         if (k_platform) {
97615338fd7Sbellard             size_t len = strlen(k_platform) + 1;
97753a5960aSpbrook             sp -= (len + n - 1) & ~(n - 1);
97853a5960aSpbrook             u_platform = sp;
979579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
98053a5960aSpbrook             memcpy_to_target(sp, k_platform, len);
98115338fd7Sbellard         }
98253a5960aSpbrook 	/*
98353a5960aSpbrook 	 * Force 16 byte _final_ alignment here for generality.
98453a5960aSpbrook 	 */
985992f48a0Sblueswir1         sp = sp &~ (abi_ulong)15;
98653a5960aSpbrook         size = (DLINFO_ITEMS + 1) * 2;
98715338fd7Sbellard         if (k_platform)
98853a5960aSpbrook           size += 2;
989f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS
99053a5960aSpbrook 	size += DLINFO_ARCH_ITEMS * 2;
991f5155289Sbellard #endif
99253a5960aSpbrook         size += envc + argc + 2;
99353a5960aSpbrook 	size += (!ibcs ? 3 : 1);	/* argc itself */
99453a5960aSpbrook         size *= n;
99553a5960aSpbrook         if (size & 15)
99653a5960aSpbrook             sp -= 16 - (size & 15);
997f5155289Sbellard 
998863cf0b7Sj_mayer         /* This is correct because Linux defines
999863cf0b7Sj_mayer          * elf_addr_t as Elf32_Off / Elf64_Off
1000863cf0b7Sj_mayer          */
100153a5960aSpbrook #define NEW_AUX_ENT(id, val) do {		\
10022f619698Sbellard             sp -= n; put_user_ual(val, sp);	\
10032f619698Sbellard             sp -= n; put_user_ual(id, sp);	\
100453a5960aSpbrook           } while(0)
10052f619698Sbellard 
10060bccf03dSbellard         NEW_AUX_ENT (AT_NULL, 0);
1007f5155289Sbellard 
10080bccf03dSbellard         /* There must be exactly DLINFO_ITEMS entries here.  */
1009992f48a0Sblueswir1         NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
1010992f48a0Sblueswir1         NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1011992f48a0Sblueswir1         NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1012992f48a0Sblueswir1         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
1013992f48a0Sblueswir1         NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
1014992f48a0Sblueswir1         NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
10150bccf03dSbellard         NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
1016992f48a0Sblueswir1         NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1017992f48a0Sblueswir1         NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1018992f48a0Sblueswir1         NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1019992f48a0Sblueswir1         NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1020992f48a0Sblueswir1         NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1021a07c67dfSpbrook         NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
102215338fd7Sbellard         if (k_platform)
102353a5960aSpbrook             NEW_AUX_ENT(AT_PLATFORM, u_platform);
1024f5155289Sbellard #ifdef ARCH_DLINFO
1025f5155289Sbellard 	/*
1026f5155289Sbellard 	 * ARCH_DLINFO must come last so platform specific code can enforce
1027f5155289Sbellard 	 * special alignment requirements on the AUXV if necessary (eg. PPC).
1028f5155289Sbellard 	 */
1029f5155289Sbellard         ARCH_DLINFO;
1030f5155289Sbellard #endif
1031f5155289Sbellard #undef NEW_AUX_ENT
1032f5155289Sbellard 
1033edf8e2afSMika Westerberg         info->saved_auxv = sp;
1034edf8e2afSMika Westerberg 
1035e5fe0c52Spbrook         sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
103631e31b8aSbellard         return sp;
103731e31b8aSbellard }
103831e31b8aSbellard 
103931e31b8aSbellard 
1040992f48a0Sblueswir1 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
104131e31b8aSbellard                                  int interpreter_fd,
1042992f48a0Sblueswir1                                  abi_ulong *interp_load_addr)
104331e31b8aSbellard {
104431e31b8aSbellard 	struct elf_phdr *elf_phdata  =  NULL;
104531e31b8aSbellard 	struct elf_phdr *eppnt;
1046992f48a0Sblueswir1 	abi_ulong load_addr = 0;
104731e31b8aSbellard 	int load_addr_set = 0;
104831e31b8aSbellard 	int retval;
1049992f48a0Sblueswir1 	abi_ulong last_bss, elf_bss;
1050992f48a0Sblueswir1 	abi_ulong error;
105131e31b8aSbellard 	int i;
105231e31b8aSbellard 
105331e31b8aSbellard 	elf_bss = 0;
105431e31b8aSbellard 	last_bss = 0;
105531e31b8aSbellard 	error = 0;
105631e31b8aSbellard 
1057644c433cSbellard #ifdef BSWAP_NEEDED
1058644c433cSbellard         bswap_ehdr(interp_elf_ex);
1059644c433cSbellard #endif
106031e31b8aSbellard 	/* First of all, some simple consistency checks */
106131e31b8aSbellard 	if ((interp_elf_ex->e_type != ET_EXEC &&
106231e31b8aSbellard              interp_elf_ex->e_type != ET_DYN) ||
106331e31b8aSbellard 	   !elf_check_arch(interp_elf_ex->e_machine)) {
1064992f48a0Sblueswir1 		return ~((abi_ulong)0UL);
106531e31b8aSbellard 	}
106631e31b8aSbellard 
1067644c433cSbellard 
106831e31b8aSbellard 	/* Now read in all of the header information */
106931e31b8aSbellard 
107054936004Sbellard 	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
1071992f48a0Sblueswir1 	    return ~(abi_ulong)0UL;
107231e31b8aSbellard 
107331e31b8aSbellard 	elf_phdata =  (struct elf_phdr *)
107431e31b8aSbellard 		malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
107531e31b8aSbellard 
107631e31b8aSbellard 	if (!elf_phdata)
1077992f48a0Sblueswir1 	  return ~((abi_ulong)0UL);
107831e31b8aSbellard 
107931e31b8aSbellard 	/*
108031e31b8aSbellard 	 * If the size of this structure has changed, then punt, since
108131e31b8aSbellard 	 * we will be doing the wrong thing.
108231e31b8aSbellard 	 */
108309bfb054Sbellard 	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
108431e31b8aSbellard 	    free(elf_phdata);
1085992f48a0Sblueswir1 	    return ~((abi_ulong)0UL);
108631e31b8aSbellard         }
108731e31b8aSbellard 
108831e31b8aSbellard 	retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
108931e31b8aSbellard 	if(retval >= 0) {
109031e31b8aSbellard 	    retval = read(interpreter_fd,
109131e31b8aSbellard 			   (char *) elf_phdata,
109231e31b8aSbellard 			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
109331e31b8aSbellard 	}
109431e31b8aSbellard 	if (retval < 0) {
109531e31b8aSbellard 		perror("load_elf_interp");
109631e31b8aSbellard 		exit(-1);
109731e31b8aSbellard 		free (elf_phdata);
109831e31b8aSbellard 		return retval;
109931e31b8aSbellard  	}
110031e31b8aSbellard #ifdef BSWAP_NEEDED
110131e31b8aSbellard 	eppnt = elf_phdata;
110231e31b8aSbellard 	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
110331e31b8aSbellard             bswap_phdr(eppnt);
110431e31b8aSbellard         }
110531e31b8aSbellard #endif
110609bfb054Sbellard 
110709bfb054Sbellard         if (interp_elf_ex->e_type == ET_DYN) {
1108e91c8a77Sths             /* in order to avoid hardcoding the interpreter load
110909bfb054Sbellard                address in qemu, we allocate a big enough memory zone */
111054936004Sbellard             error = target_mmap(0, INTERP_MAP_SIZE,
111109bfb054Sbellard                                 PROT_NONE, MAP_PRIVATE | MAP_ANON,
111209bfb054Sbellard                                 -1, 0);
111309bfb054Sbellard             if (error == -1) {
111409bfb054Sbellard                 perror("mmap");
111509bfb054Sbellard                 exit(-1);
111609bfb054Sbellard             }
111709bfb054Sbellard             load_addr = error;
111809bfb054Sbellard             load_addr_set = 1;
111909bfb054Sbellard         }
112009bfb054Sbellard 
112131e31b8aSbellard 	eppnt = elf_phdata;
112231e31b8aSbellard 	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
112331e31b8aSbellard 	  if (eppnt->p_type == PT_LOAD) {
112431e31b8aSbellard 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
112531e31b8aSbellard 	    int elf_prot = 0;
1126992f48a0Sblueswir1 	    abi_ulong vaddr = 0;
1127992f48a0Sblueswir1 	    abi_ulong k;
112831e31b8aSbellard 
112931e31b8aSbellard 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
113031e31b8aSbellard 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
113131e31b8aSbellard 	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
113231e31b8aSbellard 	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
113331e31b8aSbellard 	    	elf_type |= MAP_FIXED;
113431e31b8aSbellard 	    	vaddr = eppnt->p_vaddr;
113531e31b8aSbellard 	    }
113654936004Sbellard 	    error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
113754936004Sbellard 		 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
113831e31b8aSbellard 		 elf_prot,
113931e31b8aSbellard 		 elf_type,
114031e31b8aSbellard 		 interpreter_fd,
114154936004Sbellard 		 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
114231e31b8aSbellard 
1143e89f07d3Spbrook 	    if (error == -1) {
114431e31b8aSbellard 	      /* Real error */
114531e31b8aSbellard 	      close(interpreter_fd);
114631e31b8aSbellard 	      free(elf_phdata);
1147992f48a0Sblueswir1 	      return ~((abi_ulong)0UL);
114831e31b8aSbellard 	    }
114931e31b8aSbellard 
115031e31b8aSbellard 	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
115131e31b8aSbellard 	      load_addr = error;
115231e31b8aSbellard 	      load_addr_set = 1;
115331e31b8aSbellard 	    }
115431e31b8aSbellard 
115531e31b8aSbellard 	    /*
115631e31b8aSbellard 	     * Find the end of the file  mapping for this phdr, and keep
115731e31b8aSbellard 	     * track of the largest address we see for this.
115831e31b8aSbellard 	     */
115931e31b8aSbellard 	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
116031e31b8aSbellard 	    if (k > elf_bss) elf_bss = k;
116131e31b8aSbellard 
116231e31b8aSbellard 	    /*
116331e31b8aSbellard 	     * Do the same thing for the memory mapping - between
116431e31b8aSbellard 	     * elf_bss and last_bss is the bss section.
116531e31b8aSbellard 	     */
116631e31b8aSbellard 	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
116731e31b8aSbellard 	    if (k > last_bss) last_bss = k;
116831e31b8aSbellard 	  }
116931e31b8aSbellard 
117031e31b8aSbellard 	/* Now use mmap to map the library into memory. */
117131e31b8aSbellard 
117231e31b8aSbellard 	close(interpreter_fd);
117331e31b8aSbellard 
117431e31b8aSbellard 	/*
117531e31b8aSbellard 	 * Now fill out the bss section.  First pad the last page up
117631e31b8aSbellard 	 * to the page boundary, and then perform a mmap to make sure
117731e31b8aSbellard 	 * that there are zeromapped pages up to and including the last
117831e31b8aSbellard 	 * bss page.
117931e31b8aSbellard 	 */
1180768a4a36Sths 	padzero(elf_bss, last_bss);
118183fb7adfSbellard 	elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
118231e31b8aSbellard 
118331e31b8aSbellard 	/* Map the last of the bss segment */
118431e31b8aSbellard 	if (last_bss > elf_bss) {
118554936004Sbellard             target_mmap(elf_bss, last_bss-elf_bss,
118631e31b8aSbellard                         PROT_READ|PROT_WRITE|PROT_EXEC,
118731e31b8aSbellard                         MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
118831e31b8aSbellard 	}
118931e31b8aSbellard 	free(elf_phdata);
119031e31b8aSbellard 
119131e31b8aSbellard 	*interp_load_addr = load_addr;
1192992f48a0Sblueswir1 	return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
119331e31b8aSbellard }
119431e31b8aSbellard 
119549918a75Spbrook static int symfind(const void *s0, const void *s1)
119649918a75Spbrook {
119749918a75Spbrook     struct elf_sym *key = (struct elf_sym *)s0;
119849918a75Spbrook     struct elf_sym *sym = (struct elf_sym *)s1;
119949918a75Spbrook     int result = 0;
120049918a75Spbrook     if (key->st_value < sym->st_value) {
120149918a75Spbrook         result = -1;
120249918a75Spbrook     } else if (key->st_value > sym->st_value + sym->st_size) {
120349918a75Spbrook         result = 1;
120449918a75Spbrook     }
120549918a75Spbrook     return result;
120649918a75Spbrook }
120749918a75Spbrook 
120849918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
120949918a75Spbrook {
121049918a75Spbrook #if ELF_CLASS == ELFCLASS32
121149918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf32;
121249918a75Spbrook #else
121349918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf64;
121449918a75Spbrook #endif
121549918a75Spbrook 
121649918a75Spbrook     // binary search
121749918a75Spbrook     struct elf_sym key;
121849918a75Spbrook     struct elf_sym *sym;
121949918a75Spbrook 
122049918a75Spbrook     key.st_value = orig_addr;
122149918a75Spbrook 
122249918a75Spbrook     sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
122349918a75Spbrook     if (sym != 0) {
122449918a75Spbrook         return s->disas_strtab + sym->st_name;
122549918a75Spbrook     }
122649918a75Spbrook 
122749918a75Spbrook     return "";
122849918a75Spbrook }
122949918a75Spbrook 
123049918a75Spbrook /* FIXME: This should use elf_ops.h  */
123149918a75Spbrook static int symcmp(const void *s0, const void *s1)
123249918a75Spbrook {
123349918a75Spbrook     struct elf_sym *sym0 = (struct elf_sym *)s0;
123449918a75Spbrook     struct elf_sym *sym1 = (struct elf_sym *)s1;
123549918a75Spbrook     return (sym0->st_value < sym1->st_value)
123649918a75Spbrook         ? -1
123749918a75Spbrook         : ((sym0->st_value > sym1->st_value) ? 1 : 0);
123849918a75Spbrook }
123949918a75Spbrook 
1240689f936fSbellard /* Best attempt to load symbols from this ELF object. */
1241689f936fSbellard static void load_symbols(struct elfhdr *hdr, int fd)
1242689f936fSbellard {
124349918a75Spbrook     unsigned int i, nsyms;
1244689f936fSbellard     struct elf_shdr sechdr, symtab, strtab;
1245689f936fSbellard     char *strings;
1246e80cfcfcSbellard     struct syminfo *s;
124749918a75Spbrook     struct elf_sym *syms;
124831e31b8aSbellard 
1249689f936fSbellard     lseek(fd, hdr->e_shoff, SEEK_SET);
1250689f936fSbellard     for (i = 0; i < hdr->e_shnum; i++) {
1251689f936fSbellard         if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
1252689f936fSbellard             return;
1253689f936fSbellard #ifdef BSWAP_NEEDED
1254689f936fSbellard         bswap_shdr(&sechdr);
1255689f936fSbellard #endif
1256689f936fSbellard         if (sechdr.sh_type == SHT_SYMTAB) {
1257689f936fSbellard             symtab = sechdr;
1258689f936fSbellard             lseek(fd, hdr->e_shoff
1259689f936fSbellard                   + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
1260689f936fSbellard             if (read(fd, &strtab, sizeof(strtab))
1261689f936fSbellard                 != sizeof(strtab))
1262689f936fSbellard                 return;
1263689f936fSbellard #ifdef BSWAP_NEEDED
1264689f936fSbellard             bswap_shdr(&strtab);
1265689f936fSbellard #endif
1266689f936fSbellard             goto found;
1267689f936fSbellard         }
1268689f936fSbellard     }
1269689f936fSbellard     return; /* Shouldn't happen... */
1270689f936fSbellard 
1271689f936fSbellard  found:
1272689f936fSbellard     /* Now know where the strtab and symtab are.  Snarf them. */
1273e80cfcfcSbellard     s = malloc(sizeof(*s));
127449918a75Spbrook     syms = malloc(symtab.sh_size);
127549918a75Spbrook     if (!syms)
127649918a75Spbrook         return;
1277e80cfcfcSbellard     s->disas_strtab = strings = malloc(strtab.sh_size);
127849918a75Spbrook     if (!s->disas_strtab)
1279689f936fSbellard         return;
1280689f936fSbellard 
1281689f936fSbellard     lseek(fd, symtab.sh_offset, SEEK_SET);
128249918a75Spbrook     if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
1283689f936fSbellard         return;
1284689f936fSbellard 
128549918a75Spbrook     nsyms = symtab.sh_size / sizeof(struct elf_sym);
1286689f936fSbellard 
128749918a75Spbrook     i = 0;
128849918a75Spbrook     while (i < nsyms) {
128949918a75Spbrook #ifdef BSWAP_NEEDED
129049918a75Spbrook         bswap_sym(syms + i);
12910774bed1Sblueswir1 #endif
129249918a75Spbrook         // Throw away entries which we do not need.
129349918a75Spbrook         if (syms[i].st_shndx == SHN_UNDEF ||
129449918a75Spbrook                 syms[i].st_shndx >= SHN_LORESERVE ||
129549918a75Spbrook                 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
129649918a75Spbrook             nsyms--;
129749918a75Spbrook             if (i < nsyms) {
129849918a75Spbrook                 syms[i] = syms[nsyms];
129949918a75Spbrook             }
130049918a75Spbrook             continue;
130149918a75Spbrook         }
130249918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS)
130349918a75Spbrook         /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
130449918a75Spbrook         syms[i].st_value &= ~(target_ulong)1;
130549918a75Spbrook #endif
130649918a75Spbrook         i++;
130749918a75Spbrook     }
130849918a75Spbrook     syms = realloc(syms, nsyms * sizeof(*syms));
130949918a75Spbrook 
131049918a75Spbrook     qsort(syms, nsyms, sizeof(*syms), symcmp);
131149918a75Spbrook 
1312689f936fSbellard     lseek(fd, strtab.sh_offset, SEEK_SET);
1313689f936fSbellard     if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
1314689f936fSbellard         return;
131549918a75Spbrook     s->disas_num_syms = nsyms;
131649918a75Spbrook #if ELF_CLASS == ELFCLASS32
131749918a75Spbrook     s->disas_symtab.elf32 = syms;
131849918a75Spbrook     s->lookup_symbol = lookup_symbolxx;
131949918a75Spbrook #else
132049918a75Spbrook     s->disas_symtab.elf64 = syms;
132149918a75Spbrook     s->lookup_symbol = lookup_symbolxx;
132249918a75Spbrook #endif
1323e80cfcfcSbellard     s->next = syminfos;
1324e80cfcfcSbellard     syminfos = s;
1325689f936fSbellard }
132631e31b8aSbellard 
1327e5fe0c52Spbrook int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
132831e31b8aSbellard                     struct image_info * info)
132931e31b8aSbellard {
133031e31b8aSbellard     struct elfhdr elf_ex;
133131e31b8aSbellard     struct elfhdr interp_elf_ex;
133231e31b8aSbellard     struct exec interp_ex;
133331e31b8aSbellard     int interpreter_fd = -1; /* avoid warning */
1334992f48a0Sblueswir1     abi_ulong load_addr, load_bias;
133531e31b8aSbellard     int load_addr_set = 0;
133631e31b8aSbellard     unsigned int interpreter_type = INTERPRETER_NONE;
133731e31b8aSbellard     unsigned char ibcs2_interpreter;
133831e31b8aSbellard     int i;
1339992f48a0Sblueswir1     abi_ulong mapped_addr;
134031e31b8aSbellard     struct elf_phdr * elf_ppnt;
134131e31b8aSbellard     struct elf_phdr *elf_phdata;
1342992f48a0Sblueswir1     abi_ulong elf_bss, k, elf_brk;
134331e31b8aSbellard     int retval;
134431e31b8aSbellard     char * elf_interpreter;
1345992f48a0Sblueswir1     abi_ulong elf_entry, interp_load_addr = 0;
134631e31b8aSbellard     int status;
1347992f48a0Sblueswir1     abi_ulong start_code, end_code, start_data, end_data;
1348992f48a0Sblueswir1     abi_ulong reloc_func_desc = 0;
1349992f48a0Sblueswir1     abi_ulong elf_stack;
135031e31b8aSbellard     char passed_fileno[6];
135131e31b8aSbellard 
135231e31b8aSbellard     ibcs2_interpreter = 0;
135331e31b8aSbellard     status = 0;
135431e31b8aSbellard     load_addr = 0;
135509bfb054Sbellard     load_bias = 0;
135631e31b8aSbellard     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
135731e31b8aSbellard #ifdef BSWAP_NEEDED
135831e31b8aSbellard     bswap_ehdr(&elf_ex);
135931e31b8aSbellard #endif
136031e31b8aSbellard 
136131e31b8aSbellard     /* First of all, some simple consistency checks */
136231e31b8aSbellard     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
136331e31b8aSbellard        				(! elf_check_arch(elf_ex.e_machine))) {
136431e31b8aSbellard 	    return -ENOEXEC;
136531e31b8aSbellard     }
136631e31b8aSbellard 
1367e5fe0c52Spbrook     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1368e5fe0c52Spbrook     bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1369e5fe0c52Spbrook     bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1370e5fe0c52Spbrook     if (!bprm->p) {
1371e5fe0c52Spbrook         retval = -E2BIG;
1372e5fe0c52Spbrook     }
1373e5fe0c52Spbrook 
137431e31b8aSbellard     /* Now read in all of the header information */
137531e31b8aSbellard     elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
137631e31b8aSbellard     if (elf_phdata == NULL) {
137731e31b8aSbellard 	return -ENOMEM;
137831e31b8aSbellard     }
137931e31b8aSbellard 
138031e31b8aSbellard     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
138131e31b8aSbellard     if(retval > 0) {
138231e31b8aSbellard 	retval = read(bprm->fd, (char *) elf_phdata,
138331e31b8aSbellard 				elf_ex.e_phentsize * elf_ex.e_phnum);
138431e31b8aSbellard     }
138531e31b8aSbellard 
138631e31b8aSbellard     if (retval < 0) {
138731e31b8aSbellard 	perror("load_elf_binary");
138831e31b8aSbellard 	exit(-1);
138931e31b8aSbellard 	free (elf_phdata);
139031e31b8aSbellard 	return -errno;
139131e31b8aSbellard     }
139231e31b8aSbellard 
1393b17780d5Sbellard #ifdef BSWAP_NEEDED
1394b17780d5Sbellard     elf_ppnt = elf_phdata;
1395b17780d5Sbellard     for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
1396b17780d5Sbellard         bswap_phdr(elf_ppnt);
1397b17780d5Sbellard     }
1398b17780d5Sbellard #endif
139931e31b8aSbellard     elf_ppnt = elf_phdata;
140031e31b8aSbellard 
140131e31b8aSbellard     elf_bss = 0;
140231e31b8aSbellard     elf_brk = 0;
140331e31b8aSbellard 
140431e31b8aSbellard 
1405992f48a0Sblueswir1     elf_stack = ~((abi_ulong)0UL);
140631e31b8aSbellard     elf_interpreter = NULL;
1407992f48a0Sblueswir1     start_code = ~((abi_ulong)0UL);
140831e31b8aSbellard     end_code = 0;
1409863cf0b7Sj_mayer     start_data = 0;
141031e31b8aSbellard     end_data = 0;
141198448f58Sblueswir1     interp_ex.a_info = 0;
141231e31b8aSbellard 
141331e31b8aSbellard     for(i=0;i < elf_ex.e_phnum; i++) {
141431e31b8aSbellard 	if (elf_ppnt->p_type == PT_INTERP) {
141531e31b8aSbellard 	    if ( elf_interpreter != NULL )
141631e31b8aSbellard 	    {
141731e31b8aSbellard 		free (elf_phdata);
141831e31b8aSbellard 		free(elf_interpreter);
141931e31b8aSbellard 		close(bprm->fd);
142031e31b8aSbellard 		return -EINVAL;
142131e31b8aSbellard 	    }
142231e31b8aSbellard 
142331e31b8aSbellard 	    /* This is the program interpreter used for
142431e31b8aSbellard 	     * shared libraries - for now assume that this
142531e31b8aSbellard 	     * is an a.out format binary
142631e31b8aSbellard 	     */
142731e31b8aSbellard 
142832ce6337Sbellard 	    elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
142931e31b8aSbellard 
143031e31b8aSbellard 	    if (elf_interpreter == NULL) {
143131e31b8aSbellard 		free (elf_phdata);
143231e31b8aSbellard 		close(bprm->fd);
143331e31b8aSbellard 		return -ENOMEM;
143431e31b8aSbellard 	    }
143531e31b8aSbellard 
143631e31b8aSbellard 	    retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
143731e31b8aSbellard 	    if(retval >= 0) {
143832ce6337Sbellard 		retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
143931e31b8aSbellard 	    }
144031e31b8aSbellard 	    if(retval < 0) {
144131e31b8aSbellard 	 	perror("load_elf_binary2");
144231e31b8aSbellard 		exit(-1);
144331e31b8aSbellard 	    }
144431e31b8aSbellard 
144531e31b8aSbellard 	    /* If the program interpreter is one of these two,
144631e31b8aSbellard 	       then assume an iBCS2 image. Otherwise assume
144731e31b8aSbellard 	       a native linux image. */
144831e31b8aSbellard 
144931e31b8aSbellard 	    /* JRP - Need to add X86 lib dir stuff here... */
145031e31b8aSbellard 
145131e31b8aSbellard 	    if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
145231e31b8aSbellard 		strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
145331e31b8aSbellard 	      ibcs2_interpreter = 1;
145431e31b8aSbellard 	    }
145531e31b8aSbellard 
145631e31b8aSbellard #if 0
145731e31b8aSbellard 	    printf("Using ELF interpreter %s\n", elf_interpreter);
145831e31b8aSbellard #endif
145931e31b8aSbellard 	    if (retval >= 0) {
146032ce6337Sbellard 		retval = open(path(elf_interpreter), O_RDONLY);
146131e31b8aSbellard 		if(retval >= 0) {
146231e31b8aSbellard 		    interpreter_fd = retval;
146331e31b8aSbellard 		}
146431e31b8aSbellard 		else {
146531e31b8aSbellard 		    perror(elf_interpreter);
146631e31b8aSbellard 		    exit(-1);
146731e31b8aSbellard 		    /* retval = -errno; */
146831e31b8aSbellard 		}
146931e31b8aSbellard 	    }
147031e31b8aSbellard 
147131e31b8aSbellard 	    if (retval >= 0) {
147231e31b8aSbellard 		retval = lseek(interpreter_fd, 0, SEEK_SET);
147331e31b8aSbellard 		if(retval >= 0) {
147431e31b8aSbellard 		    retval = read(interpreter_fd,bprm->buf,128);
147531e31b8aSbellard 		}
147631e31b8aSbellard 	    }
147731e31b8aSbellard 	    if (retval >= 0) {
147831e31b8aSbellard 		interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
147931e31b8aSbellard 		interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
148031e31b8aSbellard 	    }
148131e31b8aSbellard 	    if (retval < 0) {
148231e31b8aSbellard 		perror("load_elf_binary3");
148331e31b8aSbellard 		exit(-1);
148431e31b8aSbellard 		free (elf_phdata);
148531e31b8aSbellard 		free(elf_interpreter);
148631e31b8aSbellard 		close(bprm->fd);
148731e31b8aSbellard 		return retval;
148831e31b8aSbellard 	    }
148931e31b8aSbellard 	}
149031e31b8aSbellard 	elf_ppnt++;
149131e31b8aSbellard     }
149231e31b8aSbellard 
149331e31b8aSbellard     /* Some simple consistency checks for the interpreter */
149431e31b8aSbellard     if (elf_interpreter){
149531e31b8aSbellard 	interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
149631e31b8aSbellard 
149731e31b8aSbellard 	/* Now figure out which format our binary is */
149831e31b8aSbellard 	if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
149931e31b8aSbellard 	    	(N_MAGIC(interp_ex) != QMAGIC)) {
150031e31b8aSbellard 	  interpreter_type = INTERPRETER_ELF;
150131e31b8aSbellard 	}
150231e31b8aSbellard 
150331e31b8aSbellard 	if (interp_elf_ex.e_ident[0] != 0x7f ||
1504b55266b5Sblueswir1             strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
150531e31b8aSbellard 	    interpreter_type &= ~INTERPRETER_ELF;
150631e31b8aSbellard 	}
150731e31b8aSbellard 
150831e31b8aSbellard 	if (!interpreter_type) {
150931e31b8aSbellard 	    free(elf_interpreter);
151031e31b8aSbellard 	    free(elf_phdata);
151131e31b8aSbellard 	    close(bprm->fd);
151231e31b8aSbellard 	    return -ELIBBAD;
151331e31b8aSbellard 	}
151431e31b8aSbellard     }
151531e31b8aSbellard 
151631e31b8aSbellard     /* OK, we are done with that, now set up the arg stuff,
151731e31b8aSbellard        and then start this sucker up */
151831e31b8aSbellard 
1519e5fe0c52Spbrook     {
152031e31b8aSbellard 	char * passed_p;
152131e31b8aSbellard 
152231e31b8aSbellard 	if (interpreter_type == INTERPRETER_AOUT) {
1523eba2af63Sbellard 	    snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
152431e31b8aSbellard 	    passed_p = passed_fileno;
152531e31b8aSbellard 
152631e31b8aSbellard 	    if (elf_interpreter) {
1527e5fe0c52Spbrook 		bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
152831e31b8aSbellard 		bprm->argc++;
152931e31b8aSbellard 	    }
153031e31b8aSbellard 	}
153131e31b8aSbellard 	if (!bprm->p) {
153231e31b8aSbellard 	    if (elf_interpreter) {
153331e31b8aSbellard 	        free(elf_interpreter);
153431e31b8aSbellard 	    }
153531e31b8aSbellard 	    free (elf_phdata);
153631e31b8aSbellard 	    close(bprm->fd);
153731e31b8aSbellard 	    return -E2BIG;
153831e31b8aSbellard 	}
153931e31b8aSbellard     }
154031e31b8aSbellard 
154131e31b8aSbellard     /* OK, This is the point of no return */
154231e31b8aSbellard     info->end_data = 0;
154331e31b8aSbellard     info->end_code = 0;
1544992f48a0Sblueswir1     info->start_mmap = (abi_ulong)ELF_START_MMAP;
154531e31b8aSbellard     info->mmap = 0;
1546992f48a0Sblueswir1     elf_entry = (abi_ulong) elf_ex.e_entry;
154731e31b8aSbellard 
1548379f6698SPaul Brook #if defined(CONFIG_USE_GUEST_BASE)
1549379f6698SPaul Brook     /*
1550379f6698SPaul Brook      * In case where user has not explicitly set the guest_base, we
1551379f6698SPaul Brook      * probe here that should we set it automatically.
1552379f6698SPaul Brook      */
1553379f6698SPaul Brook     if (!have_guest_base) {
1554379f6698SPaul Brook         /*
1555379f6698SPaul Brook          * Go through ELF program header table and find out whether
1556379f6698SPaul Brook 	 * any of the segments drop below our current mmap_min_addr and
1557379f6698SPaul Brook          * in that case set guest_base to corresponding address.
1558379f6698SPaul Brook          */
1559379f6698SPaul Brook         for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
1560379f6698SPaul Brook             i++, elf_ppnt++) {
1561379f6698SPaul Brook             if (elf_ppnt->p_type != PT_LOAD)
1562379f6698SPaul Brook                 continue;
1563379f6698SPaul Brook             if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
1564379f6698SPaul Brook                 guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
1565379f6698SPaul Brook                 break;
1566379f6698SPaul Brook             }
1567379f6698SPaul Brook         }
1568379f6698SPaul Brook     }
1569379f6698SPaul Brook #endif /* CONFIG_USE_GUEST_BASE */
1570379f6698SPaul Brook 
157131e31b8aSbellard     /* Do this so that we can load the interpreter, if need be.  We will
157231e31b8aSbellard        change some of these later */
157331e31b8aSbellard     info->rss = 0;
157431e31b8aSbellard     bprm->p = setup_arg_pages(bprm->p, bprm, info);
157531e31b8aSbellard     info->start_stack = bprm->p;
157631e31b8aSbellard 
157731e31b8aSbellard     /* Now we do a little grungy work by mmaping the ELF image into
157831e31b8aSbellard      * the correct location in memory.  At this point, we assume that
157931e31b8aSbellard      * the image should be loaded at fixed address, not at a variable
158031e31b8aSbellard      * address.
158131e31b8aSbellard      */
158231e31b8aSbellard 
158331e31b8aSbellard     for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
158431e31b8aSbellard         int elf_prot = 0;
158509bfb054Sbellard         int elf_flags = 0;
1586992f48a0Sblueswir1         abi_ulong error;
158709bfb054Sbellard 
158809bfb054Sbellard 	if (elf_ppnt->p_type != PT_LOAD)
158909bfb054Sbellard             continue;
159009bfb054Sbellard 
159131e31b8aSbellard         if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
159231e31b8aSbellard         if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
159331e31b8aSbellard         if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
159409bfb054Sbellard         elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
159509bfb054Sbellard         if (elf_ex.e_type == ET_EXEC || load_addr_set) {
159609bfb054Sbellard             elf_flags |= MAP_FIXED;
159709bfb054Sbellard         } else if (elf_ex.e_type == ET_DYN) {
159809bfb054Sbellard             /* Try and get dynamic programs out of the way of the default mmap
159909bfb054Sbellard                base, as well as whatever program they might try to exec.  This
160009bfb054Sbellard                is because the brk will follow the loader, and is not movable.  */
160109bfb054Sbellard             /* NOTE: for qemu, we do a big mmap to get enough space
1602e91c8a77Sths                without hardcoding any address */
160354936004Sbellard             error = target_mmap(0, ET_DYN_MAP_SIZE,
160409bfb054Sbellard                                 PROT_NONE, MAP_PRIVATE | MAP_ANON,
160509bfb054Sbellard                                 -1, 0);
160609bfb054Sbellard             if (error == -1) {
160709bfb054Sbellard                 perror("mmap");
160809bfb054Sbellard                 exit(-1);
160909bfb054Sbellard             }
161054936004Sbellard             load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
161109bfb054Sbellard         }
161231e31b8aSbellard 
161354936004Sbellard         error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
161431e31b8aSbellard                             (elf_ppnt->p_filesz +
161554936004Sbellard                              TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
161631e31b8aSbellard                             elf_prot,
161731e31b8aSbellard                             (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
161831e31b8aSbellard                             bprm->fd,
161931e31b8aSbellard                             (elf_ppnt->p_offset -
162054936004Sbellard                              TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
162109bfb054Sbellard         if (error == -1) {
162231e31b8aSbellard             perror("mmap");
162331e31b8aSbellard             exit(-1);
162431e31b8aSbellard         }
162531e31b8aSbellard 
162631e31b8aSbellard #ifdef LOW_ELF_STACK
162754936004Sbellard         if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
162854936004Sbellard             elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
162931e31b8aSbellard #endif
163031e31b8aSbellard 
163131e31b8aSbellard         if (!load_addr_set) {
163231e31b8aSbellard             load_addr_set = 1;
163309bfb054Sbellard             load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
163409bfb054Sbellard             if (elf_ex.e_type == ET_DYN) {
163509bfb054Sbellard                 load_bias += error -
163654936004Sbellard                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
163709bfb054Sbellard                 load_addr += load_bias;
163884409ddbSj_mayer                 reloc_func_desc = load_bias;
163909bfb054Sbellard             }
164031e31b8aSbellard         }
164131e31b8aSbellard         k = elf_ppnt->p_vaddr;
164209bfb054Sbellard         if (k < start_code)
164309bfb054Sbellard             start_code = k;
1644863cf0b7Sj_mayer         if (start_data < k)
1645863cf0b7Sj_mayer             start_data = k;
164631e31b8aSbellard         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
164709bfb054Sbellard         if (k > elf_bss)
164809bfb054Sbellard             elf_bss = k;
164931e31b8aSbellard         if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
165031e31b8aSbellard             end_code = k;
165109bfb054Sbellard         if (end_data < k)
165209bfb054Sbellard             end_data = k;
165331e31b8aSbellard         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
165431e31b8aSbellard         if (k > elf_brk) elf_brk = k;
165531e31b8aSbellard     }
165609bfb054Sbellard 
165709bfb054Sbellard     elf_entry += load_bias;
165809bfb054Sbellard     elf_bss += load_bias;
165909bfb054Sbellard     elf_brk += load_bias;
166009bfb054Sbellard     start_code += load_bias;
166109bfb054Sbellard     end_code += load_bias;
1662863cf0b7Sj_mayer     start_data += load_bias;
166309bfb054Sbellard     end_data += load_bias;
166431e31b8aSbellard 
166531e31b8aSbellard     if (elf_interpreter) {
166631e31b8aSbellard 	if (interpreter_type & 1) {
166731e31b8aSbellard 	    elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
166831e31b8aSbellard 	}
166931e31b8aSbellard 	else if (interpreter_type & 2) {
167031e31b8aSbellard 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
167131e31b8aSbellard 					    &interp_load_addr);
167231e31b8aSbellard 	}
167384409ddbSj_mayer         reloc_func_desc = interp_load_addr;
167431e31b8aSbellard 
167531e31b8aSbellard 	close(interpreter_fd);
167631e31b8aSbellard 	free(elf_interpreter);
167731e31b8aSbellard 
1678992f48a0Sblueswir1 	if (elf_entry == ~((abi_ulong)0UL)) {
167931e31b8aSbellard 	    printf("Unable to load interpreter\n");
168031e31b8aSbellard 	    free(elf_phdata);
168131e31b8aSbellard 	    exit(-1);
168231e31b8aSbellard 	    return 0;
168331e31b8aSbellard 	}
168431e31b8aSbellard     }
168531e31b8aSbellard 
168631e31b8aSbellard     free(elf_phdata);
168731e31b8aSbellard 
168893fcfe39Saliguori     if (qemu_log_enabled())
1689689f936fSbellard 	load_symbols(&elf_ex, bprm->fd);
1690689f936fSbellard 
169131e31b8aSbellard     if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
169231e31b8aSbellard     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
169331e31b8aSbellard 
169431e31b8aSbellard #ifdef LOW_ELF_STACK
169531e31b8aSbellard     info->start_stack = bprm->p = elf_stack - 4;
169631e31b8aSbellard #endif
169753a5960aSpbrook     bprm->p = create_elf_tables(bprm->p,
169831e31b8aSbellard 		    bprm->argc,
169931e31b8aSbellard 		    bprm->envc,
1700a1516e92Sbellard                     &elf_ex,
170109bfb054Sbellard                     load_addr, load_bias,
170231e31b8aSbellard 		    interp_load_addr,
170331e31b8aSbellard 		    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
170431e31b8aSbellard 		    info);
170592a343daSj_mayer     info->load_addr = reloc_func_desc;
170631e31b8aSbellard     info->start_brk = info->brk = elf_brk;
170731e31b8aSbellard     info->end_code = end_code;
170831e31b8aSbellard     info->start_code = start_code;
1709863cf0b7Sj_mayer     info->start_data = start_data;
171031e31b8aSbellard     info->end_data = end_data;
171131e31b8aSbellard     info->start_stack = bprm->p;
171231e31b8aSbellard 
171331e31b8aSbellard     /* Calling set_brk effectively mmaps the pages that we need for the bss and break
171431e31b8aSbellard        sections */
171531e31b8aSbellard     set_brk(elf_bss, elf_brk);
171631e31b8aSbellard 
1717768a4a36Sths     padzero(elf_bss, elf_brk);
171831e31b8aSbellard 
171931e31b8aSbellard #if 0
172031e31b8aSbellard     printf("(start_brk) %x\n" , info->start_brk);
172131e31b8aSbellard     printf("(end_code) %x\n" , info->end_code);
172231e31b8aSbellard     printf("(start_code) %x\n" , info->start_code);
172331e31b8aSbellard     printf("(end_data) %x\n" , info->end_data);
172431e31b8aSbellard     printf("(start_stack) %x\n" , info->start_stack);
172531e31b8aSbellard     printf("(brk) %x\n" , info->brk);
172631e31b8aSbellard #endif
172731e31b8aSbellard 
172831e31b8aSbellard     if ( info->personality == PER_SVR4 )
172931e31b8aSbellard     {
173031e31b8aSbellard 	    /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
173131e31b8aSbellard 	       and some applications "depend" upon this behavior.
173231e31b8aSbellard 	       Since we do not have the power to recompile these, we
173331e31b8aSbellard 	       emulate the SVr4 behavior.  Sigh.  */
173483fb7adfSbellard 	    mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
173531e31b8aSbellard                                       MAP_FIXED | MAP_PRIVATE, -1, 0);
173631e31b8aSbellard     }
173731e31b8aSbellard 
173831e31b8aSbellard     info->entry = elf_entry;
173931e31b8aSbellard 
1740edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
1741edf8e2afSMika Westerberg     bprm->core_dump = &elf_core_dump;
1742edf8e2afSMika Westerberg #endif
1743edf8e2afSMika Westerberg 
174431e31b8aSbellard     return 0;
174531e31b8aSbellard }
174631e31b8aSbellard 
1747edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
1748edf8e2afSMika Westerberg 
1749edf8e2afSMika Westerberg /*
1750edf8e2afSMika Westerberg  * Definitions to generate Intel SVR4-like core files.
1751a2547a13SLaurent Desnogues  * These mostly have the same names as the SVR4 types with "target_elf_"
1752edf8e2afSMika Westerberg  * tacked on the front to prevent clashes with linux definitions,
1753edf8e2afSMika Westerberg  * and the typedef forms have been avoided.  This is mostly like
1754edf8e2afSMika Westerberg  * the SVR4 structure, but more Linuxy, with things that Linux does
1755edf8e2afSMika Westerberg  * not support and which gdb doesn't really use excluded.
1756edf8e2afSMika Westerberg  *
1757edf8e2afSMika Westerberg  * Fields we don't dump (their contents is zero) in linux-user qemu
1758edf8e2afSMika Westerberg  * are marked with XXX.
1759edf8e2afSMika Westerberg  *
1760edf8e2afSMika Westerberg  * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
1761edf8e2afSMika Westerberg  *
1762edf8e2afSMika Westerberg  * Porting ELF coredump for target is (quite) simple process.  First you
1763edf8e2afSMika Westerberg  * define ELF_USE_CORE_DUMP in target ELF code (where init_thread() for
1764edf8e2afSMika Westerberg  * the target resides):
1765edf8e2afSMika Westerberg  *
1766edf8e2afSMika Westerberg  * #define USE_ELF_CORE_DUMP
1767edf8e2afSMika Westerberg  *
1768edf8e2afSMika Westerberg  * Next you define type of register set used for dumping.  ELF specification
1769edf8e2afSMika Westerberg  * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
1770edf8e2afSMika Westerberg  *
1771a2547a13SLaurent Desnogues  * typedef <target_regtype> target_elf_greg_t;
1772edf8e2afSMika Westerberg  * #define ELF_NREG <number of registers>
1773a2547a13SLaurent Desnogues  * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
1774edf8e2afSMika Westerberg  *
1775edf8e2afSMika Westerberg  * Then define following types to match target types.  Actual types can
1776edf8e2afSMika Westerberg  * be found from linux kernel (arch/<ARCH>/include/asm/posix_types.h):
1777edf8e2afSMika Westerberg  *
1778edf8e2afSMika Westerberg  * typedef <target_uid_type> target_uid_t;
1779edf8e2afSMika Westerberg  * typedef <target_gid_type> target_gid_t;
1780edf8e2afSMika Westerberg  * typedef <target_pid_type> target_pid_t;
1781edf8e2afSMika Westerberg  *
1782edf8e2afSMika Westerberg  * Last step is to implement target specific function that copies registers
1783edf8e2afSMika Westerberg  * from given cpu into just specified register set.  Prototype is:
1784edf8e2afSMika Westerberg  *
1785a2547a13SLaurent Desnogues  * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
1786a2547a13SLaurent Desnogues  *                                const CPUState *env);
1787edf8e2afSMika Westerberg  *
1788edf8e2afSMika Westerberg  * Parameters:
1789edf8e2afSMika Westerberg  *     regs - copy register values into here (allocated and zeroed by caller)
1790edf8e2afSMika Westerberg  *     env - copy registers from here
1791edf8e2afSMika Westerberg  *
1792edf8e2afSMika Westerberg  * Example for ARM target is provided in this file.
1793edf8e2afSMika Westerberg  */
1794edf8e2afSMika Westerberg 
1795edf8e2afSMika Westerberg /* An ELF note in memory */
1796edf8e2afSMika Westerberg struct memelfnote {
1797edf8e2afSMika Westerberg     const char *name;
1798edf8e2afSMika Westerberg     size_t     namesz;
1799edf8e2afSMika Westerberg     size_t     namesz_rounded;
1800edf8e2afSMika Westerberg     int        type;
1801edf8e2afSMika Westerberg     size_t     datasz;
1802edf8e2afSMika Westerberg     void       *data;
1803edf8e2afSMika Westerberg     size_t     notesz;
1804edf8e2afSMika Westerberg };
1805edf8e2afSMika Westerberg 
1806a2547a13SLaurent Desnogues struct target_elf_siginfo {
1807edf8e2afSMika Westerberg     int  si_signo; /* signal number */
1808edf8e2afSMika Westerberg     int  si_code;  /* extra code */
1809edf8e2afSMika Westerberg     int  si_errno; /* errno */
1810edf8e2afSMika Westerberg };
1811edf8e2afSMika Westerberg 
1812a2547a13SLaurent Desnogues struct target_elf_prstatus {
1813a2547a13SLaurent Desnogues     struct target_elf_siginfo pr_info;      /* Info associated with signal */
1814edf8e2afSMika Westerberg     short              pr_cursig;    /* Current signal */
1815edf8e2afSMika Westerberg     target_ulong       pr_sigpend;   /* XXX */
1816edf8e2afSMika Westerberg     target_ulong       pr_sighold;   /* XXX */
1817edf8e2afSMika Westerberg     target_pid_t       pr_pid;
1818edf8e2afSMika Westerberg     target_pid_t       pr_ppid;
1819edf8e2afSMika Westerberg     target_pid_t       pr_pgrp;
1820edf8e2afSMika Westerberg     target_pid_t       pr_sid;
1821edf8e2afSMika Westerberg     struct target_timeval pr_utime;  /* XXX User time */
1822edf8e2afSMika Westerberg     struct target_timeval pr_stime;  /* XXX System time */
1823edf8e2afSMika Westerberg     struct target_timeval pr_cutime; /* XXX Cumulative user time */
1824edf8e2afSMika Westerberg     struct target_timeval pr_cstime; /* XXX Cumulative system time */
1825a2547a13SLaurent Desnogues     target_elf_gregset_t      pr_reg;       /* GP registers */
1826edf8e2afSMika Westerberg     int                pr_fpvalid;   /* XXX */
1827edf8e2afSMika Westerberg };
1828edf8e2afSMika Westerberg 
1829edf8e2afSMika Westerberg #define ELF_PRARGSZ     (80) /* Number of chars for args */
1830edf8e2afSMika Westerberg 
1831a2547a13SLaurent Desnogues struct target_elf_prpsinfo {
1832edf8e2afSMika Westerberg     char         pr_state;       /* numeric process state */
1833edf8e2afSMika Westerberg     char         pr_sname;       /* char for pr_state */
1834edf8e2afSMika Westerberg     char         pr_zomb;        /* zombie */
1835edf8e2afSMika Westerberg     char         pr_nice;        /* nice val */
1836edf8e2afSMika Westerberg     target_ulong pr_flag;        /* flags */
1837edf8e2afSMika Westerberg     target_uid_t pr_uid;
1838edf8e2afSMika Westerberg     target_gid_t pr_gid;
1839edf8e2afSMika Westerberg     target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
1840edf8e2afSMika Westerberg     /* Lots missing */
1841edf8e2afSMika Westerberg     char    pr_fname[16];           /* filename of executable */
1842edf8e2afSMika Westerberg     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
1843edf8e2afSMika Westerberg };
1844edf8e2afSMika Westerberg 
1845edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */
1846edf8e2afSMika Westerberg struct elf_thread_status {
1847edf8e2afSMika Westerberg     TAILQ_ENTRY(elf_thread_status)  ets_link;
1848a2547a13SLaurent Desnogues     struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
1849edf8e2afSMika Westerberg #if 0
1850edf8e2afSMika Westerberg     elf_fpregset_t fpu;             /* NT_PRFPREG */
1851edf8e2afSMika Westerberg     struct task_struct *thread;
1852edf8e2afSMika Westerberg     elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */
1853edf8e2afSMika Westerberg #endif
1854edf8e2afSMika Westerberg     struct memelfnote notes[1];
1855edf8e2afSMika Westerberg     int num_notes;
1856edf8e2afSMika Westerberg };
1857edf8e2afSMika Westerberg 
1858edf8e2afSMika Westerberg struct elf_note_info {
1859edf8e2afSMika Westerberg     struct memelfnote   *notes;
1860a2547a13SLaurent Desnogues     struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
1861a2547a13SLaurent Desnogues     struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
1862edf8e2afSMika Westerberg 
1863edf8e2afSMika Westerberg     TAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
1864edf8e2afSMika Westerberg #if 0
1865edf8e2afSMika Westerberg     /*
1866edf8e2afSMika Westerberg      * Current version of ELF coredump doesn't support
1867edf8e2afSMika Westerberg      * dumping fp regs etc.
1868edf8e2afSMika Westerberg      */
1869edf8e2afSMika Westerberg     elf_fpregset_t *fpu;
1870edf8e2afSMika Westerberg     elf_fpxregset_t *xfpu;
1871edf8e2afSMika Westerberg     int thread_status_size;
1872edf8e2afSMika Westerberg #endif
1873edf8e2afSMika Westerberg     int notes_size;
1874edf8e2afSMika Westerberg     int numnote;
1875edf8e2afSMika Westerberg };
1876edf8e2afSMika Westerberg 
1877edf8e2afSMika Westerberg struct vm_area_struct {
1878edf8e2afSMika Westerberg     abi_ulong   vma_start;  /* start vaddr of memory region */
1879edf8e2afSMika Westerberg     abi_ulong   vma_end;    /* end vaddr of memory region */
1880edf8e2afSMika Westerberg     abi_ulong   vma_flags;  /* protection etc. flags for the region */
1881edf8e2afSMika Westerberg     TAILQ_ENTRY(vm_area_struct) vma_link;
1882edf8e2afSMika Westerberg };
1883edf8e2afSMika Westerberg 
1884edf8e2afSMika Westerberg struct mm_struct {
1885edf8e2afSMika Westerberg     TAILQ_HEAD(, vm_area_struct) mm_mmap;
1886edf8e2afSMika Westerberg     int mm_count;           /* number of mappings */
1887edf8e2afSMika Westerberg };
1888edf8e2afSMika Westerberg 
1889edf8e2afSMika Westerberg static struct mm_struct *vma_init(void);
1890edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *);
1891edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *, abi_ulong,
1892edf8e2afSMika Westerberg     abi_ulong, abi_ulong);
1893edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *);
1894edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *);
1895edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *);
1896edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *);
1897edf8e2afSMika Westerberg static int vma_walker(void *priv, unsigned long start, unsigned long end,
1898edf8e2afSMika Westerberg     unsigned long flags);
1899edf8e2afSMika Westerberg 
1900edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
1901edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int,
1902edf8e2afSMika Westerberg     unsigned int, void *);
1903a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
1904a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
1905edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *);
1906edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
1907edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *);
1908edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *);
1909edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *, long, const CPUState *);
1910edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *, const CPUState *);
1911edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t);
1912edf8e2afSMika Westerberg 
1913edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t);
1914edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int);
1915edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int);
1916edf8e2afSMika Westerberg 
1917edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
1918a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *);
1919a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *);
1920edf8e2afSMika Westerberg 
1921a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus)
1922edf8e2afSMika Westerberg {
1923edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
1924edf8e2afSMika Westerberg     prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
1925edf8e2afSMika Westerberg     prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
1926edf8e2afSMika Westerberg     prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
1927edf8e2afSMika Westerberg     prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
1928edf8e2afSMika Westerberg     prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
1929edf8e2afSMika Westerberg     prstatus->pr_pid = tswap32(prstatus->pr_pid);
1930edf8e2afSMika Westerberg     prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
1931edf8e2afSMika Westerberg     prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
1932edf8e2afSMika Westerberg     prstatus->pr_sid = tswap32(prstatus->pr_sid);
1933edf8e2afSMika Westerberg     /* cpu times are not filled, so we skip them */
1934edf8e2afSMika Westerberg     /* regs should be in correct format already */
1935edf8e2afSMika Westerberg     prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
1936edf8e2afSMika Westerberg }
1937edf8e2afSMika Westerberg 
1938a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
1939edf8e2afSMika Westerberg {
1940edf8e2afSMika Westerberg     psinfo->pr_flag = tswapl(psinfo->pr_flag);
1941edf8e2afSMika Westerberg     psinfo->pr_uid = tswap16(psinfo->pr_uid);
1942edf8e2afSMika Westerberg     psinfo->pr_gid = tswap16(psinfo->pr_gid);
1943edf8e2afSMika Westerberg     psinfo->pr_pid = tswap32(psinfo->pr_pid);
1944edf8e2afSMika Westerberg     psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
1945edf8e2afSMika Westerberg     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
1946edf8e2afSMika Westerberg     psinfo->pr_sid = tswap32(psinfo->pr_sid);
1947edf8e2afSMika Westerberg }
1948edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
1949edf8e2afSMika Westerberg 
1950edf8e2afSMika Westerberg /*
1951edf8e2afSMika Westerberg  * Minimal support for linux memory regions.  These are needed
1952edf8e2afSMika Westerberg  * when we are finding out what memory exactly belongs to
1953edf8e2afSMika Westerberg  * emulated process.  No locks needed here, as long as
1954edf8e2afSMika Westerberg  * thread that received the signal is stopped.
1955edf8e2afSMika Westerberg  */
1956edf8e2afSMika Westerberg 
1957edf8e2afSMika Westerberg static struct mm_struct *vma_init(void)
1958edf8e2afSMika Westerberg {
1959edf8e2afSMika Westerberg     struct mm_struct *mm;
1960edf8e2afSMika Westerberg 
1961edf8e2afSMika Westerberg     if ((mm = qemu_malloc(sizeof (*mm))) == NULL)
1962edf8e2afSMika Westerberg         return (NULL);
1963edf8e2afSMika Westerberg 
1964edf8e2afSMika Westerberg     mm->mm_count = 0;
1965edf8e2afSMika Westerberg     TAILQ_INIT(&mm->mm_mmap);
1966edf8e2afSMika Westerberg 
1967edf8e2afSMika Westerberg     return (mm);
1968edf8e2afSMika Westerberg }
1969edf8e2afSMika Westerberg 
1970edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm)
1971edf8e2afSMika Westerberg {
1972edf8e2afSMika Westerberg     struct vm_area_struct *vma;
1973edf8e2afSMika Westerberg 
1974edf8e2afSMika Westerberg     while ((vma = vma_first(mm)) != NULL) {
1975edf8e2afSMika Westerberg         TAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
1976edf8e2afSMika Westerberg         qemu_free(vma);
1977edf8e2afSMika Westerberg     }
1978edf8e2afSMika Westerberg     qemu_free(mm);
1979edf8e2afSMika Westerberg }
1980edf8e2afSMika Westerberg 
1981edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
1982edf8e2afSMika Westerberg     abi_ulong end, abi_ulong flags)
1983edf8e2afSMika Westerberg {
1984edf8e2afSMika Westerberg     struct vm_area_struct *vma;
1985edf8e2afSMika Westerberg 
1986edf8e2afSMika Westerberg     if ((vma = qemu_mallocz(sizeof (*vma))) == NULL)
1987edf8e2afSMika Westerberg         return (-1);
1988edf8e2afSMika Westerberg 
1989edf8e2afSMika Westerberg     vma->vma_start = start;
1990edf8e2afSMika Westerberg     vma->vma_end = end;
1991edf8e2afSMika Westerberg     vma->vma_flags = flags;
1992edf8e2afSMika Westerberg 
1993edf8e2afSMika Westerberg     TAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
1994edf8e2afSMika Westerberg     mm->mm_count++;
1995edf8e2afSMika Westerberg 
1996edf8e2afSMika Westerberg     return (0);
1997edf8e2afSMika Westerberg }
1998edf8e2afSMika Westerberg 
1999edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2000edf8e2afSMika Westerberg {
2001edf8e2afSMika Westerberg     return (TAILQ_FIRST(&mm->mm_mmap));
2002edf8e2afSMika Westerberg }
2003edf8e2afSMika Westerberg 
2004edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2005edf8e2afSMika Westerberg {
2006edf8e2afSMika Westerberg     return (TAILQ_NEXT(vma, vma_link));
2007edf8e2afSMika Westerberg }
2008edf8e2afSMika Westerberg 
2009edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm)
2010edf8e2afSMika Westerberg {
2011edf8e2afSMika Westerberg     return (mm->mm_count);
2012edf8e2afSMika Westerberg }
2013edf8e2afSMika Westerberg 
2014edf8e2afSMika Westerberg /*
2015edf8e2afSMika Westerberg  * Calculate file (dump) size of given memory region.
2016edf8e2afSMika Westerberg  */
2017edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2018edf8e2afSMika Westerberg {
2019edf8e2afSMika Westerberg     /* if we cannot even read the first page, skip it */
2020edf8e2afSMika Westerberg     if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2021edf8e2afSMika Westerberg         return (0);
2022edf8e2afSMika Westerberg 
2023edf8e2afSMika Westerberg     /*
2024edf8e2afSMika Westerberg      * Usually we don't dump executable pages as they contain
2025edf8e2afSMika Westerberg      * non-writable code that debugger can read directly from
2026edf8e2afSMika Westerberg      * target library etc.  However, thread stacks are marked
2027edf8e2afSMika Westerberg      * also executable so we read in first page of given region
2028edf8e2afSMika Westerberg      * and check whether it contains elf header.  If there is
2029edf8e2afSMika Westerberg      * no elf header, we dump it.
2030edf8e2afSMika Westerberg      */
2031edf8e2afSMika Westerberg     if (vma->vma_flags & PROT_EXEC) {
2032edf8e2afSMika Westerberg         char page[TARGET_PAGE_SIZE];
2033edf8e2afSMika Westerberg 
2034edf8e2afSMika Westerberg         copy_from_user(page, vma->vma_start, sizeof (page));
2035edf8e2afSMika Westerberg         if ((page[EI_MAG0] == ELFMAG0) &&
2036edf8e2afSMika Westerberg             (page[EI_MAG1] == ELFMAG1) &&
2037edf8e2afSMika Westerberg             (page[EI_MAG2] == ELFMAG2) &&
2038edf8e2afSMika Westerberg             (page[EI_MAG3] == ELFMAG3)) {
2039edf8e2afSMika Westerberg             /*
2040edf8e2afSMika Westerberg              * Mappings are possibly from ELF binary.  Don't dump
2041edf8e2afSMika Westerberg              * them.
2042edf8e2afSMika Westerberg              */
2043edf8e2afSMika Westerberg             return (0);
2044edf8e2afSMika Westerberg         }
2045edf8e2afSMika Westerberg     }
2046edf8e2afSMika Westerberg 
2047edf8e2afSMika Westerberg     return (vma->vma_end - vma->vma_start);
2048edf8e2afSMika Westerberg }
2049edf8e2afSMika Westerberg 
2050edf8e2afSMika Westerberg static int vma_walker(void *priv, unsigned long start, unsigned long end,
2051edf8e2afSMika Westerberg     unsigned long flags)
2052edf8e2afSMika Westerberg {
2053edf8e2afSMika Westerberg     struct mm_struct *mm = (struct mm_struct *)priv;
2054edf8e2afSMika Westerberg 
2055edf8e2afSMika Westerberg     /*
2056edf8e2afSMika Westerberg      * Don't dump anything that qemu has reserved for internal use.
2057edf8e2afSMika Westerberg      */
2058edf8e2afSMika Westerberg     if (flags & PAGE_RESERVED)
2059edf8e2afSMika Westerberg         return (0);
2060edf8e2afSMika Westerberg 
2061edf8e2afSMika Westerberg     vma_add_mapping(mm, start, end, flags);
2062edf8e2afSMika Westerberg     return (0);
2063edf8e2afSMika Westerberg }
2064edf8e2afSMika Westerberg 
2065edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type,
2066edf8e2afSMika Westerberg     unsigned int sz, void *data)
2067edf8e2afSMika Westerberg {
2068edf8e2afSMika Westerberg     unsigned int namesz;
2069edf8e2afSMika Westerberg 
2070edf8e2afSMika Westerberg     namesz = strlen(name) + 1;
2071edf8e2afSMika Westerberg     note->name = name;
2072edf8e2afSMika Westerberg     note->namesz = namesz;
2073edf8e2afSMika Westerberg     note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2074edf8e2afSMika Westerberg     note->type = type;
2075edf8e2afSMika Westerberg     note->datasz = roundup(sz, sizeof (int32_t));;
2076edf8e2afSMika Westerberg     note->data = data;
2077edf8e2afSMika Westerberg 
2078edf8e2afSMika Westerberg     /*
2079edf8e2afSMika Westerberg      * We calculate rounded up note size here as specified by
2080edf8e2afSMika Westerberg      * ELF document.
2081edf8e2afSMika Westerberg      */
2082edf8e2afSMika Westerberg     note->notesz = sizeof (struct elf_note) +
2083edf8e2afSMika Westerberg         note->namesz_rounded + note->datasz;
2084edf8e2afSMika Westerberg }
2085edf8e2afSMika Westerberg 
2086edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
2087edf8e2afSMika Westerberg     uint32_t flags)
2088edf8e2afSMika Westerberg {
2089edf8e2afSMika Westerberg     (void) memset(elf, 0, sizeof(*elf));
2090edf8e2afSMika Westerberg 
2091edf8e2afSMika Westerberg     (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2092edf8e2afSMika Westerberg     elf->e_ident[EI_CLASS] = ELF_CLASS;
2093edf8e2afSMika Westerberg     elf->e_ident[EI_DATA] = ELF_DATA;
2094edf8e2afSMika Westerberg     elf->e_ident[EI_VERSION] = EV_CURRENT;
2095edf8e2afSMika Westerberg     elf->e_ident[EI_OSABI] = ELF_OSABI;
2096edf8e2afSMika Westerberg 
2097edf8e2afSMika Westerberg     elf->e_type = ET_CORE;
2098edf8e2afSMika Westerberg     elf->e_machine = machine;
2099edf8e2afSMika Westerberg     elf->e_version = EV_CURRENT;
2100edf8e2afSMika Westerberg     elf->e_phoff = sizeof(struct elfhdr);
2101edf8e2afSMika Westerberg     elf->e_flags = flags;
2102edf8e2afSMika Westerberg     elf->e_ehsize = sizeof(struct elfhdr);
2103edf8e2afSMika Westerberg     elf->e_phentsize = sizeof(struct elf_phdr);
2104edf8e2afSMika Westerberg     elf->e_phnum = segs;
2105edf8e2afSMika Westerberg 
2106edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2107edf8e2afSMika Westerberg     bswap_ehdr(elf);
2108edf8e2afSMika Westerberg #endif
2109edf8e2afSMika Westerberg }
2110edf8e2afSMika Westerberg 
2111edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2112edf8e2afSMika Westerberg {
2113edf8e2afSMika Westerberg     phdr->p_type = PT_NOTE;
2114edf8e2afSMika Westerberg     phdr->p_offset = offset;
2115edf8e2afSMika Westerberg     phdr->p_vaddr = 0;
2116edf8e2afSMika Westerberg     phdr->p_paddr = 0;
2117edf8e2afSMika Westerberg     phdr->p_filesz = sz;
2118edf8e2afSMika Westerberg     phdr->p_memsz = 0;
2119edf8e2afSMika Westerberg     phdr->p_flags = 0;
2120edf8e2afSMika Westerberg     phdr->p_align = 0;
2121edf8e2afSMika Westerberg 
2122edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2123edf8e2afSMika Westerberg     bswap_phdr(phdr);
2124edf8e2afSMika Westerberg #endif
2125edf8e2afSMika Westerberg }
2126edf8e2afSMika Westerberg 
2127edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note)
2128edf8e2afSMika Westerberg {
2129edf8e2afSMika Westerberg     return (note->notesz);
2130edf8e2afSMika Westerberg }
2131edf8e2afSMika Westerberg 
2132a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus,
2133edf8e2afSMika Westerberg     const TaskState *ts, int signr)
2134edf8e2afSMika Westerberg {
2135edf8e2afSMika Westerberg     (void) memset(prstatus, 0, sizeof (*prstatus));
2136edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2137edf8e2afSMika Westerberg     prstatus->pr_pid = ts->ts_tid;
2138edf8e2afSMika Westerberg     prstatus->pr_ppid = getppid();
2139edf8e2afSMika Westerberg     prstatus->pr_pgrp = getpgrp();
2140edf8e2afSMika Westerberg     prstatus->pr_sid = getsid(0);
2141edf8e2afSMika Westerberg 
2142edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2143edf8e2afSMika Westerberg     bswap_prstatus(prstatus);
2144edf8e2afSMika Westerberg #endif
2145edf8e2afSMika Westerberg }
2146edf8e2afSMika Westerberg 
2147a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
2148edf8e2afSMika Westerberg {
2149edf8e2afSMika Westerberg     char *filename, *base_filename;
2150edf8e2afSMika Westerberg     unsigned int i, len;
2151edf8e2afSMika Westerberg 
2152edf8e2afSMika Westerberg     (void) memset(psinfo, 0, sizeof (*psinfo));
2153edf8e2afSMika Westerberg 
2154edf8e2afSMika Westerberg     len = ts->info->arg_end - ts->info->arg_start;
2155edf8e2afSMika Westerberg     if (len >= ELF_PRARGSZ)
2156edf8e2afSMika Westerberg         len = ELF_PRARGSZ - 1;
2157edf8e2afSMika Westerberg     if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2158edf8e2afSMika Westerberg         return -EFAULT;
2159edf8e2afSMika Westerberg     for (i = 0; i < len; i++)
2160edf8e2afSMika Westerberg         if (psinfo->pr_psargs[i] == 0)
2161edf8e2afSMika Westerberg             psinfo->pr_psargs[i] = ' ';
2162edf8e2afSMika Westerberg     psinfo->pr_psargs[len] = 0;
2163edf8e2afSMika Westerberg 
2164edf8e2afSMika Westerberg     psinfo->pr_pid = getpid();
2165edf8e2afSMika Westerberg     psinfo->pr_ppid = getppid();
2166edf8e2afSMika Westerberg     psinfo->pr_pgrp = getpgrp();
2167edf8e2afSMika Westerberg     psinfo->pr_sid = getsid(0);
2168edf8e2afSMika Westerberg     psinfo->pr_uid = getuid();
2169edf8e2afSMika Westerberg     psinfo->pr_gid = getgid();
2170edf8e2afSMika Westerberg 
2171edf8e2afSMika Westerberg     filename = strdup(ts->bprm->filename);
2172edf8e2afSMika Westerberg     base_filename = strdup(basename(filename));
2173edf8e2afSMika Westerberg     (void) strncpy(psinfo->pr_fname, base_filename,
2174edf8e2afSMika Westerberg         sizeof(psinfo->pr_fname));
2175edf8e2afSMika Westerberg     free(base_filename);
2176edf8e2afSMika Westerberg     free(filename);
2177edf8e2afSMika Westerberg 
2178edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2179edf8e2afSMika Westerberg     bswap_psinfo(psinfo);
2180edf8e2afSMika Westerberg #endif
2181edf8e2afSMika Westerberg     return (0);
2182edf8e2afSMika Westerberg }
2183edf8e2afSMika Westerberg 
2184edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2185edf8e2afSMika Westerberg {
2186edf8e2afSMika Westerberg     elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2187edf8e2afSMika Westerberg     elf_addr_t orig_auxv = auxv;
2188edf8e2afSMika Westerberg     abi_ulong val;
2189edf8e2afSMika Westerberg     void *ptr;
2190edf8e2afSMika Westerberg     int i, len;
2191edf8e2afSMika Westerberg 
2192edf8e2afSMika Westerberg     /*
2193edf8e2afSMika Westerberg      * Auxiliary vector is stored in target process stack.  It contains
2194edf8e2afSMika Westerberg      * {type, value} pairs that we need to dump into note.  This is not
2195edf8e2afSMika Westerberg      * strictly necessary but we do it here for sake of completeness.
2196edf8e2afSMika Westerberg      */
2197edf8e2afSMika Westerberg 
2198edf8e2afSMika Westerberg     /* find out lenght of the vector, AT_NULL is terminator */
2199edf8e2afSMika Westerberg     i = len = 0;
2200edf8e2afSMika Westerberg     do {
2201edf8e2afSMika Westerberg         get_user_ual(val, auxv);
2202edf8e2afSMika Westerberg         i += 2;
2203edf8e2afSMika Westerberg         auxv += 2 * sizeof (elf_addr_t);
2204edf8e2afSMika Westerberg     } while (val != AT_NULL);
2205edf8e2afSMika Westerberg     len = i * sizeof (elf_addr_t);
2206edf8e2afSMika Westerberg 
2207edf8e2afSMika Westerberg     /* read in whole auxv vector and copy it to memelfnote */
2208edf8e2afSMika Westerberg     ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2209edf8e2afSMika Westerberg     if (ptr != NULL) {
2210edf8e2afSMika Westerberg         fill_note(note, "CORE", NT_AUXV, len, ptr);
2211edf8e2afSMika Westerberg         unlock_user(ptr, auxv, len);
2212edf8e2afSMika Westerberg     }
2213edf8e2afSMika Westerberg }
2214edf8e2afSMika Westerberg 
2215edf8e2afSMika Westerberg /*
2216edf8e2afSMika Westerberg  * Constructs name of coredump file.  We have following convention
2217edf8e2afSMika Westerberg  * for the name:
2218edf8e2afSMika Westerberg  *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2219edf8e2afSMika Westerberg  *
2220edf8e2afSMika Westerberg  * Returns 0 in case of success, -1 otherwise (errno is set).
2221edf8e2afSMika Westerberg  */
2222edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf,
2223edf8e2afSMika Westerberg     size_t bufsize)
2224edf8e2afSMika Westerberg {
2225edf8e2afSMika Westerberg     char timestamp[64];
2226edf8e2afSMika Westerberg     char *filename = NULL;
2227edf8e2afSMika Westerberg     char *base_filename = NULL;
2228edf8e2afSMika Westerberg     struct timeval tv;
2229edf8e2afSMika Westerberg     struct tm tm;
2230edf8e2afSMika Westerberg 
2231edf8e2afSMika Westerberg     assert(bufsize >= PATH_MAX);
2232edf8e2afSMika Westerberg 
2233edf8e2afSMika Westerberg     if (gettimeofday(&tv, NULL) < 0) {
2234edf8e2afSMika Westerberg         (void) fprintf(stderr, "unable to get current timestamp: %s",
2235edf8e2afSMika Westerberg             strerror(errno));
2236edf8e2afSMika Westerberg         return (-1);
2237edf8e2afSMika Westerberg     }
2238edf8e2afSMika Westerberg 
2239edf8e2afSMika Westerberg     filename = strdup(ts->bprm->filename);
2240edf8e2afSMika Westerberg     base_filename = strdup(basename(filename));
2241edf8e2afSMika Westerberg     (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
2242edf8e2afSMika Westerberg         localtime_r(&tv.tv_sec, &tm));
2243edf8e2afSMika Westerberg     (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
2244edf8e2afSMika Westerberg         base_filename, timestamp, (int)getpid());
2245edf8e2afSMika Westerberg     free(base_filename);
2246edf8e2afSMika Westerberg     free(filename);
2247edf8e2afSMika Westerberg 
2248edf8e2afSMika Westerberg     return (0);
2249edf8e2afSMika Westerberg }
2250edf8e2afSMika Westerberg 
2251edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size)
2252edf8e2afSMika Westerberg {
2253edf8e2afSMika Westerberg     const char *bufp = (const char *)ptr;
2254edf8e2afSMika Westerberg     ssize_t bytes_written, bytes_left;
2255edf8e2afSMika Westerberg     struct rlimit dumpsize;
2256edf8e2afSMika Westerberg     off_t pos;
2257edf8e2afSMika Westerberg 
2258edf8e2afSMika Westerberg     bytes_written = 0;
2259edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
2260edf8e2afSMika Westerberg     if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2261edf8e2afSMika Westerberg         if (errno == ESPIPE) { /* not a seekable stream */
2262edf8e2afSMika Westerberg             bytes_left = size;
2263edf8e2afSMika Westerberg         } else {
2264edf8e2afSMika Westerberg             return pos;
2265edf8e2afSMika Westerberg         }
2266edf8e2afSMika Westerberg     } else {
2267edf8e2afSMika Westerberg         if (dumpsize.rlim_cur <= pos) {
2268edf8e2afSMika Westerberg             return -1;
2269edf8e2afSMika Westerberg         } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2270edf8e2afSMika Westerberg             bytes_left = size;
2271edf8e2afSMika Westerberg         } else {
2272edf8e2afSMika Westerberg             size_t limit_left=dumpsize.rlim_cur - pos;
2273edf8e2afSMika Westerberg             bytes_left = limit_left >= size ? size : limit_left ;
2274edf8e2afSMika Westerberg         }
2275edf8e2afSMika Westerberg     }
2276edf8e2afSMika Westerberg 
2277edf8e2afSMika Westerberg     /*
2278edf8e2afSMika Westerberg      * In normal conditions, single write(2) should do but
2279edf8e2afSMika Westerberg      * in case of socket etc. this mechanism is more portable.
2280edf8e2afSMika Westerberg      */
2281edf8e2afSMika Westerberg     do {
2282edf8e2afSMika Westerberg         bytes_written = write(fd, bufp, bytes_left);
2283edf8e2afSMika Westerberg         if (bytes_written < 0) {
2284edf8e2afSMika Westerberg             if (errno == EINTR)
2285edf8e2afSMika Westerberg                 continue;
2286edf8e2afSMika Westerberg             return (-1);
2287edf8e2afSMika Westerberg         } else if (bytes_written == 0) { /* eof */
2288edf8e2afSMika Westerberg             return (-1);
2289edf8e2afSMika Westerberg         }
2290edf8e2afSMika Westerberg         bufp += bytes_written;
2291edf8e2afSMika Westerberg         bytes_left -= bytes_written;
2292edf8e2afSMika Westerberg     } while (bytes_left > 0);
2293edf8e2afSMika Westerberg 
2294edf8e2afSMika Westerberg     return (0);
2295edf8e2afSMika Westerberg }
2296edf8e2afSMika Westerberg 
2297edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd)
2298edf8e2afSMika Westerberg {
2299edf8e2afSMika Westerberg     struct elf_note en;
2300edf8e2afSMika Westerberg 
2301edf8e2afSMika Westerberg     en.n_namesz = men->namesz;
2302edf8e2afSMika Westerberg     en.n_type = men->type;
2303edf8e2afSMika Westerberg     en.n_descsz = men->datasz;
2304edf8e2afSMika Westerberg 
2305edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2306edf8e2afSMika Westerberg     bswap_note(&en);
2307edf8e2afSMika Westerberg #endif
2308edf8e2afSMika Westerberg 
2309edf8e2afSMika Westerberg     if (dump_write(fd, &en, sizeof(en)) != 0)
2310edf8e2afSMika Westerberg         return (-1);
2311edf8e2afSMika Westerberg     if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2312edf8e2afSMika Westerberg         return (-1);
2313edf8e2afSMika Westerberg     if (dump_write(fd, men->data, men->datasz) != 0)
2314edf8e2afSMika Westerberg         return (-1);
2315edf8e2afSMika Westerberg 
2316edf8e2afSMika Westerberg     return (0);
2317edf8e2afSMika Westerberg }
2318edf8e2afSMika Westerberg 
2319edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
2320edf8e2afSMika Westerberg {
2321edf8e2afSMika Westerberg     TaskState *ts = (TaskState *)env->opaque;
2322edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2323edf8e2afSMika Westerberg 
2324edf8e2afSMika Westerberg     ets = qemu_mallocz(sizeof (*ets));
2325edf8e2afSMika Westerberg     ets->num_notes = 1; /* only prstatus is dumped */
2326edf8e2afSMika Westerberg     fill_prstatus(&ets->prstatus, ts, 0);
2327edf8e2afSMika Westerberg     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2328edf8e2afSMika Westerberg     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
2329edf8e2afSMika Westerberg         &ets->prstatus);
2330edf8e2afSMika Westerberg 
2331edf8e2afSMika Westerberg     TAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
2332edf8e2afSMika Westerberg 
2333edf8e2afSMika Westerberg     info->notes_size += note_size(&ets->notes[0]);
2334edf8e2afSMika Westerberg }
2335edf8e2afSMika Westerberg 
2336edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info,
2337edf8e2afSMika Westerberg     long signr, const CPUState *env)
2338edf8e2afSMika Westerberg {
2339edf8e2afSMika Westerberg #define NUMNOTES 3
2340edf8e2afSMika Westerberg     CPUState *cpu = NULL;
2341edf8e2afSMika Westerberg     TaskState *ts = (TaskState *)env->opaque;
2342edf8e2afSMika Westerberg     int i;
2343edf8e2afSMika Westerberg 
2344edf8e2afSMika Westerberg     (void) memset(info, 0, sizeof (*info));
2345edf8e2afSMika Westerberg 
2346edf8e2afSMika Westerberg     TAILQ_INIT(&info->thread_list);
2347edf8e2afSMika Westerberg 
2348edf8e2afSMika Westerberg     info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote));
2349edf8e2afSMika Westerberg     if (info->notes == NULL)
2350edf8e2afSMika Westerberg         return (-ENOMEM);
2351edf8e2afSMika Westerberg     info->prstatus = qemu_mallocz(sizeof (*info->prstatus));
2352edf8e2afSMika Westerberg     if (info->prstatus == NULL)
2353edf8e2afSMika Westerberg         return (-ENOMEM);
2354edf8e2afSMika Westerberg     info->psinfo = qemu_mallocz(sizeof (*info->psinfo));
2355edf8e2afSMika Westerberg     if (info->prstatus == NULL)
2356edf8e2afSMika Westerberg         return (-ENOMEM);
2357edf8e2afSMika Westerberg 
2358edf8e2afSMika Westerberg     /*
2359edf8e2afSMika Westerberg      * First fill in status (and registers) of current thread
2360edf8e2afSMika Westerberg      * including process info & aux vector.
2361edf8e2afSMika Westerberg      */
2362edf8e2afSMika Westerberg     fill_prstatus(info->prstatus, ts, signr);
2363edf8e2afSMika Westerberg     elf_core_copy_regs(&info->prstatus->pr_reg, env);
2364edf8e2afSMika Westerberg     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
2365edf8e2afSMika Westerberg         sizeof (*info->prstatus), info->prstatus);
2366edf8e2afSMika Westerberg     fill_psinfo(info->psinfo, ts);
2367edf8e2afSMika Westerberg     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
2368edf8e2afSMika Westerberg         sizeof (*info->psinfo), info->psinfo);
2369edf8e2afSMika Westerberg     fill_auxv_note(&info->notes[2], ts);
2370edf8e2afSMika Westerberg     info->numnote = 3;
2371edf8e2afSMika Westerberg 
2372edf8e2afSMika Westerberg     info->notes_size = 0;
2373edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
2374edf8e2afSMika Westerberg         info->notes_size += note_size(&info->notes[i]);
2375edf8e2afSMika Westerberg 
2376edf8e2afSMika Westerberg     /* read and fill status of all threads */
2377edf8e2afSMika Westerberg     cpu_list_lock();
2378edf8e2afSMika Westerberg     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2379edf8e2afSMika Westerberg         if (cpu == thread_env)
2380edf8e2afSMika Westerberg             continue;
2381edf8e2afSMika Westerberg         fill_thread_info(info, cpu);
2382edf8e2afSMika Westerberg     }
2383edf8e2afSMika Westerberg     cpu_list_unlock();
2384edf8e2afSMika Westerberg 
2385edf8e2afSMika Westerberg     return (0);
2386edf8e2afSMika Westerberg }
2387edf8e2afSMika Westerberg 
2388edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info)
2389edf8e2afSMika Westerberg {
2390edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2391edf8e2afSMika Westerberg 
2392edf8e2afSMika Westerberg     while (!TAILQ_EMPTY(&info->thread_list)) {
2393edf8e2afSMika Westerberg         ets = TAILQ_FIRST(&info->thread_list);
2394edf8e2afSMika Westerberg         TAILQ_REMOVE(&info->thread_list, ets, ets_link);
2395edf8e2afSMika Westerberg         qemu_free(ets);
2396edf8e2afSMika Westerberg     }
2397edf8e2afSMika Westerberg 
2398edf8e2afSMika Westerberg     qemu_free(info->prstatus);
2399edf8e2afSMika Westerberg     qemu_free(info->psinfo);
2400edf8e2afSMika Westerberg     qemu_free(info->notes);
2401edf8e2afSMika Westerberg }
2402edf8e2afSMika Westerberg 
2403edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd)
2404edf8e2afSMika Westerberg {
2405edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2406edf8e2afSMika Westerberg     int i, error = 0;
2407edf8e2afSMika Westerberg 
2408edf8e2afSMika Westerberg     /* write prstatus, psinfo and auxv for current thread */
2409edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
2410edf8e2afSMika Westerberg         if ((error = write_note(&info->notes[i], fd)) != 0)
2411edf8e2afSMika Westerberg             return (error);
2412edf8e2afSMika Westerberg 
2413edf8e2afSMika Westerberg     /* write prstatus for each thread */
2414edf8e2afSMika Westerberg     for (ets = info->thread_list.tqh_first; ets != NULL;
2415edf8e2afSMika Westerberg         ets = ets->ets_link.tqe_next) {
2416edf8e2afSMika Westerberg         if ((error = write_note(&ets->notes[0], fd)) != 0)
2417edf8e2afSMika Westerberg             return (error);
2418edf8e2afSMika Westerberg     }
2419edf8e2afSMika Westerberg 
2420edf8e2afSMika Westerberg     return (0);
2421edf8e2afSMika Westerberg }
2422edf8e2afSMika Westerberg 
2423edf8e2afSMika Westerberg /*
2424edf8e2afSMika Westerberg  * Write out ELF coredump.
2425edf8e2afSMika Westerberg  *
2426edf8e2afSMika Westerberg  * See documentation of ELF object file format in:
2427edf8e2afSMika Westerberg  * http://www.caldera.com/developers/devspecs/gabi41.pdf
2428edf8e2afSMika Westerberg  *
2429edf8e2afSMika Westerberg  * Coredump format in linux is following:
2430edf8e2afSMika Westerberg  *
2431edf8e2afSMika Westerberg  * 0   +----------------------+         \
2432edf8e2afSMika Westerberg  *     | ELF header           | ET_CORE  |
2433edf8e2afSMika Westerberg  *     +----------------------+          |
2434edf8e2afSMika Westerberg  *     | ELF program headers  |          |--- headers
2435edf8e2afSMika Westerberg  *     | - NOTE section       |          |
2436edf8e2afSMika Westerberg  *     | - PT_LOAD sections   |          |
2437edf8e2afSMika Westerberg  *     +----------------------+         /
2438edf8e2afSMika Westerberg  *     | NOTEs:               |
2439edf8e2afSMika Westerberg  *     | - NT_PRSTATUS        |
2440edf8e2afSMika Westerberg  *     | - NT_PRSINFO         |
2441edf8e2afSMika Westerberg  *     | - NT_AUXV            |
2442edf8e2afSMika Westerberg  *     +----------------------+ <-- aligned to target page
2443edf8e2afSMika Westerberg  *     | Process memory dump  |
2444edf8e2afSMika Westerberg  *     :                      :
2445edf8e2afSMika Westerberg  *     .                      .
2446edf8e2afSMika Westerberg  *     :                      :
2447edf8e2afSMika Westerberg  *     |                      |
2448edf8e2afSMika Westerberg  *     +----------------------+
2449edf8e2afSMika Westerberg  *
2450edf8e2afSMika Westerberg  * NT_PRSTATUS -> struct elf_prstatus (per thread)
2451edf8e2afSMika Westerberg  * NT_PRSINFO  -> struct elf_prpsinfo
2452edf8e2afSMika Westerberg  * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2453edf8e2afSMika Westerberg  *
2454edf8e2afSMika Westerberg  * Format follows System V format as close as possible.  Current
2455edf8e2afSMika Westerberg  * version limitations are as follows:
2456edf8e2afSMika Westerberg  *     - no floating point registers are dumped
2457edf8e2afSMika Westerberg  *
2458edf8e2afSMika Westerberg  * Function returns 0 in case of success, negative errno otherwise.
2459edf8e2afSMika Westerberg  *
2460edf8e2afSMika Westerberg  * TODO: make this work also during runtime: it should be
2461edf8e2afSMika Westerberg  * possible to force coredump from running process and then
2462edf8e2afSMika Westerberg  * continue processing.  For example qemu could set up SIGUSR2
2463edf8e2afSMika Westerberg  * handler (provided that target process haven't registered
2464edf8e2afSMika Westerberg  * handler for that) that does the dump when signal is received.
2465edf8e2afSMika Westerberg  */
2466edf8e2afSMika Westerberg static int elf_core_dump(int signr, const CPUState *env)
2467edf8e2afSMika Westerberg {
2468edf8e2afSMika Westerberg     const TaskState *ts = (const TaskState *)env->opaque;
2469edf8e2afSMika Westerberg     struct vm_area_struct *vma = NULL;
2470edf8e2afSMika Westerberg     char corefile[PATH_MAX];
2471edf8e2afSMika Westerberg     struct elf_note_info info;
2472edf8e2afSMika Westerberg     struct elfhdr elf;
2473edf8e2afSMika Westerberg     struct elf_phdr phdr;
2474edf8e2afSMika Westerberg     struct rlimit dumpsize;
2475edf8e2afSMika Westerberg     struct mm_struct *mm = NULL;
2476edf8e2afSMika Westerberg     off_t offset = 0, data_offset = 0;
2477edf8e2afSMika Westerberg     int segs = 0;
2478edf8e2afSMika Westerberg     int fd = -1;
2479edf8e2afSMika Westerberg 
2480edf8e2afSMika Westerberg     errno = 0;
2481edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
2482edf8e2afSMika Westerberg     if (dumpsize.rlim_cur == 0)
2483edf8e2afSMika Westerberg        return 0;
2484edf8e2afSMika Westerberg 
2485edf8e2afSMika Westerberg     if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2486edf8e2afSMika Westerberg         return (-errno);
2487edf8e2afSMika Westerberg 
2488edf8e2afSMika Westerberg     if ((fd = open(corefile, O_WRONLY | O_CREAT,
2489edf8e2afSMika Westerberg         S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
2490edf8e2afSMika Westerberg         return (-errno);
2491edf8e2afSMika Westerberg 
2492edf8e2afSMika Westerberg     /*
2493edf8e2afSMika Westerberg      * Walk through target process memory mappings and
2494edf8e2afSMika Westerberg      * set up structure containing this information.  After
2495edf8e2afSMika Westerberg      * this point vma_xxx functions can be used.
2496edf8e2afSMika Westerberg      */
2497edf8e2afSMika Westerberg     if ((mm = vma_init()) == NULL)
2498edf8e2afSMika Westerberg         goto out;
2499edf8e2afSMika Westerberg 
2500edf8e2afSMika Westerberg     walk_memory_regions(mm, vma_walker);
2501edf8e2afSMika Westerberg     segs = vma_get_mapping_count(mm);
2502edf8e2afSMika Westerberg 
2503edf8e2afSMika Westerberg     /*
2504edf8e2afSMika Westerberg      * Construct valid coredump ELF header.  We also
2505edf8e2afSMika Westerberg      * add one more segment for notes.
2506edf8e2afSMika Westerberg      */
2507edf8e2afSMika Westerberg     fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2508edf8e2afSMika Westerberg     if (dump_write(fd, &elf, sizeof (elf)) != 0)
2509edf8e2afSMika Westerberg         goto out;
2510edf8e2afSMika Westerberg 
2511edf8e2afSMika Westerberg     /* fill in in-memory version of notes */
2512edf8e2afSMika Westerberg     if (fill_note_info(&info, signr, env) < 0)
2513edf8e2afSMika Westerberg         goto out;
2514edf8e2afSMika Westerberg 
2515edf8e2afSMika Westerberg     offset += sizeof (elf);                             /* elf header */
2516edf8e2afSMika Westerberg     offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */
2517edf8e2afSMika Westerberg 
2518edf8e2afSMika Westerberg     /* write out notes program header */
2519edf8e2afSMika Westerberg     fill_elf_note_phdr(&phdr, info.notes_size, offset);
2520edf8e2afSMika Westerberg 
2521edf8e2afSMika Westerberg     offset += info.notes_size;
2522edf8e2afSMika Westerberg     if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2523edf8e2afSMika Westerberg         goto out;
2524edf8e2afSMika Westerberg 
2525edf8e2afSMika Westerberg     /*
2526edf8e2afSMika Westerberg      * ELF specification wants data to start at page boundary so
2527edf8e2afSMika Westerberg      * we align it here.
2528edf8e2afSMika Westerberg      */
2529edf8e2afSMika Westerberg     offset = roundup(offset, ELF_EXEC_PAGESIZE);
2530edf8e2afSMika Westerberg 
2531edf8e2afSMika Westerberg     /*
2532edf8e2afSMika Westerberg      * Write program headers for memory regions mapped in
2533edf8e2afSMika Westerberg      * the target process.
2534edf8e2afSMika Westerberg      */
2535edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2536edf8e2afSMika Westerberg         (void) memset(&phdr, 0, sizeof (phdr));
2537edf8e2afSMika Westerberg 
2538edf8e2afSMika Westerberg         phdr.p_type = PT_LOAD;
2539edf8e2afSMika Westerberg         phdr.p_offset = offset;
2540edf8e2afSMika Westerberg         phdr.p_vaddr = vma->vma_start;
2541edf8e2afSMika Westerberg         phdr.p_paddr = 0;
2542edf8e2afSMika Westerberg         phdr.p_filesz = vma_dump_size(vma);
2543edf8e2afSMika Westerberg         offset += phdr.p_filesz;
2544edf8e2afSMika Westerberg         phdr.p_memsz = vma->vma_end - vma->vma_start;
2545edf8e2afSMika Westerberg         phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2546edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_WRITE)
2547edf8e2afSMika Westerberg             phdr.p_flags |= PF_W;
2548edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_EXEC)
2549edf8e2afSMika Westerberg             phdr.p_flags |= PF_X;
2550edf8e2afSMika Westerberg         phdr.p_align = ELF_EXEC_PAGESIZE;
2551edf8e2afSMika Westerberg 
2552edf8e2afSMika Westerberg         dump_write(fd, &phdr, sizeof (phdr));
2553edf8e2afSMika Westerberg     }
2554edf8e2afSMika Westerberg 
2555edf8e2afSMika Westerberg     /*
2556edf8e2afSMika Westerberg      * Next we write notes just after program headers.  No
2557edf8e2afSMika Westerberg      * alignment needed here.
2558edf8e2afSMika Westerberg      */
2559edf8e2afSMika Westerberg     if (write_note_info(&info, fd) < 0)
2560edf8e2afSMika Westerberg         goto out;
2561edf8e2afSMika Westerberg 
2562edf8e2afSMika Westerberg     /* align data to page boundary */
2563edf8e2afSMika Westerberg     data_offset = lseek(fd, 0, SEEK_CUR);
2564edf8e2afSMika Westerberg     data_offset = TARGET_PAGE_ALIGN(data_offset);
2565edf8e2afSMika Westerberg     if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2566edf8e2afSMika Westerberg         goto out;
2567edf8e2afSMika Westerberg 
2568edf8e2afSMika Westerberg     /*
2569edf8e2afSMika Westerberg      * Finally we can dump process memory into corefile as well.
2570edf8e2afSMika Westerberg      */
2571edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2572edf8e2afSMika Westerberg         abi_ulong addr;
2573edf8e2afSMika Westerberg         abi_ulong end;
2574edf8e2afSMika Westerberg 
2575edf8e2afSMika Westerberg         end = vma->vma_start + vma_dump_size(vma);
2576edf8e2afSMika Westerberg 
2577edf8e2afSMika Westerberg         for (addr = vma->vma_start; addr < end;
2578edf8e2afSMika Westerberg             addr += TARGET_PAGE_SIZE) {
2579edf8e2afSMika Westerberg             char page[TARGET_PAGE_SIZE];
2580edf8e2afSMika Westerberg             int error;
2581edf8e2afSMika Westerberg 
2582edf8e2afSMika Westerberg             /*
2583edf8e2afSMika Westerberg              *  Read in page from target process memory and
2584edf8e2afSMika Westerberg              *  write it to coredump file.
2585edf8e2afSMika Westerberg              */
2586edf8e2afSMika Westerberg             error = copy_from_user(page, addr, sizeof (page));
2587edf8e2afSMika Westerberg             if (error != 0) {
2588edf8e2afSMika Westerberg                 (void) fprintf(stderr, "unable to dump " TARGET_FMT_lx "\n",
2589edf8e2afSMika Westerberg                     addr);
2590edf8e2afSMika Westerberg                 errno = -error;
2591edf8e2afSMika Westerberg                 goto out;
2592edf8e2afSMika Westerberg             }
2593edf8e2afSMika Westerberg             if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2594edf8e2afSMika Westerberg                 goto out;
2595edf8e2afSMika Westerberg         }
2596edf8e2afSMika Westerberg     }
2597edf8e2afSMika Westerberg 
2598edf8e2afSMika Westerberg out:
2599edf8e2afSMika Westerberg     free_note_info(&info);
2600edf8e2afSMika Westerberg     if (mm != NULL)
2601edf8e2afSMika Westerberg         vma_delete(mm);
2602edf8e2afSMika Westerberg     (void) close(fd);
2603edf8e2afSMika Westerberg 
2604edf8e2afSMika Westerberg     if (errno != 0)
2605edf8e2afSMika Westerberg         return (-errno);
2606edf8e2afSMika Westerberg     return (0);
2607edf8e2afSMika Westerberg }
2608edf8e2afSMika Westerberg 
2609edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
2610edf8e2afSMika Westerberg 
261131e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd)
261231e31b8aSbellard {
261331e31b8aSbellard     printf("a.out interpreter not yet supported\n");
261431e31b8aSbellard     return(0);
261531e31b8aSbellard }
261631e31b8aSbellard 
2617e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2618e5fe0c52Spbrook {
2619e5fe0c52Spbrook     init_thread(regs, infop);
2620e5fe0c52Spbrook }
2621