xref: /qemu/linux-user/elfload.c (revision 7dd47667b9b0b23807fc1a550644fc2427462f41)
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 */
39d97ef72eSRichard Henderson     FDPIC_FUNCPTRS =    0x0080000,      /* userspace function ptrs point to
40d97ef72eSRichard Henderson                                            descriptors (signal handling) */
41cb33da57Sblueswir1     MMAP_PAGE_ZERO =    0x0100000,
42cb33da57Sblueswir1     ADDR_COMPAT_LAYOUT = 0x0200000,
43cb33da57Sblueswir1     READ_IMPLIES_EXEC = 0x0400000,
44cb33da57Sblueswir1     ADDR_LIMIT_32BIT =  0x0800000,
45cb33da57Sblueswir1     SHORT_INODE =       0x1000000,
46cb33da57Sblueswir1     WHOLE_SECONDS =     0x2000000,
47cb33da57Sblueswir1     STICKY_TIMEOUTS =   0x4000000,
48cb33da57Sblueswir1     ADDR_LIMIT_3GB =    0x8000000,
49cb33da57Sblueswir1 };
50cb33da57Sblueswir1 
51cb33da57Sblueswir1 /*
52cb33da57Sblueswir1  * Personality types.
53cb33da57Sblueswir1  *
54cb33da57Sblueswir1  * These go in the low byte.  Avoid using the top bit, it will
55cb33da57Sblueswir1  * conflict with error returns.
56cb33da57Sblueswir1  */
57cb33da57Sblueswir1 enum {
58cb33da57Sblueswir1     PER_LINUX =         0x0000,
59cb33da57Sblueswir1     PER_LINUX_32BIT =   0x0000 | ADDR_LIMIT_32BIT,
60cb33da57Sblueswir1     PER_LINUX_FDPIC =   0x0000 | FDPIC_FUNCPTRS,
61cb33da57Sblueswir1     PER_SVR4 =          0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
62cb33da57Sblueswir1     PER_SVR3 =          0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
63d97ef72eSRichard Henderson     PER_SCOSVR3 =       0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
64cb33da57Sblueswir1     PER_OSR5 =          0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
65cb33da57Sblueswir1     PER_WYSEV386 =      0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
66cb33da57Sblueswir1     PER_ISCR4 =         0x0005 | STICKY_TIMEOUTS,
67cb33da57Sblueswir1     PER_BSD =           0x0006,
68cb33da57Sblueswir1     PER_SUNOS =         0x0006 | STICKY_TIMEOUTS,
69cb33da57Sblueswir1     PER_XENIX =         0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
70cb33da57Sblueswir1     PER_LINUX32 =       0x0008,
71cb33da57Sblueswir1     PER_LINUX32_3GB =   0x0008 | ADDR_LIMIT_3GB,
72cb33da57Sblueswir1     PER_IRIX32 =        0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
73cb33da57Sblueswir1     PER_IRIXN32 =       0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
74cb33da57Sblueswir1     PER_IRIX64 =        0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
75cb33da57Sblueswir1     PER_RISCOS =        0x000c,
76cb33da57Sblueswir1     PER_SOLARIS =       0x000d | STICKY_TIMEOUTS,
77cb33da57Sblueswir1     PER_UW7 =           0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
78cb33da57Sblueswir1     PER_OSF4 =          0x000f,                  /* OSF/1 v4 */
79cb33da57Sblueswir1     PER_HPUX =          0x0010,
80cb33da57Sblueswir1     PER_MASK =          0x00ff,
81cb33da57Sblueswir1 };
82cb33da57Sblueswir1 
83cb33da57Sblueswir1 /*
84cb33da57Sblueswir1  * Return the base personality without flags.
85cb33da57Sblueswir1  */
86cb33da57Sblueswir1 #define personality(pers)       (pers & PER_MASK)
87cb33da57Sblueswir1 
8883fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */
8983fb7adfSbellard #ifndef MAP_DENYWRITE
9083fb7adfSbellard #define MAP_DENYWRITE 0
9183fb7adfSbellard #endif
9283fb7adfSbellard 
9383fb7adfSbellard /* should probably go in elf.h */
9483fb7adfSbellard #ifndef ELIBBAD
9583fb7adfSbellard #define ELIBBAD 80
9683fb7adfSbellard #endif
9783fb7adfSbellard 
9828490231SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN
9928490231SRichard Henderson #define ELF_DATA        ELFDATA2MSB
10028490231SRichard Henderson #else
10128490231SRichard Henderson #define ELF_DATA        ELFDATA2LSB
10228490231SRichard Henderson #endif
10328490231SRichard Henderson 
10421e807faSNathan Froyd typedef target_ulong    target_elf_greg_t;
10521e807faSNathan Froyd #ifdef USE_UID16
10680f5ce75SLaurent Vivier typedef target_ushort   target_uid_t;
10780f5ce75SLaurent Vivier typedef target_ushort   target_gid_t;
10821e807faSNathan Froyd #else
10980f5ce75SLaurent Vivier typedef target_uint     target_uid_t;
11080f5ce75SLaurent Vivier typedef target_uint     target_gid_t;
11121e807faSNathan Froyd #endif
11280f5ce75SLaurent Vivier typedef target_int      target_pid_t;
11321e807faSNathan Froyd 
11430ac07d4Sbellard #ifdef TARGET_I386
11530ac07d4Sbellard 
11615338fd7Sbellard #define ELF_PLATFORM get_elf_platform()
11715338fd7Sbellard 
11815338fd7Sbellard static const char *get_elf_platform(void)
11915338fd7Sbellard {
12015338fd7Sbellard     static char elf_platform[] = "i386";
121d5975363Spbrook     int family = (thread_env->cpuid_version >> 8) & 0xff;
12215338fd7Sbellard     if (family > 6)
12315338fd7Sbellard         family = 6;
12415338fd7Sbellard     if (family >= 3)
12515338fd7Sbellard         elf_platform[1] = '0' + family;
12615338fd7Sbellard     return elf_platform;
12715338fd7Sbellard }
12815338fd7Sbellard 
12915338fd7Sbellard #define ELF_HWCAP get_elf_hwcap()
13015338fd7Sbellard 
13115338fd7Sbellard static uint32_t get_elf_hwcap(void)
13215338fd7Sbellard {
133d5975363Spbrook     return thread_env->cpuid_features;
13415338fd7Sbellard }
13515338fd7Sbellard 
13684409ddbSj_mayer #ifdef TARGET_X86_64
13784409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL
13884409ddbSj_mayer #define elf_check_arch(x) ( ((x) == ELF_ARCH) )
13984409ddbSj_mayer 
14084409ddbSj_mayer #define ELF_CLASS      ELFCLASS64
14184409ddbSj_mayer #define ELF_ARCH       EM_X86_64
14284409ddbSj_mayer 
14384409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
14484409ddbSj_mayer {
14584409ddbSj_mayer     regs->rax = 0;
14684409ddbSj_mayer     regs->rsp = infop->start_stack;
14784409ddbSj_mayer     regs->rip = infop->entry;
14884409ddbSj_mayer }
14984409ddbSj_mayer 
1509edc5d79SMika Westerberg #define ELF_NREG    27
151c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
1529edc5d79SMika Westerberg 
1539edc5d79SMika Westerberg /*
1549edc5d79SMika Westerberg  * Note that ELF_NREG should be 29 as there should be place for
1559edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
1569edc5d79SMika Westerberg  * those.
1579edc5d79SMika Westerberg  *
1589edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
1599edc5d79SMika Westerberg  */
160c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
1619edc5d79SMika Westerberg {
1629edc5d79SMika Westerberg     (*regs)[0] = env->regs[15];
1639edc5d79SMika Westerberg     (*regs)[1] = env->regs[14];
1649edc5d79SMika Westerberg     (*regs)[2] = env->regs[13];
1659edc5d79SMika Westerberg     (*regs)[3] = env->regs[12];
1669edc5d79SMika Westerberg     (*regs)[4] = env->regs[R_EBP];
1679edc5d79SMika Westerberg     (*regs)[5] = env->regs[R_EBX];
1689edc5d79SMika Westerberg     (*regs)[6] = env->regs[11];
1699edc5d79SMika Westerberg     (*regs)[7] = env->regs[10];
1709edc5d79SMika Westerberg     (*regs)[8] = env->regs[9];
1719edc5d79SMika Westerberg     (*regs)[9] = env->regs[8];
1729edc5d79SMika Westerberg     (*regs)[10] = env->regs[R_EAX];
1739edc5d79SMika Westerberg     (*regs)[11] = env->regs[R_ECX];
1749edc5d79SMika Westerberg     (*regs)[12] = env->regs[R_EDX];
1759edc5d79SMika Westerberg     (*regs)[13] = env->regs[R_ESI];
1769edc5d79SMika Westerberg     (*regs)[14] = env->regs[R_EDI];
1779edc5d79SMika Westerberg     (*regs)[15] = env->regs[R_EAX]; /* XXX */
1789edc5d79SMika Westerberg     (*regs)[16] = env->eip;
1799edc5d79SMika Westerberg     (*regs)[17] = env->segs[R_CS].selector & 0xffff;
1809edc5d79SMika Westerberg     (*regs)[18] = env->eflags;
1819edc5d79SMika Westerberg     (*regs)[19] = env->regs[R_ESP];
1829edc5d79SMika Westerberg     (*regs)[20] = env->segs[R_SS].selector & 0xffff;
1839edc5d79SMika Westerberg     (*regs)[21] = env->segs[R_FS].selector & 0xffff;
1849edc5d79SMika Westerberg     (*regs)[22] = env->segs[R_GS].selector & 0xffff;
1859edc5d79SMika Westerberg     (*regs)[23] = env->segs[R_DS].selector & 0xffff;
1869edc5d79SMika Westerberg     (*regs)[24] = env->segs[R_ES].selector & 0xffff;
1879edc5d79SMika Westerberg     (*regs)[25] = env->segs[R_FS].selector & 0xffff;
1889edc5d79SMika Westerberg     (*regs)[26] = env->segs[R_GS].selector & 0xffff;
1899edc5d79SMika Westerberg }
1909edc5d79SMika Westerberg 
19184409ddbSj_mayer #else
19284409ddbSj_mayer 
19330ac07d4Sbellard #define ELF_START_MMAP 0x80000000
19430ac07d4Sbellard 
19530ac07d4Sbellard /*
19630ac07d4Sbellard  * This is used to ensure we don't load something for the wrong architecture.
19730ac07d4Sbellard  */
19830ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
19930ac07d4Sbellard 
20030ac07d4Sbellard /*
20130ac07d4Sbellard  * These are used to set parameters in the core dumps.
20230ac07d4Sbellard  */
20330ac07d4Sbellard #define ELF_CLASS       ELFCLASS32
20430ac07d4Sbellard #define ELF_ARCH        EM_386
20530ac07d4Sbellard 
206d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
207d97ef72eSRichard Henderson                                struct image_info *infop)
208e5fe0c52Spbrook {
209e5fe0c52Spbrook     regs->esp = infop->start_stack;
210e5fe0c52Spbrook     regs->eip = infop->entry;
211e5fe0c52Spbrook 
21230ac07d4Sbellard     /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
21330ac07d4Sbellard        starts %edx contains a pointer to a function which might be
21430ac07d4Sbellard        registered using `atexit'.  This provides a mean for the
21530ac07d4Sbellard        dynamic linker to call DT_FINI functions for shared libraries
21630ac07d4Sbellard        that have been loaded before the code runs.
21730ac07d4Sbellard 
21830ac07d4Sbellard        A value of 0 tells we have no such handler.  */
219e5fe0c52Spbrook     regs->edx = 0;
220b346ff46Sbellard }
2219edc5d79SMika Westerberg 
2229edc5d79SMika Westerberg #define ELF_NREG    17
223c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
2249edc5d79SMika Westerberg 
2259edc5d79SMika Westerberg /*
2269edc5d79SMika Westerberg  * Note that ELF_NREG should be 19 as there should be place for
2279edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
2289edc5d79SMika Westerberg  * those.
2299edc5d79SMika Westerberg  *
2309edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
2319edc5d79SMika Westerberg  */
232c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
2339edc5d79SMika Westerberg {
2349edc5d79SMika Westerberg     (*regs)[0] = env->regs[R_EBX];
2359edc5d79SMika Westerberg     (*regs)[1] = env->regs[R_ECX];
2369edc5d79SMika Westerberg     (*regs)[2] = env->regs[R_EDX];
2379edc5d79SMika Westerberg     (*regs)[3] = env->regs[R_ESI];
2389edc5d79SMika Westerberg     (*regs)[4] = env->regs[R_EDI];
2399edc5d79SMika Westerberg     (*regs)[5] = env->regs[R_EBP];
2409edc5d79SMika Westerberg     (*regs)[6] = env->regs[R_EAX];
2419edc5d79SMika Westerberg     (*regs)[7] = env->segs[R_DS].selector & 0xffff;
2429edc5d79SMika Westerberg     (*regs)[8] = env->segs[R_ES].selector & 0xffff;
2439edc5d79SMika Westerberg     (*regs)[9] = env->segs[R_FS].selector & 0xffff;
2449edc5d79SMika Westerberg     (*regs)[10] = env->segs[R_GS].selector & 0xffff;
2459edc5d79SMika Westerberg     (*regs)[11] = env->regs[R_EAX]; /* XXX */
2469edc5d79SMika Westerberg     (*regs)[12] = env->eip;
2479edc5d79SMika Westerberg     (*regs)[13] = env->segs[R_CS].selector & 0xffff;
2489edc5d79SMika Westerberg     (*regs)[14] = env->eflags;
2499edc5d79SMika Westerberg     (*regs)[15] = env->regs[R_ESP];
2509edc5d79SMika Westerberg     (*regs)[16] = env->segs[R_SS].selector & 0xffff;
2519edc5d79SMika Westerberg }
25284409ddbSj_mayer #endif
253b346ff46Sbellard 
2549edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP
255b346ff46Sbellard #define ELF_EXEC_PAGESIZE       4096
256b346ff46Sbellard 
257b346ff46Sbellard #endif
258b346ff46Sbellard 
259b346ff46Sbellard #ifdef TARGET_ARM
260b346ff46Sbellard 
261b346ff46Sbellard #define ELF_START_MMAP 0x80000000
262b346ff46Sbellard 
263b346ff46Sbellard #define elf_check_arch(x) ( (x) == EM_ARM )
264b346ff46Sbellard 
265b346ff46Sbellard #define ELF_CLASS       ELFCLASS32
266b346ff46Sbellard #define ELF_ARCH        EM_ARM
267b346ff46Sbellard 
268d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
269d97ef72eSRichard Henderson                                struct image_info *infop)
270b346ff46Sbellard {
271992f48a0Sblueswir1     abi_long stack = infop->start_stack;
272b346ff46Sbellard     memset(regs, 0, sizeof(*regs));
273b346ff46Sbellard     regs->ARM_cpsr = 0x10;
2740240ded8Spbrook     if (infop->entry & 1)
2750240ded8Spbrook         regs->ARM_cpsr |= CPSR_T;
2760240ded8Spbrook     regs->ARM_pc = infop->entry & 0xfffffffe;
277b346ff46Sbellard     regs->ARM_sp = infop->start_stack;
2782f619698Sbellard     /* FIXME - what to for failure of get_user()? */
2792f619698Sbellard     get_user_ual(regs->ARM_r2, stack + 8); /* envp */
2802f619698Sbellard     get_user_ual(regs->ARM_r1, stack + 4); /* envp */
281a1516e92Sbellard     /* XXX: it seems that r0 is zeroed after ! */
282e5fe0c52Spbrook     regs->ARM_r0 = 0;
283e5fe0c52Spbrook     /* For uClinux PIC binaries.  */
284863cf0b7Sj_mayer     /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
285e5fe0c52Spbrook     regs->ARM_r10 = infop->start_data;
286b346ff46Sbellard }
287b346ff46Sbellard 
288edf8e2afSMika Westerberg #define ELF_NREG    18
289c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
290edf8e2afSMika Westerberg 
291c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
292edf8e2afSMika Westerberg {
293d049e626SNathan Froyd     (*regs)[0] = tswapl(env->regs[0]);
294d049e626SNathan Froyd     (*regs)[1] = tswapl(env->regs[1]);
295d049e626SNathan Froyd     (*regs)[2] = tswapl(env->regs[2]);
296d049e626SNathan Froyd     (*regs)[3] = tswapl(env->regs[3]);
297d049e626SNathan Froyd     (*regs)[4] = tswapl(env->regs[4]);
298d049e626SNathan Froyd     (*regs)[5] = tswapl(env->regs[5]);
299d049e626SNathan Froyd     (*regs)[6] = tswapl(env->regs[6]);
300d049e626SNathan Froyd     (*regs)[7] = tswapl(env->regs[7]);
301d049e626SNathan Froyd     (*regs)[8] = tswapl(env->regs[8]);
302d049e626SNathan Froyd     (*regs)[9] = tswapl(env->regs[9]);
303d049e626SNathan Froyd     (*regs)[10] = tswapl(env->regs[10]);
304d049e626SNathan Froyd     (*regs)[11] = tswapl(env->regs[11]);
305d049e626SNathan Froyd     (*regs)[12] = tswapl(env->regs[12]);
306d049e626SNathan Froyd     (*regs)[13] = tswapl(env->regs[13]);
307d049e626SNathan Froyd     (*regs)[14] = tswapl(env->regs[14]);
308d049e626SNathan Froyd     (*regs)[15] = tswapl(env->regs[15]);
309edf8e2afSMika Westerberg 
310d049e626SNathan Froyd     (*regs)[16] = tswapl(cpsr_read((CPUState *)env));
311d049e626SNathan Froyd     (*regs)[17] = tswapl(env->regs[0]); /* XXX */
312edf8e2afSMika Westerberg }
313edf8e2afSMika Westerberg 
31430ac07d4Sbellard #define USE_ELF_CORE_DUMP
31530ac07d4Sbellard #define ELF_EXEC_PAGESIZE       4096
31630ac07d4Sbellard 
317afce2927Sbellard enum
318afce2927Sbellard {
319afce2927Sbellard     ARM_HWCAP_ARM_SWP       = 1 << 0,
320afce2927Sbellard     ARM_HWCAP_ARM_HALF      = 1 << 1,
321afce2927Sbellard     ARM_HWCAP_ARM_THUMB     = 1 << 2,
322afce2927Sbellard     ARM_HWCAP_ARM_26BIT     = 1 << 3,
323afce2927Sbellard     ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
324afce2927Sbellard     ARM_HWCAP_ARM_FPA       = 1 << 5,
325afce2927Sbellard     ARM_HWCAP_ARM_VFP       = 1 << 6,
326afce2927Sbellard     ARM_HWCAP_ARM_EDSP      = 1 << 7,
327cf6de34aSRiku Voipio     ARM_HWCAP_ARM_JAVA      = 1 << 8,
328cf6de34aSRiku Voipio     ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
329cf6de34aSRiku Voipio     ARM_HWCAP_ARM_THUMBEE   = 1 << 10,
330cf6de34aSRiku Voipio     ARM_HWCAP_ARM_NEON      = 1 << 11,
331cf6de34aSRiku Voipio     ARM_HWCAP_ARM_VFPv3     = 1 << 12,
332cf6de34aSRiku Voipio     ARM_HWCAP_ARM_VFPv3D16  = 1 << 13,
333afce2927Sbellard };
334afce2927Sbellard 
33597cc7560SDr. David Alan Gilbert #define TARGET_HAS_GUEST_VALIDATE_BASE
33697cc7560SDr. David Alan Gilbert /* We want the opportunity to check the suggested base */
33797cc7560SDr. David Alan Gilbert bool guest_validate_base(unsigned long guest_base)
33897cc7560SDr. David Alan Gilbert {
33997cc7560SDr. David Alan Gilbert     unsigned long real_start, test_page_addr;
34097cc7560SDr. David Alan Gilbert 
34197cc7560SDr. David Alan Gilbert     /* We need to check that we can force a fault on access to the
34297cc7560SDr. David Alan Gilbert      * commpage at 0xffff0fxx
34397cc7560SDr. David Alan Gilbert      */
34497cc7560SDr. David Alan Gilbert     test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask);
34597cc7560SDr. David Alan Gilbert     /* Note it needs to be writeable to let us initialise it */
34697cc7560SDr. David Alan Gilbert     real_start = (unsigned long)
34797cc7560SDr. David Alan Gilbert                  mmap((void *)test_page_addr, qemu_host_page_size,
34897cc7560SDr. David Alan Gilbert                      PROT_READ | PROT_WRITE,
34997cc7560SDr. David Alan Gilbert                      MAP_ANONYMOUS | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
35097cc7560SDr. David Alan Gilbert 
35197cc7560SDr. David Alan Gilbert     /* If we can't map it then try another address */
35297cc7560SDr. David Alan Gilbert     if (real_start == -1ul) {
35397cc7560SDr. David Alan Gilbert         return 0;
35497cc7560SDr. David Alan Gilbert     }
35597cc7560SDr. David Alan Gilbert 
35697cc7560SDr. David Alan Gilbert     if (real_start != test_page_addr) {
35797cc7560SDr. David Alan Gilbert         /* OS didn't put the page where we asked - unmap and reject */
35897cc7560SDr. David Alan Gilbert         munmap((void *)real_start, qemu_host_page_size);
35997cc7560SDr. David Alan Gilbert         return 0;
36097cc7560SDr. David Alan Gilbert     }
36197cc7560SDr. David Alan Gilbert 
36297cc7560SDr. David Alan Gilbert     /* Leave the page mapped
36397cc7560SDr. David Alan Gilbert      * Populate it (mmap should have left it all 0'd)
36497cc7560SDr. David Alan Gilbert      */
36597cc7560SDr. David Alan Gilbert 
36697cc7560SDr. David Alan Gilbert     /* Kernel helper versions */
36797cc7560SDr. David Alan Gilbert     __put_user(5, (uint32_t *)g2h(0xffff0ffcul));
36897cc7560SDr. David Alan Gilbert 
36997cc7560SDr. David Alan Gilbert     /* Now it's populated make it RO */
37097cc7560SDr. David Alan Gilbert     if (mprotect((void *)test_page_addr, qemu_host_page_size, PROT_READ)) {
37197cc7560SDr. David Alan Gilbert         perror("Protecting guest commpage");
37297cc7560SDr. David Alan Gilbert         exit(-1);
37397cc7560SDr. David Alan Gilbert     }
37497cc7560SDr. David Alan Gilbert 
37597cc7560SDr. David Alan Gilbert     return 1; /* All good */
37697cc7560SDr. David Alan Gilbert }
37797cc7560SDr. David Alan Gilbert 
37815338fd7Sbellard #define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF               \
379afce2927Sbellard                    | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT      \
380cf6de34aSRiku Voipio                    | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP              \
381cf6de34aSRiku Voipio                    | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 )
382afce2927Sbellard 
38330ac07d4Sbellard #endif
38430ac07d4Sbellard 
385d2fbca94SGuan Xuetao #ifdef TARGET_UNICORE32
386d2fbca94SGuan Xuetao 
387d2fbca94SGuan Xuetao #define ELF_START_MMAP          0x80000000
388d2fbca94SGuan Xuetao 
389d2fbca94SGuan Xuetao #define elf_check_arch(x)       ((x) == EM_UNICORE32)
390d2fbca94SGuan Xuetao 
391d2fbca94SGuan Xuetao #define ELF_CLASS               ELFCLASS32
392d2fbca94SGuan Xuetao #define ELF_DATA                ELFDATA2LSB
393d2fbca94SGuan Xuetao #define ELF_ARCH                EM_UNICORE32
394d2fbca94SGuan Xuetao 
395d2fbca94SGuan Xuetao static inline void init_thread(struct target_pt_regs *regs,
396d2fbca94SGuan Xuetao         struct image_info *infop)
397d2fbca94SGuan Xuetao {
398d2fbca94SGuan Xuetao     abi_long stack = infop->start_stack;
399d2fbca94SGuan Xuetao     memset(regs, 0, sizeof(*regs));
400d2fbca94SGuan Xuetao     regs->UC32_REG_asr = 0x10;
401d2fbca94SGuan Xuetao     regs->UC32_REG_pc = infop->entry & 0xfffffffe;
402d2fbca94SGuan Xuetao     regs->UC32_REG_sp = infop->start_stack;
403d2fbca94SGuan Xuetao     /* FIXME - what to for failure of get_user()? */
404d2fbca94SGuan Xuetao     get_user_ual(regs->UC32_REG_02, stack + 8); /* envp */
405d2fbca94SGuan Xuetao     get_user_ual(regs->UC32_REG_01, stack + 4); /* envp */
406d2fbca94SGuan Xuetao     /* XXX: it seems that r0 is zeroed after ! */
407d2fbca94SGuan Xuetao     regs->UC32_REG_00 = 0;
408d2fbca94SGuan Xuetao }
409d2fbca94SGuan Xuetao 
410d2fbca94SGuan Xuetao #define ELF_NREG    34
411d2fbca94SGuan Xuetao typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
412d2fbca94SGuan Xuetao 
413d2fbca94SGuan Xuetao static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
414d2fbca94SGuan Xuetao {
415d2fbca94SGuan Xuetao     (*regs)[0] = env->regs[0];
416d2fbca94SGuan Xuetao     (*regs)[1] = env->regs[1];
417d2fbca94SGuan Xuetao     (*regs)[2] = env->regs[2];
418d2fbca94SGuan Xuetao     (*regs)[3] = env->regs[3];
419d2fbca94SGuan Xuetao     (*regs)[4] = env->regs[4];
420d2fbca94SGuan Xuetao     (*regs)[5] = env->regs[5];
421d2fbca94SGuan Xuetao     (*regs)[6] = env->regs[6];
422d2fbca94SGuan Xuetao     (*regs)[7] = env->regs[7];
423d2fbca94SGuan Xuetao     (*regs)[8] = env->regs[8];
424d2fbca94SGuan Xuetao     (*regs)[9] = env->regs[9];
425d2fbca94SGuan Xuetao     (*regs)[10] = env->regs[10];
426d2fbca94SGuan Xuetao     (*regs)[11] = env->regs[11];
427d2fbca94SGuan Xuetao     (*regs)[12] = env->regs[12];
428d2fbca94SGuan Xuetao     (*regs)[13] = env->regs[13];
429d2fbca94SGuan Xuetao     (*regs)[14] = env->regs[14];
430d2fbca94SGuan Xuetao     (*regs)[15] = env->regs[15];
431d2fbca94SGuan Xuetao     (*regs)[16] = env->regs[16];
432d2fbca94SGuan Xuetao     (*regs)[17] = env->regs[17];
433d2fbca94SGuan Xuetao     (*regs)[18] = env->regs[18];
434d2fbca94SGuan Xuetao     (*regs)[19] = env->regs[19];
435d2fbca94SGuan Xuetao     (*regs)[20] = env->regs[20];
436d2fbca94SGuan Xuetao     (*regs)[21] = env->regs[21];
437d2fbca94SGuan Xuetao     (*regs)[22] = env->regs[22];
438d2fbca94SGuan Xuetao     (*regs)[23] = env->regs[23];
439d2fbca94SGuan Xuetao     (*regs)[24] = env->regs[24];
440d2fbca94SGuan Xuetao     (*regs)[25] = env->regs[25];
441d2fbca94SGuan Xuetao     (*regs)[26] = env->regs[26];
442d2fbca94SGuan Xuetao     (*regs)[27] = env->regs[27];
443d2fbca94SGuan Xuetao     (*regs)[28] = env->regs[28];
444d2fbca94SGuan Xuetao     (*regs)[29] = env->regs[29];
445d2fbca94SGuan Xuetao     (*regs)[30] = env->regs[30];
446d2fbca94SGuan Xuetao     (*regs)[31] = env->regs[31];
447d2fbca94SGuan Xuetao 
448d2fbca94SGuan Xuetao     (*regs)[32] = cpu_asr_read((CPUState *)env);
449d2fbca94SGuan Xuetao     (*regs)[33] = env->regs[0]; /* XXX */
450d2fbca94SGuan Xuetao }
451d2fbca94SGuan Xuetao 
452d2fbca94SGuan Xuetao #define USE_ELF_CORE_DUMP
453d2fbca94SGuan Xuetao #define ELF_EXEC_PAGESIZE               4096
454d2fbca94SGuan Xuetao 
455d2fbca94SGuan Xuetao #define ELF_HWCAP                       (UC32_HWCAP_CMOV | UC32_HWCAP_UCF64)
456d2fbca94SGuan Xuetao 
457d2fbca94SGuan Xuetao #endif
458d2fbca94SGuan Xuetao 
459853d6f7aSbellard #ifdef TARGET_SPARC
460a315a145Sbellard #ifdef TARGET_SPARC64
461853d6f7aSbellard 
462853d6f7aSbellard #define ELF_START_MMAP 0x80000000
463cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
464cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9)
465992f48a0Sblueswir1 #ifndef TARGET_ABI32
466cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
467992f48a0Sblueswir1 #else
468992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
469992f48a0Sblueswir1 #endif
470853d6f7aSbellard 
471a315a145Sbellard #define ELF_CLASS   ELFCLASS64
4725ef54116Sbellard #define ELF_ARCH    EM_SPARCV9
4735ef54116Sbellard 
4745ef54116Sbellard #define STACK_BIAS              2047
475a315a145Sbellard 
476d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
477d97ef72eSRichard Henderson                                struct image_info *infop)
478a315a145Sbellard {
479992f48a0Sblueswir1 #ifndef TARGET_ABI32
480a315a145Sbellard     regs->tstate = 0;
481992f48a0Sblueswir1 #endif
482a315a145Sbellard     regs->pc = infop->entry;
483a315a145Sbellard     regs->npc = regs->pc + 4;
484a315a145Sbellard     regs->y = 0;
485992f48a0Sblueswir1 #ifdef TARGET_ABI32
486992f48a0Sblueswir1     regs->u_regs[14] = infop->start_stack - 16 * 4;
487992f48a0Sblueswir1 #else
488cb33da57Sblueswir1     if (personality(infop->personality) == PER_LINUX32)
489cb33da57Sblueswir1         regs->u_regs[14] = infop->start_stack - 16 * 4;
490cb33da57Sblueswir1     else
4915ef54116Sbellard         regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
492992f48a0Sblueswir1 #endif
493a315a145Sbellard }
494a315a145Sbellard 
495a315a145Sbellard #else
496a315a145Sbellard #define ELF_START_MMAP 0x80000000
497cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
498cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV)
499a315a145Sbellard #define elf_check_arch(x) ( (x) == EM_SPARC )
500a315a145Sbellard 
501853d6f7aSbellard #define ELF_CLASS   ELFCLASS32
502853d6f7aSbellard #define ELF_ARCH    EM_SPARC
503853d6f7aSbellard 
504d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
505d97ef72eSRichard Henderson                                struct image_info *infop)
506853d6f7aSbellard {
507f5155289Sbellard     regs->psr = 0;
508f5155289Sbellard     regs->pc = infop->entry;
509f5155289Sbellard     regs->npc = regs->pc + 4;
510f5155289Sbellard     regs->y = 0;
511f5155289Sbellard     regs->u_regs[14] = infop->start_stack - 16 * 4;
512853d6f7aSbellard }
513853d6f7aSbellard 
514853d6f7aSbellard #endif
515a315a145Sbellard #endif
516853d6f7aSbellard 
51767867308Sbellard #ifdef TARGET_PPC
51867867308Sbellard 
51967867308Sbellard #define ELF_START_MMAP 0x80000000
52067867308Sbellard 
521e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
52284409ddbSj_mayer 
52384409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 )
52484409ddbSj_mayer 
52584409ddbSj_mayer #define ELF_CLASS       ELFCLASS64
52684409ddbSj_mayer 
52784409ddbSj_mayer #else
52884409ddbSj_mayer 
52967867308Sbellard #define elf_check_arch(x) ( (x) == EM_PPC )
53067867308Sbellard 
53167867308Sbellard #define ELF_CLASS       ELFCLASS32
53284409ddbSj_mayer 
53384409ddbSj_mayer #endif
53484409ddbSj_mayer 
53567867308Sbellard #define ELF_ARCH        EM_PPC
53667867308Sbellard 
537df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
538df84e4f3SNathan Froyd    See arch/powerpc/include/asm/cputable.h.  */
539df84e4f3SNathan Froyd enum {
5403efa9a67Smalc     QEMU_PPC_FEATURE_32 = 0x80000000,
5413efa9a67Smalc     QEMU_PPC_FEATURE_64 = 0x40000000,
5423efa9a67Smalc     QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
5433efa9a67Smalc     QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
5443efa9a67Smalc     QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
5453efa9a67Smalc     QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
5463efa9a67Smalc     QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
5473efa9a67Smalc     QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
5483efa9a67Smalc     QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
5493efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
5503efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
5513efa9a67Smalc     QEMU_PPC_FEATURE_NO_TB = 0x00100000,
5523efa9a67Smalc     QEMU_PPC_FEATURE_POWER4 = 0x00080000,
5533efa9a67Smalc     QEMU_PPC_FEATURE_POWER5 = 0x00040000,
5543efa9a67Smalc     QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
5553efa9a67Smalc     QEMU_PPC_FEATURE_CELL = 0x00010000,
5563efa9a67Smalc     QEMU_PPC_FEATURE_BOOKE = 0x00008000,
5573efa9a67Smalc     QEMU_PPC_FEATURE_SMT = 0x00004000,
5583efa9a67Smalc     QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
5593efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
5603efa9a67Smalc     QEMU_PPC_FEATURE_PA6T = 0x00000800,
5613efa9a67Smalc     QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
5623efa9a67Smalc     QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
5633efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
5643efa9a67Smalc     QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
5653efa9a67Smalc     QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
566df84e4f3SNathan Froyd 
5673efa9a67Smalc     QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
5683efa9a67Smalc     QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
569df84e4f3SNathan Froyd };
570df84e4f3SNathan Froyd 
571df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap()
572df84e4f3SNathan Froyd 
573df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void)
574df84e4f3SNathan Froyd {
575df84e4f3SNathan Froyd     CPUState *e = thread_env;
576df84e4f3SNathan Froyd     uint32_t features = 0;
577df84e4f3SNathan Froyd 
578df84e4f3SNathan Froyd     /* We don't have to be terribly complete here; the high points are
579df84e4f3SNathan Froyd        Altivec/FP/SPE support.  Anything else is just a bonus.  */
580df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature)                                      \
581df84e4f3SNathan Froyd     do {if (e->insns_flags & flag) features |= feature; } while(0)
5823efa9a67Smalc     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
5833efa9a67Smalc     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
5843efa9a67Smalc     GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
5853efa9a67Smalc     GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
5863efa9a67Smalc     GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
5873efa9a67Smalc     GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
5883efa9a67Smalc     GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
5893efa9a67Smalc     GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
590df84e4f3SNathan Froyd #undef GET_FEATURE
591df84e4f3SNathan Froyd 
592df84e4f3SNathan Froyd     return features;
593df84e4f3SNathan Froyd }
594df84e4f3SNathan Froyd 
595f5155289Sbellard /*
596f5155289Sbellard  * The requirements here are:
597f5155289Sbellard  * - keep the final alignment of sp (sp & 0xf)
598f5155289Sbellard  * - make sure the 32-bit value at the first 16 byte aligned position of
599f5155289Sbellard  *   AUXV is greater than 16 for glibc compatibility.
600f5155289Sbellard  *   AT_IGNOREPPC is used for that.
601f5155289Sbellard  * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
602f5155289Sbellard  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
603f5155289Sbellard  */
6040bccf03dSbellard #define DLINFO_ARCH_ITEMS       5
605f5155289Sbellard #define ARCH_DLINFO                                     \
606f5155289Sbellard     do {                                                \
6070bccf03dSbellard         NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);              \
6080bccf03dSbellard         NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);              \
6090bccf03dSbellard         NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
610f5155289Sbellard         /*                                              \
611f5155289Sbellard          * Now handle glibc compatibility.              \
612f5155289Sbellard          */                                             \
6130bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
6140bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
615f5155289Sbellard     } while (0)
616f5155289Sbellard 
61767867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
61867867308Sbellard {
61967867308Sbellard     _regs->gpr[1] = infop->start_stack;
620e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
6218e78064eSRichard Henderson     _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_bias;
6228e78064eSRichard Henderson     infop->entry = ldq_raw(infop->entry) + infop->load_bias;
62384409ddbSj_mayer #endif
62467867308Sbellard     _regs->nip = infop->entry;
62567867308Sbellard }
62667867308Sbellard 
627e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h.  */
628e2f3e741SNathan Froyd #define ELF_NREG 48
629e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
630e2f3e741SNathan Froyd 
631e2f3e741SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
632e2f3e741SNathan Froyd {
633e2f3e741SNathan Froyd     int i;
634e2f3e741SNathan Froyd     target_ulong ccr = 0;
635e2f3e741SNathan Froyd 
636e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
637e2f3e741SNathan Froyd         (*regs)[i] = tswapl(env->gpr[i]);
638e2f3e741SNathan Froyd     }
639e2f3e741SNathan Froyd 
640e2f3e741SNathan Froyd     (*regs)[32] = tswapl(env->nip);
641e2f3e741SNathan Froyd     (*regs)[33] = tswapl(env->msr);
642e2f3e741SNathan Froyd     (*regs)[35] = tswapl(env->ctr);
643e2f3e741SNathan Froyd     (*regs)[36] = tswapl(env->lr);
644e2f3e741SNathan Froyd     (*regs)[37] = tswapl(env->xer);
645e2f3e741SNathan Froyd 
646e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
647e2f3e741SNathan Froyd         ccr |= env->crf[i] << (32 - ((i + 1) * 4));
648e2f3e741SNathan Froyd     }
649e2f3e741SNathan Froyd     (*regs)[38] = tswapl(ccr);
650e2f3e741SNathan Froyd }
651e2f3e741SNathan Froyd 
652e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP
65367867308Sbellard #define ELF_EXEC_PAGESIZE       4096
65467867308Sbellard 
65567867308Sbellard #endif
65667867308Sbellard 
657048f6b4dSbellard #ifdef TARGET_MIPS
658048f6b4dSbellard 
659048f6b4dSbellard #define ELF_START_MMAP 0x80000000
660048f6b4dSbellard 
661048f6b4dSbellard #define elf_check_arch(x) ( (x) == EM_MIPS )
662048f6b4dSbellard 
663388bb21aSths #ifdef TARGET_MIPS64
664388bb21aSths #define ELF_CLASS   ELFCLASS64
665388bb21aSths #else
666048f6b4dSbellard #define ELF_CLASS   ELFCLASS32
667388bb21aSths #endif
668048f6b4dSbellard #define ELF_ARCH    EM_MIPS
669048f6b4dSbellard 
670d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
671d97ef72eSRichard Henderson                                struct image_info *infop)
672048f6b4dSbellard {
673623a930eSths     regs->cp0_status = 2 << CP0St_KSU;
674048f6b4dSbellard     regs->cp0_epc = infop->entry;
675048f6b4dSbellard     regs->regs[29] = infop->start_stack;
676048f6b4dSbellard }
677048f6b4dSbellard 
67851e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h.  */
67951e52606SNathan Froyd #define ELF_NREG 45
68051e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
68151e52606SNathan Froyd 
68251e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h.  */
68351e52606SNathan Froyd enum {
68451e52606SNathan Froyd #ifdef TARGET_MIPS64
68551e52606SNathan Froyd     TARGET_EF_R0 = 0,
68651e52606SNathan Froyd #else
68751e52606SNathan Froyd     TARGET_EF_R0 = 6,
68851e52606SNathan Froyd #endif
68951e52606SNathan Froyd     TARGET_EF_R26 = TARGET_EF_R0 + 26,
69051e52606SNathan Froyd     TARGET_EF_R27 = TARGET_EF_R0 + 27,
69151e52606SNathan Froyd     TARGET_EF_LO = TARGET_EF_R0 + 32,
69251e52606SNathan Froyd     TARGET_EF_HI = TARGET_EF_R0 + 33,
69351e52606SNathan Froyd     TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
69451e52606SNathan Froyd     TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
69551e52606SNathan Froyd     TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
69651e52606SNathan Froyd     TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
69751e52606SNathan Froyd };
69851e52606SNathan Froyd 
69951e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
70051e52606SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
70151e52606SNathan Froyd {
70251e52606SNathan Froyd     int i;
70351e52606SNathan Froyd 
70451e52606SNathan Froyd     for (i = 0; i < TARGET_EF_R0; i++) {
70551e52606SNathan Froyd         (*regs)[i] = 0;
70651e52606SNathan Froyd     }
70751e52606SNathan Froyd     (*regs)[TARGET_EF_R0] = 0;
70851e52606SNathan Froyd 
70951e52606SNathan Froyd     for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
71051e52606SNathan Froyd         (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]);
71151e52606SNathan Froyd     }
71251e52606SNathan Froyd 
71351e52606SNathan Froyd     (*regs)[TARGET_EF_R26] = 0;
71451e52606SNathan Froyd     (*regs)[TARGET_EF_R27] = 0;
71551e52606SNathan Froyd     (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]);
71651e52606SNathan Froyd     (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]);
71751e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC);
71851e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr);
71951e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status);
72051e52606SNathan Froyd     (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause);
72151e52606SNathan Froyd }
72251e52606SNathan Froyd 
72351e52606SNathan Froyd #define USE_ELF_CORE_DUMP
724388bb21aSths #define ELF_EXEC_PAGESIZE        4096
725388bb21aSths 
726048f6b4dSbellard #endif /* TARGET_MIPS */
727048f6b4dSbellard 
728b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE
729b779e29eSEdgar E. Iglesias 
730b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000
731b779e29eSEdgar E. Iglesias 
7320d5d4699SEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
733b779e29eSEdgar E. Iglesias 
734b779e29eSEdgar E. Iglesias #define ELF_CLASS   ELFCLASS32
7350d5d4699SEdgar E. Iglesias #define ELF_ARCH    EM_MICROBLAZE
736b779e29eSEdgar E. Iglesias 
737d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
738d97ef72eSRichard Henderson                                struct image_info *infop)
739b779e29eSEdgar E. Iglesias {
740b779e29eSEdgar E. Iglesias     regs->pc = infop->entry;
741b779e29eSEdgar E. Iglesias     regs->r1 = infop->start_stack;
742b779e29eSEdgar E. Iglesias 
743b779e29eSEdgar E. Iglesias }
744b779e29eSEdgar E. Iglesias 
745b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE        4096
746b779e29eSEdgar E. Iglesias 
747e4cbd44dSEdgar E. Iglesias #define USE_ELF_CORE_DUMP
748e4cbd44dSEdgar E. Iglesias #define ELF_NREG 38
749e4cbd44dSEdgar E. Iglesias typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
750e4cbd44dSEdgar E. Iglesias 
751e4cbd44dSEdgar E. Iglesias /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
752e4cbd44dSEdgar E. Iglesias static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
753e4cbd44dSEdgar E. Iglesias {
754e4cbd44dSEdgar E. Iglesias     int i, pos = 0;
755e4cbd44dSEdgar E. Iglesias 
756e4cbd44dSEdgar E. Iglesias     for (i = 0; i < 32; i++) {
757e4cbd44dSEdgar E. Iglesias         (*regs)[pos++] = tswapl(env->regs[i]);
758e4cbd44dSEdgar E. Iglesias     }
759e4cbd44dSEdgar E. Iglesias 
760e4cbd44dSEdgar E. Iglesias     for (i = 0; i < 6; i++) {
761e4cbd44dSEdgar E. Iglesias         (*regs)[pos++] = tswapl(env->sregs[i]);
762e4cbd44dSEdgar E. Iglesias     }
763e4cbd44dSEdgar E. Iglesias }
764e4cbd44dSEdgar E. Iglesias 
765b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */
766b779e29eSEdgar E. Iglesias 
767fdf9b3e8Sbellard #ifdef TARGET_SH4
768fdf9b3e8Sbellard 
769fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000
770fdf9b3e8Sbellard 
771fdf9b3e8Sbellard #define elf_check_arch(x) ( (x) == EM_SH )
772fdf9b3e8Sbellard 
773fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32
774fdf9b3e8Sbellard #define ELF_ARCH  EM_SH
775fdf9b3e8Sbellard 
776d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
777d97ef72eSRichard Henderson                                struct image_info *infop)
778fdf9b3e8Sbellard {
779fdf9b3e8Sbellard     /* Check other registers XXXXX */
780fdf9b3e8Sbellard     regs->pc = infop->entry;
781072ae847Sths     regs->regs[15] = infop->start_stack;
782fdf9b3e8Sbellard }
783fdf9b3e8Sbellard 
7847631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h.  */
7857631c97eSNathan Froyd #define ELF_NREG 23
7867631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
7877631c97eSNathan Froyd 
7887631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h.  */
7897631c97eSNathan Froyd enum {
7907631c97eSNathan Froyd     TARGET_REG_PC = 16,
7917631c97eSNathan Froyd     TARGET_REG_PR = 17,
7927631c97eSNathan Froyd     TARGET_REG_SR = 18,
7937631c97eSNathan Froyd     TARGET_REG_GBR = 19,
7947631c97eSNathan Froyd     TARGET_REG_MACH = 20,
7957631c97eSNathan Froyd     TARGET_REG_MACL = 21,
7967631c97eSNathan Froyd     TARGET_REG_SYSCALL = 22
7977631c97eSNathan Froyd };
7987631c97eSNathan Froyd 
799d97ef72eSRichard Henderson static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
800d97ef72eSRichard Henderson                                       const CPUState *env)
8017631c97eSNathan Froyd {
8027631c97eSNathan Froyd     int i;
8037631c97eSNathan Froyd 
8047631c97eSNathan Froyd     for (i = 0; i < 16; i++) {
8057631c97eSNathan Froyd         (*regs[i]) = tswapl(env->gregs[i]);
8067631c97eSNathan Froyd     }
8077631c97eSNathan Froyd 
8087631c97eSNathan Froyd     (*regs)[TARGET_REG_PC] = tswapl(env->pc);
8097631c97eSNathan Froyd     (*regs)[TARGET_REG_PR] = tswapl(env->pr);
8107631c97eSNathan Froyd     (*regs)[TARGET_REG_SR] = tswapl(env->sr);
8117631c97eSNathan Froyd     (*regs)[TARGET_REG_GBR] = tswapl(env->gbr);
8127631c97eSNathan Froyd     (*regs)[TARGET_REG_MACH] = tswapl(env->mach);
8137631c97eSNathan Froyd     (*regs)[TARGET_REG_MACL] = tswapl(env->macl);
8147631c97eSNathan Froyd     (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
8157631c97eSNathan Froyd }
8167631c97eSNathan Froyd 
8177631c97eSNathan Froyd #define USE_ELF_CORE_DUMP
818fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE        4096
819fdf9b3e8Sbellard 
820fdf9b3e8Sbellard #endif
821fdf9b3e8Sbellard 
82248733d19Sths #ifdef TARGET_CRIS
82348733d19Sths 
82448733d19Sths #define ELF_START_MMAP 0x80000000
82548733d19Sths 
82648733d19Sths #define elf_check_arch(x) ( (x) == EM_CRIS )
82748733d19Sths 
82848733d19Sths #define ELF_CLASS ELFCLASS32
82948733d19Sths #define ELF_ARCH  EM_CRIS
83048733d19Sths 
831d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
832d97ef72eSRichard Henderson                                struct image_info *infop)
83348733d19Sths {
83448733d19Sths     regs->erp = infop->entry;
83548733d19Sths }
83648733d19Sths 
83748733d19Sths #define ELF_EXEC_PAGESIZE        8192
83848733d19Sths 
83948733d19Sths #endif
84048733d19Sths 
841e6e5906bSpbrook #ifdef TARGET_M68K
842e6e5906bSpbrook 
843e6e5906bSpbrook #define ELF_START_MMAP 0x80000000
844e6e5906bSpbrook 
845e6e5906bSpbrook #define elf_check_arch(x) ( (x) == EM_68K )
846e6e5906bSpbrook 
847e6e5906bSpbrook #define ELF_CLASS       ELFCLASS32
848e6e5906bSpbrook #define ELF_ARCH        EM_68K
849e6e5906bSpbrook 
850e6e5906bSpbrook /* ??? Does this need to do anything?
851e6e5906bSpbrook    #define ELF_PLAT_INIT(_r) */
852e6e5906bSpbrook 
853d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
854d97ef72eSRichard Henderson                                struct image_info *infop)
855e6e5906bSpbrook {
856e6e5906bSpbrook     regs->usp = infop->start_stack;
857e6e5906bSpbrook     regs->sr = 0;
858e6e5906bSpbrook     regs->pc = infop->entry;
859e6e5906bSpbrook }
860e6e5906bSpbrook 
8617a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h.  */
8627a93cc55SNathan Froyd #define ELF_NREG 20
8637a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
8647a93cc55SNathan Froyd 
8657a93cc55SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
8667a93cc55SNathan Froyd {
8677a93cc55SNathan Froyd     (*regs)[0] = tswapl(env->dregs[1]);
8687a93cc55SNathan Froyd     (*regs)[1] = tswapl(env->dregs[2]);
8697a93cc55SNathan Froyd     (*regs)[2] = tswapl(env->dregs[3]);
8707a93cc55SNathan Froyd     (*regs)[3] = tswapl(env->dregs[4]);
8717a93cc55SNathan Froyd     (*regs)[4] = tswapl(env->dregs[5]);
8727a93cc55SNathan Froyd     (*regs)[5] = tswapl(env->dregs[6]);
8737a93cc55SNathan Froyd     (*regs)[6] = tswapl(env->dregs[7]);
8747a93cc55SNathan Froyd     (*regs)[7] = tswapl(env->aregs[0]);
8757a93cc55SNathan Froyd     (*regs)[8] = tswapl(env->aregs[1]);
8767a93cc55SNathan Froyd     (*regs)[9] = tswapl(env->aregs[2]);
8777a93cc55SNathan Froyd     (*regs)[10] = tswapl(env->aregs[3]);
8787a93cc55SNathan Froyd     (*regs)[11] = tswapl(env->aregs[4]);
8797a93cc55SNathan Froyd     (*regs)[12] = tswapl(env->aregs[5]);
8807a93cc55SNathan Froyd     (*regs)[13] = tswapl(env->aregs[6]);
8817a93cc55SNathan Froyd     (*regs)[14] = tswapl(env->dregs[0]);
8827a93cc55SNathan Froyd     (*regs)[15] = tswapl(env->aregs[7]);
8837a93cc55SNathan Froyd     (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */
8847a93cc55SNathan Froyd     (*regs)[17] = tswapl(env->sr);
8857a93cc55SNathan Froyd     (*regs)[18] = tswapl(env->pc);
8867a93cc55SNathan Froyd     (*regs)[19] = 0;  /* FIXME: regs->format | regs->vector */
8877a93cc55SNathan Froyd }
8887a93cc55SNathan Froyd 
8897a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP
890e6e5906bSpbrook #define ELF_EXEC_PAGESIZE       8192
891e6e5906bSpbrook 
892e6e5906bSpbrook #endif
893e6e5906bSpbrook 
8947a3148a9Sj_mayer #ifdef TARGET_ALPHA
8957a3148a9Sj_mayer 
8967a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL)
8977a3148a9Sj_mayer 
8987a3148a9Sj_mayer #define elf_check_arch(x) ( (x) == ELF_ARCH )
8997a3148a9Sj_mayer 
9007a3148a9Sj_mayer #define ELF_CLASS      ELFCLASS64
9017a3148a9Sj_mayer #define ELF_ARCH       EM_ALPHA
9027a3148a9Sj_mayer 
903d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
904d97ef72eSRichard Henderson                                struct image_info *infop)
9057a3148a9Sj_mayer {
9067a3148a9Sj_mayer     regs->pc = infop->entry;
9077a3148a9Sj_mayer     regs->ps = 8;
9087a3148a9Sj_mayer     regs->usp = infop->start_stack;
9097a3148a9Sj_mayer }
9107a3148a9Sj_mayer 
9117a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE        8192
9127a3148a9Sj_mayer 
9137a3148a9Sj_mayer #endif /* TARGET_ALPHA */
9147a3148a9Sj_mayer 
915a4c075f1SUlrich Hecht #ifdef TARGET_S390X
916a4c075f1SUlrich Hecht 
917a4c075f1SUlrich Hecht #define ELF_START_MMAP (0x20000000000ULL)
918a4c075f1SUlrich Hecht 
919a4c075f1SUlrich Hecht #define elf_check_arch(x) ( (x) == ELF_ARCH )
920a4c075f1SUlrich Hecht 
921a4c075f1SUlrich Hecht #define ELF_CLASS	ELFCLASS64
922a4c075f1SUlrich Hecht #define ELF_DATA	ELFDATA2MSB
923a4c075f1SUlrich Hecht #define ELF_ARCH	EM_S390
924a4c075f1SUlrich Hecht 
925a4c075f1SUlrich Hecht static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
926a4c075f1SUlrich Hecht {
927a4c075f1SUlrich Hecht     regs->psw.addr = infop->entry;
928a4c075f1SUlrich Hecht     regs->psw.mask = PSW_MASK_64 | PSW_MASK_32;
929a4c075f1SUlrich Hecht     regs->gprs[15] = infop->start_stack;
930a4c075f1SUlrich Hecht }
931a4c075f1SUlrich Hecht 
932a4c075f1SUlrich Hecht #endif /* TARGET_S390X */
933a4c075f1SUlrich Hecht 
93415338fd7Sbellard #ifndef ELF_PLATFORM
93515338fd7Sbellard #define ELF_PLATFORM (NULL)
93615338fd7Sbellard #endif
93715338fd7Sbellard 
93815338fd7Sbellard #ifndef ELF_HWCAP
93915338fd7Sbellard #define ELF_HWCAP 0
94015338fd7Sbellard #endif
94115338fd7Sbellard 
942992f48a0Sblueswir1 #ifdef TARGET_ABI32
943cb33da57Sblueswir1 #undef ELF_CLASS
944992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32
945cb33da57Sblueswir1 #undef bswaptls
946cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr)
947cb33da57Sblueswir1 #endif
948cb33da57Sblueswir1 
94931e31b8aSbellard #include "elf.h"
95009bfb054Sbellard 
95109bfb054Sbellard struct exec
95209bfb054Sbellard {
95309bfb054Sbellard     unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
95409bfb054Sbellard     unsigned int a_text;   /* length of text, in bytes */
95509bfb054Sbellard     unsigned int a_data;   /* length of data, in bytes */
95609bfb054Sbellard     unsigned int a_bss;    /* length of uninitialized data area, in bytes */
95709bfb054Sbellard     unsigned int a_syms;   /* length of symbol table data in file, in bytes */
95809bfb054Sbellard     unsigned int a_entry;  /* start address */
95909bfb054Sbellard     unsigned int a_trsize; /* length of relocation info for text, in bytes */
96009bfb054Sbellard     unsigned int a_drsize; /* length of relocation info for data, in bytes */
96109bfb054Sbellard };
96209bfb054Sbellard 
96309bfb054Sbellard 
96409bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff)
96509bfb054Sbellard #define OMAGIC 0407
96609bfb054Sbellard #define NMAGIC 0410
96709bfb054Sbellard #define ZMAGIC 0413
96809bfb054Sbellard #define QMAGIC 0314
96909bfb054Sbellard 
97031e31b8aSbellard /* Necessary parameters */
97154936004Sbellard #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
97254936004Sbellard #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
97354936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
97431e31b8aSbellard 
97514322badSLaurent ALFONSI #define DLINFO_ITEMS 13
97631e31b8aSbellard 
97709bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
97809bfb054Sbellard {
97909bfb054Sbellard     memcpy(to, from, n);
98009bfb054Sbellard }
98109bfb054Sbellard 
98231e31b8aSbellard #ifdef BSWAP_NEEDED
98392a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr)
98431e31b8aSbellard {
98531e31b8aSbellard     bswap16s(&ehdr->e_type);            /* Object file type */
98631e31b8aSbellard     bswap16s(&ehdr->e_machine);         /* Architecture */
98731e31b8aSbellard     bswap32s(&ehdr->e_version);         /* Object file version */
98892a31b1fSbellard     bswaptls(&ehdr->e_entry);           /* Entry point virtual address */
98992a31b1fSbellard     bswaptls(&ehdr->e_phoff);           /* Program header table file offset */
99092a31b1fSbellard     bswaptls(&ehdr->e_shoff);           /* Section header table file offset */
99131e31b8aSbellard     bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
99231e31b8aSbellard     bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
99331e31b8aSbellard     bswap16s(&ehdr->e_phentsize);       /* Program header table entry size */
99431e31b8aSbellard     bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
99531e31b8aSbellard     bswap16s(&ehdr->e_shentsize);       /* Section header table entry size */
99631e31b8aSbellard     bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
99731e31b8aSbellard     bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */
99831e31b8aSbellard }
99931e31b8aSbellard 
1000991f8f0cSRichard Henderson static void bswap_phdr(struct elf_phdr *phdr, int phnum)
100131e31b8aSbellard {
1002991f8f0cSRichard Henderson     int i;
1003991f8f0cSRichard Henderson     for (i = 0; i < phnum; ++i, ++phdr) {
100431e31b8aSbellard         bswap32s(&phdr->p_type);        /* Segment type */
1005991f8f0cSRichard Henderson         bswap32s(&phdr->p_flags);       /* Segment flags */
100692a31b1fSbellard         bswaptls(&phdr->p_offset);      /* Segment file offset */
100792a31b1fSbellard         bswaptls(&phdr->p_vaddr);       /* Segment virtual address */
100892a31b1fSbellard         bswaptls(&phdr->p_paddr);       /* Segment physical address */
100992a31b1fSbellard         bswaptls(&phdr->p_filesz);      /* Segment size in file */
101092a31b1fSbellard         bswaptls(&phdr->p_memsz);       /* Segment size in memory */
101192a31b1fSbellard         bswaptls(&phdr->p_align);       /* Segment alignment */
101231e31b8aSbellard     }
1013991f8f0cSRichard Henderson }
1014689f936fSbellard 
1015991f8f0cSRichard Henderson static void bswap_shdr(struct elf_shdr *shdr, int shnum)
1016689f936fSbellard {
1017991f8f0cSRichard Henderson     int i;
1018991f8f0cSRichard Henderson     for (i = 0; i < shnum; ++i, ++shdr) {
1019689f936fSbellard         bswap32s(&shdr->sh_name);
1020689f936fSbellard         bswap32s(&shdr->sh_type);
102192a31b1fSbellard         bswaptls(&shdr->sh_flags);
102292a31b1fSbellard         bswaptls(&shdr->sh_addr);
102392a31b1fSbellard         bswaptls(&shdr->sh_offset);
102492a31b1fSbellard         bswaptls(&shdr->sh_size);
1025689f936fSbellard         bswap32s(&shdr->sh_link);
1026689f936fSbellard         bswap32s(&shdr->sh_info);
102792a31b1fSbellard         bswaptls(&shdr->sh_addralign);
102892a31b1fSbellard         bswaptls(&shdr->sh_entsize);
1029689f936fSbellard     }
1030991f8f0cSRichard Henderson }
1031689f936fSbellard 
10327a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym)
1033689f936fSbellard {
1034689f936fSbellard     bswap32s(&sym->st_name);
10357a3148a9Sj_mayer     bswaptls(&sym->st_value);
10367a3148a9Sj_mayer     bswaptls(&sym->st_size);
1037689f936fSbellard     bswap16s(&sym->st_shndx);
1038689f936fSbellard }
1039991f8f0cSRichard Henderson #else
1040991f8f0cSRichard Henderson static inline void bswap_ehdr(struct elfhdr *ehdr) { }
1041991f8f0cSRichard Henderson static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
1042991f8f0cSRichard Henderson static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
1043991f8f0cSRichard Henderson static inline void bswap_sym(struct elf_sym *sym) { }
104431e31b8aSbellard #endif
104531e31b8aSbellard 
1046edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
1047edf8e2afSMika Westerberg static int elf_core_dump(int, const CPUState *);
1048edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
1049682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
1050edf8e2afSMika Westerberg 
10519058abddSRichard Henderson /* Verify the portions of EHDR within E_IDENT for the target.
10529058abddSRichard Henderson    This can be performed before bswapping the entire header.  */
10539058abddSRichard Henderson static bool elf_check_ident(struct elfhdr *ehdr)
10549058abddSRichard Henderson {
10559058abddSRichard Henderson     return (ehdr->e_ident[EI_MAG0] == ELFMAG0
10569058abddSRichard Henderson             && ehdr->e_ident[EI_MAG1] == ELFMAG1
10579058abddSRichard Henderson             && ehdr->e_ident[EI_MAG2] == ELFMAG2
10589058abddSRichard Henderson             && ehdr->e_ident[EI_MAG3] == ELFMAG3
10599058abddSRichard Henderson             && ehdr->e_ident[EI_CLASS] == ELF_CLASS
10609058abddSRichard Henderson             && ehdr->e_ident[EI_DATA] == ELF_DATA
10619058abddSRichard Henderson             && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
10629058abddSRichard Henderson }
10639058abddSRichard Henderson 
10649058abddSRichard Henderson /* Verify the portions of EHDR outside of E_IDENT for the target.
10659058abddSRichard Henderson    This has to wait until after bswapping the header.  */
10669058abddSRichard Henderson static bool elf_check_ehdr(struct elfhdr *ehdr)
10679058abddSRichard Henderson {
10689058abddSRichard Henderson     return (elf_check_arch(ehdr->e_machine)
10699058abddSRichard Henderson             && ehdr->e_ehsize == sizeof(struct elfhdr)
10709058abddSRichard Henderson             && ehdr->e_phentsize == sizeof(struct elf_phdr)
10719058abddSRichard Henderson             && ehdr->e_shentsize == sizeof(struct elf_shdr)
10729058abddSRichard Henderson             && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
10739058abddSRichard Henderson }
10749058abddSRichard Henderson 
107531e31b8aSbellard /*
1076e5fe0c52Spbrook  * 'copy_elf_strings()' copies argument/envelope strings from user
107731e31b8aSbellard  * memory to free pages in kernel mem. These are in a format ready
107831e31b8aSbellard  * to be put directly into the top of new user memory.
107931e31b8aSbellard  *
108031e31b8aSbellard  */
1081992f48a0Sblueswir1 static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
1082992f48a0Sblueswir1                                   abi_ulong p)
108331e31b8aSbellard {
108431e31b8aSbellard     char *tmp, *tmp1, *pag = NULL;
108531e31b8aSbellard     int len, offset = 0;
108631e31b8aSbellard 
108731e31b8aSbellard     if (!p) {
108831e31b8aSbellard         return 0;       /* bullet-proofing */
108931e31b8aSbellard     }
109031e31b8aSbellard     while (argc-- > 0) {
1091edf779ffSbellard         tmp = argv[argc];
1092edf779ffSbellard         if (!tmp) {
109331e31b8aSbellard             fprintf(stderr, "VFS: argc is wrong");
109431e31b8aSbellard             exit(-1);
109531e31b8aSbellard         }
1096edf779ffSbellard         tmp1 = tmp;
1097edf779ffSbellard         while (*tmp++);
109831e31b8aSbellard         len = tmp - tmp1;
109931e31b8aSbellard         if (p < len) {  /* this shouldn't happen - 128kB */
110031e31b8aSbellard             return 0;
110131e31b8aSbellard         }
110231e31b8aSbellard         while (len) {
110331e31b8aSbellard             --p; --tmp; --len;
110431e31b8aSbellard             if (--offset < 0) {
110554936004Sbellard                 offset = p % TARGET_PAGE_SIZE;
110644a91caeSbellard                 pag = (char *)page[p/TARGET_PAGE_SIZE];
110744a91caeSbellard                 if (!pag) {
1108*7dd47667SPeter Maydell                     pag = g_try_malloc0(TARGET_PAGE_SIZE);
110953a5960aSpbrook                     page[p/TARGET_PAGE_SIZE] = pag;
111044a91caeSbellard                     if (!pag)
111131e31b8aSbellard                         return 0;
111231e31b8aSbellard                 }
111331e31b8aSbellard             }
111431e31b8aSbellard             if (len == 0 || offset == 0) {
1115edf779ffSbellard                 *(pag + offset) = *tmp;
111631e31b8aSbellard             }
111731e31b8aSbellard             else {
111831e31b8aSbellard                 int bytes_to_copy = (len > offset) ? offset : len;
111931e31b8aSbellard                 tmp -= bytes_to_copy;
112031e31b8aSbellard                 p -= bytes_to_copy;
112131e31b8aSbellard                 offset -= bytes_to_copy;
112231e31b8aSbellard                 len -= bytes_to_copy;
112331e31b8aSbellard                 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
112431e31b8aSbellard             }
112531e31b8aSbellard         }
112631e31b8aSbellard     }
112731e31b8aSbellard     return p;
112831e31b8aSbellard }
112931e31b8aSbellard 
1130992f48a0Sblueswir1 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
113131e31b8aSbellard                                  struct image_info *info)
113231e31b8aSbellard {
113360dcbcb5SRichard Henderson     abi_ulong stack_base, size, error, guard;
113431e31b8aSbellard     int i;
113531e31b8aSbellard 
113631e31b8aSbellard     /* Create enough stack to hold everything.  If we don't use
113760dcbcb5SRichard Henderson        it for args, we'll use it for something else.  */
1138703e0e89SRichard Henderson     size = guest_stack_size;
113960dcbcb5SRichard Henderson     if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) {
114054936004Sbellard         size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
114160dcbcb5SRichard Henderson     }
114260dcbcb5SRichard Henderson     guard = TARGET_PAGE_SIZE;
114360dcbcb5SRichard Henderson     if (guard < qemu_real_host_page_size) {
114460dcbcb5SRichard Henderson         guard = qemu_real_host_page_size;
114560dcbcb5SRichard Henderson     }
114660dcbcb5SRichard Henderson 
114760dcbcb5SRichard Henderson     error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
114860dcbcb5SRichard Henderson                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
114909bfb054Sbellard     if (error == -1) {
115060dcbcb5SRichard Henderson         perror("mmap stack");
115131e31b8aSbellard         exit(-1);
115231e31b8aSbellard     }
115331e31b8aSbellard 
115460dcbcb5SRichard Henderson     /* We reserve one extra page at the top of the stack as guard.  */
115560dcbcb5SRichard Henderson     target_mprotect(error, guard, PROT_NONE);
115660dcbcb5SRichard Henderson 
115760dcbcb5SRichard Henderson     info->stack_limit = error + guard;
115860dcbcb5SRichard Henderson     stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
115909bfb054Sbellard     p += stack_base;
116009bfb054Sbellard 
116131e31b8aSbellard     for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
116231e31b8aSbellard         if (bprm->page[i]) {
116331e31b8aSbellard             info->rss++;
1164579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
116553a5960aSpbrook             memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
1166*7dd47667SPeter Maydell             g_free(bprm->page[i]);
116731e31b8aSbellard         }
116854936004Sbellard         stack_base += TARGET_PAGE_SIZE;
116931e31b8aSbellard     }
117031e31b8aSbellard     return p;
117131e31b8aSbellard }
117231e31b8aSbellard 
1173cf129f3aSRichard Henderson /* Map and zero the bss.  We need to explicitly zero any fractional pages
1174cf129f3aSRichard Henderson    after the data section (i.e. bss).  */
1175cf129f3aSRichard Henderson static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
117631e31b8aSbellard {
1177cf129f3aSRichard Henderson     uintptr_t host_start, host_map_start, host_end;
1178cf129f3aSRichard Henderson 
1179cf129f3aSRichard Henderson     last_bss = TARGET_PAGE_ALIGN(last_bss);
1180cf129f3aSRichard Henderson 
1181cf129f3aSRichard Henderson     /* ??? There is confusion between qemu_real_host_page_size and
1182cf129f3aSRichard Henderson        qemu_host_page_size here and elsewhere in target_mmap, which
1183cf129f3aSRichard Henderson        may lead to the end of the data section mapping from the file
1184cf129f3aSRichard Henderson        not being mapped.  At least there was an explicit test and
1185cf129f3aSRichard Henderson        comment for that here, suggesting that "the file size must
1186cf129f3aSRichard Henderson        be known".  The comment probably pre-dates the introduction
1187cf129f3aSRichard Henderson        of the fstat system call in target_mmap which does in fact
1188cf129f3aSRichard Henderson        find out the size.  What isn't clear is if the workaround
1189cf129f3aSRichard Henderson        here is still actually needed.  For now, continue with it,
1190cf129f3aSRichard Henderson        but merge it with the "normal" mmap that would allocate the bss.  */
1191cf129f3aSRichard Henderson 
1192cf129f3aSRichard Henderson     host_start = (uintptr_t) g2h(elf_bss);
1193cf129f3aSRichard Henderson     host_end = (uintptr_t) g2h(last_bss);
1194cf129f3aSRichard Henderson     host_map_start = (host_start + qemu_real_host_page_size - 1);
1195cf129f3aSRichard Henderson     host_map_start &= -qemu_real_host_page_size;
1196cf129f3aSRichard Henderson 
1197cf129f3aSRichard Henderson     if (host_map_start < host_end) {
1198cf129f3aSRichard Henderson         void *p = mmap((void *)host_map_start, host_end - host_map_start,
1199cf129f3aSRichard Henderson                        prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1200cf129f3aSRichard Henderson         if (p == MAP_FAILED) {
120131e31b8aSbellard             perror("cannot mmap brk");
120231e31b8aSbellard             exit(-1);
120331e31b8aSbellard         }
1204cf129f3aSRichard Henderson 
1205cf129f3aSRichard Henderson         /* Since we didn't use target_mmap, make sure to record
1206cf129f3aSRichard Henderson            the validity of the pages with qemu.  */
1207cf129f3aSRichard Henderson         page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot|PAGE_VALID);
120831e31b8aSbellard     }
120931e31b8aSbellard 
1210cf129f3aSRichard Henderson     if (host_start < host_map_start) {
1211cf129f3aSRichard Henderson         memset((void *)host_start, 0, host_map_start - host_start);
1212853d6f7aSbellard     }
1213853d6f7aSbellard }
1214853d6f7aSbellard 
12151af02e83SMike Frysinger #ifdef CONFIG_USE_FDPIC
12161af02e83SMike Frysinger static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
12171af02e83SMike Frysinger {
12181af02e83SMike Frysinger     uint16_t n;
12191af02e83SMike Frysinger     struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
12201af02e83SMike Frysinger 
12211af02e83SMike Frysinger     /* elf32_fdpic_loadseg */
12221af02e83SMike Frysinger     n = info->nsegs;
12231af02e83SMike Frysinger     while (n--) {
12241af02e83SMike Frysinger         sp -= 12;
12251af02e83SMike Frysinger         put_user_u32(loadsegs[n].addr, sp+0);
12261af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_vaddr, sp+4);
12271af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_memsz, sp+8);
12281af02e83SMike Frysinger     }
12291af02e83SMike Frysinger 
12301af02e83SMike Frysinger     /* elf32_fdpic_loadmap */
12311af02e83SMike Frysinger     sp -= 4;
12321af02e83SMike Frysinger     put_user_u16(0, sp+0); /* version */
12331af02e83SMike Frysinger     put_user_u16(info->nsegs, sp+2); /* nsegs */
12341af02e83SMike Frysinger 
12351af02e83SMike Frysinger     info->personality = PER_LINUX_FDPIC;
12361af02e83SMike Frysinger     info->loadmap_addr = sp;
12371af02e83SMike Frysinger 
12381af02e83SMike Frysinger     return sp;
12391af02e83SMike Frysinger }
12401af02e83SMike Frysinger #endif
12411af02e83SMike Frysinger 
1242992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
124331e31b8aSbellard                                    struct elfhdr *exec,
12448e62a717SRichard Henderson                                    struct image_info *info,
12458e62a717SRichard Henderson                                    struct image_info *interp_info)
124631e31b8aSbellard {
1247992f48a0Sblueswir1     abi_ulong sp;
124853a5960aSpbrook     int size;
124914322badSLaurent ALFONSI     int i;
125014322badSLaurent ALFONSI     abi_ulong u_rand_bytes;
125114322badSLaurent ALFONSI     uint8_t k_rand_bytes[16];
1252992f48a0Sblueswir1     abi_ulong u_platform;
125315338fd7Sbellard     const char *k_platform;
1254863cf0b7Sj_mayer     const int n = sizeof(elf_addr_t);
125531e31b8aSbellard 
125653a5960aSpbrook     sp = p;
12571af02e83SMike Frysinger 
12581af02e83SMike Frysinger #ifdef CONFIG_USE_FDPIC
12591af02e83SMike Frysinger     /* Needs to be before we load the env/argc/... */
12601af02e83SMike Frysinger     if (elf_is_fdpic(exec)) {
12611af02e83SMike Frysinger         /* Need 4 byte alignment for these structs */
12621af02e83SMike Frysinger         sp &= ~3;
12631af02e83SMike Frysinger         sp = loader_build_fdpic_loadmap(info, sp);
12641af02e83SMike Frysinger         info->other_info = interp_info;
12651af02e83SMike Frysinger         if (interp_info) {
12661af02e83SMike Frysinger             interp_info->other_info = info;
12671af02e83SMike Frysinger             sp = loader_build_fdpic_loadmap(interp_info, sp);
12681af02e83SMike Frysinger         }
12691af02e83SMike Frysinger     }
12701af02e83SMike Frysinger #endif
12711af02e83SMike Frysinger 
127253a5960aSpbrook     u_platform = 0;
127315338fd7Sbellard     k_platform = ELF_PLATFORM;
127415338fd7Sbellard     if (k_platform) {
127515338fd7Sbellard         size_t len = strlen(k_platform) + 1;
127653a5960aSpbrook         sp -= (len + n - 1) & ~(n - 1);
127753a5960aSpbrook         u_platform = sp;
1278579a97f7Sbellard         /* FIXME - check return value of memcpy_to_target() for failure */
127953a5960aSpbrook         memcpy_to_target(sp, k_platform, len);
128015338fd7Sbellard     }
128114322badSLaurent ALFONSI 
128214322badSLaurent ALFONSI     /*
128314322badSLaurent ALFONSI      * Generate 16 random bytes for userspace PRNG seeding (not
128414322badSLaurent ALFONSI      * cryptically secure but it's not the aim of QEMU).
128514322badSLaurent ALFONSI      */
128614322badSLaurent ALFONSI     srand((unsigned int) time(NULL));
128714322badSLaurent ALFONSI     for (i = 0; i < 16; i++) {
128814322badSLaurent ALFONSI         k_rand_bytes[i] = rand();
128914322badSLaurent ALFONSI     }
129014322badSLaurent ALFONSI     sp -= 16;
129114322badSLaurent ALFONSI     u_rand_bytes = sp;
129214322badSLaurent ALFONSI     /* FIXME - check return value of memcpy_to_target() for failure */
129314322badSLaurent ALFONSI     memcpy_to_target(sp, k_rand_bytes, 16);
129414322badSLaurent ALFONSI 
129553a5960aSpbrook     /*
129653a5960aSpbrook      * Force 16 byte _final_ alignment here for generality.
129753a5960aSpbrook      */
1298992f48a0Sblueswir1     sp = sp &~ (abi_ulong)15;
129953a5960aSpbrook     size = (DLINFO_ITEMS + 1) * 2;
130015338fd7Sbellard     if (k_platform)
130153a5960aSpbrook         size += 2;
1302f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS
130353a5960aSpbrook     size += DLINFO_ARCH_ITEMS * 2;
1304f5155289Sbellard #endif
130553a5960aSpbrook     size += envc + argc + 2;
1306b9329d4bSRichard Henderson     size += 1;  /* argc itself */
130753a5960aSpbrook     size *= n;
130853a5960aSpbrook     if (size & 15)
130953a5960aSpbrook         sp -= 16 - (size & 15);
1310f5155289Sbellard 
1311863cf0b7Sj_mayer     /* This is correct because Linux defines
1312863cf0b7Sj_mayer      * elf_addr_t as Elf32_Off / Elf64_Off
1313863cf0b7Sj_mayer      */
131453a5960aSpbrook #define NEW_AUX_ENT(id, val) do {               \
13152f619698Sbellard         sp -= n; put_user_ual(val, sp);         \
13162f619698Sbellard         sp -= n; put_user_ual(id, sp);          \
131753a5960aSpbrook     } while(0)
13182f619698Sbellard 
13190bccf03dSbellard     NEW_AUX_ENT (AT_NULL, 0);
1320f5155289Sbellard 
13210bccf03dSbellard     /* There must be exactly DLINFO_ITEMS entries here.  */
13228e62a717SRichard Henderson     NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
1323992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1324992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
1325992f48a0Sblueswir1     NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
13268e62a717SRichard Henderson     NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0));
1327992f48a0Sblueswir1     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
13288e62a717SRichard Henderson     NEW_AUX_ENT(AT_ENTRY, info->entry);
1329992f48a0Sblueswir1     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
1330992f48a0Sblueswir1     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
1331992f48a0Sblueswir1     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
1332992f48a0Sblueswir1     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
1333992f48a0Sblueswir1     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
1334a07c67dfSpbrook     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
133514322badSLaurent ALFONSI     NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
133614322badSLaurent ALFONSI 
133715338fd7Sbellard     if (k_platform)
133853a5960aSpbrook         NEW_AUX_ENT(AT_PLATFORM, u_platform);
1339f5155289Sbellard #ifdef ARCH_DLINFO
1340f5155289Sbellard     /*
1341f5155289Sbellard      * ARCH_DLINFO must come last so platform specific code can enforce
1342f5155289Sbellard      * special alignment requirements on the AUXV if necessary (eg. PPC).
1343f5155289Sbellard      */
1344f5155289Sbellard     ARCH_DLINFO;
1345f5155289Sbellard #endif
1346f5155289Sbellard #undef NEW_AUX_ENT
1347f5155289Sbellard 
1348edf8e2afSMika Westerberg     info->saved_auxv = sp;
1349edf8e2afSMika Westerberg 
1350b9329d4bSRichard Henderson     sp = loader_build_argptr(envc, argc, sp, p, 0);
135131e31b8aSbellard     return sp;
135231e31b8aSbellard }
135331e31b8aSbellard 
135497cc7560SDr. David Alan Gilbert #ifndef TARGET_HAS_GUEST_VALIDATE_BASE
135597cc7560SDr. David Alan Gilbert /* If the guest doesn't have a validation function just agree */
135697cc7560SDr. David Alan Gilbert bool guest_validate_base(unsigned long guest_base)
135797cc7560SDr. David Alan Gilbert {
135897cc7560SDr. David Alan Gilbert     return 1;
135997cc7560SDr. David Alan Gilbert }
136097cc7560SDr. David Alan Gilbert #endif
136197cc7560SDr. David Alan Gilbert 
1362f3ed1f5dSPeter Maydell static void probe_guest_base(const char *image_name,
1363f3ed1f5dSPeter Maydell                              abi_ulong loaddr, abi_ulong hiaddr)
1364f3ed1f5dSPeter Maydell {
1365f3ed1f5dSPeter Maydell     /* Probe for a suitable guest base address, if the user has not set
1366f3ed1f5dSPeter Maydell      * it explicitly, and set guest_base appropriately.
1367f3ed1f5dSPeter Maydell      * In case of error we will print a suitable message and exit.
1368f3ed1f5dSPeter Maydell      */
1369f3ed1f5dSPeter Maydell #if defined(CONFIG_USE_GUEST_BASE)
1370f3ed1f5dSPeter Maydell     const char *errmsg;
1371f3ed1f5dSPeter Maydell     if (!have_guest_base && !reserved_va) {
1372f3ed1f5dSPeter Maydell         unsigned long host_start, real_start, host_size;
1373f3ed1f5dSPeter Maydell 
1374f3ed1f5dSPeter Maydell         /* Round addresses to page boundaries.  */
1375f3ed1f5dSPeter Maydell         loaddr &= qemu_host_page_mask;
1376f3ed1f5dSPeter Maydell         hiaddr = HOST_PAGE_ALIGN(hiaddr);
1377f3ed1f5dSPeter Maydell 
1378f3ed1f5dSPeter Maydell         if (loaddr < mmap_min_addr) {
1379f3ed1f5dSPeter Maydell             host_start = HOST_PAGE_ALIGN(mmap_min_addr);
1380f3ed1f5dSPeter Maydell         } else {
1381f3ed1f5dSPeter Maydell             host_start = loaddr;
1382f3ed1f5dSPeter Maydell             if (host_start != loaddr) {
1383f3ed1f5dSPeter Maydell                 errmsg = "Address overflow loading ELF binary";
1384f3ed1f5dSPeter Maydell                 goto exit_errmsg;
1385f3ed1f5dSPeter Maydell             }
1386f3ed1f5dSPeter Maydell         }
1387f3ed1f5dSPeter Maydell         host_size = hiaddr - loaddr;
1388f3ed1f5dSPeter Maydell         while (1) {
1389f3ed1f5dSPeter Maydell             /* Do not use mmap_find_vma here because that is limited to the
1390f3ed1f5dSPeter Maydell                guest address space.  We are going to make the
1391f3ed1f5dSPeter Maydell                guest address space fit whatever we're given.  */
1392f3ed1f5dSPeter Maydell             real_start = (unsigned long)
1393f3ed1f5dSPeter Maydell                 mmap((void *)host_start, host_size, PROT_NONE,
1394f3ed1f5dSPeter Maydell                      MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
1395f3ed1f5dSPeter Maydell             if (real_start == (unsigned long)-1) {
1396f3ed1f5dSPeter Maydell                 goto exit_perror;
1397f3ed1f5dSPeter Maydell             }
139897cc7560SDr. David Alan Gilbert             guest_base = real_start - loaddr;
139997cc7560SDr. David Alan Gilbert             if ((real_start == host_start) &&
140097cc7560SDr. David Alan Gilbert                 guest_validate_base(guest_base)) {
1401f3ed1f5dSPeter Maydell                 break;
1402f3ed1f5dSPeter Maydell             }
1403f3ed1f5dSPeter Maydell             /* That address didn't work.  Unmap and try a different one.
1404f3ed1f5dSPeter Maydell                The address the host picked because is typically right at
1405f3ed1f5dSPeter Maydell                the top of the host address space and leaves the guest with
1406f3ed1f5dSPeter Maydell                no usable address space.  Resort to a linear search.  We
1407f3ed1f5dSPeter Maydell                already compensated for mmap_min_addr, so this should not
1408f3ed1f5dSPeter Maydell                happen often.  Probably means we got unlucky and host
1409f3ed1f5dSPeter Maydell                address space randomization put a shared library somewhere
1410f3ed1f5dSPeter Maydell                inconvenient.  */
1411f3ed1f5dSPeter Maydell             munmap((void *)real_start, host_size);
1412f3ed1f5dSPeter Maydell             host_start += qemu_host_page_size;
1413f3ed1f5dSPeter Maydell             if (host_start == loaddr) {
1414f3ed1f5dSPeter Maydell                 /* Theoretically possible if host doesn't have any suitably
1415f3ed1f5dSPeter Maydell                    aligned areas.  Normally the first mmap will fail.  */
1416f3ed1f5dSPeter Maydell                 errmsg = "Unable to find space for application";
1417f3ed1f5dSPeter Maydell                 goto exit_errmsg;
1418f3ed1f5dSPeter Maydell             }
1419f3ed1f5dSPeter Maydell         }
1420f3ed1f5dSPeter Maydell         qemu_log("Relocating guest address space from 0x"
1421f3ed1f5dSPeter Maydell                  TARGET_ABI_FMT_lx " to 0x%lx\n",
1422f3ed1f5dSPeter Maydell                  loaddr, real_start);
1423f3ed1f5dSPeter Maydell     }
1424f3ed1f5dSPeter Maydell     return;
1425f3ed1f5dSPeter Maydell 
1426f3ed1f5dSPeter Maydell exit_perror:
1427f3ed1f5dSPeter Maydell     errmsg = strerror(errno);
1428f3ed1f5dSPeter Maydell exit_errmsg:
1429f3ed1f5dSPeter Maydell     fprintf(stderr, "%s: %s\n", image_name, errmsg);
1430f3ed1f5dSPeter Maydell     exit(-1);
1431f3ed1f5dSPeter Maydell #endif
1432f3ed1f5dSPeter Maydell }
1433f3ed1f5dSPeter Maydell 
1434f3ed1f5dSPeter Maydell 
14358e62a717SRichard Henderson /* Load an ELF image into the address space.
143631e31b8aSbellard 
14378e62a717SRichard Henderson    IMAGE_NAME is the filename of the image, to use in error messages.
14388e62a717SRichard Henderson    IMAGE_FD is the open file descriptor for the image.
14398e62a717SRichard Henderson 
14408e62a717SRichard Henderson    BPRM_BUF is a copy of the beginning of the file; this of course
14418e62a717SRichard Henderson    contains the elf file header at offset 0.  It is assumed that this
14428e62a717SRichard Henderson    buffer is sufficiently aligned to present no problems to the host
14438e62a717SRichard Henderson    in accessing data at aligned offsets within the buffer.
14448e62a717SRichard Henderson 
14458e62a717SRichard Henderson    On return: INFO values will be filled in, as necessary or available.  */
14468e62a717SRichard Henderson 
14478e62a717SRichard Henderson static void load_elf_image(const char *image_name, int image_fd,
1448bf858897SRichard Henderson                            struct image_info *info, char **pinterp_name,
14499955ffacSRichard Henderson                            char bprm_buf[BPRM_BUF_SIZE])
145031e31b8aSbellard {
14518e62a717SRichard Henderson     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
14528e62a717SRichard Henderson     struct elf_phdr *phdr;
14538e62a717SRichard Henderson     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
14548e62a717SRichard Henderson     int i, retval;
14558e62a717SRichard Henderson     const char *errmsg;
145631e31b8aSbellard 
14578e62a717SRichard Henderson     /* First of all, some simple consistency checks */
14588e62a717SRichard Henderson     errmsg = "Invalid ELF image for this architecture";
14598e62a717SRichard Henderson     if (!elf_check_ident(ehdr)) {
14608e62a717SRichard Henderson         goto exit_errmsg;
14618e62a717SRichard Henderson     }
14628e62a717SRichard Henderson     bswap_ehdr(ehdr);
14638e62a717SRichard Henderson     if (!elf_check_ehdr(ehdr)) {
14648e62a717SRichard Henderson         goto exit_errmsg;
146531e31b8aSbellard     }
146631e31b8aSbellard 
14678e62a717SRichard Henderson     i = ehdr->e_phnum * sizeof(struct elf_phdr);
14688e62a717SRichard Henderson     if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
14698e62a717SRichard Henderson         phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
14709955ffacSRichard Henderson     } else {
14718e62a717SRichard Henderson         phdr = (struct elf_phdr *) alloca(i);
14728e62a717SRichard Henderson         retval = pread(image_fd, phdr, i, ehdr->e_phoff);
14739955ffacSRichard Henderson         if (retval != i) {
14748e62a717SRichard Henderson             goto exit_read;
14759955ffacSRichard Henderson         }
147631e31b8aSbellard     }
14778e62a717SRichard Henderson     bswap_phdr(phdr, ehdr->e_phnum);
147809bfb054Sbellard 
14791af02e83SMike Frysinger #ifdef CONFIG_USE_FDPIC
14801af02e83SMike Frysinger     info->nsegs = 0;
14811af02e83SMike Frysinger     info->pt_dynamic_addr = 0;
14821af02e83SMike Frysinger #endif
14831af02e83SMike Frysinger 
1484682674b8SRichard Henderson     /* Find the maximum size of the image and allocate an appropriate
1485682674b8SRichard Henderson        amount of memory to handle that.  */
1486682674b8SRichard Henderson     loaddr = -1, hiaddr = 0;
14878e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; ++i) {
14888e62a717SRichard Henderson         if (phdr[i].p_type == PT_LOAD) {
14898e62a717SRichard Henderson             abi_ulong a = phdr[i].p_vaddr;
1490682674b8SRichard Henderson             if (a < loaddr) {
1491682674b8SRichard Henderson                 loaddr = a;
1492682674b8SRichard Henderson             }
14938e62a717SRichard Henderson             a += phdr[i].p_memsz;
1494682674b8SRichard Henderson             if (a > hiaddr) {
1495682674b8SRichard Henderson                 hiaddr = a;
1496682674b8SRichard Henderson             }
14971af02e83SMike Frysinger #ifdef CONFIG_USE_FDPIC
14981af02e83SMike Frysinger             ++info->nsegs;
14991af02e83SMike Frysinger #endif
1500682674b8SRichard Henderson         }
1501682674b8SRichard Henderson     }
1502682674b8SRichard Henderson 
1503682674b8SRichard Henderson     load_addr = loaddr;
15048e62a717SRichard Henderson     if (ehdr->e_type == ET_DYN) {
1505682674b8SRichard Henderson         /* The image indicates that it can be loaded anywhere.  Find a
1506682674b8SRichard Henderson            location that can hold the memory space required.  If the
1507682674b8SRichard Henderson            image is pre-linked, LOADDR will be non-zero.  Since we do
1508682674b8SRichard Henderson            not supply MAP_FIXED here we'll use that address if and
1509682674b8SRichard Henderson            only if it remains available.  */
1510682674b8SRichard Henderson         load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
1511682674b8SRichard Henderson                                 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
151209bfb054Sbellard                                 -1, 0);
1513682674b8SRichard Henderson         if (load_addr == -1) {
15148e62a717SRichard Henderson             goto exit_perror;
151509bfb054Sbellard         }
1516bf858897SRichard Henderson     } else if (pinterp_name != NULL) {
1517bf858897SRichard Henderson         /* This is the main executable.  Make sure that the low
1518bf858897SRichard Henderson            address does not conflict with MMAP_MIN_ADDR or the
1519bf858897SRichard Henderson            QEMU application itself.  */
1520f3ed1f5dSPeter Maydell         probe_guest_base(image_name, loaddr, hiaddr);
152109bfb054Sbellard     }
1522682674b8SRichard Henderson     load_bias = load_addr - loaddr;
152309bfb054Sbellard 
15241af02e83SMike Frysinger #ifdef CONFIG_USE_FDPIC
15251af02e83SMike Frysinger     {
15261af02e83SMike Frysinger         struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
15277267c094SAnthony Liguori             g_malloc(sizeof(*loadsegs) * info->nsegs);
15281af02e83SMike Frysinger 
15291af02e83SMike Frysinger         for (i = 0; i < ehdr->e_phnum; ++i) {
15301af02e83SMike Frysinger             switch (phdr[i].p_type) {
15311af02e83SMike Frysinger             case PT_DYNAMIC:
15321af02e83SMike Frysinger                 info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
15331af02e83SMike Frysinger                 break;
15341af02e83SMike Frysinger             case PT_LOAD:
15351af02e83SMike Frysinger                 loadsegs->addr = phdr[i].p_vaddr + load_bias;
15361af02e83SMike Frysinger                 loadsegs->p_vaddr = phdr[i].p_vaddr;
15371af02e83SMike Frysinger                 loadsegs->p_memsz = phdr[i].p_memsz;
15381af02e83SMike Frysinger                 ++loadsegs;
15391af02e83SMike Frysinger                 break;
15401af02e83SMike Frysinger             }
15411af02e83SMike Frysinger         }
15421af02e83SMike Frysinger     }
15431af02e83SMike Frysinger #endif
15441af02e83SMike Frysinger 
15458e62a717SRichard Henderson     info->load_bias = load_bias;
15468e62a717SRichard Henderson     info->load_addr = load_addr;
15478e62a717SRichard Henderson     info->entry = ehdr->e_entry + load_bias;
15488e62a717SRichard Henderson     info->start_code = -1;
15498e62a717SRichard Henderson     info->end_code = 0;
15508e62a717SRichard Henderson     info->start_data = -1;
15518e62a717SRichard Henderson     info->end_data = 0;
15528e62a717SRichard Henderson     info->brk = 0;
15538e62a717SRichard Henderson 
15548e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; i++) {
15558e62a717SRichard Henderson         struct elf_phdr *eppnt = phdr + i;
155631e31b8aSbellard         if (eppnt->p_type == PT_LOAD) {
1557682674b8SRichard Henderson             abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
155831e31b8aSbellard             int elf_prot = 0;
155931e31b8aSbellard 
156031e31b8aSbellard             if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
156131e31b8aSbellard             if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
156231e31b8aSbellard             if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
156331e31b8aSbellard 
1564682674b8SRichard Henderson             vaddr = load_bias + eppnt->p_vaddr;
1565682674b8SRichard Henderson             vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
1566682674b8SRichard Henderson             vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
1567682674b8SRichard Henderson 
1568682674b8SRichard Henderson             error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
1569682674b8SRichard Henderson                                 elf_prot, MAP_PRIVATE | MAP_FIXED,
15708e62a717SRichard Henderson                                 image_fd, eppnt->p_offset - vaddr_po);
1571e89f07d3Spbrook             if (error == -1) {
15728e62a717SRichard Henderson                 goto exit_perror;
157331e31b8aSbellard             }
157431e31b8aSbellard 
1575682674b8SRichard Henderson             vaddr_ef = vaddr + eppnt->p_filesz;
1576682674b8SRichard Henderson             vaddr_em = vaddr + eppnt->p_memsz;
157731e31b8aSbellard 
1578cf129f3aSRichard Henderson             /* If the load segment requests extra zeros (e.g. bss), map it.  */
1579682674b8SRichard Henderson             if (vaddr_ef < vaddr_em) {
1580682674b8SRichard Henderson                 zero_bss(vaddr_ef, vaddr_em, elf_prot);
1581682674b8SRichard Henderson             }
15828e62a717SRichard Henderson 
15838e62a717SRichard Henderson             /* Find the full program boundaries.  */
15848e62a717SRichard Henderson             if (elf_prot & PROT_EXEC) {
15858e62a717SRichard Henderson                 if (vaddr < info->start_code) {
15868e62a717SRichard Henderson                     info->start_code = vaddr;
1587cf129f3aSRichard Henderson                 }
15888e62a717SRichard Henderson                 if (vaddr_ef > info->end_code) {
15898e62a717SRichard Henderson                     info->end_code = vaddr_ef;
15908e62a717SRichard Henderson                 }
15918e62a717SRichard Henderson             }
15928e62a717SRichard Henderson             if (elf_prot & PROT_WRITE) {
15938e62a717SRichard Henderson                 if (vaddr < info->start_data) {
15948e62a717SRichard Henderson                     info->start_data = vaddr;
15958e62a717SRichard Henderson                 }
15968e62a717SRichard Henderson                 if (vaddr_ef > info->end_data) {
15978e62a717SRichard Henderson                     info->end_data = vaddr_ef;
15988e62a717SRichard Henderson                 }
15998e62a717SRichard Henderson                 if (vaddr_em > info->brk) {
16008e62a717SRichard Henderson                     info->brk = vaddr_em;
16018e62a717SRichard Henderson                 }
16028e62a717SRichard Henderson             }
1603bf858897SRichard Henderson         } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
1604bf858897SRichard Henderson             char *interp_name;
1605bf858897SRichard Henderson 
1606bf858897SRichard Henderson             if (*pinterp_name) {
1607bf858897SRichard Henderson                 errmsg = "Multiple PT_INTERP entries";
1608bf858897SRichard Henderson                 goto exit_errmsg;
1609bf858897SRichard Henderson             }
1610bf858897SRichard Henderson             interp_name = malloc(eppnt->p_filesz);
1611bf858897SRichard Henderson             if (!interp_name) {
1612bf858897SRichard Henderson                 goto exit_perror;
1613bf858897SRichard Henderson             }
1614bf858897SRichard Henderson 
1615bf858897SRichard Henderson             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
1616bf858897SRichard Henderson                 memcpy(interp_name, bprm_buf + eppnt->p_offset,
1617bf858897SRichard Henderson                        eppnt->p_filesz);
1618bf858897SRichard Henderson             } else {
1619bf858897SRichard Henderson                 retval = pread(image_fd, interp_name, eppnt->p_filesz,
1620bf858897SRichard Henderson                                eppnt->p_offset);
1621bf858897SRichard Henderson                 if (retval != eppnt->p_filesz) {
1622bf858897SRichard Henderson                     goto exit_perror;
1623bf858897SRichard Henderson                 }
1624bf858897SRichard Henderson             }
1625bf858897SRichard Henderson             if (interp_name[eppnt->p_filesz - 1] != 0) {
1626bf858897SRichard Henderson                 errmsg = "Invalid PT_INTERP entry";
1627bf858897SRichard Henderson                 goto exit_errmsg;
1628bf858897SRichard Henderson             }
1629bf858897SRichard Henderson             *pinterp_name = interp_name;
16308e62a717SRichard Henderson         }
16318e62a717SRichard Henderson     }
16328e62a717SRichard Henderson 
16338e62a717SRichard Henderson     if (info->end_data == 0) {
16348e62a717SRichard Henderson         info->start_data = info->end_code;
16358e62a717SRichard Henderson         info->end_data = info->end_code;
16368e62a717SRichard Henderson         info->brk = info->end_code;
163731e31b8aSbellard     }
163831e31b8aSbellard 
1639682674b8SRichard Henderson     if (qemu_log_enabled()) {
16408e62a717SRichard Henderson         load_symbols(ehdr, image_fd, load_bias);
1641682674b8SRichard Henderson     }
164231e31b8aSbellard 
16438e62a717SRichard Henderson     close(image_fd);
16448e62a717SRichard Henderson     return;
164531e31b8aSbellard 
16468e62a717SRichard Henderson  exit_read:
16478e62a717SRichard Henderson     if (retval >= 0) {
16488e62a717SRichard Henderson         errmsg = "Incomplete read of file header";
16498e62a717SRichard Henderson         goto exit_errmsg;
16508e62a717SRichard Henderson     }
16518e62a717SRichard Henderson  exit_perror:
16528e62a717SRichard Henderson     errmsg = strerror(errno);
16538e62a717SRichard Henderson  exit_errmsg:
16548e62a717SRichard Henderson     fprintf(stderr, "%s: %s\n", image_name, errmsg);
16558e62a717SRichard Henderson     exit(-1);
16568e62a717SRichard Henderson }
16578e62a717SRichard Henderson 
16588e62a717SRichard Henderson static void load_elf_interp(const char *filename, struct image_info *info,
16598e62a717SRichard Henderson                             char bprm_buf[BPRM_BUF_SIZE])
16608e62a717SRichard Henderson {
16618e62a717SRichard Henderson     int fd, retval;
16628e62a717SRichard Henderson 
16638e62a717SRichard Henderson     fd = open(path(filename), O_RDONLY);
16648e62a717SRichard Henderson     if (fd < 0) {
16658e62a717SRichard Henderson         goto exit_perror;
16668e62a717SRichard Henderson     }
16678e62a717SRichard Henderson 
16688e62a717SRichard Henderson     retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
16698e62a717SRichard Henderson     if (retval < 0) {
16708e62a717SRichard Henderson         goto exit_perror;
16718e62a717SRichard Henderson     }
16728e62a717SRichard Henderson     if (retval < BPRM_BUF_SIZE) {
16738e62a717SRichard Henderson         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
16748e62a717SRichard Henderson     }
16758e62a717SRichard Henderson 
1676bf858897SRichard Henderson     load_elf_image(filename, fd, info, NULL, bprm_buf);
16778e62a717SRichard Henderson     return;
16788e62a717SRichard Henderson 
16798e62a717SRichard Henderson  exit_perror:
16808e62a717SRichard Henderson     fprintf(stderr, "%s: %s\n", filename, strerror(errno));
16818e62a717SRichard Henderson     exit(-1);
168231e31b8aSbellard }
168331e31b8aSbellard 
168449918a75Spbrook static int symfind(const void *s0, const void *s1)
168549918a75Spbrook {
168649918a75Spbrook     struct elf_sym *key = (struct elf_sym *)s0;
168749918a75Spbrook     struct elf_sym *sym = (struct elf_sym *)s1;
168849918a75Spbrook     int result = 0;
168949918a75Spbrook     if (key->st_value < sym->st_value) {
169049918a75Spbrook         result = -1;
1691ec822001SLaurent Desnogues     } else if (key->st_value >= sym->st_value + sym->st_size) {
169249918a75Spbrook         result = 1;
169349918a75Spbrook     }
169449918a75Spbrook     return result;
169549918a75Spbrook }
169649918a75Spbrook 
169749918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
169849918a75Spbrook {
169949918a75Spbrook #if ELF_CLASS == ELFCLASS32
170049918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf32;
170149918a75Spbrook #else
170249918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf64;
170349918a75Spbrook #endif
170449918a75Spbrook 
170549918a75Spbrook     // binary search
170649918a75Spbrook     struct elf_sym key;
170749918a75Spbrook     struct elf_sym *sym;
170849918a75Spbrook 
170949918a75Spbrook     key.st_value = orig_addr;
171049918a75Spbrook 
171149918a75Spbrook     sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
17127cba04f6SBlue Swirl     if (sym != NULL) {
171349918a75Spbrook         return s->disas_strtab + sym->st_name;
171449918a75Spbrook     }
171549918a75Spbrook 
171649918a75Spbrook     return "";
171749918a75Spbrook }
171849918a75Spbrook 
171949918a75Spbrook /* FIXME: This should use elf_ops.h  */
172049918a75Spbrook static int symcmp(const void *s0, const void *s1)
172149918a75Spbrook {
172249918a75Spbrook     struct elf_sym *sym0 = (struct elf_sym *)s0;
172349918a75Spbrook     struct elf_sym *sym1 = (struct elf_sym *)s1;
172449918a75Spbrook     return (sym0->st_value < sym1->st_value)
172549918a75Spbrook         ? -1
172649918a75Spbrook         : ((sym0->st_value > sym1->st_value) ? 1 : 0);
172749918a75Spbrook }
172849918a75Spbrook 
1729689f936fSbellard /* Best attempt to load symbols from this ELF object. */
1730682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
1731689f936fSbellard {
1732682674b8SRichard Henderson     int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
1733682674b8SRichard Henderson     struct elf_shdr *shdr;
1734b9475279SCédric VINCENT     char *strings = NULL;
1735b9475279SCédric VINCENT     struct syminfo *s = NULL;
1736b9475279SCédric VINCENT     struct elf_sym *new_syms, *syms = NULL;
173731e31b8aSbellard 
1738682674b8SRichard Henderson     shnum = hdr->e_shnum;
1739682674b8SRichard Henderson     i = shnum * sizeof(struct elf_shdr);
1740682674b8SRichard Henderson     shdr = (struct elf_shdr *)alloca(i);
1741682674b8SRichard Henderson     if (pread(fd, shdr, i, hdr->e_shoff) != i) {
1742689f936fSbellard         return;
1743682674b8SRichard Henderson     }
1744682674b8SRichard Henderson 
1745682674b8SRichard Henderson     bswap_shdr(shdr, shnum);
1746682674b8SRichard Henderson     for (i = 0; i < shnum; ++i) {
1747682674b8SRichard Henderson         if (shdr[i].sh_type == SHT_SYMTAB) {
1748682674b8SRichard Henderson             sym_idx = i;
1749682674b8SRichard Henderson             str_idx = shdr[i].sh_link;
1750689f936fSbellard             goto found;
1751689f936fSbellard         }
1752689f936fSbellard     }
1753682674b8SRichard Henderson 
1754682674b8SRichard Henderson     /* There will be no symbol table if the file was stripped.  */
1755682674b8SRichard Henderson     return;
1756689f936fSbellard 
1757689f936fSbellard  found:
1758689f936fSbellard     /* Now know where the strtab and symtab are.  Snarf them.  */
1759e80cfcfcSbellard     s = malloc(sizeof(*s));
1760682674b8SRichard Henderson     if (!s) {
1761b9475279SCédric VINCENT         goto give_up;
1762682674b8SRichard Henderson     }
1763682674b8SRichard Henderson 
1764682674b8SRichard Henderson     i = shdr[str_idx].sh_size;
1765682674b8SRichard Henderson     s->disas_strtab = strings = malloc(i);
1766682674b8SRichard Henderson     if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) {
1767b9475279SCédric VINCENT         goto give_up;
1768682674b8SRichard Henderson     }
1769689f936fSbellard 
1770682674b8SRichard Henderson     i = shdr[sym_idx].sh_size;
1771682674b8SRichard Henderson     syms = malloc(i);
1772682674b8SRichard Henderson     if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) {
1773b9475279SCédric VINCENT         goto give_up;
1774682674b8SRichard Henderson     }
1775689f936fSbellard 
1776682674b8SRichard Henderson     nsyms = i / sizeof(struct elf_sym);
1777682674b8SRichard Henderson     for (i = 0; i < nsyms; ) {
177849918a75Spbrook         bswap_sym(syms + i);
1779682674b8SRichard Henderson         /* Throw away entries which we do not need.  */
1780682674b8SRichard Henderson         if (syms[i].st_shndx == SHN_UNDEF
1781682674b8SRichard Henderson             || syms[i].st_shndx >= SHN_LORESERVE
1782682674b8SRichard Henderson             || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
1783682674b8SRichard Henderson             if (i < --nsyms) {
178449918a75Spbrook                 syms[i] = syms[nsyms];
178549918a75Spbrook             }
1786682674b8SRichard Henderson         } else {
178749918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS)
178849918a75Spbrook             /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
178949918a75Spbrook             syms[i].st_value &= ~(target_ulong)1;
179049918a75Spbrook #endif
1791682674b8SRichard Henderson             syms[i].st_value += load_bias;
179249918a75Spbrook             i++;
179349918a75Spbrook         }
1794682674b8SRichard Henderson     }
179549918a75Spbrook 
1796b9475279SCédric VINCENT     /* No "useful" symbol.  */
1797b9475279SCédric VINCENT     if (nsyms == 0) {
1798b9475279SCédric VINCENT         goto give_up;
1799b9475279SCédric VINCENT     }
1800b9475279SCédric VINCENT 
18015d5c9930SRichard Henderson     /* Attempt to free the storage associated with the local symbols
18025d5c9930SRichard Henderson        that we threw away.  Whether or not this has any effect on the
18035d5c9930SRichard Henderson        memory allocation depends on the malloc implementation and how
18045d5c9930SRichard Henderson        many symbols we managed to discard.  */
18058d79de6eSStefan Weil     new_syms = realloc(syms, nsyms * sizeof(*syms));
18068d79de6eSStefan Weil     if (new_syms == NULL) {
1807b9475279SCédric VINCENT         goto give_up;
18085d5c9930SRichard Henderson     }
18098d79de6eSStefan Weil     syms = new_syms;
18105d5c9930SRichard Henderson 
181149918a75Spbrook     qsort(syms, nsyms, sizeof(*syms), symcmp);
181249918a75Spbrook 
181349918a75Spbrook     s->disas_num_syms = nsyms;
181449918a75Spbrook #if ELF_CLASS == ELFCLASS32
181549918a75Spbrook     s->disas_symtab.elf32 = syms;
181649918a75Spbrook #else
181749918a75Spbrook     s->disas_symtab.elf64 = syms;
181849918a75Spbrook #endif
1819682674b8SRichard Henderson     s->lookup_symbol = lookup_symbolxx;
1820e80cfcfcSbellard     s->next = syminfos;
1821e80cfcfcSbellard     syminfos = s;
1822b9475279SCédric VINCENT 
1823b9475279SCédric VINCENT     return;
1824b9475279SCédric VINCENT 
1825b9475279SCédric VINCENT give_up:
1826b9475279SCédric VINCENT     free(s);
1827b9475279SCédric VINCENT     free(strings);
1828b9475279SCédric VINCENT     free(syms);
1829689f936fSbellard }
183031e31b8aSbellard 
1831e5fe0c52Spbrook int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
183231e31b8aSbellard                     struct image_info * info)
183331e31b8aSbellard {
18348e62a717SRichard Henderson     struct image_info interp_info;
183531e31b8aSbellard     struct elfhdr elf_ex;
18368e62a717SRichard Henderson     char *elf_interpreter = NULL;
183731e31b8aSbellard 
1838bf858897SRichard Henderson     info->start_mmap = (abi_ulong)ELF_START_MMAP;
1839bf858897SRichard Henderson     info->mmap = 0;
1840bf858897SRichard Henderson     info->rss = 0;
184131e31b8aSbellard 
1842bf858897SRichard Henderson     load_elf_image(bprm->filename, bprm->fd, info,
1843bf858897SRichard Henderson                    &elf_interpreter, bprm->buf);
1844bf858897SRichard Henderson 
1845bf858897SRichard Henderson     /* ??? We need a copy of the elf header for passing to create_elf_tables.
1846bf858897SRichard Henderson        If we do nothing, we'll have overwritten this when we re-use bprm->buf
1847bf858897SRichard Henderson        when we load the interpreter.  */
1848bf858897SRichard Henderson     elf_ex = *(struct elfhdr *)bprm->buf;
184931e31b8aSbellard 
1850e5fe0c52Spbrook     bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1851e5fe0c52Spbrook     bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1852e5fe0c52Spbrook     bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1853e5fe0c52Spbrook     if (!bprm->p) {
1854bf858897SRichard Henderson         fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
185531e31b8aSbellard         exit(-1);
18569955ffacSRichard Henderson     }
1857379f6698SPaul Brook 
185831e31b8aSbellard     /* Do this so that we can load the interpreter, if need be.  We will
185931e31b8aSbellard        change some of these later */
186031e31b8aSbellard     bprm->p = setup_arg_pages(bprm->p, bprm, info);
186131e31b8aSbellard 
18628e62a717SRichard Henderson     if (elf_interpreter) {
18638e62a717SRichard Henderson         load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
186431e31b8aSbellard 
18658e62a717SRichard Henderson         /* If the program interpreter is one of these two, then assume
18668e62a717SRichard Henderson            an iBCS2 image.  Otherwise assume a native linux image.  */
186731e31b8aSbellard 
18688e62a717SRichard Henderson         if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
18698e62a717SRichard Henderson             || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
18708e62a717SRichard Henderson             info->personality = PER_SVR4;
18718e62a717SRichard Henderson 
187231e31b8aSbellard             /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
18738e62a717SRichard Henderson                and some applications "depend" upon this behavior.  Since
18748e62a717SRichard Henderson                we do not have the power to recompile these, we emulate
18758e62a717SRichard Henderson                the SVr4 behavior.  Sigh.  */
18768e62a717SRichard Henderson             target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
187731e31b8aSbellard                         MAP_FIXED | MAP_PRIVATE, -1, 0);
187831e31b8aSbellard         }
18798e62a717SRichard Henderson     }
188031e31b8aSbellard 
18818e62a717SRichard Henderson     bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
18828e62a717SRichard Henderson                                 info, (elf_interpreter ? &interp_info : NULL));
18838e62a717SRichard Henderson     info->start_stack = bprm->p;
18848e62a717SRichard Henderson 
18858e62a717SRichard Henderson     /* If we have an interpreter, set that as the program's entry point.
18868e78064eSRichard Henderson        Copy the load_bias as well, to help PPC64 interpret the entry
18878e62a717SRichard Henderson        point as a function descriptor.  Do this after creating elf tables
18888e62a717SRichard Henderson        so that we copy the original program entry point into the AUXV.  */
18898e62a717SRichard Henderson     if (elf_interpreter) {
18908e78064eSRichard Henderson         info->load_bias = interp_info.load_bias;
18918e62a717SRichard Henderson         info->entry = interp_info.entry;
1892bf858897SRichard Henderson         free(elf_interpreter);
18938e62a717SRichard Henderson     }
189431e31b8aSbellard 
1895edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
1896edf8e2afSMika Westerberg     bprm->core_dump = &elf_core_dump;
1897edf8e2afSMika Westerberg #endif
1898edf8e2afSMika Westerberg 
189931e31b8aSbellard     return 0;
190031e31b8aSbellard }
190131e31b8aSbellard 
1902edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
1903edf8e2afSMika Westerberg /*
1904edf8e2afSMika Westerberg  * Definitions to generate Intel SVR4-like core files.
1905a2547a13SLaurent Desnogues  * These mostly have the same names as the SVR4 types with "target_elf_"
1906edf8e2afSMika Westerberg  * tacked on the front to prevent clashes with linux definitions,
1907edf8e2afSMika Westerberg  * and the typedef forms have been avoided.  This is mostly like
1908edf8e2afSMika Westerberg  * the SVR4 structure, but more Linuxy, with things that Linux does
1909edf8e2afSMika Westerberg  * not support and which gdb doesn't really use excluded.
1910edf8e2afSMika Westerberg  *
1911edf8e2afSMika Westerberg  * Fields we don't dump (their contents is zero) in linux-user qemu
1912edf8e2afSMika Westerberg  * are marked with XXX.
1913edf8e2afSMika Westerberg  *
1914edf8e2afSMika Westerberg  * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
1915edf8e2afSMika Westerberg  *
1916edf8e2afSMika Westerberg  * Porting ELF coredump for target is (quite) simple process.  First you
1917dd0a3651SNathan Froyd  * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
1918edf8e2afSMika Westerberg  * the target resides):
1919edf8e2afSMika Westerberg  *
1920edf8e2afSMika Westerberg  * #define USE_ELF_CORE_DUMP
1921edf8e2afSMika Westerberg  *
1922edf8e2afSMika Westerberg  * Next you define type of register set used for dumping.  ELF specification
1923edf8e2afSMika Westerberg  * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
1924edf8e2afSMika Westerberg  *
1925c227f099SAnthony Liguori  * typedef <target_regtype> target_elf_greg_t;
1926edf8e2afSMika Westerberg  * #define ELF_NREG <number of registers>
1927c227f099SAnthony Liguori  * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
1928edf8e2afSMika Westerberg  *
1929edf8e2afSMika Westerberg  * Last step is to implement target specific function that copies registers
1930edf8e2afSMika Westerberg  * from given cpu into just specified register set.  Prototype is:
1931edf8e2afSMika Westerberg  *
1932c227f099SAnthony Liguori  * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
1933a2547a13SLaurent Desnogues  *                                const CPUState *env);
1934edf8e2afSMika Westerberg  *
1935edf8e2afSMika Westerberg  * Parameters:
1936edf8e2afSMika Westerberg  *     regs - copy register values into here (allocated and zeroed by caller)
1937edf8e2afSMika Westerberg  *     env - copy registers from here
1938edf8e2afSMika Westerberg  *
1939edf8e2afSMika Westerberg  * Example for ARM target is provided in this file.
1940edf8e2afSMika Westerberg  */
1941edf8e2afSMika Westerberg 
1942edf8e2afSMika Westerberg /* An ELF note in memory */
1943edf8e2afSMika Westerberg struct memelfnote {
1944edf8e2afSMika Westerberg     const char *name;
1945edf8e2afSMika Westerberg     size_t     namesz;
1946edf8e2afSMika Westerberg     size_t     namesz_rounded;
1947edf8e2afSMika Westerberg     int        type;
1948edf8e2afSMika Westerberg     size_t     datasz;
194980f5ce75SLaurent Vivier     size_t     datasz_rounded;
1950edf8e2afSMika Westerberg     void       *data;
1951edf8e2afSMika Westerberg     size_t     notesz;
1952edf8e2afSMika Westerberg };
1953edf8e2afSMika Westerberg 
1954a2547a13SLaurent Desnogues struct target_elf_siginfo {
195580f5ce75SLaurent Vivier     target_int  si_signo; /* signal number */
195680f5ce75SLaurent Vivier     target_int  si_code;  /* extra code */
195780f5ce75SLaurent Vivier     target_int  si_errno; /* errno */
1958edf8e2afSMika Westerberg };
1959edf8e2afSMika Westerberg 
1960a2547a13SLaurent Desnogues struct target_elf_prstatus {
1961a2547a13SLaurent Desnogues     struct target_elf_siginfo pr_info;      /* Info associated with signal */
196280f5ce75SLaurent Vivier     target_short       pr_cursig;    /* Current signal */
1963edf8e2afSMika Westerberg     target_ulong       pr_sigpend;   /* XXX */
1964edf8e2afSMika Westerberg     target_ulong       pr_sighold;   /* XXX */
1965c227f099SAnthony Liguori     target_pid_t       pr_pid;
1966c227f099SAnthony Liguori     target_pid_t       pr_ppid;
1967c227f099SAnthony Liguori     target_pid_t       pr_pgrp;
1968c227f099SAnthony Liguori     target_pid_t       pr_sid;
1969edf8e2afSMika Westerberg     struct target_timeval pr_utime;  /* XXX User time */
1970edf8e2afSMika Westerberg     struct target_timeval pr_stime;  /* XXX System time */
1971edf8e2afSMika Westerberg     struct target_timeval pr_cutime; /* XXX Cumulative user time */
1972edf8e2afSMika Westerberg     struct target_timeval pr_cstime; /* XXX Cumulative system time */
1973c227f099SAnthony Liguori     target_elf_gregset_t      pr_reg;       /* GP registers */
197480f5ce75SLaurent Vivier     target_int         pr_fpvalid;   /* XXX */
1975edf8e2afSMika Westerberg };
1976edf8e2afSMika Westerberg 
1977edf8e2afSMika Westerberg #define ELF_PRARGSZ     (80) /* Number of chars for args */
1978edf8e2afSMika Westerberg 
1979a2547a13SLaurent Desnogues struct target_elf_prpsinfo {
1980edf8e2afSMika Westerberg     char         pr_state;       /* numeric process state */
1981edf8e2afSMika Westerberg     char         pr_sname;       /* char for pr_state */
1982edf8e2afSMika Westerberg     char         pr_zomb;        /* zombie */
1983edf8e2afSMika Westerberg     char         pr_nice;        /* nice val */
1984edf8e2afSMika Westerberg     target_ulong pr_flag;        /* flags */
1985c227f099SAnthony Liguori     target_uid_t pr_uid;
1986c227f099SAnthony Liguori     target_gid_t pr_gid;
1987c227f099SAnthony Liguori     target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
1988edf8e2afSMika Westerberg     /* Lots missing */
1989edf8e2afSMika Westerberg     char    pr_fname[16];           /* filename of executable */
1990edf8e2afSMika Westerberg     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
1991edf8e2afSMika Westerberg };
1992edf8e2afSMika Westerberg 
1993edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */
1994edf8e2afSMika Westerberg struct elf_thread_status {
199572cf2d4fSBlue Swirl     QTAILQ_ENTRY(elf_thread_status)  ets_link;
1996a2547a13SLaurent Desnogues     struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
1997edf8e2afSMika Westerberg #if 0
1998edf8e2afSMika Westerberg     elf_fpregset_t fpu;             /* NT_PRFPREG */
1999edf8e2afSMika Westerberg     struct task_struct *thread;
2000edf8e2afSMika Westerberg     elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */
2001edf8e2afSMika Westerberg #endif
2002edf8e2afSMika Westerberg     struct memelfnote notes[1];
2003edf8e2afSMika Westerberg     int num_notes;
2004edf8e2afSMika Westerberg };
2005edf8e2afSMika Westerberg 
2006edf8e2afSMika Westerberg struct elf_note_info {
2007edf8e2afSMika Westerberg     struct memelfnote   *notes;
2008a2547a13SLaurent Desnogues     struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
2009a2547a13SLaurent Desnogues     struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
2010edf8e2afSMika Westerberg 
201172cf2d4fSBlue Swirl     QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list;
2012edf8e2afSMika Westerberg #if 0
2013edf8e2afSMika Westerberg     /*
2014edf8e2afSMika Westerberg      * Current version of ELF coredump doesn't support
2015edf8e2afSMika Westerberg      * dumping fp regs etc.
2016edf8e2afSMika Westerberg      */
2017edf8e2afSMika Westerberg     elf_fpregset_t *fpu;
2018edf8e2afSMika Westerberg     elf_fpxregset_t *xfpu;
2019edf8e2afSMika Westerberg     int thread_status_size;
2020edf8e2afSMika Westerberg #endif
2021edf8e2afSMika Westerberg     int notes_size;
2022edf8e2afSMika Westerberg     int numnote;
2023edf8e2afSMika Westerberg };
2024edf8e2afSMika Westerberg 
2025edf8e2afSMika Westerberg struct vm_area_struct {
2026edf8e2afSMika Westerberg     abi_ulong   vma_start;  /* start vaddr of memory region */
2027edf8e2afSMika Westerberg     abi_ulong   vma_end;    /* end vaddr of memory region */
2028edf8e2afSMika Westerberg     abi_ulong   vma_flags;  /* protection etc. flags for the region */
202972cf2d4fSBlue Swirl     QTAILQ_ENTRY(vm_area_struct) vma_link;
2030edf8e2afSMika Westerberg };
2031edf8e2afSMika Westerberg 
2032edf8e2afSMika Westerberg struct mm_struct {
203372cf2d4fSBlue Swirl     QTAILQ_HEAD(, vm_area_struct) mm_mmap;
2034edf8e2afSMika Westerberg     int mm_count;           /* number of mappings */
2035edf8e2afSMika Westerberg };
2036edf8e2afSMika Westerberg 
2037edf8e2afSMika Westerberg static struct mm_struct *vma_init(void);
2038edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *);
2039edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *, abi_ulong,
2040edf8e2afSMika Westerberg                            abi_ulong, abi_ulong);
2041edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *);
2042edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *);
2043edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *);
2044edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *);
2045b480d9b7SPaul Brook static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
2046edf8e2afSMika Westerberg                       unsigned long flags);
2047edf8e2afSMika Westerberg 
2048edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
2049edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int,
2050edf8e2afSMika Westerberg                       unsigned int, void *);
2051a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
2052a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
2053edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *);
2054edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
2055edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *);
2056edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *);
2057edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *, long, const CPUState *);
2058edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *, const CPUState *);
2059edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t);
2060edf8e2afSMika Westerberg 
2061edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t);
2062edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int);
2063edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int);
2064edf8e2afSMika Westerberg 
2065edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
2066a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus)
2067edf8e2afSMika Westerberg {
2068edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo);
2069edf8e2afSMika Westerberg     prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code);
2070edf8e2afSMika Westerberg     prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno);
2071edf8e2afSMika Westerberg     prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
2072edf8e2afSMika Westerberg     prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend);
2073edf8e2afSMika Westerberg     prstatus->pr_sighold = tswapl(prstatus->pr_sighold);
2074edf8e2afSMika Westerberg     prstatus->pr_pid = tswap32(prstatus->pr_pid);
2075edf8e2afSMika Westerberg     prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
2076edf8e2afSMika Westerberg     prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
2077edf8e2afSMika Westerberg     prstatus->pr_sid = tswap32(prstatus->pr_sid);
2078edf8e2afSMika Westerberg     /* cpu times are not filled, so we skip them */
2079edf8e2afSMika Westerberg     /* regs should be in correct format already */
2080edf8e2afSMika Westerberg     prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
2081edf8e2afSMika Westerberg }
2082edf8e2afSMika Westerberg 
2083a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
2084edf8e2afSMika Westerberg {
2085edf8e2afSMika Westerberg     psinfo->pr_flag = tswapl(psinfo->pr_flag);
2086edf8e2afSMika Westerberg     psinfo->pr_uid = tswap16(psinfo->pr_uid);
2087edf8e2afSMika Westerberg     psinfo->pr_gid = tswap16(psinfo->pr_gid);
2088edf8e2afSMika Westerberg     psinfo->pr_pid = tswap32(psinfo->pr_pid);
2089edf8e2afSMika Westerberg     psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
2090edf8e2afSMika Westerberg     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
2091edf8e2afSMika Westerberg     psinfo->pr_sid = tswap32(psinfo->pr_sid);
2092edf8e2afSMika Westerberg }
2093991f8f0cSRichard Henderson 
2094991f8f0cSRichard Henderson static void bswap_note(struct elf_note *en)
2095991f8f0cSRichard Henderson {
2096991f8f0cSRichard Henderson     bswap32s(&en->n_namesz);
2097991f8f0cSRichard Henderson     bswap32s(&en->n_descsz);
2098991f8f0cSRichard Henderson     bswap32s(&en->n_type);
2099991f8f0cSRichard Henderson }
2100991f8f0cSRichard Henderson #else
2101991f8f0cSRichard Henderson static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
2102991f8f0cSRichard Henderson static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
2103991f8f0cSRichard Henderson static inline void bswap_note(struct elf_note *en) { }
2104edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
2105edf8e2afSMika Westerberg 
2106edf8e2afSMika Westerberg /*
2107edf8e2afSMika Westerberg  * Minimal support for linux memory regions.  These are needed
2108edf8e2afSMika Westerberg  * when we are finding out what memory exactly belongs to
2109edf8e2afSMika Westerberg  * emulated process.  No locks needed here, as long as
2110edf8e2afSMika Westerberg  * thread that received the signal is stopped.
2111edf8e2afSMika Westerberg  */
2112edf8e2afSMika Westerberg 
2113edf8e2afSMika Westerberg static struct mm_struct *vma_init(void)
2114edf8e2afSMika Westerberg {
2115edf8e2afSMika Westerberg     struct mm_struct *mm;
2116edf8e2afSMika Westerberg 
21177267c094SAnthony Liguori     if ((mm = g_malloc(sizeof (*mm))) == NULL)
2118edf8e2afSMika Westerberg         return (NULL);
2119edf8e2afSMika Westerberg 
2120edf8e2afSMika Westerberg     mm->mm_count = 0;
212172cf2d4fSBlue Swirl     QTAILQ_INIT(&mm->mm_mmap);
2122edf8e2afSMika Westerberg 
2123edf8e2afSMika Westerberg     return (mm);
2124edf8e2afSMika Westerberg }
2125edf8e2afSMika Westerberg 
2126edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm)
2127edf8e2afSMika Westerberg {
2128edf8e2afSMika Westerberg     struct vm_area_struct *vma;
2129edf8e2afSMika Westerberg 
2130edf8e2afSMika Westerberg     while ((vma = vma_first(mm)) != NULL) {
213172cf2d4fSBlue Swirl         QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
21327267c094SAnthony Liguori         g_free(vma);
2133edf8e2afSMika Westerberg     }
21347267c094SAnthony Liguori     g_free(mm);
2135edf8e2afSMika Westerberg }
2136edf8e2afSMika Westerberg 
2137edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *mm, abi_ulong start,
2138edf8e2afSMika Westerberg                            abi_ulong end, abi_ulong flags)
2139edf8e2afSMika Westerberg {
2140edf8e2afSMika Westerberg     struct vm_area_struct *vma;
2141edf8e2afSMika Westerberg 
21427267c094SAnthony Liguori     if ((vma = g_malloc0(sizeof (*vma))) == NULL)
2143edf8e2afSMika Westerberg         return (-1);
2144edf8e2afSMika Westerberg 
2145edf8e2afSMika Westerberg     vma->vma_start = start;
2146edf8e2afSMika Westerberg     vma->vma_end = end;
2147edf8e2afSMika Westerberg     vma->vma_flags = flags;
2148edf8e2afSMika Westerberg 
214972cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
2150edf8e2afSMika Westerberg     mm->mm_count++;
2151edf8e2afSMika Westerberg 
2152edf8e2afSMika Westerberg     return (0);
2153edf8e2afSMika Westerberg }
2154edf8e2afSMika Westerberg 
2155edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm)
2156edf8e2afSMika Westerberg {
215772cf2d4fSBlue Swirl     return (QTAILQ_FIRST(&mm->mm_mmap));
2158edf8e2afSMika Westerberg }
2159edf8e2afSMika Westerberg 
2160edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
2161edf8e2afSMika Westerberg {
216272cf2d4fSBlue Swirl     return (QTAILQ_NEXT(vma, vma_link));
2163edf8e2afSMika Westerberg }
2164edf8e2afSMika Westerberg 
2165edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm)
2166edf8e2afSMika Westerberg {
2167edf8e2afSMika Westerberg     return (mm->mm_count);
2168edf8e2afSMika Westerberg }
2169edf8e2afSMika Westerberg 
2170edf8e2afSMika Westerberg /*
2171edf8e2afSMika Westerberg  * Calculate file (dump) size of given memory region.
2172edf8e2afSMika Westerberg  */
2173edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
2174edf8e2afSMika Westerberg {
2175edf8e2afSMika Westerberg     /* if we cannot even read the first page, skip it */
2176edf8e2afSMika Westerberg     if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
2177edf8e2afSMika Westerberg         return (0);
2178edf8e2afSMika Westerberg 
2179edf8e2afSMika Westerberg     /*
2180edf8e2afSMika Westerberg      * Usually we don't dump executable pages as they contain
2181edf8e2afSMika Westerberg      * non-writable code that debugger can read directly from
2182edf8e2afSMika Westerberg      * target library etc.  However, thread stacks are marked
2183edf8e2afSMika Westerberg      * also executable so we read in first page of given region
2184edf8e2afSMika Westerberg      * and check whether it contains elf header.  If there is
2185edf8e2afSMika Westerberg      * no elf header, we dump it.
2186edf8e2afSMika Westerberg      */
2187edf8e2afSMika Westerberg     if (vma->vma_flags & PROT_EXEC) {
2188edf8e2afSMika Westerberg         char page[TARGET_PAGE_SIZE];
2189edf8e2afSMika Westerberg 
2190edf8e2afSMika Westerberg         copy_from_user(page, vma->vma_start, sizeof (page));
2191edf8e2afSMika Westerberg         if ((page[EI_MAG0] == ELFMAG0) &&
2192edf8e2afSMika Westerberg             (page[EI_MAG1] == ELFMAG1) &&
2193edf8e2afSMika Westerberg             (page[EI_MAG2] == ELFMAG2) &&
2194edf8e2afSMika Westerberg             (page[EI_MAG3] == ELFMAG3)) {
2195edf8e2afSMika Westerberg             /*
2196edf8e2afSMika Westerberg              * Mappings are possibly from ELF binary.  Don't dump
2197edf8e2afSMika Westerberg              * them.
2198edf8e2afSMika Westerberg              */
2199edf8e2afSMika Westerberg             return (0);
2200edf8e2afSMika Westerberg         }
2201edf8e2afSMika Westerberg     }
2202edf8e2afSMika Westerberg 
2203edf8e2afSMika Westerberg     return (vma->vma_end - vma->vma_start);
2204edf8e2afSMika Westerberg }
2205edf8e2afSMika Westerberg 
2206b480d9b7SPaul Brook static int vma_walker(void *priv, abi_ulong start, abi_ulong end,
2207edf8e2afSMika Westerberg                       unsigned long flags)
2208edf8e2afSMika Westerberg {
2209edf8e2afSMika Westerberg     struct mm_struct *mm = (struct mm_struct *)priv;
2210edf8e2afSMika Westerberg 
2211edf8e2afSMika Westerberg     vma_add_mapping(mm, start, end, flags);
2212edf8e2afSMika Westerberg     return (0);
2213edf8e2afSMika Westerberg }
2214edf8e2afSMika Westerberg 
2215edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type,
2216edf8e2afSMika Westerberg                       unsigned int sz, void *data)
2217edf8e2afSMika Westerberg {
2218edf8e2afSMika Westerberg     unsigned int namesz;
2219edf8e2afSMika Westerberg 
2220edf8e2afSMika Westerberg     namesz = strlen(name) + 1;
2221edf8e2afSMika Westerberg     note->name = name;
2222edf8e2afSMika Westerberg     note->namesz = namesz;
2223edf8e2afSMika Westerberg     note->namesz_rounded = roundup(namesz, sizeof (int32_t));
2224edf8e2afSMika Westerberg     note->type = type;
222580f5ce75SLaurent Vivier     note->datasz = sz;
222680f5ce75SLaurent Vivier     note->datasz_rounded = roundup(sz, sizeof (int32_t));
222780f5ce75SLaurent Vivier 
2228edf8e2afSMika Westerberg     note->data = data;
2229edf8e2afSMika Westerberg 
2230edf8e2afSMika Westerberg     /*
2231edf8e2afSMika Westerberg      * We calculate rounded up note size here as specified by
2232edf8e2afSMika Westerberg      * ELF document.
2233edf8e2afSMika Westerberg      */
2234edf8e2afSMika Westerberg     note->notesz = sizeof (struct elf_note) +
223580f5ce75SLaurent Vivier         note->namesz_rounded + note->datasz_rounded;
2236edf8e2afSMika Westerberg }
2237edf8e2afSMika Westerberg 
2238edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
2239edf8e2afSMika Westerberg                             uint32_t flags)
2240edf8e2afSMika Westerberg {
2241edf8e2afSMika Westerberg     (void) memset(elf, 0, sizeof(*elf));
2242edf8e2afSMika Westerberg 
2243edf8e2afSMika Westerberg     (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
2244edf8e2afSMika Westerberg     elf->e_ident[EI_CLASS] = ELF_CLASS;
2245edf8e2afSMika Westerberg     elf->e_ident[EI_DATA] = ELF_DATA;
2246edf8e2afSMika Westerberg     elf->e_ident[EI_VERSION] = EV_CURRENT;
2247edf8e2afSMika Westerberg     elf->e_ident[EI_OSABI] = ELF_OSABI;
2248edf8e2afSMika Westerberg 
2249edf8e2afSMika Westerberg     elf->e_type = ET_CORE;
2250edf8e2afSMika Westerberg     elf->e_machine = machine;
2251edf8e2afSMika Westerberg     elf->e_version = EV_CURRENT;
2252edf8e2afSMika Westerberg     elf->e_phoff = sizeof(struct elfhdr);
2253edf8e2afSMika Westerberg     elf->e_flags = flags;
2254edf8e2afSMika Westerberg     elf->e_ehsize = sizeof(struct elfhdr);
2255edf8e2afSMika Westerberg     elf->e_phentsize = sizeof(struct elf_phdr);
2256edf8e2afSMika Westerberg     elf->e_phnum = segs;
2257edf8e2afSMika Westerberg 
2258edf8e2afSMika Westerberg     bswap_ehdr(elf);
2259edf8e2afSMika Westerberg }
2260edf8e2afSMika Westerberg 
2261edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
2262edf8e2afSMika Westerberg {
2263edf8e2afSMika Westerberg     phdr->p_type = PT_NOTE;
2264edf8e2afSMika Westerberg     phdr->p_offset = offset;
2265edf8e2afSMika Westerberg     phdr->p_vaddr = 0;
2266edf8e2afSMika Westerberg     phdr->p_paddr = 0;
2267edf8e2afSMika Westerberg     phdr->p_filesz = sz;
2268edf8e2afSMika Westerberg     phdr->p_memsz = 0;
2269edf8e2afSMika Westerberg     phdr->p_flags = 0;
2270edf8e2afSMika Westerberg     phdr->p_align = 0;
2271edf8e2afSMika Westerberg 
2272991f8f0cSRichard Henderson     bswap_phdr(phdr, 1);
2273edf8e2afSMika Westerberg }
2274edf8e2afSMika Westerberg 
2275edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note)
2276edf8e2afSMika Westerberg {
2277edf8e2afSMika Westerberg     return (note->notesz);
2278edf8e2afSMika Westerberg }
2279edf8e2afSMika Westerberg 
2280a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus,
2281edf8e2afSMika Westerberg                           const TaskState *ts, int signr)
2282edf8e2afSMika Westerberg {
2283edf8e2afSMika Westerberg     (void) memset(prstatus, 0, sizeof (*prstatus));
2284edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
2285edf8e2afSMika Westerberg     prstatus->pr_pid = ts->ts_tid;
2286edf8e2afSMika Westerberg     prstatus->pr_ppid = getppid();
2287edf8e2afSMika Westerberg     prstatus->pr_pgrp = getpgrp();
2288edf8e2afSMika Westerberg     prstatus->pr_sid = getsid(0);
2289edf8e2afSMika Westerberg 
2290edf8e2afSMika Westerberg     bswap_prstatus(prstatus);
2291edf8e2afSMika Westerberg }
2292edf8e2afSMika Westerberg 
2293a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
2294edf8e2afSMika Westerberg {
2295edf8e2afSMika Westerberg     char *filename, *base_filename;
2296edf8e2afSMika Westerberg     unsigned int i, len;
2297edf8e2afSMika Westerberg 
2298edf8e2afSMika Westerberg     (void) memset(psinfo, 0, sizeof (*psinfo));
2299edf8e2afSMika Westerberg 
2300edf8e2afSMika Westerberg     len = ts->info->arg_end - ts->info->arg_start;
2301edf8e2afSMika Westerberg     if (len >= ELF_PRARGSZ)
2302edf8e2afSMika Westerberg         len = ELF_PRARGSZ - 1;
2303edf8e2afSMika Westerberg     if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
2304edf8e2afSMika Westerberg         return -EFAULT;
2305edf8e2afSMika Westerberg     for (i = 0; i < len; i++)
2306edf8e2afSMika Westerberg         if (psinfo->pr_psargs[i] == 0)
2307edf8e2afSMika Westerberg             psinfo->pr_psargs[i] = ' ';
2308edf8e2afSMika Westerberg     psinfo->pr_psargs[len] = 0;
2309edf8e2afSMika Westerberg 
2310edf8e2afSMika Westerberg     psinfo->pr_pid = getpid();
2311edf8e2afSMika Westerberg     psinfo->pr_ppid = getppid();
2312edf8e2afSMika Westerberg     psinfo->pr_pgrp = getpgrp();
2313edf8e2afSMika Westerberg     psinfo->pr_sid = getsid(0);
2314edf8e2afSMika Westerberg     psinfo->pr_uid = getuid();
2315edf8e2afSMika Westerberg     psinfo->pr_gid = getgid();
2316edf8e2afSMika Westerberg 
2317edf8e2afSMika Westerberg     filename = strdup(ts->bprm->filename);
2318edf8e2afSMika Westerberg     base_filename = strdup(basename(filename));
2319edf8e2afSMika Westerberg     (void) strncpy(psinfo->pr_fname, base_filename,
2320edf8e2afSMika Westerberg                    sizeof(psinfo->pr_fname));
2321edf8e2afSMika Westerberg     free(base_filename);
2322edf8e2afSMika Westerberg     free(filename);
2323edf8e2afSMika Westerberg 
2324edf8e2afSMika Westerberg     bswap_psinfo(psinfo);
2325edf8e2afSMika Westerberg     return (0);
2326edf8e2afSMika Westerberg }
2327edf8e2afSMika Westerberg 
2328edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
2329edf8e2afSMika Westerberg {
2330edf8e2afSMika Westerberg     elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
2331edf8e2afSMika Westerberg     elf_addr_t orig_auxv = auxv;
2332edf8e2afSMika Westerberg     abi_ulong val;
2333edf8e2afSMika Westerberg     void *ptr;
2334edf8e2afSMika Westerberg     int i, len;
2335edf8e2afSMika Westerberg 
2336edf8e2afSMika Westerberg     /*
2337edf8e2afSMika Westerberg      * Auxiliary vector is stored in target process stack.  It contains
2338edf8e2afSMika Westerberg      * {type, value} pairs that we need to dump into note.  This is not
2339edf8e2afSMika Westerberg      * strictly necessary but we do it here for sake of completeness.
2340edf8e2afSMika Westerberg      */
2341edf8e2afSMika Westerberg 
2342edf8e2afSMika Westerberg     /* find out lenght of the vector, AT_NULL is terminator */
2343edf8e2afSMika Westerberg     i = len = 0;
2344edf8e2afSMika Westerberg     do {
2345edf8e2afSMika Westerberg         get_user_ual(val, auxv);
2346edf8e2afSMika Westerberg         i += 2;
2347edf8e2afSMika Westerberg         auxv += 2 * sizeof (elf_addr_t);
2348edf8e2afSMika Westerberg     } while (val != AT_NULL);
2349edf8e2afSMika Westerberg     len = i * sizeof (elf_addr_t);
2350edf8e2afSMika Westerberg 
2351edf8e2afSMika Westerberg     /* read in whole auxv vector and copy it to memelfnote */
2352edf8e2afSMika Westerberg     ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
2353edf8e2afSMika Westerberg     if (ptr != NULL) {
2354edf8e2afSMika Westerberg         fill_note(note, "CORE", NT_AUXV, len, ptr);
2355edf8e2afSMika Westerberg         unlock_user(ptr, auxv, len);
2356edf8e2afSMika Westerberg     }
2357edf8e2afSMika Westerberg }
2358edf8e2afSMika Westerberg 
2359edf8e2afSMika Westerberg /*
2360edf8e2afSMika Westerberg  * Constructs name of coredump file.  We have following convention
2361edf8e2afSMika Westerberg  * for the name:
2362edf8e2afSMika Westerberg  *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
2363edf8e2afSMika Westerberg  *
2364edf8e2afSMika Westerberg  * Returns 0 in case of success, -1 otherwise (errno is set).
2365edf8e2afSMika Westerberg  */
2366edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf,
2367edf8e2afSMika Westerberg                               size_t bufsize)
2368edf8e2afSMika Westerberg {
2369edf8e2afSMika Westerberg     char timestamp[64];
2370edf8e2afSMika Westerberg     char *filename = NULL;
2371edf8e2afSMika Westerberg     char *base_filename = NULL;
2372edf8e2afSMika Westerberg     struct timeval tv;
2373edf8e2afSMika Westerberg     struct tm tm;
2374edf8e2afSMika Westerberg 
2375edf8e2afSMika Westerberg     assert(bufsize >= PATH_MAX);
2376edf8e2afSMika Westerberg 
2377edf8e2afSMika Westerberg     if (gettimeofday(&tv, NULL) < 0) {
2378edf8e2afSMika Westerberg         (void) fprintf(stderr, "unable to get current timestamp: %s",
2379edf8e2afSMika Westerberg                        strerror(errno));
2380edf8e2afSMika Westerberg         return (-1);
2381edf8e2afSMika Westerberg     }
2382edf8e2afSMika Westerberg 
2383edf8e2afSMika Westerberg     filename = strdup(ts->bprm->filename);
2384edf8e2afSMika Westerberg     base_filename = strdup(basename(filename));
2385edf8e2afSMika Westerberg     (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
2386edf8e2afSMika Westerberg                     localtime_r(&tv.tv_sec, &tm));
2387edf8e2afSMika Westerberg     (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
2388edf8e2afSMika Westerberg                     base_filename, timestamp, (int)getpid());
2389edf8e2afSMika Westerberg     free(base_filename);
2390edf8e2afSMika Westerberg     free(filename);
2391edf8e2afSMika Westerberg 
2392edf8e2afSMika Westerberg     return (0);
2393edf8e2afSMika Westerberg }
2394edf8e2afSMika Westerberg 
2395edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size)
2396edf8e2afSMika Westerberg {
2397edf8e2afSMika Westerberg     const char *bufp = (const char *)ptr;
2398edf8e2afSMika Westerberg     ssize_t bytes_written, bytes_left;
2399edf8e2afSMika Westerberg     struct rlimit dumpsize;
2400edf8e2afSMika Westerberg     off_t pos;
2401edf8e2afSMika Westerberg 
2402edf8e2afSMika Westerberg     bytes_written = 0;
2403edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
2404edf8e2afSMika Westerberg     if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
2405edf8e2afSMika Westerberg         if (errno == ESPIPE) { /* not a seekable stream */
2406edf8e2afSMika Westerberg             bytes_left = size;
2407edf8e2afSMika Westerberg         } else {
2408edf8e2afSMika Westerberg             return pos;
2409edf8e2afSMika Westerberg         }
2410edf8e2afSMika Westerberg     } else {
2411edf8e2afSMika Westerberg         if (dumpsize.rlim_cur <= pos) {
2412edf8e2afSMika Westerberg             return -1;
2413edf8e2afSMika Westerberg         } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
2414edf8e2afSMika Westerberg             bytes_left = size;
2415edf8e2afSMika Westerberg         } else {
2416edf8e2afSMika Westerberg             size_t limit_left=dumpsize.rlim_cur - pos;
2417edf8e2afSMika Westerberg             bytes_left = limit_left >= size ? size : limit_left ;
2418edf8e2afSMika Westerberg         }
2419edf8e2afSMika Westerberg     }
2420edf8e2afSMika Westerberg 
2421edf8e2afSMika Westerberg     /*
2422edf8e2afSMika Westerberg      * In normal conditions, single write(2) should do but
2423edf8e2afSMika Westerberg      * in case of socket etc. this mechanism is more portable.
2424edf8e2afSMika Westerberg      */
2425edf8e2afSMika Westerberg     do {
2426edf8e2afSMika Westerberg         bytes_written = write(fd, bufp, bytes_left);
2427edf8e2afSMika Westerberg         if (bytes_written < 0) {
2428edf8e2afSMika Westerberg             if (errno == EINTR)
2429edf8e2afSMika Westerberg                 continue;
2430edf8e2afSMika Westerberg             return (-1);
2431edf8e2afSMika Westerberg         } else if (bytes_written == 0) { /* eof */
2432edf8e2afSMika Westerberg             return (-1);
2433edf8e2afSMika Westerberg         }
2434edf8e2afSMika Westerberg         bufp += bytes_written;
2435edf8e2afSMika Westerberg         bytes_left -= bytes_written;
2436edf8e2afSMika Westerberg     } while (bytes_left > 0);
2437edf8e2afSMika Westerberg 
2438edf8e2afSMika Westerberg     return (0);
2439edf8e2afSMika Westerberg }
2440edf8e2afSMika Westerberg 
2441edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd)
2442edf8e2afSMika Westerberg {
2443edf8e2afSMika Westerberg     struct elf_note en;
2444edf8e2afSMika Westerberg 
2445edf8e2afSMika Westerberg     en.n_namesz = men->namesz;
2446edf8e2afSMika Westerberg     en.n_type = men->type;
2447edf8e2afSMika Westerberg     en.n_descsz = men->datasz;
2448edf8e2afSMika Westerberg 
2449edf8e2afSMika Westerberg     bswap_note(&en);
2450edf8e2afSMika Westerberg 
2451edf8e2afSMika Westerberg     if (dump_write(fd, &en, sizeof(en)) != 0)
2452edf8e2afSMika Westerberg         return (-1);
2453edf8e2afSMika Westerberg     if (dump_write(fd, men->name, men->namesz_rounded) != 0)
2454edf8e2afSMika Westerberg         return (-1);
245580f5ce75SLaurent Vivier     if (dump_write(fd, men->data, men->datasz_rounded) != 0)
2456edf8e2afSMika Westerberg         return (-1);
2457edf8e2afSMika Westerberg 
2458edf8e2afSMika Westerberg     return (0);
2459edf8e2afSMika Westerberg }
2460edf8e2afSMika Westerberg 
2461edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *info, const CPUState *env)
2462edf8e2afSMika Westerberg {
2463edf8e2afSMika Westerberg     TaskState *ts = (TaskState *)env->opaque;
2464edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2465edf8e2afSMika Westerberg 
24667267c094SAnthony Liguori     ets = g_malloc0(sizeof (*ets));
2467edf8e2afSMika Westerberg     ets->num_notes = 1; /* only prstatus is dumped */
2468edf8e2afSMika Westerberg     fill_prstatus(&ets->prstatus, ts, 0);
2469edf8e2afSMika Westerberg     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
2470edf8e2afSMika Westerberg     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
2471edf8e2afSMika Westerberg               &ets->prstatus);
2472edf8e2afSMika Westerberg 
247372cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
2474edf8e2afSMika Westerberg 
2475edf8e2afSMika Westerberg     info->notes_size += note_size(&ets->notes[0]);
2476edf8e2afSMika Westerberg }
2477edf8e2afSMika Westerberg 
2478edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info,
2479edf8e2afSMika Westerberg                           long signr, const CPUState *env)
2480edf8e2afSMika Westerberg {
2481edf8e2afSMika Westerberg #define NUMNOTES 3
2482edf8e2afSMika Westerberg     CPUState *cpu = NULL;
2483edf8e2afSMika Westerberg     TaskState *ts = (TaskState *)env->opaque;
2484edf8e2afSMika Westerberg     int i;
2485edf8e2afSMika Westerberg 
2486edf8e2afSMika Westerberg     (void) memset(info, 0, sizeof (*info));
2487edf8e2afSMika Westerberg 
248872cf2d4fSBlue Swirl     QTAILQ_INIT(&info->thread_list);
2489edf8e2afSMika Westerberg 
24907267c094SAnthony Liguori     info->notes = g_malloc0(NUMNOTES * sizeof (struct memelfnote));
2491edf8e2afSMika Westerberg     if (info->notes == NULL)
2492edf8e2afSMika Westerberg         return (-ENOMEM);
24937267c094SAnthony Liguori     info->prstatus = g_malloc0(sizeof (*info->prstatus));
2494edf8e2afSMika Westerberg     if (info->prstatus == NULL)
2495edf8e2afSMika Westerberg         return (-ENOMEM);
24967267c094SAnthony Liguori     info->psinfo = g_malloc0(sizeof (*info->psinfo));
2497edf8e2afSMika Westerberg     if (info->prstatus == NULL)
2498edf8e2afSMika Westerberg         return (-ENOMEM);
2499edf8e2afSMika Westerberg 
2500edf8e2afSMika Westerberg     /*
2501edf8e2afSMika Westerberg      * First fill in status (and registers) of current thread
2502edf8e2afSMika Westerberg      * including process info & aux vector.
2503edf8e2afSMika Westerberg      */
2504edf8e2afSMika Westerberg     fill_prstatus(info->prstatus, ts, signr);
2505edf8e2afSMika Westerberg     elf_core_copy_regs(&info->prstatus->pr_reg, env);
2506edf8e2afSMika Westerberg     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
2507edf8e2afSMika Westerberg               sizeof (*info->prstatus), info->prstatus);
2508edf8e2afSMika Westerberg     fill_psinfo(info->psinfo, ts);
2509edf8e2afSMika Westerberg     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
2510edf8e2afSMika Westerberg               sizeof (*info->psinfo), info->psinfo);
2511edf8e2afSMika Westerberg     fill_auxv_note(&info->notes[2], ts);
2512edf8e2afSMika Westerberg     info->numnote = 3;
2513edf8e2afSMika Westerberg 
2514edf8e2afSMika Westerberg     info->notes_size = 0;
2515edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
2516edf8e2afSMika Westerberg         info->notes_size += note_size(&info->notes[i]);
2517edf8e2afSMika Westerberg 
2518edf8e2afSMika Westerberg     /* read and fill status of all threads */
2519edf8e2afSMika Westerberg     cpu_list_lock();
2520edf8e2afSMika Westerberg     for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) {
2521edf8e2afSMika Westerberg         if (cpu == thread_env)
2522edf8e2afSMika Westerberg             continue;
2523edf8e2afSMika Westerberg         fill_thread_info(info, cpu);
2524edf8e2afSMika Westerberg     }
2525edf8e2afSMika Westerberg     cpu_list_unlock();
2526edf8e2afSMika Westerberg 
2527edf8e2afSMika Westerberg     return (0);
2528edf8e2afSMika Westerberg }
2529edf8e2afSMika Westerberg 
2530edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info)
2531edf8e2afSMika Westerberg {
2532edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2533edf8e2afSMika Westerberg 
253472cf2d4fSBlue Swirl     while (!QTAILQ_EMPTY(&info->thread_list)) {
253572cf2d4fSBlue Swirl         ets = QTAILQ_FIRST(&info->thread_list);
253672cf2d4fSBlue Swirl         QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
25377267c094SAnthony Liguori         g_free(ets);
2538edf8e2afSMika Westerberg     }
2539edf8e2afSMika Westerberg 
25407267c094SAnthony Liguori     g_free(info->prstatus);
25417267c094SAnthony Liguori     g_free(info->psinfo);
25427267c094SAnthony Liguori     g_free(info->notes);
2543edf8e2afSMika Westerberg }
2544edf8e2afSMika Westerberg 
2545edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd)
2546edf8e2afSMika Westerberg {
2547edf8e2afSMika Westerberg     struct elf_thread_status *ets;
2548edf8e2afSMika Westerberg     int i, error = 0;
2549edf8e2afSMika Westerberg 
2550edf8e2afSMika Westerberg     /* write prstatus, psinfo and auxv for current thread */
2551edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
2552edf8e2afSMika Westerberg         if ((error = write_note(&info->notes[i], fd)) != 0)
2553edf8e2afSMika Westerberg             return (error);
2554edf8e2afSMika Westerberg 
2555edf8e2afSMika Westerberg     /* write prstatus for each thread */
2556edf8e2afSMika Westerberg     for (ets = info->thread_list.tqh_first; ets != NULL;
2557edf8e2afSMika Westerberg          ets = ets->ets_link.tqe_next) {
2558edf8e2afSMika Westerberg         if ((error = write_note(&ets->notes[0], fd)) != 0)
2559edf8e2afSMika Westerberg             return (error);
2560edf8e2afSMika Westerberg     }
2561edf8e2afSMika Westerberg 
2562edf8e2afSMika Westerberg     return (0);
2563edf8e2afSMika Westerberg }
2564edf8e2afSMika Westerberg 
2565edf8e2afSMika Westerberg /*
2566edf8e2afSMika Westerberg  * Write out ELF coredump.
2567edf8e2afSMika Westerberg  *
2568edf8e2afSMika Westerberg  * See documentation of ELF object file format in:
2569edf8e2afSMika Westerberg  * http://www.caldera.com/developers/devspecs/gabi41.pdf
2570edf8e2afSMika Westerberg  *
2571edf8e2afSMika Westerberg  * Coredump format in linux is following:
2572edf8e2afSMika Westerberg  *
2573edf8e2afSMika Westerberg  * 0   +----------------------+         \
2574edf8e2afSMika Westerberg  *     | ELF header           | ET_CORE  |
2575edf8e2afSMika Westerberg  *     +----------------------+          |
2576edf8e2afSMika Westerberg  *     | ELF program headers  |          |--- headers
2577edf8e2afSMika Westerberg  *     | - NOTE section       |          |
2578edf8e2afSMika Westerberg  *     | - PT_LOAD sections   |          |
2579edf8e2afSMika Westerberg  *     +----------------------+         /
2580edf8e2afSMika Westerberg  *     | NOTEs:               |
2581edf8e2afSMika Westerberg  *     | - NT_PRSTATUS        |
2582edf8e2afSMika Westerberg  *     | - NT_PRSINFO         |
2583edf8e2afSMika Westerberg  *     | - NT_AUXV            |
2584edf8e2afSMika Westerberg  *     +----------------------+ <-- aligned to target page
2585edf8e2afSMika Westerberg  *     | Process memory dump  |
2586edf8e2afSMika Westerberg  *     :                      :
2587edf8e2afSMika Westerberg  *     .                      .
2588edf8e2afSMika Westerberg  *     :                      :
2589edf8e2afSMika Westerberg  *     |                      |
2590edf8e2afSMika Westerberg  *     +----------------------+
2591edf8e2afSMika Westerberg  *
2592edf8e2afSMika Westerberg  * NT_PRSTATUS -> struct elf_prstatus (per thread)
2593edf8e2afSMika Westerberg  * NT_PRSINFO  -> struct elf_prpsinfo
2594edf8e2afSMika Westerberg  * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
2595edf8e2afSMika Westerberg  *
2596edf8e2afSMika Westerberg  * Format follows System V format as close as possible.  Current
2597edf8e2afSMika Westerberg  * version limitations are as follows:
2598edf8e2afSMika Westerberg  *     - no floating point registers are dumped
2599edf8e2afSMika Westerberg  *
2600edf8e2afSMika Westerberg  * Function returns 0 in case of success, negative errno otherwise.
2601edf8e2afSMika Westerberg  *
2602edf8e2afSMika Westerberg  * TODO: make this work also during runtime: it should be
2603edf8e2afSMika Westerberg  * possible to force coredump from running process and then
2604edf8e2afSMika Westerberg  * continue processing.  For example qemu could set up SIGUSR2
2605edf8e2afSMika Westerberg  * handler (provided that target process haven't registered
2606edf8e2afSMika Westerberg  * handler for that) that does the dump when signal is received.
2607edf8e2afSMika Westerberg  */
2608edf8e2afSMika Westerberg static int elf_core_dump(int signr, const CPUState *env)
2609edf8e2afSMika Westerberg {
2610edf8e2afSMika Westerberg     const TaskState *ts = (const TaskState *)env->opaque;
2611edf8e2afSMika Westerberg     struct vm_area_struct *vma = NULL;
2612edf8e2afSMika Westerberg     char corefile[PATH_MAX];
2613edf8e2afSMika Westerberg     struct elf_note_info info;
2614edf8e2afSMika Westerberg     struct elfhdr elf;
2615edf8e2afSMika Westerberg     struct elf_phdr phdr;
2616edf8e2afSMika Westerberg     struct rlimit dumpsize;
2617edf8e2afSMika Westerberg     struct mm_struct *mm = NULL;
2618edf8e2afSMika Westerberg     off_t offset = 0, data_offset = 0;
2619edf8e2afSMika Westerberg     int segs = 0;
2620edf8e2afSMika Westerberg     int fd = -1;
2621edf8e2afSMika Westerberg 
2622edf8e2afSMika Westerberg     errno = 0;
2623edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
2624edf8e2afSMika Westerberg     if (dumpsize.rlim_cur == 0)
2625edf8e2afSMika Westerberg         return 0;
2626edf8e2afSMika Westerberg 
2627edf8e2afSMika Westerberg     if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
2628edf8e2afSMika Westerberg         return (-errno);
2629edf8e2afSMika Westerberg 
2630edf8e2afSMika Westerberg     if ((fd = open(corefile, O_WRONLY | O_CREAT,
2631edf8e2afSMika Westerberg                    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
2632edf8e2afSMika Westerberg         return (-errno);
2633edf8e2afSMika Westerberg 
2634edf8e2afSMika Westerberg     /*
2635edf8e2afSMika Westerberg      * Walk through target process memory mappings and
2636edf8e2afSMika Westerberg      * set up structure containing this information.  After
2637edf8e2afSMika Westerberg      * this point vma_xxx functions can be used.
2638edf8e2afSMika Westerberg      */
2639edf8e2afSMika Westerberg     if ((mm = vma_init()) == NULL)
2640edf8e2afSMika Westerberg         goto out;
2641edf8e2afSMika Westerberg 
2642edf8e2afSMika Westerberg     walk_memory_regions(mm, vma_walker);
2643edf8e2afSMika Westerberg     segs = vma_get_mapping_count(mm);
2644edf8e2afSMika Westerberg 
2645edf8e2afSMika Westerberg     /*
2646edf8e2afSMika Westerberg      * Construct valid coredump ELF header.  We also
2647edf8e2afSMika Westerberg      * add one more segment for notes.
2648edf8e2afSMika Westerberg      */
2649edf8e2afSMika Westerberg     fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
2650edf8e2afSMika Westerberg     if (dump_write(fd, &elf, sizeof (elf)) != 0)
2651edf8e2afSMika Westerberg         goto out;
2652edf8e2afSMika Westerberg 
2653edf8e2afSMika Westerberg     /* fill in in-memory version of notes */
2654edf8e2afSMika Westerberg     if (fill_note_info(&info, signr, env) < 0)
2655edf8e2afSMika Westerberg         goto out;
2656edf8e2afSMika Westerberg 
2657edf8e2afSMika Westerberg     offset += sizeof (elf);                             /* elf header */
2658edf8e2afSMika Westerberg     offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */
2659edf8e2afSMika Westerberg 
2660edf8e2afSMika Westerberg     /* write out notes program header */
2661edf8e2afSMika Westerberg     fill_elf_note_phdr(&phdr, info.notes_size, offset);
2662edf8e2afSMika Westerberg 
2663edf8e2afSMika Westerberg     offset += info.notes_size;
2664edf8e2afSMika Westerberg     if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
2665edf8e2afSMika Westerberg         goto out;
2666edf8e2afSMika Westerberg 
2667edf8e2afSMika Westerberg     /*
2668edf8e2afSMika Westerberg      * ELF specification wants data to start at page boundary so
2669edf8e2afSMika Westerberg      * we align it here.
2670edf8e2afSMika Westerberg      */
267180f5ce75SLaurent Vivier     data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
2672edf8e2afSMika Westerberg 
2673edf8e2afSMika Westerberg     /*
2674edf8e2afSMika Westerberg      * Write program headers for memory regions mapped in
2675edf8e2afSMika Westerberg      * the target process.
2676edf8e2afSMika Westerberg      */
2677edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2678edf8e2afSMika Westerberg         (void) memset(&phdr, 0, sizeof (phdr));
2679edf8e2afSMika Westerberg 
2680edf8e2afSMika Westerberg         phdr.p_type = PT_LOAD;
2681edf8e2afSMika Westerberg         phdr.p_offset = offset;
2682edf8e2afSMika Westerberg         phdr.p_vaddr = vma->vma_start;
2683edf8e2afSMika Westerberg         phdr.p_paddr = 0;
2684edf8e2afSMika Westerberg         phdr.p_filesz = vma_dump_size(vma);
2685edf8e2afSMika Westerberg         offset += phdr.p_filesz;
2686edf8e2afSMika Westerberg         phdr.p_memsz = vma->vma_end - vma->vma_start;
2687edf8e2afSMika Westerberg         phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
2688edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_WRITE)
2689edf8e2afSMika Westerberg             phdr.p_flags |= PF_W;
2690edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_EXEC)
2691edf8e2afSMika Westerberg             phdr.p_flags |= PF_X;
2692edf8e2afSMika Westerberg         phdr.p_align = ELF_EXEC_PAGESIZE;
2693edf8e2afSMika Westerberg 
269480f5ce75SLaurent Vivier         bswap_phdr(&phdr, 1);
2695edf8e2afSMika Westerberg         dump_write(fd, &phdr, sizeof (phdr));
2696edf8e2afSMika Westerberg     }
2697edf8e2afSMika Westerberg 
2698edf8e2afSMika Westerberg     /*
2699edf8e2afSMika Westerberg      * Next we write notes just after program headers.  No
2700edf8e2afSMika Westerberg      * alignment needed here.
2701edf8e2afSMika Westerberg      */
2702edf8e2afSMika Westerberg     if (write_note_info(&info, fd) < 0)
2703edf8e2afSMika Westerberg         goto out;
2704edf8e2afSMika Westerberg 
2705edf8e2afSMika Westerberg     /* align data to page boundary */
2706edf8e2afSMika Westerberg     if (lseek(fd, data_offset, SEEK_SET) != data_offset)
2707edf8e2afSMika Westerberg         goto out;
2708edf8e2afSMika Westerberg 
2709edf8e2afSMika Westerberg     /*
2710edf8e2afSMika Westerberg      * Finally we can dump process memory into corefile as well.
2711edf8e2afSMika Westerberg      */
2712edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
2713edf8e2afSMika Westerberg         abi_ulong addr;
2714edf8e2afSMika Westerberg         abi_ulong end;
2715edf8e2afSMika Westerberg 
2716edf8e2afSMika Westerberg         end = vma->vma_start + vma_dump_size(vma);
2717edf8e2afSMika Westerberg 
2718edf8e2afSMika Westerberg         for (addr = vma->vma_start; addr < end;
2719edf8e2afSMika Westerberg              addr += TARGET_PAGE_SIZE) {
2720edf8e2afSMika Westerberg             char page[TARGET_PAGE_SIZE];
2721edf8e2afSMika Westerberg             int error;
2722edf8e2afSMika Westerberg 
2723edf8e2afSMika Westerberg             /*
2724edf8e2afSMika Westerberg              *  Read in page from target process memory and
2725edf8e2afSMika Westerberg              *  write it to coredump file.
2726edf8e2afSMika Westerberg              */
2727edf8e2afSMika Westerberg             error = copy_from_user(page, addr, sizeof (page));
2728edf8e2afSMika Westerberg             if (error != 0) {
272949995e17SAurelien Jarno                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
2730edf8e2afSMika Westerberg                                addr);
2731edf8e2afSMika Westerberg                 errno = -error;
2732edf8e2afSMika Westerberg                 goto out;
2733edf8e2afSMika Westerberg             }
2734edf8e2afSMika Westerberg             if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
2735edf8e2afSMika Westerberg                 goto out;
2736edf8e2afSMika Westerberg         }
2737edf8e2afSMika Westerberg     }
2738edf8e2afSMika Westerberg 
2739edf8e2afSMika Westerberg  out:
2740edf8e2afSMika Westerberg     free_note_info(&info);
2741edf8e2afSMika Westerberg     if (mm != NULL)
2742edf8e2afSMika Westerberg         vma_delete(mm);
2743edf8e2afSMika Westerberg     (void) close(fd);
2744edf8e2afSMika Westerberg 
2745edf8e2afSMika Westerberg     if (errno != 0)
2746edf8e2afSMika Westerberg         return (-errno);
2747edf8e2afSMika Westerberg     return (0);
2748edf8e2afSMika Westerberg }
2749edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
2750edf8e2afSMika Westerberg 
2751e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
2752e5fe0c52Spbrook {
2753e5fe0c52Spbrook     init_thread(regs, infop);
2754e5fe0c52Spbrook }
2755