xref: /qemu/linux-user/elfload.c (revision c581deda322080e8beb88b2e468d4af54454e4b3)
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 
10021e807faSNathan Froyd typedef target_ulong	target_elf_greg_t;
10121e807faSNathan Froyd #ifdef USE_UID16
10221e807faSNathan Froyd typedef uint16_t	target_uid_t;
10321e807faSNathan Froyd typedef uint16_t	target_gid_t;
10421e807faSNathan Froyd #else
10521e807faSNathan Froyd typedef uint32_t	target_uid_t;
10621e807faSNathan Froyd typedef uint32_t	target_gid_t;
10721e807faSNathan Froyd #endif
10821e807faSNathan Froyd typedef int32_t		target_pid_t;
10921e807faSNathan Froyd 
11030ac07d4Sbellard #ifdef TARGET_I386
11130ac07d4Sbellard 
11215338fd7Sbellard #define ELF_PLATFORM get_elf_platform()
11315338fd7Sbellard 
11415338fd7Sbellard static const char *get_elf_platform(void)
11515338fd7Sbellard {
11615338fd7Sbellard     static char elf_platform[] = "i386";
117d5975363Spbrook     int family = (thread_env->cpuid_version >> 8) & 0xff;
11815338fd7Sbellard     if (family > 6)
11915338fd7Sbellard         family = 6;
12015338fd7Sbellard     if (family >= 3)
12115338fd7Sbellard         elf_platform[1] = '0' + family;
12215338fd7Sbellard     return elf_platform;
12315338fd7Sbellard }
12415338fd7Sbellard 
12515338fd7Sbellard #define ELF_HWCAP get_elf_hwcap()
12615338fd7Sbellard 
12715338fd7Sbellard static uint32_t get_elf_hwcap(void)
12815338fd7Sbellard {
129d5975363Spbrook   return thread_env->cpuid_features;
13015338fd7Sbellard }
13115338fd7Sbellard 
13284409ddbSj_mayer #ifdef TARGET_X86_64
13384409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL
13484409ddbSj_mayer #define elf_check_arch(x) ( ((x) == ELF_ARCH) )
13584409ddbSj_mayer 
13684409ddbSj_mayer #define ELF_CLASS      ELFCLASS64
13784409ddbSj_mayer #define ELF_DATA       ELFDATA2LSB
13884409ddbSj_mayer #define ELF_ARCH       EM_X86_64
13984409ddbSj_mayer 
14084409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
14184409ddbSj_mayer {
14284409ddbSj_mayer     regs->rax = 0;
14384409ddbSj_mayer     regs->rsp = infop->start_stack;
14484409ddbSj_mayer     regs->rip = infop->entry;
14584409ddbSj_mayer }
14684409ddbSj_mayer 
1479edc5d79SMika Westerberg #define ELF_NREG    27
148c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
1499edc5d79SMika Westerberg 
1509edc5d79SMika Westerberg /*
1519edc5d79SMika Westerberg  * Note that ELF_NREG should be 29 as there should be place for
1529edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
1539edc5d79SMika Westerberg  * those.
1549edc5d79SMika Westerberg  *
1559edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
1569edc5d79SMika Westerberg  */
157c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
1589edc5d79SMika Westerberg {
1599edc5d79SMika Westerberg     (*regs)[0] = env->regs[15];
1609edc5d79SMika Westerberg     (*regs)[1] = env->regs[14];
1619edc5d79SMika Westerberg     (*regs)[2] = env->regs[13];
1629edc5d79SMika Westerberg     (*regs)[3] = env->regs[12];
1639edc5d79SMika Westerberg     (*regs)[4] = env->regs[R_EBP];
1649edc5d79SMika Westerberg     (*regs)[5] = env->regs[R_EBX];
1659edc5d79SMika Westerberg     (*regs)[6] = env->regs[11];
1669edc5d79SMika Westerberg     (*regs)[7] = env->regs[10];
1679edc5d79SMika Westerberg     (*regs)[8] = env->regs[9];
1689edc5d79SMika Westerberg     (*regs)[9] = env->regs[8];
1699edc5d79SMika Westerberg     (*regs)[10] = env->regs[R_EAX];
1709edc5d79SMika Westerberg     (*regs)[11] = env->regs[R_ECX];
1719edc5d79SMika Westerberg     (*regs)[12] = env->regs[R_EDX];
1729edc5d79SMika Westerberg     (*regs)[13] = env->regs[R_ESI];
1739edc5d79SMika Westerberg     (*regs)[14] = env->regs[R_EDI];
1749edc5d79SMika Westerberg     (*regs)[15] = env->regs[R_EAX]; /* XXX */
1759edc5d79SMika Westerberg     (*regs)[16] = env->eip;
1769edc5d79SMika Westerberg     (*regs)[17] = env->segs[R_CS].selector & 0xffff;
1779edc5d79SMika Westerberg     (*regs)[18] = env->eflags;
1789edc5d79SMika Westerberg     (*regs)[19] = env->regs[R_ESP];
1799edc5d79SMika Westerberg     (*regs)[20] = env->segs[R_SS].selector & 0xffff;
1809edc5d79SMika Westerberg     (*regs)[21] = env->segs[R_FS].selector & 0xffff;
1819edc5d79SMika Westerberg     (*regs)[22] = env->segs[R_GS].selector & 0xffff;
1829edc5d79SMika Westerberg     (*regs)[23] = env->segs[R_DS].selector & 0xffff;
1839edc5d79SMika Westerberg     (*regs)[24] = env->segs[R_ES].selector & 0xffff;
1849edc5d79SMika Westerberg     (*regs)[25] = env->segs[R_FS].selector & 0xffff;
1859edc5d79SMika Westerberg     (*regs)[26] = env->segs[R_GS].selector & 0xffff;
1869edc5d79SMika Westerberg }
1879edc5d79SMika Westerberg 
18884409ddbSj_mayer #else
18984409ddbSj_mayer 
19030ac07d4Sbellard #define ELF_START_MMAP 0x80000000
19130ac07d4Sbellard 
19230ac07d4Sbellard /*
19330ac07d4Sbellard  * This is used to ensure we don't load something for the wrong architecture.
19430ac07d4Sbellard  */
19530ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
19630ac07d4Sbellard 
19730ac07d4Sbellard /*
19830ac07d4Sbellard  * These are used to set parameters in the core dumps.
19930ac07d4Sbellard  */
20030ac07d4Sbellard #define ELF_CLASS	ELFCLASS32
20130ac07d4Sbellard #define ELF_DATA	ELFDATA2LSB
20230ac07d4Sbellard #define ELF_ARCH	EM_386
20330ac07d4Sbellard 
204e5fe0c52Spbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
205e5fe0c52Spbrook {
206e5fe0c52Spbrook     regs->esp = infop->start_stack;
207e5fe0c52Spbrook     regs->eip = infop->entry;
208e5fe0c52Spbrook 
20930ac07d4Sbellard     /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
21030ac07d4Sbellard        starts %edx contains a pointer to a function which might be
21130ac07d4Sbellard        registered using `atexit'.  This provides a mean for the
21230ac07d4Sbellard        dynamic linker to call DT_FINI functions for shared libraries
21330ac07d4Sbellard        that have been loaded before the code runs.
21430ac07d4Sbellard 
21530ac07d4Sbellard        A value of 0 tells we have no such handler.  */
216e5fe0c52Spbrook     regs->edx = 0;
217b346ff46Sbellard }
2189edc5d79SMika Westerberg 
2199edc5d79SMika Westerberg #define ELF_NREG    17
220c227f099SAnthony Liguori 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  */
229c227f099SAnthony Liguori 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 
289edf8e2afSMika Westerberg #define ELF_NREG    18
290c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
291edf8e2afSMika Westerberg 
292c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
293edf8e2afSMika Westerberg {
294d049e626SNathan Froyd     (*regs)[0] = tswapl(env->regs[0]);
295d049e626SNathan Froyd     (*regs)[1] = tswapl(env->regs[1]);
296d049e626SNathan Froyd     (*regs)[2] = tswapl(env->regs[2]);
297d049e626SNathan Froyd     (*regs)[3] = tswapl(env->regs[3]);
298d049e626SNathan Froyd     (*regs)[4] = tswapl(env->regs[4]);
299d049e626SNathan Froyd     (*regs)[5] = tswapl(env->regs[5]);
300d049e626SNathan Froyd     (*regs)[6] = tswapl(env->regs[6]);
301d049e626SNathan Froyd     (*regs)[7] = tswapl(env->regs[7]);
302d049e626SNathan Froyd     (*regs)[8] = tswapl(env->regs[8]);
303d049e626SNathan Froyd     (*regs)[9] = tswapl(env->regs[9]);
304d049e626SNathan Froyd     (*regs)[10] = tswapl(env->regs[10]);
305d049e626SNathan Froyd     (*regs)[11] = tswapl(env->regs[11]);
306d049e626SNathan Froyd     (*regs)[12] = tswapl(env->regs[12]);
307d049e626SNathan Froyd     (*regs)[13] = tswapl(env->regs[13]);
308d049e626SNathan Froyd     (*regs)[14] = tswapl(env->regs[14]);
309d049e626SNathan Froyd     (*regs)[15] = tswapl(env->regs[15]);
310edf8e2afSMika Westerberg 
311d049e626SNathan Froyd     (*regs)[16] = tswapl(cpsr_read((CPUState *)env));
312d049e626SNathan Froyd     (*regs)[17] = tswapl(env->regs[0]); /* XXX */
313edf8e2afSMika Westerberg }
314edf8e2afSMika Westerberg 
31530ac07d4Sbellard #define USE_ELF_CORE_DUMP
31630ac07d4Sbellard #define ELF_EXEC_PAGESIZE	4096
31730ac07d4Sbellard 
318afce2927Sbellard enum
319afce2927Sbellard {
320afce2927Sbellard   ARM_HWCAP_ARM_SWP       = 1 << 0,
321afce2927Sbellard   ARM_HWCAP_ARM_HALF      = 1 << 1,
322afce2927Sbellard   ARM_HWCAP_ARM_THUMB     = 1 << 2,
323afce2927Sbellard   ARM_HWCAP_ARM_26BIT     = 1 << 3,
324afce2927Sbellard   ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
325afce2927Sbellard   ARM_HWCAP_ARM_FPA       = 1 << 5,
326afce2927Sbellard   ARM_HWCAP_ARM_VFP       = 1 << 6,
327afce2927Sbellard   ARM_HWCAP_ARM_EDSP      = 1 << 7,
328cf6de34aSRiku Voipio   ARM_HWCAP_ARM_JAVA      = 1 << 8,
329cf6de34aSRiku Voipio   ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
330cf6de34aSRiku Voipio   ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
331cf6de34aSRiku Voipio   ARM_HWCAP_ARM_NEON      = 1 << 11,
332cf6de34aSRiku Voipio   ARM_HWCAP_ARM_VFPv3     = 1 << 12,
333cf6de34aSRiku Voipio   ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
334afce2927Sbellard };
335afce2927Sbellard 
33615338fd7Sbellard #define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF              \
337afce2927Sbellard                     | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT     \
338cf6de34aSRiku Voipio                     | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \
339cf6de34aSRiku Voipio                     | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
340afce2927Sbellard 
34130ac07d4Sbellard #endif
34230ac07d4Sbellard 
343853d6f7aSbellard #ifdef TARGET_SPARC
344a315a145Sbellard #ifdef TARGET_SPARC64
345853d6f7aSbellard 
346853d6f7aSbellard #define ELF_START_MMAP 0x80000000
347853d6f7aSbellard 
348992f48a0Sblueswir1 #ifndef TARGET_ABI32
349cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
350992f48a0Sblueswir1 #else
351992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
352992f48a0Sblueswir1 #endif
353853d6f7aSbellard 
354a315a145Sbellard #define ELF_CLASS   ELFCLASS64
355a315a145Sbellard #define ELF_DATA    ELFDATA2MSB
3565ef54116Sbellard #define ELF_ARCH    EM_SPARCV9
3575ef54116Sbellard 
3585ef54116Sbellard #define STACK_BIAS		2047
359a315a145Sbellard 
360a315a145Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
361a315a145Sbellard {
362992f48a0Sblueswir1 #ifndef TARGET_ABI32
363a315a145Sbellard     regs->tstate = 0;
364992f48a0Sblueswir1 #endif
365a315a145Sbellard     regs->pc = infop->entry;
366a315a145Sbellard     regs->npc = regs->pc + 4;
367a315a145Sbellard     regs->y = 0;
368992f48a0Sblueswir1 #ifdef TARGET_ABI32
369992f48a0Sblueswir1     regs->u_regs[14] = infop->start_stack - 16 * 4;
370992f48a0Sblueswir1 #else
371cb33da57Sblueswir1     if (personality(infop->personality) == PER_LINUX32)
372cb33da57Sblueswir1         regs->u_regs[14] = infop->start_stack - 16 * 4;
373cb33da57Sblueswir1     else
3745ef54116Sbellard         regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
375992f48a0Sblueswir1 #endif
376a315a145Sbellard }
377a315a145Sbellard 
378a315a145Sbellard #else
379a315a145Sbellard #define ELF_START_MMAP 0x80000000
380a315a145Sbellard 
381a315a145Sbellard #define elf_check_arch(x) ( (x) == EM_SPARC )
382a315a145Sbellard 
383853d6f7aSbellard #define ELF_CLASS   ELFCLASS32
384853d6f7aSbellard #define ELF_DATA    ELFDATA2MSB
385853d6f7aSbellard #define ELF_ARCH    EM_SPARC
386853d6f7aSbellard 
387853d6f7aSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
388853d6f7aSbellard {
389f5155289Sbellard     regs->psr = 0;
390f5155289Sbellard     regs->pc = infop->entry;
391f5155289Sbellard     regs->npc = regs->pc + 4;
392f5155289Sbellard     regs->y = 0;
393f5155289Sbellard     regs->u_regs[14] = infop->start_stack - 16 * 4;
394853d6f7aSbellard }
395853d6f7aSbellard 
396853d6f7aSbellard #endif
397a315a145Sbellard #endif
398853d6f7aSbellard 
39967867308Sbellard #ifdef TARGET_PPC
40067867308Sbellard 
40167867308Sbellard #define ELF_START_MMAP 0x80000000
40267867308Sbellard 
403e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
40484409ddbSj_mayer 
40584409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 )
40684409ddbSj_mayer 
40784409ddbSj_mayer #define ELF_CLASS	ELFCLASS64
40884409ddbSj_mayer 
40984409ddbSj_mayer #else
41084409ddbSj_mayer 
41167867308Sbellard #define elf_check_arch(x) ( (x) == EM_PPC )
41267867308Sbellard 
41367867308Sbellard #define ELF_CLASS	ELFCLASS32
41484409ddbSj_mayer 
41584409ddbSj_mayer #endif
41684409ddbSj_mayer 
41767867308Sbellard #ifdef TARGET_WORDS_BIGENDIAN
41867867308Sbellard #define ELF_DATA	ELFDATA2MSB
41967867308Sbellard #else
42067867308Sbellard #define ELF_DATA	ELFDATA2LSB
42167867308Sbellard #endif
42267867308Sbellard #define ELF_ARCH	EM_PPC
42367867308Sbellard 
424df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
425df84e4f3SNathan Froyd    See arch/powerpc/include/asm/cputable.h.  */
426df84e4f3SNathan Froyd enum {
4273efa9a67Smalc     QEMU_PPC_FEATURE_32 = 0x80000000,
4283efa9a67Smalc     QEMU_PPC_FEATURE_64 = 0x40000000,
4293efa9a67Smalc     QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
4303efa9a67Smalc     QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
4313efa9a67Smalc     QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
4323efa9a67Smalc     QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
4333efa9a67Smalc     QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
4343efa9a67Smalc     QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
4353efa9a67Smalc     QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
4363efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
4373efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
4383efa9a67Smalc     QEMU_PPC_FEATURE_NO_TB = 0x00100000,
4393efa9a67Smalc     QEMU_PPC_FEATURE_POWER4 = 0x00080000,
4403efa9a67Smalc     QEMU_PPC_FEATURE_POWER5 = 0x00040000,
4413efa9a67Smalc     QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
4423efa9a67Smalc     QEMU_PPC_FEATURE_CELL = 0x00010000,
4433efa9a67Smalc     QEMU_PPC_FEATURE_BOOKE = 0x00008000,
4443efa9a67Smalc     QEMU_PPC_FEATURE_SMT = 0x00004000,
4453efa9a67Smalc     QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
4463efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
4473efa9a67Smalc     QEMU_PPC_FEATURE_PA6T = 0x00000800,
4483efa9a67Smalc     QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
4493efa9a67Smalc     QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
4503efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
4513efa9a67Smalc     QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
4523efa9a67Smalc     QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
453df84e4f3SNathan Froyd 
4543efa9a67Smalc     QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
4553efa9a67Smalc     QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
456df84e4f3SNathan Froyd };
457df84e4f3SNathan Froyd 
458df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap()
459df84e4f3SNathan Froyd 
460df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void)
461df84e4f3SNathan Froyd {
462df84e4f3SNathan Froyd     CPUState *e = thread_env;
463df84e4f3SNathan Froyd     uint32_t features = 0;
464df84e4f3SNathan Froyd 
465df84e4f3SNathan Froyd     /* We don't have to be terribly complete here; the high points are
466df84e4f3SNathan Froyd        Altivec/FP/SPE support.  Anything else is just a bonus.  */
467df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature)              \
468df84e4f3SNathan Froyd     do {if (e->insns_flags & flag) features |= feature; } while(0)
4693efa9a67Smalc     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
4703efa9a67Smalc     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
4713efa9a67Smalc     GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
4723efa9a67Smalc     GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
4733efa9a67Smalc     GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
4743efa9a67Smalc     GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
4753efa9a67Smalc     GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
4763efa9a67Smalc     GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
477df84e4f3SNathan Froyd #undef GET_FEATURE
478df84e4f3SNathan Froyd 
479df84e4f3SNathan Froyd     return features;
480df84e4f3SNathan Froyd }
481df84e4f3SNathan Froyd 
482f5155289Sbellard /*
483f5155289Sbellard  * We need to put in some extra aux table entries to tell glibc what
484f5155289Sbellard  * the cache block size is, so it can use the dcbz instruction safely.
485f5155289Sbellard  */
486f5155289Sbellard #define AT_DCACHEBSIZE          19
487f5155289Sbellard #define AT_ICACHEBSIZE          20
488f5155289Sbellard #define AT_UCACHEBSIZE          21
489f5155289Sbellard /* A special ignored type value for PPC, for glibc compatibility.  */
490f5155289Sbellard #define AT_IGNOREPPC            22
491f5155289Sbellard /*
492f5155289Sbellard  * The requirements here are:
493f5155289Sbellard  * - keep the final alignment of sp (sp & 0xf)
494f5155289Sbellard  * - make sure the 32-bit value at the first 16 byte aligned position of
495f5155289Sbellard  *   AUXV is greater than 16 for glibc compatibility.
496f5155289Sbellard  *   AT_IGNOREPPC is used for that.
497f5155289Sbellard  * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
498f5155289Sbellard  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
499f5155289Sbellard  */
5000bccf03dSbellard #define DLINFO_ARCH_ITEMS       5
501f5155289Sbellard #define ARCH_DLINFO                                                     \
502f5155289Sbellard do {                                                                    \
5030bccf03dSbellard         NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \
5040bccf03dSbellard         NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \
5050bccf03dSbellard         NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \
506f5155289Sbellard         /*                                                              \
507f5155289Sbellard          * Now handle glibc compatibility.                              \
508f5155289Sbellard          */                                                             \
5090bccf03dSbellard 	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
5100bccf03dSbellard 	NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);			\
511f5155289Sbellard  } while (0)
512f5155289Sbellard 
51367867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
51467867308Sbellard {
51567867308Sbellard     _regs->gpr[1] = infop->start_stack;
516e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
5177983f435SRob Landley     _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_addr;
5187983f435SRob Landley     infop->entry = ldq_raw(infop->entry) + infop->load_addr;
51984409ddbSj_mayer #endif
52067867308Sbellard     _regs->nip = infop->entry;
52167867308Sbellard }
52267867308Sbellard 
523e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h.  */
524e2f3e741SNathan Froyd #define ELF_NREG 48
525e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
526e2f3e741SNathan Froyd 
527e2f3e741SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
528e2f3e741SNathan Froyd {
529e2f3e741SNathan Froyd     int i;
530e2f3e741SNathan Froyd     target_ulong ccr = 0;
531e2f3e741SNathan Froyd 
532e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
533e2f3e741SNathan Froyd         (*regs)[i] = tswapl(env->gpr[i]);
534e2f3e741SNathan Froyd     }
535e2f3e741SNathan Froyd 
536e2f3e741SNathan Froyd     (*regs)[32] = tswapl(env->nip);
537e2f3e741SNathan Froyd     (*regs)[33] = tswapl(env->msr);
538e2f3e741SNathan Froyd     (*regs)[35] = tswapl(env->ctr);
539e2f3e741SNathan Froyd     (*regs)[36] = tswapl(env->lr);
540e2f3e741SNathan Froyd     (*regs)[37] = tswapl(env->xer);
541e2f3e741SNathan Froyd 
542e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
543e2f3e741SNathan Froyd         ccr |= env->crf[i] << (32 - ((i + 1) * 4));
544e2f3e741SNathan Froyd     }
545e2f3e741SNathan Froyd     (*regs)[38] = tswapl(ccr);
546e2f3e741SNathan Froyd }
547e2f3e741SNathan Froyd 
548e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP
54967867308Sbellard #define ELF_EXEC_PAGESIZE	4096
55067867308Sbellard 
55167867308Sbellard #endif
55267867308Sbellard 
553048f6b4dSbellard #ifdef TARGET_MIPS
554048f6b4dSbellard 
555048f6b4dSbellard #define ELF_START_MMAP 0x80000000
556048f6b4dSbellard 
557048f6b4dSbellard #define elf_check_arch(x) ( (x) == EM_MIPS )
558048f6b4dSbellard 
559388bb21aSths #ifdef TARGET_MIPS64
560388bb21aSths #define ELF_CLASS   ELFCLASS64
561388bb21aSths #else
562048f6b4dSbellard #define ELF_CLASS   ELFCLASS32
563388bb21aSths #endif
564048f6b4dSbellard #ifdef TARGET_WORDS_BIGENDIAN
565048f6b4dSbellard #define ELF_DATA	ELFDATA2MSB
566048f6b4dSbellard #else
567048f6b4dSbellard #define ELF_DATA	ELFDATA2LSB
568048f6b4dSbellard #endif
569048f6b4dSbellard #define ELF_ARCH    EM_MIPS
570048f6b4dSbellard 
571048f6b4dSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
572048f6b4dSbellard {
573623a930eSths     regs->cp0_status = 2 << CP0St_KSU;
574048f6b4dSbellard     regs->cp0_epc = infop->entry;
575048f6b4dSbellard     regs->regs[29] = infop->start_stack;
576048f6b4dSbellard }
577048f6b4dSbellard 
57851e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h.  */
57951e52606SNathan Froyd #define ELF_NREG 45
58051e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
58151e52606SNathan Froyd 
58251e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h.  */
58351e52606SNathan Froyd enum {
58451e52606SNathan Froyd #ifdef TARGET_MIPS64
58551e52606SNathan Froyd     TARGET_EF_R0 = 0,
58651e52606SNathan Froyd #else
58751e52606SNathan Froyd     TARGET_EF_R0 = 6,
58851e52606SNathan Froyd #endif
58951e52606SNathan Froyd     TARGET_EF_R26 = TARGET_EF_R0 + 26,
59051e52606SNathan Froyd     TARGET_EF_R27 = TARGET_EF_R0 + 27,
59151e52606SNathan Froyd     TARGET_EF_LO = TARGET_EF_R0 + 32,
59251e52606SNathan Froyd     TARGET_EF_HI = TARGET_EF_R0 + 33,
59351e52606SNathan Froyd     TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
59451e52606SNathan Froyd     TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
59551e52606SNathan Froyd     TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
59651e52606SNathan Froyd     TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
59751e52606SNathan Froyd };
59851e52606SNathan Froyd 
59951e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
60051e52606SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
60151e52606SNathan Froyd {
60251e52606SNathan Froyd     int i;
60351e52606SNathan Froyd 
60451e52606SNathan Froyd     for (i = 0; i < TARGET_EF_R0; i++) {
60551e52606SNathan Froyd         (*regs)[i] = 0;
60651e52606SNathan Froyd     }
60751e52606SNathan Froyd     (*regs)[TARGET_EF_R0] = 0;
60851e52606SNathan Froyd 
60951e52606SNathan Froyd     for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
61051e52606SNathan Froyd         (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]);
61151e52606SNathan Froyd     }
61251e52606SNathan Froyd 
61351e52606SNathan Froyd     (*regs)[TARGET_EF_R26] = 0;
61451e52606SNathan Froyd     (*regs)[TARGET_EF_R27] = 0;
61551e52606SNathan Froyd     (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]);
61651e52606SNathan Froyd     (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]);
61751e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC);
61851e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr);
61951e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status);
62051e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause);
62151e52606SNathan Froyd }
62251e52606SNathan Froyd 
62351e52606SNathan Froyd #define USE_ELF_CORE_DUMP
624388bb21aSths #define ELF_EXEC_PAGESIZE        4096
625388bb21aSths 
626048f6b4dSbellard #endif /* TARGET_MIPS */
627048f6b4dSbellard 
628b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE
629b779e29eSEdgar E. Iglesias 
630b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000
631b779e29eSEdgar E. Iglesias 
632b779e29eSEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE )
633b779e29eSEdgar E. Iglesias 
634b779e29eSEdgar E. Iglesias #define ELF_CLASS   ELFCLASS32
635b779e29eSEdgar E. Iglesias #define ELF_DATA	ELFDATA2MSB
6360ddbc96eSMike Frysinger #define ELF_ARCH    EM_XILINX_MICROBLAZE
637b779e29eSEdgar E. Iglesias 
638b779e29eSEdgar E. Iglesias static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
639b779e29eSEdgar E. Iglesias {
640b779e29eSEdgar E. Iglesias     regs->pc = infop->entry;
641b779e29eSEdgar E. Iglesias     regs->r1 = infop->start_stack;
642b779e29eSEdgar E. Iglesias 
643b779e29eSEdgar E. Iglesias }
644b779e29eSEdgar E. Iglesias 
645b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE        4096
646b779e29eSEdgar E. Iglesias 
647b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */
648b779e29eSEdgar E. Iglesias 
649fdf9b3e8Sbellard #ifdef TARGET_SH4
650fdf9b3e8Sbellard 
651fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000
652fdf9b3e8Sbellard 
653fdf9b3e8Sbellard #define elf_check_arch(x) ( (x) == EM_SH )
654fdf9b3e8Sbellard 
655fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32
656fdf9b3e8Sbellard #define ELF_DATA  ELFDATA2LSB
657fdf9b3e8Sbellard #define ELF_ARCH  EM_SH
658fdf9b3e8Sbellard 
659fdf9b3e8Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
660fdf9b3e8Sbellard {
661fdf9b3e8Sbellard   /* Check other registers XXXXX */
662fdf9b3e8Sbellard   regs->pc = infop->entry;
663072ae847Sths   regs->regs[15] = infop->start_stack;
664fdf9b3e8Sbellard }
665fdf9b3e8Sbellard 
6667631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h.  */
6677631c97eSNathan Froyd #define ELF_NREG 23
6687631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
6697631c97eSNathan Froyd 
6707631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h.  */
6717631c97eSNathan Froyd enum {
6727631c97eSNathan Froyd     TARGET_REG_PC = 16,
6737631c97eSNathan Froyd     TARGET_REG_PR = 17,
6747631c97eSNathan Froyd     TARGET_REG_SR = 18,
6757631c97eSNathan Froyd     TARGET_REG_GBR = 19,
6767631c97eSNathan Froyd     TARGET_REG_MACH = 20,
6777631c97eSNathan Froyd     TARGET_REG_MACL = 21,
6787631c97eSNathan Froyd     TARGET_REG_SYSCALL = 22
6797631c97eSNathan Froyd };
6807631c97eSNathan Froyd 
6817631c97eSNathan Froyd static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
6827631c97eSNathan Froyd {
6837631c97eSNathan Froyd     int i;
6847631c97eSNathan Froyd 
6857631c97eSNathan Froyd     for (i = 0; i < 16; i++) {
6867631c97eSNathan Froyd         (*regs[i]) = tswapl(env->gregs[i]);
6877631c97eSNathan Froyd     }
6887631c97eSNathan Froyd 
6897631c97eSNathan Froyd     (*regs)[TARGET_REG_PC] = tswapl(env->pc);
6907631c97eSNathan Froyd     (*regs)[TARGET_REG_PR] = tswapl(env->pr);
6917631c97eSNathan Froyd     (*regs)[TARGET_REG_SR] = tswapl(env->sr);
6927631c97eSNathan Froyd     (*regs)[TARGET_REG_GBR] = tswapl(env->gbr);
6937631c97eSNathan Froyd     (*regs)[TARGET_REG_MACH] = tswapl(env->mach);
6947631c97eSNathan Froyd     (*regs)[TARGET_REG_MACL] = tswapl(env->macl);
6957631c97eSNathan Froyd     (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
6967631c97eSNathan Froyd }
6977631c97eSNathan Froyd 
6987631c97eSNathan Froyd #define USE_ELF_CORE_DUMP
699fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE        4096
700fdf9b3e8Sbellard 
701fdf9b3e8Sbellard #endif
702fdf9b3e8Sbellard 
70348733d19Sths #ifdef TARGET_CRIS
70448733d19Sths 
70548733d19Sths #define ELF_START_MMAP 0x80000000
70648733d19Sths 
70748733d19Sths #define elf_check_arch(x) ( (x) == EM_CRIS )
70848733d19Sths 
70948733d19Sths #define ELF_CLASS ELFCLASS32
71048733d19Sths #define ELF_DATA  ELFDATA2LSB
71148733d19Sths #define ELF_ARCH  EM_CRIS
71248733d19Sths 
71348733d19Sths static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
71448733d19Sths {
71548733d19Sths   regs->erp = infop->entry;
71648733d19Sths }
71748733d19Sths 
71848733d19Sths #define ELF_EXEC_PAGESIZE        8192
71948733d19Sths 
72048733d19Sths #endif
72148733d19Sths 
722e6e5906bSpbrook #ifdef TARGET_M68K
723e6e5906bSpbrook 
724e6e5906bSpbrook #define ELF_START_MMAP 0x80000000
725e6e5906bSpbrook 
726e6e5906bSpbrook #define elf_check_arch(x) ( (x) == EM_68K )
727e6e5906bSpbrook 
728e6e5906bSpbrook #define ELF_CLASS	ELFCLASS32
729e6e5906bSpbrook #define ELF_DATA	ELFDATA2MSB
730e6e5906bSpbrook #define ELF_ARCH	EM_68K
731e6e5906bSpbrook 
732e6e5906bSpbrook /* ??? Does this need to do anything?
733e6e5906bSpbrook #define ELF_PLAT_INIT(_r) */
734e6e5906bSpbrook 
735e6e5906bSpbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
736e6e5906bSpbrook {
737e6e5906bSpbrook     regs->usp = infop->start_stack;
738e6e5906bSpbrook     regs->sr = 0;
739e6e5906bSpbrook     regs->pc = infop->entry;
740e6e5906bSpbrook }
741e6e5906bSpbrook 
7427a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h.  */
7437a93cc55SNathan Froyd #define ELF_NREG 20
7447a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
7457a93cc55SNathan Froyd 
7467a93cc55SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
7477a93cc55SNathan Froyd {
7487a93cc55SNathan Froyd     (*regs)[0] = tswapl(env->dregs[1]);
7497a93cc55SNathan Froyd     (*regs)[1] = tswapl(env->dregs[2]);
7507a93cc55SNathan Froyd     (*regs)[2] = tswapl(env->dregs[3]);
7517a93cc55SNathan Froyd     (*regs)[3] = tswapl(env->dregs[4]);
7527a93cc55SNathan Froyd     (*regs)[4] = tswapl(env->dregs[5]);
7537a93cc55SNathan Froyd     (*regs)[5] = tswapl(env->dregs[6]);
7547a93cc55SNathan Froyd     (*regs)[6] = tswapl(env->dregs[7]);
7557a93cc55SNathan Froyd     (*regs)[7] = tswapl(env->aregs[0]);
7567a93cc55SNathan Froyd     (*regs)[8] = tswapl(env->aregs[1]);
7577a93cc55SNathan Froyd     (*regs)[9] = tswapl(env->aregs[2]);
7587a93cc55SNathan Froyd     (*regs)[10] = tswapl(env->aregs[3]);
7597a93cc55SNathan Froyd     (*regs)[11] = tswapl(env->aregs[4]);
7607a93cc55SNathan Froyd     (*regs)[12] = tswapl(env->aregs[5]);
7617a93cc55SNathan Froyd     (*regs)[13] = tswapl(env->aregs[6]);
7627a93cc55SNathan Froyd     (*regs)[14] = tswapl(env->dregs[0]);
7637a93cc55SNathan Froyd     (*regs)[15] = tswapl(env->aregs[7]);
7647a93cc55SNathan Froyd     (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */
7657a93cc55SNathan Froyd     (*regs)[17] = tswapl(env->sr);
7667a93cc55SNathan Froyd     (*regs)[18] = tswapl(env->pc);
7677a93cc55SNathan Froyd     (*regs)[19] = 0;  /* FIXME: regs->format | regs->vector */
7687a93cc55SNathan Froyd }
7697a93cc55SNathan Froyd 
7707a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP
771e6e5906bSpbrook #define ELF_EXEC_PAGESIZE	8192
772e6e5906bSpbrook 
773e6e5906bSpbrook #endif
774e6e5906bSpbrook 
7757a3148a9Sj_mayer #ifdef TARGET_ALPHA
7767a3148a9Sj_mayer 
7777a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL)
7787a3148a9Sj_mayer 
7797a3148a9Sj_mayer #define elf_check_arch(x) ( (x) == ELF_ARCH )
7807a3148a9Sj_mayer 
7817a3148a9Sj_mayer #define ELF_CLASS      ELFCLASS64
7827a3148a9Sj_mayer #define ELF_DATA       ELFDATA2MSB
7837a3148a9Sj_mayer #define ELF_ARCH       EM_ALPHA
7847a3148a9Sj_mayer 
7857a3148a9Sj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
7867a3148a9Sj_mayer {
7877a3148a9Sj_mayer     regs->pc = infop->entry;
7887a3148a9Sj_mayer     regs->ps = 8;
7897a3148a9Sj_mayer     regs->usp = infop->start_stack;
7907a3148a9Sj_mayer }
7917a3148a9Sj_mayer 
7927a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE        8192
7937a3148a9Sj_mayer 
7947a3148a9Sj_mayer #endif /* TARGET_ALPHA */
7957a3148a9Sj_mayer 
79615338fd7Sbellard #ifndef ELF_PLATFORM
79715338fd7Sbellard #define ELF_PLATFORM (NULL)
79815338fd7Sbellard #endif
79915338fd7Sbellard 
80015338fd7Sbellard #ifndef ELF_HWCAP
80115338fd7Sbellard #define ELF_HWCAP 0
80215338fd7Sbellard #endif
80315338fd7Sbellard 
804992f48a0Sblueswir1 #ifdef TARGET_ABI32
805cb33da57Sblueswir1 #undef ELF_CLASS
806992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32
807cb33da57Sblueswir1 #undef bswaptls
808cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr)
809cb33da57Sblueswir1 #endif
810cb33da57Sblueswir1 
81131e31b8aSbellard #include "elf.h"
81209bfb054Sbellard 
81309bfb054Sbellard struct exec
81409bfb054Sbellard {
81509bfb054Sbellard   unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
81609bfb054Sbellard   unsigned int a_text;   /* length of text, in bytes */
81709bfb054Sbellard   unsigned int a_data;   /* length of data, in bytes */
81809bfb054Sbellard   unsigned int a_bss;    /* length of uninitialized data area, in bytes */
81909bfb054Sbellard   unsigned int a_syms;   /* length of symbol table data in file, in bytes */
82009bfb054Sbellard   unsigned int a_entry;  /* start address */
82109bfb054Sbellard   unsigned int a_trsize; /* length of relocation info for text, in bytes */
82209bfb054Sbellard   unsigned int a_drsize; /* length of relocation info for data, in bytes */
82309bfb054Sbellard };
82409bfb054Sbellard 
82509bfb054Sbellard 
82609bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff)
82709bfb054Sbellard #define OMAGIC 0407
82809bfb054Sbellard #define NMAGIC 0410
82909bfb054Sbellard #define ZMAGIC 0413
83009bfb054Sbellard #define QMAGIC 0314
83109bfb054Sbellard 
83209bfb054Sbellard /* max code+data+bss space allocated to elf interpreter */
83309bfb054Sbellard #define INTERP_MAP_SIZE (32 * 1024 * 1024)
83409bfb054Sbellard 
83509bfb054Sbellard /* max code+data+bss+brk space allocated to ET_DYN executables */
83609bfb054Sbellard #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
83709bfb054Sbellard 
83831e31b8aSbellard /* Necessary parameters */
83954936004Sbellard #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
84054936004Sbellard #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
84154936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
84231e31b8aSbellard 
84331e31b8aSbellard #define INTERPRETER_NONE 0
84431e31b8aSbellard #define INTERPRETER_AOUT 1
84531e31b8aSbellard #define INTERPRETER_ELF 2
84631e31b8aSbellard 
84715338fd7Sbellard #define DLINFO_ITEMS 12
84831e31b8aSbellard 
84909bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
85009bfb054Sbellard {
85109bfb054Sbellard 	memcpy(to, from, n);
85209bfb054Sbellard }
85309bfb054Sbellard 
85431e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd);
85531e31b8aSbellard 
85631e31b8aSbellard #ifdef BSWAP_NEEDED
85792a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr)
85831e31b8aSbellard {
85931e31b8aSbellard     bswap16s(&ehdr->e_type);			/* Object file type */
86031e31b8aSbellard     bswap16s(&ehdr->e_machine);		/* Architecture */
86131e31b8aSbellard     bswap32s(&ehdr->e_version);		/* Object file version */
86292a31b1fSbellard     bswaptls(&ehdr->e_entry);		/* Entry point virtual address */
86392a31b1fSbellard     bswaptls(&ehdr->e_phoff);		/* Program header table file offset */
86492a31b1fSbellard     bswaptls(&ehdr->e_shoff);		/* Section header table file offset */
86531e31b8aSbellard     bswap32s(&ehdr->e_flags);		/* Processor-specific flags */
86631e31b8aSbellard     bswap16s(&ehdr->e_ehsize);		/* ELF header size in bytes */
86731e31b8aSbellard     bswap16s(&ehdr->e_phentsize);		/* Program header table entry size */
86831e31b8aSbellard     bswap16s(&ehdr->e_phnum);		/* Program header table entry count */
86931e31b8aSbellard     bswap16s(&ehdr->e_shentsize);		/* Section header table entry size */
87031e31b8aSbellard     bswap16s(&ehdr->e_shnum);		/* Section header table entry count */
87131e31b8aSbellard     bswap16s(&ehdr->e_shstrndx);		/* Section header string table index */
87231e31b8aSbellard }
87331e31b8aSbellard 
87492a31b1fSbellard static void bswap_phdr(struct elf_phdr *phdr)
87531e31b8aSbellard {
87631e31b8aSbellard     bswap32s(&phdr->p_type);			/* Segment type */
87792a31b1fSbellard     bswaptls(&phdr->p_offset);		/* Segment file offset */
87892a31b1fSbellard     bswaptls(&phdr->p_vaddr);		/* Segment virtual address */
87992a31b1fSbellard     bswaptls(&phdr->p_paddr);		/* Segment physical address */
88092a31b1fSbellard     bswaptls(&phdr->p_filesz);		/* Segment size in file */
88192a31b1fSbellard     bswaptls(&phdr->p_memsz);		/* Segment size in memory */
88231e31b8aSbellard     bswap32s(&phdr->p_flags);		/* Segment flags */
88392a31b1fSbellard     bswaptls(&phdr->p_align);		/* Segment alignment */
88431e31b8aSbellard }
885689f936fSbellard 
88692a31b1fSbellard static void bswap_shdr(struct elf_shdr *shdr)
887689f936fSbellard {
888689f936fSbellard     bswap32s(&shdr->sh_name);
889689f936fSbellard     bswap32s(&shdr->sh_type);
89092a31b1fSbellard     bswaptls(&shdr->sh_flags);
89192a31b1fSbellard     bswaptls(&shdr->sh_addr);
89292a31b1fSbellard     bswaptls(&shdr->sh_offset);
89392a31b1fSbellard     bswaptls(&shdr->sh_size);
894689f936fSbellard     bswap32s(&shdr->sh_link);
895689f936fSbellard     bswap32s(&shdr->sh_info);
89692a31b1fSbellard     bswaptls(&shdr->sh_addralign);
89792a31b1fSbellard     bswaptls(&shdr->sh_entsize);
898689f936fSbellard }
899689f936fSbellard 
9007a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym)
901689f936fSbellard {
902689f936fSbellard     bswap32s(&sym->st_name);
9037a3148a9Sj_mayer     bswaptls(&sym->st_value);
9047a3148a9Sj_mayer     bswaptls(&sym->st_size);
905689f936fSbellard     bswap16s(&sym->st_shndx);
906689f936fSbellard }
90731e31b8aSbellard #endif
90831e31b8aSbellard 
909edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
910edf8e2afSMika Westerberg static int elf_core_dump(int, const CPUState *);
911edf8e2afSMika Westerberg 
912edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
913edf8e2afSMika Westerberg static void bswap_note(struct elf_note *en)
914edf8e2afSMika Westerberg {
9159fdca5aaSmalc     bswap32s(&en->n_namesz);
9169fdca5aaSmalc     bswap32s(&en->n_descsz);
9179fdca5aaSmalc     bswap32s(&en->n_type);
918edf8e2afSMika Westerberg }
919edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
920edf8e2afSMika Westerberg 
921edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
922edf8e2afSMika Westerberg 
92331e31b8aSbellard /*
924e5fe0c52Spbrook  * 'copy_elf_strings()' copies argument/envelope strings from user
92531e31b8aSbellard  * memory to free pages in kernel mem. These are in a format ready
92631e31b8aSbellard  * to be put directly into the top of new user memory.
92731e31b8aSbellard  *
92831e31b8aSbellard  */
929992f48a0Sblueswir1 static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
930992f48a0Sblueswir1                                   abi_ulong p)
93131e31b8aSbellard {
93231e31b8aSbellard     char *tmp, *tmp1, *pag = NULL;
93331e31b8aSbellard     int len, offset = 0;
93431e31b8aSbellard 
93531e31b8aSbellard     if (!p) {
93631e31b8aSbellard 	return 0;       /* bullet-proofing */
93731e31b8aSbellard     }
93831e31b8aSbellard     while (argc-- > 0) {
939edf779ffSbellard         tmp = argv[argc];
940edf779ffSbellard         if (!tmp) {
94131e31b8aSbellard 	    fprintf(stderr, "VFS: argc is wrong");
94231e31b8aSbellard 	    exit(-1);
94331e31b8aSbellard 	}
944edf779ffSbellard         tmp1 = tmp;
945edf779ffSbellard 	while (*tmp++);
94631e31b8aSbellard 	len = tmp - tmp1;
94731e31b8aSbellard 	if (p < len) {  /* this shouldn't happen - 128kB */
94831e31b8aSbellard 		return 0;
94931e31b8aSbellard 	}
95031e31b8aSbellard 	while (len) {
95131e31b8aSbellard 	    --p; --tmp; --len;
95231e31b8aSbellard 	    if (--offset < 0) {
95354936004Sbellard 		offset = p % TARGET_PAGE_SIZE;
95444a91caeSbellard                 pag = (char *)page[p/TARGET_PAGE_SIZE];
95544a91caeSbellard                 if (!pag) {
95653a5960aSpbrook                     pag = (char *)malloc(TARGET_PAGE_SIZE);
9574118a970Sj_mayer                     memset(pag, 0, TARGET_PAGE_SIZE);
95853a5960aSpbrook                     page[p/TARGET_PAGE_SIZE] = pag;
95944a91caeSbellard                     if (!pag)
96031e31b8aSbellard                         return 0;
96131e31b8aSbellard 		}
96231e31b8aSbellard 	    }
96331e31b8aSbellard 	    if (len == 0 || offset == 0) {
964edf779ffSbellard 	        *(pag + offset) = *tmp;
96531e31b8aSbellard 	    }
96631e31b8aSbellard 	    else {
96731e31b8aSbellard 	      int bytes_to_copy = (len > offset) ? offset : len;
96831e31b8aSbellard 	      tmp -= bytes_to_copy;
96931e31b8aSbellard 	      p -= bytes_to_copy;
97031e31b8aSbellard 	      offset -= bytes_to_copy;
97131e31b8aSbellard 	      len -= bytes_to_copy;
97231e31b8aSbellard 	      memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
97331e31b8aSbellard 	    }
97431e31b8aSbellard 	}
97531e31b8aSbellard     }
97631e31b8aSbellard     return p;
97731e31b8aSbellard }
97831e31b8aSbellard 
979992f48a0Sblueswir1 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
98031e31b8aSbellard                                  struct image_info *info)
98131e31b8aSbellard {
982992f48a0Sblueswir1     abi_ulong stack_base, size, error;
98331e31b8aSbellard     int i;
98431e31b8aSbellard 
98531e31b8aSbellard     /* Create enough stack to hold everything.  If we don't use
98631e31b8aSbellard      * it for args, we'll use it for something else...
98731e31b8aSbellard      */
988703e0e89SRichard Henderson     size = guest_stack_size;
98954936004Sbellard     if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
99054936004Sbellard         size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
99154936004Sbellard     error = target_mmap(0,
99283fb7adfSbellard                         size + qemu_host_page_size,
99331e31b8aSbellard                         PROT_READ | PROT_WRITE,
99409bfb054Sbellard                         MAP_PRIVATE | MAP_ANONYMOUS,
99509bfb054Sbellard                         -1, 0);
99609bfb054Sbellard     if (error == -1) {
99731e31b8aSbellard         perror("stk mmap");
99831e31b8aSbellard         exit(-1);
99931e31b8aSbellard     }
100009bfb054Sbellard     /* we reserve one extra page at the top of the stack as guard */
100183fb7adfSbellard     target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
100231e31b8aSbellard 
100354936004Sbellard     stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
100409bfb054Sbellard     p += stack_base;
100509bfb054Sbellard 
100631e31b8aSbellard     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
100731e31b8aSbellard 	if (bprm->page[i]) {
100831e31b8aSbellard 	    info->rss++;
1009579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
101053a5960aSpbrook 	    memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
101153a5960aSpbrook 	    free(bprm->page[i]);
101231e31b8aSbellard 	}
101354936004Sbellard         stack_base += TARGET_PAGE_SIZE;
101431e31b8aSbellard     }
101531e31b8aSbellard     return p;
101631e31b8aSbellard }
101731e31b8aSbellard 
1018992f48a0Sblueswir1 static void set_brk(abi_ulong start, abi_ulong end)
101931e31b8aSbellard {
102031e31b8aSbellard 	/* page-align the start and end addresses... */
102154936004Sbellard         start = HOST_PAGE_ALIGN(start);
102254936004Sbellard         end = HOST_PAGE_ALIGN(end);
102331e31b8aSbellard         if (end <= start)
102431e31b8aSbellard                 return;
102554936004Sbellard         if(target_mmap(start, end - start,
102631e31b8aSbellard                        PROT_READ | PROT_WRITE | PROT_EXEC,
102731e31b8aSbellard                        MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
102831e31b8aSbellard 	    perror("cannot mmap brk");
102931e31b8aSbellard 	    exit(-1);
103031e31b8aSbellard 	}
103131e31b8aSbellard }
103231e31b8aSbellard 
103331e31b8aSbellard 
1034853d6f7aSbellard /* We need to explicitly zero any fractional pages after the data
1035853d6f7aSbellard    section (i.e. bss).  This would contain the junk from the file that
1036853d6f7aSbellard    should not be in memory. */
1037992f48a0Sblueswir1 static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
103831e31b8aSbellard {
1039992f48a0Sblueswir1         abi_ulong nbyte;
104031e31b8aSbellard 
1041768a4a36Sths 	if (elf_bss >= last_bss)
1042768a4a36Sths 		return;
1043768a4a36Sths 
1044853d6f7aSbellard         /* XXX: this is really a hack : if the real host page size is
1045853d6f7aSbellard            smaller than the target page size, some pages after the end
1046853d6f7aSbellard            of the file may not be mapped. A better fix would be to
1047853d6f7aSbellard            patch target_mmap(), but it is more complicated as the file
1048853d6f7aSbellard            size must be known */
104983fb7adfSbellard         if (qemu_real_host_page_size < qemu_host_page_size) {
1050992f48a0Sblueswir1             abi_ulong end_addr, end_addr1;
105183fb7adfSbellard             end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
105283fb7adfSbellard                 ~(qemu_real_host_page_size - 1);
1053853d6f7aSbellard             end_addr = HOST_PAGE_ALIGN(elf_bss);
1054853d6f7aSbellard             if (end_addr1 < end_addr) {
1055863cf0b7Sj_mayer                 mmap((void *)g2h(end_addr1), end_addr - end_addr1,
1056853d6f7aSbellard                      PROT_READ|PROT_WRITE|PROT_EXEC,
1057853d6f7aSbellard                      MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
1058853d6f7aSbellard             }
1059853d6f7aSbellard         }
1060853d6f7aSbellard 
106183fb7adfSbellard         nbyte = elf_bss & (qemu_host_page_size-1);
106231e31b8aSbellard         if (nbyte) {
106383fb7adfSbellard 	    nbyte = qemu_host_page_size - nbyte;
106431e31b8aSbellard 	    do {
10652f619698Sbellard                 /* FIXME - what to do if put_user() fails? */
10662f619698Sbellard 		put_user_u8(0, elf_bss);
106753a5960aSpbrook                 elf_bss++;
106831e31b8aSbellard 	    } while (--nbyte);
106931e31b8aSbellard         }
107031e31b8aSbellard }
107131e31b8aSbellard 
107253a5960aSpbrook 
1073992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
107431e31b8aSbellard                                    struct elfhdr * exec,
1075992f48a0Sblueswir1                                    abi_ulong load_addr,
1076992f48a0Sblueswir1                                    abi_ulong load_bias,
1077992f48a0Sblueswir1                                    abi_ulong interp_load_addr, int ibcs,
107831e31b8aSbellard                                    struct image_info *info)
107931e31b8aSbellard {
1080992f48a0Sblueswir1         abi_ulong sp;
108153a5960aSpbrook         int size;
1082992f48a0Sblueswir1         abi_ulong u_platform;
108315338fd7Sbellard         const char *k_platform;
1084863cf0b7Sj_mayer         const int n = sizeof(elf_addr_t);
108531e31b8aSbellard 
108653a5960aSpbrook         sp = p;
108753a5960aSpbrook         u_platform = 0;
108815338fd7Sbellard         k_platform = ELF_PLATFORM;
108915338fd7Sbellard         if (k_platform) {
109015338fd7Sbellard             size_t len = strlen(k_platform) + 1;
109153a5960aSpbrook             sp -= (len + n - 1) & ~(n - 1);
109253a5960aSpbrook             u_platform = sp;
1093579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
109453a5960aSpbrook             memcpy_to_target(sp, k_platform, len);
109515338fd7Sbellard         }
109653a5960aSpbrook 	/*
109753a5960aSpbrook 	 * Force 16 byte _final_ alignment here for generality.
109853a5960aSpbrook 	 */
1099992f48a0Sblueswir1         sp = sp &~ (abi_ulong)15;
110053a5960aSpbrook         size = (DLINFO_ITEMS + 1) * 2;
110115338fd7Sbellard         if (k_platform)
110253a5960aSpbrook           size += 2;
1103f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS
110453a5960aSpbrook 	size += DLINFO_ARCH_ITEMS * 2;
1105f5155289Sbellard #endif
110653a5960aSpbrook         size += envc + argc + 2;
110753a5960aSpbrook 	size += (!ibcs ? 3 : 1);	/* argc itself */
110853a5960aSpbrook         size *= n;
110953a5960aSpbrook         if (size & 15)
111053a5960aSpbrook             sp -= 16 - (size & 15);
1111f5155289Sbellard 
1112863cf0b7Sj_mayer         /* This is correct because Linux defines
1113863cf0b7Sj_mayer          * elf_addr_t as Elf32_Off / Elf64_Off
1114863cf0b7Sj_mayer          */
111553a5960aSpbrook #define NEW_AUX_ENT(id, val) do {		\
11162f619698Sbellard             sp -= n; put_user_ual(val, sp);	\
11172f619698Sbellard             sp -= n; put_user_ual(id, sp);	\
111853a5960aSpbrook           } while(0)
11192f619698Sbellard 
11200bccf03dSbellard         NEW_AUX_ENT (AT_NULL, 0);
1121f5155289Sbellard 
11220bccf03dSbellard         /* There must be exactly DLINFO_ITEMS entries here.  */
1123992f48a0Sblueswir1         NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
1124992f48a0Sblueswir1         NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1125992f48a0Sblueswir1         NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1126992f48a0Sblueswir1         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
1127992f48a0Sblueswir1         NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
1128992f48a0Sblueswir1         NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
11290bccf03dSbellard         NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
1130992f48a0Sblueswir1         NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1131992f48a0Sblueswir1         NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1132992f48a0Sblueswir1         NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1133992f48a0Sblueswir1         NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1134992f48a0Sblueswir1         NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1135a07c67dfSpbrook         NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
113615338fd7Sbellard         if (k_platform)
113753a5960aSpbrook             NEW_AUX_ENT(AT_PLATFORM, u_platform);
1138f5155289Sbellard #ifdef ARCH_DLINFO
1139f5155289Sbellard 	/*
1140f5155289Sbellard 	 * ARCH_DLINFO must come last so platform specific code can enforce
1141f5155289Sbellard 	 * special alignment requirements on the AUXV if necessary (eg. PPC).
1142f5155289Sbellard 	 */
1143f5155289Sbellard         ARCH_DLINFO;
1144f5155289Sbellard #endif
1145f5155289Sbellard #undef NEW_AUX_ENT
1146f5155289Sbellard 
1147edf8e2afSMika Westerberg         info->saved_auxv = sp;
1148edf8e2afSMika Westerberg 
1149e5fe0c52Spbrook         sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
115031e31b8aSbellard         return sp;
115131e31b8aSbellard }
115231e31b8aSbellard 
115331e31b8aSbellard 
1154992f48a0Sblueswir1 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
115531e31b8aSbellard                                  int interpreter_fd,
1156992f48a0Sblueswir1                                  abi_ulong *interp_load_addr)
115731e31b8aSbellard {
115831e31b8aSbellard 	struct elf_phdr *elf_phdata  =  NULL;
115931e31b8aSbellard 	struct elf_phdr *eppnt;
1160992f48a0Sblueswir1 	abi_ulong load_addr = 0;
116131e31b8aSbellard 	int load_addr_set = 0;
116231e31b8aSbellard 	int retval;
1163992f48a0Sblueswir1 	abi_ulong last_bss, elf_bss;
1164992f48a0Sblueswir1 	abi_ulong error;
116531e31b8aSbellard 	int i;
116631e31b8aSbellard 
116731e31b8aSbellard 	elf_bss = 0;
116831e31b8aSbellard 	last_bss = 0;
116931e31b8aSbellard 	error = 0;
117031e31b8aSbellard 
1171644c433cSbellard #ifdef BSWAP_NEEDED
1172644c433cSbellard         bswap_ehdr(interp_elf_ex);
1173644c433cSbellard #endif
117431e31b8aSbellard 	/* First of all, some simple consistency checks */
117531e31b8aSbellard 	if ((interp_elf_ex->e_type != ET_EXEC &&
117631e31b8aSbellard              interp_elf_ex->e_type != ET_DYN) ||
117731e31b8aSbellard 	   !elf_check_arch(interp_elf_ex->e_machine)) {
1178992f48a0Sblueswir1 		return ~((abi_ulong)0UL);
117931e31b8aSbellard 	}
118031e31b8aSbellard 
1181644c433cSbellard 
118231e31b8aSbellard 	/* Now read in all of the header information */
118331e31b8aSbellard 
118454936004Sbellard 	if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
1185992f48a0Sblueswir1 	    return ~(abi_ulong)0UL;
118631e31b8aSbellard 
118731e31b8aSbellard 	elf_phdata =  (struct elf_phdr *)
118831e31b8aSbellard 		malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
118931e31b8aSbellard 
119031e31b8aSbellard 	if (!elf_phdata)
1191992f48a0Sblueswir1 	  return ~((abi_ulong)0UL);
119231e31b8aSbellard 
119331e31b8aSbellard 	/*
119431e31b8aSbellard 	 * If the size of this structure has changed, then punt, since
119531e31b8aSbellard 	 * we will be doing the wrong thing.
119631e31b8aSbellard 	 */
119709bfb054Sbellard 	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
119831e31b8aSbellard 	    free(elf_phdata);
1199992f48a0Sblueswir1 	    return ~((abi_ulong)0UL);
120031e31b8aSbellard         }
120131e31b8aSbellard 
120231e31b8aSbellard 	retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
120331e31b8aSbellard 	if(retval >= 0) {
120431e31b8aSbellard 	    retval = read(interpreter_fd,
120531e31b8aSbellard 			   (char *) elf_phdata,
120631e31b8aSbellard 			   sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
120731e31b8aSbellard 	}
120831e31b8aSbellard 	if (retval < 0) {
120931e31b8aSbellard 		perror("load_elf_interp");
121031e31b8aSbellard 		exit(-1);
121131e31b8aSbellard 		free (elf_phdata);
121231e31b8aSbellard 		return retval;
121331e31b8aSbellard  	}
121431e31b8aSbellard #ifdef BSWAP_NEEDED
121531e31b8aSbellard 	eppnt = elf_phdata;
121631e31b8aSbellard 	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
121731e31b8aSbellard             bswap_phdr(eppnt);
121831e31b8aSbellard         }
121931e31b8aSbellard #endif
122009bfb054Sbellard 
122109bfb054Sbellard         if (interp_elf_ex->e_type == ET_DYN) {
1222e91c8a77Sths             /* in order to avoid hardcoding the interpreter load
122309bfb054Sbellard                address in qemu, we allocate a big enough memory zone */
122454936004Sbellard             error = target_mmap(0, INTERP_MAP_SIZE,
122509bfb054Sbellard                                 PROT_NONE, MAP_PRIVATE | MAP_ANON,
122609bfb054Sbellard                                 -1, 0);
122709bfb054Sbellard             if (error == -1) {
122809bfb054Sbellard                 perror("mmap");
122909bfb054Sbellard                 exit(-1);
123009bfb054Sbellard             }
123109bfb054Sbellard             load_addr = error;
123209bfb054Sbellard             load_addr_set = 1;
123309bfb054Sbellard         }
123409bfb054Sbellard 
123531e31b8aSbellard 	eppnt = elf_phdata;
123631e31b8aSbellard 	for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
123731e31b8aSbellard 	  if (eppnt->p_type == PT_LOAD) {
123831e31b8aSbellard 	    int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
123931e31b8aSbellard 	    int elf_prot = 0;
1240992f48a0Sblueswir1 	    abi_ulong vaddr = 0;
1241992f48a0Sblueswir1 	    abi_ulong k;
124231e31b8aSbellard 
124331e31b8aSbellard 	    if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
124431e31b8aSbellard 	    if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
124531e31b8aSbellard 	    if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
124631e31b8aSbellard 	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
124731e31b8aSbellard 	    	elf_type |= MAP_FIXED;
124831e31b8aSbellard 	    	vaddr = eppnt->p_vaddr;
124931e31b8aSbellard 	    }
125054936004Sbellard 	    error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
125154936004Sbellard 		 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
125231e31b8aSbellard 		 elf_prot,
125331e31b8aSbellard 		 elf_type,
125431e31b8aSbellard 		 interpreter_fd,
125554936004Sbellard 		 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
125631e31b8aSbellard 
1257e89f07d3Spbrook 	    if (error == -1) {
125831e31b8aSbellard 	      /* Real error */
125931e31b8aSbellard 	      close(interpreter_fd);
126031e31b8aSbellard 	      free(elf_phdata);
1261992f48a0Sblueswir1 	      return ~((abi_ulong)0UL);
126231e31b8aSbellard 	    }
126331e31b8aSbellard 
126431e31b8aSbellard 	    if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
126531e31b8aSbellard 	      load_addr = error;
126631e31b8aSbellard 	      load_addr_set = 1;
126731e31b8aSbellard 	    }
126831e31b8aSbellard 
126931e31b8aSbellard 	    /*
127031e31b8aSbellard 	     * Find the end of the file  mapping for this phdr, and keep
127131e31b8aSbellard 	     * track of the largest address we see for this.
127231e31b8aSbellard 	     */
127331e31b8aSbellard 	    k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
127431e31b8aSbellard 	    if (k > elf_bss) elf_bss = k;
127531e31b8aSbellard 
127631e31b8aSbellard 	    /*
127731e31b8aSbellard 	     * Do the same thing for the memory mapping - between
127831e31b8aSbellard 	     * elf_bss and last_bss is the bss section.
127931e31b8aSbellard 	     */
128031e31b8aSbellard 	    k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
128131e31b8aSbellard 	    if (k > last_bss) last_bss = k;
128231e31b8aSbellard 	  }
128331e31b8aSbellard 
128431e31b8aSbellard 	/* Now use mmap to map the library into memory. */
128531e31b8aSbellard 
128631e31b8aSbellard 	close(interpreter_fd);
128731e31b8aSbellard 
128831e31b8aSbellard 	/*
128931e31b8aSbellard 	 * Now fill out the bss section.  First pad the last page up
129031e31b8aSbellard 	 * to the page boundary, and then perform a mmap to make sure
129131e31b8aSbellard 	 * that there are zeromapped pages up to and including the last
129231e31b8aSbellard 	 * bss page.
129331e31b8aSbellard 	 */
1294768a4a36Sths 	padzero(elf_bss, last_bss);
129583fb7adfSbellard 	elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
129631e31b8aSbellard 
129731e31b8aSbellard 	/* Map the last of the bss segment */
129831e31b8aSbellard 	if (last_bss > elf_bss) {
129954936004Sbellard             target_mmap(elf_bss, last_bss-elf_bss,
130031e31b8aSbellard                         PROT_READ|PROT_WRITE|PROT_EXEC,
130131e31b8aSbellard                         MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
130231e31b8aSbellard 	}
130331e31b8aSbellard 	free(elf_phdata);
130431e31b8aSbellard 
130531e31b8aSbellard 	*interp_load_addr = load_addr;
1306992f48a0Sblueswir1 	return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
130731e31b8aSbellard }
130831e31b8aSbellard 
130949918a75Spbrook static int symfind(const void *s0, const void *s1)
131049918a75Spbrook {
131149918a75Spbrook     struct elf_sym *key = (struct elf_sym *)s0;
131249918a75Spbrook     struct elf_sym *sym = (struct elf_sym *)s1;
131349918a75Spbrook     int result = 0;
131449918a75Spbrook     if (key->st_value < sym->st_value) {
131549918a75Spbrook         result = -1;
1316ec822001SLaurent Desnogues     } else if (key->st_value >= sym->st_value + sym->st_size) {
131749918a75Spbrook         result = 1;
131849918a75Spbrook     }
131949918a75Spbrook     return result;
132049918a75Spbrook }
132149918a75Spbrook 
132249918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
132349918a75Spbrook {
132449918a75Spbrook #if ELF_CLASS == ELFCLASS32
132549918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf32;
132649918a75Spbrook #else
132749918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf64;
132849918a75Spbrook #endif
132949918a75Spbrook 
133049918a75Spbrook     // binary search
133149918a75Spbrook     struct elf_sym key;
133249918a75Spbrook     struct elf_sym *sym;
133349918a75Spbrook 
133449918a75Spbrook     key.st_value = orig_addr;
133549918a75Spbrook 
133649918a75Spbrook     sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
13377cba04f6SBlue Swirl     if (sym != NULL) {
133849918a75Spbrook         return s->disas_strtab + sym->st_name;
133949918a75Spbrook     }
134049918a75Spbrook 
134149918a75Spbrook     return "";
134249918a75Spbrook }
134349918a75Spbrook 
134449918a75Spbrook /* FIXME: This should use elf_ops.h  */
134549918a75Spbrook static int symcmp(const void *s0, const void *s1)
134649918a75Spbrook {
134749918a75Spbrook     struct elf_sym *sym0 = (struct elf_sym *)s0;
134849918a75Spbrook     struct elf_sym *sym1 = (struct elf_sym *)s1;
134949918a75Spbrook     return (sym0->st_value < sym1->st_value)
135049918a75Spbrook         ? -1
135149918a75Spbrook         : ((sym0->st_value > sym1->st_value) ? 1 : 0);
135249918a75Spbrook }
135349918a75Spbrook 
1354689f936fSbellard /* Best attempt to load symbols from this ELF object. */
1355689f936fSbellard static void load_symbols(struct elfhdr *hdr, int fd)
1356689f936fSbellard {
135749918a75Spbrook     unsigned int i, nsyms;
1358689f936fSbellard     struct elf_shdr sechdr, symtab, strtab;
1359689f936fSbellard     char *strings;
1360e80cfcfcSbellard     struct syminfo *s;
136149918a75Spbrook     struct elf_sym *syms;
136231e31b8aSbellard 
1363689f936fSbellard     lseek(fd, hdr->e_shoff, SEEK_SET);
1364689f936fSbellard     for (i = 0; i < hdr->e_shnum; i++) {
1365689f936fSbellard         if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
1366689f936fSbellard             return;
1367689f936fSbellard #ifdef BSWAP_NEEDED
1368689f936fSbellard         bswap_shdr(&sechdr);
1369689f936fSbellard #endif
1370689f936fSbellard         if (sechdr.sh_type == SHT_SYMTAB) {
1371689f936fSbellard             symtab = sechdr;
1372689f936fSbellard             lseek(fd, hdr->e_shoff
1373689f936fSbellard                   + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
1374689f936fSbellard             if (read(fd, &strtab, sizeof(strtab))
1375689f936fSbellard                 != sizeof(strtab))
1376689f936fSbellard                 return;
1377689f936fSbellard #ifdef BSWAP_NEEDED
1378689f936fSbellard             bswap_shdr(&strtab);
1379689f936fSbellard #endif
1380689f936fSbellard             goto found;
1381689f936fSbellard         }
1382689f936fSbellard     }
1383689f936fSbellard     return; /* Shouldn't happen... */
1384689f936fSbellard 
1385689f936fSbellard  found:
1386689f936fSbellard     /* Now know where the strtab and symtab are.  Snarf them. */
1387e80cfcfcSbellard     s = malloc(sizeof(*s));
138849918a75Spbrook     syms = malloc(symtab.sh_size);
138949918a75Spbrook     if (!syms)
139049918a75Spbrook         return;
1391e80cfcfcSbellard     s->disas_strtab = strings = malloc(strtab.sh_size);
139249918a75Spbrook     if (!s->disas_strtab)
1393689f936fSbellard         return;
1394689f936fSbellard 
1395689f936fSbellard     lseek(fd, symtab.sh_offset, SEEK_SET);
139649918a75Spbrook     if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
1397689f936fSbellard         return;
1398689f936fSbellard 
139949918a75Spbrook     nsyms = symtab.sh_size / sizeof(struct elf_sym);
1400689f936fSbellard 
140149918a75Spbrook     i = 0;
140249918a75Spbrook     while (i < nsyms) {
140349918a75Spbrook #ifdef BSWAP_NEEDED
140449918a75Spbrook         bswap_sym(syms + i);
14050774bed1Sblueswir1 #endif
140649918a75Spbrook         // Throw away entries which we do not need.
140749918a75Spbrook         if (syms[i].st_shndx == SHN_UNDEF ||
140849918a75Spbrook                 syms[i].st_shndx >= SHN_LORESERVE ||
140949918a75Spbrook                 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
141049918a75Spbrook             nsyms--;
141149918a75Spbrook             if (i < nsyms) {
141249918a75Spbrook                 syms[i] = syms[nsyms];
141349918a75Spbrook             }
141449918a75Spbrook             continue;
141549918a75Spbrook         }
141649918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS)
141749918a75Spbrook         /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
141849918a75Spbrook         syms[i].st_value &= ~(target_ulong)1;
141949918a75Spbrook #endif
142049918a75Spbrook         i++;
142149918a75Spbrook     }
142249918a75Spbrook     syms = realloc(syms, nsyms * sizeof(*syms));
142349918a75Spbrook 
142449918a75Spbrook     qsort(syms, nsyms, sizeof(*syms), symcmp);
142549918a75Spbrook 
1426689f936fSbellard     lseek(fd, strtab.sh_offset, SEEK_SET);
1427689f936fSbellard     if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
1428689f936fSbellard         return;
142949918a75Spbrook     s->disas_num_syms = nsyms;
143049918a75Spbrook #if ELF_CLASS == ELFCLASS32
143149918a75Spbrook     s->disas_symtab.elf32 = syms;
14329f9f0309SPaul Brook     s->lookup_symbol = lookup_symbolxx;
143349918a75Spbrook #else
143449918a75Spbrook     s->disas_symtab.elf64 = syms;
14359f9f0309SPaul Brook     s->lookup_symbol = lookup_symbolxx;
143649918a75Spbrook #endif
1437e80cfcfcSbellard     s->next = syminfos;
1438e80cfcfcSbellard     syminfos = s;
1439689f936fSbellard }
144031e31b8aSbellard 
1441e5fe0c52Spbrook int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
144231e31b8aSbellard                     struct image_info * info)
144331e31b8aSbellard {
144431e31b8aSbellard     struct elfhdr elf_ex;
144531e31b8aSbellard     struct elfhdr interp_elf_ex;
144631e31b8aSbellard     struct exec interp_ex;
144731e31b8aSbellard     int interpreter_fd = -1; /* avoid warning */
1448992f48a0Sblueswir1     abi_ulong load_addr, load_bias;
144931e31b8aSbellard     int load_addr_set = 0;
145031e31b8aSbellard     unsigned int interpreter_type = INTERPRETER_NONE;
145131e31b8aSbellard     unsigned char ibcs2_interpreter;
145231e31b8aSbellard     int i;
1453992f48a0Sblueswir1     abi_ulong mapped_addr;
145431e31b8aSbellard     struct elf_phdr * elf_ppnt;
145531e31b8aSbellard     struct elf_phdr *elf_phdata;
1456992f48a0Sblueswir1     abi_ulong elf_bss, k, elf_brk;
145731e31b8aSbellard     int retval;
145831e31b8aSbellard     char * elf_interpreter;
1459992f48a0Sblueswir1     abi_ulong elf_entry, interp_load_addr = 0;
146031e31b8aSbellard     int status;
1461992f48a0Sblueswir1     abi_ulong start_code, end_code, start_data, end_data;
1462992f48a0Sblueswir1     abi_ulong reloc_func_desc = 0;
1463992f48a0Sblueswir1     abi_ulong elf_stack;
146431e31b8aSbellard     char passed_fileno[6];
146531e31b8aSbellard 
146631e31b8aSbellard     ibcs2_interpreter = 0;
146731e31b8aSbellard     status = 0;
146831e31b8aSbellard     load_addr = 0;
146909bfb054Sbellard     load_bias = 0;
147031e31b8aSbellard     elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
147131e31b8aSbellard #ifdef BSWAP_NEEDED
147231e31b8aSbellard     bswap_ehdr(&elf_ex);
147331e31b8aSbellard #endif
147431e31b8aSbellard 
147531e31b8aSbellard     /* First of all, some simple consistency checks */
147631e31b8aSbellard     if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
147731e31b8aSbellard        				(! elf_check_arch(elf_ex.e_machine))) {
147831e31b8aSbellard 	    return -ENOEXEC;
147931e31b8aSbellard     }
148031e31b8aSbellard 
1481e5fe0c52Spbrook     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1482e5fe0c52Spbrook     bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1483e5fe0c52Spbrook     bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1484e5fe0c52Spbrook     if (!bprm->p) {
1485e5fe0c52Spbrook         retval = -E2BIG;
1486e5fe0c52Spbrook     }
1487e5fe0c52Spbrook 
148831e31b8aSbellard     /* Now read in all of the header information */
148931e31b8aSbellard     elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
149031e31b8aSbellard     if (elf_phdata == NULL) {
149131e31b8aSbellard 	return -ENOMEM;
149231e31b8aSbellard     }
149331e31b8aSbellard 
149431e31b8aSbellard     retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
149531e31b8aSbellard     if(retval > 0) {
149631e31b8aSbellard 	retval = read(bprm->fd, (char *) elf_phdata,
149731e31b8aSbellard 				elf_ex.e_phentsize * elf_ex.e_phnum);
149831e31b8aSbellard     }
149931e31b8aSbellard 
150031e31b8aSbellard     if (retval < 0) {
150131e31b8aSbellard 	perror("load_elf_binary");
150231e31b8aSbellard 	exit(-1);
150331e31b8aSbellard 	free (elf_phdata);
150431e31b8aSbellard 	return -errno;
150531e31b8aSbellard     }
150631e31b8aSbellard 
1507b17780d5Sbellard #ifdef BSWAP_NEEDED
1508b17780d5Sbellard     elf_ppnt = elf_phdata;
1509b17780d5Sbellard     for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
1510b17780d5Sbellard         bswap_phdr(elf_ppnt);
1511b17780d5Sbellard     }
1512b17780d5Sbellard #endif
151331e31b8aSbellard     elf_ppnt = elf_phdata;
151431e31b8aSbellard 
151531e31b8aSbellard     elf_bss = 0;
151631e31b8aSbellard     elf_brk = 0;
151731e31b8aSbellard 
151831e31b8aSbellard 
1519992f48a0Sblueswir1     elf_stack = ~((abi_ulong)0UL);
152031e31b8aSbellard     elf_interpreter = NULL;
1521992f48a0Sblueswir1     start_code = ~((abi_ulong)0UL);
152231e31b8aSbellard     end_code = 0;
1523863cf0b7Sj_mayer     start_data = 0;
152431e31b8aSbellard     end_data = 0;
152598448f58Sblueswir1     interp_ex.a_info = 0;
152631e31b8aSbellard 
152731e31b8aSbellard     for(i=0;i < elf_ex.e_phnum; i++) {
152831e31b8aSbellard 	if (elf_ppnt->p_type == PT_INTERP) {
152931e31b8aSbellard 	    if ( elf_interpreter != NULL )
153031e31b8aSbellard 	    {
153131e31b8aSbellard 		free (elf_phdata);
153231e31b8aSbellard 		free(elf_interpreter);
153331e31b8aSbellard 		close(bprm->fd);
153431e31b8aSbellard 		return -EINVAL;
153531e31b8aSbellard 	    }
153631e31b8aSbellard 
153731e31b8aSbellard 	    /* This is the program interpreter used for
153831e31b8aSbellard 	     * shared libraries - for now assume that this
153931e31b8aSbellard 	     * is an a.out format binary
154031e31b8aSbellard 	     */
154131e31b8aSbellard 
154232ce6337Sbellard 	    elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
154331e31b8aSbellard 
154431e31b8aSbellard 	    if (elf_interpreter == NULL) {
154531e31b8aSbellard 		free (elf_phdata);
154631e31b8aSbellard 		close(bprm->fd);
154731e31b8aSbellard 		return -ENOMEM;
154831e31b8aSbellard 	    }
154931e31b8aSbellard 
155031e31b8aSbellard 	    retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
155131e31b8aSbellard 	    if(retval >= 0) {
155232ce6337Sbellard 		retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
155331e31b8aSbellard 	    }
155431e31b8aSbellard 	    if(retval < 0) {
155531e31b8aSbellard 	 	perror("load_elf_binary2");
155631e31b8aSbellard 		exit(-1);
155731e31b8aSbellard 	    }
155831e31b8aSbellard 
155931e31b8aSbellard 	    /* If the program interpreter is one of these two,
156031e31b8aSbellard 	       then assume an iBCS2 image. Otherwise assume
156131e31b8aSbellard 	       a native linux image. */
156231e31b8aSbellard 
156331e31b8aSbellard 	    /* JRP - Need to add X86 lib dir stuff here... */
156431e31b8aSbellard 
156531e31b8aSbellard 	    if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
156631e31b8aSbellard 		strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
156731e31b8aSbellard 	      ibcs2_interpreter = 1;
156831e31b8aSbellard 	    }
156931e31b8aSbellard 
157031e31b8aSbellard #if 0
15713bc0bdcaSPaul Bolle 	    printf("Using ELF interpreter %s\n", path(elf_interpreter));
157231e31b8aSbellard #endif
157331e31b8aSbellard 	    if (retval >= 0) {
157432ce6337Sbellard 		retval = open(path(elf_interpreter), O_RDONLY);
157531e31b8aSbellard 		if(retval >= 0) {
157631e31b8aSbellard 		    interpreter_fd = retval;
157731e31b8aSbellard 		}
157831e31b8aSbellard 		else {
157931e31b8aSbellard 		    perror(elf_interpreter);
158031e31b8aSbellard 		    exit(-1);
158131e31b8aSbellard 		    /* retval = -errno; */
158231e31b8aSbellard 		}
158331e31b8aSbellard 	    }
158431e31b8aSbellard 
158531e31b8aSbellard 	    if (retval >= 0) {
158631e31b8aSbellard 		retval = lseek(interpreter_fd, 0, SEEK_SET);
158731e31b8aSbellard 		if(retval >= 0) {
158831e31b8aSbellard 		    retval = read(interpreter_fd,bprm->buf,128);
158931e31b8aSbellard 		}
159031e31b8aSbellard 	    }
159131e31b8aSbellard 	    if (retval >= 0) {
159231e31b8aSbellard 		interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
159331e31b8aSbellard 		interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */
159431e31b8aSbellard 	    }
159531e31b8aSbellard 	    if (retval < 0) {
159631e31b8aSbellard 		perror("load_elf_binary3");
159731e31b8aSbellard 		exit(-1);
159831e31b8aSbellard 		free (elf_phdata);
159931e31b8aSbellard 		free(elf_interpreter);
160031e31b8aSbellard 		close(bprm->fd);
160131e31b8aSbellard 		return retval;
160231e31b8aSbellard 	    }
160331e31b8aSbellard 	}
160431e31b8aSbellard 	elf_ppnt++;
160531e31b8aSbellard     }
160631e31b8aSbellard 
160731e31b8aSbellard     /* Some simple consistency checks for the interpreter */
160831e31b8aSbellard     if (elf_interpreter){
160931e31b8aSbellard 	interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
161031e31b8aSbellard 
161131e31b8aSbellard 	/* Now figure out which format our binary is */
161231e31b8aSbellard 	if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
161331e31b8aSbellard 	    	(N_MAGIC(interp_ex) != QMAGIC)) {
161431e31b8aSbellard 	  interpreter_type = INTERPRETER_ELF;
161531e31b8aSbellard 	}
161631e31b8aSbellard 
161731e31b8aSbellard 	if (interp_elf_ex.e_ident[0] != 0x7f ||
1618b55266b5Sblueswir1             strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
161931e31b8aSbellard 	    interpreter_type &= ~INTERPRETER_ELF;
162031e31b8aSbellard 	}
162131e31b8aSbellard 
162231e31b8aSbellard 	if (!interpreter_type) {
162331e31b8aSbellard 	    free(elf_interpreter);
162431e31b8aSbellard 	    free(elf_phdata);
162531e31b8aSbellard 	    close(bprm->fd);
162631e31b8aSbellard 	    return -ELIBBAD;
162731e31b8aSbellard 	}
162831e31b8aSbellard     }
162931e31b8aSbellard 
163031e31b8aSbellard     /* OK, we are done with that, now set up the arg stuff,
163131e31b8aSbellard        and then start this sucker up */
163231e31b8aSbellard 
1633e5fe0c52Spbrook     {
163431e31b8aSbellard 	char * passed_p;
163531e31b8aSbellard 
163631e31b8aSbellard 	if (interpreter_type == INTERPRETER_AOUT) {
1637eba2af63Sbellard 	    snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
163831e31b8aSbellard 	    passed_p = passed_fileno;
163931e31b8aSbellard 
164031e31b8aSbellard 	    if (elf_interpreter) {
1641e5fe0c52Spbrook 		bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
164231e31b8aSbellard 		bprm->argc++;
164331e31b8aSbellard 	    }
164431e31b8aSbellard 	}
164531e31b8aSbellard 	if (!bprm->p) {
164631e31b8aSbellard 	    if (elf_interpreter) {
164731e31b8aSbellard 	        free(elf_interpreter);
164831e31b8aSbellard 	    }
164931e31b8aSbellard 	    free (elf_phdata);
165031e31b8aSbellard 	    close(bprm->fd);
165131e31b8aSbellard 	    return -E2BIG;
165231e31b8aSbellard 	}
165331e31b8aSbellard     }
165431e31b8aSbellard 
165531e31b8aSbellard     /* OK, This is the point of no return */
165631e31b8aSbellard     info->end_data = 0;
165731e31b8aSbellard     info->end_code = 0;
1658992f48a0Sblueswir1     info->start_mmap = (abi_ulong)ELF_START_MMAP;
165931e31b8aSbellard     info->mmap = 0;
1660992f48a0Sblueswir1     elf_entry = (abi_ulong) elf_ex.e_entry;
166131e31b8aSbellard 
1662379f6698SPaul Brook #if defined(CONFIG_USE_GUEST_BASE)
1663379f6698SPaul Brook     /*
1664379f6698SPaul Brook      * In case where user has not explicitly set the guest_base, we
1665379f6698SPaul Brook      * probe here that should we set it automatically.
1666379f6698SPaul Brook      */
1667379f6698SPaul Brook     if (!have_guest_base) {
1668379f6698SPaul Brook         /*
1669*c581dedaSPaul Brook          * Go through ELF program header table and find the address
1670*c581dedaSPaul Brook          * range used by loadable segments.  Check that this is available on
1671*c581dedaSPaul Brook          * the host, and if not find a suitable value for guest_base.  */
1672*c581dedaSPaul Brook         abi_ulong app_start = ~0;
1673*c581dedaSPaul Brook         abi_ulong app_end = 0;
1674*c581dedaSPaul Brook         abi_ulong addr;
1675*c581dedaSPaul Brook         unsigned long host_start;
1676*c581dedaSPaul Brook         unsigned long real_start;
1677*c581dedaSPaul Brook         unsigned long host_size;
1678379f6698SPaul Brook         for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
1679379f6698SPaul Brook             i++, elf_ppnt++) {
1680379f6698SPaul Brook             if (elf_ppnt->p_type != PT_LOAD)
1681379f6698SPaul Brook                 continue;
1682*c581dedaSPaul Brook             addr = elf_ppnt->p_vaddr;
1683*c581dedaSPaul Brook             if (addr < app_start) {
1684*c581dedaSPaul Brook                 app_start = addr;
1685*c581dedaSPaul Brook             }
1686*c581dedaSPaul Brook             addr += elf_ppnt->p_memsz;
1687*c581dedaSPaul Brook             if (addr > app_end) {
1688*c581dedaSPaul Brook                 app_end = addr;
1689*c581dedaSPaul Brook             }
1690*c581dedaSPaul Brook         }
1691*c581dedaSPaul Brook 
1692*c581dedaSPaul Brook         /* If we don't have any loadable segments then something
1693*c581dedaSPaul Brook            is very wrong.  */
1694*c581dedaSPaul Brook         assert(app_start < app_end);
1695*c581dedaSPaul Brook 
1696*c581dedaSPaul Brook         /* Round addresses to page boundaries.  */
1697*c581dedaSPaul Brook         app_start = app_start & qemu_host_page_mask;
1698*c581dedaSPaul Brook         app_end = HOST_PAGE_ALIGN(app_end);
1699*c581dedaSPaul Brook         if (app_start < mmap_min_addr) {
1700*c581dedaSPaul Brook             host_start = HOST_PAGE_ALIGN(mmap_min_addr);
1701*c581dedaSPaul Brook         } else {
1702*c581dedaSPaul Brook             host_start = app_start;
1703*c581dedaSPaul Brook             if (host_start != app_start) {
1704*c581dedaSPaul Brook                 fprintf(stderr, "qemu: Address overflow loading ELF binary\n");
1705*c581dedaSPaul Brook                 abort();
1706*c581dedaSPaul Brook             }
1707*c581dedaSPaul Brook         }
1708*c581dedaSPaul Brook         host_size = app_end - app_start;
1709*c581dedaSPaul Brook         while (1) {
1710*c581dedaSPaul Brook             /* Do not use mmap_find_vma here because that is limited to the
1711*c581dedaSPaul Brook                guest address space.  We are going to make the
1712*c581dedaSPaul Brook                guest address space fit whatever we're given.  */
1713*c581dedaSPaul Brook             real_start = (unsigned long)mmap((void *)host_start, host_size,
1714*c581dedaSPaul Brook                 PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
1715*c581dedaSPaul Brook             if (real_start == (unsigned long)-1) {
1716*c581dedaSPaul Brook                 fprintf(stderr, "qemu: Virtual memory exausted\n");
1717*c581dedaSPaul Brook                 abort();
1718*c581dedaSPaul Brook             }
1719*c581dedaSPaul Brook             if (real_start == host_start) {
1720379f6698SPaul Brook                 break;
1721379f6698SPaul Brook             }
1722*c581dedaSPaul Brook             /* That address didn't work.  Unmap and try a different one.
1723*c581dedaSPaul Brook                The address the host picked because is typically
1724*c581dedaSPaul Brook                right at the top of the host address space and leaves the
1725*c581dedaSPaul Brook                guest with no usable address space.  Resort to a linear search.
1726*c581dedaSPaul Brook                We already compensated for mmap_min_addr, so this should not
1727*c581dedaSPaul Brook                happen often.  Probably means we got unlucky and host address
1728*c581dedaSPaul Brook                space randomization put a shared library somewhere
1729*c581dedaSPaul Brook                inconvenient.  */
1730*c581dedaSPaul Brook             munmap((void *)real_start, host_size);
1731*c581dedaSPaul Brook             host_start += qemu_host_page_size;
1732*c581dedaSPaul Brook             if (host_start == app_start) {
1733*c581dedaSPaul Brook                 /* Theoretically possible if host doesn't have any
1734*c581dedaSPaul Brook                    suitably aligned areas.  Normally the first mmap will
1735*c581dedaSPaul Brook                    fail.  */
1736*c581dedaSPaul Brook                 fprintf(stderr, "qemu: Unable to find space for application\n");
1737*c581dedaSPaul Brook                 abort();
1738379f6698SPaul Brook             }
1739379f6698SPaul Brook         }
1740*c581dedaSPaul Brook         qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx
1741*c581dedaSPaul Brook                  " to 0x%lx\n", app_start, real_start);
1742*c581dedaSPaul Brook         guest_base = real_start - app_start;
1743*c581dedaSPaul Brook     }
1744379f6698SPaul Brook #endif /* CONFIG_USE_GUEST_BASE */
1745379f6698SPaul Brook 
174631e31b8aSbellard     /* Do this so that we can load the interpreter, if need be.  We will
174731e31b8aSbellard        change some of these later */
174831e31b8aSbellard     info->rss = 0;
174931e31b8aSbellard     bprm->p = setup_arg_pages(bprm->p, bprm, info);
175031e31b8aSbellard     info->start_stack = bprm->p;
175131e31b8aSbellard 
175231e31b8aSbellard     /* Now we do a little grungy work by mmaping the ELF image into
175331e31b8aSbellard      * the correct location in memory.  At this point, we assume that
175431e31b8aSbellard      * the image should be loaded at fixed address, not at a variable
175531e31b8aSbellard      * address.
175631e31b8aSbellard      */
175731e31b8aSbellard 
175831e31b8aSbellard     for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
175931e31b8aSbellard         int elf_prot = 0;
176009bfb054Sbellard         int elf_flags = 0;
1761992f48a0Sblueswir1         abi_ulong error;
176209bfb054Sbellard 
176309bfb054Sbellard 	if (elf_ppnt->p_type != PT_LOAD)
176409bfb054Sbellard             continue;
176509bfb054Sbellard 
176631e31b8aSbellard         if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
176731e31b8aSbellard         if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
176831e31b8aSbellard         if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
176909bfb054Sbellard         elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
177009bfb054Sbellard         if (elf_ex.e_type == ET_EXEC || load_addr_set) {
177109bfb054Sbellard             elf_flags |= MAP_FIXED;
177209bfb054Sbellard         } else if (elf_ex.e_type == ET_DYN) {
177309bfb054Sbellard             /* Try and get dynamic programs out of the way of the default mmap
177409bfb054Sbellard                base, as well as whatever program they might try to exec.  This
177509bfb054Sbellard                is because the brk will follow the loader, and is not movable.  */
177609bfb054Sbellard             /* NOTE: for qemu, we do a big mmap to get enough space
1777e91c8a77Sths                without hardcoding any address */
177854936004Sbellard             error = target_mmap(0, ET_DYN_MAP_SIZE,
177909bfb054Sbellard                                 PROT_NONE, MAP_PRIVATE | MAP_ANON,
178009bfb054Sbellard                                 -1, 0);
178109bfb054Sbellard             if (error == -1) {
178209bfb054Sbellard                 perror("mmap");
178309bfb054Sbellard                 exit(-1);
178409bfb054Sbellard             }
178554936004Sbellard             load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
178609bfb054Sbellard         }
178731e31b8aSbellard 
178854936004Sbellard         error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
178931e31b8aSbellard                             (elf_ppnt->p_filesz +
179054936004Sbellard                              TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
179131e31b8aSbellard                             elf_prot,
179231e31b8aSbellard                             (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
179331e31b8aSbellard                             bprm->fd,
179431e31b8aSbellard                             (elf_ppnt->p_offset -
179554936004Sbellard                              TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
179609bfb054Sbellard         if (error == -1) {
179731e31b8aSbellard             perror("mmap");
179831e31b8aSbellard             exit(-1);
179931e31b8aSbellard         }
180031e31b8aSbellard 
180131e31b8aSbellard #ifdef LOW_ELF_STACK
180254936004Sbellard         if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
180354936004Sbellard             elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
180431e31b8aSbellard #endif
180531e31b8aSbellard 
180631e31b8aSbellard         if (!load_addr_set) {
180731e31b8aSbellard             load_addr_set = 1;
180809bfb054Sbellard             load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
180909bfb054Sbellard             if (elf_ex.e_type == ET_DYN) {
181009bfb054Sbellard                 load_bias += error -
181154936004Sbellard                     TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
181209bfb054Sbellard                 load_addr += load_bias;
181384409ddbSj_mayer                 reloc_func_desc = load_bias;
181409bfb054Sbellard             }
181531e31b8aSbellard         }
181631e31b8aSbellard         k = elf_ppnt->p_vaddr;
181709bfb054Sbellard         if (k < start_code)
181809bfb054Sbellard             start_code = k;
1819863cf0b7Sj_mayer         if (start_data < k)
1820863cf0b7Sj_mayer             start_data = k;
182131e31b8aSbellard         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
182209bfb054Sbellard         if (k > elf_bss)
182309bfb054Sbellard             elf_bss = k;
182431e31b8aSbellard         if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
182531e31b8aSbellard             end_code = k;
182609bfb054Sbellard         if (end_data < k)
182709bfb054Sbellard             end_data = k;
182831e31b8aSbellard         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
182931e31b8aSbellard         if (k > elf_brk) elf_brk = k;
183031e31b8aSbellard     }
183109bfb054Sbellard 
183209bfb054Sbellard     elf_entry += load_bias;
183309bfb054Sbellard     elf_bss += load_bias;
183409bfb054Sbellard     elf_brk += load_bias;
183509bfb054Sbellard     start_code += load_bias;
183609bfb054Sbellard     end_code += load_bias;
1837863cf0b7Sj_mayer     start_data += load_bias;
183809bfb054Sbellard     end_data += load_bias;
183931e31b8aSbellard 
184031e31b8aSbellard     if (elf_interpreter) {
184131e31b8aSbellard 	if (interpreter_type & 1) {
184231e31b8aSbellard 	    elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
184331e31b8aSbellard 	}
184431e31b8aSbellard 	else if (interpreter_type & 2) {
184531e31b8aSbellard 	    elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
184631e31b8aSbellard 					    &interp_load_addr);
184731e31b8aSbellard 	}
184884409ddbSj_mayer         reloc_func_desc = interp_load_addr;
184931e31b8aSbellard 
185031e31b8aSbellard 	close(interpreter_fd);
185131e31b8aSbellard 	free(elf_interpreter);
185231e31b8aSbellard 
1853992f48a0Sblueswir1 	if (elf_entry == ~((abi_ulong)0UL)) {
185431e31b8aSbellard 	    printf("Unable to load interpreter\n");
185531e31b8aSbellard 	    free(elf_phdata);
185631e31b8aSbellard 	    exit(-1);
185731e31b8aSbellard 	    return 0;
185831e31b8aSbellard 	}
185931e31b8aSbellard     }
186031e31b8aSbellard 
186131e31b8aSbellard     free(elf_phdata);
186231e31b8aSbellard 
186393fcfe39Saliguori     if (qemu_log_enabled())
1864689f936fSbellard 	load_symbols(&elf_ex, bprm->fd);
1865689f936fSbellard 
186631e31b8aSbellard     if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
186731e31b8aSbellard     info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
186831e31b8aSbellard 
186931e31b8aSbellard #ifdef LOW_ELF_STACK
187031e31b8aSbellard     info->start_stack = bprm->p = elf_stack - 4;
187131e31b8aSbellard #endif
187253a5960aSpbrook     bprm->p = create_elf_tables(bprm->p,
187331e31b8aSbellard 		    bprm->argc,
187431e31b8aSbellard 		    bprm->envc,
1875a1516e92Sbellard                     &elf_ex,
187609bfb054Sbellard                     load_addr, load_bias,
187731e31b8aSbellard 		    interp_load_addr,
187831e31b8aSbellard 		    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
187931e31b8aSbellard 		    info);
188092a343daSj_mayer     info->load_addr = reloc_func_desc;
188131e31b8aSbellard     info->start_brk = info->brk = elf_brk;
188231e31b8aSbellard     info->end_code = end_code;
188331e31b8aSbellard     info->start_code = start_code;
1884863cf0b7Sj_mayer     info->start_data = start_data;
188531e31b8aSbellard     info->end_data = end_data;
188631e31b8aSbellard     info->start_stack = bprm->p;
188731e31b8aSbellard 
188831e31b8aSbellard     /* Calling set_brk effectively mmaps the pages that we need for the bss and break
188931e31b8aSbellard        sections */
189031e31b8aSbellard     set_brk(elf_bss, elf_brk);
189131e31b8aSbellard 
1892768a4a36Sths     padzero(elf_bss, elf_brk);
189331e31b8aSbellard 
189431e31b8aSbellard #if 0
189531e31b8aSbellard     printf("(start_brk) %x\n" , info->start_brk);
189631e31b8aSbellard     printf("(end_code) %x\n" , info->end_code);
189731e31b8aSbellard     printf("(start_code) %x\n" , info->start_code);
189831e31b8aSbellard     printf("(end_data) %x\n" , info->end_data);
189931e31b8aSbellard     printf("(start_stack) %x\n" , info->start_stack);
190031e31b8aSbellard     printf("(brk) %x\n" , info->brk);
190131e31b8aSbellard #endif
190231e31b8aSbellard 
190331e31b8aSbellard     if ( info->personality == PER_SVR4 )
190431e31b8aSbellard     {
190531e31b8aSbellard 	    /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
190631e31b8aSbellard 	       and some applications "depend" upon this behavior.
190731e31b8aSbellard 	       Since we do not have the power to recompile these, we
190831e31b8aSbellard 	       emulate the SVr4 behavior.  Sigh.  */
190983fb7adfSbellard 	    mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
191031e31b8aSbellard                                       MAP_FIXED | MAP_PRIVATE, -1, 0);
191131e31b8aSbellard     }
191231e31b8aSbellard 
191331e31b8aSbellard     info->entry = elf_entry;
191431e31b8aSbellard 
1915edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
1916edf8e2afSMika Westerberg     bprm->core_dump = &elf_core_dump;
1917edf8e2afSMika Westerberg #endif
1918edf8e2afSMika Westerberg 
191931e31b8aSbellard     return 0;
192031e31b8aSbellard }
192131e31b8aSbellard 
1922edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
1923edf8e2afSMika Westerberg 
1924edf8e2afSMika Westerberg /*
1925edf8e2afSMika Westerberg  * Definitions to generate Intel SVR4-like core files.
1926a2547a13SLaurent Desnogues  * These mostly have the same names as the SVR4 types with "target_elf_"
1927edf8e2afSMika Westerberg  * tacked on the front to prevent clashes with linux definitions,
1928edf8e2afSMika Westerberg  * and the typedef forms have been avoided.  This is mostly like
1929edf8e2afSMika Westerberg  * the SVR4 structure, but more Linuxy, with things that Linux does
1930edf8e2afSMika Westerberg  * not support and which gdb doesn't really use excluded.
1931edf8e2afSMika Westerberg  *
1932edf8e2afSMika Westerberg  * Fields we don't dump (their contents is zero) in linux-user qemu
1933edf8e2afSMika Westerberg  * are marked with XXX.
1934edf8e2afSMika Westerberg  *
1935edf8e2afSMika Westerberg  * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
1936edf8e2afSMika Westerberg  *
1937edf8e2afSMika Westerberg  * Porting ELF coredump for target is (quite) simple process.  First you
1938dd0a3651SNathan Froyd  * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
1939edf8e2afSMika Westerberg  * the target resides):
1940edf8e2afSMika Westerberg  *
1941edf8e2afSMika Westerberg  * #define USE_ELF_CORE_DUMP
1942edf8e2afSMika Westerberg  *
1943edf8e2afSMika Westerberg  * Next you define type of register set used for dumping.  ELF specification
1944edf8e2afSMika Westerberg  * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
1945edf8e2afSMika Westerberg  *
1946c227f099SAnthony Liguori  * typedef <target_regtype> target_elf_greg_t;
1947edf8e2afSMika Westerberg  * #define ELF_NREG <number of registers>
1948c227f099SAnthony Liguori  * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
1949edf8e2afSMika Westerberg  *
1950edf8e2afSMika Westerberg  * Last step is to implement target specific function that copies registers
1951edf8e2afSMika Westerberg  * from given cpu into just specified register set.  Prototype is:
1952edf8e2afSMika Westerberg  *
1953c227f099SAnthony Liguori  * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
1954a2547a13SLaurent Desnogues  *                                const CPUState *env);
1955edf8e2afSMika Westerberg  *
1956edf8e2afSMika Westerberg  * Parameters:
1957edf8e2afSMika Westerberg  *     regs - copy register values into here (allocated and zeroed by caller)
1958edf8e2afSMika Westerberg  *     env - copy registers from here
1959edf8e2afSMika Westerberg  *
1960edf8e2afSMika Westerberg  * Example for ARM target is provided in this file.
1961edf8e2afSMika Westerberg  */
1962edf8e2afSMika Westerberg 
1963edf8e2afSMika Westerberg /* An ELF note in memory */
1964edf8e2afSMika Westerberg struct memelfnote {
1965edf8e2afSMika Westerberg     const char *name;
1966edf8e2afSMika Westerberg     size_t     namesz;
1967edf8e2afSMika Westerberg     size_t     namesz_rounded;
1968edf8e2afSMika Westerberg     int        type;
1969edf8e2afSMika Westerberg     size_t     datasz;
1970edf8e2afSMika Westerberg     void       *data;
1971edf8e2afSMika Westerberg     size_t     notesz;
1972edf8e2afSMika Westerberg };
1973edf8e2afSMika Westerberg 
1974a2547a13SLaurent Desnogues struct target_elf_siginfo {
1975edf8e2afSMika Westerberg     int  si_signo; /* signal number */
1976edf8e2afSMika Westerberg     int  si_code;  /* extra code */
1977edf8e2afSMika Westerberg     int  si_errno; /* errno */
1978edf8e2afSMika Westerberg };
1979edf8e2afSMika Westerberg 
1980a2547a13SLaurent Desnogues struct target_elf_prstatus {
1981a2547a13SLaurent Desnogues     struct target_elf_siginfo pr_info;      /* Info associated with signal */
1982edf8e2afSMika Westerberg     short              pr_cursig;    /* Current signal */
1983edf8e2afSMika Westerberg     target_ulong       pr_sigpend;   /* XXX */
1984edf8e2afSMika Westerberg     target_ulong       pr_sighold;   /* XXX */
1985c227f099SAnthony Liguori     target_pid_t       pr_pid;
1986c227f099SAnthony Liguori     target_pid_t       pr_ppid;
1987c227f099SAnthony Liguori     target_pid_t       pr_pgrp;
1988c227f099SAnthony Liguori     target_pid_t       pr_sid;
1989edf8e2afSMika Westerberg     struct target_timeval pr_utime;  /* XXX User time */
1990edf8e2afSMika Westerberg     struct target_timeval pr_stime;  /* XXX System time */
1991edf8e2afSMika Westerberg     struct target_timeval pr_cutime; /* XXX Cumulative user time */
1992edf8e2afSMika Westerberg     struct target_timeval pr_cstime; /* XXX Cumulative system time */
1993c227f099SAnthony Liguori     target_elf_gregset_t      pr_reg;       /* GP registers */
1994edf8e2afSMika Westerberg     int                pr_fpvalid;   /* XXX */
1995edf8e2afSMika Westerberg };
1996edf8e2afSMika Westerberg 
1997edf8e2afSMika Westerberg #define ELF_PRARGSZ     (80) /* Number of chars for args */
1998edf8e2afSMika Westerberg 
1999a2547a13SLaurent Desnogues struct target_elf_prpsinfo {
2000edf8e2afSMika Westerberg     char         pr_state;       /* numeric process state */
2001edf8e2afSMika Westerberg     char         pr_sname;       /* char for pr_state */
2002edf8e2afSMika Westerberg     char         pr_zomb;        /* zombie */
2003edf8e2afSMika Westerberg     char         pr_nice;        /* nice val */
2004edf8e2afSMika Westerberg     target_ulong pr_flag;        /* flags */
2005c227f099SAnthony Liguori     target_uid_t pr_uid;
2006c227f099SAnthony Liguori     target_gid_t pr_gid;
2007c227f099SAnthony Liguori     target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
2008edf8e2afSMika Westerberg     /* Lots missing */
2009edf8e2afSMika Westerberg     char    pr_fname[16];           /* filename of executable */
2010edf8e2afSMika Westerberg     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
2011edf8e2afSMika Westerberg };
2012edf8e2afSMika Westerberg 
2013edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */
2014edf8e2afSMika Westerberg struct elf_thread_status {
201572cf2d4fSBlue Swirl     QTAILQ_ENTRY(elf_thread_status)  ets_link;
2016a2547a13SLaurent Desnogues     struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
2017edf8e2afSMika Westerberg #if 0
2018edf8e2afSMika Westerberg     elf_fpregset_t fpu;             /* NT_PRFPREG */
2019edf8e2afSMika Westerberg     struct task_struct *thread;
2020edf8e2afSMika Westerberg     elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */
2021edf8e2afSMika Westerberg #endif
2022edf8e2afSMika Westerberg     struct memelfnote notes[1];
2023edf8e2afSMika Westerberg     int num_notes;
2024edf8e2afSMika Westerberg };
2025edf8e2afSMika Westerberg 
2026edf8e2afSMika Westerberg struct elf_note_info {
2027edf8e2afSMika Westerberg     struct memelfnote   *notes;
2028a2547a13SLaurent Desnogues     struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
2029a2547a13SLaurent Desnogues     struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
2030edf8e2afSMika Westerberg 
203172cf2d4fSBlue Swirl     QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
2032edf8e2afSMika Westerberg #if 0
2033edf8e2afSMika Westerberg     /*
2034edf8e2afSMika Westerberg      * Current version of ELF coredump doesn't support
2035edf8e2afSMika Westerberg      * dumping fp regs etc.
2036edf8e2afSMika Westerberg      */
2037edf8e2afSMika Westerberg     elf_fpregset_t *fpu;
2038edf8e2afSMika Westerberg     elf_fpxregset_t *xfpu;
2039edf8e2afSMika Westerberg     int thread_status_size;
2040edf8e2afSMika Westerberg #endif
2041edf8e2afSMika Westerberg     int notes_size;
2042edf8e2afSMika Westerberg     int numnote;
2043edf8e2afSMika Westerberg };
2044edf8e2afSMika Westerberg 
2045edf8e2afSMika Westerberg struct vm_area_struct {
2046edf8e2afSMika Westerberg     abi_ulong   vma_start;  /* start vaddr of memory region */
2047edf8e2afSMika Westerberg     abi_ulong   vma_end;    /* end vaddr of memory region */
2048edf8e2afSMika Westerberg     abi_ulong   vma_flags;  /* protection etc. flags for the region */
204972cf2d4fSBlue Swirl     QTAILQ_ENTRY(vm_area_struct) vma_link;
2050edf8e2afSMika Westerberg };
2051edf8e2afSMika Westerberg 
2052edf8e2afSMika Westerberg struct mm_struct {
205372cf2d4fSBlue Swirl     QTAILQ_HEAD(, vm_area_struct) mm_mmap;
2054edf8e2afSMika Westerberg     int mm_count;           /* number of mappings */
2055edf8e2afSMika Westerberg };
2056edf8e2afSMika Westerberg 
2057edf8e2afSMika Westerberg static struct mm_struct *vma_init(void);
2058edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *);
2059edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *, abi_ulong,
2060edf8e2afSMika Westerberg     abi_ulong, abi_ulong);
2061edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *);
2062edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *);
2063edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *);
2064edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *);
2065b480d9b7SPaul Brook static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
2066edf8e2afSMika Westerberg     unsigned long flags);
2067edf8e2afSMika Westerberg 
2068edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
2069edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int,
2070edf8e2afSMika Westerberg     unsigned int, void *);
2071a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
2072a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
2073edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *);
2074edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
2075edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *);
2076edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *);
2077edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *, long, const CPUState *);
2078edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *, const CPUState *);
2079edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t);
2080edf8e2afSMika Westerberg 
2081edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t);
2082edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int);
2083edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int);
2084edf8e2afSMika Westerberg 
2085edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2086a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *);
2087a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *);
2088edf8e2afSMika Westerberg 
2089a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus)
2090edf8e2afSMika Westerberg {
2091edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
2092edf8e2afSMika Westerberg     prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
2093edf8e2afSMika Westerberg     prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
2094edf8e2afSMika Westerberg     prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
2095edf8e2afSMika Westerberg     prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
2096edf8e2afSMika Westerberg     prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
2097edf8e2afSMika Westerberg     prstatus->pr_pid = tswap32(prstatus->pr_pid);
2098edf8e2afSMika Westerberg     prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
2099edf8e2afSMika Westerberg     prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
2100edf8e2afSMika Westerberg     prstatus->pr_sid = tswap32(prstatus->pr_sid);
2101edf8e2afSMika Westerberg     /* cpu times are not filled, so we skip them */
2102edf8e2afSMika Westerberg     /* regs should be in correct format already */
2103edf8e2afSMika Westerberg     prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
2104edf8e2afSMika Westerberg }
2105edf8e2afSMika Westerberg 
2106a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
2107edf8e2afSMika Westerberg {
2108edf8e2afSMika Westerberg     psinfo->pr_flag = tswapl(psinfo->pr_flag);
2109edf8e2afSMika Westerberg     psinfo->pr_uid = tswap16(psinfo->pr_uid);
2110edf8e2afSMika Westerberg     psinfo->pr_gid = tswap16(psinfo->pr_gid);
2111edf8e2afSMika Westerberg     psinfo->pr_pid = tswap32(psinfo->pr_pid);
2112edf8e2afSMika Westerberg     psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
2113edf8e2afSMika Westerberg     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
2114edf8e2afSMika Westerberg     psinfo->pr_sid = tswap32(psinfo->pr_sid);
2115edf8e2afSMika Westerberg }
2116edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
2117edf8e2afSMika Westerberg 
2118edf8e2afSMika Westerberg /*
2119edf8e2afSMika Westerberg  * Minimal support for linux memory regions.  These are needed
2120edf8e2afSMika Westerberg  * when we are finding out what memory exactly belongs to
2121edf8e2afSMika Westerberg  * emulated process.  No locks needed here, as long as
2122edf8e2afSMika Westerberg  * thread that received the signal is stopped.
2123edf8e2afSMika Westerberg  */
2124edf8e2afSMika Westerberg 
2125edf8e2afSMika Westerberg static struct mm_struct *vma_init(void)
2126edf8e2afSMika Westerberg {
2127edf8e2afSMika Westerberg     struct mm_struct *mm;
2128edf8e2afSMika Westerberg 
2129edf8e2afSMika Westerberg     if ((mm = qemu_malloc(sizeof (*mm))) == NULL)
2130edf8e2afSMika Westerberg         return (NULL);
2131edf8e2afSMika Westerberg 
2132edf8e2afSMika Westerberg     mm->mm_count = 0;
213372cf2d4fSBlue Swirl     QTAILQ_INIT(&mm->mm_mmap);
2134edf8e2afSMika Westerberg 
2135edf8e2afSMika Westerberg     return (mm);
2136edf8e2afSMika Westerberg }
2137edf8e2afSMika Westerberg 
2138edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm)
2139edf8e2afSMika Westerberg {
2140edf8e2afSMika Westerberg     struct vm_area_struct *vma;
2141edf8e2afSMika Westerberg 
2142edf8e2afSMika Westerberg     while ((vma = vma_first(mm)) != NULL) {
214372cf2d4fSBlue Swirl         QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
2144edf8e2afSMika Westerberg         qemu_free(vma);
2145edf8e2afSMika Westerberg     }
2146edf8e2afSMika Westerberg     qemu_free(mm);
2147edf8e2afSMika Westerberg }
2148edf8e2afSMika Westerberg 
2149edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
2150edf8e2afSMika Westerberg     abi_ulong end, abi_ulong flags)
2151edf8e2afSMika Westerberg {
2152edf8e2afSMika Westerberg     struct vm_area_struct *vma;
2153edf8e2afSMika Westerberg 
2154edf8e2afSMika Westerberg     if ((vma = qemu_mallocz(sizeof (*vma))) == NULL)
2155edf8e2afSMika Westerberg         return (-1);
2156edf8e2afSMika Westerberg 
2157edf8e2afSMika Westerberg     vma->vma_start = start;
2158edf8e2afSMika Westerberg     vma->vma_end = end;
2159edf8e2afSMika Westerberg     vma->vma_flags = flags;
2160edf8e2afSMika Westerberg 
216172cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
2162edf8e2afSMika Westerberg     mm->mm_count++;
2163edf8e2afSMika Westerberg 
2164edf8e2afSMika Westerberg     return (0);
2165edf8e2afSMika Westerberg }
2166edf8e2afSMika Westerberg 
2167edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2168edf8e2afSMika Westerberg {
216972cf2d4fSBlue Swirl     return (QTAILQ_FIRST(&mm->mm_mmap));
2170edf8e2afSMika Westerberg }
2171edf8e2afSMika Westerberg 
2172edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2173edf8e2afSMika Westerberg {
217472cf2d4fSBlue Swirl     return (QTAILQ_NEXT(vma, vma_link));
2175edf8e2afSMika Westerberg }
2176edf8e2afSMika Westerberg 
2177edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm)
2178edf8e2afSMika Westerberg {
2179edf8e2afSMika Westerberg     return (mm->mm_count);
2180edf8e2afSMika Westerberg }
2181edf8e2afSMika Westerberg 
2182edf8e2afSMika Westerberg /*
2183edf8e2afSMika Westerberg  * Calculate file (dump) size of given memory region.
2184edf8e2afSMika Westerberg  */
2185edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2186edf8e2afSMika Westerberg {
2187edf8e2afSMika Westerberg     /* if we cannot even read the first page, skip it */
2188edf8e2afSMika Westerberg     if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2189edf8e2afSMika Westerberg         return (0);
2190edf8e2afSMika Westerberg 
2191edf8e2afSMika Westerberg     /*
2192edf8e2afSMika Westerberg      * Usually we don't dump executable pages as they contain
2193edf8e2afSMika Westerberg      * non-writable code that debugger can read directly from
2194edf8e2afSMika Westerberg      * target library etc.  However, thread stacks are marked
2195edf8e2afSMika Westerberg      * also executable so we read in first page of given region
2196edf8e2afSMika Westerberg      * and check whether it contains elf header.  If there is
2197edf8e2afSMika Westerberg      * no elf header, we dump it.
2198edf8e2afSMika Westerberg      */
2199edf8e2afSMika Westerberg     if (vma->vma_flags & PROT_EXEC) {
2200edf8e2afSMika Westerberg         char page[TARGET_PAGE_SIZE];
2201edf8e2afSMika Westerberg 
2202edf8e2afSMika Westerberg         copy_from_user(page, vma->vma_start, sizeof (page));
2203edf8e2afSMika Westerberg         if ((page[EI_MAG0] == ELFMAG0) &&
2204edf8e2afSMika Westerberg             (page[EI_MAG1] == ELFMAG1) &&
2205edf8e2afSMika Westerberg             (page[EI_MAG2] == ELFMAG2) &&
2206edf8e2afSMika Westerberg             (page[EI_MAG3] == ELFMAG3)) {
2207edf8e2afSMika Westerberg             /*
2208edf8e2afSMika Westerberg              * Mappings are possibly from ELF binary.  Don't dump
2209edf8e2afSMika Westerberg              * them.
2210edf8e2afSMika Westerberg              */
2211edf8e2afSMika Westerberg             return (0);
2212edf8e2afSMika Westerberg         }
2213edf8e2afSMika Westerberg     }
2214edf8e2afSMika Westerberg 
2215edf8e2afSMika Westerberg     return (vma->vma_end - vma->vma_start);
2216edf8e2afSMika Westerberg }
2217edf8e2afSMika Westerberg 
2218b480d9b7SPaul Brook static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
2219edf8e2afSMika Westerberg     unsigned long flags)
2220edf8e2afSMika Westerberg {
2221edf8e2afSMika Westerberg     struct mm_struct *mm = (struct mm_struct *)priv;
2222edf8e2afSMika Westerberg 
2223edf8e2afSMika Westerberg     vma_add_mapping(mm, start, end, flags);
2224edf8e2afSMika Westerberg     return (0);
2225edf8e2afSMika Westerberg }
2226edf8e2afSMika Westerberg 
2227edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type,
2228edf8e2afSMika Westerberg     unsigned int sz, void *data)
2229edf8e2afSMika Westerberg {
2230edf8e2afSMika Westerberg     unsigned int namesz;
2231edf8e2afSMika Westerberg 
2232edf8e2afSMika Westerberg     namesz = strlen(name) + 1;
2233edf8e2afSMika Westerberg     note->name = name;
2234edf8e2afSMika Westerberg     note->namesz = namesz;
2235edf8e2afSMika Westerberg     note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2236edf8e2afSMika Westerberg     note->type = type;
2237edf8e2afSMika Westerberg     note->datasz = roundup(sz, sizeof (int32_t));;
2238edf8e2afSMika Westerberg     note->data = data;
2239edf8e2afSMika Westerberg 
2240edf8e2afSMika Westerberg     /*
2241edf8e2afSMika Westerberg      * We calculate rounded up note size here as specified by
2242edf8e2afSMika Westerberg      * ELF document.
2243edf8e2afSMika Westerberg      */
2244edf8e2afSMika Westerberg     note->notesz = sizeof (struct elf_note) +
2245edf8e2afSMika Westerberg         note->namesz_rounded + note->datasz;
2246edf8e2afSMika Westerberg }
2247edf8e2afSMika Westerberg 
2248edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
2249edf8e2afSMika Westerberg     uint32_t flags)
2250edf8e2afSMika Westerberg {
2251edf8e2afSMika Westerberg     (void) memset(elf, 0, sizeof(*elf));
2252edf8e2afSMika Westerberg 
2253edf8e2afSMika Westerberg     (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2254edf8e2afSMika Westerberg     elf->e_ident[EI_CLASS] = ELF_CLASS;
2255edf8e2afSMika Westerberg     elf->e_ident[EI_DATA] = ELF_DATA;
2256edf8e2afSMika Westerberg     elf->e_ident[EI_VERSION] = EV_CURRENT;
2257edf8e2afSMika Westerberg     elf->e_ident[EI_OSABI] = ELF_OSABI;
2258edf8e2afSMika Westerberg 
2259edf8e2afSMika Westerberg     elf->e_type = ET_CORE;
2260edf8e2afSMika Westerberg     elf->e_machine = machine;
2261edf8e2afSMika Westerberg     elf->e_version = EV_CURRENT;
2262edf8e2afSMika Westerberg     elf->e_phoff = sizeof(struct elfhdr);
2263edf8e2afSMika Westerberg     elf->e_flags = flags;
2264edf8e2afSMika Westerberg     elf->e_ehsize = sizeof(struct elfhdr);
2265edf8e2afSMika Westerberg     elf->e_phentsize = sizeof(struct elf_phdr);
2266edf8e2afSMika Westerberg     elf->e_phnum = segs;
2267edf8e2afSMika Westerberg 
2268edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2269edf8e2afSMika Westerberg     bswap_ehdr(elf);
2270edf8e2afSMika Westerberg #endif
2271edf8e2afSMika Westerberg }
2272edf8e2afSMika Westerberg 
2273edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2274edf8e2afSMika Westerberg {
2275edf8e2afSMika Westerberg     phdr->p_type = PT_NOTE;
2276edf8e2afSMika Westerberg     phdr->p_offset = offset;
2277edf8e2afSMika Westerberg     phdr->p_vaddr = 0;
2278edf8e2afSMika Westerberg     phdr->p_paddr = 0;
2279edf8e2afSMika Westerberg     phdr->p_filesz = sz;
2280edf8e2afSMika Westerberg     phdr->p_memsz = 0;
2281edf8e2afSMika Westerberg     phdr->p_flags = 0;
2282edf8e2afSMika Westerberg     phdr->p_align = 0;
2283edf8e2afSMika Westerberg 
2284edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2285edf8e2afSMika Westerberg     bswap_phdr(phdr);
2286edf8e2afSMika Westerberg #endif
2287edf8e2afSMika Westerberg }
2288edf8e2afSMika Westerberg 
2289edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note)
2290edf8e2afSMika Westerberg {
2291edf8e2afSMika Westerberg     return (note->notesz);
2292edf8e2afSMika Westerberg }
2293edf8e2afSMika Westerberg 
2294a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus,
2295edf8e2afSMika Westerberg     const TaskState *ts, int signr)
2296edf8e2afSMika Westerberg {
2297edf8e2afSMika Westerberg     (void) memset(prstatus, 0, sizeof (*prstatus));
2298edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2299edf8e2afSMika Westerberg     prstatus->pr_pid = ts->ts_tid;
2300edf8e2afSMika Westerberg     prstatus->pr_ppid = getppid();
2301edf8e2afSMika Westerberg     prstatus->pr_pgrp = getpgrp();
2302edf8e2afSMika Westerberg     prstatus->pr_sid = getsid(0);
2303edf8e2afSMika Westerberg 
2304edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2305edf8e2afSMika Westerberg     bswap_prstatus(prstatus);
2306edf8e2afSMika Westerberg #endif
2307edf8e2afSMika Westerberg }
2308edf8e2afSMika Westerberg 
2309a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
2310edf8e2afSMika Westerberg {
2311edf8e2afSMika Westerberg     char *filename, *base_filename;
2312edf8e2afSMika Westerberg     unsigned int i, len;
2313edf8e2afSMika Westerberg 
2314edf8e2afSMika Westerberg     (void) memset(psinfo, 0, sizeof (*psinfo));
2315edf8e2afSMika Westerberg 
2316edf8e2afSMika Westerberg     len = ts->info->arg_end - ts->info->arg_start;
2317edf8e2afSMika Westerberg     if (len >= ELF_PRARGSZ)
2318edf8e2afSMika Westerberg         len = ELF_PRARGSZ - 1;
2319edf8e2afSMika Westerberg     if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2320edf8e2afSMika Westerberg         return -EFAULT;
2321edf8e2afSMika Westerberg     for (i = 0; i < len; i++)
2322edf8e2afSMika Westerberg         if (psinfo->pr_psargs[i] == 0)
2323edf8e2afSMika Westerberg             psinfo->pr_psargs[i] = ' ';
2324edf8e2afSMika Westerberg     psinfo->pr_psargs[len] = 0;
2325edf8e2afSMika Westerberg 
2326edf8e2afSMika Westerberg     psinfo->pr_pid = getpid();
2327edf8e2afSMika Westerberg     psinfo->pr_ppid = getppid();
2328edf8e2afSMika Westerberg     psinfo->pr_pgrp = getpgrp();
2329edf8e2afSMika Westerberg     psinfo->pr_sid = getsid(0);
2330edf8e2afSMika Westerberg     psinfo->pr_uid = getuid();
2331edf8e2afSMika Westerberg     psinfo->pr_gid = getgid();
2332edf8e2afSMika Westerberg 
2333edf8e2afSMika Westerberg     filename = strdup(ts->bprm->filename);
2334edf8e2afSMika Westerberg     base_filename = strdup(basename(filename));
2335edf8e2afSMika Westerberg     (void) strncpy(psinfo->pr_fname, base_filename,
2336edf8e2afSMika Westerberg         sizeof(psinfo->pr_fname));
2337edf8e2afSMika Westerberg     free(base_filename);
2338edf8e2afSMika Westerberg     free(filename);
2339edf8e2afSMika Westerberg 
2340edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2341edf8e2afSMika Westerberg     bswap_psinfo(psinfo);
2342edf8e2afSMika Westerberg #endif
2343edf8e2afSMika Westerberg     return (0);
2344edf8e2afSMika Westerberg }
2345edf8e2afSMika Westerberg 
2346edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2347edf8e2afSMika Westerberg {
2348edf8e2afSMika Westerberg     elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2349edf8e2afSMika Westerberg     elf_addr_t orig_auxv = auxv;
2350edf8e2afSMika Westerberg     abi_ulong val;
2351edf8e2afSMika Westerberg     void *ptr;
2352edf8e2afSMika Westerberg     int i, len;
2353edf8e2afSMika Westerberg 
2354edf8e2afSMika Westerberg     /*
2355edf8e2afSMika Westerberg      * Auxiliary vector is stored in target process stack.  It contains
2356edf8e2afSMika Westerberg      * {type, value} pairs that we need to dump into note.  This is not
2357edf8e2afSMika Westerberg      * strictly necessary but we do it here for sake of completeness.
2358edf8e2afSMika Westerberg      */
2359edf8e2afSMika Westerberg 
2360edf8e2afSMika Westerberg     /* find out lenght of the vector, AT_NULL is terminator */
2361edf8e2afSMika Westerberg     i = len = 0;
2362edf8e2afSMika Westerberg     do {
2363edf8e2afSMika Westerberg         get_user_ual(val, auxv);
2364edf8e2afSMika Westerberg         i += 2;
2365edf8e2afSMika Westerberg         auxv += 2 * sizeof (elf_addr_t);
2366edf8e2afSMika Westerberg     } while (val != AT_NULL);
2367edf8e2afSMika Westerberg     len = i * sizeof (elf_addr_t);
2368edf8e2afSMika Westerberg 
2369edf8e2afSMika Westerberg     /* read in whole auxv vector and copy it to memelfnote */
2370edf8e2afSMika Westerberg     ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2371edf8e2afSMika Westerberg     if (ptr != NULL) {
2372edf8e2afSMika Westerberg         fill_note(note, "CORE", NT_AUXV, len, ptr);
2373edf8e2afSMika Westerberg         unlock_user(ptr, auxv, len);
2374edf8e2afSMika Westerberg     }
2375edf8e2afSMika Westerberg }
2376edf8e2afSMika Westerberg 
2377edf8e2afSMika Westerberg /*
2378edf8e2afSMika Westerberg  * Constructs name of coredump file.  We have following convention
2379edf8e2afSMika Westerberg  * for the name:
2380edf8e2afSMika Westerberg  *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2381edf8e2afSMika Westerberg  *
2382edf8e2afSMika Westerberg  * Returns 0 in case of success, -1 otherwise (errno is set).
2383edf8e2afSMika Westerberg  */
2384edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf,
2385edf8e2afSMika Westerberg     size_t bufsize)
2386edf8e2afSMika Westerberg {
2387edf8e2afSMika Westerberg     char timestamp[64];
2388edf8e2afSMika Westerberg     char *filename = NULL;
2389edf8e2afSMika Westerberg     char *base_filename = NULL;
2390edf8e2afSMika Westerberg     struct timeval tv;
2391edf8e2afSMika Westerberg     struct tm tm;
2392edf8e2afSMika Westerberg 
2393edf8e2afSMika Westerberg     assert(bufsize >= PATH_MAX);
2394edf8e2afSMika Westerberg 
2395edf8e2afSMika Westerberg     if (gettimeofday(&tv, NULL) < 0) {
2396edf8e2afSMika Westerberg         (void) fprintf(stderr, "unable to get current timestamp: %s",
2397edf8e2afSMika Westerberg             strerror(errno));
2398edf8e2afSMika Westerberg         return (-1);
2399edf8e2afSMika Westerberg     }
2400edf8e2afSMika Westerberg 
2401edf8e2afSMika Westerberg     filename = strdup(ts->bprm->filename);
2402edf8e2afSMika Westerberg     base_filename = strdup(basename(filename));
2403edf8e2afSMika Westerberg     (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
2404edf8e2afSMika Westerberg         localtime_r(&tv.tv_sec, &tm));
2405edf8e2afSMika Westerberg     (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
2406edf8e2afSMika Westerberg         base_filename, timestamp, (int)getpid());
2407edf8e2afSMika Westerberg     free(base_filename);
2408edf8e2afSMika Westerberg     free(filename);
2409edf8e2afSMika Westerberg 
2410edf8e2afSMika Westerberg     return (0);
2411edf8e2afSMika Westerberg }
2412edf8e2afSMika Westerberg 
2413edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size)
2414edf8e2afSMika Westerberg {
2415edf8e2afSMika Westerberg     const char *bufp = (const char *)ptr;
2416edf8e2afSMika Westerberg     ssize_t bytes_written, bytes_left;
2417edf8e2afSMika Westerberg     struct rlimit dumpsize;
2418edf8e2afSMika Westerberg     off_t pos;
2419edf8e2afSMika Westerberg 
2420edf8e2afSMika Westerberg     bytes_written = 0;
2421edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
2422edf8e2afSMika Westerberg     if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2423edf8e2afSMika Westerberg         if (errno == ESPIPE) { /* not a seekable stream */
2424edf8e2afSMika Westerberg             bytes_left = size;
2425edf8e2afSMika Westerberg         } else {
2426edf8e2afSMika Westerberg             return pos;
2427edf8e2afSMika Westerberg         }
2428edf8e2afSMika Westerberg     } else {
2429edf8e2afSMika Westerberg         if (dumpsize.rlim_cur <= pos) {
2430edf8e2afSMika Westerberg             return -1;
2431edf8e2afSMika Westerberg         } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2432edf8e2afSMika Westerberg             bytes_left = size;
2433edf8e2afSMika Westerberg         } else {
2434edf8e2afSMika Westerberg             size_t limit_left=dumpsize.rlim_cur - pos;
2435edf8e2afSMika Westerberg             bytes_left = limit_left >= size ? size : limit_left ;
2436edf8e2afSMika Westerberg         }
2437edf8e2afSMika Westerberg     }
2438edf8e2afSMika Westerberg 
2439edf8e2afSMika Westerberg     /*
2440edf8e2afSMika Westerberg      * In normal conditions, single write(2) should do but
2441edf8e2afSMika Westerberg      * in case of socket etc. this mechanism is more portable.
2442edf8e2afSMika Westerberg      */
2443edf8e2afSMika Westerberg     do {
2444edf8e2afSMika Westerberg         bytes_written = write(fd, bufp, bytes_left);
2445edf8e2afSMika Westerberg         if (bytes_written < 0) {
2446edf8e2afSMika Westerberg             if (errno == EINTR)
2447edf8e2afSMika Westerberg                 continue;
2448edf8e2afSMika Westerberg             return (-1);
2449edf8e2afSMika Westerberg         } else if (bytes_written == 0) { /* eof */
2450edf8e2afSMika Westerberg             return (-1);
2451edf8e2afSMika Westerberg         }
2452edf8e2afSMika Westerberg         bufp += bytes_written;
2453edf8e2afSMika Westerberg         bytes_left -= bytes_written;
2454edf8e2afSMika Westerberg     } while (bytes_left > 0);
2455edf8e2afSMika Westerberg 
2456edf8e2afSMika Westerberg     return (0);
2457edf8e2afSMika Westerberg }
2458edf8e2afSMika Westerberg 
2459edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd)
2460edf8e2afSMika Westerberg {
2461edf8e2afSMika Westerberg     struct elf_note en;
2462edf8e2afSMika Westerberg 
2463edf8e2afSMika Westerberg     en.n_namesz = men->namesz;
2464edf8e2afSMika Westerberg     en.n_type = men->type;
2465edf8e2afSMika Westerberg     en.n_descsz = men->datasz;
2466edf8e2afSMika Westerberg 
2467edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2468edf8e2afSMika Westerberg     bswap_note(&en);
2469edf8e2afSMika Westerberg #endif
2470edf8e2afSMika Westerberg 
2471edf8e2afSMika Westerberg     if (dump_write(fd, &en, sizeof(en)) != 0)
2472edf8e2afSMika Westerberg         return (-1);
2473edf8e2afSMika Westerberg     if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2474edf8e2afSMika Westerberg         return (-1);
2475edf8e2afSMika Westerberg     if (dump_write(fd, men->data, men->datasz) != 0)
2476edf8e2afSMika Westerberg         return (-1);
2477edf8e2afSMika Westerberg 
2478edf8e2afSMika Westerberg     return (0);
2479edf8e2afSMika Westerberg }
2480edf8e2afSMika Westerberg 
2481edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
2482edf8e2afSMika Westerberg {
2483edf8e2afSMika Westerberg     TaskState *ts = (TaskState *)env->opaque;
2484edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2485edf8e2afSMika Westerberg 
2486edf8e2afSMika Westerberg     ets = qemu_mallocz(sizeof (*ets));
2487edf8e2afSMika Westerberg     ets->num_notes = 1; /* only prstatus is dumped */
2488edf8e2afSMika Westerberg     fill_prstatus(&ets->prstatus, ts, 0);
2489edf8e2afSMika Westerberg     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2490edf8e2afSMika Westerberg     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
2491edf8e2afSMika Westerberg         &ets->prstatus);
2492edf8e2afSMika Westerberg 
249372cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
2494edf8e2afSMika Westerberg 
2495edf8e2afSMika Westerberg     info->notes_size += note_size(&ets->notes[0]);
2496edf8e2afSMika Westerberg }
2497edf8e2afSMika Westerberg 
2498edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info,
2499edf8e2afSMika Westerberg     long signr, const CPUState *env)
2500edf8e2afSMika Westerberg {
2501edf8e2afSMika Westerberg #define NUMNOTES 3
2502edf8e2afSMika Westerberg     CPUState *cpu = NULL;
2503edf8e2afSMika Westerberg     TaskState *ts = (TaskState *)env->opaque;
2504edf8e2afSMika Westerberg     int i;
2505edf8e2afSMika Westerberg 
2506edf8e2afSMika Westerberg     (void) memset(info, 0, sizeof (*info));
2507edf8e2afSMika Westerberg 
250872cf2d4fSBlue Swirl     QTAILQ_INIT(&info->thread_list);
2509edf8e2afSMika Westerberg 
2510edf8e2afSMika Westerberg     info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote));
2511edf8e2afSMika Westerberg     if (info->notes == NULL)
2512edf8e2afSMika Westerberg         return (-ENOMEM);
2513edf8e2afSMika Westerberg     info->prstatus = qemu_mallocz(sizeof (*info->prstatus));
2514edf8e2afSMika Westerberg     if (info->prstatus == NULL)
2515edf8e2afSMika Westerberg         return (-ENOMEM);
2516edf8e2afSMika Westerberg     info->psinfo = qemu_mallocz(sizeof (*info->psinfo));
2517edf8e2afSMika Westerberg     if (info->prstatus == NULL)
2518edf8e2afSMika Westerberg         return (-ENOMEM);
2519edf8e2afSMika Westerberg 
2520edf8e2afSMika Westerberg     /*
2521edf8e2afSMika Westerberg      * First fill in status (and registers) of current thread
2522edf8e2afSMika Westerberg      * including process info & aux vector.
2523edf8e2afSMika Westerberg      */
2524edf8e2afSMika Westerberg     fill_prstatus(info->prstatus, ts, signr);
2525edf8e2afSMika Westerberg     elf_core_copy_regs(&info->prstatus->pr_reg, env);
2526edf8e2afSMika Westerberg     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
2527edf8e2afSMika Westerberg         sizeof (*info->prstatus), info->prstatus);
2528edf8e2afSMika Westerberg     fill_psinfo(info->psinfo, ts);
2529edf8e2afSMika Westerberg     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
2530edf8e2afSMika Westerberg         sizeof (*info->psinfo), info->psinfo);
2531edf8e2afSMika Westerberg     fill_auxv_note(&info->notes[2], ts);
2532edf8e2afSMika Westerberg     info->numnote = 3;
2533edf8e2afSMika Westerberg 
2534edf8e2afSMika Westerberg     info->notes_size = 0;
2535edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
2536edf8e2afSMika Westerberg         info->notes_size += note_size(&info->notes[i]);
2537edf8e2afSMika Westerberg 
2538edf8e2afSMika Westerberg     /* read and fill status of all threads */
2539edf8e2afSMika Westerberg     cpu_list_lock();
2540edf8e2afSMika Westerberg     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2541edf8e2afSMika Westerberg         if (cpu == thread_env)
2542edf8e2afSMika Westerberg             continue;
2543edf8e2afSMika Westerberg         fill_thread_info(info, cpu);
2544edf8e2afSMika Westerberg     }
2545edf8e2afSMika Westerberg     cpu_list_unlock();
2546edf8e2afSMika Westerberg 
2547edf8e2afSMika Westerberg     return (0);
2548edf8e2afSMika Westerberg }
2549edf8e2afSMika Westerberg 
2550edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info)
2551edf8e2afSMika Westerberg {
2552edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2553edf8e2afSMika Westerberg 
255472cf2d4fSBlue Swirl     while (!QTAILQ_EMPTY(&info->thread_list)) {
255572cf2d4fSBlue Swirl         ets = QTAILQ_FIRST(&info->thread_list);
255672cf2d4fSBlue Swirl         QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
2557edf8e2afSMika Westerberg         qemu_free(ets);
2558edf8e2afSMika Westerberg     }
2559edf8e2afSMika Westerberg 
2560edf8e2afSMika Westerberg     qemu_free(info->prstatus);
2561edf8e2afSMika Westerberg     qemu_free(info->psinfo);
2562edf8e2afSMika Westerberg     qemu_free(info->notes);
2563edf8e2afSMika Westerberg }
2564edf8e2afSMika Westerberg 
2565edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd)
2566edf8e2afSMika Westerberg {
2567edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2568edf8e2afSMika Westerberg     int i, error = 0;
2569edf8e2afSMika Westerberg 
2570edf8e2afSMika Westerberg     /* write prstatus, psinfo and auxv for current thread */
2571edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
2572edf8e2afSMika Westerberg         if ((error = write_note(&info->notes[i], fd)) != 0)
2573edf8e2afSMika Westerberg             return (error);
2574edf8e2afSMika Westerberg 
2575edf8e2afSMika Westerberg     /* write prstatus for each thread */
2576edf8e2afSMika Westerberg     for (ets = info->thread_list.tqh_first; ets != NULL;
2577edf8e2afSMika Westerberg         ets = ets->ets_link.tqe_next) {
2578edf8e2afSMika Westerberg         if ((error = write_note(&ets->notes[0], fd)) != 0)
2579edf8e2afSMika Westerberg             return (error);
2580edf8e2afSMika Westerberg     }
2581edf8e2afSMika Westerberg 
2582edf8e2afSMika Westerberg     return (0);
2583edf8e2afSMika Westerberg }
2584edf8e2afSMika Westerberg 
2585edf8e2afSMika Westerberg /*
2586edf8e2afSMika Westerberg  * Write out ELF coredump.
2587edf8e2afSMika Westerberg  *
2588edf8e2afSMika Westerberg  * See documentation of ELF object file format in:
2589edf8e2afSMika Westerberg  * http://www.caldera.com/developers/devspecs/gabi41.pdf
2590edf8e2afSMika Westerberg  *
2591edf8e2afSMika Westerberg  * Coredump format in linux is following:
2592edf8e2afSMika Westerberg  *
2593edf8e2afSMika Westerberg  * 0   +----------------------+         \
2594edf8e2afSMika Westerberg  *     | ELF header           | ET_CORE  |
2595edf8e2afSMika Westerberg  *     +----------------------+          |
2596edf8e2afSMika Westerberg  *     | ELF program headers  |          |--- headers
2597edf8e2afSMika Westerberg  *     | - NOTE section       |          |
2598edf8e2afSMika Westerberg  *     | - PT_LOAD sections   |          |
2599edf8e2afSMika Westerberg  *     +----------------------+         /
2600edf8e2afSMika Westerberg  *     | NOTEs:               |
2601edf8e2afSMika Westerberg  *     | - NT_PRSTATUS        |
2602edf8e2afSMika Westerberg  *     | - NT_PRSINFO         |
2603edf8e2afSMika Westerberg  *     | - NT_AUXV            |
2604edf8e2afSMika Westerberg  *     +----------------------+ <-- aligned to target page
2605edf8e2afSMika Westerberg  *     | Process memory dump  |
2606edf8e2afSMika Westerberg  *     :                      :
2607edf8e2afSMika Westerberg  *     .                      .
2608edf8e2afSMika Westerberg  *     :                      :
2609edf8e2afSMika Westerberg  *     |                      |
2610edf8e2afSMika Westerberg  *     +----------------------+
2611edf8e2afSMika Westerberg  *
2612edf8e2afSMika Westerberg  * NT_PRSTATUS -> struct elf_prstatus (per thread)
2613edf8e2afSMika Westerberg  * NT_PRSINFO  -> struct elf_prpsinfo
2614edf8e2afSMika Westerberg  * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2615edf8e2afSMika Westerberg  *
2616edf8e2afSMika Westerberg  * Format follows System V format as close as possible.  Current
2617edf8e2afSMika Westerberg  * version limitations are as follows:
2618edf8e2afSMika Westerberg  *     - no floating point registers are dumped
2619edf8e2afSMika Westerberg  *
2620edf8e2afSMika Westerberg  * Function returns 0 in case of success, negative errno otherwise.
2621edf8e2afSMika Westerberg  *
2622edf8e2afSMika Westerberg  * TODO: make this work also during runtime: it should be
2623edf8e2afSMika Westerberg  * possible to force coredump from running process and then
2624edf8e2afSMika Westerberg  * continue processing.  For example qemu could set up SIGUSR2
2625edf8e2afSMika Westerberg  * handler (provided that target process haven't registered
2626edf8e2afSMika Westerberg  * handler for that) that does the dump when signal is received.
2627edf8e2afSMika Westerberg  */
2628edf8e2afSMika Westerberg static int elf_core_dump(int signr, const CPUState *env)
2629edf8e2afSMika Westerberg {
2630edf8e2afSMika Westerberg     const TaskState *ts = (const TaskState *)env->opaque;
2631edf8e2afSMika Westerberg     struct vm_area_struct *vma = NULL;
2632edf8e2afSMika Westerberg     char corefile[PATH_MAX];
2633edf8e2afSMika Westerberg     struct elf_note_info info;
2634edf8e2afSMika Westerberg     struct elfhdr elf;
2635edf8e2afSMika Westerberg     struct elf_phdr phdr;
2636edf8e2afSMika Westerberg     struct rlimit dumpsize;
2637edf8e2afSMika Westerberg     struct mm_struct *mm = NULL;
2638edf8e2afSMika Westerberg     off_t offset = 0, data_offset = 0;
2639edf8e2afSMika Westerberg     int segs = 0;
2640edf8e2afSMika Westerberg     int fd = -1;
2641edf8e2afSMika Westerberg 
2642edf8e2afSMika Westerberg     errno = 0;
2643edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
2644edf8e2afSMika Westerberg     if (dumpsize.rlim_cur == 0)
2645edf8e2afSMika Westerberg        return 0;
2646edf8e2afSMika Westerberg 
2647edf8e2afSMika Westerberg     if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2648edf8e2afSMika Westerberg         return (-errno);
2649edf8e2afSMika Westerberg 
2650edf8e2afSMika Westerberg     if ((fd = open(corefile, O_WRONLY | O_CREAT,
2651edf8e2afSMika Westerberg         S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
2652edf8e2afSMika Westerberg         return (-errno);
2653edf8e2afSMika Westerberg 
2654edf8e2afSMika Westerberg     /*
2655edf8e2afSMika Westerberg      * Walk through target process memory mappings and
2656edf8e2afSMika Westerberg      * set up structure containing this information.  After
2657edf8e2afSMika Westerberg      * this point vma_xxx functions can be used.
2658edf8e2afSMika Westerberg      */
2659edf8e2afSMika Westerberg     if ((mm = vma_init()) == NULL)
2660edf8e2afSMika Westerberg         goto out;
2661edf8e2afSMika Westerberg 
2662edf8e2afSMika Westerberg     walk_memory_regions(mm, vma_walker);
2663edf8e2afSMika Westerberg     segs = vma_get_mapping_count(mm);
2664edf8e2afSMika Westerberg 
2665edf8e2afSMika Westerberg     /*
2666edf8e2afSMika Westerberg      * Construct valid coredump ELF header.  We also
2667edf8e2afSMika Westerberg      * add one more segment for notes.
2668edf8e2afSMika Westerberg      */
2669edf8e2afSMika Westerberg     fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2670edf8e2afSMika Westerberg     if (dump_write(fd, &elf, sizeof (elf)) != 0)
2671edf8e2afSMika Westerberg         goto out;
2672edf8e2afSMika Westerberg 
2673edf8e2afSMika Westerberg     /* fill in in-memory version of notes */
2674edf8e2afSMika Westerberg     if (fill_note_info(&info, signr, env) < 0)
2675edf8e2afSMika Westerberg         goto out;
2676edf8e2afSMika Westerberg 
2677edf8e2afSMika Westerberg     offset += sizeof (elf);                             /* elf header */
2678edf8e2afSMika Westerberg     offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */
2679edf8e2afSMika Westerberg 
2680edf8e2afSMika Westerberg     /* write out notes program header */
2681edf8e2afSMika Westerberg     fill_elf_note_phdr(&phdr, info.notes_size, offset);
2682edf8e2afSMika Westerberg 
2683edf8e2afSMika Westerberg     offset += info.notes_size;
2684edf8e2afSMika Westerberg     if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2685edf8e2afSMika Westerberg         goto out;
2686edf8e2afSMika Westerberg 
2687edf8e2afSMika Westerberg     /*
2688edf8e2afSMika Westerberg      * ELF specification wants data to start at page boundary so
2689edf8e2afSMika Westerberg      * we align it here.
2690edf8e2afSMika Westerberg      */
2691edf8e2afSMika Westerberg     offset = roundup(offset, ELF_EXEC_PAGESIZE);
2692edf8e2afSMika Westerberg 
2693edf8e2afSMika Westerberg     /*
2694edf8e2afSMika Westerberg      * Write program headers for memory regions mapped in
2695edf8e2afSMika Westerberg      * the target process.
2696edf8e2afSMika Westerberg      */
2697edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2698edf8e2afSMika Westerberg         (void) memset(&phdr, 0, sizeof (phdr));
2699edf8e2afSMika Westerberg 
2700edf8e2afSMika Westerberg         phdr.p_type = PT_LOAD;
2701edf8e2afSMika Westerberg         phdr.p_offset = offset;
2702edf8e2afSMika Westerberg         phdr.p_vaddr = vma->vma_start;
2703edf8e2afSMika Westerberg         phdr.p_paddr = 0;
2704edf8e2afSMika Westerberg         phdr.p_filesz = vma_dump_size(vma);
2705edf8e2afSMika Westerberg         offset += phdr.p_filesz;
2706edf8e2afSMika Westerberg         phdr.p_memsz = vma->vma_end - vma->vma_start;
2707edf8e2afSMika Westerberg         phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2708edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_WRITE)
2709edf8e2afSMika Westerberg             phdr.p_flags |= PF_W;
2710edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_EXEC)
2711edf8e2afSMika Westerberg             phdr.p_flags |= PF_X;
2712edf8e2afSMika Westerberg         phdr.p_align = ELF_EXEC_PAGESIZE;
2713edf8e2afSMika Westerberg 
2714edf8e2afSMika Westerberg         dump_write(fd, &phdr, sizeof (phdr));
2715edf8e2afSMika Westerberg     }
2716edf8e2afSMika Westerberg 
2717edf8e2afSMika Westerberg     /*
2718edf8e2afSMika Westerberg      * Next we write notes just after program headers.  No
2719edf8e2afSMika Westerberg      * alignment needed here.
2720edf8e2afSMika Westerberg      */
2721edf8e2afSMika Westerberg     if (write_note_info(&info, fd) < 0)
2722edf8e2afSMika Westerberg         goto out;
2723edf8e2afSMika Westerberg 
2724edf8e2afSMika Westerberg     /* align data to page boundary */
2725edf8e2afSMika Westerberg     data_offset = lseek(fd, 0, SEEK_CUR);
2726edf8e2afSMika Westerberg     data_offset = TARGET_PAGE_ALIGN(data_offset);
2727edf8e2afSMika Westerberg     if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2728edf8e2afSMika Westerberg         goto out;
2729edf8e2afSMika Westerberg 
2730edf8e2afSMika Westerberg     /*
2731edf8e2afSMika Westerberg      * Finally we can dump process memory into corefile as well.
2732edf8e2afSMika Westerberg      */
2733edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2734edf8e2afSMika Westerberg         abi_ulong addr;
2735edf8e2afSMika Westerberg         abi_ulong end;
2736edf8e2afSMika Westerberg 
2737edf8e2afSMika Westerberg         end = vma->vma_start + vma_dump_size(vma);
2738edf8e2afSMika Westerberg 
2739edf8e2afSMika Westerberg         for (addr = vma->vma_start; addr < end;
2740edf8e2afSMika Westerberg             addr += TARGET_PAGE_SIZE) {
2741edf8e2afSMika Westerberg             char page[TARGET_PAGE_SIZE];
2742edf8e2afSMika Westerberg             int error;
2743edf8e2afSMika Westerberg 
2744edf8e2afSMika Westerberg             /*
2745edf8e2afSMika Westerberg              *  Read in page from target process memory and
2746edf8e2afSMika Westerberg              *  write it to coredump file.
2747edf8e2afSMika Westerberg              */
2748edf8e2afSMika Westerberg             error = copy_from_user(page, addr, sizeof (page));
2749edf8e2afSMika Westerberg             if (error != 0) {
275049995e17SAurelien Jarno                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
2751edf8e2afSMika Westerberg                     addr);
2752edf8e2afSMika Westerberg                 errno = -error;
2753edf8e2afSMika Westerberg                 goto out;
2754edf8e2afSMika Westerberg             }
2755edf8e2afSMika Westerberg             if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2756edf8e2afSMika Westerberg                 goto out;
2757edf8e2afSMika Westerberg         }
2758edf8e2afSMika Westerberg     }
2759edf8e2afSMika Westerberg 
2760edf8e2afSMika Westerberg out:
2761edf8e2afSMika Westerberg     free_note_info(&info);
2762edf8e2afSMika Westerberg     if (mm != NULL)
2763edf8e2afSMika Westerberg         vma_delete(mm);
2764edf8e2afSMika Westerberg     (void) close(fd);
2765edf8e2afSMika Westerberg 
2766edf8e2afSMika Westerberg     if (errno != 0)
2767edf8e2afSMika Westerberg         return (-errno);
2768edf8e2afSMika Westerberg     return (0);
2769edf8e2afSMika Westerberg }
2770edf8e2afSMika Westerberg 
2771edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
2772edf8e2afSMika Westerberg 
277331e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd)
277431e31b8aSbellard {
277531e31b8aSbellard     printf("a.out interpreter not yet supported\n");
277631e31b8aSbellard     return(0);
277731e31b8aSbellard }
277831e31b8aSbellard 
2779e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2780e5fe0c52Spbrook {
2781e5fe0c52Spbrook     init_thread(regs, infop);
2782e5fe0c52Spbrook }
2783