xref: /qemu/linux-user/elfload.c (revision 030912e01c0385b6b09e76549c1a8a04b624f49a)
131e31b8aSbellard /* This is the Linux kernel elf-loading code, ported into user space */
2d39594e9SPeter Maydell #include "qemu/osdep.h"
3edf8e2afSMika Westerberg #include <sys/param.h>
431e31b8aSbellard 
5edf8e2afSMika Westerberg #include <sys/resource.h>
630ab9ef2SRichard Henderson #include <sys/shm.h>
731e31b8aSbellard 
83ef693a0Sbellard #include "qemu.h"
976cad711SPaolo Bonzini #include "disas/disas.h"
10ce543844SPhilippe Mathieu-Daudé #include "qemu/bitops.h"
11f348b6d1SVeronia Bahaa #include "qemu/path.h"
12dc5e9ac7SMarkus Armbruster #include "qemu/queue.h"
13c6a2377fSRichard Henderson #include "qemu/guest-random.h"
146fd59449SRichard Henderson #include "qemu/units.h"
15ee947430SAlex Bennée #include "qemu/selfmap.h"
16c7f17e7bSRichard Henderson #include "qapi/error.h"
1731e31b8aSbellard 
18e58ffeb3Smalc #ifdef _ARCH_PPC64
19a6cc84f4Smalc #undef ARCH_DLINFO
20a6cc84f4Smalc #undef ELF_PLATFORM
21a6cc84f4Smalc #undef ELF_HWCAP
22ad6919dcSPeter Maydell #undef ELF_HWCAP2
23a6cc84f4Smalc #undef ELF_CLASS
24a6cc84f4Smalc #undef ELF_DATA
25a6cc84f4Smalc #undef ELF_ARCH
26a6cc84f4Smalc #endif
27a6cc84f4Smalc 
28edf8e2afSMika Westerberg #define ELF_OSABI   ELFOSABI_SYSV
29edf8e2afSMika Westerberg 
30cb33da57Sblueswir1 /* from personality.h */
31cb33da57Sblueswir1 
32cb33da57Sblueswir1 /*
33cb33da57Sblueswir1  * Flags for bug emulation.
34cb33da57Sblueswir1  *
35cb33da57Sblueswir1  * These occupy the top three bytes.
36cb33da57Sblueswir1  */
37cb33da57Sblueswir1 enum {
38cb33da57Sblueswir1     ADDR_NO_RANDOMIZE = 0x0040000,      /* disable randomization of VA space */
39d97ef72eSRichard Henderson     FDPIC_FUNCPTRS =    0x0080000,      /* userspace function ptrs point to
40d97ef72eSRichard Henderson                                            descriptors (signal handling) */
41cb33da57Sblueswir1     MMAP_PAGE_ZERO =    0x0100000,
42cb33da57Sblueswir1     ADDR_COMPAT_LAYOUT = 0x0200000,
43cb33da57Sblueswir1     READ_IMPLIES_EXEC = 0x0400000,
44cb33da57Sblueswir1     ADDR_LIMIT_32BIT =  0x0800000,
45cb33da57Sblueswir1     SHORT_INODE =       0x1000000,
46cb33da57Sblueswir1     WHOLE_SECONDS =     0x2000000,
47cb33da57Sblueswir1     STICKY_TIMEOUTS =   0x4000000,
48cb33da57Sblueswir1     ADDR_LIMIT_3GB =    0x8000000,
49cb33da57Sblueswir1 };
50cb33da57Sblueswir1 
51cb33da57Sblueswir1 /*
52cb33da57Sblueswir1  * Personality types.
53cb33da57Sblueswir1  *
54cb33da57Sblueswir1  * These go in the low byte.  Avoid using the top bit, it will
55cb33da57Sblueswir1  * conflict with error returns.
56cb33da57Sblueswir1  */
57cb33da57Sblueswir1 enum {
58cb33da57Sblueswir1     PER_LINUX =         0x0000,
59cb33da57Sblueswir1     PER_LINUX_32BIT =   0x0000 | ADDR_LIMIT_32BIT,
60cb33da57Sblueswir1     PER_LINUX_FDPIC =   0x0000 | FDPIC_FUNCPTRS,
61cb33da57Sblueswir1     PER_SVR4 =          0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
62cb33da57Sblueswir1     PER_SVR3 =          0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
63d97ef72eSRichard Henderson     PER_SCOSVR3 =       0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE,
64cb33da57Sblueswir1     PER_OSR5 =          0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
65cb33da57Sblueswir1     PER_WYSEV386 =      0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
66cb33da57Sblueswir1     PER_ISCR4 =         0x0005 | STICKY_TIMEOUTS,
67cb33da57Sblueswir1     PER_BSD =           0x0006,
68cb33da57Sblueswir1     PER_SUNOS =         0x0006 | STICKY_TIMEOUTS,
69cb33da57Sblueswir1     PER_XENIX =         0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
70cb33da57Sblueswir1     PER_LINUX32 =       0x0008,
71cb33da57Sblueswir1     PER_LINUX32_3GB =   0x0008 | ADDR_LIMIT_3GB,
72cb33da57Sblueswir1     PER_IRIX32 =        0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
73cb33da57Sblueswir1     PER_IRIXN32 =       0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
74cb33da57Sblueswir1     PER_IRIX64 =        0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
75cb33da57Sblueswir1     PER_RISCOS =        0x000c,
76cb33da57Sblueswir1     PER_SOLARIS =       0x000d | STICKY_TIMEOUTS,
77cb33da57Sblueswir1     PER_UW7 =           0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
78cb33da57Sblueswir1     PER_OSF4 =          0x000f,                  /* OSF/1 v4 */
79cb33da57Sblueswir1     PER_HPUX =          0x0010,
80cb33da57Sblueswir1     PER_MASK =          0x00ff,
81cb33da57Sblueswir1 };
82cb33da57Sblueswir1 
83cb33da57Sblueswir1 /*
84cb33da57Sblueswir1  * Return the base personality without flags.
85cb33da57Sblueswir1  */
86cb33da57Sblueswir1 #define personality(pers)       (pers & PER_MASK)
87cb33da57Sblueswir1 
883cb10cfaSChristophe Lyon int info_is_fdpic(struct image_info *info)
893cb10cfaSChristophe Lyon {
903cb10cfaSChristophe Lyon     return info->personality == PER_LINUX_FDPIC;
913cb10cfaSChristophe Lyon }
923cb10cfaSChristophe Lyon 
9383fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */
9483fb7adfSbellard #ifndef MAP_DENYWRITE
9583fb7adfSbellard #define MAP_DENYWRITE 0
9683fb7adfSbellard #endif
9783fb7adfSbellard 
9883fb7adfSbellard /* should probably go in elf.h */
9983fb7adfSbellard #ifndef ELIBBAD
10083fb7adfSbellard #define ELIBBAD 80
10183fb7adfSbellard #endif
10283fb7adfSbellard 
10328490231SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN
10428490231SRichard Henderson #define ELF_DATA        ELFDATA2MSB
10528490231SRichard Henderson #else
10628490231SRichard Henderson #define ELF_DATA        ELFDATA2LSB
10728490231SRichard Henderson #endif
10828490231SRichard Henderson 
109a29f998dSPaolo Bonzini #ifdef TARGET_ABI_MIPSN32
110918fc54cSPaolo Bonzini typedef abi_ullong      target_elf_greg_t;
111918fc54cSPaolo Bonzini #define tswapreg(ptr)   tswap64(ptr)
112a29f998dSPaolo Bonzini #else
113a29f998dSPaolo Bonzini typedef abi_ulong       target_elf_greg_t;
114a29f998dSPaolo Bonzini #define tswapreg(ptr)   tswapal(ptr)
115a29f998dSPaolo Bonzini #endif
116a29f998dSPaolo Bonzini 
11721e807faSNathan Froyd #ifdef USE_UID16
1181ddd592fSPaolo Bonzini typedef abi_ushort      target_uid_t;
1191ddd592fSPaolo Bonzini typedef abi_ushort      target_gid_t;
12021e807faSNathan Froyd #else
121f8fd4fc4SPaolo Bonzini typedef abi_uint        target_uid_t;
122f8fd4fc4SPaolo Bonzini typedef abi_uint        target_gid_t;
12321e807faSNathan Froyd #endif
124f8fd4fc4SPaolo Bonzini typedef abi_int         target_pid_t;
12521e807faSNathan Froyd 
12630ac07d4Sbellard #ifdef TARGET_I386
12730ac07d4Sbellard 
12815338fd7Sbellard #define ELF_PLATFORM get_elf_platform()
12915338fd7Sbellard 
13015338fd7Sbellard static const char *get_elf_platform(void)
13115338fd7Sbellard {
13215338fd7Sbellard     static char elf_platform[] = "i386";
133a2247f8eSAndreas Färber     int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL);
13415338fd7Sbellard     if (family > 6)
13515338fd7Sbellard         family = 6;
13615338fd7Sbellard     if (family >= 3)
13715338fd7Sbellard         elf_platform[1] = '0' + family;
13815338fd7Sbellard     return elf_platform;
13915338fd7Sbellard }
14015338fd7Sbellard 
14115338fd7Sbellard #define ELF_HWCAP get_elf_hwcap()
14215338fd7Sbellard 
14315338fd7Sbellard static uint32_t get_elf_hwcap(void)
14415338fd7Sbellard {
145a2247f8eSAndreas Färber     X86CPU *cpu = X86_CPU(thread_cpu);
146a2247f8eSAndreas Färber 
147a2247f8eSAndreas Färber     return cpu->env.features[FEAT_1_EDX];
14815338fd7Sbellard }
14915338fd7Sbellard 
15084409ddbSj_mayer #ifdef TARGET_X86_64
15184409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL
15284409ddbSj_mayer 
15384409ddbSj_mayer #define ELF_CLASS      ELFCLASS64
15484409ddbSj_mayer #define ELF_ARCH       EM_X86_64
15584409ddbSj_mayer 
15684409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
15784409ddbSj_mayer {
15884409ddbSj_mayer     regs->rax = 0;
15984409ddbSj_mayer     regs->rsp = infop->start_stack;
16084409ddbSj_mayer     regs->rip = infop->entry;
16184409ddbSj_mayer }
16284409ddbSj_mayer 
1639edc5d79SMika Westerberg #define ELF_NREG    27
164c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
1659edc5d79SMika Westerberg 
1669edc5d79SMika Westerberg /*
1679edc5d79SMika Westerberg  * Note that ELF_NREG should be 29 as there should be place for
1689edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
1699edc5d79SMika Westerberg  * those.
1709edc5d79SMika Westerberg  *
1719edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
1729edc5d79SMika Westerberg  */
17305390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
1749edc5d79SMika Westerberg {
175*030912e0SIlya Leoshkevich     (*regs)[0] = tswapreg(env->regs[15]);
176*030912e0SIlya Leoshkevich     (*regs)[1] = tswapreg(env->regs[14]);
177*030912e0SIlya Leoshkevich     (*regs)[2] = tswapreg(env->regs[13]);
178*030912e0SIlya Leoshkevich     (*regs)[3] = tswapreg(env->regs[12]);
179*030912e0SIlya Leoshkevich     (*regs)[4] = tswapreg(env->regs[R_EBP]);
180*030912e0SIlya Leoshkevich     (*regs)[5] = tswapreg(env->regs[R_EBX]);
181*030912e0SIlya Leoshkevich     (*regs)[6] = tswapreg(env->regs[11]);
182*030912e0SIlya Leoshkevich     (*regs)[7] = tswapreg(env->regs[10]);
183*030912e0SIlya Leoshkevich     (*regs)[8] = tswapreg(env->regs[9]);
184*030912e0SIlya Leoshkevich     (*regs)[9] = tswapreg(env->regs[8]);
185*030912e0SIlya Leoshkevich     (*regs)[10] = tswapreg(env->regs[R_EAX]);
186*030912e0SIlya Leoshkevich     (*regs)[11] = tswapreg(env->regs[R_ECX]);
187*030912e0SIlya Leoshkevich     (*regs)[12] = tswapreg(env->regs[R_EDX]);
188*030912e0SIlya Leoshkevich     (*regs)[13] = tswapreg(env->regs[R_ESI]);
189*030912e0SIlya Leoshkevich     (*regs)[14] = tswapreg(env->regs[R_EDI]);
190*030912e0SIlya Leoshkevich     (*regs)[15] = tswapreg(env->regs[R_EAX]); /* XXX */
191*030912e0SIlya Leoshkevich     (*regs)[16] = tswapreg(env->eip);
192*030912e0SIlya Leoshkevich     (*regs)[17] = tswapreg(env->segs[R_CS].selector & 0xffff);
193*030912e0SIlya Leoshkevich     (*regs)[18] = tswapreg(env->eflags);
194*030912e0SIlya Leoshkevich     (*regs)[19] = tswapreg(env->regs[R_ESP]);
195*030912e0SIlya Leoshkevich     (*regs)[20] = tswapreg(env->segs[R_SS].selector & 0xffff);
196*030912e0SIlya Leoshkevich     (*regs)[21] = tswapreg(env->segs[R_FS].selector & 0xffff);
197*030912e0SIlya Leoshkevich     (*regs)[22] = tswapreg(env->segs[R_GS].selector & 0xffff);
198*030912e0SIlya Leoshkevich     (*regs)[23] = tswapreg(env->segs[R_DS].selector & 0xffff);
199*030912e0SIlya Leoshkevich     (*regs)[24] = tswapreg(env->segs[R_ES].selector & 0xffff);
200*030912e0SIlya Leoshkevich     (*regs)[25] = tswapreg(env->segs[R_FS].selector & 0xffff);
201*030912e0SIlya Leoshkevich     (*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff);
2029edc5d79SMika Westerberg }
2039edc5d79SMika Westerberg 
20484409ddbSj_mayer #else
20584409ddbSj_mayer 
20630ac07d4Sbellard #define ELF_START_MMAP 0x80000000
20730ac07d4Sbellard 
20830ac07d4Sbellard /*
20930ac07d4Sbellard  * This is used to ensure we don't load something for the wrong architecture.
21030ac07d4Sbellard  */
21130ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
21230ac07d4Sbellard 
21330ac07d4Sbellard /*
21430ac07d4Sbellard  * These are used to set parameters in the core dumps.
21530ac07d4Sbellard  */
21630ac07d4Sbellard #define ELF_CLASS       ELFCLASS32
21730ac07d4Sbellard #define ELF_ARCH        EM_386
21830ac07d4Sbellard 
219d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
220d97ef72eSRichard Henderson                                struct image_info *infop)
221e5fe0c52Spbrook {
222e5fe0c52Spbrook     regs->esp = infop->start_stack;
223e5fe0c52Spbrook     regs->eip = infop->entry;
224e5fe0c52Spbrook 
22530ac07d4Sbellard     /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
22630ac07d4Sbellard        starts %edx contains a pointer to a function which might be
22730ac07d4Sbellard        registered using `atexit'.  This provides a mean for the
22830ac07d4Sbellard        dynamic linker to call DT_FINI functions for shared libraries
22930ac07d4Sbellard        that have been loaded before the code runs.
23030ac07d4Sbellard 
23130ac07d4Sbellard        A value of 0 tells we have no such handler.  */
232e5fe0c52Spbrook     regs->edx = 0;
233b346ff46Sbellard }
2349edc5d79SMika Westerberg 
2359edc5d79SMika Westerberg #define ELF_NREG    17
236c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
2379edc5d79SMika Westerberg 
2389edc5d79SMika Westerberg /*
2399edc5d79SMika Westerberg  * Note that ELF_NREG should be 19 as there should be place for
2409edc5d79SMika Westerberg  * TRAPNO and ERR "registers" as well but linux doesn't dump
2419edc5d79SMika Westerberg  * those.
2429edc5d79SMika Westerberg  *
2439edc5d79SMika Westerberg  * See linux kernel: arch/x86/include/asm/elf.h
2449edc5d79SMika Westerberg  */
24505390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env)
2469edc5d79SMika Westerberg {
247*030912e0SIlya Leoshkevich     (*regs)[0] = tswapreg(env->regs[R_EBX]);
248*030912e0SIlya Leoshkevich     (*regs)[1] = tswapreg(env->regs[R_ECX]);
249*030912e0SIlya Leoshkevich     (*regs)[2] = tswapreg(env->regs[R_EDX]);
250*030912e0SIlya Leoshkevich     (*regs)[3] = tswapreg(env->regs[R_ESI]);
251*030912e0SIlya Leoshkevich     (*regs)[4] = tswapreg(env->regs[R_EDI]);
252*030912e0SIlya Leoshkevich     (*regs)[5] = tswapreg(env->regs[R_EBP]);
253*030912e0SIlya Leoshkevich     (*regs)[6] = tswapreg(env->regs[R_EAX]);
254*030912e0SIlya Leoshkevich     (*regs)[7] = tswapreg(env->segs[R_DS].selector & 0xffff);
255*030912e0SIlya Leoshkevich     (*regs)[8] = tswapreg(env->segs[R_ES].selector & 0xffff);
256*030912e0SIlya Leoshkevich     (*regs)[9] = tswapreg(env->segs[R_FS].selector & 0xffff);
257*030912e0SIlya Leoshkevich     (*regs)[10] = tswapreg(env->segs[R_GS].selector & 0xffff);
258*030912e0SIlya Leoshkevich     (*regs)[11] = tswapreg(env->regs[R_EAX]); /* XXX */
259*030912e0SIlya Leoshkevich     (*regs)[12] = tswapreg(env->eip);
260*030912e0SIlya Leoshkevich     (*regs)[13] = tswapreg(env->segs[R_CS].selector & 0xffff);
261*030912e0SIlya Leoshkevich     (*regs)[14] = tswapreg(env->eflags);
262*030912e0SIlya Leoshkevich     (*regs)[15] = tswapreg(env->regs[R_ESP]);
263*030912e0SIlya Leoshkevich     (*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff);
2649edc5d79SMika Westerberg }
26584409ddbSj_mayer #endif
266b346ff46Sbellard 
2679edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP
268b346ff46Sbellard #define ELF_EXEC_PAGESIZE       4096
269b346ff46Sbellard 
270b346ff46Sbellard #endif
271b346ff46Sbellard 
272b346ff46Sbellard #ifdef TARGET_ARM
273b346ff46Sbellard 
27424e76ff0SPeter Maydell #ifndef TARGET_AARCH64
27524e76ff0SPeter Maydell /* 32 bit ARM definitions */
27624e76ff0SPeter Maydell 
277b346ff46Sbellard #define ELF_START_MMAP 0x80000000
278b346ff46Sbellard 
279b597c3f7SPeter Crosthwaite #define ELF_ARCH        EM_ARM
280b346ff46Sbellard #define ELF_CLASS       ELFCLASS32
281b346ff46Sbellard 
282d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
283d97ef72eSRichard Henderson                                struct image_info *infop)
284b346ff46Sbellard {
285992f48a0Sblueswir1     abi_long stack = infop->start_stack;
286b346ff46Sbellard     memset(regs, 0, sizeof(*regs));
28799033caeSAlexander Graf 
288167e4cdcSPeter Maydell     regs->uregs[16] = ARM_CPU_MODE_USR;
289167e4cdcSPeter Maydell     if (infop->entry & 1) {
290167e4cdcSPeter Maydell         regs->uregs[16] |= CPSR_T;
291167e4cdcSPeter Maydell     }
292167e4cdcSPeter Maydell     regs->uregs[15] = infop->entry & 0xfffffffe;
293167e4cdcSPeter Maydell     regs->uregs[13] = infop->start_stack;
2942f619698Sbellard     /* FIXME - what to for failure of get_user()? */
295167e4cdcSPeter Maydell     get_user_ual(regs->uregs[2], stack + 8); /* envp */
296167e4cdcSPeter Maydell     get_user_ual(regs->uregs[1], stack + 4); /* envp */
297a1516e92Sbellard     /* XXX: it seems that r0 is zeroed after ! */
298167e4cdcSPeter Maydell     regs->uregs[0] = 0;
299e5fe0c52Spbrook     /* For uClinux PIC binaries.  */
300863cf0b7Sj_mayer     /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
301167e4cdcSPeter Maydell     regs->uregs[10] = infop->start_data;
3023cb10cfaSChristophe Lyon 
3033cb10cfaSChristophe Lyon     /* Support ARM FDPIC.  */
3043cb10cfaSChristophe Lyon     if (info_is_fdpic(infop)) {
3053cb10cfaSChristophe Lyon         /* As described in the ABI document, r7 points to the loadmap info
3063cb10cfaSChristophe Lyon          * prepared by the kernel. If an interpreter is needed, r8 points
3073cb10cfaSChristophe Lyon          * to the interpreter loadmap and r9 points to the interpreter
3083cb10cfaSChristophe Lyon          * PT_DYNAMIC info. If no interpreter is needed, r8 is zero, and
3093cb10cfaSChristophe Lyon          * r9 points to the main program PT_DYNAMIC info.
3103cb10cfaSChristophe Lyon          */
3113cb10cfaSChristophe Lyon         regs->uregs[7] = infop->loadmap_addr;
3123cb10cfaSChristophe Lyon         if (infop->interpreter_loadmap_addr) {
3133cb10cfaSChristophe Lyon             /* Executable is dynamically loaded.  */
3143cb10cfaSChristophe Lyon             regs->uregs[8] = infop->interpreter_loadmap_addr;
3153cb10cfaSChristophe Lyon             regs->uregs[9] = infop->interpreter_pt_dynamic_addr;
3163cb10cfaSChristophe Lyon         } else {
3173cb10cfaSChristophe Lyon             regs->uregs[8] = 0;
3183cb10cfaSChristophe Lyon             regs->uregs[9] = infop->pt_dynamic_addr;
3193cb10cfaSChristophe Lyon         }
3203cb10cfaSChristophe Lyon     }
321b346ff46Sbellard }
322b346ff46Sbellard 
323edf8e2afSMika Westerberg #define ELF_NREG    18
324c227f099SAnthony Liguori typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
325edf8e2afSMika Westerberg 
32605390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env)
327edf8e2afSMika Westerberg {
32886cd7b2dSPaolo Bonzini     (*regs)[0] = tswapreg(env->regs[0]);
32986cd7b2dSPaolo Bonzini     (*regs)[1] = tswapreg(env->regs[1]);
33086cd7b2dSPaolo Bonzini     (*regs)[2] = tswapreg(env->regs[2]);
33186cd7b2dSPaolo Bonzini     (*regs)[3] = tswapreg(env->regs[3]);
33286cd7b2dSPaolo Bonzini     (*regs)[4] = tswapreg(env->regs[4]);
33386cd7b2dSPaolo Bonzini     (*regs)[5] = tswapreg(env->regs[5]);
33486cd7b2dSPaolo Bonzini     (*regs)[6] = tswapreg(env->regs[6]);
33586cd7b2dSPaolo Bonzini     (*regs)[7] = tswapreg(env->regs[7]);
33686cd7b2dSPaolo Bonzini     (*regs)[8] = tswapreg(env->regs[8]);
33786cd7b2dSPaolo Bonzini     (*regs)[9] = tswapreg(env->regs[9]);
33886cd7b2dSPaolo Bonzini     (*regs)[10] = tswapreg(env->regs[10]);
33986cd7b2dSPaolo Bonzini     (*regs)[11] = tswapreg(env->regs[11]);
34086cd7b2dSPaolo Bonzini     (*regs)[12] = tswapreg(env->regs[12]);
34186cd7b2dSPaolo Bonzini     (*regs)[13] = tswapreg(env->regs[13]);
34286cd7b2dSPaolo Bonzini     (*regs)[14] = tswapreg(env->regs[14]);
34386cd7b2dSPaolo Bonzini     (*regs)[15] = tswapreg(env->regs[15]);
344edf8e2afSMika Westerberg 
34586cd7b2dSPaolo Bonzini     (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env));
34686cd7b2dSPaolo Bonzini     (*regs)[17] = tswapreg(env->regs[0]); /* XXX */
347edf8e2afSMika Westerberg }
348edf8e2afSMika Westerberg 
34930ac07d4Sbellard #define USE_ELF_CORE_DUMP
35030ac07d4Sbellard #define ELF_EXEC_PAGESIZE       4096
35130ac07d4Sbellard 
352afce2927Sbellard enum
353afce2927Sbellard {
354afce2927Sbellard     ARM_HWCAP_ARM_SWP       = 1 << 0,
355afce2927Sbellard     ARM_HWCAP_ARM_HALF      = 1 << 1,
356afce2927Sbellard     ARM_HWCAP_ARM_THUMB     = 1 << 2,
357afce2927Sbellard     ARM_HWCAP_ARM_26BIT     = 1 << 3,
358afce2927Sbellard     ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
359afce2927Sbellard     ARM_HWCAP_ARM_FPA       = 1 << 5,
360afce2927Sbellard     ARM_HWCAP_ARM_VFP       = 1 << 6,
361afce2927Sbellard     ARM_HWCAP_ARM_EDSP      = 1 << 7,
362cf6de34aSRiku Voipio     ARM_HWCAP_ARM_JAVA      = 1 << 8,
363cf6de34aSRiku Voipio     ARM_HWCAP_ARM_IWMMXT    = 1 << 9,
36443ce393eSPeter Maydell     ARM_HWCAP_ARM_CRUNCH    = 1 << 10,
36543ce393eSPeter Maydell     ARM_HWCAP_ARM_THUMBEE   = 1 << 11,
36643ce393eSPeter Maydell     ARM_HWCAP_ARM_NEON      = 1 << 12,
36743ce393eSPeter Maydell     ARM_HWCAP_ARM_VFPv3     = 1 << 13,
36843ce393eSPeter Maydell     ARM_HWCAP_ARM_VFPv3D16  = 1 << 14,
36924682654SPeter Maydell     ARM_HWCAP_ARM_TLS       = 1 << 15,
37024682654SPeter Maydell     ARM_HWCAP_ARM_VFPv4     = 1 << 16,
37124682654SPeter Maydell     ARM_HWCAP_ARM_IDIVA     = 1 << 17,
37224682654SPeter Maydell     ARM_HWCAP_ARM_IDIVT     = 1 << 18,
37324682654SPeter Maydell     ARM_HWCAP_ARM_VFPD32    = 1 << 19,
37424682654SPeter Maydell     ARM_HWCAP_ARM_LPAE      = 1 << 20,
37524682654SPeter Maydell     ARM_HWCAP_ARM_EVTSTRM   = 1 << 21,
376afce2927Sbellard };
377afce2927Sbellard 
378ad6919dcSPeter Maydell enum {
379ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_AES      = 1 << 0,
380ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_PMULL    = 1 << 1,
381ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_SHA1     = 1 << 2,
382ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_SHA2     = 1 << 3,
383ad6919dcSPeter Maydell     ARM_HWCAP2_ARM_CRC32    = 1 << 4,
384ad6919dcSPeter Maydell };
385ad6919dcSPeter Maydell 
3866b1275ffSPeter Maydell /* The commpage only exists for 32 bit kernels */
3876b1275ffSPeter Maydell 
388ee947430SAlex Bennée #define ARM_COMMPAGE (intptr_t)0xffff0f00u
389ee947430SAlex Bennée 
390ee947430SAlex Bennée static bool init_guest_commpage(void)
39197cc7560SDr. David Alan Gilbert {
3923e8f1628SRichard Henderson     void *want = g2h_untagged(ARM_COMMPAGE & -qemu_host_page_size);
393ee947430SAlex Bennée     void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
3945c3e87f3SAlex Bennée                       MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
39597cc7560SDr. David Alan Gilbert 
396ee947430SAlex Bennée     if (addr == MAP_FAILED) {
397ee947430SAlex Bennée         perror("Allocating guest commpage");
398ee947430SAlex Bennée         exit(EXIT_FAILURE);
399ee947430SAlex Bennée     }
400ee947430SAlex Bennée     if (addr != want) {
401ee947430SAlex Bennée         return false;
402806d1021SMeador Inge     }
403806d1021SMeador Inge 
404ee947430SAlex Bennée     /* Set kernel helper versions; rest of page is 0.  */
4053e8f1628SRichard Henderson     __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu));
40697cc7560SDr. David Alan Gilbert 
407ee947430SAlex Bennée     if (mprotect(addr, qemu_host_page_size, PROT_READ)) {
40897cc7560SDr. David Alan Gilbert         perror("Protecting guest commpage");
409ee947430SAlex Bennée         exit(EXIT_FAILURE);
41097cc7560SDr. David Alan Gilbert     }
411ee947430SAlex Bennée     return true;
41297cc7560SDr. David Alan Gilbert }
413adf050b1SBenoit Canet 
414adf050b1SBenoit Canet #define ELF_HWCAP get_elf_hwcap()
415ad6919dcSPeter Maydell #define ELF_HWCAP2 get_elf_hwcap2()
416adf050b1SBenoit Canet 
417adf050b1SBenoit Canet static uint32_t get_elf_hwcap(void)
418adf050b1SBenoit Canet {
419a2247f8eSAndreas Färber     ARMCPU *cpu = ARM_CPU(thread_cpu);
420adf050b1SBenoit Canet     uint32_t hwcaps = 0;
421adf050b1SBenoit Canet 
422adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_SWP;
423adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_HALF;
424adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_THUMB;
425adf050b1SBenoit Canet     hwcaps |= ARM_HWCAP_ARM_FAST_MULT;
426adf050b1SBenoit Canet 
427adf050b1SBenoit Canet     /* probe for the extra features */
428adf050b1SBenoit Canet #define GET_FEATURE(feat, hwcap) \
429a2247f8eSAndreas Färber     do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0)
430962fcbf2SRichard Henderson 
431962fcbf2SRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \
432962fcbf2SRichard Henderson     do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
433962fcbf2SRichard Henderson 
43424682654SPeter Maydell     /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */
43524682654SPeter Maydell     GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP);
436adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT);
437adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE);
438adf050b1SBenoit Canet     GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON);
43924682654SPeter Maydell     GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS);
440bfa8a370SRichard Henderson     GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE);
441873b73c0SPeter Maydell     GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA);
442873b73c0SPeter Maydell     GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT);
443bfa8a370SRichard Henderson     GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP);
444bfa8a370SRichard Henderson 
445bfa8a370SRichard Henderson     if (cpu_isar_feature(aa32_fpsp_v3, cpu) ||
446bfa8a370SRichard Henderson         cpu_isar_feature(aa32_fpdp_v3, cpu)) {
447bfa8a370SRichard Henderson         hwcaps |= ARM_HWCAP_ARM_VFPv3;
448bfa8a370SRichard Henderson         if (cpu_isar_feature(aa32_simd_r32, cpu)) {
449bfa8a370SRichard Henderson             hwcaps |= ARM_HWCAP_ARM_VFPD32;
450bfa8a370SRichard Henderson         } else {
451bfa8a370SRichard Henderson             hwcaps |= ARM_HWCAP_ARM_VFPv3D16;
452bfa8a370SRichard Henderson         }
453bfa8a370SRichard Henderson     }
454bfa8a370SRichard Henderson     GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4);
455adf050b1SBenoit Canet 
456adf050b1SBenoit Canet     return hwcaps;
457adf050b1SBenoit Canet }
458afce2927Sbellard 
459ad6919dcSPeter Maydell static uint32_t get_elf_hwcap2(void)
460ad6919dcSPeter Maydell {
461ad6919dcSPeter Maydell     ARMCPU *cpu = ARM_CPU(thread_cpu);
462ad6919dcSPeter Maydell     uint32_t hwcaps = 0;
463ad6919dcSPeter Maydell 
464962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES);
465962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL);
466962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1);
467962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2);
468962fcbf2SRichard Henderson     GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32);
469ad6919dcSPeter Maydell     return hwcaps;
470ad6919dcSPeter Maydell }
471ad6919dcSPeter Maydell 
472ad6919dcSPeter Maydell #undef GET_FEATURE
473962fcbf2SRichard Henderson #undef GET_FEATURE_ID
474ad6919dcSPeter Maydell 
47513ec4ec3SRichard Henderson #define ELF_PLATFORM get_elf_platform()
47613ec4ec3SRichard Henderson 
47713ec4ec3SRichard Henderson static const char *get_elf_platform(void)
47813ec4ec3SRichard Henderson {
47913ec4ec3SRichard Henderson     CPUARMState *env = thread_cpu->env_ptr;
48013ec4ec3SRichard Henderson 
48113ec4ec3SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN
48213ec4ec3SRichard Henderson # define END  "b"
48313ec4ec3SRichard Henderson #else
48413ec4ec3SRichard Henderson # define END  "l"
48513ec4ec3SRichard Henderson #endif
48613ec4ec3SRichard Henderson 
48713ec4ec3SRichard Henderson     if (arm_feature(env, ARM_FEATURE_V8)) {
48813ec4ec3SRichard Henderson         return "v8" END;
48913ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V7)) {
49013ec4ec3SRichard Henderson         if (arm_feature(env, ARM_FEATURE_M)) {
49113ec4ec3SRichard Henderson             return "v7m" END;
49213ec4ec3SRichard Henderson         } else {
49313ec4ec3SRichard Henderson             return "v7" END;
49413ec4ec3SRichard Henderson         }
49513ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V6)) {
49613ec4ec3SRichard Henderson         return "v6" END;
49713ec4ec3SRichard Henderson     } else if (arm_feature(env, ARM_FEATURE_V5)) {
49813ec4ec3SRichard Henderson         return "v5" END;
49913ec4ec3SRichard Henderson     } else {
50013ec4ec3SRichard Henderson         return "v4" END;
50113ec4ec3SRichard Henderson     }
50213ec4ec3SRichard Henderson 
50313ec4ec3SRichard Henderson #undef END
50413ec4ec3SRichard Henderson }
50513ec4ec3SRichard Henderson 
50624e76ff0SPeter Maydell #else
50724e76ff0SPeter Maydell /* 64 bit ARM definitions */
50824e76ff0SPeter Maydell #define ELF_START_MMAP 0x80000000
50924e76ff0SPeter Maydell 
510b597c3f7SPeter Crosthwaite #define ELF_ARCH        EM_AARCH64
51124e76ff0SPeter Maydell #define ELF_CLASS       ELFCLASS64
512e20e3ec9SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN
513e20e3ec9SRichard Henderson # define ELF_PLATFORM    "aarch64_be"
514e20e3ec9SRichard Henderson #else
51524e76ff0SPeter Maydell # define ELF_PLATFORM    "aarch64"
516e20e3ec9SRichard Henderson #endif
51724e76ff0SPeter Maydell 
51824e76ff0SPeter Maydell static inline void init_thread(struct target_pt_regs *regs,
51924e76ff0SPeter Maydell                                struct image_info *infop)
52024e76ff0SPeter Maydell {
52124e76ff0SPeter Maydell     abi_long stack = infop->start_stack;
52224e76ff0SPeter Maydell     memset(regs, 0, sizeof(*regs));
52324e76ff0SPeter Maydell 
52424e76ff0SPeter Maydell     regs->pc = infop->entry & ~0x3ULL;
52524e76ff0SPeter Maydell     regs->sp = stack;
52624e76ff0SPeter Maydell }
52724e76ff0SPeter Maydell 
52824e76ff0SPeter Maydell #define ELF_NREG    34
52924e76ff0SPeter Maydell typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG];
53024e76ff0SPeter Maydell 
53124e76ff0SPeter Maydell static void elf_core_copy_regs(target_elf_gregset_t *regs,
53224e76ff0SPeter Maydell                                const CPUARMState *env)
53324e76ff0SPeter Maydell {
53424e76ff0SPeter Maydell     int i;
53524e76ff0SPeter Maydell 
53624e76ff0SPeter Maydell     for (i = 0; i < 32; i++) {
53724e76ff0SPeter Maydell         (*regs)[i] = tswapreg(env->xregs[i]);
53824e76ff0SPeter Maydell     }
53924e76ff0SPeter Maydell     (*regs)[32] = tswapreg(env->pc);
54024e76ff0SPeter Maydell     (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env));
54124e76ff0SPeter Maydell }
54224e76ff0SPeter Maydell 
54324e76ff0SPeter Maydell #define USE_ELF_CORE_DUMP
54424e76ff0SPeter Maydell #define ELF_EXEC_PAGESIZE       4096
54524e76ff0SPeter Maydell 
54624e76ff0SPeter Maydell enum {
54724e76ff0SPeter Maydell     ARM_HWCAP_A64_FP            = 1 << 0,
54824e76ff0SPeter Maydell     ARM_HWCAP_A64_ASIMD         = 1 << 1,
54924e76ff0SPeter Maydell     ARM_HWCAP_A64_EVTSTRM       = 1 << 2,
55024e76ff0SPeter Maydell     ARM_HWCAP_A64_AES           = 1 << 3,
55124e76ff0SPeter Maydell     ARM_HWCAP_A64_PMULL         = 1 << 4,
55224e76ff0SPeter Maydell     ARM_HWCAP_A64_SHA1          = 1 << 5,
55324e76ff0SPeter Maydell     ARM_HWCAP_A64_SHA2          = 1 << 6,
55424e76ff0SPeter Maydell     ARM_HWCAP_A64_CRC32         = 1 << 7,
555955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ATOMICS       = 1 << 8,
556955f56d4SArd Biesheuvel     ARM_HWCAP_A64_FPHP          = 1 << 9,
557955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDHP       = 1 << 10,
558955f56d4SArd Biesheuvel     ARM_HWCAP_A64_CPUID         = 1 << 11,
559955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDRDM      = 1 << 12,
560955f56d4SArd Biesheuvel     ARM_HWCAP_A64_JSCVT         = 1 << 13,
561955f56d4SArd Biesheuvel     ARM_HWCAP_A64_FCMA          = 1 << 14,
562955f56d4SArd Biesheuvel     ARM_HWCAP_A64_LRCPC         = 1 << 15,
563955f56d4SArd Biesheuvel     ARM_HWCAP_A64_DCPOP         = 1 << 16,
564955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SHA3          = 1 << 17,
565955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SM3           = 1 << 18,
566955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SM4           = 1 << 19,
567955f56d4SArd Biesheuvel     ARM_HWCAP_A64_ASIMDDP       = 1 << 20,
568955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SHA512        = 1 << 21,
569955f56d4SArd Biesheuvel     ARM_HWCAP_A64_SVE           = 1 << 22,
5700083a1faSRichard Henderson     ARM_HWCAP_A64_ASIMDFHM      = 1 << 23,
5710083a1faSRichard Henderson     ARM_HWCAP_A64_DIT           = 1 << 24,
5720083a1faSRichard Henderson     ARM_HWCAP_A64_USCAT         = 1 << 25,
5730083a1faSRichard Henderson     ARM_HWCAP_A64_ILRCPC        = 1 << 26,
5740083a1faSRichard Henderson     ARM_HWCAP_A64_FLAGM         = 1 << 27,
5750083a1faSRichard Henderson     ARM_HWCAP_A64_SSBS          = 1 << 28,
5760083a1faSRichard Henderson     ARM_HWCAP_A64_SB            = 1 << 29,
5770083a1faSRichard Henderson     ARM_HWCAP_A64_PACA          = 1 << 30,
5780083a1faSRichard Henderson     ARM_HWCAP_A64_PACG          = 1UL << 31,
5792041df4aSRichard Henderson 
5802041df4aSRichard Henderson     ARM_HWCAP2_A64_DCPODP       = 1 << 0,
5812041df4aSRichard Henderson     ARM_HWCAP2_A64_SVE2         = 1 << 1,
5822041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEAES       = 1 << 2,
5832041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEPMULL     = 1 << 3,
5842041df4aSRichard Henderson     ARM_HWCAP2_A64_SVEBITPERM   = 1 << 4,
5852041df4aSRichard Henderson     ARM_HWCAP2_A64_SVESHA3      = 1 << 5,
5862041df4aSRichard Henderson     ARM_HWCAP2_A64_SVESM4       = 1 << 6,
5872041df4aSRichard Henderson     ARM_HWCAP2_A64_FLAGM2       = 1 << 7,
5882041df4aSRichard Henderson     ARM_HWCAP2_A64_FRINT        = 1 << 8,
58968948d18SRichard Henderson     ARM_HWCAP2_A64_SVEI8MM      = 1 << 9,
59068948d18SRichard Henderson     ARM_HWCAP2_A64_SVEF32MM     = 1 << 10,
59168948d18SRichard Henderson     ARM_HWCAP2_A64_SVEF64MM     = 1 << 11,
59268948d18SRichard Henderson     ARM_HWCAP2_A64_SVEBF16      = 1 << 12,
59368948d18SRichard Henderson     ARM_HWCAP2_A64_I8MM         = 1 << 13,
59468948d18SRichard Henderson     ARM_HWCAP2_A64_BF16         = 1 << 14,
59568948d18SRichard Henderson     ARM_HWCAP2_A64_DGH          = 1 << 15,
59668948d18SRichard Henderson     ARM_HWCAP2_A64_RNG          = 1 << 16,
59768948d18SRichard Henderson     ARM_HWCAP2_A64_BTI          = 1 << 17,
59868948d18SRichard Henderson     ARM_HWCAP2_A64_MTE          = 1 << 18,
59924e76ff0SPeter Maydell };
60024e76ff0SPeter Maydell 
60124e76ff0SPeter Maydell #define ELF_HWCAP   get_elf_hwcap()
6022041df4aSRichard Henderson #define ELF_HWCAP2  get_elf_hwcap2()
6032041df4aSRichard Henderson 
6042041df4aSRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \
6052041df4aSRichard Henderson     do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0)
60624e76ff0SPeter Maydell 
60724e76ff0SPeter Maydell static uint32_t get_elf_hwcap(void)
60824e76ff0SPeter Maydell {
60924e76ff0SPeter Maydell     ARMCPU *cpu = ARM_CPU(thread_cpu);
61024e76ff0SPeter Maydell     uint32_t hwcaps = 0;
61124e76ff0SPeter Maydell 
61224e76ff0SPeter Maydell     hwcaps |= ARM_HWCAP_A64_FP;
61324e76ff0SPeter Maydell     hwcaps |= ARM_HWCAP_A64_ASIMD;
61437020ff1SAlex Bennée     hwcaps |= ARM_HWCAP_A64_CPUID;
61524e76ff0SPeter Maydell 
61624e76ff0SPeter Maydell     /* probe for the extra features */
617962fcbf2SRichard Henderson 
618962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES);
619962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL);
620962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha1, ARM_HWCAP_A64_SHA1);
621962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha256, ARM_HWCAP_A64_SHA2);
622962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha512, ARM_HWCAP_A64_SHA512);
623962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_crc32, ARM_HWCAP_A64_CRC32);
624962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3);
625962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3);
626962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4);
6275763190fSRichard Henderson     GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP);
628962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS);
629962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM);
630962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP);
631962fcbf2SRichard Henderson     GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA);
632cd208a1cSRichard Henderson     GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE);
63329d26ab2SRichard Henderson     GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG);
6341c9af3a9SRichard Henderson     GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM);
6351c9af3a9SRichard Henderson     GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT);
6369888bd1eSRichard Henderson     GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB);
637b89d9c98SRichard Henderson     GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM);
6380d57b499SBeata Michalska     GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP);
6392677cf9fSPeter Maydell     GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC);
640a1229109SPeter Maydell     GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC);
641962fcbf2SRichard Henderson 
6422041df4aSRichard Henderson     return hwcaps;
6432041df4aSRichard Henderson }
6442041df4aSRichard Henderson 
6452041df4aSRichard Henderson static uint32_t get_elf_hwcap2(void)
6462041df4aSRichard Henderson {
6472041df4aSRichard Henderson     ARMCPU *cpu = ARM_CPU(thread_cpu);
6482041df4aSRichard Henderson     uint32_t hwcaps = 0;
6492041df4aSRichard Henderson 
6500d57b499SBeata Michalska     GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
651cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2, ARM_HWCAP2_A64_SVE2);
652cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_aes, ARM_HWCAP2_A64_SVEAES);
653cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_pmull128, ARM_HWCAP2_A64_SVEPMULL);
654cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_bitperm, ARM_HWCAP2_A64_SVEBITPERM);
655cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_sha3, ARM_HWCAP2_A64_SVESHA3);
656cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve2_sm4, ARM_HWCAP2_A64_SVESM4);
6572041df4aSRichard Henderson     GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
6582041df4aSRichard Henderson     GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
659cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve_i8mm, ARM_HWCAP2_A64_SVEI8MM);
660cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve_f32mm, ARM_HWCAP2_A64_SVEF32MM);
661cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_sve_f64mm, ARM_HWCAP2_A64_SVEF64MM);
6626c47a905SRichard Henderson     GET_FEATURE_ID(aa64_sve_bf16, ARM_HWCAP2_A64_SVEBF16);
663cdc8d8b2SRichard Henderson     GET_FEATURE_ID(aa64_i8mm, ARM_HWCAP2_A64_I8MM);
6646c47a905SRichard Henderson     GET_FEATURE_ID(aa64_bf16, ARM_HWCAP2_A64_BF16);
66568948d18SRichard Henderson     GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
66668948d18SRichard Henderson     GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
66768948d18SRichard Henderson     GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
66824e76ff0SPeter Maydell 
66924e76ff0SPeter Maydell     return hwcaps;
67024e76ff0SPeter Maydell }
67124e76ff0SPeter Maydell 
6722041df4aSRichard Henderson #undef GET_FEATURE_ID
6732041df4aSRichard Henderson 
67424e76ff0SPeter Maydell #endif /* not TARGET_AARCH64 */
67524e76ff0SPeter Maydell #endif /* TARGET_ARM */
67630ac07d4Sbellard 
677853d6f7aSbellard #ifdef TARGET_SPARC
678a315a145Sbellard #ifdef TARGET_SPARC64
679853d6f7aSbellard 
680853d6f7aSbellard #define ELF_START_MMAP 0x80000000
681cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
682cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9)
683992f48a0Sblueswir1 #ifndef TARGET_ABI32
684cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
685992f48a0Sblueswir1 #else
686992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
687992f48a0Sblueswir1 #endif
688853d6f7aSbellard 
689a315a145Sbellard #define ELF_CLASS   ELFCLASS64
6905ef54116Sbellard #define ELF_ARCH    EM_SPARCV9
691a315a145Sbellard #else
692a315a145Sbellard #define ELF_START_MMAP 0x80000000
693cf973e46SArtyom Tarasenko #define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \
694cf973e46SArtyom Tarasenko                     | HWCAP_SPARC_MULDIV)
695853d6f7aSbellard #define ELF_CLASS   ELFCLASS32
696853d6f7aSbellard #define ELF_ARCH    EM_SPARC
697089a2256SRichard Henderson #endif /* TARGET_SPARC64 */
698853d6f7aSbellard 
699d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
700d97ef72eSRichard Henderson                                struct image_info *infop)
701853d6f7aSbellard {
702089a2256SRichard Henderson     /* Note that target_cpu_copy_regs does not read psr/tstate. */
703f5155289Sbellard     regs->pc = infop->entry;
704f5155289Sbellard     regs->npc = regs->pc + 4;
705f5155289Sbellard     regs->y = 0;
706089a2256SRichard Henderson     regs->u_regs[14] = (infop->start_stack - 16 * sizeof(abi_ulong)
707089a2256SRichard Henderson                         - TARGET_STACK_BIAS);
708853d6f7aSbellard }
709089a2256SRichard Henderson #endif /* TARGET_SPARC */
710853d6f7aSbellard 
71167867308Sbellard #ifdef TARGET_PPC
71267867308Sbellard 
7134ecd4d16SPeter Crosthwaite #define ELF_MACHINE    PPC_ELF_MACHINE
71467867308Sbellard #define ELF_START_MMAP 0x80000000
71567867308Sbellard 
716e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
71784409ddbSj_mayer 
71884409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 )
71984409ddbSj_mayer 
72084409ddbSj_mayer #define ELF_CLASS       ELFCLASS64
72184409ddbSj_mayer 
72284409ddbSj_mayer #else
72384409ddbSj_mayer 
72467867308Sbellard #define ELF_CLASS       ELFCLASS32
72584409ddbSj_mayer 
72684409ddbSj_mayer #endif
72784409ddbSj_mayer 
72867867308Sbellard #define ELF_ARCH        EM_PPC
72967867308Sbellard 
730df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP).
731df84e4f3SNathan Froyd    See arch/powerpc/include/asm/cputable.h.  */
732df84e4f3SNathan Froyd enum {
7333efa9a67Smalc     QEMU_PPC_FEATURE_32 = 0x80000000,
7343efa9a67Smalc     QEMU_PPC_FEATURE_64 = 0x40000000,
7353efa9a67Smalc     QEMU_PPC_FEATURE_601_INSTR = 0x20000000,
7363efa9a67Smalc     QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000,
7373efa9a67Smalc     QEMU_PPC_FEATURE_HAS_FPU = 0x08000000,
7383efa9a67Smalc     QEMU_PPC_FEATURE_HAS_MMU = 0x04000000,
7393efa9a67Smalc     QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000,
7403efa9a67Smalc     QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000,
7413efa9a67Smalc     QEMU_PPC_FEATURE_HAS_SPE = 0x00800000,
7423efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000,
7433efa9a67Smalc     QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000,
7443efa9a67Smalc     QEMU_PPC_FEATURE_NO_TB = 0x00100000,
7453efa9a67Smalc     QEMU_PPC_FEATURE_POWER4 = 0x00080000,
7463efa9a67Smalc     QEMU_PPC_FEATURE_POWER5 = 0x00040000,
7473efa9a67Smalc     QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000,
7483efa9a67Smalc     QEMU_PPC_FEATURE_CELL = 0x00010000,
7493efa9a67Smalc     QEMU_PPC_FEATURE_BOOKE = 0x00008000,
7503efa9a67Smalc     QEMU_PPC_FEATURE_SMT = 0x00004000,
7513efa9a67Smalc     QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000,
7523efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000,
7533efa9a67Smalc     QEMU_PPC_FEATURE_PA6T = 0x00000800,
7543efa9a67Smalc     QEMU_PPC_FEATURE_HAS_DFP = 0x00000400,
7553efa9a67Smalc     QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200,
7563efa9a67Smalc     QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100,
7573efa9a67Smalc     QEMU_PPC_FEATURE_HAS_VSX = 0x00000080,
7583efa9a67Smalc     QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040,
759df84e4f3SNathan Froyd 
7603efa9a67Smalc     QEMU_PPC_FEATURE_TRUE_LE = 0x00000002,
7613efa9a67Smalc     QEMU_PPC_FEATURE_PPC_LE = 0x00000001,
762a60438ddSTom Musta 
763a60438ddSTom Musta     /* Feature definitions in AT_HWCAP2.  */
764a60438ddSTom Musta     QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */
765a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */
766a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */
767a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */
768a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */
769a60438ddSTom Musta     QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */
77024c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_VEC_CRYPTO = 0x02000000,
77124c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HTM_NOSC = 0x01000000,
772be0c46d4SSandipan Das     QEMU_PPC_FEATURE2_ARCH_3_00 = 0x00800000, /* ISA 3.00 */
77324c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HAS_IEEE128 = 0x00400000, /* VSX IEEE Bin Float 128-bit */
77424c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */
77524c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */
77624c373ecSLaurent Vivier     QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */
777df84e4f3SNathan Froyd };
778df84e4f3SNathan Froyd 
779df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap()
780df84e4f3SNathan Froyd 
781df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void)
782df84e4f3SNathan Froyd {
783a2247f8eSAndreas Färber     PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
784df84e4f3SNathan Froyd     uint32_t features = 0;
785df84e4f3SNathan Froyd 
786df84e4f3SNathan Froyd     /* We don't have to be terribly complete here; the high points are
787df84e4f3SNathan Froyd        Altivec/FP/SPE support.  Anything else is just a bonus.  */
788df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature)                                      \
789a2247f8eSAndreas Färber     do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
79058eb5308SMichael Walle #define GET_FEATURE2(flags, feature) \
79158eb5308SMichael Walle     do { \
79258eb5308SMichael Walle         if ((cpu->env.insns_flags2 & flags) == flags) { \
79358eb5308SMichael Walle             features |= feature; \
79458eb5308SMichael Walle         } \
79558eb5308SMichael Walle     } while (0)
7963efa9a67Smalc     GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64);
7973efa9a67Smalc     GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU);
7983efa9a67Smalc     GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC);
7993efa9a67Smalc     GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE);
8003efa9a67Smalc     GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE);
8013efa9a67Smalc     GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE);
8023efa9a67Smalc     GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE);
8033efa9a67Smalc     GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC);
8040e019746STom Musta     GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP);
8050e019746STom Musta     GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX);
8060e019746STom Musta     GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 |
8070e019746STom Musta                   PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206),
8080e019746STom Musta                   QEMU_PPC_FEATURE_ARCH_2_06);
809df84e4f3SNathan Froyd #undef GET_FEATURE
8100e019746STom Musta #undef GET_FEATURE2
811df84e4f3SNathan Froyd 
812df84e4f3SNathan Froyd     return features;
813df84e4f3SNathan Froyd }
814df84e4f3SNathan Froyd 
815a60438ddSTom Musta #define ELF_HWCAP2 get_elf_hwcap2()
816a60438ddSTom Musta 
817a60438ddSTom Musta static uint32_t get_elf_hwcap2(void)
818a60438ddSTom Musta {
819a60438ddSTom Musta     PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);
820a60438ddSTom Musta     uint32_t features = 0;
821a60438ddSTom Musta 
822a60438ddSTom Musta #define GET_FEATURE(flag, feature)                                      \
823a60438ddSTom Musta     do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0)
824a60438ddSTom Musta #define GET_FEATURE2(flag, feature)                                      \
825a60438ddSTom Musta     do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0)
826a60438ddSTom Musta 
827a60438ddSTom Musta     GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL);
828a60438ddSTom Musta     GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR);
829a60438ddSTom Musta     GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
83024c373ecSLaurent Vivier                   PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07 |
83124c373ecSLaurent Vivier                   QEMU_PPC_FEATURE2_VEC_CRYPTO);
83224c373ecSLaurent Vivier     GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 |
8338a589aebSKhem Raj                  QEMU_PPC_FEATURE2_DARN | QEMU_PPC_FEATURE2_HAS_IEEE128);
834a60438ddSTom Musta 
835a60438ddSTom Musta #undef GET_FEATURE
836a60438ddSTom Musta #undef GET_FEATURE2
837a60438ddSTom Musta 
838a60438ddSTom Musta     return features;
839a60438ddSTom Musta }
840a60438ddSTom Musta 
841f5155289Sbellard /*
842f5155289Sbellard  * The requirements here are:
843f5155289Sbellard  * - keep the final alignment of sp (sp & 0xf)
844f5155289Sbellard  * - make sure the 32-bit value at the first 16 byte aligned position of
845f5155289Sbellard  *   AUXV is greater than 16 for glibc compatibility.
846f5155289Sbellard  *   AT_IGNOREPPC is used for that.
847f5155289Sbellard  * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
848f5155289Sbellard  *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
849f5155289Sbellard  */
8500bccf03dSbellard #define DLINFO_ARCH_ITEMS       5
851f5155289Sbellard #define ARCH_DLINFO                                     \
852f5155289Sbellard     do {                                                \
853623e250aSTom Musta         PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);              \
854f5155289Sbellard         /*                                              \
85582991bedSPeter Maydell          * Handle glibc compatibility: these magic entries must \
85682991bedSPeter Maydell          * be at the lowest addresses in the final auxv.        \
857f5155289Sbellard          */                                             \
8580bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
8590bccf03dSbellard         NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \
86082991bedSPeter Maydell         NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \
86182991bedSPeter Maydell         NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \
86282991bedSPeter Maydell         NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \
863f5155289Sbellard     } while (0)
864f5155289Sbellard 
86567867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
86667867308Sbellard {
86767867308Sbellard     _regs->gpr[1] = infop->start_stack;
868e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
869d90b94cdSDoug Kwan     if (get_ppc64_abi(infop) < 2) {
8702ccf97ecSPeter Maydell         uint64_t val;
8712ccf97ecSPeter Maydell         get_user_u64(val, infop->entry + 8);
8722ccf97ecSPeter Maydell         _regs->gpr[2] = val + infop->load_bias;
8732ccf97ecSPeter Maydell         get_user_u64(val, infop->entry);
8742ccf97ecSPeter Maydell         infop->entry = val + infop->load_bias;
875d90b94cdSDoug Kwan     } else {
876d90b94cdSDoug Kwan         _regs->gpr[12] = infop->entry;  /* r12 set to global entry address */
877d90b94cdSDoug Kwan     }
87884409ddbSj_mayer #endif
87967867308Sbellard     _regs->nip = infop->entry;
88067867308Sbellard }
88167867308Sbellard 
882e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h.  */
883e2f3e741SNathan Froyd #define ELF_NREG 48
884e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
885e2f3e741SNathan Froyd 
88605390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env)
887e2f3e741SNathan Froyd {
888e2f3e741SNathan Froyd     int i;
889e2f3e741SNathan Froyd     target_ulong ccr = 0;
890e2f3e741SNathan Froyd 
891e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->gpr); i++) {
89286cd7b2dSPaolo Bonzini         (*regs)[i] = tswapreg(env->gpr[i]);
893e2f3e741SNathan Froyd     }
894e2f3e741SNathan Froyd 
89586cd7b2dSPaolo Bonzini     (*regs)[32] = tswapreg(env->nip);
89686cd7b2dSPaolo Bonzini     (*regs)[33] = tswapreg(env->msr);
89786cd7b2dSPaolo Bonzini     (*regs)[35] = tswapreg(env->ctr);
89886cd7b2dSPaolo Bonzini     (*regs)[36] = tswapreg(env->lr);
89986cd7b2dSPaolo Bonzini     (*regs)[37] = tswapreg(env->xer);
900e2f3e741SNathan Froyd 
901e2f3e741SNathan Froyd     for (i = 0; i < ARRAY_SIZE(env->crf); i++) {
902e2f3e741SNathan Froyd         ccr |= env->crf[i] << (32 - ((i + 1) * 4));
903e2f3e741SNathan Froyd     }
90486cd7b2dSPaolo Bonzini     (*regs)[38] = tswapreg(ccr);
905e2f3e741SNathan Froyd }
906e2f3e741SNathan Froyd 
907e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP
90867867308Sbellard #define ELF_EXEC_PAGESIZE       4096
90967867308Sbellard 
91067867308Sbellard #endif
91167867308Sbellard 
912048f6b4dSbellard #ifdef TARGET_MIPS
913048f6b4dSbellard 
914048f6b4dSbellard #define ELF_START_MMAP 0x80000000
915048f6b4dSbellard 
916388bb21aSths #ifdef TARGET_MIPS64
917388bb21aSths #define ELF_CLASS   ELFCLASS64
918388bb21aSths #else
919048f6b4dSbellard #define ELF_CLASS   ELFCLASS32
920388bb21aSths #endif
921048f6b4dSbellard #define ELF_ARCH    EM_MIPS
922048f6b4dSbellard 
923f72541f3SAleksandar Markovic #define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_NANOMIPS)
924f72541f3SAleksandar Markovic 
925ace3d654SCarlo Marcelo Arenas Belón #ifdef TARGET_ABI_MIPSN32
926ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) ((x) & EF_MIPS_ABI2)
927ace3d654SCarlo Marcelo Arenas Belón #else
928ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (!((x) & EF_MIPS_ABI2))
929ace3d654SCarlo Marcelo Arenas Belón #endif
930ace3d654SCarlo Marcelo Arenas Belón 
931d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
932d97ef72eSRichard Henderson                                struct image_info *infop)
933048f6b4dSbellard {
934623a930eSths     regs->cp0_status = 2 << CP0St_KSU;
935048f6b4dSbellard     regs->cp0_epc = infop->entry;
936048f6b4dSbellard     regs->regs[29] = infop->start_stack;
937048f6b4dSbellard }
938048f6b4dSbellard 
93951e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h.  */
94051e52606SNathan Froyd #define ELF_NREG 45
94151e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
94251e52606SNathan Froyd 
94351e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h.  */
94451e52606SNathan Froyd enum {
94551e52606SNathan Froyd #ifdef TARGET_MIPS64
94651e52606SNathan Froyd     TARGET_EF_R0 = 0,
94751e52606SNathan Froyd #else
94851e52606SNathan Froyd     TARGET_EF_R0 = 6,
94951e52606SNathan Froyd #endif
95051e52606SNathan Froyd     TARGET_EF_R26 = TARGET_EF_R0 + 26,
95151e52606SNathan Froyd     TARGET_EF_R27 = TARGET_EF_R0 + 27,
95251e52606SNathan Froyd     TARGET_EF_LO = TARGET_EF_R0 + 32,
95351e52606SNathan Froyd     TARGET_EF_HI = TARGET_EF_R0 + 33,
95451e52606SNathan Froyd     TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34,
95551e52606SNathan Froyd     TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35,
95651e52606SNathan Froyd     TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36,
95751e52606SNathan Froyd     TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37
95851e52606SNathan Froyd };
95951e52606SNathan Froyd 
96051e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
96105390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env)
96251e52606SNathan Froyd {
96351e52606SNathan Froyd     int i;
96451e52606SNathan Froyd 
96551e52606SNathan Froyd     for (i = 0; i < TARGET_EF_R0; i++) {
96651e52606SNathan Froyd         (*regs)[i] = 0;
96751e52606SNathan Froyd     }
96851e52606SNathan Froyd     (*regs)[TARGET_EF_R0] = 0;
96951e52606SNathan Froyd 
97051e52606SNathan Froyd     for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) {
971a29f998dSPaolo Bonzini         (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]);
97251e52606SNathan Froyd     }
97351e52606SNathan Froyd 
97451e52606SNathan Froyd     (*regs)[TARGET_EF_R26] = 0;
97551e52606SNathan Froyd     (*regs)[TARGET_EF_R27] = 0;
976a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]);
977a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]);
978a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC);
979a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr);
980a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status);
981a29f998dSPaolo Bonzini     (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause);
98251e52606SNathan Froyd }
98351e52606SNathan Froyd 
98451e52606SNathan Froyd #define USE_ELF_CORE_DUMP
985388bb21aSths #define ELF_EXEC_PAGESIZE        4096
986388bb21aSths 
98746a1ee4fSJames Cowgill /* See arch/mips/include/uapi/asm/hwcap.h.  */
98846a1ee4fSJames Cowgill enum {
98946a1ee4fSJames Cowgill     HWCAP_MIPS_R6           = (1 << 0),
99046a1ee4fSJames Cowgill     HWCAP_MIPS_MSA          = (1 << 1),
9919ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_CRC32        = (1 << 2),
9929ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MIPS16       = (1 << 3),
9939ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MDMX         = (1 << 4),
9949ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MIPS3D       = (1 << 5),
9959ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_SMARTMIPS    = (1 << 6),
9969ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_DSP          = (1 << 7),
9979ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_DSP2         = (1 << 8),
9989ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_DSP3         = (1 << 9),
9999ea313baSPhilippe Mathieu-Daudé     HWCAP_MIPS_MIPS16E2     = (1 << 10),
10009ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_MMI      = (1 << 11),
10019ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_EXT      = (1 << 12),
10029ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_EXT2     = (1 << 13),
10039ea313baSPhilippe Mathieu-Daudé     HWCAP_LOONGSON_CPUCFG   = (1 << 14),
100446a1ee4fSJames Cowgill };
100546a1ee4fSJames Cowgill 
100646a1ee4fSJames Cowgill #define ELF_HWCAP get_elf_hwcap()
100746a1ee4fSJames Cowgill 
10087d9a3d96SPhilippe Mathieu-Daudé #define GET_FEATURE_INSN(_flag, _hwcap) \
10096dd97bfcSPhilippe Mathieu-Daudé     do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0)
10106dd97bfcSPhilippe Mathieu-Daudé 
1011388765a0SPhilippe Mathieu-Daudé #define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \
1012388765a0SPhilippe Mathieu-Daudé     do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0)
1013388765a0SPhilippe Mathieu-Daudé 
1014ce543844SPhilippe Mathieu-Daudé #define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \
1015ce543844SPhilippe Mathieu-Daudé     do { \
1016ce543844SPhilippe Mathieu-Daudé         if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \
1017ce543844SPhilippe Mathieu-Daudé             hwcaps |= _hwcap; \
1018ce543844SPhilippe Mathieu-Daudé         } \
1019ce543844SPhilippe Mathieu-Daudé     } while (0)
1020ce543844SPhilippe Mathieu-Daudé 
102146a1ee4fSJames Cowgill static uint32_t get_elf_hwcap(void)
102246a1ee4fSJames Cowgill {
102346a1ee4fSJames Cowgill     MIPSCPU *cpu = MIPS_CPU(thread_cpu);
102446a1ee4fSJames Cowgill     uint32_t hwcaps = 0;
102546a1ee4fSJames Cowgill 
1026ce543844SPhilippe Mathieu-Daudé     GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH,
1027ce543844SPhilippe Mathieu-Daudé                         2, HWCAP_MIPS_R6);
1028388765a0SPhilippe Mathieu-Daudé     GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA);
102953673d0fSPhilippe Mathieu-Daudé     GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI);
103053673d0fSPhilippe Mathieu-Daudé     GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT);
103146a1ee4fSJames Cowgill 
103246a1ee4fSJames Cowgill     return hwcaps;
103346a1ee4fSJames Cowgill }
103446a1ee4fSJames Cowgill 
1035ce543844SPhilippe Mathieu-Daudé #undef GET_FEATURE_REG_EQU
1036388765a0SPhilippe Mathieu-Daudé #undef GET_FEATURE_REG_SET
10377d9a3d96SPhilippe Mathieu-Daudé #undef GET_FEATURE_INSN
10386dd97bfcSPhilippe Mathieu-Daudé 
1039048f6b4dSbellard #endif /* TARGET_MIPS */
1040048f6b4dSbellard 
1041b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE
1042b779e29eSEdgar E. Iglesias 
1043b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000
1044b779e29eSEdgar E. Iglesias 
10450d5d4699SEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
1046b779e29eSEdgar E. Iglesias 
1047b779e29eSEdgar E. Iglesias #define ELF_CLASS   ELFCLASS32
10480d5d4699SEdgar E. Iglesias #define ELF_ARCH    EM_MICROBLAZE
1049b779e29eSEdgar E. Iglesias 
1050d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1051d97ef72eSRichard Henderson                                struct image_info *infop)
1052b779e29eSEdgar E. Iglesias {
1053b779e29eSEdgar E. Iglesias     regs->pc = infop->entry;
1054b779e29eSEdgar E. Iglesias     regs->r1 = infop->start_stack;
1055b779e29eSEdgar E. Iglesias 
1056b779e29eSEdgar E. Iglesias }
1057b779e29eSEdgar E. Iglesias 
1058b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE        4096
1059b779e29eSEdgar E. Iglesias 
1060e4cbd44dSEdgar E. Iglesias #define USE_ELF_CORE_DUMP
1061e4cbd44dSEdgar E. Iglesias #define ELF_NREG 38
1062e4cbd44dSEdgar E. Iglesias typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1063e4cbd44dSEdgar E. Iglesias 
1064e4cbd44dSEdgar E. Iglesias /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
106505390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env)
1066e4cbd44dSEdgar E. Iglesias {
1067e4cbd44dSEdgar E. Iglesias     int i, pos = 0;
1068e4cbd44dSEdgar E. Iglesias 
1069e4cbd44dSEdgar E. Iglesias     for (i = 0; i < 32; i++) {
107086cd7b2dSPaolo Bonzini         (*regs)[pos++] = tswapreg(env->regs[i]);
1071e4cbd44dSEdgar E. Iglesias     }
1072e4cbd44dSEdgar E. Iglesias 
1073af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->pc);
10741074c0fbSRichard Henderson     (*regs)[pos++] = tswapreg(mb_cpu_read_msr(env));
1075af20a93aSRichard Henderson     (*regs)[pos++] = 0;
1076af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->ear);
1077af20a93aSRichard Henderson     (*regs)[pos++] = 0;
1078af20a93aSRichard Henderson     (*regs)[pos++] = tswapreg(env->esr);
1079e4cbd44dSEdgar E. Iglesias }
1080e4cbd44dSEdgar E. Iglesias 
1081b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */
1082b779e29eSEdgar E. Iglesias 
1083a0a839b6SMarek Vasut #ifdef TARGET_NIOS2
1084a0a839b6SMarek Vasut 
1085a0a839b6SMarek Vasut #define ELF_START_MMAP 0x80000000
1086a0a839b6SMarek Vasut 
1087a0a839b6SMarek Vasut #define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2)
1088a0a839b6SMarek Vasut 
1089a0a839b6SMarek Vasut #define ELF_CLASS   ELFCLASS32
1090a0a839b6SMarek Vasut #define ELF_ARCH    EM_ALTERA_NIOS2
1091a0a839b6SMarek Vasut 
1092a0a839b6SMarek Vasut static void init_thread(struct target_pt_regs *regs, struct image_info *infop)
1093a0a839b6SMarek Vasut {
1094a0a839b6SMarek Vasut     regs->ea = infop->entry;
1095a0a839b6SMarek Vasut     regs->sp = infop->start_stack;
1096a0a839b6SMarek Vasut     regs->estatus = 0x3;
1097a0a839b6SMarek Vasut }
1098a0a839b6SMarek Vasut 
1099a0a839b6SMarek Vasut #define ELF_EXEC_PAGESIZE        4096
1100a0a839b6SMarek Vasut 
1101a0a839b6SMarek Vasut #define USE_ELF_CORE_DUMP
1102a0a839b6SMarek Vasut #define ELF_NREG 49
1103a0a839b6SMarek Vasut typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1104a0a839b6SMarek Vasut 
1105a0a839b6SMarek Vasut /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */
1106a0a839b6SMarek Vasut static void elf_core_copy_regs(target_elf_gregset_t *regs,
1107a0a839b6SMarek Vasut                                const CPUNios2State *env)
1108a0a839b6SMarek Vasut {
1109a0a839b6SMarek Vasut     int i;
1110a0a839b6SMarek Vasut 
1111a0a839b6SMarek Vasut     (*regs)[0] = -1;
1112a0a839b6SMarek Vasut     for (i = 1; i < 8; i++)    /* r0-r7 */
1113a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i + 7]);
1114a0a839b6SMarek Vasut 
1115a0a839b6SMarek Vasut     for (i = 8; i < 16; i++)   /* r8-r15 */
1116a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i - 8]);
1117a0a839b6SMarek Vasut 
1118a0a839b6SMarek Vasut     for (i = 16; i < 24; i++)  /* r16-r23 */
1119a0a839b6SMarek Vasut         (*regs)[i] = tswapreg(env->regs[i + 7]);
1120a0a839b6SMarek Vasut     (*regs)[24] = -1;    /* R_ET */
1121a0a839b6SMarek Vasut     (*regs)[25] = -1;    /* R_BT */
1122a0a839b6SMarek Vasut     (*regs)[26] = tswapreg(env->regs[R_GP]);
1123a0a839b6SMarek Vasut     (*regs)[27] = tswapreg(env->regs[R_SP]);
1124a0a839b6SMarek Vasut     (*regs)[28] = tswapreg(env->regs[R_FP]);
1125a0a839b6SMarek Vasut     (*regs)[29] = tswapreg(env->regs[R_EA]);
1126a0a839b6SMarek Vasut     (*regs)[30] = -1;    /* R_SSTATUS */
1127a0a839b6SMarek Vasut     (*regs)[31] = tswapreg(env->regs[R_RA]);
1128a0a839b6SMarek Vasut 
1129a0a839b6SMarek Vasut     (*regs)[32] = tswapreg(env->regs[R_PC]);
1130a0a839b6SMarek Vasut 
1131a0a839b6SMarek Vasut     (*regs)[33] = -1; /* R_STATUS */
1132a0a839b6SMarek Vasut     (*regs)[34] = tswapreg(env->regs[CR_ESTATUS]);
1133a0a839b6SMarek Vasut 
1134a0a839b6SMarek Vasut     for (i = 35; i < 49; i++)    /* ... */
1135a0a839b6SMarek Vasut         (*regs)[i] = -1;
1136a0a839b6SMarek Vasut }
1137a0a839b6SMarek Vasut 
1138a0a839b6SMarek Vasut #endif /* TARGET_NIOS2 */
1139a0a839b6SMarek Vasut 
1140d962783eSJia Liu #ifdef TARGET_OPENRISC
1141d962783eSJia Liu 
1142d962783eSJia Liu #define ELF_START_MMAP 0x08000000
1143d962783eSJia Liu 
1144d962783eSJia Liu #define ELF_ARCH EM_OPENRISC
1145d962783eSJia Liu #define ELF_CLASS ELFCLASS32
1146d962783eSJia Liu #define ELF_DATA  ELFDATA2MSB
1147d962783eSJia Liu 
1148d962783eSJia Liu static inline void init_thread(struct target_pt_regs *regs,
1149d962783eSJia Liu                                struct image_info *infop)
1150d962783eSJia Liu {
1151d962783eSJia Liu     regs->pc = infop->entry;
1152d962783eSJia Liu     regs->gpr[1] = infop->start_stack;
1153d962783eSJia Liu }
1154d962783eSJia Liu 
1155d962783eSJia Liu #define USE_ELF_CORE_DUMP
1156d962783eSJia Liu #define ELF_EXEC_PAGESIZE 8192
1157d962783eSJia Liu 
1158d962783eSJia Liu /* See linux kernel arch/openrisc/include/asm/elf.h.  */
1159d962783eSJia Liu #define ELF_NREG 34 /* gprs and pc, sr */
1160d962783eSJia Liu typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1161d962783eSJia Liu 
1162d962783eSJia Liu static void elf_core_copy_regs(target_elf_gregset_t *regs,
1163d962783eSJia Liu                                const CPUOpenRISCState *env)
1164d962783eSJia Liu {
1165d962783eSJia Liu     int i;
1166d962783eSJia Liu 
1167d962783eSJia Liu     for (i = 0; i < 32; i++) {
1168d89e71e8SStafford Horne         (*regs)[i] = tswapreg(cpu_get_gpr(env, i));
1169d962783eSJia Liu     }
117086cd7b2dSPaolo Bonzini     (*regs)[32] = tswapreg(env->pc);
117184775c43SRichard Henderson     (*regs)[33] = tswapreg(cpu_get_sr(env));
1172d962783eSJia Liu }
1173d962783eSJia Liu #define ELF_HWCAP 0
1174d962783eSJia Liu #define ELF_PLATFORM NULL
1175d962783eSJia Liu 
1176d962783eSJia Liu #endif /* TARGET_OPENRISC */
1177d962783eSJia Liu 
1178fdf9b3e8Sbellard #ifdef TARGET_SH4
1179fdf9b3e8Sbellard 
1180fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000
1181fdf9b3e8Sbellard 
1182fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32
1183fdf9b3e8Sbellard #define ELF_ARCH  EM_SH
1184fdf9b3e8Sbellard 
1185d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1186d97ef72eSRichard Henderson                                struct image_info *infop)
1187fdf9b3e8Sbellard {
1188fdf9b3e8Sbellard     /* Check other registers XXXXX */
1189fdf9b3e8Sbellard     regs->pc = infop->entry;
1190072ae847Sths     regs->regs[15] = infop->start_stack;
1191fdf9b3e8Sbellard }
1192fdf9b3e8Sbellard 
11937631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h.  */
11947631c97eSNathan Froyd #define ELF_NREG 23
11957631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
11967631c97eSNathan Froyd 
11977631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h.  */
11987631c97eSNathan Froyd enum {
11997631c97eSNathan Froyd     TARGET_REG_PC = 16,
12007631c97eSNathan Froyd     TARGET_REG_PR = 17,
12017631c97eSNathan Froyd     TARGET_REG_SR = 18,
12027631c97eSNathan Froyd     TARGET_REG_GBR = 19,
12037631c97eSNathan Froyd     TARGET_REG_MACH = 20,
12047631c97eSNathan Froyd     TARGET_REG_MACL = 21,
12057631c97eSNathan Froyd     TARGET_REG_SYSCALL = 22
12067631c97eSNathan Froyd };
12077631c97eSNathan Froyd 
1208d97ef72eSRichard Henderson static inline void elf_core_copy_regs(target_elf_gregset_t *regs,
120905390248SAndreas Färber                                       const CPUSH4State *env)
12107631c97eSNathan Froyd {
12117631c97eSNathan Froyd     int i;
12127631c97eSNathan Froyd 
12137631c97eSNathan Froyd     for (i = 0; i < 16; i++) {
121472cd500bSPhilippe Mathieu-Daudé         (*regs)[i] = tswapreg(env->gregs[i]);
12157631c97eSNathan Froyd     }
12167631c97eSNathan Froyd 
121786cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
121886cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_PR] = tswapreg(env->pr);
121986cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_SR] = tswapreg(env->sr);
122086cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr);
122186cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_MACH] = tswapreg(env->mach);
122286cd7b2dSPaolo Bonzini     (*regs)[TARGET_REG_MACL] = tswapreg(env->macl);
12237631c97eSNathan Froyd     (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */
12247631c97eSNathan Froyd }
12257631c97eSNathan Froyd 
12267631c97eSNathan Froyd #define USE_ELF_CORE_DUMP
1227fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE        4096
1228fdf9b3e8Sbellard 
1229e42fd944SRichard Henderson enum {
1230e42fd944SRichard Henderson     SH_CPU_HAS_FPU            = 0x0001, /* Hardware FPU support */
1231e42fd944SRichard Henderson     SH_CPU_HAS_P2_FLUSH_BUG   = 0x0002, /* Need to flush the cache in P2 area */
1232e42fd944SRichard Henderson     SH_CPU_HAS_MMU_PAGE_ASSOC = 0x0004, /* SH3: TLB way selection bit support */
1233e42fd944SRichard Henderson     SH_CPU_HAS_DSP            = 0x0008, /* SH-DSP: DSP support */
1234e42fd944SRichard Henderson     SH_CPU_HAS_PERF_COUNTER   = 0x0010, /* Hardware performance counters */
1235e42fd944SRichard Henderson     SH_CPU_HAS_PTEA           = 0x0020, /* PTEA register */
1236e42fd944SRichard Henderson     SH_CPU_HAS_LLSC           = 0x0040, /* movli.l/movco.l */
1237e42fd944SRichard Henderson     SH_CPU_HAS_L2_CACHE       = 0x0080, /* Secondary cache / URAM */
1238e42fd944SRichard Henderson     SH_CPU_HAS_OP32           = 0x0100, /* 32-bit instruction support */
1239e42fd944SRichard Henderson     SH_CPU_HAS_PTEAEX         = 0x0200, /* PTE ASID Extension support */
1240e42fd944SRichard Henderson };
1241e42fd944SRichard Henderson 
1242e42fd944SRichard Henderson #define ELF_HWCAP get_elf_hwcap()
1243e42fd944SRichard Henderson 
1244e42fd944SRichard Henderson static uint32_t get_elf_hwcap(void)
1245e42fd944SRichard Henderson {
1246e42fd944SRichard Henderson     SuperHCPU *cpu = SUPERH_CPU(thread_cpu);
1247e42fd944SRichard Henderson     uint32_t hwcap = 0;
1248e42fd944SRichard Henderson 
1249e42fd944SRichard Henderson     hwcap |= SH_CPU_HAS_FPU;
1250e42fd944SRichard Henderson 
1251e42fd944SRichard Henderson     if (cpu->env.features & SH_FEATURE_SH4A) {
1252e42fd944SRichard Henderson         hwcap |= SH_CPU_HAS_LLSC;
1253e42fd944SRichard Henderson     }
1254e42fd944SRichard Henderson 
1255e42fd944SRichard Henderson     return hwcap;
1256e42fd944SRichard Henderson }
1257e42fd944SRichard Henderson 
1258fdf9b3e8Sbellard #endif
1259fdf9b3e8Sbellard 
126048733d19Sths #ifdef TARGET_CRIS
126148733d19Sths 
126248733d19Sths #define ELF_START_MMAP 0x80000000
126348733d19Sths 
126448733d19Sths #define ELF_CLASS ELFCLASS32
126548733d19Sths #define ELF_ARCH  EM_CRIS
126648733d19Sths 
1267d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1268d97ef72eSRichard Henderson                                struct image_info *infop)
126948733d19Sths {
127048733d19Sths     regs->erp = infop->entry;
127148733d19Sths }
127248733d19Sths 
127348733d19Sths #define ELF_EXEC_PAGESIZE        8192
127448733d19Sths 
127548733d19Sths #endif
127648733d19Sths 
1277e6e5906bSpbrook #ifdef TARGET_M68K
1278e6e5906bSpbrook 
1279e6e5906bSpbrook #define ELF_START_MMAP 0x80000000
1280e6e5906bSpbrook 
1281e6e5906bSpbrook #define ELF_CLASS       ELFCLASS32
1282e6e5906bSpbrook #define ELF_ARCH        EM_68K
1283e6e5906bSpbrook 
1284e6e5906bSpbrook /* ??? Does this need to do anything?
1285e6e5906bSpbrook    #define ELF_PLAT_INIT(_r) */
1286e6e5906bSpbrook 
1287d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1288d97ef72eSRichard Henderson                                struct image_info *infop)
1289e6e5906bSpbrook {
1290e6e5906bSpbrook     regs->usp = infop->start_stack;
1291e6e5906bSpbrook     regs->sr = 0;
1292e6e5906bSpbrook     regs->pc = infop->entry;
1293e6e5906bSpbrook }
1294e6e5906bSpbrook 
12957a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h.  */
12967a93cc55SNathan Froyd #define ELF_NREG 20
12977a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
12987a93cc55SNathan Froyd 
129905390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env)
13007a93cc55SNathan Froyd {
130186cd7b2dSPaolo Bonzini     (*regs)[0] = tswapreg(env->dregs[1]);
130286cd7b2dSPaolo Bonzini     (*regs)[1] = tswapreg(env->dregs[2]);
130386cd7b2dSPaolo Bonzini     (*regs)[2] = tswapreg(env->dregs[3]);
130486cd7b2dSPaolo Bonzini     (*regs)[3] = tswapreg(env->dregs[4]);
130586cd7b2dSPaolo Bonzini     (*regs)[4] = tswapreg(env->dregs[5]);
130686cd7b2dSPaolo Bonzini     (*regs)[5] = tswapreg(env->dregs[6]);
130786cd7b2dSPaolo Bonzini     (*regs)[6] = tswapreg(env->dregs[7]);
130886cd7b2dSPaolo Bonzini     (*regs)[7] = tswapreg(env->aregs[0]);
130986cd7b2dSPaolo Bonzini     (*regs)[8] = tswapreg(env->aregs[1]);
131086cd7b2dSPaolo Bonzini     (*regs)[9] = tswapreg(env->aregs[2]);
131186cd7b2dSPaolo Bonzini     (*regs)[10] = tswapreg(env->aregs[3]);
131286cd7b2dSPaolo Bonzini     (*regs)[11] = tswapreg(env->aregs[4]);
131386cd7b2dSPaolo Bonzini     (*regs)[12] = tswapreg(env->aregs[5]);
131486cd7b2dSPaolo Bonzini     (*regs)[13] = tswapreg(env->aregs[6]);
131586cd7b2dSPaolo Bonzini     (*regs)[14] = tswapreg(env->dregs[0]);
131686cd7b2dSPaolo Bonzini     (*regs)[15] = tswapreg(env->aregs[7]);
131786cd7b2dSPaolo Bonzini     (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */
131886cd7b2dSPaolo Bonzini     (*regs)[17] = tswapreg(env->sr);
131986cd7b2dSPaolo Bonzini     (*regs)[18] = tswapreg(env->pc);
13207a93cc55SNathan Froyd     (*regs)[19] = 0;  /* FIXME: regs->format | regs->vector */
13217a93cc55SNathan Froyd }
13227a93cc55SNathan Froyd 
13237a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP
1324e6e5906bSpbrook #define ELF_EXEC_PAGESIZE       8192
1325e6e5906bSpbrook 
1326e6e5906bSpbrook #endif
1327e6e5906bSpbrook 
13287a3148a9Sj_mayer #ifdef TARGET_ALPHA
13297a3148a9Sj_mayer 
13307a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL)
13317a3148a9Sj_mayer 
13327a3148a9Sj_mayer #define ELF_CLASS      ELFCLASS64
13337a3148a9Sj_mayer #define ELF_ARCH       EM_ALPHA
13347a3148a9Sj_mayer 
1335d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
1336d97ef72eSRichard Henderson                                struct image_info *infop)
13377a3148a9Sj_mayer {
13387a3148a9Sj_mayer     regs->pc = infop->entry;
13397a3148a9Sj_mayer     regs->ps = 8;
13407a3148a9Sj_mayer     regs->usp = infop->start_stack;
13417a3148a9Sj_mayer }
13427a3148a9Sj_mayer 
13437a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE        8192
13447a3148a9Sj_mayer 
13457a3148a9Sj_mayer #endif /* TARGET_ALPHA */
13467a3148a9Sj_mayer 
1347a4c075f1SUlrich Hecht #ifdef TARGET_S390X
1348a4c075f1SUlrich Hecht 
1349a4c075f1SUlrich Hecht #define ELF_START_MMAP (0x20000000000ULL)
1350a4c075f1SUlrich Hecht 
1351a4c075f1SUlrich Hecht #define ELF_CLASS	ELFCLASS64
1352a4c075f1SUlrich Hecht #define ELF_DATA	ELFDATA2MSB
1353a4c075f1SUlrich Hecht #define ELF_ARCH	EM_S390
1354a4c075f1SUlrich Hecht 
13556d88baf1SDavid Hildenbrand #include "elf.h"
13566d88baf1SDavid Hildenbrand 
13576d88baf1SDavid Hildenbrand #define ELF_HWCAP get_elf_hwcap()
13586d88baf1SDavid Hildenbrand 
13596d88baf1SDavid Hildenbrand #define GET_FEATURE(_feat, _hwcap) \
13606d88baf1SDavid Hildenbrand     do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0)
13616d88baf1SDavid Hildenbrand 
13626d88baf1SDavid Hildenbrand static uint32_t get_elf_hwcap(void)
13636d88baf1SDavid Hildenbrand {
13646d88baf1SDavid Hildenbrand     /*
13656d88baf1SDavid Hildenbrand      * Let's assume we always have esan3 and zarch.
13666d88baf1SDavid Hildenbrand      * 31-bit processes can use 64-bit registers (high gprs).
13676d88baf1SDavid Hildenbrand      */
13686d88baf1SDavid Hildenbrand     uint32_t hwcap = HWCAP_S390_ESAN3 | HWCAP_S390_ZARCH | HWCAP_S390_HIGH_GPRS;
13696d88baf1SDavid Hildenbrand 
13706d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_STFLE, HWCAP_S390_STFLE);
13716d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_MSA, HWCAP_S390_MSA);
13726d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_LONG_DISPLACEMENT, HWCAP_S390_LDISP);
13736d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_EXTENDED_IMMEDIATE, HWCAP_S390_EIMM);
13746d88baf1SDavid Hildenbrand     if (s390_has_feat(S390_FEAT_EXTENDED_TRANSLATION_3) &&
13756d88baf1SDavid Hildenbrand         s390_has_feat(S390_FEAT_ETF3_ENH)) {
13766d88baf1SDavid Hildenbrand         hwcap |= HWCAP_S390_ETF3EH;
13776d88baf1SDavid Hildenbrand     }
13786d88baf1SDavid Hildenbrand     GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS);
1379da215c23SDavid Hildenbrand     GET_FEATURE(S390_FEAT_VECTOR_ENH, HWCAP_S390_VXRS_EXT);
13806d88baf1SDavid Hildenbrand 
13816d88baf1SDavid Hildenbrand     return hwcap;
13826d88baf1SDavid Hildenbrand }
13836d88baf1SDavid Hildenbrand 
1384a4c075f1SUlrich Hecht static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
1385a4c075f1SUlrich Hecht {
1386a4c075f1SUlrich Hecht     regs->psw.addr = infop->entry;
1387a4c075f1SUlrich Hecht     regs->psw.mask = PSW_MASK_64 | PSW_MASK_32;
1388a4c075f1SUlrich Hecht     regs->gprs[15] = infop->start_stack;
1389a4c075f1SUlrich Hecht }
1390a4c075f1SUlrich Hecht 
13914a1e8931SIlya Leoshkevich /* See linux kernel: arch/s390/include/uapi/asm/ptrace.h (s390_regs).  */
13924a1e8931SIlya Leoshkevich #define ELF_NREG 27
13934a1e8931SIlya Leoshkevich typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
13944a1e8931SIlya Leoshkevich 
13954a1e8931SIlya Leoshkevich enum {
13964a1e8931SIlya Leoshkevich     TARGET_REG_PSWM = 0,
13974a1e8931SIlya Leoshkevich     TARGET_REG_PSWA = 1,
13984a1e8931SIlya Leoshkevich     TARGET_REG_GPRS = 2,
13994a1e8931SIlya Leoshkevich     TARGET_REG_ARS = 18,
14004a1e8931SIlya Leoshkevich     TARGET_REG_ORIG_R2 = 26,
14014a1e8931SIlya Leoshkevich };
14024a1e8931SIlya Leoshkevich 
14034a1e8931SIlya Leoshkevich static void elf_core_copy_regs(target_elf_gregset_t *regs,
14044a1e8931SIlya Leoshkevich                                const CPUS390XState *env)
14054a1e8931SIlya Leoshkevich {
14064a1e8931SIlya Leoshkevich     int i;
14074a1e8931SIlya Leoshkevich     uint32_t *aregs;
14084a1e8931SIlya Leoshkevich 
14094a1e8931SIlya Leoshkevich     (*regs)[TARGET_REG_PSWM] = tswapreg(env->psw.mask);
14104a1e8931SIlya Leoshkevich     (*regs)[TARGET_REG_PSWA] = tswapreg(env->psw.addr);
14114a1e8931SIlya Leoshkevich     for (i = 0; i < 16; i++) {
14124a1e8931SIlya Leoshkevich         (*regs)[TARGET_REG_GPRS + i] = tswapreg(env->regs[i]);
14134a1e8931SIlya Leoshkevich     }
14144a1e8931SIlya Leoshkevich     aregs = (uint32_t *)&((*regs)[TARGET_REG_ARS]);
14154a1e8931SIlya Leoshkevich     for (i = 0; i < 16; i++) {
14164a1e8931SIlya Leoshkevich         aregs[i] = tswap32(env->aregs[i]);
14174a1e8931SIlya Leoshkevich     }
14184a1e8931SIlya Leoshkevich     (*regs)[TARGET_REG_ORIG_R2] = 0;
14194a1e8931SIlya Leoshkevich }
14204a1e8931SIlya Leoshkevich 
14214a1e8931SIlya Leoshkevich #define USE_ELF_CORE_DUMP
14224a1e8931SIlya Leoshkevich #define ELF_EXEC_PAGESIZE 4096
14234a1e8931SIlya Leoshkevich 
1424a4c075f1SUlrich Hecht #endif /* TARGET_S390X */
1425a4c075f1SUlrich Hecht 
142647ae93cdSMichael Clark #ifdef TARGET_RISCV
142747ae93cdSMichael Clark 
142847ae93cdSMichael Clark #define ELF_START_MMAP 0x80000000
142947ae93cdSMichael Clark #define ELF_ARCH  EM_RISCV
143047ae93cdSMichael Clark 
143147ae93cdSMichael Clark #ifdef TARGET_RISCV32
143247ae93cdSMichael Clark #define ELF_CLASS ELFCLASS32
143347ae93cdSMichael Clark #else
143447ae93cdSMichael Clark #define ELF_CLASS ELFCLASS64
143547ae93cdSMichael Clark #endif
143647ae93cdSMichael Clark 
1437cb46938cSKito Cheng #define ELF_HWCAP get_elf_hwcap()
1438cb46938cSKito Cheng 
1439cb46938cSKito Cheng static uint32_t get_elf_hwcap(void)
1440cb46938cSKito Cheng {
1441cb46938cSKito Cheng #define MISA_BIT(EXT) (1 << (EXT - 'A'))
1442cb46938cSKito Cheng     RISCVCPU *cpu = RISCV_CPU(thread_cpu);
1443cb46938cSKito Cheng     uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
1444cb46938cSKito Cheng                     | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
1445cb46938cSKito Cheng 
1446cb46938cSKito Cheng     return cpu->env.misa & mask;
1447cb46938cSKito Cheng #undef MISA_BIT
1448cb46938cSKito Cheng }
1449cb46938cSKito Cheng 
145047ae93cdSMichael Clark static inline void init_thread(struct target_pt_regs *regs,
145147ae93cdSMichael Clark                                struct image_info *infop)
145247ae93cdSMichael Clark {
145347ae93cdSMichael Clark     regs->sepc = infop->entry;
145447ae93cdSMichael Clark     regs->sp = infop->start_stack;
145547ae93cdSMichael Clark }
145647ae93cdSMichael Clark 
145747ae93cdSMichael Clark #define ELF_EXEC_PAGESIZE 4096
145847ae93cdSMichael Clark 
145947ae93cdSMichael Clark #endif /* TARGET_RISCV */
146047ae93cdSMichael Clark 
14617c248bcdSRichard Henderson #ifdef TARGET_HPPA
14627c248bcdSRichard Henderson 
14637c248bcdSRichard Henderson #define ELF_START_MMAP  0x80000000
14647c248bcdSRichard Henderson #define ELF_CLASS       ELFCLASS32
14657c248bcdSRichard Henderson #define ELF_ARCH        EM_PARISC
14667c248bcdSRichard Henderson #define ELF_PLATFORM    "PARISC"
14677c248bcdSRichard Henderson #define STACK_GROWS_DOWN 0
14687c248bcdSRichard Henderson #define STACK_ALIGNMENT  64
14697c248bcdSRichard Henderson 
14707c248bcdSRichard Henderson static inline void init_thread(struct target_pt_regs *regs,
14717c248bcdSRichard Henderson                                struct image_info *infop)
14727c248bcdSRichard Henderson {
14737c248bcdSRichard Henderson     regs->iaoq[0] = infop->entry;
14747c248bcdSRichard Henderson     regs->iaoq[1] = infop->entry + 4;
14757c248bcdSRichard Henderson     regs->gr[23] = 0;
14767c248bcdSRichard Henderson     regs->gr[24] = infop->arg_start;
14777c248bcdSRichard Henderson     regs->gr[25] = (infop->arg_end - infop->arg_start) / sizeof(abi_ulong);
14787c248bcdSRichard Henderson     /* The top-of-stack contains a linkage buffer.  */
14797c248bcdSRichard Henderson     regs->gr[30] = infop->start_stack + 64;
14807c248bcdSRichard Henderson     regs->gr[31] = infop->entry;
14817c248bcdSRichard Henderson }
14827c248bcdSRichard Henderson 
14837c248bcdSRichard Henderson #endif /* TARGET_HPPA */
14847c248bcdSRichard Henderson 
1485ba7651fbSMax Filippov #ifdef TARGET_XTENSA
1486ba7651fbSMax Filippov 
1487ba7651fbSMax Filippov #define ELF_START_MMAP 0x20000000
1488ba7651fbSMax Filippov 
1489ba7651fbSMax Filippov #define ELF_CLASS       ELFCLASS32
1490ba7651fbSMax Filippov #define ELF_ARCH        EM_XTENSA
1491ba7651fbSMax Filippov 
1492ba7651fbSMax Filippov static inline void init_thread(struct target_pt_regs *regs,
1493ba7651fbSMax Filippov                                struct image_info *infop)
1494ba7651fbSMax Filippov {
1495ba7651fbSMax Filippov     regs->windowbase = 0;
1496ba7651fbSMax Filippov     regs->windowstart = 1;
1497ba7651fbSMax Filippov     regs->areg[1] = infop->start_stack;
1498ba7651fbSMax Filippov     regs->pc = infop->entry;
1499ba7651fbSMax Filippov }
1500ba7651fbSMax Filippov 
1501ba7651fbSMax Filippov /* See linux kernel: arch/xtensa/include/asm/elf.h.  */
1502ba7651fbSMax Filippov #define ELF_NREG 128
1503ba7651fbSMax Filippov typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
1504ba7651fbSMax Filippov 
1505ba7651fbSMax Filippov enum {
1506ba7651fbSMax Filippov     TARGET_REG_PC,
1507ba7651fbSMax Filippov     TARGET_REG_PS,
1508ba7651fbSMax Filippov     TARGET_REG_LBEG,
1509ba7651fbSMax Filippov     TARGET_REG_LEND,
1510ba7651fbSMax Filippov     TARGET_REG_LCOUNT,
1511ba7651fbSMax Filippov     TARGET_REG_SAR,
1512ba7651fbSMax Filippov     TARGET_REG_WINDOWSTART,
1513ba7651fbSMax Filippov     TARGET_REG_WINDOWBASE,
1514ba7651fbSMax Filippov     TARGET_REG_THREADPTR,
1515ba7651fbSMax Filippov     TARGET_REG_AR0 = 64,
1516ba7651fbSMax Filippov };
1517ba7651fbSMax Filippov 
1518ba7651fbSMax Filippov static void elf_core_copy_regs(target_elf_gregset_t *regs,
1519ba7651fbSMax Filippov                                const CPUXtensaState *env)
1520ba7651fbSMax Filippov {
1521ba7651fbSMax Filippov     unsigned i;
1522ba7651fbSMax Filippov 
1523ba7651fbSMax Filippov     (*regs)[TARGET_REG_PC] = tswapreg(env->pc);
1524ba7651fbSMax Filippov     (*regs)[TARGET_REG_PS] = tswapreg(env->sregs[PS] & ~PS_EXCM);
1525ba7651fbSMax Filippov     (*regs)[TARGET_REG_LBEG] = tswapreg(env->sregs[LBEG]);
1526ba7651fbSMax Filippov     (*regs)[TARGET_REG_LEND] = tswapreg(env->sregs[LEND]);
1527ba7651fbSMax Filippov     (*regs)[TARGET_REG_LCOUNT] = tswapreg(env->sregs[LCOUNT]);
1528ba7651fbSMax Filippov     (*regs)[TARGET_REG_SAR] = tswapreg(env->sregs[SAR]);
1529ba7651fbSMax Filippov     (*regs)[TARGET_REG_WINDOWSTART] = tswapreg(env->sregs[WINDOW_START]);
1530ba7651fbSMax Filippov     (*regs)[TARGET_REG_WINDOWBASE] = tswapreg(env->sregs[WINDOW_BASE]);
1531ba7651fbSMax Filippov     (*regs)[TARGET_REG_THREADPTR] = tswapreg(env->uregs[THREADPTR]);
1532ba7651fbSMax Filippov     xtensa_sync_phys_from_window((CPUXtensaState *)env);
1533ba7651fbSMax Filippov     for (i = 0; i < env->config->nareg; ++i) {
1534ba7651fbSMax Filippov         (*regs)[TARGET_REG_AR0 + i] = tswapreg(env->phys_regs[i]);
1535ba7651fbSMax Filippov     }
1536ba7651fbSMax Filippov }
1537ba7651fbSMax Filippov 
1538ba7651fbSMax Filippov #define USE_ELF_CORE_DUMP
1539ba7651fbSMax Filippov #define ELF_EXEC_PAGESIZE       4096
1540ba7651fbSMax Filippov 
1541ba7651fbSMax Filippov #endif /* TARGET_XTENSA */
1542ba7651fbSMax Filippov 
1543d2a56bd2STaylor Simpson #ifdef TARGET_HEXAGON
1544d2a56bd2STaylor Simpson 
1545d2a56bd2STaylor Simpson #define ELF_START_MMAP 0x20000000
1546d2a56bd2STaylor Simpson 
1547d2a56bd2STaylor Simpson #define ELF_CLASS       ELFCLASS32
1548d2a56bd2STaylor Simpson #define ELF_ARCH        EM_HEXAGON
1549d2a56bd2STaylor Simpson 
1550d2a56bd2STaylor Simpson static inline void init_thread(struct target_pt_regs *regs,
1551d2a56bd2STaylor Simpson                                struct image_info *infop)
1552d2a56bd2STaylor Simpson {
1553d2a56bd2STaylor Simpson     regs->sepc = infop->entry;
1554d2a56bd2STaylor Simpson     regs->sp = infop->start_stack;
1555d2a56bd2STaylor Simpson }
1556d2a56bd2STaylor Simpson 
1557d2a56bd2STaylor Simpson #endif /* TARGET_HEXAGON */
1558d2a56bd2STaylor Simpson 
155915338fd7Sbellard #ifndef ELF_PLATFORM
156015338fd7Sbellard #define ELF_PLATFORM (NULL)
156115338fd7Sbellard #endif
156215338fd7Sbellard 
156375be901cSPeter Crosthwaite #ifndef ELF_MACHINE
156475be901cSPeter Crosthwaite #define ELF_MACHINE ELF_ARCH
156575be901cSPeter Crosthwaite #endif
156675be901cSPeter Crosthwaite 
1567d276a604SPeter Crosthwaite #ifndef elf_check_arch
1568d276a604SPeter Crosthwaite #define elf_check_arch(x) ((x) == ELF_ARCH)
1569d276a604SPeter Crosthwaite #endif
1570d276a604SPeter Crosthwaite 
1571ace3d654SCarlo Marcelo Arenas Belón #ifndef elf_check_abi
1572ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (1)
1573ace3d654SCarlo Marcelo Arenas Belón #endif
1574ace3d654SCarlo Marcelo Arenas Belón 
157515338fd7Sbellard #ifndef ELF_HWCAP
157615338fd7Sbellard #define ELF_HWCAP 0
157715338fd7Sbellard #endif
157815338fd7Sbellard 
15797c4ee5bcSRichard Henderson #ifndef STACK_GROWS_DOWN
15807c4ee5bcSRichard Henderson #define STACK_GROWS_DOWN 1
15817c4ee5bcSRichard Henderson #endif
15827c4ee5bcSRichard Henderson 
15837c4ee5bcSRichard Henderson #ifndef STACK_ALIGNMENT
15847c4ee5bcSRichard Henderson #define STACK_ALIGNMENT 16
15857c4ee5bcSRichard Henderson #endif
15867c4ee5bcSRichard Henderson 
1587992f48a0Sblueswir1 #ifdef TARGET_ABI32
1588cb33da57Sblueswir1 #undef ELF_CLASS
1589992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32
1590cb33da57Sblueswir1 #undef bswaptls
1591cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr)
1592cb33da57Sblueswir1 #endif
1593cb33da57Sblueswir1 
159431e31b8aSbellard #include "elf.h"
159509bfb054Sbellard 
1596e8384b37SRichard Henderson /* We must delay the following stanzas until after "elf.h". */
1597e8384b37SRichard Henderson #if defined(TARGET_AARCH64)
1598e8384b37SRichard Henderson 
1599e8384b37SRichard Henderson static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
1600e8384b37SRichard Henderson                                     const uint32_t *data,
1601e8384b37SRichard Henderson                                     struct image_info *info,
1602e8384b37SRichard Henderson                                     Error **errp)
1603e8384b37SRichard Henderson {
1604e8384b37SRichard Henderson     if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
1605e8384b37SRichard Henderson         if (pr_datasz != sizeof(uint32_t)) {
1606e8384b37SRichard Henderson             error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND");
1607e8384b37SRichard Henderson             return false;
1608e8384b37SRichard Henderson         }
1609e8384b37SRichard Henderson         /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */
1610e8384b37SRichard Henderson         info->note_flags = *data;
1611e8384b37SRichard Henderson     }
1612e8384b37SRichard Henderson     return true;
1613e8384b37SRichard Henderson }
1614e8384b37SRichard Henderson #define ARCH_USE_GNU_PROPERTY 1
1615e8384b37SRichard Henderson 
1616e8384b37SRichard Henderson #else
1617e8384b37SRichard Henderson 
161883f990ebSRichard Henderson static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz,
161983f990ebSRichard Henderson                                     const uint32_t *data,
162083f990ebSRichard Henderson                                     struct image_info *info,
162183f990ebSRichard Henderson                                     Error **errp)
162283f990ebSRichard Henderson {
162383f990ebSRichard Henderson     g_assert_not_reached();
162483f990ebSRichard Henderson }
162583f990ebSRichard Henderson #define ARCH_USE_GNU_PROPERTY 0
162683f990ebSRichard Henderson 
1627e8384b37SRichard Henderson #endif
1628e8384b37SRichard Henderson 
162909bfb054Sbellard struct exec
163009bfb054Sbellard {
163109bfb054Sbellard     unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
163209bfb054Sbellard     unsigned int a_text;   /* length of text, in bytes */
163309bfb054Sbellard     unsigned int a_data;   /* length of data, in bytes */
163409bfb054Sbellard     unsigned int a_bss;    /* length of uninitialized data area, in bytes */
163509bfb054Sbellard     unsigned int a_syms;   /* length of symbol table data in file, in bytes */
163609bfb054Sbellard     unsigned int a_entry;  /* start address */
163709bfb054Sbellard     unsigned int a_trsize; /* length of relocation info for text, in bytes */
163809bfb054Sbellard     unsigned int a_drsize; /* length of relocation info for data, in bytes */
163909bfb054Sbellard };
164009bfb054Sbellard 
164109bfb054Sbellard 
164209bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff)
164309bfb054Sbellard #define OMAGIC 0407
164409bfb054Sbellard #define NMAGIC 0410
164509bfb054Sbellard #define ZMAGIC 0413
164609bfb054Sbellard #define QMAGIC 0314
164709bfb054Sbellard 
164831e31b8aSbellard /* Necessary parameters */
164994894ff2SShivaprasad G Bhat #define TARGET_ELF_EXEC_PAGESIZE \
165094894ff2SShivaprasad G Bhat         (((eppnt->p_align & ~qemu_host_page_mask) != 0) ? \
165194894ff2SShivaprasad G Bhat          TARGET_PAGE_SIZE : MAX(qemu_host_page_size, TARGET_PAGE_SIZE))
165294894ff2SShivaprasad G Bhat #define TARGET_ELF_PAGELENGTH(_v) ROUND_UP((_v), TARGET_ELF_EXEC_PAGESIZE)
165379cb1f1dSYongbok Kim #define TARGET_ELF_PAGESTART(_v) ((_v) & \
165479cb1f1dSYongbok Kim                                  ~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1))
165554936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
165631e31b8aSbellard 
1657e0d1673dSLirong Yuan #define DLINFO_ITEMS 16
165831e31b8aSbellard 
165909bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
166009bfb054Sbellard {
166109bfb054Sbellard     memcpy(to, from, n);
166209bfb054Sbellard }
166309bfb054Sbellard 
166431e31b8aSbellard #ifdef BSWAP_NEEDED
166592a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr)
166631e31b8aSbellard {
166731e31b8aSbellard     bswap16s(&ehdr->e_type);            /* Object file type */
166831e31b8aSbellard     bswap16s(&ehdr->e_machine);         /* Architecture */
166931e31b8aSbellard     bswap32s(&ehdr->e_version);         /* Object file version */
167092a31b1fSbellard     bswaptls(&ehdr->e_entry);           /* Entry point virtual address */
167192a31b1fSbellard     bswaptls(&ehdr->e_phoff);           /* Program header table file offset */
167292a31b1fSbellard     bswaptls(&ehdr->e_shoff);           /* Section header table file offset */
167331e31b8aSbellard     bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
167431e31b8aSbellard     bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
167531e31b8aSbellard     bswap16s(&ehdr->e_phentsize);       /* Program header table entry size */
167631e31b8aSbellard     bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
167731e31b8aSbellard     bswap16s(&ehdr->e_shentsize);       /* Section header table entry size */
167831e31b8aSbellard     bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
167931e31b8aSbellard     bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */
168031e31b8aSbellard }
168131e31b8aSbellard 
1682991f8f0cSRichard Henderson static void bswap_phdr(struct elf_phdr *phdr, int phnum)
168331e31b8aSbellard {
1684991f8f0cSRichard Henderson     int i;
1685991f8f0cSRichard Henderson     for (i = 0; i < phnum; ++i, ++phdr) {
168631e31b8aSbellard         bswap32s(&phdr->p_type);        /* Segment type */
1687991f8f0cSRichard Henderson         bswap32s(&phdr->p_flags);       /* Segment flags */
168892a31b1fSbellard         bswaptls(&phdr->p_offset);      /* Segment file offset */
168992a31b1fSbellard         bswaptls(&phdr->p_vaddr);       /* Segment virtual address */
169092a31b1fSbellard         bswaptls(&phdr->p_paddr);       /* Segment physical address */
169192a31b1fSbellard         bswaptls(&phdr->p_filesz);      /* Segment size in file */
169292a31b1fSbellard         bswaptls(&phdr->p_memsz);       /* Segment size in memory */
169392a31b1fSbellard         bswaptls(&phdr->p_align);       /* Segment alignment */
169431e31b8aSbellard     }
1695991f8f0cSRichard Henderson }
1696689f936fSbellard 
1697991f8f0cSRichard Henderson static void bswap_shdr(struct elf_shdr *shdr, int shnum)
1698689f936fSbellard {
1699991f8f0cSRichard Henderson     int i;
1700991f8f0cSRichard Henderson     for (i = 0; i < shnum; ++i, ++shdr) {
1701689f936fSbellard         bswap32s(&shdr->sh_name);
1702689f936fSbellard         bswap32s(&shdr->sh_type);
170392a31b1fSbellard         bswaptls(&shdr->sh_flags);
170492a31b1fSbellard         bswaptls(&shdr->sh_addr);
170592a31b1fSbellard         bswaptls(&shdr->sh_offset);
170692a31b1fSbellard         bswaptls(&shdr->sh_size);
1707689f936fSbellard         bswap32s(&shdr->sh_link);
1708689f936fSbellard         bswap32s(&shdr->sh_info);
170992a31b1fSbellard         bswaptls(&shdr->sh_addralign);
171092a31b1fSbellard         bswaptls(&shdr->sh_entsize);
1711689f936fSbellard     }
1712991f8f0cSRichard Henderson }
1713689f936fSbellard 
17147a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym)
1715689f936fSbellard {
1716689f936fSbellard     bswap32s(&sym->st_name);
17177a3148a9Sj_mayer     bswaptls(&sym->st_value);
17187a3148a9Sj_mayer     bswaptls(&sym->st_size);
1719689f936fSbellard     bswap16s(&sym->st_shndx);
1720689f936fSbellard }
17215dd0db52SStefan Markovic 
17225dd0db52SStefan Markovic #ifdef TARGET_MIPS
17235dd0db52SStefan Markovic static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags)
17245dd0db52SStefan Markovic {
17255dd0db52SStefan Markovic     bswap16s(&abiflags->version);
17265dd0db52SStefan Markovic     bswap32s(&abiflags->ases);
17275dd0db52SStefan Markovic     bswap32s(&abiflags->isa_ext);
17285dd0db52SStefan Markovic     bswap32s(&abiflags->flags1);
17295dd0db52SStefan Markovic     bswap32s(&abiflags->flags2);
17305dd0db52SStefan Markovic }
17315dd0db52SStefan Markovic #endif
1732991f8f0cSRichard Henderson #else
1733991f8f0cSRichard Henderson static inline void bswap_ehdr(struct elfhdr *ehdr) { }
1734991f8f0cSRichard Henderson static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { }
1735991f8f0cSRichard Henderson static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { }
1736991f8f0cSRichard Henderson static inline void bswap_sym(struct elf_sym *sym) { }
17375dd0db52SStefan Markovic #ifdef TARGET_MIPS
17385dd0db52SStefan Markovic static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { }
17395dd0db52SStefan Markovic #endif
174031e31b8aSbellard #endif
174131e31b8aSbellard 
1742edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
17439349b4f9SAndreas Färber static int elf_core_dump(int, const CPUArchState *);
1744edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
1745682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias);
1746edf8e2afSMika Westerberg 
17479058abddSRichard Henderson /* Verify the portions of EHDR within E_IDENT for the target.
17489058abddSRichard Henderson    This can be performed before bswapping the entire header.  */
17499058abddSRichard Henderson static bool elf_check_ident(struct elfhdr *ehdr)
17509058abddSRichard Henderson {
17519058abddSRichard Henderson     return (ehdr->e_ident[EI_MAG0] == ELFMAG0
17529058abddSRichard Henderson             && ehdr->e_ident[EI_MAG1] == ELFMAG1
17539058abddSRichard Henderson             && ehdr->e_ident[EI_MAG2] == ELFMAG2
17549058abddSRichard Henderson             && ehdr->e_ident[EI_MAG3] == ELFMAG3
17559058abddSRichard Henderson             && ehdr->e_ident[EI_CLASS] == ELF_CLASS
17569058abddSRichard Henderson             && ehdr->e_ident[EI_DATA] == ELF_DATA
17579058abddSRichard Henderson             && ehdr->e_ident[EI_VERSION] == EV_CURRENT);
17589058abddSRichard Henderson }
17599058abddSRichard Henderson 
17609058abddSRichard Henderson /* Verify the portions of EHDR outside of E_IDENT for the target.
17619058abddSRichard Henderson    This has to wait until after bswapping the header.  */
17629058abddSRichard Henderson static bool elf_check_ehdr(struct elfhdr *ehdr)
17639058abddSRichard Henderson {
17649058abddSRichard Henderson     return (elf_check_arch(ehdr->e_machine)
1765ace3d654SCarlo Marcelo Arenas Belón             && elf_check_abi(ehdr->e_flags)
17669058abddSRichard Henderson             && ehdr->e_ehsize == sizeof(struct elfhdr)
17679058abddSRichard Henderson             && ehdr->e_phentsize == sizeof(struct elf_phdr)
17689058abddSRichard Henderson             && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN));
17699058abddSRichard Henderson }
17709058abddSRichard Henderson 
177131e31b8aSbellard /*
1772e5fe0c52Spbrook  * 'copy_elf_strings()' copies argument/envelope strings from user
177331e31b8aSbellard  * memory to free pages in kernel mem. These are in a format ready
177431e31b8aSbellard  * to be put directly into the top of new user memory.
177531e31b8aSbellard  *
177631e31b8aSbellard  */
177759baae9aSStefan Brüns static abi_ulong copy_elf_strings(int argc, char **argv, char *scratch,
177859baae9aSStefan Brüns                                   abi_ulong p, abi_ulong stack_limit)
177931e31b8aSbellard {
178059baae9aSStefan Brüns     char *tmp;
17817c4ee5bcSRichard Henderson     int len, i;
178259baae9aSStefan Brüns     abi_ulong top = p;
178331e31b8aSbellard 
178431e31b8aSbellard     if (!p) {
178531e31b8aSbellard         return 0;       /* bullet-proofing */
178631e31b8aSbellard     }
178759baae9aSStefan Brüns 
17887c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
17897c4ee5bcSRichard Henderson         int offset = ((p - 1) % TARGET_PAGE_SIZE) + 1;
17907c4ee5bcSRichard Henderson         for (i = argc - 1; i >= 0; --i) {
17917c4ee5bcSRichard Henderson             tmp = argv[i];
1792edf779ffSbellard             if (!tmp) {
179331e31b8aSbellard                 fprintf(stderr, "VFS: argc is wrong");
179431e31b8aSbellard                 exit(-1);
179531e31b8aSbellard             }
179659baae9aSStefan Brüns             len = strlen(tmp) + 1;
179759baae9aSStefan Brüns             tmp += len;
179859baae9aSStefan Brüns 
179959baae9aSStefan Brüns             if (len > (p - stack_limit)) {
180031e31b8aSbellard                 return 0;
180131e31b8aSbellard             }
180231e31b8aSbellard             while (len) {
180331e31b8aSbellard                 int bytes_to_copy = (len > offset) ? offset : len;
180431e31b8aSbellard                 tmp -= bytes_to_copy;
180531e31b8aSbellard                 p -= bytes_to_copy;
180631e31b8aSbellard                 offset -= bytes_to_copy;
180731e31b8aSbellard                 len -= bytes_to_copy;
180859baae9aSStefan Brüns 
180959baae9aSStefan Brüns                 memcpy_fromfs(scratch + offset, tmp, bytes_to_copy);
181059baae9aSStefan Brüns 
181159baae9aSStefan Brüns                 if (offset == 0) {
181259baae9aSStefan Brüns                     memcpy_to_target(p, scratch, top - p);
181359baae9aSStefan Brüns                     top = p;
181459baae9aSStefan Brüns                     offset = TARGET_PAGE_SIZE;
181531e31b8aSbellard                 }
181631e31b8aSbellard             }
181731e31b8aSbellard         }
18187c4ee5bcSRichard Henderson         if (p != top) {
181959baae9aSStefan Brüns             memcpy_to_target(p, scratch + offset, top - p);
182059baae9aSStefan Brüns         }
18217c4ee5bcSRichard Henderson     } else {
18227c4ee5bcSRichard Henderson         int remaining = TARGET_PAGE_SIZE - (p % TARGET_PAGE_SIZE);
18237c4ee5bcSRichard Henderson         for (i = 0; i < argc; ++i) {
18247c4ee5bcSRichard Henderson             tmp = argv[i];
18257c4ee5bcSRichard Henderson             if (!tmp) {
18267c4ee5bcSRichard Henderson                 fprintf(stderr, "VFS: argc is wrong");
18277c4ee5bcSRichard Henderson                 exit(-1);
18287c4ee5bcSRichard Henderson             }
18297c4ee5bcSRichard Henderson             len = strlen(tmp) + 1;
18307c4ee5bcSRichard Henderson             if (len > (stack_limit - p)) {
18317c4ee5bcSRichard Henderson                 return 0;
18327c4ee5bcSRichard Henderson             }
18337c4ee5bcSRichard Henderson             while (len) {
18347c4ee5bcSRichard Henderson                 int bytes_to_copy = (len > remaining) ? remaining : len;
18357c4ee5bcSRichard Henderson 
18367c4ee5bcSRichard Henderson                 memcpy_fromfs(scratch + (p - top), tmp, bytes_to_copy);
18377c4ee5bcSRichard Henderson 
18387c4ee5bcSRichard Henderson                 tmp += bytes_to_copy;
18397c4ee5bcSRichard Henderson                 remaining -= bytes_to_copy;
18407c4ee5bcSRichard Henderson                 p += bytes_to_copy;
18417c4ee5bcSRichard Henderson                 len -= bytes_to_copy;
18427c4ee5bcSRichard Henderson 
18437c4ee5bcSRichard Henderson                 if (remaining == 0) {
18447c4ee5bcSRichard Henderson                     memcpy_to_target(top, scratch, p - top);
18457c4ee5bcSRichard Henderson                     top = p;
18467c4ee5bcSRichard Henderson                     remaining = TARGET_PAGE_SIZE;
18477c4ee5bcSRichard Henderson                 }
18487c4ee5bcSRichard Henderson             }
18497c4ee5bcSRichard Henderson         }
18507c4ee5bcSRichard Henderson         if (p != top) {
18517c4ee5bcSRichard Henderson             memcpy_to_target(top, scratch, p - top);
18527c4ee5bcSRichard Henderson         }
18537c4ee5bcSRichard Henderson     }
185459baae9aSStefan Brüns 
185531e31b8aSbellard     return p;
185631e31b8aSbellard }
185731e31b8aSbellard 
185859baae9aSStefan Brüns /* Older linux kernels provide up to MAX_ARG_PAGES (default: 32) of
185959baae9aSStefan Brüns  * argument/environment space. Newer kernels (>2.6.33) allow more,
186059baae9aSStefan Brüns  * dependent on stack size, but guarantee at least 32 pages for
186159baae9aSStefan Brüns  * backwards compatibility.
186259baae9aSStefan Brüns  */
186359baae9aSStefan Brüns #define STACK_LOWER_LIMIT (32 * TARGET_PAGE_SIZE)
186459baae9aSStefan Brüns 
186559baae9aSStefan Brüns static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
186631e31b8aSbellard                                  struct image_info *info)
186731e31b8aSbellard {
186859baae9aSStefan Brüns     abi_ulong size, error, guard;
186931e31b8aSbellard 
1870703e0e89SRichard Henderson     size = guest_stack_size;
187159baae9aSStefan Brüns     if (size < STACK_LOWER_LIMIT) {
187259baae9aSStefan Brüns         size = STACK_LOWER_LIMIT;
187360dcbcb5SRichard Henderson     }
187460dcbcb5SRichard Henderson     guard = TARGET_PAGE_SIZE;
187560dcbcb5SRichard Henderson     if (guard < qemu_real_host_page_size) {
187660dcbcb5SRichard Henderson         guard = qemu_real_host_page_size;
187760dcbcb5SRichard Henderson     }
187860dcbcb5SRichard Henderson 
187960dcbcb5SRichard Henderson     error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
188060dcbcb5SRichard Henderson                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
188109bfb054Sbellard     if (error == -1) {
188260dcbcb5SRichard Henderson         perror("mmap stack");
188331e31b8aSbellard         exit(-1);
188431e31b8aSbellard     }
188531e31b8aSbellard 
188660dcbcb5SRichard Henderson     /* We reserve one extra page at the top of the stack as guard.  */
18877c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
188860dcbcb5SRichard Henderson         target_mprotect(error, guard, PROT_NONE);
188960dcbcb5SRichard Henderson         info->stack_limit = error + guard;
189059baae9aSStefan Brüns         return info->stack_limit + size - sizeof(void *);
18917c4ee5bcSRichard Henderson     } else {
18927c4ee5bcSRichard Henderson         target_mprotect(error + size, guard, PROT_NONE);
18937c4ee5bcSRichard Henderson         info->stack_limit = error + size;
18947c4ee5bcSRichard Henderson         return error;
18957c4ee5bcSRichard Henderson     }
189631e31b8aSbellard }
189731e31b8aSbellard 
1898cf129f3aSRichard Henderson /* Map and zero the bss.  We need to explicitly zero any fractional pages
1899cf129f3aSRichard Henderson    after the data section (i.e. bss).  */
1900cf129f3aSRichard Henderson static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
190131e31b8aSbellard {
1902cf129f3aSRichard Henderson     uintptr_t host_start, host_map_start, host_end;
1903cf129f3aSRichard Henderson 
1904cf129f3aSRichard Henderson     last_bss = TARGET_PAGE_ALIGN(last_bss);
1905cf129f3aSRichard Henderson 
1906cf129f3aSRichard Henderson     /* ??? There is confusion between qemu_real_host_page_size and
1907cf129f3aSRichard Henderson        qemu_host_page_size here and elsewhere in target_mmap, which
1908cf129f3aSRichard Henderson        may lead to the end of the data section mapping from the file
1909cf129f3aSRichard Henderson        not being mapped.  At least there was an explicit test and
1910cf129f3aSRichard Henderson        comment for that here, suggesting that "the file size must
1911cf129f3aSRichard Henderson        be known".  The comment probably pre-dates the introduction
1912cf129f3aSRichard Henderson        of the fstat system call in target_mmap which does in fact
1913cf129f3aSRichard Henderson        find out the size.  What isn't clear is if the workaround
1914cf129f3aSRichard Henderson        here is still actually needed.  For now, continue with it,
1915cf129f3aSRichard Henderson        but merge it with the "normal" mmap that would allocate the bss.  */
1916cf129f3aSRichard Henderson 
19173e8f1628SRichard Henderson     host_start = (uintptr_t) g2h_untagged(elf_bss);
19183e8f1628SRichard Henderson     host_end = (uintptr_t) g2h_untagged(last_bss);
19190c2d70c4SPaolo Bonzini     host_map_start = REAL_HOST_PAGE_ALIGN(host_start);
1920cf129f3aSRichard Henderson 
1921cf129f3aSRichard Henderson     if (host_map_start < host_end) {
1922cf129f3aSRichard Henderson         void *p = mmap((void *)host_map_start, host_end - host_map_start,
1923cf129f3aSRichard Henderson                        prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1924cf129f3aSRichard Henderson         if (p == MAP_FAILED) {
192531e31b8aSbellard             perror("cannot mmap brk");
192631e31b8aSbellard             exit(-1);
192731e31b8aSbellard         }
1928f46e9a0bSTom Musta     }
1929cf129f3aSRichard Henderson 
1930f46e9a0bSTom Musta     /* Ensure that the bss page(s) are valid */
1931f46e9a0bSTom Musta     if ((page_get_flags(last_bss-1) & prot) != prot) {
1932cf129f3aSRichard Henderson         page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot | PAGE_VALID);
193331e31b8aSbellard     }
193431e31b8aSbellard 
1935cf129f3aSRichard Henderson     if (host_start < host_map_start) {
1936cf129f3aSRichard Henderson         memset((void *)host_start, 0, host_map_start - host_start);
1937853d6f7aSbellard     }
1938853d6f7aSbellard }
1939853d6f7aSbellard 
1940cf58affeSChristophe Lyon #ifdef TARGET_ARM
1941cf58affeSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec)
1942cf58affeSChristophe Lyon {
1943cf58affeSChristophe Lyon     return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC;
1944cf58affeSChristophe Lyon }
1945cf58affeSChristophe Lyon #else
1946a99856cdSChristophe Lyon /* Default implementation, always false.  */
1947a99856cdSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec)
1948a99856cdSChristophe Lyon {
1949a99856cdSChristophe Lyon     return 0;
1950a99856cdSChristophe Lyon }
1951cf58affeSChristophe Lyon #endif
1952a99856cdSChristophe Lyon 
19531af02e83SMike Frysinger static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
19541af02e83SMike Frysinger {
19551af02e83SMike Frysinger     uint16_t n;
19561af02e83SMike Frysinger     struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
19571af02e83SMike Frysinger 
19581af02e83SMike Frysinger     /* elf32_fdpic_loadseg */
19591af02e83SMike Frysinger     n = info->nsegs;
19601af02e83SMike Frysinger     while (n--) {
19611af02e83SMike Frysinger         sp -= 12;
19621af02e83SMike Frysinger         put_user_u32(loadsegs[n].addr, sp+0);
19631af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_vaddr, sp+4);
19641af02e83SMike Frysinger         put_user_u32(loadsegs[n].p_memsz, sp+8);
19651af02e83SMike Frysinger     }
19661af02e83SMike Frysinger 
19671af02e83SMike Frysinger     /* elf32_fdpic_loadmap */
19681af02e83SMike Frysinger     sp -= 4;
19691af02e83SMike Frysinger     put_user_u16(0, sp+0); /* version */
19701af02e83SMike Frysinger     put_user_u16(info->nsegs, sp+2); /* nsegs */
19711af02e83SMike Frysinger 
19721af02e83SMike Frysinger     info->personality = PER_LINUX_FDPIC;
19731af02e83SMike Frysinger     info->loadmap_addr = sp;
19741af02e83SMike Frysinger 
19751af02e83SMike Frysinger     return sp;
19761af02e83SMike Frysinger }
19771af02e83SMike Frysinger 
1978992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
197931e31b8aSbellard                                    struct elfhdr *exec,
19808e62a717SRichard Henderson                                    struct image_info *info,
19818e62a717SRichard Henderson                                    struct image_info *interp_info)
198231e31b8aSbellard {
1983992f48a0Sblueswir1     abi_ulong sp;
19847c4ee5bcSRichard Henderson     abi_ulong u_argc, u_argv, u_envp, u_auxv;
198553a5960aSpbrook     int size;
198614322badSLaurent ALFONSI     int i;
198714322badSLaurent ALFONSI     abi_ulong u_rand_bytes;
198814322badSLaurent ALFONSI     uint8_t k_rand_bytes[16];
1989992f48a0Sblueswir1     abi_ulong u_platform;
199015338fd7Sbellard     const char *k_platform;
1991863cf0b7Sj_mayer     const int n = sizeof(elf_addr_t);
199231e31b8aSbellard 
199353a5960aSpbrook     sp = p;
19941af02e83SMike Frysinger 
19951af02e83SMike Frysinger     /* Needs to be before we load the env/argc/... */
19961af02e83SMike Frysinger     if (elf_is_fdpic(exec)) {
19971af02e83SMike Frysinger         /* Need 4 byte alignment for these structs */
19981af02e83SMike Frysinger         sp &= ~3;
19991af02e83SMike Frysinger         sp = loader_build_fdpic_loadmap(info, sp);
20001af02e83SMike Frysinger         info->other_info = interp_info;
20011af02e83SMike Frysinger         if (interp_info) {
20021af02e83SMike Frysinger             interp_info->other_info = info;
20031af02e83SMike Frysinger             sp = loader_build_fdpic_loadmap(interp_info, sp);
20043cb10cfaSChristophe Lyon             info->interpreter_loadmap_addr = interp_info->loadmap_addr;
20053cb10cfaSChristophe Lyon             info->interpreter_pt_dynamic_addr = interp_info->pt_dynamic_addr;
20063cb10cfaSChristophe Lyon         } else {
20073cb10cfaSChristophe Lyon             info->interpreter_loadmap_addr = 0;
20083cb10cfaSChristophe Lyon             info->interpreter_pt_dynamic_addr = 0;
20091af02e83SMike Frysinger         }
20101af02e83SMike Frysinger     }
20111af02e83SMike Frysinger 
201253a5960aSpbrook     u_platform = 0;
201315338fd7Sbellard     k_platform = ELF_PLATFORM;
201415338fd7Sbellard     if (k_platform) {
201515338fd7Sbellard         size_t len = strlen(k_platform) + 1;
20167c4ee5bcSRichard Henderson         if (STACK_GROWS_DOWN) {
201753a5960aSpbrook             sp -= (len + n - 1) & ~(n - 1);
201853a5960aSpbrook             u_platform = sp;
2019579a97f7Sbellard             /* FIXME - check return value of memcpy_to_target() for failure */
202053a5960aSpbrook             memcpy_to_target(sp, k_platform, len);
20217c4ee5bcSRichard Henderson         } else {
20227c4ee5bcSRichard Henderson             memcpy_to_target(sp, k_platform, len);
20237c4ee5bcSRichard Henderson             u_platform = sp;
20247c4ee5bcSRichard Henderson             sp += len + 1;
20257c4ee5bcSRichard Henderson         }
20267c4ee5bcSRichard Henderson     }
20277c4ee5bcSRichard Henderson 
20287c4ee5bcSRichard Henderson     /* Provide 16 byte alignment for the PRNG, and basic alignment for
20297c4ee5bcSRichard Henderson      * the argv and envp pointers.
20307c4ee5bcSRichard Henderson      */
20317c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
20327c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_DOWN(sp, 16);
20337c4ee5bcSRichard Henderson     } else {
20347c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_UP(sp, 16);
203515338fd7Sbellard     }
203614322badSLaurent ALFONSI 
203714322badSLaurent ALFONSI     /*
2038c6a2377fSRichard Henderson      * Generate 16 random bytes for userspace PRNG seeding.
203914322badSLaurent ALFONSI      */
2040c6a2377fSRichard Henderson     qemu_guest_getrandom_nofail(k_rand_bytes, sizeof(k_rand_bytes));
20417c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
204214322badSLaurent ALFONSI         sp -= 16;
204314322badSLaurent ALFONSI         u_rand_bytes = sp;
204414322badSLaurent ALFONSI         /* FIXME - check return value of memcpy_to_target() for failure */
204514322badSLaurent ALFONSI         memcpy_to_target(sp, k_rand_bytes, 16);
20467c4ee5bcSRichard Henderson     } else {
20477c4ee5bcSRichard Henderson         memcpy_to_target(sp, k_rand_bytes, 16);
20487c4ee5bcSRichard Henderson         u_rand_bytes = sp;
20497c4ee5bcSRichard Henderson         sp += 16;
20507c4ee5bcSRichard Henderson     }
205114322badSLaurent ALFONSI 
205253a5960aSpbrook     size = (DLINFO_ITEMS + 1) * 2;
205315338fd7Sbellard     if (k_platform)
205453a5960aSpbrook         size += 2;
2055f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS
205653a5960aSpbrook     size += DLINFO_ARCH_ITEMS * 2;
2057f5155289Sbellard #endif
2058ad6919dcSPeter Maydell #ifdef ELF_HWCAP2
2059ad6919dcSPeter Maydell     size += 2;
2060ad6919dcSPeter Maydell #endif
2061f516511eSPeter Maydell     info->auxv_len = size * n;
2062f516511eSPeter Maydell 
206353a5960aSpbrook     size += envc + argc + 2;
2064b9329d4bSRichard Henderson     size += 1;  /* argc itself */
206553a5960aSpbrook     size *= n;
20667c4ee5bcSRichard Henderson 
20677c4ee5bcSRichard Henderson     /* Allocate space and finalize stack alignment for entry now.  */
20687c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
20697c4ee5bcSRichard Henderson         u_argc = QEMU_ALIGN_DOWN(sp - size, STACK_ALIGNMENT);
20707c4ee5bcSRichard Henderson         sp = u_argc;
20717c4ee5bcSRichard Henderson     } else {
20727c4ee5bcSRichard Henderson         u_argc = sp;
20737c4ee5bcSRichard Henderson         sp = QEMU_ALIGN_UP(sp + size, STACK_ALIGNMENT);
20747c4ee5bcSRichard Henderson     }
20757c4ee5bcSRichard Henderson 
20767c4ee5bcSRichard Henderson     u_argv = u_argc + n;
20777c4ee5bcSRichard Henderson     u_envp = u_argv + (argc + 1) * n;
20787c4ee5bcSRichard Henderson     u_auxv = u_envp + (envc + 1) * n;
20797c4ee5bcSRichard Henderson     info->saved_auxv = u_auxv;
20807c4ee5bcSRichard Henderson     info->arg_start = u_argv;
20817c4ee5bcSRichard Henderson     info->arg_end = u_argv + argc * n;
2082f5155289Sbellard 
2083863cf0b7Sj_mayer     /* This is correct because Linux defines
2084863cf0b7Sj_mayer      * elf_addr_t as Elf32_Off / Elf64_Off
2085863cf0b7Sj_mayer      */
208653a5960aSpbrook #define NEW_AUX_ENT(id, val) do {               \
20877c4ee5bcSRichard Henderson         put_user_ual(id, u_auxv);  u_auxv += n; \
20887c4ee5bcSRichard Henderson         put_user_ual(val, u_auxv); u_auxv += n; \
208953a5960aSpbrook     } while(0)
20902f619698Sbellard 
209182991bedSPeter Maydell #ifdef ARCH_DLINFO
209282991bedSPeter Maydell     /*
209382991bedSPeter Maydell      * ARCH_DLINFO must come first so platform specific code can enforce
209482991bedSPeter Maydell      * special alignment requirements on the AUXV if necessary (eg. PPC).
209582991bedSPeter Maydell      */
209682991bedSPeter Maydell     ARCH_DLINFO;
209782991bedSPeter Maydell #endif
2098f516511eSPeter Maydell     /* There must be exactly DLINFO_ITEMS entries here, or the assert
2099f516511eSPeter Maydell      * on info->auxv_len will trigger.
2100f516511eSPeter Maydell      */
21018e62a717SRichard Henderson     NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
2102992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
2103992f48a0Sblueswir1     NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
210433143c44SLaurent Vivier     if ((info->alignment & ~qemu_host_page_mask) != 0) {
210533143c44SLaurent Vivier         /* Target doesn't support host page size alignment */
210633143c44SLaurent Vivier         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
210733143c44SLaurent Vivier     } else {
210833143c44SLaurent Vivier         NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE,
210933143c44SLaurent Vivier                                                qemu_host_page_size)));
211033143c44SLaurent Vivier     }
21118e62a717SRichard Henderson     NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0));
2112992f48a0Sblueswir1     NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
21138e62a717SRichard Henderson     NEW_AUX_ENT(AT_ENTRY, info->entry);
2114992f48a0Sblueswir1     NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
2115992f48a0Sblueswir1     NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
2116992f48a0Sblueswir1     NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
2117992f48a0Sblueswir1     NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
2118992f48a0Sblueswir1     NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
2119a07c67dfSpbrook     NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
212014322badSLaurent ALFONSI     NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes);
2121444cd5c3SMarco A L Barbosa     NEW_AUX_ENT(AT_SECURE, (abi_ulong) qemu_getauxval(AT_SECURE));
2122e0d1673dSLirong Yuan     NEW_AUX_ENT(AT_EXECFN, info->file_string);
212314322badSLaurent ALFONSI 
2124ad6919dcSPeter Maydell #ifdef ELF_HWCAP2
2125ad6919dcSPeter Maydell     NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2);
2126ad6919dcSPeter Maydell #endif
2127ad6919dcSPeter Maydell 
21287c4ee5bcSRichard Henderson     if (u_platform) {
212953a5960aSpbrook         NEW_AUX_ENT(AT_PLATFORM, u_platform);
21307c4ee5bcSRichard Henderson     }
21317c4ee5bcSRichard Henderson     NEW_AUX_ENT (AT_NULL, 0);
2132f5155289Sbellard #undef NEW_AUX_ENT
2133f5155289Sbellard 
2134f516511eSPeter Maydell     /* Check that our initial calculation of the auxv length matches how much
2135f516511eSPeter Maydell      * we actually put into it.
2136f516511eSPeter Maydell      */
2137f516511eSPeter Maydell     assert(info->auxv_len == u_auxv - info->saved_auxv);
2138edf8e2afSMika Westerberg 
21397c4ee5bcSRichard Henderson     put_user_ual(argc, u_argc);
21407c4ee5bcSRichard Henderson 
21417c4ee5bcSRichard Henderson     p = info->arg_strings;
21427c4ee5bcSRichard Henderson     for (i = 0; i < argc; ++i) {
21437c4ee5bcSRichard Henderson         put_user_ual(p, u_argv);
21447c4ee5bcSRichard Henderson         u_argv += n;
21457c4ee5bcSRichard Henderson         p += target_strlen(p) + 1;
21467c4ee5bcSRichard Henderson     }
21477c4ee5bcSRichard Henderson     put_user_ual(0, u_argv);
21487c4ee5bcSRichard Henderson 
21497c4ee5bcSRichard Henderson     p = info->env_strings;
21507c4ee5bcSRichard Henderson     for (i = 0; i < envc; ++i) {
21517c4ee5bcSRichard Henderson         put_user_ual(p, u_envp);
21527c4ee5bcSRichard Henderson         u_envp += n;
21537c4ee5bcSRichard Henderson         p += target_strlen(p) + 1;
21547c4ee5bcSRichard Henderson     }
21557c4ee5bcSRichard Henderson     put_user_ual(0, u_envp);
21567c4ee5bcSRichard Henderson 
215731e31b8aSbellard     return sp;
215831e31b8aSbellard }
215931e31b8aSbellard 
2160ee947430SAlex Bennée #ifndef ARM_COMMPAGE
2161ee947430SAlex Bennée #define ARM_COMMPAGE 0
2162ee947430SAlex Bennée #define init_guest_commpage() true
2163ee947430SAlex Bennée #endif
2164ee947430SAlex Bennée 
2165ee947430SAlex Bennée static void pgb_fail_in_use(const char *image_name)
2166ee947430SAlex Bennée {
2167ee947430SAlex Bennée     error_report("%s: requires virtual address space that is in use "
2168ee947430SAlex Bennée                  "(omit the -B option or choose a different value)",
2169ee947430SAlex Bennée                  image_name);
2170ee947430SAlex Bennée     exit(EXIT_FAILURE);
2171ee947430SAlex Bennée }
2172ee947430SAlex Bennée 
2173ee947430SAlex Bennée static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr,
2174ee947430SAlex Bennée                                 abi_ulong guest_hiaddr, long align)
2175ee947430SAlex Bennée {
2176ee947430SAlex Bennée     const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
2177ee947430SAlex Bennée     void *addr, *test;
2178ee947430SAlex Bennée 
2179ee947430SAlex Bennée     if (!QEMU_IS_ALIGNED(guest_base, align)) {
21805ca870b9SRichard Henderson         fprintf(stderr, "Requested guest base %p does not satisfy "
2181ee947430SAlex Bennée                 "host minimum alignment (0x%lx)\n",
21825ca870b9SRichard Henderson                 (void *)guest_base, align);
2183ee947430SAlex Bennée         exit(EXIT_FAILURE);
2184ee947430SAlex Bennée     }
2185ee947430SAlex Bennée 
2186ee947430SAlex Bennée     /* Sanity check the guest binary. */
2187ee947430SAlex Bennée     if (reserved_va) {
2188ee947430SAlex Bennée         if (guest_hiaddr > reserved_va) {
2189ee947430SAlex Bennée             error_report("%s: requires more than reserved virtual "
2190ee947430SAlex Bennée                          "address space (0x%" PRIx64 " > 0x%lx)",
2191ee947430SAlex Bennée                          image_name, (uint64_t)guest_hiaddr, reserved_va);
2192ee947430SAlex Bennée             exit(EXIT_FAILURE);
2193ee947430SAlex Bennée         }
2194ee947430SAlex Bennée     } else {
2195a932eec4SAlex Bennée #if HOST_LONG_BITS < TARGET_ABI_BITS
2196ee947430SAlex Bennée         if ((guest_hiaddr - guest_base) > ~(uintptr_t)0) {
2197ee947430SAlex Bennée             error_report("%s: requires more virtual address space "
2198ee947430SAlex Bennée                          "than the host can provide (0x%" PRIx64 ")",
2199ee947430SAlex Bennée                          image_name, (uint64_t)guest_hiaddr - guest_base);
2200ee947430SAlex Bennée             exit(EXIT_FAILURE);
2201ee947430SAlex Bennée         }
2202a932eec4SAlex Bennée #endif
2203ee947430SAlex Bennée     }
2204ee947430SAlex Bennée 
2205ee947430SAlex Bennée     /*
2206ee947430SAlex Bennée      * Expand the allocation to the entire reserved_va.
2207ee947430SAlex Bennée      * Exclude the mmap_min_addr hole.
2208ee947430SAlex Bennée      */
2209ee947430SAlex Bennée     if (reserved_va) {
2210ee947430SAlex Bennée         guest_loaddr = (guest_base >= mmap_min_addr ? 0
2211ee947430SAlex Bennée                         : mmap_min_addr - guest_base);
2212ee947430SAlex Bennée         guest_hiaddr = reserved_va;
2213ee947430SAlex Bennée     }
2214ee947430SAlex Bennée 
2215ee947430SAlex Bennée     /* Reserve the address space for the binary, or reserved_va. */
22163e8f1628SRichard Henderson     test = g2h_untagged(guest_loaddr);
2217ee947430SAlex Bennée     addr = mmap(test, guest_hiaddr - guest_loaddr, PROT_NONE, flags, -1, 0);
2218ee947430SAlex Bennée     if (test != addr) {
2219ee947430SAlex Bennée         pgb_fail_in_use(image_name);
2220ee947430SAlex Bennée     }
2221ee947430SAlex Bennée }
2222ee947430SAlex Bennée 
2223ad592e37SAlex Bennée /**
2224ad592e37SAlex Bennée  * pgd_find_hole_fallback: potential mmap address
2225ad592e37SAlex Bennée  * @guest_size: size of available space
2226ad592e37SAlex Bennée  * @brk: location of break
2227ad592e37SAlex Bennée  * @align: memory alignment
2228ad592e37SAlex Bennée  *
2229ad592e37SAlex Bennée  * This is a fallback method for finding a hole in the host address
2230ad592e37SAlex Bennée  * space if we don't have the benefit of being able to access
2231ad592e37SAlex Bennée  * /proc/self/map. It can potentially take a very long time as we can
2232ad592e37SAlex Bennée  * only dumbly iterate up the host address space seeing if the
2233ad592e37SAlex Bennée  * allocation would work.
2234ad592e37SAlex Bennée  */
22355c3e87f3SAlex Bennée static uintptr_t pgd_find_hole_fallback(uintptr_t guest_size, uintptr_t brk,
22365c3e87f3SAlex Bennée                                         long align, uintptr_t offset)
2237ad592e37SAlex Bennée {
2238ad592e37SAlex Bennée     uintptr_t base;
2239ad592e37SAlex Bennée 
2240ad592e37SAlex Bennée     /* Start (aligned) at the bottom and work our way up */
2241ad592e37SAlex Bennée     base = ROUND_UP(mmap_min_addr, align);
2242ad592e37SAlex Bennée 
2243ad592e37SAlex Bennée     while (true) {
2244ad592e37SAlex Bennée         uintptr_t align_start, end;
2245ad592e37SAlex Bennée         align_start = ROUND_UP(base, align);
22465c3e87f3SAlex Bennée         end = align_start + guest_size + offset;
2247ad592e37SAlex Bennée 
2248ad592e37SAlex Bennée         /* if brk is anywhere in the range give ourselves some room to grow. */
2249ad592e37SAlex Bennée         if (align_start <= brk && brk < end) {
2250ad592e37SAlex Bennée             base = brk + (16 * MiB);
2251ad592e37SAlex Bennée             continue;
2252ad592e37SAlex Bennée         } else if (align_start + guest_size < align_start) {
2253ad592e37SAlex Bennée             /* we have run out of space */
2254ad592e37SAlex Bennée             return -1;
2255ad592e37SAlex Bennée         } else {
22562667e069SAlex Bennée             int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE |
22572667e069SAlex Bennée                 MAP_FIXED_NOREPLACE;
2258ad592e37SAlex Bennée             void * mmap_start = mmap((void *) align_start, guest_size,
2259ad592e37SAlex Bennée                                      PROT_NONE, flags, -1, 0);
2260ad592e37SAlex Bennée             if (mmap_start != MAP_FAILED) {
22617e588fbcSVincent Fazio                 munmap(mmap_start, guest_size);
2262934eed51SVincent Fazio                 if (mmap_start == (void *) align_start) {
22635c3e87f3SAlex Bennée                     return (uintptr_t) mmap_start + offset;
2264ad592e37SAlex Bennée                 }
22652667e069SAlex Bennée             }
2266ad592e37SAlex Bennée             base += qemu_host_page_size;
2267ad592e37SAlex Bennée         }
2268ad592e37SAlex Bennée     }
2269ad592e37SAlex Bennée }
2270ad592e37SAlex Bennée 
2271ee947430SAlex Bennée /* Return value for guest_base, or -1 if no hole found. */
2272ee947430SAlex Bennée static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size,
22735c3e87f3SAlex Bennée                                long align, uintptr_t offset)
2274ee947430SAlex Bennée {
2275ee947430SAlex Bennée     GSList *maps, *iter;
2276ee947430SAlex Bennée     uintptr_t this_start, this_end, next_start, brk;
2277ee947430SAlex Bennée     intptr_t ret = -1;
2278ee947430SAlex Bennée 
2279ee947430SAlex Bennée     assert(QEMU_IS_ALIGNED(guest_loaddr, align));
2280ee947430SAlex Bennée 
2281ee947430SAlex Bennée     maps = read_self_maps();
2282ee947430SAlex Bennée 
2283ee947430SAlex Bennée     /* Read brk after we've read the maps, which will malloc. */
2284ee947430SAlex Bennée     brk = (uintptr_t)sbrk(0);
2285ee947430SAlex Bennée 
2286ad592e37SAlex Bennée     if (!maps) {
22870266e8e3SVincent Fazio         ret = pgd_find_hole_fallback(guest_size, brk, align, offset);
22880266e8e3SVincent Fazio         return ret == -1 ? -1 : ret - guest_loaddr;
2289ad592e37SAlex Bennée     }
2290ad592e37SAlex Bennée 
2291ee947430SAlex Bennée     /* The first hole is before the first map entry. */
2292ee947430SAlex Bennée     this_start = mmap_min_addr;
2293ee947430SAlex Bennée 
2294ee947430SAlex Bennée     for (iter = maps; iter;
2295ee947430SAlex Bennée          this_start = next_start, iter = g_slist_next(iter)) {
2296ee947430SAlex Bennée         uintptr_t align_start, hole_size;
2297ee947430SAlex Bennée 
2298ee947430SAlex Bennée         this_end = ((MapInfo *)iter->data)->start;
2299ee947430SAlex Bennée         next_start = ((MapInfo *)iter->data)->end;
23005c3e87f3SAlex Bennée         align_start = ROUND_UP(this_start + offset, align);
2301ee947430SAlex Bennée 
2302ee947430SAlex Bennée         /* Skip holes that are too small. */
2303ee947430SAlex Bennée         if (align_start >= this_end) {
2304ee947430SAlex Bennée             continue;
2305ee947430SAlex Bennée         }
2306ee947430SAlex Bennée         hole_size = this_end - align_start;
2307ee947430SAlex Bennée         if (hole_size < guest_size) {
2308ee947430SAlex Bennée             continue;
2309ee947430SAlex Bennée         }
2310ee947430SAlex Bennée 
2311ee947430SAlex Bennée         /* If this hole contains brk, give ourselves some room to grow. */
2312ee947430SAlex Bennée         if (this_start <= brk && brk < this_end) {
2313ee947430SAlex Bennée             hole_size -= guest_size;
2314ee947430SAlex Bennée             if (sizeof(uintptr_t) == 8 && hole_size >= 1 * GiB) {
2315ee947430SAlex Bennée                 align_start += 1 * GiB;
2316ee947430SAlex Bennée             } else if (hole_size >= 16 * MiB) {
2317ee947430SAlex Bennée                 align_start += 16 * MiB;
2318ee947430SAlex Bennée             } else {
2319ee947430SAlex Bennée                 align_start = (this_end - guest_size) & -align;
2320ee947430SAlex Bennée                 if (align_start < this_start) {
2321ee947430SAlex Bennée                     continue;
2322ee947430SAlex Bennée                 }
2323ee947430SAlex Bennée             }
2324ee947430SAlex Bennée         }
2325ee947430SAlex Bennée 
2326ee947430SAlex Bennée         /* Record the lowest successful match. */
2327ee947430SAlex Bennée         if (ret < 0) {
2328ee947430SAlex Bennée             ret = align_start - guest_loaddr;
2329ee947430SAlex Bennée         }
2330ee947430SAlex Bennée         /* If this hole contains the identity map, select it. */
2331ee947430SAlex Bennée         if (align_start <= guest_loaddr &&
2332ee947430SAlex Bennée             guest_loaddr + guest_size <= this_end) {
2333ee947430SAlex Bennée             ret = 0;
2334ee947430SAlex Bennée         }
2335ee947430SAlex Bennée         /* If this hole ends above the identity map, stop looking. */
2336ee947430SAlex Bennée         if (this_end >= guest_loaddr) {
2337ee947430SAlex Bennée             break;
2338ee947430SAlex Bennée         }
2339ee947430SAlex Bennée     }
2340ee947430SAlex Bennée     free_self_maps(maps);
2341ee947430SAlex Bennée 
2342ee947430SAlex Bennée     return ret;
2343ee947430SAlex Bennée }
2344ee947430SAlex Bennée 
2345ee947430SAlex Bennée static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
2346ee947430SAlex Bennée                        abi_ulong orig_hiaddr, long align)
2347ee947430SAlex Bennée {
2348ee947430SAlex Bennée     uintptr_t loaddr = orig_loaddr;
2349ee947430SAlex Bennée     uintptr_t hiaddr = orig_hiaddr;
23505c3e87f3SAlex Bennée     uintptr_t offset = 0;
2351ee947430SAlex Bennée     uintptr_t addr;
2352ee947430SAlex Bennée 
2353ee947430SAlex Bennée     if (hiaddr != orig_hiaddr) {
2354ee947430SAlex Bennée         error_report("%s: requires virtual address space that the "
2355ee947430SAlex Bennée                      "host cannot provide (0x%" PRIx64 ")",
2356ee947430SAlex Bennée                      image_name, (uint64_t)orig_hiaddr);
2357ee947430SAlex Bennée         exit(EXIT_FAILURE);
2358ee947430SAlex Bennée     }
2359ee947430SAlex Bennée 
2360ee947430SAlex Bennée     loaddr &= -align;
2361ee947430SAlex Bennée     if (ARM_COMMPAGE) {
2362ee947430SAlex Bennée         /*
2363ee947430SAlex Bennée          * Extend the allocation to include the commpage.
23645c3e87f3SAlex Bennée          * For a 64-bit host, this is just 4GiB; for a 32-bit host we
23655c3e87f3SAlex Bennée          * need to ensure there is space bellow the guest_base so we
23665c3e87f3SAlex Bennée          * can map the commpage in the place needed when the address
23675c3e87f3SAlex Bennée          * arithmetic wraps around.
2368ee947430SAlex Bennée          */
2369ee947430SAlex Bennée         if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) {
2370ee947430SAlex Bennée             hiaddr = (uintptr_t) 4 << 30;
2371ee947430SAlex Bennée         } else {
23725c3e87f3SAlex Bennée             offset = -(ARM_COMMPAGE & -align);
2373ee947430SAlex Bennée         }
2374ee947430SAlex Bennée     }
2375ee947430SAlex Bennée 
23765c3e87f3SAlex Bennée     addr = pgb_find_hole(loaddr, hiaddr - loaddr, align, offset);
2377ee947430SAlex Bennée     if (addr == -1) {
2378ee947430SAlex Bennée         /*
2379ee947430SAlex Bennée          * If ARM_COMMPAGE, there *might* be a non-consecutive allocation
2380ee947430SAlex Bennée          * that can satisfy both.  But as the normal arm32 link base address
2381ee947430SAlex Bennée          * is ~32k, and we extend down to include the commpage, making the
2382ee947430SAlex Bennée          * overhead only ~96k, this is unlikely.
2383ee947430SAlex Bennée          */
2384ee947430SAlex Bennée         error_report("%s: Unable to allocate %#zx bytes of "
2385ee947430SAlex Bennée                      "virtual address space", image_name,
2386ee947430SAlex Bennée                      (size_t)(hiaddr - loaddr));
2387ee947430SAlex Bennée         exit(EXIT_FAILURE);
2388ee947430SAlex Bennée     }
2389ee947430SAlex Bennée 
2390ee947430SAlex Bennée     guest_base = addr;
2391ee947430SAlex Bennée }
2392ee947430SAlex Bennée 
2393ee947430SAlex Bennée static void pgb_dynamic(const char *image_name, long align)
2394ee947430SAlex Bennée {
2395ee947430SAlex Bennée     /*
2396ee947430SAlex Bennée      * The executable is dynamic and does not require a fixed address.
2397ee947430SAlex Bennée      * All we need is a commpage that satisfies align.
2398ee947430SAlex Bennée      * If we do not need a commpage, leave guest_base == 0.
2399ee947430SAlex Bennée      */
2400ee947430SAlex Bennée     if (ARM_COMMPAGE) {
2401ee947430SAlex Bennée         uintptr_t addr, commpage;
2402ee947430SAlex Bennée 
2403ee947430SAlex Bennée         /* 64-bit hosts should have used reserved_va. */
2404ee947430SAlex Bennée         assert(sizeof(uintptr_t) == 4);
2405ee947430SAlex Bennée 
2406ee947430SAlex Bennée         /*
2407ee947430SAlex Bennée          * By putting the commpage at the first hole, that puts guest_base
2408ee947430SAlex Bennée          * just above that, and maximises the positive guest addresses.
2409ee947430SAlex Bennée          */
2410ee947430SAlex Bennée         commpage = ARM_COMMPAGE & -align;
24115c3e87f3SAlex Bennée         addr = pgb_find_hole(commpage, -commpage, align, 0);
2412ee947430SAlex Bennée         assert(addr != -1);
2413ee947430SAlex Bennée         guest_base = addr;
2414ee947430SAlex Bennée     }
2415ee947430SAlex Bennée }
2416ee947430SAlex Bennée 
2417ee947430SAlex Bennée static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr,
2418ee947430SAlex Bennée                             abi_ulong guest_hiaddr, long align)
2419ee947430SAlex Bennée {
2420c1f6ad79SAlex Bennée     int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
2421ee947430SAlex Bennée     void *addr, *test;
2422ee947430SAlex Bennée 
2423ee947430SAlex Bennée     if (guest_hiaddr > reserved_va) {
2424ee947430SAlex Bennée         error_report("%s: requires more than reserved virtual "
2425ee947430SAlex Bennée                      "address space (0x%" PRIx64 " > 0x%lx)",
2426ee947430SAlex Bennée                      image_name, (uint64_t)guest_hiaddr, reserved_va);
2427ee947430SAlex Bennée         exit(EXIT_FAILURE);
2428ee947430SAlex Bennée     }
2429ee947430SAlex Bennée 
2430ee947430SAlex Bennée     /* Widen the "image" to the entire reserved address space. */
2431ee947430SAlex Bennée     pgb_static(image_name, 0, reserved_va, align);
2432ee947430SAlex Bennée 
24332667e069SAlex Bennée     /* osdep.h defines this as 0 if it's missing */
2434c1f6ad79SAlex Bennée     flags |= MAP_FIXED_NOREPLACE;
2435c1f6ad79SAlex Bennée 
2436ee947430SAlex Bennée     /* Reserve the memory on the host. */
2437ee947430SAlex Bennée     assert(guest_base != 0);
24383e8f1628SRichard Henderson     test = g2h_untagged(0);
2439ee947430SAlex Bennée     addr = mmap(test, reserved_va, PROT_NONE, flags, -1, 0);
2440fb730c86SAlex Bennée     if (addr == MAP_FAILED || addr != test) {
2441ee947430SAlex Bennée         error_report("Unable to reserve 0x%lx bytes of virtual address "
2442fb730c86SAlex Bennée                      "space at %p (%s) for use as guest address space (check your"
2443fb730c86SAlex Bennée                      "virtual memory ulimit setting, min_mmap_addr or reserve less "
2444fb730c86SAlex Bennée                      "using -R option)", reserved_va, test, strerror(errno));
2445ee947430SAlex Bennée         exit(EXIT_FAILURE);
2446ee947430SAlex Bennée     }
2447ee947430SAlex Bennée }
2448ee947430SAlex Bennée 
2449ee947430SAlex Bennée void probe_guest_base(const char *image_name, abi_ulong guest_loaddr,
2450ee947430SAlex Bennée                       abi_ulong guest_hiaddr)
2451dce10401SMeador Inge {
245230ab9ef2SRichard Henderson     /* In order to use host shmat, we must be able to honor SHMLBA.  */
2453ee947430SAlex Bennée     uintptr_t align = MAX(SHMLBA, qemu_host_page_size);
2454dce10401SMeador Inge 
2455ee947430SAlex Bennée     if (have_guest_base) {
2456ee947430SAlex Bennée         pgb_have_guest_base(image_name, guest_loaddr, guest_hiaddr, align);
2457ee947430SAlex Bennée     } else if (reserved_va) {
2458ee947430SAlex Bennée         pgb_reserved_va(image_name, guest_loaddr, guest_hiaddr, align);
2459ee947430SAlex Bennée     } else if (guest_loaddr) {
2460ee947430SAlex Bennée         pgb_static(image_name, guest_loaddr, guest_hiaddr, align);
2461293f2060SLuke Shumaker     } else {
2462ee947430SAlex Bennée         pgb_dynamic(image_name, align);
2463806d1021SMeador Inge     }
2464806d1021SMeador Inge 
2465ee947430SAlex Bennée     /* Reserve and initialize the commpage. */
2466ee947430SAlex Bennée     if (!init_guest_commpage()) {
2467ee947430SAlex Bennée         /*
2468ee947430SAlex Bennée          * With have_guest_base, the user has selected the address and
2469ee947430SAlex Bennée          * we are trying to work with that.  Otherwise, we have selected
2470ee947430SAlex Bennée          * free space and init_guest_commpage must succeeded.
24717ad75eeaSLuke Shumaker          */
2472ee947430SAlex Bennée         assert(have_guest_base);
2473ee947430SAlex Bennée         pgb_fail_in_use(image_name);
2474dce10401SMeador Inge     }
2475dce10401SMeador Inge 
2476ee947430SAlex Bennée     assert(QEMU_IS_ALIGNED(guest_base, align));
2477ee947430SAlex Bennée     qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space "
2478ee947430SAlex Bennée                   "@ 0x%" PRIx64 "\n", (uint64_t)guest_base);
2479dce10401SMeador Inge }
2480dce10401SMeador Inge 
248183f990ebSRichard Henderson enum {
248283f990ebSRichard Henderson     /* The string "GNU\0" as a magic number. */
248383f990ebSRichard Henderson     GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16),
248483f990ebSRichard Henderson     NOTE_DATA_SZ = 1 * KiB,
248583f990ebSRichard Henderson     NOTE_NAME_SZ = 4,
248683f990ebSRichard Henderson     ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8,
248783f990ebSRichard Henderson };
248883f990ebSRichard Henderson 
248983f990ebSRichard Henderson /*
249083f990ebSRichard Henderson  * Process a single gnu_property entry.
249183f990ebSRichard Henderson  * Return false for error.
249283f990ebSRichard Henderson  */
249383f990ebSRichard Henderson static bool parse_elf_property(const uint32_t *data, int *off, int datasz,
249483f990ebSRichard Henderson                                struct image_info *info, bool have_prev_type,
249583f990ebSRichard Henderson                                uint32_t *prev_type, Error **errp)
249683f990ebSRichard Henderson {
249783f990ebSRichard Henderson     uint32_t pr_type, pr_datasz, step;
249883f990ebSRichard Henderson 
249983f990ebSRichard Henderson     if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) {
250083f990ebSRichard Henderson         goto error_data;
250183f990ebSRichard Henderson     }
250283f990ebSRichard Henderson     datasz -= *off;
250383f990ebSRichard Henderson     data += *off / sizeof(uint32_t);
250483f990ebSRichard Henderson 
250583f990ebSRichard Henderson     if (datasz < 2 * sizeof(uint32_t)) {
250683f990ebSRichard Henderson         goto error_data;
250783f990ebSRichard Henderson     }
250883f990ebSRichard Henderson     pr_type = data[0];
250983f990ebSRichard Henderson     pr_datasz = data[1];
251083f990ebSRichard Henderson     data += 2;
251183f990ebSRichard Henderson     datasz -= 2 * sizeof(uint32_t);
251283f990ebSRichard Henderson     step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN);
251383f990ebSRichard Henderson     if (step > datasz) {
251483f990ebSRichard Henderson         goto error_data;
251583f990ebSRichard Henderson     }
251683f990ebSRichard Henderson 
251783f990ebSRichard Henderson     /* Properties are supposed to be unique and sorted on pr_type. */
251883f990ebSRichard Henderson     if (have_prev_type && pr_type <= *prev_type) {
251983f990ebSRichard Henderson         if (pr_type == *prev_type) {
252083f990ebSRichard Henderson             error_setg(errp, "Duplicate property in PT_GNU_PROPERTY");
252183f990ebSRichard Henderson         } else {
252283f990ebSRichard Henderson             error_setg(errp, "Unsorted property in PT_GNU_PROPERTY");
252383f990ebSRichard Henderson         }
252483f990ebSRichard Henderson         return false;
252583f990ebSRichard Henderson     }
252683f990ebSRichard Henderson     *prev_type = pr_type;
252783f990ebSRichard Henderson 
252883f990ebSRichard Henderson     if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) {
252983f990ebSRichard Henderson         return false;
253083f990ebSRichard Henderson     }
253183f990ebSRichard Henderson 
253283f990ebSRichard Henderson     *off += 2 * sizeof(uint32_t) + step;
253383f990ebSRichard Henderson     return true;
253483f990ebSRichard Henderson 
253583f990ebSRichard Henderson  error_data:
253683f990ebSRichard Henderson     error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY");
253783f990ebSRichard Henderson     return false;
253883f990ebSRichard Henderson }
253983f990ebSRichard Henderson 
254083f990ebSRichard Henderson /* Process NT_GNU_PROPERTY_TYPE_0. */
254183f990ebSRichard Henderson static bool parse_elf_properties(int image_fd,
254283f990ebSRichard Henderson                                  struct image_info *info,
254383f990ebSRichard Henderson                                  const struct elf_phdr *phdr,
254483f990ebSRichard Henderson                                  char bprm_buf[BPRM_BUF_SIZE],
254583f990ebSRichard Henderson                                  Error **errp)
254683f990ebSRichard Henderson {
254783f990ebSRichard Henderson     union {
254883f990ebSRichard Henderson         struct elf_note nhdr;
254983f990ebSRichard Henderson         uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)];
255083f990ebSRichard Henderson     } note;
255183f990ebSRichard Henderson 
255283f990ebSRichard Henderson     int n, off, datasz;
255383f990ebSRichard Henderson     bool have_prev_type;
255483f990ebSRichard Henderson     uint32_t prev_type;
255583f990ebSRichard Henderson 
255683f990ebSRichard Henderson     /* Unless the arch requires properties, ignore them. */
255783f990ebSRichard Henderson     if (!ARCH_USE_GNU_PROPERTY) {
255883f990ebSRichard Henderson         return true;
255983f990ebSRichard Henderson     }
256083f990ebSRichard Henderson 
256183f990ebSRichard Henderson     /* If the properties are crazy large, that's too bad. */
256283f990ebSRichard Henderson     n = phdr->p_filesz;
256383f990ebSRichard Henderson     if (n > sizeof(note)) {
256483f990ebSRichard Henderson         error_setg(errp, "PT_GNU_PROPERTY too large");
256583f990ebSRichard Henderson         return false;
256683f990ebSRichard Henderson     }
256783f990ebSRichard Henderson     if (n < sizeof(note.nhdr)) {
256883f990ebSRichard Henderson         error_setg(errp, "PT_GNU_PROPERTY too small");
256983f990ebSRichard Henderson         return false;
257083f990ebSRichard Henderson     }
257183f990ebSRichard Henderson 
257283f990ebSRichard Henderson     if (phdr->p_offset + n <= BPRM_BUF_SIZE) {
257383f990ebSRichard Henderson         memcpy(&note, bprm_buf + phdr->p_offset, n);
257483f990ebSRichard Henderson     } else {
257583f990ebSRichard Henderson         ssize_t len = pread(image_fd, &note, n, phdr->p_offset);
257683f990ebSRichard Henderson         if (len != n) {
257783f990ebSRichard Henderson             error_setg_errno(errp, errno, "Error reading file header");
257883f990ebSRichard Henderson             return false;
257983f990ebSRichard Henderson         }
258083f990ebSRichard Henderson     }
258183f990ebSRichard Henderson 
258283f990ebSRichard Henderson     /*
258383f990ebSRichard Henderson      * The contents of a valid PT_GNU_PROPERTY is a sequence
258483f990ebSRichard Henderson      * of uint32_t -- swap them all now.
258583f990ebSRichard Henderson      */
258683f990ebSRichard Henderson #ifdef BSWAP_NEEDED
258783f990ebSRichard Henderson     for (int i = 0; i < n / 4; i++) {
258883f990ebSRichard Henderson         bswap32s(note.data + i);
258983f990ebSRichard Henderson     }
259083f990ebSRichard Henderson #endif
259183f990ebSRichard Henderson 
259283f990ebSRichard Henderson     /*
259383f990ebSRichard Henderson      * Note that nhdr is 3 words, and that the "name" described by namesz
259483f990ebSRichard Henderson      * immediately follows nhdr and is thus at the 4th word.  Further, all
259583f990ebSRichard Henderson      * of the inputs to the kernel's round_up are multiples of 4.
259683f990ebSRichard Henderson      */
259783f990ebSRichard Henderson     if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 ||
259883f990ebSRichard Henderson         note.nhdr.n_namesz != NOTE_NAME_SZ ||
259983f990ebSRichard Henderson         note.data[3] != GNU0_MAGIC) {
260083f990ebSRichard Henderson         error_setg(errp, "Invalid note in PT_GNU_PROPERTY");
260183f990ebSRichard Henderson         return false;
260283f990ebSRichard Henderson     }
260383f990ebSRichard Henderson     off = sizeof(note.nhdr) + NOTE_NAME_SZ;
260483f990ebSRichard Henderson 
260583f990ebSRichard Henderson     datasz = note.nhdr.n_descsz + off;
260683f990ebSRichard Henderson     if (datasz > n) {
260783f990ebSRichard Henderson         error_setg(errp, "Invalid note size in PT_GNU_PROPERTY");
260883f990ebSRichard Henderson         return false;
260983f990ebSRichard Henderson     }
261083f990ebSRichard Henderson 
261183f990ebSRichard Henderson     have_prev_type = false;
261283f990ebSRichard Henderson     prev_type = 0;
261383f990ebSRichard Henderson     while (1) {
261483f990ebSRichard Henderson         if (off == datasz) {
261583f990ebSRichard Henderson             return true;  /* end, exit ok */
261683f990ebSRichard Henderson         }
261783f990ebSRichard Henderson         if (!parse_elf_property(note.data, &off, datasz, info,
261883f990ebSRichard Henderson                                 have_prev_type, &prev_type, errp)) {
261983f990ebSRichard Henderson             return false;
262083f990ebSRichard Henderson         }
262183f990ebSRichard Henderson         have_prev_type = true;
262283f990ebSRichard Henderson     }
262383f990ebSRichard Henderson }
262483f990ebSRichard Henderson 
26258e62a717SRichard Henderson /* Load an ELF image into the address space.
262631e31b8aSbellard 
26278e62a717SRichard Henderson    IMAGE_NAME is the filename of the image, to use in error messages.
26288e62a717SRichard Henderson    IMAGE_FD is the open file descriptor for the image.
26298e62a717SRichard Henderson 
26308e62a717SRichard Henderson    BPRM_BUF is a copy of the beginning of the file; this of course
26318e62a717SRichard Henderson    contains the elf file header at offset 0.  It is assumed that this
26328e62a717SRichard Henderson    buffer is sufficiently aligned to present no problems to the host
26338e62a717SRichard Henderson    in accessing data at aligned offsets within the buffer.
26348e62a717SRichard Henderson 
26358e62a717SRichard Henderson    On return: INFO values will be filled in, as necessary or available.  */
26368e62a717SRichard Henderson 
26378e62a717SRichard Henderson static void load_elf_image(const char *image_name, int image_fd,
2638bf858897SRichard Henderson                            struct image_info *info, char **pinterp_name,
26399955ffacSRichard Henderson                            char bprm_buf[BPRM_BUF_SIZE])
264031e31b8aSbellard {
26418e62a717SRichard Henderson     struct elfhdr *ehdr = (struct elfhdr *)bprm_buf;
26428e62a717SRichard Henderson     struct elf_phdr *phdr;
26438e62a717SRichard Henderson     abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
2644e8384b37SRichard Henderson     int i, retval, prot_exec;
2645c7f17e7bSRichard Henderson     Error *err = NULL;
264631e31b8aSbellard 
26478e62a717SRichard Henderson     /* First of all, some simple consistency checks */
26488e62a717SRichard Henderson     if (!elf_check_ident(ehdr)) {
2649c7f17e7bSRichard Henderson         error_setg(&err, "Invalid ELF image for this architecture");
26508e62a717SRichard Henderson         goto exit_errmsg;
26518e62a717SRichard Henderson     }
26528e62a717SRichard Henderson     bswap_ehdr(ehdr);
26538e62a717SRichard Henderson     if (!elf_check_ehdr(ehdr)) {
2654c7f17e7bSRichard Henderson         error_setg(&err, "Invalid ELF image for this architecture");
26558e62a717SRichard Henderson         goto exit_errmsg;
265631e31b8aSbellard     }
265731e31b8aSbellard 
26588e62a717SRichard Henderson     i = ehdr->e_phnum * sizeof(struct elf_phdr);
26598e62a717SRichard Henderson     if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) {
26608e62a717SRichard Henderson         phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff);
26619955ffacSRichard Henderson     } else {
26628e62a717SRichard Henderson         phdr = (struct elf_phdr *) alloca(i);
26638e62a717SRichard Henderson         retval = pread(image_fd, phdr, i, ehdr->e_phoff);
26649955ffacSRichard Henderson         if (retval != i) {
26658e62a717SRichard Henderson             goto exit_read;
26669955ffacSRichard Henderson         }
266731e31b8aSbellard     }
26688e62a717SRichard Henderson     bswap_phdr(phdr, ehdr->e_phnum);
266909bfb054Sbellard 
26701af02e83SMike Frysinger     info->nsegs = 0;
26711af02e83SMike Frysinger     info->pt_dynamic_addr = 0;
26721af02e83SMike Frysinger 
267398c1076cSAlex Bennée     mmap_lock();
267498c1076cSAlex Bennée 
26758a1a5274SRichard Henderson     /*
26768a1a5274SRichard Henderson      * Find the maximum size of the image and allocate an appropriate
26778a1a5274SRichard Henderson      * amount of memory to handle that.  Locate the interpreter, if any.
26788a1a5274SRichard Henderson      */
2679682674b8SRichard Henderson     loaddr = -1, hiaddr = 0;
268033143c44SLaurent Vivier     info->alignment = 0;
26818e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; ++i) {
26824d9d535aSRichard Henderson         struct elf_phdr *eppnt = phdr + i;
26834d9d535aSRichard Henderson         if (eppnt->p_type == PT_LOAD) {
26844d9d535aSRichard Henderson             abi_ulong a = eppnt->p_vaddr - eppnt->p_offset;
2685682674b8SRichard Henderson             if (a < loaddr) {
2686682674b8SRichard Henderson                 loaddr = a;
2687682674b8SRichard Henderson             }
26884d9d535aSRichard Henderson             a = eppnt->p_vaddr + eppnt->p_memsz;
2689682674b8SRichard Henderson             if (a > hiaddr) {
2690682674b8SRichard Henderson                 hiaddr = a;
2691682674b8SRichard Henderson             }
26921af02e83SMike Frysinger             ++info->nsegs;
26934d9d535aSRichard Henderson             info->alignment |= eppnt->p_align;
26948a1a5274SRichard Henderson         } else if (eppnt->p_type == PT_INTERP && pinterp_name) {
26958a1a5274SRichard Henderson             g_autofree char *interp_name = NULL;
26968a1a5274SRichard Henderson 
26978a1a5274SRichard Henderson             if (*pinterp_name) {
2698c7f17e7bSRichard Henderson                 error_setg(&err, "Multiple PT_INTERP entries");
26998a1a5274SRichard Henderson                 goto exit_errmsg;
27008a1a5274SRichard Henderson             }
2701c7f17e7bSRichard Henderson 
27028a1a5274SRichard Henderson             interp_name = g_malloc(eppnt->p_filesz);
27038a1a5274SRichard Henderson 
27048a1a5274SRichard Henderson             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
27058a1a5274SRichard Henderson                 memcpy(interp_name, bprm_buf + eppnt->p_offset,
27068a1a5274SRichard Henderson                        eppnt->p_filesz);
27078a1a5274SRichard Henderson             } else {
27088a1a5274SRichard Henderson                 retval = pread(image_fd, interp_name, eppnt->p_filesz,
27098a1a5274SRichard Henderson                                eppnt->p_offset);
27108a1a5274SRichard Henderson                 if (retval != eppnt->p_filesz) {
2711c7f17e7bSRichard Henderson                     goto exit_read;
27128a1a5274SRichard Henderson                 }
27138a1a5274SRichard Henderson             }
27148a1a5274SRichard Henderson             if (interp_name[eppnt->p_filesz - 1] != 0) {
2715c7f17e7bSRichard Henderson                 error_setg(&err, "Invalid PT_INTERP entry");
27168a1a5274SRichard Henderson                 goto exit_errmsg;
27178a1a5274SRichard Henderson             }
27188a1a5274SRichard Henderson             *pinterp_name = g_steal_pointer(&interp_name);
271983f990ebSRichard Henderson         } else if (eppnt->p_type == PT_GNU_PROPERTY) {
272083f990ebSRichard Henderson             if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
272183f990ebSRichard Henderson                 goto exit_errmsg;
272283f990ebSRichard Henderson             }
2723682674b8SRichard Henderson         }
2724682674b8SRichard Henderson     }
2725682674b8SRichard Henderson 
27266fd59449SRichard Henderson     if (pinterp_name != NULL) {
27276fd59449SRichard Henderson         /*
27286fd59449SRichard Henderson          * This is the main executable.
27296fd59449SRichard Henderson          *
27306fd59449SRichard Henderson          * Reserve extra space for brk.
27316fd59449SRichard Henderson          * We hold on to this space while placing the interpreter
27326fd59449SRichard Henderson          * and the stack, lest they be placed immediately after
27336fd59449SRichard Henderson          * the data segment and block allocation from the brk.
27346fd59449SRichard Henderson          *
27356fd59449SRichard Henderson          * 16MB is chosen as "large enough" without being so large
27366fd59449SRichard Henderson          * as to allow the result to not fit with a 32-bit guest on
27376fd59449SRichard Henderson          * a 32-bit host.
27386fd59449SRichard Henderson          */
27396fd59449SRichard Henderson         info->reserve_brk = 16 * MiB;
27406fd59449SRichard Henderson         hiaddr += info->reserve_brk;
27416fd59449SRichard Henderson 
27426fd59449SRichard Henderson         if (ehdr->e_type == ET_EXEC) {
27436fd59449SRichard Henderson             /*
27446fd59449SRichard Henderson              * Make sure that the low address does not conflict with
27456fd59449SRichard Henderson              * MMAP_MIN_ADDR or the QEMU application itself.
27466fd59449SRichard Henderson              */
27476fd59449SRichard Henderson             probe_guest_base(image_name, loaddr, hiaddr);
2748ee947430SAlex Bennée         } else {
2749ee947430SAlex Bennée             /*
2750ee947430SAlex Bennée              * The binary is dynamic, but we still need to
2751ee947430SAlex Bennée              * select guest_base.  In this case we pass a size.
2752ee947430SAlex Bennée              */
2753ee947430SAlex Bennée             probe_guest_base(image_name, 0, hiaddr - loaddr);
27546fd59449SRichard Henderson         }
27556fd59449SRichard Henderson     }
27566fd59449SRichard Henderson 
27576fd59449SRichard Henderson     /*
27586fd59449SRichard Henderson      * Reserve address space for all of this.
27596fd59449SRichard Henderson      *
27606fd59449SRichard Henderson      * In the case of ET_EXEC, we supply MAP_FIXED so that we get
27616fd59449SRichard Henderson      * exactly the address range that is required.
27626fd59449SRichard Henderson      *
27636fd59449SRichard Henderson      * Otherwise this is ET_DYN, and we are searching for a location
27646fd59449SRichard Henderson      * that can hold the memory space required.  If the image is
27656fd59449SRichard Henderson      * pre-linked, LOADDR will be non-zero, and the kernel should
27666fd59449SRichard Henderson      * honor that address if it happens to be free.
27676fd59449SRichard Henderson      *
27686fd59449SRichard Henderson      * In both cases, we will overwrite pages in this range with mappings
27696fd59449SRichard Henderson      * from the executable.
27706fd59449SRichard Henderson      */
2771682674b8SRichard Henderson     load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
27726fd59449SRichard Henderson                             MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
27736fd59449SRichard Henderson                             (ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
277409bfb054Sbellard                             -1, 0);
2775682674b8SRichard Henderson     if (load_addr == -1) {
2776c7f17e7bSRichard Henderson         goto exit_mmap;
277709bfb054Sbellard     }
2778682674b8SRichard Henderson     load_bias = load_addr - loaddr;
277909bfb054Sbellard 
2780a99856cdSChristophe Lyon     if (elf_is_fdpic(ehdr)) {
27811af02e83SMike Frysinger         struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
27827267c094SAnthony Liguori             g_malloc(sizeof(*loadsegs) * info->nsegs);
27831af02e83SMike Frysinger 
27841af02e83SMike Frysinger         for (i = 0; i < ehdr->e_phnum; ++i) {
27851af02e83SMike Frysinger             switch (phdr[i].p_type) {
27861af02e83SMike Frysinger             case PT_DYNAMIC:
27871af02e83SMike Frysinger                 info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
27881af02e83SMike Frysinger                 break;
27891af02e83SMike Frysinger             case PT_LOAD:
27901af02e83SMike Frysinger                 loadsegs->addr = phdr[i].p_vaddr + load_bias;
27911af02e83SMike Frysinger                 loadsegs->p_vaddr = phdr[i].p_vaddr;
27921af02e83SMike Frysinger                 loadsegs->p_memsz = phdr[i].p_memsz;
27931af02e83SMike Frysinger                 ++loadsegs;
27941af02e83SMike Frysinger                 break;
27951af02e83SMike Frysinger             }
27961af02e83SMike Frysinger         }
27971af02e83SMike Frysinger     }
27981af02e83SMike Frysinger 
27998e62a717SRichard Henderson     info->load_bias = load_bias;
2800dc12567aSJosh Kunz     info->code_offset = load_bias;
2801dc12567aSJosh Kunz     info->data_offset = load_bias;
28028e62a717SRichard Henderson     info->load_addr = load_addr;
28038e62a717SRichard Henderson     info->entry = ehdr->e_entry + load_bias;
28048e62a717SRichard Henderson     info->start_code = -1;
28058e62a717SRichard Henderson     info->end_code = 0;
28068e62a717SRichard Henderson     info->start_data = -1;
28078e62a717SRichard Henderson     info->end_data = 0;
28088e62a717SRichard Henderson     info->brk = 0;
2809d8fd2954SPaul Brook     info->elf_flags = ehdr->e_flags;
28108e62a717SRichard Henderson 
2811e8384b37SRichard Henderson     prot_exec = PROT_EXEC;
2812e8384b37SRichard Henderson #ifdef TARGET_AARCH64
2813e8384b37SRichard Henderson     /*
2814e8384b37SRichard Henderson      * If the BTI feature is present, this indicates that the executable
2815e8384b37SRichard Henderson      * pages of the startup binary should be mapped with PROT_BTI, so that
2816e8384b37SRichard Henderson      * branch targets are enforced.
2817e8384b37SRichard Henderson      *
2818e8384b37SRichard Henderson      * The startup binary is either the interpreter or the static executable.
2819e8384b37SRichard Henderson      * The interpreter is responsible for all pages of a dynamic executable.
2820e8384b37SRichard Henderson      *
2821e8384b37SRichard Henderson      * Elf notes are backward compatible to older cpus.
2822e8384b37SRichard Henderson      * Do not enable BTI unless it is supported.
2823e8384b37SRichard Henderson      */
2824e8384b37SRichard Henderson     if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
2825e8384b37SRichard Henderson         && (pinterp_name == NULL || *pinterp_name == 0)
2826e8384b37SRichard Henderson         && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) {
2827e8384b37SRichard Henderson         prot_exec |= TARGET_PROT_BTI;
2828e8384b37SRichard Henderson     }
2829e8384b37SRichard Henderson #endif
2830e8384b37SRichard Henderson 
28318e62a717SRichard Henderson     for (i = 0; i < ehdr->e_phnum; i++) {
28328e62a717SRichard Henderson         struct elf_phdr *eppnt = phdr + i;
283331e31b8aSbellard         if (eppnt->p_type == PT_LOAD) {
283494894ff2SShivaprasad G Bhat             abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len;
283531e31b8aSbellard             int elf_prot = 0;
283631e31b8aSbellard 
2837e5eaf570SRichard Henderson             if (eppnt->p_flags & PF_R) {
2838e5eaf570SRichard Henderson                 elf_prot |= PROT_READ;
2839e5eaf570SRichard Henderson             }
2840e5eaf570SRichard Henderson             if (eppnt->p_flags & PF_W) {
2841e5eaf570SRichard Henderson                 elf_prot |= PROT_WRITE;
2842e5eaf570SRichard Henderson             }
2843e5eaf570SRichard Henderson             if (eppnt->p_flags & PF_X) {
2844e8384b37SRichard Henderson                 elf_prot |= prot_exec;
2845e5eaf570SRichard Henderson             }
284631e31b8aSbellard 
2847682674b8SRichard Henderson             vaddr = load_bias + eppnt->p_vaddr;
2848682674b8SRichard Henderson             vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
2849682674b8SRichard Henderson             vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
285022d113b5SGiuseppe Musacchio 
285122d113b5SGiuseppe Musacchio             vaddr_ef = vaddr + eppnt->p_filesz;
285222d113b5SGiuseppe Musacchio             vaddr_em = vaddr + eppnt->p_memsz;
2853682674b8SRichard Henderson 
2854d87146bcSGiuseppe Musacchio             /*
285522d113b5SGiuseppe Musacchio              * Some segments may be completely empty, with a non-zero p_memsz
285622d113b5SGiuseppe Musacchio              * but no backing file segment.
2857d87146bcSGiuseppe Musacchio              */
2858d87146bcSGiuseppe Musacchio             if (eppnt->p_filesz != 0) {
285922d113b5SGiuseppe Musacchio                 vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po);
2860d87146bcSGiuseppe Musacchio                 error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
2861d87146bcSGiuseppe Musacchio                                     MAP_PRIVATE | MAP_FIXED,
28628e62a717SRichard Henderson                                     image_fd, eppnt->p_offset - vaddr_po);
2863d87146bcSGiuseppe Musacchio 
2864e89f07d3Spbrook                 if (error == -1) {
2865c7f17e7bSRichard Henderson                     goto exit_mmap;
286631e31b8aSbellard                 }
286731e31b8aSbellard 
286822d113b5SGiuseppe Musacchio                 /*
286922d113b5SGiuseppe Musacchio                  * If the load segment requests extra zeros (e.g. bss), map it.
287022d113b5SGiuseppe Musacchio                  */
287122d113b5SGiuseppe Musacchio                 if (eppnt->p_filesz < eppnt->p_memsz) {
2872682674b8SRichard Henderson                     zero_bss(vaddr_ef, vaddr_em, elf_prot);
2873682674b8SRichard Henderson                 }
287422d113b5SGiuseppe Musacchio             } else if (eppnt->p_memsz != 0) {
287522d113b5SGiuseppe Musacchio                 vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_memsz + vaddr_po);
287622d113b5SGiuseppe Musacchio                 error = target_mmap(vaddr_ps, vaddr_len, elf_prot,
287722d113b5SGiuseppe Musacchio                                     MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
287822d113b5SGiuseppe Musacchio                                     -1, 0);
287922d113b5SGiuseppe Musacchio 
288022d113b5SGiuseppe Musacchio                 if (error == -1) {
288122d113b5SGiuseppe Musacchio                     goto exit_mmap;
288222d113b5SGiuseppe Musacchio                 }
288322d113b5SGiuseppe Musacchio             }
28848e62a717SRichard Henderson 
28858e62a717SRichard Henderson             /* Find the full program boundaries.  */
28868e62a717SRichard Henderson             if (elf_prot & PROT_EXEC) {
28878e62a717SRichard Henderson                 if (vaddr < info->start_code) {
28888e62a717SRichard Henderson                     info->start_code = vaddr;
2889cf129f3aSRichard Henderson                 }
28908e62a717SRichard Henderson                 if (vaddr_ef > info->end_code) {
28918e62a717SRichard Henderson                     info->end_code = vaddr_ef;
28928e62a717SRichard Henderson                 }
28938e62a717SRichard Henderson             }
28948e62a717SRichard Henderson             if (elf_prot & PROT_WRITE) {
28958e62a717SRichard Henderson                 if (vaddr < info->start_data) {
28968e62a717SRichard Henderson                     info->start_data = vaddr;
28978e62a717SRichard Henderson                 }
28988e62a717SRichard Henderson                 if (vaddr_ef > info->end_data) {
28998e62a717SRichard Henderson                     info->end_data = vaddr_ef;
29008e62a717SRichard Henderson                 }
29018a045188STimothy E Baldwin             }
29028e62a717SRichard Henderson             if (vaddr_em > info->brk) {
29038e62a717SRichard Henderson                 info->brk = vaddr_em;
29048e62a717SRichard Henderson             }
29055dd0db52SStefan Markovic #ifdef TARGET_MIPS
29065dd0db52SStefan Markovic         } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) {
29075dd0db52SStefan Markovic             Mips_elf_abiflags_v0 abiflags;
29085dd0db52SStefan Markovic             if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) {
2909c7f17e7bSRichard Henderson                 error_setg(&err, "Invalid PT_MIPS_ABIFLAGS entry");
29105dd0db52SStefan Markovic                 goto exit_errmsg;
29115dd0db52SStefan Markovic             }
29125dd0db52SStefan Markovic             if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) {
29135dd0db52SStefan Markovic                 memcpy(&abiflags, bprm_buf + eppnt->p_offset,
29145dd0db52SStefan Markovic                        sizeof(Mips_elf_abiflags_v0));
29155dd0db52SStefan Markovic             } else {
29165dd0db52SStefan Markovic                 retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0),
29175dd0db52SStefan Markovic                                eppnt->p_offset);
29185dd0db52SStefan Markovic                 if (retval != sizeof(Mips_elf_abiflags_v0)) {
2919c7f17e7bSRichard Henderson                     goto exit_read;
29205dd0db52SStefan Markovic                 }
29215dd0db52SStefan Markovic             }
29225dd0db52SStefan Markovic             bswap_mips_abiflags(&abiflags);
2923c94cb6c9SStefan Markovic             info->fp_abi = abiflags.fp_abi;
29245dd0db52SStefan Markovic #endif
29258e62a717SRichard Henderson         }
29268e62a717SRichard Henderson     }
29278e62a717SRichard Henderson 
29288e62a717SRichard Henderson     if (info->end_data == 0) {
29298e62a717SRichard Henderson         info->start_data = info->end_code;
29308e62a717SRichard Henderson         info->end_data = info->end_code;
293131e31b8aSbellard     }
293231e31b8aSbellard 
2933682674b8SRichard Henderson     if (qemu_log_enabled()) {
29348e62a717SRichard Henderson         load_symbols(ehdr, image_fd, load_bias);
2935682674b8SRichard Henderson     }
293631e31b8aSbellard 
293798c1076cSAlex Bennée     mmap_unlock();
293898c1076cSAlex Bennée 
29398e62a717SRichard Henderson     close(image_fd);
29408e62a717SRichard Henderson     return;
294131e31b8aSbellard 
29428e62a717SRichard Henderson  exit_read:
29438e62a717SRichard Henderson     if (retval >= 0) {
2944c7f17e7bSRichard Henderson         error_setg(&err, "Incomplete read of file header");
2945c7f17e7bSRichard Henderson     } else {
2946c7f17e7bSRichard Henderson         error_setg_errno(&err, errno, "Error reading file header");
29478e62a717SRichard Henderson     }
2948c7f17e7bSRichard Henderson     goto exit_errmsg;
2949c7f17e7bSRichard Henderson  exit_mmap:
2950c7f17e7bSRichard Henderson     error_setg_errno(&err, errno, "Error mapping file");
2951c7f17e7bSRichard Henderson     goto exit_errmsg;
29528e62a717SRichard Henderson  exit_errmsg:
2953c7f17e7bSRichard Henderson     error_reportf_err(err, "%s: ", image_name);
29548e62a717SRichard Henderson     exit(-1);
29558e62a717SRichard Henderson }
29568e62a717SRichard Henderson 
29578e62a717SRichard Henderson static void load_elf_interp(const char *filename, struct image_info *info,
29588e62a717SRichard Henderson                             char bprm_buf[BPRM_BUF_SIZE])
29598e62a717SRichard Henderson {
29608e62a717SRichard Henderson     int fd, retval;
2961808f6563SRichard Henderson     Error *err = NULL;
29628e62a717SRichard Henderson 
29638e62a717SRichard Henderson     fd = open(path(filename), O_RDONLY);
29648e62a717SRichard Henderson     if (fd < 0) {
2965808f6563SRichard Henderson         error_setg_file_open(&err, errno, filename);
2966808f6563SRichard Henderson         error_report_err(err);
2967808f6563SRichard Henderson         exit(-1);
29688e62a717SRichard Henderson     }
29698e62a717SRichard Henderson 
29708e62a717SRichard Henderson     retval = read(fd, bprm_buf, BPRM_BUF_SIZE);
29718e62a717SRichard Henderson     if (retval < 0) {
2972808f6563SRichard Henderson         error_setg_errno(&err, errno, "Error reading file header");
2973808f6563SRichard Henderson         error_reportf_err(err, "%s: ", filename);
2974808f6563SRichard Henderson         exit(-1);
29758e62a717SRichard Henderson     }
2976808f6563SRichard Henderson 
29778e62a717SRichard Henderson     if (retval < BPRM_BUF_SIZE) {
29788e62a717SRichard Henderson         memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval);
29798e62a717SRichard Henderson     }
29808e62a717SRichard Henderson 
2981bf858897SRichard Henderson     load_elf_image(filename, fd, info, NULL, bprm_buf);
298231e31b8aSbellard }
298331e31b8aSbellard 
298449918a75Spbrook static int symfind(const void *s0, const void *s1)
298549918a75Spbrook {
2986c7c530cdSStefan Weil     target_ulong addr = *(target_ulong *)s0;
298749918a75Spbrook     struct elf_sym *sym = (struct elf_sym *)s1;
298849918a75Spbrook     int result = 0;
2989c7c530cdSStefan Weil     if (addr < sym->st_value) {
299049918a75Spbrook         result = -1;
2991c7c530cdSStefan Weil     } else if (addr >= sym->st_value + sym->st_size) {
299249918a75Spbrook         result = 1;
299349918a75Spbrook     }
299449918a75Spbrook     return result;
299549918a75Spbrook }
299649918a75Spbrook 
299749918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
299849918a75Spbrook {
299949918a75Spbrook #if ELF_CLASS == ELFCLASS32
300049918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf32;
300149918a75Spbrook #else
300249918a75Spbrook     struct elf_sym *syms = s->disas_symtab.elf64;
300349918a75Spbrook #endif
300449918a75Spbrook 
300549918a75Spbrook     // binary search
300649918a75Spbrook     struct elf_sym *sym;
300749918a75Spbrook 
3008c7c530cdSStefan Weil     sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind);
30097cba04f6SBlue Swirl     if (sym != NULL) {
301049918a75Spbrook         return s->disas_strtab + sym->st_name;
301149918a75Spbrook     }
301249918a75Spbrook 
301349918a75Spbrook     return "";
301449918a75Spbrook }
301549918a75Spbrook 
301649918a75Spbrook /* FIXME: This should use elf_ops.h  */
301749918a75Spbrook static int symcmp(const void *s0, const void *s1)
301849918a75Spbrook {
301949918a75Spbrook     struct elf_sym *sym0 = (struct elf_sym *)s0;
302049918a75Spbrook     struct elf_sym *sym1 = (struct elf_sym *)s1;
302149918a75Spbrook     return (sym0->st_value < sym1->st_value)
302249918a75Spbrook         ? -1
302349918a75Spbrook         : ((sym0->st_value > sym1->st_value) ? 1 : 0);
302449918a75Spbrook }
302549918a75Spbrook 
3026689f936fSbellard /* Best attempt to load symbols from this ELF object. */
3027682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
3028689f936fSbellard {
3029682674b8SRichard Henderson     int i, shnum, nsyms, sym_idx = 0, str_idx = 0;
30301e06262dSPeter Maydell     uint64_t segsz;
3031682674b8SRichard Henderson     struct elf_shdr *shdr;
3032b9475279SCédric VINCENT     char *strings = NULL;
3033b9475279SCédric VINCENT     struct syminfo *s = NULL;
3034b9475279SCédric VINCENT     struct elf_sym *new_syms, *syms = NULL;
303531e31b8aSbellard 
3036682674b8SRichard Henderson     shnum = hdr->e_shnum;
3037682674b8SRichard Henderson     i = shnum * sizeof(struct elf_shdr);
3038682674b8SRichard Henderson     shdr = (struct elf_shdr *)alloca(i);
3039682674b8SRichard Henderson     if (pread(fd, shdr, i, hdr->e_shoff) != i) {
3040689f936fSbellard         return;
3041682674b8SRichard Henderson     }
3042682674b8SRichard Henderson 
3043682674b8SRichard Henderson     bswap_shdr(shdr, shnum);
3044682674b8SRichard Henderson     for (i = 0; i < shnum; ++i) {
3045682674b8SRichard Henderson         if (shdr[i].sh_type == SHT_SYMTAB) {
3046682674b8SRichard Henderson             sym_idx = i;
3047682674b8SRichard Henderson             str_idx = shdr[i].sh_link;
3048689f936fSbellard             goto found;
3049689f936fSbellard         }
3050689f936fSbellard     }
3051682674b8SRichard Henderson 
3052682674b8SRichard Henderson     /* There will be no symbol table if the file was stripped.  */
3053682674b8SRichard Henderson     return;
3054689f936fSbellard 
3055689f936fSbellard  found:
3056689f936fSbellard     /* Now know where the strtab and symtab are.  Snarf them.  */
30570ef9ea29SPeter Maydell     s = g_try_new(struct syminfo, 1);
3058682674b8SRichard Henderson     if (!s) {
3059b9475279SCédric VINCENT         goto give_up;
3060682674b8SRichard Henderson     }
3061682674b8SRichard Henderson 
30621e06262dSPeter Maydell     segsz = shdr[str_idx].sh_size;
30631e06262dSPeter Maydell     s->disas_strtab = strings = g_try_malloc(segsz);
30641e06262dSPeter Maydell     if (!strings ||
30651e06262dSPeter Maydell         pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) {
3066b9475279SCédric VINCENT         goto give_up;
3067682674b8SRichard Henderson     }
3068689f936fSbellard 
30691e06262dSPeter Maydell     segsz = shdr[sym_idx].sh_size;
30701e06262dSPeter Maydell     syms = g_try_malloc(segsz);
30711e06262dSPeter Maydell     if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) {
3072b9475279SCédric VINCENT         goto give_up;
3073682674b8SRichard Henderson     }
3074689f936fSbellard 
30751e06262dSPeter Maydell     if (segsz / sizeof(struct elf_sym) > INT_MAX) {
30761e06262dSPeter Maydell         /* Implausibly large symbol table: give up rather than ploughing
30771e06262dSPeter Maydell          * on with the number of symbols calculation overflowing
30781e06262dSPeter Maydell          */
30791e06262dSPeter Maydell         goto give_up;
30801e06262dSPeter Maydell     }
30811e06262dSPeter Maydell     nsyms = segsz / sizeof(struct elf_sym);
3082682674b8SRichard Henderson     for (i = 0; i < nsyms; ) {
308349918a75Spbrook         bswap_sym(syms + i);
3084682674b8SRichard Henderson         /* Throw away entries which we do not need.  */
3085682674b8SRichard Henderson         if (syms[i].st_shndx == SHN_UNDEF
3086682674b8SRichard Henderson             || syms[i].st_shndx >= SHN_LORESERVE
3087682674b8SRichard Henderson             || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
3088682674b8SRichard Henderson             if (i < --nsyms) {
308949918a75Spbrook                 syms[i] = syms[nsyms];
309049918a75Spbrook             }
3091682674b8SRichard Henderson         } else {
309249918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS)
309349918a75Spbrook             /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
309449918a75Spbrook             syms[i].st_value &= ~(target_ulong)1;
309549918a75Spbrook #endif
3096682674b8SRichard Henderson             syms[i].st_value += load_bias;
309749918a75Spbrook             i++;
309849918a75Spbrook         }
3099682674b8SRichard Henderson     }
310049918a75Spbrook 
3101b9475279SCédric VINCENT     /* No "useful" symbol.  */
3102b9475279SCédric VINCENT     if (nsyms == 0) {
3103b9475279SCédric VINCENT         goto give_up;
3104b9475279SCédric VINCENT     }
3105b9475279SCédric VINCENT 
31065d5c9930SRichard Henderson     /* Attempt to free the storage associated with the local symbols
31075d5c9930SRichard Henderson        that we threw away.  Whether or not this has any effect on the
31085d5c9930SRichard Henderson        memory allocation depends on the malloc implementation and how
31095d5c9930SRichard Henderson        many symbols we managed to discard.  */
31100ef9ea29SPeter Maydell     new_syms = g_try_renew(struct elf_sym, syms, nsyms);
31118d79de6eSStefan Weil     if (new_syms == NULL) {
3112b9475279SCédric VINCENT         goto give_up;
31135d5c9930SRichard Henderson     }
31148d79de6eSStefan Weil     syms = new_syms;
31155d5c9930SRichard Henderson 
311649918a75Spbrook     qsort(syms, nsyms, sizeof(*syms), symcmp);
311749918a75Spbrook 
311849918a75Spbrook     s->disas_num_syms = nsyms;
311949918a75Spbrook #if ELF_CLASS == ELFCLASS32
312049918a75Spbrook     s->disas_symtab.elf32 = syms;
312149918a75Spbrook #else
312249918a75Spbrook     s->disas_symtab.elf64 = syms;
312349918a75Spbrook #endif
3124682674b8SRichard Henderson     s->lookup_symbol = lookup_symbolxx;
3125e80cfcfcSbellard     s->next = syminfos;
3126e80cfcfcSbellard     syminfos = s;
3127b9475279SCédric VINCENT 
3128b9475279SCédric VINCENT     return;
3129b9475279SCédric VINCENT 
3130b9475279SCédric VINCENT give_up:
31310ef9ea29SPeter Maydell     g_free(s);
31320ef9ea29SPeter Maydell     g_free(strings);
31330ef9ea29SPeter Maydell     g_free(syms);
3134689f936fSbellard }
313531e31b8aSbellard 
3136768fe76eSYunQiang Su uint32_t get_elf_eflags(int fd)
3137768fe76eSYunQiang Su {
3138768fe76eSYunQiang Su     struct elfhdr ehdr;
3139768fe76eSYunQiang Su     off_t offset;
3140768fe76eSYunQiang Su     int ret;
3141768fe76eSYunQiang Su 
3142768fe76eSYunQiang Su     /* Read ELF header */
3143768fe76eSYunQiang Su     offset = lseek(fd, 0, SEEK_SET);
3144768fe76eSYunQiang Su     if (offset == (off_t) -1) {
3145768fe76eSYunQiang Su         return 0;
3146768fe76eSYunQiang Su     }
3147768fe76eSYunQiang Su     ret = read(fd, &ehdr, sizeof(ehdr));
3148768fe76eSYunQiang Su     if (ret < sizeof(ehdr)) {
3149768fe76eSYunQiang Su         return 0;
3150768fe76eSYunQiang Su     }
3151768fe76eSYunQiang Su     offset = lseek(fd, offset, SEEK_SET);
3152768fe76eSYunQiang Su     if (offset == (off_t) -1) {
3153768fe76eSYunQiang Su         return 0;
3154768fe76eSYunQiang Su     }
3155768fe76eSYunQiang Su 
3156768fe76eSYunQiang Su     /* Check ELF signature */
3157768fe76eSYunQiang Su     if (!elf_check_ident(&ehdr)) {
3158768fe76eSYunQiang Su         return 0;
3159768fe76eSYunQiang Su     }
3160768fe76eSYunQiang Su 
3161768fe76eSYunQiang Su     /* check header */
3162768fe76eSYunQiang Su     bswap_ehdr(&ehdr);
3163768fe76eSYunQiang Su     if (!elf_check_ehdr(&ehdr)) {
3164768fe76eSYunQiang Su         return 0;
3165768fe76eSYunQiang Su     }
3166768fe76eSYunQiang Su 
3167768fe76eSYunQiang Su     /* return architecture id */
3168768fe76eSYunQiang Su     return ehdr.e_flags;
3169768fe76eSYunQiang Su }
3170768fe76eSYunQiang Su 
3171f0116c54SWill Newton int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
317231e31b8aSbellard {
31738e62a717SRichard Henderson     struct image_info interp_info;
317431e31b8aSbellard     struct elfhdr elf_ex;
31758e62a717SRichard Henderson     char *elf_interpreter = NULL;
317659baae9aSStefan Brüns     char *scratch;
317731e31b8aSbellard 
3178abcac736SDaniel Santos     memset(&interp_info, 0, sizeof(interp_info));
3179abcac736SDaniel Santos #ifdef TARGET_MIPS
3180abcac736SDaniel Santos     interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
3181abcac736SDaniel Santos #endif
3182abcac736SDaniel Santos 
3183bf858897SRichard Henderson     info->start_mmap = (abi_ulong)ELF_START_MMAP;
318431e31b8aSbellard 
3185bf858897SRichard Henderson     load_elf_image(bprm->filename, bprm->fd, info,
3186bf858897SRichard Henderson                    &elf_interpreter, bprm->buf);
3187bf858897SRichard Henderson 
3188bf858897SRichard Henderson     /* ??? We need a copy of the elf header for passing to create_elf_tables.
3189bf858897SRichard Henderson        If we do nothing, we'll have overwritten this when we re-use bprm->buf
3190bf858897SRichard Henderson        when we load the interpreter.  */
3191bf858897SRichard Henderson     elf_ex = *(struct elfhdr *)bprm->buf;
319231e31b8aSbellard 
319359baae9aSStefan Brüns     /* Do this so that we can load the interpreter, if need be.  We will
319459baae9aSStefan Brüns        change some of these later */
319559baae9aSStefan Brüns     bprm->p = setup_arg_pages(bprm, info);
319659baae9aSStefan Brüns 
319759baae9aSStefan Brüns     scratch = g_new0(char, TARGET_PAGE_SIZE);
31987c4ee5bcSRichard Henderson     if (STACK_GROWS_DOWN) {
319959baae9aSStefan Brüns         bprm->p = copy_elf_strings(1, &bprm->filename, scratch,
320059baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
32017c4ee5bcSRichard Henderson         info->file_string = bprm->p;
320259baae9aSStefan Brüns         bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch,
320359baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
32047c4ee5bcSRichard Henderson         info->env_strings = bprm->p;
320559baae9aSStefan Brüns         bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch,
320659baae9aSStefan Brüns                                    bprm->p, info->stack_limit);
32077c4ee5bcSRichard Henderson         info->arg_strings = bprm->p;
32087c4ee5bcSRichard Henderson     } else {
32097c4ee5bcSRichard Henderson         info->arg_strings = bprm->p;
32107c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch,
32117c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
32127c4ee5bcSRichard Henderson         info->env_strings = bprm->p;
32137c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch,
32147c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
32157c4ee5bcSRichard Henderson         info->file_string = bprm->p;
32167c4ee5bcSRichard Henderson         bprm->p = copy_elf_strings(1, &bprm->filename, scratch,
32177c4ee5bcSRichard Henderson                                    bprm->p, info->stack_limit);
32187c4ee5bcSRichard Henderson     }
32197c4ee5bcSRichard Henderson 
322059baae9aSStefan Brüns     g_free(scratch);
322159baae9aSStefan Brüns 
3222e5fe0c52Spbrook     if (!bprm->p) {
3223bf858897SRichard Henderson         fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
322431e31b8aSbellard         exit(-1);
32259955ffacSRichard Henderson     }
3226379f6698SPaul Brook 
32278e62a717SRichard Henderson     if (elf_interpreter) {
32288e62a717SRichard Henderson         load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
322931e31b8aSbellard 
32308e62a717SRichard Henderson         /* If the program interpreter is one of these two, then assume
32318e62a717SRichard Henderson            an iBCS2 image.  Otherwise assume a native linux image.  */
323231e31b8aSbellard 
32338e62a717SRichard Henderson         if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0
32348e62a717SRichard Henderson             || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) {
32358e62a717SRichard Henderson             info->personality = PER_SVR4;
32368e62a717SRichard Henderson 
323731e31b8aSbellard             /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
32388e62a717SRichard Henderson                and some applications "depend" upon this behavior.  Since
32398e62a717SRichard Henderson                we do not have the power to recompile these, we emulate
32408e62a717SRichard Henderson                the SVr4 behavior.  Sigh.  */
32418e62a717SRichard Henderson             target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
324268754b44SPeter Maydell                         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
324331e31b8aSbellard         }
3244c94cb6c9SStefan Markovic #ifdef TARGET_MIPS
3245c94cb6c9SStefan Markovic         info->interp_fp_abi = interp_info.fp_abi;
3246c94cb6c9SStefan Markovic #endif
32478e62a717SRichard Henderson     }
324831e31b8aSbellard 
32498e62a717SRichard Henderson     bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex,
32508e62a717SRichard Henderson                                 info, (elf_interpreter ? &interp_info : NULL));
32518e62a717SRichard Henderson     info->start_stack = bprm->p;
32528e62a717SRichard Henderson 
32538e62a717SRichard Henderson     /* If we have an interpreter, set that as the program's entry point.
32548e78064eSRichard Henderson        Copy the load_bias as well, to help PPC64 interpret the entry
32558e62a717SRichard Henderson        point as a function descriptor.  Do this after creating elf tables
32568e62a717SRichard Henderson        so that we copy the original program entry point into the AUXV.  */
32578e62a717SRichard Henderson     if (elf_interpreter) {
32588e78064eSRichard Henderson         info->load_bias = interp_info.load_bias;
32598e62a717SRichard Henderson         info->entry = interp_info.entry;
32602b323087SPhilippe Mathieu-Daudé         g_free(elf_interpreter);
32618e62a717SRichard Henderson     }
326231e31b8aSbellard 
3263edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
3264edf8e2afSMika Westerberg     bprm->core_dump = &elf_core_dump;
3265edf8e2afSMika Westerberg #endif
3266edf8e2afSMika Westerberg 
32676fd59449SRichard Henderson     /*
32686fd59449SRichard Henderson      * If we reserved extra space for brk, release it now.
32696fd59449SRichard Henderson      * The implementation of do_brk in syscalls.c expects to be able
32706fd59449SRichard Henderson      * to mmap pages in this space.
32716fd59449SRichard Henderson      */
32726fd59449SRichard Henderson     if (info->reserve_brk) {
32736fd59449SRichard Henderson         abi_ulong start_brk = HOST_PAGE_ALIGN(info->brk);
32746fd59449SRichard Henderson         abi_ulong end_brk = HOST_PAGE_ALIGN(info->brk + info->reserve_brk);
32756fd59449SRichard Henderson         target_munmap(start_brk, end_brk - start_brk);
32766fd59449SRichard Henderson     }
32776fd59449SRichard Henderson 
327831e31b8aSbellard     return 0;
327931e31b8aSbellard }
328031e31b8aSbellard 
3281edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP
3282edf8e2afSMika Westerberg /*
3283edf8e2afSMika Westerberg  * Definitions to generate Intel SVR4-like core files.
3284a2547a13SLaurent Desnogues  * These mostly have the same names as the SVR4 types with "target_elf_"
3285edf8e2afSMika Westerberg  * tacked on the front to prevent clashes with linux definitions,
3286edf8e2afSMika Westerberg  * and the typedef forms have been avoided.  This is mostly like
3287edf8e2afSMika Westerberg  * the SVR4 structure, but more Linuxy, with things that Linux does
3288edf8e2afSMika Westerberg  * not support and which gdb doesn't really use excluded.
3289edf8e2afSMika Westerberg  *
3290edf8e2afSMika Westerberg  * Fields we don't dump (their contents is zero) in linux-user qemu
3291edf8e2afSMika Westerberg  * are marked with XXX.
3292edf8e2afSMika Westerberg  *
3293edf8e2afSMika Westerberg  * Core dump code is copied from linux kernel (fs/binfmt_elf.c).
3294edf8e2afSMika Westerberg  *
3295edf8e2afSMika Westerberg  * Porting ELF coredump for target is (quite) simple process.  First you
3296dd0a3651SNathan Froyd  * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for
3297edf8e2afSMika Westerberg  * the target resides):
3298edf8e2afSMika Westerberg  *
3299edf8e2afSMika Westerberg  * #define USE_ELF_CORE_DUMP
3300edf8e2afSMika Westerberg  *
3301edf8e2afSMika Westerberg  * Next you define type of register set used for dumping.  ELF specification
3302edf8e2afSMika Westerberg  * says that it needs to be array of elf_greg_t that has size of ELF_NREG.
3303edf8e2afSMika Westerberg  *
3304c227f099SAnthony Liguori  * typedef <target_regtype> target_elf_greg_t;
3305edf8e2afSMika Westerberg  * #define ELF_NREG <number of registers>
3306c227f099SAnthony Liguori  * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG];
3307edf8e2afSMika Westerberg  *
3308edf8e2afSMika Westerberg  * Last step is to implement target specific function that copies registers
3309edf8e2afSMika Westerberg  * from given cpu into just specified register set.  Prototype is:
3310edf8e2afSMika Westerberg  *
3311c227f099SAnthony Liguori  * static void elf_core_copy_regs(taret_elf_gregset_t *regs,
33129349b4f9SAndreas Färber  *                                const CPUArchState *env);
3313edf8e2afSMika Westerberg  *
3314edf8e2afSMika Westerberg  * Parameters:
3315edf8e2afSMika Westerberg  *     regs - copy register values into here (allocated and zeroed by caller)
3316edf8e2afSMika Westerberg  *     env - copy registers from here
3317edf8e2afSMika Westerberg  *
3318edf8e2afSMika Westerberg  * Example for ARM target is provided in this file.
3319edf8e2afSMika Westerberg  */
3320edf8e2afSMika Westerberg 
3321edf8e2afSMika Westerberg /* An ELF note in memory */
3322edf8e2afSMika Westerberg struct memelfnote {
3323edf8e2afSMika Westerberg     const char *name;
3324edf8e2afSMika Westerberg     size_t     namesz;
3325edf8e2afSMika Westerberg     size_t     namesz_rounded;
3326edf8e2afSMika Westerberg     int        type;
3327edf8e2afSMika Westerberg     size_t     datasz;
332880f5ce75SLaurent Vivier     size_t     datasz_rounded;
3329edf8e2afSMika Westerberg     void       *data;
3330edf8e2afSMika Westerberg     size_t     notesz;
3331edf8e2afSMika Westerberg };
3332edf8e2afSMika Westerberg 
3333a2547a13SLaurent Desnogues struct target_elf_siginfo {
3334f8fd4fc4SPaolo Bonzini     abi_int    si_signo; /* signal number */
3335f8fd4fc4SPaolo Bonzini     abi_int    si_code;  /* extra code */
3336f8fd4fc4SPaolo Bonzini     abi_int    si_errno; /* errno */
3337edf8e2afSMika Westerberg };
3338edf8e2afSMika Westerberg 
3339a2547a13SLaurent Desnogues struct target_elf_prstatus {
3340a2547a13SLaurent Desnogues     struct target_elf_siginfo pr_info;      /* Info associated with signal */
33411ddd592fSPaolo Bonzini     abi_short          pr_cursig;    /* Current signal */
3342ca98ac83SPaolo Bonzini     abi_ulong          pr_sigpend;   /* XXX */
3343ca98ac83SPaolo Bonzini     abi_ulong          pr_sighold;   /* XXX */
3344c227f099SAnthony Liguori     target_pid_t       pr_pid;
3345c227f099SAnthony Liguori     target_pid_t       pr_ppid;
3346c227f099SAnthony Liguori     target_pid_t       pr_pgrp;
3347c227f099SAnthony Liguori     target_pid_t       pr_sid;
3348edf8e2afSMika Westerberg     struct target_timeval pr_utime;  /* XXX User time */
3349edf8e2afSMika Westerberg     struct target_timeval pr_stime;  /* XXX System time */
3350edf8e2afSMika Westerberg     struct target_timeval pr_cutime; /* XXX Cumulative user time */
3351edf8e2afSMika Westerberg     struct target_timeval pr_cstime; /* XXX Cumulative system time */
3352c227f099SAnthony Liguori     target_elf_gregset_t      pr_reg;       /* GP registers */
3353f8fd4fc4SPaolo Bonzini     abi_int            pr_fpvalid;   /* XXX */
3354edf8e2afSMika Westerberg };
3355edf8e2afSMika Westerberg 
3356edf8e2afSMika Westerberg #define ELF_PRARGSZ     (80) /* Number of chars for args */
3357edf8e2afSMika Westerberg 
3358a2547a13SLaurent Desnogues struct target_elf_prpsinfo {
3359edf8e2afSMika Westerberg     char         pr_state;       /* numeric process state */
3360edf8e2afSMika Westerberg     char         pr_sname;       /* char for pr_state */
3361edf8e2afSMika Westerberg     char         pr_zomb;        /* zombie */
3362edf8e2afSMika Westerberg     char         pr_nice;        /* nice val */
3363ca98ac83SPaolo Bonzini     abi_ulong    pr_flag;        /* flags */
3364c227f099SAnthony Liguori     target_uid_t pr_uid;
3365c227f099SAnthony Liguori     target_gid_t pr_gid;
3366c227f099SAnthony Liguori     target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
3367edf8e2afSMika Westerberg     /* Lots missing */
3368d7eb2b92SAlistair Francis     char    pr_fname[16] QEMU_NONSTRING; /* filename of executable */
3369edf8e2afSMika Westerberg     char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
3370edf8e2afSMika Westerberg };
3371edf8e2afSMika Westerberg 
3372edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */
3373edf8e2afSMika Westerberg struct elf_thread_status {
337472cf2d4fSBlue Swirl     QTAILQ_ENTRY(elf_thread_status)  ets_link;
3375a2547a13SLaurent Desnogues     struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */
3376edf8e2afSMika Westerberg #if 0
3377edf8e2afSMika Westerberg     elf_fpregset_t fpu;             /* NT_PRFPREG */
3378edf8e2afSMika Westerberg     struct task_struct *thread;
3379edf8e2afSMika Westerberg     elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */
3380edf8e2afSMika Westerberg #endif
3381edf8e2afSMika Westerberg     struct memelfnote notes[1];
3382edf8e2afSMika Westerberg     int num_notes;
3383edf8e2afSMika Westerberg };
3384edf8e2afSMika Westerberg 
3385edf8e2afSMika Westerberg struct elf_note_info {
3386edf8e2afSMika Westerberg     struct memelfnote   *notes;
3387a2547a13SLaurent Desnogues     struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */
3388a2547a13SLaurent Desnogues     struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */
3389edf8e2afSMika Westerberg 
3390b58deb34SPaolo Bonzini     QTAILQ_HEAD(, elf_thread_status) thread_list;
3391edf8e2afSMika Westerberg #if 0
3392edf8e2afSMika Westerberg     /*
3393edf8e2afSMika Westerberg      * Current version of ELF coredump doesn't support
3394edf8e2afSMika Westerberg      * dumping fp regs etc.
3395edf8e2afSMika Westerberg      */
3396edf8e2afSMika Westerberg     elf_fpregset_t *fpu;
3397edf8e2afSMika Westerberg     elf_fpxregset_t *xfpu;
3398edf8e2afSMika Westerberg     int thread_status_size;
3399edf8e2afSMika Westerberg #endif
3400edf8e2afSMika Westerberg     int notes_size;
3401edf8e2afSMika Westerberg     int numnote;
3402edf8e2afSMika Westerberg };
3403edf8e2afSMika Westerberg 
3404edf8e2afSMika Westerberg struct vm_area_struct {
34051a1c4db9SMikhail Ilyin     target_ulong   vma_start;  /* start vaddr of memory region */
34061a1c4db9SMikhail Ilyin     target_ulong   vma_end;    /* end vaddr of memory region */
3407edf8e2afSMika Westerberg     abi_ulong      vma_flags;  /* protection etc. flags for the region */
340872cf2d4fSBlue Swirl     QTAILQ_ENTRY(vm_area_struct) vma_link;
3409edf8e2afSMika Westerberg };
3410edf8e2afSMika Westerberg 
3411edf8e2afSMika Westerberg struct mm_struct {
341272cf2d4fSBlue Swirl     QTAILQ_HEAD(, vm_area_struct) mm_mmap;
3413edf8e2afSMika Westerberg     int mm_count;           /* number of mappings */
3414edf8e2afSMika Westerberg };
3415edf8e2afSMika Westerberg 
3416edf8e2afSMika Westerberg static struct mm_struct *vma_init(void);
3417edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *);
34181a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *, target_ulong,
34191a1c4db9SMikhail Ilyin                            target_ulong, abi_ulong);
3420edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *);
3421edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *);
3422edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *);
3423edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *);
34241a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end,
3425edf8e2afSMika Westerberg                       unsigned long flags);
3426edf8e2afSMika Westerberg 
3427edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t);
3428edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int,
3429edf8e2afSMika Westerberg                       unsigned int, void *);
3430a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int);
3431a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *);
3432edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *);
3433edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t);
3434edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *);
3435edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *);
34369349b4f9SAndreas Färber static int fill_note_info(struct elf_note_info *, long, const CPUArchState *);
34379349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *, const CPUArchState *);
3438edf8e2afSMika Westerberg 
3439edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t);
3440edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int);
3441edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int);
3442edf8e2afSMika Westerberg 
3443edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED
3444a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus)
3445edf8e2afSMika Westerberg {
3446ca98ac83SPaolo Bonzini     prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo);
3447ca98ac83SPaolo Bonzini     prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code);
3448ca98ac83SPaolo Bonzini     prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno);
3449edf8e2afSMika Westerberg     prstatus->pr_cursig = tswap16(prstatus->pr_cursig);
3450ca98ac83SPaolo Bonzini     prstatus->pr_sigpend = tswapal(prstatus->pr_sigpend);
3451ca98ac83SPaolo Bonzini     prstatus->pr_sighold = tswapal(prstatus->pr_sighold);
3452edf8e2afSMika Westerberg     prstatus->pr_pid = tswap32(prstatus->pr_pid);
3453edf8e2afSMika Westerberg     prstatus->pr_ppid = tswap32(prstatus->pr_ppid);
3454edf8e2afSMika Westerberg     prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp);
3455edf8e2afSMika Westerberg     prstatus->pr_sid = tswap32(prstatus->pr_sid);
3456edf8e2afSMika Westerberg     /* cpu times are not filled, so we skip them */
3457edf8e2afSMika Westerberg     /* regs should be in correct format already */
3458edf8e2afSMika Westerberg     prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid);
3459edf8e2afSMika Westerberg }
3460edf8e2afSMika Westerberg 
3461a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo)
3462edf8e2afSMika Westerberg {
3463ca98ac83SPaolo Bonzini     psinfo->pr_flag = tswapal(psinfo->pr_flag);
3464edf8e2afSMika Westerberg     psinfo->pr_uid = tswap16(psinfo->pr_uid);
3465edf8e2afSMika Westerberg     psinfo->pr_gid = tswap16(psinfo->pr_gid);
3466edf8e2afSMika Westerberg     psinfo->pr_pid = tswap32(psinfo->pr_pid);
3467edf8e2afSMika Westerberg     psinfo->pr_ppid = tswap32(psinfo->pr_ppid);
3468edf8e2afSMika Westerberg     psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp);
3469edf8e2afSMika Westerberg     psinfo->pr_sid = tswap32(psinfo->pr_sid);
3470edf8e2afSMika Westerberg }
3471991f8f0cSRichard Henderson 
3472991f8f0cSRichard Henderson static void bswap_note(struct elf_note *en)
3473991f8f0cSRichard Henderson {
3474991f8f0cSRichard Henderson     bswap32s(&en->n_namesz);
3475991f8f0cSRichard Henderson     bswap32s(&en->n_descsz);
3476991f8f0cSRichard Henderson     bswap32s(&en->n_type);
3477991f8f0cSRichard Henderson }
3478991f8f0cSRichard Henderson #else
3479991f8f0cSRichard Henderson static inline void bswap_prstatus(struct target_elf_prstatus *p) { }
3480991f8f0cSRichard Henderson static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {}
3481991f8f0cSRichard Henderson static inline void bswap_note(struct elf_note *en) { }
3482edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */
3483edf8e2afSMika Westerberg 
3484edf8e2afSMika Westerberg /*
3485edf8e2afSMika Westerberg  * Minimal support for linux memory regions.  These are needed
3486edf8e2afSMika Westerberg  * when we are finding out what memory exactly belongs to
3487edf8e2afSMika Westerberg  * emulated process.  No locks needed here, as long as
3488edf8e2afSMika Westerberg  * thread that received the signal is stopped.
3489edf8e2afSMika Westerberg  */
3490edf8e2afSMika Westerberg 
3491edf8e2afSMika Westerberg static struct mm_struct *vma_init(void)
3492edf8e2afSMika Westerberg {
3493edf8e2afSMika Westerberg     struct mm_struct *mm;
3494edf8e2afSMika Westerberg 
34957267c094SAnthony Liguori     if ((mm = g_malloc(sizeof (*mm))) == NULL)
3496edf8e2afSMika Westerberg         return (NULL);
3497edf8e2afSMika Westerberg 
3498edf8e2afSMika Westerberg     mm->mm_count = 0;
349972cf2d4fSBlue Swirl     QTAILQ_INIT(&mm->mm_mmap);
3500edf8e2afSMika Westerberg 
3501edf8e2afSMika Westerberg     return (mm);
3502edf8e2afSMika Westerberg }
3503edf8e2afSMika Westerberg 
3504edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm)
3505edf8e2afSMika Westerberg {
3506edf8e2afSMika Westerberg     struct vm_area_struct *vma;
3507edf8e2afSMika Westerberg 
3508edf8e2afSMika Westerberg     while ((vma = vma_first(mm)) != NULL) {
350972cf2d4fSBlue Swirl         QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link);
35107267c094SAnthony Liguori         g_free(vma);
3511edf8e2afSMika Westerberg     }
35127267c094SAnthony Liguori     g_free(mm);
3513edf8e2afSMika Westerberg }
3514edf8e2afSMika Westerberg 
35151a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *mm, target_ulong start,
35161a1c4db9SMikhail Ilyin                            target_ulong end, abi_ulong flags)
3517edf8e2afSMika Westerberg {
3518edf8e2afSMika Westerberg     struct vm_area_struct *vma;
3519edf8e2afSMika Westerberg 
35207267c094SAnthony Liguori     if ((vma = g_malloc0(sizeof (*vma))) == NULL)
3521edf8e2afSMika Westerberg         return (-1);
3522edf8e2afSMika Westerberg 
3523edf8e2afSMika Westerberg     vma->vma_start = start;
3524edf8e2afSMika Westerberg     vma->vma_end = end;
3525edf8e2afSMika Westerberg     vma->vma_flags = flags;
3526edf8e2afSMika Westerberg 
352772cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link);
3528edf8e2afSMika Westerberg     mm->mm_count++;
3529edf8e2afSMika Westerberg 
3530edf8e2afSMika Westerberg     return (0);
3531edf8e2afSMika Westerberg }
3532edf8e2afSMika Westerberg 
3533edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm)
3534edf8e2afSMika Westerberg {
353572cf2d4fSBlue Swirl     return (QTAILQ_FIRST(&mm->mm_mmap));
3536edf8e2afSMika Westerberg }
3537edf8e2afSMika Westerberg 
3538edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma)
3539edf8e2afSMika Westerberg {
354072cf2d4fSBlue Swirl     return (QTAILQ_NEXT(vma, vma_link));
3541edf8e2afSMika Westerberg }
3542edf8e2afSMika Westerberg 
3543edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm)
3544edf8e2afSMika Westerberg {
3545edf8e2afSMika Westerberg     return (mm->mm_count);
3546edf8e2afSMika Westerberg }
3547edf8e2afSMika Westerberg 
3548edf8e2afSMika Westerberg /*
3549edf8e2afSMika Westerberg  * Calculate file (dump) size of given memory region.
3550edf8e2afSMika Westerberg  */
3551edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma)
3552edf8e2afSMika Westerberg {
3553edf8e2afSMika Westerberg     /* if we cannot even read the first page, skip it */
3554c7169b02SRichard Henderson     if (!access_ok_untagged(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE))
3555edf8e2afSMika Westerberg         return (0);
3556edf8e2afSMika Westerberg 
3557edf8e2afSMika Westerberg     /*
3558edf8e2afSMika Westerberg      * Usually we don't dump executable pages as they contain
3559edf8e2afSMika Westerberg      * non-writable code that debugger can read directly from
3560edf8e2afSMika Westerberg      * target library etc.  However, thread stacks are marked
3561edf8e2afSMika Westerberg      * also executable so we read in first page of given region
3562edf8e2afSMika Westerberg      * and check whether it contains elf header.  If there is
3563edf8e2afSMika Westerberg      * no elf header, we dump it.
3564edf8e2afSMika Westerberg      */
3565edf8e2afSMika Westerberg     if (vma->vma_flags & PROT_EXEC) {
3566edf8e2afSMika Westerberg         char page[TARGET_PAGE_SIZE];
3567edf8e2afSMika Westerberg 
3568022625a8SPeter Maydell         if (copy_from_user(page, vma->vma_start, sizeof (page))) {
3569022625a8SPeter Maydell             return 0;
3570022625a8SPeter Maydell         }
3571edf8e2afSMika Westerberg         if ((page[EI_MAG0] == ELFMAG0) &&
3572edf8e2afSMika Westerberg             (page[EI_MAG1] == ELFMAG1) &&
3573edf8e2afSMika Westerberg             (page[EI_MAG2] == ELFMAG2) &&
3574edf8e2afSMika Westerberg             (page[EI_MAG3] == ELFMAG3)) {
3575edf8e2afSMika Westerberg             /*
3576edf8e2afSMika Westerberg              * Mappings are possibly from ELF binary.  Don't dump
3577edf8e2afSMika Westerberg              * them.
3578edf8e2afSMika Westerberg              */
3579edf8e2afSMika Westerberg             return (0);
3580edf8e2afSMika Westerberg         }
3581edf8e2afSMika Westerberg     }
3582edf8e2afSMika Westerberg 
3583edf8e2afSMika Westerberg     return (vma->vma_end - vma->vma_start);
3584edf8e2afSMika Westerberg }
3585edf8e2afSMika Westerberg 
35861a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end,
3587edf8e2afSMika Westerberg                       unsigned long flags)
3588edf8e2afSMika Westerberg {
3589edf8e2afSMika Westerberg     struct mm_struct *mm = (struct mm_struct *)priv;
3590edf8e2afSMika Westerberg 
3591edf8e2afSMika Westerberg     vma_add_mapping(mm, start, end, flags);
3592edf8e2afSMika Westerberg     return (0);
3593edf8e2afSMika Westerberg }
3594edf8e2afSMika Westerberg 
3595edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type,
3596edf8e2afSMika Westerberg                       unsigned int sz, void *data)
3597edf8e2afSMika Westerberg {
3598edf8e2afSMika Westerberg     unsigned int namesz;
3599edf8e2afSMika Westerberg 
3600edf8e2afSMika Westerberg     namesz = strlen(name) + 1;
3601edf8e2afSMika Westerberg     note->name = name;
3602edf8e2afSMika Westerberg     note->namesz = namesz;
3603edf8e2afSMika Westerberg     note->namesz_rounded = roundup(namesz, sizeof (int32_t));
3604edf8e2afSMika Westerberg     note->type = type;
360580f5ce75SLaurent Vivier     note->datasz = sz;
360680f5ce75SLaurent Vivier     note->datasz_rounded = roundup(sz, sizeof (int32_t));
360780f5ce75SLaurent Vivier 
3608edf8e2afSMika Westerberg     note->data = data;
3609edf8e2afSMika Westerberg 
3610edf8e2afSMika Westerberg     /*
3611edf8e2afSMika Westerberg      * We calculate rounded up note size here as specified by
3612edf8e2afSMika Westerberg      * ELF document.
3613edf8e2afSMika Westerberg      */
3614edf8e2afSMika Westerberg     note->notesz = sizeof (struct elf_note) +
361580f5ce75SLaurent Vivier         note->namesz_rounded + note->datasz_rounded;
3616edf8e2afSMika Westerberg }
3617edf8e2afSMika Westerberg 
3618edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine,
3619edf8e2afSMika Westerberg                             uint32_t flags)
3620edf8e2afSMika Westerberg {
3621edf8e2afSMika Westerberg     (void) memset(elf, 0, sizeof(*elf));
3622edf8e2afSMika Westerberg 
3623edf8e2afSMika Westerberg     (void) memcpy(elf->e_ident, ELFMAG, SELFMAG);
3624edf8e2afSMika Westerberg     elf->e_ident[EI_CLASS] = ELF_CLASS;
3625edf8e2afSMika Westerberg     elf->e_ident[EI_DATA] = ELF_DATA;
3626edf8e2afSMika Westerberg     elf->e_ident[EI_VERSION] = EV_CURRENT;
3627edf8e2afSMika Westerberg     elf->e_ident[EI_OSABI] = ELF_OSABI;
3628edf8e2afSMika Westerberg 
3629edf8e2afSMika Westerberg     elf->e_type = ET_CORE;
3630edf8e2afSMika Westerberg     elf->e_machine = machine;
3631edf8e2afSMika Westerberg     elf->e_version = EV_CURRENT;
3632edf8e2afSMika Westerberg     elf->e_phoff = sizeof(struct elfhdr);
3633edf8e2afSMika Westerberg     elf->e_flags = flags;
3634edf8e2afSMika Westerberg     elf->e_ehsize = sizeof(struct elfhdr);
3635edf8e2afSMika Westerberg     elf->e_phentsize = sizeof(struct elf_phdr);
3636edf8e2afSMika Westerberg     elf->e_phnum = segs;
3637edf8e2afSMika Westerberg 
3638edf8e2afSMika Westerberg     bswap_ehdr(elf);
3639edf8e2afSMika Westerberg }
3640edf8e2afSMika Westerberg 
3641edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset)
3642edf8e2afSMika Westerberg {
3643edf8e2afSMika Westerberg     phdr->p_type = PT_NOTE;
3644edf8e2afSMika Westerberg     phdr->p_offset = offset;
3645edf8e2afSMika Westerberg     phdr->p_vaddr = 0;
3646edf8e2afSMika Westerberg     phdr->p_paddr = 0;
3647edf8e2afSMika Westerberg     phdr->p_filesz = sz;
3648edf8e2afSMika Westerberg     phdr->p_memsz = 0;
3649edf8e2afSMika Westerberg     phdr->p_flags = 0;
3650edf8e2afSMika Westerberg     phdr->p_align = 0;
3651edf8e2afSMika Westerberg 
3652991f8f0cSRichard Henderson     bswap_phdr(phdr, 1);
3653edf8e2afSMika Westerberg }
3654edf8e2afSMika Westerberg 
3655edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note)
3656edf8e2afSMika Westerberg {
3657edf8e2afSMika Westerberg     return (note->notesz);
3658edf8e2afSMika Westerberg }
3659edf8e2afSMika Westerberg 
3660a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus,
3661edf8e2afSMika Westerberg                           const TaskState *ts, int signr)
3662edf8e2afSMika Westerberg {
3663edf8e2afSMika Westerberg     (void) memset(prstatus, 0, sizeof (*prstatus));
3664edf8e2afSMika Westerberg     prstatus->pr_info.si_signo = prstatus->pr_cursig = signr;
3665edf8e2afSMika Westerberg     prstatus->pr_pid = ts->ts_tid;
3666edf8e2afSMika Westerberg     prstatus->pr_ppid = getppid();
3667edf8e2afSMika Westerberg     prstatus->pr_pgrp = getpgrp();
3668edf8e2afSMika Westerberg     prstatus->pr_sid = getsid(0);
3669edf8e2afSMika Westerberg 
3670edf8e2afSMika Westerberg     bswap_prstatus(prstatus);
3671edf8e2afSMika Westerberg }
3672edf8e2afSMika Westerberg 
3673a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts)
3674edf8e2afSMika Westerberg {
3675900cfbcaSJim Meyering     char *base_filename;
3676edf8e2afSMika Westerberg     unsigned int i, len;
3677edf8e2afSMika Westerberg 
3678edf8e2afSMika Westerberg     (void) memset(psinfo, 0, sizeof (*psinfo));
3679edf8e2afSMika Westerberg 
36805f779a3aSIlya Leoshkevich     len = ts->info->env_strings - ts->info->arg_strings;
3681edf8e2afSMika Westerberg     if (len >= ELF_PRARGSZ)
3682edf8e2afSMika Westerberg         len = ELF_PRARGSZ - 1;
36835f779a3aSIlya Leoshkevich     if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_strings, len)) {
3684edf8e2afSMika Westerberg         return -EFAULT;
36855f779a3aSIlya Leoshkevich     }
3686edf8e2afSMika Westerberg     for (i = 0; i < len; i++)
3687edf8e2afSMika Westerberg         if (psinfo->pr_psargs[i] == 0)
3688edf8e2afSMika Westerberg             psinfo->pr_psargs[i] = ' ';
3689edf8e2afSMika Westerberg     psinfo->pr_psargs[len] = 0;
3690edf8e2afSMika Westerberg 
3691edf8e2afSMika Westerberg     psinfo->pr_pid = getpid();
3692edf8e2afSMika Westerberg     psinfo->pr_ppid = getppid();
3693edf8e2afSMika Westerberg     psinfo->pr_pgrp = getpgrp();
3694edf8e2afSMika Westerberg     psinfo->pr_sid = getsid(0);
3695edf8e2afSMika Westerberg     psinfo->pr_uid = getuid();
3696edf8e2afSMika Westerberg     psinfo->pr_gid = getgid();
3697edf8e2afSMika Westerberg 
3698900cfbcaSJim Meyering     base_filename = g_path_get_basename(ts->bprm->filename);
3699900cfbcaSJim Meyering     /*
3700900cfbcaSJim Meyering      * Using strncpy here is fine: at max-length,
3701900cfbcaSJim Meyering      * this field is not NUL-terminated.
3702900cfbcaSJim Meyering      */
3703edf8e2afSMika Westerberg     (void) strncpy(psinfo->pr_fname, base_filename,
3704edf8e2afSMika Westerberg                    sizeof(psinfo->pr_fname));
3705edf8e2afSMika Westerberg 
3706900cfbcaSJim Meyering     g_free(base_filename);
3707edf8e2afSMika Westerberg     bswap_psinfo(psinfo);
3708edf8e2afSMika Westerberg     return (0);
3709edf8e2afSMika Westerberg }
3710edf8e2afSMika Westerberg 
3711edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts)
3712edf8e2afSMika Westerberg {
3713edf8e2afSMika Westerberg     elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv;
3714edf8e2afSMika Westerberg     elf_addr_t orig_auxv = auxv;
3715edf8e2afSMika Westerberg     void *ptr;
3716125b0f55SAlexander Graf     int len = ts->info->auxv_len;
3717edf8e2afSMika Westerberg 
3718edf8e2afSMika Westerberg     /*
3719edf8e2afSMika Westerberg      * Auxiliary vector is stored in target process stack.  It contains
3720edf8e2afSMika Westerberg      * {type, value} pairs that we need to dump into note.  This is not
3721edf8e2afSMika Westerberg      * strictly necessary but we do it here for sake of completeness.
3722edf8e2afSMika Westerberg      */
3723edf8e2afSMika Westerberg 
3724edf8e2afSMika Westerberg     /* read in whole auxv vector and copy it to memelfnote */
3725edf8e2afSMika Westerberg     ptr = lock_user(VERIFY_READ, orig_auxv, len, 0);
3726edf8e2afSMika Westerberg     if (ptr != NULL) {
3727edf8e2afSMika Westerberg         fill_note(note, "CORE", NT_AUXV, len, ptr);
3728edf8e2afSMika Westerberg         unlock_user(ptr, auxv, len);
3729edf8e2afSMika Westerberg     }
3730edf8e2afSMika Westerberg }
3731edf8e2afSMika Westerberg 
3732edf8e2afSMika Westerberg /*
3733edf8e2afSMika Westerberg  * Constructs name of coredump file.  We have following convention
3734edf8e2afSMika Westerberg  * for the name:
3735edf8e2afSMika Westerberg  *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core
3736edf8e2afSMika Westerberg  *
373768af19adSDaniel P. Berrangé  * Returns the filename
3738edf8e2afSMika Westerberg  */
373968af19adSDaniel P. Berrangé static char *core_dump_filename(const TaskState *ts)
3740edf8e2afSMika Westerberg {
374168af19adSDaniel P. Berrangé     g_autoptr(GDateTime) now = g_date_time_new_now_local();
374268af19adSDaniel P. Berrangé     g_autofree char *nowstr = g_date_time_format(now, "%Y%m%d-%H%M%S");
374368af19adSDaniel P. Berrangé     g_autofree char *base_filename = g_path_get_basename(ts->bprm->filename);
3744edf8e2afSMika Westerberg 
374568af19adSDaniel P. Berrangé     return g_strdup_printf("qemu_%s_%s_%d.core",
374668af19adSDaniel P. Berrangé                            base_filename, nowstr, (int)getpid());
3747edf8e2afSMika Westerberg }
3748edf8e2afSMika Westerberg 
3749edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size)
3750edf8e2afSMika Westerberg {
3751edf8e2afSMika Westerberg     const char *bufp = (const char *)ptr;
3752edf8e2afSMika Westerberg     ssize_t bytes_written, bytes_left;
3753edf8e2afSMika Westerberg     struct rlimit dumpsize;
3754edf8e2afSMika Westerberg     off_t pos;
3755edf8e2afSMika Westerberg 
3756edf8e2afSMika Westerberg     bytes_written = 0;
3757edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
3758edf8e2afSMika Westerberg     if ((pos = lseek(fd, 0, SEEK_CUR))==-1) {
3759edf8e2afSMika Westerberg         if (errno == ESPIPE) { /* not a seekable stream */
3760edf8e2afSMika Westerberg             bytes_left = size;
3761edf8e2afSMika Westerberg         } else {
3762edf8e2afSMika Westerberg             return pos;
3763edf8e2afSMika Westerberg         }
3764edf8e2afSMika Westerberg     } else {
3765edf8e2afSMika Westerberg         if (dumpsize.rlim_cur <= pos) {
3766edf8e2afSMika Westerberg             return -1;
3767edf8e2afSMika Westerberg         } else if (dumpsize.rlim_cur == RLIM_INFINITY) {
3768edf8e2afSMika Westerberg             bytes_left = size;
3769edf8e2afSMika Westerberg         } else {
3770edf8e2afSMika Westerberg             size_t limit_left=dumpsize.rlim_cur - pos;
3771edf8e2afSMika Westerberg             bytes_left = limit_left >= size ? size : limit_left ;
3772edf8e2afSMika Westerberg         }
3773edf8e2afSMika Westerberg     }
3774edf8e2afSMika Westerberg 
3775edf8e2afSMika Westerberg     /*
3776edf8e2afSMika Westerberg      * In normal conditions, single write(2) should do but
3777edf8e2afSMika Westerberg      * in case of socket etc. this mechanism is more portable.
3778edf8e2afSMika Westerberg      */
3779edf8e2afSMika Westerberg     do {
3780edf8e2afSMika Westerberg         bytes_written = write(fd, bufp, bytes_left);
3781edf8e2afSMika Westerberg         if (bytes_written < 0) {
3782edf8e2afSMika Westerberg             if (errno == EINTR)
3783edf8e2afSMika Westerberg                 continue;
3784edf8e2afSMika Westerberg             return (-1);
3785edf8e2afSMika Westerberg         } else if (bytes_written == 0) { /* eof */
3786edf8e2afSMika Westerberg             return (-1);
3787edf8e2afSMika Westerberg         }
3788edf8e2afSMika Westerberg         bufp += bytes_written;
3789edf8e2afSMika Westerberg         bytes_left -= bytes_written;
3790edf8e2afSMika Westerberg     } while (bytes_left > 0);
3791edf8e2afSMika Westerberg 
3792edf8e2afSMika Westerberg     return (0);
3793edf8e2afSMika Westerberg }
3794edf8e2afSMika Westerberg 
3795edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd)
3796edf8e2afSMika Westerberg {
3797edf8e2afSMika Westerberg     struct elf_note en;
3798edf8e2afSMika Westerberg 
3799edf8e2afSMika Westerberg     en.n_namesz = men->namesz;
3800edf8e2afSMika Westerberg     en.n_type = men->type;
3801edf8e2afSMika Westerberg     en.n_descsz = men->datasz;
3802edf8e2afSMika Westerberg 
3803edf8e2afSMika Westerberg     bswap_note(&en);
3804edf8e2afSMika Westerberg 
3805edf8e2afSMika Westerberg     if (dump_write(fd, &en, sizeof(en)) != 0)
3806edf8e2afSMika Westerberg         return (-1);
3807edf8e2afSMika Westerberg     if (dump_write(fd, men->name, men->namesz_rounded) != 0)
3808edf8e2afSMika Westerberg         return (-1);
380980f5ce75SLaurent Vivier     if (dump_write(fd, men->data, men->datasz_rounded) != 0)
3810edf8e2afSMika Westerberg         return (-1);
3811edf8e2afSMika Westerberg 
3812edf8e2afSMika Westerberg     return (0);
3813edf8e2afSMika Westerberg }
3814edf8e2afSMika Westerberg 
38159349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env)
3816edf8e2afSMika Westerberg {
381729a0af61SRichard Henderson     CPUState *cpu = env_cpu((CPUArchState *)env);
38180429a971SAndreas Färber     TaskState *ts = (TaskState *)cpu->opaque;
3819edf8e2afSMika Westerberg     struct elf_thread_status *ets;
3820edf8e2afSMika Westerberg 
38217267c094SAnthony Liguori     ets = g_malloc0(sizeof (*ets));
3822edf8e2afSMika Westerberg     ets->num_notes = 1; /* only prstatus is dumped */
3823edf8e2afSMika Westerberg     fill_prstatus(&ets->prstatus, ts, 0);
3824edf8e2afSMika Westerberg     elf_core_copy_regs(&ets->prstatus.pr_reg, env);
3825edf8e2afSMika Westerberg     fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus),
3826edf8e2afSMika Westerberg               &ets->prstatus);
3827edf8e2afSMika Westerberg 
382872cf2d4fSBlue Swirl     QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link);
3829edf8e2afSMika Westerberg 
3830edf8e2afSMika Westerberg     info->notes_size += note_size(&ets->notes[0]);
3831edf8e2afSMika Westerberg }
3832edf8e2afSMika Westerberg 
38336afafa86SPeter Maydell static void init_note_info(struct elf_note_info *info)
38346afafa86SPeter Maydell {
38356afafa86SPeter Maydell     /* Initialize the elf_note_info structure so that it is at
38366afafa86SPeter Maydell      * least safe to call free_note_info() on it. Must be
38376afafa86SPeter Maydell      * called before calling fill_note_info().
38386afafa86SPeter Maydell      */
38396afafa86SPeter Maydell     memset(info, 0, sizeof (*info));
38406afafa86SPeter Maydell     QTAILQ_INIT(&info->thread_list);
38416afafa86SPeter Maydell }
38426afafa86SPeter Maydell 
3843edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info,
38449349b4f9SAndreas Färber                           long signr, const CPUArchState *env)
3845edf8e2afSMika Westerberg {
3846edf8e2afSMika Westerberg #define NUMNOTES 3
384729a0af61SRichard Henderson     CPUState *cpu = env_cpu((CPUArchState *)env);
38480429a971SAndreas Färber     TaskState *ts = (TaskState *)cpu->opaque;
3849edf8e2afSMika Westerberg     int i;
3850edf8e2afSMika Westerberg 
3851c78d65e8SMarkus Armbruster     info->notes = g_new0(struct memelfnote, NUMNOTES);
3852edf8e2afSMika Westerberg     if (info->notes == NULL)
3853edf8e2afSMika Westerberg         return (-ENOMEM);
38547267c094SAnthony Liguori     info->prstatus = g_malloc0(sizeof (*info->prstatus));
3855edf8e2afSMika Westerberg     if (info->prstatus == NULL)
3856edf8e2afSMika Westerberg         return (-ENOMEM);
38577267c094SAnthony Liguori     info->psinfo = g_malloc0(sizeof (*info->psinfo));
3858edf8e2afSMika Westerberg     if (info->prstatus == NULL)
3859edf8e2afSMika Westerberg         return (-ENOMEM);
3860edf8e2afSMika Westerberg 
3861edf8e2afSMika Westerberg     /*
3862edf8e2afSMika Westerberg      * First fill in status (and registers) of current thread
3863edf8e2afSMika Westerberg      * including process info & aux vector.
3864edf8e2afSMika Westerberg      */
3865edf8e2afSMika Westerberg     fill_prstatus(info->prstatus, ts, signr);
3866edf8e2afSMika Westerberg     elf_core_copy_regs(&info->prstatus->pr_reg, env);
3867edf8e2afSMika Westerberg     fill_note(&info->notes[0], "CORE", NT_PRSTATUS,
3868edf8e2afSMika Westerberg               sizeof (*info->prstatus), info->prstatus);
3869edf8e2afSMika Westerberg     fill_psinfo(info->psinfo, ts);
3870edf8e2afSMika Westerberg     fill_note(&info->notes[1], "CORE", NT_PRPSINFO,
3871edf8e2afSMika Westerberg               sizeof (*info->psinfo), info->psinfo);
3872edf8e2afSMika Westerberg     fill_auxv_note(&info->notes[2], ts);
3873edf8e2afSMika Westerberg     info->numnote = 3;
3874edf8e2afSMika Westerberg 
3875edf8e2afSMika Westerberg     info->notes_size = 0;
3876edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
3877edf8e2afSMika Westerberg         info->notes_size += note_size(&info->notes[i]);
3878edf8e2afSMika Westerberg 
3879edf8e2afSMika Westerberg     /* read and fill status of all threads */
3880edf8e2afSMika Westerberg     cpu_list_lock();
3881bdc44640SAndreas Färber     CPU_FOREACH(cpu) {
3882a2247f8eSAndreas Färber         if (cpu == thread_cpu) {
3883edf8e2afSMika Westerberg             continue;
3884182735efSAndreas Färber         }
3885182735efSAndreas Färber         fill_thread_info(info, (CPUArchState *)cpu->env_ptr);
3886edf8e2afSMika Westerberg     }
3887edf8e2afSMika Westerberg     cpu_list_unlock();
3888edf8e2afSMika Westerberg 
3889edf8e2afSMika Westerberg     return (0);
3890edf8e2afSMika Westerberg }
3891edf8e2afSMika Westerberg 
3892edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info)
3893edf8e2afSMika Westerberg {
3894edf8e2afSMika Westerberg     struct elf_thread_status *ets;
3895edf8e2afSMika Westerberg 
389672cf2d4fSBlue Swirl     while (!QTAILQ_EMPTY(&info->thread_list)) {
389772cf2d4fSBlue Swirl         ets = QTAILQ_FIRST(&info->thread_list);
389872cf2d4fSBlue Swirl         QTAILQ_REMOVE(&info->thread_list, ets, ets_link);
38997267c094SAnthony Liguori         g_free(ets);
3900edf8e2afSMika Westerberg     }
3901edf8e2afSMika Westerberg 
39027267c094SAnthony Liguori     g_free(info->prstatus);
39037267c094SAnthony Liguori     g_free(info->psinfo);
39047267c094SAnthony Liguori     g_free(info->notes);
3905edf8e2afSMika Westerberg }
3906edf8e2afSMika Westerberg 
3907edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd)
3908edf8e2afSMika Westerberg {
3909edf8e2afSMika Westerberg     struct elf_thread_status *ets;
3910edf8e2afSMika Westerberg     int i, error = 0;
3911edf8e2afSMika Westerberg 
3912edf8e2afSMika Westerberg     /* write prstatus, psinfo and auxv for current thread */
3913edf8e2afSMika Westerberg     for (i = 0; i < info->numnote; i++)
3914edf8e2afSMika Westerberg         if ((error = write_note(&info->notes[i], fd)) != 0)
3915edf8e2afSMika Westerberg             return (error);
3916edf8e2afSMika Westerberg 
3917edf8e2afSMika Westerberg     /* write prstatus for each thread */
391852a53afeSEmilio G. Cota     QTAILQ_FOREACH(ets, &info->thread_list, ets_link) {
3919edf8e2afSMika Westerberg         if ((error = write_note(&ets->notes[0], fd)) != 0)
3920edf8e2afSMika Westerberg             return (error);
3921edf8e2afSMika Westerberg     }
3922edf8e2afSMika Westerberg 
3923edf8e2afSMika Westerberg     return (0);
3924edf8e2afSMika Westerberg }
3925edf8e2afSMika Westerberg 
3926edf8e2afSMika Westerberg /*
3927edf8e2afSMika Westerberg  * Write out ELF coredump.
3928edf8e2afSMika Westerberg  *
3929edf8e2afSMika Westerberg  * See documentation of ELF object file format in:
3930edf8e2afSMika Westerberg  * http://www.caldera.com/developers/devspecs/gabi41.pdf
3931edf8e2afSMika Westerberg  *
3932edf8e2afSMika Westerberg  * Coredump format in linux is following:
3933edf8e2afSMika Westerberg  *
3934edf8e2afSMika Westerberg  * 0   +----------------------+         \
3935edf8e2afSMika Westerberg  *     | ELF header           | ET_CORE  |
3936edf8e2afSMika Westerberg  *     +----------------------+          |
3937edf8e2afSMika Westerberg  *     | ELF program headers  |          |--- headers
3938edf8e2afSMika Westerberg  *     | - NOTE section       |          |
3939edf8e2afSMika Westerberg  *     | - PT_LOAD sections   |          |
3940edf8e2afSMika Westerberg  *     +----------------------+         /
3941edf8e2afSMika Westerberg  *     | NOTEs:               |
3942edf8e2afSMika Westerberg  *     | - NT_PRSTATUS        |
3943edf8e2afSMika Westerberg  *     | - NT_PRSINFO         |
3944edf8e2afSMika Westerberg  *     | - NT_AUXV            |
3945edf8e2afSMika Westerberg  *     +----------------------+ <-- aligned to target page
3946edf8e2afSMika Westerberg  *     | Process memory dump  |
3947edf8e2afSMika Westerberg  *     :                      :
3948edf8e2afSMika Westerberg  *     .                      .
3949edf8e2afSMika Westerberg  *     :                      :
3950edf8e2afSMika Westerberg  *     |                      |
3951edf8e2afSMika Westerberg  *     +----------------------+
3952edf8e2afSMika Westerberg  *
3953edf8e2afSMika Westerberg  * NT_PRSTATUS -> struct elf_prstatus (per thread)
3954edf8e2afSMika Westerberg  * NT_PRSINFO  -> struct elf_prpsinfo
3955edf8e2afSMika Westerberg  * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()).
3956edf8e2afSMika Westerberg  *
3957edf8e2afSMika Westerberg  * Format follows System V format as close as possible.  Current
3958edf8e2afSMika Westerberg  * version limitations are as follows:
3959edf8e2afSMika Westerberg  *     - no floating point registers are dumped
3960edf8e2afSMika Westerberg  *
3961edf8e2afSMika Westerberg  * Function returns 0 in case of success, negative errno otherwise.
3962edf8e2afSMika Westerberg  *
3963edf8e2afSMika Westerberg  * TODO: make this work also during runtime: it should be
3964edf8e2afSMika Westerberg  * possible to force coredump from running process and then
3965edf8e2afSMika Westerberg  * continue processing.  For example qemu could set up SIGUSR2
3966edf8e2afSMika Westerberg  * handler (provided that target process haven't registered
3967edf8e2afSMika Westerberg  * handler for that) that does the dump when signal is received.
3968edf8e2afSMika Westerberg  */
39699349b4f9SAndreas Färber static int elf_core_dump(int signr, const CPUArchState *env)
3970edf8e2afSMika Westerberg {
397129a0af61SRichard Henderson     const CPUState *cpu = env_cpu((CPUArchState *)env);
39720429a971SAndreas Färber     const TaskState *ts = (const TaskState *)cpu->opaque;
3973edf8e2afSMika Westerberg     struct vm_area_struct *vma = NULL;
397468af19adSDaniel P. Berrangé     g_autofree char *corefile = NULL;
3975edf8e2afSMika Westerberg     struct elf_note_info info;
3976edf8e2afSMika Westerberg     struct elfhdr elf;
3977edf8e2afSMika Westerberg     struct elf_phdr phdr;
3978edf8e2afSMika Westerberg     struct rlimit dumpsize;
3979edf8e2afSMika Westerberg     struct mm_struct *mm = NULL;
3980edf8e2afSMika Westerberg     off_t offset = 0, data_offset = 0;
3981edf8e2afSMika Westerberg     int segs = 0;
3982edf8e2afSMika Westerberg     int fd = -1;
3983edf8e2afSMika Westerberg 
39846afafa86SPeter Maydell     init_note_info(&info);
39856afafa86SPeter Maydell 
3986edf8e2afSMika Westerberg     errno = 0;
3987edf8e2afSMika Westerberg     getrlimit(RLIMIT_CORE, &dumpsize);
3988edf8e2afSMika Westerberg     if (dumpsize.rlim_cur == 0)
3989edf8e2afSMika Westerberg         return 0;
3990edf8e2afSMika Westerberg 
399168af19adSDaniel P. Berrangé     corefile = core_dump_filename(ts);
3992edf8e2afSMika Westerberg 
3993edf8e2afSMika Westerberg     if ((fd = open(corefile, O_WRONLY | O_CREAT,
3994edf8e2afSMika Westerberg                    S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0)
3995edf8e2afSMika Westerberg         return (-errno);
3996edf8e2afSMika Westerberg 
3997edf8e2afSMika Westerberg     /*
3998edf8e2afSMika Westerberg      * Walk through target process memory mappings and
3999edf8e2afSMika Westerberg      * set up structure containing this information.  After
4000edf8e2afSMika Westerberg      * this point vma_xxx functions can be used.
4001edf8e2afSMika Westerberg      */
4002edf8e2afSMika Westerberg     if ((mm = vma_init()) == NULL)
4003edf8e2afSMika Westerberg         goto out;
4004edf8e2afSMika Westerberg 
4005edf8e2afSMika Westerberg     walk_memory_regions(mm, vma_walker);
4006edf8e2afSMika Westerberg     segs = vma_get_mapping_count(mm);
4007edf8e2afSMika Westerberg 
4008edf8e2afSMika Westerberg     /*
4009edf8e2afSMika Westerberg      * Construct valid coredump ELF header.  We also
4010edf8e2afSMika Westerberg      * add one more segment for notes.
4011edf8e2afSMika Westerberg      */
4012edf8e2afSMika Westerberg     fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0);
4013edf8e2afSMika Westerberg     if (dump_write(fd, &elf, sizeof (elf)) != 0)
4014edf8e2afSMika Westerberg         goto out;
4015edf8e2afSMika Westerberg 
4016b6af0975SDaniel P. Berrange     /* fill in the in-memory version of notes */
4017edf8e2afSMika Westerberg     if (fill_note_info(&info, signr, env) < 0)
4018edf8e2afSMika Westerberg         goto out;
4019edf8e2afSMika Westerberg 
4020edf8e2afSMika Westerberg     offset += sizeof (elf);                             /* elf header */
4021edf8e2afSMika Westerberg     offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */
4022edf8e2afSMika Westerberg 
4023edf8e2afSMika Westerberg     /* write out notes program header */
4024edf8e2afSMika Westerberg     fill_elf_note_phdr(&phdr, info.notes_size, offset);
4025edf8e2afSMika Westerberg 
4026edf8e2afSMika Westerberg     offset += info.notes_size;
4027edf8e2afSMika Westerberg     if (dump_write(fd, &phdr, sizeof (phdr)) != 0)
4028edf8e2afSMika Westerberg         goto out;
4029edf8e2afSMika Westerberg 
4030edf8e2afSMika Westerberg     /*
4031edf8e2afSMika Westerberg      * ELF specification wants data to start at page boundary so
4032edf8e2afSMika Westerberg      * we align it here.
4033edf8e2afSMika Westerberg      */
403480f5ce75SLaurent Vivier     data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE);
4035edf8e2afSMika Westerberg 
4036edf8e2afSMika Westerberg     /*
4037edf8e2afSMika Westerberg      * Write program headers for memory regions mapped in
4038edf8e2afSMika Westerberg      * the target process.
4039edf8e2afSMika Westerberg      */
4040edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
4041edf8e2afSMika Westerberg         (void) memset(&phdr, 0, sizeof (phdr));
4042edf8e2afSMika Westerberg 
4043edf8e2afSMika Westerberg         phdr.p_type = PT_LOAD;
4044edf8e2afSMika Westerberg         phdr.p_offset = offset;
4045edf8e2afSMika Westerberg         phdr.p_vaddr = vma->vma_start;
4046edf8e2afSMika Westerberg         phdr.p_paddr = 0;
4047edf8e2afSMika Westerberg         phdr.p_filesz = vma_dump_size(vma);
4048edf8e2afSMika Westerberg         offset += phdr.p_filesz;
4049edf8e2afSMika Westerberg         phdr.p_memsz = vma->vma_end - vma->vma_start;
4050edf8e2afSMika Westerberg         phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0;
4051edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_WRITE)
4052edf8e2afSMika Westerberg             phdr.p_flags |= PF_W;
4053edf8e2afSMika Westerberg         if (vma->vma_flags & PROT_EXEC)
4054edf8e2afSMika Westerberg             phdr.p_flags |= PF_X;
4055edf8e2afSMika Westerberg         phdr.p_align = ELF_EXEC_PAGESIZE;
4056edf8e2afSMika Westerberg 
405780f5ce75SLaurent Vivier         bswap_phdr(&phdr, 1);
4058772034b6SPeter Maydell         if (dump_write(fd, &phdr, sizeof(phdr)) != 0) {
4059772034b6SPeter Maydell             goto out;
4060772034b6SPeter Maydell         }
4061edf8e2afSMika Westerberg     }
4062edf8e2afSMika Westerberg 
4063edf8e2afSMika Westerberg     /*
4064edf8e2afSMika Westerberg      * Next we write notes just after program headers.  No
4065edf8e2afSMika Westerberg      * alignment needed here.
4066edf8e2afSMika Westerberg      */
4067edf8e2afSMika Westerberg     if (write_note_info(&info, fd) < 0)
4068edf8e2afSMika Westerberg         goto out;
4069edf8e2afSMika Westerberg 
4070edf8e2afSMika Westerberg     /* align data to page boundary */
4071edf8e2afSMika Westerberg     if (lseek(fd, data_offset, SEEK_SET) != data_offset)
4072edf8e2afSMika Westerberg         goto out;
4073edf8e2afSMika Westerberg 
4074edf8e2afSMika Westerberg     /*
4075edf8e2afSMika Westerberg      * Finally we can dump process memory into corefile as well.
4076edf8e2afSMika Westerberg      */
4077edf8e2afSMika Westerberg     for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) {
4078edf8e2afSMika Westerberg         abi_ulong addr;
4079edf8e2afSMika Westerberg         abi_ulong end;
4080edf8e2afSMika Westerberg 
4081edf8e2afSMika Westerberg         end = vma->vma_start + vma_dump_size(vma);
4082edf8e2afSMika Westerberg 
4083edf8e2afSMika Westerberg         for (addr = vma->vma_start; addr < end;
4084edf8e2afSMika Westerberg              addr += TARGET_PAGE_SIZE) {
4085edf8e2afSMika Westerberg             char page[TARGET_PAGE_SIZE];
4086edf8e2afSMika Westerberg             int error;
4087edf8e2afSMika Westerberg 
4088edf8e2afSMika Westerberg             /*
4089edf8e2afSMika Westerberg              *  Read in page from target process memory and
4090edf8e2afSMika Westerberg              *  write it to coredump file.
4091edf8e2afSMika Westerberg              */
4092edf8e2afSMika Westerberg             error = copy_from_user(page, addr, sizeof (page));
4093edf8e2afSMika Westerberg             if (error != 0) {
409449995e17SAurelien Jarno                 (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n",
4095edf8e2afSMika Westerberg                                addr);
4096edf8e2afSMika Westerberg                 errno = -error;
4097edf8e2afSMika Westerberg                 goto out;
4098edf8e2afSMika Westerberg             }
4099edf8e2afSMika Westerberg             if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0)
4100edf8e2afSMika Westerberg                 goto out;
4101edf8e2afSMika Westerberg         }
4102edf8e2afSMika Westerberg     }
4103edf8e2afSMika Westerberg 
4104edf8e2afSMika Westerberg  out:
4105edf8e2afSMika Westerberg     free_note_info(&info);
4106edf8e2afSMika Westerberg     if (mm != NULL)
4107edf8e2afSMika Westerberg         vma_delete(mm);
4108edf8e2afSMika Westerberg     (void) close(fd);
4109edf8e2afSMika Westerberg 
4110edf8e2afSMika Westerberg     if (errno != 0)
4111edf8e2afSMika Westerberg         return (-errno);
4112edf8e2afSMika Westerberg     return (0);
4113edf8e2afSMika Westerberg }
4114edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */
4115edf8e2afSMika Westerberg 
4116e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
4117e5fe0c52Spbrook {
4118e5fe0c52Spbrook     init_thread(regs, infop);
4119e5fe0c52Spbrook }
4120