xref: /qemu/linux-user/elfload.c (revision 1074c0fb9153f631ce93f7e7d74b935fdcb0d82a)
131e31b8aSbellard /* This is the Linux kernel elf-loading code, ported into user space */
2d39594e9SPeter Maydell #include "qemu/osdep.h"
3edf8e2afSMika Westerberg #include <sys/param.h>
431e31b8aSbellard 
5edf8e2afSMika Westerberg #include <sys/resource.h>
630ab9ef2SRichard Henderson #include <sys/shm.h>
731e31b8aSbellard 
83ef693a0Sbellard #include "qemu.h"
976cad711SPaolo Bonzini #include "disas/disas.h"
10f348b6d1SVeronia Bahaa #include "qemu/path.h"
11dc5e9ac7SMarkus Armbruster #include "qemu/queue.h"
12c6a2377fSRichard Henderson #include "qemu/guest-random.h"
136fd59449SRichard Henderson #include "qemu/units.h"
14ee947430SAlex Bennée #include "qemu/selfmap.h"
1531e31b8aSbellard 
16e58ffeb3Smalc #ifdef _ARCH_PPC64
17a6cc84f4Smalc #undef ARCH_DLINFO
18a6cc84f4Smalc #undef ELF_PLATFORM
19a6cc84f4Smalc #undef ELF_HWCAP
20ad6919dcSPeter Maydell #undef ELF_HWCAP2
21a6cc84f4Smalc #undef ELF_CLASS
22a6cc84f4Smalc #undef ELF_DATA
23a6cc84f4Smalc #undef ELF_ARCH
24a6cc84f4Smalc #endif
25a6cc84f4Smalc 
26edf8e2afSMika Westerberg #define ELF_OSABI   ELFOSABI_SYSV
27edf8e2afSMika Westerberg 
28cb33da57Sblueswir1 /* from personality.h */
29cb33da57Sblueswir1 
30cb33da57Sblueswir1 /*
31cb33da57Sblueswir1  * Flags for bug emulation.
32cb33da57Sblueswir1  *
33cb33da57Sblueswir1  * These occupy the top three bytes.
34cb33da57Sblueswir1  */
35cb33da57Sblueswir1 enum {
36cb33da57Sblueswir1     ADDR_NO_RANDOMIZE = 0x0040000,      /* disable randomization of VA space */
37d97ef72eSRichard Henderson     FDPIC_FUNCPTRS =    0x0080000,      /* userspace function ptrs point to
38d97ef72eSRichard Henderson                                            descriptors (signal handling) */
39cb33da57Sblueswir1     MMAP_PAGE_ZERO =    0x0100000,
40cb33da57Sblueswir1     ADDR_COMPAT_LAYOUT = 0x0200000,
41cb33da57Sblueswir1     READ_IMPLIES_EXEC = 0x0400000,
42cb33da57Sblueswir1     ADDR_LIMIT_32BIT =  0x0800000,
43cb33da57Sblueswir1     SHORT_INODE =       0x1000000,
44cb33da57Sblueswir1     WHOLE_SECONDS =     0x2000000,
45cb33da57Sblueswir1     STICKY_TIMEOUTS =   0x4000000,
46cb33da57Sblueswir1     ADDR_LIMIT_3GB =    0x8000000,
47cb33da57Sblueswir1 };
48cb33da57Sblueswir1 
49cb33da57Sblueswir1 /*
50cb33da57Sblueswir1  * Personality types.
51cb33da57Sblueswir1  *
52cb33da57Sblueswir1  * These go in the low byte.  Avoid using the top bit, it will
53cb33da57Sblueswir1  * conflict with error returns.
54cb33da57Sblueswir1  */
55cb33da57Sblueswir1 enum {
56cb33da57Sblueswir1     PER_LINUX =         0x0000,
57cb33da57Sblueswir1     PER_LINUX_32BIT =   0x0000 | ADDR_LIMIT_32BIT,
58cb33da57Sblueswir1     PER_LINUX_FDPIC =   0x0000 | FDPIC_FUNCPTRS,
59cb33da57Sblueswir1     PER_SVR4 =          0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
60cb33da57Sblueswir1     PER_SVR3 =          0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
61d97ef72eSRichard Henderson     PER_SCOSVR3 =       0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
62cb33da57Sblueswir1     PER_OSR5 =          0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
63cb33da57Sblueswir1     PER_WYSEV386 =      0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
64cb33da57Sblueswir1     PER_ISCR4 =         0x0005 | STICKY_TIMEOUTS,
65cb33da57Sblueswir1     PER_BSD =           0x0006,
66cb33da57Sblueswir1     PER_SUNOS =         0x0006 | STICKY_TIMEOUTS,
67cb33da57Sblueswir1     PER_XENIX =         0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
68cb33da57Sblueswir1     PER_LINUX32 =       0x0008,
69cb33da57Sblueswir1     PER_LINUX32_3GB =   0x0008 | ADDR_LIMIT_3GB,
70cb33da57Sblueswir1     PER_IRIX32 =        0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
71cb33da57Sblueswir1     PER_IRIXN32 =       0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
72cb33da57Sblueswir1     PER_IRIX64 =        0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
73cb33da57Sblueswir1     PER_RISCOS =        0x000c,
74cb33da57Sblueswir1     PER_SOLARIS =       0x000d | STICKY_TIMEOUTS,
75cb33da57Sblueswir1     PER_UW7 =           0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
76cb33da57Sblueswir1     PER_OSF4 =          0x000f,                  /* OSF/1 v4 */
77cb33da57Sblueswir1     PER_HPUX =          0x0010,
78cb33da57Sblueswir1     PER_MASK =          0x00ff,
79cb33da57Sblueswir1 };
80cb33da57Sblueswir1 
81cb33da57Sblueswir1 /*
82cb33da57Sblueswir1  * Return the base personality without flags.
83cb33da57Sblueswir1  */
84cb33da57Sblueswir1 #define personality(pers)       (pers & PER_MASK)
85cb33da57Sblueswir1 
863cb10cfaSChristophe Lyon int info_is_fdpic(struct image_info *info)
873cb10cfaSChristophe Lyon {
883cb10cfaSChristophe Lyon     return info->personality == PER_LINUX_FDPIC;
893cb10cfaSChristophe Lyon }
903cb10cfaSChristophe Lyon 
9183fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */
9283fb7adfSbellard #ifndef MAP_DENYWRITE
9383fb7adfSbellard #define MAP_DENYWRITE 0
9483fb7adfSbellard #endif
9583fb7adfSbellard 
9683fb7adfSbellard /* should probably go in elf.h */
9783fb7adfSbellard #ifndef ELIBBAD
9883fb7adfSbellard #define ELIBBAD 80
9983fb7adfSbellard #endif
10083fb7adfSbellard 
10128490231SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN
10228490231SRichard Henderson #define ELF_DATA        ELFDATA2MSB
10328490231SRichard Henderson #else
10428490231SRichard Henderson #define ELF_DATA        ELFDATA2LSB
10528490231SRichard Henderson #endif
10628490231SRichard Henderson 
107a29f998dSPaolo Bonzini #ifdef TARGET_ABI_MIPSN32
108918fc54cSPaolo Bonzini typedef abi_ullong      target_elf_greg_t;
109918fc54cSPaolo Bonzini #define tswapreg(ptr)   tswap64(ptr)
110a29f998dSPaolo Bonzini #else
111a29f998dSPaolo Bonzini typedef abi_ulong       target_elf_greg_t;
112a29f998dSPaolo Bonzini #define tswapreg(ptr)   tswapal(ptr)
113a29f998dSPaolo Bonzini #endif
114a29f998dSPaolo Bonzini 
11521e807faSNathan Froyd #ifdef USE_UID16
1161ddd592fSPaolo Bonzini typedef abi_ushort      target_uid_t;
1171ddd592fSPaolo Bonzini typedef abi_ushort      target_gid_t;
11821e807faSNathan Froyd #else
119f8fd4fc4SPaolo Bonzini typedef abi_uint        target_uid_t;
120f8fd4fc4SPaolo Bonzini typedef abi_uint        target_gid_t;
12121e807faSNathan Froyd #endif
122f8fd4fc4SPaolo Bonzini typedef abi_int         target_pid_t;
12321e807faSNathan Froyd 
12430ac07d4Sbellard #ifdef TARGET_I386
12530ac07d4Sbellard 
12615338fd7Sbellard #define ELF_PLATFORM get_elf_platform()
12715338fd7Sbellard 
12815338fd7Sbellard static const char *get_elf_platform(void)
12915338fd7Sbellard {
13015338fd7Sbellard     static char elf_platform[] = "i386";
131a2247f8eSAndreas Färber     int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
13215338fd7Sbellard     if (family > 6)
13315338fd7Sbellard         family = 6;
13415338fd7Sbellard     if (family >= 3)
13515338fd7Sbellard         elf_platform[1] = '0' + family;
13615338fd7Sbellard     return elf_platform;
13715338fd7Sbellard }
13815338fd7Sbellard 
13915338fd7Sbellard #define ELF_HWCAP get_elf_hwcap()
14015338fd7Sbellard 
14115338fd7Sbellard static uint32_t get_elf_hwcap(void)
14215338fd7Sbellard {
143a2247f8eSAndreas Färber     X86CPU *cpu = X86_CPU(thread_cpu);
144a2247f8eSAndreas Färber 
145a2247f8eSAndreas Färber     return cpu->env.features[FEAT_1_EDX];
14615338fd7Sbellard }
14715338fd7Sbellard 
14884409ddbSj_mayer #ifdef TARGET_X86_64
14984409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL
15084409ddbSj_mayer 
15184409ddbSj_mayer #define ELF_CLASS      ELFCLASS64
15284409ddbSj_mayer #define ELF_ARCH       EM_X86_64
15384409ddbSj_mayer 
15484409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
15584409ddbSj_mayer {
15684409ddbSj_mayer     regs->rax = 0;
15784409ddbSj_mayer     regs->rsp = infop->start_stack;
15884409ddbSj_mayer     regs->rip = infop->entry;
15984409ddbSj_mayer }
16084409ddbSj_mayer 
1619edc5d79SMika Westerberg #define ELF_NREG    27
162c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
1639edc5d79SMika Westerberg 
1649edc5d79SMika Westerberg /*
1659edc5d79SMika Westerberg  * Note that ELF_NREG should be 29 as there should be place for
1669edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
1679edc5d79SMika Westerberg  * those.
1689edc5d79SMika Westerberg  *
1699edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
1709edc5d79SMika Westerberg  */
17105390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
1729edc5d79SMika Westerberg {
1739edc5d79SMika Westerberg     (*regs)[0] = env->regs[15];
1749edc5d79SMika Westerberg     (*regs)[1] = env->regs[14];
1759edc5d79SMika Westerberg     (*regs)[2] = env->regs[13];
1769edc5d79SMika Westerberg     (*regs)[3] = env->regs[12];
1779edc5d79SMika Westerberg     (*regs)[4] = env->regs[R_EBP];
1789edc5d79SMika Westerberg     (*regs)[5] = env->regs[R_EBX];
1799edc5d79SMika Westerberg     (*regs)[6] = env->regs[11];
1809edc5d79SMika Westerberg     (*regs)[7] = env->regs[10];
1819edc5d79SMika Westerberg     (*regs)[8] = env->regs[9];
1829edc5d79SMika Westerberg     (*regs)[9] = env->regs[8];
1839edc5d79SMika Westerberg     (*regs)[10] = env->regs[R_EAX];
1849edc5d79SMika Westerberg     (*regs)[11] = env->regs[R_ECX];
1859edc5d79SMika Westerberg     (*regs)[12] = env->regs[R_EDX];
1869edc5d79SMika Westerberg     (*regs)[13] = env->regs[R_ESI];
1879edc5d79SMika Westerberg     (*regs)[14] = env->regs[R_EDI];
1889edc5d79SMika Westerberg     (*regs)[15] = env->regs[R_EAX]; /* XXX */
1899edc5d79SMika Westerberg     (*regs)[16] = env->eip;
1909edc5d79SMika Westerberg     (*regs)[17] = env->segs[R_CS].selector & 0xffff;
1919edc5d79SMika Westerberg     (*regs)[18] = env->eflags;
1929edc5d79SMika Westerberg     (*regs)[19] = env->regs[R_ESP];
1939edc5d79SMika Westerberg     (*regs)[20] = env->segs[R_SS].selector & 0xffff;
1949edc5d79SMika Westerberg     (*regs)[21] = env->segs[R_FS].selector & 0xffff;
1959edc5d79SMika Westerberg     (*regs)[22] = env->segs[R_GS].selector & 0xffff;
1969edc5d79SMika Westerberg     (*regs)[23] = env->segs[R_DS].selector & 0xffff;
1979edc5d79SMika Westerberg     (*regs)[24] = env->segs[R_ES].selector & 0xffff;
1989edc5d79SMika Westerberg     (*regs)[25] = env->segs[R_FS].selector & 0xffff;
1999edc5d79SMika Westerberg     (*regs)[26] = env->segs[R_GS].selector & 0xffff;
2009edc5d79SMika Westerberg }
2019edc5d79SMika Westerberg 
20284409ddbSj_mayer #else
20384409ddbSj_mayer 
20430ac07d4Sbellard #define ELF_START_MMAP 0x80000000
20530ac07d4Sbellard 
20630ac07d4Sbellard /*
20730ac07d4Sbellard  * This is used to ensure we don't load something for the wrong architecture.
20830ac07d4Sbellard  */
20930ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
21030ac07d4Sbellard 
21130ac07d4Sbellard /*
21230ac07d4Sbellard  * These are used to set parameters in the core dumps.
21330ac07d4Sbellard  */
21430ac07d4Sbellard #define ELF_CLASS       ELFCLASS32
21530ac07d4Sbellard #define ELF_ARCH        EM_386
21630ac07d4Sbellard 
217d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
218d97ef72eSRichard Henderson                                struct image_info *infop)
219e5fe0c52Spbrook {
220e5fe0c52Spbrook     regs->esp = infop->start_stack;
221e5fe0c52Spbrook     regs->eip = infop->entry;
222e5fe0c52Spbrook 
22330ac07d4Sbellard     /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
22430ac07d4Sbellard        starts %edx contains a pointer to a function which might be
22530ac07d4Sbellard        registered using `atexit'.  This provides a mean for the
22630ac07d4Sbellard        dynamic linker to call DT_FINI functions for shared libraries
22730ac07d4Sbellard        that have been loaded before the code runs.
22830ac07d4Sbellard 
22930ac07d4Sbellard        A value of 0 tells we have no such handler.  */
230e5fe0c52Spbrook     regs->edx = 0;
231b346ff46Sbellard }
2329edc5d79SMika Westerberg 
2339edc5d79SMika Westerberg #define ELF_NREG    17
234c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
2359edc5d79SMika Westerberg 
2369edc5d79SMika Westerberg /*
2379edc5d79SMika Westerberg  * Note that ELF_NREG should be 19 as there should be place for
2389edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
2399edc5d79SMika Westerberg  * those.
2409edc5d79SMika Westerberg  *
2419edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
2429edc5d79SMika Westerberg  */
24305390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
2449edc5d79SMika Westerberg {
2459edc5d79SMika Westerberg     (*regs)[0] = env->regs[R_EBX];
2469edc5d79SMika Westerberg     (*regs)[1] = env->regs[R_ECX];
2479edc5d79SMika Westerberg     (*regs)[2] = env->regs[R_EDX];
2489edc5d79SMika Westerberg     (*regs)[3] = env->regs[R_ESI];
2499edc5d79SMika Westerberg     (*regs)[4] = env->regs[R_EDI];
2509edc5d79SMika Westerberg     (*regs)[5] = env->regs[R_EBP];
2519edc5d79SMika Westerberg     (*regs)[6] = env->regs[R_EAX];
2529edc5d79SMika Westerberg     (*regs)[7] = env->segs[R_DS].selector & 0xffff;
2539edc5d79SMika Westerberg     (*regs)[8] = env->segs[R_ES].selector & 0xffff;
2549edc5d79SMika Westerberg     (*regs)[9] = env->segs[R_FS].selector & 0xffff;
2559edc5d79SMika Westerberg     (*regs)[10] = env->segs[R_GS].selector & 0xffff;
2569edc5d79SMika Westerberg     (*regs)[11] = env->regs[R_EAX]; /* XXX */
2579edc5d79SMika Westerberg     (*regs)[12] = env->eip;
2589edc5d79SMika Westerberg     (*regs)[13] = env->segs[R_CS].selector & 0xffff;
2599edc5d79SMika Westerberg     (*regs)[14] = env->eflags;
2609edc5d79SMika Westerberg     (*regs)[15] = env->regs[R_ESP];
2619edc5d79SMika Westerberg     (*regs)[16] = env->segs[R_SS].selector & 0xffff;
2629edc5d79SMika Westerberg }
26384409ddbSj_mayer #endif
264b346ff46Sbellard 
2659edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP
266b346ff46Sbellard #define ELF_EXEC_PAGESIZE       4096
267b346ff46Sbellard 
268b346ff46Sbellard #endif
269b346ff46Sbellard 
270b346ff46Sbellard #ifdef TARGET_ARM
271b346ff46Sbellard 
27224e76ff0SPeter Maydell #ifndef TARGET_AARCH64
27324e76ff0SPeter Maydell /* 32 bit ARM definitions */
27424e76ff0SPeter Maydell 
275b346ff46Sbellard #define ELF_START_MMAP 0x80000000
276b346ff46Sbellard 
277b597c3f7SPeter Crosthwaite #define ELF_ARCH        EM_ARM
278b346ff46Sbellard #define ELF_CLASS       ELFCLASS32
279b346ff46Sbellard 
280d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
281d97ef72eSRichard Henderson                                struct image_info *infop)
282b346ff46Sbellard {
283992f48a0Sblueswir1     abi_long stack = infop->start_stack;
284b346ff46Sbellard     memset(regs, 0, sizeof(*regs));
28599033caeSAlexander Graf 
286167e4cdcSPeter Maydell     regs->uregs[16] = ARM_CPU_MODE_USR;
287167e4cdcSPeter Maydell     if (infop->entry & 1) {
288167e4cdcSPeter Maydell         regs->uregs[16] |= CPSR_T;
289167e4cdcSPeter Maydell     }
290167e4cdcSPeter Maydell     regs->uregs[15] = infop->entry & 0xfffffffe;
291167e4cdcSPeter Maydell     regs->uregs[13] = infop->start_stack;
2922f619698Sbellard     /* FIXME - what to for failure of get_user()? */
293167e4cdcSPeter Maydell     get_user_ual(regs->uregs[2], stack + 8); /* envp */
294167e4cdcSPeter Maydell     get_user_ual(regs->uregs[1], stack + 4); /* envp */
295a1516e92Sbellard     /* XXX: it seems that r0 is zeroed after ! */
296167e4cdcSPeter Maydell     regs->uregs[0] = 0;
297e5fe0c52Spbrook     /* For uClinux PIC binaries.  */
298863cf0b7Sj_mayer     /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
299167e4cdcSPeter Maydell     regs->uregs[10] = infop->start_data;
3003cb10cfaSChristophe Lyon 
3013cb10cfaSChristophe Lyon     /* Support ARM FDPIC.  */
3023cb10cfaSChristophe Lyon     if (info_is_fdpic(infop)) {
3033cb10cfaSChristophe Lyon         /* As described in the ABI document, r7 points to the loadmap info
3043cb10cfaSChristophe Lyon          * prepared by the kernel. If an interpreter is needed, r8 points
3053cb10cfaSChristophe Lyon          * to the interpreter loadmap and r9 points to the interpreter
3063cb10cfaSChristophe Lyon          * PT_DYNAMIC info. If no interpreter is needed, r8 is zero, and
3073cb10cfaSChristophe Lyon          * r9 points to the main program PT_DYNAMIC info.
3083cb10cfaSChristophe Lyon          */
3093cb10cfaSChristophe Lyon         regs->uregs[7] = infop->loadmap_addr;
3103cb10cfaSChristophe Lyon         if (infop->interpreter_loadmap_addr) {
3113cb10cfaSChristophe Lyon             /* Executable is dynamically loaded.  */
3123cb10cfaSChristophe Lyon             regs->uregs[8] = infop->interpreter_loadmap_addr;
3133cb10cfaSChristophe Lyon             regs->uregs[9] = infop->interpreter_pt_dynamic_addr;
3143cb10cfaSChristophe Lyon         } else {
3153cb10cfaSChristophe Lyon             regs->uregs[8] = 0;
3163cb10cfaSChristophe Lyon             regs->uregs[9] = infop->pt_dynamic_addr;
3173cb10cfaSChristophe Lyon         }
3183cb10cfaSChristophe Lyon     }
319b346ff46Sbellard }
320b346ff46Sbellard 
321edf8e2afSMika Westerberg #define ELF_NREG    18
322c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
323edf8e2afSMika Westerberg 
32405390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env)
325edf8e2afSMika Westerberg {
32686cd7b2dSPaolo Bonzini     (*regs)[0] = tswapreg(env->regs[0]);
32786cd7b2dSPaolo Bonzini     (*regs)[1] = tswapreg(env->regs[1]);
32886cd7b2dSPaolo Bonzini     (*regs)[2] = tswapreg(env->regs[2]);
32986cd7b2dSPaolo Bonzini     (*regs)[3] = tswapreg(env->regs[3]);
33086cd7b2dSPaolo Bonzini     (*regs)[4] = tswapreg(env->regs[4]);
33186cd7b2dSPaolo Bonzini     (*regs)[5] = tswapreg(env->regs[5]);
33286cd7b2dSPaolo Bonzini     (*regs)[6] = tswapreg(env->regs[6]);
33386cd7b2dSPaolo Bonzini     (*regs)[7] = tswapreg(env->regs[7]);
33486cd7b2dSPaolo Bonzini     (*regs)[8] = tswapreg(env->regs[8]);
33586cd7b2dSPaolo Bonzini     (*regs)[9] = tswapreg(env->regs[9]);
33686cd7b2dSPaolo Bonzini     (*regs)[10] = tswapreg(env->regs[10]);
33786cd7b2dSPaolo Bonzini     (*regs)[11] = tswapreg(env->regs[11]);
33886cd7b2dSPaolo Bonzini     (*regs)[12] = tswapreg(env->regs[12]);
33986cd7b2dSPaolo Bonzini     (*regs)[13] = tswapreg(env->regs[13]);
34086cd7b2dSPaolo Bonzini     (*regs)[14] = tswapreg(env->regs[14]);
34186cd7b2dSPaolo Bonzini     (*regs)[15] = tswapreg(env->regs[15]);
342edf8e2afSMika Westerberg 
34386cd7b2dSPaolo Bonzini     (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env));
34486cd7b2dSPaolo Bonzini     (*regs)[17] = tswapreg(env->regs[0]); /* XXX */
345edf8e2afSMika Westerberg }
346edf8e2afSMika Westerberg 
34730ac07d4Sbellard #define USE_ELF_CORE_DUMP
34830ac07d4Sbellard #define ELF_EXEC_PAGESIZE       4096
34930ac07d4Sbellard 
350afce2927Sbellard enum
351afce2927Sbellard {
352afce2927Sbellard     ARM_HWCAP_ARM_SWP       = 1 << 0,
353afce2927Sbellard     ARM_HWCAP_ARM_HALF      = 1 << 1,
354afce2927Sbellard     ARM_HWCAP_ARM_THUMB     = 1 << 2,
355afce2927Sbellard     ARM_HWCAP_ARM_26BIT     = 1 << 3,
356afce2927Sbellard     ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
357afce2927Sbellard     ARM_HWCAP_ARM_FPA       = 1 << 5,
358afce2927Sbellard     ARM_HWCAP_ARM_VFP       = 1 << 6,
359afce2927Sbellard     ARM_HWCAP_ARM_EDSP      = 1 << 7,
360cf6de34aSRiku Voipio     ARM_HWCAP_ARM_JAVA      = 1 << 8,
361cf6de34aSRiku Voipio     ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
36243ce393eSPeter Maydell     ARM_HWCAP_ARM_CRUNCH    = 1 << 10,
36343ce393eSPeter Maydell     ARM_HWCAP_ARM_THUMBEE   = 1 << 11,
36443ce393eSPeter Maydell     ARM_HWCAP_ARM_NEON      = 1 << 12,
36543ce393eSPeter Maydell     ARM_HWCAP_ARM_VFPv3     = 1 << 13,
36643ce393eSPeter Maydell     ARM_HWCAP_ARM_VFPv3D16  = 1 << 14,
36724682654SPeter Maydell     ARM_HWCAP_ARM_TLS       = 1 << 15,
36824682654SPeter Maydell     ARM_HWCAP_ARM_VFPv4     = 1 << 16,
36924682654SPeter Maydell     ARM_HWCAP_ARM_IDIVA     = 1 << 17,
37024682654SPeter Maydell     ARM_HWCAP_ARM_IDIVT     = 1 << 18,
37124682654SPeter Maydell     ARM_HWCAP_ARM_VFPD32    = 1 << 19,
37224682654SPeter Maydell     ARM_HWCAP_ARM_LPAE      = 1 << 20,
37324682654SPeter Maydell     ARM_HWCAP_ARM_EVTSTRM   = 1 << 21,
374afce2927Sbellard };
375afce2927Sbellard 
376ad6919dcSPeter Maydell enum {
377ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_AES      = 1 << 0,
378ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_PMULL    = 1 << 1,
379ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_SHA1     = 1 << 2,
380ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_SHA2     = 1 << 3,
381ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_CRC32    = 1 << 4,
382ad6919dcSPeter Maydell };
383ad6919dcSPeter Maydell 
3846b1275ffSPeter Maydell /* The commpage only exists for 32 bit kernels */
3856b1275ffSPeter Maydell 
386ee947430SAlex Bennée #define ARM_COMMPAGE (intptr_t)0xffff0f00u
387ee947430SAlex Bennée 
388ee947430SAlex Bennée static bool init_guest_commpage(void)
38997cc7560SDr. David Alan Gilbert {
390ee947430SAlex Bennée     void *want = g2h(ARM_COMMPAGE & -qemu_host_page_size);
391ee947430SAlex Bennée     void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
3925c3e87f3SAlex Bennée                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
39397cc7560SDr. David Alan Gilbert 
394ee947430SAlex Bennée     if (addr == MAP_FAILED) {
395ee947430SAlex Bennée         perror("Allocating guest commpage");
396ee947430SAlex Bennée         exit(EXIT_FAILURE);
397ee947430SAlex Bennée     }
398ee947430SAlex Bennée     if (addr != want) {
399ee947430SAlex Bennée         return false;
400806d1021SMeador Inge     }
401806d1021SMeador Inge 
402ee947430SAlex Bennée     /* Set kernel helper versions; rest of page is 0.  */
403ee947430SAlex Bennée     __put_user(5, (uint32_t *)g2h(0xffff0ffcu));
40497cc7560SDr. David Alan Gilbert 
405ee947430SAlex Bennée     if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
40697cc7560SDr. David Alan Gilbert         perror("Protecting guest commpage");
407ee947430SAlex Bennée         exit(EXIT_FAILURE);
40897cc7560SDr. David Alan Gilbert     }
409ee947430SAlex Bennée     return true;
41097cc7560SDr. David Alan Gilbert }
411adf050b1SBenoit Canet 
412adf050b1SBenoit Canet #define ELF_HWCAP get_elf_hwcap()
413ad6919dcSPeter Maydell #define ELF_HWCAP2 get_elf_hwcap2()
414adf050b1SBenoit Canet 
415adf050b1SBenoit Canet static uint32_t get_elf_hwcap(void)
416adf050b1SBenoit Canet {
417a2247f8eSAndreas Färber     ARMCPU *cpu = ARM_CPU(thread_cpu);
418adf050b1SBenoit Canet     uint32_t hwcaps = 0;
419adf050b1SBenoit Canet 
420adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_SWP;
421adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_HALF;
422adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_THUMB;
423adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
424adf050b1SBenoit Canet 
425adf050b1SBenoit Canet     /* probe for the extra features */
426adf050b1SBenoit Canet #define GET_FEATURE(feat, hwcap) \
427a2247f8eSAndreas Färber     do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
428962fcbf2SRichard Henderson 
429962fcbf2SRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \
430962fcbf2SRichard Henderson     do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
431962fcbf2SRichard Henderson 
43224682654SPeter Maydell     /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */
43324682654SPeter Maydell     GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP);
434adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
435adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
436adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
43724682654SPeter Maydell     GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
438bfa8a370SRichard Henderson     GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
439873b73c0SPeter Maydell     GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA);
440873b73c0SPeter Maydell     GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT);
441bfa8a370SRichard Henderson     GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP);
442bfa8a370SRichard Henderson 
443bfa8a370SRichard Henderson     if (cpu_isar_feature(aa32_fpsp_v3, cpu) ||
444bfa8a370SRichard Henderson         cpu_isar_feature(aa32_fpdp_v3, cpu)) {
445bfa8a370SRichard Henderson         hwcaps |= ARM_HWCAP_ARM_VFPv3;
446bfa8a370SRichard Henderson         if (cpu_isar_feature(aa32_simd_r32, cpu)) {
447bfa8a370SRichard Henderson             hwcaps |= ARM_HWCAP_ARM_VFPD32;
448bfa8a370SRichard Henderson         } else {
449bfa8a370SRichard Henderson             hwcaps |= ARM_HWCAP_ARM_VFPv3D16;
450bfa8a370SRichard Henderson         }
451bfa8a370SRichard Henderson     }
452bfa8a370SRichard Henderson     GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4);
453adf050b1SBenoit Canet 
454adf050b1SBenoit Canet     return hwcaps;
455adf050b1SBenoit Canet }
456afce2927Sbellard 
457ad6919dcSPeter Maydell static uint32_t get_elf_hwcap2(void)
458ad6919dcSPeter Maydell {
459ad6919dcSPeter Maydell     ARMCPU *cpu = ARM_CPU(thread_cpu);
460ad6919dcSPeter Maydell     uint32_t hwcaps = 0;
461ad6919dcSPeter Maydell 
462962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES);
463962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL);
464962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1);
465962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2);
466962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32);
467ad6919dcSPeter Maydell     return hwcaps;
468ad6919dcSPeter Maydell }
469ad6919dcSPeter Maydell 
470ad6919dcSPeter Maydell #undef GET_FEATURE
471962fcbf2SRichard Henderson #undef GET_FEATURE_ID
472ad6919dcSPeter Maydell 
47313ec4ec3SRichard Henderson #define ELF_PLATFORM get_elf_platform()
47413ec4ec3SRichard Henderson 
47513ec4ec3SRichard Henderson static const char *get_elf_platform(void)
47613ec4ec3SRichard Henderson {
47713ec4ec3SRichard Henderson     CPUARMState *env = thread_cpu->env_ptr;
47813ec4ec3SRichard Henderson 
47913ec4ec3SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN
48013ec4ec3SRichard Henderson # define END  "b"
48113ec4ec3SRichard Henderson #else
48213ec4ec3SRichard Henderson # define END  "l"
48313ec4ec3SRichard Henderson #endif
48413ec4ec3SRichard Henderson 
48513ec4ec3SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)) {
48613ec4ec3SRichard Henderson         return "v8" END;
48713ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V7)) {
48813ec4ec3SRichard Henderson         if (arm_feature(env, ARM_FEATURE_M)) {
48913ec4ec3SRichard Henderson             return "v7m" END;
49013ec4ec3SRichard Henderson         } else {
49113ec4ec3SRichard Henderson             return "v7" END;
49213ec4ec3SRichard Henderson         }
49313ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V6)) {
49413ec4ec3SRichard Henderson         return "v6" END;
49513ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V5)) {
49613ec4ec3SRichard Henderson         return "v5" END;
49713ec4ec3SRichard Henderson     } else {
49813ec4ec3SRichard Henderson         return "v4" END;
49913ec4ec3SRichard Henderson     }
50013ec4ec3SRichard Henderson 
50113ec4ec3SRichard Henderson #undef END
50213ec4ec3SRichard Henderson }
50313ec4ec3SRichard Henderson 
50424e76ff0SPeter Maydell #else
50524e76ff0SPeter Maydell /* 64 bit ARM definitions */
50624e76ff0SPeter Maydell #define ELF_START_MMAP 0x80000000
50724e76ff0SPeter Maydell 
508b597c3f7SPeter Crosthwaite #define ELF_ARCH        EM_AARCH64
50924e76ff0SPeter Maydell #define ELF_CLASS       ELFCLASS64
510e20e3ec9SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN
511e20e3ec9SRichard Henderson # define ELF_PLATFORM    "aarch64_be"
512e20e3ec9SRichard Henderson #else
51324e76ff0SPeter Maydell # define ELF_PLATFORM    "aarch64"
514e20e3ec9SRichard Henderson #endif
51524e76ff0SPeter Maydell 
51624e76ff0SPeter Maydell static inline void init_thread(struct target_pt_regs *regs,
51724e76ff0SPeter Maydell                                struct image_info *infop)
51824e76ff0SPeter Maydell {
51924e76ff0SPeter Maydell     abi_long stack = infop->start_stack;
52024e76ff0SPeter Maydell     memset(regs, 0, sizeof(*regs));
52124e76ff0SPeter Maydell 
52224e76ff0SPeter Maydell     regs->pc = infop->entry & ~0x3ULL;
52324e76ff0SPeter Maydell     regs->sp = stack;
52424e76ff0SPeter Maydell }
52524e76ff0SPeter Maydell 
52624e76ff0SPeter Maydell #define ELF_NREG    34
52724e76ff0SPeter Maydell typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
52824e76ff0SPeter Maydell 
52924e76ff0SPeter Maydell static void elf_core_copy_regs(target_elf_gregset_t *regs,
53024e76ff0SPeter Maydell                                const CPUARMState *env)
53124e76ff0SPeter Maydell {
53224e76ff0SPeter Maydell     int i;
53324e76ff0SPeter Maydell 
53424e76ff0SPeter Maydell     for (i = 0; i < 32; i++) {
53524e76ff0SPeter Maydell         (*regs)[i] = tswapreg(env->xregs[i]);
53624e76ff0SPeter Maydell     }
53724e76ff0SPeter Maydell     (*regs)[32] = tswapreg(env->pc);
53824e76ff0SPeter Maydell     (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env));
53924e76ff0SPeter Maydell }
54024e76ff0SPeter Maydell 
54124e76ff0SPeter Maydell #define USE_ELF_CORE_DUMP
54224e76ff0SPeter Maydell #define ELF_EXEC_PAGESIZE       4096
54324e76ff0SPeter Maydell 
54424e76ff0SPeter Maydell enum {
54524e76ff0SPeter Maydell     ARM_HWCAP_A64_FP            = 1 << 0,
54624e76ff0SPeter Maydell     ARM_HWCAP_A64_ASIMD         = 1 << 1,
54724e76ff0SPeter Maydell     ARM_HWCAP_A64_EVTSTRM       = 1 << 2,
54824e76ff0SPeter Maydell     ARM_HWCAP_A64_AES           = 1 << 3,
54924e76ff0SPeter Maydell     ARM_HWCAP_A64_PMULL         = 1 << 4,
55024e76ff0SPeter Maydell     ARM_HWCAP_A64_SHA1          = 1 << 5,
55124e76ff0SPeter Maydell     ARM_HWCAP_A64_SHA2          = 1 << 6,
55224e76ff0SPeter Maydell     ARM_HWCAP_A64_CRC32         = 1 << 7,
553955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ATOMICS       = 1 << 8,
554955f56d4SArd Biesheuvel     ARM_HWCAP_A64_FPHP          = 1 << 9,
555955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDHP       = 1 << 10,
556955f56d4SArd Biesheuvel     ARM_HWCAP_A64_CPUID         = 1 << 11,
557955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDRDM      = 1 << 12,
558955f56d4SArd Biesheuvel     ARM_HWCAP_A64_JSCVT         = 1 << 13,
559955f56d4SArd Biesheuvel     ARM_HWCAP_A64_FCMA          = 1 << 14,
560955f56d4SArd Biesheuvel     ARM_HWCAP_A64_LRCPC         = 1 << 15,
561955f56d4SArd Biesheuvel     ARM_HWCAP_A64_DCPOP         = 1 << 16,
562955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SHA3          = 1 << 17,
563955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SM3           = 1 << 18,
564955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SM4           = 1 << 19,
565955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDDP       = 1 << 20,
566955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SHA512        = 1 << 21,
567955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SVE           = 1 << 22,
5680083a1faSRichard Henderson     ARM_HWCAP_A64_ASIMDFHM      = 1 << 23,
5690083a1faSRichard Henderson     ARM_HWCAP_A64_DIT           = 1 << 24,
5700083a1faSRichard Henderson     ARM_HWCAP_A64_USCAT         = 1 << 25,
5710083a1faSRichard Henderson     ARM_HWCAP_A64_ILRCPC        = 1 << 26,
5720083a1faSRichard Henderson     ARM_HWCAP_A64_FLAGM         = 1 << 27,
5730083a1faSRichard Henderson     ARM_HWCAP_A64_SSBS          = 1 << 28,
5740083a1faSRichard Henderson     ARM_HWCAP_A64_SB            = 1 << 29,
5750083a1faSRichard Henderson     ARM_HWCAP_A64_PACA          = 1 << 30,
5760083a1faSRichard Henderson     ARM_HWCAP_A64_PACG          = 1UL << 31,
5772041df4aSRichard Henderson 
5782041df4aSRichard Henderson     ARM_HWCAP2_A64_DCPODP       = 1 << 0,
5792041df4aSRichard Henderson     ARM_HWCAP2_A64_SVE2         = 1 << 1,
5802041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEAES       = 1 << 2,
5812041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEPMULL     = 1 << 3,
5822041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEBITPERM   = 1 << 4,
5832041df4aSRichard Henderson     ARM_HWCAP2_A64_SVESHA3      = 1 << 5,
5842041df4aSRichard Henderson     ARM_HWCAP2_A64_SVESM4       = 1 << 6,
5852041df4aSRichard Henderson     ARM_HWCAP2_A64_FLAGM2       = 1 << 7,
5862041df4aSRichard Henderson     ARM_HWCAP2_A64_FRINT        = 1 << 8,
58724e76ff0SPeter Maydell };
58824e76ff0SPeter Maydell 
58924e76ff0SPeter Maydell #define ELF_HWCAP   get_elf_hwcap()
5902041df4aSRichard Henderson #define ELF_HWCAP2  get_elf_hwcap2()
5912041df4aSRichard Henderson 
5922041df4aSRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \
5932041df4aSRichard Henderson     do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
59424e76ff0SPeter Maydell 
59524e76ff0SPeter Maydell static uint32_t get_elf_hwcap(void)
59624e76ff0SPeter Maydell {
59724e76ff0SPeter Maydell     ARMCPU *cpu = ARM_CPU(thread_cpu);
59824e76ff0SPeter Maydell     uint32_t hwcaps = 0;
59924e76ff0SPeter Maydell 
60024e76ff0SPeter Maydell     hwcaps |= ARM_HWCAP_A64_FP;
60124e76ff0SPeter Maydell     hwcaps |= ARM_HWCAP_A64_ASIMD;
60237020ff1SAlex Bennée     hwcaps |= ARM_HWCAP_A64_CPUID;
60324e76ff0SPeter Maydell 
60424e76ff0SPeter Maydell     /* probe for the extra features */
605962fcbf2SRichard Henderson 
606962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES);
607962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL);
608962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha1, ARM_HWCAP_A64_SHA1);
609962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha256, ARM_HWCAP_A64_SHA2);
610962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha512, ARM_HWCAP_A64_SHA512);
611962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_crc32, ARM_HWCAP_A64_CRC32);
612962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3);
613962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3);
614962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4);
6155763190fSRichard Henderson     GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
616962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS);
617962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM);
618962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
619962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
620cd208a1cSRichard Henderson     GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
62129d26ab2SRichard Henderson     GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
6221c9af3a9SRichard Henderson     GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
6231c9af3a9SRichard Henderson     GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
6249888bd1eSRichard Henderson     GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
625b89d9c98SRichard Henderson     GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
6260d57b499SBeata Michalska     GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
6272677cf9fSPeter Maydell     GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
628a1229109SPeter Maydell     GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
629962fcbf2SRichard Henderson 
6302041df4aSRichard Henderson     return hwcaps;
6312041df4aSRichard Henderson }
6322041df4aSRichard Henderson 
6332041df4aSRichard Henderson static uint32_t get_elf_hwcap2(void)
6342041df4aSRichard Henderson {
6352041df4aSRichard Henderson     ARMCPU *cpu = ARM_CPU(thread_cpu);
6362041df4aSRichard Henderson     uint32_t hwcaps = 0;
6372041df4aSRichard Henderson 
6380d57b499SBeata Michalska     GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
6392041df4aSRichard Henderson     GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
6402041df4aSRichard Henderson     GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
64124e76ff0SPeter Maydell 
64224e76ff0SPeter Maydell     return hwcaps;
64324e76ff0SPeter Maydell }
64424e76ff0SPeter Maydell 
6452041df4aSRichard Henderson #undef GET_FEATURE_ID
6462041df4aSRichard Henderson 
64724e76ff0SPeter Maydell #endif /* not TARGET_AARCH64 */
64824e76ff0SPeter Maydell #endif /* TARGET_ARM */
64930ac07d4Sbellard 
650853d6f7aSbellard #ifdef TARGET_SPARC
651a315a145Sbellard #ifdef TARGET_SPARC64
652853d6f7aSbellard 
653853d6f7aSbellard #define ELF_START_MMAP 0x80000000
654cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
655cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9)
656992f48a0Sblueswir1 #ifndef TARGET_ABI32
657cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
658992f48a0Sblueswir1 #else
659992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
660992f48a0Sblueswir1 #endif
661853d6f7aSbellard 
662a315a145Sbellard #define ELF_CLASS   ELFCLASS64
6635ef54116Sbellard #define ELF_ARCH    EM_SPARCV9
6645ef54116Sbellard 
6655ef54116Sbellard #define STACK_BIAS              2047
666a315a145Sbellard 
667d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
668d97ef72eSRichard Henderson                                struct image_info *infop)
669a315a145Sbellard {
670992f48a0Sblueswir1 #ifndef TARGET_ABI32
671a315a145Sbellard     regs->tstate = 0;
672992f48a0Sblueswir1 #endif
673a315a145Sbellard     regs->pc = infop->entry;
674a315a145Sbellard     regs->npc = regs->pc + 4;
675a315a145Sbellard     regs->y = 0;
676992f48a0Sblueswir1 #ifdef TARGET_ABI32
677992f48a0Sblueswir1     regs->u_regs[14] = infop->start_stack - 16 * 4;
678992f48a0Sblueswir1 #else
679cb33da57Sblueswir1     if (personality(infop->personality) == PER_LINUX32)
680cb33da57Sblueswir1         regs->u_regs[14] = infop->start_stack - 16 * 4;
681cb33da57Sblueswir1     else
6825ef54116Sbellard         regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
683992f48a0Sblueswir1 #endif
684a315a145Sbellard }
685a315a145Sbellard 
686a315a145Sbellard #else
687a315a145Sbellard #define ELF_START_MMAP 0x80000000
688cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
689cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV)
690a315a145Sbellard 
691853d6f7aSbellard #define ELF_CLASS   ELFCLASS32
692853d6f7aSbellard #define ELF_ARCH    EM_SPARC
693853d6f7aSbellard 
694d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
695d97ef72eSRichard Henderson                                struct image_info *infop)
696853d6f7aSbellard {
697f5155289Sbellard     regs->psr = 0;
698f5155289Sbellard     regs->pc = infop->entry;
699f5155289Sbellard     regs->npc = regs->pc + 4;
700f5155289Sbellard     regs->y = 0;
701f5155289Sbellard     regs->u_regs[14] = infop->start_stack - 16 * 4;
702853d6f7aSbellard }
703853d6f7aSbellard 
704853d6f7aSbellard #endif
705a315a145Sbellard #endif
706853d6f7aSbellard 
70767867308Sbellard #ifdef TARGET_PPC
70867867308Sbellard 
7094ecd4d16SPeter Crosthwaite #define ELF_MACHINE    PPC_ELF_MACHINE
71067867308Sbellard #define ELF_START_MMAP 0x80000000
71167867308Sbellard 
712e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
71384409ddbSj_mayer 
71484409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 )
71584409ddbSj_mayer 
71684409ddbSj_mayer #define ELF_CLASS       ELFCLASS64
71784409ddbSj_mayer 
71884409ddbSj_mayer #else
71984409ddbSj_mayer 
72067867308Sbellard #define ELF_CLASS       ELFCLASS32
72184409ddbSj_mayer 
72284409ddbSj_mayer #endif
72384409ddbSj_mayer 
72467867308Sbellard #define ELF_ARCH        EM_PPC
72567867308Sbellard 
726df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
727df84e4f3SNathan Froyd    See arch/powerpc/include/asm/cputable.h.  */
728df84e4f3SNathan Froyd enum {
7293efa9a67Smalc     QEMU_PPC_FEATURE_32 = 0x80000000,
7303efa9a67Smalc     QEMU_PPC_FEATURE_64 = 0x40000000,
7313efa9a67Smalc     QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
7323efa9a67Smalc     QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
7333efa9a67Smalc     QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
7343efa9a67Smalc     QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
7353efa9a67Smalc     QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
7363efa9a67Smalc     QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
7373efa9a67Smalc     QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
7383efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
7393efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
7403efa9a67Smalc     QEMU_PPC_FEATURE_NO_TB = 0x00100000,
7413efa9a67Smalc     QEMU_PPC_FEATURE_POWER4 = 0x00080000,
7423efa9a67Smalc     QEMU_PPC_FEATURE_POWER5 = 0x00040000,
7433efa9a67Smalc     QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
7443efa9a67Smalc     QEMU_PPC_FEATURE_CELL = 0x00010000,
7453efa9a67Smalc     QEMU_PPC_FEATURE_BOOKE = 0x00008000,
7463efa9a67Smalc     QEMU_PPC_FEATURE_SMT = 0x00004000,
7473efa9a67Smalc     QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
7483efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
7493efa9a67Smalc     QEMU_PPC_FEATURE_PA6T = 0x00000800,
7503efa9a67Smalc     QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
7513efa9a67Smalc     QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
7523efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
7533efa9a67Smalc     QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
7543efa9a67Smalc     QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
755df84e4f3SNathan Froyd 
7563efa9a67Smalc     QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
7573efa9a67Smalc     QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
758a60438ddSTom Musta 
759a60438ddSTom Musta     /* Feature definitions in AT_HWCAP2.  */
760a60438ddSTom Musta     QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */
761a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */
762a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */
763a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */
764a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */
765a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */
76624c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_VEC_CRYPTO = 0x02000000,
76724c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HTM_NOSC = 0x01000000,
768be0c46d4SSandipan Das     QEMU_PPC_FEATURE2_ARCH_3_00 = 0x00800000, /* ISA 3.00 */
76924c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HAS_IEEE128 = 0x00400000, /* VSX IEEE Bin Float 128-bit */
77024c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */
77124c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */
77224c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */
773df84e4f3SNathan Froyd };
774df84e4f3SNathan Froyd 
775df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap()
776df84e4f3SNathan Froyd 
777df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void)
778df84e4f3SNathan Froyd {
779a2247f8eSAndreas Färber     PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
780df84e4f3SNathan Froyd     uint32_t features = 0;
781df84e4f3SNathan Froyd 
782df84e4f3SNathan Froyd     /* We don't have to be terribly complete here; the high points are
783df84e4f3SNathan Froyd        Altivec/FP/SPE support.  Anything else is just a bonus.  */
784df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature)                                      \
785a2247f8eSAndreas Färber     do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
78658eb5308SMichael Walle #define GET_FEATURE2(flags, feature) \
78758eb5308SMichael Walle     do { \
78858eb5308SMichael Walle         if ((cpu->env.insns_flags2 & flags) == flags) { \
78958eb5308SMichael Walle             features |= feature; \
79058eb5308SMichael Walle         } \
79158eb5308SMichael Walle     } while (0)
7923efa9a67Smalc     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
7933efa9a67Smalc     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
7943efa9a67Smalc     GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
7953efa9a67Smalc     GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
7963efa9a67Smalc     GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
7973efa9a67Smalc     GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
7983efa9a67Smalc     GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
7993efa9a67Smalc     GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
8000e019746STom Musta     GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP);
8010e019746STom Musta     GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX);
8020e019746STom Musta     GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 |
8030e019746STom Musta                   PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206),
8040e019746STom Musta                   QEMU_PPC_FEATURE_ARCH_2_06);
805df84e4f3SNathan Froyd #undef GET_FEATURE
8060e019746STom Musta #undef GET_FEATURE2
807df84e4f3SNathan Froyd 
808df84e4f3SNathan Froyd     return features;
809df84e4f3SNathan Froyd }
810df84e4f3SNathan Froyd 
811a60438ddSTom Musta #define ELF_HWCAP2 get_elf_hwcap2()
812a60438ddSTom Musta 
813a60438ddSTom Musta static uint32_t get_elf_hwcap2(void)
814a60438ddSTom Musta {
815a60438ddSTom Musta     PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
816a60438ddSTom Musta     uint32_t features = 0;
817a60438ddSTom Musta 
818a60438ddSTom Musta #define GET_FEATURE(flag, feature)                                      \
819a60438ddSTom Musta     do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
820a60438ddSTom Musta #define GET_FEATURE2(flag, feature)                                      \
821a60438ddSTom Musta     do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0)
822a60438ddSTom Musta 
823a60438ddSTom Musta     GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL);
824a60438ddSTom Musta     GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR);
825a60438ddSTom Musta     GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
82624c373ecSLaurent Vivier                   PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07 |
82724c373ecSLaurent Vivier                   QEMU_PPC_FEATURE2_VEC_CRYPTO);
82824c373ecSLaurent Vivier     GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 |
82924c373ecSLaurent Vivier                  QEMU_PPC_FEATURE2_DARN);
830a60438ddSTom Musta 
831a60438ddSTom Musta #undef GET_FEATURE
832a60438ddSTom Musta #undef GET_FEATURE2
833a60438ddSTom Musta 
834a60438ddSTom Musta     return features;
835a60438ddSTom Musta }
836a60438ddSTom Musta 
837f5155289Sbellard /*
838f5155289Sbellard  * The requirements here are:
839f5155289Sbellard  * - keep the final alignment of sp (sp & 0xf)
840f5155289Sbellard  * - make sure the 32-bit value at the first 16 byte aligned position of
841f5155289Sbellard  *   AUXV is greater than 16 for glibc compatibility.
842f5155289Sbellard  *   AT_IGNOREPPC is used for that.
843f5155289Sbellard  * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
844f5155289Sbellard  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
845f5155289Sbellard  */
8460bccf03dSbellard #define DLINFO_ARCH_ITEMS       5
847f5155289Sbellard #define ARCH_DLINFO                                     \
848f5155289Sbellard     do {                                                \
849623e250aSTom Musta         PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);              \
850f5155289Sbellard         /*                                              \
85182991bedSPeter Maydell          * Handle glibc compatibility: these magic entries must \
85282991bedSPeter Maydell          * be at the lowest addresses in the final auxv.        \
853f5155289Sbellard          */                                             \
8540bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
8550bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
85682991bedSPeter Maydell         NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \
85782991bedSPeter Maydell         NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \
85882991bedSPeter Maydell         NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
859f5155289Sbellard     } while (0)
860f5155289Sbellard 
86167867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
86267867308Sbellard {
86367867308Sbellard     _regs->gpr[1] = infop->start_stack;
864e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
865d90b94cdSDoug Kwan     if (get_ppc64_abi(infop) < 2) {
8662ccf97ecSPeter Maydell         uint64_t val;
8672ccf97ecSPeter Maydell         get_user_u64(val, infop->entry + 8);
8682ccf97ecSPeter Maydell         _regs->gpr[2] = val + infop->load_bias;
8692ccf97ecSPeter Maydell         get_user_u64(val, infop->entry);
8702ccf97ecSPeter Maydell         infop->entry = val + infop->load_bias;
871d90b94cdSDoug Kwan     } else {
872d90b94cdSDoug Kwan         _regs->gpr[12] = infop->entry;  /* r12 set to global entry address */
873d90b94cdSDoug Kwan     }
87484409ddbSj_mayer #endif
87567867308Sbellard     _regs->nip = infop->entry;
87667867308Sbellard }
87767867308Sbellard 
878e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h.  */
879e2f3e741SNathan Froyd #define ELF_NREG 48
880e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
881e2f3e741SNathan Froyd 
88205390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env)
883e2f3e741SNathan Froyd {
884e2f3e741SNathan Froyd     int i;
885e2f3e741SNathan Froyd     target_ulong ccr = 0;
886e2f3e741SNathan Froyd 
887e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
88886cd7b2dSPaolo Bonzini         (*regs)[i] = tswapreg(env->gpr[i]);
889e2f3e741SNathan Froyd     }
890e2f3e741SNathan Froyd 
89186cd7b2dSPaolo Bonzini     (*regs)[32] = tswapreg(env->nip);
89286cd7b2dSPaolo Bonzini     (*regs)[33] = tswapreg(env->msr);
89386cd7b2dSPaolo Bonzini     (*regs)[35] = tswapreg(env->ctr);
89486cd7b2dSPaolo Bonzini     (*regs)[36] = tswapreg(env->lr);
89586cd7b2dSPaolo Bonzini     (*regs)[37] = tswapreg(env->xer);
896e2f3e741SNathan Froyd 
897e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
898e2f3e741SNathan Froyd         ccr |= env->crf[i] << (32 - ((i + 1) * 4));
899e2f3e741SNathan Froyd     }
90086cd7b2dSPaolo Bonzini     (*regs)[38] = tswapreg(ccr);
901e2f3e741SNathan Froyd }
902e2f3e741SNathan Froyd 
903e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP
90467867308Sbellard #define ELF_EXEC_PAGESIZE       4096
90567867308Sbellard 
90667867308Sbellard #endif
90767867308Sbellard 
908048f6b4dSbellard #ifdef TARGET_MIPS
909048f6b4dSbellard 
910048f6b4dSbellard #define ELF_START_MMAP 0x80000000
911048f6b4dSbellard 
912388bb21aSths #ifdef TARGET_MIPS64
913388bb21aSths #define ELF_CLASS   ELFCLASS64
914388bb21aSths #else
915048f6b4dSbellard #define ELF_CLASS   ELFCLASS32
916388bb21aSths #endif
917048f6b4dSbellard #define ELF_ARCH    EM_MIPS
918048f6b4dSbellard 
919f72541f3SAleksandar Markovic #define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_NANOMIPS)
920f72541f3SAleksandar Markovic 
921ace3d654SCarlo Marcelo Arenas Belón #ifdef TARGET_ABI_MIPSN32
922ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) ((x) & EF_MIPS_ABI2)
923ace3d654SCarlo Marcelo Arenas Belón #else
924ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (!((x) & EF_MIPS_ABI2))
925ace3d654SCarlo Marcelo Arenas Belón #endif
926ace3d654SCarlo Marcelo Arenas Belón 
927d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
928d97ef72eSRichard Henderson                                struct image_info *infop)
929048f6b4dSbellard {
930623a930eSths     regs->cp0_status = 2 << CP0St_KSU;
931048f6b4dSbellard     regs->cp0_epc = infop->entry;
932048f6b4dSbellard     regs->regs[29] = infop->start_stack;
933048f6b4dSbellard }
934048f6b4dSbellard 
93551e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h.  */
93651e52606SNathan Froyd #define ELF_NREG 45
93751e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
93851e52606SNathan Froyd 
93951e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h.  */
94051e52606SNathan Froyd enum {
94151e52606SNathan Froyd #ifdef TARGET_MIPS64
94251e52606SNathan Froyd     TARGET_EF_R0 = 0,
94351e52606SNathan Froyd #else
94451e52606SNathan Froyd     TARGET_EF_R0 = 6,
94551e52606SNathan Froyd #endif
94651e52606SNathan Froyd     TARGET_EF_R26 = TARGET_EF_R0 + 26,
94751e52606SNathan Froyd     TARGET_EF_R27 = TARGET_EF_R0 + 27,
94851e52606SNathan Froyd     TARGET_EF_LO = TARGET_EF_R0 + 32,
94951e52606SNathan Froyd     TARGET_EF_HI = TARGET_EF_R0 + 33,
95051e52606SNathan Froyd     TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
95151e52606SNathan Froyd     TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
95251e52606SNathan Froyd     TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
95351e52606SNathan Froyd     TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
95451e52606SNathan Froyd };
95551e52606SNathan Froyd 
95651e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
95705390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env)
95851e52606SNathan Froyd {
95951e52606SNathan Froyd     int i;
96051e52606SNathan Froyd 
96151e52606SNathan Froyd     for (i = 0; i < TARGET_EF_R0; i++) {
96251e52606SNathan Froyd         (*regs)[i] = 0;
96351e52606SNathan Froyd     }
96451e52606SNathan Froyd     (*regs)[TARGET_EF_R0] = 0;
96551e52606SNathan Froyd 
96651e52606SNathan Froyd     for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
967a29f998dSPaolo Bonzini         (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]);
96851e52606SNathan Froyd     }
96951e52606SNathan Froyd 
97051e52606SNathan Froyd     (*regs)[TARGET_EF_R26] = 0;
97151e52606SNathan Froyd     (*regs)[TARGET_EF_R27] = 0;
972a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]);
973a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]);
974a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC);
975a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr);
976a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status);
977a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause);
97851e52606SNathan Froyd }
97951e52606SNathan Froyd 
98051e52606SNathan Froyd #define USE_ELF_CORE_DUMP
981388bb21aSths #define ELF_EXEC_PAGESIZE        4096
982388bb21aSths 
98346a1ee4fSJames Cowgill /* See arch/mips/include/uapi/asm/hwcap.h.  */
98446a1ee4fSJames Cowgill enum {
98546a1ee4fSJames Cowgill     HWCAP_MIPS_R6           = (1 << 0),
98646a1ee4fSJames Cowgill     HWCAP_MIPS_MSA          = (1 << 1),
98746a1ee4fSJames Cowgill };
98846a1ee4fSJames Cowgill 
98946a1ee4fSJames Cowgill #define ELF_HWCAP get_elf_hwcap()
99046a1ee4fSJames Cowgill 
99146a1ee4fSJames Cowgill static uint32_t get_elf_hwcap(void)
99246a1ee4fSJames Cowgill {
99346a1ee4fSJames Cowgill     MIPSCPU *cpu = MIPS_CPU(thread_cpu);
99446a1ee4fSJames Cowgill     uint32_t hwcaps = 0;
99546a1ee4fSJames Cowgill 
99646a1ee4fSJames Cowgill #define GET_FEATURE(flag, hwcap) \
99746a1ee4fSJames Cowgill     do { if (cpu->env.insn_flags & (flag)) { hwcaps |= hwcap; } } while (0)
99846a1ee4fSJames Cowgill 
99946a1ee4fSJames Cowgill     GET_FEATURE(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6);
100046a1ee4fSJames Cowgill     GET_FEATURE(ASE_MSA, HWCAP_MIPS_MSA);
100146a1ee4fSJames Cowgill 
100246a1ee4fSJames Cowgill #undef GET_FEATURE
100346a1ee4fSJames Cowgill 
100446a1ee4fSJames Cowgill     return hwcaps;
100546a1ee4fSJames Cowgill }
100646a1ee4fSJames Cowgill 
1007048f6b4dSbellard #endif /* TARGET_MIPS */
1008048f6b4dSbellard 
1009b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE
1010b779e29eSEdgar E. Iglesias 
1011b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000
1012b779e29eSEdgar E. Iglesias 
10130d5d4699SEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
1014b779e29eSEdgar E. Iglesias 
1015b779e29eSEdgar E. Iglesias #define ELF_CLASS   ELFCLASS32
10160d5d4699SEdgar E. Iglesias #define ELF_ARCH    EM_MICROBLAZE
1017b779e29eSEdgar E. Iglesias 
1018d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1019d97ef72eSRichard Henderson                                struct image_info *infop)
1020b779e29eSEdgar E. Iglesias {
1021b779e29eSEdgar E. Iglesias     regs->pc = infop->entry;
1022b779e29eSEdgar E. Iglesias     regs->r1 = infop->start_stack;
1023b779e29eSEdgar E. Iglesias 
1024b779e29eSEdgar E. Iglesias }
1025b779e29eSEdgar E. Iglesias 
1026b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE        4096
1027b779e29eSEdgar E. Iglesias 
1028e4cbd44dSEdgar E. Iglesias #define USE_ELF_CORE_DUMP
1029e4cbd44dSEdgar E. Iglesias #define ELF_NREG 38
1030e4cbd44dSEdgar E. Iglesias typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1031e4cbd44dSEdgar E. Iglesias 
1032e4cbd44dSEdgar E. Iglesias /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
103305390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env)
1034e4cbd44dSEdgar E. Iglesias {
1035e4cbd44dSEdgar E. Iglesias     int i, pos = 0;
1036e4cbd44dSEdgar E. Iglesias 
1037e4cbd44dSEdgar E. Iglesias     for (i = 0; i < 32; i++) {
103886cd7b2dSPaolo Bonzini         (*regs)[pos++] = tswapreg(env->regs[i]);
1039e4cbd44dSEdgar E. Iglesias     }
1040e4cbd44dSEdgar E. Iglesias 
1041af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->pc);
1042*1074c0fbSRichard Henderson     (*regs)[pos++] = tswapreg(mb_cpu_read_msr(env));
1043af20a93aSRichard Henderson     (*regs)[pos++] = 0;
1044af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->ear);
1045af20a93aSRichard Henderson     (*regs)[pos++] = 0;
1046af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->esr);
1047e4cbd44dSEdgar E. Iglesias }
1048e4cbd44dSEdgar E. Iglesias 
1049b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */
1050b779e29eSEdgar E. Iglesias 
1051a0a839b6SMarek Vasut #ifdef TARGET_NIOS2
1052a0a839b6SMarek Vasut 
1053a0a839b6SMarek Vasut #define ELF_START_MMAP 0x80000000
1054a0a839b6SMarek Vasut 
1055a0a839b6SMarek Vasut #define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2)
1056a0a839b6SMarek Vasut 
1057a0a839b6SMarek Vasut #define ELF_CLASS   ELFCLASS32
1058a0a839b6SMarek Vasut #define ELF_ARCH    EM_ALTERA_NIOS2
1059a0a839b6SMarek Vasut 
1060a0a839b6SMarek Vasut static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
1061a0a839b6SMarek Vasut {
1062a0a839b6SMarek Vasut     regs->ea = infop->entry;
1063a0a839b6SMarek Vasut     regs->sp = infop->start_stack;
1064a0a839b6SMarek Vasut     regs->estatus = 0x3;
1065a0a839b6SMarek Vasut }
1066a0a839b6SMarek Vasut 
1067a0a839b6SMarek Vasut #define ELF_EXEC_PAGESIZE        4096
1068a0a839b6SMarek Vasut 
1069a0a839b6SMarek Vasut #define USE_ELF_CORE_DUMP
1070a0a839b6SMarek Vasut #define ELF_NREG 49
1071a0a839b6SMarek Vasut typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1072a0a839b6SMarek Vasut 
1073a0a839b6SMarek Vasut /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
1074a0a839b6SMarek Vasut static void elf_core_copy_regs(target_elf_gregset_t *regs,
1075a0a839b6SMarek Vasut                                const CPUNios2State *env)
1076a0a839b6SMarek Vasut {
1077a0a839b6SMarek Vasut     int i;
1078a0a839b6SMarek Vasut 
1079a0a839b6SMarek Vasut     (*regs)[0] = -1;
1080a0a839b6SMarek Vasut     for (i = 1; i < 8; i++)    /* r0-r7 */
1081a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i + 7]);
1082a0a839b6SMarek Vasut 
1083a0a839b6SMarek Vasut     for (i = 8; i < 16; i++)   /* r8-r15 */
1084a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i - 8]);
1085a0a839b6SMarek Vasut 
1086a0a839b6SMarek Vasut     for (i = 16; i < 24; i++)  /* r16-r23 */
1087a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i + 7]);
1088a0a839b6SMarek Vasut     (*regs)[24] = -1;    /* R_ET */
1089a0a839b6SMarek Vasut     (*regs)[25] = -1;    /* R_BT */
1090a0a839b6SMarek Vasut     (*regs)[26] = tswapreg(env->regs[R_GP]);
1091a0a839b6SMarek Vasut     (*regs)[27] = tswapreg(env->regs[R_SP]);
1092a0a839b6SMarek Vasut     (*regs)[28] = tswapreg(env->regs[R_FP]);
1093a0a839b6SMarek Vasut     (*regs)[29] = tswapreg(env->regs[R_EA]);
1094a0a839b6SMarek Vasut     (*regs)[30] = -1;    /* R_SSTATUS */
1095a0a839b6SMarek Vasut     (*regs)[31] = tswapreg(env->regs[R_RA]);
1096a0a839b6SMarek Vasut 
1097a0a839b6SMarek Vasut     (*regs)[32] = tswapreg(env->regs[R_PC]);
1098a0a839b6SMarek Vasut 
1099a0a839b6SMarek Vasut     (*regs)[33] = -1; /* R_STATUS */
1100a0a839b6SMarek Vasut     (*regs)[34] = tswapreg(env->regs[CR_ESTATUS]);
1101a0a839b6SMarek Vasut 
1102a0a839b6SMarek Vasut     for (i = 35; i < 49; i++)    /* ... */
1103a0a839b6SMarek Vasut         (*regs)[i] = -1;
1104a0a839b6SMarek Vasut }
1105a0a839b6SMarek Vasut 
1106a0a839b6SMarek Vasut #endif /* TARGET_NIOS2 */
1107a0a839b6SMarek Vasut 
1108d962783eSJia Liu #ifdef TARGET_OPENRISC
1109d962783eSJia Liu 
1110d962783eSJia Liu #define ELF_START_MMAP 0x08000000
1111d962783eSJia Liu 
1112d962783eSJia Liu #define ELF_ARCH EM_OPENRISC
1113d962783eSJia Liu #define ELF_CLASS ELFCLASS32
1114d962783eSJia Liu #define ELF_DATA  ELFDATA2MSB
1115d962783eSJia Liu 
1116d962783eSJia Liu static inline void init_thread(struct target_pt_regs *regs,
1117d962783eSJia Liu                                struct image_info *infop)
1118d962783eSJia Liu {
1119d962783eSJia Liu     regs->pc = infop->entry;
1120d962783eSJia Liu     regs->gpr[1] = infop->start_stack;
1121d962783eSJia Liu }
1122d962783eSJia Liu 
1123d962783eSJia Liu #define USE_ELF_CORE_DUMP
1124d962783eSJia Liu #define ELF_EXEC_PAGESIZE 8192
1125d962783eSJia Liu 
1126d962783eSJia Liu /* See linux kernel arch/openrisc/include/asm/elf.h.  */
1127d962783eSJia Liu #define ELF_NREG 34 /* gprs and pc, sr */
1128d962783eSJia Liu typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1129d962783eSJia Liu 
1130d962783eSJia Liu static void elf_core_copy_regs(target_elf_gregset_t *regs,
1131d962783eSJia Liu                                const CPUOpenRISCState *env)
1132d962783eSJia Liu {
1133d962783eSJia Liu     int i;
1134d962783eSJia Liu 
1135d962783eSJia Liu     for (i = 0; i < 32; i++) {
1136d89e71e8SStafford Horne         (*regs)[i] = tswapreg(cpu_get_gpr(env, i));
1137d962783eSJia Liu     }
113886cd7b2dSPaolo Bonzini     (*regs)[32] = tswapreg(env->pc);
113984775c43SRichard Henderson     (*regs)[33] = tswapreg(cpu_get_sr(env));
1140d962783eSJia Liu }
1141d962783eSJia Liu #define ELF_HWCAP 0
1142d962783eSJia Liu #define ELF_PLATFORM NULL
1143d962783eSJia Liu 
1144d962783eSJia Liu #endif /* TARGET_OPENRISC */
1145d962783eSJia Liu 
1146fdf9b3e8Sbellard #ifdef TARGET_SH4
1147fdf9b3e8Sbellard 
1148fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000
1149fdf9b3e8Sbellard 
1150fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32
1151fdf9b3e8Sbellard #define ELF_ARCH  EM_SH
1152fdf9b3e8Sbellard 
1153d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1154d97ef72eSRichard Henderson                                struct image_info *infop)
1155fdf9b3e8Sbellard {
1156fdf9b3e8Sbellard     /* Check other registers XXXXX */
1157fdf9b3e8Sbellard     regs->pc = infop->entry;
1158072ae847Sths     regs->regs[15] = infop->start_stack;
1159fdf9b3e8Sbellard }
1160fdf9b3e8Sbellard 
11617631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h.  */
11627631c97eSNathan Froyd #define ELF_NREG 23
11637631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
11647631c97eSNathan Froyd 
11657631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h.  */
11667631c97eSNathan Froyd enum {
11677631c97eSNathan Froyd     TARGET_REG_PC = 16,
11687631c97eSNathan Froyd     TARGET_REG_PR = 17,
11697631c97eSNathan Froyd     TARGET_REG_SR = 18,
11707631c97eSNathan Froyd     TARGET_REG_GBR = 19,
11717631c97eSNathan Froyd     TARGET_REG_MACH = 20,
11727631c97eSNathan Froyd     TARGET_REG_MACL = 21,
11737631c97eSNathan Froyd     TARGET_REG_SYSCALL = 22
11747631c97eSNathan Froyd };
11757631c97eSNathan Froyd 
1176d97ef72eSRichard Henderson static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
117705390248SAndreas Färber                                       const CPUSH4State *env)
11787631c97eSNathan Froyd {
11797631c97eSNathan Froyd     int i;
11807631c97eSNathan Froyd 
11817631c97eSNathan Froyd     for (i = 0; i < 16; i++) {
118272cd500bSPhilippe Mathieu-Daudé         (*regs)[i] = tswapreg(env->gregs[i]);
11837631c97eSNathan Froyd     }
11847631c97eSNathan Froyd 
118586cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
118686cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_PR] = tswapreg(env->pr);
118786cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_SR] = tswapreg(env->sr);
118886cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr);
118986cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_MACH] = tswapreg(env->mach);
119086cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_MACL] = tswapreg(env->macl);
11917631c97eSNathan Froyd     (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
11927631c97eSNathan Froyd }
11937631c97eSNathan Froyd 
11947631c97eSNathan Froyd #define USE_ELF_CORE_DUMP
1195fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE        4096
1196fdf9b3e8Sbellard 
1197e42fd944SRichard Henderson enum {
1198e42fd944SRichard Henderson     SH_CPU_HAS_FPU            = 0x0001, /* Hardware FPU support */
1199e42fd944SRichard Henderson     SH_CPU_HAS_P2_FLUSH_BUG   = 0x0002, /* Need to flush the cache in P2 area */
1200e42fd944SRichard Henderson     SH_CPU_HAS_MMU_PAGE_ASSOC = 0x0004, /* SH3: TLB way selection bit support */
1201e42fd944SRichard Henderson     SH_CPU_HAS_DSP            = 0x0008, /* SH-DSP: DSP support */
1202e42fd944SRichard Henderson     SH_CPU_HAS_PERF_COUNTER   = 0x0010, /* Hardware performance counters */
1203e42fd944SRichard Henderson     SH_CPU_HAS_PTEA           = 0x0020, /* PTEA register */
1204e42fd944SRichard Henderson     SH_CPU_HAS_LLSC           = 0x0040, /* movli.l/movco.l */
1205e42fd944SRichard Henderson     SH_CPU_HAS_L2_CACHE       = 0x0080, /* Secondary cache / URAM */
1206e42fd944SRichard Henderson     SH_CPU_HAS_OP32           = 0x0100, /* 32-bit instruction support */
1207e42fd944SRichard Henderson     SH_CPU_HAS_PTEAEX         = 0x0200, /* PTE ASID Extension support */
1208e42fd944SRichard Henderson };
1209e42fd944SRichard Henderson 
1210e42fd944SRichard Henderson #define ELF_HWCAP get_elf_hwcap()
1211e42fd944SRichard Henderson 
1212e42fd944SRichard Henderson static uint32_t get_elf_hwcap(void)
1213e42fd944SRichard Henderson {
1214e42fd944SRichard Henderson     SuperHCPU *cpu = SUPERH_CPU(thread_cpu);
1215e42fd944SRichard Henderson     uint32_t hwcap = 0;
1216e42fd944SRichard Henderson 
1217e42fd944SRichard Henderson     hwcap |= SH_CPU_HAS_FPU;
1218e42fd944SRichard Henderson 
1219e42fd944SRichard Henderson     if (cpu->env.features & SH_FEATURE_SH4A) {
1220e42fd944SRichard Henderson         hwcap |= SH_CPU_HAS_LLSC;
1221e42fd944SRichard Henderson     }
1222e42fd944SRichard Henderson 
1223e42fd944SRichard Henderson     return hwcap;
1224e42fd944SRichard Henderson }
1225e42fd944SRichard Henderson 
1226fdf9b3e8Sbellard #endif
1227fdf9b3e8Sbellard 
122848733d19Sths #ifdef TARGET_CRIS
122948733d19Sths 
123048733d19Sths #define ELF_START_MMAP 0x80000000
123148733d19Sths 
123248733d19Sths #define ELF_CLASS ELFCLASS32
123348733d19Sths #define ELF_ARCH  EM_CRIS
123448733d19Sths 
1235d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1236d97ef72eSRichard Henderson                                struct image_info *infop)
123748733d19Sths {
123848733d19Sths     regs->erp = infop->entry;
123948733d19Sths }
124048733d19Sths 
124148733d19Sths #define ELF_EXEC_PAGESIZE        8192
124248733d19Sths 
124348733d19Sths #endif
124448733d19Sths 
1245e6e5906bSpbrook #ifdef TARGET_M68K
1246e6e5906bSpbrook 
1247e6e5906bSpbrook #define ELF_START_MMAP 0x80000000
1248e6e5906bSpbrook 
1249e6e5906bSpbrook #define ELF_CLASS       ELFCLASS32
1250e6e5906bSpbrook #define ELF_ARCH        EM_68K
1251e6e5906bSpbrook 
1252e6e5906bSpbrook /* ??? Does this need to do anything?
1253e6e5906bSpbrook    #define ELF_PLAT_INIT(_r) */
1254e6e5906bSpbrook 
1255d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1256d97ef72eSRichard Henderson                                struct image_info *infop)
1257e6e5906bSpbrook {
1258e6e5906bSpbrook     regs->usp = infop->start_stack;
1259e6e5906bSpbrook     regs->sr = 0;
1260e6e5906bSpbrook     regs->pc = infop->entry;
1261e6e5906bSpbrook }
1262e6e5906bSpbrook 
12637a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h.  */
12647a93cc55SNathan Froyd #define ELF_NREG 20
12657a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
12667a93cc55SNathan Froyd 
126705390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env)
12687a93cc55SNathan Froyd {
126986cd7b2dSPaolo Bonzini     (*regs)[0] = tswapreg(env->dregs[1]);
127086cd7b2dSPaolo Bonzini     (*regs)[1] = tswapreg(env->dregs[2]);
127186cd7b2dSPaolo Bonzini     (*regs)[2] = tswapreg(env->dregs[3]);
127286cd7b2dSPaolo Bonzini     (*regs)[3] = tswapreg(env->dregs[4]);
127386cd7b2dSPaolo Bonzini     (*regs)[4] = tswapreg(env->dregs[5]);
127486cd7b2dSPaolo Bonzini     (*regs)[5] = tswapreg(env->dregs[6]);
127586cd7b2dSPaolo Bonzini     (*regs)[6] = tswapreg(env->dregs[7]);
127686cd7b2dSPaolo Bonzini     (*regs)[7] = tswapreg(env->aregs[0]);
127786cd7b2dSPaolo Bonzini     (*regs)[8] = tswapreg(env->aregs[1]);
127886cd7b2dSPaolo Bonzini     (*regs)[9] = tswapreg(env->aregs[2]);
127986cd7b2dSPaolo Bonzini     (*regs)[10] = tswapreg(env->aregs[3]);
128086cd7b2dSPaolo Bonzini     (*regs)[11] = tswapreg(env->aregs[4]);
128186cd7b2dSPaolo Bonzini     (*regs)[12] = tswapreg(env->aregs[5]);
128286cd7b2dSPaolo Bonzini     (*regs)[13] = tswapreg(env->aregs[6]);
128386cd7b2dSPaolo Bonzini     (*regs)[14] = tswapreg(env->dregs[0]);
128486cd7b2dSPaolo Bonzini     (*regs)[15] = tswapreg(env->aregs[7]);
128586cd7b2dSPaolo Bonzini     (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */
128686cd7b2dSPaolo Bonzini     (*regs)[17] = tswapreg(env->sr);
128786cd7b2dSPaolo Bonzini     (*regs)[18] = tswapreg(env->pc);
12887a93cc55SNathan Froyd     (*regs)[19] = 0;  /* FIXME: regs->format | regs->vector */
12897a93cc55SNathan Froyd }
12907a93cc55SNathan Froyd 
12917a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP
1292e6e5906bSpbrook #define ELF_EXEC_PAGESIZE       8192
1293e6e5906bSpbrook 
1294e6e5906bSpbrook #endif
1295e6e5906bSpbrook 
12967a3148a9Sj_mayer #ifdef TARGET_ALPHA
12977a3148a9Sj_mayer 
12987a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL)
12997a3148a9Sj_mayer 
13007a3148a9Sj_mayer #define ELF_CLASS      ELFCLASS64
13017a3148a9Sj_mayer #define ELF_ARCH       EM_ALPHA
13027a3148a9Sj_mayer 
1303d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1304d97ef72eSRichard Henderson                                struct image_info *infop)
13057a3148a9Sj_mayer {
13067a3148a9Sj_mayer     regs->pc = infop->entry;
13077a3148a9Sj_mayer     regs->ps = 8;
13087a3148a9Sj_mayer     regs->usp = infop->start_stack;
13097a3148a9Sj_mayer }
13107a3148a9Sj_mayer 
13117a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE        8192
13127a3148a9Sj_mayer 
13137a3148a9Sj_mayer #endif /* TARGET_ALPHA */
13147a3148a9Sj_mayer 
1315a4c075f1SUlrich Hecht #ifdef TARGET_S390X
1316a4c075f1SUlrich Hecht 
1317a4c075f1SUlrich Hecht #define ELF_START_MMAP (0x20000000000ULL)
1318a4c075f1SUlrich Hecht 
1319a4c075f1SUlrich Hecht #define ELF_CLASS	ELFCLASS64
1320a4c075f1SUlrich Hecht #define ELF_DATA	ELFDATA2MSB
1321a4c075f1SUlrich Hecht #define ELF_ARCH	EM_S390
1322a4c075f1SUlrich Hecht 
13236d88baf1SDavid Hildenbrand #include "elf.h"
13246d88baf1SDavid Hildenbrand 
13256d88baf1SDavid Hildenbrand #define ELF_HWCAP get_elf_hwcap()
13266d88baf1SDavid Hildenbrand 
13276d88baf1SDavid Hildenbrand #define GET_FEATURE(_feat, _hwcap) \
13286d88baf1SDavid Hildenbrand     do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0)
13296d88baf1SDavid Hildenbrand 
13306d88baf1SDavid Hildenbrand static uint32_t get_elf_hwcap(void)
13316d88baf1SDavid Hildenbrand {
13326d88baf1SDavid Hildenbrand     /*
13336d88baf1SDavid Hildenbrand      * Let's assume we always have esan3 and zarch.
13346d88baf1SDavid Hildenbrand      * 31-bit processes can use 64-bit registers (high gprs).
13356d88baf1SDavid Hildenbrand      */
13366d88baf1SDavid Hildenbrand     uint32_t hwcap = HWCAP_S390_ESAN3 | HWCAP_S390_ZARCH | HWCAP_S390_HIGH_GPRS;
13376d88baf1SDavid Hildenbrand 
13386d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_STFLE, HWCAP_S390_STFLE);
13396d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_MSA, HWCAP_S390_MSA);
13406d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_LONG_DISPLACEMENT, HWCAP_S390_LDISP);
13416d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_EXTENDED_IMMEDIATE, HWCAP_S390_EIMM);
13426d88baf1SDavid Hildenbrand     if (s390_has_feat(S390_FEAT_EXTENDED_TRANSLATION_3) &&
13436d88baf1SDavid Hildenbrand         s390_has_feat(S390_FEAT_ETF3_ENH)) {
13446d88baf1SDavid Hildenbrand         hwcap |= HWCAP_S390_ETF3EH;
13456d88baf1SDavid Hildenbrand     }
13466d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS);
13476d88baf1SDavid Hildenbrand 
13486d88baf1SDavid Hildenbrand     return hwcap;
13496d88baf1SDavid Hildenbrand }
13506d88baf1SDavid Hildenbrand 
1351a4c075f1SUlrich Hecht static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
1352a4c075f1SUlrich Hecht {
1353a4c075f1SUlrich Hecht     regs->psw.addr = infop->entry;
1354a4c075f1SUlrich Hecht     regs->psw.mask = PSW_MASK_64 | PSW_MASK_32;
1355a4c075f1SUlrich Hecht     regs->gprs[15] = infop->start_stack;
1356a4c075f1SUlrich Hecht }
1357a4c075f1SUlrich Hecht 
1358a4c075f1SUlrich Hecht #endif /* TARGET_S390X */
1359a4c075f1SUlrich Hecht 
1360b16189b2SChen Gang #ifdef TARGET_TILEGX
1361b16189b2SChen Gang 
1362b16189b2SChen Gang /* 42 bits real used address, a half for user mode */
1363b16189b2SChen Gang #define ELF_START_MMAP (0x00000020000000000ULL)
1364b16189b2SChen Gang 
1365b16189b2SChen Gang #define elf_check_arch(x) ((x) == EM_TILEGX)
1366b16189b2SChen Gang 
1367b16189b2SChen Gang #define ELF_CLASS   ELFCLASS64
1368b16189b2SChen Gang #define ELF_DATA    ELFDATA2LSB
1369b16189b2SChen Gang #define ELF_ARCH    EM_TILEGX
1370b16189b2SChen Gang 
1371b16189b2SChen Gang static inline void init_thread(struct target_pt_regs *regs,
1372b16189b2SChen Gang                                struct image_info *infop)
1373b16189b2SChen Gang {
1374b16189b2SChen Gang     regs->pc = infop->entry;
1375b16189b2SChen Gang     regs->sp = infop->start_stack;
1376b16189b2SChen Gang 
1377b16189b2SChen Gang }
1378b16189b2SChen Gang 
1379b16189b2SChen Gang #define ELF_EXEC_PAGESIZE        65536 /* TILE-Gx page size is 64KB */
1380b16189b2SChen Gang 
1381b16189b2SChen Gang #endif /* TARGET_TILEGX */
1382b16189b2SChen Gang 
138347ae93cdSMichael Clark #ifdef TARGET_RISCV
138447ae93cdSMichael Clark 
138547ae93cdSMichael Clark #define ELF_START_MMAP 0x80000000
138647ae93cdSMichael Clark #define ELF_ARCH  EM_RISCV
138747ae93cdSMichael Clark 
138847ae93cdSMichael Clark #ifdef TARGET_RISCV32
138947ae93cdSMichael Clark #define ELF_CLASS ELFCLASS32
139047ae93cdSMichael Clark #else
139147ae93cdSMichael Clark #define ELF_CLASS ELFCLASS64
139247ae93cdSMichael Clark #endif
139347ae93cdSMichael Clark 
139447ae93cdSMichael Clark static inline void init_thread(struct target_pt_regs *regs,
139547ae93cdSMichael Clark                                struct image_info *infop)
139647ae93cdSMichael Clark {
139747ae93cdSMichael Clark     regs->sepc = infop->entry;
139847ae93cdSMichael Clark     regs->sp = infop->start_stack;
139947ae93cdSMichael Clark }
140047ae93cdSMichael Clark 
140147ae93cdSMichael Clark #define ELF_EXEC_PAGESIZE 4096
140247ae93cdSMichael Clark 
140347ae93cdSMichael Clark #endif /* TARGET_RISCV */
140447ae93cdSMichael Clark 
14057c248bcdSRichard Henderson #ifdef TARGET_HPPA
14067c248bcdSRichard Henderson 
14077c248bcdSRichard Henderson #define ELF_START_MMAP  0x80000000
14087c248bcdSRichard Henderson #define ELF_CLASS       ELFCLASS32
14097c248bcdSRichard Henderson #define ELF_ARCH        EM_PARISC
14107c248bcdSRichard Henderson #define ELF_PLATFORM    "PARISC"
14117c248bcdSRichard Henderson #define STACK_GROWS_DOWN 0
14127c248bcdSRichard Henderson #define STACK_ALIGNMENT  64
14137c248bcdSRichard Henderson 
14147c248bcdSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
14157c248bcdSRichard Henderson                                struct image_info *infop)
14167c248bcdSRichard Henderson {
14177c248bcdSRichard Henderson     regs->iaoq[0] = infop->entry;
14187c248bcdSRichard Henderson     regs->iaoq[1] = infop->entry + 4;
14197c248bcdSRichard Henderson     regs->gr[23] = 0;
14207c248bcdSRichard Henderson     regs->gr[24] = infop->arg_start;
14217c248bcdSRichard Henderson     regs->gr[25] = (infop->arg_end - infop->arg_start) / sizeof(abi_ulong);
14227c248bcdSRichard Henderson     /* The top-of-stack contains a linkage buffer.  */
14237c248bcdSRichard Henderson     regs->gr[30] = infop->start_stack + 64;
14247c248bcdSRichard Henderson     regs->gr[31] = infop->entry;
14257c248bcdSRichard Henderson }
14267c248bcdSRichard Henderson 
14277c248bcdSRichard Henderson #endif /* TARGET_HPPA */
14287c248bcdSRichard Henderson 
1429ba7651fbSMax Filippov #ifdef TARGET_XTENSA
1430ba7651fbSMax Filippov 
1431ba7651fbSMax Filippov #define ELF_START_MMAP 0x20000000
1432ba7651fbSMax Filippov 
1433ba7651fbSMax Filippov #define ELF_CLASS       ELFCLASS32
1434ba7651fbSMax Filippov #define ELF_ARCH        EM_XTENSA
1435ba7651fbSMax Filippov 
1436ba7651fbSMax Filippov static inline void init_thread(struct target_pt_regs *regs,
1437ba7651fbSMax Filippov                                struct image_info *infop)
1438ba7651fbSMax Filippov {
1439ba7651fbSMax Filippov     regs->windowbase = 0;
1440ba7651fbSMax Filippov     regs->windowstart = 1;
1441ba7651fbSMax Filippov     regs->areg[1] = infop->start_stack;
1442ba7651fbSMax Filippov     regs->pc = infop->entry;
1443ba7651fbSMax Filippov }
1444ba7651fbSMax Filippov 
1445ba7651fbSMax Filippov /* See linux kernel: arch/xtensa/include/asm/elf.h.  */
1446ba7651fbSMax Filippov #define ELF_NREG 128
1447ba7651fbSMax Filippov typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1448ba7651fbSMax Filippov 
1449ba7651fbSMax Filippov enum {
1450ba7651fbSMax Filippov     TARGET_REG_PC,
1451ba7651fbSMax Filippov     TARGET_REG_PS,
1452ba7651fbSMax Filippov     TARGET_REG_LBEG,
1453ba7651fbSMax Filippov     TARGET_REG_LEND,
1454ba7651fbSMax Filippov     TARGET_REG_LCOUNT,
1455ba7651fbSMax Filippov     TARGET_REG_SAR,
1456ba7651fbSMax Filippov     TARGET_REG_WINDOWSTART,
1457ba7651fbSMax Filippov     TARGET_REG_WINDOWBASE,
1458ba7651fbSMax Filippov     TARGET_REG_THREADPTR,
1459ba7651fbSMax Filippov     TARGET_REG_AR0 = 64,
1460ba7651fbSMax Filippov };
1461ba7651fbSMax Filippov 
1462ba7651fbSMax Filippov static void elf_core_copy_regs(target_elf_gregset_t *regs,
1463ba7651fbSMax Filippov                                const CPUXtensaState *env)
1464ba7651fbSMax Filippov {
1465ba7651fbSMax Filippov     unsigned i;
1466ba7651fbSMax Filippov 
1467ba7651fbSMax Filippov     (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
1468ba7651fbSMax Filippov     (*regs)[TARGET_REG_PS] = tswapreg(env->sregs[PS] & ~PS_EXCM);
1469ba7651fbSMax Filippov     (*regs)[TARGET_REG_LBEG] = tswapreg(env->sregs[LBEG]);
1470ba7651fbSMax Filippov     (*regs)[TARGET_REG_LEND] = tswapreg(env->sregs[LEND]);
1471ba7651fbSMax Filippov     (*regs)[TARGET_REG_LCOUNT] = tswapreg(env->sregs[LCOUNT]);
1472ba7651fbSMax Filippov     (*regs)[TARGET_REG_SAR] = tswapreg(env->sregs[SAR]);
1473ba7651fbSMax Filippov     (*regs)[TARGET_REG_WINDOWSTART] = tswapreg(env->sregs[WINDOW_START]);
1474ba7651fbSMax Filippov     (*regs)[TARGET_REG_WINDOWBASE] = tswapreg(env->sregs[WINDOW_BASE]);
1475ba7651fbSMax Filippov     (*regs)[TARGET_REG_THREADPTR] = tswapreg(env->uregs[THREADPTR]);
1476ba7651fbSMax Filippov     xtensa_sync_phys_from_window((CPUXtensaState *)env);
1477ba7651fbSMax Filippov     for (i = 0; i < env->config->nareg; ++i) {
1478ba7651fbSMax Filippov         (*regs)[TARGET_REG_AR0 + i] = tswapreg(env->phys_regs[i]);
1479ba7651fbSMax Filippov     }
1480ba7651fbSMax Filippov }
1481ba7651fbSMax Filippov 
1482ba7651fbSMax Filippov #define USE_ELF_CORE_DUMP
1483ba7651fbSMax Filippov #define ELF_EXEC_PAGESIZE       4096
1484ba7651fbSMax Filippov 
1485ba7651fbSMax Filippov #endif /* TARGET_XTENSA */
1486ba7651fbSMax Filippov 
148715338fd7Sbellard #ifndef ELF_PLATFORM
148815338fd7Sbellard #define ELF_PLATFORM (NULL)
148915338fd7Sbellard #endif
149015338fd7Sbellard 
149175be901cSPeter Crosthwaite #ifndef ELF_MACHINE
149275be901cSPeter Crosthwaite #define ELF_MACHINE ELF_ARCH
149375be901cSPeter Crosthwaite #endif
149475be901cSPeter Crosthwaite 
1495d276a604SPeter Crosthwaite #ifndef elf_check_arch
1496d276a604SPeter Crosthwaite #define elf_check_arch(x) ((x) == ELF_ARCH)
1497d276a604SPeter Crosthwaite #endif
1498d276a604SPeter Crosthwaite 
1499ace3d654SCarlo Marcelo Arenas Belón #ifndef elf_check_abi
1500ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (1)
1501ace3d654SCarlo Marcelo Arenas Belón #endif
1502ace3d654SCarlo Marcelo Arenas Belón 
150315338fd7Sbellard #ifndef ELF_HWCAP
150415338fd7Sbellard #define ELF_HWCAP 0
150515338fd7Sbellard #endif
150615338fd7Sbellard 
15077c4ee5bcSRichard Henderson #ifndef STACK_GROWS_DOWN
15087c4ee5bcSRichard Henderson #define STACK_GROWS_DOWN 1
15097c4ee5bcSRichard Henderson #endif
15107c4ee5bcSRichard Henderson 
15117c4ee5bcSRichard Henderson #ifndef STACK_ALIGNMENT
15127c4ee5bcSRichard Henderson #define STACK_ALIGNMENT 16
15137c4ee5bcSRichard Henderson #endif
15147c4ee5bcSRichard Henderson 
1515992f48a0Sblueswir1 #ifdef TARGET_ABI32
1516cb33da57Sblueswir1 #undef ELF_CLASS
1517992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32
1518cb33da57Sblueswir1 #undef bswaptls
1519cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr)
1520cb33da57Sblueswir1 #endif
1521cb33da57Sblueswir1 
152231e31b8aSbellard #include "elf.h"
152309bfb054Sbellard 
152409bfb054Sbellard struct exec
152509bfb054Sbellard {
152609bfb054Sbellard     unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
152709bfb054Sbellard     unsigned int a_text;   /* length of text, in bytes */
152809bfb054Sbellard     unsigned int a_data;   /* length of data, in bytes */
152909bfb054Sbellard     unsigned int a_bss;    /* length of uninitialized data area, in bytes */
153009bfb054Sbellard     unsigned int a_syms;   /* length of symbol table data in file, in bytes */
153109bfb054Sbellard     unsigned int a_entry;  /* start address */
153209bfb054Sbellard     unsigned int a_trsize; /* length of relocation info for text, in bytes */
153309bfb054Sbellard     unsigned int a_drsize; /* length of relocation info for data, in bytes */
153409bfb054Sbellard };
153509bfb054Sbellard 
153609bfb054Sbellard 
153709bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff)
153809bfb054Sbellard #define OMAGIC 0407
153909bfb054Sbellard #define NMAGIC 0410
154009bfb054Sbellard #define ZMAGIC 0413
154109bfb054Sbellard #define QMAGIC 0314
154209bfb054Sbellard 
154331e31b8aSbellard /* Necessary parameters */
154494894ff2SShivaprasad G Bhat #define TARGET_ELF_EXEC_PAGESIZE \
154594894ff2SShivaprasad G Bhat         (((eppnt->p_align & ~qemu_host_page_mask) != 0) ? \
154694894ff2SShivaprasad G Bhat          TARGET_PAGE_SIZE : MAX(qemu_host_page_size, TARGET_PAGE_SIZE))
154794894ff2SShivaprasad G Bhat #define TARGET_ELF_PAGELENGTH(_v) ROUND_UP((_v), TARGET_ELF_EXEC_PAGESIZE)
154879cb1f1dSYongbok Kim #define TARGET_ELF_PAGESTART(_v) ((_v) & \
154979cb1f1dSYongbok Kim                                  ~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1))
155054936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
155131e31b8aSbellard 
1552e0d1673dSLirong Yuan #define DLINFO_ITEMS 16
155331e31b8aSbellard 
155409bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
155509bfb054Sbellard {
155609bfb054Sbellard     memcpy(to, from, n);
155709bfb054Sbellard }
155809bfb054Sbellard 
155931e31b8aSbellard #ifdef BSWAP_NEEDED
156092a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr)
156131e31b8aSbellard {
156231e31b8aSbellard     bswap16s(&ehdr->e_type);            /* Object file type */
156331e31b8aSbellard     bswap16s(&ehdr->e_machine);         /* Architecture */
156431e31b8aSbellard     bswap32s(&ehdr->e_version);         /* Object file version */
156592a31b1fSbellard     bswaptls(&ehdr->e_entry);           /* Entry point virtual address */
156692a31b1fSbellard     bswaptls(&ehdr->e_phoff);           /* Program header table file offset */
156792a31b1fSbellard     bswaptls(&ehdr->e_shoff);           /* Section header table file offset */
156831e31b8aSbellard     bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
156931e31b8aSbellard     bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
157031e31b8aSbellard     bswap16s(&ehdr->e_phentsize);       /* Program header table entry size */
157131e31b8aSbellard     bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
157231e31b8aSbellard     bswap16s(&ehdr->e_shentsize);       /* Section header table entry size */
157331e31b8aSbellard     bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
157431e31b8aSbellard     bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */
157531e31b8aSbellard }
157631e31b8aSbellard 
1577991f8f0cSRichard Henderson static void bswap_phdr(struct elf_phdr *phdr, int phnum)
157831e31b8aSbellard {
1579991f8f0cSRichard Henderson     int i;
1580991f8f0cSRichard Henderson     for (i = 0; i < phnum; ++i, ++phdr) {
158131e31b8aSbellard         bswap32s(&phdr->p_type);        /* Segment type */
1582991f8f0cSRichard Henderson         bswap32s(&phdr->p_flags);       /* Segment flags */
158392a31b1fSbellard         bswaptls(&phdr->p_offset);      /* Segment file offset */
158492a31b1fSbellard         bswaptls(&phdr->p_vaddr);       /* Segment virtual address */
158592a31b1fSbellard         bswaptls(&phdr->p_paddr);       /* Segment physical address */
158692a31b1fSbellard         bswaptls(&phdr->p_filesz);      /* Segment size in file */
158792a31b1fSbellard         bswaptls(&phdr->p_memsz);       /* Segment size in memory */
158892a31b1fSbellard         bswaptls(&phdr->p_align);       /* Segment alignment */
158931e31b8aSbellard     }
1590991f8f0cSRichard Henderson }
1591689f936fSbellard 
1592991f8f0cSRichard Henderson static void bswap_shdr(struct elf_shdr *shdr, int shnum)
1593689f936fSbellard {
1594991f8f0cSRichard Henderson     int i;
1595991f8f0cSRichard Henderson     for (i = 0; i < shnum; ++i, ++shdr) {
1596689f936fSbellard         bswap32s(&shdr->sh_name);
1597689f936fSbellard         bswap32s(&shdr->sh_type);
159892a31b1fSbellard         bswaptls(&shdr->sh_flags);
159992a31b1fSbellard         bswaptls(&shdr->sh_addr);
160092a31b1fSbellard         bswaptls(&shdr->sh_offset);
160192a31b1fSbellard         bswaptls(&shdr->sh_size);
1602689f936fSbellard         bswap32s(&shdr->sh_link);
1603689f936fSbellard         bswap32s(&shdr->sh_info);
160492a31b1fSbellard         bswaptls(&shdr->sh_addralign);
160592a31b1fSbellard         bswaptls(&shdr->sh_entsize);
1606689f936fSbellard     }
1607991f8f0cSRichard Henderson }
1608689f936fSbellard 
16097a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym)
1610689f936fSbellard {
1611689f936fSbellard     bswap32s(&sym->st_name);
16127a3148a9Sj_mayer     bswaptls(&sym->st_value);
16137a3148a9Sj_mayer     bswaptls(&sym->st_size);
1614689f936fSbellard     bswap16s(&sym->st_shndx);
1615689f936fSbellard }
16165dd0db52SStefan Markovic 
16175dd0db52SStefan Markovic #ifdef TARGET_MIPS
16185dd0db52SStefan Markovic static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags)
16195dd0db52SStefan Markovic {
16205dd0db52SStefan Markovic     bswap16s(&abiflags->version);
16215dd0db52SStefan Markovic     bswap32s(&abiflags->ases);
16225dd0db52SStefan Markovic     bswap32s(&abiflags->isa_ext);
16235dd0db52SStefan Markovic     bswap32s(&abiflags->flags1);
16245dd0db52SStefan Markovic     bswap32s(&abiflags->flags2);
16255dd0db52SStefan Markovic }
16265dd0db52SStefan Markovic #endif
1627991f8f0cSRichard Henderson #else
1628991f8f0cSRichard Henderson static inline void bswap_ehdr(struct elfhdr *ehdr) { }
1629991f8f0cSRichard Henderson static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
1630991f8f0cSRichard Henderson static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
1631991f8f0cSRichard Henderson static inline void bswap_sym(struct elf_sym *sym) { }
16325dd0db52SStefan Markovic #ifdef TARGET_MIPS
16335dd0db52SStefan Markovic static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { }
16345dd0db52SStefan Markovic #endif
163531e31b8aSbellard #endif
163631e31b8aSbellard 
1637edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
16389349b4f9SAndreas Färber static int elf_core_dump(int, const CPUArchState *);
1639edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
1640682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
1641edf8e2afSMika Westerberg 
16429058abddSRichard Henderson /* Verify the portions of EHDR within E_IDENT for the target.
16439058abddSRichard Henderson    This can be performed before bswapping the entire header.  */
16449058abddSRichard Henderson static bool elf_check_ident(struct elfhdr *ehdr)
16459058abddSRichard Henderson {
16469058abddSRichard Henderson     return (ehdr->e_ident[EI_MAG0] == ELFMAG0
16479058abddSRichard Henderson             && ehdr->e_ident[EI_MAG1] == ELFMAG1
16489058abddSRichard Henderson             && ehdr->e_ident[EI_MAG2] == ELFMAG2
16499058abddSRichard Henderson             && ehdr->e_ident[EI_MAG3] == ELFMAG3
16509058abddSRichard Henderson             && ehdr->e_ident[EI_CLASS] == ELF_CLASS
16519058abddSRichard Henderson             && ehdr->e_ident[EI_DATA] == ELF_DATA
16529058abddSRichard Henderson             && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
16539058abddSRichard Henderson }
16549058abddSRichard Henderson 
16559058abddSRichard Henderson /* Verify the portions of EHDR outside of E_IDENT for the target.
16569058abddSRichard Henderson    This has to wait until after bswapping the header.  */
16579058abddSRichard Henderson static bool elf_check_ehdr(struct elfhdr *ehdr)
16589058abddSRichard Henderson {
16599058abddSRichard Henderson     return (elf_check_arch(ehdr->e_machine)
1660ace3d654SCarlo Marcelo Arenas Belón             && elf_check_abi(ehdr->e_flags)
16619058abddSRichard Henderson             && ehdr->e_ehsize == sizeof(struct elfhdr)
16629058abddSRichard Henderson             && ehdr->e_phentsize == sizeof(struct elf_phdr)
16639058abddSRichard Henderson             && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
16649058abddSRichard Henderson }
16659058abddSRichard Henderson 
166631e31b8aSbellard /*
1667e5fe0c52Spbrook  * 'copy_elf_strings()' copies argument/envelope strings from user
166831e31b8aSbellard  * memory to free pages in kernel mem. These are in a format ready
166931e31b8aSbellard  * to be put directly into the top of new user memory.
167031e31b8aSbellard  *
167131e31b8aSbellard  */
167259baae9aSStefan Brüns static abi_ulong copy_elf_strings(int argc, char **argv, char *scratch,
167359baae9aSStefan Brüns                                   abi_ulong p, abi_ulong stack_limit)
167431e31b8aSbellard {
167559baae9aSStefan Brüns     char *tmp;
16767c4ee5bcSRichard Henderson     int len, i;
167759baae9aSStefan Brüns     abi_ulong top = p;
167831e31b8aSbellard 
167931e31b8aSbellard     if (!p) {
168031e31b8aSbellard         return 0;       /* bullet-proofing */
168131e31b8aSbellard     }
168259baae9aSStefan Brüns 
16837c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
16847c4ee5bcSRichard Henderson         int offset = ((p - 1) % TARGET_PAGE_SIZE) + 1;
16857c4ee5bcSRichard Henderson         for (i = argc - 1; i >= 0; --i) {
16867c4ee5bcSRichard Henderson             tmp = argv[i];
1687edf779ffSbellard             if (!tmp) {
168831e31b8aSbellard                 fprintf(stderr, "VFS: argc is wrong");
168931e31b8aSbellard                 exit(-1);
169031e31b8aSbellard             }
169159baae9aSStefan Brüns             len = strlen(tmp) + 1;
169259baae9aSStefan Brüns             tmp += len;
169359baae9aSStefan Brüns 
169459baae9aSStefan Brüns             if (len > (p - stack_limit)) {
169531e31b8aSbellard                 return 0;
169631e31b8aSbellard             }
169731e31b8aSbellard             while (len) {
169831e31b8aSbellard                 int bytes_to_copy = (len > offset) ? offset : len;
169931e31b8aSbellard                 tmp -= bytes_to_copy;
170031e31b8aSbellard                 p -= bytes_to_copy;
170131e31b8aSbellard                 offset -= bytes_to_copy;
170231e31b8aSbellard                 len -= bytes_to_copy;
170359baae9aSStefan Brüns 
170459baae9aSStefan Brüns                 memcpy_fromfs(scratch + offset, tmp, bytes_to_copy);
170559baae9aSStefan Brüns 
170659baae9aSStefan Brüns                 if (offset == 0) {
170759baae9aSStefan Brüns                     memcpy_to_target(p, scratch, top - p);
170859baae9aSStefan Brüns                     top = p;
170959baae9aSStefan Brüns                     offset = TARGET_PAGE_SIZE;
171031e31b8aSbellard                 }
171131e31b8aSbellard             }
171231e31b8aSbellard         }
17137c4ee5bcSRichard Henderson         if (p != top) {
171459baae9aSStefan Brüns             memcpy_to_target(p, scratch + offset, top - p);
171559baae9aSStefan Brüns         }
17167c4ee5bcSRichard Henderson     } else {
17177c4ee5bcSRichard Henderson         int remaining = TARGET_PAGE_SIZE - (p % TARGET_PAGE_SIZE);
17187c4ee5bcSRichard Henderson         for (i = 0; i < argc; ++i) {
17197c4ee5bcSRichard Henderson             tmp = argv[i];
17207c4ee5bcSRichard Henderson             if (!tmp) {
17217c4ee5bcSRichard Henderson                 fprintf(stderr, "VFS: argc is wrong");
17227c4ee5bcSRichard Henderson                 exit(-1);
17237c4ee5bcSRichard Henderson             }
17247c4ee5bcSRichard Henderson             len = strlen(tmp) + 1;
17257c4ee5bcSRichard Henderson             if (len > (stack_limit - p)) {
17267c4ee5bcSRichard Henderson                 return 0;
17277c4ee5bcSRichard Henderson             }
17287c4ee5bcSRichard Henderson             while (len) {
17297c4ee5bcSRichard Henderson                 int bytes_to_copy = (len > remaining) ? remaining : len;
17307c4ee5bcSRichard Henderson 
17317c4ee5bcSRichard Henderson                 memcpy_fromfs(scratch + (p - top), tmp, bytes_to_copy);
17327c4ee5bcSRichard Henderson 
17337c4ee5bcSRichard Henderson                 tmp += bytes_to_copy;
17347c4ee5bcSRichard Henderson                 remaining -= bytes_to_copy;
17357c4ee5bcSRichard Henderson                 p += bytes_to_copy;
17367c4ee5bcSRichard Henderson                 len -= bytes_to_copy;
17377c4ee5bcSRichard Henderson 
17387c4ee5bcSRichard Henderson                 if (remaining == 0) {
17397c4ee5bcSRichard Henderson                     memcpy_to_target(top, scratch, p - top);
17407c4ee5bcSRichard Henderson                     top = p;
17417c4ee5bcSRichard Henderson                     remaining = TARGET_PAGE_SIZE;
17427c4ee5bcSRichard Henderson                 }
17437c4ee5bcSRichard Henderson             }
17447c4ee5bcSRichard Henderson         }
17457c4ee5bcSRichard Henderson         if (p != top) {
17467c4ee5bcSRichard Henderson             memcpy_to_target(top, scratch, p - top);
17477c4ee5bcSRichard Henderson         }
17487c4ee5bcSRichard Henderson     }
174959baae9aSStefan Brüns 
175031e31b8aSbellard     return p;
175131e31b8aSbellard }
175231e31b8aSbellard 
175359baae9aSStefan Brüns /* Older linux kernels provide up to MAX_ARG_PAGES (default: 32) of
175459baae9aSStefan Brüns  * argument/environment space. Newer kernels (>2.6.33) allow more,
175559baae9aSStefan Brüns  * dependent on stack size, but guarantee at least 32 pages for
175659baae9aSStefan Brüns  * backwards compatibility.
175759baae9aSStefan Brüns  */
175859baae9aSStefan Brüns #define STACK_LOWER_LIMIT (32 * TARGET_PAGE_SIZE)
175959baae9aSStefan Brüns 
176059baae9aSStefan Brüns static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
176131e31b8aSbellard                                  struct image_info *info)
176231e31b8aSbellard {
176359baae9aSStefan Brüns     abi_ulong size, error, guard;
176431e31b8aSbellard 
1765703e0e89SRichard Henderson     size = guest_stack_size;
176659baae9aSStefan Brüns     if (size < STACK_LOWER_LIMIT) {
176759baae9aSStefan Brüns         size = STACK_LOWER_LIMIT;
176860dcbcb5SRichard Henderson     }
176960dcbcb5SRichard Henderson     guard = TARGET_PAGE_SIZE;
177060dcbcb5SRichard Henderson     if (guard < qemu_real_host_page_size) {
177160dcbcb5SRichard Henderson         guard = qemu_real_host_page_size;
177260dcbcb5SRichard Henderson     }
177360dcbcb5SRichard Henderson 
177460dcbcb5SRichard Henderson     error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
177560dcbcb5SRichard Henderson                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
177609bfb054Sbellard     if (error == -1) {
177760dcbcb5SRichard Henderson         perror("mmap stack");
177831e31b8aSbellard         exit(-1);
177931e31b8aSbellard     }
178031e31b8aSbellard 
178160dcbcb5SRichard Henderson     /* We reserve one extra page at the top of the stack as guard.  */
17827c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
178360dcbcb5SRichard Henderson         target_mprotect(error, guard, PROT_NONE);
178460dcbcb5SRichard Henderson         info->stack_limit = error + guard;
178559baae9aSStefan Brüns         return info->stack_limit + size - sizeof(void *);
17867c4ee5bcSRichard Henderson     } else {
17877c4ee5bcSRichard Henderson         target_mprotect(error + size, guard, PROT_NONE);
17887c4ee5bcSRichard Henderson         info->stack_limit = error + size;
17897c4ee5bcSRichard Henderson         return error;
17907c4ee5bcSRichard Henderson     }
179131e31b8aSbellard }
179231e31b8aSbellard 
1793cf129f3aSRichard Henderson /* Map and zero the bss.  We need to explicitly zero any fractional pages
1794cf129f3aSRichard Henderson    after the data section (i.e. bss).  */
1795cf129f3aSRichard Henderson static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
179631e31b8aSbellard {
1797cf129f3aSRichard Henderson     uintptr_t host_start, host_map_start, host_end;
1798cf129f3aSRichard Henderson 
1799cf129f3aSRichard Henderson     last_bss = TARGET_PAGE_ALIGN(last_bss);
1800cf129f3aSRichard Henderson 
1801cf129f3aSRichard Henderson     /* ??? There is confusion between qemu_real_host_page_size and
1802cf129f3aSRichard Henderson        qemu_host_page_size here and elsewhere in target_mmap, which
1803cf129f3aSRichard Henderson        may lead to the end of the data section mapping from the file
1804cf129f3aSRichard Henderson        not being mapped.  At least there was an explicit test and
1805cf129f3aSRichard Henderson        comment for that here, suggesting that "the file size must
1806cf129f3aSRichard Henderson        be known".  The comment probably pre-dates the introduction
1807cf129f3aSRichard Henderson        of the fstat system call in target_mmap which does in fact
1808cf129f3aSRichard Henderson        find out the size.  What isn't clear is if the workaround
1809cf129f3aSRichard Henderson        here is still actually needed.  For now, continue with it,
1810cf129f3aSRichard Henderson        but merge it with the "normal" mmap that would allocate the bss.  */
1811cf129f3aSRichard Henderson 
1812cf129f3aSRichard Henderson     host_start = (uintptr_t) g2h(elf_bss);
1813cf129f3aSRichard Henderson     host_end = (uintptr_t) g2h(last_bss);
18140c2d70c4SPaolo Bonzini     host_map_start = REAL_HOST_PAGE_ALIGN(host_start);
1815cf129f3aSRichard Henderson 
1816cf129f3aSRichard Henderson     if (host_map_start < host_end) {
1817cf129f3aSRichard Henderson         void *p = mmap((void *)host_map_start, host_end - host_map_start,
1818cf129f3aSRichard Henderson                        prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1819cf129f3aSRichard Henderson         if (p == MAP_FAILED) {
182031e31b8aSbellard             perror("cannot mmap brk");
182131e31b8aSbellard             exit(-1);
182231e31b8aSbellard         }
1823f46e9a0bSTom Musta     }
1824cf129f3aSRichard Henderson 
1825f46e9a0bSTom Musta     /* Ensure that the bss page(s) are valid */
1826f46e9a0bSTom Musta     if ((page_get_flags(last_bss-1) & prot) != prot) {
1827cf129f3aSRichard Henderson         page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot | PAGE_VALID);
182831e31b8aSbellard     }
182931e31b8aSbellard 
1830cf129f3aSRichard Henderson     if (host_start < host_map_start) {
1831cf129f3aSRichard Henderson         memset((void *)host_start, 0, host_map_start - host_start);
1832853d6f7aSbellard     }
1833853d6f7aSbellard }
1834853d6f7aSbellard 
1835cf58affeSChristophe Lyon #ifdef TARGET_ARM
1836cf58affeSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec)
1837cf58affeSChristophe Lyon {
1838cf58affeSChristophe Lyon     return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC;
1839cf58affeSChristophe Lyon }
1840cf58affeSChristophe Lyon #else
1841a99856cdSChristophe Lyon /* Default implementation, always false.  */
1842a99856cdSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec)
1843a99856cdSChristophe Lyon {
1844a99856cdSChristophe Lyon     return 0;
1845a99856cdSChristophe Lyon }
1846cf58affeSChristophe Lyon #endif
1847a99856cdSChristophe Lyon 
18481af02e83SMike Frysinger static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
18491af02e83SMike Frysinger {
18501af02e83SMike Frysinger     uint16_t n;
18511af02e83SMike Frysinger     struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
18521af02e83SMike Frysinger 
18531af02e83SMike Frysinger     /* elf32_fdpic_loadseg */
18541af02e83SMike Frysinger     n = info->nsegs;
18551af02e83SMike Frysinger     while (n--) {
18561af02e83SMike Frysinger         sp -= 12;
18571af02e83SMike Frysinger         put_user_u32(loadsegs[n].addr, sp+0);
18581af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_vaddr, sp+4);
18591af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_memsz, sp+8);
18601af02e83SMike Frysinger     }
18611af02e83SMike Frysinger 
18621af02e83SMike Frysinger     /* elf32_fdpic_loadmap */
18631af02e83SMike Frysinger     sp -= 4;
18641af02e83SMike Frysinger     put_user_u16(0, sp+0); /* version */
18651af02e83SMike Frysinger     put_user_u16(info->nsegs, sp+2); /* nsegs */
18661af02e83SMike Frysinger 
18671af02e83SMike Frysinger     info->personality = PER_LINUX_FDPIC;
18681af02e83SMike Frysinger     info->loadmap_addr = sp;
18691af02e83SMike Frysinger 
18701af02e83SMike Frysinger     return sp;
18711af02e83SMike Frysinger }
18721af02e83SMike Frysinger 
1873992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
187431e31b8aSbellard                                    struct elfhdr *exec,
18758e62a717SRichard Henderson                                    struct image_info *info,
18768e62a717SRichard Henderson                                    struct image_info *interp_info)
187731e31b8aSbellard {
1878992f48a0Sblueswir1     abi_ulong sp;
18797c4ee5bcSRichard Henderson     abi_ulong u_argc, u_argv, u_envp, u_auxv;
188053a5960aSpbrook     int size;
188114322badSLaurent ALFONSI     int i;
188214322badSLaurent ALFONSI     abi_ulong u_rand_bytes;
188314322badSLaurent ALFONSI     uint8_t k_rand_bytes[16];
1884992f48a0Sblueswir1     abi_ulong u_platform;
188515338fd7Sbellard     const char *k_platform;
1886863cf0b7Sj_mayer     const int n = sizeof(elf_addr_t);
188731e31b8aSbellard 
188853a5960aSpbrook     sp = p;
18891af02e83SMike Frysinger 
18901af02e83SMike Frysinger     /* Needs to be before we load the env/argc/... */
18911af02e83SMike Frysinger     if (elf_is_fdpic(exec)) {
18921af02e83SMike Frysinger         /* Need 4 byte alignment for these structs */
18931af02e83SMike Frysinger         sp &= ~3;
18941af02e83SMike Frysinger         sp = loader_build_fdpic_loadmap(info, sp);
18951af02e83SMike Frysinger         info->other_info = interp_info;
18961af02e83SMike Frysinger         if (interp_info) {
18971af02e83SMike Frysinger             interp_info->other_info = info;
18981af02e83SMike Frysinger             sp = loader_build_fdpic_loadmap(interp_info, sp);
18993cb10cfaSChristophe Lyon             info->interpreter_loadmap_addr = interp_info->loadmap_addr;
19003cb10cfaSChristophe Lyon             info->interpreter_pt_dynamic_addr = interp_info->pt_dynamic_addr;
19013cb10cfaSChristophe Lyon         } else {
19023cb10cfaSChristophe Lyon             info->interpreter_loadmap_addr = 0;
19033cb10cfaSChristophe Lyon             info->interpreter_pt_dynamic_addr = 0;
19041af02e83SMike Frysinger         }
19051af02e83SMike Frysinger     }
19061af02e83SMike Frysinger 
190753a5960aSpbrook     u_platform = 0;
190815338fd7Sbellard     k_platform = ELF_PLATFORM;
190915338fd7Sbellard     if (k_platform) {
191015338fd7Sbellard         size_t len = strlen(k_platform) + 1;
19117c4ee5bcSRichard Henderson         if (STACK_GROWS_DOWN) {
191253a5960aSpbrook             sp -= (len + n - 1) & ~(n - 1);
191353a5960aSpbrook             u_platform = sp;
1914579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
191553a5960aSpbrook             memcpy_to_target(sp, k_platform, len);
19167c4ee5bcSRichard Henderson         } else {
19177c4ee5bcSRichard Henderson             memcpy_to_target(sp, k_platform, len);
19187c4ee5bcSRichard Henderson             u_platform = sp;
19197c4ee5bcSRichard Henderson             sp += len + 1;
19207c4ee5bcSRichard Henderson         }
19217c4ee5bcSRichard Henderson     }
19227c4ee5bcSRichard Henderson 
19237c4ee5bcSRichard Henderson     /* Provide 16 byte alignment for the PRNG, and basic alignment for
19247c4ee5bcSRichard Henderson      * the argv and envp pointers.
19257c4ee5bcSRichard Henderson      */
19267c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
19277c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_DOWN(sp, 16);
19287c4ee5bcSRichard Henderson     } else {
19297c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_UP(sp, 16);
193015338fd7Sbellard     }
193114322badSLaurent ALFONSI 
193214322badSLaurent ALFONSI     /*
1933c6a2377fSRichard Henderson      * Generate 16 random bytes for userspace PRNG seeding.
193414322badSLaurent ALFONSI      */
1935c6a2377fSRichard Henderson     qemu_guest_getrandom_nofail(k_rand_bytes, sizeof(k_rand_bytes));
19367c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
193714322badSLaurent ALFONSI         sp -= 16;
193814322badSLaurent ALFONSI         u_rand_bytes = sp;
193914322badSLaurent ALFONSI         /* FIXME - check return value of memcpy_to_target() for failure */
194014322badSLaurent ALFONSI         memcpy_to_target(sp, k_rand_bytes, 16);
19417c4ee5bcSRichard Henderson     } else {
19427c4ee5bcSRichard Henderson         memcpy_to_target(sp, k_rand_bytes, 16);
19437c4ee5bcSRichard Henderson         u_rand_bytes = sp;
19447c4ee5bcSRichard Henderson         sp += 16;
19457c4ee5bcSRichard Henderson     }
194614322badSLaurent ALFONSI 
194753a5960aSpbrook     size = (DLINFO_ITEMS + 1) * 2;
194815338fd7Sbellard     if (k_platform)
194953a5960aSpbrook         size += 2;
1950f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS
195153a5960aSpbrook     size += DLINFO_ARCH_ITEMS * 2;
1952f5155289Sbellard #endif
1953ad6919dcSPeter Maydell #ifdef ELF_HWCAP2
1954ad6919dcSPeter Maydell     size += 2;
1955ad6919dcSPeter Maydell #endif
1956f516511eSPeter Maydell     info->auxv_len = size * n;
1957f516511eSPeter Maydell 
195853a5960aSpbrook     size += envc + argc + 2;
1959b9329d4bSRichard Henderson     size += 1;  /* argc itself */
196053a5960aSpbrook     size *= n;
19617c4ee5bcSRichard Henderson 
19627c4ee5bcSRichard Henderson     /* Allocate space and finalize stack alignment for entry now.  */
19637c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
19647c4ee5bcSRichard Henderson         u_argc = QEMU_ALIGN_DOWN(sp - size, STACK_ALIGNMENT);
19657c4ee5bcSRichard Henderson         sp = u_argc;
19667c4ee5bcSRichard Henderson     } else {
19677c4ee5bcSRichard Henderson         u_argc = sp;
19687c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_UP(sp + size, STACK_ALIGNMENT);
19697c4ee5bcSRichard Henderson     }
19707c4ee5bcSRichard Henderson 
19717c4ee5bcSRichard Henderson     u_argv = u_argc + n;
19727c4ee5bcSRichard Henderson     u_envp = u_argv + (argc + 1) * n;
19737c4ee5bcSRichard Henderson     u_auxv = u_envp + (envc + 1) * n;
19747c4ee5bcSRichard Henderson     info->saved_auxv = u_auxv;
19757c4ee5bcSRichard Henderson     info->arg_start = u_argv;
19767c4ee5bcSRichard Henderson     info->arg_end = u_argv + argc * n;
1977f5155289Sbellard 
1978863cf0b7Sj_mayer     /* This is correct because Linux defines
1979863cf0b7Sj_mayer      * elf_addr_t as Elf32_Off / Elf64_Off
1980863cf0b7Sj_mayer      */
198153a5960aSpbrook #define NEW_AUX_ENT(id, val) do {               \
19827c4ee5bcSRichard Henderson         put_user_ual(id, u_auxv);  u_auxv += n; \
19837c4ee5bcSRichard Henderson         put_user_ual(val, u_auxv); u_auxv += n; \
198453a5960aSpbrook     } while(0)
19852f619698Sbellard 
198682991bedSPeter Maydell #ifdef ARCH_DLINFO
198782991bedSPeter Maydell     /*
198882991bedSPeter Maydell      * ARCH_DLINFO must come first so platform specific code can enforce
198982991bedSPeter Maydell      * special alignment requirements on the AUXV if necessary (eg. PPC).
199082991bedSPeter Maydell      */
199182991bedSPeter Maydell     ARCH_DLINFO;
199282991bedSPeter Maydell #endif
1993f516511eSPeter Maydell     /* There must be exactly DLINFO_ITEMS entries here, or the assert
1994f516511eSPeter Maydell      * on info->auxv_len will trigger.
1995f516511eSPeter Maydell      */
19968e62a717SRichard Henderson     NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
1997992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
1998992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
199933143c44SLaurent Vivier     if ((info->alignment & ~qemu_host_page_mask) != 0) {
200033143c44SLaurent Vivier         /* Target doesn't support host page size alignment */
200133143c44SLaurent Vivier         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
200233143c44SLaurent Vivier     } else {
200333143c44SLaurent Vivier         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE,
200433143c44SLaurent Vivier                                                qemu_host_page_size)));
200533143c44SLaurent Vivier     }
20068e62a717SRichard Henderson     NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0));
2007992f48a0Sblueswir1     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
20088e62a717SRichard Henderson     NEW_AUX_ENT(AT_ENTRY, info->entry);
2009992f48a0Sblueswir1     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
2010992f48a0Sblueswir1     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
2011992f48a0Sblueswir1     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
2012992f48a0Sblueswir1     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
2013992f48a0Sblueswir1     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
2014a07c67dfSpbrook     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
201514322badSLaurent ALFONSI     NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
2016444cd5c3SMarco A L Barbosa     NEW_AUX_ENT(AT_SECURE, (abi_ulong) qemu_getauxval(AT_SECURE));
2017e0d1673dSLirong Yuan     NEW_AUX_ENT(AT_EXECFN, info->file_string);
201814322badSLaurent ALFONSI 
2019ad6919dcSPeter Maydell #ifdef ELF_HWCAP2
2020ad6919dcSPeter Maydell     NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2);
2021ad6919dcSPeter Maydell #endif
2022ad6919dcSPeter Maydell 
20237c4ee5bcSRichard Henderson     if (u_platform) {
202453a5960aSpbrook         NEW_AUX_ENT(AT_PLATFORM, u_platform);
20257c4ee5bcSRichard Henderson     }
20267c4ee5bcSRichard Henderson     NEW_AUX_ENT (AT_NULL, 0);
2027f5155289Sbellard #undef NEW_AUX_ENT
2028f5155289Sbellard 
2029f516511eSPeter Maydell     /* Check that our initial calculation of the auxv length matches how much
2030f516511eSPeter Maydell      * we actually put into it.
2031f516511eSPeter Maydell      */
2032f516511eSPeter Maydell     assert(info->auxv_len == u_auxv - info->saved_auxv);
2033edf8e2afSMika Westerberg 
20347c4ee5bcSRichard Henderson     put_user_ual(argc, u_argc);
20357c4ee5bcSRichard Henderson 
20367c4ee5bcSRichard Henderson     p = info->arg_strings;
20377c4ee5bcSRichard Henderson     for (i = 0; i < argc; ++i) {
20387c4ee5bcSRichard Henderson         put_user_ual(p, u_argv);
20397c4ee5bcSRichard Henderson         u_argv += n;
20407c4ee5bcSRichard Henderson         p += target_strlen(p) + 1;
20417c4ee5bcSRichard Henderson     }
20427c4ee5bcSRichard Henderson     put_user_ual(0, u_argv);
20437c4ee5bcSRichard Henderson 
20447c4ee5bcSRichard Henderson     p = info->env_strings;
20457c4ee5bcSRichard Henderson     for (i = 0; i < envc; ++i) {
20467c4ee5bcSRichard Henderson         put_user_ual(p, u_envp);
20477c4ee5bcSRichard Henderson         u_envp += n;
20487c4ee5bcSRichard Henderson         p += target_strlen(p) + 1;
20497c4ee5bcSRichard Henderson     }
20507c4ee5bcSRichard Henderson     put_user_ual(0, u_envp);
20517c4ee5bcSRichard Henderson 
205231e31b8aSbellard     return sp;
205331e31b8aSbellard }
205431e31b8aSbellard 
2055ee947430SAlex Bennée #ifndef ARM_COMMPAGE
2056ee947430SAlex Bennée #define ARM_COMMPAGE 0
2057ee947430SAlex Bennée #define init_guest_commpage() true
2058ee947430SAlex Bennée #endif
2059ee947430SAlex Bennée 
2060ee947430SAlex Bennée static void pgb_fail_in_use(const char *image_name)
2061ee947430SAlex Bennée {
2062ee947430SAlex Bennée     error_report("%s: requires virtual address space that is in use "
2063ee947430SAlex Bennée                  "(omit the -B option or choose a different value)",
2064ee947430SAlex Bennée                  image_name);
2065ee947430SAlex Bennée     exit(EXIT_FAILURE);
2066ee947430SAlex Bennée }
2067ee947430SAlex Bennée 
2068ee947430SAlex Bennée static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr,
2069ee947430SAlex Bennée                                 abi_ulong guest_hiaddr, long align)
2070ee947430SAlex Bennée {
2071ee947430SAlex Bennée     const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
2072ee947430SAlex Bennée     void *addr, *test;
2073ee947430SAlex Bennée 
2074ee947430SAlex Bennée     if (!QEMU_IS_ALIGNED(guest_base, align)) {
2075ee947430SAlex Bennée         fprintf(stderr, "Requested guest base 0x%lx does not satisfy "
2076ee947430SAlex Bennée                 "host minimum alignment (0x%lx)\n",
2077ee947430SAlex Bennée                 guest_base, align);
2078ee947430SAlex Bennée         exit(EXIT_FAILURE);
2079ee947430SAlex Bennée     }
2080ee947430SAlex Bennée 
2081ee947430SAlex Bennée     /* Sanity check the guest binary. */
2082ee947430SAlex Bennée     if (reserved_va) {
2083ee947430SAlex Bennée         if (guest_hiaddr > reserved_va) {
2084ee947430SAlex Bennée             error_report("%s: requires more than reserved virtual "
2085ee947430SAlex Bennée                          "address space (0x%" PRIx64 " > 0x%lx)",
2086ee947430SAlex Bennée                          image_name, (uint64_t)guest_hiaddr, reserved_va);
2087ee947430SAlex Bennée             exit(EXIT_FAILURE);
2088ee947430SAlex Bennée         }
2089ee947430SAlex Bennée     } else {
2090a932eec4SAlex Bennée #if HOST_LONG_BITS < TARGET_ABI_BITS
2091ee947430SAlex Bennée         if ((guest_hiaddr - guest_base) > ~(uintptr_t)0) {
2092ee947430SAlex Bennée             error_report("%s: requires more virtual address space "
2093ee947430SAlex Bennée                          "than the host can provide (0x%" PRIx64 ")",
2094ee947430SAlex Bennée                          image_name, (uint64_t)guest_hiaddr - guest_base);
2095ee947430SAlex Bennée             exit(EXIT_FAILURE);
2096ee947430SAlex Bennée         }
2097a932eec4SAlex Bennée #endif
2098ee947430SAlex Bennée     }
2099ee947430SAlex Bennée 
2100ee947430SAlex Bennée     /*
2101ee947430SAlex Bennée      * Expand the allocation to the entire reserved_va.
2102ee947430SAlex Bennée      * Exclude the mmap_min_addr hole.
2103ee947430SAlex Bennée      */
2104ee947430SAlex Bennée     if (reserved_va) {
2105ee947430SAlex Bennée         guest_loaddr = (guest_base >= mmap_min_addr ? 0
2106ee947430SAlex Bennée                         : mmap_min_addr - guest_base);
2107ee947430SAlex Bennée         guest_hiaddr = reserved_va;
2108ee947430SAlex Bennée     }
2109ee947430SAlex Bennée 
2110ee947430SAlex Bennée     /* Reserve the address space for the binary, or reserved_va. */
2111ee947430SAlex Bennée     test = g2h(guest_loaddr);
2112ee947430SAlex Bennée     addr = mmap(test, guest_hiaddr - guest_loaddr, PROT_NONE, flags, -1, 0);
2113ee947430SAlex Bennée     if (test != addr) {
2114ee947430SAlex Bennée         pgb_fail_in_use(image_name);
2115ee947430SAlex Bennée     }
2116ee947430SAlex Bennée }
2117ee947430SAlex Bennée 
2118ad592e37SAlex Bennée /**
2119ad592e37SAlex Bennée  * pgd_find_hole_fallback: potential mmap address
2120ad592e37SAlex Bennée  * @guest_size: size of available space
2121ad592e37SAlex Bennée  * @brk: location of break
2122ad592e37SAlex Bennée  * @align: memory alignment
2123ad592e37SAlex Bennée  *
2124ad592e37SAlex Bennée  * This is a fallback method for finding a hole in the host address
2125ad592e37SAlex Bennée  * space if we don't have the benefit of being able to access
2126ad592e37SAlex Bennée  * /proc/self/map. It can potentially take a very long time as we can
2127ad592e37SAlex Bennée  * only dumbly iterate up the host address space seeing if the
2128ad592e37SAlex Bennée  * allocation would work.
2129ad592e37SAlex Bennée  */
21305c3e87f3SAlex Bennée static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk,
21315c3e87f3SAlex Bennée                                         long align, uintptr_t offset)
2132ad592e37SAlex Bennée {
2133ad592e37SAlex Bennée     uintptr_t base;
2134ad592e37SAlex Bennée 
2135ad592e37SAlex Bennée     /* Start (aligned) at the bottom and work our way up */
2136ad592e37SAlex Bennée     base = ROUND_UP(mmap_min_addr, align);
2137ad592e37SAlex Bennée 
2138ad592e37SAlex Bennée     while (true) {
2139ad592e37SAlex Bennée         uintptr_t align_start, end;
2140ad592e37SAlex Bennée         align_start = ROUND_UP(base, align);
21415c3e87f3SAlex Bennée         end = align_start + guest_size + offset;
2142ad592e37SAlex Bennée 
2143ad592e37SAlex Bennée         /* if brk is anywhere in the range give ourselves some room to grow. */
2144ad592e37SAlex Bennée         if (align_start <= brk && brk < end) {
2145ad592e37SAlex Bennée             base = brk + (16 * MiB);
2146ad592e37SAlex Bennée             continue;
2147ad592e37SAlex Bennée         } else if (align_start + guest_size < align_start) {
2148ad592e37SAlex Bennée             /* we have run out of space */
2149ad592e37SAlex Bennée             return -1;
2150ad592e37SAlex Bennée         } else {
21512667e069SAlex Bennée             int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE |
21522667e069SAlex Bennée                 MAP_FIXED_NOREPLACE;
2153ad592e37SAlex Bennée             void * mmap_start = mmap((void *) align_start, guest_size,
2154ad592e37SAlex Bennée                                      PROT_NONE, flags, -1, 0);
2155ad592e37SAlex Bennée             if (mmap_start != MAP_FAILED) {
2156ad592e37SAlex Bennée                 munmap((void *) align_start, guest_size);
21572667e069SAlex Bennée                 if (MAP_FIXED_NOREPLACE || mmap_start == (void *) align_start) {
21585c3e87f3SAlex Bennée                     return (uintptr_t) mmap_start + offset;
2159ad592e37SAlex Bennée                 }
21602667e069SAlex Bennée             }
2161ad592e37SAlex Bennée             base += qemu_host_page_size;
2162ad592e37SAlex Bennée         }
2163ad592e37SAlex Bennée     }
2164ad592e37SAlex Bennée }
2165ad592e37SAlex Bennée 
2166ee947430SAlex Bennée /* Return value for guest_base, or -1 if no hole found. */
2167ee947430SAlex Bennée static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size,
21685c3e87f3SAlex Bennée                                long align, uintptr_t offset)
2169ee947430SAlex Bennée {
2170ee947430SAlex Bennée     GSList *maps, *iter;
2171ee947430SAlex Bennée     uintptr_t this_start, this_end, next_start, brk;
2172ee947430SAlex Bennée     intptr_t ret = -1;
2173ee947430SAlex Bennée 
2174ee947430SAlex Bennée     assert(QEMU_IS_ALIGNED(guest_loaddr, align));
2175ee947430SAlex Bennée 
2176ee947430SAlex Bennée     maps = read_self_maps();
2177ee947430SAlex Bennée 
2178ee947430SAlex Bennée     /* Read brk after we've read the maps, which will malloc. */
2179ee947430SAlex Bennée     brk = (uintptr_t)sbrk(0);
2180ee947430SAlex Bennée 
2181ad592e37SAlex Bennée     if (!maps) {
21825c3e87f3SAlex Bennée         return pgd_find_hole_fallback(guest_size, brk, align, offset);
2183ad592e37SAlex Bennée     }
2184ad592e37SAlex Bennée 
2185ee947430SAlex Bennée     /* The first hole is before the first map entry. */
2186ee947430SAlex Bennée     this_start = mmap_min_addr;
2187ee947430SAlex Bennée 
2188ee947430SAlex Bennée     for (iter = maps; iter;
2189ee947430SAlex Bennée          this_start = next_start, iter = g_slist_next(iter)) {
2190ee947430SAlex Bennée         uintptr_t align_start, hole_size;
2191ee947430SAlex Bennée 
2192ee947430SAlex Bennée         this_end = ((MapInfo *)iter->data)->start;
2193ee947430SAlex Bennée         next_start = ((MapInfo *)iter->data)->end;
21945c3e87f3SAlex Bennée         align_start = ROUND_UP(this_start + offset, align);
2195ee947430SAlex Bennée 
2196ee947430SAlex Bennée         /* Skip holes that are too small. */
2197ee947430SAlex Bennée         if (align_start >= this_end) {
2198ee947430SAlex Bennée             continue;
2199ee947430SAlex Bennée         }
2200ee947430SAlex Bennée         hole_size = this_end - align_start;
2201ee947430SAlex Bennée         if (hole_size < guest_size) {
2202ee947430SAlex Bennée             continue;
2203ee947430SAlex Bennée         }
2204ee947430SAlex Bennée 
2205ee947430SAlex Bennée         /* If this hole contains brk, give ourselves some room to grow. */
2206ee947430SAlex Bennée         if (this_start <= brk && brk < this_end) {
2207ee947430SAlex Bennée             hole_size -= guest_size;
2208ee947430SAlex Bennée             if (sizeof(uintptr_t) == 8 && hole_size >= 1 * GiB) {
2209ee947430SAlex Bennée                 align_start += 1 * GiB;
2210ee947430SAlex Bennée             } else if (hole_size >= 16 * MiB) {
2211ee947430SAlex Bennée                 align_start += 16 * MiB;
2212ee947430SAlex Bennée             } else {
2213ee947430SAlex Bennée                 align_start = (this_end - guest_size) & -align;
2214ee947430SAlex Bennée                 if (align_start < this_start) {
2215ee947430SAlex Bennée                     continue;
2216ee947430SAlex Bennée                 }
2217ee947430SAlex Bennée             }
2218ee947430SAlex Bennée         }
2219ee947430SAlex Bennée 
2220ee947430SAlex Bennée         /* Record the lowest successful match. */
2221ee947430SAlex Bennée         if (ret < 0) {
2222ee947430SAlex Bennée             ret = align_start - guest_loaddr;
2223ee947430SAlex Bennée         }
2224ee947430SAlex Bennée         /* If this hole contains the identity map, select it. */
2225ee947430SAlex Bennée         if (align_start <= guest_loaddr &&
2226ee947430SAlex Bennée             guest_loaddr + guest_size <= this_end) {
2227ee947430SAlex Bennée             ret = 0;
2228ee947430SAlex Bennée         }
2229ee947430SAlex Bennée         /* If this hole ends above the identity map, stop looking. */
2230ee947430SAlex Bennée         if (this_end >= guest_loaddr) {
2231ee947430SAlex Bennée             break;
2232ee947430SAlex Bennée         }
2233ee947430SAlex Bennée     }
2234ee947430SAlex Bennée     free_self_maps(maps);
2235ee947430SAlex Bennée 
2236ee947430SAlex Bennée     return ret;
2237ee947430SAlex Bennée }
2238ee947430SAlex Bennée 
2239ee947430SAlex Bennée static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
2240ee947430SAlex Bennée                        abi_ulong orig_hiaddr, long align)
2241ee947430SAlex Bennée {
2242ee947430SAlex Bennée     uintptr_t loaddr = orig_loaddr;
2243ee947430SAlex Bennée     uintptr_t hiaddr = orig_hiaddr;
22445c3e87f3SAlex Bennée     uintptr_t offset = 0;
2245ee947430SAlex Bennée     uintptr_t addr;
2246ee947430SAlex Bennée 
2247ee947430SAlex Bennée     if (hiaddr != orig_hiaddr) {
2248ee947430SAlex Bennée         error_report("%s: requires virtual address space that the "
2249ee947430SAlex Bennée                      "host cannot provide (0x%" PRIx64 ")",
2250ee947430SAlex Bennée                      image_name, (uint64_t)orig_hiaddr);
2251ee947430SAlex Bennée         exit(EXIT_FAILURE);
2252ee947430SAlex Bennée     }
2253ee947430SAlex Bennée 
2254ee947430SAlex Bennée     loaddr &= -align;
2255ee947430SAlex Bennée     if (ARM_COMMPAGE) {
2256ee947430SAlex Bennée         /*
2257ee947430SAlex Bennée          * Extend the allocation to include the commpage.
22585c3e87f3SAlex Bennée          * For a 64-bit host, this is just 4GiB; for a 32-bit host we
22595c3e87f3SAlex Bennée          * need to ensure there is space bellow the guest_base so we
22605c3e87f3SAlex Bennée          * can map the commpage in the place needed when the address
22615c3e87f3SAlex Bennée          * arithmetic wraps around.
2262ee947430SAlex Bennée          */
2263ee947430SAlex Bennée         if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
2264ee947430SAlex Bennée             hiaddr = (uintptr_t) 4 << 30;
2265ee947430SAlex Bennée         } else {
22665c3e87f3SAlex Bennée             offset = -(ARM_COMMPAGE & -align);
2267ee947430SAlex Bennée         }
2268ee947430SAlex Bennée     }
2269ee947430SAlex Bennée 
22705c3e87f3SAlex Bennée     addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
2271ee947430SAlex Bennée     if (addr == -1) {
2272ee947430SAlex Bennée         /*
2273ee947430SAlex Bennée          * If ARM_COMMPAGE, there *might* be a non-consecutive allocation
2274ee947430SAlex Bennée          * that can satisfy both.  But as the normal arm32 link base address
2275ee947430SAlex Bennée          * is ~32k, and we extend down to include the commpage, making the
2276ee947430SAlex Bennée          * overhead only ~96k, this is unlikely.
2277ee947430SAlex Bennée          */
2278ee947430SAlex Bennée         error_report("%s: Unable to allocate %#zx bytes of "
2279ee947430SAlex Bennée                      "virtual address space", image_name,
2280ee947430SAlex Bennée                      (size_t)(hiaddr - loaddr));
2281ee947430SAlex Bennée         exit(EXIT_FAILURE);
2282ee947430SAlex Bennée     }
2283ee947430SAlex Bennée 
2284ee947430SAlex Bennée     guest_base = addr;
2285ee947430SAlex Bennée }
2286ee947430SAlex Bennée 
2287ee947430SAlex Bennée static void pgb_dynamic(const char *image_name, long align)
2288ee947430SAlex Bennée {
2289ee947430SAlex Bennée     /*
2290ee947430SAlex Bennée      * The executable is dynamic and does not require a fixed address.
2291ee947430SAlex Bennée      * All we need is a commpage that satisfies align.
2292ee947430SAlex Bennée      * If we do not need a commpage, leave guest_base == 0.
2293ee947430SAlex Bennée      */
2294ee947430SAlex Bennée     if (ARM_COMMPAGE) {
2295ee947430SAlex Bennée         uintptr_t addr, commpage;
2296ee947430SAlex Bennée 
2297ee947430SAlex Bennée         /* 64-bit hosts should have used reserved_va. */
2298ee947430SAlex Bennée         assert(sizeof(uintptr_t) == 4);
2299ee947430SAlex Bennée 
2300ee947430SAlex Bennée         /*
2301ee947430SAlex Bennée          * By putting the commpage at the first hole, that puts guest_base
2302ee947430SAlex Bennée          * just above that, and maximises the positive guest addresses.
2303ee947430SAlex Bennée          */
2304ee947430SAlex Bennée         commpage = ARM_COMMPAGE & -align;
23055c3e87f3SAlex Bennée         addr = pgb_find_hole(commpage, -commpage, align, 0);
2306ee947430SAlex Bennée         assert(addr != -1);
2307ee947430SAlex Bennée         guest_base = addr;
2308ee947430SAlex Bennée     }
2309ee947430SAlex Bennée }
2310ee947430SAlex Bennée 
2311ee947430SAlex Bennée static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr,
2312ee947430SAlex Bennée                             abi_ulong guest_hiaddr, long align)
2313ee947430SAlex Bennée {
2314c1f6ad79SAlex Bennée     int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
2315ee947430SAlex Bennée     void *addr, *test;
2316ee947430SAlex Bennée 
2317ee947430SAlex Bennée     if (guest_hiaddr > reserved_va) {
2318ee947430SAlex Bennée         error_report("%s: requires more than reserved virtual "
2319ee947430SAlex Bennée                      "address space (0x%" PRIx64 " > 0x%lx)",
2320ee947430SAlex Bennée                      image_name, (uint64_t)guest_hiaddr, reserved_va);
2321ee947430SAlex Bennée         exit(EXIT_FAILURE);
2322ee947430SAlex Bennée     }
2323ee947430SAlex Bennée 
2324ee947430SAlex Bennée     /* Widen the "image" to the entire reserved address space. */
2325ee947430SAlex Bennée     pgb_static(image_name, 0, reserved_va, align);
2326ee947430SAlex Bennée 
23272667e069SAlex Bennée     /* osdep.h defines this as 0 if it's missing */
2328c1f6ad79SAlex Bennée     flags |= MAP_FIXED_NOREPLACE;
2329c1f6ad79SAlex Bennée 
2330ee947430SAlex Bennée     /* Reserve the memory on the host. */
2331ee947430SAlex Bennée     assert(guest_base != 0);
2332ee947430SAlex Bennée     test = g2h(0);
2333ee947430SAlex Bennée     addr = mmap(test, reserved_va, PROT_NONE, flags, -1, 0);
2334ee947430SAlex Bennée     if (addr == MAP_FAILED) {
2335ee947430SAlex Bennée         error_report("Unable to reserve 0x%lx bytes of virtual address "
2336c1f6ad79SAlex Bennée                      "space (%s) for use as guest address space (check your "
2337ee947430SAlex Bennée                      "virtual memory ulimit setting or reserve less "
2338c1f6ad79SAlex Bennée                      "using -R option)", reserved_va, strerror(errno));
2339ee947430SAlex Bennée         exit(EXIT_FAILURE);
2340ee947430SAlex Bennée     }
2341ee947430SAlex Bennée     assert(addr == test);
2342ee947430SAlex Bennée }
2343ee947430SAlex Bennée 
2344ee947430SAlex Bennée void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
2345ee947430SAlex Bennée                       abi_ulong guest_hiaddr)
2346dce10401SMeador Inge {
234730ab9ef2SRichard Henderson     /* In order to use host shmat, we must be able to honor SHMLBA.  */
2348ee947430SAlex Bennée     uintptr_t align = MAX(SHMLBA, qemu_host_page_size);
2349dce10401SMeador Inge 
2350ee947430SAlex Bennée     if (have_guest_base) {
2351ee947430SAlex Bennée         pgb_have_guest_base(image_name, guest_loaddr, guest_hiaddr, align);
2352ee947430SAlex Bennée     } else if (reserved_va) {
2353ee947430SAlex Bennée         pgb_reserved_va(image_name, guest_loaddr, guest_hiaddr, align);
2354ee947430SAlex Bennée     } else if (guest_loaddr) {
2355ee947430SAlex Bennée         pgb_static(image_name, guest_loaddr, guest_hiaddr, align);
2356293f2060SLuke Shumaker     } else {
2357ee947430SAlex Bennée         pgb_dynamic(image_name, align);
2358806d1021SMeador Inge     }
2359806d1021SMeador Inge 
2360ee947430SAlex Bennée     /* Reserve and initialize the commpage. */
2361ee947430SAlex Bennée     if (!init_guest_commpage()) {
2362ee947430SAlex Bennée         /*
2363ee947430SAlex Bennée          * With have_guest_base, the user has selected the address and
2364ee947430SAlex Bennée          * we are trying to work with that.  Otherwise, we have selected
2365ee947430SAlex Bennée          * free space and init_guest_commpage must succeeded.
23667ad75eeaSLuke Shumaker          */
2367ee947430SAlex Bennée         assert(have_guest_base);
2368ee947430SAlex Bennée         pgb_fail_in_use(image_name);
2369dce10401SMeador Inge     }
2370dce10401SMeador Inge 
2371ee947430SAlex Bennée     assert(QEMU_IS_ALIGNED(guest_base, align));
2372ee947430SAlex Bennée     qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space "
2373ee947430SAlex Bennée                   "@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
2374dce10401SMeador Inge }
2375dce10401SMeador Inge 
23768e62a717SRichard Henderson /* Load an ELF image into the address space.
237731e31b8aSbellard 
23788e62a717SRichard Henderson    IMAGE_NAME is the filename of the image, to use in error messages.
23798e62a717SRichard Henderson    IMAGE_FD is the open file descriptor for the image.
23808e62a717SRichard Henderson 
23818e62a717SRichard Henderson    BPRM_BUF is a copy of the beginning of the file; this of course
23828e62a717SRichard Henderson    contains the elf file header at offset 0.  It is assumed that this
23838e62a717SRichard Henderson    buffer is sufficiently aligned to present no problems to the host
23848e62a717SRichard Henderson    in accessing data at aligned offsets within the buffer.
23858e62a717SRichard Henderson 
23868e62a717SRichard Henderson    On return: INFO values will be filled in, as necessary or available.  */
23878e62a717SRichard Henderson 
23888e62a717SRichard Henderson static void load_elf_image(const char *image_name, int image_fd,
2389bf858897SRichard Henderson                            struct image_info *info, char **pinterp_name,
23909955ffacSRichard Henderson                            char bprm_buf[BPRM_BUF_SIZE])
239131e31b8aSbellard {
23928e62a717SRichard Henderson     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
23938e62a717SRichard Henderson     struct elf_phdr *phdr;
23948e62a717SRichard Henderson     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
23958e62a717SRichard Henderson     int i, retval;
23968e62a717SRichard Henderson     const char *errmsg;
239731e31b8aSbellard 
23988e62a717SRichard Henderson     /* First of all, some simple consistency checks */
23998e62a717SRichard Henderson     errmsg = "Invalid ELF image for this architecture";
24008e62a717SRichard Henderson     if (!elf_check_ident(ehdr)) {
24018e62a717SRichard Henderson         goto exit_errmsg;
24028e62a717SRichard Henderson     }
24038e62a717SRichard Henderson     bswap_ehdr(ehdr);
24048e62a717SRichard Henderson     if (!elf_check_ehdr(ehdr)) {
24058e62a717SRichard Henderson         goto exit_errmsg;
240631e31b8aSbellard     }
240731e31b8aSbellard 
24088e62a717SRichard Henderson     i = ehdr->e_phnum * sizeof(struct elf_phdr);
24098e62a717SRichard Henderson     if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
24108e62a717SRichard Henderson         phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
24119955ffacSRichard Henderson     } else {
24128e62a717SRichard Henderson         phdr = (struct elf_phdr *) alloca(i);
24138e62a717SRichard Henderson         retval = pread(image_fd, phdr, i, ehdr->e_phoff);
24149955ffacSRichard Henderson         if (retval != i) {
24158e62a717SRichard Henderson             goto exit_read;
24169955ffacSRichard Henderson         }
241731e31b8aSbellard     }
24188e62a717SRichard Henderson     bswap_phdr(phdr, ehdr->e_phnum);
241909bfb054Sbellard 
24201af02e83SMike Frysinger     info->nsegs = 0;
24211af02e83SMike Frysinger     info->pt_dynamic_addr = 0;
24221af02e83SMike Frysinger 
242398c1076cSAlex Bennée     mmap_lock();
242498c1076cSAlex Bennée 
2425682674b8SRichard Henderson     /* Find the maximum size of the image and allocate an appropriate
2426682674b8SRichard Henderson        amount of memory to handle that.  */
2427682674b8SRichard Henderson     loaddr = -1, hiaddr = 0;
242833143c44SLaurent Vivier     info->alignment = 0;
24298e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; ++i) {
24308e62a717SRichard Henderson         if (phdr[i].p_type == PT_LOAD) {
2431a93934feSJonas Maebe             abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset;
2432682674b8SRichard Henderson             if (a < loaddr) {
2433682674b8SRichard Henderson                 loaddr = a;
2434682674b8SRichard Henderson             }
2435ccf661f8STom Musta             a = phdr[i].p_vaddr + phdr[i].p_memsz;
2436682674b8SRichard Henderson             if (a > hiaddr) {
2437682674b8SRichard Henderson                 hiaddr = a;
2438682674b8SRichard Henderson             }
24391af02e83SMike Frysinger             ++info->nsegs;
244033143c44SLaurent Vivier             info->alignment |= phdr[i].p_align;
2441682674b8SRichard Henderson         }
2442682674b8SRichard Henderson     }
2443682674b8SRichard Henderson 
24446fd59449SRichard Henderson     if (pinterp_name != NULL) {
24456fd59449SRichard Henderson         /*
24466fd59449SRichard Henderson          * This is the main executable.
24476fd59449SRichard Henderson          *
24486fd59449SRichard Henderson          * Reserve extra space for brk.
24496fd59449SRichard Henderson          * We hold on to this space while placing the interpreter
24506fd59449SRichard Henderson          * and the stack, lest they be placed immediately after
24516fd59449SRichard Henderson          * the data segment and block allocation from the brk.
24526fd59449SRichard Henderson          *
24536fd59449SRichard Henderson          * 16MB is chosen as "large enough" without being so large
24546fd59449SRichard Henderson          * as to allow the result to not fit with a 32-bit guest on
24556fd59449SRichard Henderson          * a 32-bit host.
24566fd59449SRichard Henderson          */
24576fd59449SRichard Henderson         info->reserve_brk = 16 * MiB;
24586fd59449SRichard Henderson         hiaddr += info->reserve_brk;
24596fd59449SRichard Henderson 
24606fd59449SRichard Henderson         if (ehdr->e_type == ET_EXEC) {
24616fd59449SRichard Henderson             /*
24626fd59449SRichard Henderson              * Make sure that the low address does not conflict with
24636fd59449SRichard Henderson              * MMAP_MIN_ADDR or the QEMU application itself.
24646fd59449SRichard Henderson              */
24656fd59449SRichard Henderson             probe_guest_base(image_name, loaddr, hiaddr);
2466ee947430SAlex Bennée         } else {
2467ee947430SAlex Bennée             /*
2468ee947430SAlex Bennée              * The binary is dynamic, but we still need to
2469ee947430SAlex Bennée              * select guest_base.  In this case we pass a size.
2470ee947430SAlex Bennée              */
2471ee947430SAlex Bennée             probe_guest_base(image_name, 0, hiaddr - loaddr);
24726fd59449SRichard Henderson         }
24736fd59449SRichard Henderson     }
24746fd59449SRichard Henderson 
24756fd59449SRichard Henderson     /*
24766fd59449SRichard Henderson      * Reserve address space for all of this.
24776fd59449SRichard Henderson      *
24786fd59449SRichard Henderson      * In the case of ET_EXEC, we supply MAP_FIXED so that we get
24796fd59449SRichard Henderson      * exactly the address range that is required.
24806fd59449SRichard Henderson      *
24816fd59449SRichard Henderson      * Otherwise this is ET_DYN, and we are searching for a location
24826fd59449SRichard Henderson      * that can hold the memory space required.  If the image is
24836fd59449SRichard Henderson      * pre-linked, LOADDR will be non-zero, and the kernel should
24846fd59449SRichard Henderson      * honor that address if it happens to be free.
24856fd59449SRichard Henderson      *
24866fd59449SRichard Henderson      * In both cases, we will overwrite pages in this range with mappings
24876fd59449SRichard Henderson      * from the executable.
24886fd59449SRichard Henderson      */
2489682674b8SRichard Henderson     load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
24906fd59449SRichard Henderson                             MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
24916fd59449SRichard Henderson                             (ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
249209bfb054Sbellard                             -1, 0);
2493682674b8SRichard Henderson     if (load_addr == -1) {
24948e62a717SRichard Henderson         goto exit_perror;
249509bfb054Sbellard     }
2496682674b8SRichard Henderson     load_bias = load_addr - loaddr;
249709bfb054Sbellard 
2498a99856cdSChristophe Lyon     if (elf_is_fdpic(ehdr)) {
24991af02e83SMike Frysinger         struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
25007267c094SAnthony Liguori             g_malloc(sizeof(*loadsegs) * info->nsegs);
25011af02e83SMike Frysinger 
25021af02e83SMike Frysinger         for (i = 0; i < ehdr->e_phnum; ++i) {
25031af02e83SMike Frysinger             switch (phdr[i].p_type) {
25041af02e83SMike Frysinger             case PT_DYNAMIC:
25051af02e83SMike Frysinger                 info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
25061af02e83SMike Frysinger                 break;
25071af02e83SMike Frysinger             case PT_LOAD:
25081af02e83SMike Frysinger                 loadsegs->addr = phdr[i].p_vaddr + load_bias;
25091af02e83SMike Frysinger                 loadsegs->p_vaddr = phdr[i].p_vaddr;
25101af02e83SMike Frysinger                 loadsegs->p_memsz = phdr[i].p_memsz;
25111af02e83SMike Frysinger                 ++loadsegs;
25121af02e83SMike Frysinger                 break;
25131af02e83SMike Frysinger             }
25141af02e83SMike Frysinger         }
25151af02e83SMike Frysinger     }
25161af02e83SMike Frysinger 
25178e62a717SRichard Henderson     info->load_bias = load_bias;
2518dc12567aSJosh Kunz     info->code_offset = load_bias;
2519dc12567aSJosh Kunz     info->data_offset = load_bias;
25208e62a717SRichard Henderson     info->load_addr = load_addr;
25218e62a717SRichard Henderson     info->entry = ehdr->e_entry + load_bias;
25228e62a717SRichard Henderson     info->start_code = -1;
25238e62a717SRichard Henderson     info->end_code = 0;
25248e62a717SRichard Henderson     info->start_data = -1;
25258e62a717SRichard Henderson     info->end_data = 0;
25268e62a717SRichard Henderson     info->brk = 0;
2527d8fd2954SPaul Brook     info->elf_flags = ehdr->e_flags;
25288e62a717SRichard Henderson 
25298e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; i++) {
25308e62a717SRichard Henderson         struct elf_phdr *eppnt = phdr + i;
253131e31b8aSbellard         if (eppnt->p_type == PT_LOAD) {
253294894ff2SShivaprasad G Bhat             abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
253331e31b8aSbellard             int elf_prot = 0;
253431e31b8aSbellard 
253531e31b8aSbellard             if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
253631e31b8aSbellard             if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
253731e31b8aSbellard             if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
253831e31b8aSbellard 
2539682674b8SRichard Henderson             vaddr = load_bias + eppnt->p_vaddr;
2540682674b8SRichard Henderson             vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
2541682674b8SRichard Henderson             vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
254294894ff2SShivaprasad G Bhat             vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po);
2543682674b8SRichard Henderson 
2544d87146bcSGiuseppe Musacchio             /*
2545d87146bcSGiuseppe Musacchio              * Some segments may be completely empty without any backing file
2546d87146bcSGiuseppe Musacchio              * segment, in that case just let zero_bss allocate an empty buffer
2547d87146bcSGiuseppe Musacchio              * for it.
2548d87146bcSGiuseppe Musacchio              */
2549d87146bcSGiuseppe Musacchio             if (eppnt->p_filesz != 0) {
2550d87146bcSGiuseppe Musacchio                 error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
2551d87146bcSGiuseppe Musacchio                                     MAP_PRIVATE | MAP_FIXED,
25528e62a717SRichard Henderson                                     image_fd, eppnt->p_offset - vaddr_po);
2553d87146bcSGiuseppe Musacchio 
2554e89f07d3Spbrook                 if (error == -1) {
25558e62a717SRichard Henderson                     goto exit_perror;
255631e31b8aSbellard                 }
2557d87146bcSGiuseppe Musacchio             }
255831e31b8aSbellard 
2559682674b8SRichard Henderson             vaddr_ef = vaddr + eppnt->p_filesz;
2560682674b8SRichard Henderson             vaddr_em = vaddr + eppnt->p_memsz;
256131e31b8aSbellard 
2562cf129f3aSRichard Henderson             /* If the load segment requests extra zeros (e.g. bss), map it.  */
2563682674b8SRichard Henderson             if (vaddr_ef < vaddr_em) {
2564682674b8SRichard Henderson                 zero_bss(vaddr_ef, vaddr_em, elf_prot);
2565682674b8SRichard Henderson             }
25668e62a717SRichard Henderson 
25678e62a717SRichard Henderson             /* Find the full program boundaries.  */
25688e62a717SRichard Henderson             if (elf_prot & PROT_EXEC) {
25698e62a717SRichard Henderson                 if (vaddr < info->start_code) {
25708e62a717SRichard Henderson                     info->start_code = vaddr;
2571cf129f3aSRichard Henderson                 }
25728e62a717SRichard Henderson                 if (vaddr_ef > info->end_code) {
25738e62a717SRichard Henderson                     info->end_code = vaddr_ef;
25748e62a717SRichard Henderson                 }
25758e62a717SRichard Henderson             }
25768e62a717SRichard Henderson             if (elf_prot & PROT_WRITE) {
25778e62a717SRichard Henderson                 if (vaddr < info->start_data) {
25788e62a717SRichard Henderson                     info->start_data = vaddr;
25798e62a717SRichard Henderson                 }
25808e62a717SRichard Henderson                 if (vaddr_ef > info->end_data) {
25818e62a717SRichard Henderson                     info->end_data = vaddr_ef;
25828e62a717SRichard Henderson                 }
25838e62a717SRichard Henderson                 if (vaddr_em > info->brk) {
25848e62a717SRichard Henderson                     info->brk = vaddr_em;
25858e62a717SRichard Henderson                 }
25868e62a717SRichard Henderson             }
2587bf858897SRichard Henderson         } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
2588bf858897SRichard Henderson             char *interp_name;
2589bf858897SRichard Henderson 
2590bf858897SRichard Henderson             if (*pinterp_name) {
2591bf858897SRichard Henderson                 errmsg = "Multiple PT_INTERP entries";
2592bf858897SRichard Henderson                 goto exit_errmsg;
2593bf858897SRichard Henderson             }
2594bf858897SRichard Henderson             interp_name = malloc(eppnt->p_filesz);
2595bf858897SRichard Henderson             if (!interp_name) {
2596bf858897SRichard Henderson                 goto exit_perror;
2597bf858897SRichard Henderson             }
2598bf858897SRichard Henderson 
2599bf858897SRichard Henderson             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
2600bf858897SRichard Henderson                 memcpy(interp_name, bprm_buf + eppnt->p_offset,
2601bf858897SRichard Henderson                        eppnt->p_filesz);
2602bf858897SRichard Henderson             } else {
2603bf858897SRichard Henderson                 retval = pread(image_fd, interp_name, eppnt->p_filesz,
2604bf858897SRichard Henderson                                eppnt->p_offset);
2605bf858897SRichard Henderson                 if (retval != eppnt->p_filesz) {
2606bf858897SRichard Henderson                     goto exit_perror;
2607bf858897SRichard Henderson                 }
2608bf858897SRichard Henderson             }
2609bf858897SRichard Henderson             if (interp_name[eppnt->p_filesz - 1] != 0) {
2610bf858897SRichard Henderson                 errmsg = "Invalid PT_INTERP entry";
2611bf858897SRichard Henderson                 goto exit_errmsg;
2612bf858897SRichard Henderson             }
2613bf858897SRichard Henderson             *pinterp_name = interp_name;
26145dd0db52SStefan Markovic #ifdef TARGET_MIPS
26155dd0db52SStefan Markovic         } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
26165dd0db52SStefan Markovic             Mips_elf_abiflags_v0 abiflags;
26175dd0db52SStefan Markovic             if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
26185dd0db52SStefan Markovic                 errmsg = "Invalid PT_MIPS_ABIFLAGS entry";
26195dd0db52SStefan Markovic                 goto exit_errmsg;
26205dd0db52SStefan Markovic             }
26215dd0db52SStefan Markovic             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
26225dd0db52SStefan Markovic                 memcpy(&abiflags, bprm_buf + eppnt->p_offset,
26235dd0db52SStefan Markovic                        sizeof(Mips_elf_abiflags_v0));
26245dd0db52SStefan Markovic             } else {
26255dd0db52SStefan Markovic                 retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
26265dd0db52SStefan Markovic                                eppnt->p_offset);
26275dd0db52SStefan Markovic                 if (retval != sizeof(Mips_elf_abiflags_v0)) {
26285dd0db52SStefan Markovic                     goto exit_perror;
26295dd0db52SStefan Markovic                 }
26305dd0db52SStefan Markovic             }
26315dd0db52SStefan Markovic             bswap_mips_abiflags(&abiflags);
2632c94cb6c9SStefan Markovic             info->fp_abi = abiflags.fp_abi;
26335dd0db52SStefan Markovic #endif
26348e62a717SRichard Henderson         }
26358e62a717SRichard Henderson     }
26368e62a717SRichard Henderson 
26378e62a717SRichard Henderson     if (info->end_data == 0) {
26388e62a717SRichard Henderson         info->start_data = info->end_code;
26398e62a717SRichard Henderson         info->end_data = info->end_code;
26408e62a717SRichard Henderson         info->brk = info->end_code;
264131e31b8aSbellard     }
264231e31b8aSbellard 
2643682674b8SRichard Henderson     if (qemu_log_enabled()) {
26448e62a717SRichard Henderson         load_symbols(ehdr, image_fd, load_bias);
2645682674b8SRichard Henderson     }
264631e31b8aSbellard 
264798c1076cSAlex Bennée     mmap_unlock();
264898c1076cSAlex Bennée 
26498e62a717SRichard Henderson     close(image_fd);
26508e62a717SRichard Henderson     return;
265131e31b8aSbellard 
26528e62a717SRichard Henderson  exit_read:
26538e62a717SRichard Henderson     if (retval >= 0) {
26548e62a717SRichard Henderson         errmsg = "Incomplete read of file header";
26558e62a717SRichard Henderson         goto exit_errmsg;
26568e62a717SRichard Henderson     }
26578e62a717SRichard Henderson  exit_perror:
26588e62a717SRichard Henderson     errmsg = strerror(errno);
26598e62a717SRichard Henderson  exit_errmsg:
26608e62a717SRichard Henderson     fprintf(stderr, "%s: %s\n", image_name, errmsg);
26618e62a717SRichard Henderson     exit(-1);
26628e62a717SRichard Henderson }
26638e62a717SRichard Henderson 
26648e62a717SRichard Henderson static void load_elf_interp(const char *filename, struct image_info *info,
26658e62a717SRichard Henderson                             char bprm_buf[BPRM_BUF_SIZE])
26668e62a717SRichard Henderson {
26678e62a717SRichard Henderson     int fd, retval;
26688e62a717SRichard Henderson 
26698e62a717SRichard Henderson     fd = open(path(filename), O_RDONLY);
26708e62a717SRichard Henderson     if (fd < 0) {
26718e62a717SRichard Henderson         goto exit_perror;
26728e62a717SRichard Henderson     }
26738e62a717SRichard Henderson 
26748e62a717SRichard Henderson     retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
26758e62a717SRichard Henderson     if (retval < 0) {
26768e62a717SRichard Henderson         goto exit_perror;
26778e62a717SRichard Henderson     }
26788e62a717SRichard Henderson     if (retval < BPRM_BUF_SIZE) {
26798e62a717SRichard Henderson         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
26808e62a717SRichard Henderson     }
26818e62a717SRichard Henderson 
2682bf858897SRichard Henderson     load_elf_image(filename, fd, info, NULL, bprm_buf);
26838e62a717SRichard Henderson     return;
26848e62a717SRichard Henderson 
26858e62a717SRichard Henderson  exit_perror:
26868e62a717SRichard Henderson     fprintf(stderr, "%s: %s\n", filename, strerror(errno));
26878e62a717SRichard Henderson     exit(-1);
268831e31b8aSbellard }
268931e31b8aSbellard 
269049918a75Spbrook static int symfind(const void *s0, const void *s1)
269149918a75Spbrook {
2692c7c530cdSStefan Weil     target_ulong addr = *(target_ulong *)s0;
269349918a75Spbrook     struct elf_sym *sym = (struct elf_sym *)s1;
269449918a75Spbrook     int result = 0;
2695c7c530cdSStefan Weil     if (addr < sym->st_value) {
269649918a75Spbrook         result = -1;
2697c7c530cdSStefan Weil     } else if (addr >= sym->st_value + sym->st_size) {
269849918a75Spbrook         result = 1;
269949918a75Spbrook     }
270049918a75Spbrook     return result;
270149918a75Spbrook }
270249918a75Spbrook 
270349918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
270449918a75Spbrook {
270549918a75Spbrook #if ELF_CLASS == ELFCLASS32
270649918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf32;
270749918a75Spbrook #else
270849918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf64;
270949918a75Spbrook #endif
271049918a75Spbrook 
271149918a75Spbrook     // binary search
271249918a75Spbrook     struct elf_sym *sym;
271349918a75Spbrook 
2714c7c530cdSStefan Weil     sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
27157cba04f6SBlue Swirl     if (sym != NULL) {
271649918a75Spbrook         return s->disas_strtab + sym->st_name;
271749918a75Spbrook     }
271849918a75Spbrook 
271949918a75Spbrook     return "";
272049918a75Spbrook }
272149918a75Spbrook 
272249918a75Spbrook /* FIXME: This should use elf_ops.h  */
272349918a75Spbrook static int symcmp(const void *s0, const void *s1)
272449918a75Spbrook {
272549918a75Spbrook     struct elf_sym *sym0 = (struct elf_sym *)s0;
272649918a75Spbrook     struct elf_sym *sym1 = (struct elf_sym *)s1;
272749918a75Spbrook     return (sym0->st_value < sym1->st_value)
272849918a75Spbrook         ? -1
272949918a75Spbrook         : ((sym0->st_value > sym1->st_value) ? 1 : 0);
273049918a75Spbrook }
273149918a75Spbrook 
2732689f936fSbellard /* Best attempt to load symbols from this ELF object. */
2733682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
2734689f936fSbellard {
2735682674b8SRichard Henderson     int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
27361e06262dSPeter Maydell     uint64_t segsz;
2737682674b8SRichard Henderson     struct elf_shdr *shdr;
2738b9475279SCédric VINCENT     char *strings = NULL;
2739b9475279SCédric VINCENT     struct syminfo *s = NULL;
2740b9475279SCédric VINCENT     struct elf_sym *new_syms, *syms = NULL;
274131e31b8aSbellard 
2742682674b8SRichard Henderson     shnum = hdr->e_shnum;
2743682674b8SRichard Henderson     i = shnum * sizeof(struct elf_shdr);
2744682674b8SRichard Henderson     shdr = (struct elf_shdr *)alloca(i);
2745682674b8SRichard Henderson     if (pread(fd, shdr, i, hdr->e_shoff) != i) {
2746689f936fSbellard         return;
2747682674b8SRichard Henderson     }
2748682674b8SRichard Henderson 
2749682674b8SRichard Henderson     bswap_shdr(shdr, shnum);
2750682674b8SRichard Henderson     for (i = 0; i < shnum; ++i) {
2751682674b8SRichard Henderson         if (shdr[i].sh_type == SHT_SYMTAB) {
2752682674b8SRichard Henderson             sym_idx = i;
2753682674b8SRichard Henderson             str_idx = shdr[i].sh_link;
2754689f936fSbellard             goto found;
2755689f936fSbellard         }
2756689f936fSbellard     }
2757682674b8SRichard Henderson 
2758682674b8SRichard Henderson     /* There will be no symbol table if the file was stripped.  */
2759682674b8SRichard Henderson     return;
2760689f936fSbellard 
2761689f936fSbellard  found:
2762689f936fSbellard     /* Now know where the strtab and symtab are.  Snarf them.  */
27630ef9ea29SPeter Maydell     s = g_try_new(struct syminfo, 1);
2764682674b8SRichard Henderson     if (!s) {
2765b9475279SCédric VINCENT         goto give_up;
2766682674b8SRichard Henderson     }
2767682674b8SRichard Henderson 
27681e06262dSPeter Maydell     segsz = shdr[str_idx].sh_size;
27691e06262dSPeter Maydell     s->disas_strtab = strings = g_try_malloc(segsz);
27701e06262dSPeter Maydell     if (!strings ||
27711e06262dSPeter Maydell         pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) {
2772b9475279SCédric VINCENT         goto give_up;
2773682674b8SRichard Henderson     }
2774689f936fSbellard 
27751e06262dSPeter Maydell     segsz = shdr[sym_idx].sh_size;
27761e06262dSPeter Maydell     syms = g_try_malloc(segsz);
27771e06262dSPeter Maydell     if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) {
2778b9475279SCédric VINCENT         goto give_up;
2779682674b8SRichard Henderson     }
2780689f936fSbellard 
27811e06262dSPeter Maydell     if (segsz / sizeof(struct elf_sym) > INT_MAX) {
27821e06262dSPeter Maydell         /* Implausibly large symbol table: give up rather than ploughing
27831e06262dSPeter Maydell          * on with the number of symbols calculation overflowing
27841e06262dSPeter Maydell          */
27851e06262dSPeter Maydell         goto give_up;
27861e06262dSPeter Maydell     }
27871e06262dSPeter Maydell     nsyms = segsz / sizeof(struct elf_sym);
2788682674b8SRichard Henderson     for (i = 0; i < nsyms; ) {
278949918a75Spbrook         bswap_sym(syms + i);
2790682674b8SRichard Henderson         /* Throw away entries which we do not need.  */
2791682674b8SRichard Henderson         if (syms[i].st_shndx == SHN_UNDEF
2792682674b8SRichard Henderson             || syms[i].st_shndx >= SHN_LORESERVE
2793682674b8SRichard Henderson             || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
2794682674b8SRichard Henderson             if (i < --nsyms) {
279549918a75Spbrook                 syms[i] = syms[nsyms];
279649918a75Spbrook             }
2797682674b8SRichard Henderson         } else {
279849918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS)
279949918a75Spbrook             /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
280049918a75Spbrook             syms[i].st_value &= ~(target_ulong)1;
280149918a75Spbrook #endif
2802682674b8SRichard Henderson             syms[i].st_value += load_bias;
280349918a75Spbrook             i++;
280449918a75Spbrook         }
2805682674b8SRichard Henderson     }
280649918a75Spbrook 
2807b9475279SCédric VINCENT     /* No "useful" symbol.  */
2808b9475279SCédric VINCENT     if (nsyms == 0) {
2809b9475279SCédric VINCENT         goto give_up;
2810b9475279SCédric VINCENT     }
2811b9475279SCédric VINCENT 
28125d5c9930SRichard Henderson     /* Attempt to free the storage associated with the local symbols
28135d5c9930SRichard Henderson        that we threw away.  Whether or not this has any effect on the
28145d5c9930SRichard Henderson        memory allocation depends on the malloc implementation and how
28155d5c9930SRichard Henderson        many symbols we managed to discard.  */
28160ef9ea29SPeter Maydell     new_syms = g_try_renew(struct elf_sym, syms, nsyms);
28178d79de6eSStefan Weil     if (new_syms == NULL) {
2818b9475279SCédric VINCENT         goto give_up;
28195d5c9930SRichard Henderson     }
28208d79de6eSStefan Weil     syms = new_syms;
28215d5c9930SRichard Henderson 
282249918a75Spbrook     qsort(syms, nsyms, sizeof(*syms), symcmp);
282349918a75Spbrook 
282449918a75Spbrook     s->disas_num_syms = nsyms;
282549918a75Spbrook #if ELF_CLASS == ELFCLASS32
282649918a75Spbrook     s->disas_symtab.elf32 = syms;
282749918a75Spbrook #else
282849918a75Spbrook     s->disas_symtab.elf64 = syms;
282949918a75Spbrook #endif
2830682674b8SRichard Henderson     s->lookup_symbol = lookup_symbolxx;
2831e80cfcfcSbellard     s->next = syminfos;
2832e80cfcfcSbellard     syminfos = s;
2833b9475279SCédric VINCENT 
2834b9475279SCédric VINCENT     return;
2835b9475279SCédric VINCENT 
2836b9475279SCédric VINCENT give_up:
28370ef9ea29SPeter Maydell     g_free(s);
28380ef9ea29SPeter Maydell     g_free(strings);
28390ef9ea29SPeter Maydell     g_free(syms);
2840689f936fSbellard }
284131e31b8aSbellard 
2842768fe76eSYunQiang Su uint32_t get_elf_eflags(int fd)
2843768fe76eSYunQiang Su {
2844768fe76eSYunQiang Su     struct elfhdr ehdr;
2845768fe76eSYunQiang Su     off_t offset;
2846768fe76eSYunQiang Su     int ret;
2847768fe76eSYunQiang Su 
2848768fe76eSYunQiang Su     /* Read ELF header */
2849768fe76eSYunQiang Su     offset = lseek(fd, 0, SEEK_SET);
2850768fe76eSYunQiang Su     if (offset == (off_t) -1) {
2851768fe76eSYunQiang Su         return 0;
2852768fe76eSYunQiang Su     }
2853768fe76eSYunQiang Su     ret = read(fd, &ehdr, sizeof(ehdr));
2854768fe76eSYunQiang Su     if (ret < sizeof(ehdr)) {
2855768fe76eSYunQiang Su         return 0;
2856768fe76eSYunQiang Su     }
2857768fe76eSYunQiang Su     offset = lseek(fd, offset, SEEK_SET);
2858768fe76eSYunQiang Su     if (offset == (off_t) -1) {
2859768fe76eSYunQiang Su         return 0;
2860768fe76eSYunQiang Su     }
2861768fe76eSYunQiang Su 
2862768fe76eSYunQiang Su     /* Check ELF signature */
2863768fe76eSYunQiang Su     if (!elf_check_ident(&ehdr)) {
2864768fe76eSYunQiang Su         return 0;
2865768fe76eSYunQiang Su     }
2866768fe76eSYunQiang Su 
2867768fe76eSYunQiang Su     /* check header */
2868768fe76eSYunQiang Su     bswap_ehdr(&ehdr);
2869768fe76eSYunQiang Su     if (!elf_check_ehdr(&ehdr)) {
2870768fe76eSYunQiang Su         return 0;
2871768fe76eSYunQiang Su     }
2872768fe76eSYunQiang Su 
2873768fe76eSYunQiang Su     /* return architecture id */
2874768fe76eSYunQiang Su     return ehdr.e_flags;
2875768fe76eSYunQiang Su }
2876768fe76eSYunQiang Su 
2877f0116c54SWill Newton int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
287831e31b8aSbellard {
28798e62a717SRichard Henderson     struct image_info interp_info;
288031e31b8aSbellard     struct elfhdr elf_ex;
28818e62a717SRichard Henderson     char *elf_interpreter = NULL;
288259baae9aSStefan Brüns     char *scratch;
288331e31b8aSbellard 
2884abcac736SDaniel Santos     memset(&interp_info, 0, sizeof(interp_info));
2885abcac736SDaniel Santos #ifdef TARGET_MIPS
2886abcac736SDaniel Santos     interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
2887abcac736SDaniel Santos #endif
2888abcac736SDaniel Santos 
2889bf858897SRichard Henderson     info->start_mmap = (abi_ulong)ELF_START_MMAP;
289031e31b8aSbellard 
2891bf858897SRichard Henderson     load_elf_image(bprm->filename, bprm->fd, info,
2892bf858897SRichard Henderson                    &elf_interpreter, bprm->buf);
2893bf858897SRichard Henderson 
2894bf858897SRichard Henderson     /* ??? We need a copy of the elf header for passing to create_elf_tables.
2895bf858897SRichard Henderson        If we do nothing, we'll have overwritten this when we re-use bprm->buf
2896bf858897SRichard Henderson        when we load the interpreter.  */
2897bf858897SRichard Henderson     elf_ex = *(struct elfhdr *)bprm->buf;
289831e31b8aSbellard 
289959baae9aSStefan Brüns     /* Do this so that we can load the interpreter, if need be.  We will
290059baae9aSStefan Brüns        change some of these later */
290159baae9aSStefan Brüns     bprm->p = setup_arg_pages(bprm, info);
290259baae9aSStefan Brüns 
290359baae9aSStefan Brüns     scratch = g_new0(char, TARGET_PAGE_SIZE);
29047c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
290559baae9aSStefan Brüns         bprm->p = copy_elf_strings(1, &bprm->filename, scratch,
290659baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
29077c4ee5bcSRichard Henderson         info->file_string = bprm->p;
290859baae9aSStefan Brüns         bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch,
290959baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
29107c4ee5bcSRichard Henderson         info->env_strings = bprm->p;
291159baae9aSStefan Brüns         bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch,
291259baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
29137c4ee5bcSRichard Henderson         info->arg_strings = bprm->p;
29147c4ee5bcSRichard Henderson     } else {
29157c4ee5bcSRichard Henderson         info->arg_strings = bprm->p;
29167c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch,
29177c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
29187c4ee5bcSRichard Henderson         info->env_strings = bprm->p;
29197c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch,
29207c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
29217c4ee5bcSRichard Henderson         info->file_string = bprm->p;
29227c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(1, &bprm->filename, scratch,
29237c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
29247c4ee5bcSRichard Henderson     }
29257c4ee5bcSRichard Henderson 
292659baae9aSStefan Brüns     g_free(scratch);
292759baae9aSStefan Brüns 
2928e5fe0c52Spbrook     if (!bprm->p) {
2929bf858897SRichard Henderson         fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
293031e31b8aSbellard         exit(-1);
29319955ffacSRichard Henderson     }
2932379f6698SPaul Brook 
29338e62a717SRichard Henderson     if (elf_interpreter) {
29348e62a717SRichard Henderson         load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
293531e31b8aSbellard 
29368e62a717SRichard Henderson         /* If the program interpreter is one of these two, then assume
29378e62a717SRichard Henderson            an iBCS2 image.  Otherwise assume a native linux image.  */
293831e31b8aSbellard 
29398e62a717SRichard Henderson         if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
29408e62a717SRichard Henderson             || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
29418e62a717SRichard Henderson             info->personality = PER_SVR4;
29428e62a717SRichard Henderson 
294331e31b8aSbellard             /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
29448e62a717SRichard Henderson                and some applications "depend" upon this behavior.  Since
29458e62a717SRichard Henderson                we do not have the power to recompile these, we emulate
29468e62a717SRichard Henderson                the SVr4 behavior.  Sigh.  */
29478e62a717SRichard Henderson             target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
294868754b44SPeter Maydell                         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
294931e31b8aSbellard         }
2950c94cb6c9SStefan Markovic #ifdef TARGET_MIPS
2951c94cb6c9SStefan Markovic         info->interp_fp_abi = interp_info.fp_abi;
2952c94cb6c9SStefan Markovic #endif
29538e62a717SRichard Henderson     }
295431e31b8aSbellard 
29558e62a717SRichard Henderson     bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
29568e62a717SRichard Henderson                                 info, (elf_interpreter ? &interp_info : NULL));
29578e62a717SRichard Henderson     info->start_stack = bprm->p;
29588e62a717SRichard Henderson 
29598e62a717SRichard Henderson     /* If we have an interpreter, set that as the program's entry point.
29608e78064eSRichard Henderson        Copy the load_bias as well, to help PPC64 interpret the entry
29618e62a717SRichard Henderson        point as a function descriptor.  Do this after creating elf tables
29628e62a717SRichard Henderson        so that we copy the original program entry point into the AUXV.  */
29638e62a717SRichard Henderson     if (elf_interpreter) {
29648e78064eSRichard Henderson         info->load_bias = interp_info.load_bias;
29658e62a717SRichard Henderson         info->entry = interp_info.entry;
2966bf858897SRichard Henderson         free(elf_interpreter);
29678e62a717SRichard Henderson     }
296831e31b8aSbellard 
2969edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
2970edf8e2afSMika Westerberg     bprm->core_dump = &elf_core_dump;
2971edf8e2afSMika Westerberg #endif
2972edf8e2afSMika Westerberg 
29736fd59449SRichard Henderson     /*
29746fd59449SRichard Henderson      * If we reserved extra space for brk, release it now.
29756fd59449SRichard Henderson      * The implementation of do_brk in syscalls.c expects to be able
29766fd59449SRichard Henderson      * to mmap pages in this space.
29776fd59449SRichard Henderson      */
29786fd59449SRichard Henderson     if (info->reserve_brk) {
29796fd59449SRichard Henderson         abi_ulong start_brk = HOST_PAGE_ALIGN(info->brk);
29806fd59449SRichard Henderson         abi_ulong end_brk = HOST_PAGE_ALIGN(info->brk + info->reserve_brk);
29816fd59449SRichard Henderson         target_munmap(start_brk, end_brk - start_brk);
29826fd59449SRichard Henderson     }
29836fd59449SRichard Henderson 
298431e31b8aSbellard     return 0;
298531e31b8aSbellard }
298631e31b8aSbellard 
2987edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
2988edf8e2afSMika Westerberg /*
2989edf8e2afSMika Westerberg  * Definitions to generate Intel SVR4-like core files.
2990a2547a13SLaurent Desnogues  * These mostly have the same names as the SVR4 types with "target_elf_"
2991edf8e2afSMika Westerberg  * tacked on the front to prevent clashes with linux definitions,
2992edf8e2afSMika Westerberg  * and the typedef forms have been avoided.  This is mostly like
2993edf8e2afSMika Westerberg  * the SVR4 structure, but more Linuxy, with things that Linux does
2994edf8e2afSMika Westerberg  * not support and which gdb doesn't really use excluded.
2995edf8e2afSMika Westerberg  *
2996edf8e2afSMika Westerberg  * Fields we don't dump (their contents is zero) in linux-user qemu
2997edf8e2afSMika Westerberg  * are marked with XXX.
2998edf8e2afSMika Westerberg  *
2999edf8e2afSMika Westerberg  * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
3000edf8e2afSMika Westerberg  *
3001edf8e2afSMika Westerberg  * Porting ELF coredump for target is (quite) simple process.  First you
3002dd0a3651SNathan Froyd  * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
3003edf8e2afSMika Westerberg  * the target resides):
3004edf8e2afSMika Westerberg  *
3005edf8e2afSMika Westerberg  * #define USE_ELF_CORE_DUMP
3006edf8e2afSMika Westerberg  *
3007edf8e2afSMika Westerberg  * Next you define type of register set used for dumping.  ELF specification
3008edf8e2afSMika Westerberg  * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
3009edf8e2afSMika Westerberg  *
3010c227f099SAnthony Liguori  * typedef <target_regtype> target_elf_greg_t;
3011edf8e2afSMika Westerberg  * #define ELF_NREG <number of registers>
3012c227f099SAnthony Liguori  * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
3013edf8e2afSMika Westerberg  *
3014edf8e2afSMika Westerberg  * Last step is to implement target specific function that copies registers
3015edf8e2afSMika Westerberg  * from given cpu into just specified register set.  Prototype is:
3016edf8e2afSMika Westerberg  *
3017c227f099SAnthony Liguori  * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
30189349b4f9SAndreas Färber  *                                const CPUArchState *env);
3019edf8e2afSMika Westerberg  *
3020edf8e2afSMika Westerberg  * Parameters:
3021edf8e2afSMika Westerberg  *     regs - copy register values into here (allocated and zeroed by caller)
3022edf8e2afSMika Westerberg  *     env - copy registers from here
3023edf8e2afSMika Westerberg  *
3024edf8e2afSMika Westerberg  * Example for ARM target is provided in this file.
3025edf8e2afSMika Westerberg  */
3026edf8e2afSMika Westerberg 
3027edf8e2afSMika Westerberg /* An ELF note in memory */
3028edf8e2afSMika Westerberg struct memelfnote {
3029edf8e2afSMika Westerberg     const char *name;
3030edf8e2afSMika Westerberg     size_t     namesz;
3031edf8e2afSMika Westerberg     size_t     namesz_rounded;
3032edf8e2afSMika Westerberg     int        type;
3033edf8e2afSMika Westerberg     size_t     datasz;
303480f5ce75SLaurent Vivier     size_t     datasz_rounded;
3035edf8e2afSMika Westerberg     void       *data;
3036edf8e2afSMika Westerberg     size_t     notesz;
3037edf8e2afSMika Westerberg };
3038edf8e2afSMika Westerberg 
3039a2547a13SLaurent Desnogues struct target_elf_siginfo {
3040f8fd4fc4SPaolo Bonzini     abi_int    si_signo; /* signal number */
3041f8fd4fc4SPaolo Bonzini     abi_int    si_code;  /* extra code */
3042f8fd4fc4SPaolo Bonzini     abi_int    si_errno; /* errno */
3043edf8e2afSMika Westerberg };
3044edf8e2afSMika Westerberg 
3045a2547a13SLaurent Desnogues struct target_elf_prstatus {
3046a2547a13SLaurent Desnogues     struct target_elf_siginfo pr_info;      /* Info associated with signal */
30471ddd592fSPaolo Bonzini     abi_short          pr_cursig;    /* Current signal */
3048ca98ac83SPaolo Bonzini     abi_ulong          pr_sigpend;   /* XXX */
3049ca98ac83SPaolo Bonzini     abi_ulong          pr_sighold;   /* XXX */
3050c227f099SAnthony Liguori     target_pid_t       pr_pid;
3051c227f099SAnthony Liguori     target_pid_t       pr_ppid;
3052c227f099SAnthony Liguori     target_pid_t       pr_pgrp;
3053c227f099SAnthony Liguori     target_pid_t       pr_sid;
3054edf8e2afSMika Westerberg     struct target_timeval pr_utime;  /* XXX User time */
3055edf8e2afSMika Westerberg     struct target_timeval pr_stime;  /* XXX System time */
3056edf8e2afSMika Westerberg     struct target_timeval pr_cutime; /* XXX Cumulative user time */
3057edf8e2afSMika Westerberg     struct target_timeval pr_cstime; /* XXX Cumulative system time */
3058c227f099SAnthony Liguori     target_elf_gregset_t      pr_reg;       /* GP registers */
3059f8fd4fc4SPaolo Bonzini     abi_int            pr_fpvalid;   /* XXX */
3060edf8e2afSMika Westerberg };
3061edf8e2afSMika Westerberg 
3062edf8e2afSMika Westerberg #define ELF_PRARGSZ     (80) /* Number of chars for args */
3063edf8e2afSMika Westerberg 
3064a2547a13SLaurent Desnogues struct target_elf_prpsinfo {
3065edf8e2afSMika Westerberg     char         pr_state;       /* numeric process state */
3066edf8e2afSMika Westerberg     char         pr_sname;       /* char for pr_state */
3067edf8e2afSMika Westerberg     char         pr_zomb;        /* zombie */
3068edf8e2afSMika Westerberg     char         pr_nice;        /* nice val */
3069ca98ac83SPaolo Bonzini     abi_ulong    pr_flag;        /* flags */
3070c227f099SAnthony Liguori     target_uid_t pr_uid;
3071c227f099SAnthony Liguori     target_gid_t pr_gid;
3072c227f099SAnthony Liguori     target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
3073edf8e2afSMika Westerberg     /* Lots missing */
3074d7eb2b92SAlistair Francis     char    pr_fname[16] QEMU_NONSTRING; /* filename of executable */
3075edf8e2afSMika Westerberg     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
3076edf8e2afSMika Westerberg };
3077edf8e2afSMika Westerberg 
3078edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */
3079edf8e2afSMika Westerberg struct elf_thread_status {
308072cf2d4fSBlue Swirl     QTAILQ_ENTRY(elf_thread_status)  ets_link;
3081a2547a13SLaurent Desnogues     struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
3082edf8e2afSMika Westerberg #if 0
3083edf8e2afSMika Westerberg     elf_fpregset_t fpu;             /* NT_PRFPREG */
3084edf8e2afSMika Westerberg     struct task_struct *thread;
3085edf8e2afSMika Westerberg     elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */
3086edf8e2afSMika Westerberg #endif
3087edf8e2afSMika Westerberg     struct memelfnote notes[1];
3088edf8e2afSMika Westerberg     int num_notes;
3089edf8e2afSMika Westerberg };
3090edf8e2afSMika Westerberg 
3091edf8e2afSMika Westerberg struct elf_note_info {
3092edf8e2afSMika Westerberg     struct memelfnote   *notes;
3093a2547a13SLaurent Desnogues     struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
3094a2547a13SLaurent Desnogues     struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
3095edf8e2afSMika Westerberg 
3096b58deb34SPaolo Bonzini     QTAILQ_HEAD(, elf_thread_status) thread_list;
3097edf8e2afSMika Westerberg #if 0
3098edf8e2afSMika Westerberg     /*
3099edf8e2afSMika Westerberg      * Current version of ELF coredump doesn't support
3100edf8e2afSMika Westerberg      * dumping fp regs etc.
3101edf8e2afSMika Westerberg      */
3102edf8e2afSMika Westerberg     elf_fpregset_t *fpu;
3103edf8e2afSMika Westerberg     elf_fpxregset_t *xfpu;
3104edf8e2afSMika Westerberg     int thread_status_size;
3105edf8e2afSMika Westerberg #endif
3106edf8e2afSMika Westerberg     int notes_size;
3107edf8e2afSMika Westerberg     int numnote;
3108edf8e2afSMika Westerberg };
3109edf8e2afSMika Westerberg 
3110edf8e2afSMika Westerberg struct vm_area_struct {
31111a1c4db9SMikhail Ilyin     target_ulong   vma_start;  /* start vaddr of memory region */
31121a1c4db9SMikhail Ilyin     target_ulong   vma_end;    /* end vaddr of memory region */
3113edf8e2afSMika Westerberg     abi_ulong      vma_flags;  /* protection etc. flags for the region */
311472cf2d4fSBlue Swirl     QTAILQ_ENTRY(vm_area_struct) vma_link;
3115edf8e2afSMika Westerberg };
3116edf8e2afSMika Westerberg 
3117edf8e2afSMika Westerberg struct mm_struct {
311872cf2d4fSBlue Swirl     QTAILQ_HEAD(, vm_area_struct) mm_mmap;
3119edf8e2afSMika Westerberg     int mm_count;           /* number of mappings */
3120edf8e2afSMika Westerberg };
3121edf8e2afSMika Westerberg 
3122edf8e2afSMika Westerberg static struct mm_struct *vma_init(void);
3123edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *);
31241a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *, target_ulong,
31251a1c4db9SMikhail Ilyin                            target_ulong, abi_ulong);
3126edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *);
3127edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *);
3128edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *);
3129edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *);
31301a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end,
3131edf8e2afSMika Westerberg                       unsigned long flags);
3132edf8e2afSMika Westerberg 
3133edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
3134edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int,
3135edf8e2afSMika Westerberg                       unsigned int, void *);
3136a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
3137a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
3138edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *);
3139edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
3140edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *);
3141edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *);
31429349b4f9SAndreas Färber static int fill_note_info(struct elf_note_info *, long, const CPUArchState *);
31439349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *, const CPUArchState *);
3144edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t);
3145edf8e2afSMika Westerberg 
3146edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t);
3147edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int);
3148edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int);
3149edf8e2afSMika Westerberg 
3150edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
3151a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus)
3152edf8e2afSMika Westerberg {
3153ca98ac83SPaolo Bonzini     prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo);
3154ca98ac83SPaolo Bonzini     prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code);
3155ca98ac83SPaolo Bonzini     prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno);
3156edf8e2afSMika Westerberg     prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
3157ca98ac83SPaolo Bonzini     prstatus->pr_sigpend = tswapal(prstatus->pr_sigpend);
3158ca98ac83SPaolo Bonzini     prstatus->pr_sighold = tswapal(prstatus->pr_sighold);
3159edf8e2afSMika Westerberg     prstatus->pr_pid = tswap32(prstatus->pr_pid);
3160edf8e2afSMika Westerberg     prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
3161edf8e2afSMika Westerberg     prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
3162edf8e2afSMika Westerberg     prstatus->pr_sid = tswap32(prstatus->pr_sid);
3163edf8e2afSMika Westerberg     /* cpu times are not filled, so we skip them */
3164edf8e2afSMika Westerberg     /* regs should be in correct format already */
3165edf8e2afSMika Westerberg     prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
3166edf8e2afSMika Westerberg }
3167edf8e2afSMika Westerberg 
3168a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
3169edf8e2afSMika Westerberg {
3170ca98ac83SPaolo Bonzini     psinfo->pr_flag = tswapal(psinfo->pr_flag);
3171edf8e2afSMika Westerberg     psinfo->pr_uid = tswap16(psinfo->pr_uid);
3172edf8e2afSMika Westerberg     psinfo->pr_gid = tswap16(psinfo->pr_gid);
3173edf8e2afSMika Westerberg     psinfo->pr_pid = tswap32(psinfo->pr_pid);
3174edf8e2afSMika Westerberg     psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
3175edf8e2afSMika Westerberg     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
3176edf8e2afSMika Westerberg     psinfo->pr_sid = tswap32(psinfo->pr_sid);
3177edf8e2afSMika Westerberg }
3178991f8f0cSRichard Henderson 
3179991f8f0cSRichard Henderson static void bswap_note(struct elf_note *en)
3180991f8f0cSRichard Henderson {
3181991f8f0cSRichard Henderson     bswap32s(&en->n_namesz);
3182991f8f0cSRichard Henderson     bswap32s(&en->n_descsz);
3183991f8f0cSRichard Henderson     bswap32s(&en->n_type);
3184991f8f0cSRichard Henderson }
3185991f8f0cSRichard Henderson #else
3186991f8f0cSRichard Henderson static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
3187991f8f0cSRichard Henderson static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
3188991f8f0cSRichard Henderson static inline void bswap_note(struct elf_note *en) { }
3189edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
3190edf8e2afSMika Westerberg 
3191edf8e2afSMika Westerberg /*
3192edf8e2afSMika Westerberg  * Minimal support for linux memory regions.  These are needed
3193edf8e2afSMika Westerberg  * when we are finding out what memory exactly belongs to
3194edf8e2afSMika Westerberg  * emulated process.  No locks needed here, as long as
3195edf8e2afSMika Westerberg  * thread that received the signal is stopped.
3196edf8e2afSMika Westerberg  */
3197edf8e2afSMika Westerberg 
3198edf8e2afSMika Westerberg static struct mm_struct *vma_init(void)
3199edf8e2afSMika Westerberg {
3200edf8e2afSMika Westerberg     struct mm_struct *mm;
3201edf8e2afSMika Westerberg 
32027267c094SAnthony Liguori     if ((mm = g_malloc(sizeof (*mm))) == NULL)
3203edf8e2afSMika Westerberg         return (NULL);
3204edf8e2afSMika Westerberg 
3205edf8e2afSMika Westerberg     mm->mm_count = 0;
320672cf2d4fSBlue Swirl     QTAILQ_INIT(&mm->mm_mmap);
3207edf8e2afSMika Westerberg 
3208edf8e2afSMika Westerberg     return (mm);
3209edf8e2afSMika Westerberg }
3210edf8e2afSMika Westerberg 
3211edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm)
3212edf8e2afSMika Westerberg {
3213edf8e2afSMika Westerberg     struct vm_area_struct *vma;
3214edf8e2afSMika Westerberg 
3215edf8e2afSMika Westerberg     while ((vma = vma_first(mm)) != NULL) {
321672cf2d4fSBlue Swirl         QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
32177267c094SAnthony Liguori         g_free(vma);
3218edf8e2afSMika Westerberg     }
32197267c094SAnthony Liguori     g_free(mm);
3220edf8e2afSMika Westerberg }
3221edf8e2afSMika Westerberg 
32221a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *mm, target_ulong start,
32231a1c4db9SMikhail Ilyin                            target_ulong end, abi_ulong flags)
3224edf8e2afSMika Westerberg {
3225edf8e2afSMika Westerberg     struct vm_area_struct *vma;
3226edf8e2afSMika Westerberg 
32277267c094SAnthony Liguori     if ((vma = g_malloc0(sizeof (*vma))) == NULL)
3228edf8e2afSMika Westerberg         return (-1);
3229edf8e2afSMika Westerberg 
3230edf8e2afSMika Westerberg     vma->vma_start = start;
3231edf8e2afSMika Westerberg     vma->vma_end = end;
3232edf8e2afSMika Westerberg     vma->vma_flags = flags;
3233edf8e2afSMika Westerberg 
323472cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
3235edf8e2afSMika Westerberg     mm->mm_count++;
3236edf8e2afSMika Westerberg 
3237edf8e2afSMika Westerberg     return (0);
3238edf8e2afSMika Westerberg }
3239edf8e2afSMika Westerberg 
3240edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm)
3241edf8e2afSMika Westerberg {
324272cf2d4fSBlue Swirl     return (QTAILQ_FIRST(&mm->mm_mmap));
3243edf8e2afSMika Westerberg }
3244edf8e2afSMika Westerberg 
3245edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
3246edf8e2afSMika Westerberg {
324772cf2d4fSBlue Swirl     return (QTAILQ_NEXT(vma, vma_link));
3248edf8e2afSMika Westerberg }
3249edf8e2afSMika Westerberg 
3250edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm)
3251edf8e2afSMika Westerberg {
3252edf8e2afSMika Westerberg     return (mm->mm_count);
3253edf8e2afSMika Westerberg }
3254edf8e2afSMika Westerberg 
3255edf8e2afSMika Westerberg /*
3256edf8e2afSMika Westerberg  * Calculate file (dump) size of given memory region.
3257edf8e2afSMika Westerberg  */
3258edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
3259edf8e2afSMika Westerberg {
3260edf8e2afSMika Westerberg     /* if we cannot even read the first page, skip it */
3261edf8e2afSMika Westerberg     if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
3262edf8e2afSMika Westerberg         return (0);
3263edf8e2afSMika Westerberg 
3264edf8e2afSMika Westerberg     /*
3265edf8e2afSMika Westerberg      * Usually we don't dump executable pages as they contain
3266edf8e2afSMika Westerberg      * non-writable code that debugger can read directly from
3267edf8e2afSMika Westerberg      * target library etc.  However, thread stacks are marked
3268edf8e2afSMika Westerberg      * also executable so we read in first page of given region
3269edf8e2afSMika Westerberg      * and check whether it contains elf header.  If there is
3270edf8e2afSMika Westerberg      * no elf header, we dump it.
3271edf8e2afSMika Westerberg      */
3272edf8e2afSMika Westerberg     if (vma->vma_flags & PROT_EXEC) {
3273edf8e2afSMika Westerberg         char page[TARGET_PAGE_SIZE];
3274edf8e2afSMika Westerberg 
3275edf8e2afSMika Westerberg         copy_from_user(page, vma->vma_start, sizeof (page));
3276edf8e2afSMika Westerberg         if ((page[EI_MAG0] == ELFMAG0) &&
3277edf8e2afSMika Westerberg             (page[EI_MAG1] == ELFMAG1) &&
3278edf8e2afSMika Westerberg             (page[EI_MAG2] == ELFMAG2) &&
3279edf8e2afSMika Westerberg             (page[EI_MAG3] == ELFMAG3)) {
3280edf8e2afSMika Westerberg             /*
3281edf8e2afSMika Westerberg              * Mappings are possibly from ELF binary.  Don't dump
3282edf8e2afSMika Westerberg              * them.
3283edf8e2afSMika Westerberg              */
3284edf8e2afSMika Westerberg             return (0);
3285edf8e2afSMika Westerberg         }
3286edf8e2afSMika Westerberg     }
3287edf8e2afSMika Westerberg 
3288edf8e2afSMika Westerberg     return (vma->vma_end - vma->vma_start);
3289edf8e2afSMika Westerberg }
3290edf8e2afSMika Westerberg 
32911a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end,
3292edf8e2afSMika Westerberg                       unsigned long flags)
3293edf8e2afSMika Westerberg {
3294edf8e2afSMika Westerberg     struct mm_struct *mm = (struct mm_struct *)priv;
3295edf8e2afSMika Westerberg 
3296edf8e2afSMika Westerberg     vma_add_mapping(mm, start, end, flags);
3297edf8e2afSMika Westerberg     return (0);
3298edf8e2afSMika Westerberg }
3299edf8e2afSMika Westerberg 
3300edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type,
3301edf8e2afSMika Westerberg                       unsigned int sz, void *data)
3302edf8e2afSMika Westerberg {
3303edf8e2afSMika Westerberg     unsigned int namesz;
3304edf8e2afSMika Westerberg 
3305edf8e2afSMika Westerberg     namesz = strlen(name) + 1;
3306edf8e2afSMika Westerberg     note->name = name;
3307edf8e2afSMika Westerberg     note->namesz = namesz;
3308edf8e2afSMika Westerberg     note->namesz_rounded = roundup(namesz, sizeof (int32_t));
3309edf8e2afSMika Westerberg     note->type = type;
331080f5ce75SLaurent Vivier     note->datasz = sz;
331180f5ce75SLaurent Vivier     note->datasz_rounded = roundup(sz, sizeof (int32_t));
331280f5ce75SLaurent Vivier 
3313edf8e2afSMika Westerberg     note->data = data;
3314edf8e2afSMika Westerberg 
3315edf8e2afSMika Westerberg     /*
3316edf8e2afSMika Westerberg      * We calculate rounded up note size here as specified by
3317edf8e2afSMika Westerberg      * ELF document.
3318edf8e2afSMika Westerberg      */
3319edf8e2afSMika Westerberg     note->notesz = sizeof (struct elf_note) +
332080f5ce75SLaurent Vivier         note->namesz_rounded + note->datasz_rounded;
3321edf8e2afSMika Westerberg }
3322edf8e2afSMika Westerberg 
3323edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
3324edf8e2afSMika Westerberg                             uint32_t flags)
3325edf8e2afSMika Westerberg {
3326edf8e2afSMika Westerberg     (void) memset(elf, 0, sizeof(*elf));
3327edf8e2afSMika Westerberg 
3328edf8e2afSMika Westerberg     (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
3329edf8e2afSMika Westerberg     elf->e_ident[EI_CLASS] = ELF_CLASS;
3330edf8e2afSMika Westerberg     elf->e_ident[EI_DATA] = ELF_DATA;
3331edf8e2afSMika Westerberg     elf->e_ident[EI_VERSION] = EV_CURRENT;
3332edf8e2afSMika Westerberg     elf->e_ident[EI_OSABI] = ELF_OSABI;
3333edf8e2afSMika Westerberg 
3334edf8e2afSMika Westerberg     elf->e_type = ET_CORE;
3335edf8e2afSMika Westerberg     elf->e_machine = machine;
3336edf8e2afSMika Westerberg     elf->e_version = EV_CURRENT;
3337edf8e2afSMika Westerberg     elf->e_phoff = sizeof(struct elfhdr);
3338edf8e2afSMika Westerberg     elf->e_flags = flags;
3339edf8e2afSMika Westerberg     elf->e_ehsize = sizeof(struct elfhdr);
3340edf8e2afSMika Westerberg     elf->e_phentsize = sizeof(struct elf_phdr);
3341edf8e2afSMika Westerberg     elf->e_phnum = segs;
3342edf8e2afSMika Westerberg 
3343edf8e2afSMika Westerberg     bswap_ehdr(elf);
3344edf8e2afSMika Westerberg }
3345edf8e2afSMika Westerberg 
3346edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
3347edf8e2afSMika Westerberg {
3348edf8e2afSMika Westerberg     phdr->p_type = PT_NOTE;
3349edf8e2afSMika Westerberg     phdr->p_offset = offset;
3350edf8e2afSMika Westerberg     phdr->p_vaddr = 0;
3351edf8e2afSMika Westerberg     phdr->p_paddr = 0;
3352edf8e2afSMika Westerberg     phdr->p_filesz = sz;
3353edf8e2afSMika Westerberg     phdr->p_memsz = 0;
3354edf8e2afSMika Westerberg     phdr->p_flags = 0;
3355edf8e2afSMika Westerberg     phdr->p_align = 0;
3356edf8e2afSMika Westerberg 
3357991f8f0cSRichard Henderson     bswap_phdr(phdr, 1);
3358edf8e2afSMika Westerberg }
3359edf8e2afSMika Westerberg 
3360edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note)
3361edf8e2afSMika Westerberg {
3362edf8e2afSMika Westerberg     return (note->notesz);
3363edf8e2afSMika Westerberg }
3364edf8e2afSMika Westerberg 
3365a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus,
3366edf8e2afSMika Westerberg                           const TaskState *ts, int signr)
3367edf8e2afSMika Westerberg {
3368edf8e2afSMika Westerberg     (void) memset(prstatus, 0, sizeof (*prstatus));
3369edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
3370edf8e2afSMika Westerberg     prstatus->pr_pid = ts->ts_tid;
3371edf8e2afSMika Westerberg     prstatus->pr_ppid = getppid();
3372edf8e2afSMika Westerberg     prstatus->pr_pgrp = getpgrp();
3373edf8e2afSMika Westerberg     prstatus->pr_sid = getsid(0);
3374edf8e2afSMika Westerberg 
3375edf8e2afSMika Westerberg     bswap_prstatus(prstatus);
3376edf8e2afSMika Westerberg }
3377edf8e2afSMika Westerberg 
3378a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
3379edf8e2afSMika Westerberg {
3380900cfbcaSJim Meyering     char *base_filename;
3381edf8e2afSMika Westerberg     unsigned int i, len;
3382edf8e2afSMika Westerberg 
3383edf8e2afSMika Westerberg     (void) memset(psinfo, 0, sizeof (*psinfo));
3384edf8e2afSMika Westerberg 
3385edf8e2afSMika Westerberg     len = ts->info->arg_end - ts->info->arg_start;
3386edf8e2afSMika Westerberg     if (len >= ELF_PRARGSZ)
3387edf8e2afSMika Westerberg         len = ELF_PRARGSZ - 1;
3388edf8e2afSMika Westerberg     if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len))
3389edf8e2afSMika Westerberg         return -EFAULT;
3390edf8e2afSMika Westerberg     for (i = 0; i < len; i++)
3391edf8e2afSMika Westerberg         if (psinfo->pr_psargs[i] == 0)
3392edf8e2afSMika Westerberg             psinfo->pr_psargs[i] = ' ';
3393edf8e2afSMika Westerberg     psinfo->pr_psargs[len] = 0;
3394edf8e2afSMika Westerberg 
3395edf8e2afSMika Westerberg     psinfo->pr_pid = getpid();
3396edf8e2afSMika Westerberg     psinfo->pr_ppid = getppid();
3397edf8e2afSMika Westerberg     psinfo->pr_pgrp = getpgrp();
3398edf8e2afSMika Westerberg     psinfo->pr_sid = getsid(0);
3399edf8e2afSMika Westerberg     psinfo->pr_uid = getuid();
3400edf8e2afSMika Westerberg     psinfo->pr_gid = getgid();
3401edf8e2afSMika Westerberg 
3402900cfbcaSJim Meyering     base_filename = g_path_get_basename(ts->bprm->filename);
3403900cfbcaSJim Meyering     /*
3404900cfbcaSJim Meyering      * Using strncpy here is fine: at max-length,
3405900cfbcaSJim Meyering      * this field is not NUL-terminated.
3406900cfbcaSJim Meyering      */
3407edf8e2afSMika Westerberg     (void) strncpy(psinfo->pr_fname, base_filename,
3408edf8e2afSMika Westerberg                    sizeof(psinfo->pr_fname));
3409edf8e2afSMika Westerberg 
3410900cfbcaSJim Meyering     g_free(base_filename);
3411edf8e2afSMika Westerberg     bswap_psinfo(psinfo);
3412edf8e2afSMika Westerberg     return (0);
3413edf8e2afSMika Westerberg }
3414edf8e2afSMika Westerberg 
3415edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
3416edf8e2afSMika Westerberg {
3417edf8e2afSMika Westerberg     elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
3418edf8e2afSMika Westerberg     elf_addr_t orig_auxv = auxv;
3419edf8e2afSMika Westerberg     void *ptr;
3420125b0f55SAlexander Graf     int len = ts->info->auxv_len;
3421edf8e2afSMika Westerberg 
3422edf8e2afSMika Westerberg     /*
3423edf8e2afSMika Westerberg      * Auxiliary vector is stored in target process stack.  It contains
3424edf8e2afSMika Westerberg      * {type, value} pairs that we need to dump into note.  This is not
3425edf8e2afSMika Westerberg      * strictly necessary but we do it here for sake of completeness.
3426edf8e2afSMika Westerberg      */
3427edf8e2afSMika Westerberg 
3428edf8e2afSMika Westerberg     /* read in whole auxv vector and copy it to memelfnote */
3429edf8e2afSMika Westerberg     ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
3430edf8e2afSMika Westerberg     if (ptr != NULL) {
3431edf8e2afSMika Westerberg         fill_note(note, "CORE", NT_AUXV, len, ptr);
3432edf8e2afSMika Westerberg         unlock_user(ptr, auxv, len);
3433edf8e2afSMika Westerberg     }
3434edf8e2afSMika Westerberg }
3435edf8e2afSMika Westerberg 
3436edf8e2afSMika Westerberg /*
3437edf8e2afSMika Westerberg  * Constructs name of coredump file.  We have following convention
3438edf8e2afSMika Westerberg  * for the name:
3439edf8e2afSMika Westerberg  *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
3440edf8e2afSMika Westerberg  *
3441edf8e2afSMika Westerberg  * Returns 0 in case of success, -1 otherwise (errno is set).
3442edf8e2afSMika Westerberg  */
3443edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf,
3444edf8e2afSMika Westerberg                               size_t bufsize)
3445edf8e2afSMika Westerberg {
3446edf8e2afSMika Westerberg     char timestamp[64];
3447edf8e2afSMika Westerberg     char *base_filename = NULL;
3448edf8e2afSMika Westerberg     struct timeval tv;
3449edf8e2afSMika Westerberg     struct tm tm;
3450edf8e2afSMika Westerberg 
3451edf8e2afSMika Westerberg     assert(bufsize >= PATH_MAX);
3452edf8e2afSMika Westerberg 
3453edf8e2afSMika Westerberg     if (gettimeofday(&tv, NULL) < 0) {
3454edf8e2afSMika Westerberg         (void) fprintf(stderr, "unable to get current timestamp: %s",
3455edf8e2afSMika Westerberg                        strerror(errno));
3456edf8e2afSMika Westerberg         return (-1);
3457edf8e2afSMika Westerberg     }
3458edf8e2afSMika Westerberg 
3459b8da57faSWei Jiangang     base_filename = g_path_get_basename(ts->bprm->filename);
3460edf8e2afSMika Westerberg     (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S",
3461edf8e2afSMika Westerberg                     localtime_r(&tv.tv_sec, &tm));
3462edf8e2afSMika Westerberg     (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core",
3463edf8e2afSMika Westerberg                     base_filename, timestamp, (int)getpid());
3464b8da57faSWei Jiangang     g_free(base_filename);
3465edf8e2afSMika Westerberg 
3466edf8e2afSMika Westerberg     return (0);
3467edf8e2afSMika Westerberg }
3468edf8e2afSMika Westerberg 
3469edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size)
3470edf8e2afSMika Westerberg {
3471edf8e2afSMika Westerberg     const char *bufp = (const char *)ptr;
3472edf8e2afSMika Westerberg     ssize_t bytes_written, bytes_left;
3473edf8e2afSMika Westerberg     struct rlimit dumpsize;
3474edf8e2afSMika Westerberg     off_t pos;
3475edf8e2afSMika Westerberg 
3476edf8e2afSMika Westerberg     bytes_written = 0;
3477edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
3478edf8e2afSMika Westerberg     if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
3479edf8e2afSMika Westerberg         if (errno == ESPIPE) { /* not a seekable stream */
3480edf8e2afSMika Westerberg             bytes_left = size;
3481edf8e2afSMika Westerberg         } else {
3482edf8e2afSMika Westerberg             return pos;
3483edf8e2afSMika Westerberg         }
3484edf8e2afSMika Westerberg     } else {
3485edf8e2afSMika Westerberg         if (dumpsize.rlim_cur <= pos) {
3486edf8e2afSMika Westerberg             return -1;
3487edf8e2afSMika Westerberg         } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
3488edf8e2afSMika Westerberg             bytes_left = size;
3489edf8e2afSMika Westerberg         } else {
3490edf8e2afSMika Westerberg             size_t limit_left=dumpsize.rlim_cur - pos;
3491edf8e2afSMika Westerberg             bytes_left = limit_left >= size ? size : limit_left ;
3492edf8e2afSMika Westerberg         }
3493edf8e2afSMika Westerberg     }
3494edf8e2afSMika Westerberg 
3495edf8e2afSMika Westerberg     /*
3496edf8e2afSMika Westerberg      * In normal conditions, single write(2) should do but
3497edf8e2afSMika Westerberg      * in case of socket etc. this mechanism is more portable.
3498edf8e2afSMika Westerberg      */
3499edf8e2afSMika Westerberg     do {
3500edf8e2afSMika Westerberg         bytes_written = write(fd, bufp, bytes_left);
3501edf8e2afSMika Westerberg         if (bytes_written < 0) {
3502edf8e2afSMika Westerberg             if (errno == EINTR)
3503edf8e2afSMika Westerberg                 continue;
3504edf8e2afSMika Westerberg             return (-1);
3505edf8e2afSMika Westerberg         } else if (bytes_written == 0) { /* eof */
3506edf8e2afSMika Westerberg             return (-1);
3507edf8e2afSMika Westerberg         }
3508edf8e2afSMika Westerberg         bufp += bytes_written;
3509edf8e2afSMika Westerberg         bytes_left -= bytes_written;
3510edf8e2afSMika Westerberg     } while (bytes_left > 0);
3511edf8e2afSMika Westerberg 
3512edf8e2afSMika Westerberg     return (0);
3513edf8e2afSMika Westerberg }
3514edf8e2afSMika Westerberg 
3515edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd)
3516edf8e2afSMika Westerberg {
3517edf8e2afSMika Westerberg     struct elf_note en;
3518edf8e2afSMika Westerberg 
3519edf8e2afSMika Westerberg     en.n_namesz = men->namesz;
3520edf8e2afSMika Westerberg     en.n_type = men->type;
3521edf8e2afSMika Westerberg     en.n_descsz = men->datasz;
3522edf8e2afSMika Westerberg 
3523edf8e2afSMika Westerberg     bswap_note(&en);
3524edf8e2afSMika Westerberg 
3525edf8e2afSMika Westerberg     if (dump_write(fd, &en, sizeof(en)) != 0)
3526edf8e2afSMika Westerberg         return (-1);
3527edf8e2afSMika Westerberg     if (dump_write(fd, men->name, men->namesz_rounded) != 0)
3528edf8e2afSMika Westerberg         return (-1);
352980f5ce75SLaurent Vivier     if (dump_write(fd, men->data, men->datasz_rounded) != 0)
3530edf8e2afSMika Westerberg         return (-1);
3531edf8e2afSMika Westerberg 
3532edf8e2afSMika Westerberg     return (0);
3533edf8e2afSMika Westerberg }
3534edf8e2afSMika Westerberg 
35359349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env)
3536edf8e2afSMika Westerberg {
353729a0af61SRichard Henderson     CPUState *cpu = env_cpu((CPUArchState *)env);
35380429a971SAndreas Färber     TaskState *ts = (TaskState *)cpu->opaque;
3539edf8e2afSMika Westerberg     struct elf_thread_status *ets;
3540edf8e2afSMika Westerberg 
35417267c094SAnthony Liguori     ets = g_malloc0(sizeof (*ets));
3542edf8e2afSMika Westerberg     ets->num_notes = 1; /* only prstatus is dumped */
3543edf8e2afSMika Westerberg     fill_prstatus(&ets->prstatus, ts, 0);
3544edf8e2afSMika Westerberg     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
3545edf8e2afSMika Westerberg     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
3546edf8e2afSMika Westerberg               &ets->prstatus);
3547edf8e2afSMika Westerberg 
354872cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
3549edf8e2afSMika Westerberg 
3550edf8e2afSMika Westerberg     info->notes_size += note_size(&ets->notes[0]);
3551edf8e2afSMika Westerberg }
3552edf8e2afSMika Westerberg 
35536afafa86SPeter Maydell static void init_note_info(struct elf_note_info *info)
35546afafa86SPeter Maydell {
35556afafa86SPeter Maydell     /* Initialize the elf_note_info structure so that it is at
35566afafa86SPeter Maydell      * least safe to call free_note_info() on it. Must be
35576afafa86SPeter Maydell      * called before calling fill_note_info().
35586afafa86SPeter Maydell      */
35596afafa86SPeter Maydell     memset(info, 0, sizeof (*info));
35606afafa86SPeter Maydell     QTAILQ_INIT(&info->thread_list);
35616afafa86SPeter Maydell }
35626afafa86SPeter Maydell 
3563edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info,
35649349b4f9SAndreas Färber                           long signr, const CPUArchState *env)
3565edf8e2afSMika Westerberg {
3566edf8e2afSMika Westerberg #define NUMNOTES 3
356729a0af61SRichard Henderson     CPUState *cpu = env_cpu((CPUArchState *)env);
35680429a971SAndreas Färber     TaskState *ts = (TaskState *)cpu->opaque;
3569edf8e2afSMika Westerberg     int i;
3570edf8e2afSMika Westerberg 
3571c78d65e8SMarkus Armbruster     info->notes = g_new0(struct memelfnote, NUMNOTES);
3572edf8e2afSMika Westerberg     if (info->notes == NULL)
3573edf8e2afSMika Westerberg         return (-ENOMEM);
35747267c094SAnthony Liguori     info->prstatus = g_malloc0(sizeof (*info->prstatus));
3575edf8e2afSMika Westerberg     if (info->prstatus == NULL)
3576edf8e2afSMika Westerberg         return (-ENOMEM);
35777267c094SAnthony Liguori     info->psinfo = g_malloc0(sizeof (*info->psinfo));
3578edf8e2afSMika Westerberg     if (info->prstatus == NULL)
3579edf8e2afSMika Westerberg         return (-ENOMEM);
3580edf8e2afSMika Westerberg 
3581edf8e2afSMika Westerberg     /*
3582edf8e2afSMika Westerberg      * First fill in status (and registers) of current thread
3583edf8e2afSMika Westerberg      * including process info & aux vector.
3584edf8e2afSMika Westerberg      */
3585edf8e2afSMika Westerberg     fill_prstatus(info->prstatus, ts, signr);
3586edf8e2afSMika Westerberg     elf_core_copy_regs(&info->prstatus->pr_reg, env);
3587edf8e2afSMika Westerberg     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
3588edf8e2afSMika Westerberg               sizeof (*info->prstatus), info->prstatus);
3589edf8e2afSMika Westerberg     fill_psinfo(info->psinfo, ts);
3590edf8e2afSMika Westerberg     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
3591edf8e2afSMika Westerberg               sizeof (*info->psinfo), info->psinfo);
3592edf8e2afSMika Westerberg     fill_auxv_note(&info->notes[2], ts);
3593edf8e2afSMika Westerberg     info->numnote = 3;
3594edf8e2afSMika Westerberg 
3595edf8e2afSMika Westerberg     info->notes_size = 0;
3596edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
3597edf8e2afSMika Westerberg         info->notes_size += note_size(&info->notes[i]);
3598edf8e2afSMika Westerberg 
3599edf8e2afSMika Westerberg     /* read and fill status of all threads */
3600edf8e2afSMika Westerberg     cpu_list_lock();
3601bdc44640SAndreas Färber     CPU_FOREACH(cpu) {
3602a2247f8eSAndreas Färber         if (cpu == thread_cpu) {
3603edf8e2afSMika Westerberg             continue;
3604182735efSAndreas Färber         }
3605182735efSAndreas Färber         fill_thread_info(info, (CPUArchState *)cpu->env_ptr);
3606edf8e2afSMika Westerberg     }
3607edf8e2afSMika Westerberg     cpu_list_unlock();
3608edf8e2afSMika Westerberg 
3609edf8e2afSMika Westerberg     return (0);
3610edf8e2afSMika Westerberg }
3611edf8e2afSMika Westerberg 
3612edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info)
3613edf8e2afSMika Westerberg {
3614edf8e2afSMika Westerberg     struct elf_thread_status *ets;
3615edf8e2afSMika Westerberg 
361672cf2d4fSBlue Swirl     while (!QTAILQ_EMPTY(&info->thread_list)) {
361772cf2d4fSBlue Swirl         ets = QTAILQ_FIRST(&info->thread_list);
361872cf2d4fSBlue Swirl         QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
36197267c094SAnthony Liguori         g_free(ets);
3620edf8e2afSMika Westerberg     }
3621edf8e2afSMika Westerberg 
36227267c094SAnthony Liguori     g_free(info->prstatus);
36237267c094SAnthony Liguori     g_free(info->psinfo);
36247267c094SAnthony Liguori     g_free(info->notes);
3625edf8e2afSMika Westerberg }
3626edf8e2afSMika Westerberg 
3627edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd)
3628edf8e2afSMika Westerberg {
3629edf8e2afSMika Westerberg     struct elf_thread_status *ets;
3630edf8e2afSMika Westerberg     int i, error = 0;
3631edf8e2afSMika Westerberg 
3632edf8e2afSMika Westerberg     /* write prstatus, psinfo and auxv for current thread */
3633edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
3634edf8e2afSMika Westerberg         if ((error = write_note(&info->notes[i], fd)) != 0)
3635edf8e2afSMika Westerberg             return (error);
3636edf8e2afSMika Westerberg 
3637edf8e2afSMika Westerberg     /* write prstatus for each thread */
363852a53afeSEmilio G. Cota     QTAILQ_FOREACH(ets, &info->thread_list, ets_link) {
3639edf8e2afSMika Westerberg         if ((error = write_note(&ets->notes[0], fd)) != 0)
3640edf8e2afSMika Westerberg             return (error);
3641edf8e2afSMika Westerberg     }
3642edf8e2afSMika Westerberg 
3643edf8e2afSMika Westerberg     return (0);
3644edf8e2afSMika Westerberg }
3645edf8e2afSMika Westerberg 
3646edf8e2afSMika Westerberg /*
3647edf8e2afSMika Westerberg  * Write out ELF coredump.
3648edf8e2afSMika Westerberg  *
3649edf8e2afSMika Westerberg  * See documentation of ELF object file format in:
3650edf8e2afSMika Westerberg  * http://www.caldera.com/developers/devspecs/gabi41.pdf
3651edf8e2afSMika Westerberg  *
3652edf8e2afSMika Westerberg  * Coredump format in linux is following:
3653edf8e2afSMika Westerberg  *
3654edf8e2afSMika Westerberg  * 0   +----------------------+         \
3655edf8e2afSMika Westerberg  *     | ELF header           | ET_CORE  |
3656edf8e2afSMika Westerberg  *     +----------------------+          |
3657edf8e2afSMika Westerberg  *     | ELF program headers  |          |--- headers
3658edf8e2afSMika Westerberg  *     | - NOTE section       |          |
3659edf8e2afSMika Westerberg  *     | - PT_LOAD sections   |          |
3660edf8e2afSMika Westerberg  *     +----------------------+         /
3661edf8e2afSMika Westerberg  *     | NOTEs:               |
3662edf8e2afSMika Westerberg  *     | - NT_PRSTATUS        |
3663edf8e2afSMika Westerberg  *     | - NT_PRSINFO         |
3664edf8e2afSMika Westerberg  *     | - NT_AUXV            |
3665edf8e2afSMika Westerberg  *     +----------------------+ <-- aligned to target page
3666edf8e2afSMika Westerberg  *     | Process memory dump  |
3667edf8e2afSMika Westerberg  *     :                      :
3668edf8e2afSMika Westerberg  *     .                      .
3669edf8e2afSMika Westerberg  *     :                      :
3670edf8e2afSMika Westerberg  *     |                      |
3671edf8e2afSMika Westerberg  *     +----------------------+
3672edf8e2afSMika Westerberg  *
3673edf8e2afSMika Westerberg  * NT_PRSTATUS -> struct elf_prstatus (per thread)
3674edf8e2afSMika Westerberg  * NT_PRSINFO  -> struct elf_prpsinfo
3675edf8e2afSMika Westerberg  * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
3676edf8e2afSMika Westerberg  *
3677edf8e2afSMika Westerberg  * Format follows System V format as close as possible.  Current
3678edf8e2afSMika Westerberg  * version limitations are as follows:
3679edf8e2afSMika Westerberg  *     - no floating point registers are dumped
3680edf8e2afSMika Westerberg  *
3681edf8e2afSMika Westerberg  * Function returns 0 in case of success, negative errno otherwise.
3682edf8e2afSMika Westerberg  *
3683edf8e2afSMika Westerberg  * TODO: make this work also during runtime: it should be
3684edf8e2afSMika Westerberg  * possible to force coredump from running process and then
3685edf8e2afSMika Westerberg  * continue processing.  For example qemu could set up SIGUSR2
3686edf8e2afSMika Westerberg  * handler (provided that target process haven't registered
3687edf8e2afSMika Westerberg  * handler for that) that does the dump when signal is received.
3688edf8e2afSMika Westerberg  */
36899349b4f9SAndreas Färber static int elf_core_dump(int signr, const CPUArchState *env)
3690edf8e2afSMika Westerberg {
369129a0af61SRichard Henderson     const CPUState *cpu = env_cpu((CPUArchState *)env);
36920429a971SAndreas Färber     const TaskState *ts = (const TaskState *)cpu->opaque;
3693edf8e2afSMika Westerberg     struct vm_area_struct *vma = NULL;
3694edf8e2afSMika Westerberg     char corefile[PATH_MAX];
3695edf8e2afSMika Westerberg     struct elf_note_info info;
3696edf8e2afSMika Westerberg     struct elfhdr elf;
3697edf8e2afSMika Westerberg     struct elf_phdr phdr;
3698edf8e2afSMika Westerberg     struct rlimit dumpsize;
3699edf8e2afSMika Westerberg     struct mm_struct *mm = NULL;
3700edf8e2afSMika Westerberg     off_t offset = 0, data_offset = 0;
3701edf8e2afSMika Westerberg     int segs = 0;
3702edf8e2afSMika Westerberg     int fd = -1;
3703edf8e2afSMika Westerberg 
37046afafa86SPeter Maydell     init_note_info(&info);
37056afafa86SPeter Maydell 
3706edf8e2afSMika Westerberg     errno = 0;
3707edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
3708edf8e2afSMika Westerberg     if (dumpsize.rlim_cur == 0)
3709edf8e2afSMika Westerberg         return 0;
3710edf8e2afSMika Westerberg 
3711edf8e2afSMika Westerberg     if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0)
3712edf8e2afSMika Westerberg         return (-errno);
3713edf8e2afSMika Westerberg 
3714edf8e2afSMika Westerberg     if ((fd = open(corefile, O_WRONLY | O_CREAT,
3715edf8e2afSMika Westerberg                    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
3716edf8e2afSMika Westerberg         return (-errno);
3717edf8e2afSMika Westerberg 
3718edf8e2afSMika Westerberg     /*
3719edf8e2afSMika Westerberg      * Walk through target process memory mappings and
3720edf8e2afSMika Westerberg      * set up structure containing this information.  After
3721edf8e2afSMika Westerberg      * this point vma_xxx functions can be used.
3722edf8e2afSMika Westerberg      */
3723edf8e2afSMika Westerberg     if ((mm = vma_init()) == NULL)
3724edf8e2afSMika Westerberg         goto out;
3725edf8e2afSMika Westerberg 
3726edf8e2afSMika Westerberg     walk_memory_regions(mm, vma_walker);
3727edf8e2afSMika Westerberg     segs = vma_get_mapping_count(mm);
3728edf8e2afSMika Westerberg 
3729edf8e2afSMika Westerberg     /*
3730edf8e2afSMika Westerberg      * Construct valid coredump ELF header.  We also
3731edf8e2afSMika Westerberg      * add one more segment for notes.
3732edf8e2afSMika Westerberg      */
3733edf8e2afSMika Westerberg     fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
3734edf8e2afSMika Westerberg     if (dump_write(fd, &elf, sizeof (elf)) != 0)
3735edf8e2afSMika Westerberg         goto out;
3736edf8e2afSMika Westerberg 
3737b6af0975SDaniel P. Berrange     /* fill in the in-memory version of notes */
3738edf8e2afSMika Westerberg     if (fill_note_info(&info, signr, env) < 0)
3739edf8e2afSMika Westerberg         goto out;
3740edf8e2afSMika Westerberg 
3741edf8e2afSMika Westerberg     offset += sizeof (elf);                             /* elf header */
3742edf8e2afSMika Westerberg     offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */
3743edf8e2afSMika Westerberg 
3744edf8e2afSMika Westerberg     /* write out notes program header */
3745edf8e2afSMika Westerberg     fill_elf_note_phdr(&phdr, info.notes_size, offset);
3746edf8e2afSMika Westerberg 
3747edf8e2afSMika Westerberg     offset += info.notes_size;
3748edf8e2afSMika Westerberg     if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
3749edf8e2afSMika Westerberg         goto out;
3750edf8e2afSMika Westerberg 
3751edf8e2afSMika Westerberg     /*
3752edf8e2afSMika Westerberg      * ELF specification wants data to start at page boundary so
3753edf8e2afSMika Westerberg      * we align it here.
3754edf8e2afSMika Westerberg      */
375580f5ce75SLaurent Vivier     data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
3756edf8e2afSMika Westerberg 
3757edf8e2afSMika Westerberg     /*
3758edf8e2afSMika Westerberg      * Write program headers for memory regions mapped in
3759edf8e2afSMika Westerberg      * the target process.
3760edf8e2afSMika Westerberg      */
3761edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
3762edf8e2afSMika Westerberg         (void) memset(&phdr, 0, sizeof (phdr));
3763edf8e2afSMika Westerberg 
3764edf8e2afSMika Westerberg         phdr.p_type = PT_LOAD;
3765edf8e2afSMika Westerberg         phdr.p_offset = offset;
3766edf8e2afSMika Westerberg         phdr.p_vaddr = vma->vma_start;
3767edf8e2afSMika Westerberg         phdr.p_paddr = 0;
3768edf8e2afSMika Westerberg         phdr.p_filesz = vma_dump_size(vma);
3769edf8e2afSMika Westerberg         offset += phdr.p_filesz;
3770edf8e2afSMika Westerberg         phdr.p_memsz = vma->vma_end - vma->vma_start;
3771edf8e2afSMika Westerberg         phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
3772edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_WRITE)
3773edf8e2afSMika Westerberg             phdr.p_flags |= PF_W;
3774edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_EXEC)
3775edf8e2afSMika Westerberg             phdr.p_flags |= PF_X;
3776edf8e2afSMika Westerberg         phdr.p_align = ELF_EXEC_PAGESIZE;
3777edf8e2afSMika Westerberg 
377880f5ce75SLaurent Vivier         bswap_phdr(&phdr, 1);
3779772034b6SPeter Maydell         if (dump_write(fd, &phdr, sizeof(phdr)) != 0) {
3780772034b6SPeter Maydell             goto out;
3781772034b6SPeter Maydell         }
3782edf8e2afSMika Westerberg     }
3783edf8e2afSMika Westerberg 
3784edf8e2afSMika Westerberg     /*
3785edf8e2afSMika Westerberg      * Next we write notes just after program headers.  No
3786edf8e2afSMika Westerberg      * alignment needed here.
3787edf8e2afSMika Westerberg      */
3788edf8e2afSMika Westerberg     if (write_note_info(&info, fd) < 0)
3789edf8e2afSMika Westerberg         goto out;
3790edf8e2afSMika Westerberg 
3791edf8e2afSMika Westerberg     /* align data to page boundary */
3792edf8e2afSMika Westerberg     if (lseek(fd, data_offset, SEEK_SET) != data_offset)
3793edf8e2afSMika Westerberg         goto out;
3794edf8e2afSMika Westerberg 
3795edf8e2afSMika Westerberg     /*
3796edf8e2afSMika Westerberg      * Finally we can dump process memory into corefile as well.
3797edf8e2afSMika Westerberg      */
3798edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
3799edf8e2afSMika Westerberg         abi_ulong addr;
3800edf8e2afSMika Westerberg         abi_ulong end;
3801edf8e2afSMika Westerberg 
3802edf8e2afSMika Westerberg         end = vma->vma_start + vma_dump_size(vma);
3803edf8e2afSMika Westerberg 
3804edf8e2afSMika Westerberg         for (addr = vma->vma_start; addr < end;
3805edf8e2afSMika Westerberg              addr += TARGET_PAGE_SIZE) {
3806edf8e2afSMika Westerberg             char page[TARGET_PAGE_SIZE];
3807edf8e2afSMika Westerberg             int error;
3808edf8e2afSMika Westerberg 
3809edf8e2afSMika Westerberg             /*
3810edf8e2afSMika Westerberg              *  Read in page from target process memory and
3811edf8e2afSMika Westerberg              *  write it to coredump file.
3812edf8e2afSMika Westerberg              */
3813edf8e2afSMika Westerberg             error = copy_from_user(page, addr, sizeof (page));
3814edf8e2afSMika Westerberg             if (error != 0) {
381549995e17SAurelien Jarno                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
3816edf8e2afSMika Westerberg                                addr);
3817edf8e2afSMika Westerberg                 errno = -error;
3818edf8e2afSMika Westerberg                 goto out;
3819edf8e2afSMika Westerberg             }
3820edf8e2afSMika Westerberg             if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
3821edf8e2afSMika Westerberg                 goto out;
3822edf8e2afSMika Westerberg         }
3823edf8e2afSMika Westerberg     }
3824edf8e2afSMika Westerberg 
3825edf8e2afSMika Westerberg  out:
3826edf8e2afSMika Westerberg     free_note_info(&info);
3827edf8e2afSMika Westerberg     if (mm != NULL)
3828edf8e2afSMika Westerberg         vma_delete(mm);
3829edf8e2afSMika Westerberg     (void) close(fd);
3830edf8e2afSMika Westerberg 
3831edf8e2afSMika Westerberg     if (errno != 0)
3832edf8e2afSMika Westerberg         return (-errno);
3833edf8e2afSMika Westerberg     return (0);
3834edf8e2afSMika Westerberg }
3835edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
3836edf8e2afSMika Westerberg 
3837e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
3838e5fe0c52Spbrook {
3839e5fe0c52Spbrook     init_thread(regs, infop);
3840e5fe0c52Spbrook }
3841