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(¬e, bprm_buf + phdr->p_offset, n); 257483f990ebSRichard Henderson } else { 257583f990ebSRichard Henderson ssize_t len = pread(image_fd, ¬e, 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