xref: /qemu/linux-user/elfload.c (revision f101c25cd66dc4dea1135d2f1783a0786534923a)
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"
93b249d26SPeter Maydell #include "user-internals.h"
10db2af69dSRichard Henderson #include "signal-common.h"
113ad0a769SPeter Maydell #include "loader.h"
125423e6d3SPeter Maydell #include "user-mmap.h"
1376cad711SPaolo Bonzini #include "disas/disas.h"
14ce543844SPhilippe Mathieu-Daudé #include "qemu/bitops.h"
15f348b6d1SVeronia Bahaa #include "qemu/path.h"
16dc5e9ac7SMarkus Armbruster #include "qemu/queue.h"
17c6a2377fSRichard Henderson #include "qemu/guest-random.h"
186fd59449SRichard Henderson #include "qemu/units.h"
19ee947430SAlex Bennée #include "qemu/selfmap.h"
20370ed600SJamie Iles #include "qemu/lockable.h"
21c7f17e7bSRichard Henderson #include "qapi/error.h"
22cc37d98bSRichard Henderson #include "qemu/error-report.h"
23db2af69dSRichard Henderson #include "target_signal.h"
247c10cb38SIlya Leoshkevich #include "accel/tcg/debuginfo.h"
2531e31b8aSbellard 
26e58ffeb3Smalc #ifdef _ARCH_PPC64
27a6cc84f4Smalc #undef ARCH_DLINFO
28a6cc84f4Smalc #undef ELF_PLATFORM
29a6cc84f4Smalc #undef ELF_HWCAP
30ad6919dcSPeter Maydell #undef ELF_HWCAP2
31a6cc84f4Smalc #undef ELF_CLASS
32a6cc84f4Smalc #undef ELF_DATA
33a6cc84f4Smalc #undef ELF_ARCH
34a6cc84f4Smalc #endif
35a6cc84f4Smalc 
36edf8e2afSMika Westerberg #define ELF_OSABI   ELFOSABI_SYSV
37edf8e2afSMika Westerberg 
38cb33da57Sblueswir1 /* from personality.h */
39cb33da57Sblueswir1 
40cb33da57Sblueswir1 /*
41cb33da57Sblueswir1  * Flags for bug emulation.
42cb33da57Sblueswir1  *
43cb33da57Sblueswir1  * These occupy the top three bytes.
44cb33da57Sblueswir1  */
45cb33da57Sblueswir1 enum {
46cb33da57Sblueswir1     ADDR_NO_RANDOMIZE = 0x0040000,      /* disable randomization of VA space */
47d97ef72eSRichard Henderson     FDPIC_FUNCPTRS =    0x0080000,      /* userspace function ptrs point to
48d97ef72eSRichard Henderson                                            descriptors (signal handling) */
49cb33da57Sblueswir1     MMAP_PAGE_ZERO =    0x0100000,
50cb33da57Sblueswir1     ADDR_COMPAT_LAYOUT = 0x0200000,
51cb33da57Sblueswir1     READ_IMPLIES_EXEC = 0x0400000,
52cb33da57Sblueswir1     ADDR_LIMIT_32BIT =  0x0800000,
53cb33da57Sblueswir1     SHORT_INODE =       0x1000000,
54cb33da57Sblueswir1     WHOLE_SECONDS =     0x2000000,
55cb33da57Sblueswir1     STICKY_TIMEOUTS =   0x4000000,
56cb33da57Sblueswir1     ADDR_LIMIT_3GB =    0x8000000,
57cb33da57Sblueswir1 };
58cb33da57Sblueswir1 
59cb33da57Sblueswir1 /*
60cb33da57Sblueswir1  * Personality types.
61cb33da57Sblueswir1  *
62cb33da57Sblueswir1  * These go in the low byte.  Avoid using the top bit, it will
63cb33da57Sblueswir1  * conflict with error returns.
64cb33da57Sblueswir1  */
65cb33da57Sblueswir1 enum {
66cb33da57Sblueswir1     PER_LINUX =         0x0000,
67cb33da57Sblueswir1     PER_LINUX_32BIT =   0x0000 | ADDR_LIMIT_32BIT,
68cb33da57Sblueswir1     PER_LINUX_FDPIC =   0x0000 | FDPIC_FUNCPTRS,
69cb33da57Sblueswir1     PER_SVR4 =          0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
70cb33da57Sblueswir1     PER_SVR3 =          0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
71d97ef72eSRichard Henderson     PER_SCOSVR3 =       0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
72cb33da57Sblueswir1     PER_OSR5 =          0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
73cb33da57Sblueswir1     PER_WYSEV386 =      0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
74cb33da57Sblueswir1     PER_ISCR4 =         0x0005 | STICKY_TIMEOUTS,
75cb33da57Sblueswir1     PER_BSD =           0x0006,
76cb33da57Sblueswir1     PER_SUNOS =         0x0006 | STICKY_TIMEOUTS,
77cb33da57Sblueswir1     PER_XENIX =         0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
78cb33da57Sblueswir1     PER_LINUX32 =       0x0008,
79cb33da57Sblueswir1     PER_LINUX32_3GB =   0x0008 | ADDR_LIMIT_3GB,
80cb33da57Sblueswir1     PER_IRIX32 =        0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
81cb33da57Sblueswir1     PER_IRIXN32 =       0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
82cb33da57Sblueswir1     PER_IRIX64 =        0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
83cb33da57Sblueswir1     PER_RISCOS =        0x000c,
84cb33da57Sblueswir1     PER_SOLARIS =       0x000d | STICKY_TIMEOUTS,
85cb33da57Sblueswir1     PER_UW7 =           0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
86cb33da57Sblueswir1     PER_OSF4 =          0x000f,                  /* OSF/1 v4 */
87cb33da57Sblueswir1     PER_HPUX =          0x0010,
88cb33da57Sblueswir1     PER_MASK =          0x00ff,
89cb33da57Sblueswir1 };
90cb33da57Sblueswir1 
91cb33da57Sblueswir1 /*
92cb33da57Sblueswir1  * Return the base personality without flags.
93cb33da57Sblueswir1  */
94cb33da57Sblueswir1 #define personality(pers)       (pers & PER_MASK)
95cb33da57Sblueswir1 
963cb10cfaSChristophe Lyon int info_is_fdpic(struct image_info *info)
973cb10cfaSChristophe Lyon {
983cb10cfaSChristophe Lyon     return info->personality == PER_LINUX_FDPIC;
993cb10cfaSChristophe Lyon }
1003cb10cfaSChristophe Lyon 
10183fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */
10283fb7adfSbellard #ifndef MAP_DENYWRITE
10383fb7adfSbellard #define MAP_DENYWRITE 0
10483fb7adfSbellard #endif
10583fb7adfSbellard 
10683fb7adfSbellard /* should probably go in elf.h */
10783fb7adfSbellard #ifndef ELIBBAD
10883fb7adfSbellard #define ELIBBAD 80
10983fb7adfSbellard #endif
11083fb7adfSbellard 
111ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN
11228490231SRichard Henderson #define ELF_DATA        ELFDATA2MSB
11328490231SRichard Henderson #else
11428490231SRichard Henderson #define ELF_DATA        ELFDATA2LSB
11528490231SRichard Henderson #endif
11628490231SRichard Henderson 
117a29f998dSPaolo Bonzini #ifdef TARGET_ABI_MIPSN32
118918fc54cSPaolo Bonzini typedef abi_ullong      target_elf_greg_t;
119918fc54cSPaolo Bonzini #define tswapreg(ptr)   tswap64(ptr)
120a29f998dSPaolo Bonzini #else
121a29f998dSPaolo Bonzini typedef abi_ulong       target_elf_greg_t;
122a29f998dSPaolo Bonzini #define tswapreg(ptr)   tswapal(ptr)
123a29f998dSPaolo Bonzini #endif
124a29f998dSPaolo Bonzini 
12521e807faSNathan Froyd #ifdef USE_UID16
1261ddd592fSPaolo Bonzini typedef abi_ushort      target_uid_t;
1271ddd592fSPaolo Bonzini typedef abi_ushort      target_gid_t;
12821e807faSNathan Froyd #else
129f8fd4fc4SPaolo Bonzini typedef abi_uint        target_uid_t;
130f8fd4fc4SPaolo Bonzini typedef abi_uint        target_gid_t;
13121e807faSNathan Froyd #endif
132f8fd4fc4SPaolo Bonzini typedef abi_int         target_pid_t;
13321e807faSNathan Froyd 
13430ac07d4Sbellard #ifdef TARGET_I386
13530ac07d4Sbellard 
13615338fd7Sbellard #define ELF_HWCAP get_elf_hwcap()
13715338fd7Sbellard 
13815338fd7Sbellard static uint32_t get_elf_hwcap(void)
13915338fd7Sbellard {
140a2247f8eSAndreas Färber     X86CPU *cpu = X86_CPU(thread_cpu);
141a2247f8eSAndreas Färber 
142a2247f8eSAndreas Färber     return cpu->env.features[FEAT_1_EDX];
14315338fd7Sbellard }
14415338fd7Sbellard 
14584409ddbSj_mayer #ifdef TARGET_X86_64
14684409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL
14784409ddbSj_mayer 
14884409ddbSj_mayer #define ELF_CLASS      ELFCLASS64
14984409ddbSj_mayer #define ELF_ARCH       EM_X86_64
15084409ddbSj_mayer 
1519263ba84SRichard Henderson #define ELF_PLATFORM   "x86_64"
1529263ba84SRichard Henderson 
15384409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
15484409ddbSj_mayer {
15584409ddbSj_mayer     regs->rax = 0;
15684409ddbSj_mayer     regs->rsp = infop->start_stack;
15784409ddbSj_mayer     regs->rip = infop->entry;
15884409ddbSj_mayer }
15984409ddbSj_mayer 
1609edc5d79SMika Westerberg #define ELF_NREG    27
161c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
1629edc5d79SMika Westerberg 
1639edc5d79SMika Westerberg /*
1649edc5d79SMika Westerberg  * Note that ELF_NREG should be 29 as there should be place for
1659edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
1669edc5d79SMika Westerberg  * those.
1679edc5d79SMika Westerberg  *
1689edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
1699edc5d79SMika Westerberg  */
17005390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
1719edc5d79SMika Westerberg {
172030912e0SIlya Leoshkevich     (*regs)[0] = tswapreg(env->regs[15]);
173030912e0SIlya Leoshkevich     (*regs)[1] = tswapreg(env->regs[14]);
174030912e0SIlya Leoshkevich     (*regs)[2] = tswapreg(env->regs[13]);
175030912e0SIlya Leoshkevich     (*regs)[3] = tswapreg(env->regs[12]);
176030912e0SIlya Leoshkevich     (*regs)[4] = tswapreg(env->regs[R_EBP]);
177030912e0SIlya Leoshkevich     (*regs)[5] = tswapreg(env->regs[R_EBX]);
178030912e0SIlya Leoshkevich     (*regs)[6] = tswapreg(env->regs[11]);
179030912e0SIlya Leoshkevich     (*regs)[7] = tswapreg(env->regs[10]);
180030912e0SIlya Leoshkevich     (*regs)[8] = tswapreg(env->regs[9]);
181030912e0SIlya Leoshkevich     (*regs)[9] = tswapreg(env->regs[8]);
182030912e0SIlya Leoshkevich     (*regs)[10] = tswapreg(env->regs[R_EAX]);
183030912e0SIlya Leoshkevich     (*regs)[11] = tswapreg(env->regs[R_ECX]);
184030912e0SIlya Leoshkevich     (*regs)[12] = tswapreg(env->regs[R_EDX]);
185030912e0SIlya Leoshkevich     (*regs)[13] = tswapreg(env->regs[R_ESI]);
186030912e0SIlya Leoshkevich     (*regs)[14] = tswapreg(env->regs[R_EDI]);
187030912e0SIlya Leoshkevich     (*regs)[15] = tswapreg(env->regs[R_EAX]); /* XXX */
188030912e0SIlya Leoshkevich     (*regs)[16] = tswapreg(env->eip);
189030912e0SIlya Leoshkevich     (*regs)[17] = tswapreg(env->segs[R_CS].selector & 0xffff);
190030912e0SIlya Leoshkevich     (*regs)[18] = tswapreg(env->eflags);
191030912e0SIlya Leoshkevich     (*regs)[19] = tswapreg(env->regs[R_ESP]);
192030912e0SIlya Leoshkevich     (*regs)[20] = tswapreg(env->segs[R_SS].selector & 0xffff);
193030912e0SIlya Leoshkevich     (*regs)[21] = tswapreg(env->segs[R_FS].selector & 0xffff);
194030912e0SIlya Leoshkevich     (*regs)[22] = tswapreg(env->segs[R_GS].selector & 0xffff);
195030912e0SIlya Leoshkevich     (*regs)[23] = tswapreg(env->segs[R_DS].selector & 0xffff);
196030912e0SIlya Leoshkevich     (*regs)[24] = tswapreg(env->segs[R_ES].selector & 0xffff);
197030912e0SIlya Leoshkevich     (*regs)[25] = tswapreg(env->segs[R_FS].selector & 0xffff);
198030912e0SIlya Leoshkevich     (*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff);
1999edc5d79SMika Westerberg }
2009edc5d79SMika Westerberg 
201d461b73eSRichard Henderson #if ULONG_MAX > UINT32_MAX
202d461b73eSRichard Henderson #define INIT_GUEST_COMMPAGE
203d461b73eSRichard Henderson static bool init_guest_commpage(void)
204d461b73eSRichard Henderson {
205d461b73eSRichard Henderson     /*
206d461b73eSRichard Henderson      * The vsyscall page is at a high negative address aka kernel space,
207d461b73eSRichard Henderson      * which means that we cannot actually allocate it with target_mmap.
208d461b73eSRichard Henderson      * We still should be able to use page_set_flags, unless the user
209d461b73eSRichard Henderson      * has specified -R reserved_va, which would trigger an assert().
210d461b73eSRichard Henderson      */
211d461b73eSRichard Henderson     if (reserved_va != 0 &&
21295059f9cSRichard Henderson         TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE - 1 > reserved_va) {
213d461b73eSRichard Henderson         error_report("Cannot allocate vsyscall page");
214d461b73eSRichard Henderson         exit(EXIT_FAILURE);
215d461b73eSRichard Henderson     }
216d461b73eSRichard Henderson     page_set_flags(TARGET_VSYSCALL_PAGE,
21749840a4aSRichard Henderson                    TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK,
218d461b73eSRichard Henderson                    PAGE_EXEC | PAGE_VALID);
219d461b73eSRichard Henderson     return true;
220d461b73eSRichard Henderson }
221d461b73eSRichard Henderson #endif
22284409ddbSj_mayer #else
22384409ddbSj_mayer 
22430ac07d4Sbellard #define ELF_START_MMAP 0x80000000
22530ac07d4Sbellard 
22630ac07d4Sbellard /*
22730ac07d4Sbellard  * This is used to ensure we don't load something for the wrong architecture.
22830ac07d4Sbellard  */
22930ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
23030ac07d4Sbellard 
23130ac07d4Sbellard /*
23230ac07d4Sbellard  * These are used to set parameters in the core dumps.
23330ac07d4Sbellard  */
23430ac07d4Sbellard #define ELF_CLASS       ELFCLASS32
23530ac07d4Sbellard #define ELF_ARCH        EM_386
23630ac07d4Sbellard 
2379263ba84SRichard Henderson #define ELF_PLATFORM get_elf_platform()
238872f3d04SRichard Henderson #define EXSTACK_DEFAULT true
2399263ba84SRichard Henderson 
2409263ba84SRichard Henderson static const char *get_elf_platform(void)
2419263ba84SRichard Henderson {
2429263ba84SRichard Henderson     static char elf_platform[] = "i386";
2439263ba84SRichard Henderson     int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
2449263ba84SRichard Henderson     if (family > 6) {
2459263ba84SRichard Henderson         family = 6;
2469263ba84SRichard Henderson     }
2479263ba84SRichard Henderson     if (family >= 3) {
2489263ba84SRichard Henderson         elf_platform[1] = '0' + family;
2499263ba84SRichard Henderson     }
2509263ba84SRichard Henderson     return elf_platform;
2519263ba84SRichard Henderson }
2529263ba84SRichard Henderson 
253d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
254d97ef72eSRichard Henderson                                struct image_info *infop)
255e5fe0c52Spbrook {
256e5fe0c52Spbrook     regs->esp = infop->start_stack;
257e5fe0c52Spbrook     regs->eip = infop->entry;
258e5fe0c52Spbrook 
25930ac07d4Sbellard     /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
26030ac07d4Sbellard        starts %edx contains a pointer to a function which might be
26130ac07d4Sbellard        registered using `atexit'.  This provides a mean for the
26230ac07d4Sbellard        dynamic linker to call DT_FINI functions for shared libraries
26330ac07d4Sbellard        that have been loaded before the code runs.
26430ac07d4Sbellard 
26530ac07d4Sbellard        A value of 0 tells we have no such handler.  */
266e5fe0c52Spbrook     regs->edx = 0;
267b346ff46Sbellard }
2689edc5d79SMika Westerberg 
2699edc5d79SMika Westerberg #define ELF_NREG    17
270c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
2719edc5d79SMika Westerberg 
2729edc5d79SMika Westerberg /*
2739edc5d79SMika Westerberg  * Note that ELF_NREG should be 19 as there should be place for
2749edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
2759edc5d79SMika Westerberg  * those.
2769edc5d79SMika Westerberg  *
2779edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
2789edc5d79SMika Westerberg  */
27905390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
2809edc5d79SMika Westerberg {
281030912e0SIlya Leoshkevich     (*regs)[0] = tswapreg(env->regs[R_EBX]);
282030912e0SIlya Leoshkevich     (*regs)[1] = tswapreg(env->regs[R_ECX]);
283030912e0SIlya Leoshkevich     (*regs)[2] = tswapreg(env->regs[R_EDX]);
284030912e0SIlya Leoshkevich     (*regs)[3] = tswapreg(env->regs[R_ESI]);
285030912e0SIlya Leoshkevich     (*regs)[4] = tswapreg(env->regs[R_EDI]);
286030912e0SIlya Leoshkevich     (*regs)[5] = tswapreg(env->regs[R_EBP]);
287030912e0SIlya Leoshkevich     (*regs)[6] = tswapreg(env->regs[R_EAX]);
288030912e0SIlya Leoshkevich     (*regs)[7] = tswapreg(env->segs[R_DS].selector & 0xffff);
289030912e0SIlya Leoshkevich     (*regs)[8] = tswapreg(env->segs[R_ES].selector & 0xffff);
290030912e0SIlya Leoshkevich     (*regs)[9] = tswapreg(env->segs[R_FS].selector & 0xffff);
291030912e0SIlya Leoshkevich     (*regs)[10] = tswapreg(env->segs[R_GS].selector & 0xffff);
292030912e0SIlya Leoshkevich     (*regs)[11] = tswapreg(env->regs[R_EAX]); /* XXX */
293030912e0SIlya Leoshkevich     (*regs)[12] = tswapreg(env->eip);
294030912e0SIlya Leoshkevich     (*regs)[13] = tswapreg(env->segs[R_CS].selector & 0xffff);
295030912e0SIlya Leoshkevich     (*regs)[14] = tswapreg(env->eflags);
296030912e0SIlya Leoshkevich     (*regs)[15] = tswapreg(env->regs[R_ESP]);
297030912e0SIlya Leoshkevich     (*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff);
2989edc5d79SMika Westerberg }
29984409ddbSj_mayer #endif
300b346ff46Sbellard 
3019edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP
302b346ff46Sbellard #define ELF_EXEC_PAGESIZE       4096
303b346ff46Sbellard 
304b346ff46Sbellard #endif
305b346ff46Sbellard 
306b346ff46Sbellard #ifdef TARGET_ARM
307b346ff46Sbellard 
30824e76ff0SPeter Maydell #ifndef TARGET_AARCH64
30924e76ff0SPeter Maydell /* 32 bit ARM definitions */
31024e76ff0SPeter Maydell 
311b346ff46Sbellard #define ELF_START_MMAP 0x80000000
312b346ff46Sbellard 
313b597c3f7SPeter Crosthwaite #define ELF_ARCH        EM_ARM
314b346ff46Sbellard #define ELF_CLASS       ELFCLASS32
315872f3d04SRichard Henderson #define EXSTACK_DEFAULT true
316b346ff46Sbellard 
317d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
318d97ef72eSRichard Henderson                                struct image_info *infop)
319b346ff46Sbellard {
320992f48a0Sblueswir1     abi_long stack = infop->start_stack;
321b346ff46Sbellard     memset(regs, 0, sizeof(*regs));
32299033caeSAlexander Graf 
323167e4cdcSPeter Maydell     regs->uregs[16] = ARM_CPU_MODE_USR;
324167e4cdcSPeter Maydell     if (infop->entry & 1) {
325167e4cdcSPeter Maydell         regs->uregs[16] |= CPSR_T;
326167e4cdcSPeter Maydell     }
327167e4cdcSPeter Maydell     regs->uregs[15] = infop->entry & 0xfffffffe;
328167e4cdcSPeter Maydell     regs->uregs[13] = infop->start_stack;
3292f619698Sbellard     /* FIXME - what to for failure of get_user()? */
330167e4cdcSPeter Maydell     get_user_ual(regs->uregs[2], stack + 8); /* envp */
331167e4cdcSPeter Maydell     get_user_ual(regs->uregs[1], stack + 4); /* envp */
332a1516e92Sbellard     /* XXX: it seems that r0 is zeroed after ! */
333167e4cdcSPeter Maydell     regs->uregs[0] = 0;
334e5fe0c52Spbrook     /* For uClinux PIC binaries.  */
335863cf0b7Sj_mayer     /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
336167e4cdcSPeter Maydell     regs->uregs[10] = infop->start_data;
3373cb10cfaSChristophe Lyon 
3383cb10cfaSChristophe Lyon     /* Support ARM FDPIC.  */
3393cb10cfaSChristophe Lyon     if (info_is_fdpic(infop)) {
3403cb10cfaSChristophe Lyon         /* As described in the ABI document, r7 points to the loadmap info
3413cb10cfaSChristophe Lyon          * prepared by the kernel. If an interpreter is needed, r8 points
3423cb10cfaSChristophe Lyon          * to the interpreter loadmap and r9 points to the interpreter
3433cb10cfaSChristophe Lyon          * PT_DYNAMIC info. If no interpreter is needed, r8 is zero, and
3443cb10cfaSChristophe Lyon          * r9 points to the main program PT_DYNAMIC info.
3453cb10cfaSChristophe Lyon          */
3463cb10cfaSChristophe Lyon         regs->uregs[7] = infop->loadmap_addr;
3473cb10cfaSChristophe Lyon         if (infop->interpreter_loadmap_addr) {
3483cb10cfaSChristophe Lyon             /* Executable is dynamically loaded.  */
3493cb10cfaSChristophe Lyon             regs->uregs[8] = infop->interpreter_loadmap_addr;
3503cb10cfaSChristophe Lyon             regs->uregs[9] = infop->interpreter_pt_dynamic_addr;
3513cb10cfaSChristophe Lyon         } else {
3523cb10cfaSChristophe Lyon             regs->uregs[8] = 0;
3533cb10cfaSChristophe Lyon             regs->uregs[9] = infop->pt_dynamic_addr;
3543cb10cfaSChristophe Lyon         }
3553cb10cfaSChristophe Lyon     }
356b346ff46Sbellard }
357b346ff46Sbellard 
358edf8e2afSMika Westerberg #define ELF_NREG    18
359c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
360edf8e2afSMika Westerberg 
36105390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env)
362edf8e2afSMika Westerberg {
36386cd7b2dSPaolo Bonzini     (*regs)[0] = tswapreg(env->regs[0]);
36486cd7b2dSPaolo Bonzini     (*regs)[1] = tswapreg(env->regs[1]);
36586cd7b2dSPaolo Bonzini     (*regs)[2] = tswapreg(env->regs[2]);
36686cd7b2dSPaolo Bonzini     (*regs)[3] = tswapreg(env->regs[3]);
36786cd7b2dSPaolo Bonzini     (*regs)[4] = tswapreg(env->regs[4]);
36886cd7b2dSPaolo Bonzini     (*regs)[5] = tswapreg(env->regs[5]);
36986cd7b2dSPaolo Bonzini     (*regs)[6] = tswapreg(env->regs[6]);
37086cd7b2dSPaolo Bonzini     (*regs)[7] = tswapreg(env->regs[7]);
37186cd7b2dSPaolo Bonzini     (*regs)[8] = tswapreg(env->regs[8]);
37286cd7b2dSPaolo Bonzini     (*regs)[9] = tswapreg(env->regs[9]);
37386cd7b2dSPaolo Bonzini     (*regs)[10] = tswapreg(env->regs[10]);
37486cd7b2dSPaolo Bonzini     (*regs)[11] = tswapreg(env->regs[11]);
37586cd7b2dSPaolo Bonzini     (*regs)[12] = tswapreg(env->regs[12]);
37686cd7b2dSPaolo Bonzini     (*regs)[13] = tswapreg(env->regs[13]);
37786cd7b2dSPaolo Bonzini     (*regs)[14] = tswapreg(env->regs[14]);
37886cd7b2dSPaolo Bonzini     (*regs)[15] = tswapreg(env->regs[15]);
379edf8e2afSMika Westerberg 
38086cd7b2dSPaolo Bonzini     (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env));
38186cd7b2dSPaolo Bonzini     (*regs)[17] = tswapreg(env->regs[0]); /* XXX */
382edf8e2afSMika Westerberg }
383edf8e2afSMika Westerberg 
38430ac07d4Sbellard #define USE_ELF_CORE_DUMP
38530ac07d4Sbellard #define ELF_EXEC_PAGESIZE       4096
38630ac07d4Sbellard 
387afce2927Sbellard enum
388afce2927Sbellard {
389afce2927Sbellard     ARM_HWCAP_ARM_SWP       = 1 << 0,
390afce2927Sbellard     ARM_HWCAP_ARM_HALF      = 1 << 1,
391afce2927Sbellard     ARM_HWCAP_ARM_THUMB     = 1 << 2,
392afce2927Sbellard     ARM_HWCAP_ARM_26BIT     = 1 << 3,
393afce2927Sbellard     ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
394afce2927Sbellard     ARM_HWCAP_ARM_FPA       = 1 << 5,
395afce2927Sbellard     ARM_HWCAP_ARM_VFP       = 1 << 6,
396afce2927Sbellard     ARM_HWCAP_ARM_EDSP      = 1 << 7,
397cf6de34aSRiku Voipio     ARM_HWCAP_ARM_JAVA      = 1 << 8,
398cf6de34aSRiku Voipio     ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
39943ce393eSPeter Maydell     ARM_HWCAP_ARM_CRUNCH    = 1 << 10,
40043ce393eSPeter Maydell     ARM_HWCAP_ARM_THUMBEE   = 1 << 11,
40143ce393eSPeter Maydell     ARM_HWCAP_ARM_NEON      = 1 << 12,
40243ce393eSPeter Maydell     ARM_HWCAP_ARM_VFPv3     = 1 << 13,
40343ce393eSPeter Maydell     ARM_HWCAP_ARM_VFPv3D16  = 1 << 14,
40424682654SPeter Maydell     ARM_HWCAP_ARM_TLS       = 1 << 15,
40524682654SPeter Maydell     ARM_HWCAP_ARM_VFPv4     = 1 << 16,
40624682654SPeter Maydell     ARM_HWCAP_ARM_IDIVA     = 1 << 17,
40724682654SPeter Maydell     ARM_HWCAP_ARM_IDIVT     = 1 << 18,
40824682654SPeter Maydell     ARM_HWCAP_ARM_VFPD32    = 1 << 19,
40924682654SPeter Maydell     ARM_HWCAP_ARM_LPAE      = 1 << 20,
41024682654SPeter Maydell     ARM_HWCAP_ARM_EVTSTRM   = 1 << 21,
411afce2927Sbellard };
412afce2927Sbellard 
413ad6919dcSPeter Maydell enum {
414ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_AES      = 1 << 0,
415ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_PMULL    = 1 << 1,
416ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_SHA1     = 1 << 2,
417ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_SHA2     = 1 << 3,
418ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_CRC32    = 1 << 4,
419ad6919dcSPeter Maydell };
420ad6919dcSPeter Maydell 
4216b1275ffSPeter Maydell /* The commpage only exists for 32 bit kernels */
4226b1275ffSPeter Maydell 
42366346fafSRichard Henderson #define HI_COMMPAGE (intptr_t)0xffff0f00u
424ee947430SAlex Bennée 
425ee947430SAlex Bennée static bool init_guest_commpage(void)
42697cc7560SDr. David Alan Gilbert {
4276cda41daSRichard Henderson     abi_ptr commpage = HI_COMMPAGE & -qemu_host_page_size;
4286cda41daSRichard Henderson     void *want = g2h_untagged(commpage);
4296cda41daSRichard Henderson     void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
4305c3e87f3SAlex Bennée                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
43197cc7560SDr. David Alan Gilbert 
4326cda41daSRichard Henderson     if (addr == MAP_FAILED) {
433ee947430SAlex Bennée         perror("Allocating guest commpage");
434ee947430SAlex Bennée         exit(EXIT_FAILURE);
435ee947430SAlex Bennée     }
436ee947430SAlex Bennée     if (addr != want) {
437ee947430SAlex Bennée         return false;
438806d1021SMeador Inge     }
439806d1021SMeador Inge 
440ee947430SAlex Bennée     /* Set kernel helper versions; rest of page is 0.  */
4416cda41daSRichard Henderson     __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu));
44297cc7560SDr. David Alan Gilbert 
4436cda41daSRichard Henderson     if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
44497cc7560SDr. David Alan Gilbert         perror("Protecting guest commpage");
445ee947430SAlex Bennée         exit(EXIT_FAILURE);
44697cc7560SDr. David Alan Gilbert     }
4476cda41daSRichard Henderson 
4486cda41daSRichard Henderson     page_set_flags(commpage, commpage | ~qemu_host_page_mask,
4496cda41daSRichard Henderson                    PAGE_READ | PAGE_EXEC | PAGE_VALID);
450ee947430SAlex Bennée     return true;
45197cc7560SDr. David Alan Gilbert }
452adf050b1SBenoit Canet 
453adf050b1SBenoit Canet #define ELF_HWCAP get_elf_hwcap()
454ad6919dcSPeter Maydell #define ELF_HWCAP2 get_elf_hwcap2()
455adf050b1SBenoit Canet 
456adf050b1SBenoit Canet static uint32_t get_elf_hwcap(void)
457adf050b1SBenoit Canet {
458a2247f8eSAndreas Färber     ARMCPU *cpu = ARM_CPU(thread_cpu);
459adf050b1SBenoit Canet     uint32_t hwcaps = 0;
460adf050b1SBenoit Canet 
461adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_SWP;
462adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_HALF;
463adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_THUMB;
464adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
465adf050b1SBenoit Canet 
466adf050b1SBenoit Canet     /* probe for the extra features */
467adf050b1SBenoit Canet #define GET_FEATURE(feat, hwcap) \
468a2247f8eSAndreas Färber     do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
469962fcbf2SRichard Henderson 
470962fcbf2SRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \
471962fcbf2SRichard Henderson     do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
472962fcbf2SRichard Henderson 
47324682654SPeter Maydell     /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */
47424682654SPeter Maydell     GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP);
475adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
476adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
477adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
47824682654SPeter Maydell     GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
479bfa8a370SRichard Henderson     GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
480873b73c0SPeter Maydell     GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA);
481873b73c0SPeter Maydell     GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT);
482bfa8a370SRichard Henderson     GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP);
483bfa8a370SRichard Henderson 
484bfa8a370SRichard Henderson     if (cpu_isar_feature(aa32_fpsp_v3, cpu) ||
485bfa8a370SRichard Henderson         cpu_isar_feature(aa32_fpdp_v3, cpu)) {
486bfa8a370SRichard Henderson         hwcaps |= ARM_HWCAP_ARM_VFPv3;
487bfa8a370SRichard Henderson         if (cpu_isar_feature(aa32_simd_r32, cpu)) {
488bfa8a370SRichard Henderson             hwcaps |= ARM_HWCAP_ARM_VFPD32;
489bfa8a370SRichard Henderson         } else {
490bfa8a370SRichard Henderson             hwcaps |= ARM_HWCAP_ARM_VFPv3D16;
491bfa8a370SRichard Henderson         }
492bfa8a370SRichard Henderson     }
493bfa8a370SRichard Henderson     GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4);
494adf050b1SBenoit Canet 
495adf050b1SBenoit Canet     return hwcaps;
496adf050b1SBenoit Canet }
497afce2927Sbellard 
498ad6919dcSPeter Maydell static uint32_t get_elf_hwcap2(void)
499ad6919dcSPeter Maydell {
500ad6919dcSPeter Maydell     ARMCPU *cpu = ARM_CPU(thread_cpu);
501ad6919dcSPeter Maydell     uint32_t hwcaps = 0;
502ad6919dcSPeter Maydell 
503962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES);
504962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL);
505962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1);
506962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2);
507962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32);
508ad6919dcSPeter Maydell     return hwcaps;
509ad6919dcSPeter Maydell }
510ad6919dcSPeter Maydell 
511ad6919dcSPeter Maydell #undef GET_FEATURE
512962fcbf2SRichard Henderson #undef GET_FEATURE_ID
513ad6919dcSPeter Maydell 
51413ec4ec3SRichard Henderson #define ELF_PLATFORM get_elf_platform()
51513ec4ec3SRichard Henderson 
51613ec4ec3SRichard Henderson static const char *get_elf_platform(void)
51713ec4ec3SRichard Henderson {
51813ec4ec3SRichard Henderson     CPUARMState *env = thread_cpu->env_ptr;
51913ec4ec3SRichard Henderson 
520ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN
52113ec4ec3SRichard Henderson # define END  "b"
52213ec4ec3SRichard Henderson #else
52313ec4ec3SRichard Henderson # define END  "l"
52413ec4ec3SRichard Henderson #endif
52513ec4ec3SRichard Henderson 
52613ec4ec3SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)) {
52713ec4ec3SRichard Henderson         return "v8" END;
52813ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V7)) {
52913ec4ec3SRichard Henderson         if (arm_feature(env, ARM_FEATURE_M)) {
53013ec4ec3SRichard Henderson             return "v7m" END;
53113ec4ec3SRichard Henderson         } else {
53213ec4ec3SRichard Henderson             return "v7" END;
53313ec4ec3SRichard Henderson         }
53413ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V6)) {
53513ec4ec3SRichard Henderson         return "v6" END;
53613ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V5)) {
53713ec4ec3SRichard Henderson         return "v5" END;
53813ec4ec3SRichard Henderson     } else {
53913ec4ec3SRichard Henderson         return "v4" END;
54013ec4ec3SRichard Henderson     }
54113ec4ec3SRichard Henderson 
54213ec4ec3SRichard Henderson #undef END
54313ec4ec3SRichard Henderson }
54413ec4ec3SRichard Henderson 
54524e76ff0SPeter Maydell #else
54624e76ff0SPeter Maydell /* 64 bit ARM definitions */
54724e76ff0SPeter Maydell #define ELF_START_MMAP 0x80000000
54824e76ff0SPeter Maydell 
549b597c3f7SPeter Crosthwaite #define ELF_ARCH        EM_AARCH64
55024e76ff0SPeter Maydell #define ELF_CLASS       ELFCLASS64
551ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN
552e20e3ec9SRichard Henderson # define ELF_PLATFORM    "aarch64_be"
553e20e3ec9SRichard Henderson #else
55424e76ff0SPeter Maydell # define ELF_PLATFORM    "aarch64"
555e20e3ec9SRichard Henderson #endif
55624e76ff0SPeter Maydell 
55724e76ff0SPeter Maydell static inline void init_thread(struct target_pt_regs *regs,
55824e76ff0SPeter Maydell                                struct image_info *infop)
55924e76ff0SPeter Maydell {
56024e76ff0SPeter Maydell     abi_long stack = infop->start_stack;
56124e76ff0SPeter Maydell     memset(regs, 0, sizeof(*regs));
56224e76ff0SPeter Maydell 
56324e76ff0SPeter Maydell     regs->pc = infop->entry & ~0x3ULL;
56424e76ff0SPeter Maydell     regs->sp = stack;
56524e76ff0SPeter Maydell }
56624e76ff0SPeter Maydell 
56724e76ff0SPeter Maydell #define ELF_NREG    34
56824e76ff0SPeter Maydell typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
56924e76ff0SPeter Maydell 
57024e76ff0SPeter Maydell static void elf_core_copy_regs(target_elf_gregset_t *regs,
57124e76ff0SPeter Maydell                                const CPUARMState *env)
57224e76ff0SPeter Maydell {
57324e76ff0SPeter Maydell     int i;
57424e76ff0SPeter Maydell 
57524e76ff0SPeter Maydell     for (i = 0; i < 32; i++) {
57624e76ff0SPeter Maydell         (*regs)[i] = tswapreg(env->xregs[i]);
57724e76ff0SPeter Maydell     }
57824e76ff0SPeter Maydell     (*regs)[32] = tswapreg(env->pc);
57924e76ff0SPeter Maydell     (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env));
58024e76ff0SPeter Maydell }
58124e76ff0SPeter Maydell 
58224e76ff0SPeter Maydell #define USE_ELF_CORE_DUMP
58324e76ff0SPeter Maydell #define ELF_EXEC_PAGESIZE       4096
58424e76ff0SPeter Maydell 
58524e76ff0SPeter Maydell enum {
58624e76ff0SPeter Maydell     ARM_HWCAP_A64_FP            = 1 << 0,
58724e76ff0SPeter Maydell     ARM_HWCAP_A64_ASIMD         = 1 << 1,
58824e76ff0SPeter Maydell     ARM_HWCAP_A64_EVTSTRM       = 1 << 2,
58924e76ff0SPeter Maydell     ARM_HWCAP_A64_AES           = 1 << 3,
59024e76ff0SPeter Maydell     ARM_HWCAP_A64_PMULL         = 1 << 4,
59124e76ff0SPeter Maydell     ARM_HWCAP_A64_SHA1          = 1 << 5,
59224e76ff0SPeter Maydell     ARM_HWCAP_A64_SHA2          = 1 << 6,
59324e76ff0SPeter Maydell     ARM_HWCAP_A64_CRC32         = 1 << 7,
594955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ATOMICS       = 1 << 8,
595955f56d4SArd Biesheuvel     ARM_HWCAP_A64_FPHP          = 1 << 9,
596955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDHP       = 1 << 10,
597955f56d4SArd Biesheuvel     ARM_HWCAP_A64_CPUID         = 1 << 11,
598955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDRDM      = 1 << 12,
599955f56d4SArd Biesheuvel     ARM_HWCAP_A64_JSCVT         = 1 << 13,
600955f56d4SArd Biesheuvel     ARM_HWCAP_A64_FCMA          = 1 << 14,
601955f56d4SArd Biesheuvel     ARM_HWCAP_A64_LRCPC         = 1 << 15,
602955f56d4SArd Biesheuvel     ARM_HWCAP_A64_DCPOP         = 1 << 16,
603955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SHA3          = 1 << 17,
604955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SM3           = 1 << 18,
605955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SM4           = 1 << 19,
606955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDDP       = 1 << 20,
607955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SHA512        = 1 << 21,
608955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SVE           = 1 << 22,
6090083a1faSRichard Henderson     ARM_HWCAP_A64_ASIMDFHM      = 1 << 23,
6100083a1faSRichard Henderson     ARM_HWCAP_A64_DIT           = 1 << 24,
6110083a1faSRichard Henderson     ARM_HWCAP_A64_USCAT         = 1 << 25,
6120083a1faSRichard Henderson     ARM_HWCAP_A64_ILRCPC        = 1 << 26,
6130083a1faSRichard Henderson     ARM_HWCAP_A64_FLAGM         = 1 << 27,
6140083a1faSRichard Henderson     ARM_HWCAP_A64_SSBS          = 1 << 28,
6150083a1faSRichard Henderson     ARM_HWCAP_A64_SB            = 1 << 29,
6160083a1faSRichard Henderson     ARM_HWCAP_A64_PACA          = 1 << 30,
6170083a1faSRichard Henderson     ARM_HWCAP_A64_PACG          = 1UL << 31,
6182041df4aSRichard Henderson 
6192041df4aSRichard Henderson     ARM_HWCAP2_A64_DCPODP       = 1 << 0,
6202041df4aSRichard Henderson     ARM_HWCAP2_A64_SVE2         = 1 << 1,
6212041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEAES       = 1 << 2,
6222041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEPMULL     = 1 << 3,
6232041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEBITPERM   = 1 << 4,
6242041df4aSRichard Henderson     ARM_HWCAP2_A64_SVESHA3      = 1 << 5,
6252041df4aSRichard Henderson     ARM_HWCAP2_A64_SVESM4       = 1 << 6,
6262041df4aSRichard Henderson     ARM_HWCAP2_A64_FLAGM2       = 1 << 7,
6272041df4aSRichard Henderson     ARM_HWCAP2_A64_FRINT        = 1 << 8,
62868948d18SRichard Henderson     ARM_HWCAP2_A64_SVEI8MM      = 1 << 9,
62968948d18SRichard Henderson     ARM_HWCAP2_A64_SVEF32MM     = 1 << 10,
63068948d18SRichard Henderson     ARM_HWCAP2_A64_SVEF64MM     = 1 << 11,
63168948d18SRichard Henderson     ARM_HWCAP2_A64_SVEBF16      = 1 << 12,
63268948d18SRichard Henderson     ARM_HWCAP2_A64_I8MM         = 1 << 13,
63368948d18SRichard Henderson     ARM_HWCAP2_A64_BF16         = 1 << 14,
63468948d18SRichard Henderson     ARM_HWCAP2_A64_DGH          = 1 << 15,
63568948d18SRichard Henderson     ARM_HWCAP2_A64_RNG          = 1 << 16,
63668948d18SRichard Henderson     ARM_HWCAP2_A64_BTI          = 1 << 17,
63768948d18SRichard Henderson     ARM_HWCAP2_A64_MTE          = 1 << 18,
638f9982ceaSRichard Henderson     ARM_HWCAP2_A64_ECV          = 1 << 19,
639f9982ceaSRichard Henderson     ARM_HWCAP2_A64_AFP          = 1 << 20,
640f9982ceaSRichard Henderson     ARM_HWCAP2_A64_RPRES        = 1 << 21,
641f9982ceaSRichard Henderson     ARM_HWCAP2_A64_MTE3         = 1 << 22,
642f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME          = 1 << 23,
643f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME_I16I64   = 1 << 24,
644f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME_F64F64   = 1 << 25,
645f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME_I8I32    = 1 << 26,
646f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME_F16F32   = 1 << 27,
647f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME_B16F32   = 1 << 28,
648f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME_F32F32   = 1 << 29,
649f9982ceaSRichard Henderson     ARM_HWCAP2_A64_SME_FA64     = 1 << 30,
65024e76ff0SPeter Maydell };
65124e76ff0SPeter Maydell 
65224e76ff0SPeter Maydell #define ELF_HWCAP   get_elf_hwcap()
6532041df4aSRichard Henderson #define ELF_HWCAP2  get_elf_hwcap2()
6542041df4aSRichard Henderson 
6552041df4aSRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \
6562041df4aSRichard Henderson     do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
65724e76ff0SPeter Maydell 
65824e76ff0SPeter Maydell static uint32_t get_elf_hwcap(void)
65924e76ff0SPeter Maydell {
66024e76ff0SPeter Maydell     ARMCPU *cpu = ARM_CPU(thread_cpu);
66124e76ff0SPeter Maydell     uint32_t hwcaps = 0;
66224e76ff0SPeter Maydell 
66324e76ff0SPeter Maydell     hwcaps |= ARM_HWCAP_A64_FP;
66424e76ff0SPeter Maydell     hwcaps |= ARM_HWCAP_A64_ASIMD;
66537020ff1SAlex Bennée     hwcaps |= ARM_HWCAP_A64_CPUID;
66624e76ff0SPeter Maydell 
66724e76ff0SPeter Maydell     /* probe for the extra features */
668962fcbf2SRichard Henderson 
669962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES);
670962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL);
671962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha1, ARM_HWCAP_A64_SHA1);
672962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha256, ARM_HWCAP_A64_SHA2);
673962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha512, ARM_HWCAP_A64_SHA512);
674962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_crc32, ARM_HWCAP_A64_CRC32);
675962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3);
676962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3);
677962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4);
6785763190fSRichard Henderson     GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
679962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS);
680962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM);
681962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
682962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
683cd208a1cSRichard Henderson     GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
68429d26ab2SRichard Henderson     GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
6851c9af3a9SRichard Henderson     GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
6861c9af3a9SRichard Henderson     GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
6879888bd1eSRichard Henderson     GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
688b89d9c98SRichard Henderson     GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
6890d57b499SBeata Michalska     GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
6902677cf9fSPeter Maydell     GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
691a1229109SPeter Maydell     GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
692962fcbf2SRichard Henderson 
6932041df4aSRichard Henderson     return hwcaps;
6942041df4aSRichard Henderson }
6952041df4aSRichard Henderson 
6962041df4aSRichard Henderson static uint32_t get_elf_hwcap2(void)
6972041df4aSRichard Henderson {
6982041df4aSRichard Henderson     ARMCPU *cpu = ARM_CPU(thread_cpu);
6992041df4aSRichard Henderson     uint32_t hwcaps = 0;
7002041df4aSRichard Henderson 
7010d57b499SBeata Michalska     GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
702cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2, ARM_HWCAP2_A64_SVE2);
703cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_aes, ARM_HWCAP2_A64_SVEAES);
704cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_pmull128, ARM_HWCAP2_A64_SVEPMULL);
705cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_bitperm, ARM_HWCAP2_A64_SVEBITPERM);
706cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_sha3, ARM_HWCAP2_A64_SVESHA3);
707cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_sm4, ARM_HWCAP2_A64_SVESM4);
7082041df4aSRichard Henderson     GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
7092041df4aSRichard Henderson     GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
710cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve_i8mm, ARM_HWCAP2_A64_SVEI8MM);
711cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve_f32mm, ARM_HWCAP2_A64_SVEF32MM);
712cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve_f64mm, ARM_HWCAP2_A64_SVEF64MM);
7136c47a905SRichard Henderson     GET_FEATURE_ID(aa64_sve_bf16, ARM_HWCAP2_A64_SVEBF16);
714cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_i8mm, ARM_HWCAP2_A64_I8MM);
7156c47a905SRichard Henderson     GET_FEATURE_ID(aa64_bf16, ARM_HWCAP2_A64_BF16);
71668948d18SRichard Henderson     GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
71768948d18SRichard Henderson     GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
71868948d18SRichard Henderson     GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
719f9982ceaSRichard Henderson     GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME |
720f9982ceaSRichard Henderson                               ARM_HWCAP2_A64_SME_F32F32 |
721f9982ceaSRichard Henderson                               ARM_HWCAP2_A64_SME_B16F32 |
722f9982ceaSRichard Henderson                               ARM_HWCAP2_A64_SME_F16F32 |
723f9982ceaSRichard Henderson                               ARM_HWCAP2_A64_SME_I8I32));
724f9982ceaSRichard Henderson     GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64);
725f9982ceaSRichard Henderson     GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64);
726f9982ceaSRichard Henderson     GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64);
72724e76ff0SPeter Maydell 
72824e76ff0SPeter Maydell     return hwcaps;
72924e76ff0SPeter Maydell }
73024e76ff0SPeter Maydell 
7312041df4aSRichard Henderson #undef GET_FEATURE_ID
7322041df4aSRichard Henderson 
73324e76ff0SPeter Maydell #endif /* not TARGET_AARCH64 */
73424e76ff0SPeter Maydell #endif /* TARGET_ARM */
73530ac07d4Sbellard 
736853d6f7aSbellard #ifdef TARGET_SPARC
737a315a145Sbellard #ifdef TARGET_SPARC64
738853d6f7aSbellard 
739853d6f7aSbellard #define ELF_START_MMAP 0x80000000
740cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
741cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9)
742992f48a0Sblueswir1 #ifndef TARGET_ABI32
743cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
744992f48a0Sblueswir1 #else
745992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
746992f48a0Sblueswir1 #endif
747853d6f7aSbellard 
748a315a145Sbellard #define ELF_CLASS   ELFCLASS64
7495ef54116Sbellard #define ELF_ARCH    EM_SPARCV9
750a315a145Sbellard #else
751a315a145Sbellard #define ELF_START_MMAP 0x80000000
752cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
753cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV)
754853d6f7aSbellard #define ELF_CLASS   ELFCLASS32
755853d6f7aSbellard #define ELF_ARCH    EM_SPARC
756089a2256SRichard Henderson #endif /* TARGET_SPARC64 */
757853d6f7aSbellard 
758d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
759d97ef72eSRichard Henderson                                struct image_info *infop)
760853d6f7aSbellard {
761089a2256SRichard Henderson     /* Note that target_cpu_copy_regs does not read psr/tstate. */
762f5155289Sbellard     regs->pc = infop->entry;
763f5155289Sbellard     regs->npc = regs->pc + 4;
764f5155289Sbellard     regs->y = 0;
765089a2256SRichard Henderson     regs->u_regs[14] = (infop->start_stack - 16 * sizeof(abi_ulong)
766089a2256SRichard Henderson                         - TARGET_STACK_BIAS);
767853d6f7aSbellard }
768089a2256SRichard Henderson #endif /* TARGET_SPARC */
769853d6f7aSbellard 
77067867308Sbellard #ifdef TARGET_PPC
77167867308Sbellard 
7724ecd4d16SPeter Crosthwaite #define ELF_MACHINE    PPC_ELF_MACHINE
77367867308Sbellard #define ELF_START_MMAP 0x80000000
77467867308Sbellard 
77574154d7eSThomas Huth #if defined(TARGET_PPC64)
77684409ddbSj_mayer 
77784409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 )
77884409ddbSj_mayer 
77984409ddbSj_mayer #define ELF_CLASS       ELFCLASS64
78084409ddbSj_mayer 
78184409ddbSj_mayer #else
78284409ddbSj_mayer 
78367867308Sbellard #define ELF_CLASS       ELFCLASS32
784872f3d04SRichard Henderson #define EXSTACK_DEFAULT true
78584409ddbSj_mayer 
78684409ddbSj_mayer #endif
78784409ddbSj_mayer 
78867867308Sbellard #define ELF_ARCH        EM_PPC
78967867308Sbellard 
790df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
791df84e4f3SNathan Froyd    See arch/powerpc/include/asm/cputable.h.  */
792df84e4f3SNathan Froyd enum {
7933efa9a67Smalc     QEMU_PPC_FEATURE_32 = 0x80000000,
7943efa9a67Smalc     QEMU_PPC_FEATURE_64 = 0x40000000,
7953efa9a67Smalc     QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
7963efa9a67Smalc     QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
7973efa9a67Smalc     QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
7983efa9a67Smalc     QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
7993efa9a67Smalc     QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
8003efa9a67Smalc     QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
8013efa9a67Smalc     QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
8023efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
8033efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
8043efa9a67Smalc     QEMU_PPC_FEATURE_NO_TB = 0x00100000,
8053efa9a67Smalc     QEMU_PPC_FEATURE_POWER4 = 0x00080000,
8063efa9a67Smalc     QEMU_PPC_FEATURE_POWER5 = 0x00040000,
8073efa9a67Smalc     QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
8083efa9a67Smalc     QEMU_PPC_FEATURE_CELL = 0x00010000,
8093efa9a67Smalc     QEMU_PPC_FEATURE_BOOKE = 0x00008000,
8103efa9a67Smalc     QEMU_PPC_FEATURE_SMT = 0x00004000,
8113efa9a67Smalc     QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
8123efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
8133efa9a67Smalc     QEMU_PPC_FEATURE_PA6T = 0x00000800,
8143efa9a67Smalc     QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
8153efa9a67Smalc     QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
8163efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
8173efa9a67Smalc     QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
8183efa9a67Smalc     QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
819df84e4f3SNathan Froyd 
8203efa9a67Smalc     QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
8213efa9a67Smalc     QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
822a60438ddSTom Musta 
823a60438ddSTom Musta     /* Feature definitions in AT_HWCAP2.  */
824a60438ddSTom Musta     QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */
825a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */
826a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */
827a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */
828a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */
829a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */
83024c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_VEC_CRYPTO = 0x02000000,
83124c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HTM_NOSC = 0x01000000,
832be0c46d4SSandipan Das     QEMU_PPC_FEATURE2_ARCH_3_00 = 0x00800000, /* ISA 3.00 */
83324c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HAS_IEEE128 = 0x00400000, /* VSX IEEE Bin Float 128-bit */
83424c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */
83524c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */
83624c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */
83796c343ccSJoel Stanley     QEMU_PPC_FEATURE2_ARCH_3_1 = 0x00040000, /* ISA 3.1 */
83896c343ccSJoel Stanley     QEMU_PPC_FEATURE2_MMA = 0x00020000, /* Matrix-Multiply Assist */
839df84e4f3SNathan Froyd };
840df84e4f3SNathan Froyd 
841df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap()
842df84e4f3SNathan Froyd 
843df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void)
844df84e4f3SNathan Froyd {
845a2247f8eSAndreas Färber     PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
846df84e4f3SNathan Froyd     uint32_t features = 0;
847df84e4f3SNathan Froyd 
848df84e4f3SNathan Froyd     /* We don't have to be terribly complete here; the high points are
849df84e4f3SNathan Froyd        Altivec/FP/SPE support.  Anything else is just a bonus.  */
850df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature)                                      \
851a2247f8eSAndreas Färber     do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
85258eb5308SMichael Walle #define GET_FEATURE2(flags, feature) \
85358eb5308SMichael Walle     do { \
85458eb5308SMichael Walle         if ((cpu->env.insns_flags2 & flags) == flags) { \
85558eb5308SMichael Walle             features |= feature; \
85658eb5308SMichael Walle         } \
85758eb5308SMichael Walle     } while (0)
8583efa9a67Smalc     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
8593efa9a67Smalc     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
8603efa9a67Smalc     GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
8613efa9a67Smalc     GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
8623efa9a67Smalc     GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
8633efa9a67Smalc     GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
8643efa9a67Smalc     GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
8653efa9a67Smalc     GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
8660e019746STom Musta     GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP);
8670e019746STom Musta     GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX);
8680e019746STom Musta     GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 |
8690e019746STom Musta                   PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206),
8700e019746STom Musta                   QEMU_PPC_FEATURE_ARCH_2_06);
871df84e4f3SNathan Froyd #undef GET_FEATURE
8720e019746STom Musta #undef GET_FEATURE2
873df84e4f3SNathan Froyd 
874df84e4f3SNathan Froyd     return features;
875df84e4f3SNathan Froyd }
876df84e4f3SNathan Froyd 
877a60438ddSTom Musta #define ELF_HWCAP2 get_elf_hwcap2()
878a60438ddSTom Musta 
879a60438ddSTom Musta static uint32_t get_elf_hwcap2(void)
880a60438ddSTom Musta {
881a60438ddSTom Musta     PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
882a60438ddSTom Musta     uint32_t features = 0;
883a60438ddSTom Musta 
884a60438ddSTom Musta #define GET_FEATURE(flag, feature)                                      \
885a60438ddSTom Musta     do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
886a60438ddSTom Musta #define GET_FEATURE2(flag, feature)                                      \
887a60438ddSTom Musta     do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0)
888a60438ddSTom Musta 
889a60438ddSTom Musta     GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL);
890a60438ddSTom Musta     GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR);
891a60438ddSTom Musta     GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
89224c373ecSLaurent Vivier                   PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07 |
89324c373ecSLaurent Vivier                   QEMU_PPC_FEATURE2_VEC_CRYPTO);
89424c373ecSLaurent Vivier     GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 |
8958a589aebSKhem Raj                  QEMU_PPC_FEATURE2_DARN | QEMU_PPC_FEATURE2_HAS_IEEE128);
89696c343ccSJoel Stanley     GET_FEATURE2(PPC2_ISA310, QEMU_PPC_FEATURE2_ARCH_3_1 |
89796c343ccSJoel Stanley                  QEMU_PPC_FEATURE2_MMA);
898a60438ddSTom Musta 
899a60438ddSTom Musta #undef GET_FEATURE
900a60438ddSTom Musta #undef GET_FEATURE2
901a60438ddSTom Musta 
902a60438ddSTom Musta     return features;
903a60438ddSTom Musta }
904a60438ddSTom Musta 
905f5155289Sbellard /*
906f5155289Sbellard  * The requirements here are:
907f5155289Sbellard  * - keep the final alignment of sp (sp & 0xf)
908f5155289Sbellard  * - make sure the 32-bit value at the first 16 byte aligned position of
909f5155289Sbellard  *   AUXV is greater than 16 for glibc compatibility.
910f5155289Sbellard  *   AT_IGNOREPPC is used for that.
911f5155289Sbellard  * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
912f5155289Sbellard  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
913f5155289Sbellard  */
9140bccf03dSbellard #define DLINFO_ARCH_ITEMS       5
915f5155289Sbellard #define ARCH_DLINFO                                     \
916f5155289Sbellard     do {                                                \
917623e250aSTom Musta         PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);              \
918f5155289Sbellard         /*                                              \
91982991bedSPeter Maydell          * Handle glibc compatibility: these magic entries must \
92082991bedSPeter Maydell          * be at the lowest addresses in the final auxv.        \
921f5155289Sbellard          */                                             \
9220bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
9230bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
92482991bedSPeter Maydell         NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \
92582991bedSPeter Maydell         NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \
92682991bedSPeter Maydell         NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
927f5155289Sbellard     } while (0)
928f5155289Sbellard 
92967867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
93067867308Sbellard {
93167867308Sbellard     _regs->gpr[1] = infop->start_stack;
93274154d7eSThomas Huth #if defined(TARGET_PPC64)
933d90b94cdSDoug Kwan     if (get_ppc64_abi(infop) < 2) {
9342ccf97ecSPeter Maydell         uint64_t val;
9352ccf97ecSPeter Maydell         get_user_u64(val, infop->entry + 8);
9362ccf97ecSPeter Maydell         _regs->gpr[2] = val + infop->load_bias;
9372ccf97ecSPeter Maydell         get_user_u64(val, infop->entry);
9382ccf97ecSPeter Maydell         infop->entry = val + infop->load_bias;
939d90b94cdSDoug Kwan     } else {
940d90b94cdSDoug Kwan         _regs->gpr[12] = infop->entry;  /* r12 set to global entry address */
941d90b94cdSDoug Kwan     }
94284409ddbSj_mayer #endif
94367867308Sbellard     _regs->nip = infop->entry;
94467867308Sbellard }
94567867308Sbellard 
946e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h.  */
947e2f3e741SNathan Froyd #define ELF_NREG 48
948e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
949e2f3e741SNathan Froyd 
95005390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env)
951e2f3e741SNathan Froyd {
952e2f3e741SNathan Froyd     int i;
953e2f3e741SNathan Froyd     target_ulong ccr = 0;
954e2f3e741SNathan Froyd 
955e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
95686cd7b2dSPaolo Bonzini         (*regs)[i] = tswapreg(env->gpr[i]);
957e2f3e741SNathan Froyd     }
958e2f3e741SNathan Froyd 
95986cd7b2dSPaolo Bonzini     (*regs)[32] = tswapreg(env->nip);
96086cd7b2dSPaolo Bonzini     (*regs)[33] = tswapreg(env->msr);
96186cd7b2dSPaolo Bonzini     (*regs)[35] = tswapreg(env->ctr);
96286cd7b2dSPaolo Bonzini     (*regs)[36] = tswapreg(env->lr);
96310de0521SMatheus Ferst     (*regs)[37] = tswapreg(cpu_read_xer(env));
964e2f3e741SNathan Froyd 
9652060436aSHarsh Prateek Bora     ccr = ppc_get_cr(env);
96686cd7b2dSPaolo Bonzini     (*regs)[38] = tswapreg(ccr);
967e2f3e741SNathan Froyd }
968e2f3e741SNathan Froyd 
969e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP
97067867308Sbellard #define ELF_EXEC_PAGESIZE       4096
97167867308Sbellard 
97267867308Sbellard #endif
97367867308Sbellard 
9743418fe25SSong Gao #ifdef TARGET_LOONGARCH64
9753418fe25SSong Gao 
9763418fe25SSong Gao #define ELF_START_MMAP 0x80000000
9773418fe25SSong Gao 
9783418fe25SSong Gao #define ELF_CLASS   ELFCLASS64
9793418fe25SSong Gao #define ELF_ARCH    EM_LOONGARCH
980872f3d04SRichard Henderson #define EXSTACK_DEFAULT true
9813418fe25SSong Gao 
9823418fe25SSong Gao #define elf_check_arch(x) ((x) == EM_LOONGARCH)
9833418fe25SSong Gao 
9843418fe25SSong Gao static inline void init_thread(struct target_pt_regs *regs,
9853418fe25SSong Gao                                struct image_info *infop)
9863418fe25SSong Gao {
9873418fe25SSong Gao     /*Set crmd PG,DA = 1,0 */
9883418fe25SSong Gao     regs->csr.crmd = 2 << 3;
9893418fe25SSong Gao     regs->csr.era = infop->entry;
9903418fe25SSong Gao     regs->regs[3] = infop->start_stack;
9913418fe25SSong Gao }
9923418fe25SSong Gao 
9933418fe25SSong Gao /* See linux kernel: arch/loongarch/include/asm/elf.h */
9943418fe25SSong Gao #define ELF_NREG 45
9953418fe25SSong Gao typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
9963418fe25SSong Gao 
9973418fe25SSong Gao enum {
9983418fe25SSong Gao     TARGET_EF_R0 = 0,
9993418fe25SSong Gao     TARGET_EF_CSR_ERA = TARGET_EF_R0 + 33,
10003418fe25SSong Gao     TARGET_EF_CSR_BADV = TARGET_EF_R0 + 34,
10013418fe25SSong Gao };
10023418fe25SSong Gao 
10033418fe25SSong Gao static void elf_core_copy_regs(target_elf_gregset_t *regs,
10043418fe25SSong Gao                                const CPULoongArchState *env)
10053418fe25SSong Gao {
10063418fe25SSong Gao     int i;
10073418fe25SSong Gao 
10083418fe25SSong Gao     (*regs)[TARGET_EF_R0] = 0;
10093418fe25SSong Gao 
10103418fe25SSong Gao     for (i = 1; i < ARRAY_SIZE(env->gpr); i++) {
10113418fe25SSong Gao         (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]);
10123418fe25SSong Gao     }
10133418fe25SSong Gao 
10143418fe25SSong Gao     (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc);
10153418fe25SSong Gao     (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV);
10163418fe25SSong Gao }
10173418fe25SSong Gao 
10183418fe25SSong Gao #define USE_ELF_CORE_DUMP
10193418fe25SSong Gao #define ELF_EXEC_PAGESIZE        4096
10203418fe25SSong Gao 
10213418fe25SSong Gao #define ELF_HWCAP get_elf_hwcap()
10223418fe25SSong Gao 
10233418fe25SSong Gao /* See arch/loongarch/include/uapi/asm/hwcap.h */
10243418fe25SSong Gao enum {
10253418fe25SSong Gao     HWCAP_LOONGARCH_CPUCFG   = (1 << 0),
10263418fe25SSong Gao     HWCAP_LOONGARCH_LAM      = (1 << 1),
10273418fe25SSong Gao     HWCAP_LOONGARCH_UAL      = (1 << 2),
10283418fe25SSong Gao     HWCAP_LOONGARCH_FPU      = (1 << 3),
10293418fe25SSong Gao     HWCAP_LOONGARCH_LSX      = (1 << 4),
10303418fe25SSong Gao     HWCAP_LOONGARCH_LASX     = (1 << 5),
10313418fe25SSong Gao     HWCAP_LOONGARCH_CRC32    = (1 << 6),
10323418fe25SSong Gao     HWCAP_LOONGARCH_COMPLEX  = (1 << 7),
10333418fe25SSong Gao     HWCAP_LOONGARCH_CRYPTO   = (1 << 8),
10343418fe25SSong Gao     HWCAP_LOONGARCH_LVZ      = (1 << 9),
10353418fe25SSong Gao     HWCAP_LOONGARCH_LBT_X86  = (1 << 10),
10363418fe25SSong Gao     HWCAP_LOONGARCH_LBT_ARM  = (1 << 11),
10373418fe25SSong Gao     HWCAP_LOONGARCH_LBT_MIPS = (1 << 12),
10383418fe25SSong Gao };
10393418fe25SSong Gao 
10403418fe25SSong Gao static uint32_t get_elf_hwcap(void)
10413418fe25SSong Gao {
10423418fe25SSong Gao     LoongArchCPU *cpu = LOONGARCH_CPU(thread_cpu);
10433418fe25SSong Gao     uint32_t hwcaps = 0;
10443418fe25SSong Gao 
10453418fe25SSong Gao     hwcaps |= HWCAP_LOONGARCH_CRC32;
10463418fe25SSong Gao 
10473418fe25SSong Gao     if (FIELD_EX32(cpu->env.cpucfg[1], CPUCFG1, UAL)) {
10483418fe25SSong Gao         hwcaps |= HWCAP_LOONGARCH_UAL;
10493418fe25SSong Gao     }
10503418fe25SSong Gao 
10513418fe25SSong Gao     if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, FP)) {
10523418fe25SSong Gao         hwcaps |= HWCAP_LOONGARCH_FPU;
10533418fe25SSong Gao     }
10543418fe25SSong Gao 
10553418fe25SSong Gao     if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LAM)) {
10563418fe25SSong Gao         hwcaps |= HWCAP_LOONGARCH_LAM;
10573418fe25SSong Gao     }
10583418fe25SSong Gao 
10593418fe25SSong Gao     return hwcaps;
10603418fe25SSong Gao }
10613418fe25SSong Gao 
10623418fe25SSong Gao #define ELF_PLATFORM "loongarch"
10633418fe25SSong Gao 
10643418fe25SSong Gao #endif /* TARGET_LOONGARCH64 */
10653418fe25SSong Gao 
1066048f6b4dSbellard #ifdef TARGET_MIPS
1067048f6b4dSbellard 
1068048f6b4dSbellard #define ELF_START_MMAP 0x80000000
1069048f6b4dSbellard 
1070388bb21aSths #ifdef TARGET_MIPS64
1071388bb21aSths #define ELF_CLASS   ELFCLASS64
1072388bb21aSths #else
1073048f6b4dSbellard #define ELF_CLASS   ELFCLASS32
1074388bb21aSths #endif
1075048f6b4dSbellard #define ELF_ARCH    EM_MIPS
1076872f3d04SRichard Henderson #define EXSTACK_DEFAULT true
1077048f6b4dSbellard 
1078ace3d654SCarlo Marcelo Arenas Belón #ifdef TARGET_ABI_MIPSN32
1079ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) ((x) & EF_MIPS_ABI2)
1080ace3d654SCarlo Marcelo Arenas Belón #else
1081ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (!((x) & EF_MIPS_ABI2))
1082ace3d654SCarlo Marcelo Arenas Belón #endif
1083ace3d654SCarlo Marcelo Arenas Belón 
1084fbf47c18SJiaxun Yang #define ELF_BASE_PLATFORM get_elf_base_platform()
1085fbf47c18SJiaxun Yang 
1086fbf47c18SJiaxun Yang #define MATCH_PLATFORM_INSN(_flags, _base_platform)      \
1087fbf47c18SJiaxun Yang     do { if ((cpu->env.insn_flags & (_flags)) == _flags) \
1088fbf47c18SJiaxun Yang     { return _base_platform; } } while (0)
1089fbf47c18SJiaxun Yang 
1090fbf47c18SJiaxun Yang static const char *get_elf_base_platform(void)
1091fbf47c18SJiaxun Yang {
1092fbf47c18SJiaxun Yang     MIPSCPU *cpu = MIPS_CPU(thread_cpu);
1093fbf47c18SJiaxun Yang 
1094fbf47c18SJiaxun Yang     /* 64 bit ISAs goes first */
1095fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS64R6, "mips64r6");
1096fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS64R5, "mips64r5");
1097fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS64R2, "mips64r2");
1098fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS64R1, "mips64");
1099fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS5, "mips5");
1100fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS4, "mips4");
1101fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS3, "mips3");
1102fbf47c18SJiaxun Yang 
1103fbf47c18SJiaxun Yang     /* 32 bit ISAs */
1104fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS32R6, "mips32r6");
1105fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS32R5, "mips32r5");
1106fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS32R2, "mips32r2");
1107fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS32R1, "mips32");
1108fbf47c18SJiaxun Yang     MATCH_PLATFORM_INSN(CPU_MIPS2, "mips2");
1109fbf47c18SJiaxun Yang 
1110fbf47c18SJiaxun Yang     /* Fallback */
1111fbf47c18SJiaxun Yang     return "mips";
1112fbf47c18SJiaxun Yang }
1113fbf47c18SJiaxun Yang #undef MATCH_PLATFORM_INSN
1114fbf47c18SJiaxun Yang 
1115d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1116d97ef72eSRichard Henderson                                struct image_info *infop)
1117048f6b4dSbellard {
1118623a930eSths     regs->cp0_status = 2 << CP0St_KSU;
1119048f6b4dSbellard     regs->cp0_epc = infop->entry;
1120048f6b4dSbellard     regs->regs[29] = infop->start_stack;
1121048f6b4dSbellard }
1122048f6b4dSbellard 
112351e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h.  */
112451e52606SNathan Froyd #define ELF_NREG 45
112551e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
112651e52606SNathan Froyd 
112751e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h.  */
112851e52606SNathan Froyd enum {
112951e52606SNathan Froyd #ifdef TARGET_MIPS64
113051e52606SNathan Froyd     TARGET_EF_R0 = 0,
113151e52606SNathan Froyd #else
113251e52606SNathan Froyd     TARGET_EF_R0 = 6,
113351e52606SNathan Froyd #endif
113451e52606SNathan Froyd     TARGET_EF_R26 = TARGET_EF_R0 + 26,
113551e52606SNathan Froyd     TARGET_EF_R27 = TARGET_EF_R0 + 27,
113651e52606SNathan Froyd     TARGET_EF_LO = TARGET_EF_R0 + 32,
113751e52606SNathan Froyd     TARGET_EF_HI = TARGET_EF_R0 + 33,
113851e52606SNathan Froyd     TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
113951e52606SNathan Froyd     TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
114051e52606SNathan Froyd     TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
114151e52606SNathan Froyd     TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
114251e52606SNathan Froyd };
114351e52606SNathan Froyd 
114451e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
114505390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env)
114651e52606SNathan Froyd {
114751e52606SNathan Froyd     int i;
114851e52606SNathan Froyd 
114951e52606SNathan Froyd     for (i = 0; i < TARGET_EF_R0; i++) {
115051e52606SNathan Froyd         (*regs)[i] = 0;
115151e52606SNathan Froyd     }
115251e52606SNathan Froyd     (*regs)[TARGET_EF_R0] = 0;
115351e52606SNathan Froyd 
115451e52606SNathan Froyd     for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
1155a29f998dSPaolo Bonzini         (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]);
115651e52606SNathan Froyd     }
115751e52606SNathan Froyd 
115851e52606SNathan Froyd     (*regs)[TARGET_EF_R26] = 0;
115951e52606SNathan Froyd     (*regs)[TARGET_EF_R27] = 0;
1160a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]);
1161a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]);
1162a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC);
1163a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr);
1164a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status);
1165a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause);
116651e52606SNathan Froyd }
116751e52606SNathan Froyd 
116851e52606SNathan Froyd #define USE_ELF_CORE_DUMP
1169388bb21aSths #define ELF_EXEC_PAGESIZE        4096
1170388bb21aSths 
117146a1ee4fSJames Cowgill /* See arch/mips/include/uapi/asm/hwcap.h.  */
117246a1ee4fSJames Cowgill enum {
117346a1ee4fSJames Cowgill     HWCAP_MIPS_R6           = (1 << 0),
117446a1ee4fSJames Cowgill     HWCAP_MIPS_MSA          = (1 << 1),
11759ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_CRC32        = (1 << 2),
11769ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MIPS16       = (1 << 3),
11779ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MDMX         = (1 << 4),
11789ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MIPS3D       = (1 << 5),
11799ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_SMARTMIPS    = (1 << 6),
11809ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_DSP          = (1 << 7),
11819ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_DSP2         = (1 << 8),
11829ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_DSP3         = (1 << 9),
11839ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MIPS16E2     = (1 << 10),
11849ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_MMI      = (1 << 11),
11859ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_EXT      = (1 << 12),
11869ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_EXT2     = (1 << 13),
11879ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_CPUCFG   = (1 << 14),
118846a1ee4fSJames Cowgill };
118946a1ee4fSJames Cowgill 
119046a1ee4fSJames Cowgill #define ELF_HWCAP get_elf_hwcap()
119146a1ee4fSJames Cowgill 
11927d9a3d96SPhilippe Mathieu-Daudé #define GET_FEATURE_INSN(_flag, _hwcap) \
11936dd97bfcSPhilippe Mathieu-Daudé     do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0)
11946dd97bfcSPhilippe Mathieu-Daudé 
1195388765a0SPhilippe Mathieu-Daudé #define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \
1196388765a0SPhilippe Mathieu-Daudé     do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0)
1197388765a0SPhilippe Mathieu-Daudé 
1198ce543844SPhilippe Mathieu-Daudé #define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \
1199ce543844SPhilippe Mathieu-Daudé     do { \
1200ce543844SPhilippe Mathieu-Daudé         if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \
1201ce543844SPhilippe Mathieu-Daudé             hwcaps |= _hwcap; \
1202ce543844SPhilippe Mathieu-Daudé         } \
1203ce543844SPhilippe Mathieu-Daudé     } while (0)
1204ce543844SPhilippe Mathieu-Daudé 
120546a1ee4fSJames Cowgill static uint32_t get_elf_hwcap(void)
120646a1ee4fSJames Cowgill {
120746a1ee4fSJames Cowgill     MIPSCPU *cpu = MIPS_CPU(thread_cpu);
120846a1ee4fSJames Cowgill     uint32_t hwcaps = 0;
120946a1ee4fSJames Cowgill 
1210ce543844SPhilippe Mathieu-Daudé     GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH,
1211ce543844SPhilippe Mathieu-Daudé                         2, HWCAP_MIPS_R6);
1212388765a0SPhilippe Mathieu-Daudé     GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA);
121353673d0fSPhilippe Mathieu-Daudé     GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI);
121453673d0fSPhilippe Mathieu-Daudé     GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT);
121546a1ee4fSJames Cowgill 
121646a1ee4fSJames Cowgill     return hwcaps;
121746a1ee4fSJames Cowgill }
121846a1ee4fSJames Cowgill 
1219ce543844SPhilippe Mathieu-Daudé #undef GET_FEATURE_REG_EQU
1220388765a0SPhilippe Mathieu-Daudé #undef GET_FEATURE_REG_SET
12217d9a3d96SPhilippe Mathieu-Daudé #undef GET_FEATURE_INSN
12226dd97bfcSPhilippe Mathieu-Daudé 
1223048f6b4dSbellard #endif /* TARGET_MIPS */
1224048f6b4dSbellard 
1225b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE
1226b779e29eSEdgar E. Iglesias 
1227b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000
1228b779e29eSEdgar E. Iglesias 
12290d5d4699SEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
1230b779e29eSEdgar E. Iglesias 
1231b779e29eSEdgar E. Iglesias #define ELF_CLASS   ELFCLASS32
12320d5d4699SEdgar E. Iglesias #define ELF_ARCH    EM_MICROBLAZE
1233b779e29eSEdgar E. Iglesias 
1234d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1235d97ef72eSRichard Henderson                                struct image_info *infop)
1236b779e29eSEdgar E. Iglesias {
1237b779e29eSEdgar E. Iglesias     regs->pc = infop->entry;
1238b779e29eSEdgar E. Iglesias     regs->r1 = infop->start_stack;
1239b779e29eSEdgar E. Iglesias 
1240b779e29eSEdgar E. Iglesias }
1241b779e29eSEdgar E. Iglesias 
1242b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE        4096
1243b779e29eSEdgar E. Iglesias 
1244e4cbd44dSEdgar E. Iglesias #define USE_ELF_CORE_DUMP
1245e4cbd44dSEdgar E. Iglesias #define ELF_NREG 38
1246e4cbd44dSEdgar E. Iglesias typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1247e4cbd44dSEdgar E. Iglesias 
1248e4cbd44dSEdgar E. Iglesias /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
124905390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env)
1250e4cbd44dSEdgar E. Iglesias {
1251e4cbd44dSEdgar E. Iglesias     int i, pos = 0;
1252e4cbd44dSEdgar E. Iglesias 
1253e4cbd44dSEdgar E. Iglesias     for (i = 0; i < 32; i++) {
125486cd7b2dSPaolo Bonzini         (*regs)[pos++] = tswapreg(env->regs[i]);
1255e4cbd44dSEdgar E. Iglesias     }
1256e4cbd44dSEdgar E. Iglesias 
1257af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->pc);
12581074c0fbSRichard Henderson     (*regs)[pos++] = tswapreg(mb_cpu_read_msr(env));
1259af20a93aSRichard Henderson     (*regs)[pos++] = 0;
1260af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->ear);
1261af20a93aSRichard Henderson     (*regs)[pos++] = 0;
1262af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->esr);
1263e4cbd44dSEdgar E. Iglesias }
1264e4cbd44dSEdgar E. Iglesias 
1265b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */
1266b779e29eSEdgar E. Iglesias 
1267a0a839b6SMarek Vasut #ifdef TARGET_NIOS2
1268a0a839b6SMarek Vasut 
1269a0a839b6SMarek Vasut #define ELF_START_MMAP 0x80000000
1270a0a839b6SMarek Vasut 
1271a0a839b6SMarek Vasut #define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2)
1272a0a839b6SMarek Vasut 
1273a0a839b6SMarek Vasut #define ELF_CLASS   ELFCLASS32
1274a0a839b6SMarek Vasut #define ELF_ARCH    EM_ALTERA_NIOS2
1275a0a839b6SMarek Vasut 
1276a0a839b6SMarek Vasut static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
1277a0a839b6SMarek Vasut {
1278a0a839b6SMarek Vasut     regs->ea = infop->entry;
1279a0a839b6SMarek Vasut     regs->sp = infop->start_stack;
1280a0a839b6SMarek Vasut }
1281a0a839b6SMarek Vasut 
1282f5ef0e51SRichard Henderson #define LO_COMMPAGE  TARGET_PAGE_SIZE
1283f5ef0e51SRichard Henderson 
1284f5ef0e51SRichard Henderson static bool init_guest_commpage(void)
1285f5ef0e51SRichard Henderson {
1286f5ef0e51SRichard Henderson     static const uint8_t kuser_page[4 + 2 * 64] = {
1287f5ef0e51SRichard Henderson         /* __kuser_helper_version */
1288f5ef0e51SRichard Henderson         [0x00] = 0x02, 0x00, 0x00, 0x00,
1289f5ef0e51SRichard Henderson 
1290f5ef0e51SRichard Henderson         /* __kuser_cmpxchg */
1291f5ef0e51SRichard Henderson         [0x04] = 0x3a, 0x6c, 0x3b, 0x00,  /* trap 16 */
1292f5ef0e51SRichard Henderson                  0x3a, 0x28, 0x00, 0xf8,  /* ret */
1293f5ef0e51SRichard Henderson 
1294f5ef0e51SRichard Henderson         /* __kuser_sigtramp */
1295f5ef0e51SRichard Henderson         [0x44] = 0xc4, 0x22, 0x80, 0x00,  /* movi r2, __NR_rt_sigreturn */
1296f5ef0e51SRichard Henderson                  0x3a, 0x68, 0x3b, 0x00,  /* trap 0 */
1297f5ef0e51SRichard Henderson     };
1298f5ef0e51SRichard Henderson 
1299f5ef0e51SRichard Henderson     void *want = g2h_untagged(LO_COMMPAGE & -qemu_host_page_size);
1300f5ef0e51SRichard Henderson     void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
1301f5ef0e51SRichard Henderson                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1302f5ef0e51SRichard Henderson 
1303f5ef0e51SRichard Henderson     if (addr == MAP_FAILED) {
1304f5ef0e51SRichard Henderson         perror("Allocating guest commpage");
1305f5ef0e51SRichard Henderson         exit(EXIT_FAILURE);
1306f5ef0e51SRichard Henderson     }
1307f5ef0e51SRichard Henderson     if (addr != want) {
1308f5ef0e51SRichard Henderson         return false;
1309f5ef0e51SRichard Henderson     }
1310f5ef0e51SRichard Henderson 
1311f5ef0e51SRichard Henderson     memcpy(addr, kuser_page, sizeof(kuser_page));
1312f5ef0e51SRichard Henderson 
1313f5ef0e51SRichard Henderson     if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
1314f5ef0e51SRichard Henderson         perror("Protecting guest commpage");
1315f5ef0e51SRichard Henderson         exit(EXIT_FAILURE);
1316f5ef0e51SRichard Henderson     }
1317f5ef0e51SRichard Henderson 
131849840a4aSRichard Henderson     page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
1319f5ef0e51SRichard Henderson                    PAGE_READ | PAGE_EXEC | PAGE_VALID);
1320f5ef0e51SRichard Henderson     return true;
1321f5ef0e51SRichard Henderson }
1322f5ef0e51SRichard Henderson 
1323a0a839b6SMarek Vasut #define ELF_EXEC_PAGESIZE        4096
1324a0a839b6SMarek Vasut 
1325a0a839b6SMarek Vasut #define USE_ELF_CORE_DUMP
1326a0a839b6SMarek Vasut #define ELF_NREG 49
1327a0a839b6SMarek Vasut typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1328a0a839b6SMarek Vasut 
1329a0a839b6SMarek Vasut /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
1330a0a839b6SMarek Vasut static void elf_core_copy_regs(target_elf_gregset_t *regs,
1331a0a839b6SMarek Vasut                                const CPUNios2State *env)
1332a0a839b6SMarek Vasut {
1333a0a839b6SMarek Vasut     int i;
1334a0a839b6SMarek Vasut 
1335a0a839b6SMarek Vasut     (*regs)[0] = -1;
1336a0a839b6SMarek Vasut     for (i = 1; i < 8; i++)    /* r0-r7 */
1337a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i + 7]);
1338a0a839b6SMarek Vasut 
1339a0a839b6SMarek Vasut     for (i = 8; i < 16; i++)   /* r8-r15 */
1340a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i - 8]);
1341a0a839b6SMarek Vasut 
1342a0a839b6SMarek Vasut     for (i = 16; i < 24; i++)  /* r16-r23 */
1343a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i + 7]);
1344a0a839b6SMarek Vasut     (*regs)[24] = -1;    /* R_ET */
1345a0a839b6SMarek Vasut     (*regs)[25] = -1;    /* R_BT */
1346a0a839b6SMarek Vasut     (*regs)[26] = tswapreg(env->regs[R_GP]);
1347a0a839b6SMarek Vasut     (*regs)[27] = tswapreg(env->regs[R_SP]);
1348a0a839b6SMarek Vasut     (*regs)[28] = tswapreg(env->regs[R_FP]);
1349a0a839b6SMarek Vasut     (*regs)[29] = tswapreg(env->regs[R_EA]);
1350a0a839b6SMarek Vasut     (*regs)[30] = -1;    /* R_SSTATUS */
1351a0a839b6SMarek Vasut     (*regs)[31] = tswapreg(env->regs[R_RA]);
1352a0a839b6SMarek Vasut 
135317a406eeSRichard Henderson     (*regs)[32] = tswapreg(env->pc);
1354a0a839b6SMarek Vasut 
1355a0a839b6SMarek Vasut     (*regs)[33] = -1; /* R_STATUS */
1356a0a839b6SMarek Vasut     (*regs)[34] = tswapreg(env->regs[CR_ESTATUS]);
1357a0a839b6SMarek Vasut 
1358a0a839b6SMarek Vasut     for (i = 35; i < 49; i++)    /* ... */
1359a0a839b6SMarek Vasut         (*regs)[i] = -1;
1360a0a839b6SMarek Vasut }
1361a0a839b6SMarek Vasut 
1362a0a839b6SMarek Vasut #endif /* TARGET_NIOS2 */
1363a0a839b6SMarek Vasut 
1364d962783eSJia Liu #ifdef TARGET_OPENRISC
1365d962783eSJia Liu 
1366d962783eSJia Liu #define ELF_START_MMAP 0x08000000
1367d962783eSJia Liu 
1368d962783eSJia Liu #define ELF_ARCH EM_OPENRISC
1369d962783eSJia Liu #define ELF_CLASS ELFCLASS32
1370d962783eSJia Liu #define ELF_DATA  ELFDATA2MSB
1371d962783eSJia Liu 
1372d962783eSJia Liu static inline void init_thread(struct target_pt_regs *regs,
1373d962783eSJia Liu                                struct image_info *infop)
1374d962783eSJia Liu {
1375d962783eSJia Liu     regs->pc = infop->entry;
1376d962783eSJia Liu     regs->gpr[1] = infop->start_stack;
1377d962783eSJia Liu }
1378d962783eSJia Liu 
1379d962783eSJia Liu #define USE_ELF_CORE_DUMP
1380d962783eSJia Liu #define ELF_EXEC_PAGESIZE 8192
1381d962783eSJia Liu 
1382d962783eSJia Liu /* See linux kernel arch/openrisc/include/asm/elf.h.  */
1383d962783eSJia Liu #define ELF_NREG 34 /* gprs and pc, sr */
1384d962783eSJia Liu typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1385d962783eSJia Liu 
1386d962783eSJia Liu static void elf_core_copy_regs(target_elf_gregset_t *regs,
1387d962783eSJia Liu                                const CPUOpenRISCState *env)
1388d962783eSJia Liu {
1389d962783eSJia Liu     int i;
1390d962783eSJia Liu 
1391d962783eSJia Liu     for (i = 0; i < 32; i++) {
1392d89e71e8SStafford Horne         (*regs)[i] = tswapreg(cpu_get_gpr(env, i));
1393d962783eSJia Liu     }
139486cd7b2dSPaolo Bonzini     (*regs)[32] = tswapreg(env->pc);
139584775c43SRichard Henderson     (*regs)[33] = tswapreg(cpu_get_sr(env));
1396d962783eSJia Liu }
1397d962783eSJia Liu #define ELF_HWCAP 0
1398d962783eSJia Liu #define ELF_PLATFORM NULL
1399d962783eSJia Liu 
1400d962783eSJia Liu #endif /* TARGET_OPENRISC */
1401d962783eSJia Liu 
1402fdf9b3e8Sbellard #ifdef TARGET_SH4
1403fdf9b3e8Sbellard 
1404fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000
1405fdf9b3e8Sbellard 
1406fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32
1407fdf9b3e8Sbellard #define ELF_ARCH  EM_SH
1408fdf9b3e8Sbellard 
1409d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1410d97ef72eSRichard Henderson                                struct image_info *infop)
1411fdf9b3e8Sbellard {
1412fdf9b3e8Sbellard     /* Check other registers XXXXX */
1413fdf9b3e8Sbellard     regs->pc = infop->entry;
1414072ae847Sths     regs->regs[15] = infop->start_stack;
1415fdf9b3e8Sbellard }
1416fdf9b3e8Sbellard 
14177631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h.  */
14187631c97eSNathan Froyd #define ELF_NREG 23
14197631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
14207631c97eSNathan Froyd 
14217631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h.  */
14227631c97eSNathan Froyd enum {
14237631c97eSNathan Froyd     TARGET_REG_PC = 16,
14247631c97eSNathan Froyd     TARGET_REG_PR = 17,
14257631c97eSNathan Froyd     TARGET_REG_SR = 18,
14267631c97eSNathan Froyd     TARGET_REG_GBR = 19,
14277631c97eSNathan Froyd     TARGET_REG_MACH = 20,
14287631c97eSNathan Froyd     TARGET_REG_MACL = 21,
14297631c97eSNathan Froyd     TARGET_REG_SYSCALL = 22
14307631c97eSNathan Froyd };
14317631c97eSNathan Froyd 
1432d97ef72eSRichard Henderson static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
143305390248SAndreas Färber                                       const CPUSH4State *env)
14347631c97eSNathan Froyd {
14357631c97eSNathan Froyd     int i;
14367631c97eSNathan Froyd 
14377631c97eSNathan Froyd     for (i = 0; i < 16; i++) {
143872cd500bSPhilippe Mathieu-Daudé         (*regs)[i] = tswapreg(env->gregs[i]);
14397631c97eSNathan Froyd     }
14407631c97eSNathan Froyd 
144186cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
144286cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_PR] = tswapreg(env->pr);
144386cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_SR] = tswapreg(env->sr);
144486cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr);
144586cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_MACH] = tswapreg(env->mach);
144686cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_MACL] = tswapreg(env->macl);
14477631c97eSNathan Froyd     (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
14487631c97eSNathan Froyd }
14497631c97eSNathan Froyd 
14507631c97eSNathan Froyd #define USE_ELF_CORE_DUMP
1451fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE        4096
1452fdf9b3e8Sbellard 
1453e42fd944SRichard Henderson enum {
1454e42fd944SRichard Henderson     SH_CPU_HAS_FPU            = 0x0001, /* Hardware FPU support */
1455e42fd944SRichard Henderson     SH_CPU_HAS_P2_FLUSH_BUG   = 0x0002, /* Need to flush the cache in P2 area */
1456e42fd944SRichard Henderson     SH_CPU_HAS_MMU_PAGE_ASSOC = 0x0004, /* SH3: TLB way selection bit support */
1457e42fd944SRichard Henderson     SH_CPU_HAS_DSP            = 0x0008, /* SH-DSP: DSP support */
1458e42fd944SRichard Henderson     SH_CPU_HAS_PERF_COUNTER   = 0x0010, /* Hardware performance counters */
1459e42fd944SRichard Henderson     SH_CPU_HAS_PTEA           = 0x0020, /* PTEA register */
1460e42fd944SRichard Henderson     SH_CPU_HAS_LLSC           = 0x0040, /* movli.l/movco.l */
1461e42fd944SRichard Henderson     SH_CPU_HAS_L2_CACHE       = 0x0080, /* Secondary cache / URAM */
1462e42fd944SRichard Henderson     SH_CPU_HAS_OP32           = 0x0100, /* 32-bit instruction support */
1463e42fd944SRichard Henderson     SH_CPU_HAS_PTEAEX         = 0x0200, /* PTE ASID Extension support */
1464e42fd944SRichard Henderson };
1465e42fd944SRichard Henderson 
1466e42fd944SRichard Henderson #define ELF_HWCAP get_elf_hwcap()
1467e42fd944SRichard Henderson 
1468e42fd944SRichard Henderson static uint32_t get_elf_hwcap(void)
1469e42fd944SRichard Henderson {
1470e42fd944SRichard Henderson     SuperHCPU *cpu = SUPERH_CPU(thread_cpu);
1471e42fd944SRichard Henderson     uint32_t hwcap = 0;
1472e42fd944SRichard Henderson 
1473e42fd944SRichard Henderson     hwcap |= SH_CPU_HAS_FPU;
1474e42fd944SRichard Henderson 
1475e42fd944SRichard Henderson     if (cpu->env.features & SH_FEATURE_SH4A) {
1476e42fd944SRichard Henderson         hwcap |= SH_CPU_HAS_LLSC;
1477e42fd944SRichard Henderson     }
1478e42fd944SRichard Henderson 
1479e42fd944SRichard Henderson     return hwcap;
1480e42fd944SRichard Henderson }
1481e42fd944SRichard Henderson 
1482fdf9b3e8Sbellard #endif
1483fdf9b3e8Sbellard 
148448733d19Sths #ifdef TARGET_CRIS
148548733d19Sths 
148648733d19Sths #define ELF_START_MMAP 0x80000000
148748733d19Sths 
148848733d19Sths #define ELF_CLASS ELFCLASS32
148948733d19Sths #define ELF_ARCH  EM_CRIS
149048733d19Sths 
1491d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1492d97ef72eSRichard Henderson                                struct image_info *infop)
149348733d19Sths {
149448733d19Sths     regs->erp = infop->entry;
149548733d19Sths }
149648733d19Sths 
149748733d19Sths #define ELF_EXEC_PAGESIZE        8192
149848733d19Sths 
149948733d19Sths #endif
150048733d19Sths 
1501e6e5906bSpbrook #ifdef TARGET_M68K
1502e6e5906bSpbrook 
1503e6e5906bSpbrook #define ELF_START_MMAP 0x80000000
1504e6e5906bSpbrook 
1505e6e5906bSpbrook #define ELF_CLASS       ELFCLASS32
1506e6e5906bSpbrook #define ELF_ARCH        EM_68K
1507e6e5906bSpbrook 
1508e6e5906bSpbrook /* ??? Does this need to do anything?
1509e6e5906bSpbrook    #define ELF_PLAT_INIT(_r) */
1510e6e5906bSpbrook 
1511d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1512d97ef72eSRichard Henderson                                struct image_info *infop)
1513e6e5906bSpbrook {
1514e6e5906bSpbrook     regs->usp = infop->start_stack;
1515e6e5906bSpbrook     regs->sr = 0;
1516e6e5906bSpbrook     regs->pc = infop->entry;
1517e6e5906bSpbrook }
1518e6e5906bSpbrook 
15197a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h.  */
15207a93cc55SNathan Froyd #define ELF_NREG 20
15217a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
15227a93cc55SNathan Froyd 
152305390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env)
15247a93cc55SNathan Froyd {
152586cd7b2dSPaolo Bonzini     (*regs)[0] = tswapreg(env->dregs[1]);
152686cd7b2dSPaolo Bonzini     (*regs)[1] = tswapreg(env->dregs[2]);
152786cd7b2dSPaolo Bonzini     (*regs)[2] = tswapreg(env->dregs[3]);
152886cd7b2dSPaolo Bonzini     (*regs)[3] = tswapreg(env->dregs[4]);
152986cd7b2dSPaolo Bonzini     (*regs)[4] = tswapreg(env->dregs[5]);
153086cd7b2dSPaolo Bonzini     (*regs)[5] = tswapreg(env->dregs[6]);
153186cd7b2dSPaolo Bonzini     (*regs)[6] = tswapreg(env->dregs[7]);
153286cd7b2dSPaolo Bonzini     (*regs)[7] = tswapreg(env->aregs[0]);
153386cd7b2dSPaolo Bonzini     (*regs)[8] = tswapreg(env->aregs[1]);
153486cd7b2dSPaolo Bonzini     (*regs)[9] = tswapreg(env->aregs[2]);
153586cd7b2dSPaolo Bonzini     (*regs)[10] = tswapreg(env->aregs[3]);
153686cd7b2dSPaolo Bonzini     (*regs)[11] = tswapreg(env->aregs[4]);
153786cd7b2dSPaolo Bonzini     (*regs)[12] = tswapreg(env->aregs[5]);
153886cd7b2dSPaolo Bonzini     (*regs)[13] = tswapreg(env->aregs[6]);
153986cd7b2dSPaolo Bonzini     (*regs)[14] = tswapreg(env->dregs[0]);
154086cd7b2dSPaolo Bonzini     (*regs)[15] = tswapreg(env->aregs[7]);
154186cd7b2dSPaolo Bonzini     (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */
154286cd7b2dSPaolo Bonzini     (*regs)[17] = tswapreg(env->sr);
154386cd7b2dSPaolo Bonzini     (*regs)[18] = tswapreg(env->pc);
15447a93cc55SNathan Froyd     (*regs)[19] = 0;  /* FIXME: regs->format | regs->vector */
15457a93cc55SNathan Froyd }
15467a93cc55SNathan Froyd 
15477a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP
1548e6e5906bSpbrook #define ELF_EXEC_PAGESIZE       8192
1549e6e5906bSpbrook 
1550e6e5906bSpbrook #endif
1551e6e5906bSpbrook 
15527a3148a9Sj_mayer #ifdef TARGET_ALPHA
15537a3148a9Sj_mayer 
15547a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL)
15557a3148a9Sj_mayer 
15567a3148a9Sj_mayer #define ELF_CLASS      ELFCLASS64
15577a3148a9Sj_mayer #define ELF_ARCH       EM_ALPHA
15587a3148a9Sj_mayer 
1559d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1560d97ef72eSRichard Henderson                                struct image_info *infop)
15617a3148a9Sj_mayer {
15627a3148a9Sj_mayer     regs->pc = infop->entry;
15637a3148a9Sj_mayer     regs->ps = 8;
15647a3148a9Sj_mayer     regs->usp = infop->start_stack;
15657a3148a9Sj_mayer }
15667a3148a9Sj_mayer 
15677a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE        8192
15687a3148a9Sj_mayer 
15697a3148a9Sj_mayer #endif /* TARGET_ALPHA */
15707a3148a9Sj_mayer 
1571a4c075f1SUlrich Hecht #ifdef TARGET_S390X
1572a4c075f1SUlrich Hecht 
1573a4c075f1SUlrich Hecht #define ELF_START_MMAP (0x20000000000ULL)
1574a4c075f1SUlrich Hecht 
1575a4c075f1SUlrich Hecht #define ELF_CLASS	ELFCLASS64
1576a4c075f1SUlrich Hecht #define ELF_DATA	ELFDATA2MSB
1577a4c075f1SUlrich Hecht #define ELF_ARCH	EM_S390
1578a4c075f1SUlrich Hecht 
15796d88baf1SDavid Hildenbrand #include "elf.h"
15806d88baf1SDavid Hildenbrand 
15816d88baf1SDavid Hildenbrand #define ELF_HWCAP get_elf_hwcap()
15826d88baf1SDavid Hildenbrand 
15836d88baf1SDavid Hildenbrand #define GET_FEATURE(_feat, _hwcap) \
15846d88baf1SDavid Hildenbrand     do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0)
15856d88baf1SDavid Hildenbrand 
1586e1b819c8SIlya Leoshkevich uint32_t get_elf_hwcap(void)
15876d88baf1SDavid Hildenbrand {
15886d88baf1SDavid Hildenbrand     /*
15896d88baf1SDavid Hildenbrand      * Let's assume we always have esan3 and zarch.
15906d88baf1SDavid Hildenbrand      * 31-bit processes can use 64-bit registers (high gprs).
15916d88baf1SDavid Hildenbrand      */
15926d88baf1SDavid Hildenbrand     uint32_t hwcap = HWCAP_S390_ESAN3 | HWCAP_S390_ZARCH | HWCAP_S390_HIGH_GPRS;
15936d88baf1SDavid Hildenbrand 
15946d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_STFLE, HWCAP_S390_STFLE);
15956d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_MSA, HWCAP_S390_MSA);
15966d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_LONG_DISPLACEMENT, HWCAP_S390_LDISP);
15976d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_EXTENDED_IMMEDIATE, HWCAP_S390_EIMM);
15986d88baf1SDavid Hildenbrand     if (s390_has_feat(S390_FEAT_EXTENDED_TRANSLATION_3) &&
15996d88baf1SDavid Hildenbrand         s390_has_feat(S390_FEAT_ETF3_ENH)) {
16006d88baf1SDavid Hildenbrand         hwcap |= HWCAP_S390_ETF3EH;
16016d88baf1SDavid Hildenbrand     }
16026d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS);
1603da215c23SDavid Hildenbrand     GET_FEATURE(S390_FEAT_VECTOR_ENH, HWCAP_S390_VXRS_EXT);
16046d88baf1SDavid Hildenbrand 
16056d88baf1SDavid Hildenbrand     return hwcap;
16066d88baf1SDavid Hildenbrand }
16076d88baf1SDavid Hildenbrand 
1608e19807beSIlya Leoshkevich const char *elf_hwcap_str(uint32_t bit)
1609e19807beSIlya Leoshkevich {
1610e19807beSIlya Leoshkevich     static const char *hwcap_str[] = {
1611e19807beSIlya Leoshkevich         [HWCAP_S390_ESAN3]     = "esan3",
1612e19807beSIlya Leoshkevich         [HWCAP_S390_ZARCH]     = "zarch",
1613e19807beSIlya Leoshkevich         [HWCAP_S390_STFLE]     = "stfle",
1614e19807beSIlya Leoshkevich         [HWCAP_S390_MSA]       = "msa",
1615e19807beSIlya Leoshkevich         [HWCAP_S390_LDISP]     = "ldisp",
1616e19807beSIlya Leoshkevich         [HWCAP_S390_EIMM]      = "eimm",
1617e19807beSIlya Leoshkevich         [HWCAP_S390_DFP]       = "dfp",
1618e19807beSIlya Leoshkevich         [HWCAP_S390_HPAGE]     = "edat",
1619e19807beSIlya Leoshkevich         [HWCAP_S390_ETF3EH]    = "etf3eh",
1620e19807beSIlya Leoshkevich         [HWCAP_S390_HIGH_GPRS] = "highgprs",
1621e19807beSIlya Leoshkevich         [HWCAP_S390_TE]        = "te",
1622e19807beSIlya Leoshkevich         [HWCAP_S390_VXRS]      = "vx",
1623e19807beSIlya Leoshkevich         [HWCAP_S390_VXRS_BCD]  = "vxd",
1624e19807beSIlya Leoshkevich         [HWCAP_S390_VXRS_EXT]  = "vxe",
1625e19807beSIlya Leoshkevich         [HWCAP_S390_GS]        = "gs",
1626e19807beSIlya Leoshkevich         [HWCAP_S390_VXRS_EXT2] = "vxe2",
1627e19807beSIlya Leoshkevich         [HWCAP_S390_VXRS_PDE]  = "vxp",
1628e19807beSIlya Leoshkevich         [HWCAP_S390_SORT]      = "sort",
1629e19807beSIlya Leoshkevich         [HWCAP_S390_DFLT]      = "dflt",
1630e19807beSIlya Leoshkevich     };
1631e19807beSIlya Leoshkevich 
1632e19807beSIlya Leoshkevich     return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL;
1633e19807beSIlya Leoshkevich }
1634e19807beSIlya Leoshkevich 
1635a4c075f1SUlrich Hecht static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
1636a4c075f1SUlrich Hecht {
1637a4c075f1SUlrich Hecht     regs->psw.addr = infop->entry;
1638a4c075f1SUlrich Hecht     regs->psw.mask = PSW_MASK_64 | PSW_MASK_32;
1639a4c075f1SUlrich Hecht     regs->gprs[15] = infop->start_stack;
1640a4c075f1SUlrich Hecht }
1641a4c075f1SUlrich Hecht 
16424a1e8931SIlya Leoshkevich /* See linux kernel: arch/s390/include/uapi/asm/ptrace.h (s390_regs).  */
16434a1e8931SIlya Leoshkevich #define ELF_NREG 27
16444a1e8931SIlya Leoshkevich typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
16454a1e8931SIlya Leoshkevich 
16464a1e8931SIlya Leoshkevich enum {
16474a1e8931SIlya Leoshkevich     TARGET_REG_PSWM = 0,
16484a1e8931SIlya Leoshkevich     TARGET_REG_PSWA = 1,
16494a1e8931SIlya Leoshkevich     TARGET_REG_GPRS = 2,
16504a1e8931SIlya Leoshkevich     TARGET_REG_ARS = 18,
16514a1e8931SIlya Leoshkevich     TARGET_REG_ORIG_R2 = 26,
16524a1e8931SIlya Leoshkevich };
16534a1e8931SIlya Leoshkevich 
16544a1e8931SIlya Leoshkevich static void elf_core_copy_regs(target_elf_gregset_t *regs,
16554a1e8931SIlya Leoshkevich                                const CPUS390XState *env)
16564a1e8931SIlya Leoshkevich {
16574a1e8931SIlya Leoshkevich     int i;
16584a1e8931SIlya Leoshkevich     uint32_t *aregs;
16594a1e8931SIlya Leoshkevich 
16604a1e8931SIlya Leoshkevich     (*regs)[TARGET_REG_PSWM] = tswapreg(env->psw.mask);
16614a1e8931SIlya Leoshkevich     (*regs)[TARGET_REG_PSWA] = tswapreg(env->psw.addr);
16624a1e8931SIlya Leoshkevich     for (i = 0; i < 16; i++) {
16634a1e8931SIlya Leoshkevich         (*regs)[TARGET_REG_GPRS + i] = tswapreg(env->regs[i]);
16644a1e8931SIlya Leoshkevich     }
16654a1e8931SIlya Leoshkevich     aregs = (uint32_t *)&((*regs)[TARGET_REG_ARS]);
16664a1e8931SIlya Leoshkevich     for (i = 0; i < 16; i++) {
16674a1e8931SIlya Leoshkevich         aregs[i] = tswap32(env->aregs[i]);
16684a1e8931SIlya Leoshkevich     }
16694a1e8931SIlya Leoshkevich     (*regs)[TARGET_REG_ORIG_R2] = 0;
16704a1e8931SIlya Leoshkevich }
16714a1e8931SIlya Leoshkevich 
16724a1e8931SIlya Leoshkevich #define USE_ELF_CORE_DUMP
16734a1e8931SIlya Leoshkevich #define ELF_EXEC_PAGESIZE 4096
16744a1e8931SIlya Leoshkevich 
1675a4c075f1SUlrich Hecht #endif /* TARGET_S390X */
1676a4c075f1SUlrich Hecht 
167747ae93cdSMichael Clark #ifdef TARGET_RISCV
167847ae93cdSMichael Clark 
167947ae93cdSMichael Clark #define ELF_START_MMAP 0x80000000
168047ae93cdSMichael Clark #define ELF_ARCH  EM_RISCV
168147ae93cdSMichael Clark 
168247ae93cdSMichael Clark #ifdef TARGET_RISCV32
168347ae93cdSMichael Clark #define ELF_CLASS ELFCLASS32
168447ae93cdSMichael Clark #else
168547ae93cdSMichael Clark #define ELF_CLASS ELFCLASS64
168647ae93cdSMichael Clark #endif
168747ae93cdSMichael Clark 
1688cb46938cSKito Cheng #define ELF_HWCAP get_elf_hwcap()
1689cb46938cSKito Cheng 
1690cb46938cSKito Cheng static uint32_t get_elf_hwcap(void)
1691cb46938cSKito Cheng {
1692cb46938cSKito Cheng #define MISA_BIT(EXT) (1 << (EXT - 'A'))
1693cb46938cSKito Cheng     RISCVCPU *cpu = RISCV_CPU(thread_cpu);
1694cb46938cSKito Cheng     uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
1695cb46938cSKito Cheng                     | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
1696cb46938cSKito Cheng 
1697e91a7227SRichard Henderson     return cpu->env.misa_ext & mask;
1698cb46938cSKito Cheng #undef MISA_BIT
1699cb46938cSKito Cheng }
1700cb46938cSKito Cheng 
170147ae93cdSMichael Clark static inline void init_thread(struct target_pt_regs *regs,
170247ae93cdSMichael Clark                                struct image_info *infop)
170347ae93cdSMichael Clark {
170447ae93cdSMichael Clark     regs->sepc = infop->entry;
170547ae93cdSMichael Clark     regs->sp = infop->start_stack;
170647ae93cdSMichael Clark }
170747ae93cdSMichael Clark 
170847ae93cdSMichael Clark #define ELF_EXEC_PAGESIZE 4096
170947ae93cdSMichael Clark 
171047ae93cdSMichael Clark #endif /* TARGET_RISCV */
171147ae93cdSMichael Clark 
17127c248bcdSRichard Henderson #ifdef TARGET_HPPA
17137c248bcdSRichard Henderson 
17147c248bcdSRichard Henderson #define ELF_START_MMAP  0x80000000
17157c248bcdSRichard Henderson #define ELF_CLASS       ELFCLASS32
17167c248bcdSRichard Henderson #define ELF_ARCH        EM_PARISC
17177c248bcdSRichard Henderson #define ELF_PLATFORM    "PARISC"
17187c248bcdSRichard Henderson #define STACK_GROWS_DOWN 0
17197c248bcdSRichard Henderson #define STACK_ALIGNMENT  64
17207c248bcdSRichard Henderson 
17217c248bcdSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
17227c248bcdSRichard Henderson                                struct image_info *infop)
17237c248bcdSRichard Henderson {
17247c248bcdSRichard Henderson     regs->iaoq[0] = infop->entry;
17257c248bcdSRichard Henderson     regs->iaoq[1] = infop->entry + 4;
17267c248bcdSRichard Henderson     regs->gr[23] = 0;
172760f1c801SRichard Henderson     regs->gr[24] = infop->argv;
172860f1c801SRichard Henderson     regs->gr[25] = infop->argc;
17297c248bcdSRichard Henderson     /* The top-of-stack contains a linkage buffer.  */
17307c248bcdSRichard Henderson     regs->gr[30] = infop->start_stack + 64;
17317c248bcdSRichard Henderson     regs->gr[31] = infop->entry;
17327c248bcdSRichard Henderson }
17337c248bcdSRichard Henderson 
1734eee816c0SRichard Henderson #define LO_COMMPAGE  0
1735eee816c0SRichard Henderson 
1736eee816c0SRichard Henderson static bool init_guest_commpage(void)
1737eee816c0SRichard Henderson {
1738eee816c0SRichard Henderson     void *want = g2h_untagged(LO_COMMPAGE);
1739eee816c0SRichard Henderson     void *addr = mmap(want, qemu_host_page_size, PROT_NONE,
1740eee816c0SRichard Henderson                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1741eee816c0SRichard Henderson 
1742eee816c0SRichard Henderson     if (addr == MAP_FAILED) {
1743eee816c0SRichard Henderson         perror("Allocating guest commpage");
1744eee816c0SRichard Henderson         exit(EXIT_FAILURE);
1745eee816c0SRichard Henderson     }
1746eee816c0SRichard Henderson     if (addr != want) {
1747eee816c0SRichard Henderson         return false;
1748eee816c0SRichard Henderson     }
1749eee816c0SRichard Henderson 
1750eee816c0SRichard Henderson     /*
1751eee816c0SRichard Henderson      * On Linux, page zero is normally marked execute only + gateway.
1752eee816c0SRichard Henderson      * Normal read or write is supposed to fail (thus PROT_NONE above),
1753eee816c0SRichard Henderson      * but specific offsets have kernel code mapped to raise permissions
1754eee816c0SRichard Henderson      * and implement syscalls.  Here, simply mark the page executable.
1755eee816c0SRichard Henderson      * Special case the entry points during translation (see do_page_zero).
1756eee816c0SRichard Henderson      */
175749840a4aSRichard Henderson     page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK,
1758eee816c0SRichard Henderson                    PAGE_EXEC | PAGE_VALID);
1759eee816c0SRichard Henderson     return true;
1760eee816c0SRichard Henderson }
1761eee816c0SRichard Henderson 
17627c248bcdSRichard Henderson #endif /* TARGET_HPPA */
17637c248bcdSRichard Henderson 
1764ba7651fbSMax Filippov #ifdef TARGET_XTENSA
1765ba7651fbSMax Filippov 
1766ba7651fbSMax Filippov #define ELF_START_MMAP 0x20000000
1767ba7651fbSMax Filippov 
1768ba7651fbSMax Filippov #define ELF_CLASS       ELFCLASS32
1769ba7651fbSMax Filippov #define ELF_ARCH        EM_XTENSA
1770ba7651fbSMax Filippov 
1771ba7651fbSMax Filippov static inline void init_thread(struct target_pt_regs *regs,
1772ba7651fbSMax Filippov                                struct image_info *infop)
1773ba7651fbSMax Filippov {
1774ba7651fbSMax Filippov     regs->windowbase = 0;
1775ba7651fbSMax Filippov     regs->windowstart = 1;
1776ba7651fbSMax Filippov     regs->areg[1] = infop->start_stack;
1777ba7651fbSMax Filippov     regs->pc = infop->entry;
1778d2796be6SMax Filippov     if (info_is_fdpic(infop)) {
1779d2796be6SMax Filippov         regs->areg[4] = infop->loadmap_addr;
1780d2796be6SMax Filippov         regs->areg[5] = infop->interpreter_loadmap_addr;
1781d2796be6SMax Filippov         if (infop->interpreter_loadmap_addr) {
1782d2796be6SMax Filippov             regs->areg[6] = infop->interpreter_pt_dynamic_addr;
1783d2796be6SMax Filippov         } else {
1784d2796be6SMax Filippov             regs->areg[6] = infop->pt_dynamic_addr;
1785d2796be6SMax Filippov         }
1786d2796be6SMax Filippov     }
1787ba7651fbSMax Filippov }
1788ba7651fbSMax Filippov 
1789ba7651fbSMax Filippov /* See linux kernel: arch/xtensa/include/asm/elf.h.  */
1790ba7651fbSMax Filippov #define ELF_NREG 128
1791ba7651fbSMax Filippov typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1792ba7651fbSMax Filippov 
1793ba7651fbSMax Filippov enum {
1794ba7651fbSMax Filippov     TARGET_REG_PC,
1795ba7651fbSMax Filippov     TARGET_REG_PS,
1796ba7651fbSMax Filippov     TARGET_REG_LBEG,
1797ba7651fbSMax Filippov     TARGET_REG_LEND,
1798ba7651fbSMax Filippov     TARGET_REG_LCOUNT,
1799ba7651fbSMax Filippov     TARGET_REG_SAR,
1800ba7651fbSMax Filippov     TARGET_REG_WINDOWSTART,
1801ba7651fbSMax Filippov     TARGET_REG_WINDOWBASE,
1802ba7651fbSMax Filippov     TARGET_REG_THREADPTR,
1803ba7651fbSMax Filippov     TARGET_REG_AR0 = 64,
1804ba7651fbSMax Filippov };
1805ba7651fbSMax Filippov 
1806ba7651fbSMax Filippov static void elf_core_copy_regs(target_elf_gregset_t *regs,
1807ba7651fbSMax Filippov                                const CPUXtensaState *env)
1808ba7651fbSMax Filippov {
1809ba7651fbSMax Filippov     unsigned i;
1810ba7651fbSMax Filippov 
1811ba7651fbSMax Filippov     (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
1812ba7651fbSMax Filippov     (*regs)[TARGET_REG_PS] = tswapreg(env->sregs[PS] & ~PS_EXCM);
1813ba7651fbSMax Filippov     (*regs)[TARGET_REG_LBEG] = tswapreg(env->sregs[LBEG]);
1814ba7651fbSMax Filippov     (*regs)[TARGET_REG_LEND] = tswapreg(env->sregs[LEND]);
1815ba7651fbSMax Filippov     (*regs)[TARGET_REG_LCOUNT] = tswapreg(env->sregs[LCOUNT]);
1816ba7651fbSMax Filippov     (*regs)[TARGET_REG_SAR] = tswapreg(env->sregs[SAR]);
1817ba7651fbSMax Filippov     (*regs)[TARGET_REG_WINDOWSTART] = tswapreg(env->sregs[WINDOW_START]);
1818ba7651fbSMax Filippov     (*regs)[TARGET_REG_WINDOWBASE] = tswapreg(env->sregs[WINDOW_BASE]);
1819ba7651fbSMax Filippov     (*regs)[TARGET_REG_THREADPTR] = tswapreg(env->uregs[THREADPTR]);
1820ba7651fbSMax Filippov     xtensa_sync_phys_from_window((CPUXtensaState *)env);
1821ba7651fbSMax Filippov     for (i = 0; i < env->config->nareg; ++i) {
1822ba7651fbSMax Filippov         (*regs)[TARGET_REG_AR0 + i] = tswapreg(env->phys_regs[i]);
1823ba7651fbSMax Filippov     }
1824ba7651fbSMax Filippov }
1825ba7651fbSMax Filippov 
1826ba7651fbSMax Filippov #define USE_ELF_CORE_DUMP
1827ba7651fbSMax Filippov #define ELF_EXEC_PAGESIZE       4096
1828ba7651fbSMax Filippov 
1829ba7651fbSMax Filippov #endif /* TARGET_XTENSA */
1830ba7651fbSMax Filippov 
1831d2a56bd2STaylor Simpson #ifdef TARGET_HEXAGON
1832d2a56bd2STaylor Simpson 
1833d2a56bd2STaylor Simpson #define ELF_START_MMAP 0x20000000
1834d2a56bd2STaylor Simpson 
1835d2a56bd2STaylor Simpson #define ELF_CLASS       ELFCLASS32
1836d2a56bd2STaylor Simpson #define ELF_ARCH        EM_HEXAGON
1837d2a56bd2STaylor Simpson 
1838d2a56bd2STaylor Simpson static inline void init_thread(struct target_pt_regs *regs,
1839d2a56bd2STaylor Simpson                                struct image_info *infop)
1840d2a56bd2STaylor Simpson {
1841d2a56bd2STaylor Simpson     regs->sepc = infop->entry;
1842d2a56bd2STaylor Simpson     regs->sp = infop->start_stack;
1843d2a56bd2STaylor Simpson }
1844d2a56bd2STaylor Simpson 
1845d2a56bd2STaylor Simpson #endif /* TARGET_HEXAGON */
1846d2a56bd2STaylor Simpson 
1847fcdc0ab4SJiaxun Yang #ifndef ELF_BASE_PLATFORM
1848fcdc0ab4SJiaxun Yang #define ELF_BASE_PLATFORM (NULL)
1849fcdc0ab4SJiaxun Yang #endif
1850fcdc0ab4SJiaxun Yang 
185115338fd7Sbellard #ifndef ELF_PLATFORM
185215338fd7Sbellard #define ELF_PLATFORM (NULL)
185315338fd7Sbellard #endif
185415338fd7Sbellard 
185575be901cSPeter Crosthwaite #ifndef ELF_MACHINE
185675be901cSPeter Crosthwaite #define ELF_MACHINE ELF_ARCH
185775be901cSPeter Crosthwaite #endif
185875be901cSPeter Crosthwaite 
1859d276a604SPeter Crosthwaite #ifndef elf_check_arch
1860d276a604SPeter Crosthwaite #define elf_check_arch(x) ((x) == ELF_ARCH)
1861d276a604SPeter Crosthwaite #endif
1862d276a604SPeter Crosthwaite 
1863ace3d654SCarlo Marcelo Arenas Belón #ifndef elf_check_abi
1864ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (1)
1865ace3d654SCarlo Marcelo Arenas Belón #endif
1866ace3d654SCarlo Marcelo Arenas Belón 
186715338fd7Sbellard #ifndef ELF_HWCAP
186815338fd7Sbellard #define ELF_HWCAP 0
186915338fd7Sbellard #endif
187015338fd7Sbellard 
18717c4ee5bcSRichard Henderson #ifndef STACK_GROWS_DOWN
18727c4ee5bcSRichard Henderson #define STACK_GROWS_DOWN 1
18737c4ee5bcSRichard Henderson #endif
18747c4ee5bcSRichard Henderson 
18757c4ee5bcSRichard Henderson #ifndef STACK_ALIGNMENT
18767c4ee5bcSRichard Henderson #define STACK_ALIGNMENT 16
18777c4ee5bcSRichard Henderson #endif
18787c4ee5bcSRichard Henderson 
1879992f48a0Sblueswir1 #ifdef TARGET_ABI32
1880cb33da57Sblueswir1 #undef ELF_CLASS
1881992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32
1882cb33da57Sblueswir1 #undef bswaptls
1883cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr)
1884cb33da57Sblueswir1 #endif
1885cb33da57Sblueswir1 
1886872f3d04SRichard Henderson #ifndef EXSTACK_DEFAULT
1887872f3d04SRichard Henderson #define EXSTACK_DEFAULT false
1888872f3d04SRichard Henderson #endif
1889872f3d04SRichard Henderson 
189031e31b8aSbellard #include "elf.h"
189109bfb054Sbellard 
1892e8384b37SRichard Henderson /* We must delay the following stanzas until after "elf.h". */
1893e8384b37SRichard Henderson #if defined(TARGET_AARCH64)
1894e8384b37SRichard Henderson 
1895e8384b37SRichard Henderson static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
1896e8384b37SRichard Henderson                                     const uint32_t *data,
1897e8384b37SRichard Henderson                                     struct image_info *info,
1898e8384b37SRichard Henderson                                     Error **errp)
1899e8384b37SRichard Henderson {
1900e8384b37SRichard Henderson     if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
1901e8384b37SRichard Henderson         if (pr_datasz != sizeof(uint32_t)) {
1902e8384b37SRichard Henderson             error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
1903e8384b37SRichard Henderson             return false;
1904e8384b37SRichard Henderson         }
1905e8384b37SRichard Henderson         /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
1906e8384b37SRichard Henderson         info->note_flags = *data;
1907e8384b37SRichard Henderson     }
1908e8384b37SRichard Henderson     return true;
1909e8384b37SRichard Henderson }
1910e8384b37SRichard Henderson #define ARCH_USE_GNU_PROPERTY 1
1911e8384b37SRichard Henderson 
1912e8384b37SRichard Henderson #else
1913e8384b37SRichard Henderson 
191483f990ebSRichard Henderson static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
191583f990ebSRichard Henderson                                     const uint32_t *data,
191683f990ebSRichard Henderson                                     struct image_info *info,
191783f990ebSRichard Henderson                                     Error **errp)
191883f990ebSRichard Henderson {
191983f990ebSRichard Henderson     g_assert_not_reached();
192083f990ebSRichard Henderson }
192183f990ebSRichard Henderson #define ARCH_USE_GNU_PROPERTY 0
192283f990ebSRichard Henderson 
1923e8384b37SRichard Henderson #endif
1924e8384b37SRichard Henderson 
192509bfb054Sbellard struct exec
192609bfb054Sbellard {
192709bfb054Sbellard     unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
192809bfb054Sbellard     unsigned int a_text;   /* length of text, in bytes */
192909bfb054Sbellard     unsigned int a_data;   /* length of data, in bytes */
193009bfb054Sbellard     unsigned int a_bss;    /* length of uninitialized data area, in bytes */
193109bfb054Sbellard     unsigned int a_syms;   /* length of symbol table data in file, in bytes */
193209bfb054Sbellard     unsigned int a_entry;  /* start address */
193309bfb054Sbellard     unsigned int a_trsize; /* length of relocation info for text, in bytes */
193409bfb054Sbellard     unsigned int a_drsize; /* length of relocation info for data, in bytes */
193509bfb054Sbellard };
193609bfb054Sbellard 
193709bfb054Sbellard 
193809bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff)
193909bfb054Sbellard #define OMAGIC 0407
194009bfb054Sbellard #define NMAGIC 0410
194109bfb054Sbellard #define ZMAGIC 0413
194209bfb054Sbellard #define QMAGIC 0314
194309bfb054Sbellard 
194431e31b8aSbellard /* Necessary parameters */
194594894ff2SShivaprasad G Bhat #define TARGET_ELF_EXEC_PAGESIZE \
194694894ff2SShivaprasad G Bhat         (((eppnt->p_align & ~qemu_host_page_mask) != 0) ? \
194794894ff2SShivaprasad G Bhat          TARGET_PAGE_SIZE : MAX(qemu_host_page_size, TARGET_PAGE_SIZE))
194894894ff2SShivaprasad G Bhat #define TARGET_ELF_PAGELENGTH(_v) ROUND_UP((_v), TARGET_ELF_EXEC_PAGESIZE)
194979cb1f1dSYongbok Kim #define TARGET_ELF_PAGESTART(_v) ((_v) & \
195079cb1f1dSYongbok Kim                                  ~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1))
195154936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
195231e31b8aSbellard 
1953e0d1673dSLirong Yuan #define DLINFO_ITEMS 16
195431e31b8aSbellard 
195509bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
195609bfb054Sbellard {
195709bfb054Sbellard     memcpy(to, from, n);
195809bfb054Sbellard }
195909bfb054Sbellard 
196031e31b8aSbellard #ifdef BSWAP_NEEDED
196192a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr)
196231e31b8aSbellard {
196331e31b8aSbellard     bswap16s(&ehdr->e_type);            /* Object file type */
196431e31b8aSbellard     bswap16s(&ehdr->e_machine);         /* Architecture */
196531e31b8aSbellard     bswap32s(&ehdr->e_version);         /* Object file version */
196692a31b1fSbellard     bswaptls(&ehdr->e_entry);           /* Entry point virtual address */
196792a31b1fSbellard     bswaptls(&ehdr->e_phoff);           /* Program header table file offset */
196892a31b1fSbellard     bswaptls(&ehdr->e_shoff);           /* Section header table file offset */
196931e31b8aSbellard     bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
197031e31b8aSbellard     bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
197131e31b8aSbellard     bswap16s(&ehdr->e_phentsize);       /* Program header table entry size */
197231e31b8aSbellard     bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
197331e31b8aSbellard     bswap16s(&ehdr->e_shentsize);       /* Section header table entry size */
197431e31b8aSbellard     bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
197531e31b8aSbellard     bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */
197631e31b8aSbellard }
197731e31b8aSbellard 
1978991f8f0cSRichard Henderson static void bswap_phdr(struct elf_phdr *phdr, int phnum)
197931e31b8aSbellard {
1980991f8f0cSRichard Henderson     int i;
1981991f8f0cSRichard Henderson     for (i = 0; i < phnum; ++i, ++phdr) {
198231e31b8aSbellard         bswap32s(&phdr->p_type);        /* Segment type */
1983991f8f0cSRichard Henderson         bswap32s(&phdr->p_flags);       /* Segment flags */
198492a31b1fSbellard         bswaptls(&phdr->p_offset);      /* Segment file offset */
198592a31b1fSbellard         bswaptls(&phdr->p_vaddr);       /* Segment virtual address */
198692a31b1fSbellard         bswaptls(&phdr->p_paddr);       /* Segment physical address */
198792a31b1fSbellard         bswaptls(&phdr->p_filesz);      /* Segment size in file */
198892a31b1fSbellard         bswaptls(&phdr->p_memsz);       /* Segment size in memory */
198992a31b1fSbellard         bswaptls(&phdr->p_align);       /* Segment alignment */
199031e31b8aSbellard     }
1991991f8f0cSRichard Henderson }
1992689f936fSbellard 
1993991f8f0cSRichard Henderson static void bswap_shdr(struct elf_shdr *shdr, int shnum)
1994689f936fSbellard {
1995991f8f0cSRichard Henderson     int i;
1996991f8f0cSRichard Henderson     for (i = 0; i < shnum; ++i, ++shdr) {
1997689f936fSbellard         bswap32s(&shdr->sh_name);
1998689f936fSbellard         bswap32s(&shdr->sh_type);
199992a31b1fSbellard         bswaptls(&shdr->sh_flags);
200092a31b1fSbellard         bswaptls(&shdr->sh_addr);
200192a31b1fSbellard         bswaptls(&shdr->sh_offset);
200292a31b1fSbellard         bswaptls(&shdr->sh_size);
2003689f936fSbellard         bswap32s(&shdr->sh_link);
2004689f936fSbellard         bswap32s(&shdr->sh_info);
200592a31b1fSbellard         bswaptls(&shdr->sh_addralign);
200692a31b1fSbellard         bswaptls(&shdr->sh_entsize);
2007689f936fSbellard     }
2008991f8f0cSRichard Henderson }
2009689f936fSbellard 
20107a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym)
2011689f936fSbellard {
2012689f936fSbellard     bswap32s(&sym->st_name);
20137a3148a9Sj_mayer     bswaptls(&sym->st_value);
20147a3148a9Sj_mayer     bswaptls(&sym->st_size);
2015689f936fSbellard     bswap16s(&sym->st_shndx);
2016689f936fSbellard }
20175dd0db52SStefan Markovic 
20185dd0db52SStefan Markovic #ifdef TARGET_MIPS
20195dd0db52SStefan Markovic static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags)
20205dd0db52SStefan Markovic {
20215dd0db52SStefan Markovic     bswap16s(&abiflags->version);
20225dd0db52SStefan Markovic     bswap32s(&abiflags->ases);
20235dd0db52SStefan Markovic     bswap32s(&abiflags->isa_ext);
20245dd0db52SStefan Markovic     bswap32s(&abiflags->flags1);
20255dd0db52SStefan Markovic     bswap32s(&abiflags->flags2);
20265dd0db52SStefan Markovic }
20275dd0db52SStefan Markovic #endif
2028991f8f0cSRichard Henderson #else
2029991f8f0cSRichard Henderson static inline void bswap_ehdr(struct elfhdr *ehdr) { }
2030991f8f0cSRichard Henderson static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
2031991f8f0cSRichard Henderson static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
2032991f8f0cSRichard Henderson static inline void bswap_sym(struct elf_sym *sym) { }
20335dd0db52SStefan Markovic #ifdef TARGET_MIPS
20345dd0db52SStefan Markovic static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { }
20355dd0db52SStefan Markovic #endif
203631e31b8aSbellard #endif
203731e31b8aSbellard 
2038edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
20399349b4f9SAndreas Färber static int elf_core_dump(int, const CPUArchState *);
2040edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
2041682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
2042edf8e2afSMika Westerberg 
20439058abddSRichard Henderson /* Verify the portions of EHDR within E_IDENT for the target.
20449058abddSRichard Henderson    This can be performed before bswapping the entire header.  */
20459058abddSRichard Henderson static bool elf_check_ident(struct elfhdr *ehdr)
20469058abddSRichard Henderson {
20479058abddSRichard Henderson     return (ehdr->e_ident[EI_MAG0] == ELFMAG0
20489058abddSRichard Henderson             && ehdr->e_ident[EI_MAG1] == ELFMAG1
20499058abddSRichard Henderson             && ehdr->e_ident[EI_MAG2] == ELFMAG2
20509058abddSRichard Henderson             && ehdr->e_ident[EI_MAG3] == ELFMAG3
20519058abddSRichard Henderson             && ehdr->e_ident[EI_CLASS] == ELF_CLASS
20529058abddSRichard Henderson             && ehdr->e_ident[EI_DATA] == ELF_DATA
20539058abddSRichard Henderson             && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
20549058abddSRichard Henderson }
20559058abddSRichard Henderson 
20569058abddSRichard Henderson /* Verify the portions of EHDR outside of E_IDENT for the target.
20579058abddSRichard Henderson    This has to wait until after bswapping the header.  */
20589058abddSRichard Henderson static bool elf_check_ehdr(struct elfhdr *ehdr)
20599058abddSRichard Henderson {
20609058abddSRichard Henderson     return (elf_check_arch(ehdr->e_machine)
2061ace3d654SCarlo Marcelo Arenas Belón             && elf_check_abi(ehdr->e_flags)
20629058abddSRichard Henderson             && ehdr->e_ehsize == sizeof(struct elfhdr)
20639058abddSRichard Henderson             && ehdr->e_phentsize == sizeof(struct elf_phdr)
20649058abddSRichard Henderson             && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
20659058abddSRichard Henderson }
20669058abddSRichard Henderson 
206731e31b8aSbellard /*
2068e5fe0c52Spbrook  * 'copy_elf_strings()' copies argument/envelope strings from user
206931e31b8aSbellard  * memory to free pages in kernel mem. These are in a format ready
207031e31b8aSbellard  * to be put directly into the top of new user memory.
207131e31b8aSbellard  *
207231e31b8aSbellard  */
207359baae9aSStefan Brüns static abi_ulong copy_elf_strings(int argc, char **argv, char *scratch,
207459baae9aSStefan Brüns                                   abi_ulong p, abi_ulong stack_limit)
207531e31b8aSbellard {
207659baae9aSStefan Brüns     char *tmp;
20777c4ee5bcSRichard Henderson     int len, i;
207859baae9aSStefan Brüns     abi_ulong top = p;
207931e31b8aSbellard 
208031e31b8aSbellard     if (!p) {
208131e31b8aSbellard         return 0;       /* bullet-proofing */
208231e31b8aSbellard     }
208359baae9aSStefan Brüns 
20847c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
20857c4ee5bcSRichard Henderson         int offset = ((p - 1) % TARGET_PAGE_SIZE) + 1;
20867c4ee5bcSRichard Henderson         for (i = argc - 1; i >= 0; --i) {
20877c4ee5bcSRichard Henderson             tmp = argv[i];
2088edf779ffSbellard             if (!tmp) {
208931e31b8aSbellard                 fprintf(stderr, "VFS: argc is wrong");
209031e31b8aSbellard                 exit(-1);
209131e31b8aSbellard             }
209259baae9aSStefan Brüns             len = strlen(tmp) + 1;
209359baae9aSStefan Brüns             tmp += len;
209459baae9aSStefan Brüns 
209559baae9aSStefan Brüns             if (len > (p - stack_limit)) {
209631e31b8aSbellard                 return 0;
209731e31b8aSbellard             }
209831e31b8aSbellard             while (len) {
209931e31b8aSbellard                 int bytes_to_copy = (len > offset) ? offset : len;
210031e31b8aSbellard                 tmp -= bytes_to_copy;
210131e31b8aSbellard                 p -= bytes_to_copy;
210231e31b8aSbellard                 offset -= bytes_to_copy;
210331e31b8aSbellard                 len -= bytes_to_copy;
210459baae9aSStefan Brüns 
210559baae9aSStefan Brüns                 memcpy_fromfs(scratch + offset, tmp, bytes_to_copy);
210659baae9aSStefan Brüns 
210759baae9aSStefan Brüns                 if (offset == 0) {
210859baae9aSStefan Brüns                     memcpy_to_target(p, scratch, top - p);
210959baae9aSStefan Brüns                     top = p;
211059baae9aSStefan Brüns                     offset = TARGET_PAGE_SIZE;
211131e31b8aSbellard                 }
211231e31b8aSbellard             }
211331e31b8aSbellard         }
21147c4ee5bcSRichard Henderson         if (p != top) {
211559baae9aSStefan Brüns             memcpy_to_target(p, scratch + offset, top - p);
211659baae9aSStefan Brüns         }
21177c4ee5bcSRichard Henderson     } else {
21187c4ee5bcSRichard Henderson         int remaining = TARGET_PAGE_SIZE - (p % TARGET_PAGE_SIZE);
21197c4ee5bcSRichard Henderson         for (i = 0; i < argc; ++i) {
21207c4ee5bcSRichard Henderson             tmp = argv[i];
21217c4ee5bcSRichard Henderson             if (!tmp) {
21227c4ee5bcSRichard Henderson                 fprintf(stderr, "VFS: argc is wrong");
21237c4ee5bcSRichard Henderson                 exit(-1);
21247c4ee5bcSRichard Henderson             }
21257c4ee5bcSRichard Henderson             len = strlen(tmp) + 1;
21267c4ee5bcSRichard Henderson             if (len > (stack_limit - p)) {
21277c4ee5bcSRichard Henderson                 return 0;
21287c4ee5bcSRichard Henderson             }
21297c4ee5bcSRichard Henderson             while (len) {
21307c4ee5bcSRichard Henderson                 int bytes_to_copy = (len > remaining) ? remaining : len;
21317c4ee5bcSRichard Henderson 
21327c4ee5bcSRichard Henderson                 memcpy_fromfs(scratch + (p - top), tmp, bytes_to_copy);
21337c4ee5bcSRichard Henderson 
21347c4ee5bcSRichard Henderson                 tmp += bytes_to_copy;
21357c4ee5bcSRichard Henderson                 remaining -= bytes_to_copy;
21367c4ee5bcSRichard Henderson                 p += bytes_to_copy;
21377c4ee5bcSRichard Henderson                 len -= bytes_to_copy;
21387c4ee5bcSRichard Henderson 
21397c4ee5bcSRichard Henderson                 if (remaining == 0) {
21407c4ee5bcSRichard Henderson                     memcpy_to_target(top, scratch, p - top);
21417c4ee5bcSRichard Henderson                     top = p;
21427c4ee5bcSRichard Henderson                     remaining = TARGET_PAGE_SIZE;
21437c4ee5bcSRichard Henderson                 }
21447c4ee5bcSRichard Henderson             }
21457c4ee5bcSRichard Henderson         }
21467c4ee5bcSRichard Henderson         if (p != top) {
21477c4ee5bcSRichard Henderson             memcpy_to_target(top, scratch, p - top);
21487c4ee5bcSRichard Henderson         }
21497c4ee5bcSRichard Henderson     }
215059baae9aSStefan Brüns 
215131e31b8aSbellard     return p;
215231e31b8aSbellard }
215331e31b8aSbellard 
215459baae9aSStefan Brüns /* Older linux kernels provide up to MAX_ARG_PAGES (default: 32) of
215559baae9aSStefan Brüns  * argument/environment space. Newer kernels (>2.6.33) allow more,
215659baae9aSStefan Brüns  * dependent on stack size, but guarantee at least 32 pages for
215759baae9aSStefan Brüns  * backwards compatibility.
215859baae9aSStefan Brüns  */
215959baae9aSStefan Brüns #define STACK_LOWER_LIMIT (32 * TARGET_PAGE_SIZE)
216059baae9aSStefan Brüns 
216159baae9aSStefan Brüns static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
216231e31b8aSbellard                                  struct image_info *info)
216331e31b8aSbellard {
216459baae9aSStefan Brüns     abi_ulong size, error, guard;
2165872f3d04SRichard Henderson     int prot;
216631e31b8aSbellard 
2167703e0e89SRichard Henderson     size = guest_stack_size;
216859baae9aSStefan Brüns     if (size < STACK_LOWER_LIMIT) {
216959baae9aSStefan Brüns         size = STACK_LOWER_LIMIT;
217060dcbcb5SRichard Henderson     }
2171f4388205SHelge Deller 
2172f4388205SHelge Deller     if (STACK_GROWS_DOWN) {
217360dcbcb5SRichard Henderson         guard = TARGET_PAGE_SIZE;
21748e3b0cbbSMarc-André Lureau         if (guard < qemu_real_host_page_size()) {
21758e3b0cbbSMarc-André Lureau             guard = qemu_real_host_page_size();
217660dcbcb5SRichard Henderson         }
2177f4388205SHelge Deller     } else {
2178f4388205SHelge Deller         /* no guard page for hppa target where stack grows upwards. */
2179f4388205SHelge Deller         guard = 0;
2180f4388205SHelge Deller     }
218160dcbcb5SRichard Henderson 
2182872f3d04SRichard Henderson     prot = PROT_READ | PROT_WRITE;
2183872f3d04SRichard Henderson     if (info->exec_stack) {
2184872f3d04SRichard Henderson         prot |= PROT_EXEC;
2185872f3d04SRichard Henderson     }
2186872f3d04SRichard Henderson     error = target_mmap(0, size + guard, prot,
218760dcbcb5SRichard Henderson                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
218809bfb054Sbellard     if (error == -1) {
218960dcbcb5SRichard Henderson         perror("mmap stack");
219031e31b8aSbellard         exit(-1);
219131e31b8aSbellard     }
219231e31b8aSbellard 
219360dcbcb5SRichard Henderson     /* We reserve one extra page at the top of the stack as guard.  */
21947c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
219560dcbcb5SRichard Henderson         target_mprotect(error, guard, PROT_NONE);
219660dcbcb5SRichard Henderson         info->stack_limit = error + guard;
219759baae9aSStefan Brüns         return info->stack_limit + size - sizeof(void *);
21987c4ee5bcSRichard Henderson     } else {
21997c4ee5bcSRichard Henderson         info->stack_limit = error + size;
22007c4ee5bcSRichard Henderson         return error;
22017c4ee5bcSRichard Henderson     }
220231e31b8aSbellard }
220331e31b8aSbellard 
2204cf129f3aSRichard Henderson /* Map and zero the bss.  We need to explicitly zero any fractional pages
2205cf129f3aSRichard Henderson    after the data section (i.e. bss).  */
2206cf129f3aSRichard Henderson static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
220731e31b8aSbellard {
2208cf129f3aSRichard Henderson     uintptr_t host_start, host_map_start, host_end;
2209cf129f3aSRichard Henderson 
2210cf129f3aSRichard Henderson     last_bss = TARGET_PAGE_ALIGN(last_bss);
2211cf129f3aSRichard Henderson 
2212cf129f3aSRichard Henderson     /* ??? There is confusion between qemu_real_host_page_size and
2213cf129f3aSRichard Henderson        qemu_host_page_size here and elsewhere in target_mmap, which
2214cf129f3aSRichard Henderson        may lead to the end of the data section mapping from the file
2215cf129f3aSRichard Henderson        not being mapped.  At least there was an explicit test and
2216cf129f3aSRichard Henderson        comment for that here, suggesting that "the file size must
2217cf129f3aSRichard Henderson        be known".  The comment probably pre-dates the introduction
2218cf129f3aSRichard Henderson        of the fstat system call in target_mmap which does in fact
2219cf129f3aSRichard Henderson        find out the size.  What isn't clear is if the workaround
2220cf129f3aSRichard Henderson        here is still actually needed.  For now, continue with it,
2221cf129f3aSRichard Henderson        but merge it with the "normal" mmap that would allocate the bss.  */
2222cf129f3aSRichard Henderson 
22233e8f1628SRichard Henderson     host_start = (uintptr_t) g2h_untagged(elf_bss);
22243e8f1628SRichard Henderson     host_end = (uintptr_t) g2h_untagged(last_bss);
22250c2d70c4SPaolo Bonzini     host_map_start = REAL_HOST_PAGE_ALIGN(host_start);
2226cf129f3aSRichard Henderson 
2227cf129f3aSRichard Henderson     if (host_map_start < host_end) {
2228cf129f3aSRichard Henderson         void *p = mmap((void *)host_map_start, host_end - host_map_start,
2229cf129f3aSRichard Henderson                        prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
2230cf129f3aSRichard Henderson         if (p == MAP_FAILED) {
223131e31b8aSbellard             perror("cannot mmap brk");
223231e31b8aSbellard             exit(-1);
223331e31b8aSbellard         }
2234f46e9a0bSTom Musta     }
2235cf129f3aSRichard Henderson 
2236f46e9a0bSTom Musta     /* Ensure that the bss page(s) are valid */
2237f46e9a0bSTom Musta     if ((page_get_flags(last_bss-1) & prot) != prot) {
223849840a4aSRichard Henderson         page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss - 1,
223949840a4aSRichard Henderson                        prot | PAGE_VALID);
224031e31b8aSbellard     }
224131e31b8aSbellard 
2242cf129f3aSRichard Henderson     if (host_start < host_map_start) {
2243cf129f3aSRichard Henderson         memset((void *)host_start, 0, host_map_start - host_start);
2244853d6f7aSbellard     }
2245853d6f7aSbellard }
2246853d6f7aSbellard 
2247d2796be6SMax Filippov #if defined(TARGET_ARM)
2248cf58affeSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec)
2249cf58affeSChristophe Lyon {
2250cf58affeSChristophe Lyon     return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC;
2251cf58affeSChristophe Lyon }
2252d2796be6SMax Filippov #elif defined(TARGET_XTENSA)
2253d2796be6SMax Filippov static int elf_is_fdpic(struct elfhdr *exec)
2254d2796be6SMax Filippov {
2255d2796be6SMax Filippov     return exec->e_ident[EI_OSABI] == ELFOSABI_XTENSA_FDPIC;
2256d2796be6SMax Filippov }
2257cf58affeSChristophe Lyon #else
2258a99856cdSChristophe Lyon /* Default implementation, always false.  */
2259a99856cdSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec)
2260a99856cdSChristophe Lyon {
2261a99856cdSChristophe Lyon     return 0;
2262a99856cdSChristophe Lyon }
2263cf58affeSChristophe Lyon #endif
2264a99856cdSChristophe Lyon 
22651af02e83SMike Frysinger static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
22661af02e83SMike Frysinger {
22671af02e83SMike Frysinger     uint16_t n;
22681af02e83SMike Frysinger     struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
22691af02e83SMike Frysinger 
22701af02e83SMike Frysinger     /* elf32_fdpic_loadseg */
22711af02e83SMike Frysinger     n = info->nsegs;
22721af02e83SMike Frysinger     while (n--) {
22731af02e83SMike Frysinger         sp -= 12;
22741af02e83SMike Frysinger         put_user_u32(loadsegs[n].addr, sp+0);
22751af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_vaddr, sp+4);
22761af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_memsz, sp+8);
22771af02e83SMike Frysinger     }
22781af02e83SMike Frysinger 
22791af02e83SMike Frysinger     /* elf32_fdpic_loadmap */
22801af02e83SMike Frysinger     sp -= 4;
22811af02e83SMike Frysinger     put_user_u16(0, sp+0); /* version */
22821af02e83SMike Frysinger     put_user_u16(info->nsegs, sp+2); /* nsegs */
22831af02e83SMike Frysinger 
22841af02e83SMike Frysinger     info->personality = PER_LINUX_FDPIC;
22851af02e83SMike Frysinger     info->loadmap_addr = sp;
22861af02e83SMike Frysinger 
22871af02e83SMike Frysinger     return sp;
22881af02e83SMike Frysinger }
22891af02e83SMike Frysinger 
2290992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
229131e31b8aSbellard                                    struct elfhdr *exec,
22928e62a717SRichard Henderson                                    struct image_info *info,
22938e62a717SRichard Henderson                                    struct image_info *interp_info)
229431e31b8aSbellard {
2295992f48a0Sblueswir1     abi_ulong sp;
22967c4ee5bcSRichard Henderson     abi_ulong u_argc, u_argv, u_envp, u_auxv;
229753a5960aSpbrook     int size;
229814322badSLaurent ALFONSI     int i;
229914322badSLaurent ALFONSI     abi_ulong u_rand_bytes;
230014322badSLaurent ALFONSI     uint8_t k_rand_bytes[16];
2301fcdc0ab4SJiaxun Yang     abi_ulong u_platform, u_base_platform;
2302fcdc0ab4SJiaxun Yang     const char *k_platform, *k_base_platform;
2303863cf0b7Sj_mayer     const int n = sizeof(elf_addr_t);
230431e31b8aSbellard 
230553a5960aSpbrook     sp = p;
23061af02e83SMike Frysinger 
23071af02e83SMike Frysinger     /* Needs to be before we load the env/argc/... */
23081af02e83SMike Frysinger     if (elf_is_fdpic(exec)) {
23091af02e83SMike Frysinger         /* Need 4 byte alignment for these structs */
23101af02e83SMike Frysinger         sp &= ~3;
23111af02e83SMike Frysinger         sp = loader_build_fdpic_loadmap(info, sp);
23121af02e83SMike Frysinger         info->other_info = interp_info;
23131af02e83SMike Frysinger         if (interp_info) {
23141af02e83SMike Frysinger             interp_info->other_info = info;
23151af02e83SMike Frysinger             sp = loader_build_fdpic_loadmap(interp_info, sp);
23163cb10cfaSChristophe Lyon             info->interpreter_loadmap_addr = interp_info->loadmap_addr;
23173cb10cfaSChristophe Lyon             info->interpreter_pt_dynamic_addr = interp_info->pt_dynamic_addr;
23183cb10cfaSChristophe Lyon         } else {
23193cb10cfaSChristophe Lyon             info->interpreter_loadmap_addr = 0;
23203cb10cfaSChristophe Lyon             info->interpreter_pt_dynamic_addr = 0;
23211af02e83SMike Frysinger         }
23221af02e83SMike Frysinger     }
23231af02e83SMike Frysinger 
2324fcdc0ab4SJiaxun Yang     u_base_platform = 0;
2325fcdc0ab4SJiaxun Yang     k_base_platform = ELF_BASE_PLATFORM;
2326fcdc0ab4SJiaxun Yang     if (k_base_platform) {
2327fcdc0ab4SJiaxun Yang         size_t len = strlen(k_base_platform) + 1;
2328fcdc0ab4SJiaxun Yang         if (STACK_GROWS_DOWN) {
2329fcdc0ab4SJiaxun Yang             sp -= (len + n - 1) & ~(n - 1);
2330fcdc0ab4SJiaxun Yang             u_base_platform = sp;
2331fcdc0ab4SJiaxun Yang             /* FIXME - check return value of memcpy_to_target() for failure */
2332fcdc0ab4SJiaxun Yang             memcpy_to_target(sp, k_base_platform, len);
2333fcdc0ab4SJiaxun Yang         } else {
2334fcdc0ab4SJiaxun Yang             memcpy_to_target(sp, k_base_platform, len);
2335fcdc0ab4SJiaxun Yang             u_base_platform = sp;
2336fcdc0ab4SJiaxun Yang             sp += len + 1;
2337fcdc0ab4SJiaxun Yang         }
2338fcdc0ab4SJiaxun Yang     }
2339fcdc0ab4SJiaxun Yang 
234053a5960aSpbrook     u_platform = 0;
234115338fd7Sbellard     k_platform = ELF_PLATFORM;
234215338fd7Sbellard     if (k_platform) {
234315338fd7Sbellard         size_t len = strlen(k_platform) + 1;
23447c4ee5bcSRichard Henderson         if (STACK_GROWS_DOWN) {
234553a5960aSpbrook             sp -= (len + n - 1) & ~(n - 1);
234653a5960aSpbrook             u_platform = sp;
2347579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
234853a5960aSpbrook             memcpy_to_target(sp, k_platform, len);
23497c4ee5bcSRichard Henderson         } else {
23507c4ee5bcSRichard Henderson             memcpy_to_target(sp, k_platform, len);
23517c4ee5bcSRichard Henderson             u_platform = sp;
23527c4ee5bcSRichard Henderson             sp += len + 1;
23537c4ee5bcSRichard Henderson         }
23547c4ee5bcSRichard Henderson     }
23557c4ee5bcSRichard Henderson 
23567c4ee5bcSRichard Henderson     /* Provide 16 byte alignment for the PRNG, and basic alignment for
23577c4ee5bcSRichard Henderson      * the argv and envp pointers.
23587c4ee5bcSRichard Henderson      */
23597c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
23607c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_DOWN(sp, 16);
23617c4ee5bcSRichard Henderson     } else {
23627c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_UP(sp, 16);
236315338fd7Sbellard     }
236414322badSLaurent ALFONSI 
236514322badSLaurent ALFONSI     /*
2366c6a2377fSRichard Henderson      * Generate 16 random bytes for userspace PRNG seeding.
236714322badSLaurent ALFONSI      */
2368c6a2377fSRichard Henderson     qemu_guest_getrandom_nofail(k_rand_bytes, sizeof(k_rand_bytes));
23697c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
237014322badSLaurent ALFONSI         sp -= 16;
237114322badSLaurent ALFONSI         u_rand_bytes = sp;
237214322badSLaurent ALFONSI         /* FIXME - check return value of memcpy_to_target() for failure */
237314322badSLaurent ALFONSI         memcpy_to_target(sp, k_rand_bytes, 16);
23747c4ee5bcSRichard Henderson     } else {
23757c4ee5bcSRichard Henderson         memcpy_to_target(sp, k_rand_bytes, 16);
23767c4ee5bcSRichard Henderson         u_rand_bytes = sp;
23777c4ee5bcSRichard Henderson         sp += 16;
23787c4ee5bcSRichard Henderson     }
237914322badSLaurent ALFONSI 
238053a5960aSpbrook     size = (DLINFO_ITEMS + 1) * 2;
2381fcdc0ab4SJiaxun Yang     if (k_base_platform)
2382fcdc0ab4SJiaxun Yang         size += 2;
238315338fd7Sbellard     if (k_platform)
238453a5960aSpbrook         size += 2;
2385f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS
238653a5960aSpbrook     size += DLINFO_ARCH_ITEMS * 2;
2387f5155289Sbellard #endif
2388ad6919dcSPeter Maydell #ifdef ELF_HWCAP2
2389ad6919dcSPeter Maydell     size += 2;
2390ad6919dcSPeter Maydell #endif
2391f516511eSPeter Maydell     info->auxv_len = size * n;
2392f516511eSPeter Maydell 
239353a5960aSpbrook     size += envc + argc + 2;
2394b9329d4bSRichard Henderson     size += 1;  /* argc itself */
239553a5960aSpbrook     size *= n;
23967c4ee5bcSRichard Henderson 
23977c4ee5bcSRichard Henderson     /* Allocate space and finalize stack alignment for entry now.  */
23987c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
23997c4ee5bcSRichard Henderson         u_argc = QEMU_ALIGN_DOWN(sp - size, STACK_ALIGNMENT);
24007c4ee5bcSRichard Henderson         sp = u_argc;
24017c4ee5bcSRichard Henderson     } else {
24027c4ee5bcSRichard Henderson         u_argc = sp;
24037c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_UP(sp + size, STACK_ALIGNMENT);
24047c4ee5bcSRichard Henderson     }
24057c4ee5bcSRichard Henderson 
24067c4ee5bcSRichard Henderson     u_argv = u_argc + n;
24077c4ee5bcSRichard Henderson     u_envp = u_argv + (argc + 1) * n;
24087c4ee5bcSRichard Henderson     u_auxv = u_envp + (envc + 1) * n;
24097c4ee5bcSRichard Henderson     info->saved_auxv = u_auxv;
241060f1c801SRichard Henderson     info->argc = argc;
241160f1c801SRichard Henderson     info->envc = envc;
241260f1c801SRichard Henderson     info->argv = u_argv;
241360f1c801SRichard Henderson     info->envp = u_envp;
2414f5155289Sbellard 
2415863cf0b7Sj_mayer     /* This is correct because Linux defines
2416863cf0b7Sj_mayer      * elf_addr_t as Elf32_Off / Elf64_Off
2417863cf0b7Sj_mayer      */
241853a5960aSpbrook #define NEW_AUX_ENT(id, val) do {               \
24197c4ee5bcSRichard Henderson         put_user_ual(id, u_auxv);  u_auxv += n; \
24207c4ee5bcSRichard Henderson         put_user_ual(val, u_auxv); u_auxv += n; \
242153a5960aSpbrook     } while(0)
24222f619698Sbellard 
242382991bedSPeter Maydell #ifdef ARCH_DLINFO
242482991bedSPeter Maydell     /*
242582991bedSPeter Maydell      * ARCH_DLINFO must come first so platform specific code can enforce
242682991bedSPeter Maydell      * special alignment requirements on the AUXV if necessary (eg. PPC).
242782991bedSPeter Maydell      */
242882991bedSPeter Maydell     ARCH_DLINFO;
242982991bedSPeter Maydell #endif
2430f516511eSPeter Maydell     /* There must be exactly DLINFO_ITEMS entries here, or the assert
2431f516511eSPeter Maydell      * on info->auxv_len will trigger.
2432f516511eSPeter Maydell      */
24338e62a717SRichard Henderson     NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
2434992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
2435992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
243633143c44SLaurent Vivier     if ((info->alignment & ~qemu_host_page_mask) != 0) {
243733143c44SLaurent Vivier         /* Target doesn't support host page size alignment */
243833143c44SLaurent Vivier         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
243933143c44SLaurent Vivier     } else {
244033143c44SLaurent Vivier         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE,
244133143c44SLaurent Vivier                                                qemu_host_page_size)));
244233143c44SLaurent Vivier     }
24438e62a717SRichard Henderson     NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0));
2444992f48a0Sblueswir1     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
24458e62a717SRichard Henderson     NEW_AUX_ENT(AT_ENTRY, info->entry);
2446992f48a0Sblueswir1     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
2447992f48a0Sblueswir1     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
2448992f48a0Sblueswir1     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
2449992f48a0Sblueswir1     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
2450992f48a0Sblueswir1     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
2451a07c67dfSpbrook     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
245214322badSLaurent ALFONSI     NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
2453444cd5c3SMarco A L Barbosa     NEW_AUX_ENT(AT_SECURE, (abi_ulong) qemu_getauxval(AT_SECURE));
2454e0d1673dSLirong Yuan     NEW_AUX_ENT(AT_EXECFN, info->file_string);
245514322badSLaurent ALFONSI 
2456ad6919dcSPeter Maydell #ifdef ELF_HWCAP2
2457ad6919dcSPeter Maydell     NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2);
2458ad6919dcSPeter Maydell #endif
2459ad6919dcSPeter Maydell 
2460fcdc0ab4SJiaxun Yang     if (u_base_platform) {
2461fcdc0ab4SJiaxun Yang         NEW_AUX_ENT(AT_BASE_PLATFORM, u_base_platform);
2462fcdc0ab4SJiaxun Yang     }
24637c4ee5bcSRichard Henderson     if (u_platform) {
246453a5960aSpbrook         NEW_AUX_ENT(AT_PLATFORM, u_platform);
24657c4ee5bcSRichard Henderson     }
24667c4ee5bcSRichard Henderson     NEW_AUX_ENT (AT_NULL, 0);
2467f5155289Sbellard #undef NEW_AUX_ENT
2468f5155289Sbellard 
2469f516511eSPeter Maydell     /* Check that our initial calculation of the auxv length matches how much
2470f516511eSPeter Maydell      * we actually put into it.
2471f516511eSPeter Maydell      */
2472f516511eSPeter Maydell     assert(info->auxv_len == u_auxv - info->saved_auxv);
2473edf8e2afSMika Westerberg 
24747c4ee5bcSRichard Henderson     put_user_ual(argc, u_argc);
24757c4ee5bcSRichard Henderson 
24767c4ee5bcSRichard Henderson     p = info->arg_strings;
24777c4ee5bcSRichard Henderson     for (i = 0; i < argc; ++i) {
24787c4ee5bcSRichard Henderson         put_user_ual(p, u_argv);
24797c4ee5bcSRichard Henderson         u_argv += n;
24807c4ee5bcSRichard Henderson         p += target_strlen(p) + 1;
24817c4ee5bcSRichard Henderson     }
24827c4ee5bcSRichard Henderson     put_user_ual(0, u_argv);
24837c4ee5bcSRichard Henderson 
24847c4ee5bcSRichard Henderson     p = info->env_strings;
24857c4ee5bcSRichard Henderson     for (i = 0; i < envc; ++i) {
24867c4ee5bcSRichard Henderson         put_user_ual(p, u_envp);
24877c4ee5bcSRichard Henderson         u_envp += n;
24887c4ee5bcSRichard Henderson         p += target_strlen(p) + 1;
24897c4ee5bcSRichard Henderson     }
24907c4ee5bcSRichard Henderson     put_user_ual(0, u_envp);
24917c4ee5bcSRichard Henderson 
249231e31b8aSbellard     return sp;
249331e31b8aSbellard }
249431e31b8aSbellard 
2495f5ef0e51SRichard Henderson #if defined(HI_COMMPAGE)
2496eee816c0SRichard Henderson #define LO_COMMPAGE -1
2497f5ef0e51SRichard Henderson #elif defined(LO_COMMPAGE)
249866346fafSRichard Henderson #define HI_COMMPAGE 0
2499f5ef0e51SRichard Henderson #else
2500f5ef0e51SRichard Henderson #define HI_COMMPAGE 0
2501eee816c0SRichard Henderson #define LO_COMMPAGE -1
2502d461b73eSRichard Henderson #ifndef INIT_GUEST_COMMPAGE
2503ee947430SAlex Bennée #define init_guest_commpage() true
2504ee947430SAlex Bennée #endif
2505d461b73eSRichard Henderson #endif
2506ee947430SAlex Bennée 
2507ee947430SAlex Bennée static void pgb_fail_in_use(const char *image_name)
2508ee947430SAlex Bennée {
2509ee947430SAlex Bennée     error_report("%s: requires virtual address space that is in use "
2510ee947430SAlex Bennée                  "(omit the -B option or choose a different value)",
2511ee947430SAlex Bennée                  image_name);
2512ee947430SAlex Bennée     exit(EXIT_FAILURE);
2513ee947430SAlex Bennée }
2514ee947430SAlex Bennée 
2515ee947430SAlex Bennée static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr,
2516ee947430SAlex Bennée                                 abi_ulong guest_hiaddr, long align)
2517ee947430SAlex Bennée {
2518ee947430SAlex Bennée     const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
2519ee947430SAlex Bennée     void *addr, *test;
2520ee947430SAlex Bennée 
2521ee947430SAlex Bennée     if (!QEMU_IS_ALIGNED(guest_base, align)) {
25225ca870b9SRichard Henderson         fprintf(stderr, "Requested guest base %p does not satisfy "
2523ee947430SAlex Bennée                 "host minimum alignment (0x%lx)\n",
25245ca870b9SRichard Henderson                 (void *)guest_base, align);
2525ee947430SAlex Bennée         exit(EXIT_FAILURE);
2526ee947430SAlex Bennée     }
2527ee947430SAlex Bennée 
2528ee947430SAlex Bennée     /* Sanity check the guest binary. */
2529ee947430SAlex Bennée     if (reserved_va) {
2530ee947430SAlex Bennée         if (guest_hiaddr > reserved_va) {
2531ee947430SAlex Bennée             error_report("%s: requires more than reserved virtual "
2532ee947430SAlex Bennée                          "address space (0x%" PRIx64 " > 0x%lx)",
253395059f9cSRichard Henderson                          image_name, (uint64_t)guest_hiaddr, reserved_va);
2534ee947430SAlex Bennée             exit(EXIT_FAILURE);
2535ee947430SAlex Bennée         }
2536ee947430SAlex Bennée     } else {
2537a932eec4SAlex Bennée #if HOST_LONG_BITS < TARGET_ABI_BITS
2538ee947430SAlex Bennée         if ((guest_hiaddr - guest_base) > ~(uintptr_t)0) {
2539ee947430SAlex Bennée             error_report("%s: requires more virtual address space "
2540ee947430SAlex Bennée                          "than the host can provide (0x%" PRIx64 ")",
2541a3a67f54SRichard Henderson                          image_name, (uint64_t)guest_hiaddr + 1 - guest_base);
2542ee947430SAlex Bennée             exit(EXIT_FAILURE);
2543ee947430SAlex Bennée         }
2544a932eec4SAlex Bennée #endif
2545ee947430SAlex Bennée     }
2546ee947430SAlex Bennée 
2547ee947430SAlex Bennée     /*
2548ee947430SAlex Bennée      * Expand the allocation to the entire reserved_va.
2549ee947430SAlex Bennée      * Exclude the mmap_min_addr hole.
2550ee947430SAlex Bennée      */
2551ee947430SAlex Bennée     if (reserved_va) {
2552ee947430SAlex Bennée         guest_loaddr = (guest_base >= mmap_min_addr ? 0
2553ee947430SAlex Bennée                         : mmap_min_addr - guest_base);
255495059f9cSRichard Henderson         guest_hiaddr = reserved_va;
2555ee947430SAlex Bennée     }
2556ee947430SAlex Bennée 
2557ee947430SAlex Bennée     /* Reserve the address space for the binary, or reserved_va. */
25583e8f1628SRichard Henderson     test = g2h_untagged(guest_loaddr);
2559a3a67f54SRichard Henderson     addr = mmap(test, guest_hiaddr - guest_loaddr + 1, PROT_NONE, flags, -1, 0);
2560ee947430SAlex Bennée     if (test != addr) {
2561ee947430SAlex Bennée         pgb_fail_in_use(image_name);
2562ee947430SAlex Bennée     }
2563e7588237SAlex Bennée     qemu_log_mask(CPU_LOG_PAGE,
2564a3a67f54SRichard Henderson                   "%s: base @ %p for %" PRIu64 " bytes\n",
2565a3a67f54SRichard Henderson                   __func__, addr, (uint64_t)guest_hiaddr - guest_loaddr + 1);
2566ee947430SAlex Bennée }
2567ee947430SAlex Bennée 
2568ad592e37SAlex Bennée /**
2569ad592e37SAlex Bennée  * pgd_find_hole_fallback: potential mmap address
2570ad592e37SAlex Bennée  * @guest_size: size of available space
2571ad592e37SAlex Bennée  * @brk: location of break
2572ad592e37SAlex Bennée  * @align: memory alignment
2573ad592e37SAlex Bennée  *
2574ad592e37SAlex Bennée  * This is a fallback method for finding a hole in the host address
2575ad592e37SAlex Bennée  * space if we don't have the benefit of being able to access
2576ad592e37SAlex Bennée  * /proc/self/map. It can potentially take a very long time as we can
2577ad592e37SAlex Bennée  * only dumbly iterate up the host address space seeing if the
2578ad592e37SAlex Bennée  * allocation would work.
2579ad592e37SAlex Bennée  */
25805c3e87f3SAlex Bennée static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk,
25815c3e87f3SAlex Bennée                                         long align, uintptr_t offset)
2582ad592e37SAlex Bennée {
2583ad592e37SAlex Bennée     uintptr_t base;
2584ad592e37SAlex Bennée 
2585ad592e37SAlex Bennée     /* Start (aligned) at the bottom and work our way up */
2586ad592e37SAlex Bennée     base = ROUND_UP(mmap_min_addr, align);
2587ad592e37SAlex Bennée 
2588ad592e37SAlex Bennée     while (true) {
2589ad592e37SAlex Bennée         uintptr_t align_start, end;
2590ad592e37SAlex Bennée         align_start = ROUND_UP(base, align);
25915c3e87f3SAlex Bennée         end = align_start + guest_size + offset;
2592ad592e37SAlex Bennée 
2593ad592e37SAlex Bennée         /* if brk is anywhere in the range give ourselves some room to grow. */
2594ad592e37SAlex Bennée         if (align_start <= brk && brk < end) {
2595ad592e37SAlex Bennée             base = brk + (16 * MiB);
2596ad592e37SAlex Bennée             continue;
2597ad592e37SAlex Bennée         } else if (align_start + guest_size < align_start) {
2598ad592e37SAlex Bennée             /* we have run out of space */
2599ad592e37SAlex Bennée             return -1;
2600ad592e37SAlex Bennée         } else {
26012667e069SAlex Bennée             int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE |
26022667e069SAlex Bennée                 MAP_FIXED_NOREPLACE;
2603ad592e37SAlex Bennée             void * mmap_start = mmap((void *) align_start, guest_size,
2604ad592e37SAlex Bennée                                      PROT_NONE, flags, -1, 0);
2605ad592e37SAlex Bennée             if (mmap_start != MAP_FAILED) {
26067e588fbcSVincent Fazio                 munmap(mmap_start, guest_size);
2607934eed51SVincent Fazio                 if (mmap_start == (void *) align_start) {
2608e7588237SAlex Bennée                     qemu_log_mask(CPU_LOG_PAGE,
2609e7588237SAlex Bennée                                   "%s: base @ %p for %" PRIdPTR" bytes\n",
2610e7588237SAlex Bennée                                   __func__, mmap_start + offset, guest_size);
26115c3e87f3SAlex Bennée                     return (uintptr_t) mmap_start + offset;
2612ad592e37SAlex Bennée                 }
26132667e069SAlex Bennée             }
2614ad592e37SAlex Bennée             base += qemu_host_page_size;
2615ad592e37SAlex Bennée         }
2616ad592e37SAlex Bennée     }
2617ad592e37SAlex Bennée }
2618ad592e37SAlex Bennée 
2619ee947430SAlex Bennée /* Return value for guest_base, or -1 if no hole found. */
2620ee947430SAlex Bennée static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size,
26215c3e87f3SAlex Bennée                                long align, uintptr_t offset)
2622ee947430SAlex Bennée {
2623ee947430SAlex Bennée     GSList *maps, *iter;
2624ee947430SAlex Bennée     uintptr_t this_start, this_end, next_start, brk;
2625ee947430SAlex Bennée     intptr_t ret = -1;
2626ee947430SAlex Bennée 
2627ee947430SAlex Bennée     assert(QEMU_IS_ALIGNED(guest_loaddr, align));
2628ee947430SAlex Bennée 
2629ee947430SAlex Bennée     maps = read_self_maps();
2630ee947430SAlex Bennée 
2631ee947430SAlex Bennée     /* Read brk after we've read the maps, which will malloc. */
2632ee947430SAlex Bennée     brk = (uintptr_t)sbrk(0);
2633ee947430SAlex Bennée 
2634ad592e37SAlex Bennée     if (!maps) {
2635190674f3SAlex Bennée         return pgd_find_hole_fallback(guest_size, brk, align, offset);
2636ad592e37SAlex Bennée     }
2637ad592e37SAlex Bennée 
2638ee947430SAlex Bennée     /* The first hole is before the first map entry. */
2639ee947430SAlex Bennée     this_start = mmap_min_addr;
2640ee947430SAlex Bennée 
2641ee947430SAlex Bennée     for (iter = maps; iter;
2642ee947430SAlex Bennée          this_start = next_start, iter = g_slist_next(iter)) {
2643ee947430SAlex Bennée         uintptr_t align_start, hole_size;
2644ee947430SAlex Bennée 
2645ee947430SAlex Bennée         this_end = ((MapInfo *)iter->data)->start;
2646ee947430SAlex Bennée         next_start = ((MapInfo *)iter->data)->end;
26475c3e87f3SAlex Bennée         align_start = ROUND_UP(this_start + offset, align);
2648ee947430SAlex Bennée 
2649ee947430SAlex Bennée         /* Skip holes that are too small. */
2650ee947430SAlex Bennée         if (align_start >= this_end) {
2651ee947430SAlex Bennée             continue;
2652ee947430SAlex Bennée         }
2653ee947430SAlex Bennée         hole_size = this_end - align_start;
2654ee947430SAlex Bennée         if (hole_size < guest_size) {
2655ee947430SAlex Bennée             continue;
2656ee947430SAlex Bennée         }
2657ee947430SAlex Bennée 
2658ee947430SAlex Bennée         /* If this hole contains brk, give ourselves some room to grow. */
2659ee947430SAlex Bennée         if (this_start <= brk && brk < this_end) {
2660ee947430SAlex Bennée             hole_size -= guest_size;
2661ee947430SAlex Bennée             if (sizeof(uintptr_t) == 8 && hole_size >= 1 * GiB) {
2662ee947430SAlex Bennée                 align_start += 1 * GiB;
2663ee947430SAlex Bennée             } else if (hole_size >= 16 * MiB) {
2664ee947430SAlex Bennée                 align_start += 16 * MiB;
2665ee947430SAlex Bennée             } else {
2666ee947430SAlex Bennée                 align_start = (this_end - guest_size) & -align;
2667ee947430SAlex Bennée                 if (align_start < this_start) {
2668ee947430SAlex Bennée                     continue;
2669ee947430SAlex Bennée                 }
2670ee947430SAlex Bennée             }
2671ee947430SAlex Bennée         }
2672ee947430SAlex Bennée 
2673ee947430SAlex Bennée         /* Record the lowest successful match. */
2674ee947430SAlex Bennée         if (ret < 0) {
2675190674f3SAlex Bennée             ret = align_start;
2676ee947430SAlex Bennée         }
2677ee947430SAlex Bennée         /* If this hole contains the identity map, select it. */
2678ee947430SAlex Bennée         if (align_start <= guest_loaddr &&
2679ee947430SAlex Bennée             guest_loaddr + guest_size <= this_end) {
2680ee947430SAlex Bennée             ret = 0;
2681ee947430SAlex Bennée         }
2682ee947430SAlex Bennée         /* If this hole ends above the identity map, stop looking. */
2683ee947430SAlex Bennée         if (this_end >= guest_loaddr) {
2684ee947430SAlex Bennée             break;
2685ee947430SAlex Bennée         }
2686ee947430SAlex Bennée     }
2687ee947430SAlex Bennée     free_self_maps(maps);
2688ee947430SAlex Bennée 
2689e7588237SAlex Bennée     if (ret != -1) {
2690e7588237SAlex Bennée         qemu_log_mask(CPU_LOG_PAGE, "%s: base @ %" PRIxPTR
2691e7588237SAlex Bennée                       " for %" PRIuPTR " bytes\n",
2692e7588237SAlex Bennée                       __func__, ret, guest_size);
2693e7588237SAlex Bennée     }
2694e7588237SAlex Bennée 
2695ee947430SAlex Bennée     return ret;
2696ee947430SAlex Bennée }
2697ee947430SAlex Bennée 
2698ee947430SAlex Bennée static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
2699ee947430SAlex Bennée                        abi_ulong orig_hiaddr, long align)
2700ee947430SAlex Bennée {
2701ee947430SAlex Bennée     uintptr_t loaddr = orig_loaddr;
2702ee947430SAlex Bennée     uintptr_t hiaddr = orig_hiaddr;
27035c3e87f3SAlex Bennée     uintptr_t offset = 0;
2704ee947430SAlex Bennée     uintptr_t addr;
2705ee947430SAlex Bennée 
2706ee947430SAlex Bennée     if (hiaddr != orig_hiaddr) {
2707ee947430SAlex Bennée         error_report("%s: requires virtual address space that the "
2708ee947430SAlex Bennée                      "host cannot provide (0x%" PRIx64 ")",
2709a3a67f54SRichard Henderson                      image_name, (uint64_t)orig_hiaddr + 1);
2710ee947430SAlex Bennée         exit(EXIT_FAILURE);
2711ee947430SAlex Bennée     }
2712ee947430SAlex Bennée 
2713ee947430SAlex Bennée     loaddr &= -align;
271466346fafSRichard Henderson     if (HI_COMMPAGE) {
2715ee947430SAlex Bennée         /*
2716ee947430SAlex Bennée          * Extend the allocation to include the commpage.
27175c3e87f3SAlex Bennée          * For a 64-bit host, this is just 4GiB; for a 32-bit host we
27185c3e87f3SAlex Bennée          * need to ensure there is space bellow the guest_base so we
27195c3e87f3SAlex Bennée          * can map the commpage in the place needed when the address
27205c3e87f3SAlex Bennée          * arithmetic wraps around.
2721ee947430SAlex Bennée          */
2722ee947430SAlex Bennée         if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
2723a3a67f54SRichard Henderson             hiaddr = UINT32_MAX;
2724ee947430SAlex Bennée         } else {
272566346fafSRichard Henderson             offset = -(HI_COMMPAGE & -align);
2726ee947430SAlex Bennée         }
2727eee816c0SRichard Henderson     } else if (LO_COMMPAGE != -1) {
2728f5ef0e51SRichard Henderson         loaddr = MIN(loaddr, LO_COMMPAGE & -align);
2729ee947430SAlex Bennée     }
2730ee947430SAlex Bennée 
2731a3a67f54SRichard Henderson     addr = pgb_find_hole(loaddr, hiaddr - loaddr + 1, align, offset);
2732ee947430SAlex Bennée     if (addr == -1) {
2733ee947430SAlex Bennée         /*
273466346fafSRichard Henderson          * If HI_COMMPAGE, there *might* be a non-consecutive allocation
2735ee947430SAlex Bennée          * that can satisfy both.  But as the normal arm32 link base address
2736ee947430SAlex Bennée          * is ~32k, and we extend down to include the commpage, making the
2737ee947430SAlex Bennée          * overhead only ~96k, this is unlikely.
2738ee947430SAlex Bennée          */
2739ee947430SAlex Bennée         error_report("%s: Unable to allocate %#zx bytes of "
2740ee947430SAlex Bennée                      "virtual address space", image_name,
2741ee947430SAlex Bennée                      (size_t)(hiaddr - loaddr));
2742ee947430SAlex Bennée         exit(EXIT_FAILURE);
2743ee947430SAlex Bennée     }
2744ee947430SAlex Bennée 
2745ee947430SAlex Bennée     guest_base = addr;
2746e7588237SAlex Bennée 
2747e7588237SAlex Bennée     qemu_log_mask(CPU_LOG_PAGE, "%s: base @ %"PRIxPTR" for %" PRIuPTR" bytes\n",
2748e7588237SAlex Bennée                   __func__, addr, hiaddr - loaddr);
2749ee947430SAlex Bennée }
2750ee947430SAlex Bennée 
2751ee947430SAlex Bennée static void pgb_dynamic(const char *image_name, long align)
2752ee947430SAlex Bennée {
2753ee947430SAlex Bennée     /*
2754ee947430SAlex Bennée      * The executable is dynamic and does not require a fixed address.
2755ee947430SAlex Bennée      * All we need is a commpage that satisfies align.
2756ee947430SAlex Bennée      * If we do not need a commpage, leave guest_base == 0.
2757ee947430SAlex Bennée      */
275866346fafSRichard Henderson     if (HI_COMMPAGE) {
2759ee947430SAlex Bennée         uintptr_t addr, commpage;
2760ee947430SAlex Bennée 
2761ee947430SAlex Bennée         /* 64-bit hosts should have used reserved_va. */
2762ee947430SAlex Bennée         assert(sizeof(uintptr_t) == 4);
2763ee947430SAlex Bennée 
2764ee947430SAlex Bennée         /*
2765ee947430SAlex Bennée          * By putting the commpage at the first hole, that puts guest_base
2766ee947430SAlex Bennée          * just above that, and maximises the positive guest addresses.
2767ee947430SAlex Bennée          */
276866346fafSRichard Henderson         commpage = HI_COMMPAGE & -align;
27695c3e87f3SAlex Bennée         addr = pgb_find_hole(commpage, -commpage, align, 0);
2770ee947430SAlex Bennée         assert(addr != -1);
2771ee947430SAlex Bennée         guest_base = addr;
2772ee947430SAlex Bennée     }
2773ee947430SAlex Bennée }
2774ee947430SAlex Bennée 
2775ee947430SAlex Bennée static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr,
2776ee947430SAlex Bennée                             abi_ulong guest_hiaddr, long align)
2777ee947430SAlex Bennée {
2778c1f6ad79SAlex Bennée     int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
2779ee947430SAlex Bennée     void *addr, *test;
2780ee947430SAlex Bennée 
2781ee947430SAlex Bennée     if (guest_hiaddr > reserved_va) {
2782ee947430SAlex Bennée         error_report("%s: requires more than reserved virtual "
2783ee947430SAlex Bennée                      "address space (0x%" PRIx64 " > 0x%lx)",
278495059f9cSRichard Henderson                      image_name, (uint64_t)guest_hiaddr, reserved_va);
2785ee947430SAlex Bennée         exit(EXIT_FAILURE);
2786ee947430SAlex Bennée     }
2787ee947430SAlex Bennée 
2788ee947430SAlex Bennée     /* Widen the "image" to the entire reserved address space. */
2789ee947430SAlex Bennée     pgb_static(image_name, 0, reserved_va, align);
2790ee947430SAlex Bennée 
27912667e069SAlex Bennée     /* osdep.h defines this as 0 if it's missing */
2792c1f6ad79SAlex Bennée     flags |= MAP_FIXED_NOREPLACE;
2793c1f6ad79SAlex Bennée 
2794ee947430SAlex Bennée     /* Reserve the memory on the host. */
2795ee947430SAlex Bennée     assert(guest_base != 0);
27963e8f1628SRichard Henderson     test = g2h_untagged(0);
279795059f9cSRichard Henderson     addr = mmap(test, reserved_va + 1, PROT_NONE, flags, -1, 0);
2798fb730c86SAlex Bennée     if (addr == MAP_FAILED || addr != test) {
2799ee947430SAlex Bennée         error_report("Unable to reserve 0x%lx bytes of virtual address "
2800fb730c86SAlex Bennée                      "space at %p (%s) for use as guest address space (check your "
2801*f101c25cSAndrew Jeffery                      "virtual memory ulimit setting, mmap_min_addr or reserve less "
280295059f9cSRichard Henderson                      "using -R option)", reserved_va + 1, test, strerror(errno));
2803ee947430SAlex Bennée         exit(EXIT_FAILURE);
2804ee947430SAlex Bennée     }
2805e7588237SAlex Bennée 
2806e7588237SAlex Bennée     qemu_log_mask(CPU_LOG_PAGE, "%s: base @ %p for %lu bytes\n",
280795059f9cSRichard Henderson                   __func__, addr, reserved_va + 1);
2808ee947430SAlex Bennée }
2809ee947430SAlex Bennée 
2810ee947430SAlex Bennée void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
2811ee947430SAlex Bennée                       abi_ulong guest_hiaddr)
2812dce10401SMeador Inge {
281330ab9ef2SRichard Henderson     /* In order to use host shmat, we must be able to honor SHMLBA.  */
2814ee947430SAlex Bennée     uintptr_t align = MAX(SHMLBA, qemu_host_page_size);
2815dce10401SMeador Inge 
2816ee947430SAlex Bennée     if (have_guest_base) {
2817ee947430SAlex Bennée         pgb_have_guest_base(image_name, guest_loaddr, guest_hiaddr, align);
2818ee947430SAlex Bennée     } else if (reserved_va) {
2819ee947430SAlex Bennée         pgb_reserved_va(image_name, guest_loaddr, guest_hiaddr, align);
2820ee947430SAlex Bennée     } else if (guest_loaddr) {
2821ee947430SAlex Bennée         pgb_static(image_name, guest_loaddr, guest_hiaddr, align);
2822293f2060SLuke Shumaker     } else {
2823ee947430SAlex Bennée         pgb_dynamic(image_name, align);
2824806d1021SMeador Inge     }
2825806d1021SMeador Inge 
2826ee947430SAlex Bennée     /* Reserve and initialize the commpage. */
2827ee947430SAlex Bennée     if (!init_guest_commpage()) {
2828ee947430SAlex Bennée         /*
2829ee947430SAlex Bennée          * With have_guest_base, the user has selected the address and
2830ee947430SAlex Bennée          * we are trying to work with that.  Otherwise, we have selected
2831ee947430SAlex Bennée          * free space and init_guest_commpage must succeeded.
28327ad75eeaSLuke Shumaker          */
2833ee947430SAlex Bennée         assert(have_guest_base);
2834ee947430SAlex Bennée         pgb_fail_in_use(image_name);
2835dce10401SMeador Inge     }
2836dce10401SMeador Inge 
2837ee947430SAlex Bennée     assert(QEMU_IS_ALIGNED(guest_base, align));
2838ee947430SAlex Bennée     qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space "
2839ee947430SAlex Bennée                   "@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
2840dce10401SMeador Inge }
2841dce10401SMeador Inge 
284283f990ebSRichard Henderson enum {
284383f990ebSRichard Henderson     /* The string "GNU\0" as a magic number. */
284483f990ebSRichard Henderson     GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
284583f990ebSRichard Henderson     NOTE_DATA_SZ = 1 * KiB,
284683f990ebSRichard Henderson     NOTE_NAME_SZ = 4,
284783f990ebSRichard Henderson     ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
284883f990ebSRichard Henderson };
284983f990ebSRichard Henderson 
285083f990ebSRichard Henderson /*
285183f990ebSRichard Henderson  * Process a single gnu_property entry.
285283f990ebSRichard Henderson  * Return false for error.
285383f990ebSRichard Henderson  */
285483f990ebSRichard Henderson static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
285583f990ebSRichard Henderson                                struct image_info *info, bool have_prev_type,
285683f990ebSRichard Henderson                                uint32_t *prev_type, Error **errp)
285783f990ebSRichard Henderson {
285883f990ebSRichard Henderson     uint32_t pr_type, pr_datasz, step;
285983f990ebSRichard Henderson 
286083f990ebSRichard Henderson     if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
286183f990ebSRichard Henderson         goto error_data;
286283f990ebSRichard Henderson     }
286383f990ebSRichard Henderson     datasz -= *off;
286483f990ebSRichard Henderson     data += *off / sizeof(uint32_t);
286583f990ebSRichard Henderson 
286683f990ebSRichard Henderson     if (datasz < 2 * sizeof(uint32_t)) {
286783f990ebSRichard Henderson         goto error_data;
286883f990ebSRichard Henderson     }
286983f990ebSRichard Henderson     pr_type = data[0];
287083f990ebSRichard Henderson     pr_datasz = data[1];
287183f990ebSRichard Henderson     data += 2;
287283f990ebSRichard Henderson     datasz -= 2 * sizeof(uint32_t);
287383f990ebSRichard Henderson     step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
287483f990ebSRichard Henderson     if (step > datasz) {
287583f990ebSRichard Henderson         goto error_data;
287683f990ebSRichard Henderson     }
287783f990ebSRichard Henderson 
287883f990ebSRichard Henderson     /* Properties are supposed to be unique and sorted on pr_type. */
287983f990ebSRichard Henderson     if (have_prev_type && pr_type <= *prev_type) {
288083f990ebSRichard Henderson         if (pr_type == *prev_type) {
288183f990ebSRichard Henderson             error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
288283f990ebSRichard Henderson         } else {
288383f990ebSRichard Henderson             error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
288483f990ebSRichard Henderson         }
288583f990ebSRichard Henderson         return false;
288683f990ebSRichard Henderson     }
288783f990ebSRichard Henderson     *prev_type = pr_type;
288883f990ebSRichard Henderson 
288983f990ebSRichard Henderson     if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
289083f990ebSRichard Henderson         return false;
289183f990ebSRichard Henderson     }
289283f990ebSRichard Henderson 
289383f990ebSRichard Henderson     *off += 2 * sizeof(uint32_t) + step;
289483f990ebSRichard Henderson     return true;
289583f990ebSRichard Henderson 
289683f990ebSRichard Henderson  error_data:
289783f990ebSRichard Henderson     error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
289883f990ebSRichard Henderson     return false;
289983f990ebSRichard Henderson }
290083f990ebSRichard Henderson 
290183f990ebSRichard Henderson /* Process NT_GNU_PROPERTY_TYPE_0. */
290283f990ebSRichard Henderson static bool parse_elf_properties(int image_fd,
290383f990ebSRichard Henderson                                  struct image_info *info,
290483f990ebSRichard Henderson                                  const struct elf_phdr *phdr,
290583f990ebSRichard Henderson                                  char bprm_buf[BPRM_BUF_SIZE],
290683f990ebSRichard Henderson                                  Error **errp)
290783f990ebSRichard Henderson {
290883f990ebSRichard Henderson     union {
290983f990ebSRichard Henderson         struct elf_note nhdr;
291083f990ebSRichard Henderson         uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
291183f990ebSRichard Henderson     } note;
291283f990ebSRichard Henderson 
291383f990ebSRichard Henderson     int n, off, datasz;
291483f990ebSRichard Henderson     bool have_prev_type;
291583f990ebSRichard Henderson     uint32_t prev_type;
291683f990ebSRichard Henderson 
291783f990ebSRichard Henderson     /* Unless the arch requires properties, ignore them. */
291883f990ebSRichard Henderson     if (!ARCH_USE_GNU_PROPERTY) {
291983f990ebSRichard Henderson         return true;
292083f990ebSRichard Henderson     }
292183f990ebSRichard Henderson 
292283f990ebSRichard Henderson     /* If the properties are crazy large, that's too bad. */
292383f990ebSRichard Henderson     n = phdr->p_filesz;
292483f990ebSRichard Henderson     if (n > sizeof(note)) {
292583f990ebSRichard Henderson         error_setg(errp, "PT_GNU_PROPERTY too large");
292683f990ebSRichard Henderson         return false;
292783f990ebSRichard Henderson     }
292883f990ebSRichard Henderson     if (n < sizeof(note.nhdr)) {
292983f990ebSRichard Henderson         error_setg(errp, "PT_GNU_PROPERTY too small");
293083f990ebSRichard Henderson         return false;
293183f990ebSRichard Henderson     }
293283f990ebSRichard Henderson 
293383f990ebSRichard Henderson     if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
293483f990ebSRichard Henderson         memcpy(&note, bprm_buf + phdr->p_offset, n);
293583f990ebSRichard Henderson     } else {
293683f990ebSRichard Henderson         ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
293783f990ebSRichard Henderson         if (len != n) {
293883f990ebSRichard Henderson             error_setg_errno(errp, errno, "Error reading file header");
293983f990ebSRichard Henderson             return false;
294083f990ebSRichard Henderson         }
294183f990ebSRichard Henderson     }
294283f990ebSRichard Henderson 
294383f990ebSRichard Henderson     /*
294483f990ebSRichard Henderson      * The contents of a valid PT_GNU_PROPERTY is a sequence
294583f990ebSRichard Henderson      * of uint32_t -- swap them all now.
294683f990ebSRichard Henderson      */
294783f990ebSRichard Henderson #ifdef BSWAP_NEEDED
294883f990ebSRichard Henderson     for (int i = 0; i < n / 4; i++) {
294983f990ebSRichard Henderson         bswap32s(note.data + i);
295083f990ebSRichard Henderson     }
295183f990ebSRichard Henderson #endif
295283f990ebSRichard Henderson 
295383f990ebSRichard Henderson     /*
295483f990ebSRichard Henderson      * Note that nhdr is 3 words, and that the "name" described by namesz
295583f990ebSRichard Henderson      * immediately follows nhdr and is thus at the 4th word.  Further, all
295683f990ebSRichard Henderson      * of the inputs to the kernel's round_up are multiples of 4.
295783f990ebSRichard Henderson      */
295883f990ebSRichard Henderson     if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
295983f990ebSRichard Henderson         note.nhdr.n_namesz != NOTE_NAME_SZ ||
296083f990ebSRichard Henderson         note.data[3] != GNU0_MAGIC) {
296183f990ebSRichard Henderson         error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
296283f990ebSRichard Henderson         return false;
296383f990ebSRichard Henderson     }
296483f990ebSRichard Henderson     off = sizeof(note.nhdr) + NOTE_NAME_SZ;
296583f990ebSRichard Henderson 
296683f990ebSRichard Henderson     datasz = note.nhdr.n_descsz + off;
296783f990ebSRichard Henderson     if (datasz > n) {
296883f990ebSRichard Henderson         error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
296983f990ebSRichard Henderson         return false;
297083f990ebSRichard Henderson     }
297183f990ebSRichard Henderson 
297283f990ebSRichard Henderson     have_prev_type = false;
297383f990ebSRichard Henderson     prev_type = 0;
297483f990ebSRichard Henderson     while (1) {
297583f990ebSRichard Henderson         if (off == datasz) {
297683f990ebSRichard Henderson             return true;  /* end, exit ok */
297783f990ebSRichard Henderson         }
297883f990ebSRichard Henderson         if (!parse_elf_property(note.data, &off, datasz, info,
297983f990ebSRichard Henderson                                 have_prev_type, &prev_type, errp)) {
298083f990ebSRichard Henderson             return false;
298183f990ebSRichard Henderson         }
298283f990ebSRichard Henderson         have_prev_type = true;
298383f990ebSRichard Henderson     }
298483f990ebSRichard Henderson }
298583f990ebSRichard Henderson 
29868e62a717SRichard Henderson /* Load an ELF image into the address space.
298731e31b8aSbellard 
29888e62a717SRichard Henderson    IMAGE_NAME is the filename of the image, to use in error messages.
29898e62a717SRichard Henderson    IMAGE_FD is the open file descriptor for the image.
29908e62a717SRichard Henderson 
29918e62a717SRichard Henderson    BPRM_BUF is a copy of the beginning of the file; this of course
29928e62a717SRichard Henderson    contains the elf file header at offset 0.  It is assumed that this
29938e62a717SRichard Henderson    buffer is sufficiently aligned to present no problems to the host
29948e62a717SRichard Henderson    in accessing data at aligned offsets within the buffer.
29958e62a717SRichard Henderson 
29968e62a717SRichard Henderson    On return: INFO values will be filled in, as necessary or available.  */
29978e62a717SRichard Henderson 
29988e62a717SRichard Henderson static void load_elf_image(const char *image_name, int image_fd,
2999bf858897SRichard Henderson                            struct image_info *info, char **pinterp_name,
30009955ffacSRichard Henderson                            char bprm_buf[BPRM_BUF_SIZE])
300131e31b8aSbellard {
30028e62a717SRichard Henderson     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
30038e62a717SRichard Henderson     struct elf_phdr *phdr;
30048e62a717SRichard Henderson     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
3005e8384b37SRichard Henderson     int i, retval, prot_exec;
3006c7f17e7bSRichard Henderson     Error *err = NULL;
300731e31b8aSbellard 
30088e62a717SRichard Henderson     /* First of all, some simple consistency checks */
30098e62a717SRichard Henderson     if (!elf_check_ident(ehdr)) {
3010c7f17e7bSRichard Henderson         error_setg(&err, "Invalid ELF image for this architecture");
30118e62a717SRichard Henderson         goto exit_errmsg;
30128e62a717SRichard Henderson     }
30138e62a717SRichard Henderson     bswap_ehdr(ehdr);
30148e62a717SRichard Henderson     if (!elf_check_ehdr(ehdr)) {
3015c7f17e7bSRichard Henderson         error_setg(&err, "Invalid ELF image for this architecture");
30168e62a717SRichard Henderson         goto exit_errmsg;
301731e31b8aSbellard     }
301831e31b8aSbellard 
30198e62a717SRichard Henderson     i = ehdr->e_phnum * sizeof(struct elf_phdr);
30208e62a717SRichard Henderson     if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
30218e62a717SRichard Henderson         phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
30229955ffacSRichard Henderson     } else {
30238e62a717SRichard Henderson         phdr = (struct elf_phdr *) alloca(i);
30248e62a717SRichard Henderson         retval = pread(image_fd, phdr, i, ehdr->e_phoff);
30259955ffacSRichard Henderson         if (retval != i) {
30268e62a717SRichard Henderson             goto exit_read;
30279955ffacSRichard Henderson         }
302831e31b8aSbellard     }
30298e62a717SRichard Henderson     bswap_phdr(phdr, ehdr->e_phnum);
303009bfb054Sbellard 
30311af02e83SMike Frysinger     info->nsegs = 0;
30321af02e83SMike Frysinger     info->pt_dynamic_addr = 0;
30331af02e83SMike Frysinger 
303498c1076cSAlex Bennée     mmap_lock();
303598c1076cSAlex Bennée 
30368a1a5274SRichard Henderson     /*
30378a1a5274SRichard Henderson      * Find the maximum size of the image and allocate an appropriate
30388a1a5274SRichard Henderson      * amount of memory to handle that.  Locate the interpreter, if any.
30398a1a5274SRichard Henderson      */
3040682674b8SRichard Henderson     loaddr = -1, hiaddr = 0;
304133143c44SLaurent Vivier     info->alignment = 0;
3042872f3d04SRichard Henderson     info->exec_stack = EXSTACK_DEFAULT;
30438e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; ++i) {
30444d9d535aSRichard Henderson         struct elf_phdr *eppnt = phdr + i;
30454d9d535aSRichard Henderson         if (eppnt->p_type == PT_LOAD) {
30464d9d535aSRichard Henderson             abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
3047682674b8SRichard Henderson             if (a < loaddr) {
3048682674b8SRichard Henderson                 loaddr = a;
3049682674b8SRichard Henderson             }
3050a3a67f54SRichard Henderson             a = eppnt->p_vaddr + eppnt->p_memsz - 1;
3051682674b8SRichard Henderson             if (a > hiaddr) {
3052682674b8SRichard Henderson                 hiaddr = a;
3053682674b8SRichard Henderson             }
30541af02e83SMike Frysinger             ++info->nsegs;
30554d9d535aSRichard Henderson             info->alignment |= eppnt->p_align;
30568a1a5274SRichard Henderson         } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
30578a1a5274SRichard Henderson             g_autofree char *interp_name = NULL;
30588a1a5274SRichard Henderson 
30598a1a5274SRichard Henderson             if (*pinterp_name) {
3060c7f17e7bSRichard Henderson                 error_setg(&err, "Multiple PT_INTERP entries");
30618a1a5274SRichard Henderson                 goto exit_errmsg;
30628a1a5274SRichard Henderson             }
3063c7f17e7bSRichard Henderson 
30648a1a5274SRichard Henderson             interp_name = g_malloc(eppnt->p_filesz);
30658a1a5274SRichard Henderson 
30668a1a5274SRichard Henderson             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
30678a1a5274SRichard Henderson                 memcpy(interp_name, bprm_buf + eppnt->p_offset,
30688a1a5274SRichard Henderson                        eppnt->p_filesz);
30698a1a5274SRichard Henderson             } else {
30708a1a5274SRichard Henderson                 retval = pread(image_fd, interp_name, eppnt->p_filesz,
30718a1a5274SRichard Henderson                                eppnt->p_offset);
30728a1a5274SRichard Henderson                 if (retval != eppnt->p_filesz) {
3073c7f17e7bSRichard Henderson                     goto exit_read;
30748a1a5274SRichard Henderson                 }
30758a1a5274SRichard Henderson             }
30768a1a5274SRichard Henderson             if (interp_name[eppnt->p_filesz - 1] != 0) {
3077c7f17e7bSRichard Henderson                 error_setg(&err, "Invalid PT_INTERP entry");
30788a1a5274SRichard Henderson                 goto exit_errmsg;
30798a1a5274SRichard Henderson             }
30808a1a5274SRichard Henderson             *pinterp_name = g_steal_pointer(&interp_name);
308183f990ebSRichard Henderson         } else if (eppnt->p_type == PT_GNU_PROPERTY) {
308283f990ebSRichard Henderson             if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
308383f990ebSRichard Henderson                 goto exit_errmsg;
308483f990ebSRichard Henderson             }
3085872f3d04SRichard Henderson         } else if (eppnt->p_type == PT_GNU_STACK) {
3086872f3d04SRichard Henderson             info->exec_stack = eppnt->p_flags & PF_X;
3087682674b8SRichard Henderson         }
3088682674b8SRichard Henderson     }
3089682674b8SRichard Henderson 
30906fd59449SRichard Henderson     if (pinterp_name != NULL) {
30916fd59449SRichard Henderson         /*
30926fd59449SRichard Henderson          * This is the main executable.
30936fd59449SRichard Henderson          *
30946fd59449SRichard Henderson          * Reserve extra space for brk.
30956fd59449SRichard Henderson          * We hold on to this space while placing the interpreter
30966fd59449SRichard Henderson          * and the stack, lest they be placed immediately after
30976fd59449SRichard Henderson          * the data segment and block allocation from the brk.
30986fd59449SRichard Henderson          *
309911d36727SAlex Bennée          * 16MB is chosen as "large enough" without being so large as
310011d36727SAlex Bennée          * to allow the result to not fit with a 32-bit guest on a
310111d36727SAlex Bennée          * 32-bit host. However some 64 bit guests (e.g. s390x)
310211d36727SAlex Bennée          * attempt to place their heap further ahead and currently
310311d36727SAlex Bennée          * nothing stops them smashing into QEMUs address space.
31046fd59449SRichard Henderson          */
310511d36727SAlex Bennée #if TARGET_LONG_BITS == 64
310611d36727SAlex Bennée         info->reserve_brk = 32 * MiB;
310711d36727SAlex Bennée #else
31086fd59449SRichard Henderson         info->reserve_brk = 16 * MiB;
310911d36727SAlex Bennée #endif
31106fd59449SRichard Henderson         hiaddr += info->reserve_brk;
31116fd59449SRichard Henderson 
31126fd59449SRichard Henderson         if (ehdr->e_type == ET_EXEC) {
31136fd59449SRichard Henderson             /*
31146fd59449SRichard Henderson              * Make sure that the low address does not conflict with
31156fd59449SRichard Henderson              * MMAP_MIN_ADDR or the QEMU application itself.
31166fd59449SRichard Henderson              */
31176fd59449SRichard Henderson             probe_guest_base(image_name, loaddr, hiaddr);
3118ee947430SAlex Bennée         } else {
3119ee947430SAlex Bennée             /*
3120ee947430SAlex Bennée              * The binary is dynamic, but we still need to
3121ee947430SAlex Bennée              * select guest_base.  In this case we pass a size.
3122ee947430SAlex Bennée              */
3123ee947430SAlex Bennée             probe_guest_base(image_name, 0, hiaddr - loaddr);
31246fd59449SRichard Henderson         }
31256fd59449SRichard Henderson     }
31266fd59449SRichard Henderson 
31276fd59449SRichard Henderson     /*
31286fd59449SRichard Henderson      * Reserve address space for all of this.
31296fd59449SRichard Henderson      *
31306fd59449SRichard Henderson      * In the case of ET_EXEC, we supply MAP_FIXED so that we get
31316fd59449SRichard Henderson      * exactly the address range that is required.
31326fd59449SRichard Henderson      *
31336fd59449SRichard Henderson      * Otherwise this is ET_DYN, and we are searching for a location
31346fd59449SRichard Henderson      * that can hold the memory space required.  If the image is
31356fd59449SRichard Henderson      * pre-linked, LOADDR will be non-zero, and the kernel should
31366fd59449SRichard Henderson      * honor that address if it happens to be free.
31376fd59449SRichard Henderson      *
31386fd59449SRichard Henderson      * In both cases, we will overwrite pages in this range with mappings
31396fd59449SRichard Henderson      * from the executable.
31406fd59449SRichard Henderson      */
3141a3a67f54SRichard Henderson     load_addr = target_mmap(loaddr, (size_t)hiaddr - loaddr + 1, PROT_NONE,
31426fd59449SRichard Henderson                             MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
31436fd59449SRichard Henderson                             (ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
314409bfb054Sbellard                             -1, 0);
3145682674b8SRichard Henderson     if (load_addr == -1) {
3146c7f17e7bSRichard Henderson         goto exit_mmap;
314709bfb054Sbellard     }
3148682674b8SRichard Henderson     load_bias = load_addr - loaddr;
314909bfb054Sbellard 
3150a99856cdSChristophe Lyon     if (elf_is_fdpic(ehdr)) {
31511af02e83SMike Frysinger         struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
31527267c094SAnthony Liguori             g_malloc(sizeof(*loadsegs) * info->nsegs);
31531af02e83SMike Frysinger 
31541af02e83SMike Frysinger         for (i = 0; i < ehdr->e_phnum; ++i) {
31551af02e83SMike Frysinger             switch (phdr[i].p_type) {
31561af02e83SMike Frysinger             case PT_DYNAMIC:
31571af02e83SMike Frysinger                 info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
31581af02e83SMike Frysinger                 break;
31591af02e83SMike Frysinger             case PT_LOAD:
31601af02e83SMike Frysinger                 loadsegs->addr = phdr[i].p_vaddr + load_bias;
31611af02e83SMike Frysinger                 loadsegs->p_vaddr = phdr[i].p_vaddr;
31621af02e83SMike Frysinger                 loadsegs->p_memsz = phdr[i].p_memsz;
31631af02e83SMike Frysinger                 ++loadsegs;
31641af02e83SMike Frysinger                 break;
31651af02e83SMike Frysinger             }
31661af02e83SMike Frysinger         }
31671af02e83SMike Frysinger     }
31681af02e83SMike Frysinger 
31698e62a717SRichard Henderson     info->load_bias = load_bias;
3170dc12567aSJosh Kunz     info->code_offset = load_bias;
3171dc12567aSJosh Kunz     info->data_offset = load_bias;
31728e62a717SRichard Henderson     info->load_addr = load_addr;
31738e62a717SRichard Henderson     info->entry = ehdr->e_entry + load_bias;
31748e62a717SRichard Henderson     info->start_code = -1;
31758e62a717SRichard Henderson     info->end_code = 0;
31768e62a717SRichard Henderson     info->start_data = -1;
31778e62a717SRichard Henderson     info->end_data = 0;
31788e62a717SRichard Henderson     info->brk = 0;
3179d8fd2954SPaul Brook     info->elf_flags = ehdr->e_flags;
31808e62a717SRichard Henderson 
3181e8384b37SRichard Henderson     prot_exec = PROT_EXEC;
3182e8384b37SRichard Henderson #ifdef TARGET_AARCH64
3183e8384b37SRichard Henderson     /*
3184e8384b37SRichard Henderson      * If the BTI feature is present, this indicates that the executable
3185e8384b37SRichard Henderson      * pages of the startup binary should be mapped with PROT_BTI, so that
3186e8384b37SRichard Henderson      * branch targets are enforced.
3187e8384b37SRichard Henderson      *
3188e8384b37SRichard Henderson      * The startup binary is either the interpreter or the static executable.
3189e8384b37SRichard Henderson      * The interpreter is responsible for all pages of a dynamic executable.
3190e8384b37SRichard Henderson      *
3191e8384b37SRichard Henderson      * Elf notes are backward compatible to older cpus.
3192e8384b37SRichard Henderson      * Do not enable BTI unless it is supported.
3193e8384b37SRichard Henderson      */
3194e8384b37SRichard Henderson     if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
3195e8384b37SRichard Henderson         && (pinterp_name == NULL || *pinterp_name == 0)
3196e8384b37SRichard Henderson         && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
3197e8384b37SRichard Henderson         prot_exec |= TARGET_PROT_BTI;
3198e8384b37SRichard Henderson     }
3199e8384b37SRichard Henderson #endif
3200e8384b37SRichard Henderson 
32018e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; i++) {
32028e62a717SRichard Henderson         struct elf_phdr *eppnt = phdr + i;
320331e31b8aSbellard         if (eppnt->p_type == PT_LOAD) {
320494894ff2SShivaprasad G Bhat             abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
320531e31b8aSbellard             int elf_prot = 0;
320631e31b8aSbellard 
3207e5eaf570SRichard Henderson             if (eppnt->p_flags & PF_R) {
3208e5eaf570SRichard Henderson                 elf_prot |= PROT_READ;
3209e5eaf570SRichard Henderson             }
3210e5eaf570SRichard Henderson             if (eppnt->p_flags & PF_W) {
3211e5eaf570SRichard Henderson                 elf_prot |= PROT_WRITE;
3212e5eaf570SRichard Henderson             }
3213e5eaf570SRichard Henderson             if (eppnt->p_flags & PF_X) {
3214e8384b37SRichard Henderson                 elf_prot |= prot_exec;
3215e5eaf570SRichard Henderson             }
321631e31b8aSbellard 
3217682674b8SRichard Henderson             vaddr = load_bias + eppnt->p_vaddr;
3218682674b8SRichard Henderson             vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
3219682674b8SRichard Henderson             vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
322022d113b5SGiuseppe Musacchio 
322122d113b5SGiuseppe Musacchio             vaddr_ef = vaddr + eppnt->p_filesz;
322222d113b5SGiuseppe Musacchio             vaddr_em = vaddr + eppnt->p_memsz;
3223682674b8SRichard Henderson 
3224d87146bcSGiuseppe Musacchio             /*
322522d113b5SGiuseppe Musacchio              * Some segments may be completely empty, with a non-zero p_memsz
322622d113b5SGiuseppe Musacchio              * but no backing file segment.
3227d87146bcSGiuseppe Musacchio              */
3228d87146bcSGiuseppe Musacchio             if (eppnt->p_filesz != 0) {
322922d113b5SGiuseppe Musacchio                 vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po);
3230d87146bcSGiuseppe Musacchio                 error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
3231d87146bcSGiuseppe Musacchio                                     MAP_PRIVATE | MAP_FIXED,
32328e62a717SRichard Henderson                                     image_fd, eppnt->p_offset - vaddr_po);
3233d87146bcSGiuseppe Musacchio 
3234e89f07d3Spbrook                 if (error == -1) {
3235c7f17e7bSRichard Henderson                     goto exit_mmap;
323631e31b8aSbellard                 }
323731e31b8aSbellard 
323822d113b5SGiuseppe Musacchio                 /*
323922d113b5SGiuseppe Musacchio                  * If the load segment requests extra zeros (e.g. bss), map it.
324022d113b5SGiuseppe Musacchio                  */
324122d113b5SGiuseppe Musacchio                 if (eppnt->p_filesz < eppnt->p_memsz) {
3242682674b8SRichard Henderson                     zero_bss(vaddr_ef, vaddr_em, elf_prot);
3243682674b8SRichard Henderson                 }
324422d113b5SGiuseppe Musacchio             } else if (eppnt->p_memsz != 0) {
324522d113b5SGiuseppe Musacchio                 vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_memsz + vaddr_po);
324622d113b5SGiuseppe Musacchio                 error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
324722d113b5SGiuseppe Musacchio                                     MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
324822d113b5SGiuseppe Musacchio                                     -1, 0);
324922d113b5SGiuseppe Musacchio 
325022d113b5SGiuseppe Musacchio                 if (error == -1) {
325122d113b5SGiuseppe Musacchio                     goto exit_mmap;
325222d113b5SGiuseppe Musacchio                 }
325322d113b5SGiuseppe Musacchio             }
32548e62a717SRichard Henderson 
32558e62a717SRichard Henderson             /* Find the full program boundaries.  */
32568e62a717SRichard Henderson             if (elf_prot & PROT_EXEC) {
32578e62a717SRichard Henderson                 if (vaddr < info->start_code) {
32588e62a717SRichard Henderson                     info->start_code = vaddr;
3259cf129f3aSRichard Henderson                 }
32608e62a717SRichard Henderson                 if (vaddr_ef > info->end_code) {
32618e62a717SRichard Henderson                     info->end_code = vaddr_ef;
32628e62a717SRichard Henderson                 }
32638e62a717SRichard Henderson             }
32648e62a717SRichard Henderson             if (elf_prot & PROT_WRITE) {
32658e62a717SRichard Henderson                 if (vaddr < info->start_data) {
32668e62a717SRichard Henderson                     info->start_data = vaddr;
32678e62a717SRichard Henderson                 }
32688e62a717SRichard Henderson                 if (vaddr_ef > info->end_data) {
32698e62a717SRichard Henderson                     info->end_data = vaddr_ef;
32708e62a717SRichard Henderson                 }
32718a045188STimothy E Baldwin             }
32728e62a717SRichard Henderson             if (vaddr_em > info->brk) {
32738e62a717SRichard Henderson                 info->brk = vaddr_em;
32748e62a717SRichard Henderson             }
32755dd0db52SStefan Markovic #ifdef TARGET_MIPS
32765dd0db52SStefan Markovic         } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
32775dd0db52SStefan Markovic             Mips_elf_abiflags_v0 abiflags;
32785dd0db52SStefan Markovic             if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
3279c7f17e7bSRichard Henderson                 error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
32805dd0db52SStefan Markovic                 goto exit_errmsg;
32815dd0db52SStefan Markovic             }
32825dd0db52SStefan Markovic             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
32835dd0db52SStefan Markovic                 memcpy(&abiflags, bprm_buf + eppnt->p_offset,
32845dd0db52SStefan Markovic                        sizeof(Mips_elf_abiflags_v0));
32855dd0db52SStefan Markovic             } else {
32865dd0db52SStefan Markovic                 retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
32875dd0db52SStefan Markovic                                eppnt->p_offset);
32885dd0db52SStefan Markovic                 if (retval != sizeof(Mips_elf_abiflags_v0)) {
3289c7f17e7bSRichard Henderson                     goto exit_read;
32905dd0db52SStefan Markovic                 }
32915dd0db52SStefan Markovic             }
32925dd0db52SStefan Markovic             bswap_mips_abiflags(&abiflags);
3293c94cb6c9SStefan Markovic             info->fp_abi = abiflags.fp_abi;
32945dd0db52SStefan Markovic #endif
32958e62a717SRichard Henderson         }
32968e62a717SRichard Henderson     }
32978e62a717SRichard Henderson 
32988e62a717SRichard Henderson     if (info->end_data == 0) {
32998e62a717SRichard Henderson         info->start_data = info->end_code;
33008e62a717SRichard Henderson         info->end_data = info->end_code;
330131e31b8aSbellard     }
330231e31b8aSbellard 
3303682674b8SRichard Henderson     if (qemu_log_enabled()) {
33048e62a717SRichard Henderson         load_symbols(ehdr, image_fd, load_bias);
3305682674b8SRichard Henderson     }
330631e31b8aSbellard 
33077c10cb38SIlya Leoshkevich     debuginfo_report_elf(image_name, image_fd, load_bias);
33087c10cb38SIlya Leoshkevich 
330998c1076cSAlex Bennée     mmap_unlock();
331098c1076cSAlex Bennée 
33118e62a717SRichard Henderson     close(image_fd);
33128e62a717SRichard Henderson     return;
331331e31b8aSbellard 
33148e62a717SRichard Henderson  exit_read:
33158e62a717SRichard Henderson     if (retval >= 0) {
3316c7f17e7bSRichard Henderson         error_setg(&err, "Incomplete read of file header");
3317c7f17e7bSRichard Henderson     } else {
3318c7f17e7bSRichard Henderson         error_setg_errno(&err, errno, "Error reading file header");
33198e62a717SRichard Henderson     }
3320c7f17e7bSRichard Henderson     goto exit_errmsg;
3321c7f17e7bSRichard Henderson  exit_mmap:
3322c7f17e7bSRichard Henderson     error_setg_errno(&err, errno, "Error mapping file");
3323c7f17e7bSRichard Henderson     goto exit_errmsg;
33248e62a717SRichard Henderson  exit_errmsg:
3325c7f17e7bSRichard Henderson     error_reportf_err(err, "%s: ", image_name);
33268e62a717SRichard Henderson     exit(-1);
33278e62a717SRichard Henderson }
33288e62a717SRichard Henderson 
33298e62a717SRichard Henderson static void load_elf_interp(const char *filename, struct image_info *info,
33308e62a717SRichard Henderson                             char bprm_buf[BPRM_BUF_SIZE])
33318e62a717SRichard Henderson {
33328e62a717SRichard Henderson     int fd, retval;
3333808f6563SRichard Henderson     Error *err = NULL;
33348e62a717SRichard Henderson 
33358e62a717SRichard Henderson     fd = open(path(filename), O_RDONLY);
33368e62a717SRichard Henderson     if (fd < 0) {
3337808f6563SRichard Henderson         error_setg_file_open(&err, errno, filename);
3338808f6563SRichard Henderson         error_report_err(err);
3339808f6563SRichard Henderson         exit(-1);
33408e62a717SRichard Henderson     }
33418e62a717SRichard Henderson 
33428e62a717SRichard Henderson     retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
33438e62a717SRichard Henderson     if (retval < 0) {
3344808f6563SRichard Henderson         error_setg_errno(&err, errno, "Error reading file header");
3345808f6563SRichard Henderson         error_reportf_err(err, "%s: ", filename);
3346808f6563SRichard Henderson         exit(-1);
33478e62a717SRichard Henderson     }
3348808f6563SRichard Henderson 
33498e62a717SRichard Henderson     if (retval < BPRM_BUF_SIZE) {
33508e62a717SRichard Henderson         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
33518e62a717SRichard Henderson     }
33528e62a717SRichard Henderson 
3353bf858897SRichard Henderson     load_elf_image(filename, fd, info, NULL, bprm_buf);
335431e31b8aSbellard }
335531e31b8aSbellard 
335649918a75Spbrook static int symfind(const void *s0, const void *s1)
335749918a75Spbrook {
335849918a75Spbrook     struct elf_sym *sym = (struct elf_sym *)s1;
3359b6235a75SRichard Henderson     __typeof(sym->st_value) addr = *(uint64_t *)s0;
336049918a75Spbrook     int result = 0;
3361b6235a75SRichard Henderson 
3362c7c530cdSStefan Weil     if (addr < sym->st_value) {
336349918a75Spbrook         result = -1;
3364c7c530cdSStefan Weil     } else if (addr >= sym->st_value + sym->st_size) {
336549918a75Spbrook         result = 1;
336649918a75Spbrook     }
336749918a75Spbrook     return result;
336849918a75Spbrook }
336949918a75Spbrook 
3370b6235a75SRichard Henderson static const char *lookup_symbolxx(struct syminfo *s, uint64_t orig_addr)
337149918a75Spbrook {
337249918a75Spbrook #if ELF_CLASS == ELFCLASS32
337349918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf32;
337449918a75Spbrook #else
337549918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf64;
337649918a75Spbrook #endif
337749918a75Spbrook 
337849918a75Spbrook     // binary search
337949918a75Spbrook     struct elf_sym *sym;
338049918a75Spbrook 
3381c7c530cdSStefan Weil     sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
33827cba04f6SBlue Swirl     if (sym != NULL) {
338349918a75Spbrook         return s->disas_strtab + sym->st_name;
338449918a75Spbrook     }
338549918a75Spbrook 
338649918a75Spbrook     return "";
338749918a75Spbrook }
338849918a75Spbrook 
338949918a75Spbrook /* FIXME: This should use elf_ops.h  */
339049918a75Spbrook static int symcmp(const void *s0, const void *s1)
339149918a75Spbrook {
339249918a75Spbrook     struct elf_sym *sym0 = (struct elf_sym *)s0;
339349918a75Spbrook     struct elf_sym *sym1 = (struct elf_sym *)s1;
339449918a75Spbrook     return (sym0->st_value < sym1->st_value)
339549918a75Spbrook         ? -1
339649918a75Spbrook         : ((sym0->st_value > sym1->st_value) ? 1 : 0);
339749918a75Spbrook }
339849918a75Spbrook 
3399689f936fSbellard /* Best attempt to load symbols from this ELF object. */
3400682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
3401689f936fSbellard {
3402682674b8SRichard Henderson     int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
34031e06262dSPeter Maydell     uint64_t segsz;
3404682674b8SRichard Henderson     struct elf_shdr *shdr;
3405b9475279SCédric VINCENT     char *strings = NULL;
3406b9475279SCédric VINCENT     struct syminfo *s = NULL;
3407b9475279SCédric VINCENT     struct elf_sym *new_syms, *syms = NULL;
340831e31b8aSbellard 
3409682674b8SRichard Henderson     shnum = hdr->e_shnum;
3410682674b8SRichard Henderson     i = shnum * sizeof(struct elf_shdr);
3411682674b8SRichard Henderson     shdr = (struct elf_shdr *)alloca(i);
3412682674b8SRichard Henderson     if (pread(fd, shdr, i, hdr->e_shoff) != i) {
3413689f936fSbellard         return;
3414682674b8SRichard Henderson     }
3415682674b8SRichard Henderson 
3416682674b8SRichard Henderson     bswap_shdr(shdr, shnum);
3417682674b8SRichard Henderson     for (i = 0; i < shnum; ++i) {
3418682674b8SRichard Henderson         if (shdr[i].sh_type == SHT_SYMTAB) {
3419682674b8SRichard Henderson             sym_idx = i;
3420682674b8SRichard Henderson             str_idx = shdr[i].sh_link;
3421689f936fSbellard             goto found;
3422689f936fSbellard         }
3423689f936fSbellard     }
3424682674b8SRichard Henderson 
3425682674b8SRichard Henderson     /* There will be no symbol table if the file was stripped.  */
3426682674b8SRichard Henderson     return;
3427689f936fSbellard 
3428689f936fSbellard  found:
3429689f936fSbellard     /* Now know where the strtab and symtab are.  Snarf them.  */
34300ef9ea29SPeter Maydell     s = g_try_new(struct syminfo, 1);
3431682674b8SRichard Henderson     if (!s) {
3432b9475279SCédric VINCENT         goto give_up;
3433682674b8SRichard Henderson     }
3434682674b8SRichard Henderson 
34351e06262dSPeter Maydell     segsz = shdr[str_idx].sh_size;
34361e06262dSPeter Maydell     s->disas_strtab = strings = g_try_malloc(segsz);
34371e06262dSPeter Maydell     if (!strings ||
34381e06262dSPeter Maydell         pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) {
3439b9475279SCédric VINCENT         goto give_up;
3440682674b8SRichard Henderson     }
3441689f936fSbellard 
34421e06262dSPeter Maydell     segsz = shdr[sym_idx].sh_size;
34431e06262dSPeter Maydell     syms = g_try_malloc(segsz);
34441e06262dSPeter Maydell     if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) {
3445b9475279SCédric VINCENT         goto give_up;
3446682674b8SRichard Henderson     }
3447689f936fSbellard 
34481e06262dSPeter Maydell     if (segsz / sizeof(struct elf_sym) > INT_MAX) {
34491e06262dSPeter Maydell         /* Implausibly large symbol table: give up rather than ploughing
34501e06262dSPeter Maydell          * on with the number of symbols calculation overflowing
34511e06262dSPeter Maydell          */
34521e06262dSPeter Maydell         goto give_up;
34531e06262dSPeter Maydell     }
34541e06262dSPeter Maydell     nsyms = segsz / sizeof(struct elf_sym);
3455682674b8SRichard Henderson     for (i = 0; i < nsyms; ) {
345649918a75Spbrook         bswap_sym(syms + i);
3457682674b8SRichard Henderson         /* Throw away entries which we do not need.  */
3458682674b8SRichard Henderson         if (syms[i].st_shndx == SHN_UNDEF
3459682674b8SRichard Henderson             || syms[i].st_shndx >= SHN_LORESERVE
3460682674b8SRichard Henderson             || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
3461682674b8SRichard Henderson             if (i < --nsyms) {
346249918a75Spbrook                 syms[i] = syms[nsyms];
346349918a75Spbrook             }
3464682674b8SRichard Henderson         } else {
346549918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS)
346649918a75Spbrook             /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
346749918a75Spbrook             syms[i].st_value &= ~(target_ulong)1;
346849918a75Spbrook #endif
3469682674b8SRichard Henderson             syms[i].st_value += load_bias;
347049918a75Spbrook             i++;
347149918a75Spbrook         }
3472682674b8SRichard Henderson     }
347349918a75Spbrook 
3474b9475279SCédric VINCENT     /* No "useful" symbol.  */
3475b9475279SCédric VINCENT     if (nsyms == 0) {
3476b9475279SCédric VINCENT         goto give_up;
3477b9475279SCédric VINCENT     }
3478b9475279SCédric VINCENT 
34795d5c9930SRichard Henderson     /* Attempt to free the storage associated with the local symbols
34805d5c9930SRichard Henderson        that we threw away.  Whether or not this has any effect on the
34815d5c9930SRichard Henderson        memory allocation depends on the malloc implementation and how
34825d5c9930SRichard Henderson        many symbols we managed to discard.  */
34830ef9ea29SPeter Maydell     new_syms = g_try_renew(struct elf_sym, syms, nsyms);
34848d79de6eSStefan Weil     if (new_syms == NULL) {
3485b9475279SCédric VINCENT         goto give_up;
34865d5c9930SRichard Henderson     }
34878d79de6eSStefan Weil     syms = new_syms;
34885d5c9930SRichard Henderson 
348949918a75Spbrook     qsort(syms, nsyms, sizeof(*syms), symcmp);
349049918a75Spbrook 
349149918a75Spbrook     s->disas_num_syms = nsyms;
349249918a75Spbrook #if ELF_CLASS == ELFCLASS32
349349918a75Spbrook     s->disas_symtab.elf32 = syms;
349449918a75Spbrook #else
349549918a75Spbrook     s->disas_symtab.elf64 = syms;
349649918a75Spbrook #endif
3497682674b8SRichard Henderson     s->lookup_symbol = lookup_symbolxx;
3498e80cfcfcSbellard     s->next = syminfos;
3499e80cfcfcSbellard     syminfos = s;
3500b9475279SCédric VINCENT 
3501b9475279SCédric VINCENT     return;
3502b9475279SCédric VINCENT 
3503b9475279SCédric VINCENT give_up:
35040ef9ea29SPeter Maydell     g_free(s);
35050ef9ea29SPeter Maydell     g_free(strings);
35060ef9ea29SPeter Maydell     g_free(syms);
3507689f936fSbellard }
350831e31b8aSbellard 
3509768fe76eSYunQiang Su uint32_t get_elf_eflags(int fd)
3510768fe76eSYunQiang Su {
3511768fe76eSYunQiang Su     struct elfhdr ehdr;
3512768fe76eSYunQiang Su     off_t offset;
3513768fe76eSYunQiang Su     int ret;
3514768fe76eSYunQiang Su 
3515768fe76eSYunQiang Su     /* Read ELF header */
3516768fe76eSYunQiang Su     offset = lseek(fd, 0, SEEK_SET);
3517768fe76eSYunQiang Su     if (offset == (off_t) -1) {
3518768fe76eSYunQiang Su         return 0;
3519768fe76eSYunQiang Su     }
3520768fe76eSYunQiang Su     ret = read(fd, &ehdr, sizeof(ehdr));
3521768fe76eSYunQiang Su     if (ret < sizeof(ehdr)) {
3522768fe76eSYunQiang Su         return 0;
3523768fe76eSYunQiang Su     }
3524768fe76eSYunQiang Su     offset = lseek(fd, offset, SEEK_SET);
3525768fe76eSYunQiang Su     if (offset == (off_t) -1) {
3526768fe76eSYunQiang Su         return 0;
3527768fe76eSYunQiang Su     }
3528768fe76eSYunQiang Su 
3529768fe76eSYunQiang Su     /* Check ELF signature */
3530768fe76eSYunQiang Su     if (!elf_check_ident(&ehdr)) {
3531768fe76eSYunQiang Su         return 0;
3532768fe76eSYunQiang Su     }
3533768fe76eSYunQiang Su 
3534768fe76eSYunQiang Su     /* check header */
3535768fe76eSYunQiang Su     bswap_ehdr(&ehdr);
3536768fe76eSYunQiang Su     if (!elf_check_ehdr(&ehdr)) {
3537768fe76eSYunQiang Su         return 0;
3538768fe76eSYunQiang Su     }
3539768fe76eSYunQiang Su 
3540768fe76eSYunQiang Su     /* return architecture id */
3541768fe76eSYunQiang Su     return ehdr.e_flags;
3542768fe76eSYunQiang Su }
3543768fe76eSYunQiang Su 
3544f0116c54SWill Newton int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
354531e31b8aSbellard {
35468e62a717SRichard Henderson     struct image_info interp_info;
354731e31b8aSbellard     struct elfhdr elf_ex;
35488e62a717SRichard Henderson     char *elf_interpreter = NULL;
354959baae9aSStefan Brüns     char *scratch;
355031e31b8aSbellard 
3551abcac736SDaniel Santos     memset(&interp_info, 0, sizeof(interp_info));
3552abcac736SDaniel Santos #ifdef TARGET_MIPS
3553abcac736SDaniel Santos     interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
3554abcac736SDaniel Santos #endif
3555abcac736SDaniel Santos 
3556bf858897SRichard Henderson     info->start_mmap = (abi_ulong)ELF_START_MMAP;
355731e31b8aSbellard 
3558bf858897SRichard Henderson     load_elf_image(bprm->filename, bprm->fd, info,
3559bf858897SRichard Henderson                    &elf_interpreter, bprm->buf);
3560bf858897SRichard Henderson 
3561bf858897SRichard Henderson     /* ??? We need a copy of the elf header for passing to create_elf_tables.
3562bf858897SRichard Henderson        If we do nothing, we'll have overwritten this when we re-use bprm->buf
3563bf858897SRichard Henderson        when we load the interpreter.  */
3564bf858897SRichard Henderson     elf_ex = *(struct elfhdr *)bprm->buf;
356531e31b8aSbellard 
356659baae9aSStefan Brüns     /* Do this so that we can load the interpreter, if need be.  We will
356759baae9aSStefan Brüns        change some of these later */
356859baae9aSStefan Brüns     bprm->p = setup_arg_pages(bprm, info);
356959baae9aSStefan Brüns 
357059baae9aSStefan Brüns     scratch = g_new0(char, TARGET_PAGE_SIZE);
35717c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
357259baae9aSStefan Brüns         bprm->p = copy_elf_strings(1, &bprm->filename, scratch,
357359baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
35747c4ee5bcSRichard Henderson         info->file_string = bprm->p;
357559baae9aSStefan Brüns         bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch,
357659baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
35777c4ee5bcSRichard Henderson         info->env_strings = bprm->p;
357859baae9aSStefan Brüns         bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch,
357959baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
35807c4ee5bcSRichard Henderson         info->arg_strings = bprm->p;
35817c4ee5bcSRichard Henderson     } else {
35827c4ee5bcSRichard Henderson         info->arg_strings = bprm->p;
35837c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch,
35847c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
35857c4ee5bcSRichard Henderson         info->env_strings = bprm->p;
35867c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch,
35877c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
35887c4ee5bcSRichard Henderson         info->file_string = bprm->p;
35897c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(1, &bprm->filename, scratch,
35907c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
35917c4ee5bcSRichard Henderson     }
35927c4ee5bcSRichard Henderson 
359359baae9aSStefan Brüns     g_free(scratch);
359459baae9aSStefan Brüns 
3595e5fe0c52Spbrook     if (!bprm->p) {
3596bf858897SRichard Henderson         fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
359731e31b8aSbellard         exit(-1);
35989955ffacSRichard Henderson     }
3599379f6698SPaul Brook 
36008e62a717SRichard Henderson     if (elf_interpreter) {
36018e62a717SRichard Henderson         load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
360231e31b8aSbellard 
36038e62a717SRichard Henderson         /* If the program interpreter is one of these two, then assume
36048e62a717SRichard Henderson            an iBCS2 image.  Otherwise assume a native linux image.  */
360531e31b8aSbellard 
36068e62a717SRichard Henderson         if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
36078e62a717SRichard Henderson             || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
36088e62a717SRichard Henderson             info->personality = PER_SVR4;
36098e62a717SRichard Henderson 
361031e31b8aSbellard             /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
36118e62a717SRichard Henderson                and some applications "depend" upon this behavior.  Since
36128e62a717SRichard Henderson                we do not have the power to recompile these, we emulate
36138e62a717SRichard Henderson                the SVr4 behavior.  Sigh.  */
36148e62a717SRichard Henderson             target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
361568754b44SPeter Maydell                         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
361631e31b8aSbellard         }
3617c94cb6c9SStefan Markovic #ifdef TARGET_MIPS
3618c94cb6c9SStefan Markovic         info->interp_fp_abi = interp_info.fp_abi;
3619c94cb6c9SStefan Markovic #endif
36208e62a717SRichard Henderson     }
362131e31b8aSbellard 
3622db2af69dSRichard Henderson     /*
3623db2af69dSRichard Henderson      * TODO: load a vdso, which would also contain the signal trampolines.
3624db2af69dSRichard Henderson      * Otherwise, allocate a private page to hold them.
3625db2af69dSRichard Henderson      */
3626db2af69dSRichard Henderson     if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
3627802ae45eSLaurent Vivier         abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
3628db2af69dSRichard Henderson                                           PROT_READ | PROT_WRITE,
3629db2af69dSRichard Henderson                                           MAP_PRIVATE | MAP_ANON, -1, 0);
3630802ae45eSLaurent Vivier         if (tramp_page == -1) {
3631802ae45eSLaurent Vivier             return -errno;
3632802ae45eSLaurent Vivier         }
3633802ae45eSLaurent Vivier 
3634db2af69dSRichard Henderson         setup_sigtramp(tramp_page);
3635db2af69dSRichard Henderson         target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
3636db2af69dSRichard Henderson     }
3637db2af69dSRichard Henderson 
36388e62a717SRichard Henderson     bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
36398e62a717SRichard Henderson                                 info, (elf_interpreter ? &interp_info : NULL));
36408e62a717SRichard Henderson     info->start_stack = bprm->p;
36418e62a717SRichard Henderson 
36428e62a717SRichard Henderson     /* If we have an interpreter, set that as the program's entry point.
36438e78064eSRichard Henderson        Copy the load_bias as well, to help PPC64 interpret the entry
36448e62a717SRichard Henderson        point as a function descriptor.  Do this after creating elf tables
36458e62a717SRichard Henderson        so that we copy the original program entry point into the AUXV.  */
36468e62a717SRichard Henderson     if (elf_interpreter) {
36478e78064eSRichard Henderson         info->load_bias = interp_info.load_bias;
36488e62a717SRichard Henderson         info->entry = interp_info.entry;
36492b323087SPhilippe Mathieu-Daudé         g_free(elf_interpreter);
36508e62a717SRichard Henderson     }
365131e31b8aSbellard 
3652edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
3653edf8e2afSMika Westerberg     bprm->core_dump = &elf_core_dump;
3654edf8e2afSMika Westerberg #endif
3655edf8e2afSMika Westerberg 
36566fd59449SRichard Henderson     /*
36576fd59449SRichard Henderson      * If we reserved extra space for brk, release it now.
36586fd59449SRichard Henderson      * The implementation of do_brk in syscalls.c expects to be able
36596fd59449SRichard Henderson      * to mmap pages in this space.
36606fd59449SRichard Henderson      */
36616fd59449SRichard Henderson     if (info->reserve_brk) {
36626fd59449SRichard Henderson         abi_ulong start_brk = HOST_PAGE_ALIGN(info->brk);
36636fd59449SRichard Henderson         abi_ulong end_brk = HOST_PAGE_ALIGN(info->brk + info->reserve_brk);
36646fd59449SRichard Henderson         target_munmap(start_brk, end_brk - start_brk);
36656fd59449SRichard Henderson     }
36666fd59449SRichard Henderson 
366731e31b8aSbellard     return 0;
366831e31b8aSbellard }
366931e31b8aSbellard 
3670edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
3671edf8e2afSMika Westerberg /*
3672edf8e2afSMika Westerberg  * Definitions to generate Intel SVR4-like core files.
3673a2547a13SLaurent Desnogues  * These mostly have the same names as the SVR4 types with "target_elf_"
3674edf8e2afSMika Westerberg  * tacked on the front to prevent clashes with linux definitions,
3675edf8e2afSMika Westerberg  * and the typedef forms have been avoided.  This is mostly like
3676edf8e2afSMika Westerberg  * the SVR4 structure, but more Linuxy, with things that Linux does
3677edf8e2afSMika Westerberg  * not support and which gdb doesn't really use excluded.
3678edf8e2afSMika Westerberg  *
3679edf8e2afSMika Westerberg  * Fields we don't dump (their contents is zero) in linux-user qemu
3680edf8e2afSMika Westerberg  * are marked with XXX.
3681edf8e2afSMika Westerberg  *
3682edf8e2afSMika Westerberg  * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
3683edf8e2afSMika Westerberg  *
3684edf8e2afSMika Westerberg  * Porting ELF coredump for target is (quite) simple process.  First you
3685dd0a3651SNathan Froyd  * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
3686edf8e2afSMika Westerberg  * the target resides):
3687edf8e2afSMika Westerberg  *
3688edf8e2afSMika Westerberg  * #define USE_ELF_CORE_DUMP
3689edf8e2afSMika Westerberg  *
3690edf8e2afSMika Westerberg  * Next you define type of register set used for dumping.  ELF specification
3691edf8e2afSMika Westerberg  * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
3692edf8e2afSMika Westerberg  *
3693c227f099SAnthony Liguori  * typedef <target_regtype> target_elf_greg_t;
3694edf8e2afSMika Westerberg  * #define ELF_NREG <number of registers>
3695c227f099SAnthony Liguori  * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
3696edf8e2afSMika Westerberg  *
3697edf8e2afSMika Westerberg  * Last step is to implement target specific function that copies registers
3698edf8e2afSMika Westerberg  * from given cpu into just specified register set.  Prototype is:
3699edf8e2afSMika Westerberg  *
3700c227f099SAnthony Liguori  * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
37019349b4f9SAndreas Färber  *                                const CPUArchState *env);
3702edf8e2afSMika Westerberg  *
3703edf8e2afSMika Westerberg  * Parameters:
3704edf8e2afSMika Westerberg  *     regs - copy register values into here (allocated and zeroed by caller)
3705edf8e2afSMika Westerberg  *     env - copy registers from here
3706edf8e2afSMika Westerberg  *
3707edf8e2afSMika Westerberg  * Example for ARM target is provided in this file.
3708edf8e2afSMika Westerberg  */
3709edf8e2afSMika Westerberg 
3710edf8e2afSMika Westerberg /* An ELF note in memory */
3711edf8e2afSMika Westerberg struct memelfnote {
3712edf8e2afSMika Westerberg     const char *name;
3713edf8e2afSMika Westerberg     size_t     namesz;
3714edf8e2afSMika Westerberg     size_t     namesz_rounded;
3715edf8e2afSMika Westerberg     int        type;
3716edf8e2afSMika Westerberg     size_t     datasz;
371780f5ce75SLaurent Vivier     size_t     datasz_rounded;
3718edf8e2afSMika Westerberg     void       *data;
3719edf8e2afSMika Westerberg     size_t     notesz;
3720edf8e2afSMika Westerberg };
3721edf8e2afSMika Westerberg 
3722a2547a13SLaurent Desnogues struct target_elf_siginfo {
3723f8fd4fc4SPaolo Bonzini     abi_int    si_signo; /* signal number */
3724f8fd4fc4SPaolo Bonzini     abi_int    si_code;  /* extra code */
3725f8fd4fc4SPaolo Bonzini     abi_int    si_errno; /* errno */
3726edf8e2afSMika Westerberg };
3727edf8e2afSMika Westerberg 
3728a2547a13SLaurent Desnogues struct target_elf_prstatus {
3729a2547a13SLaurent Desnogues     struct target_elf_siginfo pr_info;      /* Info associated with signal */
37301ddd592fSPaolo Bonzini     abi_short          pr_cursig;    /* Current signal */
3731ca98ac83SPaolo Bonzini     abi_ulong          pr_sigpend;   /* XXX */
3732ca98ac83SPaolo Bonzini     abi_ulong          pr_sighold;   /* XXX */
3733c227f099SAnthony Liguori     target_pid_t       pr_pid;
3734c227f099SAnthony Liguori     target_pid_t       pr_ppid;
3735c227f099SAnthony Liguori     target_pid_t       pr_pgrp;
3736c227f099SAnthony Liguori     target_pid_t       pr_sid;
3737edf8e2afSMika Westerberg     struct target_timeval pr_utime;  /* XXX User time */
3738edf8e2afSMika Westerberg     struct target_timeval pr_stime;  /* XXX System time */
3739edf8e2afSMika Westerberg     struct target_timeval pr_cutime; /* XXX Cumulative user time */
3740edf8e2afSMika Westerberg     struct target_timeval pr_cstime; /* XXX Cumulative system time */
3741c227f099SAnthony Liguori     target_elf_gregset_t      pr_reg;       /* GP registers */
3742f8fd4fc4SPaolo Bonzini     abi_int            pr_fpvalid;   /* XXX */
3743edf8e2afSMika Westerberg };
3744edf8e2afSMika Westerberg 
3745edf8e2afSMika Westerberg #define ELF_PRARGSZ     (80) /* Number of chars for args */
3746edf8e2afSMika Westerberg 
3747a2547a13SLaurent Desnogues struct target_elf_prpsinfo {
3748edf8e2afSMika Westerberg     char         pr_state;       /* numeric process state */
3749edf8e2afSMika Westerberg     char         pr_sname;       /* char for pr_state */
3750edf8e2afSMika Westerberg     char         pr_zomb;        /* zombie */
3751edf8e2afSMika Westerberg     char         pr_nice;        /* nice val */
3752ca98ac83SPaolo Bonzini     abi_ulong    pr_flag;        /* flags */
3753c227f099SAnthony Liguori     target_uid_t pr_uid;
3754c227f099SAnthony Liguori     target_gid_t pr_gid;
3755c227f099SAnthony Liguori     target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
3756edf8e2afSMika Westerberg     /* Lots missing */
3757d7eb2b92SAlistair Francis     char    pr_fname[16] QEMU_NONSTRING; /* filename of executable */
3758edf8e2afSMika Westerberg     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
3759edf8e2afSMika Westerberg };
3760edf8e2afSMika Westerberg 
3761edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */
3762edf8e2afSMika Westerberg struct elf_thread_status {
376372cf2d4fSBlue Swirl     QTAILQ_ENTRY(elf_thread_status)  ets_link;
3764a2547a13SLaurent Desnogues     struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
3765edf8e2afSMika Westerberg #if 0
3766edf8e2afSMika Westerberg     elf_fpregset_t fpu;             /* NT_PRFPREG */
3767edf8e2afSMika Westerberg     struct task_struct *thread;
3768edf8e2afSMika Westerberg     elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */
3769edf8e2afSMika Westerberg #endif
3770edf8e2afSMika Westerberg     struct memelfnote notes[1];
3771edf8e2afSMika Westerberg     int num_notes;
3772edf8e2afSMika Westerberg };
3773edf8e2afSMika Westerberg 
3774edf8e2afSMika Westerberg struct elf_note_info {
3775edf8e2afSMika Westerberg     struct memelfnote   *notes;
3776a2547a13SLaurent Desnogues     struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
3777a2547a13SLaurent Desnogues     struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
3778edf8e2afSMika Westerberg 
3779b58deb34SPaolo Bonzini     QTAILQ_HEAD(, elf_thread_status) thread_list;
3780edf8e2afSMika Westerberg #if 0
3781edf8e2afSMika Westerberg     /*
3782edf8e2afSMika Westerberg      * Current version of ELF coredump doesn't support
3783edf8e2afSMika Westerberg      * dumping fp regs etc.
3784edf8e2afSMika Westerberg      */
3785edf8e2afSMika Westerberg     elf_fpregset_t *fpu;
3786edf8e2afSMika Westerberg     elf_fpxregset_t *xfpu;
3787edf8e2afSMika Westerberg     int thread_status_size;
3788edf8e2afSMika Westerberg #endif
3789edf8e2afSMika Westerberg     int notes_size;
3790edf8e2afSMika Westerberg     int numnote;
3791edf8e2afSMika Westerberg };
3792edf8e2afSMika Westerberg 
3793edf8e2afSMika Westerberg struct vm_area_struct {
37941a1c4db9SMikhail Ilyin     target_ulong   vma_start;  /* start vaddr of memory region */
37951a1c4db9SMikhail Ilyin     target_ulong   vma_end;    /* end vaddr of memory region */
3796edf8e2afSMika Westerberg     abi_ulong      vma_flags;  /* protection etc. flags for the region */
379772cf2d4fSBlue Swirl     QTAILQ_ENTRY(vm_area_struct) vma_link;
3798edf8e2afSMika Westerberg };
3799edf8e2afSMika Westerberg 
3800edf8e2afSMika Westerberg struct mm_struct {
380172cf2d4fSBlue Swirl     QTAILQ_HEAD(, vm_area_struct) mm_mmap;
3802edf8e2afSMika Westerberg     int mm_count;           /* number of mappings */
3803edf8e2afSMika Westerberg };
3804edf8e2afSMika Westerberg 
3805edf8e2afSMika Westerberg static struct mm_struct *vma_init(void);
3806edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *);
38071a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *, target_ulong,
38081a1c4db9SMikhail Ilyin                            target_ulong, abi_ulong);
3809edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *);
3810edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *);
3811edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *);
3812edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *);
38131a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end,
3814edf8e2afSMika Westerberg                       unsigned long flags);
3815edf8e2afSMika Westerberg 
3816edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
3817edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int,
3818edf8e2afSMika Westerberg                       unsigned int, void *);
3819a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
3820a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
3821edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *);
3822edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
3823edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *);
3824edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *);
38259349b4f9SAndreas Färber static int fill_note_info(struct elf_note_info *, long, const CPUArchState *);
38269349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *, const CPUArchState *);
3827edf8e2afSMika Westerberg 
3828edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t);
3829edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int);
3830edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int);
3831edf8e2afSMika Westerberg 
3832edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
3833a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus)
3834edf8e2afSMika Westerberg {
3835ca98ac83SPaolo Bonzini     prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo);
3836ca98ac83SPaolo Bonzini     prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code);
3837ca98ac83SPaolo Bonzini     prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno);
3838edf8e2afSMika Westerberg     prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
3839ca98ac83SPaolo Bonzini     prstatus->pr_sigpend = tswapal(prstatus->pr_sigpend);
3840ca98ac83SPaolo Bonzini     prstatus->pr_sighold = tswapal(prstatus->pr_sighold);
3841edf8e2afSMika Westerberg     prstatus->pr_pid = tswap32(prstatus->pr_pid);
3842edf8e2afSMika Westerberg     prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
3843edf8e2afSMika Westerberg     prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
3844edf8e2afSMika Westerberg     prstatus->pr_sid = tswap32(prstatus->pr_sid);
3845edf8e2afSMika Westerberg     /* cpu times are not filled, so we skip them */
3846edf8e2afSMika Westerberg     /* regs should be in correct format already */
3847edf8e2afSMika Westerberg     prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
3848edf8e2afSMika Westerberg }
3849edf8e2afSMika Westerberg 
3850a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
3851edf8e2afSMika Westerberg {
3852ca98ac83SPaolo Bonzini     psinfo->pr_flag = tswapal(psinfo->pr_flag);
3853edf8e2afSMika Westerberg     psinfo->pr_uid = tswap16(psinfo->pr_uid);
3854edf8e2afSMika Westerberg     psinfo->pr_gid = tswap16(psinfo->pr_gid);
3855edf8e2afSMika Westerberg     psinfo->pr_pid = tswap32(psinfo->pr_pid);
3856edf8e2afSMika Westerberg     psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
3857edf8e2afSMika Westerberg     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
3858edf8e2afSMika Westerberg     psinfo->pr_sid = tswap32(psinfo->pr_sid);
3859edf8e2afSMika Westerberg }
3860991f8f0cSRichard Henderson 
3861991f8f0cSRichard Henderson static void bswap_note(struct elf_note *en)
3862991f8f0cSRichard Henderson {
3863991f8f0cSRichard Henderson     bswap32s(&en->n_namesz);
3864991f8f0cSRichard Henderson     bswap32s(&en->n_descsz);
3865991f8f0cSRichard Henderson     bswap32s(&en->n_type);
3866991f8f0cSRichard Henderson }
3867991f8f0cSRichard Henderson #else
3868991f8f0cSRichard Henderson static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
3869991f8f0cSRichard Henderson static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
3870991f8f0cSRichard Henderson static inline void bswap_note(struct elf_note *en) { }
3871edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
3872edf8e2afSMika Westerberg 
3873edf8e2afSMika Westerberg /*
3874edf8e2afSMika Westerberg  * Minimal support for linux memory regions.  These are needed
3875edf8e2afSMika Westerberg  * when we are finding out what memory exactly belongs to
3876edf8e2afSMika Westerberg  * emulated process.  No locks needed here, as long as
3877edf8e2afSMika Westerberg  * thread that received the signal is stopped.
3878edf8e2afSMika Westerberg  */
3879edf8e2afSMika Westerberg 
3880edf8e2afSMika Westerberg static struct mm_struct *vma_init(void)
3881edf8e2afSMika Westerberg {
3882edf8e2afSMika Westerberg     struct mm_struct *mm;
3883edf8e2afSMika Westerberg 
38847267c094SAnthony Liguori     if ((mm = g_malloc(sizeof (*mm))) == NULL)
3885edf8e2afSMika Westerberg         return (NULL);
3886edf8e2afSMika Westerberg 
3887edf8e2afSMika Westerberg     mm->mm_count = 0;
388872cf2d4fSBlue Swirl     QTAILQ_INIT(&mm->mm_mmap);
3889edf8e2afSMika Westerberg 
3890edf8e2afSMika Westerberg     return (mm);
3891edf8e2afSMika Westerberg }
3892edf8e2afSMika Westerberg 
3893edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm)
3894edf8e2afSMika Westerberg {
3895edf8e2afSMika Westerberg     struct vm_area_struct *vma;
3896edf8e2afSMika Westerberg 
3897edf8e2afSMika Westerberg     while ((vma = vma_first(mm)) != NULL) {
389872cf2d4fSBlue Swirl         QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
38997267c094SAnthony Liguori         g_free(vma);
3900edf8e2afSMika Westerberg     }
39017267c094SAnthony Liguori     g_free(mm);
3902edf8e2afSMika Westerberg }
3903edf8e2afSMika Westerberg 
39041a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *mm, target_ulong start,
39051a1c4db9SMikhail Ilyin                            target_ulong end, abi_ulong flags)
3906edf8e2afSMika Westerberg {
3907edf8e2afSMika Westerberg     struct vm_area_struct *vma;
3908edf8e2afSMika Westerberg 
39097267c094SAnthony Liguori     if ((vma = g_malloc0(sizeof (*vma))) == NULL)
3910edf8e2afSMika Westerberg         return (-1);
3911edf8e2afSMika Westerberg 
3912edf8e2afSMika Westerberg     vma->vma_start = start;
3913edf8e2afSMika Westerberg     vma->vma_end = end;
3914edf8e2afSMika Westerberg     vma->vma_flags = flags;
3915edf8e2afSMika Westerberg 
391672cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
3917edf8e2afSMika Westerberg     mm->mm_count++;
3918edf8e2afSMika Westerberg 
3919edf8e2afSMika Westerberg     return (0);
3920edf8e2afSMika Westerberg }
3921edf8e2afSMika Westerberg 
3922edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm)
3923edf8e2afSMika Westerberg {
392472cf2d4fSBlue Swirl     return (QTAILQ_FIRST(&mm->mm_mmap));
3925edf8e2afSMika Westerberg }
3926edf8e2afSMika Westerberg 
3927edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
3928edf8e2afSMika Westerberg {
392972cf2d4fSBlue Swirl     return (QTAILQ_NEXT(vma, vma_link));
3930edf8e2afSMika Westerberg }
3931edf8e2afSMika Westerberg 
3932edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm)
3933edf8e2afSMika Westerberg {
3934edf8e2afSMika Westerberg     return (mm->mm_count);
3935edf8e2afSMika Westerberg }
3936edf8e2afSMika Westerberg 
3937edf8e2afSMika Westerberg /*
3938edf8e2afSMika Westerberg  * Calculate file (dump) size of given memory region.
3939edf8e2afSMika Westerberg  */
3940edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
3941edf8e2afSMika Westerberg {
3942edf8e2afSMika Westerberg     /* if we cannot even read the first page, skip it */
3943c7169b02SRichard Henderson     if (!access_ok_untagged(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
3944edf8e2afSMika Westerberg         return (0);
3945edf8e2afSMika Westerberg 
3946edf8e2afSMika Westerberg     /*
3947edf8e2afSMika Westerberg      * Usually we don't dump executable pages as they contain
3948edf8e2afSMika Westerberg      * non-writable code that debugger can read directly from
3949edf8e2afSMika Westerberg      * target library etc.  However, thread stacks are marked
3950edf8e2afSMika Westerberg      * also executable so we read in first page of given region
3951edf8e2afSMika Westerberg      * and check whether it contains elf header.  If there is
3952edf8e2afSMika Westerberg      * no elf header, we dump it.
3953edf8e2afSMika Westerberg      */
3954edf8e2afSMika Westerberg     if (vma->vma_flags & PROT_EXEC) {
3955edf8e2afSMika Westerberg         char page[TARGET_PAGE_SIZE];
3956edf8e2afSMika Westerberg 
3957022625a8SPeter Maydell         if (copy_from_user(page, vma->vma_start, sizeof (page))) {
3958022625a8SPeter Maydell             return 0;
3959022625a8SPeter Maydell         }
3960edf8e2afSMika Westerberg         if ((page[EI_MAG0] == ELFMAG0) &&
3961edf8e2afSMika Westerberg             (page[EI_MAG1] == ELFMAG1) &&
3962edf8e2afSMika Westerberg             (page[EI_MAG2] == ELFMAG2) &&
3963edf8e2afSMika Westerberg             (page[EI_MAG3] == ELFMAG3)) {
3964edf8e2afSMika Westerberg             /*
3965edf8e2afSMika Westerberg              * Mappings are possibly from ELF binary.  Don't dump
3966edf8e2afSMika Westerberg              * them.
3967edf8e2afSMika Westerberg              */
3968edf8e2afSMika Westerberg             return (0);
3969edf8e2afSMika Westerberg         }
3970edf8e2afSMika Westerberg     }
3971edf8e2afSMika Westerberg 
3972edf8e2afSMika Westerberg     return (vma->vma_end - vma->vma_start);
3973edf8e2afSMika Westerberg }
3974edf8e2afSMika Westerberg 
39751a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end,
3976edf8e2afSMika Westerberg                       unsigned long flags)
3977edf8e2afSMika Westerberg {
3978edf8e2afSMika Westerberg     struct mm_struct *mm = (struct mm_struct *)priv;
3979edf8e2afSMika Westerberg 
3980edf8e2afSMika Westerberg     vma_add_mapping(mm, start, end, flags);
3981edf8e2afSMika Westerberg     return (0);
3982edf8e2afSMika Westerberg }
3983edf8e2afSMika Westerberg 
3984edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type,
3985edf8e2afSMika Westerberg                       unsigned int sz, void *data)
3986edf8e2afSMika Westerberg {
3987edf8e2afSMika Westerberg     unsigned int namesz;
3988edf8e2afSMika Westerberg 
3989edf8e2afSMika Westerberg     namesz = strlen(name) + 1;
3990edf8e2afSMika Westerberg     note->name = name;
3991edf8e2afSMika Westerberg     note->namesz = namesz;
3992edf8e2afSMika Westerberg     note->namesz_rounded = roundup(namesz, sizeof (int32_t));
3993edf8e2afSMika Westerberg     note->type = type;
399480f5ce75SLaurent Vivier     note->datasz = sz;
399580f5ce75SLaurent Vivier     note->datasz_rounded = roundup(sz, sizeof (int32_t));
399680f5ce75SLaurent Vivier 
3997edf8e2afSMika Westerberg     note->data = data;
3998edf8e2afSMika Westerberg 
3999edf8e2afSMika Westerberg     /*
4000edf8e2afSMika Westerberg      * We calculate rounded up note size here as specified by
4001edf8e2afSMika Westerberg      * ELF document.
4002edf8e2afSMika Westerberg      */
4003edf8e2afSMika Westerberg     note->notesz = sizeof (struct elf_note) +
400480f5ce75SLaurent Vivier         note->namesz_rounded + note->datasz_rounded;
4005edf8e2afSMika Westerberg }
4006edf8e2afSMika Westerberg 
4007edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
4008edf8e2afSMika Westerberg                             uint32_t flags)
4009edf8e2afSMika Westerberg {
4010edf8e2afSMika Westerberg     (void) memset(elf, 0, sizeof(*elf));
4011edf8e2afSMika Westerberg 
4012edf8e2afSMika Westerberg     (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
4013edf8e2afSMika Westerberg     elf->e_ident[EI_CLASS] = ELF_CLASS;
4014edf8e2afSMika Westerberg     elf->e_ident[EI_DATA] = ELF_DATA;
4015edf8e2afSMika Westerberg     elf->e_ident[EI_VERSION] = EV_CURRENT;
4016edf8e2afSMika Westerberg     elf->e_ident[EI_OSABI] = ELF_OSABI;
4017edf8e2afSMika Westerberg 
4018edf8e2afSMika Westerberg     elf->e_type = ET_CORE;
4019edf8e2afSMika Westerberg     elf->e_machine = machine;
4020edf8e2afSMika Westerberg     elf->e_version = EV_CURRENT;
4021edf8e2afSMika Westerberg     elf->e_phoff = sizeof(struct elfhdr);
4022edf8e2afSMika Westerberg     elf->e_flags = flags;
4023edf8e2afSMika Westerberg     elf->e_ehsize = sizeof(struct elfhdr);
4024edf8e2afSMika Westerberg     elf->e_phentsize = sizeof(struct elf_phdr);
4025edf8e2afSMika Westerberg     elf->e_phnum = segs;
4026edf8e2afSMika Westerberg 
4027edf8e2afSMika Westerberg     bswap_ehdr(elf);
4028edf8e2afSMika Westerberg }
4029edf8e2afSMika Westerberg 
4030edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
4031edf8e2afSMika Westerberg {
4032edf8e2afSMika Westerberg     phdr->p_type = PT_NOTE;
4033edf8e2afSMika Westerberg     phdr->p_offset = offset;
4034edf8e2afSMika Westerberg     phdr->p_vaddr = 0;
4035edf8e2afSMika Westerberg     phdr->p_paddr = 0;
4036edf8e2afSMika Westerberg     phdr->p_filesz = sz;
4037edf8e2afSMika Westerberg     phdr->p_memsz = 0;
4038edf8e2afSMika Westerberg     phdr->p_flags = 0;
4039edf8e2afSMika Westerberg     phdr->p_align = 0;
4040edf8e2afSMika Westerberg 
4041991f8f0cSRichard Henderson     bswap_phdr(phdr, 1);
4042edf8e2afSMika Westerberg }
4043edf8e2afSMika Westerberg 
4044edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note)
4045edf8e2afSMika Westerberg {
4046edf8e2afSMika Westerberg     return (note->notesz);
4047edf8e2afSMika Westerberg }
4048edf8e2afSMika Westerberg 
4049a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus,
4050edf8e2afSMika Westerberg                           const TaskState *ts, int signr)
4051edf8e2afSMika Westerberg {
4052edf8e2afSMika Westerberg     (void) memset(prstatus, 0, sizeof (*prstatus));
4053edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
4054edf8e2afSMika Westerberg     prstatus->pr_pid = ts->ts_tid;
4055edf8e2afSMika Westerberg     prstatus->pr_ppid = getppid();
4056edf8e2afSMika Westerberg     prstatus->pr_pgrp = getpgrp();
4057edf8e2afSMika Westerberg     prstatus->pr_sid = getsid(0);
4058edf8e2afSMika Westerberg 
4059edf8e2afSMika Westerberg     bswap_prstatus(prstatus);
4060edf8e2afSMika Westerberg }
4061edf8e2afSMika Westerberg 
4062a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
4063edf8e2afSMika Westerberg {
4064900cfbcaSJim Meyering     char *base_filename;
4065edf8e2afSMika Westerberg     unsigned int i, len;
4066edf8e2afSMika Westerberg 
4067edf8e2afSMika Westerberg     (void) memset(psinfo, 0, sizeof (*psinfo));
4068edf8e2afSMika Westerberg 
40695f779a3aSIlya Leoshkevich     len = ts->info->env_strings - ts->info->arg_strings;
4070edf8e2afSMika Westerberg     if (len >= ELF_PRARGSZ)
4071edf8e2afSMika Westerberg         len = ELF_PRARGSZ - 1;
40725f779a3aSIlya Leoshkevich     if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_strings, len)) {
4073edf8e2afSMika Westerberg         return -EFAULT;
40745f779a3aSIlya Leoshkevich     }
4075edf8e2afSMika Westerberg     for (i = 0; i < len; i++)
4076edf8e2afSMika Westerberg         if (psinfo->pr_psargs[i] == 0)
4077edf8e2afSMika Westerberg             psinfo->pr_psargs[i] = ' ';
4078edf8e2afSMika Westerberg     psinfo->pr_psargs[len] = 0;
4079edf8e2afSMika Westerberg 
4080edf8e2afSMika Westerberg     psinfo->pr_pid = getpid();
4081edf8e2afSMika Westerberg     psinfo->pr_ppid = getppid();
4082edf8e2afSMika Westerberg     psinfo->pr_pgrp = getpgrp();
4083edf8e2afSMika Westerberg     psinfo->pr_sid = getsid(0);
4084edf8e2afSMika Westerberg     psinfo->pr_uid = getuid();
4085edf8e2afSMika Westerberg     psinfo->pr_gid = getgid();
4086edf8e2afSMika Westerberg 
4087900cfbcaSJim Meyering     base_filename = g_path_get_basename(ts->bprm->filename);
4088900cfbcaSJim Meyering     /*
4089900cfbcaSJim Meyering      * Using strncpy here is fine: at max-length,
4090900cfbcaSJim Meyering      * this field is not NUL-terminated.
4091900cfbcaSJim Meyering      */
4092edf8e2afSMika Westerberg     (void) strncpy(psinfo->pr_fname, base_filename,
4093edf8e2afSMika Westerberg                    sizeof(psinfo->pr_fname));
4094edf8e2afSMika Westerberg 
4095900cfbcaSJim Meyering     g_free(base_filename);
4096edf8e2afSMika Westerberg     bswap_psinfo(psinfo);
4097edf8e2afSMika Westerberg     return (0);
4098edf8e2afSMika Westerberg }
4099edf8e2afSMika Westerberg 
4100edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
4101edf8e2afSMika Westerberg {
4102edf8e2afSMika Westerberg     elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
4103edf8e2afSMika Westerberg     elf_addr_t orig_auxv = auxv;
4104edf8e2afSMika Westerberg     void *ptr;
4105125b0f55SAlexander Graf     int len = ts->info->auxv_len;
4106edf8e2afSMika Westerberg 
4107edf8e2afSMika Westerberg     /*
4108edf8e2afSMika Westerberg      * Auxiliary vector is stored in target process stack.  It contains
4109edf8e2afSMika Westerberg      * {type, value} pairs that we need to dump into note.  This is not
4110edf8e2afSMika Westerberg      * strictly necessary but we do it here for sake of completeness.
4111edf8e2afSMika Westerberg      */
4112edf8e2afSMika Westerberg 
4113edf8e2afSMika Westerberg     /* read in whole auxv vector and copy it to memelfnote */
4114edf8e2afSMika Westerberg     ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
4115edf8e2afSMika Westerberg     if (ptr != NULL) {
4116edf8e2afSMika Westerberg         fill_note(note, "CORE", NT_AUXV, len, ptr);
4117edf8e2afSMika Westerberg         unlock_user(ptr, auxv, len);
4118edf8e2afSMika Westerberg     }
4119edf8e2afSMika Westerberg }
4120edf8e2afSMika Westerberg 
4121edf8e2afSMika Westerberg /*
4122edf8e2afSMika Westerberg  * Constructs name of coredump file.  We have following convention
4123edf8e2afSMika Westerberg  * for the name:
4124edf8e2afSMika Westerberg  *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
4125edf8e2afSMika Westerberg  *
412668af19adSDaniel P. Berrangé  * Returns the filename
4127edf8e2afSMika Westerberg  */
412868af19adSDaniel P. Berrangé static char *core_dump_filename(const TaskState *ts)
4129edf8e2afSMika Westerberg {
413068af19adSDaniel P. Berrangé     g_autoptr(GDateTime) now = g_date_time_new_now_local();
413168af19adSDaniel P. Berrangé     g_autofree char *nowstr = g_date_time_format(now, "%Y%m%d-%H%M%S");
413268af19adSDaniel P. Berrangé     g_autofree char *base_filename = g_path_get_basename(ts->bprm->filename);
4133edf8e2afSMika Westerberg 
413468af19adSDaniel P. Berrangé     return g_strdup_printf("qemu_%s_%s_%d.core",
413568af19adSDaniel P. Berrangé                            base_filename, nowstr, (int)getpid());
4136edf8e2afSMika Westerberg }
4137edf8e2afSMika Westerberg 
4138edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size)
4139edf8e2afSMika Westerberg {
4140edf8e2afSMika Westerberg     const char *bufp = (const char *)ptr;
4141edf8e2afSMika Westerberg     ssize_t bytes_written, bytes_left;
4142edf8e2afSMika Westerberg     struct rlimit dumpsize;
4143edf8e2afSMika Westerberg     off_t pos;
4144edf8e2afSMika Westerberg 
4145edf8e2afSMika Westerberg     bytes_written = 0;
4146edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
4147edf8e2afSMika Westerberg     if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
4148edf8e2afSMika Westerberg         if (errno == ESPIPE) { /* not a seekable stream */
4149edf8e2afSMika Westerberg             bytes_left = size;
4150edf8e2afSMika Westerberg         } else {
4151edf8e2afSMika Westerberg             return pos;
4152edf8e2afSMika Westerberg         }
4153edf8e2afSMika Westerberg     } else {
4154edf8e2afSMika Westerberg         if (dumpsize.rlim_cur <= pos) {
4155edf8e2afSMika Westerberg             return -1;
4156edf8e2afSMika Westerberg         } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
4157edf8e2afSMika Westerberg             bytes_left = size;
4158edf8e2afSMika Westerberg         } else {
4159edf8e2afSMika Westerberg             size_t limit_left=dumpsize.rlim_cur - pos;
4160edf8e2afSMika Westerberg             bytes_left = limit_left >= size ? size : limit_left ;
4161edf8e2afSMika Westerberg         }
4162edf8e2afSMika Westerberg     }
4163edf8e2afSMika Westerberg 
4164edf8e2afSMika Westerberg     /*
4165edf8e2afSMika Westerberg      * In normal conditions, single write(2) should do but
4166edf8e2afSMika Westerberg      * in case of socket etc. this mechanism is more portable.
4167edf8e2afSMika Westerberg      */
4168edf8e2afSMika Westerberg     do {
4169edf8e2afSMika Westerberg         bytes_written = write(fd, bufp, bytes_left);
4170edf8e2afSMika Westerberg         if (bytes_written < 0) {
4171edf8e2afSMika Westerberg             if (errno == EINTR)
4172edf8e2afSMika Westerberg                 continue;
4173edf8e2afSMika Westerberg             return (-1);
4174edf8e2afSMika Westerberg         } else if (bytes_written == 0) { /* eof */
4175edf8e2afSMika Westerberg             return (-1);
4176edf8e2afSMika Westerberg         }
4177edf8e2afSMika Westerberg         bufp += bytes_written;
4178edf8e2afSMika Westerberg         bytes_left -= bytes_written;
4179edf8e2afSMika Westerberg     } while (bytes_left > 0);
4180edf8e2afSMika Westerberg 
4181edf8e2afSMika Westerberg     return (0);
4182edf8e2afSMika Westerberg }
4183edf8e2afSMika Westerberg 
4184edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd)
4185edf8e2afSMika Westerberg {
4186edf8e2afSMika Westerberg     struct elf_note en;
4187edf8e2afSMika Westerberg 
4188edf8e2afSMika Westerberg     en.n_namesz = men->namesz;
4189edf8e2afSMika Westerberg     en.n_type = men->type;
4190edf8e2afSMika Westerberg     en.n_descsz = men->datasz;
4191edf8e2afSMika Westerberg 
4192edf8e2afSMika Westerberg     bswap_note(&en);
4193edf8e2afSMika Westerberg 
4194edf8e2afSMika Westerberg     if (dump_write(fd, &en, sizeof(en)) != 0)
4195edf8e2afSMika Westerberg         return (-1);
4196edf8e2afSMika Westerberg     if (dump_write(fd, men->name, men->namesz_rounded) != 0)
4197edf8e2afSMika Westerberg         return (-1);
419880f5ce75SLaurent Vivier     if (dump_write(fd, men->data, men->datasz_rounded) != 0)
4199edf8e2afSMika Westerberg         return (-1);
4200edf8e2afSMika Westerberg 
4201edf8e2afSMika Westerberg     return (0);
4202edf8e2afSMika Westerberg }
4203edf8e2afSMika Westerberg 
42049349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env)
4205edf8e2afSMika Westerberg {
420629a0af61SRichard Henderson     CPUState *cpu = env_cpu((CPUArchState *)env);
42070429a971SAndreas Färber     TaskState *ts = (TaskState *)cpu->opaque;
4208edf8e2afSMika Westerberg     struct elf_thread_status *ets;
4209edf8e2afSMika Westerberg 
42107267c094SAnthony Liguori     ets = g_malloc0(sizeof (*ets));
4211edf8e2afSMika Westerberg     ets->num_notes = 1; /* only prstatus is dumped */
4212edf8e2afSMika Westerberg     fill_prstatus(&ets->prstatus, ts, 0);
4213edf8e2afSMika Westerberg     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
4214edf8e2afSMika Westerberg     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
4215edf8e2afSMika Westerberg               &ets->prstatus);
4216edf8e2afSMika Westerberg 
421772cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
4218edf8e2afSMika Westerberg 
4219edf8e2afSMika Westerberg     info->notes_size += note_size(&ets->notes[0]);
4220edf8e2afSMika Westerberg }
4221edf8e2afSMika Westerberg 
42226afafa86SPeter Maydell static void init_note_info(struct elf_note_info *info)
42236afafa86SPeter Maydell {
42246afafa86SPeter Maydell     /* Initialize the elf_note_info structure so that it is at
42256afafa86SPeter Maydell      * least safe to call free_note_info() on it. Must be
42266afafa86SPeter Maydell      * called before calling fill_note_info().
42276afafa86SPeter Maydell      */
42286afafa86SPeter Maydell     memset(info, 0, sizeof (*info));
42296afafa86SPeter Maydell     QTAILQ_INIT(&info->thread_list);
42306afafa86SPeter Maydell }
42316afafa86SPeter Maydell 
4232edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info,
42339349b4f9SAndreas Färber                           long signr, const CPUArchState *env)
4234edf8e2afSMika Westerberg {
4235edf8e2afSMika Westerberg #define NUMNOTES 3
423629a0af61SRichard Henderson     CPUState *cpu = env_cpu((CPUArchState *)env);
42370429a971SAndreas Färber     TaskState *ts = (TaskState *)cpu->opaque;
4238edf8e2afSMika Westerberg     int i;
4239edf8e2afSMika Westerberg 
4240c78d65e8SMarkus Armbruster     info->notes = g_new0(struct memelfnote, NUMNOTES);
4241edf8e2afSMika Westerberg     if (info->notes == NULL)
4242edf8e2afSMika Westerberg         return (-ENOMEM);
42437267c094SAnthony Liguori     info->prstatus = g_malloc0(sizeof (*info->prstatus));
4244edf8e2afSMika Westerberg     if (info->prstatus == NULL)
4245edf8e2afSMika Westerberg         return (-ENOMEM);
42467267c094SAnthony Liguori     info->psinfo = g_malloc0(sizeof (*info->psinfo));
4247edf8e2afSMika Westerberg     if (info->prstatus == NULL)
4248edf8e2afSMika Westerberg         return (-ENOMEM);
4249edf8e2afSMika Westerberg 
4250edf8e2afSMika Westerberg     /*
4251edf8e2afSMika Westerberg      * First fill in status (and registers) of current thread
4252edf8e2afSMika Westerberg      * including process info & aux vector.
4253edf8e2afSMika Westerberg      */
4254edf8e2afSMika Westerberg     fill_prstatus(info->prstatus, ts, signr);
4255edf8e2afSMika Westerberg     elf_core_copy_regs(&info->prstatus->pr_reg, env);
4256edf8e2afSMika Westerberg     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
4257edf8e2afSMika Westerberg               sizeof (*info->prstatus), info->prstatus);
4258edf8e2afSMika Westerberg     fill_psinfo(info->psinfo, ts);
4259edf8e2afSMika Westerberg     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
4260edf8e2afSMika Westerberg               sizeof (*info->psinfo), info->psinfo);
4261edf8e2afSMika Westerberg     fill_auxv_note(&info->notes[2], ts);
4262edf8e2afSMika Westerberg     info->numnote = 3;
4263edf8e2afSMika Westerberg 
4264edf8e2afSMika Westerberg     info->notes_size = 0;
4265edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
4266edf8e2afSMika Westerberg         info->notes_size += note_size(&info->notes[i]);
4267edf8e2afSMika Westerberg 
4268edf8e2afSMika Westerberg     /* read and fill status of all threads */
4269370ed600SJamie Iles     WITH_QEMU_LOCK_GUARD(&qemu_cpu_list_lock) {
4270bdc44640SAndreas Färber         CPU_FOREACH(cpu) {
4271a2247f8eSAndreas Färber             if (cpu == thread_cpu) {
4272edf8e2afSMika Westerberg                 continue;
4273182735efSAndreas Färber             }
42742f6f4290SPhilippe Mathieu-Daudé             fill_thread_info(info, cpu->env_ptr);
4275edf8e2afSMika Westerberg         }
4276370ed600SJamie Iles     }
4277edf8e2afSMika Westerberg 
4278edf8e2afSMika Westerberg     return (0);
4279edf8e2afSMika Westerberg }
4280edf8e2afSMika Westerberg 
4281edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info)
4282edf8e2afSMika Westerberg {
4283edf8e2afSMika Westerberg     struct elf_thread_status *ets;
4284edf8e2afSMika Westerberg 
428572cf2d4fSBlue Swirl     while (!QTAILQ_EMPTY(&info->thread_list)) {
428672cf2d4fSBlue Swirl         ets = QTAILQ_FIRST(&info->thread_list);
428772cf2d4fSBlue Swirl         QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
42887267c094SAnthony Liguori         g_free(ets);
4289edf8e2afSMika Westerberg     }
4290edf8e2afSMika Westerberg 
42917267c094SAnthony Liguori     g_free(info->prstatus);
42927267c094SAnthony Liguori     g_free(info->psinfo);
42937267c094SAnthony Liguori     g_free(info->notes);
4294edf8e2afSMika Westerberg }
4295edf8e2afSMika Westerberg 
4296edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd)
4297edf8e2afSMika Westerberg {
4298edf8e2afSMika Westerberg     struct elf_thread_status *ets;
4299edf8e2afSMika Westerberg     int i, error = 0;
4300edf8e2afSMika Westerberg 
4301edf8e2afSMika Westerberg     /* write prstatus, psinfo and auxv for current thread */
4302edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
4303edf8e2afSMika Westerberg         if ((error = write_note(&info->notes[i], fd)) != 0)
4304edf8e2afSMika Westerberg             return (error);
4305edf8e2afSMika Westerberg 
4306edf8e2afSMika Westerberg     /* write prstatus for each thread */
430752a53afeSEmilio G. Cota     QTAILQ_FOREACH(ets, &info->thread_list, ets_link) {
4308edf8e2afSMika Westerberg         if ((error = write_note(&ets->notes[0], fd)) != 0)
4309edf8e2afSMika Westerberg             return (error);
4310edf8e2afSMika Westerberg     }
4311edf8e2afSMika Westerberg 
4312edf8e2afSMika Westerberg     return (0);
4313edf8e2afSMika Westerberg }
4314edf8e2afSMika Westerberg 
4315edf8e2afSMika Westerberg /*
4316edf8e2afSMika Westerberg  * Write out ELF coredump.
4317edf8e2afSMika Westerberg  *
4318edf8e2afSMika Westerberg  * See documentation of ELF object file format in:
4319edf8e2afSMika Westerberg  * http://www.caldera.com/developers/devspecs/gabi41.pdf
4320edf8e2afSMika Westerberg  *
4321edf8e2afSMika Westerberg  * Coredump format in linux is following:
4322edf8e2afSMika Westerberg  *
4323edf8e2afSMika Westerberg  * 0   +----------------------+         \
4324edf8e2afSMika Westerberg  *     | ELF header           | ET_CORE  |
4325edf8e2afSMika Westerberg  *     +----------------------+          |
4326edf8e2afSMika Westerberg  *     | ELF program headers  |          |--- headers
4327edf8e2afSMika Westerberg  *     | - NOTE section       |          |
4328edf8e2afSMika Westerberg  *     | - PT_LOAD sections   |          |
4329edf8e2afSMika Westerberg  *     +----------------------+         /
4330edf8e2afSMika Westerberg  *     | NOTEs:               |
4331edf8e2afSMika Westerberg  *     | - NT_PRSTATUS        |
4332edf8e2afSMika Westerberg  *     | - NT_PRSINFO         |
4333edf8e2afSMika Westerberg  *     | - NT_AUXV            |
4334edf8e2afSMika Westerberg  *     +----------------------+ <-- aligned to target page
4335edf8e2afSMika Westerberg  *     | Process memory dump  |
4336edf8e2afSMika Westerberg  *     :                      :
4337edf8e2afSMika Westerberg  *     .                      .
4338edf8e2afSMika Westerberg  *     :                      :
4339edf8e2afSMika Westerberg  *     |                      |
4340edf8e2afSMika Westerberg  *     +----------------------+
4341edf8e2afSMika Westerberg  *
4342edf8e2afSMika Westerberg  * NT_PRSTATUS -> struct elf_prstatus (per thread)
4343edf8e2afSMika Westerberg  * NT_PRSINFO  -> struct elf_prpsinfo
4344edf8e2afSMika Westerberg  * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
4345edf8e2afSMika Westerberg  *
4346edf8e2afSMika Westerberg  * Format follows System V format as close as possible.  Current
4347edf8e2afSMika Westerberg  * version limitations are as follows:
4348edf8e2afSMika Westerberg  *     - no floating point registers are dumped
4349edf8e2afSMika Westerberg  *
4350edf8e2afSMika Westerberg  * Function returns 0 in case of success, negative errno otherwise.
4351edf8e2afSMika Westerberg  *
4352edf8e2afSMika Westerberg  * TODO: make this work also during runtime: it should be
4353edf8e2afSMika Westerberg  * possible to force coredump from running process and then
4354edf8e2afSMika Westerberg  * continue processing.  For example qemu could set up SIGUSR2
4355edf8e2afSMika Westerberg  * handler (provided that target process haven't registered
4356edf8e2afSMika Westerberg  * handler for that) that does the dump when signal is received.
4357edf8e2afSMika Westerberg  */
43589349b4f9SAndreas Färber static int elf_core_dump(int signr, const CPUArchState *env)
4359edf8e2afSMika Westerberg {
436029a0af61SRichard Henderson     const CPUState *cpu = env_cpu((CPUArchState *)env);
43610429a971SAndreas Färber     const TaskState *ts = (const TaskState *)cpu->opaque;
4362edf8e2afSMika Westerberg     struct vm_area_struct *vma = NULL;
436368af19adSDaniel P. Berrangé     g_autofree char *corefile = NULL;
4364edf8e2afSMika Westerberg     struct elf_note_info info;
4365edf8e2afSMika Westerberg     struct elfhdr elf;
4366edf8e2afSMika Westerberg     struct elf_phdr phdr;
4367edf8e2afSMika Westerberg     struct rlimit dumpsize;
4368edf8e2afSMika Westerberg     struct mm_struct *mm = NULL;
4369edf8e2afSMika Westerberg     off_t offset = 0, data_offset = 0;
4370edf8e2afSMika Westerberg     int segs = 0;
4371edf8e2afSMika Westerberg     int fd = -1;
4372edf8e2afSMika Westerberg 
43736afafa86SPeter Maydell     init_note_info(&info);
43746afafa86SPeter Maydell 
4375edf8e2afSMika Westerberg     errno = 0;
4376edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
4377edf8e2afSMika Westerberg     if (dumpsize.rlim_cur == 0)
4378edf8e2afSMika Westerberg         return 0;
4379edf8e2afSMika Westerberg 
438068af19adSDaniel P. Berrangé     corefile = core_dump_filename(ts);
4381edf8e2afSMika Westerberg 
4382edf8e2afSMika Westerberg     if ((fd = open(corefile, O_WRONLY | O_CREAT,
4383edf8e2afSMika Westerberg                    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
4384edf8e2afSMika Westerberg         return (-errno);
4385edf8e2afSMika Westerberg 
4386edf8e2afSMika Westerberg     /*
4387edf8e2afSMika Westerberg      * Walk through target process memory mappings and
4388edf8e2afSMika Westerberg      * set up structure containing this information.  After
4389edf8e2afSMika Westerberg      * this point vma_xxx functions can be used.
4390edf8e2afSMika Westerberg      */
4391edf8e2afSMika Westerberg     if ((mm = vma_init()) == NULL)
4392edf8e2afSMika Westerberg         goto out;
4393edf8e2afSMika Westerberg 
4394edf8e2afSMika Westerberg     walk_memory_regions(mm, vma_walker);
4395edf8e2afSMika Westerberg     segs = vma_get_mapping_count(mm);
4396edf8e2afSMika Westerberg 
4397edf8e2afSMika Westerberg     /*
4398edf8e2afSMika Westerberg      * Construct valid coredump ELF header.  We also
4399edf8e2afSMika Westerberg      * add one more segment for notes.
4400edf8e2afSMika Westerberg      */
4401edf8e2afSMika Westerberg     fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
4402edf8e2afSMika Westerberg     if (dump_write(fd, &elf, sizeof (elf)) != 0)
4403edf8e2afSMika Westerberg         goto out;
4404edf8e2afSMika Westerberg 
4405b6af0975SDaniel P. Berrange     /* fill in the in-memory version of notes */
4406edf8e2afSMika Westerberg     if (fill_note_info(&info, signr, env) < 0)
4407edf8e2afSMika Westerberg         goto out;
4408edf8e2afSMika Westerberg 
4409edf8e2afSMika Westerberg     offset += sizeof (elf);                             /* elf header */
4410edf8e2afSMika Westerberg     offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */
4411edf8e2afSMika Westerberg 
4412edf8e2afSMika Westerberg     /* write out notes program header */
4413edf8e2afSMika Westerberg     fill_elf_note_phdr(&phdr, info.notes_size, offset);
4414edf8e2afSMika Westerberg 
4415edf8e2afSMika Westerberg     offset += info.notes_size;
4416edf8e2afSMika Westerberg     if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
4417edf8e2afSMika Westerberg         goto out;
4418edf8e2afSMika Westerberg 
4419edf8e2afSMika Westerberg     /*
4420edf8e2afSMika Westerberg      * ELF specification wants data to start at page boundary so
4421edf8e2afSMika Westerberg      * we align it here.
4422edf8e2afSMika Westerberg      */
442380f5ce75SLaurent Vivier     data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
4424edf8e2afSMika Westerberg 
4425edf8e2afSMika Westerberg     /*
4426edf8e2afSMika Westerberg      * Write program headers for memory regions mapped in
4427edf8e2afSMika Westerberg      * the target process.
4428edf8e2afSMika Westerberg      */
4429edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
4430edf8e2afSMika Westerberg         (void) memset(&phdr, 0, sizeof (phdr));
4431edf8e2afSMika Westerberg 
4432edf8e2afSMika Westerberg         phdr.p_type = PT_LOAD;
4433edf8e2afSMika Westerberg         phdr.p_offset = offset;
4434edf8e2afSMika Westerberg         phdr.p_vaddr = vma->vma_start;
4435edf8e2afSMika Westerberg         phdr.p_paddr = 0;
4436edf8e2afSMika Westerberg         phdr.p_filesz = vma_dump_size(vma);
4437edf8e2afSMika Westerberg         offset += phdr.p_filesz;
4438edf8e2afSMika Westerberg         phdr.p_memsz = vma->vma_end - vma->vma_start;
4439edf8e2afSMika Westerberg         phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
4440edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_WRITE)
4441edf8e2afSMika Westerberg             phdr.p_flags |= PF_W;
4442edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_EXEC)
4443edf8e2afSMika Westerberg             phdr.p_flags |= PF_X;
4444edf8e2afSMika Westerberg         phdr.p_align = ELF_EXEC_PAGESIZE;
4445edf8e2afSMika Westerberg 
444680f5ce75SLaurent Vivier         bswap_phdr(&phdr, 1);
4447772034b6SPeter Maydell         if (dump_write(fd, &phdr, sizeof(phdr)) != 0) {
4448772034b6SPeter Maydell             goto out;
4449772034b6SPeter Maydell         }
4450edf8e2afSMika Westerberg     }
4451edf8e2afSMika Westerberg 
4452edf8e2afSMika Westerberg     /*
4453edf8e2afSMika Westerberg      * Next we write notes just after program headers.  No
4454edf8e2afSMika Westerberg      * alignment needed here.
4455edf8e2afSMika Westerberg      */
4456edf8e2afSMika Westerberg     if (write_note_info(&info, fd) < 0)
4457edf8e2afSMika Westerberg         goto out;
4458edf8e2afSMika Westerberg 
4459edf8e2afSMika Westerberg     /* align data to page boundary */
4460edf8e2afSMika Westerberg     if (lseek(fd, data_offset, SEEK_SET) != data_offset)
4461edf8e2afSMika Westerberg         goto out;
4462edf8e2afSMika Westerberg 
4463edf8e2afSMika Westerberg     /*
4464edf8e2afSMika Westerberg      * Finally we can dump process memory into corefile as well.
4465edf8e2afSMika Westerberg      */
4466edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
4467edf8e2afSMika Westerberg         abi_ulong addr;
4468edf8e2afSMika Westerberg         abi_ulong end;
4469edf8e2afSMika Westerberg 
4470edf8e2afSMika Westerberg         end = vma->vma_start + vma_dump_size(vma);
4471edf8e2afSMika Westerberg 
4472edf8e2afSMika Westerberg         for (addr = vma->vma_start; addr < end;
4473edf8e2afSMika Westerberg              addr += TARGET_PAGE_SIZE) {
4474edf8e2afSMika Westerberg             char page[TARGET_PAGE_SIZE];
4475edf8e2afSMika Westerberg             int error;
4476edf8e2afSMika Westerberg 
4477edf8e2afSMika Westerberg             /*
4478edf8e2afSMika Westerberg              *  Read in page from target process memory and
4479edf8e2afSMika Westerberg              *  write it to coredump file.
4480edf8e2afSMika Westerberg              */
4481edf8e2afSMika Westerberg             error = copy_from_user(page, addr, sizeof (page));
4482edf8e2afSMika Westerberg             if (error != 0) {
448349995e17SAurelien Jarno                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
4484edf8e2afSMika Westerberg                                addr);
4485edf8e2afSMika Westerberg                 errno = -error;
4486edf8e2afSMika Westerberg                 goto out;
4487edf8e2afSMika Westerberg             }
4488edf8e2afSMika Westerberg             if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
4489edf8e2afSMika Westerberg                 goto out;
4490edf8e2afSMika Westerberg         }
4491edf8e2afSMika Westerberg     }
4492edf8e2afSMika Westerberg 
4493edf8e2afSMika Westerberg  out:
4494edf8e2afSMika Westerberg     free_note_info(&info);
4495edf8e2afSMika Westerberg     if (mm != NULL)
4496edf8e2afSMika Westerberg         vma_delete(mm);
4497edf8e2afSMika Westerberg     (void) close(fd);
4498edf8e2afSMika Westerberg 
4499edf8e2afSMika Westerberg     if (errno != 0)
4500edf8e2afSMika Westerberg         return (-errno);
4501edf8e2afSMika Westerberg     return (0);
4502edf8e2afSMika Westerberg }
4503edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
4504edf8e2afSMika Westerberg 
4505e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
4506e5fe0c52Spbrook {
4507e5fe0c52Spbrook     init_thread(regs, infop);
4508e5fe0c52Spbrook }
4509