131e31b8aSbellard /* This is the Linux kernel elf-loading code, ported into user space */ 2d39594e9SPeter Maydell #include "qemu/osdep.h" 3edf8e2afSMika Westerberg #include <sys/param.h> 431e31b8aSbellard 5edf8e2afSMika Westerberg #include <sys/resource.h> 630ab9ef2SRichard Henderson #include <sys/shm.h> 731e31b8aSbellard 83ef693a0Sbellard #include "qemu.h" 976cad711SPaolo Bonzini #include "disas/disas.h" 10f348b6d1SVeronia Bahaa #include "qemu/path.h" 11dc5e9ac7SMarkus Armbruster #include "qemu/queue.h" 12c6a2377fSRichard Henderson #include "qemu/guest-random.h" 136fd59449SRichard Henderson #include "qemu/units.h" 14*ee947430SAlex Bennée #include "qemu/selfmap.h" 1531e31b8aSbellard 16e58ffeb3Smalc #ifdef _ARCH_PPC64 17a6cc84f4Smalc #undef ARCH_DLINFO 18a6cc84f4Smalc #undef ELF_PLATFORM 19a6cc84f4Smalc #undef ELF_HWCAP 20ad6919dcSPeter Maydell #undef ELF_HWCAP2 21a6cc84f4Smalc #undef ELF_CLASS 22a6cc84f4Smalc #undef ELF_DATA 23a6cc84f4Smalc #undef ELF_ARCH 24a6cc84f4Smalc #endif 25a6cc84f4Smalc 26edf8e2afSMika Westerberg #define ELF_OSABI ELFOSABI_SYSV 27edf8e2afSMika Westerberg 28cb33da57Sblueswir1 /* from personality.h */ 29cb33da57Sblueswir1 30cb33da57Sblueswir1 /* 31cb33da57Sblueswir1 * Flags for bug emulation. 32cb33da57Sblueswir1 * 33cb33da57Sblueswir1 * These occupy the top three bytes. 34cb33da57Sblueswir1 */ 35cb33da57Sblueswir1 enum { 36cb33da57Sblueswir1 ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */ 37d97ef72eSRichard Henderson FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to 38d97ef72eSRichard Henderson descriptors (signal handling) */ 39cb33da57Sblueswir1 MMAP_PAGE_ZERO = 0x0100000, 40cb33da57Sblueswir1 ADDR_COMPAT_LAYOUT = 0x0200000, 41cb33da57Sblueswir1 READ_IMPLIES_EXEC = 0x0400000, 42cb33da57Sblueswir1 ADDR_LIMIT_32BIT = 0x0800000, 43cb33da57Sblueswir1 SHORT_INODE = 0x1000000, 44cb33da57Sblueswir1 WHOLE_SECONDS = 0x2000000, 45cb33da57Sblueswir1 STICKY_TIMEOUTS = 0x4000000, 46cb33da57Sblueswir1 ADDR_LIMIT_3GB = 0x8000000, 47cb33da57Sblueswir1 }; 48cb33da57Sblueswir1 49cb33da57Sblueswir1 /* 50cb33da57Sblueswir1 * Personality types. 51cb33da57Sblueswir1 * 52cb33da57Sblueswir1 * These go in the low byte. Avoid using the top bit, it will 53cb33da57Sblueswir1 * conflict with error returns. 54cb33da57Sblueswir1 */ 55cb33da57Sblueswir1 enum { 56cb33da57Sblueswir1 PER_LINUX = 0x0000, 57cb33da57Sblueswir1 PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, 58cb33da57Sblueswir1 PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS, 59cb33da57Sblueswir1 PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 60cb33da57Sblueswir1 PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, 61d97ef72eSRichard Henderson PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE, 62cb33da57Sblueswir1 PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, 63cb33da57Sblueswir1 PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, 64cb33da57Sblueswir1 PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, 65cb33da57Sblueswir1 PER_BSD = 0x0006, 66cb33da57Sblueswir1 PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, 67cb33da57Sblueswir1 PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, 68cb33da57Sblueswir1 PER_LINUX32 = 0x0008, 69cb33da57Sblueswir1 PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB, 70cb33da57Sblueswir1 PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */ 71cb33da57Sblueswir1 PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */ 72cb33da57Sblueswir1 PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */ 73cb33da57Sblueswir1 PER_RISCOS = 0x000c, 74cb33da57Sblueswir1 PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, 75cb33da57Sblueswir1 PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 76cb33da57Sblueswir1 PER_OSF4 = 0x000f, /* OSF/1 v4 */ 77cb33da57Sblueswir1 PER_HPUX = 0x0010, 78cb33da57Sblueswir1 PER_MASK = 0x00ff, 79cb33da57Sblueswir1 }; 80cb33da57Sblueswir1 81cb33da57Sblueswir1 /* 82cb33da57Sblueswir1 * Return the base personality without flags. 83cb33da57Sblueswir1 */ 84cb33da57Sblueswir1 #define personality(pers) (pers & PER_MASK) 85cb33da57Sblueswir1 863cb10cfaSChristophe Lyon int info_is_fdpic(struct image_info *info) 873cb10cfaSChristophe Lyon { 883cb10cfaSChristophe Lyon return info->personality == PER_LINUX_FDPIC; 893cb10cfaSChristophe Lyon } 903cb10cfaSChristophe Lyon 9183fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */ 9283fb7adfSbellard #ifndef MAP_DENYWRITE 9383fb7adfSbellard #define MAP_DENYWRITE 0 9483fb7adfSbellard #endif 9583fb7adfSbellard 9683fb7adfSbellard /* should probably go in elf.h */ 9783fb7adfSbellard #ifndef ELIBBAD 9883fb7adfSbellard #define ELIBBAD 80 9983fb7adfSbellard #endif 10083fb7adfSbellard 10128490231SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN 10228490231SRichard Henderson #define ELF_DATA ELFDATA2MSB 10328490231SRichard Henderson #else 10428490231SRichard Henderson #define ELF_DATA ELFDATA2LSB 10528490231SRichard Henderson #endif 10628490231SRichard Henderson 107a29f998dSPaolo Bonzini #ifdef TARGET_ABI_MIPSN32 108918fc54cSPaolo Bonzini typedef abi_ullong target_elf_greg_t; 109918fc54cSPaolo Bonzini #define tswapreg(ptr) tswap64(ptr) 110a29f998dSPaolo Bonzini #else 111a29f998dSPaolo Bonzini typedef abi_ulong target_elf_greg_t; 112a29f998dSPaolo Bonzini #define tswapreg(ptr) tswapal(ptr) 113a29f998dSPaolo Bonzini #endif 114a29f998dSPaolo Bonzini 11521e807faSNathan Froyd #ifdef USE_UID16 1161ddd592fSPaolo Bonzini typedef abi_ushort target_uid_t; 1171ddd592fSPaolo Bonzini typedef abi_ushort target_gid_t; 11821e807faSNathan Froyd #else 119f8fd4fc4SPaolo Bonzini typedef abi_uint target_uid_t; 120f8fd4fc4SPaolo Bonzini typedef abi_uint target_gid_t; 12121e807faSNathan Froyd #endif 122f8fd4fc4SPaolo Bonzini typedef abi_int target_pid_t; 12321e807faSNathan Froyd 12430ac07d4Sbellard #ifdef TARGET_I386 12530ac07d4Sbellard 12615338fd7Sbellard #define ELF_PLATFORM get_elf_platform() 12715338fd7Sbellard 12815338fd7Sbellard static const char *get_elf_platform(void) 12915338fd7Sbellard { 13015338fd7Sbellard static char elf_platform[] = "i386"; 131a2247f8eSAndreas Färber int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); 13215338fd7Sbellard if (family > 6) 13315338fd7Sbellard family = 6; 13415338fd7Sbellard if (family >= 3) 13515338fd7Sbellard elf_platform[1] = '0' + family; 13615338fd7Sbellard return elf_platform; 13715338fd7Sbellard } 13815338fd7Sbellard 13915338fd7Sbellard #define ELF_HWCAP get_elf_hwcap() 14015338fd7Sbellard 14115338fd7Sbellard static uint32_t get_elf_hwcap(void) 14215338fd7Sbellard { 143a2247f8eSAndreas Färber X86CPU *cpu = X86_CPU(thread_cpu); 144a2247f8eSAndreas Färber 145a2247f8eSAndreas Färber return cpu->env.features[FEAT_1_EDX]; 14615338fd7Sbellard } 14715338fd7Sbellard 14884409ddbSj_mayer #ifdef TARGET_X86_64 14984409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL 15084409ddbSj_mayer 15184409ddbSj_mayer #define ELF_CLASS ELFCLASS64 15284409ddbSj_mayer #define ELF_ARCH EM_X86_64 15384409ddbSj_mayer 15484409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 15584409ddbSj_mayer { 15684409ddbSj_mayer regs->rax = 0; 15784409ddbSj_mayer regs->rsp = infop->start_stack; 15884409ddbSj_mayer regs->rip = infop->entry; 15984409ddbSj_mayer } 16084409ddbSj_mayer 1619edc5d79SMika Westerberg #define ELF_NREG 27 162c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1639edc5d79SMika Westerberg 1649edc5d79SMika Westerberg /* 1659edc5d79SMika Westerberg * Note that ELF_NREG should be 29 as there should be place for 1669edc5d79SMika Westerberg * TRAPNO and ERR "registers" as well but linux doesn't dump 1679edc5d79SMika Westerberg * those. 1689edc5d79SMika Westerberg * 1699edc5d79SMika Westerberg * See linux kernel: arch/x86/include/asm/elf.h 1709edc5d79SMika Westerberg */ 17105390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) 1729edc5d79SMika Westerberg { 1739edc5d79SMika Westerberg (*regs)[0] = env->regs[15]; 1749edc5d79SMika Westerberg (*regs)[1] = env->regs[14]; 1759edc5d79SMika Westerberg (*regs)[2] = env->regs[13]; 1769edc5d79SMika Westerberg (*regs)[3] = env->regs[12]; 1779edc5d79SMika Westerberg (*regs)[4] = env->regs[R_EBP]; 1789edc5d79SMika Westerberg (*regs)[5] = env->regs[R_EBX]; 1799edc5d79SMika Westerberg (*regs)[6] = env->regs[11]; 1809edc5d79SMika Westerberg (*regs)[7] = env->regs[10]; 1819edc5d79SMika Westerberg (*regs)[8] = env->regs[9]; 1829edc5d79SMika Westerberg (*regs)[9] = env->regs[8]; 1839edc5d79SMika Westerberg (*regs)[10] = env->regs[R_EAX]; 1849edc5d79SMika Westerberg (*regs)[11] = env->regs[R_ECX]; 1859edc5d79SMika Westerberg (*regs)[12] = env->regs[R_EDX]; 1869edc5d79SMika Westerberg (*regs)[13] = env->regs[R_ESI]; 1879edc5d79SMika Westerberg (*regs)[14] = env->regs[R_EDI]; 1889edc5d79SMika Westerberg (*regs)[15] = env->regs[R_EAX]; /* XXX */ 1899edc5d79SMika Westerberg (*regs)[16] = env->eip; 1909edc5d79SMika Westerberg (*regs)[17] = env->segs[R_CS].selector & 0xffff; 1919edc5d79SMika Westerberg (*regs)[18] = env->eflags; 1929edc5d79SMika Westerberg (*regs)[19] = env->regs[R_ESP]; 1939edc5d79SMika Westerberg (*regs)[20] = env->segs[R_SS].selector & 0xffff; 1949edc5d79SMika Westerberg (*regs)[21] = env->segs[R_FS].selector & 0xffff; 1959edc5d79SMika Westerberg (*regs)[22] = env->segs[R_GS].selector & 0xffff; 1969edc5d79SMika Westerberg (*regs)[23] = env->segs[R_DS].selector & 0xffff; 1979edc5d79SMika Westerberg (*regs)[24] = env->segs[R_ES].selector & 0xffff; 1989edc5d79SMika Westerberg (*regs)[25] = env->segs[R_FS].selector & 0xffff; 1999edc5d79SMika Westerberg (*regs)[26] = env->segs[R_GS].selector & 0xffff; 2009edc5d79SMika Westerberg } 2019edc5d79SMika Westerberg 20284409ddbSj_mayer #else 20384409ddbSj_mayer 20430ac07d4Sbellard #define ELF_START_MMAP 0x80000000 20530ac07d4Sbellard 20630ac07d4Sbellard /* 20730ac07d4Sbellard * This is used to ensure we don't load something for the wrong architecture. 20830ac07d4Sbellard */ 20930ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) 21030ac07d4Sbellard 21130ac07d4Sbellard /* 21230ac07d4Sbellard * These are used to set parameters in the core dumps. 21330ac07d4Sbellard */ 21430ac07d4Sbellard #define ELF_CLASS ELFCLASS32 21530ac07d4Sbellard #define ELF_ARCH EM_386 21630ac07d4Sbellard 217d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 218d97ef72eSRichard Henderson struct image_info *infop) 219e5fe0c52Spbrook { 220e5fe0c52Spbrook regs->esp = infop->start_stack; 221e5fe0c52Spbrook regs->eip = infop->entry; 222e5fe0c52Spbrook 22330ac07d4Sbellard /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program 22430ac07d4Sbellard starts %edx contains a pointer to a function which might be 22530ac07d4Sbellard registered using `atexit'. This provides a mean for the 22630ac07d4Sbellard dynamic linker to call DT_FINI functions for shared libraries 22730ac07d4Sbellard that have been loaded before the code runs. 22830ac07d4Sbellard 22930ac07d4Sbellard A value of 0 tells we have no such handler. */ 230e5fe0c52Spbrook regs->edx = 0; 231b346ff46Sbellard } 2329edc5d79SMika Westerberg 2339edc5d79SMika Westerberg #define ELF_NREG 17 234c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 2359edc5d79SMika Westerberg 2369edc5d79SMika Westerberg /* 2379edc5d79SMika Westerberg * Note that ELF_NREG should be 19 as there should be place for 2389edc5d79SMika Westerberg * TRAPNO and ERR "registers" as well but linux doesn't dump 2399edc5d79SMika Westerberg * those. 2409edc5d79SMika Westerberg * 2419edc5d79SMika Westerberg * See linux kernel: arch/x86/include/asm/elf.h 2429edc5d79SMika Westerberg */ 24305390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) 2449edc5d79SMika Westerberg { 2459edc5d79SMika Westerberg (*regs)[0] = env->regs[R_EBX]; 2469edc5d79SMika Westerberg (*regs)[1] = env->regs[R_ECX]; 2479edc5d79SMika Westerberg (*regs)[2] = env->regs[R_EDX]; 2489edc5d79SMika Westerberg (*regs)[3] = env->regs[R_ESI]; 2499edc5d79SMika Westerberg (*regs)[4] = env->regs[R_EDI]; 2509edc5d79SMika Westerberg (*regs)[5] = env->regs[R_EBP]; 2519edc5d79SMika Westerberg (*regs)[6] = env->regs[R_EAX]; 2529edc5d79SMika Westerberg (*regs)[7] = env->segs[R_DS].selector & 0xffff; 2539edc5d79SMika Westerberg (*regs)[8] = env->segs[R_ES].selector & 0xffff; 2549edc5d79SMika Westerberg (*regs)[9] = env->segs[R_FS].selector & 0xffff; 2559edc5d79SMika Westerberg (*regs)[10] = env->segs[R_GS].selector & 0xffff; 2569edc5d79SMika Westerberg (*regs)[11] = env->regs[R_EAX]; /* XXX */ 2579edc5d79SMika Westerberg (*regs)[12] = env->eip; 2589edc5d79SMika Westerberg (*regs)[13] = env->segs[R_CS].selector & 0xffff; 2599edc5d79SMika Westerberg (*regs)[14] = env->eflags; 2609edc5d79SMika Westerberg (*regs)[15] = env->regs[R_ESP]; 2619edc5d79SMika Westerberg (*regs)[16] = env->segs[R_SS].selector & 0xffff; 2629edc5d79SMika Westerberg } 26384409ddbSj_mayer #endif 264b346ff46Sbellard 2659edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP 266b346ff46Sbellard #define ELF_EXEC_PAGESIZE 4096 267b346ff46Sbellard 268b346ff46Sbellard #endif 269b346ff46Sbellard 270b346ff46Sbellard #ifdef TARGET_ARM 271b346ff46Sbellard 27224e76ff0SPeter Maydell #ifndef TARGET_AARCH64 27324e76ff0SPeter Maydell /* 32 bit ARM definitions */ 27424e76ff0SPeter Maydell 275b346ff46Sbellard #define ELF_START_MMAP 0x80000000 276b346ff46Sbellard 277b597c3f7SPeter Crosthwaite #define ELF_ARCH EM_ARM 278b346ff46Sbellard #define ELF_CLASS ELFCLASS32 279b346ff46Sbellard 280d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 281d97ef72eSRichard Henderson struct image_info *infop) 282b346ff46Sbellard { 283992f48a0Sblueswir1 abi_long stack = infop->start_stack; 284b346ff46Sbellard memset(regs, 0, sizeof(*regs)); 28599033caeSAlexander Graf 286167e4cdcSPeter Maydell regs->uregs[16] = ARM_CPU_MODE_USR; 287167e4cdcSPeter Maydell if (infop->entry & 1) { 288167e4cdcSPeter Maydell regs->uregs[16] |= CPSR_T; 289167e4cdcSPeter Maydell } 290167e4cdcSPeter Maydell regs->uregs[15] = infop->entry & 0xfffffffe; 291167e4cdcSPeter Maydell regs->uregs[13] = infop->start_stack; 2922f619698Sbellard /* FIXME - what to for failure of get_user()? */ 293167e4cdcSPeter Maydell get_user_ual(regs->uregs[2], stack + 8); /* envp */ 294167e4cdcSPeter Maydell get_user_ual(regs->uregs[1], stack + 4); /* envp */ 295a1516e92Sbellard /* XXX: it seems that r0 is zeroed after ! */ 296167e4cdcSPeter Maydell regs->uregs[0] = 0; 297e5fe0c52Spbrook /* For uClinux PIC binaries. */ 298863cf0b7Sj_mayer /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ 299167e4cdcSPeter Maydell regs->uregs[10] = infop->start_data; 3003cb10cfaSChristophe Lyon 3013cb10cfaSChristophe Lyon /* Support ARM FDPIC. */ 3023cb10cfaSChristophe Lyon if (info_is_fdpic(infop)) { 3033cb10cfaSChristophe Lyon /* As described in the ABI document, r7 points to the loadmap info 3043cb10cfaSChristophe Lyon * prepared by the kernel. If an interpreter is needed, r8 points 3053cb10cfaSChristophe Lyon * to the interpreter loadmap and r9 points to the interpreter 3063cb10cfaSChristophe Lyon * PT_DYNAMIC info. If no interpreter is needed, r8 is zero, and 3073cb10cfaSChristophe Lyon * r9 points to the main program PT_DYNAMIC info. 3083cb10cfaSChristophe Lyon */ 3093cb10cfaSChristophe Lyon regs->uregs[7] = infop->loadmap_addr; 3103cb10cfaSChristophe Lyon if (infop->interpreter_loadmap_addr) { 3113cb10cfaSChristophe Lyon /* Executable is dynamically loaded. */ 3123cb10cfaSChristophe Lyon regs->uregs[8] = infop->interpreter_loadmap_addr; 3133cb10cfaSChristophe Lyon regs->uregs[9] = infop->interpreter_pt_dynamic_addr; 3143cb10cfaSChristophe Lyon } else { 3153cb10cfaSChristophe Lyon regs->uregs[8] = 0; 3163cb10cfaSChristophe Lyon regs->uregs[9] = infop->pt_dynamic_addr; 3173cb10cfaSChristophe Lyon } 3183cb10cfaSChristophe Lyon } 319b346ff46Sbellard } 320b346ff46Sbellard 321edf8e2afSMika Westerberg #define ELF_NREG 18 322c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 323edf8e2afSMika Westerberg 32405390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env) 325edf8e2afSMika Westerberg { 32686cd7b2dSPaolo Bonzini (*regs)[0] = tswapreg(env->regs[0]); 32786cd7b2dSPaolo Bonzini (*regs)[1] = tswapreg(env->regs[1]); 32886cd7b2dSPaolo Bonzini (*regs)[2] = tswapreg(env->regs[2]); 32986cd7b2dSPaolo Bonzini (*regs)[3] = tswapreg(env->regs[3]); 33086cd7b2dSPaolo Bonzini (*regs)[4] = tswapreg(env->regs[4]); 33186cd7b2dSPaolo Bonzini (*regs)[5] = tswapreg(env->regs[5]); 33286cd7b2dSPaolo Bonzini (*regs)[6] = tswapreg(env->regs[6]); 33386cd7b2dSPaolo Bonzini (*regs)[7] = tswapreg(env->regs[7]); 33486cd7b2dSPaolo Bonzini (*regs)[8] = tswapreg(env->regs[8]); 33586cd7b2dSPaolo Bonzini (*regs)[9] = tswapreg(env->regs[9]); 33686cd7b2dSPaolo Bonzini (*regs)[10] = tswapreg(env->regs[10]); 33786cd7b2dSPaolo Bonzini (*regs)[11] = tswapreg(env->regs[11]); 33886cd7b2dSPaolo Bonzini (*regs)[12] = tswapreg(env->regs[12]); 33986cd7b2dSPaolo Bonzini (*regs)[13] = tswapreg(env->regs[13]); 34086cd7b2dSPaolo Bonzini (*regs)[14] = tswapreg(env->regs[14]); 34186cd7b2dSPaolo Bonzini (*regs)[15] = tswapreg(env->regs[15]); 342edf8e2afSMika Westerberg 34386cd7b2dSPaolo Bonzini (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env)); 34486cd7b2dSPaolo Bonzini (*regs)[17] = tswapreg(env->regs[0]); /* XXX */ 345edf8e2afSMika Westerberg } 346edf8e2afSMika Westerberg 34730ac07d4Sbellard #define USE_ELF_CORE_DUMP 34830ac07d4Sbellard #define ELF_EXEC_PAGESIZE 4096 34930ac07d4Sbellard 350afce2927Sbellard enum 351afce2927Sbellard { 352afce2927Sbellard ARM_HWCAP_ARM_SWP = 1 << 0, 353afce2927Sbellard ARM_HWCAP_ARM_HALF = 1 << 1, 354afce2927Sbellard ARM_HWCAP_ARM_THUMB = 1 << 2, 355afce2927Sbellard ARM_HWCAP_ARM_26BIT = 1 << 3, 356afce2927Sbellard ARM_HWCAP_ARM_FAST_MULT = 1 << 4, 357afce2927Sbellard ARM_HWCAP_ARM_FPA = 1 << 5, 358afce2927Sbellard ARM_HWCAP_ARM_VFP = 1 << 6, 359afce2927Sbellard ARM_HWCAP_ARM_EDSP = 1 << 7, 360cf6de34aSRiku Voipio ARM_HWCAP_ARM_JAVA = 1 << 8, 361cf6de34aSRiku Voipio ARM_HWCAP_ARM_IWMMXT = 1 << 9, 36243ce393eSPeter Maydell ARM_HWCAP_ARM_CRUNCH = 1 << 10, 36343ce393eSPeter Maydell ARM_HWCAP_ARM_THUMBEE = 1 << 11, 36443ce393eSPeter Maydell ARM_HWCAP_ARM_NEON = 1 << 12, 36543ce393eSPeter Maydell ARM_HWCAP_ARM_VFPv3 = 1 << 13, 36643ce393eSPeter Maydell ARM_HWCAP_ARM_VFPv3D16 = 1 << 14, 36724682654SPeter Maydell ARM_HWCAP_ARM_TLS = 1 << 15, 36824682654SPeter Maydell ARM_HWCAP_ARM_VFPv4 = 1 << 16, 36924682654SPeter Maydell ARM_HWCAP_ARM_IDIVA = 1 << 17, 37024682654SPeter Maydell ARM_HWCAP_ARM_IDIVT = 1 << 18, 37124682654SPeter Maydell ARM_HWCAP_ARM_VFPD32 = 1 << 19, 37224682654SPeter Maydell ARM_HWCAP_ARM_LPAE = 1 << 20, 37324682654SPeter Maydell ARM_HWCAP_ARM_EVTSTRM = 1 << 21, 374afce2927Sbellard }; 375afce2927Sbellard 376ad6919dcSPeter Maydell enum { 377ad6919dcSPeter Maydell ARM_HWCAP2_ARM_AES = 1 << 0, 378ad6919dcSPeter Maydell ARM_HWCAP2_ARM_PMULL = 1 << 1, 379ad6919dcSPeter Maydell ARM_HWCAP2_ARM_SHA1 = 1 << 2, 380ad6919dcSPeter Maydell ARM_HWCAP2_ARM_SHA2 = 1 << 3, 381ad6919dcSPeter Maydell ARM_HWCAP2_ARM_CRC32 = 1 << 4, 382ad6919dcSPeter Maydell }; 383ad6919dcSPeter Maydell 3846b1275ffSPeter Maydell /* The commpage only exists for 32 bit kernels */ 3856b1275ffSPeter Maydell 386*ee947430SAlex Bennée #define ARM_COMMPAGE (intptr_t)0xffff0f00u 387*ee947430SAlex Bennée 388*ee947430SAlex Bennée static bool init_guest_commpage(void) 38997cc7560SDr. David Alan Gilbert { 390*ee947430SAlex Bennée void *want = g2h(ARM_COMMPAGE & -qemu_host_page_size); 391*ee947430SAlex Bennée void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, 392*ee947430SAlex Bennée MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 39397cc7560SDr. David Alan Gilbert 394*ee947430SAlex Bennée if (addr == MAP_FAILED) { 395*ee947430SAlex Bennée perror("Allocating guest commpage"); 396*ee947430SAlex Bennée exit(EXIT_FAILURE); 397*ee947430SAlex Bennée } 398*ee947430SAlex Bennée if (addr != want) { 399*ee947430SAlex Bennée return false; 400806d1021SMeador Inge } 401806d1021SMeador Inge 402*ee947430SAlex Bennée /* Set kernel helper versions; rest of page is 0. */ 403*ee947430SAlex Bennée __put_user(5, (uint32_t *)g2h(0xffff0ffcu)); 40497cc7560SDr. David Alan Gilbert 405*ee947430SAlex Bennée if (mprotect(addr, qemu_host_page_size, PROT_READ)) { 40697cc7560SDr. David Alan Gilbert perror("Protecting guest commpage"); 407*ee947430SAlex Bennée exit(EXIT_FAILURE); 40897cc7560SDr. David Alan Gilbert } 409*ee947430SAlex Bennée return true; 41097cc7560SDr. David Alan Gilbert } 411adf050b1SBenoit Canet 412adf050b1SBenoit Canet #define ELF_HWCAP get_elf_hwcap() 413ad6919dcSPeter Maydell #define ELF_HWCAP2 get_elf_hwcap2() 414adf050b1SBenoit Canet 415adf050b1SBenoit Canet static uint32_t get_elf_hwcap(void) 416adf050b1SBenoit Canet { 417a2247f8eSAndreas Färber ARMCPU *cpu = ARM_CPU(thread_cpu); 418adf050b1SBenoit Canet uint32_t hwcaps = 0; 419adf050b1SBenoit Canet 420adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_SWP; 421adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_HALF; 422adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_THUMB; 423adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_FAST_MULT; 424adf050b1SBenoit Canet 425adf050b1SBenoit Canet /* probe for the extra features */ 426adf050b1SBenoit Canet #define GET_FEATURE(feat, hwcap) \ 427a2247f8eSAndreas Färber do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) 428962fcbf2SRichard Henderson 429962fcbf2SRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \ 430962fcbf2SRichard Henderson do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) 431962fcbf2SRichard Henderson 43224682654SPeter Maydell /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */ 43324682654SPeter Maydell GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP); 434adf050b1SBenoit Canet GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT); 435adf050b1SBenoit Canet GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); 436adf050b1SBenoit Canet GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON); 43724682654SPeter Maydell GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS); 438bfa8a370SRichard Henderson GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE); 439873b73c0SPeter Maydell GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA); 440873b73c0SPeter Maydell GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT); 441bfa8a370SRichard Henderson GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP); 442bfa8a370SRichard Henderson 443bfa8a370SRichard Henderson if (cpu_isar_feature(aa32_fpsp_v3, cpu) || 444bfa8a370SRichard Henderson cpu_isar_feature(aa32_fpdp_v3, cpu)) { 445bfa8a370SRichard Henderson hwcaps |= ARM_HWCAP_ARM_VFPv3; 446bfa8a370SRichard Henderson if (cpu_isar_feature(aa32_simd_r32, cpu)) { 447bfa8a370SRichard Henderson hwcaps |= ARM_HWCAP_ARM_VFPD32; 448bfa8a370SRichard Henderson } else { 449bfa8a370SRichard Henderson hwcaps |= ARM_HWCAP_ARM_VFPv3D16; 450bfa8a370SRichard Henderson } 451bfa8a370SRichard Henderson } 452bfa8a370SRichard Henderson GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4); 453adf050b1SBenoit Canet 454adf050b1SBenoit Canet return hwcaps; 455adf050b1SBenoit Canet } 456afce2927Sbellard 457ad6919dcSPeter Maydell static uint32_t get_elf_hwcap2(void) 458ad6919dcSPeter Maydell { 459ad6919dcSPeter Maydell ARMCPU *cpu = ARM_CPU(thread_cpu); 460ad6919dcSPeter Maydell uint32_t hwcaps = 0; 461ad6919dcSPeter Maydell 462962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES); 463962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL); 464962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1); 465962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2); 466962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32); 467ad6919dcSPeter Maydell return hwcaps; 468ad6919dcSPeter Maydell } 469ad6919dcSPeter Maydell 470ad6919dcSPeter Maydell #undef GET_FEATURE 471962fcbf2SRichard Henderson #undef GET_FEATURE_ID 472ad6919dcSPeter Maydell 47313ec4ec3SRichard Henderson #define ELF_PLATFORM get_elf_platform() 47413ec4ec3SRichard Henderson 47513ec4ec3SRichard Henderson static const char *get_elf_platform(void) 47613ec4ec3SRichard Henderson { 47713ec4ec3SRichard Henderson CPUARMState *env = thread_cpu->env_ptr; 47813ec4ec3SRichard Henderson 47913ec4ec3SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN 48013ec4ec3SRichard Henderson # define END "b" 48113ec4ec3SRichard Henderson #else 48213ec4ec3SRichard Henderson # define END "l" 48313ec4ec3SRichard Henderson #endif 48413ec4ec3SRichard Henderson 48513ec4ec3SRichard Henderson if (arm_feature(env, ARM_FEATURE_V8)) { 48613ec4ec3SRichard Henderson return "v8" END; 48713ec4ec3SRichard Henderson } else if (arm_feature(env, ARM_FEATURE_V7)) { 48813ec4ec3SRichard Henderson if (arm_feature(env, ARM_FEATURE_M)) { 48913ec4ec3SRichard Henderson return "v7m" END; 49013ec4ec3SRichard Henderson } else { 49113ec4ec3SRichard Henderson return "v7" END; 49213ec4ec3SRichard Henderson } 49313ec4ec3SRichard Henderson } else if (arm_feature(env, ARM_FEATURE_V6)) { 49413ec4ec3SRichard Henderson return "v6" END; 49513ec4ec3SRichard Henderson } else if (arm_feature(env, ARM_FEATURE_V5)) { 49613ec4ec3SRichard Henderson return "v5" END; 49713ec4ec3SRichard Henderson } else { 49813ec4ec3SRichard Henderson return "v4" END; 49913ec4ec3SRichard Henderson } 50013ec4ec3SRichard Henderson 50113ec4ec3SRichard Henderson #undef END 50213ec4ec3SRichard Henderson } 50313ec4ec3SRichard Henderson 50424e76ff0SPeter Maydell #else 50524e76ff0SPeter Maydell /* 64 bit ARM definitions */ 50624e76ff0SPeter Maydell #define ELF_START_MMAP 0x80000000 50724e76ff0SPeter Maydell 508b597c3f7SPeter Crosthwaite #define ELF_ARCH EM_AARCH64 50924e76ff0SPeter Maydell #define ELF_CLASS ELFCLASS64 510e20e3ec9SRichard Henderson #ifdef TARGET_WORDS_BIGENDIAN 511e20e3ec9SRichard Henderson # define ELF_PLATFORM "aarch64_be" 512e20e3ec9SRichard Henderson #else 51324e76ff0SPeter Maydell # define ELF_PLATFORM "aarch64" 514e20e3ec9SRichard Henderson #endif 51524e76ff0SPeter Maydell 51624e76ff0SPeter Maydell static inline void init_thread(struct target_pt_regs *regs, 51724e76ff0SPeter Maydell struct image_info *infop) 51824e76ff0SPeter Maydell { 51924e76ff0SPeter Maydell abi_long stack = infop->start_stack; 52024e76ff0SPeter Maydell memset(regs, 0, sizeof(*regs)); 52124e76ff0SPeter Maydell 52224e76ff0SPeter Maydell regs->pc = infop->entry & ~0x3ULL; 52324e76ff0SPeter Maydell regs->sp = stack; 52424e76ff0SPeter Maydell } 52524e76ff0SPeter Maydell 52624e76ff0SPeter Maydell #define ELF_NREG 34 52724e76ff0SPeter Maydell typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 52824e76ff0SPeter Maydell 52924e76ff0SPeter Maydell static void elf_core_copy_regs(target_elf_gregset_t *regs, 53024e76ff0SPeter Maydell const CPUARMState *env) 53124e76ff0SPeter Maydell { 53224e76ff0SPeter Maydell int i; 53324e76ff0SPeter Maydell 53424e76ff0SPeter Maydell for (i = 0; i < 32; i++) { 53524e76ff0SPeter Maydell (*regs)[i] = tswapreg(env->xregs[i]); 53624e76ff0SPeter Maydell } 53724e76ff0SPeter Maydell (*regs)[32] = tswapreg(env->pc); 53824e76ff0SPeter Maydell (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env)); 53924e76ff0SPeter Maydell } 54024e76ff0SPeter Maydell 54124e76ff0SPeter Maydell #define USE_ELF_CORE_DUMP 54224e76ff0SPeter Maydell #define ELF_EXEC_PAGESIZE 4096 54324e76ff0SPeter Maydell 54424e76ff0SPeter Maydell enum { 54524e76ff0SPeter Maydell ARM_HWCAP_A64_FP = 1 << 0, 54624e76ff0SPeter Maydell ARM_HWCAP_A64_ASIMD = 1 << 1, 54724e76ff0SPeter Maydell ARM_HWCAP_A64_EVTSTRM = 1 << 2, 54824e76ff0SPeter Maydell ARM_HWCAP_A64_AES = 1 << 3, 54924e76ff0SPeter Maydell ARM_HWCAP_A64_PMULL = 1 << 4, 55024e76ff0SPeter Maydell ARM_HWCAP_A64_SHA1 = 1 << 5, 55124e76ff0SPeter Maydell ARM_HWCAP_A64_SHA2 = 1 << 6, 55224e76ff0SPeter Maydell ARM_HWCAP_A64_CRC32 = 1 << 7, 553955f56d4SArd Biesheuvel ARM_HWCAP_A64_ATOMICS = 1 << 8, 554955f56d4SArd Biesheuvel ARM_HWCAP_A64_FPHP = 1 << 9, 555955f56d4SArd Biesheuvel ARM_HWCAP_A64_ASIMDHP = 1 << 10, 556955f56d4SArd Biesheuvel ARM_HWCAP_A64_CPUID = 1 << 11, 557955f56d4SArd Biesheuvel ARM_HWCAP_A64_ASIMDRDM = 1 << 12, 558955f56d4SArd Biesheuvel ARM_HWCAP_A64_JSCVT = 1 << 13, 559955f56d4SArd Biesheuvel ARM_HWCAP_A64_FCMA = 1 << 14, 560955f56d4SArd Biesheuvel ARM_HWCAP_A64_LRCPC = 1 << 15, 561955f56d4SArd Biesheuvel ARM_HWCAP_A64_DCPOP = 1 << 16, 562955f56d4SArd Biesheuvel ARM_HWCAP_A64_SHA3 = 1 << 17, 563955f56d4SArd Biesheuvel ARM_HWCAP_A64_SM3 = 1 << 18, 564955f56d4SArd Biesheuvel ARM_HWCAP_A64_SM4 = 1 << 19, 565955f56d4SArd Biesheuvel ARM_HWCAP_A64_ASIMDDP = 1 << 20, 566955f56d4SArd Biesheuvel ARM_HWCAP_A64_SHA512 = 1 << 21, 567955f56d4SArd Biesheuvel ARM_HWCAP_A64_SVE = 1 << 22, 5680083a1faSRichard Henderson ARM_HWCAP_A64_ASIMDFHM = 1 << 23, 5690083a1faSRichard Henderson ARM_HWCAP_A64_DIT = 1 << 24, 5700083a1faSRichard Henderson ARM_HWCAP_A64_USCAT = 1 << 25, 5710083a1faSRichard Henderson ARM_HWCAP_A64_ILRCPC = 1 << 26, 5720083a1faSRichard Henderson ARM_HWCAP_A64_FLAGM = 1 << 27, 5730083a1faSRichard Henderson ARM_HWCAP_A64_SSBS = 1 << 28, 5740083a1faSRichard Henderson ARM_HWCAP_A64_SB = 1 << 29, 5750083a1faSRichard Henderson ARM_HWCAP_A64_PACA = 1 << 30, 5760083a1faSRichard Henderson ARM_HWCAP_A64_PACG = 1UL << 31, 5772041df4aSRichard Henderson 5782041df4aSRichard Henderson ARM_HWCAP2_A64_DCPODP = 1 << 0, 5792041df4aSRichard Henderson ARM_HWCAP2_A64_SVE2 = 1 << 1, 5802041df4aSRichard Henderson ARM_HWCAP2_A64_SVEAES = 1 << 2, 5812041df4aSRichard Henderson ARM_HWCAP2_A64_SVEPMULL = 1 << 3, 5822041df4aSRichard Henderson ARM_HWCAP2_A64_SVEBITPERM = 1 << 4, 5832041df4aSRichard Henderson ARM_HWCAP2_A64_SVESHA3 = 1 << 5, 5842041df4aSRichard Henderson ARM_HWCAP2_A64_SVESM4 = 1 << 6, 5852041df4aSRichard Henderson ARM_HWCAP2_A64_FLAGM2 = 1 << 7, 5862041df4aSRichard Henderson ARM_HWCAP2_A64_FRINT = 1 << 8, 58724e76ff0SPeter Maydell }; 58824e76ff0SPeter Maydell 58924e76ff0SPeter Maydell #define ELF_HWCAP get_elf_hwcap() 5902041df4aSRichard Henderson #define ELF_HWCAP2 get_elf_hwcap2() 5912041df4aSRichard Henderson 5922041df4aSRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \ 5932041df4aSRichard Henderson do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) 59424e76ff0SPeter Maydell 59524e76ff0SPeter Maydell static uint32_t get_elf_hwcap(void) 59624e76ff0SPeter Maydell { 59724e76ff0SPeter Maydell ARMCPU *cpu = ARM_CPU(thread_cpu); 59824e76ff0SPeter Maydell uint32_t hwcaps = 0; 59924e76ff0SPeter Maydell 60024e76ff0SPeter Maydell hwcaps |= ARM_HWCAP_A64_FP; 60124e76ff0SPeter Maydell hwcaps |= ARM_HWCAP_A64_ASIMD; 60237020ff1SAlex Bennée hwcaps |= ARM_HWCAP_A64_CPUID; 60324e76ff0SPeter Maydell 60424e76ff0SPeter Maydell /* probe for the extra features */ 605962fcbf2SRichard Henderson 606962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES); 607962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL); 608962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha1, ARM_HWCAP_A64_SHA1); 609962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha256, ARM_HWCAP_A64_SHA2); 610962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha512, ARM_HWCAP_A64_SHA512); 611962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_crc32, ARM_HWCAP_A64_CRC32); 612962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3); 613962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3); 614962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4); 6155763190fSRichard Henderson GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP); 616962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS); 617962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM); 618962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP); 619962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA); 620cd208a1cSRichard Henderson GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE); 62129d26ab2SRichard Henderson GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG); 6221c9af3a9SRichard Henderson GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM); 6231c9af3a9SRichard Henderson GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT); 6249888bd1eSRichard Henderson GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB); 625b89d9c98SRichard Henderson GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM); 6260d57b499SBeata Michalska GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP); 6272677cf9fSPeter Maydell GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC); 628a1229109SPeter Maydell GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC); 629962fcbf2SRichard Henderson 6302041df4aSRichard Henderson return hwcaps; 6312041df4aSRichard Henderson } 6322041df4aSRichard Henderson 6332041df4aSRichard Henderson static uint32_t get_elf_hwcap2(void) 6342041df4aSRichard Henderson { 6352041df4aSRichard Henderson ARMCPU *cpu = ARM_CPU(thread_cpu); 6362041df4aSRichard Henderson uint32_t hwcaps = 0; 6372041df4aSRichard Henderson 6380d57b499SBeata Michalska GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP); 6392041df4aSRichard Henderson GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2); 6402041df4aSRichard Henderson GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT); 64124e76ff0SPeter Maydell 64224e76ff0SPeter Maydell return hwcaps; 64324e76ff0SPeter Maydell } 64424e76ff0SPeter Maydell 6452041df4aSRichard Henderson #undef GET_FEATURE_ID 6462041df4aSRichard Henderson 64724e76ff0SPeter Maydell #endif /* not TARGET_AARCH64 */ 64824e76ff0SPeter Maydell #endif /* TARGET_ARM */ 64930ac07d4Sbellard 650853d6f7aSbellard #ifdef TARGET_SPARC 651a315a145Sbellard #ifdef TARGET_SPARC64 652853d6f7aSbellard 653853d6f7aSbellard #define ELF_START_MMAP 0x80000000 654cf973e46SArtyom Tarasenko #define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ 655cf973e46SArtyom Tarasenko | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9) 656992f48a0Sblueswir1 #ifndef TARGET_ABI32 657cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) 658992f48a0Sblueswir1 #else 659992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) 660992f48a0Sblueswir1 #endif 661853d6f7aSbellard 662a315a145Sbellard #define ELF_CLASS ELFCLASS64 6635ef54116Sbellard #define ELF_ARCH EM_SPARCV9 6645ef54116Sbellard 6655ef54116Sbellard #define STACK_BIAS 2047 666a315a145Sbellard 667d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 668d97ef72eSRichard Henderson struct image_info *infop) 669a315a145Sbellard { 670992f48a0Sblueswir1 #ifndef TARGET_ABI32 671a315a145Sbellard regs->tstate = 0; 672992f48a0Sblueswir1 #endif 673a315a145Sbellard regs->pc = infop->entry; 674a315a145Sbellard regs->npc = regs->pc + 4; 675a315a145Sbellard regs->y = 0; 676992f48a0Sblueswir1 #ifdef TARGET_ABI32 677992f48a0Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 678992f48a0Sblueswir1 #else 679cb33da57Sblueswir1 if (personality(infop->personality) == PER_LINUX32) 680cb33da57Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 681cb33da57Sblueswir1 else 6825ef54116Sbellard regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; 683992f48a0Sblueswir1 #endif 684a315a145Sbellard } 685a315a145Sbellard 686a315a145Sbellard #else 687a315a145Sbellard #define ELF_START_MMAP 0x80000000 688cf973e46SArtyom Tarasenko #define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ 689cf973e46SArtyom Tarasenko | HWCAP_SPARC_MULDIV) 690a315a145Sbellard 691853d6f7aSbellard #define ELF_CLASS ELFCLASS32 692853d6f7aSbellard #define ELF_ARCH EM_SPARC 693853d6f7aSbellard 694d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 695d97ef72eSRichard Henderson struct image_info *infop) 696853d6f7aSbellard { 697f5155289Sbellard regs->psr = 0; 698f5155289Sbellard regs->pc = infop->entry; 699f5155289Sbellard regs->npc = regs->pc + 4; 700f5155289Sbellard regs->y = 0; 701f5155289Sbellard regs->u_regs[14] = infop->start_stack - 16 * 4; 702853d6f7aSbellard } 703853d6f7aSbellard 704853d6f7aSbellard #endif 705a315a145Sbellard #endif 706853d6f7aSbellard 70767867308Sbellard #ifdef TARGET_PPC 70867867308Sbellard 7094ecd4d16SPeter Crosthwaite #define ELF_MACHINE PPC_ELF_MACHINE 71067867308Sbellard #define ELF_START_MMAP 0x80000000 71167867308Sbellard 712e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 71384409ddbSj_mayer 71484409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 ) 71584409ddbSj_mayer 71684409ddbSj_mayer #define ELF_CLASS ELFCLASS64 71784409ddbSj_mayer 71884409ddbSj_mayer #else 71984409ddbSj_mayer 72067867308Sbellard #define ELF_CLASS ELFCLASS32 72184409ddbSj_mayer 72284409ddbSj_mayer #endif 72384409ddbSj_mayer 72467867308Sbellard #define ELF_ARCH EM_PPC 72567867308Sbellard 726df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). 727df84e4f3SNathan Froyd See arch/powerpc/include/asm/cputable.h. */ 728df84e4f3SNathan Froyd enum { 7293efa9a67Smalc QEMU_PPC_FEATURE_32 = 0x80000000, 7303efa9a67Smalc QEMU_PPC_FEATURE_64 = 0x40000000, 7313efa9a67Smalc QEMU_PPC_FEATURE_601_INSTR = 0x20000000, 7323efa9a67Smalc QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000, 7333efa9a67Smalc QEMU_PPC_FEATURE_HAS_FPU = 0x08000000, 7343efa9a67Smalc QEMU_PPC_FEATURE_HAS_MMU = 0x04000000, 7353efa9a67Smalc QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000, 7363efa9a67Smalc QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000, 7373efa9a67Smalc QEMU_PPC_FEATURE_HAS_SPE = 0x00800000, 7383efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000, 7393efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000, 7403efa9a67Smalc QEMU_PPC_FEATURE_NO_TB = 0x00100000, 7413efa9a67Smalc QEMU_PPC_FEATURE_POWER4 = 0x00080000, 7423efa9a67Smalc QEMU_PPC_FEATURE_POWER5 = 0x00040000, 7433efa9a67Smalc QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000, 7443efa9a67Smalc QEMU_PPC_FEATURE_CELL = 0x00010000, 7453efa9a67Smalc QEMU_PPC_FEATURE_BOOKE = 0x00008000, 7463efa9a67Smalc QEMU_PPC_FEATURE_SMT = 0x00004000, 7473efa9a67Smalc QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000, 7483efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000, 7493efa9a67Smalc QEMU_PPC_FEATURE_PA6T = 0x00000800, 7503efa9a67Smalc QEMU_PPC_FEATURE_HAS_DFP = 0x00000400, 7513efa9a67Smalc QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200, 7523efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100, 7533efa9a67Smalc QEMU_PPC_FEATURE_HAS_VSX = 0x00000080, 7543efa9a67Smalc QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040, 755df84e4f3SNathan Froyd 7563efa9a67Smalc QEMU_PPC_FEATURE_TRUE_LE = 0x00000002, 7573efa9a67Smalc QEMU_PPC_FEATURE_PPC_LE = 0x00000001, 758a60438ddSTom Musta 759a60438ddSTom Musta /* Feature definitions in AT_HWCAP2. */ 760a60438ddSTom Musta QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */ 761a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */ 762a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */ 763a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */ 764a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */ 765a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */ 76624c373ecSLaurent Vivier QEMU_PPC_FEATURE2_VEC_CRYPTO = 0x02000000, 76724c373ecSLaurent Vivier QEMU_PPC_FEATURE2_HTM_NOSC = 0x01000000, 768be0c46d4SSandipan Das QEMU_PPC_FEATURE2_ARCH_3_00 = 0x00800000, /* ISA 3.00 */ 76924c373ecSLaurent Vivier QEMU_PPC_FEATURE2_HAS_IEEE128 = 0x00400000, /* VSX IEEE Bin Float 128-bit */ 77024c373ecSLaurent Vivier QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */ 77124c373ecSLaurent Vivier QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */ 77224c373ecSLaurent Vivier QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */ 773df84e4f3SNathan Froyd }; 774df84e4f3SNathan Froyd 775df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap() 776df84e4f3SNathan Froyd 777df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void) 778df84e4f3SNathan Froyd { 779a2247f8eSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); 780df84e4f3SNathan Froyd uint32_t features = 0; 781df84e4f3SNathan Froyd 782df84e4f3SNathan Froyd /* We don't have to be terribly complete here; the high points are 783df84e4f3SNathan Froyd Altivec/FP/SPE support. Anything else is just a bonus. */ 784df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature) \ 785a2247f8eSAndreas Färber do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) 78658eb5308SMichael Walle #define GET_FEATURE2(flags, feature) \ 78758eb5308SMichael Walle do { \ 78858eb5308SMichael Walle if ((cpu->env.insns_flags2 & flags) == flags) { \ 78958eb5308SMichael Walle features |= feature; \ 79058eb5308SMichael Walle } \ 79158eb5308SMichael Walle } while (0) 7923efa9a67Smalc GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); 7933efa9a67Smalc GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); 7943efa9a67Smalc GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); 7953efa9a67Smalc GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE); 7963efa9a67Smalc GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE); 7973efa9a67Smalc GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE); 7983efa9a67Smalc GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE); 7993efa9a67Smalc GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC); 8000e019746STom Musta GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP); 8010e019746STom Musta GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX); 8020e019746STom Musta GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | 8030e019746STom Musta PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206), 8040e019746STom Musta QEMU_PPC_FEATURE_ARCH_2_06); 805df84e4f3SNathan Froyd #undef GET_FEATURE 8060e019746STom Musta #undef GET_FEATURE2 807df84e4f3SNathan Froyd 808df84e4f3SNathan Froyd return features; 809df84e4f3SNathan Froyd } 810df84e4f3SNathan Froyd 811a60438ddSTom Musta #define ELF_HWCAP2 get_elf_hwcap2() 812a60438ddSTom Musta 813a60438ddSTom Musta static uint32_t get_elf_hwcap2(void) 814a60438ddSTom Musta { 815a60438ddSTom Musta PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); 816a60438ddSTom Musta uint32_t features = 0; 817a60438ddSTom Musta 818a60438ddSTom Musta #define GET_FEATURE(flag, feature) \ 819a60438ddSTom Musta do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) 820a60438ddSTom Musta #define GET_FEATURE2(flag, feature) \ 821a60438ddSTom Musta do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0) 822a60438ddSTom Musta 823a60438ddSTom Musta GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL); 824a60438ddSTom Musta GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR); 825a60438ddSTom Musta GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | 82624c373ecSLaurent Vivier PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07 | 82724c373ecSLaurent Vivier QEMU_PPC_FEATURE2_VEC_CRYPTO); 82824c373ecSLaurent Vivier GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 | 82924c373ecSLaurent Vivier QEMU_PPC_FEATURE2_DARN); 830a60438ddSTom Musta 831a60438ddSTom Musta #undef GET_FEATURE 832a60438ddSTom Musta #undef GET_FEATURE2 833a60438ddSTom Musta 834a60438ddSTom Musta return features; 835a60438ddSTom Musta } 836a60438ddSTom Musta 837f5155289Sbellard /* 838f5155289Sbellard * The requirements here are: 839f5155289Sbellard * - keep the final alignment of sp (sp & 0xf) 840f5155289Sbellard * - make sure the 32-bit value at the first 16 byte aligned position of 841f5155289Sbellard * AUXV is greater than 16 for glibc compatibility. 842f5155289Sbellard * AT_IGNOREPPC is used for that. 843f5155289Sbellard * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, 844f5155289Sbellard * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. 845f5155289Sbellard */ 8460bccf03dSbellard #define DLINFO_ARCH_ITEMS 5 847f5155289Sbellard #define ARCH_DLINFO \ 848f5155289Sbellard do { \ 849623e250aSTom Musta PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); \ 850f5155289Sbellard /* \ 85182991bedSPeter Maydell * Handle glibc compatibility: these magic entries must \ 85282991bedSPeter Maydell * be at the lowest addresses in the final auxv. \ 853f5155289Sbellard */ \ 8540bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 8550bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 85682991bedSPeter Maydell NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \ 85782991bedSPeter Maydell NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \ 85882991bedSPeter Maydell NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ 859f5155289Sbellard } while (0) 860f5155289Sbellard 86167867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) 86267867308Sbellard { 86367867308Sbellard _regs->gpr[1] = infop->start_stack; 864e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 865d90b94cdSDoug Kwan if (get_ppc64_abi(infop) < 2) { 8662ccf97ecSPeter Maydell uint64_t val; 8672ccf97ecSPeter Maydell get_user_u64(val, infop->entry + 8); 8682ccf97ecSPeter Maydell _regs->gpr[2] = val + infop->load_bias; 8692ccf97ecSPeter Maydell get_user_u64(val, infop->entry); 8702ccf97ecSPeter Maydell infop->entry = val + infop->load_bias; 871d90b94cdSDoug Kwan } else { 872d90b94cdSDoug Kwan _regs->gpr[12] = infop->entry; /* r12 set to global entry address */ 873d90b94cdSDoug Kwan } 87484409ddbSj_mayer #endif 87567867308Sbellard _regs->nip = infop->entry; 87667867308Sbellard } 87767867308Sbellard 878e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h. */ 879e2f3e741SNathan Froyd #define ELF_NREG 48 880e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 881e2f3e741SNathan Froyd 88205390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env) 883e2f3e741SNathan Froyd { 884e2f3e741SNathan Froyd int i; 885e2f3e741SNathan Froyd target_ulong ccr = 0; 886e2f3e741SNathan Froyd 887e2f3e741SNathan Froyd for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 88886cd7b2dSPaolo Bonzini (*regs)[i] = tswapreg(env->gpr[i]); 889e2f3e741SNathan Froyd } 890e2f3e741SNathan Froyd 89186cd7b2dSPaolo Bonzini (*regs)[32] = tswapreg(env->nip); 89286cd7b2dSPaolo Bonzini (*regs)[33] = tswapreg(env->msr); 89386cd7b2dSPaolo Bonzini (*regs)[35] = tswapreg(env->ctr); 89486cd7b2dSPaolo Bonzini (*regs)[36] = tswapreg(env->lr); 89586cd7b2dSPaolo Bonzini (*regs)[37] = tswapreg(env->xer); 896e2f3e741SNathan Froyd 897e2f3e741SNathan Froyd for (i = 0; i < ARRAY_SIZE(env->crf); i++) { 898e2f3e741SNathan Froyd ccr |= env->crf[i] << (32 - ((i + 1) * 4)); 899e2f3e741SNathan Froyd } 90086cd7b2dSPaolo Bonzini (*regs)[38] = tswapreg(ccr); 901e2f3e741SNathan Froyd } 902e2f3e741SNathan Froyd 903e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP 90467867308Sbellard #define ELF_EXEC_PAGESIZE 4096 90567867308Sbellard 90667867308Sbellard #endif 90767867308Sbellard 908048f6b4dSbellard #ifdef TARGET_MIPS 909048f6b4dSbellard 910048f6b4dSbellard #define ELF_START_MMAP 0x80000000 911048f6b4dSbellard 912388bb21aSths #ifdef TARGET_MIPS64 913388bb21aSths #define ELF_CLASS ELFCLASS64 914388bb21aSths #else 915048f6b4dSbellard #define ELF_CLASS ELFCLASS32 916388bb21aSths #endif 917048f6b4dSbellard #define ELF_ARCH EM_MIPS 918048f6b4dSbellard 919f72541f3SAleksandar Markovic #define elf_check_arch(x) ((x) == EM_MIPS || (x) == EM_NANOMIPS) 920f72541f3SAleksandar Markovic 921d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 922d97ef72eSRichard Henderson struct image_info *infop) 923048f6b4dSbellard { 924623a930eSths regs->cp0_status = 2 << CP0St_KSU; 925048f6b4dSbellard regs->cp0_epc = infop->entry; 926048f6b4dSbellard regs->regs[29] = infop->start_stack; 927048f6b4dSbellard } 928048f6b4dSbellard 92951e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h. */ 93051e52606SNathan Froyd #define ELF_NREG 45 93151e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 93251e52606SNathan Froyd 93351e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h. */ 93451e52606SNathan Froyd enum { 93551e52606SNathan Froyd #ifdef TARGET_MIPS64 93651e52606SNathan Froyd TARGET_EF_R0 = 0, 93751e52606SNathan Froyd #else 93851e52606SNathan Froyd TARGET_EF_R0 = 6, 93951e52606SNathan Froyd #endif 94051e52606SNathan Froyd TARGET_EF_R26 = TARGET_EF_R0 + 26, 94151e52606SNathan Froyd TARGET_EF_R27 = TARGET_EF_R0 + 27, 94251e52606SNathan Froyd TARGET_EF_LO = TARGET_EF_R0 + 32, 94351e52606SNathan Froyd TARGET_EF_HI = TARGET_EF_R0 + 33, 94451e52606SNathan Froyd TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34, 94551e52606SNathan Froyd TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35, 94651e52606SNathan Froyd TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36, 94751e52606SNathan Froyd TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37 94851e52606SNathan Froyd }; 94951e52606SNathan Froyd 95051e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 95105390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env) 95251e52606SNathan Froyd { 95351e52606SNathan Froyd int i; 95451e52606SNathan Froyd 95551e52606SNathan Froyd for (i = 0; i < TARGET_EF_R0; i++) { 95651e52606SNathan Froyd (*regs)[i] = 0; 95751e52606SNathan Froyd } 95851e52606SNathan Froyd (*regs)[TARGET_EF_R0] = 0; 95951e52606SNathan Froyd 96051e52606SNathan Froyd for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { 961a29f998dSPaolo Bonzini (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); 96251e52606SNathan Froyd } 96351e52606SNathan Froyd 96451e52606SNathan Froyd (*regs)[TARGET_EF_R26] = 0; 96551e52606SNathan Froyd (*regs)[TARGET_EF_R27] = 0; 966a29f998dSPaolo Bonzini (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]); 967a29f998dSPaolo Bonzini (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]); 968a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC); 969a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr); 970a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status); 971a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause); 97251e52606SNathan Froyd } 97351e52606SNathan Froyd 97451e52606SNathan Froyd #define USE_ELF_CORE_DUMP 975388bb21aSths #define ELF_EXEC_PAGESIZE 4096 976388bb21aSths 97746a1ee4fSJames Cowgill /* See arch/mips/include/uapi/asm/hwcap.h. */ 97846a1ee4fSJames Cowgill enum { 97946a1ee4fSJames Cowgill HWCAP_MIPS_R6 = (1 << 0), 98046a1ee4fSJames Cowgill HWCAP_MIPS_MSA = (1 << 1), 98146a1ee4fSJames Cowgill }; 98246a1ee4fSJames Cowgill 98346a1ee4fSJames Cowgill #define ELF_HWCAP get_elf_hwcap() 98446a1ee4fSJames Cowgill 98546a1ee4fSJames Cowgill static uint32_t get_elf_hwcap(void) 98646a1ee4fSJames Cowgill { 98746a1ee4fSJames Cowgill MIPSCPU *cpu = MIPS_CPU(thread_cpu); 98846a1ee4fSJames Cowgill uint32_t hwcaps = 0; 98946a1ee4fSJames Cowgill 99046a1ee4fSJames Cowgill #define GET_FEATURE(flag, hwcap) \ 99146a1ee4fSJames Cowgill do { if (cpu->env.insn_flags & (flag)) { hwcaps |= hwcap; } } while (0) 99246a1ee4fSJames Cowgill 99346a1ee4fSJames Cowgill GET_FEATURE(ISA_MIPS32R6 | ISA_MIPS64R6, HWCAP_MIPS_R6); 99446a1ee4fSJames Cowgill GET_FEATURE(ASE_MSA, HWCAP_MIPS_MSA); 99546a1ee4fSJames Cowgill 99646a1ee4fSJames Cowgill #undef GET_FEATURE 99746a1ee4fSJames Cowgill 99846a1ee4fSJames Cowgill return hwcaps; 99946a1ee4fSJames Cowgill } 100046a1ee4fSJames Cowgill 1001048f6b4dSbellard #endif /* TARGET_MIPS */ 1002048f6b4dSbellard 1003b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 1004b779e29eSEdgar E. Iglesias 1005b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000 1006b779e29eSEdgar E. Iglesias 10070d5d4699SEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD) 1008b779e29eSEdgar E. Iglesias 1009b779e29eSEdgar E. Iglesias #define ELF_CLASS ELFCLASS32 10100d5d4699SEdgar E. Iglesias #define ELF_ARCH EM_MICROBLAZE 1011b779e29eSEdgar E. Iglesias 1012d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1013d97ef72eSRichard Henderson struct image_info *infop) 1014b779e29eSEdgar E. Iglesias { 1015b779e29eSEdgar E. Iglesias regs->pc = infop->entry; 1016b779e29eSEdgar E. Iglesias regs->r1 = infop->start_stack; 1017b779e29eSEdgar E. Iglesias 1018b779e29eSEdgar E. Iglesias } 1019b779e29eSEdgar E. Iglesias 1020b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE 4096 1021b779e29eSEdgar E. Iglesias 1022e4cbd44dSEdgar E. Iglesias #define USE_ELF_CORE_DUMP 1023e4cbd44dSEdgar E. Iglesias #define ELF_NREG 38 1024e4cbd44dSEdgar E. Iglesias typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1025e4cbd44dSEdgar E. Iglesias 1026e4cbd44dSEdgar E. Iglesias /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 102705390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env) 1028e4cbd44dSEdgar E. Iglesias { 1029e4cbd44dSEdgar E. Iglesias int i, pos = 0; 1030e4cbd44dSEdgar E. Iglesias 1031e4cbd44dSEdgar E. Iglesias for (i = 0; i < 32; i++) { 103286cd7b2dSPaolo Bonzini (*regs)[pos++] = tswapreg(env->regs[i]); 1033e4cbd44dSEdgar E. Iglesias } 1034e4cbd44dSEdgar E. Iglesias 1035e4cbd44dSEdgar E. Iglesias for (i = 0; i < 6; i++) { 103686cd7b2dSPaolo Bonzini (*regs)[pos++] = tswapreg(env->sregs[i]); 1037e4cbd44dSEdgar E. Iglesias } 1038e4cbd44dSEdgar E. Iglesias } 1039e4cbd44dSEdgar E. Iglesias 1040b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */ 1041b779e29eSEdgar E. Iglesias 1042a0a839b6SMarek Vasut #ifdef TARGET_NIOS2 1043a0a839b6SMarek Vasut 1044a0a839b6SMarek Vasut #define ELF_START_MMAP 0x80000000 1045a0a839b6SMarek Vasut 1046a0a839b6SMarek Vasut #define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2) 1047a0a839b6SMarek Vasut 1048a0a839b6SMarek Vasut #define ELF_CLASS ELFCLASS32 1049a0a839b6SMarek Vasut #define ELF_ARCH EM_ALTERA_NIOS2 1050a0a839b6SMarek Vasut 1051a0a839b6SMarek Vasut static void init_thread(struct target_pt_regs *regs, struct image_info *infop) 1052a0a839b6SMarek Vasut { 1053a0a839b6SMarek Vasut regs->ea = infop->entry; 1054a0a839b6SMarek Vasut regs->sp = infop->start_stack; 1055a0a839b6SMarek Vasut regs->estatus = 0x3; 1056a0a839b6SMarek Vasut } 1057a0a839b6SMarek Vasut 1058a0a839b6SMarek Vasut #define ELF_EXEC_PAGESIZE 4096 1059a0a839b6SMarek Vasut 1060a0a839b6SMarek Vasut #define USE_ELF_CORE_DUMP 1061a0a839b6SMarek Vasut #define ELF_NREG 49 1062a0a839b6SMarek Vasut typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1063a0a839b6SMarek Vasut 1064a0a839b6SMarek Vasut /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 1065a0a839b6SMarek Vasut static void elf_core_copy_regs(target_elf_gregset_t *regs, 1066a0a839b6SMarek Vasut const CPUNios2State *env) 1067a0a839b6SMarek Vasut { 1068a0a839b6SMarek Vasut int i; 1069a0a839b6SMarek Vasut 1070a0a839b6SMarek Vasut (*regs)[0] = -1; 1071a0a839b6SMarek Vasut for (i = 1; i < 8; i++) /* r0-r7 */ 1072a0a839b6SMarek Vasut (*regs)[i] = tswapreg(env->regs[i + 7]); 1073a0a839b6SMarek Vasut 1074a0a839b6SMarek Vasut for (i = 8; i < 16; i++) /* r8-r15 */ 1075a0a839b6SMarek Vasut (*regs)[i] = tswapreg(env->regs[i - 8]); 1076a0a839b6SMarek Vasut 1077a0a839b6SMarek Vasut for (i = 16; i < 24; i++) /* r16-r23 */ 1078a0a839b6SMarek Vasut (*regs)[i] = tswapreg(env->regs[i + 7]); 1079a0a839b6SMarek Vasut (*regs)[24] = -1; /* R_ET */ 1080a0a839b6SMarek Vasut (*regs)[25] = -1; /* R_BT */ 1081a0a839b6SMarek Vasut (*regs)[26] = tswapreg(env->regs[R_GP]); 1082a0a839b6SMarek Vasut (*regs)[27] = tswapreg(env->regs[R_SP]); 1083a0a839b6SMarek Vasut (*regs)[28] = tswapreg(env->regs[R_FP]); 1084a0a839b6SMarek Vasut (*regs)[29] = tswapreg(env->regs[R_EA]); 1085a0a839b6SMarek Vasut (*regs)[30] = -1; /* R_SSTATUS */ 1086a0a839b6SMarek Vasut (*regs)[31] = tswapreg(env->regs[R_RA]); 1087a0a839b6SMarek Vasut 1088a0a839b6SMarek Vasut (*regs)[32] = tswapreg(env->regs[R_PC]); 1089a0a839b6SMarek Vasut 1090a0a839b6SMarek Vasut (*regs)[33] = -1; /* R_STATUS */ 1091a0a839b6SMarek Vasut (*regs)[34] = tswapreg(env->regs[CR_ESTATUS]); 1092a0a839b6SMarek Vasut 1093a0a839b6SMarek Vasut for (i = 35; i < 49; i++) /* ... */ 1094a0a839b6SMarek Vasut (*regs)[i] = -1; 1095a0a839b6SMarek Vasut } 1096a0a839b6SMarek Vasut 1097a0a839b6SMarek Vasut #endif /* TARGET_NIOS2 */ 1098a0a839b6SMarek Vasut 1099d962783eSJia Liu #ifdef TARGET_OPENRISC 1100d962783eSJia Liu 1101d962783eSJia Liu #define ELF_START_MMAP 0x08000000 1102d962783eSJia Liu 1103d962783eSJia Liu #define ELF_ARCH EM_OPENRISC 1104d962783eSJia Liu #define ELF_CLASS ELFCLASS32 1105d962783eSJia Liu #define ELF_DATA ELFDATA2MSB 1106d962783eSJia Liu 1107d962783eSJia Liu static inline void init_thread(struct target_pt_regs *regs, 1108d962783eSJia Liu struct image_info *infop) 1109d962783eSJia Liu { 1110d962783eSJia Liu regs->pc = infop->entry; 1111d962783eSJia Liu regs->gpr[1] = infop->start_stack; 1112d962783eSJia Liu } 1113d962783eSJia Liu 1114d962783eSJia Liu #define USE_ELF_CORE_DUMP 1115d962783eSJia Liu #define ELF_EXEC_PAGESIZE 8192 1116d962783eSJia Liu 1117d962783eSJia Liu /* See linux kernel arch/openrisc/include/asm/elf.h. */ 1118d962783eSJia Liu #define ELF_NREG 34 /* gprs and pc, sr */ 1119d962783eSJia Liu typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1120d962783eSJia Liu 1121d962783eSJia Liu static void elf_core_copy_regs(target_elf_gregset_t *regs, 1122d962783eSJia Liu const CPUOpenRISCState *env) 1123d962783eSJia Liu { 1124d962783eSJia Liu int i; 1125d962783eSJia Liu 1126d962783eSJia Liu for (i = 0; i < 32; i++) { 1127d89e71e8SStafford Horne (*regs)[i] = tswapreg(cpu_get_gpr(env, i)); 1128d962783eSJia Liu } 112986cd7b2dSPaolo Bonzini (*regs)[32] = tswapreg(env->pc); 113084775c43SRichard Henderson (*regs)[33] = tswapreg(cpu_get_sr(env)); 1131d962783eSJia Liu } 1132d962783eSJia Liu #define ELF_HWCAP 0 1133d962783eSJia Liu #define ELF_PLATFORM NULL 1134d962783eSJia Liu 1135d962783eSJia Liu #endif /* TARGET_OPENRISC */ 1136d962783eSJia Liu 1137fdf9b3e8Sbellard #ifdef TARGET_SH4 1138fdf9b3e8Sbellard 1139fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000 1140fdf9b3e8Sbellard 1141fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32 1142fdf9b3e8Sbellard #define ELF_ARCH EM_SH 1143fdf9b3e8Sbellard 1144d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1145d97ef72eSRichard Henderson struct image_info *infop) 1146fdf9b3e8Sbellard { 1147fdf9b3e8Sbellard /* Check other registers XXXXX */ 1148fdf9b3e8Sbellard regs->pc = infop->entry; 1149072ae847Sths regs->regs[15] = infop->start_stack; 1150fdf9b3e8Sbellard } 1151fdf9b3e8Sbellard 11527631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h. */ 11537631c97eSNathan Froyd #define ELF_NREG 23 11547631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 11557631c97eSNathan Froyd 11567631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h. */ 11577631c97eSNathan Froyd enum { 11587631c97eSNathan Froyd TARGET_REG_PC = 16, 11597631c97eSNathan Froyd TARGET_REG_PR = 17, 11607631c97eSNathan Froyd TARGET_REG_SR = 18, 11617631c97eSNathan Froyd TARGET_REG_GBR = 19, 11627631c97eSNathan Froyd TARGET_REG_MACH = 20, 11637631c97eSNathan Froyd TARGET_REG_MACL = 21, 11647631c97eSNathan Froyd TARGET_REG_SYSCALL = 22 11657631c97eSNathan Froyd }; 11667631c97eSNathan Froyd 1167d97ef72eSRichard Henderson static inline void elf_core_copy_regs(target_elf_gregset_t *regs, 116805390248SAndreas Färber const CPUSH4State *env) 11697631c97eSNathan Froyd { 11707631c97eSNathan Froyd int i; 11717631c97eSNathan Froyd 11727631c97eSNathan Froyd for (i = 0; i < 16; i++) { 117372cd500bSPhilippe Mathieu-Daudé (*regs)[i] = tswapreg(env->gregs[i]); 11747631c97eSNathan Froyd } 11757631c97eSNathan Froyd 117686cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_PC] = tswapreg(env->pc); 117786cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_PR] = tswapreg(env->pr); 117886cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_SR] = tswapreg(env->sr); 117986cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr); 118086cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_MACH] = tswapreg(env->mach); 118186cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_MACL] = tswapreg(env->macl); 11827631c97eSNathan Froyd (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */ 11837631c97eSNathan Froyd } 11847631c97eSNathan Froyd 11857631c97eSNathan Froyd #define USE_ELF_CORE_DUMP 1186fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE 4096 1187fdf9b3e8Sbellard 1188e42fd944SRichard Henderson enum { 1189e42fd944SRichard Henderson SH_CPU_HAS_FPU = 0x0001, /* Hardware FPU support */ 1190e42fd944SRichard Henderson SH_CPU_HAS_P2_FLUSH_BUG = 0x0002, /* Need to flush the cache in P2 area */ 1191e42fd944SRichard Henderson SH_CPU_HAS_MMU_PAGE_ASSOC = 0x0004, /* SH3: TLB way selection bit support */ 1192e42fd944SRichard Henderson SH_CPU_HAS_DSP = 0x0008, /* SH-DSP: DSP support */ 1193e42fd944SRichard Henderson SH_CPU_HAS_PERF_COUNTER = 0x0010, /* Hardware performance counters */ 1194e42fd944SRichard Henderson SH_CPU_HAS_PTEA = 0x0020, /* PTEA register */ 1195e42fd944SRichard Henderson SH_CPU_HAS_LLSC = 0x0040, /* movli.l/movco.l */ 1196e42fd944SRichard Henderson SH_CPU_HAS_L2_CACHE = 0x0080, /* Secondary cache / URAM */ 1197e42fd944SRichard Henderson SH_CPU_HAS_OP32 = 0x0100, /* 32-bit instruction support */ 1198e42fd944SRichard Henderson SH_CPU_HAS_PTEAEX = 0x0200, /* PTE ASID Extension support */ 1199e42fd944SRichard Henderson }; 1200e42fd944SRichard Henderson 1201e42fd944SRichard Henderson #define ELF_HWCAP get_elf_hwcap() 1202e42fd944SRichard Henderson 1203e42fd944SRichard Henderson static uint32_t get_elf_hwcap(void) 1204e42fd944SRichard Henderson { 1205e42fd944SRichard Henderson SuperHCPU *cpu = SUPERH_CPU(thread_cpu); 1206e42fd944SRichard Henderson uint32_t hwcap = 0; 1207e42fd944SRichard Henderson 1208e42fd944SRichard Henderson hwcap |= SH_CPU_HAS_FPU; 1209e42fd944SRichard Henderson 1210e42fd944SRichard Henderson if (cpu->env.features & SH_FEATURE_SH4A) { 1211e42fd944SRichard Henderson hwcap |= SH_CPU_HAS_LLSC; 1212e42fd944SRichard Henderson } 1213e42fd944SRichard Henderson 1214e42fd944SRichard Henderson return hwcap; 1215e42fd944SRichard Henderson } 1216e42fd944SRichard Henderson 1217fdf9b3e8Sbellard #endif 1218fdf9b3e8Sbellard 121948733d19Sths #ifdef TARGET_CRIS 122048733d19Sths 122148733d19Sths #define ELF_START_MMAP 0x80000000 122248733d19Sths 122348733d19Sths #define ELF_CLASS ELFCLASS32 122448733d19Sths #define ELF_ARCH EM_CRIS 122548733d19Sths 1226d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1227d97ef72eSRichard Henderson struct image_info *infop) 122848733d19Sths { 122948733d19Sths regs->erp = infop->entry; 123048733d19Sths } 123148733d19Sths 123248733d19Sths #define ELF_EXEC_PAGESIZE 8192 123348733d19Sths 123448733d19Sths #endif 123548733d19Sths 1236e6e5906bSpbrook #ifdef TARGET_M68K 1237e6e5906bSpbrook 1238e6e5906bSpbrook #define ELF_START_MMAP 0x80000000 1239e6e5906bSpbrook 1240e6e5906bSpbrook #define ELF_CLASS ELFCLASS32 1241e6e5906bSpbrook #define ELF_ARCH EM_68K 1242e6e5906bSpbrook 1243e6e5906bSpbrook /* ??? Does this need to do anything? 1244e6e5906bSpbrook #define ELF_PLAT_INIT(_r) */ 1245e6e5906bSpbrook 1246d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1247d97ef72eSRichard Henderson struct image_info *infop) 1248e6e5906bSpbrook { 1249e6e5906bSpbrook regs->usp = infop->start_stack; 1250e6e5906bSpbrook regs->sr = 0; 1251e6e5906bSpbrook regs->pc = infop->entry; 1252e6e5906bSpbrook } 1253e6e5906bSpbrook 12547a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h. */ 12557a93cc55SNathan Froyd #define ELF_NREG 20 12567a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 12577a93cc55SNathan Froyd 125805390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env) 12597a93cc55SNathan Froyd { 126086cd7b2dSPaolo Bonzini (*regs)[0] = tswapreg(env->dregs[1]); 126186cd7b2dSPaolo Bonzini (*regs)[1] = tswapreg(env->dregs[2]); 126286cd7b2dSPaolo Bonzini (*regs)[2] = tswapreg(env->dregs[3]); 126386cd7b2dSPaolo Bonzini (*regs)[3] = tswapreg(env->dregs[4]); 126486cd7b2dSPaolo Bonzini (*regs)[4] = tswapreg(env->dregs[5]); 126586cd7b2dSPaolo Bonzini (*regs)[5] = tswapreg(env->dregs[6]); 126686cd7b2dSPaolo Bonzini (*regs)[6] = tswapreg(env->dregs[7]); 126786cd7b2dSPaolo Bonzini (*regs)[7] = tswapreg(env->aregs[0]); 126886cd7b2dSPaolo Bonzini (*regs)[8] = tswapreg(env->aregs[1]); 126986cd7b2dSPaolo Bonzini (*regs)[9] = tswapreg(env->aregs[2]); 127086cd7b2dSPaolo Bonzini (*regs)[10] = tswapreg(env->aregs[3]); 127186cd7b2dSPaolo Bonzini (*regs)[11] = tswapreg(env->aregs[4]); 127286cd7b2dSPaolo Bonzini (*regs)[12] = tswapreg(env->aregs[5]); 127386cd7b2dSPaolo Bonzini (*regs)[13] = tswapreg(env->aregs[6]); 127486cd7b2dSPaolo Bonzini (*regs)[14] = tswapreg(env->dregs[0]); 127586cd7b2dSPaolo Bonzini (*regs)[15] = tswapreg(env->aregs[7]); 127686cd7b2dSPaolo Bonzini (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */ 127786cd7b2dSPaolo Bonzini (*regs)[17] = tswapreg(env->sr); 127886cd7b2dSPaolo Bonzini (*regs)[18] = tswapreg(env->pc); 12797a93cc55SNathan Froyd (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */ 12807a93cc55SNathan Froyd } 12817a93cc55SNathan Froyd 12827a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP 1283e6e5906bSpbrook #define ELF_EXEC_PAGESIZE 8192 1284e6e5906bSpbrook 1285e6e5906bSpbrook #endif 1286e6e5906bSpbrook 12877a3148a9Sj_mayer #ifdef TARGET_ALPHA 12887a3148a9Sj_mayer 12897a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL) 12907a3148a9Sj_mayer 12917a3148a9Sj_mayer #define ELF_CLASS ELFCLASS64 12927a3148a9Sj_mayer #define ELF_ARCH EM_ALPHA 12937a3148a9Sj_mayer 1294d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1295d97ef72eSRichard Henderson struct image_info *infop) 12967a3148a9Sj_mayer { 12977a3148a9Sj_mayer regs->pc = infop->entry; 12987a3148a9Sj_mayer regs->ps = 8; 12997a3148a9Sj_mayer regs->usp = infop->start_stack; 13007a3148a9Sj_mayer } 13017a3148a9Sj_mayer 13027a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE 8192 13037a3148a9Sj_mayer 13047a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 13057a3148a9Sj_mayer 1306a4c075f1SUlrich Hecht #ifdef TARGET_S390X 1307a4c075f1SUlrich Hecht 1308a4c075f1SUlrich Hecht #define ELF_START_MMAP (0x20000000000ULL) 1309a4c075f1SUlrich Hecht 1310a4c075f1SUlrich Hecht #define ELF_CLASS ELFCLASS64 1311a4c075f1SUlrich Hecht #define ELF_DATA ELFDATA2MSB 1312a4c075f1SUlrich Hecht #define ELF_ARCH EM_S390 1313a4c075f1SUlrich Hecht 13146d88baf1SDavid Hildenbrand #include "elf.h" 13156d88baf1SDavid Hildenbrand 13166d88baf1SDavid Hildenbrand #define ELF_HWCAP get_elf_hwcap() 13176d88baf1SDavid Hildenbrand 13186d88baf1SDavid Hildenbrand #define GET_FEATURE(_feat, _hwcap) \ 13196d88baf1SDavid Hildenbrand do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0) 13206d88baf1SDavid Hildenbrand 13216d88baf1SDavid Hildenbrand static uint32_t get_elf_hwcap(void) 13226d88baf1SDavid Hildenbrand { 13236d88baf1SDavid Hildenbrand /* 13246d88baf1SDavid Hildenbrand * Let's assume we always have esan3 and zarch. 13256d88baf1SDavid Hildenbrand * 31-bit processes can use 64-bit registers (high gprs). 13266d88baf1SDavid Hildenbrand */ 13276d88baf1SDavid Hildenbrand uint32_t hwcap = HWCAP_S390_ESAN3 | HWCAP_S390_ZARCH | HWCAP_S390_HIGH_GPRS; 13286d88baf1SDavid Hildenbrand 13296d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_STFLE, HWCAP_S390_STFLE); 13306d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_MSA, HWCAP_S390_MSA); 13316d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_LONG_DISPLACEMENT, HWCAP_S390_LDISP); 13326d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_EXTENDED_IMMEDIATE, HWCAP_S390_EIMM); 13336d88baf1SDavid Hildenbrand if (s390_has_feat(S390_FEAT_EXTENDED_TRANSLATION_3) && 13346d88baf1SDavid Hildenbrand s390_has_feat(S390_FEAT_ETF3_ENH)) { 13356d88baf1SDavid Hildenbrand hwcap |= HWCAP_S390_ETF3EH; 13366d88baf1SDavid Hildenbrand } 13376d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS); 13386d88baf1SDavid Hildenbrand 13396d88baf1SDavid Hildenbrand return hwcap; 13406d88baf1SDavid Hildenbrand } 13416d88baf1SDavid Hildenbrand 1342a4c075f1SUlrich Hecht static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 1343a4c075f1SUlrich Hecht { 1344a4c075f1SUlrich Hecht regs->psw.addr = infop->entry; 1345a4c075f1SUlrich Hecht regs->psw.mask = PSW_MASK_64 | PSW_MASK_32; 1346a4c075f1SUlrich Hecht regs->gprs[15] = infop->start_stack; 1347a4c075f1SUlrich Hecht } 1348a4c075f1SUlrich Hecht 1349a4c075f1SUlrich Hecht #endif /* TARGET_S390X */ 1350a4c075f1SUlrich Hecht 1351b16189b2SChen Gang #ifdef TARGET_TILEGX 1352b16189b2SChen Gang 1353b16189b2SChen Gang /* 42 bits real used address, a half for user mode */ 1354b16189b2SChen Gang #define ELF_START_MMAP (0x00000020000000000ULL) 1355b16189b2SChen Gang 1356b16189b2SChen Gang #define elf_check_arch(x) ((x) == EM_TILEGX) 1357b16189b2SChen Gang 1358b16189b2SChen Gang #define ELF_CLASS ELFCLASS64 1359b16189b2SChen Gang #define ELF_DATA ELFDATA2LSB 1360b16189b2SChen Gang #define ELF_ARCH EM_TILEGX 1361b16189b2SChen Gang 1362b16189b2SChen Gang static inline void init_thread(struct target_pt_regs *regs, 1363b16189b2SChen Gang struct image_info *infop) 1364b16189b2SChen Gang { 1365b16189b2SChen Gang regs->pc = infop->entry; 1366b16189b2SChen Gang regs->sp = infop->start_stack; 1367b16189b2SChen Gang 1368b16189b2SChen Gang } 1369b16189b2SChen Gang 1370b16189b2SChen Gang #define ELF_EXEC_PAGESIZE 65536 /* TILE-Gx page size is 64KB */ 1371b16189b2SChen Gang 1372b16189b2SChen Gang #endif /* TARGET_TILEGX */ 1373b16189b2SChen Gang 137447ae93cdSMichael Clark #ifdef TARGET_RISCV 137547ae93cdSMichael Clark 137647ae93cdSMichael Clark #define ELF_START_MMAP 0x80000000 137747ae93cdSMichael Clark #define ELF_ARCH EM_RISCV 137847ae93cdSMichael Clark 137947ae93cdSMichael Clark #ifdef TARGET_RISCV32 138047ae93cdSMichael Clark #define ELF_CLASS ELFCLASS32 138147ae93cdSMichael Clark #else 138247ae93cdSMichael Clark #define ELF_CLASS ELFCLASS64 138347ae93cdSMichael Clark #endif 138447ae93cdSMichael Clark 138547ae93cdSMichael Clark static inline void init_thread(struct target_pt_regs *regs, 138647ae93cdSMichael Clark struct image_info *infop) 138747ae93cdSMichael Clark { 138847ae93cdSMichael Clark regs->sepc = infop->entry; 138947ae93cdSMichael Clark regs->sp = infop->start_stack; 139047ae93cdSMichael Clark } 139147ae93cdSMichael Clark 139247ae93cdSMichael Clark #define ELF_EXEC_PAGESIZE 4096 139347ae93cdSMichael Clark 139447ae93cdSMichael Clark #endif /* TARGET_RISCV */ 139547ae93cdSMichael Clark 13967c248bcdSRichard Henderson #ifdef TARGET_HPPA 13977c248bcdSRichard Henderson 13987c248bcdSRichard Henderson #define ELF_START_MMAP 0x80000000 13997c248bcdSRichard Henderson #define ELF_CLASS ELFCLASS32 14007c248bcdSRichard Henderson #define ELF_ARCH EM_PARISC 14017c248bcdSRichard Henderson #define ELF_PLATFORM "PARISC" 14027c248bcdSRichard Henderson #define STACK_GROWS_DOWN 0 14037c248bcdSRichard Henderson #define STACK_ALIGNMENT 64 14047c248bcdSRichard Henderson 14057c248bcdSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 14067c248bcdSRichard Henderson struct image_info *infop) 14077c248bcdSRichard Henderson { 14087c248bcdSRichard Henderson regs->iaoq[0] = infop->entry; 14097c248bcdSRichard Henderson regs->iaoq[1] = infop->entry + 4; 14107c248bcdSRichard Henderson regs->gr[23] = 0; 14117c248bcdSRichard Henderson regs->gr[24] = infop->arg_start; 14127c248bcdSRichard Henderson regs->gr[25] = (infop->arg_end - infop->arg_start) / sizeof(abi_ulong); 14137c248bcdSRichard Henderson /* The top-of-stack contains a linkage buffer. */ 14147c248bcdSRichard Henderson regs->gr[30] = infop->start_stack + 64; 14157c248bcdSRichard Henderson regs->gr[31] = infop->entry; 14167c248bcdSRichard Henderson } 14177c248bcdSRichard Henderson 14187c248bcdSRichard Henderson #endif /* TARGET_HPPA */ 14197c248bcdSRichard Henderson 1420ba7651fbSMax Filippov #ifdef TARGET_XTENSA 1421ba7651fbSMax Filippov 1422ba7651fbSMax Filippov #define ELF_START_MMAP 0x20000000 1423ba7651fbSMax Filippov 1424ba7651fbSMax Filippov #define ELF_CLASS ELFCLASS32 1425ba7651fbSMax Filippov #define ELF_ARCH EM_XTENSA 1426ba7651fbSMax Filippov 1427ba7651fbSMax Filippov static inline void init_thread(struct target_pt_regs *regs, 1428ba7651fbSMax Filippov struct image_info *infop) 1429ba7651fbSMax Filippov { 1430ba7651fbSMax Filippov regs->windowbase = 0; 1431ba7651fbSMax Filippov regs->windowstart = 1; 1432ba7651fbSMax Filippov regs->areg[1] = infop->start_stack; 1433ba7651fbSMax Filippov regs->pc = infop->entry; 1434ba7651fbSMax Filippov } 1435ba7651fbSMax Filippov 1436ba7651fbSMax Filippov /* See linux kernel: arch/xtensa/include/asm/elf.h. */ 1437ba7651fbSMax Filippov #define ELF_NREG 128 1438ba7651fbSMax Filippov typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1439ba7651fbSMax Filippov 1440ba7651fbSMax Filippov enum { 1441ba7651fbSMax Filippov TARGET_REG_PC, 1442ba7651fbSMax Filippov TARGET_REG_PS, 1443ba7651fbSMax Filippov TARGET_REG_LBEG, 1444ba7651fbSMax Filippov TARGET_REG_LEND, 1445ba7651fbSMax Filippov TARGET_REG_LCOUNT, 1446ba7651fbSMax Filippov TARGET_REG_SAR, 1447ba7651fbSMax Filippov TARGET_REG_WINDOWSTART, 1448ba7651fbSMax Filippov TARGET_REG_WINDOWBASE, 1449ba7651fbSMax Filippov TARGET_REG_THREADPTR, 1450ba7651fbSMax Filippov TARGET_REG_AR0 = 64, 1451ba7651fbSMax Filippov }; 1452ba7651fbSMax Filippov 1453ba7651fbSMax Filippov static void elf_core_copy_regs(target_elf_gregset_t *regs, 1454ba7651fbSMax Filippov const CPUXtensaState *env) 1455ba7651fbSMax Filippov { 1456ba7651fbSMax Filippov unsigned i; 1457ba7651fbSMax Filippov 1458ba7651fbSMax Filippov (*regs)[TARGET_REG_PC] = tswapreg(env->pc); 1459ba7651fbSMax Filippov (*regs)[TARGET_REG_PS] = tswapreg(env->sregs[PS] & ~PS_EXCM); 1460ba7651fbSMax Filippov (*regs)[TARGET_REG_LBEG] = tswapreg(env->sregs[LBEG]); 1461ba7651fbSMax Filippov (*regs)[TARGET_REG_LEND] = tswapreg(env->sregs[LEND]); 1462ba7651fbSMax Filippov (*regs)[TARGET_REG_LCOUNT] = tswapreg(env->sregs[LCOUNT]); 1463ba7651fbSMax Filippov (*regs)[TARGET_REG_SAR] = tswapreg(env->sregs[SAR]); 1464ba7651fbSMax Filippov (*regs)[TARGET_REG_WINDOWSTART] = tswapreg(env->sregs[WINDOW_START]); 1465ba7651fbSMax Filippov (*regs)[TARGET_REG_WINDOWBASE] = tswapreg(env->sregs[WINDOW_BASE]); 1466ba7651fbSMax Filippov (*regs)[TARGET_REG_THREADPTR] = tswapreg(env->uregs[THREADPTR]); 1467ba7651fbSMax Filippov xtensa_sync_phys_from_window((CPUXtensaState *)env); 1468ba7651fbSMax Filippov for (i = 0; i < env->config->nareg; ++i) { 1469ba7651fbSMax Filippov (*regs)[TARGET_REG_AR0 + i] = tswapreg(env->phys_regs[i]); 1470ba7651fbSMax Filippov } 1471ba7651fbSMax Filippov } 1472ba7651fbSMax Filippov 1473ba7651fbSMax Filippov #define USE_ELF_CORE_DUMP 1474ba7651fbSMax Filippov #define ELF_EXEC_PAGESIZE 4096 1475ba7651fbSMax Filippov 1476ba7651fbSMax Filippov #endif /* TARGET_XTENSA */ 1477ba7651fbSMax Filippov 147815338fd7Sbellard #ifndef ELF_PLATFORM 147915338fd7Sbellard #define ELF_PLATFORM (NULL) 148015338fd7Sbellard #endif 148115338fd7Sbellard 148275be901cSPeter Crosthwaite #ifndef ELF_MACHINE 148375be901cSPeter Crosthwaite #define ELF_MACHINE ELF_ARCH 148475be901cSPeter Crosthwaite #endif 148575be901cSPeter Crosthwaite 1486d276a604SPeter Crosthwaite #ifndef elf_check_arch 1487d276a604SPeter Crosthwaite #define elf_check_arch(x) ((x) == ELF_ARCH) 1488d276a604SPeter Crosthwaite #endif 1489d276a604SPeter Crosthwaite 149015338fd7Sbellard #ifndef ELF_HWCAP 149115338fd7Sbellard #define ELF_HWCAP 0 149215338fd7Sbellard #endif 149315338fd7Sbellard 14947c4ee5bcSRichard Henderson #ifndef STACK_GROWS_DOWN 14957c4ee5bcSRichard Henderson #define STACK_GROWS_DOWN 1 14967c4ee5bcSRichard Henderson #endif 14977c4ee5bcSRichard Henderson 14987c4ee5bcSRichard Henderson #ifndef STACK_ALIGNMENT 14997c4ee5bcSRichard Henderson #define STACK_ALIGNMENT 16 15007c4ee5bcSRichard Henderson #endif 15017c4ee5bcSRichard Henderson 1502992f48a0Sblueswir1 #ifdef TARGET_ABI32 1503cb33da57Sblueswir1 #undef ELF_CLASS 1504992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32 1505cb33da57Sblueswir1 #undef bswaptls 1506cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr) 1507cb33da57Sblueswir1 #endif 1508cb33da57Sblueswir1 150931e31b8aSbellard #include "elf.h" 151009bfb054Sbellard 151109bfb054Sbellard struct exec 151209bfb054Sbellard { 151309bfb054Sbellard unsigned int a_info; /* Use macros N_MAGIC, etc for access */ 151409bfb054Sbellard unsigned int a_text; /* length of text, in bytes */ 151509bfb054Sbellard unsigned int a_data; /* length of data, in bytes */ 151609bfb054Sbellard unsigned int a_bss; /* length of uninitialized data area, in bytes */ 151709bfb054Sbellard unsigned int a_syms; /* length of symbol table data in file, in bytes */ 151809bfb054Sbellard unsigned int a_entry; /* start address */ 151909bfb054Sbellard unsigned int a_trsize; /* length of relocation info for text, in bytes */ 152009bfb054Sbellard unsigned int a_drsize; /* length of relocation info for data, in bytes */ 152109bfb054Sbellard }; 152209bfb054Sbellard 152309bfb054Sbellard 152409bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff) 152509bfb054Sbellard #define OMAGIC 0407 152609bfb054Sbellard #define NMAGIC 0410 152709bfb054Sbellard #define ZMAGIC 0413 152809bfb054Sbellard #define QMAGIC 0314 152909bfb054Sbellard 153031e31b8aSbellard /* Necessary parameters */ 153194894ff2SShivaprasad G Bhat #define TARGET_ELF_EXEC_PAGESIZE \ 153294894ff2SShivaprasad G Bhat (((eppnt->p_align & ~qemu_host_page_mask) != 0) ? \ 153394894ff2SShivaprasad G Bhat TARGET_PAGE_SIZE : MAX(qemu_host_page_size, TARGET_PAGE_SIZE)) 153494894ff2SShivaprasad G Bhat #define TARGET_ELF_PAGELENGTH(_v) ROUND_UP((_v), TARGET_ELF_EXEC_PAGESIZE) 153579cb1f1dSYongbok Kim #define TARGET_ELF_PAGESTART(_v) ((_v) & \ 153679cb1f1dSYongbok Kim ~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1)) 153754936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) 153831e31b8aSbellard 1539e0d1673dSLirong Yuan #define DLINFO_ITEMS 16 154031e31b8aSbellard 154109bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) 154209bfb054Sbellard { 154309bfb054Sbellard memcpy(to, from, n); 154409bfb054Sbellard } 154509bfb054Sbellard 154631e31b8aSbellard #ifdef BSWAP_NEEDED 154792a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr) 154831e31b8aSbellard { 154931e31b8aSbellard bswap16s(&ehdr->e_type); /* Object file type */ 155031e31b8aSbellard bswap16s(&ehdr->e_machine); /* Architecture */ 155131e31b8aSbellard bswap32s(&ehdr->e_version); /* Object file version */ 155292a31b1fSbellard bswaptls(&ehdr->e_entry); /* Entry point virtual address */ 155392a31b1fSbellard bswaptls(&ehdr->e_phoff); /* Program header table file offset */ 155492a31b1fSbellard bswaptls(&ehdr->e_shoff); /* Section header table file offset */ 155531e31b8aSbellard bswap32s(&ehdr->e_flags); /* Processor-specific flags */ 155631e31b8aSbellard bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ 155731e31b8aSbellard bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ 155831e31b8aSbellard bswap16s(&ehdr->e_phnum); /* Program header table entry count */ 155931e31b8aSbellard bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ 156031e31b8aSbellard bswap16s(&ehdr->e_shnum); /* Section header table entry count */ 156131e31b8aSbellard bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ 156231e31b8aSbellard } 156331e31b8aSbellard 1564991f8f0cSRichard Henderson static void bswap_phdr(struct elf_phdr *phdr, int phnum) 156531e31b8aSbellard { 1566991f8f0cSRichard Henderson int i; 1567991f8f0cSRichard Henderson for (i = 0; i < phnum; ++i, ++phdr) { 156831e31b8aSbellard bswap32s(&phdr->p_type); /* Segment type */ 1569991f8f0cSRichard Henderson bswap32s(&phdr->p_flags); /* Segment flags */ 157092a31b1fSbellard bswaptls(&phdr->p_offset); /* Segment file offset */ 157192a31b1fSbellard bswaptls(&phdr->p_vaddr); /* Segment virtual address */ 157292a31b1fSbellard bswaptls(&phdr->p_paddr); /* Segment physical address */ 157392a31b1fSbellard bswaptls(&phdr->p_filesz); /* Segment size in file */ 157492a31b1fSbellard bswaptls(&phdr->p_memsz); /* Segment size in memory */ 157592a31b1fSbellard bswaptls(&phdr->p_align); /* Segment alignment */ 157631e31b8aSbellard } 1577991f8f0cSRichard Henderson } 1578689f936fSbellard 1579991f8f0cSRichard Henderson static void bswap_shdr(struct elf_shdr *shdr, int shnum) 1580689f936fSbellard { 1581991f8f0cSRichard Henderson int i; 1582991f8f0cSRichard Henderson for (i = 0; i < shnum; ++i, ++shdr) { 1583689f936fSbellard bswap32s(&shdr->sh_name); 1584689f936fSbellard bswap32s(&shdr->sh_type); 158592a31b1fSbellard bswaptls(&shdr->sh_flags); 158692a31b1fSbellard bswaptls(&shdr->sh_addr); 158792a31b1fSbellard bswaptls(&shdr->sh_offset); 158892a31b1fSbellard bswaptls(&shdr->sh_size); 1589689f936fSbellard bswap32s(&shdr->sh_link); 1590689f936fSbellard bswap32s(&shdr->sh_info); 159192a31b1fSbellard bswaptls(&shdr->sh_addralign); 159292a31b1fSbellard bswaptls(&shdr->sh_entsize); 1593689f936fSbellard } 1594991f8f0cSRichard Henderson } 1595689f936fSbellard 15967a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym) 1597689f936fSbellard { 1598689f936fSbellard bswap32s(&sym->st_name); 15997a3148a9Sj_mayer bswaptls(&sym->st_value); 16007a3148a9Sj_mayer bswaptls(&sym->st_size); 1601689f936fSbellard bswap16s(&sym->st_shndx); 1602689f936fSbellard } 16035dd0db52SStefan Markovic 16045dd0db52SStefan Markovic #ifdef TARGET_MIPS 16055dd0db52SStefan Markovic static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) 16065dd0db52SStefan Markovic { 16075dd0db52SStefan Markovic bswap16s(&abiflags->version); 16085dd0db52SStefan Markovic bswap32s(&abiflags->ases); 16095dd0db52SStefan Markovic bswap32s(&abiflags->isa_ext); 16105dd0db52SStefan Markovic bswap32s(&abiflags->flags1); 16115dd0db52SStefan Markovic bswap32s(&abiflags->flags2); 16125dd0db52SStefan Markovic } 16135dd0db52SStefan Markovic #endif 1614991f8f0cSRichard Henderson #else 1615991f8f0cSRichard Henderson static inline void bswap_ehdr(struct elfhdr *ehdr) { } 1616991f8f0cSRichard Henderson static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { } 1617991f8f0cSRichard Henderson static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { } 1618991f8f0cSRichard Henderson static inline void bswap_sym(struct elf_sym *sym) { } 16195dd0db52SStefan Markovic #ifdef TARGET_MIPS 16205dd0db52SStefan Markovic static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { } 16215dd0db52SStefan Markovic #endif 162231e31b8aSbellard #endif 162331e31b8aSbellard 1624edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 16259349b4f9SAndreas Färber static int elf_core_dump(int, const CPUArchState *); 1626edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 1627682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias); 1628edf8e2afSMika Westerberg 16299058abddSRichard Henderson /* Verify the portions of EHDR within E_IDENT for the target. 16309058abddSRichard Henderson This can be performed before bswapping the entire header. */ 16319058abddSRichard Henderson static bool elf_check_ident(struct elfhdr *ehdr) 16329058abddSRichard Henderson { 16339058abddSRichard Henderson return (ehdr->e_ident[EI_MAG0] == ELFMAG0 16349058abddSRichard Henderson && ehdr->e_ident[EI_MAG1] == ELFMAG1 16359058abddSRichard Henderson && ehdr->e_ident[EI_MAG2] == ELFMAG2 16369058abddSRichard Henderson && ehdr->e_ident[EI_MAG3] == ELFMAG3 16379058abddSRichard Henderson && ehdr->e_ident[EI_CLASS] == ELF_CLASS 16389058abddSRichard Henderson && ehdr->e_ident[EI_DATA] == ELF_DATA 16399058abddSRichard Henderson && ehdr->e_ident[EI_VERSION] == EV_CURRENT); 16409058abddSRichard Henderson } 16419058abddSRichard Henderson 16429058abddSRichard Henderson /* Verify the portions of EHDR outside of E_IDENT for the target. 16439058abddSRichard Henderson This has to wait until after bswapping the header. */ 16449058abddSRichard Henderson static bool elf_check_ehdr(struct elfhdr *ehdr) 16459058abddSRichard Henderson { 16469058abddSRichard Henderson return (elf_check_arch(ehdr->e_machine) 16479058abddSRichard Henderson && ehdr->e_ehsize == sizeof(struct elfhdr) 16489058abddSRichard Henderson && ehdr->e_phentsize == sizeof(struct elf_phdr) 16499058abddSRichard Henderson && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)); 16509058abddSRichard Henderson } 16519058abddSRichard Henderson 165231e31b8aSbellard /* 1653e5fe0c52Spbrook * 'copy_elf_strings()' copies argument/envelope strings from user 165431e31b8aSbellard * memory to free pages in kernel mem. These are in a format ready 165531e31b8aSbellard * to be put directly into the top of new user memory. 165631e31b8aSbellard * 165731e31b8aSbellard */ 165859baae9aSStefan Brüns static abi_ulong copy_elf_strings(int argc, char **argv, char *scratch, 165959baae9aSStefan Brüns abi_ulong p, abi_ulong stack_limit) 166031e31b8aSbellard { 166159baae9aSStefan Brüns char *tmp; 16627c4ee5bcSRichard Henderson int len, i; 166359baae9aSStefan Brüns abi_ulong top = p; 166431e31b8aSbellard 166531e31b8aSbellard if (!p) { 166631e31b8aSbellard return 0; /* bullet-proofing */ 166731e31b8aSbellard } 166859baae9aSStefan Brüns 16697c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 16707c4ee5bcSRichard Henderson int offset = ((p - 1) % TARGET_PAGE_SIZE) + 1; 16717c4ee5bcSRichard Henderson for (i = argc - 1; i >= 0; --i) { 16727c4ee5bcSRichard Henderson tmp = argv[i]; 1673edf779ffSbellard if (!tmp) { 167431e31b8aSbellard fprintf(stderr, "VFS: argc is wrong"); 167531e31b8aSbellard exit(-1); 167631e31b8aSbellard } 167759baae9aSStefan Brüns len = strlen(tmp) + 1; 167859baae9aSStefan Brüns tmp += len; 167959baae9aSStefan Brüns 168059baae9aSStefan Brüns if (len > (p - stack_limit)) { 168131e31b8aSbellard return 0; 168231e31b8aSbellard } 168331e31b8aSbellard while (len) { 168431e31b8aSbellard int bytes_to_copy = (len > offset) ? offset : len; 168531e31b8aSbellard tmp -= bytes_to_copy; 168631e31b8aSbellard p -= bytes_to_copy; 168731e31b8aSbellard offset -= bytes_to_copy; 168831e31b8aSbellard len -= bytes_to_copy; 168959baae9aSStefan Brüns 169059baae9aSStefan Brüns memcpy_fromfs(scratch + offset, tmp, bytes_to_copy); 169159baae9aSStefan Brüns 169259baae9aSStefan Brüns if (offset == 0) { 169359baae9aSStefan Brüns memcpy_to_target(p, scratch, top - p); 169459baae9aSStefan Brüns top = p; 169559baae9aSStefan Brüns offset = TARGET_PAGE_SIZE; 169631e31b8aSbellard } 169731e31b8aSbellard } 169831e31b8aSbellard } 16997c4ee5bcSRichard Henderson if (p != top) { 170059baae9aSStefan Brüns memcpy_to_target(p, scratch + offset, top - p); 170159baae9aSStefan Brüns } 17027c4ee5bcSRichard Henderson } else { 17037c4ee5bcSRichard Henderson int remaining = TARGET_PAGE_SIZE - (p % TARGET_PAGE_SIZE); 17047c4ee5bcSRichard Henderson for (i = 0; i < argc; ++i) { 17057c4ee5bcSRichard Henderson tmp = argv[i]; 17067c4ee5bcSRichard Henderson if (!tmp) { 17077c4ee5bcSRichard Henderson fprintf(stderr, "VFS: argc is wrong"); 17087c4ee5bcSRichard Henderson exit(-1); 17097c4ee5bcSRichard Henderson } 17107c4ee5bcSRichard Henderson len = strlen(tmp) + 1; 17117c4ee5bcSRichard Henderson if (len > (stack_limit - p)) { 17127c4ee5bcSRichard Henderson return 0; 17137c4ee5bcSRichard Henderson } 17147c4ee5bcSRichard Henderson while (len) { 17157c4ee5bcSRichard Henderson int bytes_to_copy = (len > remaining) ? remaining : len; 17167c4ee5bcSRichard Henderson 17177c4ee5bcSRichard Henderson memcpy_fromfs(scratch + (p - top), tmp, bytes_to_copy); 17187c4ee5bcSRichard Henderson 17197c4ee5bcSRichard Henderson tmp += bytes_to_copy; 17207c4ee5bcSRichard Henderson remaining -= bytes_to_copy; 17217c4ee5bcSRichard Henderson p += bytes_to_copy; 17227c4ee5bcSRichard Henderson len -= bytes_to_copy; 17237c4ee5bcSRichard Henderson 17247c4ee5bcSRichard Henderson if (remaining == 0) { 17257c4ee5bcSRichard Henderson memcpy_to_target(top, scratch, p - top); 17267c4ee5bcSRichard Henderson top = p; 17277c4ee5bcSRichard Henderson remaining = TARGET_PAGE_SIZE; 17287c4ee5bcSRichard Henderson } 17297c4ee5bcSRichard Henderson } 17307c4ee5bcSRichard Henderson } 17317c4ee5bcSRichard Henderson if (p != top) { 17327c4ee5bcSRichard Henderson memcpy_to_target(top, scratch, p - top); 17337c4ee5bcSRichard Henderson } 17347c4ee5bcSRichard Henderson } 173559baae9aSStefan Brüns 173631e31b8aSbellard return p; 173731e31b8aSbellard } 173831e31b8aSbellard 173959baae9aSStefan Brüns /* Older linux kernels provide up to MAX_ARG_PAGES (default: 32) of 174059baae9aSStefan Brüns * argument/environment space. Newer kernels (>2.6.33) allow more, 174159baae9aSStefan Brüns * dependent on stack size, but guarantee at least 32 pages for 174259baae9aSStefan Brüns * backwards compatibility. 174359baae9aSStefan Brüns */ 174459baae9aSStefan Brüns #define STACK_LOWER_LIMIT (32 * TARGET_PAGE_SIZE) 174559baae9aSStefan Brüns 174659baae9aSStefan Brüns static abi_ulong setup_arg_pages(struct linux_binprm *bprm, 174731e31b8aSbellard struct image_info *info) 174831e31b8aSbellard { 174959baae9aSStefan Brüns abi_ulong size, error, guard; 175031e31b8aSbellard 1751703e0e89SRichard Henderson size = guest_stack_size; 175259baae9aSStefan Brüns if (size < STACK_LOWER_LIMIT) { 175359baae9aSStefan Brüns size = STACK_LOWER_LIMIT; 175460dcbcb5SRichard Henderson } 175560dcbcb5SRichard Henderson guard = TARGET_PAGE_SIZE; 175660dcbcb5SRichard Henderson if (guard < qemu_real_host_page_size) { 175760dcbcb5SRichard Henderson guard = qemu_real_host_page_size; 175860dcbcb5SRichard Henderson } 175960dcbcb5SRichard Henderson 176060dcbcb5SRichard Henderson error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE, 176160dcbcb5SRichard Henderson MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 176209bfb054Sbellard if (error == -1) { 176360dcbcb5SRichard Henderson perror("mmap stack"); 176431e31b8aSbellard exit(-1); 176531e31b8aSbellard } 176631e31b8aSbellard 176760dcbcb5SRichard Henderson /* We reserve one extra page at the top of the stack as guard. */ 17687c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 176960dcbcb5SRichard Henderson target_mprotect(error, guard, PROT_NONE); 177060dcbcb5SRichard Henderson info->stack_limit = error + guard; 177159baae9aSStefan Brüns return info->stack_limit + size - sizeof(void *); 17727c4ee5bcSRichard Henderson } else { 17737c4ee5bcSRichard Henderson target_mprotect(error + size, guard, PROT_NONE); 17747c4ee5bcSRichard Henderson info->stack_limit = error + size; 17757c4ee5bcSRichard Henderson return error; 17767c4ee5bcSRichard Henderson } 177731e31b8aSbellard } 177831e31b8aSbellard 1779cf129f3aSRichard Henderson /* Map and zero the bss. We need to explicitly zero any fractional pages 1780cf129f3aSRichard Henderson after the data section (i.e. bss). */ 1781cf129f3aSRichard Henderson static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot) 178231e31b8aSbellard { 1783cf129f3aSRichard Henderson uintptr_t host_start, host_map_start, host_end; 1784cf129f3aSRichard Henderson 1785cf129f3aSRichard Henderson last_bss = TARGET_PAGE_ALIGN(last_bss); 1786cf129f3aSRichard Henderson 1787cf129f3aSRichard Henderson /* ??? There is confusion between qemu_real_host_page_size and 1788cf129f3aSRichard Henderson qemu_host_page_size here and elsewhere in target_mmap, which 1789cf129f3aSRichard Henderson may lead to the end of the data section mapping from the file 1790cf129f3aSRichard Henderson not being mapped. At least there was an explicit test and 1791cf129f3aSRichard Henderson comment for that here, suggesting that "the file size must 1792cf129f3aSRichard Henderson be known". The comment probably pre-dates the introduction 1793cf129f3aSRichard Henderson of the fstat system call in target_mmap which does in fact 1794cf129f3aSRichard Henderson find out the size. What isn't clear is if the workaround 1795cf129f3aSRichard Henderson here is still actually needed. For now, continue with it, 1796cf129f3aSRichard Henderson but merge it with the "normal" mmap that would allocate the bss. */ 1797cf129f3aSRichard Henderson 1798cf129f3aSRichard Henderson host_start = (uintptr_t) g2h(elf_bss); 1799cf129f3aSRichard Henderson host_end = (uintptr_t) g2h(last_bss); 18000c2d70c4SPaolo Bonzini host_map_start = REAL_HOST_PAGE_ALIGN(host_start); 1801cf129f3aSRichard Henderson 1802cf129f3aSRichard Henderson if (host_map_start < host_end) { 1803cf129f3aSRichard Henderson void *p = mmap((void *)host_map_start, host_end - host_map_start, 1804cf129f3aSRichard Henderson prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 1805cf129f3aSRichard Henderson if (p == MAP_FAILED) { 180631e31b8aSbellard perror("cannot mmap brk"); 180731e31b8aSbellard exit(-1); 180831e31b8aSbellard } 1809f46e9a0bSTom Musta } 1810cf129f3aSRichard Henderson 1811f46e9a0bSTom Musta /* Ensure that the bss page(s) are valid */ 1812f46e9a0bSTom Musta if ((page_get_flags(last_bss-1) & prot) != prot) { 1813cf129f3aSRichard Henderson page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot | PAGE_VALID); 181431e31b8aSbellard } 181531e31b8aSbellard 1816cf129f3aSRichard Henderson if (host_start < host_map_start) { 1817cf129f3aSRichard Henderson memset((void *)host_start, 0, host_map_start - host_start); 1818853d6f7aSbellard } 1819853d6f7aSbellard } 1820853d6f7aSbellard 1821cf58affeSChristophe Lyon #ifdef TARGET_ARM 1822cf58affeSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec) 1823cf58affeSChristophe Lyon { 1824cf58affeSChristophe Lyon return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC; 1825cf58affeSChristophe Lyon } 1826cf58affeSChristophe Lyon #else 1827a99856cdSChristophe Lyon /* Default implementation, always false. */ 1828a99856cdSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec) 1829a99856cdSChristophe Lyon { 1830a99856cdSChristophe Lyon return 0; 1831a99856cdSChristophe Lyon } 1832cf58affeSChristophe Lyon #endif 1833a99856cdSChristophe Lyon 18341af02e83SMike Frysinger static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp) 18351af02e83SMike Frysinger { 18361af02e83SMike Frysinger uint16_t n; 18371af02e83SMike Frysinger struct elf32_fdpic_loadseg *loadsegs = info->loadsegs; 18381af02e83SMike Frysinger 18391af02e83SMike Frysinger /* elf32_fdpic_loadseg */ 18401af02e83SMike Frysinger n = info->nsegs; 18411af02e83SMike Frysinger while (n--) { 18421af02e83SMike Frysinger sp -= 12; 18431af02e83SMike Frysinger put_user_u32(loadsegs[n].addr, sp+0); 18441af02e83SMike Frysinger put_user_u32(loadsegs[n].p_vaddr, sp+4); 18451af02e83SMike Frysinger put_user_u32(loadsegs[n].p_memsz, sp+8); 18461af02e83SMike Frysinger } 18471af02e83SMike Frysinger 18481af02e83SMike Frysinger /* elf32_fdpic_loadmap */ 18491af02e83SMike Frysinger sp -= 4; 18501af02e83SMike Frysinger put_user_u16(0, sp+0); /* version */ 18511af02e83SMike Frysinger put_user_u16(info->nsegs, sp+2); /* nsegs */ 18521af02e83SMike Frysinger 18531af02e83SMike Frysinger info->personality = PER_LINUX_FDPIC; 18541af02e83SMike Frysinger info->loadmap_addr = sp; 18551af02e83SMike Frysinger 18561af02e83SMike Frysinger return sp; 18571af02e83SMike Frysinger } 18581af02e83SMike Frysinger 1859992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, 186031e31b8aSbellard struct elfhdr *exec, 18618e62a717SRichard Henderson struct image_info *info, 18628e62a717SRichard Henderson struct image_info *interp_info) 186331e31b8aSbellard { 1864992f48a0Sblueswir1 abi_ulong sp; 18657c4ee5bcSRichard Henderson abi_ulong u_argc, u_argv, u_envp, u_auxv; 186653a5960aSpbrook int size; 186714322badSLaurent ALFONSI int i; 186814322badSLaurent ALFONSI abi_ulong u_rand_bytes; 186914322badSLaurent ALFONSI uint8_t k_rand_bytes[16]; 1870992f48a0Sblueswir1 abi_ulong u_platform; 187115338fd7Sbellard const char *k_platform; 1872863cf0b7Sj_mayer const int n = sizeof(elf_addr_t); 187331e31b8aSbellard 187453a5960aSpbrook sp = p; 18751af02e83SMike Frysinger 18761af02e83SMike Frysinger /* Needs to be before we load the env/argc/... */ 18771af02e83SMike Frysinger if (elf_is_fdpic(exec)) { 18781af02e83SMike Frysinger /* Need 4 byte alignment for these structs */ 18791af02e83SMike Frysinger sp &= ~3; 18801af02e83SMike Frysinger sp = loader_build_fdpic_loadmap(info, sp); 18811af02e83SMike Frysinger info->other_info = interp_info; 18821af02e83SMike Frysinger if (interp_info) { 18831af02e83SMike Frysinger interp_info->other_info = info; 18841af02e83SMike Frysinger sp = loader_build_fdpic_loadmap(interp_info, sp); 18853cb10cfaSChristophe Lyon info->interpreter_loadmap_addr = interp_info->loadmap_addr; 18863cb10cfaSChristophe Lyon info->interpreter_pt_dynamic_addr = interp_info->pt_dynamic_addr; 18873cb10cfaSChristophe Lyon } else { 18883cb10cfaSChristophe Lyon info->interpreter_loadmap_addr = 0; 18893cb10cfaSChristophe Lyon info->interpreter_pt_dynamic_addr = 0; 18901af02e83SMike Frysinger } 18911af02e83SMike Frysinger } 18921af02e83SMike Frysinger 189353a5960aSpbrook u_platform = 0; 189415338fd7Sbellard k_platform = ELF_PLATFORM; 189515338fd7Sbellard if (k_platform) { 189615338fd7Sbellard size_t len = strlen(k_platform) + 1; 18977c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 189853a5960aSpbrook sp -= (len + n - 1) & ~(n - 1); 189953a5960aSpbrook u_platform = sp; 1900579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 190153a5960aSpbrook memcpy_to_target(sp, k_platform, len); 19027c4ee5bcSRichard Henderson } else { 19037c4ee5bcSRichard Henderson memcpy_to_target(sp, k_platform, len); 19047c4ee5bcSRichard Henderson u_platform = sp; 19057c4ee5bcSRichard Henderson sp += len + 1; 19067c4ee5bcSRichard Henderson } 19077c4ee5bcSRichard Henderson } 19087c4ee5bcSRichard Henderson 19097c4ee5bcSRichard Henderson /* Provide 16 byte alignment for the PRNG, and basic alignment for 19107c4ee5bcSRichard Henderson * the argv and envp pointers. 19117c4ee5bcSRichard Henderson */ 19127c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 19137c4ee5bcSRichard Henderson sp = QEMU_ALIGN_DOWN(sp, 16); 19147c4ee5bcSRichard Henderson } else { 19157c4ee5bcSRichard Henderson sp = QEMU_ALIGN_UP(sp, 16); 191615338fd7Sbellard } 191714322badSLaurent ALFONSI 191814322badSLaurent ALFONSI /* 1919c6a2377fSRichard Henderson * Generate 16 random bytes for userspace PRNG seeding. 192014322badSLaurent ALFONSI */ 1921c6a2377fSRichard Henderson qemu_guest_getrandom_nofail(k_rand_bytes, sizeof(k_rand_bytes)); 19227c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 192314322badSLaurent ALFONSI sp -= 16; 192414322badSLaurent ALFONSI u_rand_bytes = sp; 192514322badSLaurent ALFONSI /* FIXME - check return value of memcpy_to_target() for failure */ 192614322badSLaurent ALFONSI memcpy_to_target(sp, k_rand_bytes, 16); 19277c4ee5bcSRichard Henderson } else { 19287c4ee5bcSRichard Henderson memcpy_to_target(sp, k_rand_bytes, 16); 19297c4ee5bcSRichard Henderson u_rand_bytes = sp; 19307c4ee5bcSRichard Henderson sp += 16; 19317c4ee5bcSRichard Henderson } 193214322badSLaurent ALFONSI 193353a5960aSpbrook size = (DLINFO_ITEMS + 1) * 2; 193415338fd7Sbellard if (k_platform) 193553a5960aSpbrook size += 2; 1936f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS 193753a5960aSpbrook size += DLINFO_ARCH_ITEMS * 2; 1938f5155289Sbellard #endif 1939ad6919dcSPeter Maydell #ifdef ELF_HWCAP2 1940ad6919dcSPeter Maydell size += 2; 1941ad6919dcSPeter Maydell #endif 1942f516511eSPeter Maydell info->auxv_len = size * n; 1943f516511eSPeter Maydell 194453a5960aSpbrook size += envc + argc + 2; 1945b9329d4bSRichard Henderson size += 1; /* argc itself */ 194653a5960aSpbrook size *= n; 19477c4ee5bcSRichard Henderson 19487c4ee5bcSRichard Henderson /* Allocate space and finalize stack alignment for entry now. */ 19497c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 19507c4ee5bcSRichard Henderson u_argc = QEMU_ALIGN_DOWN(sp - size, STACK_ALIGNMENT); 19517c4ee5bcSRichard Henderson sp = u_argc; 19527c4ee5bcSRichard Henderson } else { 19537c4ee5bcSRichard Henderson u_argc = sp; 19547c4ee5bcSRichard Henderson sp = QEMU_ALIGN_UP(sp + size, STACK_ALIGNMENT); 19557c4ee5bcSRichard Henderson } 19567c4ee5bcSRichard Henderson 19577c4ee5bcSRichard Henderson u_argv = u_argc + n; 19587c4ee5bcSRichard Henderson u_envp = u_argv + (argc + 1) * n; 19597c4ee5bcSRichard Henderson u_auxv = u_envp + (envc + 1) * n; 19607c4ee5bcSRichard Henderson info->saved_auxv = u_auxv; 19617c4ee5bcSRichard Henderson info->arg_start = u_argv; 19627c4ee5bcSRichard Henderson info->arg_end = u_argv + argc * n; 1963f5155289Sbellard 1964863cf0b7Sj_mayer /* This is correct because Linux defines 1965863cf0b7Sj_mayer * elf_addr_t as Elf32_Off / Elf64_Off 1966863cf0b7Sj_mayer */ 196753a5960aSpbrook #define NEW_AUX_ENT(id, val) do { \ 19687c4ee5bcSRichard Henderson put_user_ual(id, u_auxv); u_auxv += n; \ 19697c4ee5bcSRichard Henderson put_user_ual(val, u_auxv); u_auxv += n; \ 197053a5960aSpbrook } while(0) 19712f619698Sbellard 197282991bedSPeter Maydell #ifdef ARCH_DLINFO 197382991bedSPeter Maydell /* 197482991bedSPeter Maydell * ARCH_DLINFO must come first so platform specific code can enforce 197582991bedSPeter Maydell * special alignment requirements on the AUXV if necessary (eg. PPC). 197682991bedSPeter Maydell */ 197782991bedSPeter Maydell ARCH_DLINFO; 197882991bedSPeter Maydell #endif 1979f516511eSPeter Maydell /* There must be exactly DLINFO_ITEMS entries here, or the assert 1980f516511eSPeter Maydell * on info->auxv_len will trigger. 1981f516511eSPeter Maydell */ 19828e62a717SRichard Henderson NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff)); 1983992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); 1984992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); 198533143c44SLaurent Vivier if ((info->alignment & ~qemu_host_page_mask) != 0) { 198633143c44SLaurent Vivier /* Target doesn't support host page size alignment */ 198733143c44SLaurent Vivier NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE)); 198833143c44SLaurent Vivier } else { 198933143c44SLaurent Vivier NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE, 199033143c44SLaurent Vivier qemu_host_page_size))); 199133143c44SLaurent Vivier } 19928e62a717SRichard Henderson NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0)); 1993992f48a0Sblueswir1 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); 19948e62a717SRichard Henderson NEW_AUX_ENT(AT_ENTRY, info->entry); 1995992f48a0Sblueswir1 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); 1996992f48a0Sblueswir1 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); 1997992f48a0Sblueswir1 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); 1998992f48a0Sblueswir1 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); 1999992f48a0Sblueswir1 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); 2000a07c67dfSpbrook NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); 200114322badSLaurent ALFONSI NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes); 2002444cd5c3SMarco A L Barbosa NEW_AUX_ENT(AT_SECURE, (abi_ulong) qemu_getauxval(AT_SECURE)); 2003e0d1673dSLirong Yuan NEW_AUX_ENT(AT_EXECFN, info->file_string); 200414322badSLaurent ALFONSI 2005ad6919dcSPeter Maydell #ifdef ELF_HWCAP2 2006ad6919dcSPeter Maydell NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); 2007ad6919dcSPeter Maydell #endif 2008ad6919dcSPeter Maydell 20097c4ee5bcSRichard Henderson if (u_platform) { 201053a5960aSpbrook NEW_AUX_ENT(AT_PLATFORM, u_platform); 20117c4ee5bcSRichard Henderson } 20127c4ee5bcSRichard Henderson NEW_AUX_ENT (AT_NULL, 0); 2013f5155289Sbellard #undef NEW_AUX_ENT 2014f5155289Sbellard 2015f516511eSPeter Maydell /* Check that our initial calculation of the auxv length matches how much 2016f516511eSPeter Maydell * we actually put into it. 2017f516511eSPeter Maydell */ 2018f516511eSPeter Maydell assert(info->auxv_len == u_auxv - info->saved_auxv); 2019edf8e2afSMika Westerberg 20207c4ee5bcSRichard Henderson put_user_ual(argc, u_argc); 20217c4ee5bcSRichard Henderson 20227c4ee5bcSRichard Henderson p = info->arg_strings; 20237c4ee5bcSRichard Henderson for (i = 0; i < argc; ++i) { 20247c4ee5bcSRichard Henderson put_user_ual(p, u_argv); 20257c4ee5bcSRichard Henderson u_argv += n; 20267c4ee5bcSRichard Henderson p += target_strlen(p) + 1; 20277c4ee5bcSRichard Henderson } 20287c4ee5bcSRichard Henderson put_user_ual(0, u_argv); 20297c4ee5bcSRichard Henderson 20307c4ee5bcSRichard Henderson p = info->env_strings; 20317c4ee5bcSRichard Henderson for (i = 0; i < envc; ++i) { 20327c4ee5bcSRichard Henderson put_user_ual(p, u_envp); 20337c4ee5bcSRichard Henderson u_envp += n; 20347c4ee5bcSRichard Henderson p += target_strlen(p) + 1; 20357c4ee5bcSRichard Henderson } 20367c4ee5bcSRichard Henderson put_user_ual(0, u_envp); 20377c4ee5bcSRichard Henderson 203831e31b8aSbellard return sp; 203931e31b8aSbellard } 204031e31b8aSbellard 2041*ee947430SAlex Bennée #ifndef ARM_COMMPAGE 2042*ee947430SAlex Bennée #define ARM_COMMPAGE 0 2043*ee947430SAlex Bennée #define init_guest_commpage() true 2044*ee947430SAlex Bennée #endif 2045*ee947430SAlex Bennée 2046*ee947430SAlex Bennée static void pgb_fail_in_use(const char *image_name) 2047*ee947430SAlex Bennée { 2048*ee947430SAlex Bennée error_report("%s: requires virtual address space that is in use " 2049*ee947430SAlex Bennée "(omit the -B option or choose a different value)", 2050*ee947430SAlex Bennée image_name); 2051*ee947430SAlex Bennée exit(EXIT_FAILURE); 2052*ee947430SAlex Bennée } 2053*ee947430SAlex Bennée 2054*ee947430SAlex Bennée static void pgb_have_guest_base(const char *image_name, abi_ulong guest_loaddr, 2055*ee947430SAlex Bennée abi_ulong guest_hiaddr, long align) 2056*ee947430SAlex Bennée { 2057*ee947430SAlex Bennée const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; 2058*ee947430SAlex Bennée void *addr, *test; 2059*ee947430SAlex Bennée 2060*ee947430SAlex Bennée if (!QEMU_IS_ALIGNED(guest_base, align)) { 2061*ee947430SAlex Bennée fprintf(stderr, "Requested guest base 0x%lx does not satisfy " 2062*ee947430SAlex Bennée "host minimum alignment (0x%lx)\n", 2063*ee947430SAlex Bennée guest_base, align); 2064*ee947430SAlex Bennée exit(EXIT_FAILURE); 2065*ee947430SAlex Bennée } 2066*ee947430SAlex Bennée 2067*ee947430SAlex Bennée /* Sanity check the guest binary. */ 2068*ee947430SAlex Bennée if (reserved_va) { 2069*ee947430SAlex Bennée if (guest_hiaddr > reserved_va) { 2070*ee947430SAlex Bennée error_report("%s: requires more than reserved virtual " 2071*ee947430SAlex Bennée "address space (0x%" PRIx64 " > 0x%lx)", 2072*ee947430SAlex Bennée image_name, (uint64_t)guest_hiaddr, reserved_va); 2073*ee947430SAlex Bennée exit(EXIT_FAILURE); 2074*ee947430SAlex Bennée } 2075*ee947430SAlex Bennée } else { 2076*ee947430SAlex Bennée if ((guest_hiaddr - guest_base) > ~(uintptr_t)0) { 2077*ee947430SAlex Bennée error_report("%s: requires more virtual address space " 2078*ee947430SAlex Bennée "than the host can provide (0x%" PRIx64 ")", 2079*ee947430SAlex Bennée image_name, (uint64_t)guest_hiaddr - guest_base); 2080*ee947430SAlex Bennée exit(EXIT_FAILURE); 2081*ee947430SAlex Bennée } 2082*ee947430SAlex Bennée } 2083*ee947430SAlex Bennée 2084*ee947430SAlex Bennée /* 2085*ee947430SAlex Bennée * Expand the allocation to the entire reserved_va. 2086*ee947430SAlex Bennée * Exclude the mmap_min_addr hole. 2087*ee947430SAlex Bennée */ 2088*ee947430SAlex Bennée if (reserved_va) { 2089*ee947430SAlex Bennée guest_loaddr = (guest_base >= mmap_min_addr ? 0 2090*ee947430SAlex Bennée : mmap_min_addr - guest_base); 2091*ee947430SAlex Bennée guest_hiaddr = reserved_va; 2092*ee947430SAlex Bennée } 2093*ee947430SAlex Bennée 2094*ee947430SAlex Bennée /* Reserve the address space for the binary, or reserved_va. */ 2095*ee947430SAlex Bennée test = g2h(guest_loaddr); 2096*ee947430SAlex Bennée addr = mmap(test, guest_hiaddr - guest_loaddr, PROT_NONE, flags, -1, 0); 2097*ee947430SAlex Bennée if (test != addr) { 2098*ee947430SAlex Bennée pgb_fail_in_use(image_name); 2099*ee947430SAlex Bennée } 2100*ee947430SAlex Bennée } 2101*ee947430SAlex Bennée 2102*ee947430SAlex Bennée /* Return value for guest_base, or -1 if no hole found. */ 2103*ee947430SAlex Bennée static uintptr_t pgb_find_hole(uintptr_t guest_loaddr, uintptr_t guest_size, 2104*ee947430SAlex Bennée long align) 2105*ee947430SAlex Bennée { 2106*ee947430SAlex Bennée GSList *maps, *iter; 2107*ee947430SAlex Bennée uintptr_t this_start, this_end, next_start, brk; 2108*ee947430SAlex Bennée intptr_t ret = -1; 2109*ee947430SAlex Bennée 2110*ee947430SAlex Bennée assert(QEMU_IS_ALIGNED(guest_loaddr, align)); 2111*ee947430SAlex Bennée 2112*ee947430SAlex Bennée maps = read_self_maps(); 2113*ee947430SAlex Bennée 2114*ee947430SAlex Bennée /* Read brk after we've read the maps, which will malloc. */ 2115*ee947430SAlex Bennée brk = (uintptr_t)sbrk(0); 2116*ee947430SAlex Bennée 2117*ee947430SAlex Bennée /* The first hole is before the first map entry. */ 2118*ee947430SAlex Bennée this_start = mmap_min_addr; 2119*ee947430SAlex Bennée 2120*ee947430SAlex Bennée for (iter = maps; iter; 2121*ee947430SAlex Bennée this_start = next_start, iter = g_slist_next(iter)) { 2122*ee947430SAlex Bennée uintptr_t align_start, hole_size; 2123*ee947430SAlex Bennée 2124*ee947430SAlex Bennée this_end = ((MapInfo *)iter->data)->start; 2125*ee947430SAlex Bennée next_start = ((MapInfo *)iter->data)->end; 2126*ee947430SAlex Bennée align_start = ROUND_UP(this_start, align); 2127*ee947430SAlex Bennée 2128*ee947430SAlex Bennée /* Skip holes that are too small. */ 2129*ee947430SAlex Bennée if (align_start >= this_end) { 2130*ee947430SAlex Bennée continue; 2131*ee947430SAlex Bennée } 2132*ee947430SAlex Bennée hole_size = this_end - align_start; 2133*ee947430SAlex Bennée if (hole_size < guest_size) { 2134*ee947430SAlex Bennée continue; 2135*ee947430SAlex Bennée } 2136*ee947430SAlex Bennée 2137*ee947430SAlex Bennée /* If this hole contains brk, give ourselves some room to grow. */ 2138*ee947430SAlex Bennée if (this_start <= brk && brk < this_end) { 2139*ee947430SAlex Bennée hole_size -= guest_size; 2140*ee947430SAlex Bennée if (sizeof(uintptr_t) == 8 && hole_size >= 1 * GiB) { 2141*ee947430SAlex Bennée align_start += 1 * GiB; 2142*ee947430SAlex Bennée } else if (hole_size >= 16 * MiB) { 2143*ee947430SAlex Bennée align_start += 16 * MiB; 2144*ee947430SAlex Bennée } else { 2145*ee947430SAlex Bennée align_start = (this_end - guest_size) & -align; 2146*ee947430SAlex Bennée if (align_start < this_start) { 2147*ee947430SAlex Bennée continue; 2148*ee947430SAlex Bennée } 2149*ee947430SAlex Bennée } 2150*ee947430SAlex Bennée } 2151*ee947430SAlex Bennée 2152*ee947430SAlex Bennée /* Record the lowest successful match. */ 2153*ee947430SAlex Bennée if (ret < 0) { 2154*ee947430SAlex Bennée ret = align_start - guest_loaddr; 2155*ee947430SAlex Bennée } 2156*ee947430SAlex Bennée /* If this hole contains the identity map, select it. */ 2157*ee947430SAlex Bennée if (align_start <= guest_loaddr && 2158*ee947430SAlex Bennée guest_loaddr + guest_size <= this_end) { 2159*ee947430SAlex Bennée ret = 0; 2160*ee947430SAlex Bennée } 2161*ee947430SAlex Bennée /* If this hole ends above the identity map, stop looking. */ 2162*ee947430SAlex Bennée if (this_end >= guest_loaddr) { 2163*ee947430SAlex Bennée break; 2164*ee947430SAlex Bennée } 2165*ee947430SAlex Bennée } 2166*ee947430SAlex Bennée free_self_maps(maps); 2167*ee947430SAlex Bennée 2168*ee947430SAlex Bennée return ret; 2169*ee947430SAlex Bennée } 2170*ee947430SAlex Bennée 2171*ee947430SAlex Bennée static void pgb_static(const char *image_name, abi_ulong orig_loaddr, 2172*ee947430SAlex Bennée abi_ulong orig_hiaddr, long align) 2173*ee947430SAlex Bennée { 2174*ee947430SAlex Bennée uintptr_t loaddr = orig_loaddr; 2175*ee947430SAlex Bennée uintptr_t hiaddr = orig_hiaddr; 2176*ee947430SAlex Bennée uintptr_t addr; 2177*ee947430SAlex Bennée 2178*ee947430SAlex Bennée if (hiaddr != orig_hiaddr) { 2179*ee947430SAlex Bennée error_report("%s: requires virtual address space that the " 2180*ee947430SAlex Bennée "host cannot provide (0x%" PRIx64 ")", 2181*ee947430SAlex Bennée image_name, (uint64_t)orig_hiaddr); 2182*ee947430SAlex Bennée exit(EXIT_FAILURE); 2183*ee947430SAlex Bennée } 2184*ee947430SAlex Bennée 2185*ee947430SAlex Bennée loaddr &= -align; 2186*ee947430SAlex Bennée if (ARM_COMMPAGE) { 2187*ee947430SAlex Bennée /* 2188*ee947430SAlex Bennée * Extend the allocation to include the commpage. 2189*ee947430SAlex Bennée * For a 64-bit host, this is just 4GiB; for a 32-bit host, 2190*ee947430SAlex Bennée * the address arithmetic will wrap around, but the difference 2191*ee947430SAlex Bennée * will produce the correct allocation size. 2192*ee947430SAlex Bennée */ 2193*ee947430SAlex Bennée if (sizeof(uintptr_t) == 8 || loaddr >= 0x80000000u) { 2194*ee947430SAlex Bennée hiaddr = (uintptr_t)4 << 30; 2195*ee947430SAlex Bennée } else { 2196*ee947430SAlex Bennée loaddr = ARM_COMMPAGE & -align; 2197*ee947430SAlex Bennée } 2198*ee947430SAlex Bennée } 2199*ee947430SAlex Bennée 2200*ee947430SAlex Bennée addr = pgb_find_hole(loaddr, hiaddr - loaddr, align); 2201*ee947430SAlex Bennée if (addr == -1) { 2202*ee947430SAlex Bennée /* 2203*ee947430SAlex Bennée * If ARM_COMMPAGE, there *might* be a non-consecutive allocation 2204*ee947430SAlex Bennée * that can satisfy both. But as the normal arm32 link base address 2205*ee947430SAlex Bennée * is ~32k, and we extend down to include the commpage, making the 2206*ee947430SAlex Bennée * overhead only ~96k, this is unlikely. 2207*ee947430SAlex Bennée */ 2208*ee947430SAlex Bennée error_report("%s: Unable to allocate %#zx bytes of " 2209*ee947430SAlex Bennée "virtual address space", image_name, 2210*ee947430SAlex Bennée (size_t)(hiaddr - loaddr)); 2211*ee947430SAlex Bennée exit(EXIT_FAILURE); 2212*ee947430SAlex Bennée } 2213*ee947430SAlex Bennée 2214*ee947430SAlex Bennée guest_base = addr; 2215*ee947430SAlex Bennée } 2216*ee947430SAlex Bennée 2217*ee947430SAlex Bennée static void pgb_dynamic(const char *image_name, long align) 2218*ee947430SAlex Bennée { 2219*ee947430SAlex Bennée /* 2220*ee947430SAlex Bennée * The executable is dynamic and does not require a fixed address. 2221*ee947430SAlex Bennée * All we need is a commpage that satisfies align. 2222*ee947430SAlex Bennée * If we do not need a commpage, leave guest_base == 0. 2223*ee947430SAlex Bennée */ 2224*ee947430SAlex Bennée if (ARM_COMMPAGE) { 2225*ee947430SAlex Bennée uintptr_t addr, commpage; 2226*ee947430SAlex Bennée 2227*ee947430SAlex Bennée /* 64-bit hosts should have used reserved_va. */ 2228*ee947430SAlex Bennée assert(sizeof(uintptr_t) == 4); 2229*ee947430SAlex Bennée 2230*ee947430SAlex Bennée /* 2231*ee947430SAlex Bennée * By putting the commpage at the first hole, that puts guest_base 2232*ee947430SAlex Bennée * just above that, and maximises the positive guest addresses. 2233*ee947430SAlex Bennée */ 2234*ee947430SAlex Bennée commpage = ARM_COMMPAGE & -align; 2235*ee947430SAlex Bennée addr = pgb_find_hole(commpage, -commpage, align); 2236*ee947430SAlex Bennée assert(addr != -1); 2237*ee947430SAlex Bennée guest_base = addr; 2238*ee947430SAlex Bennée } 2239*ee947430SAlex Bennée } 2240*ee947430SAlex Bennée 2241*ee947430SAlex Bennée static void pgb_reserved_va(const char *image_name, abi_ulong guest_loaddr, 2242*ee947430SAlex Bennée abi_ulong guest_hiaddr, long align) 2243*ee947430SAlex Bennée { 2244*ee947430SAlex Bennée const int flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; 2245*ee947430SAlex Bennée void *addr, *test; 2246*ee947430SAlex Bennée 2247*ee947430SAlex Bennée if (guest_hiaddr > reserved_va) { 2248*ee947430SAlex Bennée error_report("%s: requires more than reserved virtual " 2249*ee947430SAlex Bennée "address space (0x%" PRIx64 " > 0x%lx)", 2250*ee947430SAlex Bennée image_name, (uint64_t)guest_hiaddr, reserved_va); 2251*ee947430SAlex Bennée exit(EXIT_FAILURE); 2252*ee947430SAlex Bennée } 2253*ee947430SAlex Bennée 2254*ee947430SAlex Bennée /* Widen the "image" to the entire reserved address space. */ 2255*ee947430SAlex Bennée pgb_static(image_name, 0, reserved_va, align); 2256*ee947430SAlex Bennée 2257*ee947430SAlex Bennée /* Reserve the memory on the host. */ 2258*ee947430SAlex Bennée assert(guest_base != 0); 2259*ee947430SAlex Bennée test = g2h(0); 2260*ee947430SAlex Bennée addr = mmap(test, reserved_va, PROT_NONE, flags, -1, 0); 2261*ee947430SAlex Bennée if (addr == MAP_FAILED) { 2262*ee947430SAlex Bennée error_report("Unable to reserve 0x%lx bytes of virtual address " 2263*ee947430SAlex Bennée "space for use as guest address space (check your " 2264*ee947430SAlex Bennée "virtual memory ulimit setting or reserve less " 2265*ee947430SAlex Bennée "using -R option)", reserved_va); 2266*ee947430SAlex Bennée exit(EXIT_FAILURE); 2267*ee947430SAlex Bennée } 2268*ee947430SAlex Bennée assert(addr == test); 2269*ee947430SAlex Bennée } 2270*ee947430SAlex Bennée 2271*ee947430SAlex Bennée void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, 2272*ee947430SAlex Bennée abi_ulong guest_hiaddr) 2273dce10401SMeador Inge { 227430ab9ef2SRichard Henderson /* In order to use host shmat, we must be able to honor SHMLBA. */ 2275*ee947430SAlex Bennée uintptr_t align = MAX(SHMLBA, qemu_host_page_size); 2276dce10401SMeador Inge 2277*ee947430SAlex Bennée if (have_guest_base) { 2278*ee947430SAlex Bennée pgb_have_guest_base(image_name, guest_loaddr, guest_hiaddr, align); 2279*ee947430SAlex Bennée } else if (reserved_va) { 2280*ee947430SAlex Bennée pgb_reserved_va(image_name, guest_loaddr, guest_hiaddr, align); 2281*ee947430SAlex Bennée } else if (guest_loaddr) { 2282*ee947430SAlex Bennée pgb_static(image_name, guest_loaddr, guest_hiaddr, align); 2283293f2060SLuke Shumaker } else { 2284*ee947430SAlex Bennée pgb_dynamic(image_name, align); 2285806d1021SMeador Inge } 2286806d1021SMeador Inge 2287*ee947430SAlex Bennée /* Reserve and initialize the commpage. */ 2288*ee947430SAlex Bennée if (!init_guest_commpage()) { 2289*ee947430SAlex Bennée /* 2290*ee947430SAlex Bennée * With have_guest_base, the user has selected the address and 2291*ee947430SAlex Bennée * we are trying to work with that. Otherwise, we have selected 2292*ee947430SAlex Bennée * free space and init_guest_commpage must succeeded. 22937ad75eeaSLuke Shumaker */ 2294*ee947430SAlex Bennée assert(have_guest_base); 2295*ee947430SAlex Bennée pgb_fail_in_use(image_name); 2296dce10401SMeador Inge } 2297dce10401SMeador Inge 2298*ee947430SAlex Bennée assert(QEMU_IS_ALIGNED(guest_base, align)); 2299*ee947430SAlex Bennée qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space " 2300*ee947430SAlex Bennée "@ 0x%" PRIx64 "\n", (uint64_t)guest_base); 2301dce10401SMeador Inge } 2302dce10401SMeador Inge 23038e62a717SRichard Henderson /* Load an ELF image into the address space. 230431e31b8aSbellard 23058e62a717SRichard Henderson IMAGE_NAME is the filename of the image, to use in error messages. 23068e62a717SRichard Henderson IMAGE_FD is the open file descriptor for the image. 23078e62a717SRichard Henderson 23088e62a717SRichard Henderson BPRM_BUF is a copy of the beginning of the file; this of course 23098e62a717SRichard Henderson contains the elf file header at offset 0. It is assumed that this 23108e62a717SRichard Henderson buffer is sufficiently aligned to present no problems to the host 23118e62a717SRichard Henderson in accessing data at aligned offsets within the buffer. 23128e62a717SRichard Henderson 23138e62a717SRichard Henderson On return: INFO values will be filled in, as necessary or available. */ 23148e62a717SRichard Henderson 23158e62a717SRichard Henderson static void load_elf_image(const char *image_name, int image_fd, 2316bf858897SRichard Henderson struct image_info *info, char **pinterp_name, 23179955ffacSRichard Henderson char bprm_buf[BPRM_BUF_SIZE]) 231831e31b8aSbellard { 23198e62a717SRichard Henderson struct elfhdr *ehdr = (struct elfhdr *)bprm_buf; 23208e62a717SRichard Henderson struct elf_phdr *phdr; 23218e62a717SRichard Henderson abi_ulong load_addr, load_bias, loaddr, hiaddr, error; 23228e62a717SRichard Henderson int i, retval; 23238e62a717SRichard Henderson const char *errmsg; 232431e31b8aSbellard 23258e62a717SRichard Henderson /* First of all, some simple consistency checks */ 23268e62a717SRichard Henderson errmsg = "Invalid ELF image for this architecture"; 23278e62a717SRichard Henderson if (!elf_check_ident(ehdr)) { 23288e62a717SRichard Henderson goto exit_errmsg; 23298e62a717SRichard Henderson } 23308e62a717SRichard Henderson bswap_ehdr(ehdr); 23318e62a717SRichard Henderson if (!elf_check_ehdr(ehdr)) { 23328e62a717SRichard Henderson goto exit_errmsg; 233331e31b8aSbellard } 233431e31b8aSbellard 23358e62a717SRichard Henderson i = ehdr->e_phnum * sizeof(struct elf_phdr); 23368e62a717SRichard Henderson if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) { 23378e62a717SRichard Henderson phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff); 23389955ffacSRichard Henderson } else { 23398e62a717SRichard Henderson phdr = (struct elf_phdr *) alloca(i); 23408e62a717SRichard Henderson retval = pread(image_fd, phdr, i, ehdr->e_phoff); 23419955ffacSRichard Henderson if (retval != i) { 23428e62a717SRichard Henderson goto exit_read; 23439955ffacSRichard Henderson } 234431e31b8aSbellard } 23458e62a717SRichard Henderson bswap_phdr(phdr, ehdr->e_phnum); 234609bfb054Sbellard 23471af02e83SMike Frysinger info->nsegs = 0; 23481af02e83SMike Frysinger info->pt_dynamic_addr = 0; 23491af02e83SMike Frysinger 235098c1076cSAlex Bennée mmap_lock(); 235198c1076cSAlex Bennée 2352682674b8SRichard Henderson /* Find the maximum size of the image and allocate an appropriate 2353682674b8SRichard Henderson amount of memory to handle that. */ 2354682674b8SRichard Henderson loaddr = -1, hiaddr = 0; 235533143c44SLaurent Vivier info->alignment = 0; 23568e62a717SRichard Henderson for (i = 0; i < ehdr->e_phnum; ++i) { 23578e62a717SRichard Henderson if (phdr[i].p_type == PT_LOAD) { 2358a93934feSJonas Maebe abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset; 2359682674b8SRichard Henderson if (a < loaddr) { 2360682674b8SRichard Henderson loaddr = a; 2361682674b8SRichard Henderson } 2362ccf661f8STom Musta a = phdr[i].p_vaddr + phdr[i].p_memsz; 2363682674b8SRichard Henderson if (a > hiaddr) { 2364682674b8SRichard Henderson hiaddr = a; 2365682674b8SRichard Henderson } 23661af02e83SMike Frysinger ++info->nsegs; 236733143c44SLaurent Vivier info->alignment |= phdr[i].p_align; 2368682674b8SRichard Henderson } 2369682674b8SRichard Henderson } 2370682674b8SRichard Henderson 23716fd59449SRichard Henderson if (pinterp_name != NULL) { 23726fd59449SRichard Henderson /* 23736fd59449SRichard Henderson * This is the main executable. 23746fd59449SRichard Henderson * 23756fd59449SRichard Henderson * Reserve extra space for brk. 23766fd59449SRichard Henderson * We hold on to this space while placing the interpreter 23776fd59449SRichard Henderson * and the stack, lest they be placed immediately after 23786fd59449SRichard Henderson * the data segment and block allocation from the brk. 23796fd59449SRichard Henderson * 23806fd59449SRichard Henderson * 16MB is chosen as "large enough" without being so large 23816fd59449SRichard Henderson * as to allow the result to not fit with a 32-bit guest on 23826fd59449SRichard Henderson * a 32-bit host. 23836fd59449SRichard Henderson */ 23846fd59449SRichard Henderson info->reserve_brk = 16 * MiB; 23856fd59449SRichard Henderson hiaddr += info->reserve_brk; 23866fd59449SRichard Henderson 23876fd59449SRichard Henderson if (ehdr->e_type == ET_EXEC) { 23886fd59449SRichard Henderson /* 23896fd59449SRichard Henderson * Make sure that the low address does not conflict with 23906fd59449SRichard Henderson * MMAP_MIN_ADDR or the QEMU application itself. 23916fd59449SRichard Henderson */ 23926fd59449SRichard Henderson probe_guest_base(image_name, loaddr, hiaddr); 2393*ee947430SAlex Bennée } else { 2394*ee947430SAlex Bennée /* 2395*ee947430SAlex Bennée * The binary is dynamic, but we still need to 2396*ee947430SAlex Bennée * select guest_base. In this case we pass a size. 2397*ee947430SAlex Bennée */ 2398*ee947430SAlex Bennée probe_guest_base(image_name, 0, hiaddr - loaddr); 23996fd59449SRichard Henderson } 24006fd59449SRichard Henderson } 24016fd59449SRichard Henderson 24026fd59449SRichard Henderson /* 24036fd59449SRichard Henderson * Reserve address space for all of this. 24046fd59449SRichard Henderson * 24056fd59449SRichard Henderson * In the case of ET_EXEC, we supply MAP_FIXED so that we get 24066fd59449SRichard Henderson * exactly the address range that is required. 24076fd59449SRichard Henderson * 24086fd59449SRichard Henderson * Otherwise this is ET_DYN, and we are searching for a location 24096fd59449SRichard Henderson * that can hold the memory space required. If the image is 24106fd59449SRichard Henderson * pre-linked, LOADDR will be non-zero, and the kernel should 24116fd59449SRichard Henderson * honor that address if it happens to be free. 24126fd59449SRichard Henderson * 24136fd59449SRichard Henderson * In both cases, we will overwrite pages in this range with mappings 24146fd59449SRichard Henderson * from the executable. 24156fd59449SRichard Henderson */ 2416682674b8SRichard Henderson load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE, 24176fd59449SRichard Henderson MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | 24186fd59449SRichard Henderson (ehdr->e_type == ET_EXEC ? MAP_FIXED : 0), 241909bfb054Sbellard -1, 0); 2420682674b8SRichard Henderson if (load_addr == -1) { 24218e62a717SRichard Henderson goto exit_perror; 242209bfb054Sbellard } 2423682674b8SRichard Henderson load_bias = load_addr - loaddr; 242409bfb054Sbellard 2425a99856cdSChristophe Lyon if (elf_is_fdpic(ehdr)) { 24261af02e83SMike Frysinger struct elf32_fdpic_loadseg *loadsegs = info->loadsegs = 24277267c094SAnthony Liguori g_malloc(sizeof(*loadsegs) * info->nsegs); 24281af02e83SMike Frysinger 24291af02e83SMike Frysinger for (i = 0; i < ehdr->e_phnum; ++i) { 24301af02e83SMike Frysinger switch (phdr[i].p_type) { 24311af02e83SMike Frysinger case PT_DYNAMIC: 24321af02e83SMike Frysinger info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias; 24331af02e83SMike Frysinger break; 24341af02e83SMike Frysinger case PT_LOAD: 24351af02e83SMike Frysinger loadsegs->addr = phdr[i].p_vaddr + load_bias; 24361af02e83SMike Frysinger loadsegs->p_vaddr = phdr[i].p_vaddr; 24371af02e83SMike Frysinger loadsegs->p_memsz = phdr[i].p_memsz; 24381af02e83SMike Frysinger ++loadsegs; 24391af02e83SMike Frysinger break; 24401af02e83SMike Frysinger } 24411af02e83SMike Frysinger } 24421af02e83SMike Frysinger } 24431af02e83SMike Frysinger 24448e62a717SRichard Henderson info->load_bias = load_bias; 2445dc12567aSJosh Kunz info->code_offset = load_bias; 2446dc12567aSJosh Kunz info->data_offset = load_bias; 24478e62a717SRichard Henderson info->load_addr = load_addr; 24488e62a717SRichard Henderson info->entry = ehdr->e_entry + load_bias; 24498e62a717SRichard Henderson info->start_code = -1; 24508e62a717SRichard Henderson info->end_code = 0; 24518e62a717SRichard Henderson info->start_data = -1; 24528e62a717SRichard Henderson info->end_data = 0; 24538e62a717SRichard Henderson info->brk = 0; 2454d8fd2954SPaul Brook info->elf_flags = ehdr->e_flags; 24558e62a717SRichard Henderson 24568e62a717SRichard Henderson for (i = 0; i < ehdr->e_phnum; i++) { 24578e62a717SRichard Henderson struct elf_phdr *eppnt = phdr + i; 245831e31b8aSbellard if (eppnt->p_type == PT_LOAD) { 245994894ff2SShivaprasad G Bhat abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em, vaddr_len; 246031e31b8aSbellard int elf_prot = 0; 246131e31b8aSbellard 246231e31b8aSbellard if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; 246331e31b8aSbellard if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 246431e31b8aSbellard if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 246531e31b8aSbellard 2466682674b8SRichard Henderson vaddr = load_bias + eppnt->p_vaddr; 2467682674b8SRichard Henderson vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr); 2468682674b8SRichard Henderson vaddr_ps = TARGET_ELF_PAGESTART(vaddr); 246994894ff2SShivaprasad G Bhat vaddr_len = TARGET_ELF_PAGELENGTH(eppnt->p_filesz + vaddr_po); 2470682674b8SRichard Henderson 2471d87146bcSGiuseppe Musacchio /* 2472d87146bcSGiuseppe Musacchio * Some segments may be completely empty without any backing file 2473d87146bcSGiuseppe Musacchio * segment, in that case just let zero_bss allocate an empty buffer 2474d87146bcSGiuseppe Musacchio * for it. 2475d87146bcSGiuseppe Musacchio */ 2476d87146bcSGiuseppe Musacchio if (eppnt->p_filesz != 0) { 2477d87146bcSGiuseppe Musacchio error = target_mmap(vaddr_ps, vaddr_len, elf_prot, 2478d87146bcSGiuseppe Musacchio MAP_PRIVATE | MAP_FIXED, 24798e62a717SRichard Henderson image_fd, eppnt->p_offset - vaddr_po); 2480d87146bcSGiuseppe Musacchio 2481e89f07d3Spbrook if (error == -1) { 24828e62a717SRichard Henderson goto exit_perror; 248331e31b8aSbellard } 2484d87146bcSGiuseppe Musacchio } 248531e31b8aSbellard 2486682674b8SRichard Henderson vaddr_ef = vaddr + eppnt->p_filesz; 2487682674b8SRichard Henderson vaddr_em = vaddr + eppnt->p_memsz; 248831e31b8aSbellard 2489cf129f3aSRichard Henderson /* If the load segment requests extra zeros (e.g. bss), map it. */ 2490682674b8SRichard Henderson if (vaddr_ef < vaddr_em) { 2491682674b8SRichard Henderson zero_bss(vaddr_ef, vaddr_em, elf_prot); 2492682674b8SRichard Henderson } 24938e62a717SRichard Henderson 24948e62a717SRichard Henderson /* Find the full program boundaries. */ 24958e62a717SRichard Henderson if (elf_prot & PROT_EXEC) { 24968e62a717SRichard Henderson if (vaddr < info->start_code) { 24978e62a717SRichard Henderson info->start_code = vaddr; 2498cf129f3aSRichard Henderson } 24998e62a717SRichard Henderson if (vaddr_ef > info->end_code) { 25008e62a717SRichard Henderson info->end_code = vaddr_ef; 25018e62a717SRichard Henderson } 25028e62a717SRichard Henderson } 25038e62a717SRichard Henderson if (elf_prot & PROT_WRITE) { 25048e62a717SRichard Henderson if (vaddr < info->start_data) { 25058e62a717SRichard Henderson info->start_data = vaddr; 25068e62a717SRichard Henderson } 25078e62a717SRichard Henderson if (vaddr_ef > info->end_data) { 25088e62a717SRichard Henderson info->end_data = vaddr_ef; 25098e62a717SRichard Henderson } 25108e62a717SRichard Henderson if (vaddr_em > info->brk) { 25118e62a717SRichard Henderson info->brk = vaddr_em; 25128e62a717SRichard Henderson } 25138e62a717SRichard Henderson } 2514bf858897SRichard Henderson } else if (eppnt->p_type == PT_INTERP && pinterp_name) { 2515bf858897SRichard Henderson char *interp_name; 2516bf858897SRichard Henderson 2517bf858897SRichard Henderson if (*pinterp_name) { 2518bf858897SRichard Henderson errmsg = "Multiple PT_INTERP entries"; 2519bf858897SRichard Henderson goto exit_errmsg; 2520bf858897SRichard Henderson } 2521bf858897SRichard Henderson interp_name = malloc(eppnt->p_filesz); 2522bf858897SRichard Henderson if (!interp_name) { 2523bf858897SRichard Henderson goto exit_perror; 2524bf858897SRichard Henderson } 2525bf858897SRichard Henderson 2526bf858897SRichard Henderson if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) { 2527bf858897SRichard Henderson memcpy(interp_name, bprm_buf + eppnt->p_offset, 2528bf858897SRichard Henderson eppnt->p_filesz); 2529bf858897SRichard Henderson } else { 2530bf858897SRichard Henderson retval = pread(image_fd, interp_name, eppnt->p_filesz, 2531bf858897SRichard Henderson eppnt->p_offset); 2532bf858897SRichard Henderson if (retval != eppnt->p_filesz) { 2533bf858897SRichard Henderson goto exit_perror; 2534bf858897SRichard Henderson } 2535bf858897SRichard Henderson } 2536bf858897SRichard Henderson if (interp_name[eppnt->p_filesz - 1] != 0) { 2537bf858897SRichard Henderson errmsg = "Invalid PT_INTERP entry"; 2538bf858897SRichard Henderson goto exit_errmsg; 2539bf858897SRichard Henderson } 2540bf858897SRichard Henderson *pinterp_name = interp_name; 25415dd0db52SStefan Markovic #ifdef TARGET_MIPS 25425dd0db52SStefan Markovic } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) { 25435dd0db52SStefan Markovic Mips_elf_abiflags_v0 abiflags; 25445dd0db52SStefan Markovic if (eppnt->p_filesz < sizeof(Mips_elf_abiflags_v0)) { 25455dd0db52SStefan Markovic errmsg = "Invalid PT_MIPS_ABIFLAGS entry"; 25465dd0db52SStefan Markovic goto exit_errmsg; 25475dd0db52SStefan Markovic } 25485dd0db52SStefan Markovic if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) { 25495dd0db52SStefan Markovic memcpy(&abiflags, bprm_buf + eppnt->p_offset, 25505dd0db52SStefan Markovic sizeof(Mips_elf_abiflags_v0)); 25515dd0db52SStefan Markovic } else { 25525dd0db52SStefan Markovic retval = pread(image_fd, &abiflags, sizeof(Mips_elf_abiflags_v0), 25535dd0db52SStefan Markovic eppnt->p_offset); 25545dd0db52SStefan Markovic if (retval != sizeof(Mips_elf_abiflags_v0)) { 25555dd0db52SStefan Markovic goto exit_perror; 25565dd0db52SStefan Markovic } 25575dd0db52SStefan Markovic } 25585dd0db52SStefan Markovic bswap_mips_abiflags(&abiflags); 2559c94cb6c9SStefan Markovic info->fp_abi = abiflags.fp_abi; 25605dd0db52SStefan Markovic #endif 25618e62a717SRichard Henderson } 25628e62a717SRichard Henderson } 25638e62a717SRichard Henderson 25648e62a717SRichard Henderson if (info->end_data == 0) { 25658e62a717SRichard Henderson info->start_data = info->end_code; 25668e62a717SRichard Henderson info->end_data = info->end_code; 25678e62a717SRichard Henderson info->brk = info->end_code; 256831e31b8aSbellard } 256931e31b8aSbellard 2570682674b8SRichard Henderson if (qemu_log_enabled()) { 25718e62a717SRichard Henderson load_symbols(ehdr, image_fd, load_bias); 2572682674b8SRichard Henderson } 257331e31b8aSbellard 257498c1076cSAlex Bennée mmap_unlock(); 257598c1076cSAlex Bennée 25768e62a717SRichard Henderson close(image_fd); 25778e62a717SRichard Henderson return; 257831e31b8aSbellard 25798e62a717SRichard Henderson exit_read: 25808e62a717SRichard Henderson if (retval >= 0) { 25818e62a717SRichard Henderson errmsg = "Incomplete read of file header"; 25828e62a717SRichard Henderson goto exit_errmsg; 25838e62a717SRichard Henderson } 25848e62a717SRichard Henderson exit_perror: 25858e62a717SRichard Henderson errmsg = strerror(errno); 25868e62a717SRichard Henderson exit_errmsg: 25878e62a717SRichard Henderson fprintf(stderr, "%s: %s\n", image_name, errmsg); 25888e62a717SRichard Henderson exit(-1); 25898e62a717SRichard Henderson } 25908e62a717SRichard Henderson 25918e62a717SRichard Henderson static void load_elf_interp(const char *filename, struct image_info *info, 25928e62a717SRichard Henderson char bprm_buf[BPRM_BUF_SIZE]) 25938e62a717SRichard Henderson { 25948e62a717SRichard Henderson int fd, retval; 25958e62a717SRichard Henderson 25968e62a717SRichard Henderson fd = open(path(filename), O_RDONLY); 25978e62a717SRichard Henderson if (fd < 0) { 25988e62a717SRichard Henderson goto exit_perror; 25998e62a717SRichard Henderson } 26008e62a717SRichard Henderson 26018e62a717SRichard Henderson retval = read(fd, bprm_buf, BPRM_BUF_SIZE); 26028e62a717SRichard Henderson if (retval < 0) { 26038e62a717SRichard Henderson goto exit_perror; 26048e62a717SRichard Henderson } 26058e62a717SRichard Henderson if (retval < BPRM_BUF_SIZE) { 26068e62a717SRichard Henderson memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval); 26078e62a717SRichard Henderson } 26088e62a717SRichard Henderson 2609bf858897SRichard Henderson load_elf_image(filename, fd, info, NULL, bprm_buf); 26108e62a717SRichard Henderson return; 26118e62a717SRichard Henderson 26128e62a717SRichard Henderson exit_perror: 26138e62a717SRichard Henderson fprintf(stderr, "%s: %s\n", filename, strerror(errno)); 26148e62a717SRichard Henderson exit(-1); 261531e31b8aSbellard } 261631e31b8aSbellard 261749918a75Spbrook static int symfind(const void *s0, const void *s1) 261849918a75Spbrook { 2619c7c530cdSStefan Weil target_ulong addr = *(target_ulong *)s0; 262049918a75Spbrook struct elf_sym *sym = (struct elf_sym *)s1; 262149918a75Spbrook int result = 0; 2622c7c530cdSStefan Weil if (addr < sym->st_value) { 262349918a75Spbrook result = -1; 2624c7c530cdSStefan Weil } else if (addr >= sym->st_value + sym->st_size) { 262549918a75Spbrook result = 1; 262649918a75Spbrook } 262749918a75Spbrook return result; 262849918a75Spbrook } 262949918a75Spbrook 263049918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr) 263149918a75Spbrook { 263249918a75Spbrook #if ELF_CLASS == ELFCLASS32 263349918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf32; 263449918a75Spbrook #else 263549918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf64; 263649918a75Spbrook #endif 263749918a75Spbrook 263849918a75Spbrook // binary search 263949918a75Spbrook struct elf_sym *sym; 264049918a75Spbrook 2641c7c530cdSStefan Weil sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind); 26427cba04f6SBlue Swirl if (sym != NULL) { 264349918a75Spbrook return s->disas_strtab + sym->st_name; 264449918a75Spbrook } 264549918a75Spbrook 264649918a75Spbrook return ""; 264749918a75Spbrook } 264849918a75Spbrook 264949918a75Spbrook /* FIXME: This should use elf_ops.h */ 265049918a75Spbrook static int symcmp(const void *s0, const void *s1) 265149918a75Spbrook { 265249918a75Spbrook struct elf_sym *sym0 = (struct elf_sym *)s0; 265349918a75Spbrook struct elf_sym *sym1 = (struct elf_sym *)s1; 265449918a75Spbrook return (sym0->st_value < sym1->st_value) 265549918a75Spbrook ? -1 265649918a75Spbrook : ((sym0->st_value > sym1->st_value) ? 1 : 0); 265749918a75Spbrook } 265849918a75Spbrook 2659689f936fSbellard /* Best attempt to load symbols from this ELF object. */ 2660682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) 2661689f936fSbellard { 2662682674b8SRichard Henderson int i, shnum, nsyms, sym_idx = 0, str_idx = 0; 26631e06262dSPeter Maydell uint64_t segsz; 2664682674b8SRichard Henderson struct elf_shdr *shdr; 2665b9475279SCédric VINCENT char *strings = NULL; 2666b9475279SCédric VINCENT struct syminfo *s = NULL; 2667b9475279SCédric VINCENT struct elf_sym *new_syms, *syms = NULL; 266831e31b8aSbellard 2669682674b8SRichard Henderson shnum = hdr->e_shnum; 2670682674b8SRichard Henderson i = shnum * sizeof(struct elf_shdr); 2671682674b8SRichard Henderson shdr = (struct elf_shdr *)alloca(i); 2672682674b8SRichard Henderson if (pread(fd, shdr, i, hdr->e_shoff) != i) { 2673689f936fSbellard return; 2674682674b8SRichard Henderson } 2675682674b8SRichard Henderson 2676682674b8SRichard Henderson bswap_shdr(shdr, shnum); 2677682674b8SRichard Henderson for (i = 0; i < shnum; ++i) { 2678682674b8SRichard Henderson if (shdr[i].sh_type == SHT_SYMTAB) { 2679682674b8SRichard Henderson sym_idx = i; 2680682674b8SRichard Henderson str_idx = shdr[i].sh_link; 2681689f936fSbellard goto found; 2682689f936fSbellard } 2683689f936fSbellard } 2684682674b8SRichard Henderson 2685682674b8SRichard Henderson /* There will be no symbol table if the file was stripped. */ 2686682674b8SRichard Henderson return; 2687689f936fSbellard 2688689f936fSbellard found: 2689689f936fSbellard /* Now know where the strtab and symtab are. Snarf them. */ 26900ef9ea29SPeter Maydell s = g_try_new(struct syminfo, 1); 2691682674b8SRichard Henderson if (!s) { 2692b9475279SCédric VINCENT goto give_up; 2693682674b8SRichard Henderson } 2694682674b8SRichard Henderson 26951e06262dSPeter Maydell segsz = shdr[str_idx].sh_size; 26961e06262dSPeter Maydell s->disas_strtab = strings = g_try_malloc(segsz); 26971e06262dSPeter Maydell if (!strings || 26981e06262dSPeter Maydell pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) { 2699b9475279SCédric VINCENT goto give_up; 2700682674b8SRichard Henderson } 2701689f936fSbellard 27021e06262dSPeter Maydell segsz = shdr[sym_idx].sh_size; 27031e06262dSPeter Maydell syms = g_try_malloc(segsz); 27041e06262dSPeter Maydell if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) { 2705b9475279SCédric VINCENT goto give_up; 2706682674b8SRichard Henderson } 2707689f936fSbellard 27081e06262dSPeter Maydell if (segsz / sizeof(struct elf_sym) > INT_MAX) { 27091e06262dSPeter Maydell /* Implausibly large symbol table: give up rather than ploughing 27101e06262dSPeter Maydell * on with the number of symbols calculation overflowing 27111e06262dSPeter Maydell */ 27121e06262dSPeter Maydell goto give_up; 27131e06262dSPeter Maydell } 27141e06262dSPeter Maydell nsyms = segsz / sizeof(struct elf_sym); 2715682674b8SRichard Henderson for (i = 0; i < nsyms; ) { 271649918a75Spbrook bswap_sym(syms + i); 2717682674b8SRichard Henderson /* Throw away entries which we do not need. */ 2718682674b8SRichard Henderson if (syms[i].st_shndx == SHN_UNDEF 2719682674b8SRichard Henderson || syms[i].st_shndx >= SHN_LORESERVE 2720682674b8SRichard Henderson || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 2721682674b8SRichard Henderson if (i < --nsyms) { 272249918a75Spbrook syms[i] = syms[nsyms]; 272349918a75Spbrook } 2724682674b8SRichard Henderson } else { 272549918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS) 272649918a75Spbrook /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 272749918a75Spbrook syms[i].st_value &= ~(target_ulong)1; 272849918a75Spbrook #endif 2729682674b8SRichard Henderson syms[i].st_value += load_bias; 273049918a75Spbrook i++; 273149918a75Spbrook } 2732682674b8SRichard Henderson } 273349918a75Spbrook 2734b9475279SCédric VINCENT /* No "useful" symbol. */ 2735b9475279SCédric VINCENT if (nsyms == 0) { 2736b9475279SCédric VINCENT goto give_up; 2737b9475279SCédric VINCENT } 2738b9475279SCédric VINCENT 27395d5c9930SRichard Henderson /* Attempt to free the storage associated with the local symbols 27405d5c9930SRichard Henderson that we threw away. Whether or not this has any effect on the 27415d5c9930SRichard Henderson memory allocation depends on the malloc implementation and how 27425d5c9930SRichard Henderson many symbols we managed to discard. */ 27430ef9ea29SPeter Maydell new_syms = g_try_renew(struct elf_sym, syms, nsyms); 27448d79de6eSStefan Weil if (new_syms == NULL) { 2745b9475279SCédric VINCENT goto give_up; 27465d5c9930SRichard Henderson } 27478d79de6eSStefan Weil syms = new_syms; 27485d5c9930SRichard Henderson 274949918a75Spbrook qsort(syms, nsyms, sizeof(*syms), symcmp); 275049918a75Spbrook 275149918a75Spbrook s->disas_num_syms = nsyms; 275249918a75Spbrook #if ELF_CLASS == ELFCLASS32 275349918a75Spbrook s->disas_symtab.elf32 = syms; 275449918a75Spbrook #else 275549918a75Spbrook s->disas_symtab.elf64 = syms; 275649918a75Spbrook #endif 2757682674b8SRichard Henderson s->lookup_symbol = lookup_symbolxx; 2758e80cfcfcSbellard s->next = syminfos; 2759e80cfcfcSbellard syminfos = s; 2760b9475279SCédric VINCENT 2761b9475279SCédric VINCENT return; 2762b9475279SCédric VINCENT 2763b9475279SCédric VINCENT give_up: 27640ef9ea29SPeter Maydell g_free(s); 27650ef9ea29SPeter Maydell g_free(strings); 27660ef9ea29SPeter Maydell g_free(syms); 2767689f936fSbellard } 276831e31b8aSbellard 2769768fe76eSYunQiang Su uint32_t get_elf_eflags(int fd) 2770768fe76eSYunQiang Su { 2771768fe76eSYunQiang Su struct elfhdr ehdr; 2772768fe76eSYunQiang Su off_t offset; 2773768fe76eSYunQiang Su int ret; 2774768fe76eSYunQiang Su 2775768fe76eSYunQiang Su /* Read ELF header */ 2776768fe76eSYunQiang Su offset = lseek(fd, 0, SEEK_SET); 2777768fe76eSYunQiang Su if (offset == (off_t) -1) { 2778768fe76eSYunQiang Su return 0; 2779768fe76eSYunQiang Su } 2780768fe76eSYunQiang Su ret = read(fd, &ehdr, sizeof(ehdr)); 2781768fe76eSYunQiang Su if (ret < sizeof(ehdr)) { 2782768fe76eSYunQiang Su return 0; 2783768fe76eSYunQiang Su } 2784768fe76eSYunQiang Su offset = lseek(fd, offset, SEEK_SET); 2785768fe76eSYunQiang Su if (offset == (off_t) -1) { 2786768fe76eSYunQiang Su return 0; 2787768fe76eSYunQiang Su } 2788768fe76eSYunQiang Su 2789768fe76eSYunQiang Su /* Check ELF signature */ 2790768fe76eSYunQiang Su if (!elf_check_ident(&ehdr)) { 2791768fe76eSYunQiang Su return 0; 2792768fe76eSYunQiang Su } 2793768fe76eSYunQiang Su 2794768fe76eSYunQiang Su /* check header */ 2795768fe76eSYunQiang Su bswap_ehdr(&ehdr); 2796768fe76eSYunQiang Su if (!elf_check_ehdr(&ehdr)) { 2797768fe76eSYunQiang Su return 0; 2798768fe76eSYunQiang Su } 2799768fe76eSYunQiang Su 2800768fe76eSYunQiang Su /* return architecture id */ 2801768fe76eSYunQiang Su return ehdr.e_flags; 2802768fe76eSYunQiang Su } 2803768fe76eSYunQiang Su 2804f0116c54SWill Newton int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) 280531e31b8aSbellard { 28068e62a717SRichard Henderson struct image_info interp_info; 280731e31b8aSbellard struct elfhdr elf_ex; 28088e62a717SRichard Henderson char *elf_interpreter = NULL; 280959baae9aSStefan Brüns char *scratch; 281031e31b8aSbellard 2811abcac736SDaniel Santos memset(&interp_info, 0, sizeof(interp_info)); 2812abcac736SDaniel Santos #ifdef TARGET_MIPS 2813abcac736SDaniel Santos interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN; 2814abcac736SDaniel Santos #endif 2815abcac736SDaniel Santos 2816bf858897SRichard Henderson info->start_mmap = (abi_ulong)ELF_START_MMAP; 281731e31b8aSbellard 2818bf858897SRichard Henderson load_elf_image(bprm->filename, bprm->fd, info, 2819bf858897SRichard Henderson &elf_interpreter, bprm->buf); 2820bf858897SRichard Henderson 2821bf858897SRichard Henderson /* ??? We need a copy of the elf header for passing to create_elf_tables. 2822bf858897SRichard Henderson If we do nothing, we'll have overwritten this when we re-use bprm->buf 2823bf858897SRichard Henderson when we load the interpreter. */ 2824bf858897SRichard Henderson elf_ex = *(struct elfhdr *)bprm->buf; 282531e31b8aSbellard 282659baae9aSStefan Brüns /* Do this so that we can load the interpreter, if need be. We will 282759baae9aSStefan Brüns change some of these later */ 282859baae9aSStefan Brüns bprm->p = setup_arg_pages(bprm, info); 282959baae9aSStefan Brüns 283059baae9aSStefan Brüns scratch = g_new0(char, TARGET_PAGE_SIZE); 28317c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 283259baae9aSStefan Brüns bprm->p = copy_elf_strings(1, &bprm->filename, scratch, 283359baae9aSStefan Brüns bprm->p, info->stack_limit); 28347c4ee5bcSRichard Henderson info->file_string = bprm->p; 283559baae9aSStefan Brüns bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch, 283659baae9aSStefan Brüns bprm->p, info->stack_limit); 28377c4ee5bcSRichard Henderson info->env_strings = bprm->p; 283859baae9aSStefan Brüns bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch, 283959baae9aSStefan Brüns bprm->p, info->stack_limit); 28407c4ee5bcSRichard Henderson info->arg_strings = bprm->p; 28417c4ee5bcSRichard Henderson } else { 28427c4ee5bcSRichard Henderson info->arg_strings = bprm->p; 28437c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch, 28447c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 28457c4ee5bcSRichard Henderson info->env_strings = bprm->p; 28467c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch, 28477c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 28487c4ee5bcSRichard Henderson info->file_string = bprm->p; 28497c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(1, &bprm->filename, scratch, 28507c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 28517c4ee5bcSRichard Henderson } 28527c4ee5bcSRichard Henderson 285359baae9aSStefan Brüns g_free(scratch); 285459baae9aSStefan Brüns 2855e5fe0c52Spbrook if (!bprm->p) { 2856bf858897SRichard Henderson fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG)); 285731e31b8aSbellard exit(-1); 28589955ffacSRichard Henderson } 2859379f6698SPaul Brook 28608e62a717SRichard Henderson if (elf_interpreter) { 28618e62a717SRichard Henderson load_elf_interp(elf_interpreter, &interp_info, bprm->buf); 286231e31b8aSbellard 28638e62a717SRichard Henderson /* If the program interpreter is one of these two, then assume 28648e62a717SRichard Henderson an iBCS2 image. Otherwise assume a native linux image. */ 286531e31b8aSbellard 28668e62a717SRichard Henderson if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0 28678e62a717SRichard Henderson || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) { 28688e62a717SRichard Henderson info->personality = PER_SVR4; 28698e62a717SRichard Henderson 287031e31b8aSbellard /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 28718e62a717SRichard Henderson and some applications "depend" upon this behavior. Since 28728e62a717SRichard Henderson we do not have the power to recompile these, we emulate 28738e62a717SRichard Henderson the SVr4 behavior. Sigh. */ 28748e62a717SRichard Henderson target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, 287568754b44SPeter Maydell MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 287631e31b8aSbellard } 2877c94cb6c9SStefan Markovic #ifdef TARGET_MIPS 2878c94cb6c9SStefan Markovic info->interp_fp_abi = interp_info.fp_abi; 2879c94cb6c9SStefan Markovic #endif 28808e62a717SRichard Henderson } 288131e31b8aSbellard 28828e62a717SRichard Henderson bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex, 28838e62a717SRichard Henderson info, (elf_interpreter ? &interp_info : NULL)); 28848e62a717SRichard Henderson info->start_stack = bprm->p; 28858e62a717SRichard Henderson 28868e62a717SRichard Henderson /* If we have an interpreter, set that as the program's entry point. 28878e78064eSRichard Henderson Copy the load_bias as well, to help PPC64 interpret the entry 28888e62a717SRichard Henderson point as a function descriptor. Do this after creating elf tables 28898e62a717SRichard Henderson so that we copy the original program entry point into the AUXV. */ 28908e62a717SRichard Henderson if (elf_interpreter) { 28918e78064eSRichard Henderson info->load_bias = interp_info.load_bias; 28928e62a717SRichard Henderson info->entry = interp_info.entry; 2893bf858897SRichard Henderson free(elf_interpreter); 28948e62a717SRichard Henderson } 289531e31b8aSbellard 2896edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 2897edf8e2afSMika Westerberg bprm->core_dump = &elf_core_dump; 2898edf8e2afSMika Westerberg #endif 2899edf8e2afSMika Westerberg 29006fd59449SRichard Henderson /* 29016fd59449SRichard Henderson * If we reserved extra space for brk, release it now. 29026fd59449SRichard Henderson * The implementation of do_brk in syscalls.c expects to be able 29036fd59449SRichard Henderson * to mmap pages in this space. 29046fd59449SRichard Henderson */ 29056fd59449SRichard Henderson if (info->reserve_brk) { 29066fd59449SRichard Henderson abi_ulong start_brk = HOST_PAGE_ALIGN(info->brk); 29076fd59449SRichard Henderson abi_ulong end_brk = HOST_PAGE_ALIGN(info->brk + info->reserve_brk); 29086fd59449SRichard Henderson target_munmap(start_brk, end_brk - start_brk); 29096fd59449SRichard Henderson } 29106fd59449SRichard Henderson 291131e31b8aSbellard return 0; 291231e31b8aSbellard } 291331e31b8aSbellard 2914edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 2915edf8e2afSMika Westerberg /* 2916edf8e2afSMika Westerberg * Definitions to generate Intel SVR4-like core files. 2917a2547a13SLaurent Desnogues * These mostly have the same names as the SVR4 types with "target_elf_" 2918edf8e2afSMika Westerberg * tacked on the front to prevent clashes with linux definitions, 2919edf8e2afSMika Westerberg * and the typedef forms have been avoided. This is mostly like 2920edf8e2afSMika Westerberg * the SVR4 structure, but more Linuxy, with things that Linux does 2921edf8e2afSMika Westerberg * not support and which gdb doesn't really use excluded. 2922edf8e2afSMika Westerberg * 2923edf8e2afSMika Westerberg * Fields we don't dump (their contents is zero) in linux-user qemu 2924edf8e2afSMika Westerberg * are marked with XXX. 2925edf8e2afSMika Westerberg * 2926edf8e2afSMika Westerberg * Core dump code is copied from linux kernel (fs/binfmt_elf.c). 2927edf8e2afSMika Westerberg * 2928edf8e2afSMika Westerberg * Porting ELF coredump for target is (quite) simple process. First you 2929dd0a3651SNathan Froyd * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for 2930edf8e2afSMika Westerberg * the target resides): 2931edf8e2afSMika Westerberg * 2932edf8e2afSMika Westerberg * #define USE_ELF_CORE_DUMP 2933edf8e2afSMika Westerberg * 2934edf8e2afSMika Westerberg * Next you define type of register set used for dumping. ELF specification 2935edf8e2afSMika Westerberg * says that it needs to be array of elf_greg_t that has size of ELF_NREG. 2936edf8e2afSMika Westerberg * 2937c227f099SAnthony Liguori * typedef <target_regtype> target_elf_greg_t; 2938edf8e2afSMika Westerberg * #define ELF_NREG <number of registers> 2939c227f099SAnthony Liguori * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; 2940edf8e2afSMika Westerberg * 2941edf8e2afSMika Westerberg * Last step is to implement target specific function that copies registers 2942edf8e2afSMika Westerberg * from given cpu into just specified register set. Prototype is: 2943edf8e2afSMika Westerberg * 2944c227f099SAnthony Liguori * static void elf_core_copy_regs(taret_elf_gregset_t *regs, 29459349b4f9SAndreas Färber * const CPUArchState *env); 2946edf8e2afSMika Westerberg * 2947edf8e2afSMika Westerberg * Parameters: 2948edf8e2afSMika Westerberg * regs - copy register values into here (allocated and zeroed by caller) 2949edf8e2afSMika Westerberg * env - copy registers from here 2950edf8e2afSMika Westerberg * 2951edf8e2afSMika Westerberg * Example for ARM target is provided in this file. 2952edf8e2afSMika Westerberg */ 2953edf8e2afSMika Westerberg 2954edf8e2afSMika Westerberg /* An ELF note in memory */ 2955edf8e2afSMika Westerberg struct memelfnote { 2956edf8e2afSMika Westerberg const char *name; 2957edf8e2afSMika Westerberg size_t namesz; 2958edf8e2afSMika Westerberg size_t namesz_rounded; 2959edf8e2afSMika Westerberg int type; 2960edf8e2afSMika Westerberg size_t datasz; 296180f5ce75SLaurent Vivier size_t datasz_rounded; 2962edf8e2afSMika Westerberg void *data; 2963edf8e2afSMika Westerberg size_t notesz; 2964edf8e2afSMika Westerberg }; 2965edf8e2afSMika Westerberg 2966a2547a13SLaurent Desnogues struct target_elf_siginfo { 2967f8fd4fc4SPaolo Bonzini abi_int si_signo; /* signal number */ 2968f8fd4fc4SPaolo Bonzini abi_int si_code; /* extra code */ 2969f8fd4fc4SPaolo Bonzini abi_int si_errno; /* errno */ 2970edf8e2afSMika Westerberg }; 2971edf8e2afSMika Westerberg 2972a2547a13SLaurent Desnogues struct target_elf_prstatus { 2973a2547a13SLaurent Desnogues struct target_elf_siginfo pr_info; /* Info associated with signal */ 29741ddd592fSPaolo Bonzini abi_short pr_cursig; /* Current signal */ 2975ca98ac83SPaolo Bonzini abi_ulong pr_sigpend; /* XXX */ 2976ca98ac83SPaolo Bonzini abi_ulong pr_sighold; /* XXX */ 2977c227f099SAnthony Liguori target_pid_t pr_pid; 2978c227f099SAnthony Liguori target_pid_t pr_ppid; 2979c227f099SAnthony Liguori target_pid_t pr_pgrp; 2980c227f099SAnthony Liguori target_pid_t pr_sid; 2981edf8e2afSMika Westerberg struct target_timeval pr_utime; /* XXX User time */ 2982edf8e2afSMika Westerberg struct target_timeval pr_stime; /* XXX System time */ 2983edf8e2afSMika Westerberg struct target_timeval pr_cutime; /* XXX Cumulative user time */ 2984edf8e2afSMika Westerberg struct target_timeval pr_cstime; /* XXX Cumulative system time */ 2985c227f099SAnthony Liguori target_elf_gregset_t pr_reg; /* GP registers */ 2986f8fd4fc4SPaolo Bonzini abi_int pr_fpvalid; /* XXX */ 2987edf8e2afSMika Westerberg }; 2988edf8e2afSMika Westerberg 2989edf8e2afSMika Westerberg #define ELF_PRARGSZ (80) /* Number of chars for args */ 2990edf8e2afSMika Westerberg 2991a2547a13SLaurent Desnogues struct target_elf_prpsinfo { 2992edf8e2afSMika Westerberg char pr_state; /* numeric process state */ 2993edf8e2afSMika Westerberg char pr_sname; /* char for pr_state */ 2994edf8e2afSMika Westerberg char pr_zomb; /* zombie */ 2995edf8e2afSMika Westerberg char pr_nice; /* nice val */ 2996ca98ac83SPaolo Bonzini abi_ulong pr_flag; /* flags */ 2997c227f099SAnthony Liguori target_uid_t pr_uid; 2998c227f099SAnthony Liguori target_gid_t pr_gid; 2999c227f099SAnthony Liguori target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; 3000edf8e2afSMika Westerberg /* Lots missing */ 3001d7eb2b92SAlistair Francis char pr_fname[16] QEMU_NONSTRING; /* filename of executable */ 3002edf8e2afSMika Westerberg char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ 3003edf8e2afSMika Westerberg }; 3004edf8e2afSMika Westerberg 3005edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */ 3006edf8e2afSMika Westerberg struct elf_thread_status { 300772cf2d4fSBlue Swirl QTAILQ_ENTRY(elf_thread_status) ets_link; 3008a2547a13SLaurent Desnogues struct target_elf_prstatus prstatus; /* NT_PRSTATUS */ 3009edf8e2afSMika Westerberg #if 0 3010edf8e2afSMika Westerberg elf_fpregset_t fpu; /* NT_PRFPREG */ 3011edf8e2afSMika Westerberg struct task_struct *thread; 3012edf8e2afSMika Westerberg elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */ 3013edf8e2afSMika Westerberg #endif 3014edf8e2afSMika Westerberg struct memelfnote notes[1]; 3015edf8e2afSMika Westerberg int num_notes; 3016edf8e2afSMika Westerberg }; 3017edf8e2afSMika Westerberg 3018edf8e2afSMika Westerberg struct elf_note_info { 3019edf8e2afSMika Westerberg struct memelfnote *notes; 3020a2547a13SLaurent Desnogues struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */ 3021a2547a13SLaurent Desnogues struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */ 3022edf8e2afSMika Westerberg 3023b58deb34SPaolo Bonzini QTAILQ_HEAD(, elf_thread_status) thread_list; 3024edf8e2afSMika Westerberg #if 0 3025edf8e2afSMika Westerberg /* 3026edf8e2afSMika Westerberg * Current version of ELF coredump doesn't support 3027edf8e2afSMika Westerberg * dumping fp regs etc. 3028edf8e2afSMika Westerberg */ 3029edf8e2afSMika Westerberg elf_fpregset_t *fpu; 3030edf8e2afSMika Westerberg elf_fpxregset_t *xfpu; 3031edf8e2afSMika Westerberg int thread_status_size; 3032edf8e2afSMika Westerberg #endif 3033edf8e2afSMika Westerberg int notes_size; 3034edf8e2afSMika Westerberg int numnote; 3035edf8e2afSMika Westerberg }; 3036edf8e2afSMika Westerberg 3037edf8e2afSMika Westerberg struct vm_area_struct { 30381a1c4db9SMikhail Ilyin target_ulong vma_start; /* start vaddr of memory region */ 30391a1c4db9SMikhail Ilyin target_ulong vma_end; /* end vaddr of memory region */ 3040edf8e2afSMika Westerberg abi_ulong vma_flags; /* protection etc. flags for the region */ 304172cf2d4fSBlue Swirl QTAILQ_ENTRY(vm_area_struct) vma_link; 3042edf8e2afSMika Westerberg }; 3043edf8e2afSMika Westerberg 3044edf8e2afSMika Westerberg struct mm_struct { 304572cf2d4fSBlue Swirl QTAILQ_HEAD(, vm_area_struct) mm_mmap; 3046edf8e2afSMika Westerberg int mm_count; /* number of mappings */ 3047edf8e2afSMika Westerberg }; 3048edf8e2afSMika Westerberg 3049edf8e2afSMika Westerberg static struct mm_struct *vma_init(void); 3050edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *); 30511a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *, target_ulong, 30521a1c4db9SMikhail Ilyin target_ulong, abi_ulong); 3053edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *); 3054edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *); 3055edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *); 3056edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *); 30571a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end, 3058edf8e2afSMika Westerberg unsigned long flags); 3059edf8e2afSMika Westerberg 3060edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); 3061edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int, 3062edf8e2afSMika Westerberg unsigned int, void *); 3063a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); 3064a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); 3065edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *); 3066edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); 3067edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *); 3068edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *); 30699349b4f9SAndreas Färber static int fill_note_info(struct elf_note_info *, long, const CPUArchState *); 30709349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *, const CPUArchState *); 3071edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t); 3072edf8e2afSMika Westerberg 3073edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t); 3074edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int); 3075edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int); 3076edf8e2afSMika Westerberg 3077edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 3078a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus) 3079edf8e2afSMika Westerberg { 3080ca98ac83SPaolo Bonzini prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo); 3081ca98ac83SPaolo Bonzini prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code); 3082ca98ac83SPaolo Bonzini prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno); 3083edf8e2afSMika Westerberg prstatus->pr_cursig = tswap16(prstatus->pr_cursig); 3084ca98ac83SPaolo Bonzini prstatus->pr_sigpend = tswapal(prstatus->pr_sigpend); 3085ca98ac83SPaolo Bonzini prstatus->pr_sighold = tswapal(prstatus->pr_sighold); 3086edf8e2afSMika Westerberg prstatus->pr_pid = tswap32(prstatus->pr_pid); 3087edf8e2afSMika Westerberg prstatus->pr_ppid = tswap32(prstatus->pr_ppid); 3088edf8e2afSMika Westerberg prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp); 3089edf8e2afSMika Westerberg prstatus->pr_sid = tswap32(prstatus->pr_sid); 3090edf8e2afSMika Westerberg /* cpu times are not filled, so we skip them */ 3091edf8e2afSMika Westerberg /* regs should be in correct format already */ 3092edf8e2afSMika Westerberg prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid); 3093edf8e2afSMika Westerberg } 3094edf8e2afSMika Westerberg 3095a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) 3096edf8e2afSMika Westerberg { 3097ca98ac83SPaolo Bonzini psinfo->pr_flag = tswapal(psinfo->pr_flag); 3098edf8e2afSMika Westerberg psinfo->pr_uid = tswap16(psinfo->pr_uid); 3099edf8e2afSMika Westerberg psinfo->pr_gid = tswap16(psinfo->pr_gid); 3100edf8e2afSMika Westerberg psinfo->pr_pid = tswap32(psinfo->pr_pid); 3101edf8e2afSMika Westerberg psinfo->pr_ppid = tswap32(psinfo->pr_ppid); 3102edf8e2afSMika Westerberg psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp); 3103edf8e2afSMika Westerberg psinfo->pr_sid = tswap32(psinfo->pr_sid); 3104edf8e2afSMika Westerberg } 3105991f8f0cSRichard Henderson 3106991f8f0cSRichard Henderson static void bswap_note(struct elf_note *en) 3107991f8f0cSRichard Henderson { 3108991f8f0cSRichard Henderson bswap32s(&en->n_namesz); 3109991f8f0cSRichard Henderson bswap32s(&en->n_descsz); 3110991f8f0cSRichard Henderson bswap32s(&en->n_type); 3111991f8f0cSRichard Henderson } 3112991f8f0cSRichard Henderson #else 3113991f8f0cSRichard Henderson static inline void bswap_prstatus(struct target_elf_prstatus *p) { } 3114991f8f0cSRichard Henderson static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {} 3115991f8f0cSRichard Henderson static inline void bswap_note(struct elf_note *en) { } 3116edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 3117edf8e2afSMika Westerberg 3118edf8e2afSMika Westerberg /* 3119edf8e2afSMika Westerberg * Minimal support for linux memory regions. These are needed 3120edf8e2afSMika Westerberg * when we are finding out what memory exactly belongs to 3121edf8e2afSMika Westerberg * emulated process. No locks needed here, as long as 3122edf8e2afSMika Westerberg * thread that received the signal is stopped. 3123edf8e2afSMika Westerberg */ 3124edf8e2afSMika Westerberg 3125edf8e2afSMika Westerberg static struct mm_struct *vma_init(void) 3126edf8e2afSMika Westerberg { 3127edf8e2afSMika Westerberg struct mm_struct *mm; 3128edf8e2afSMika Westerberg 31297267c094SAnthony Liguori if ((mm = g_malloc(sizeof (*mm))) == NULL) 3130edf8e2afSMika Westerberg return (NULL); 3131edf8e2afSMika Westerberg 3132edf8e2afSMika Westerberg mm->mm_count = 0; 313372cf2d4fSBlue Swirl QTAILQ_INIT(&mm->mm_mmap); 3134edf8e2afSMika Westerberg 3135edf8e2afSMika Westerberg return (mm); 3136edf8e2afSMika Westerberg } 3137edf8e2afSMika Westerberg 3138edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm) 3139edf8e2afSMika Westerberg { 3140edf8e2afSMika Westerberg struct vm_area_struct *vma; 3141edf8e2afSMika Westerberg 3142edf8e2afSMika Westerberg while ((vma = vma_first(mm)) != NULL) { 314372cf2d4fSBlue Swirl QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link); 31447267c094SAnthony Liguori g_free(vma); 3145edf8e2afSMika Westerberg } 31467267c094SAnthony Liguori g_free(mm); 3147edf8e2afSMika Westerberg } 3148edf8e2afSMika Westerberg 31491a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *mm, target_ulong start, 31501a1c4db9SMikhail Ilyin target_ulong end, abi_ulong flags) 3151edf8e2afSMika Westerberg { 3152edf8e2afSMika Westerberg struct vm_area_struct *vma; 3153edf8e2afSMika Westerberg 31547267c094SAnthony Liguori if ((vma = g_malloc0(sizeof (*vma))) == NULL) 3155edf8e2afSMika Westerberg return (-1); 3156edf8e2afSMika Westerberg 3157edf8e2afSMika Westerberg vma->vma_start = start; 3158edf8e2afSMika Westerberg vma->vma_end = end; 3159edf8e2afSMika Westerberg vma->vma_flags = flags; 3160edf8e2afSMika Westerberg 316172cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link); 3162edf8e2afSMika Westerberg mm->mm_count++; 3163edf8e2afSMika Westerberg 3164edf8e2afSMika Westerberg return (0); 3165edf8e2afSMika Westerberg } 3166edf8e2afSMika Westerberg 3167edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm) 3168edf8e2afSMika Westerberg { 316972cf2d4fSBlue Swirl return (QTAILQ_FIRST(&mm->mm_mmap)); 3170edf8e2afSMika Westerberg } 3171edf8e2afSMika Westerberg 3172edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma) 3173edf8e2afSMika Westerberg { 317472cf2d4fSBlue Swirl return (QTAILQ_NEXT(vma, vma_link)); 3175edf8e2afSMika Westerberg } 3176edf8e2afSMika Westerberg 3177edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm) 3178edf8e2afSMika Westerberg { 3179edf8e2afSMika Westerberg return (mm->mm_count); 3180edf8e2afSMika Westerberg } 3181edf8e2afSMika Westerberg 3182edf8e2afSMika Westerberg /* 3183edf8e2afSMika Westerberg * Calculate file (dump) size of given memory region. 3184edf8e2afSMika Westerberg */ 3185edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma) 3186edf8e2afSMika Westerberg { 3187edf8e2afSMika Westerberg /* if we cannot even read the first page, skip it */ 3188edf8e2afSMika Westerberg if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE)) 3189edf8e2afSMika Westerberg return (0); 3190edf8e2afSMika Westerberg 3191edf8e2afSMika Westerberg /* 3192edf8e2afSMika Westerberg * Usually we don't dump executable pages as they contain 3193edf8e2afSMika Westerberg * non-writable code that debugger can read directly from 3194edf8e2afSMika Westerberg * target library etc. However, thread stacks are marked 3195edf8e2afSMika Westerberg * also executable so we read in first page of given region 3196edf8e2afSMika Westerberg * and check whether it contains elf header. If there is 3197edf8e2afSMika Westerberg * no elf header, we dump it. 3198edf8e2afSMika Westerberg */ 3199edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) { 3200edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 3201edf8e2afSMika Westerberg 3202edf8e2afSMika Westerberg copy_from_user(page, vma->vma_start, sizeof (page)); 3203edf8e2afSMika Westerberg if ((page[EI_MAG0] == ELFMAG0) && 3204edf8e2afSMika Westerberg (page[EI_MAG1] == ELFMAG1) && 3205edf8e2afSMika Westerberg (page[EI_MAG2] == ELFMAG2) && 3206edf8e2afSMika Westerberg (page[EI_MAG3] == ELFMAG3)) { 3207edf8e2afSMika Westerberg /* 3208edf8e2afSMika Westerberg * Mappings are possibly from ELF binary. Don't dump 3209edf8e2afSMika Westerberg * them. 3210edf8e2afSMika Westerberg */ 3211edf8e2afSMika Westerberg return (0); 3212edf8e2afSMika Westerberg } 3213edf8e2afSMika Westerberg } 3214edf8e2afSMika Westerberg 3215edf8e2afSMika Westerberg return (vma->vma_end - vma->vma_start); 3216edf8e2afSMika Westerberg } 3217edf8e2afSMika Westerberg 32181a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end, 3219edf8e2afSMika Westerberg unsigned long flags) 3220edf8e2afSMika Westerberg { 3221edf8e2afSMika Westerberg struct mm_struct *mm = (struct mm_struct *)priv; 3222edf8e2afSMika Westerberg 3223edf8e2afSMika Westerberg vma_add_mapping(mm, start, end, flags); 3224edf8e2afSMika Westerberg return (0); 3225edf8e2afSMika Westerberg } 3226edf8e2afSMika Westerberg 3227edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type, 3228edf8e2afSMika Westerberg unsigned int sz, void *data) 3229edf8e2afSMika Westerberg { 3230edf8e2afSMika Westerberg unsigned int namesz; 3231edf8e2afSMika Westerberg 3232edf8e2afSMika Westerberg namesz = strlen(name) + 1; 3233edf8e2afSMika Westerberg note->name = name; 3234edf8e2afSMika Westerberg note->namesz = namesz; 3235edf8e2afSMika Westerberg note->namesz_rounded = roundup(namesz, sizeof (int32_t)); 3236edf8e2afSMika Westerberg note->type = type; 323780f5ce75SLaurent Vivier note->datasz = sz; 323880f5ce75SLaurent Vivier note->datasz_rounded = roundup(sz, sizeof (int32_t)); 323980f5ce75SLaurent Vivier 3240edf8e2afSMika Westerberg note->data = data; 3241edf8e2afSMika Westerberg 3242edf8e2afSMika Westerberg /* 3243edf8e2afSMika Westerberg * We calculate rounded up note size here as specified by 3244edf8e2afSMika Westerberg * ELF document. 3245edf8e2afSMika Westerberg */ 3246edf8e2afSMika Westerberg note->notesz = sizeof (struct elf_note) + 324780f5ce75SLaurent Vivier note->namesz_rounded + note->datasz_rounded; 3248edf8e2afSMika Westerberg } 3249edf8e2afSMika Westerberg 3250edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, 3251edf8e2afSMika Westerberg uint32_t flags) 3252edf8e2afSMika Westerberg { 3253edf8e2afSMika Westerberg (void) memset(elf, 0, sizeof(*elf)); 3254edf8e2afSMika Westerberg 3255edf8e2afSMika Westerberg (void) memcpy(elf->e_ident, ELFMAG, SELFMAG); 3256edf8e2afSMika Westerberg elf->e_ident[EI_CLASS] = ELF_CLASS; 3257edf8e2afSMika Westerberg elf->e_ident[EI_DATA] = ELF_DATA; 3258edf8e2afSMika Westerberg elf->e_ident[EI_VERSION] = EV_CURRENT; 3259edf8e2afSMika Westerberg elf->e_ident[EI_OSABI] = ELF_OSABI; 3260edf8e2afSMika Westerberg 3261edf8e2afSMika Westerberg elf->e_type = ET_CORE; 3262edf8e2afSMika Westerberg elf->e_machine = machine; 3263edf8e2afSMika Westerberg elf->e_version = EV_CURRENT; 3264edf8e2afSMika Westerberg elf->e_phoff = sizeof(struct elfhdr); 3265edf8e2afSMika Westerberg elf->e_flags = flags; 3266edf8e2afSMika Westerberg elf->e_ehsize = sizeof(struct elfhdr); 3267edf8e2afSMika Westerberg elf->e_phentsize = sizeof(struct elf_phdr); 3268edf8e2afSMika Westerberg elf->e_phnum = segs; 3269edf8e2afSMika Westerberg 3270edf8e2afSMika Westerberg bswap_ehdr(elf); 3271edf8e2afSMika Westerberg } 3272edf8e2afSMika Westerberg 3273edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) 3274edf8e2afSMika Westerberg { 3275edf8e2afSMika Westerberg phdr->p_type = PT_NOTE; 3276edf8e2afSMika Westerberg phdr->p_offset = offset; 3277edf8e2afSMika Westerberg phdr->p_vaddr = 0; 3278edf8e2afSMika Westerberg phdr->p_paddr = 0; 3279edf8e2afSMika Westerberg phdr->p_filesz = sz; 3280edf8e2afSMika Westerberg phdr->p_memsz = 0; 3281edf8e2afSMika Westerberg phdr->p_flags = 0; 3282edf8e2afSMika Westerberg phdr->p_align = 0; 3283edf8e2afSMika Westerberg 3284991f8f0cSRichard Henderson bswap_phdr(phdr, 1); 3285edf8e2afSMika Westerberg } 3286edf8e2afSMika Westerberg 3287edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note) 3288edf8e2afSMika Westerberg { 3289edf8e2afSMika Westerberg return (note->notesz); 3290edf8e2afSMika Westerberg } 3291edf8e2afSMika Westerberg 3292a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus, 3293edf8e2afSMika Westerberg const TaskState *ts, int signr) 3294edf8e2afSMika Westerberg { 3295edf8e2afSMika Westerberg (void) memset(prstatus, 0, sizeof (*prstatus)); 3296edf8e2afSMika Westerberg prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 3297edf8e2afSMika Westerberg prstatus->pr_pid = ts->ts_tid; 3298edf8e2afSMika Westerberg prstatus->pr_ppid = getppid(); 3299edf8e2afSMika Westerberg prstatus->pr_pgrp = getpgrp(); 3300edf8e2afSMika Westerberg prstatus->pr_sid = getsid(0); 3301edf8e2afSMika Westerberg 3302edf8e2afSMika Westerberg bswap_prstatus(prstatus); 3303edf8e2afSMika Westerberg } 3304edf8e2afSMika Westerberg 3305a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) 3306edf8e2afSMika Westerberg { 3307900cfbcaSJim Meyering char *base_filename; 3308edf8e2afSMika Westerberg unsigned int i, len; 3309edf8e2afSMika Westerberg 3310edf8e2afSMika Westerberg (void) memset(psinfo, 0, sizeof (*psinfo)); 3311edf8e2afSMika Westerberg 3312edf8e2afSMika Westerberg len = ts->info->arg_end - ts->info->arg_start; 3313edf8e2afSMika Westerberg if (len >= ELF_PRARGSZ) 3314edf8e2afSMika Westerberg len = ELF_PRARGSZ - 1; 3315edf8e2afSMika Westerberg if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len)) 3316edf8e2afSMika Westerberg return -EFAULT; 3317edf8e2afSMika Westerberg for (i = 0; i < len; i++) 3318edf8e2afSMika Westerberg if (psinfo->pr_psargs[i] == 0) 3319edf8e2afSMika Westerberg psinfo->pr_psargs[i] = ' '; 3320edf8e2afSMika Westerberg psinfo->pr_psargs[len] = 0; 3321edf8e2afSMika Westerberg 3322edf8e2afSMika Westerberg psinfo->pr_pid = getpid(); 3323edf8e2afSMika Westerberg psinfo->pr_ppid = getppid(); 3324edf8e2afSMika Westerberg psinfo->pr_pgrp = getpgrp(); 3325edf8e2afSMika Westerberg psinfo->pr_sid = getsid(0); 3326edf8e2afSMika Westerberg psinfo->pr_uid = getuid(); 3327edf8e2afSMika Westerberg psinfo->pr_gid = getgid(); 3328edf8e2afSMika Westerberg 3329900cfbcaSJim Meyering base_filename = g_path_get_basename(ts->bprm->filename); 3330900cfbcaSJim Meyering /* 3331900cfbcaSJim Meyering * Using strncpy here is fine: at max-length, 3332900cfbcaSJim Meyering * this field is not NUL-terminated. 3333900cfbcaSJim Meyering */ 3334edf8e2afSMika Westerberg (void) strncpy(psinfo->pr_fname, base_filename, 3335edf8e2afSMika Westerberg sizeof(psinfo->pr_fname)); 3336edf8e2afSMika Westerberg 3337900cfbcaSJim Meyering g_free(base_filename); 3338edf8e2afSMika Westerberg bswap_psinfo(psinfo); 3339edf8e2afSMika Westerberg return (0); 3340edf8e2afSMika Westerberg } 3341edf8e2afSMika Westerberg 3342edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) 3343edf8e2afSMika Westerberg { 3344edf8e2afSMika Westerberg elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; 3345edf8e2afSMika Westerberg elf_addr_t orig_auxv = auxv; 3346edf8e2afSMika Westerberg void *ptr; 3347125b0f55SAlexander Graf int len = ts->info->auxv_len; 3348edf8e2afSMika Westerberg 3349edf8e2afSMika Westerberg /* 3350edf8e2afSMika Westerberg * Auxiliary vector is stored in target process stack. It contains 3351edf8e2afSMika Westerberg * {type, value} pairs that we need to dump into note. This is not 3352edf8e2afSMika Westerberg * strictly necessary but we do it here for sake of completeness. 3353edf8e2afSMika Westerberg */ 3354edf8e2afSMika Westerberg 3355edf8e2afSMika Westerberg /* read in whole auxv vector and copy it to memelfnote */ 3356edf8e2afSMika Westerberg ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); 3357edf8e2afSMika Westerberg if (ptr != NULL) { 3358edf8e2afSMika Westerberg fill_note(note, "CORE", NT_AUXV, len, ptr); 3359edf8e2afSMika Westerberg unlock_user(ptr, auxv, len); 3360edf8e2afSMika Westerberg } 3361edf8e2afSMika Westerberg } 3362edf8e2afSMika Westerberg 3363edf8e2afSMika Westerberg /* 3364edf8e2afSMika Westerberg * Constructs name of coredump file. We have following convention 3365edf8e2afSMika Westerberg * for the name: 3366edf8e2afSMika Westerberg * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core 3367edf8e2afSMika Westerberg * 3368edf8e2afSMika Westerberg * Returns 0 in case of success, -1 otherwise (errno is set). 3369edf8e2afSMika Westerberg */ 3370edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf, 3371edf8e2afSMika Westerberg size_t bufsize) 3372edf8e2afSMika Westerberg { 3373edf8e2afSMika Westerberg char timestamp[64]; 3374edf8e2afSMika Westerberg char *base_filename = NULL; 3375edf8e2afSMika Westerberg struct timeval tv; 3376edf8e2afSMika Westerberg struct tm tm; 3377edf8e2afSMika Westerberg 3378edf8e2afSMika Westerberg assert(bufsize >= PATH_MAX); 3379edf8e2afSMika Westerberg 3380edf8e2afSMika Westerberg if (gettimeofday(&tv, NULL) < 0) { 3381edf8e2afSMika Westerberg (void) fprintf(stderr, "unable to get current timestamp: %s", 3382edf8e2afSMika Westerberg strerror(errno)); 3383edf8e2afSMika Westerberg return (-1); 3384edf8e2afSMika Westerberg } 3385edf8e2afSMika Westerberg 3386b8da57faSWei Jiangang base_filename = g_path_get_basename(ts->bprm->filename); 3387edf8e2afSMika Westerberg (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", 3388edf8e2afSMika Westerberg localtime_r(&tv.tv_sec, &tm)); 3389edf8e2afSMika Westerberg (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", 3390edf8e2afSMika Westerberg base_filename, timestamp, (int)getpid()); 3391b8da57faSWei Jiangang g_free(base_filename); 3392edf8e2afSMika Westerberg 3393edf8e2afSMika Westerberg return (0); 3394edf8e2afSMika Westerberg } 3395edf8e2afSMika Westerberg 3396edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size) 3397edf8e2afSMika Westerberg { 3398edf8e2afSMika Westerberg const char *bufp = (const char *)ptr; 3399edf8e2afSMika Westerberg ssize_t bytes_written, bytes_left; 3400edf8e2afSMika Westerberg struct rlimit dumpsize; 3401edf8e2afSMika Westerberg off_t pos; 3402edf8e2afSMika Westerberg 3403edf8e2afSMika Westerberg bytes_written = 0; 3404edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 3405edf8e2afSMika Westerberg if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { 3406edf8e2afSMika Westerberg if (errno == ESPIPE) { /* not a seekable stream */ 3407edf8e2afSMika Westerberg bytes_left = size; 3408edf8e2afSMika Westerberg } else { 3409edf8e2afSMika Westerberg return pos; 3410edf8e2afSMika Westerberg } 3411edf8e2afSMika Westerberg } else { 3412edf8e2afSMika Westerberg if (dumpsize.rlim_cur <= pos) { 3413edf8e2afSMika Westerberg return -1; 3414edf8e2afSMika Westerberg } else if (dumpsize.rlim_cur == RLIM_INFINITY) { 3415edf8e2afSMika Westerberg bytes_left = size; 3416edf8e2afSMika Westerberg } else { 3417edf8e2afSMika Westerberg size_t limit_left=dumpsize.rlim_cur - pos; 3418edf8e2afSMika Westerberg bytes_left = limit_left >= size ? size : limit_left ; 3419edf8e2afSMika Westerberg } 3420edf8e2afSMika Westerberg } 3421edf8e2afSMika Westerberg 3422edf8e2afSMika Westerberg /* 3423edf8e2afSMika Westerberg * In normal conditions, single write(2) should do but 3424edf8e2afSMika Westerberg * in case of socket etc. this mechanism is more portable. 3425edf8e2afSMika Westerberg */ 3426edf8e2afSMika Westerberg do { 3427edf8e2afSMika Westerberg bytes_written = write(fd, bufp, bytes_left); 3428edf8e2afSMika Westerberg if (bytes_written < 0) { 3429edf8e2afSMika Westerberg if (errno == EINTR) 3430edf8e2afSMika Westerberg continue; 3431edf8e2afSMika Westerberg return (-1); 3432edf8e2afSMika Westerberg } else if (bytes_written == 0) { /* eof */ 3433edf8e2afSMika Westerberg return (-1); 3434edf8e2afSMika Westerberg } 3435edf8e2afSMika Westerberg bufp += bytes_written; 3436edf8e2afSMika Westerberg bytes_left -= bytes_written; 3437edf8e2afSMika Westerberg } while (bytes_left > 0); 3438edf8e2afSMika Westerberg 3439edf8e2afSMika Westerberg return (0); 3440edf8e2afSMika Westerberg } 3441edf8e2afSMika Westerberg 3442edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd) 3443edf8e2afSMika Westerberg { 3444edf8e2afSMika Westerberg struct elf_note en; 3445edf8e2afSMika Westerberg 3446edf8e2afSMika Westerberg en.n_namesz = men->namesz; 3447edf8e2afSMika Westerberg en.n_type = men->type; 3448edf8e2afSMika Westerberg en.n_descsz = men->datasz; 3449edf8e2afSMika Westerberg 3450edf8e2afSMika Westerberg bswap_note(&en); 3451edf8e2afSMika Westerberg 3452edf8e2afSMika Westerberg if (dump_write(fd, &en, sizeof(en)) != 0) 3453edf8e2afSMika Westerberg return (-1); 3454edf8e2afSMika Westerberg if (dump_write(fd, men->name, men->namesz_rounded) != 0) 3455edf8e2afSMika Westerberg return (-1); 345680f5ce75SLaurent Vivier if (dump_write(fd, men->data, men->datasz_rounded) != 0) 3457edf8e2afSMika Westerberg return (-1); 3458edf8e2afSMika Westerberg 3459edf8e2afSMika Westerberg return (0); 3460edf8e2afSMika Westerberg } 3461edf8e2afSMika Westerberg 34629349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env) 3463edf8e2afSMika Westerberg { 346429a0af61SRichard Henderson CPUState *cpu = env_cpu((CPUArchState *)env); 34650429a971SAndreas Färber TaskState *ts = (TaskState *)cpu->opaque; 3466edf8e2afSMika Westerberg struct elf_thread_status *ets; 3467edf8e2afSMika Westerberg 34687267c094SAnthony Liguori ets = g_malloc0(sizeof (*ets)); 3469edf8e2afSMika Westerberg ets->num_notes = 1; /* only prstatus is dumped */ 3470edf8e2afSMika Westerberg fill_prstatus(&ets->prstatus, ts, 0); 3471edf8e2afSMika Westerberg elf_core_copy_regs(&ets->prstatus.pr_reg, env); 3472edf8e2afSMika Westerberg fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus), 3473edf8e2afSMika Westerberg &ets->prstatus); 3474edf8e2afSMika Westerberg 347572cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link); 3476edf8e2afSMika Westerberg 3477edf8e2afSMika Westerberg info->notes_size += note_size(&ets->notes[0]); 3478edf8e2afSMika Westerberg } 3479edf8e2afSMika Westerberg 34806afafa86SPeter Maydell static void init_note_info(struct elf_note_info *info) 34816afafa86SPeter Maydell { 34826afafa86SPeter Maydell /* Initialize the elf_note_info structure so that it is at 34836afafa86SPeter Maydell * least safe to call free_note_info() on it. Must be 34846afafa86SPeter Maydell * called before calling fill_note_info(). 34856afafa86SPeter Maydell */ 34866afafa86SPeter Maydell memset(info, 0, sizeof (*info)); 34876afafa86SPeter Maydell QTAILQ_INIT(&info->thread_list); 34886afafa86SPeter Maydell } 34896afafa86SPeter Maydell 3490edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info, 34919349b4f9SAndreas Färber long signr, const CPUArchState *env) 3492edf8e2afSMika Westerberg { 3493edf8e2afSMika Westerberg #define NUMNOTES 3 349429a0af61SRichard Henderson CPUState *cpu = env_cpu((CPUArchState *)env); 34950429a971SAndreas Färber TaskState *ts = (TaskState *)cpu->opaque; 3496edf8e2afSMika Westerberg int i; 3497edf8e2afSMika Westerberg 3498c78d65e8SMarkus Armbruster info->notes = g_new0(struct memelfnote, NUMNOTES); 3499edf8e2afSMika Westerberg if (info->notes == NULL) 3500edf8e2afSMika Westerberg return (-ENOMEM); 35017267c094SAnthony Liguori info->prstatus = g_malloc0(sizeof (*info->prstatus)); 3502edf8e2afSMika Westerberg if (info->prstatus == NULL) 3503edf8e2afSMika Westerberg return (-ENOMEM); 35047267c094SAnthony Liguori info->psinfo = g_malloc0(sizeof (*info->psinfo)); 3505edf8e2afSMika Westerberg if (info->prstatus == NULL) 3506edf8e2afSMika Westerberg return (-ENOMEM); 3507edf8e2afSMika Westerberg 3508edf8e2afSMika Westerberg /* 3509edf8e2afSMika Westerberg * First fill in status (and registers) of current thread 3510edf8e2afSMika Westerberg * including process info & aux vector. 3511edf8e2afSMika Westerberg */ 3512edf8e2afSMika Westerberg fill_prstatus(info->prstatus, ts, signr); 3513edf8e2afSMika Westerberg elf_core_copy_regs(&info->prstatus->pr_reg, env); 3514edf8e2afSMika Westerberg fill_note(&info->notes[0], "CORE", NT_PRSTATUS, 3515edf8e2afSMika Westerberg sizeof (*info->prstatus), info->prstatus); 3516edf8e2afSMika Westerberg fill_psinfo(info->psinfo, ts); 3517edf8e2afSMika Westerberg fill_note(&info->notes[1], "CORE", NT_PRPSINFO, 3518edf8e2afSMika Westerberg sizeof (*info->psinfo), info->psinfo); 3519edf8e2afSMika Westerberg fill_auxv_note(&info->notes[2], ts); 3520edf8e2afSMika Westerberg info->numnote = 3; 3521edf8e2afSMika Westerberg 3522edf8e2afSMika Westerberg info->notes_size = 0; 3523edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 3524edf8e2afSMika Westerberg info->notes_size += note_size(&info->notes[i]); 3525edf8e2afSMika Westerberg 3526edf8e2afSMika Westerberg /* read and fill status of all threads */ 3527edf8e2afSMika Westerberg cpu_list_lock(); 3528bdc44640SAndreas Färber CPU_FOREACH(cpu) { 3529a2247f8eSAndreas Färber if (cpu == thread_cpu) { 3530edf8e2afSMika Westerberg continue; 3531182735efSAndreas Färber } 3532182735efSAndreas Färber fill_thread_info(info, (CPUArchState *)cpu->env_ptr); 3533edf8e2afSMika Westerberg } 3534edf8e2afSMika Westerberg cpu_list_unlock(); 3535edf8e2afSMika Westerberg 3536edf8e2afSMika Westerberg return (0); 3537edf8e2afSMika Westerberg } 3538edf8e2afSMika Westerberg 3539edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info) 3540edf8e2afSMika Westerberg { 3541edf8e2afSMika Westerberg struct elf_thread_status *ets; 3542edf8e2afSMika Westerberg 354372cf2d4fSBlue Swirl while (!QTAILQ_EMPTY(&info->thread_list)) { 354472cf2d4fSBlue Swirl ets = QTAILQ_FIRST(&info->thread_list); 354572cf2d4fSBlue Swirl QTAILQ_REMOVE(&info->thread_list, ets, ets_link); 35467267c094SAnthony Liguori g_free(ets); 3547edf8e2afSMika Westerberg } 3548edf8e2afSMika Westerberg 35497267c094SAnthony Liguori g_free(info->prstatus); 35507267c094SAnthony Liguori g_free(info->psinfo); 35517267c094SAnthony Liguori g_free(info->notes); 3552edf8e2afSMika Westerberg } 3553edf8e2afSMika Westerberg 3554edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd) 3555edf8e2afSMika Westerberg { 3556edf8e2afSMika Westerberg struct elf_thread_status *ets; 3557edf8e2afSMika Westerberg int i, error = 0; 3558edf8e2afSMika Westerberg 3559edf8e2afSMika Westerberg /* write prstatus, psinfo and auxv for current thread */ 3560edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 3561edf8e2afSMika Westerberg if ((error = write_note(&info->notes[i], fd)) != 0) 3562edf8e2afSMika Westerberg return (error); 3563edf8e2afSMika Westerberg 3564edf8e2afSMika Westerberg /* write prstatus for each thread */ 356552a53afeSEmilio G. Cota QTAILQ_FOREACH(ets, &info->thread_list, ets_link) { 3566edf8e2afSMika Westerberg if ((error = write_note(&ets->notes[0], fd)) != 0) 3567edf8e2afSMika Westerberg return (error); 3568edf8e2afSMika Westerberg } 3569edf8e2afSMika Westerberg 3570edf8e2afSMika Westerberg return (0); 3571edf8e2afSMika Westerberg } 3572edf8e2afSMika Westerberg 3573edf8e2afSMika Westerberg /* 3574edf8e2afSMika Westerberg * Write out ELF coredump. 3575edf8e2afSMika Westerberg * 3576edf8e2afSMika Westerberg * See documentation of ELF object file format in: 3577edf8e2afSMika Westerberg * http://www.caldera.com/developers/devspecs/gabi41.pdf 3578edf8e2afSMika Westerberg * 3579edf8e2afSMika Westerberg * Coredump format in linux is following: 3580edf8e2afSMika Westerberg * 3581edf8e2afSMika Westerberg * 0 +----------------------+ \ 3582edf8e2afSMika Westerberg * | ELF header | ET_CORE | 3583edf8e2afSMika Westerberg * +----------------------+ | 3584edf8e2afSMika Westerberg * | ELF program headers | |--- headers 3585edf8e2afSMika Westerberg * | - NOTE section | | 3586edf8e2afSMika Westerberg * | - PT_LOAD sections | | 3587edf8e2afSMika Westerberg * +----------------------+ / 3588edf8e2afSMika Westerberg * | NOTEs: | 3589edf8e2afSMika Westerberg * | - NT_PRSTATUS | 3590edf8e2afSMika Westerberg * | - NT_PRSINFO | 3591edf8e2afSMika Westerberg * | - NT_AUXV | 3592edf8e2afSMika Westerberg * +----------------------+ <-- aligned to target page 3593edf8e2afSMika Westerberg * | Process memory dump | 3594edf8e2afSMika Westerberg * : : 3595edf8e2afSMika Westerberg * . . 3596edf8e2afSMika Westerberg * : : 3597edf8e2afSMika Westerberg * | | 3598edf8e2afSMika Westerberg * +----------------------+ 3599edf8e2afSMika Westerberg * 3600edf8e2afSMika Westerberg * NT_PRSTATUS -> struct elf_prstatus (per thread) 3601edf8e2afSMika Westerberg * NT_PRSINFO -> struct elf_prpsinfo 3602edf8e2afSMika Westerberg * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()). 3603edf8e2afSMika Westerberg * 3604edf8e2afSMika Westerberg * Format follows System V format as close as possible. Current 3605edf8e2afSMika Westerberg * version limitations are as follows: 3606edf8e2afSMika Westerberg * - no floating point registers are dumped 3607edf8e2afSMika Westerberg * 3608edf8e2afSMika Westerberg * Function returns 0 in case of success, negative errno otherwise. 3609edf8e2afSMika Westerberg * 3610edf8e2afSMika Westerberg * TODO: make this work also during runtime: it should be 3611edf8e2afSMika Westerberg * possible to force coredump from running process and then 3612edf8e2afSMika Westerberg * continue processing. For example qemu could set up SIGUSR2 3613edf8e2afSMika Westerberg * handler (provided that target process haven't registered 3614edf8e2afSMika Westerberg * handler for that) that does the dump when signal is received. 3615edf8e2afSMika Westerberg */ 36169349b4f9SAndreas Färber static int elf_core_dump(int signr, const CPUArchState *env) 3617edf8e2afSMika Westerberg { 361829a0af61SRichard Henderson const CPUState *cpu = env_cpu((CPUArchState *)env); 36190429a971SAndreas Färber const TaskState *ts = (const TaskState *)cpu->opaque; 3620edf8e2afSMika Westerberg struct vm_area_struct *vma = NULL; 3621edf8e2afSMika Westerberg char corefile[PATH_MAX]; 3622edf8e2afSMika Westerberg struct elf_note_info info; 3623edf8e2afSMika Westerberg struct elfhdr elf; 3624edf8e2afSMika Westerberg struct elf_phdr phdr; 3625edf8e2afSMika Westerberg struct rlimit dumpsize; 3626edf8e2afSMika Westerberg struct mm_struct *mm = NULL; 3627edf8e2afSMika Westerberg off_t offset = 0, data_offset = 0; 3628edf8e2afSMika Westerberg int segs = 0; 3629edf8e2afSMika Westerberg int fd = -1; 3630edf8e2afSMika Westerberg 36316afafa86SPeter Maydell init_note_info(&info); 36326afafa86SPeter Maydell 3633edf8e2afSMika Westerberg errno = 0; 3634edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 3635edf8e2afSMika Westerberg if (dumpsize.rlim_cur == 0) 3636edf8e2afSMika Westerberg return 0; 3637edf8e2afSMika Westerberg 3638edf8e2afSMika Westerberg if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0) 3639edf8e2afSMika Westerberg return (-errno); 3640edf8e2afSMika Westerberg 3641edf8e2afSMika Westerberg if ((fd = open(corefile, O_WRONLY | O_CREAT, 3642edf8e2afSMika Westerberg S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) 3643edf8e2afSMika Westerberg return (-errno); 3644edf8e2afSMika Westerberg 3645edf8e2afSMika Westerberg /* 3646edf8e2afSMika Westerberg * Walk through target process memory mappings and 3647edf8e2afSMika Westerberg * set up structure containing this information. After 3648edf8e2afSMika Westerberg * this point vma_xxx functions can be used. 3649edf8e2afSMika Westerberg */ 3650edf8e2afSMika Westerberg if ((mm = vma_init()) == NULL) 3651edf8e2afSMika Westerberg goto out; 3652edf8e2afSMika Westerberg 3653edf8e2afSMika Westerberg walk_memory_regions(mm, vma_walker); 3654edf8e2afSMika Westerberg segs = vma_get_mapping_count(mm); 3655edf8e2afSMika Westerberg 3656edf8e2afSMika Westerberg /* 3657edf8e2afSMika Westerberg * Construct valid coredump ELF header. We also 3658edf8e2afSMika Westerberg * add one more segment for notes. 3659edf8e2afSMika Westerberg */ 3660edf8e2afSMika Westerberg fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0); 3661edf8e2afSMika Westerberg if (dump_write(fd, &elf, sizeof (elf)) != 0) 3662edf8e2afSMika Westerberg goto out; 3663edf8e2afSMika Westerberg 3664b6af0975SDaniel P. Berrange /* fill in the in-memory version of notes */ 3665edf8e2afSMika Westerberg if (fill_note_info(&info, signr, env) < 0) 3666edf8e2afSMika Westerberg goto out; 3667edf8e2afSMika Westerberg 3668edf8e2afSMika Westerberg offset += sizeof (elf); /* elf header */ 3669edf8e2afSMika Westerberg offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */ 3670edf8e2afSMika Westerberg 3671edf8e2afSMika Westerberg /* write out notes program header */ 3672edf8e2afSMika Westerberg fill_elf_note_phdr(&phdr, info.notes_size, offset); 3673edf8e2afSMika Westerberg 3674edf8e2afSMika Westerberg offset += info.notes_size; 3675edf8e2afSMika Westerberg if (dump_write(fd, &phdr, sizeof (phdr)) != 0) 3676edf8e2afSMika Westerberg goto out; 3677edf8e2afSMika Westerberg 3678edf8e2afSMika Westerberg /* 3679edf8e2afSMika Westerberg * ELF specification wants data to start at page boundary so 3680edf8e2afSMika Westerberg * we align it here. 3681edf8e2afSMika Westerberg */ 368280f5ce75SLaurent Vivier data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE); 3683edf8e2afSMika Westerberg 3684edf8e2afSMika Westerberg /* 3685edf8e2afSMika Westerberg * Write program headers for memory regions mapped in 3686edf8e2afSMika Westerberg * the target process. 3687edf8e2afSMika Westerberg */ 3688edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 3689edf8e2afSMika Westerberg (void) memset(&phdr, 0, sizeof (phdr)); 3690edf8e2afSMika Westerberg 3691edf8e2afSMika Westerberg phdr.p_type = PT_LOAD; 3692edf8e2afSMika Westerberg phdr.p_offset = offset; 3693edf8e2afSMika Westerberg phdr.p_vaddr = vma->vma_start; 3694edf8e2afSMika Westerberg phdr.p_paddr = 0; 3695edf8e2afSMika Westerberg phdr.p_filesz = vma_dump_size(vma); 3696edf8e2afSMika Westerberg offset += phdr.p_filesz; 3697edf8e2afSMika Westerberg phdr.p_memsz = vma->vma_end - vma->vma_start; 3698edf8e2afSMika Westerberg phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0; 3699edf8e2afSMika Westerberg if (vma->vma_flags & PROT_WRITE) 3700edf8e2afSMika Westerberg phdr.p_flags |= PF_W; 3701edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) 3702edf8e2afSMika Westerberg phdr.p_flags |= PF_X; 3703edf8e2afSMika Westerberg phdr.p_align = ELF_EXEC_PAGESIZE; 3704edf8e2afSMika Westerberg 370580f5ce75SLaurent Vivier bswap_phdr(&phdr, 1); 3706772034b6SPeter Maydell if (dump_write(fd, &phdr, sizeof(phdr)) != 0) { 3707772034b6SPeter Maydell goto out; 3708772034b6SPeter Maydell } 3709edf8e2afSMika Westerberg } 3710edf8e2afSMika Westerberg 3711edf8e2afSMika Westerberg /* 3712edf8e2afSMika Westerberg * Next we write notes just after program headers. No 3713edf8e2afSMika Westerberg * alignment needed here. 3714edf8e2afSMika Westerberg */ 3715edf8e2afSMika Westerberg if (write_note_info(&info, fd) < 0) 3716edf8e2afSMika Westerberg goto out; 3717edf8e2afSMika Westerberg 3718edf8e2afSMika Westerberg /* align data to page boundary */ 3719edf8e2afSMika Westerberg if (lseek(fd, data_offset, SEEK_SET) != data_offset) 3720edf8e2afSMika Westerberg goto out; 3721edf8e2afSMika Westerberg 3722edf8e2afSMika Westerberg /* 3723edf8e2afSMika Westerberg * Finally we can dump process memory into corefile as well. 3724edf8e2afSMika Westerberg */ 3725edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 3726edf8e2afSMika Westerberg abi_ulong addr; 3727edf8e2afSMika Westerberg abi_ulong end; 3728edf8e2afSMika Westerberg 3729edf8e2afSMika Westerberg end = vma->vma_start + vma_dump_size(vma); 3730edf8e2afSMika Westerberg 3731edf8e2afSMika Westerberg for (addr = vma->vma_start; addr < end; 3732edf8e2afSMika Westerberg addr += TARGET_PAGE_SIZE) { 3733edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 3734edf8e2afSMika Westerberg int error; 3735edf8e2afSMika Westerberg 3736edf8e2afSMika Westerberg /* 3737edf8e2afSMika Westerberg * Read in page from target process memory and 3738edf8e2afSMika Westerberg * write it to coredump file. 3739edf8e2afSMika Westerberg */ 3740edf8e2afSMika Westerberg error = copy_from_user(page, addr, sizeof (page)); 3741edf8e2afSMika Westerberg if (error != 0) { 374249995e17SAurelien Jarno (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n", 3743edf8e2afSMika Westerberg addr); 3744edf8e2afSMika Westerberg errno = -error; 3745edf8e2afSMika Westerberg goto out; 3746edf8e2afSMika Westerberg } 3747edf8e2afSMika Westerberg if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0) 3748edf8e2afSMika Westerberg goto out; 3749edf8e2afSMika Westerberg } 3750edf8e2afSMika Westerberg } 3751edf8e2afSMika Westerberg 3752edf8e2afSMika Westerberg out: 3753edf8e2afSMika Westerberg free_note_info(&info); 3754edf8e2afSMika Westerberg if (mm != NULL) 3755edf8e2afSMika Westerberg vma_delete(mm); 3756edf8e2afSMika Westerberg (void) close(fd); 3757edf8e2afSMika Westerberg 3758edf8e2afSMika Westerberg if (errno != 0) 3759edf8e2afSMika Westerberg return (-errno); 3760edf8e2afSMika Westerberg return (0); 3761edf8e2afSMika Westerberg } 3762edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 3763edf8e2afSMika Westerberg 3764e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) 3765e5fe0c52Spbrook { 3766e5fe0c52Spbrook init_thread(regs, infop); 3767e5fe0c52Spbrook } 3768