131e31b8aSbellard /* This is the Linux kernel elf-loading code, ported into user space */ 2d39594e9SPeter Maydell #include "qemu/osdep.h" 3edf8e2afSMika Westerberg #include <sys/param.h> 431e31b8aSbellard 5edf8e2afSMika Westerberg #include <sys/resource.h> 630ab9ef2SRichard Henderson #include <sys/shm.h> 731e31b8aSbellard 83ef693a0Sbellard #include "qemu.h" 93b249d26SPeter Maydell #include "user-internals.h" 10db2af69dSRichard Henderson #include "signal-common.h" 113ad0a769SPeter Maydell #include "loader.h" 125423e6d3SPeter Maydell #include "user-mmap.h" 1376cad711SPaolo Bonzini #include "disas/disas.h" 14ce543844SPhilippe Mathieu-Daudé #include "qemu/bitops.h" 15f348b6d1SVeronia Bahaa #include "qemu/path.h" 16dc5e9ac7SMarkus Armbruster #include "qemu/queue.h" 17c6a2377fSRichard Henderson #include "qemu/guest-random.h" 186fd59449SRichard Henderson #include "qemu/units.h" 19ee947430SAlex Bennée #include "qemu/selfmap.h" 20370ed600SJamie Iles #include "qemu/lockable.h" 21c7f17e7bSRichard Henderson #include "qapi/error.h" 22cc37d98bSRichard Henderson #include "qemu/error-report.h" 23db2af69dSRichard Henderson #include "target_signal.h" 247c10cb38SIlya Leoshkevich #include "accel/tcg/debuginfo.h" 2531e31b8aSbellard 26e58ffeb3Smalc #ifdef _ARCH_PPC64 27a6cc84f4Smalc #undef ARCH_DLINFO 28a6cc84f4Smalc #undef ELF_PLATFORM 29a6cc84f4Smalc #undef ELF_HWCAP 30ad6919dcSPeter Maydell #undef ELF_HWCAP2 31a6cc84f4Smalc #undef ELF_CLASS 32a6cc84f4Smalc #undef ELF_DATA 33a6cc84f4Smalc #undef ELF_ARCH 34a6cc84f4Smalc #endif 35a6cc84f4Smalc 36edf8e2afSMika Westerberg #define ELF_OSABI ELFOSABI_SYSV 37edf8e2afSMika Westerberg 38cb33da57Sblueswir1 /* from personality.h */ 39cb33da57Sblueswir1 40cb33da57Sblueswir1 /* 41cb33da57Sblueswir1 * Flags for bug emulation. 42cb33da57Sblueswir1 * 43cb33da57Sblueswir1 * These occupy the top three bytes. 44cb33da57Sblueswir1 */ 45cb33da57Sblueswir1 enum { 46cb33da57Sblueswir1 ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */ 47d97ef72eSRichard Henderson FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to 48d97ef72eSRichard Henderson descriptors (signal handling) */ 49cb33da57Sblueswir1 MMAP_PAGE_ZERO = 0x0100000, 50cb33da57Sblueswir1 ADDR_COMPAT_LAYOUT = 0x0200000, 51cb33da57Sblueswir1 READ_IMPLIES_EXEC = 0x0400000, 52cb33da57Sblueswir1 ADDR_LIMIT_32BIT = 0x0800000, 53cb33da57Sblueswir1 SHORT_INODE = 0x1000000, 54cb33da57Sblueswir1 WHOLE_SECONDS = 0x2000000, 55cb33da57Sblueswir1 STICKY_TIMEOUTS = 0x4000000, 56cb33da57Sblueswir1 ADDR_LIMIT_3GB = 0x8000000, 57cb33da57Sblueswir1 }; 58cb33da57Sblueswir1 59cb33da57Sblueswir1 /* 60cb33da57Sblueswir1 * Personality types. 61cb33da57Sblueswir1 * 62cb33da57Sblueswir1 * These go in the low byte. Avoid using the top bit, it will 63cb33da57Sblueswir1 * conflict with error returns. 64cb33da57Sblueswir1 */ 65cb33da57Sblueswir1 enum { 66cb33da57Sblueswir1 PER_LINUX = 0x0000, 67cb33da57Sblueswir1 PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, 68cb33da57Sblueswir1 PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS, 69cb33da57Sblueswir1 PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 70cb33da57Sblueswir1 PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, 71d97ef72eSRichard Henderson PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE, 72cb33da57Sblueswir1 PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, 73cb33da57Sblueswir1 PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, 74cb33da57Sblueswir1 PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, 75cb33da57Sblueswir1 PER_BSD = 0x0006, 76cb33da57Sblueswir1 PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, 77cb33da57Sblueswir1 PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, 78cb33da57Sblueswir1 PER_LINUX32 = 0x0008, 79cb33da57Sblueswir1 PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB, 80cb33da57Sblueswir1 PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */ 81cb33da57Sblueswir1 PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */ 82cb33da57Sblueswir1 PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */ 83cb33da57Sblueswir1 PER_RISCOS = 0x000c, 84cb33da57Sblueswir1 PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, 85cb33da57Sblueswir1 PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 86cb33da57Sblueswir1 PER_OSF4 = 0x000f, /* OSF/1 v4 */ 87cb33da57Sblueswir1 PER_HPUX = 0x0010, 88cb33da57Sblueswir1 PER_MASK = 0x00ff, 89cb33da57Sblueswir1 }; 90cb33da57Sblueswir1 91cb33da57Sblueswir1 /* 92cb33da57Sblueswir1 * Return the base personality without flags. 93cb33da57Sblueswir1 */ 94cb33da57Sblueswir1 #define personality(pers) (pers & PER_MASK) 95cb33da57Sblueswir1 963cb10cfaSChristophe Lyon int info_is_fdpic(struct image_info *info) 973cb10cfaSChristophe Lyon { 983cb10cfaSChristophe Lyon return info->personality == PER_LINUX_FDPIC; 993cb10cfaSChristophe Lyon } 1003cb10cfaSChristophe Lyon 10183fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */ 10283fb7adfSbellard #ifndef MAP_DENYWRITE 10383fb7adfSbellard #define MAP_DENYWRITE 0 10483fb7adfSbellard #endif 10583fb7adfSbellard 10683fb7adfSbellard /* should probably go in elf.h */ 10783fb7adfSbellard #ifndef ELIBBAD 10883fb7adfSbellard #define ELIBBAD 80 10983fb7adfSbellard #endif 11083fb7adfSbellard 111ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN 11228490231SRichard Henderson #define ELF_DATA ELFDATA2MSB 11328490231SRichard Henderson #else 11428490231SRichard Henderson #define ELF_DATA ELFDATA2LSB 11528490231SRichard Henderson #endif 11628490231SRichard Henderson 117a29f998dSPaolo Bonzini #ifdef TARGET_ABI_MIPSN32 118918fc54cSPaolo Bonzini typedef abi_ullong target_elf_greg_t; 119918fc54cSPaolo Bonzini #define tswapreg(ptr) tswap64(ptr) 120a29f998dSPaolo Bonzini #else 121a29f998dSPaolo Bonzini typedef abi_ulong target_elf_greg_t; 122a29f998dSPaolo Bonzini #define tswapreg(ptr) tswapal(ptr) 123a29f998dSPaolo Bonzini #endif 124a29f998dSPaolo Bonzini 12521e807faSNathan Froyd #ifdef USE_UID16 1261ddd592fSPaolo Bonzini typedef abi_ushort target_uid_t; 1271ddd592fSPaolo Bonzini typedef abi_ushort target_gid_t; 12821e807faSNathan Froyd #else 129f8fd4fc4SPaolo Bonzini typedef abi_uint target_uid_t; 130f8fd4fc4SPaolo Bonzini typedef abi_uint target_gid_t; 13121e807faSNathan Froyd #endif 132f8fd4fc4SPaolo Bonzini typedef abi_int target_pid_t; 13321e807faSNathan Froyd 13430ac07d4Sbellard #ifdef TARGET_I386 13530ac07d4Sbellard 13615338fd7Sbellard #define ELF_HWCAP get_elf_hwcap() 13715338fd7Sbellard 13815338fd7Sbellard static uint32_t get_elf_hwcap(void) 13915338fd7Sbellard { 140a2247f8eSAndreas Färber X86CPU *cpu = X86_CPU(thread_cpu); 141a2247f8eSAndreas Färber 142a2247f8eSAndreas Färber return cpu->env.features[FEAT_1_EDX]; 14315338fd7Sbellard } 14415338fd7Sbellard 14584409ddbSj_mayer #ifdef TARGET_X86_64 14684409ddbSj_mayer #define ELF_CLASS ELFCLASS64 14784409ddbSj_mayer #define ELF_ARCH EM_X86_64 14884409ddbSj_mayer 1499263ba84SRichard Henderson #define ELF_PLATFORM "x86_64" 1509263ba84SRichard Henderson 15184409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 15284409ddbSj_mayer { 15384409ddbSj_mayer regs->rax = 0; 15484409ddbSj_mayer regs->rsp = infop->start_stack; 15584409ddbSj_mayer regs->rip = infop->entry; 15684409ddbSj_mayer } 15784409ddbSj_mayer 1589edc5d79SMika Westerberg #define ELF_NREG 27 159c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1609edc5d79SMika Westerberg 1619edc5d79SMika Westerberg /* 1629edc5d79SMika Westerberg * Note that ELF_NREG should be 29 as there should be place for 1639edc5d79SMika Westerberg * TRAPNO and ERR "registers" as well but linux doesn't dump 1649edc5d79SMika Westerberg * those. 1659edc5d79SMika Westerberg * 1669edc5d79SMika Westerberg * See linux kernel: arch/x86/include/asm/elf.h 1679edc5d79SMika Westerberg */ 16805390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) 1699edc5d79SMika Westerberg { 170030912e0SIlya Leoshkevich (*regs)[0] = tswapreg(env->regs[15]); 171030912e0SIlya Leoshkevich (*regs)[1] = tswapreg(env->regs[14]); 172030912e0SIlya Leoshkevich (*regs)[2] = tswapreg(env->regs[13]); 173030912e0SIlya Leoshkevich (*regs)[3] = tswapreg(env->regs[12]); 174030912e0SIlya Leoshkevich (*regs)[4] = tswapreg(env->regs[R_EBP]); 175030912e0SIlya Leoshkevich (*regs)[5] = tswapreg(env->regs[R_EBX]); 176030912e0SIlya Leoshkevich (*regs)[6] = tswapreg(env->regs[11]); 177030912e0SIlya Leoshkevich (*regs)[7] = tswapreg(env->regs[10]); 178030912e0SIlya Leoshkevich (*regs)[8] = tswapreg(env->regs[9]); 179030912e0SIlya Leoshkevich (*regs)[9] = tswapreg(env->regs[8]); 180030912e0SIlya Leoshkevich (*regs)[10] = tswapreg(env->regs[R_EAX]); 181030912e0SIlya Leoshkevich (*regs)[11] = tswapreg(env->regs[R_ECX]); 182030912e0SIlya Leoshkevich (*regs)[12] = tswapreg(env->regs[R_EDX]); 183030912e0SIlya Leoshkevich (*regs)[13] = tswapreg(env->regs[R_ESI]); 184030912e0SIlya Leoshkevich (*regs)[14] = tswapreg(env->regs[R_EDI]); 185030912e0SIlya Leoshkevich (*regs)[15] = tswapreg(env->regs[R_EAX]); /* XXX */ 186030912e0SIlya Leoshkevich (*regs)[16] = tswapreg(env->eip); 187030912e0SIlya Leoshkevich (*regs)[17] = tswapreg(env->segs[R_CS].selector & 0xffff); 188030912e0SIlya Leoshkevich (*regs)[18] = tswapreg(env->eflags); 189030912e0SIlya Leoshkevich (*regs)[19] = tswapreg(env->regs[R_ESP]); 190030912e0SIlya Leoshkevich (*regs)[20] = tswapreg(env->segs[R_SS].selector & 0xffff); 191030912e0SIlya Leoshkevich (*regs)[21] = tswapreg(env->segs[R_FS].selector & 0xffff); 192030912e0SIlya Leoshkevich (*regs)[22] = tswapreg(env->segs[R_GS].selector & 0xffff); 193030912e0SIlya Leoshkevich (*regs)[23] = tswapreg(env->segs[R_DS].selector & 0xffff); 194030912e0SIlya Leoshkevich (*regs)[24] = tswapreg(env->segs[R_ES].selector & 0xffff); 195030912e0SIlya Leoshkevich (*regs)[25] = tswapreg(env->segs[R_FS].selector & 0xffff); 196030912e0SIlya Leoshkevich (*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff); 1979edc5d79SMika Westerberg } 1989edc5d79SMika Westerberg 199d461b73eSRichard Henderson #if ULONG_MAX > UINT32_MAX 200d461b73eSRichard Henderson #define INIT_GUEST_COMMPAGE 201d461b73eSRichard Henderson static bool init_guest_commpage(void) 202d461b73eSRichard Henderson { 203d461b73eSRichard Henderson /* 204d461b73eSRichard Henderson * The vsyscall page is at a high negative address aka kernel space, 205d461b73eSRichard Henderson * which means that we cannot actually allocate it with target_mmap. 206d461b73eSRichard Henderson * We still should be able to use page_set_flags, unless the user 207d461b73eSRichard Henderson * has specified -R reserved_va, which would trigger an assert(). 208d461b73eSRichard Henderson */ 209d461b73eSRichard Henderson if (reserved_va != 0 && 21095059f9cSRichard Henderson TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE - 1 > reserved_va) { 211d461b73eSRichard Henderson error_report("Cannot allocate vsyscall page"); 212d461b73eSRichard Henderson exit(EXIT_FAILURE); 213d461b73eSRichard Henderson } 214d461b73eSRichard Henderson page_set_flags(TARGET_VSYSCALL_PAGE, 21549840a4aSRichard Henderson TARGET_VSYSCALL_PAGE | ~TARGET_PAGE_MASK, 216d461b73eSRichard Henderson PAGE_EXEC | PAGE_VALID); 217d461b73eSRichard Henderson return true; 218d461b73eSRichard Henderson } 219d461b73eSRichard Henderson #endif 22084409ddbSj_mayer #else 22184409ddbSj_mayer 22230ac07d4Sbellard /* 22330ac07d4Sbellard * This is used to ensure we don't load something for the wrong architecture. 22430ac07d4Sbellard */ 22530ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) 22630ac07d4Sbellard 22730ac07d4Sbellard /* 22830ac07d4Sbellard * These are used to set parameters in the core dumps. 22930ac07d4Sbellard */ 23030ac07d4Sbellard #define ELF_CLASS ELFCLASS32 23130ac07d4Sbellard #define ELF_ARCH EM_386 23230ac07d4Sbellard 2339263ba84SRichard Henderson #define ELF_PLATFORM get_elf_platform() 234872f3d04SRichard Henderson #define EXSTACK_DEFAULT true 2359263ba84SRichard Henderson 2369263ba84SRichard Henderson static const char *get_elf_platform(void) 2379263ba84SRichard Henderson { 2389263ba84SRichard Henderson static char elf_platform[] = "i386"; 2399263ba84SRichard Henderson int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); 2409263ba84SRichard Henderson if (family > 6) { 2419263ba84SRichard Henderson family = 6; 2429263ba84SRichard Henderson } 2439263ba84SRichard Henderson if (family >= 3) { 2449263ba84SRichard Henderson elf_platform[1] = '0' + family; 2459263ba84SRichard Henderson } 2469263ba84SRichard Henderson return elf_platform; 2479263ba84SRichard Henderson } 2489263ba84SRichard Henderson 249d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 250d97ef72eSRichard Henderson struct image_info *infop) 251e5fe0c52Spbrook { 252e5fe0c52Spbrook regs->esp = infop->start_stack; 253e5fe0c52Spbrook regs->eip = infop->entry; 254e5fe0c52Spbrook 25530ac07d4Sbellard /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program 25630ac07d4Sbellard starts %edx contains a pointer to a function which might be 25730ac07d4Sbellard registered using `atexit'. This provides a mean for the 25830ac07d4Sbellard dynamic linker to call DT_FINI functions for shared libraries 25930ac07d4Sbellard that have been loaded before the code runs. 26030ac07d4Sbellard 26130ac07d4Sbellard A value of 0 tells we have no such handler. */ 262e5fe0c52Spbrook regs->edx = 0; 263b346ff46Sbellard } 2649edc5d79SMika Westerberg 2659edc5d79SMika Westerberg #define ELF_NREG 17 266c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 2679edc5d79SMika Westerberg 2689edc5d79SMika Westerberg /* 2699edc5d79SMika Westerberg * Note that ELF_NREG should be 19 as there should be place for 2709edc5d79SMika Westerberg * TRAPNO and ERR "registers" as well but linux doesn't dump 2719edc5d79SMika Westerberg * those. 2729edc5d79SMika Westerberg * 2739edc5d79SMika Westerberg * See linux kernel: arch/x86/include/asm/elf.h 2749edc5d79SMika Westerberg */ 27505390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) 2769edc5d79SMika Westerberg { 277030912e0SIlya Leoshkevich (*regs)[0] = tswapreg(env->regs[R_EBX]); 278030912e0SIlya Leoshkevich (*regs)[1] = tswapreg(env->regs[R_ECX]); 279030912e0SIlya Leoshkevich (*regs)[2] = tswapreg(env->regs[R_EDX]); 280030912e0SIlya Leoshkevich (*regs)[3] = tswapreg(env->regs[R_ESI]); 281030912e0SIlya Leoshkevich (*regs)[4] = tswapreg(env->regs[R_EDI]); 282030912e0SIlya Leoshkevich (*regs)[5] = tswapreg(env->regs[R_EBP]); 283030912e0SIlya Leoshkevich (*regs)[6] = tswapreg(env->regs[R_EAX]); 284030912e0SIlya Leoshkevich (*regs)[7] = tswapreg(env->segs[R_DS].selector & 0xffff); 285030912e0SIlya Leoshkevich (*regs)[8] = tswapreg(env->segs[R_ES].selector & 0xffff); 286030912e0SIlya Leoshkevich (*regs)[9] = tswapreg(env->segs[R_FS].selector & 0xffff); 287030912e0SIlya Leoshkevich (*regs)[10] = tswapreg(env->segs[R_GS].selector & 0xffff); 288030912e0SIlya Leoshkevich (*regs)[11] = tswapreg(env->regs[R_EAX]); /* XXX */ 289030912e0SIlya Leoshkevich (*regs)[12] = tswapreg(env->eip); 290030912e0SIlya Leoshkevich (*regs)[13] = tswapreg(env->segs[R_CS].selector & 0xffff); 291030912e0SIlya Leoshkevich (*regs)[14] = tswapreg(env->eflags); 292030912e0SIlya Leoshkevich (*regs)[15] = tswapreg(env->regs[R_ESP]); 293030912e0SIlya Leoshkevich (*regs)[16] = tswapreg(env->segs[R_SS].selector & 0xffff); 2949edc5d79SMika Westerberg } 29584409ddbSj_mayer #endif 296b346ff46Sbellard 2979edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP 298b346ff46Sbellard #define ELF_EXEC_PAGESIZE 4096 299b346ff46Sbellard 300b346ff46Sbellard #endif 301b346ff46Sbellard 302b346ff46Sbellard #ifdef TARGET_ARM 303b346ff46Sbellard 30424e76ff0SPeter Maydell #ifndef TARGET_AARCH64 30524e76ff0SPeter Maydell /* 32 bit ARM definitions */ 30624e76ff0SPeter Maydell 307b597c3f7SPeter Crosthwaite #define ELF_ARCH EM_ARM 308b346ff46Sbellard #define ELF_CLASS ELFCLASS32 309872f3d04SRichard Henderson #define EXSTACK_DEFAULT true 310b346ff46Sbellard 311d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 312d97ef72eSRichard Henderson struct image_info *infop) 313b346ff46Sbellard { 314992f48a0Sblueswir1 abi_long stack = infop->start_stack; 315b346ff46Sbellard memset(regs, 0, sizeof(*regs)); 31699033caeSAlexander Graf 317167e4cdcSPeter Maydell regs->uregs[16] = ARM_CPU_MODE_USR; 318167e4cdcSPeter Maydell if (infop->entry & 1) { 319167e4cdcSPeter Maydell regs->uregs[16] |= CPSR_T; 320167e4cdcSPeter Maydell } 321167e4cdcSPeter Maydell regs->uregs[15] = infop->entry & 0xfffffffe; 322167e4cdcSPeter Maydell regs->uregs[13] = infop->start_stack; 3232f619698Sbellard /* FIXME - what to for failure of get_user()? */ 324167e4cdcSPeter Maydell get_user_ual(regs->uregs[2], stack + 8); /* envp */ 325167e4cdcSPeter Maydell get_user_ual(regs->uregs[1], stack + 4); /* envp */ 326a1516e92Sbellard /* XXX: it seems that r0 is zeroed after ! */ 327167e4cdcSPeter Maydell regs->uregs[0] = 0; 328e5fe0c52Spbrook /* For uClinux PIC binaries. */ 329863cf0b7Sj_mayer /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ 330167e4cdcSPeter Maydell regs->uregs[10] = infop->start_data; 3313cb10cfaSChristophe Lyon 3323cb10cfaSChristophe Lyon /* Support ARM FDPIC. */ 3333cb10cfaSChristophe Lyon if (info_is_fdpic(infop)) { 3343cb10cfaSChristophe Lyon /* As described in the ABI document, r7 points to the loadmap info 3353cb10cfaSChristophe Lyon * prepared by the kernel. If an interpreter is needed, r8 points 3363cb10cfaSChristophe Lyon * to the interpreter loadmap and r9 points to the interpreter 3373cb10cfaSChristophe Lyon * PT_DYNAMIC info. If no interpreter is needed, r8 is zero, and 3383cb10cfaSChristophe Lyon * r9 points to the main program PT_DYNAMIC info. 3393cb10cfaSChristophe Lyon */ 3403cb10cfaSChristophe Lyon regs->uregs[7] = infop->loadmap_addr; 3413cb10cfaSChristophe Lyon if (infop->interpreter_loadmap_addr) { 3423cb10cfaSChristophe Lyon /* Executable is dynamically loaded. */ 3433cb10cfaSChristophe Lyon regs->uregs[8] = infop->interpreter_loadmap_addr; 3443cb10cfaSChristophe Lyon regs->uregs[9] = infop->interpreter_pt_dynamic_addr; 3453cb10cfaSChristophe Lyon } else { 3463cb10cfaSChristophe Lyon regs->uregs[8] = 0; 3473cb10cfaSChristophe Lyon regs->uregs[9] = infop->pt_dynamic_addr; 3483cb10cfaSChristophe Lyon } 3493cb10cfaSChristophe Lyon } 350b346ff46Sbellard } 351b346ff46Sbellard 352edf8e2afSMika Westerberg #define ELF_NREG 18 353c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 354edf8e2afSMika Westerberg 35505390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env) 356edf8e2afSMika Westerberg { 35786cd7b2dSPaolo Bonzini (*regs)[0] = tswapreg(env->regs[0]); 35886cd7b2dSPaolo Bonzini (*regs)[1] = tswapreg(env->regs[1]); 35986cd7b2dSPaolo Bonzini (*regs)[2] = tswapreg(env->regs[2]); 36086cd7b2dSPaolo Bonzini (*regs)[3] = tswapreg(env->regs[3]); 36186cd7b2dSPaolo Bonzini (*regs)[4] = tswapreg(env->regs[4]); 36286cd7b2dSPaolo Bonzini (*regs)[5] = tswapreg(env->regs[5]); 36386cd7b2dSPaolo Bonzini (*regs)[6] = tswapreg(env->regs[6]); 36486cd7b2dSPaolo Bonzini (*regs)[7] = tswapreg(env->regs[7]); 36586cd7b2dSPaolo Bonzini (*regs)[8] = tswapreg(env->regs[8]); 36686cd7b2dSPaolo Bonzini (*regs)[9] = tswapreg(env->regs[9]); 36786cd7b2dSPaolo Bonzini (*regs)[10] = tswapreg(env->regs[10]); 36886cd7b2dSPaolo Bonzini (*regs)[11] = tswapreg(env->regs[11]); 36986cd7b2dSPaolo Bonzini (*regs)[12] = tswapreg(env->regs[12]); 37086cd7b2dSPaolo Bonzini (*regs)[13] = tswapreg(env->regs[13]); 37186cd7b2dSPaolo Bonzini (*regs)[14] = tswapreg(env->regs[14]); 37286cd7b2dSPaolo Bonzini (*regs)[15] = tswapreg(env->regs[15]); 373edf8e2afSMika Westerberg 37486cd7b2dSPaolo Bonzini (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env)); 37586cd7b2dSPaolo Bonzini (*regs)[17] = tswapreg(env->regs[0]); /* XXX */ 376edf8e2afSMika Westerberg } 377edf8e2afSMika Westerberg 37830ac07d4Sbellard #define USE_ELF_CORE_DUMP 37930ac07d4Sbellard #define ELF_EXEC_PAGESIZE 4096 38030ac07d4Sbellard 381afce2927Sbellard enum 382afce2927Sbellard { 383afce2927Sbellard ARM_HWCAP_ARM_SWP = 1 << 0, 384afce2927Sbellard ARM_HWCAP_ARM_HALF = 1 << 1, 385afce2927Sbellard ARM_HWCAP_ARM_THUMB = 1 << 2, 386afce2927Sbellard ARM_HWCAP_ARM_26BIT = 1 << 3, 387afce2927Sbellard ARM_HWCAP_ARM_FAST_MULT = 1 << 4, 388afce2927Sbellard ARM_HWCAP_ARM_FPA = 1 << 5, 389afce2927Sbellard ARM_HWCAP_ARM_VFP = 1 << 6, 390afce2927Sbellard ARM_HWCAP_ARM_EDSP = 1 << 7, 391cf6de34aSRiku Voipio ARM_HWCAP_ARM_JAVA = 1 << 8, 392cf6de34aSRiku Voipio ARM_HWCAP_ARM_IWMMXT = 1 << 9, 39343ce393eSPeter Maydell ARM_HWCAP_ARM_CRUNCH = 1 << 10, 39443ce393eSPeter Maydell ARM_HWCAP_ARM_THUMBEE = 1 << 11, 39543ce393eSPeter Maydell ARM_HWCAP_ARM_NEON = 1 << 12, 39643ce393eSPeter Maydell ARM_HWCAP_ARM_VFPv3 = 1 << 13, 39743ce393eSPeter Maydell ARM_HWCAP_ARM_VFPv3D16 = 1 << 14, 39824682654SPeter Maydell ARM_HWCAP_ARM_TLS = 1 << 15, 39924682654SPeter Maydell ARM_HWCAP_ARM_VFPv4 = 1 << 16, 40024682654SPeter Maydell ARM_HWCAP_ARM_IDIVA = 1 << 17, 40124682654SPeter Maydell ARM_HWCAP_ARM_IDIVT = 1 << 18, 40224682654SPeter Maydell ARM_HWCAP_ARM_VFPD32 = 1 << 19, 40324682654SPeter Maydell ARM_HWCAP_ARM_LPAE = 1 << 20, 40424682654SPeter Maydell ARM_HWCAP_ARM_EVTSTRM = 1 << 21, 40523d7f14dSPeter Maydell ARM_HWCAP_ARM_FPHP = 1 << 22, 40623d7f14dSPeter Maydell ARM_HWCAP_ARM_ASIMDHP = 1 << 23, 40723d7f14dSPeter Maydell ARM_HWCAP_ARM_ASIMDDP = 1 << 24, 40823d7f14dSPeter Maydell ARM_HWCAP_ARM_ASIMDFHM = 1 << 25, 40923d7f14dSPeter Maydell ARM_HWCAP_ARM_ASIMDBF16 = 1 << 26, 41023d7f14dSPeter Maydell ARM_HWCAP_ARM_I8MM = 1 << 27, 411afce2927Sbellard }; 412afce2927Sbellard 413ad6919dcSPeter Maydell enum { 414ad6919dcSPeter Maydell ARM_HWCAP2_ARM_AES = 1 << 0, 415ad6919dcSPeter Maydell ARM_HWCAP2_ARM_PMULL = 1 << 1, 416ad6919dcSPeter Maydell ARM_HWCAP2_ARM_SHA1 = 1 << 2, 417ad6919dcSPeter Maydell ARM_HWCAP2_ARM_SHA2 = 1 << 3, 418ad6919dcSPeter Maydell ARM_HWCAP2_ARM_CRC32 = 1 << 4, 41923d7f14dSPeter Maydell ARM_HWCAP2_ARM_SB = 1 << 5, 42023d7f14dSPeter Maydell ARM_HWCAP2_ARM_SSBS = 1 << 6, 421ad6919dcSPeter Maydell }; 422ad6919dcSPeter Maydell 4236b1275ffSPeter Maydell /* The commpage only exists for 32 bit kernels */ 4246b1275ffSPeter Maydell 42566346fafSRichard Henderson #define HI_COMMPAGE (intptr_t)0xffff0f00u 426ee947430SAlex Bennée 427ee947430SAlex Bennée static bool init_guest_commpage(void) 42897cc7560SDr. David Alan Gilbert { 429d713cf4dSPhilippe Mathieu-Daudé ARMCPU *cpu = ARM_CPU(thread_cpu); 430d713cf4dSPhilippe Mathieu-Daudé abi_ptr commpage; 431d713cf4dSPhilippe Mathieu-Daudé void *want; 432d713cf4dSPhilippe Mathieu-Daudé void *addr; 433d713cf4dSPhilippe Mathieu-Daudé 434d713cf4dSPhilippe Mathieu-Daudé /* 435d713cf4dSPhilippe Mathieu-Daudé * M-profile allocates maximum of 2GB address space, so can never 436d713cf4dSPhilippe Mathieu-Daudé * allocate the commpage. Skip it. 437d713cf4dSPhilippe Mathieu-Daudé */ 438d713cf4dSPhilippe Mathieu-Daudé if (arm_feature(&cpu->env, ARM_FEATURE_M)) { 439d713cf4dSPhilippe Mathieu-Daudé return true; 440d713cf4dSPhilippe Mathieu-Daudé } 441d713cf4dSPhilippe Mathieu-Daudé 442d713cf4dSPhilippe Mathieu-Daudé commpage = HI_COMMPAGE & -qemu_host_page_size; 443d713cf4dSPhilippe Mathieu-Daudé want = g2h_untagged(commpage); 444d713cf4dSPhilippe Mathieu-Daudé addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, 4455c3e87f3SAlex Bennée MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 44697cc7560SDr. David Alan Gilbert 4476cda41daSRichard Henderson if (addr == MAP_FAILED) { 448ee947430SAlex Bennée perror("Allocating guest commpage"); 449ee947430SAlex Bennée exit(EXIT_FAILURE); 450ee947430SAlex Bennée } 451ee947430SAlex Bennée if (addr != want) { 452ee947430SAlex Bennée return false; 453806d1021SMeador Inge } 454806d1021SMeador Inge 455ee947430SAlex Bennée /* Set kernel helper versions; rest of page is 0. */ 4566cda41daSRichard Henderson __put_user(5, (uint32_t *)g2h_untagged(0xffff0ffcu)); 45797cc7560SDr. David Alan Gilbert 4586cda41daSRichard Henderson if (mprotect(addr, qemu_host_page_size, PROT_READ)) { 45997cc7560SDr. David Alan Gilbert perror("Protecting guest commpage"); 460ee947430SAlex Bennée exit(EXIT_FAILURE); 46197cc7560SDr. David Alan Gilbert } 4626cda41daSRichard Henderson 4636cda41daSRichard Henderson page_set_flags(commpage, commpage | ~qemu_host_page_mask, 4646cda41daSRichard Henderson PAGE_READ | PAGE_EXEC | PAGE_VALID); 465ee947430SAlex Bennée return true; 46697cc7560SDr. David Alan Gilbert } 467adf050b1SBenoit Canet 468adf050b1SBenoit Canet #define ELF_HWCAP get_elf_hwcap() 469ad6919dcSPeter Maydell #define ELF_HWCAP2 get_elf_hwcap2() 470adf050b1SBenoit Canet 471a55b9e72SHelge Deller uint32_t get_elf_hwcap(void) 472adf050b1SBenoit Canet { 473a2247f8eSAndreas Färber ARMCPU *cpu = ARM_CPU(thread_cpu); 474adf050b1SBenoit Canet uint32_t hwcaps = 0; 475adf050b1SBenoit Canet 476adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_SWP; 477adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_HALF; 478adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_THUMB; 479adf050b1SBenoit Canet hwcaps |= ARM_HWCAP_ARM_FAST_MULT; 480adf050b1SBenoit Canet 481adf050b1SBenoit Canet /* probe for the extra features */ 482adf050b1SBenoit Canet #define GET_FEATURE(feat, hwcap) \ 483a2247f8eSAndreas Färber do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) 484962fcbf2SRichard Henderson 485962fcbf2SRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \ 486962fcbf2SRichard Henderson do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) 487962fcbf2SRichard Henderson 48824682654SPeter Maydell /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */ 48924682654SPeter Maydell GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP); 490adf050b1SBenoit Canet GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT); 491adf050b1SBenoit Canet GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); 492adf050b1SBenoit Canet GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON); 49324682654SPeter Maydell GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS); 494bfa8a370SRichard Henderson GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE); 495873b73c0SPeter Maydell GET_FEATURE_ID(aa32_arm_div, ARM_HWCAP_ARM_IDIVA); 496873b73c0SPeter Maydell GET_FEATURE_ID(aa32_thumb_div, ARM_HWCAP_ARM_IDIVT); 497bfa8a370SRichard Henderson GET_FEATURE_ID(aa32_vfp, ARM_HWCAP_ARM_VFP); 498bfa8a370SRichard Henderson 499bfa8a370SRichard Henderson if (cpu_isar_feature(aa32_fpsp_v3, cpu) || 500bfa8a370SRichard Henderson cpu_isar_feature(aa32_fpdp_v3, cpu)) { 501bfa8a370SRichard Henderson hwcaps |= ARM_HWCAP_ARM_VFPv3; 502bfa8a370SRichard Henderson if (cpu_isar_feature(aa32_simd_r32, cpu)) { 503bfa8a370SRichard Henderson hwcaps |= ARM_HWCAP_ARM_VFPD32; 504bfa8a370SRichard Henderson } else { 505bfa8a370SRichard Henderson hwcaps |= ARM_HWCAP_ARM_VFPv3D16; 506bfa8a370SRichard Henderson } 507bfa8a370SRichard Henderson } 508bfa8a370SRichard Henderson GET_FEATURE_ID(aa32_simdfmac, ARM_HWCAP_ARM_VFPv4); 509429b7e01SPeter Maydell /* 510429b7e01SPeter Maydell * MVFR1.FPHP and .SIMDHP must be in sync, and QEMU uses the same 511429b7e01SPeter Maydell * isar_feature function for both. The kernel reports them as two hwcaps. 512429b7e01SPeter Maydell */ 513429b7e01SPeter Maydell GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_FPHP); 514429b7e01SPeter Maydell GET_FEATURE_ID(aa32_fp16_arith, ARM_HWCAP_ARM_ASIMDHP); 515429b7e01SPeter Maydell GET_FEATURE_ID(aa32_dp, ARM_HWCAP_ARM_ASIMDDP); 516429b7e01SPeter Maydell GET_FEATURE_ID(aa32_fhm, ARM_HWCAP_ARM_ASIMDFHM); 517429b7e01SPeter Maydell GET_FEATURE_ID(aa32_bf16, ARM_HWCAP_ARM_ASIMDBF16); 518429b7e01SPeter Maydell GET_FEATURE_ID(aa32_i8mm, ARM_HWCAP_ARM_I8MM); 519adf050b1SBenoit Canet 520adf050b1SBenoit Canet return hwcaps; 521adf050b1SBenoit Canet } 522afce2927Sbellard 523a55b9e72SHelge Deller uint32_t get_elf_hwcap2(void) 524ad6919dcSPeter Maydell { 525ad6919dcSPeter Maydell ARMCPU *cpu = ARM_CPU(thread_cpu); 526ad6919dcSPeter Maydell uint32_t hwcaps = 0; 527ad6919dcSPeter Maydell 528962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_aes, ARM_HWCAP2_ARM_AES); 529962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_pmull, ARM_HWCAP2_ARM_PMULL); 530962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_sha1, ARM_HWCAP2_ARM_SHA1); 531962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_sha2, ARM_HWCAP2_ARM_SHA2); 532962fcbf2SRichard Henderson GET_FEATURE_ID(aa32_crc32, ARM_HWCAP2_ARM_CRC32); 533429b7e01SPeter Maydell GET_FEATURE_ID(aa32_sb, ARM_HWCAP2_ARM_SB); 534429b7e01SPeter Maydell GET_FEATURE_ID(aa32_ssbs, ARM_HWCAP2_ARM_SSBS); 535ad6919dcSPeter Maydell return hwcaps; 536ad6919dcSPeter Maydell } 537ad6919dcSPeter Maydell 538a55b9e72SHelge Deller const char *elf_hwcap_str(uint32_t bit) 539a55b9e72SHelge Deller { 540a55b9e72SHelge Deller static const char *hwcap_str[] = { 541a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_SWP )] = "swp", 542a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_HALF )] = "half", 543a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_THUMB )] = "thumb", 544a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_26BIT )] = "26bit", 545a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_FAST_MULT)] = "fast_mult", 546a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_FPA )] = "fpa", 547a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_VFP )] = "vfp", 548a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_EDSP )] = "edsp", 549a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_JAVA )] = "java", 550a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_IWMMXT )] = "iwmmxt", 551a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_CRUNCH )] = "crunch", 552a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_THUMBEE )] = "thumbee", 553a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_NEON )] = "neon", 554a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_VFPv3 )] = "vfpv3", 555a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_VFPv3D16 )] = "vfpv3d16", 556a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_TLS )] = "tls", 557a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_VFPv4 )] = "vfpv4", 558a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_IDIVA )] = "idiva", 559a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_IDIVT )] = "idivt", 560a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_VFPD32 )] = "vfpd32", 561a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_LPAE )] = "lpae", 562a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_ARM_EVTSTRM )] = "evtstrm", 56323d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP_ARM_FPHP )] = "fphp", 56423d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP_ARM_ASIMDHP )] = "asimdhp", 56523d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP_ARM_ASIMDDP )] = "asimddp", 56623d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP_ARM_ASIMDFHM )] = "asimdfhm", 56723d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP_ARM_ASIMDBF16)] = "asimdbf16", 56823d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP_ARM_I8MM )] = "i8mm", 569a55b9e72SHelge Deller }; 570a55b9e72SHelge Deller 571a55b9e72SHelge Deller return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; 572a55b9e72SHelge Deller } 573a55b9e72SHelge Deller 574a55b9e72SHelge Deller const char *elf_hwcap2_str(uint32_t bit) 575a55b9e72SHelge Deller { 576a55b9e72SHelge Deller static const char *hwcap_str[] = { 577a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_ARM_AES )] = "aes", 578a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_ARM_PMULL)] = "pmull", 579a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_ARM_SHA1 )] = "sha1", 580a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_ARM_SHA2 )] = "sha2", 581a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_ARM_CRC32)] = "crc32", 58223d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP2_ARM_SB )] = "sb", 58323d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP2_ARM_SSBS )] = "ssbs", 584a55b9e72SHelge Deller }; 585a55b9e72SHelge Deller 586a55b9e72SHelge Deller return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; 587a55b9e72SHelge Deller } 588a55b9e72SHelge Deller 589ad6919dcSPeter Maydell #undef GET_FEATURE 590962fcbf2SRichard Henderson #undef GET_FEATURE_ID 591ad6919dcSPeter Maydell 59213ec4ec3SRichard Henderson #define ELF_PLATFORM get_elf_platform() 59313ec4ec3SRichard Henderson 59413ec4ec3SRichard Henderson static const char *get_elf_platform(void) 59513ec4ec3SRichard Henderson { 596b77af26eSRichard Henderson CPUARMState *env = cpu_env(thread_cpu); 59713ec4ec3SRichard Henderson 598ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN 59913ec4ec3SRichard Henderson # define END "b" 60013ec4ec3SRichard Henderson #else 60113ec4ec3SRichard Henderson # define END "l" 60213ec4ec3SRichard Henderson #endif 60313ec4ec3SRichard Henderson 60413ec4ec3SRichard Henderson if (arm_feature(env, ARM_FEATURE_V8)) { 60513ec4ec3SRichard Henderson return "v8" END; 60613ec4ec3SRichard Henderson } else if (arm_feature(env, ARM_FEATURE_V7)) { 60713ec4ec3SRichard Henderson if (arm_feature(env, ARM_FEATURE_M)) { 60813ec4ec3SRichard Henderson return "v7m" END; 60913ec4ec3SRichard Henderson } else { 61013ec4ec3SRichard Henderson return "v7" END; 61113ec4ec3SRichard Henderson } 61213ec4ec3SRichard Henderson } else if (arm_feature(env, ARM_FEATURE_V6)) { 61313ec4ec3SRichard Henderson return "v6" END; 61413ec4ec3SRichard Henderson } else if (arm_feature(env, ARM_FEATURE_V5)) { 61513ec4ec3SRichard Henderson return "v5" END; 61613ec4ec3SRichard Henderson } else { 61713ec4ec3SRichard Henderson return "v4" END; 61813ec4ec3SRichard Henderson } 61913ec4ec3SRichard Henderson 62013ec4ec3SRichard Henderson #undef END 62113ec4ec3SRichard Henderson } 62213ec4ec3SRichard Henderson 62324e76ff0SPeter Maydell #else 62424e76ff0SPeter Maydell /* 64 bit ARM definitions */ 62524e76ff0SPeter Maydell 626b597c3f7SPeter Crosthwaite #define ELF_ARCH EM_AARCH64 62724e76ff0SPeter Maydell #define ELF_CLASS ELFCLASS64 628ee3eb3a7SMarc-André Lureau #if TARGET_BIG_ENDIAN 629e20e3ec9SRichard Henderson # define ELF_PLATFORM "aarch64_be" 630e20e3ec9SRichard Henderson #else 63124e76ff0SPeter Maydell # define ELF_PLATFORM "aarch64" 632e20e3ec9SRichard Henderson #endif 63324e76ff0SPeter Maydell 63424e76ff0SPeter Maydell static inline void init_thread(struct target_pt_regs *regs, 63524e76ff0SPeter Maydell struct image_info *infop) 63624e76ff0SPeter Maydell { 63724e76ff0SPeter Maydell abi_long stack = infop->start_stack; 63824e76ff0SPeter Maydell memset(regs, 0, sizeof(*regs)); 63924e76ff0SPeter Maydell 64024e76ff0SPeter Maydell regs->pc = infop->entry & ~0x3ULL; 64124e76ff0SPeter Maydell regs->sp = stack; 64224e76ff0SPeter Maydell } 64324e76ff0SPeter Maydell 64424e76ff0SPeter Maydell #define ELF_NREG 34 64524e76ff0SPeter Maydell typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 64624e76ff0SPeter Maydell 64724e76ff0SPeter Maydell static void elf_core_copy_regs(target_elf_gregset_t *regs, 64824e76ff0SPeter Maydell const CPUARMState *env) 64924e76ff0SPeter Maydell { 65024e76ff0SPeter Maydell int i; 65124e76ff0SPeter Maydell 65224e76ff0SPeter Maydell for (i = 0; i < 32; i++) { 65324e76ff0SPeter Maydell (*regs)[i] = tswapreg(env->xregs[i]); 65424e76ff0SPeter Maydell } 65524e76ff0SPeter Maydell (*regs)[32] = tswapreg(env->pc); 65624e76ff0SPeter Maydell (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env)); 65724e76ff0SPeter Maydell } 65824e76ff0SPeter Maydell 65924e76ff0SPeter Maydell #define USE_ELF_CORE_DUMP 66024e76ff0SPeter Maydell #define ELF_EXEC_PAGESIZE 4096 66124e76ff0SPeter Maydell 66224e76ff0SPeter Maydell enum { 66324e76ff0SPeter Maydell ARM_HWCAP_A64_FP = 1 << 0, 66424e76ff0SPeter Maydell ARM_HWCAP_A64_ASIMD = 1 << 1, 66524e76ff0SPeter Maydell ARM_HWCAP_A64_EVTSTRM = 1 << 2, 66624e76ff0SPeter Maydell ARM_HWCAP_A64_AES = 1 << 3, 66724e76ff0SPeter Maydell ARM_HWCAP_A64_PMULL = 1 << 4, 66824e76ff0SPeter Maydell ARM_HWCAP_A64_SHA1 = 1 << 5, 66924e76ff0SPeter Maydell ARM_HWCAP_A64_SHA2 = 1 << 6, 67024e76ff0SPeter Maydell ARM_HWCAP_A64_CRC32 = 1 << 7, 671955f56d4SArd Biesheuvel ARM_HWCAP_A64_ATOMICS = 1 << 8, 672955f56d4SArd Biesheuvel ARM_HWCAP_A64_FPHP = 1 << 9, 673955f56d4SArd Biesheuvel ARM_HWCAP_A64_ASIMDHP = 1 << 10, 674955f56d4SArd Biesheuvel ARM_HWCAP_A64_CPUID = 1 << 11, 675955f56d4SArd Biesheuvel ARM_HWCAP_A64_ASIMDRDM = 1 << 12, 676955f56d4SArd Biesheuvel ARM_HWCAP_A64_JSCVT = 1 << 13, 677955f56d4SArd Biesheuvel ARM_HWCAP_A64_FCMA = 1 << 14, 678955f56d4SArd Biesheuvel ARM_HWCAP_A64_LRCPC = 1 << 15, 679955f56d4SArd Biesheuvel ARM_HWCAP_A64_DCPOP = 1 << 16, 680955f56d4SArd Biesheuvel ARM_HWCAP_A64_SHA3 = 1 << 17, 681955f56d4SArd Biesheuvel ARM_HWCAP_A64_SM3 = 1 << 18, 682955f56d4SArd Biesheuvel ARM_HWCAP_A64_SM4 = 1 << 19, 683955f56d4SArd Biesheuvel ARM_HWCAP_A64_ASIMDDP = 1 << 20, 684955f56d4SArd Biesheuvel ARM_HWCAP_A64_SHA512 = 1 << 21, 685955f56d4SArd Biesheuvel ARM_HWCAP_A64_SVE = 1 << 22, 6860083a1faSRichard Henderson ARM_HWCAP_A64_ASIMDFHM = 1 << 23, 6870083a1faSRichard Henderson ARM_HWCAP_A64_DIT = 1 << 24, 6880083a1faSRichard Henderson ARM_HWCAP_A64_USCAT = 1 << 25, 6890083a1faSRichard Henderson ARM_HWCAP_A64_ILRCPC = 1 << 26, 6900083a1faSRichard Henderson ARM_HWCAP_A64_FLAGM = 1 << 27, 6910083a1faSRichard Henderson ARM_HWCAP_A64_SSBS = 1 << 28, 6920083a1faSRichard Henderson ARM_HWCAP_A64_SB = 1 << 29, 6930083a1faSRichard Henderson ARM_HWCAP_A64_PACA = 1 << 30, 6940083a1faSRichard Henderson ARM_HWCAP_A64_PACG = 1UL << 31, 6952041df4aSRichard Henderson 6962041df4aSRichard Henderson ARM_HWCAP2_A64_DCPODP = 1 << 0, 6972041df4aSRichard Henderson ARM_HWCAP2_A64_SVE2 = 1 << 1, 6982041df4aSRichard Henderson ARM_HWCAP2_A64_SVEAES = 1 << 2, 6992041df4aSRichard Henderson ARM_HWCAP2_A64_SVEPMULL = 1 << 3, 7002041df4aSRichard Henderson ARM_HWCAP2_A64_SVEBITPERM = 1 << 4, 7012041df4aSRichard Henderson ARM_HWCAP2_A64_SVESHA3 = 1 << 5, 7022041df4aSRichard Henderson ARM_HWCAP2_A64_SVESM4 = 1 << 6, 7032041df4aSRichard Henderson ARM_HWCAP2_A64_FLAGM2 = 1 << 7, 7042041df4aSRichard Henderson ARM_HWCAP2_A64_FRINT = 1 << 8, 70568948d18SRichard Henderson ARM_HWCAP2_A64_SVEI8MM = 1 << 9, 70668948d18SRichard Henderson ARM_HWCAP2_A64_SVEF32MM = 1 << 10, 70768948d18SRichard Henderson ARM_HWCAP2_A64_SVEF64MM = 1 << 11, 70868948d18SRichard Henderson ARM_HWCAP2_A64_SVEBF16 = 1 << 12, 70968948d18SRichard Henderson ARM_HWCAP2_A64_I8MM = 1 << 13, 71068948d18SRichard Henderson ARM_HWCAP2_A64_BF16 = 1 << 14, 71168948d18SRichard Henderson ARM_HWCAP2_A64_DGH = 1 << 15, 71268948d18SRichard Henderson ARM_HWCAP2_A64_RNG = 1 << 16, 71368948d18SRichard Henderson ARM_HWCAP2_A64_BTI = 1 << 17, 71468948d18SRichard Henderson ARM_HWCAP2_A64_MTE = 1 << 18, 715f9982ceaSRichard Henderson ARM_HWCAP2_A64_ECV = 1 << 19, 716f9982ceaSRichard Henderson ARM_HWCAP2_A64_AFP = 1 << 20, 717f9982ceaSRichard Henderson ARM_HWCAP2_A64_RPRES = 1 << 21, 718f9982ceaSRichard Henderson ARM_HWCAP2_A64_MTE3 = 1 << 22, 719f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME = 1 << 23, 720f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_I16I64 = 1 << 24, 721f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_F64F64 = 1 << 25, 722f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_I8I32 = 1 << 26, 723f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_F16F32 = 1 << 27, 724f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_B16F32 = 1 << 28, 725f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_F32F32 = 1 << 29, 726f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_FA64 = 1 << 30, 72723d7f14dSPeter Maydell ARM_HWCAP2_A64_WFXT = 1ULL << 31, 72823d7f14dSPeter Maydell ARM_HWCAP2_A64_EBF16 = 1ULL << 32, 72923d7f14dSPeter Maydell ARM_HWCAP2_A64_SVE_EBF16 = 1ULL << 33, 73023d7f14dSPeter Maydell ARM_HWCAP2_A64_CSSC = 1ULL << 34, 73123d7f14dSPeter Maydell ARM_HWCAP2_A64_RPRFM = 1ULL << 35, 73223d7f14dSPeter Maydell ARM_HWCAP2_A64_SVE2P1 = 1ULL << 36, 73323d7f14dSPeter Maydell ARM_HWCAP2_A64_SME2 = 1ULL << 37, 73423d7f14dSPeter Maydell ARM_HWCAP2_A64_SME2P1 = 1ULL << 38, 73523d7f14dSPeter Maydell ARM_HWCAP2_A64_SME_I16I32 = 1ULL << 39, 73623d7f14dSPeter Maydell ARM_HWCAP2_A64_SME_BI32I32 = 1ULL << 40, 73723d7f14dSPeter Maydell ARM_HWCAP2_A64_SME_B16B16 = 1ULL << 41, 73823d7f14dSPeter Maydell ARM_HWCAP2_A64_SME_F16F16 = 1ULL << 42, 73923d7f14dSPeter Maydell ARM_HWCAP2_A64_MOPS = 1ULL << 43, 74023d7f14dSPeter Maydell ARM_HWCAP2_A64_HBC = 1ULL << 44, 74124e76ff0SPeter Maydell }; 74224e76ff0SPeter Maydell 74324e76ff0SPeter Maydell #define ELF_HWCAP get_elf_hwcap() 7442041df4aSRichard Henderson #define ELF_HWCAP2 get_elf_hwcap2() 7452041df4aSRichard Henderson 7462041df4aSRichard Henderson #define GET_FEATURE_ID(feat, hwcap) \ 7472041df4aSRichard Henderson do { if (cpu_isar_feature(feat, cpu)) { hwcaps |= hwcap; } } while (0) 74824e76ff0SPeter Maydell 749a55b9e72SHelge Deller uint32_t get_elf_hwcap(void) 75024e76ff0SPeter Maydell { 75124e76ff0SPeter Maydell ARMCPU *cpu = ARM_CPU(thread_cpu); 75224e76ff0SPeter Maydell uint32_t hwcaps = 0; 75324e76ff0SPeter Maydell 75424e76ff0SPeter Maydell hwcaps |= ARM_HWCAP_A64_FP; 75524e76ff0SPeter Maydell hwcaps |= ARM_HWCAP_A64_ASIMD; 75637020ff1SAlex Bennée hwcaps |= ARM_HWCAP_A64_CPUID; 75724e76ff0SPeter Maydell 75824e76ff0SPeter Maydell /* probe for the extra features */ 759962fcbf2SRichard Henderson 760962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_aes, ARM_HWCAP_A64_AES); 761962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_pmull, ARM_HWCAP_A64_PMULL); 762962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha1, ARM_HWCAP_A64_SHA1); 763962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha256, ARM_HWCAP_A64_SHA2); 764962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha512, ARM_HWCAP_A64_SHA512); 765962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_crc32, ARM_HWCAP_A64_CRC32); 766962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sha3, ARM_HWCAP_A64_SHA3); 767962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sm3, ARM_HWCAP_A64_SM3); 768962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_sm4, ARM_HWCAP_A64_SM4); 7695763190fSRichard Henderson GET_FEATURE_ID(aa64_fp16, ARM_HWCAP_A64_FPHP | ARM_HWCAP_A64_ASIMDHP); 770962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_atomics, ARM_HWCAP_A64_ATOMICS); 771962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_rdm, ARM_HWCAP_A64_ASIMDRDM); 772962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_dp, ARM_HWCAP_A64_ASIMDDP); 773962fcbf2SRichard Henderson GET_FEATURE_ID(aa64_fcma, ARM_HWCAP_A64_FCMA); 774cd208a1cSRichard Henderson GET_FEATURE_ID(aa64_sve, ARM_HWCAP_A64_SVE); 77529d26ab2SRichard Henderson GET_FEATURE_ID(aa64_pauth, ARM_HWCAP_A64_PACA | ARM_HWCAP_A64_PACG); 7761c9af3a9SRichard Henderson GET_FEATURE_ID(aa64_fhm, ARM_HWCAP_A64_ASIMDFHM); 7771c9af3a9SRichard Henderson GET_FEATURE_ID(aa64_jscvt, ARM_HWCAP_A64_JSCVT); 7789888bd1eSRichard Henderson GET_FEATURE_ID(aa64_sb, ARM_HWCAP_A64_SB); 779b89d9c98SRichard Henderson GET_FEATURE_ID(aa64_condm_4, ARM_HWCAP_A64_FLAGM); 7800d57b499SBeata Michalska GET_FEATURE_ID(aa64_dcpop, ARM_HWCAP_A64_DCPOP); 7812677cf9fSPeter Maydell GET_FEATURE_ID(aa64_rcpc_8_3, ARM_HWCAP_A64_LRCPC); 782a1229109SPeter Maydell GET_FEATURE_ID(aa64_rcpc_8_4, ARM_HWCAP_A64_ILRCPC); 783962fcbf2SRichard Henderson 7842041df4aSRichard Henderson return hwcaps; 7852041df4aSRichard Henderson } 7862041df4aSRichard Henderson 787a55b9e72SHelge Deller uint32_t get_elf_hwcap2(void) 7882041df4aSRichard Henderson { 7892041df4aSRichard Henderson ARMCPU *cpu = ARM_CPU(thread_cpu); 7902041df4aSRichard Henderson uint32_t hwcaps = 0; 7912041df4aSRichard Henderson 7920d57b499SBeata Michalska GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP); 793cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve2, ARM_HWCAP2_A64_SVE2); 794cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve2_aes, ARM_HWCAP2_A64_SVEAES); 795cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve2_pmull128, ARM_HWCAP2_A64_SVEPMULL); 796cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve2_bitperm, ARM_HWCAP2_A64_SVEBITPERM); 797cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve2_sha3, ARM_HWCAP2_A64_SVESHA3); 798cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve2_sm4, ARM_HWCAP2_A64_SVESM4); 7992041df4aSRichard Henderson GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2); 8002041df4aSRichard Henderson GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT); 801cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve_i8mm, ARM_HWCAP2_A64_SVEI8MM); 802cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve_f32mm, ARM_HWCAP2_A64_SVEF32MM); 803cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_sve_f64mm, ARM_HWCAP2_A64_SVEF64MM); 8046c47a905SRichard Henderson GET_FEATURE_ID(aa64_sve_bf16, ARM_HWCAP2_A64_SVEBF16); 805cdc8d8b2SRichard Henderson GET_FEATURE_ID(aa64_i8mm, ARM_HWCAP2_A64_I8MM); 8066c47a905SRichard Henderson GET_FEATURE_ID(aa64_bf16, ARM_HWCAP2_A64_BF16); 80768948d18SRichard Henderson GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG); 80868948d18SRichard Henderson GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI); 80968948d18SRichard Henderson GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE); 810f9982ceaSRichard Henderson GET_FEATURE_ID(aa64_sme, (ARM_HWCAP2_A64_SME | 811f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_F32F32 | 812f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_B16F32 | 813f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_F16F32 | 814f9982ceaSRichard Henderson ARM_HWCAP2_A64_SME_I8I32)); 815f9982ceaSRichard Henderson GET_FEATURE_ID(aa64_sme_f64f64, ARM_HWCAP2_A64_SME_F64F64); 816f9982ceaSRichard Henderson GET_FEATURE_ID(aa64_sme_i16i64, ARM_HWCAP2_A64_SME_I16I64); 817f9982ceaSRichard Henderson GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64); 8183039b090SPeter Maydell GET_FEATURE_ID(aa64_hbc, ARM_HWCAP2_A64_HBC); 819706a92fbSPeter Maydell GET_FEATURE_ID(aa64_mops, ARM_HWCAP2_A64_MOPS); 82024e76ff0SPeter Maydell 82124e76ff0SPeter Maydell return hwcaps; 82224e76ff0SPeter Maydell } 82324e76ff0SPeter Maydell 824a55b9e72SHelge Deller const char *elf_hwcap_str(uint32_t bit) 825a55b9e72SHelge Deller { 826a55b9e72SHelge Deller static const char *hwcap_str[] = { 827a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_FP )] = "fp", 828a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_ASIMD )] = "asimd", 829a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_EVTSTRM )] = "evtstrm", 830a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_AES )] = "aes", 831a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_PMULL )] = "pmull", 832a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SHA1 )] = "sha1", 833a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SHA2 )] = "sha2", 834a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_CRC32 )] = "crc32", 835a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_ATOMICS )] = "atomics", 836a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_FPHP )] = "fphp", 837a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_ASIMDHP )] = "asimdhp", 838a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_CPUID )] = "cpuid", 839a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_ASIMDRDM)] = "asimdrdm", 840a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_JSCVT )] = "jscvt", 841a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_FCMA )] = "fcma", 842a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_LRCPC )] = "lrcpc", 843a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_DCPOP )] = "dcpop", 844a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SHA3 )] = "sha3", 845a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SM3 )] = "sm3", 846a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SM4 )] = "sm4", 847a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_ASIMDDP )] = "asimddp", 848a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SHA512 )] = "sha512", 849a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SVE )] = "sve", 850a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_ASIMDFHM)] = "asimdfhm", 851a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_DIT )] = "dit", 852a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_USCAT )] = "uscat", 853a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_ILRCPC )] = "ilrcpc", 854a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_FLAGM )] = "flagm", 855a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SSBS )] = "ssbs", 856a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_SB )] = "sb", 857a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_PACA )] = "paca", 858a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP_A64_PACG )] = "pacg", 859a55b9e72SHelge Deller }; 860a55b9e72SHelge Deller 861a55b9e72SHelge Deller return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; 862a55b9e72SHelge Deller } 863a55b9e72SHelge Deller 864a55b9e72SHelge Deller const char *elf_hwcap2_str(uint32_t bit) 865a55b9e72SHelge Deller { 866a55b9e72SHelge Deller static const char *hwcap_str[] = { 867a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_DCPODP )] = "dcpodp", 868a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVE2 )] = "sve2", 869a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVEAES )] = "sveaes", 870a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVEPMULL )] = "svepmull", 871a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVEBITPERM )] = "svebitperm", 872a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVESHA3 )] = "svesha3", 873a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVESM4 )] = "svesm4", 874a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_FLAGM2 )] = "flagm2", 875a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_FRINT )] = "frint", 876a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVEI8MM )] = "svei8mm", 877a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVEF32MM )] = "svef32mm", 878a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVEF64MM )] = "svef64mm", 879a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SVEBF16 )] = "svebf16", 880a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_I8MM )] = "i8mm", 881a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_BF16 )] = "bf16", 882a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_DGH )] = "dgh", 883a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_RNG )] = "rng", 884a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_BTI )] = "bti", 885a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_MTE )] = "mte", 886a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_ECV )] = "ecv", 887a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_AFP )] = "afp", 888a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_RPRES )] = "rpres", 889a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_MTE3 )] = "mte3", 890a55b9e72SHelge Deller [__builtin_ctz(ARM_HWCAP2_A64_SME )] = "sme", 891e2e40a77SPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_SME_I16I64 )] = "smei16i64", 892e2e40a77SPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_SME_F64F64 )] = "smef64f64", 893e2e40a77SPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_SME_I8I32 )] = "smei8i32", 894e2e40a77SPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_SME_F16F32 )] = "smef16f32", 895e2e40a77SPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_SME_B16F32 )] = "smeb16f32", 896e2e40a77SPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_SME_F32F32 )] = "smef32f32", 897e2e40a77SPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_SME_FA64 )] = "smefa64", 89823d7f14dSPeter Maydell [__builtin_ctz(ARM_HWCAP2_A64_WFXT )] = "wfxt", 89923d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_EBF16 )] = "ebf16", 90023d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SVE_EBF16 )] = "sveebf16", 90123d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_CSSC )] = "cssc", 90223d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_RPRFM )] = "rprfm", 90323d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SVE2P1 )] = "sve2p1", 90423d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SME2 )] = "sme2", 90523d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SME2P1 )] = "sme2p1", 90623d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SME_I16I32 )] = "smei16i32", 90723d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SME_BI32I32)] = "smebi32i32", 90823d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SME_B16B16 )] = "smeb16b16", 90923d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_SME_F16F16 )] = "smef16f16", 91023d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_MOPS )] = "mops", 91123d7f14dSPeter Maydell [__builtin_ctzll(ARM_HWCAP2_A64_HBC )] = "hbc", 912a55b9e72SHelge Deller }; 913a55b9e72SHelge Deller 914a55b9e72SHelge Deller return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; 915a55b9e72SHelge Deller } 916a55b9e72SHelge Deller 9172041df4aSRichard Henderson #undef GET_FEATURE_ID 9182041df4aSRichard Henderson 91924e76ff0SPeter Maydell #endif /* not TARGET_AARCH64 */ 92024e76ff0SPeter Maydell #endif /* TARGET_ARM */ 92130ac07d4Sbellard 922853d6f7aSbellard #ifdef TARGET_SPARC 923a315a145Sbellard #ifdef TARGET_SPARC64 924853d6f7aSbellard 925cf973e46SArtyom Tarasenko #define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ 926cf973e46SArtyom Tarasenko | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9) 927992f48a0Sblueswir1 #ifndef TARGET_ABI32 928cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) 929992f48a0Sblueswir1 #else 930992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) 931992f48a0Sblueswir1 #endif 932853d6f7aSbellard 933a315a145Sbellard #define ELF_CLASS ELFCLASS64 9345ef54116Sbellard #define ELF_ARCH EM_SPARCV9 935a315a145Sbellard #else 936cf973e46SArtyom Tarasenko #define ELF_HWCAP (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ 937cf973e46SArtyom Tarasenko | HWCAP_SPARC_MULDIV) 938853d6f7aSbellard #define ELF_CLASS ELFCLASS32 939853d6f7aSbellard #define ELF_ARCH EM_SPARC 940089a2256SRichard Henderson #endif /* TARGET_SPARC64 */ 941853d6f7aSbellard 942d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 943d97ef72eSRichard Henderson struct image_info *infop) 944853d6f7aSbellard { 945089a2256SRichard Henderson /* Note that target_cpu_copy_regs does not read psr/tstate. */ 946f5155289Sbellard regs->pc = infop->entry; 947f5155289Sbellard regs->npc = regs->pc + 4; 948f5155289Sbellard regs->y = 0; 949089a2256SRichard Henderson regs->u_regs[14] = (infop->start_stack - 16 * sizeof(abi_ulong) 950089a2256SRichard Henderson - TARGET_STACK_BIAS); 951853d6f7aSbellard } 952089a2256SRichard Henderson #endif /* TARGET_SPARC */ 953853d6f7aSbellard 95467867308Sbellard #ifdef TARGET_PPC 95567867308Sbellard 9564ecd4d16SPeter Crosthwaite #define ELF_MACHINE PPC_ELF_MACHINE 95767867308Sbellard 95874154d7eSThomas Huth #if defined(TARGET_PPC64) 95984409ddbSj_mayer 96084409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 ) 96184409ddbSj_mayer 96284409ddbSj_mayer #define ELF_CLASS ELFCLASS64 96384409ddbSj_mayer 96484409ddbSj_mayer #else 96584409ddbSj_mayer 96667867308Sbellard #define ELF_CLASS ELFCLASS32 967872f3d04SRichard Henderson #define EXSTACK_DEFAULT true 96884409ddbSj_mayer 96984409ddbSj_mayer #endif 97084409ddbSj_mayer 97167867308Sbellard #define ELF_ARCH EM_PPC 97267867308Sbellard 973df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). 974df84e4f3SNathan Froyd See arch/powerpc/include/asm/cputable.h. */ 975df84e4f3SNathan Froyd enum { 9763efa9a67Smalc QEMU_PPC_FEATURE_32 = 0x80000000, 9773efa9a67Smalc QEMU_PPC_FEATURE_64 = 0x40000000, 9783efa9a67Smalc QEMU_PPC_FEATURE_601_INSTR = 0x20000000, 9793efa9a67Smalc QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000, 9803efa9a67Smalc QEMU_PPC_FEATURE_HAS_FPU = 0x08000000, 9813efa9a67Smalc QEMU_PPC_FEATURE_HAS_MMU = 0x04000000, 9823efa9a67Smalc QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000, 9833efa9a67Smalc QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000, 9843efa9a67Smalc QEMU_PPC_FEATURE_HAS_SPE = 0x00800000, 9853efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000, 9863efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000, 9873efa9a67Smalc QEMU_PPC_FEATURE_NO_TB = 0x00100000, 9883efa9a67Smalc QEMU_PPC_FEATURE_POWER4 = 0x00080000, 9893efa9a67Smalc QEMU_PPC_FEATURE_POWER5 = 0x00040000, 9903efa9a67Smalc QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000, 9913efa9a67Smalc QEMU_PPC_FEATURE_CELL = 0x00010000, 9923efa9a67Smalc QEMU_PPC_FEATURE_BOOKE = 0x00008000, 9933efa9a67Smalc QEMU_PPC_FEATURE_SMT = 0x00004000, 9943efa9a67Smalc QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000, 9953efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000, 9963efa9a67Smalc QEMU_PPC_FEATURE_PA6T = 0x00000800, 9973efa9a67Smalc QEMU_PPC_FEATURE_HAS_DFP = 0x00000400, 9983efa9a67Smalc QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200, 9993efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100, 10003efa9a67Smalc QEMU_PPC_FEATURE_HAS_VSX = 0x00000080, 10013efa9a67Smalc QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040, 1002df84e4f3SNathan Froyd 10033efa9a67Smalc QEMU_PPC_FEATURE_TRUE_LE = 0x00000002, 10043efa9a67Smalc QEMU_PPC_FEATURE_PPC_LE = 0x00000001, 1005a60438ddSTom Musta 1006a60438ddSTom Musta /* Feature definitions in AT_HWCAP2. */ 1007a60438ddSTom Musta QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */ 1008a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */ 1009a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */ 1010a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */ 1011a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */ 1012a60438ddSTom Musta QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */ 101324c373ecSLaurent Vivier QEMU_PPC_FEATURE2_VEC_CRYPTO = 0x02000000, 101424c373ecSLaurent Vivier QEMU_PPC_FEATURE2_HTM_NOSC = 0x01000000, 1015be0c46d4SSandipan Das QEMU_PPC_FEATURE2_ARCH_3_00 = 0x00800000, /* ISA 3.00 */ 101624c373ecSLaurent Vivier QEMU_PPC_FEATURE2_HAS_IEEE128 = 0x00400000, /* VSX IEEE Bin Float 128-bit */ 101724c373ecSLaurent Vivier QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */ 101824c373ecSLaurent Vivier QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */ 101924c373ecSLaurent Vivier QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */ 102096c343ccSJoel Stanley QEMU_PPC_FEATURE2_ARCH_3_1 = 0x00040000, /* ISA 3.1 */ 102196c343ccSJoel Stanley QEMU_PPC_FEATURE2_MMA = 0x00020000, /* Matrix-Multiply Assist */ 1022df84e4f3SNathan Froyd }; 1023df84e4f3SNathan Froyd 1024df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap() 1025df84e4f3SNathan Froyd 1026df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void) 1027df84e4f3SNathan Froyd { 1028a2247f8eSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); 1029df84e4f3SNathan Froyd uint32_t features = 0; 1030df84e4f3SNathan Froyd 1031df84e4f3SNathan Froyd /* We don't have to be terribly complete here; the high points are 1032df84e4f3SNathan Froyd Altivec/FP/SPE support. Anything else is just a bonus. */ 1033df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature) \ 1034a2247f8eSAndreas Färber do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) 103558eb5308SMichael Walle #define GET_FEATURE2(flags, feature) \ 103658eb5308SMichael Walle do { \ 103758eb5308SMichael Walle if ((cpu->env.insns_flags2 & flags) == flags) { \ 103858eb5308SMichael Walle features |= feature; \ 103958eb5308SMichael Walle } \ 104058eb5308SMichael Walle } while (0) 10413efa9a67Smalc GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); 10423efa9a67Smalc GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); 10433efa9a67Smalc GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); 10443efa9a67Smalc GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE); 10453efa9a67Smalc GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE); 10463efa9a67Smalc GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE); 10473efa9a67Smalc GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE); 10483efa9a67Smalc GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC); 10490e019746STom Musta GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP); 10500e019746STom Musta GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX); 10510e019746STom Musta GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | 10520e019746STom Musta PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206), 10530e019746STom Musta QEMU_PPC_FEATURE_ARCH_2_06); 1054df84e4f3SNathan Froyd #undef GET_FEATURE 10550e019746STom Musta #undef GET_FEATURE2 1056df84e4f3SNathan Froyd 1057df84e4f3SNathan Froyd return features; 1058df84e4f3SNathan Froyd } 1059df84e4f3SNathan Froyd 1060a60438ddSTom Musta #define ELF_HWCAP2 get_elf_hwcap2() 1061a60438ddSTom Musta 1062a60438ddSTom Musta static uint32_t get_elf_hwcap2(void) 1063a60438ddSTom Musta { 1064a60438ddSTom Musta PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); 1065a60438ddSTom Musta uint32_t features = 0; 1066a60438ddSTom Musta 1067a60438ddSTom Musta #define GET_FEATURE(flag, feature) \ 1068a60438ddSTom Musta do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) 1069a60438ddSTom Musta #define GET_FEATURE2(flag, feature) \ 1070a60438ddSTom Musta do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0) 1071a60438ddSTom Musta 1072a60438ddSTom Musta GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL); 1073a60438ddSTom Musta GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR); 1074a60438ddSTom Musta GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | 107524c373ecSLaurent Vivier PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07 | 107624c373ecSLaurent Vivier QEMU_PPC_FEATURE2_VEC_CRYPTO); 107724c373ecSLaurent Vivier GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 | 10788a589aebSKhem Raj QEMU_PPC_FEATURE2_DARN | QEMU_PPC_FEATURE2_HAS_IEEE128); 107996c343ccSJoel Stanley GET_FEATURE2(PPC2_ISA310, QEMU_PPC_FEATURE2_ARCH_3_1 | 108096c343ccSJoel Stanley QEMU_PPC_FEATURE2_MMA); 1081a60438ddSTom Musta 1082a60438ddSTom Musta #undef GET_FEATURE 1083a60438ddSTom Musta #undef GET_FEATURE2 1084a60438ddSTom Musta 1085a60438ddSTom Musta return features; 1086a60438ddSTom Musta } 1087a60438ddSTom Musta 1088f5155289Sbellard /* 1089f5155289Sbellard * The requirements here are: 1090f5155289Sbellard * - keep the final alignment of sp (sp & 0xf) 1091f5155289Sbellard * - make sure the 32-bit value at the first 16 byte aligned position of 1092f5155289Sbellard * AUXV is greater than 16 for glibc compatibility. 1093f5155289Sbellard * AT_IGNOREPPC is used for that. 1094f5155289Sbellard * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, 1095f5155289Sbellard * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. 1096f5155289Sbellard */ 10970bccf03dSbellard #define DLINFO_ARCH_ITEMS 5 1098f5155289Sbellard #define ARCH_DLINFO \ 1099f5155289Sbellard do { \ 1100623e250aSTom Musta PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); \ 1101f5155289Sbellard /* \ 110282991bedSPeter Maydell * Handle glibc compatibility: these magic entries must \ 110382991bedSPeter Maydell * be at the lowest addresses in the final auxv. \ 1104f5155289Sbellard */ \ 11050bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 11060bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 110782991bedSPeter Maydell NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \ 110882991bedSPeter Maydell NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \ 110982991bedSPeter Maydell NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ 1110f5155289Sbellard } while (0) 1111f5155289Sbellard 111267867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) 111367867308Sbellard { 111467867308Sbellard _regs->gpr[1] = infop->start_stack; 111574154d7eSThomas Huth #if defined(TARGET_PPC64) 1116d90b94cdSDoug Kwan if (get_ppc64_abi(infop) < 2) { 11172ccf97ecSPeter Maydell uint64_t val; 11182ccf97ecSPeter Maydell get_user_u64(val, infop->entry + 8); 11192ccf97ecSPeter Maydell _regs->gpr[2] = val + infop->load_bias; 11202ccf97ecSPeter Maydell get_user_u64(val, infop->entry); 11212ccf97ecSPeter Maydell infop->entry = val + infop->load_bias; 1122d90b94cdSDoug Kwan } else { 1123d90b94cdSDoug Kwan _regs->gpr[12] = infop->entry; /* r12 set to global entry address */ 1124d90b94cdSDoug Kwan } 112584409ddbSj_mayer #endif 112667867308Sbellard _regs->nip = infop->entry; 112767867308Sbellard } 112867867308Sbellard 1129e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h. */ 1130e2f3e741SNathan Froyd #define ELF_NREG 48 1131e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1132e2f3e741SNathan Froyd 113305390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env) 1134e2f3e741SNathan Froyd { 1135e2f3e741SNathan Froyd int i; 1136e2f3e741SNathan Froyd target_ulong ccr = 0; 1137e2f3e741SNathan Froyd 1138e2f3e741SNathan Froyd for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 113986cd7b2dSPaolo Bonzini (*regs)[i] = tswapreg(env->gpr[i]); 1140e2f3e741SNathan Froyd } 1141e2f3e741SNathan Froyd 114286cd7b2dSPaolo Bonzini (*regs)[32] = tswapreg(env->nip); 114386cd7b2dSPaolo Bonzini (*regs)[33] = tswapreg(env->msr); 114486cd7b2dSPaolo Bonzini (*regs)[35] = tswapreg(env->ctr); 114586cd7b2dSPaolo Bonzini (*regs)[36] = tswapreg(env->lr); 114610de0521SMatheus Ferst (*regs)[37] = tswapreg(cpu_read_xer(env)); 1147e2f3e741SNathan Froyd 11482060436aSHarsh Prateek Bora ccr = ppc_get_cr(env); 114986cd7b2dSPaolo Bonzini (*regs)[38] = tswapreg(ccr); 1150e2f3e741SNathan Froyd } 1151e2f3e741SNathan Froyd 1152e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP 115367867308Sbellard #define ELF_EXEC_PAGESIZE 4096 115467867308Sbellard 115567867308Sbellard #endif 115667867308Sbellard 11573418fe25SSong Gao #ifdef TARGET_LOONGARCH64 11583418fe25SSong Gao 11593418fe25SSong Gao #define ELF_CLASS ELFCLASS64 11603418fe25SSong Gao #define ELF_ARCH EM_LOONGARCH 1161872f3d04SRichard Henderson #define EXSTACK_DEFAULT true 11623418fe25SSong Gao 11633418fe25SSong Gao #define elf_check_arch(x) ((x) == EM_LOONGARCH) 11643418fe25SSong Gao 11653418fe25SSong Gao static inline void init_thread(struct target_pt_regs *regs, 11663418fe25SSong Gao struct image_info *infop) 11673418fe25SSong Gao { 11683418fe25SSong Gao /*Set crmd PG,DA = 1,0 */ 11693418fe25SSong Gao regs->csr.crmd = 2 << 3; 11703418fe25SSong Gao regs->csr.era = infop->entry; 11713418fe25SSong Gao regs->regs[3] = infop->start_stack; 11723418fe25SSong Gao } 11733418fe25SSong Gao 11743418fe25SSong Gao /* See linux kernel: arch/loongarch/include/asm/elf.h */ 11753418fe25SSong Gao #define ELF_NREG 45 11763418fe25SSong Gao typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 11773418fe25SSong Gao 11783418fe25SSong Gao enum { 11793418fe25SSong Gao TARGET_EF_R0 = 0, 11803418fe25SSong Gao TARGET_EF_CSR_ERA = TARGET_EF_R0 + 33, 11813418fe25SSong Gao TARGET_EF_CSR_BADV = TARGET_EF_R0 + 34, 11823418fe25SSong Gao }; 11833418fe25SSong Gao 11843418fe25SSong Gao static void elf_core_copy_regs(target_elf_gregset_t *regs, 11853418fe25SSong Gao const CPULoongArchState *env) 11863418fe25SSong Gao { 11873418fe25SSong Gao int i; 11883418fe25SSong Gao 11893418fe25SSong Gao (*regs)[TARGET_EF_R0] = 0; 11903418fe25SSong Gao 11913418fe25SSong Gao for (i = 1; i < ARRAY_SIZE(env->gpr); i++) { 11923418fe25SSong Gao (*regs)[TARGET_EF_R0 + i] = tswapreg(env->gpr[i]); 11933418fe25SSong Gao } 11943418fe25SSong Gao 11953418fe25SSong Gao (*regs)[TARGET_EF_CSR_ERA] = tswapreg(env->pc); 11963418fe25SSong Gao (*regs)[TARGET_EF_CSR_BADV] = tswapreg(env->CSR_BADV); 11973418fe25SSong Gao } 11983418fe25SSong Gao 11993418fe25SSong Gao #define USE_ELF_CORE_DUMP 12003418fe25SSong Gao #define ELF_EXEC_PAGESIZE 4096 12013418fe25SSong Gao 12023418fe25SSong Gao #define ELF_HWCAP get_elf_hwcap() 12033418fe25SSong Gao 12043418fe25SSong Gao /* See arch/loongarch/include/uapi/asm/hwcap.h */ 12053418fe25SSong Gao enum { 12063418fe25SSong Gao HWCAP_LOONGARCH_CPUCFG = (1 << 0), 12073418fe25SSong Gao HWCAP_LOONGARCH_LAM = (1 << 1), 12083418fe25SSong Gao HWCAP_LOONGARCH_UAL = (1 << 2), 12093418fe25SSong Gao HWCAP_LOONGARCH_FPU = (1 << 3), 12103418fe25SSong Gao HWCAP_LOONGARCH_LSX = (1 << 4), 12113418fe25SSong Gao HWCAP_LOONGARCH_LASX = (1 << 5), 12123418fe25SSong Gao HWCAP_LOONGARCH_CRC32 = (1 << 6), 12133418fe25SSong Gao HWCAP_LOONGARCH_COMPLEX = (1 << 7), 12143418fe25SSong Gao HWCAP_LOONGARCH_CRYPTO = (1 << 8), 12153418fe25SSong Gao HWCAP_LOONGARCH_LVZ = (1 << 9), 12163418fe25SSong Gao HWCAP_LOONGARCH_LBT_X86 = (1 << 10), 12173418fe25SSong Gao HWCAP_LOONGARCH_LBT_ARM = (1 << 11), 12183418fe25SSong Gao HWCAP_LOONGARCH_LBT_MIPS = (1 << 12), 12193418fe25SSong Gao }; 12203418fe25SSong Gao 12213418fe25SSong Gao static uint32_t get_elf_hwcap(void) 12223418fe25SSong Gao { 12233418fe25SSong Gao LoongArchCPU *cpu = LOONGARCH_CPU(thread_cpu); 12243418fe25SSong Gao uint32_t hwcaps = 0; 12253418fe25SSong Gao 12263418fe25SSong Gao hwcaps |= HWCAP_LOONGARCH_CRC32; 12273418fe25SSong Gao 12283418fe25SSong Gao if (FIELD_EX32(cpu->env.cpucfg[1], CPUCFG1, UAL)) { 12293418fe25SSong Gao hwcaps |= HWCAP_LOONGARCH_UAL; 12303418fe25SSong Gao } 12313418fe25SSong Gao 12323418fe25SSong Gao if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, FP)) { 12333418fe25SSong Gao hwcaps |= HWCAP_LOONGARCH_FPU; 12343418fe25SSong Gao } 12353418fe25SSong Gao 12363418fe25SSong Gao if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LAM)) { 12373418fe25SSong Gao hwcaps |= HWCAP_LOONGARCH_LAM; 12383418fe25SSong Gao } 12393418fe25SSong Gao 1240a9f6004fSJiajie Chen if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LSX)) { 1241a9f6004fSJiajie Chen hwcaps |= HWCAP_LOONGARCH_LSX; 1242a9f6004fSJiajie Chen } 1243a9f6004fSJiajie Chen 1244a9f6004fSJiajie Chen if (FIELD_EX32(cpu->env.cpucfg[2], CPUCFG2, LASX)) { 1245a9f6004fSJiajie Chen hwcaps |= HWCAP_LOONGARCH_LASX; 1246a9f6004fSJiajie Chen } 1247a9f6004fSJiajie Chen 12483418fe25SSong Gao return hwcaps; 12493418fe25SSong Gao } 12503418fe25SSong Gao 12513418fe25SSong Gao #define ELF_PLATFORM "loongarch" 12523418fe25SSong Gao 12533418fe25SSong Gao #endif /* TARGET_LOONGARCH64 */ 12543418fe25SSong Gao 1255048f6b4dSbellard #ifdef TARGET_MIPS 1256048f6b4dSbellard 1257388bb21aSths #ifdef TARGET_MIPS64 1258388bb21aSths #define ELF_CLASS ELFCLASS64 1259388bb21aSths #else 1260048f6b4dSbellard #define ELF_CLASS ELFCLASS32 1261388bb21aSths #endif 1262048f6b4dSbellard #define ELF_ARCH EM_MIPS 1263872f3d04SRichard Henderson #define EXSTACK_DEFAULT true 1264048f6b4dSbellard 1265ace3d654SCarlo Marcelo Arenas Belón #ifdef TARGET_ABI_MIPSN32 1266ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) ((x) & EF_MIPS_ABI2) 1267ace3d654SCarlo Marcelo Arenas Belón #else 1268ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (!((x) & EF_MIPS_ABI2)) 1269ace3d654SCarlo Marcelo Arenas Belón #endif 1270ace3d654SCarlo Marcelo Arenas Belón 1271fbf47c18SJiaxun Yang #define ELF_BASE_PLATFORM get_elf_base_platform() 1272fbf47c18SJiaxun Yang 1273fbf47c18SJiaxun Yang #define MATCH_PLATFORM_INSN(_flags, _base_platform) \ 1274fbf47c18SJiaxun Yang do { if ((cpu->env.insn_flags & (_flags)) == _flags) \ 1275fbf47c18SJiaxun Yang { return _base_platform; } } while (0) 1276fbf47c18SJiaxun Yang 1277fbf47c18SJiaxun Yang static const char *get_elf_base_platform(void) 1278fbf47c18SJiaxun Yang { 1279fbf47c18SJiaxun Yang MIPSCPU *cpu = MIPS_CPU(thread_cpu); 1280fbf47c18SJiaxun Yang 1281fbf47c18SJiaxun Yang /* 64 bit ISAs goes first */ 1282fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS64R6, "mips64r6"); 1283fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS64R5, "mips64r5"); 1284fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS64R2, "mips64r2"); 1285fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS64R1, "mips64"); 1286fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS5, "mips5"); 1287fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS4, "mips4"); 1288fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS3, "mips3"); 1289fbf47c18SJiaxun Yang 1290fbf47c18SJiaxun Yang /* 32 bit ISAs */ 1291fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS32R6, "mips32r6"); 1292fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS32R5, "mips32r5"); 1293fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS32R2, "mips32r2"); 1294fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS32R1, "mips32"); 1295fbf47c18SJiaxun Yang MATCH_PLATFORM_INSN(CPU_MIPS2, "mips2"); 1296fbf47c18SJiaxun Yang 1297fbf47c18SJiaxun Yang /* Fallback */ 1298fbf47c18SJiaxun Yang return "mips"; 1299fbf47c18SJiaxun Yang } 1300fbf47c18SJiaxun Yang #undef MATCH_PLATFORM_INSN 1301fbf47c18SJiaxun Yang 1302d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1303d97ef72eSRichard Henderson struct image_info *infop) 1304048f6b4dSbellard { 1305623a930eSths regs->cp0_status = 2 << CP0St_KSU; 1306048f6b4dSbellard regs->cp0_epc = infop->entry; 1307048f6b4dSbellard regs->regs[29] = infop->start_stack; 1308048f6b4dSbellard } 1309048f6b4dSbellard 131051e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h. */ 131151e52606SNathan Froyd #define ELF_NREG 45 131251e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 131351e52606SNathan Froyd 131451e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h. */ 131551e52606SNathan Froyd enum { 131651e52606SNathan Froyd #ifdef TARGET_MIPS64 131751e52606SNathan Froyd TARGET_EF_R0 = 0, 131851e52606SNathan Froyd #else 131951e52606SNathan Froyd TARGET_EF_R0 = 6, 132051e52606SNathan Froyd #endif 132151e52606SNathan Froyd TARGET_EF_R26 = TARGET_EF_R0 + 26, 132251e52606SNathan Froyd TARGET_EF_R27 = TARGET_EF_R0 + 27, 132351e52606SNathan Froyd TARGET_EF_LO = TARGET_EF_R0 + 32, 132451e52606SNathan Froyd TARGET_EF_HI = TARGET_EF_R0 + 33, 132551e52606SNathan Froyd TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34, 132651e52606SNathan Froyd TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35, 132751e52606SNathan Froyd TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36, 132851e52606SNathan Froyd TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37 132951e52606SNathan Froyd }; 133051e52606SNathan Froyd 133151e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 133205390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env) 133351e52606SNathan Froyd { 133451e52606SNathan Froyd int i; 133551e52606SNathan Froyd 133651e52606SNathan Froyd for (i = 0; i < TARGET_EF_R0; i++) { 133751e52606SNathan Froyd (*regs)[i] = 0; 133851e52606SNathan Froyd } 133951e52606SNathan Froyd (*regs)[TARGET_EF_R0] = 0; 134051e52606SNathan Froyd 134151e52606SNathan Froyd for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { 1342a29f998dSPaolo Bonzini (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); 134351e52606SNathan Froyd } 134451e52606SNathan Froyd 134551e52606SNathan Froyd (*regs)[TARGET_EF_R26] = 0; 134651e52606SNathan Froyd (*regs)[TARGET_EF_R27] = 0; 1347a29f998dSPaolo Bonzini (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]); 1348a29f998dSPaolo Bonzini (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]); 1349a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC); 1350a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr); 1351a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status); 1352a29f998dSPaolo Bonzini (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause); 135351e52606SNathan Froyd } 135451e52606SNathan Froyd 135551e52606SNathan Froyd #define USE_ELF_CORE_DUMP 1356388bb21aSths #define ELF_EXEC_PAGESIZE 4096 1357388bb21aSths 135846a1ee4fSJames Cowgill /* See arch/mips/include/uapi/asm/hwcap.h. */ 135946a1ee4fSJames Cowgill enum { 136046a1ee4fSJames Cowgill HWCAP_MIPS_R6 = (1 << 0), 136146a1ee4fSJames Cowgill HWCAP_MIPS_MSA = (1 << 1), 13629ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_CRC32 = (1 << 2), 13639ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_MIPS16 = (1 << 3), 13649ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_MDMX = (1 << 4), 13659ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_MIPS3D = (1 << 5), 13669ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_SMARTMIPS = (1 << 6), 13679ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_DSP = (1 << 7), 13689ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_DSP2 = (1 << 8), 13699ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_DSP3 = (1 << 9), 13709ea313baSPhilippe Mathieu-Daudé HWCAP_MIPS_MIPS16E2 = (1 << 10), 13719ea313baSPhilippe Mathieu-Daudé HWCAP_LOONGSON_MMI = (1 << 11), 13729ea313baSPhilippe Mathieu-Daudé HWCAP_LOONGSON_EXT = (1 << 12), 13739ea313baSPhilippe Mathieu-Daudé HWCAP_LOONGSON_EXT2 = (1 << 13), 13749ea313baSPhilippe Mathieu-Daudé HWCAP_LOONGSON_CPUCFG = (1 << 14), 137546a1ee4fSJames Cowgill }; 137646a1ee4fSJames Cowgill 137746a1ee4fSJames Cowgill #define ELF_HWCAP get_elf_hwcap() 137846a1ee4fSJames Cowgill 13797d9a3d96SPhilippe Mathieu-Daudé #define GET_FEATURE_INSN(_flag, _hwcap) \ 13806dd97bfcSPhilippe Mathieu-Daudé do { if (cpu->env.insn_flags & (_flag)) { hwcaps |= _hwcap; } } while (0) 13816dd97bfcSPhilippe Mathieu-Daudé 1382388765a0SPhilippe Mathieu-Daudé #define GET_FEATURE_REG_SET(_reg, _mask, _hwcap) \ 1383388765a0SPhilippe Mathieu-Daudé do { if (cpu->env._reg & (_mask)) { hwcaps |= _hwcap; } } while (0) 1384388765a0SPhilippe Mathieu-Daudé 1385ce543844SPhilippe Mathieu-Daudé #define GET_FEATURE_REG_EQU(_reg, _start, _length, _val, _hwcap) \ 1386ce543844SPhilippe Mathieu-Daudé do { \ 1387ce543844SPhilippe Mathieu-Daudé if (extract32(cpu->env._reg, (_start), (_length)) == (_val)) { \ 1388ce543844SPhilippe Mathieu-Daudé hwcaps |= _hwcap; \ 1389ce543844SPhilippe Mathieu-Daudé } \ 1390ce543844SPhilippe Mathieu-Daudé } while (0) 1391ce543844SPhilippe Mathieu-Daudé 139246a1ee4fSJames Cowgill static uint32_t get_elf_hwcap(void) 139346a1ee4fSJames Cowgill { 139446a1ee4fSJames Cowgill MIPSCPU *cpu = MIPS_CPU(thread_cpu); 139546a1ee4fSJames Cowgill uint32_t hwcaps = 0; 139646a1ee4fSJames Cowgill 1397ce543844SPhilippe Mathieu-Daudé GET_FEATURE_REG_EQU(CP0_Config0, CP0C0_AR, CP0C0_AR_LENGTH, 1398ce543844SPhilippe Mathieu-Daudé 2, HWCAP_MIPS_R6); 1399388765a0SPhilippe Mathieu-Daudé GET_FEATURE_REG_SET(CP0_Config3, 1 << CP0C3_MSAP, HWCAP_MIPS_MSA); 140053673d0fSPhilippe Mathieu-Daudé GET_FEATURE_INSN(ASE_LMMI, HWCAP_LOONGSON_MMI); 140153673d0fSPhilippe Mathieu-Daudé GET_FEATURE_INSN(ASE_LEXT, HWCAP_LOONGSON_EXT); 140246a1ee4fSJames Cowgill 140346a1ee4fSJames Cowgill return hwcaps; 140446a1ee4fSJames Cowgill } 140546a1ee4fSJames Cowgill 1406ce543844SPhilippe Mathieu-Daudé #undef GET_FEATURE_REG_EQU 1407388765a0SPhilippe Mathieu-Daudé #undef GET_FEATURE_REG_SET 14087d9a3d96SPhilippe Mathieu-Daudé #undef GET_FEATURE_INSN 14096dd97bfcSPhilippe Mathieu-Daudé 1410048f6b4dSbellard #endif /* TARGET_MIPS */ 1411048f6b4dSbellard 1412b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 1413b779e29eSEdgar E. Iglesias 14140d5d4699SEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD) 1415b779e29eSEdgar E. Iglesias 1416b779e29eSEdgar E. Iglesias #define ELF_CLASS ELFCLASS32 14170d5d4699SEdgar E. Iglesias #define ELF_ARCH EM_MICROBLAZE 1418b779e29eSEdgar E. Iglesias 1419d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1420d97ef72eSRichard Henderson struct image_info *infop) 1421b779e29eSEdgar E. Iglesias { 1422b779e29eSEdgar E. Iglesias regs->pc = infop->entry; 1423b779e29eSEdgar E. Iglesias regs->r1 = infop->start_stack; 1424b779e29eSEdgar E. Iglesias 1425b779e29eSEdgar E. Iglesias } 1426b779e29eSEdgar E. Iglesias 1427b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE 4096 1428b779e29eSEdgar E. Iglesias 1429e4cbd44dSEdgar E. Iglesias #define USE_ELF_CORE_DUMP 1430e4cbd44dSEdgar E. Iglesias #define ELF_NREG 38 1431e4cbd44dSEdgar E. Iglesias typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1432e4cbd44dSEdgar E. Iglesias 1433e4cbd44dSEdgar E. Iglesias /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 143405390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env) 1435e4cbd44dSEdgar E. Iglesias { 1436e4cbd44dSEdgar E. Iglesias int i, pos = 0; 1437e4cbd44dSEdgar E. Iglesias 1438e4cbd44dSEdgar E. Iglesias for (i = 0; i < 32; i++) { 143986cd7b2dSPaolo Bonzini (*regs)[pos++] = tswapreg(env->regs[i]); 1440e4cbd44dSEdgar E. Iglesias } 1441e4cbd44dSEdgar E. Iglesias 1442af20a93aSRichard Henderson (*regs)[pos++] = tswapreg(env->pc); 14431074c0fbSRichard Henderson (*regs)[pos++] = tswapreg(mb_cpu_read_msr(env)); 1444af20a93aSRichard Henderson (*regs)[pos++] = 0; 1445af20a93aSRichard Henderson (*regs)[pos++] = tswapreg(env->ear); 1446af20a93aSRichard Henderson (*regs)[pos++] = 0; 1447af20a93aSRichard Henderson (*regs)[pos++] = tswapreg(env->esr); 1448e4cbd44dSEdgar E. Iglesias } 1449e4cbd44dSEdgar E. Iglesias 1450b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */ 1451b779e29eSEdgar E. Iglesias 1452a0a839b6SMarek Vasut #ifdef TARGET_NIOS2 1453a0a839b6SMarek Vasut 1454a0a839b6SMarek Vasut #define elf_check_arch(x) ((x) == EM_ALTERA_NIOS2) 1455a0a839b6SMarek Vasut 1456a0a839b6SMarek Vasut #define ELF_CLASS ELFCLASS32 1457a0a839b6SMarek Vasut #define ELF_ARCH EM_ALTERA_NIOS2 1458a0a839b6SMarek Vasut 1459a0a839b6SMarek Vasut static void init_thread(struct target_pt_regs *regs, struct image_info *infop) 1460a0a839b6SMarek Vasut { 1461a0a839b6SMarek Vasut regs->ea = infop->entry; 1462a0a839b6SMarek Vasut regs->sp = infop->start_stack; 1463a0a839b6SMarek Vasut } 1464a0a839b6SMarek Vasut 1465f5ef0e51SRichard Henderson #define LO_COMMPAGE TARGET_PAGE_SIZE 1466f5ef0e51SRichard Henderson 1467f5ef0e51SRichard Henderson static bool init_guest_commpage(void) 1468f5ef0e51SRichard Henderson { 1469f5ef0e51SRichard Henderson static const uint8_t kuser_page[4 + 2 * 64] = { 1470f5ef0e51SRichard Henderson /* __kuser_helper_version */ 1471f5ef0e51SRichard Henderson [0x00] = 0x02, 0x00, 0x00, 0x00, 1472f5ef0e51SRichard Henderson 1473f5ef0e51SRichard Henderson /* __kuser_cmpxchg */ 1474f5ef0e51SRichard Henderson [0x04] = 0x3a, 0x6c, 0x3b, 0x00, /* trap 16 */ 1475f5ef0e51SRichard Henderson 0x3a, 0x28, 0x00, 0xf8, /* ret */ 1476f5ef0e51SRichard Henderson 1477f5ef0e51SRichard Henderson /* __kuser_sigtramp */ 1478f5ef0e51SRichard Henderson [0x44] = 0xc4, 0x22, 0x80, 0x00, /* movi r2, __NR_rt_sigreturn */ 1479f5ef0e51SRichard Henderson 0x3a, 0x68, 0x3b, 0x00, /* trap 0 */ 1480f5ef0e51SRichard Henderson }; 1481f5ef0e51SRichard Henderson 1482f5ef0e51SRichard Henderson void *want = g2h_untagged(LO_COMMPAGE & -qemu_host_page_size); 1483f5ef0e51SRichard Henderson void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, 1484f5ef0e51SRichard Henderson MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1485f5ef0e51SRichard Henderson 1486f5ef0e51SRichard Henderson if (addr == MAP_FAILED) { 1487f5ef0e51SRichard Henderson perror("Allocating guest commpage"); 1488f5ef0e51SRichard Henderson exit(EXIT_FAILURE); 1489f5ef0e51SRichard Henderson } 1490f5ef0e51SRichard Henderson if (addr != want) { 1491f5ef0e51SRichard Henderson return false; 1492f5ef0e51SRichard Henderson } 1493f5ef0e51SRichard Henderson 1494f5ef0e51SRichard Henderson memcpy(addr, kuser_page, sizeof(kuser_page)); 1495f5ef0e51SRichard Henderson 1496f5ef0e51SRichard Henderson if (mprotect(addr, qemu_host_page_size, PROT_READ)) { 1497f5ef0e51SRichard Henderson perror("Protecting guest commpage"); 1498f5ef0e51SRichard Henderson exit(EXIT_FAILURE); 1499f5ef0e51SRichard Henderson } 1500f5ef0e51SRichard Henderson 150149840a4aSRichard Henderson page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK, 1502f5ef0e51SRichard Henderson PAGE_READ | PAGE_EXEC | PAGE_VALID); 1503f5ef0e51SRichard Henderson return true; 1504f5ef0e51SRichard Henderson } 1505f5ef0e51SRichard Henderson 1506a0a839b6SMarek Vasut #define ELF_EXEC_PAGESIZE 4096 1507a0a839b6SMarek Vasut 1508a0a839b6SMarek Vasut #define USE_ELF_CORE_DUMP 1509a0a839b6SMarek Vasut #define ELF_NREG 49 1510a0a839b6SMarek Vasut typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1511a0a839b6SMarek Vasut 1512a0a839b6SMarek Vasut /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 1513a0a839b6SMarek Vasut static void elf_core_copy_regs(target_elf_gregset_t *regs, 1514a0a839b6SMarek Vasut const CPUNios2State *env) 1515a0a839b6SMarek Vasut { 1516a0a839b6SMarek Vasut int i; 1517a0a839b6SMarek Vasut 1518a0a839b6SMarek Vasut (*regs)[0] = -1; 1519a0a839b6SMarek Vasut for (i = 1; i < 8; i++) /* r0-r7 */ 1520a0a839b6SMarek Vasut (*regs)[i] = tswapreg(env->regs[i + 7]); 1521a0a839b6SMarek Vasut 1522a0a839b6SMarek Vasut for (i = 8; i < 16; i++) /* r8-r15 */ 1523a0a839b6SMarek Vasut (*regs)[i] = tswapreg(env->regs[i - 8]); 1524a0a839b6SMarek Vasut 1525a0a839b6SMarek Vasut for (i = 16; i < 24; i++) /* r16-r23 */ 1526a0a839b6SMarek Vasut (*regs)[i] = tswapreg(env->regs[i + 7]); 1527a0a839b6SMarek Vasut (*regs)[24] = -1; /* R_ET */ 1528a0a839b6SMarek Vasut (*regs)[25] = -1; /* R_BT */ 1529a0a839b6SMarek Vasut (*regs)[26] = tswapreg(env->regs[R_GP]); 1530a0a839b6SMarek Vasut (*regs)[27] = tswapreg(env->regs[R_SP]); 1531a0a839b6SMarek Vasut (*regs)[28] = tswapreg(env->regs[R_FP]); 1532a0a839b6SMarek Vasut (*regs)[29] = tswapreg(env->regs[R_EA]); 1533a0a839b6SMarek Vasut (*regs)[30] = -1; /* R_SSTATUS */ 1534a0a839b6SMarek Vasut (*regs)[31] = tswapreg(env->regs[R_RA]); 1535a0a839b6SMarek Vasut 153617a406eeSRichard Henderson (*regs)[32] = tswapreg(env->pc); 1537a0a839b6SMarek Vasut 1538a0a839b6SMarek Vasut (*regs)[33] = -1; /* R_STATUS */ 1539a0a839b6SMarek Vasut (*regs)[34] = tswapreg(env->regs[CR_ESTATUS]); 1540a0a839b6SMarek Vasut 1541a0a839b6SMarek Vasut for (i = 35; i < 49; i++) /* ... */ 1542a0a839b6SMarek Vasut (*regs)[i] = -1; 1543a0a839b6SMarek Vasut } 1544a0a839b6SMarek Vasut 1545a0a839b6SMarek Vasut #endif /* TARGET_NIOS2 */ 1546a0a839b6SMarek Vasut 1547d962783eSJia Liu #ifdef TARGET_OPENRISC 1548d962783eSJia Liu 1549d962783eSJia Liu #define ELF_ARCH EM_OPENRISC 1550d962783eSJia Liu #define ELF_CLASS ELFCLASS32 1551d962783eSJia Liu #define ELF_DATA ELFDATA2MSB 1552d962783eSJia Liu 1553d962783eSJia Liu static inline void init_thread(struct target_pt_regs *regs, 1554d962783eSJia Liu struct image_info *infop) 1555d962783eSJia Liu { 1556d962783eSJia Liu regs->pc = infop->entry; 1557d962783eSJia Liu regs->gpr[1] = infop->start_stack; 1558d962783eSJia Liu } 1559d962783eSJia Liu 1560d962783eSJia Liu #define USE_ELF_CORE_DUMP 1561d962783eSJia Liu #define ELF_EXEC_PAGESIZE 8192 1562d962783eSJia Liu 1563d962783eSJia Liu /* See linux kernel arch/openrisc/include/asm/elf.h. */ 1564d962783eSJia Liu #define ELF_NREG 34 /* gprs and pc, sr */ 1565d962783eSJia Liu typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1566d962783eSJia Liu 1567d962783eSJia Liu static void elf_core_copy_regs(target_elf_gregset_t *regs, 1568d962783eSJia Liu const CPUOpenRISCState *env) 1569d962783eSJia Liu { 1570d962783eSJia Liu int i; 1571d962783eSJia Liu 1572d962783eSJia Liu for (i = 0; i < 32; i++) { 1573d89e71e8SStafford Horne (*regs)[i] = tswapreg(cpu_get_gpr(env, i)); 1574d962783eSJia Liu } 157586cd7b2dSPaolo Bonzini (*regs)[32] = tswapreg(env->pc); 157684775c43SRichard Henderson (*regs)[33] = tswapreg(cpu_get_sr(env)); 1577d962783eSJia Liu } 1578d962783eSJia Liu #define ELF_HWCAP 0 1579d962783eSJia Liu #define ELF_PLATFORM NULL 1580d962783eSJia Liu 1581d962783eSJia Liu #endif /* TARGET_OPENRISC */ 1582d962783eSJia Liu 1583fdf9b3e8Sbellard #ifdef TARGET_SH4 1584fdf9b3e8Sbellard 1585fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32 1586fdf9b3e8Sbellard #define ELF_ARCH EM_SH 1587fdf9b3e8Sbellard 1588d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1589d97ef72eSRichard Henderson struct image_info *infop) 1590fdf9b3e8Sbellard { 1591fdf9b3e8Sbellard /* Check other registers XXXXX */ 1592fdf9b3e8Sbellard regs->pc = infop->entry; 1593072ae847Sths regs->regs[15] = infop->start_stack; 1594fdf9b3e8Sbellard } 1595fdf9b3e8Sbellard 15967631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h. */ 15977631c97eSNathan Froyd #define ELF_NREG 23 15987631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 15997631c97eSNathan Froyd 16007631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h. */ 16017631c97eSNathan Froyd enum { 16027631c97eSNathan Froyd TARGET_REG_PC = 16, 16037631c97eSNathan Froyd TARGET_REG_PR = 17, 16047631c97eSNathan Froyd TARGET_REG_SR = 18, 16057631c97eSNathan Froyd TARGET_REG_GBR = 19, 16067631c97eSNathan Froyd TARGET_REG_MACH = 20, 16077631c97eSNathan Froyd TARGET_REG_MACL = 21, 16087631c97eSNathan Froyd TARGET_REG_SYSCALL = 22 16097631c97eSNathan Froyd }; 16107631c97eSNathan Froyd 1611d97ef72eSRichard Henderson static inline void elf_core_copy_regs(target_elf_gregset_t *regs, 161205390248SAndreas Färber const CPUSH4State *env) 16137631c97eSNathan Froyd { 16147631c97eSNathan Froyd int i; 16157631c97eSNathan Froyd 16167631c97eSNathan Froyd for (i = 0; i < 16; i++) { 161772cd500bSPhilippe Mathieu-Daudé (*regs)[i] = tswapreg(env->gregs[i]); 16187631c97eSNathan Froyd } 16197631c97eSNathan Froyd 162086cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_PC] = tswapreg(env->pc); 162186cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_PR] = tswapreg(env->pr); 162286cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_SR] = tswapreg(env->sr); 162386cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr); 162486cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_MACH] = tswapreg(env->mach); 162586cd7b2dSPaolo Bonzini (*regs)[TARGET_REG_MACL] = tswapreg(env->macl); 16267631c97eSNathan Froyd (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */ 16277631c97eSNathan Froyd } 16287631c97eSNathan Froyd 16297631c97eSNathan Froyd #define USE_ELF_CORE_DUMP 1630fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE 4096 1631fdf9b3e8Sbellard 1632e42fd944SRichard Henderson enum { 1633e42fd944SRichard Henderson SH_CPU_HAS_FPU = 0x0001, /* Hardware FPU support */ 1634e42fd944SRichard Henderson SH_CPU_HAS_P2_FLUSH_BUG = 0x0002, /* Need to flush the cache in P2 area */ 1635e42fd944SRichard Henderson SH_CPU_HAS_MMU_PAGE_ASSOC = 0x0004, /* SH3: TLB way selection bit support */ 1636e42fd944SRichard Henderson SH_CPU_HAS_DSP = 0x0008, /* SH-DSP: DSP support */ 1637e42fd944SRichard Henderson SH_CPU_HAS_PERF_COUNTER = 0x0010, /* Hardware performance counters */ 1638e42fd944SRichard Henderson SH_CPU_HAS_PTEA = 0x0020, /* PTEA register */ 1639e42fd944SRichard Henderson SH_CPU_HAS_LLSC = 0x0040, /* movli.l/movco.l */ 1640e42fd944SRichard Henderson SH_CPU_HAS_L2_CACHE = 0x0080, /* Secondary cache / URAM */ 1641e42fd944SRichard Henderson SH_CPU_HAS_OP32 = 0x0100, /* 32-bit instruction support */ 1642e42fd944SRichard Henderson SH_CPU_HAS_PTEAEX = 0x0200, /* PTE ASID Extension support */ 1643e42fd944SRichard Henderson }; 1644e42fd944SRichard Henderson 1645e42fd944SRichard Henderson #define ELF_HWCAP get_elf_hwcap() 1646e42fd944SRichard Henderson 1647e42fd944SRichard Henderson static uint32_t get_elf_hwcap(void) 1648e42fd944SRichard Henderson { 1649e42fd944SRichard Henderson SuperHCPU *cpu = SUPERH_CPU(thread_cpu); 1650e42fd944SRichard Henderson uint32_t hwcap = 0; 1651e42fd944SRichard Henderson 1652e42fd944SRichard Henderson hwcap |= SH_CPU_HAS_FPU; 1653e42fd944SRichard Henderson 1654e42fd944SRichard Henderson if (cpu->env.features & SH_FEATURE_SH4A) { 1655e42fd944SRichard Henderson hwcap |= SH_CPU_HAS_LLSC; 1656e42fd944SRichard Henderson } 1657e42fd944SRichard Henderson 1658e42fd944SRichard Henderson return hwcap; 1659e42fd944SRichard Henderson } 1660e42fd944SRichard Henderson 1661fdf9b3e8Sbellard #endif 1662fdf9b3e8Sbellard 166348733d19Sths #ifdef TARGET_CRIS 166448733d19Sths 166548733d19Sths #define ELF_CLASS ELFCLASS32 166648733d19Sths #define ELF_ARCH EM_CRIS 166748733d19Sths 1668d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1669d97ef72eSRichard Henderson struct image_info *infop) 167048733d19Sths { 167148733d19Sths regs->erp = infop->entry; 167248733d19Sths } 167348733d19Sths 167448733d19Sths #define ELF_EXEC_PAGESIZE 8192 167548733d19Sths 167648733d19Sths #endif 167748733d19Sths 1678e6e5906bSpbrook #ifdef TARGET_M68K 1679e6e5906bSpbrook 1680e6e5906bSpbrook #define ELF_CLASS ELFCLASS32 1681e6e5906bSpbrook #define ELF_ARCH EM_68K 1682e6e5906bSpbrook 1683e6e5906bSpbrook /* ??? Does this need to do anything? 1684e6e5906bSpbrook #define ELF_PLAT_INIT(_r) */ 1685e6e5906bSpbrook 1686d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1687d97ef72eSRichard Henderson struct image_info *infop) 1688e6e5906bSpbrook { 1689e6e5906bSpbrook regs->usp = infop->start_stack; 1690e6e5906bSpbrook regs->sr = 0; 1691e6e5906bSpbrook regs->pc = infop->entry; 1692e6e5906bSpbrook } 1693e6e5906bSpbrook 16947a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h. */ 16957a93cc55SNathan Froyd #define ELF_NREG 20 16967a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 16977a93cc55SNathan Froyd 169805390248SAndreas Färber static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env) 16997a93cc55SNathan Froyd { 170086cd7b2dSPaolo Bonzini (*regs)[0] = tswapreg(env->dregs[1]); 170186cd7b2dSPaolo Bonzini (*regs)[1] = tswapreg(env->dregs[2]); 170286cd7b2dSPaolo Bonzini (*regs)[2] = tswapreg(env->dregs[3]); 170386cd7b2dSPaolo Bonzini (*regs)[3] = tswapreg(env->dregs[4]); 170486cd7b2dSPaolo Bonzini (*regs)[4] = tswapreg(env->dregs[5]); 170586cd7b2dSPaolo Bonzini (*regs)[5] = tswapreg(env->dregs[6]); 170686cd7b2dSPaolo Bonzini (*regs)[6] = tswapreg(env->dregs[7]); 170786cd7b2dSPaolo Bonzini (*regs)[7] = tswapreg(env->aregs[0]); 170886cd7b2dSPaolo Bonzini (*regs)[8] = tswapreg(env->aregs[1]); 170986cd7b2dSPaolo Bonzini (*regs)[9] = tswapreg(env->aregs[2]); 171086cd7b2dSPaolo Bonzini (*regs)[10] = tswapreg(env->aregs[3]); 171186cd7b2dSPaolo Bonzini (*regs)[11] = tswapreg(env->aregs[4]); 171286cd7b2dSPaolo Bonzini (*regs)[12] = tswapreg(env->aregs[5]); 171386cd7b2dSPaolo Bonzini (*regs)[13] = tswapreg(env->aregs[6]); 171486cd7b2dSPaolo Bonzini (*regs)[14] = tswapreg(env->dregs[0]); 171586cd7b2dSPaolo Bonzini (*regs)[15] = tswapreg(env->aregs[7]); 171686cd7b2dSPaolo Bonzini (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */ 171786cd7b2dSPaolo Bonzini (*regs)[17] = tswapreg(env->sr); 171886cd7b2dSPaolo Bonzini (*regs)[18] = tswapreg(env->pc); 17197a93cc55SNathan Froyd (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */ 17207a93cc55SNathan Froyd } 17217a93cc55SNathan Froyd 17227a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP 1723e6e5906bSpbrook #define ELF_EXEC_PAGESIZE 8192 1724e6e5906bSpbrook 1725e6e5906bSpbrook #endif 1726e6e5906bSpbrook 17277a3148a9Sj_mayer #ifdef TARGET_ALPHA 17287a3148a9Sj_mayer 17297a3148a9Sj_mayer #define ELF_CLASS ELFCLASS64 17307a3148a9Sj_mayer #define ELF_ARCH EM_ALPHA 17317a3148a9Sj_mayer 1732d97ef72eSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 1733d97ef72eSRichard Henderson struct image_info *infop) 17347a3148a9Sj_mayer { 17357a3148a9Sj_mayer regs->pc = infop->entry; 17367a3148a9Sj_mayer regs->ps = 8; 17377a3148a9Sj_mayer regs->usp = infop->start_stack; 17387a3148a9Sj_mayer } 17397a3148a9Sj_mayer 17407a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE 8192 17417a3148a9Sj_mayer 17427a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 17437a3148a9Sj_mayer 1744a4c075f1SUlrich Hecht #ifdef TARGET_S390X 1745a4c075f1SUlrich Hecht 1746a4c075f1SUlrich Hecht #define ELF_CLASS ELFCLASS64 1747a4c075f1SUlrich Hecht #define ELF_DATA ELFDATA2MSB 1748a4c075f1SUlrich Hecht #define ELF_ARCH EM_S390 1749a4c075f1SUlrich Hecht 17506d88baf1SDavid Hildenbrand #include "elf.h" 17516d88baf1SDavid Hildenbrand 17526d88baf1SDavid Hildenbrand #define ELF_HWCAP get_elf_hwcap() 17536d88baf1SDavid Hildenbrand 17546d88baf1SDavid Hildenbrand #define GET_FEATURE(_feat, _hwcap) \ 17556d88baf1SDavid Hildenbrand do { if (s390_has_feat(_feat)) { hwcap |= _hwcap; } } while (0) 17566d88baf1SDavid Hildenbrand 1757e1b819c8SIlya Leoshkevich uint32_t get_elf_hwcap(void) 17586d88baf1SDavid Hildenbrand { 17596d88baf1SDavid Hildenbrand /* 17606d88baf1SDavid Hildenbrand * Let's assume we always have esan3 and zarch. 17616d88baf1SDavid Hildenbrand * 31-bit processes can use 64-bit registers (high gprs). 17626d88baf1SDavid Hildenbrand */ 17636d88baf1SDavid Hildenbrand uint32_t hwcap = HWCAP_S390_ESAN3 | HWCAP_S390_ZARCH | HWCAP_S390_HIGH_GPRS; 17646d88baf1SDavid Hildenbrand 17656d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_STFLE, HWCAP_S390_STFLE); 17666d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_MSA, HWCAP_S390_MSA); 17676d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_LONG_DISPLACEMENT, HWCAP_S390_LDISP); 17686d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_EXTENDED_IMMEDIATE, HWCAP_S390_EIMM); 17696d88baf1SDavid Hildenbrand if (s390_has_feat(S390_FEAT_EXTENDED_TRANSLATION_3) && 17706d88baf1SDavid Hildenbrand s390_has_feat(S390_FEAT_ETF3_ENH)) { 17716d88baf1SDavid Hildenbrand hwcap |= HWCAP_S390_ETF3EH; 17726d88baf1SDavid Hildenbrand } 17736d88baf1SDavid Hildenbrand GET_FEATURE(S390_FEAT_VECTOR, HWCAP_S390_VXRS); 1774da215c23SDavid Hildenbrand GET_FEATURE(S390_FEAT_VECTOR_ENH, HWCAP_S390_VXRS_EXT); 1775ffc8453bSIlya Leoshkevich GET_FEATURE(S390_FEAT_VECTOR_ENH2, HWCAP_S390_VXRS_EXT2); 17766d88baf1SDavid Hildenbrand 17776d88baf1SDavid Hildenbrand return hwcap; 17786d88baf1SDavid Hildenbrand } 17796d88baf1SDavid Hildenbrand 1780e19807beSIlya Leoshkevich const char *elf_hwcap_str(uint32_t bit) 1781e19807beSIlya Leoshkevich { 1782e19807beSIlya Leoshkevich static const char *hwcap_str[] = { 17837f114a58SIlya Leoshkevich [HWCAP_S390_NR_ESAN3] = "esan3", 17847f114a58SIlya Leoshkevich [HWCAP_S390_NR_ZARCH] = "zarch", 17857f114a58SIlya Leoshkevich [HWCAP_S390_NR_STFLE] = "stfle", 17867f114a58SIlya Leoshkevich [HWCAP_S390_NR_MSA] = "msa", 17877f114a58SIlya Leoshkevich [HWCAP_S390_NR_LDISP] = "ldisp", 17887f114a58SIlya Leoshkevich [HWCAP_S390_NR_EIMM] = "eimm", 17897f114a58SIlya Leoshkevich [HWCAP_S390_NR_DFP] = "dfp", 17907f114a58SIlya Leoshkevich [HWCAP_S390_NR_HPAGE] = "edat", 17917f114a58SIlya Leoshkevich [HWCAP_S390_NR_ETF3EH] = "etf3eh", 17927f114a58SIlya Leoshkevich [HWCAP_S390_NR_HIGH_GPRS] = "highgprs", 17937f114a58SIlya Leoshkevich [HWCAP_S390_NR_TE] = "te", 17947f114a58SIlya Leoshkevich [HWCAP_S390_NR_VXRS] = "vx", 17957f114a58SIlya Leoshkevich [HWCAP_S390_NR_VXRS_BCD] = "vxd", 17967f114a58SIlya Leoshkevich [HWCAP_S390_NR_VXRS_EXT] = "vxe", 17977f114a58SIlya Leoshkevich [HWCAP_S390_NR_GS] = "gs", 17987f114a58SIlya Leoshkevich [HWCAP_S390_NR_VXRS_EXT2] = "vxe2", 17997f114a58SIlya Leoshkevich [HWCAP_S390_NR_VXRS_PDE] = "vxp", 18007f114a58SIlya Leoshkevich [HWCAP_S390_NR_SORT] = "sort", 18017f114a58SIlya Leoshkevich [HWCAP_S390_NR_DFLT] = "dflt", 18027f114a58SIlya Leoshkevich [HWCAP_S390_NR_NNPA] = "nnpa", 18037f114a58SIlya Leoshkevich [HWCAP_S390_NR_PCI_MIO] = "pcimio", 18047f114a58SIlya Leoshkevich [HWCAP_S390_NR_SIE] = "sie", 1805e19807beSIlya Leoshkevich }; 1806e19807beSIlya Leoshkevich 1807e19807beSIlya Leoshkevich return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; 1808e19807beSIlya Leoshkevich } 1809e19807beSIlya Leoshkevich 1810a4c075f1SUlrich Hecht static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 1811a4c075f1SUlrich Hecht { 1812a4c075f1SUlrich Hecht regs->psw.addr = infop->entry; 181378a1e153SIlya Leoshkevich regs->psw.mask = PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | \ 181478a1e153SIlya Leoshkevich PSW_MASK_MCHECK | PSW_MASK_PSTATE | PSW_MASK_64 | \ 181578a1e153SIlya Leoshkevich PSW_MASK_32; 1816a4c075f1SUlrich Hecht regs->gprs[15] = infop->start_stack; 1817a4c075f1SUlrich Hecht } 1818a4c075f1SUlrich Hecht 18194a1e8931SIlya Leoshkevich /* See linux kernel: arch/s390/include/uapi/asm/ptrace.h (s390_regs). */ 18204a1e8931SIlya Leoshkevich #define ELF_NREG 27 18214a1e8931SIlya Leoshkevich typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 18224a1e8931SIlya Leoshkevich 18234a1e8931SIlya Leoshkevich enum { 18244a1e8931SIlya Leoshkevich TARGET_REG_PSWM = 0, 18254a1e8931SIlya Leoshkevich TARGET_REG_PSWA = 1, 18264a1e8931SIlya Leoshkevich TARGET_REG_GPRS = 2, 18274a1e8931SIlya Leoshkevich TARGET_REG_ARS = 18, 18284a1e8931SIlya Leoshkevich TARGET_REG_ORIG_R2 = 26, 18294a1e8931SIlya Leoshkevich }; 18304a1e8931SIlya Leoshkevich 18314a1e8931SIlya Leoshkevich static void elf_core_copy_regs(target_elf_gregset_t *regs, 18324a1e8931SIlya Leoshkevich const CPUS390XState *env) 18334a1e8931SIlya Leoshkevich { 18344a1e8931SIlya Leoshkevich int i; 18354a1e8931SIlya Leoshkevich uint32_t *aregs; 18364a1e8931SIlya Leoshkevich 18374a1e8931SIlya Leoshkevich (*regs)[TARGET_REG_PSWM] = tswapreg(env->psw.mask); 18384a1e8931SIlya Leoshkevich (*regs)[TARGET_REG_PSWA] = tswapreg(env->psw.addr); 18394a1e8931SIlya Leoshkevich for (i = 0; i < 16; i++) { 18404a1e8931SIlya Leoshkevich (*regs)[TARGET_REG_GPRS + i] = tswapreg(env->regs[i]); 18414a1e8931SIlya Leoshkevich } 18424a1e8931SIlya Leoshkevich aregs = (uint32_t *)&((*regs)[TARGET_REG_ARS]); 18434a1e8931SIlya Leoshkevich for (i = 0; i < 16; i++) { 18444a1e8931SIlya Leoshkevich aregs[i] = tswap32(env->aregs[i]); 18454a1e8931SIlya Leoshkevich } 18464a1e8931SIlya Leoshkevich (*regs)[TARGET_REG_ORIG_R2] = 0; 18474a1e8931SIlya Leoshkevich } 18484a1e8931SIlya Leoshkevich 18494a1e8931SIlya Leoshkevich #define USE_ELF_CORE_DUMP 18504a1e8931SIlya Leoshkevich #define ELF_EXEC_PAGESIZE 4096 18514a1e8931SIlya Leoshkevich 1852a4c075f1SUlrich Hecht #endif /* TARGET_S390X */ 1853a4c075f1SUlrich Hecht 185447ae93cdSMichael Clark #ifdef TARGET_RISCV 185547ae93cdSMichael Clark 185647ae93cdSMichael Clark #define ELF_ARCH EM_RISCV 185747ae93cdSMichael Clark 185847ae93cdSMichael Clark #ifdef TARGET_RISCV32 185947ae93cdSMichael Clark #define ELF_CLASS ELFCLASS32 186047ae93cdSMichael Clark #else 186147ae93cdSMichael Clark #define ELF_CLASS ELFCLASS64 186247ae93cdSMichael Clark #endif 186347ae93cdSMichael Clark 1864cb46938cSKito Cheng #define ELF_HWCAP get_elf_hwcap() 1865cb46938cSKito Cheng 1866cb46938cSKito Cheng static uint32_t get_elf_hwcap(void) 1867cb46938cSKito Cheng { 1868cb46938cSKito Cheng #define MISA_BIT(EXT) (1 << (EXT - 'A')) 1869cb46938cSKito Cheng RISCVCPU *cpu = RISCV_CPU(thread_cpu); 1870cb46938cSKito Cheng uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A') 18714333f092SNathan Egge | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C') 18724333f092SNathan Egge | MISA_BIT('V'); 1873cb46938cSKito Cheng 1874e91a7227SRichard Henderson return cpu->env.misa_ext & mask; 1875cb46938cSKito Cheng #undef MISA_BIT 1876cb46938cSKito Cheng } 1877cb46938cSKito Cheng 187847ae93cdSMichael Clark static inline void init_thread(struct target_pt_regs *regs, 187947ae93cdSMichael Clark struct image_info *infop) 188047ae93cdSMichael Clark { 188147ae93cdSMichael Clark regs->sepc = infop->entry; 188247ae93cdSMichael Clark regs->sp = infop->start_stack; 188347ae93cdSMichael Clark } 188447ae93cdSMichael Clark 188547ae93cdSMichael Clark #define ELF_EXEC_PAGESIZE 4096 188647ae93cdSMichael Clark 188747ae93cdSMichael Clark #endif /* TARGET_RISCV */ 188847ae93cdSMichael Clark 18897c248bcdSRichard Henderson #ifdef TARGET_HPPA 18907c248bcdSRichard Henderson 18917c248bcdSRichard Henderson #define ELF_CLASS ELFCLASS32 18927c248bcdSRichard Henderson #define ELF_ARCH EM_PARISC 18937c248bcdSRichard Henderson #define ELF_PLATFORM "PARISC" 18947c248bcdSRichard Henderson #define STACK_GROWS_DOWN 0 18957c248bcdSRichard Henderson #define STACK_ALIGNMENT 64 18967c248bcdSRichard Henderson 18977c248bcdSRichard Henderson static inline void init_thread(struct target_pt_regs *regs, 18987c248bcdSRichard Henderson struct image_info *infop) 18997c248bcdSRichard Henderson { 19007c248bcdSRichard Henderson regs->iaoq[0] = infop->entry; 19017c248bcdSRichard Henderson regs->iaoq[1] = infop->entry + 4; 19027c248bcdSRichard Henderson regs->gr[23] = 0; 190360f1c801SRichard Henderson regs->gr[24] = infop->argv; 190460f1c801SRichard Henderson regs->gr[25] = infop->argc; 19057c248bcdSRichard Henderson /* The top-of-stack contains a linkage buffer. */ 19067c248bcdSRichard Henderson regs->gr[30] = infop->start_stack + 64; 19077c248bcdSRichard Henderson regs->gr[31] = infop->entry; 19087c248bcdSRichard Henderson } 19097c248bcdSRichard Henderson 1910eee816c0SRichard Henderson #define LO_COMMPAGE 0 1911eee816c0SRichard Henderson 1912eee816c0SRichard Henderson static bool init_guest_commpage(void) 1913eee816c0SRichard Henderson { 1914eee816c0SRichard Henderson void *want = g2h_untagged(LO_COMMPAGE); 1915eee816c0SRichard Henderson void *addr = mmap(want, qemu_host_page_size, PROT_NONE, 1916eee816c0SRichard Henderson MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); 1917eee816c0SRichard Henderson 1918eee816c0SRichard Henderson if (addr == MAP_FAILED) { 1919eee816c0SRichard Henderson perror("Allocating guest commpage"); 1920eee816c0SRichard Henderson exit(EXIT_FAILURE); 1921eee816c0SRichard Henderson } 1922eee816c0SRichard Henderson if (addr != want) { 1923eee816c0SRichard Henderson return false; 1924eee816c0SRichard Henderson } 1925eee816c0SRichard Henderson 1926eee816c0SRichard Henderson /* 1927eee816c0SRichard Henderson * On Linux, page zero is normally marked execute only + gateway. 1928eee816c0SRichard Henderson * Normal read or write is supposed to fail (thus PROT_NONE above), 1929eee816c0SRichard Henderson * but specific offsets have kernel code mapped to raise permissions 1930eee816c0SRichard Henderson * and implement syscalls. Here, simply mark the page executable. 1931eee816c0SRichard Henderson * Special case the entry points during translation (see do_page_zero). 1932eee816c0SRichard Henderson */ 193349840a4aSRichard Henderson page_set_flags(LO_COMMPAGE, LO_COMMPAGE | ~TARGET_PAGE_MASK, 1934eee816c0SRichard Henderson PAGE_EXEC | PAGE_VALID); 1935eee816c0SRichard Henderson return true; 1936eee816c0SRichard Henderson } 1937eee816c0SRichard Henderson 19387c248bcdSRichard Henderson #endif /* TARGET_HPPA */ 19397c248bcdSRichard Henderson 1940ba7651fbSMax Filippov #ifdef TARGET_XTENSA 1941ba7651fbSMax Filippov 1942ba7651fbSMax Filippov #define ELF_CLASS ELFCLASS32 1943ba7651fbSMax Filippov #define ELF_ARCH EM_XTENSA 1944ba7651fbSMax Filippov 1945ba7651fbSMax Filippov static inline void init_thread(struct target_pt_regs *regs, 1946ba7651fbSMax Filippov struct image_info *infop) 1947ba7651fbSMax Filippov { 1948ba7651fbSMax Filippov regs->windowbase = 0; 1949ba7651fbSMax Filippov regs->windowstart = 1; 1950ba7651fbSMax Filippov regs->areg[1] = infop->start_stack; 1951ba7651fbSMax Filippov regs->pc = infop->entry; 1952d2796be6SMax Filippov if (info_is_fdpic(infop)) { 1953d2796be6SMax Filippov regs->areg[4] = infop->loadmap_addr; 1954d2796be6SMax Filippov regs->areg[5] = infop->interpreter_loadmap_addr; 1955d2796be6SMax Filippov if (infop->interpreter_loadmap_addr) { 1956d2796be6SMax Filippov regs->areg[6] = infop->interpreter_pt_dynamic_addr; 1957d2796be6SMax Filippov } else { 1958d2796be6SMax Filippov regs->areg[6] = infop->pt_dynamic_addr; 1959d2796be6SMax Filippov } 1960d2796be6SMax Filippov } 1961ba7651fbSMax Filippov } 1962ba7651fbSMax Filippov 1963ba7651fbSMax Filippov /* See linux kernel: arch/xtensa/include/asm/elf.h. */ 1964ba7651fbSMax Filippov #define ELF_NREG 128 1965ba7651fbSMax Filippov typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1966ba7651fbSMax Filippov 1967ba7651fbSMax Filippov enum { 1968ba7651fbSMax Filippov TARGET_REG_PC, 1969ba7651fbSMax Filippov TARGET_REG_PS, 1970ba7651fbSMax Filippov TARGET_REG_LBEG, 1971ba7651fbSMax Filippov TARGET_REG_LEND, 1972ba7651fbSMax Filippov TARGET_REG_LCOUNT, 1973ba7651fbSMax Filippov TARGET_REG_SAR, 1974ba7651fbSMax Filippov TARGET_REG_WINDOWSTART, 1975ba7651fbSMax Filippov TARGET_REG_WINDOWBASE, 1976ba7651fbSMax Filippov TARGET_REG_THREADPTR, 1977ba7651fbSMax Filippov TARGET_REG_AR0 = 64, 1978ba7651fbSMax Filippov }; 1979ba7651fbSMax Filippov 1980ba7651fbSMax Filippov static void elf_core_copy_regs(target_elf_gregset_t *regs, 1981ba7651fbSMax Filippov const CPUXtensaState *env) 1982ba7651fbSMax Filippov { 1983ba7651fbSMax Filippov unsigned i; 1984ba7651fbSMax Filippov 1985ba7651fbSMax Filippov (*regs)[TARGET_REG_PC] = tswapreg(env->pc); 1986ba7651fbSMax Filippov (*regs)[TARGET_REG_PS] = tswapreg(env->sregs[PS] & ~PS_EXCM); 1987ba7651fbSMax Filippov (*regs)[TARGET_REG_LBEG] = tswapreg(env->sregs[LBEG]); 1988ba7651fbSMax Filippov (*regs)[TARGET_REG_LEND] = tswapreg(env->sregs[LEND]); 1989ba7651fbSMax Filippov (*regs)[TARGET_REG_LCOUNT] = tswapreg(env->sregs[LCOUNT]); 1990ba7651fbSMax Filippov (*regs)[TARGET_REG_SAR] = tswapreg(env->sregs[SAR]); 1991ba7651fbSMax Filippov (*regs)[TARGET_REG_WINDOWSTART] = tswapreg(env->sregs[WINDOW_START]); 1992ba7651fbSMax Filippov (*regs)[TARGET_REG_WINDOWBASE] = tswapreg(env->sregs[WINDOW_BASE]); 1993ba7651fbSMax Filippov (*regs)[TARGET_REG_THREADPTR] = tswapreg(env->uregs[THREADPTR]); 1994ba7651fbSMax Filippov xtensa_sync_phys_from_window((CPUXtensaState *)env); 1995ba7651fbSMax Filippov for (i = 0; i < env->config->nareg; ++i) { 1996ba7651fbSMax Filippov (*regs)[TARGET_REG_AR0 + i] = tswapreg(env->phys_regs[i]); 1997ba7651fbSMax Filippov } 1998ba7651fbSMax Filippov } 1999ba7651fbSMax Filippov 2000ba7651fbSMax Filippov #define USE_ELF_CORE_DUMP 2001ba7651fbSMax Filippov #define ELF_EXEC_PAGESIZE 4096 2002ba7651fbSMax Filippov 2003ba7651fbSMax Filippov #endif /* TARGET_XTENSA */ 2004ba7651fbSMax Filippov 2005d2a56bd2STaylor Simpson #ifdef TARGET_HEXAGON 2006d2a56bd2STaylor Simpson 2007d2a56bd2STaylor Simpson #define ELF_CLASS ELFCLASS32 2008d2a56bd2STaylor Simpson #define ELF_ARCH EM_HEXAGON 2009d2a56bd2STaylor Simpson 2010d2a56bd2STaylor Simpson static inline void init_thread(struct target_pt_regs *regs, 2011d2a56bd2STaylor Simpson struct image_info *infop) 2012d2a56bd2STaylor Simpson { 2013d2a56bd2STaylor Simpson regs->sepc = infop->entry; 2014d2a56bd2STaylor Simpson regs->sp = infop->start_stack; 2015d2a56bd2STaylor Simpson } 2016d2a56bd2STaylor Simpson 2017d2a56bd2STaylor Simpson #endif /* TARGET_HEXAGON */ 2018d2a56bd2STaylor Simpson 2019fcdc0ab4SJiaxun Yang #ifndef ELF_BASE_PLATFORM 2020fcdc0ab4SJiaxun Yang #define ELF_BASE_PLATFORM (NULL) 2021fcdc0ab4SJiaxun Yang #endif 2022fcdc0ab4SJiaxun Yang 202315338fd7Sbellard #ifndef ELF_PLATFORM 202415338fd7Sbellard #define ELF_PLATFORM (NULL) 202515338fd7Sbellard #endif 202615338fd7Sbellard 202775be901cSPeter Crosthwaite #ifndef ELF_MACHINE 202875be901cSPeter Crosthwaite #define ELF_MACHINE ELF_ARCH 202975be901cSPeter Crosthwaite #endif 203075be901cSPeter Crosthwaite 2031d276a604SPeter Crosthwaite #ifndef elf_check_arch 2032d276a604SPeter Crosthwaite #define elf_check_arch(x) ((x) == ELF_ARCH) 2033d276a604SPeter Crosthwaite #endif 2034d276a604SPeter Crosthwaite 2035ace3d654SCarlo Marcelo Arenas Belón #ifndef elf_check_abi 2036ace3d654SCarlo Marcelo Arenas Belón #define elf_check_abi(x) (1) 2037ace3d654SCarlo Marcelo Arenas Belón #endif 2038ace3d654SCarlo Marcelo Arenas Belón 203915338fd7Sbellard #ifndef ELF_HWCAP 204015338fd7Sbellard #define ELF_HWCAP 0 204115338fd7Sbellard #endif 204215338fd7Sbellard 20437c4ee5bcSRichard Henderson #ifndef STACK_GROWS_DOWN 20447c4ee5bcSRichard Henderson #define STACK_GROWS_DOWN 1 20457c4ee5bcSRichard Henderson #endif 20467c4ee5bcSRichard Henderson 20477c4ee5bcSRichard Henderson #ifndef STACK_ALIGNMENT 20487c4ee5bcSRichard Henderson #define STACK_ALIGNMENT 16 20497c4ee5bcSRichard Henderson #endif 20507c4ee5bcSRichard Henderson 2051992f48a0Sblueswir1 #ifdef TARGET_ABI32 2052cb33da57Sblueswir1 #undef ELF_CLASS 2053992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32 2054cb33da57Sblueswir1 #undef bswaptls 2055cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr) 2056cb33da57Sblueswir1 #endif 2057cb33da57Sblueswir1 2058872f3d04SRichard Henderson #ifndef EXSTACK_DEFAULT 2059872f3d04SRichard Henderson #define EXSTACK_DEFAULT false 2060872f3d04SRichard Henderson #endif 2061872f3d04SRichard Henderson 206231e31b8aSbellard #include "elf.h" 206309bfb054Sbellard 2064e8384b37SRichard Henderson /* We must delay the following stanzas until after "elf.h". */ 2065e8384b37SRichard Henderson #if defined(TARGET_AARCH64) 2066e8384b37SRichard Henderson 2067e8384b37SRichard Henderson static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz, 2068e8384b37SRichard Henderson const uint32_t *data, 2069e8384b37SRichard Henderson struct image_info *info, 2070e8384b37SRichard Henderson Error **errp) 2071e8384b37SRichard Henderson { 2072e8384b37SRichard Henderson if (pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) { 2073e8384b37SRichard Henderson if (pr_datasz != sizeof(uint32_t)) { 2074e8384b37SRichard Henderson error_setg(errp, "Ill-formed GNU_PROPERTY_AARCH64_FEATURE_1_AND"); 2075e8384b37SRichard Henderson return false; 2076e8384b37SRichard Henderson } 2077e8384b37SRichard Henderson /* We will extract GNU_PROPERTY_AARCH64_FEATURE_1_BTI later. */ 2078e8384b37SRichard Henderson info->note_flags = *data; 2079e8384b37SRichard Henderson } 2080e8384b37SRichard Henderson return true; 2081e8384b37SRichard Henderson } 2082e8384b37SRichard Henderson #define ARCH_USE_GNU_PROPERTY 1 2083e8384b37SRichard Henderson 2084e8384b37SRichard Henderson #else 2085e8384b37SRichard Henderson 208683f990ebSRichard Henderson static bool arch_parse_elf_property(uint32_t pr_type, uint32_t pr_datasz, 208783f990ebSRichard Henderson const uint32_t *data, 208883f990ebSRichard Henderson struct image_info *info, 208983f990ebSRichard Henderson Error **errp) 209083f990ebSRichard Henderson { 209183f990ebSRichard Henderson g_assert_not_reached(); 209283f990ebSRichard Henderson } 209383f990ebSRichard Henderson #define ARCH_USE_GNU_PROPERTY 0 209483f990ebSRichard Henderson 2095e8384b37SRichard Henderson #endif 2096e8384b37SRichard Henderson 209709bfb054Sbellard struct exec 209809bfb054Sbellard { 209909bfb054Sbellard unsigned int a_info; /* Use macros N_MAGIC, etc for access */ 210009bfb054Sbellard unsigned int a_text; /* length of text, in bytes */ 210109bfb054Sbellard unsigned int a_data; /* length of data, in bytes */ 210209bfb054Sbellard unsigned int a_bss; /* length of uninitialized data area, in bytes */ 210309bfb054Sbellard unsigned int a_syms; /* length of symbol table data in file, in bytes */ 210409bfb054Sbellard unsigned int a_entry; /* start address */ 210509bfb054Sbellard unsigned int a_trsize; /* length of relocation info for text, in bytes */ 210609bfb054Sbellard unsigned int a_drsize; /* length of relocation info for data, in bytes */ 210709bfb054Sbellard }; 210809bfb054Sbellard 210909bfb054Sbellard 211009bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff) 211109bfb054Sbellard #define OMAGIC 0407 211209bfb054Sbellard #define NMAGIC 0410 211309bfb054Sbellard #define ZMAGIC 0413 211409bfb054Sbellard #define QMAGIC 0314 211509bfb054Sbellard 2116e0d1673dSLirong Yuan #define DLINFO_ITEMS 16 211731e31b8aSbellard 211809bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) 211909bfb054Sbellard { 212009bfb054Sbellard memcpy(to, from, n); 212109bfb054Sbellard } 212209bfb054Sbellard 212331e31b8aSbellard #ifdef BSWAP_NEEDED 212492a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr) 212531e31b8aSbellard { 212631e31b8aSbellard bswap16s(&ehdr->e_type); /* Object file type */ 212731e31b8aSbellard bswap16s(&ehdr->e_machine); /* Architecture */ 212831e31b8aSbellard bswap32s(&ehdr->e_version); /* Object file version */ 212992a31b1fSbellard bswaptls(&ehdr->e_entry); /* Entry point virtual address */ 213092a31b1fSbellard bswaptls(&ehdr->e_phoff); /* Program header table file offset */ 213192a31b1fSbellard bswaptls(&ehdr->e_shoff); /* Section header table file offset */ 213231e31b8aSbellard bswap32s(&ehdr->e_flags); /* Processor-specific flags */ 213331e31b8aSbellard bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ 213431e31b8aSbellard bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ 213531e31b8aSbellard bswap16s(&ehdr->e_phnum); /* Program header table entry count */ 213631e31b8aSbellard bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ 213731e31b8aSbellard bswap16s(&ehdr->e_shnum); /* Section header table entry count */ 213831e31b8aSbellard bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ 213931e31b8aSbellard } 214031e31b8aSbellard 2141991f8f0cSRichard Henderson static void bswap_phdr(struct elf_phdr *phdr, int phnum) 214231e31b8aSbellard { 2143991f8f0cSRichard Henderson int i; 2144991f8f0cSRichard Henderson for (i = 0; i < phnum; ++i, ++phdr) { 214531e31b8aSbellard bswap32s(&phdr->p_type); /* Segment type */ 2146991f8f0cSRichard Henderson bswap32s(&phdr->p_flags); /* Segment flags */ 214792a31b1fSbellard bswaptls(&phdr->p_offset); /* Segment file offset */ 214892a31b1fSbellard bswaptls(&phdr->p_vaddr); /* Segment virtual address */ 214992a31b1fSbellard bswaptls(&phdr->p_paddr); /* Segment physical address */ 215092a31b1fSbellard bswaptls(&phdr->p_filesz); /* Segment size in file */ 215192a31b1fSbellard bswaptls(&phdr->p_memsz); /* Segment size in memory */ 215292a31b1fSbellard bswaptls(&phdr->p_align); /* Segment alignment */ 215331e31b8aSbellard } 2154991f8f0cSRichard Henderson } 2155689f936fSbellard 2156991f8f0cSRichard Henderson static void bswap_shdr(struct elf_shdr *shdr, int shnum) 2157689f936fSbellard { 2158991f8f0cSRichard Henderson int i; 2159991f8f0cSRichard Henderson for (i = 0; i < shnum; ++i, ++shdr) { 2160689f936fSbellard bswap32s(&shdr->sh_name); 2161689f936fSbellard bswap32s(&shdr->sh_type); 216292a31b1fSbellard bswaptls(&shdr->sh_flags); 216392a31b1fSbellard bswaptls(&shdr->sh_addr); 216492a31b1fSbellard bswaptls(&shdr->sh_offset); 216592a31b1fSbellard bswaptls(&shdr->sh_size); 2166689f936fSbellard bswap32s(&shdr->sh_link); 2167689f936fSbellard bswap32s(&shdr->sh_info); 216892a31b1fSbellard bswaptls(&shdr->sh_addralign); 216992a31b1fSbellard bswaptls(&shdr->sh_entsize); 2170689f936fSbellard } 2171991f8f0cSRichard Henderson } 2172689f936fSbellard 21737a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym) 2174689f936fSbellard { 2175689f936fSbellard bswap32s(&sym->st_name); 21767a3148a9Sj_mayer bswaptls(&sym->st_value); 21777a3148a9Sj_mayer bswaptls(&sym->st_size); 2178689f936fSbellard bswap16s(&sym->st_shndx); 2179689f936fSbellard } 21805dd0db52SStefan Markovic 21815dd0db52SStefan Markovic #ifdef TARGET_MIPS 21825dd0db52SStefan Markovic static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) 21835dd0db52SStefan Markovic { 21845dd0db52SStefan Markovic bswap16s(&abiflags->version); 21855dd0db52SStefan Markovic bswap32s(&abiflags->ases); 21865dd0db52SStefan Markovic bswap32s(&abiflags->isa_ext); 21875dd0db52SStefan Markovic bswap32s(&abiflags->flags1); 21885dd0db52SStefan Markovic bswap32s(&abiflags->flags2); 21895dd0db52SStefan Markovic } 21905dd0db52SStefan Markovic #endif 2191991f8f0cSRichard Henderson #else 2192991f8f0cSRichard Henderson static inline void bswap_ehdr(struct elfhdr *ehdr) { } 2193991f8f0cSRichard Henderson static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { } 2194991f8f0cSRichard Henderson static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { } 2195991f8f0cSRichard Henderson static inline void bswap_sym(struct elf_sym *sym) { } 21965dd0db52SStefan Markovic #ifdef TARGET_MIPS 21975dd0db52SStefan Markovic static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { } 21985dd0db52SStefan Markovic #endif 219931e31b8aSbellard #endif 220031e31b8aSbellard 2201edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 22029349b4f9SAndreas Färber static int elf_core_dump(int, const CPUArchState *); 2203edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 2204*86cf82dcSRichard Henderson static void load_symbols(struct elfhdr *hdr, const ImageSource *src, 2205*86cf82dcSRichard Henderson abi_ulong load_bias); 2206edf8e2afSMika Westerberg 22079058abddSRichard Henderson /* Verify the portions of EHDR within E_IDENT for the target. 22089058abddSRichard Henderson This can be performed before bswapping the entire header. */ 22099058abddSRichard Henderson static bool elf_check_ident(struct elfhdr *ehdr) 22109058abddSRichard Henderson { 22119058abddSRichard Henderson return (ehdr->e_ident[EI_MAG0] == ELFMAG0 22129058abddSRichard Henderson && ehdr->e_ident[EI_MAG1] == ELFMAG1 22139058abddSRichard Henderson && ehdr->e_ident[EI_MAG2] == ELFMAG2 22149058abddSRichard Henderson && ehdr->e_ident[EI_MAG3] == ELFMAG3 22159058abddSRichard Henderson && ehdr->e_ident[EI_CLASS] == ELF_CLASS 22169058abddSRichard Henderson && ehdr->e_ident[EI_DATA] == ELF_DATA 22179058abddSRichard Henderson && ehdr->e_ident[EI_VERSION] == EV_CURRENT); 22189058abddSRichard Henderson } 22199058abddSRichard Henderson 22209058abddSRichard Henderson /* Verify the portions of EHDR outside of E_IDENT for the target. 22219058abddSRichard Henderson This has to wait until after bswapping the header. */ 22229058abddSRichard Henderson static bool elf_check_ehdr(struct elfhdr *ehdr) 22239058abddSRichard Henderson { 22249058abddSRichard Henderson return (elf_check_arch(ehdr->e_machine) 2225ace3d654SCarlo Marcelo Arenas Belón && elf_check_abi(ehdr->e_flags) 22269058abddSRichard Henderson && ehdr->e_ehsize == sizeof(struct elfhdr) 22279058abddSRichard Henderson && ehdr->e_phentsize == sizeof(struct elf_phdr) 22289058abddSRichard Henderson && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)); 22299058abddSRichard Henderson } 22309058abddSRichard Henderson 223131e31b8aSbellard /* 2232e5fe0c52Spbrook * 'copy_elf_strings()' copies argument/envelope strings from user 223331e31b8aSbellard * memory to free pages in kernel mem. These are in a format ready 223431e31b8aSbellard * to be put directly into the top of new user memory. 223531e31b8aSbellard * 223631e31b8aSbellard */ 223759baae9aSStefan Brüns static abi_ulong copy_elf_strings(int argc, char **argv, char *scratch, 223859baae9aSStefan Brüns abi_ulong p, abi_ulong stack_limit) 223931e31b8aSbellard { 224059baae9aSStefan Brüns char *tmp; 22417c4ee5bcSRichard Henderson int len, i; 224259baae9aSStefan Brüns abi_ulong top = p; 224331e31b8aSbellard 224431e31b8aSbellard if (!p) { 224531e31b8aSbellard return 0; /* bullet-proofing */ 224631e31b8aSbellard } 224759baae9aSStefan Brüns 22487c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 22497c4ee5bcSRichard Henderson int offset = ((p - 1) % TARGET_PAGE_SIZE) + 1; 22507c4ee5bcSRichard Henderson for (i = argc - 1; i >= 0; --i) { 22517c4ee5bcSRichard Henderson tmp = argv[i]; 2252edf779ffSbellard if (!tmp) { 225331e31b8aSbellard fprintf(stderr, "VFS: argc is wrong"); 225431e31b8aSbellard exit(-1); 225531e31b8aSbellard } 225659baae9aSStefan Brüns len = strlen(tmp) + 1; 225759baae9aSStefan Brüns tmp += len; 225859baae9aSStefan Brüns 225959baae9aSStefan Brüns if (len > (p - stack_limit)) { 226031e31b8aSbellard return 0; 226131e31b8aSbellard } 226231e31b8aSbellard while (len) { 226331e31b8aSbellard int bytes_to_copy = (len > offset) ? offset : len; 226431e31b8aSbellard tmp -= bytes_to_copy; 226531e31b8aSbellard p -= bytes_to_copy; 226631e31b8aSbellard offset -= bytes_to_copy; 226731e31b8aSbellard len -= bytes_to_copy; 226859baae9aSStefan Brüns 226959baae9aSStefan Brüns memcpy_fromfs(scratch + offset, tmp, bytes_to_copy); 227059baae9aSStefan Brüns 227159baae9aSStefan Brüns if (offset == 0) { 227259baae9aSStefan Brüns memcpy_to_target(p, scratch, top - p); 227359baae9aSStefan Brüns top = p; 227459baae9aSStefan Brüns offset = TARGET_PAGE_SIZE; 227531e31b8aSbellard } 227631e31b8aSbellard } 227731e31b8aSbellard } 22787c4ee5bcSRichard Henderson if (p != top) { 227959baae9aSStefan Brüns memcpy_to_target(p, scratch + offset, top - p); 228059baae9aSStefan Brüns } 22817c4ee5bcSRichard Henderson } else { 22827c4ee5bcSRichard Henderson int remaining = TARGET_PAGE_SIZE - (p % TARGET_PAGE_SIZE); 22837c4ee5bcSRichard Henderson for (i = 0; i < argc; ++i) { 22847c4ee5bcSRichard Henderson tmp = argv[i]; 22857c4ee5bcSRichard Henderson if (!tmp) { 22867c4ee5bcSRichard Henderson fprintf(stderr, "VFS: argc is wrong"); 22877c4ee5bcSRichard Henderson exit(-1); 22887c4ee5bcSRichard Henderson } 22897c4ee5bcSRichard Henderson len = strlen(tmp) + 1; 22907c4ee5bcSRichard Henderson if (len > (stack_limit - p)) { 22917c4ee5bcSRichard Henderson return 0; 22927c4ee5bcSRichard Henderson } 22937c4ee5bcSRichard Henderson while (len) { 22947c4ee5bcSRichard Henderson int bytes_to_copy = (len > remaining) ? remaining : len; 22957c4ee5bcSRichard Henderson 22967c4ee5bcSRichard Henderson memcpy_fromfs(scratch + (p - top), tmp, bytes_to_copy); 22977c4ee5bcSRichard Henderson 22987c4ee5bcSRichard Henderson tmp += bytes_to_copy; 22997c4ee5bcSRichard Henderson remaining -= bytes_to_copy; 23007c4ee5bcSRichard Henderson p += bytes_to_copy; 23017c4ee5bcSRichard Henderson len -= bytes_to_copy; 23027c4ee5bcSRichard Henderson 23037c4ee5bcSRichard Henderson if (remaining == 0) { 23047c4ee5bcSRichard Henderson memcpy_to_target(top, scratch, p - top); 23057c4ee5bcSRichard Henderson top = p; 23067c4ee5bcSRichard Henderson remaining = TARGET_PAGE_SIZE; 23077c4ee5bcSRichard Henderson } 23087c4ee5bcSRichard Henderson } 23097c4ee5bcSRichard Henderson } 23107c4ee5bcSRichard Henderson if (p != top) { 23117c4ee5bcSRichard Henderson memcpy_to_target(top, scratch, p - top); 23127c4ee5bcSRichard Henderson } 23137c4ee5bcSRichard Henderson } 231459baae9aSStefan Brüns 231531e31b8aSbellard return p; 231631e31b8aSbellard } 231731e31b8aSbellard 231859baae9aSStefan Brüns /* Older linux kernels provide up to MAX_ARG_PAGES (default: 32) of 231959baae9aSStefan Brüns * argument/environment space. Newer kernels (>2.6.33) allow more, 232059baae9aSStefan Brüns * dependent on stack size, but guarantee at least 32 pages for 232159baae9aSStefan Brüns * backwards compatibility. 232259baae9aSStefan Brüns */ 232359baae9aSStefan Brüns #define STACK_LOWER_LIMIT (32 * TARGET_PAGE_SIZE) 232459baae9aSStefan Brüns 232559baae9aSStefan Brüns static abi_ulong setup_arg_pages(struct linux_binprm *bprm, 232631e31b8aSbellard struct image_info *info) 232731e31b8aSbellard { 232859baae9aSStefan Brüns abi_ulong size, error, guard; 2329872f3d04SRichard Henderson int prot; 233031e31b8aSbellard 2331703e0e89SRichard Henderson size = guest_stack_size; 233259baae9aSStefan Brüns if (size < STACK_LOWER_LIMIT) { 233359baae9aSStefan Brüns size = STACK_LOWER_LIMIT; 233460dcbcb5SRichard Henderson } 2335f4388205SHelge Deller 2336f4388205SHelge Deller if (STACK_GROWS_DOWN) { 233760dcbcb5SRichard Henderson guard = TARGET_PAGE_SIZE; 23388e3b0cbbSMarc-André Lureau if (guard < qemu_real_host_page_size()) { 23398e3b0cbbSMarc-André Lureau guard = qemu_real_host_page_size(); 234060dcbcb5SRichard Henderson } 2341f4388205SHelge Deller } else { 2342f4388205SHelge Deller /* no guard page for hppa target where stack grows upwards. */ 2343f4388205SHelge Deller guard = 0; 2344f4388205SHelge Deller } 234560dcbcb5SRichard Henderson 2346872f3d04SRichard Henderson prot = PROT_READ | PROT_WRITE; 2347872f3d04SRichard Henderson if (info->exec_stack) { 2348872f3d04SRichard Henderson prot |= PROT_EXEC; 2349872f3d04SRichard Henderson } 2350872f3d04SRichard Henderson error = target_mmap(0, size + guard, prot, 235160dcbcb5SRichard Henderson MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 235209bfb054Sbellard if (error == -1) { 235360dcbcb5SRichard Henderson perror("mmap stack"); 235431e31b8aSbellard exit(-1); 235531e31b8aSbellard } 235631e31b8aSbellard 235760dcbcb5SRichard Henderson /* We reserve one extra page at the top of the stack as guard. */ 23587c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 235960dcbcb5SRichard Henderson target_mprotect(error, guard, PROT_NONE); 236060dcbcb5SRichard Henderson info->stack_limit = error + guard; 236159baae9aSStefan Brüns return info->stack_limit + size - sizeof(void *); 23627c4ee5bcSRichard Henderson } else { 23637c4ee5bcSRichard Henderson info->stack_limit = error + size; 23647c4ee5bcSRichard Henderson return error; 23657c4ee5bcSRichard Henderson } 236631e31b8aSbellard } 236731e31b8aSbellard 23682d385be6SRichard Henderson /** 23692d385be6SRichard Henderson * zero_bss: 23702d385be6SRichard Henderson * 23712d385be6SRichard Henderson * Map and zero the bss. We need to explicitly zero any fractional pages 23722d385be6SRichard Henderson * after the data section (i.e. bss). Return false on mapping failure. 23732d385be6SRichard Henderson */ 2374e6e66b03SRichard Henderson static bool zero_bss(abi_ulong start_bss, abi_ulong end_bss, 2375e6e66b03SRichard Henderson int prot, Error **errp) 237631e31b8aSbellard { 23772d385be6SRichard Henderson abi_ulong align_bss; 2378cf129f3aSRichard Henderson 2379e6e66b03SRichard Henderson /* We only expect writable bss; the code segment shouldn't need this. */ 2380e6e66b03SRichard Henderson if (!(prot & PROT_WRITE)) { 2381e6e66b03SRichard Henderson error_setg(errp, "PT_LOAD with non-writable bss"); 2382e6e66b03SRichard Henderson return false; 2383e6e66b03SRichard Henderson } 2384e6e66b03SRichard Henderson 23852d385be6SRichard Henderson align_bss = TARGET_PAGE_ALIGN(start_bss); 23862d385be6SRichard Henderson end_bss = TARGET_PAGE_ALIGN(end_bss); 2387cf129f3aSRichard Henderson 23882d385be6SRichard Henderson if (start_bss < align_bss) { 23892d385be6SRichard Henderson int flags = page_get_flags(start_bss); 2390cf129f3aSRichard Henderson 2391e6e66b03SRichard Henderson if (!(flags & PAGE_BITS)) { 2392e6e66b03SRichard Henderson /* 2393e6e66b03SRichard Henderson * The whole address space of the executable was reserved 2394e6e66b03SRichard Henderson * at the start, therefore all pages will be VALID. 2395e6e66b03SRichard Henderson * But assuming there are no PROT_NONE PT_LOAD segments, 2396e6e66b03SRichard Henderson * a PROT_NONE page means no data all bss, and we can 2397e6e66b03SRichard Henderson * simply extend the new anon mapping back to the start 2398e6e66b03SRichard Henderson * of the page of bss. 2399e6e66b03SRichard Henderson */ 24002d385be6SRichard Henderson align_bss -= TARGET_PAGE_SIZE; 24012d385be6SRichard Henderson } else { 2402e6e66b03SRichard Henderson /* 2403e6e66b03SRichard Henderson * The start of the bss shares a page with something. 2404e6e66b03SRichard Henderson * The only thing that we expect is the data section, 2405e6e66b03SRichard Henderson * which would already be marked writable. 2406e6e66b03SRichard Henderson * Overlapping the RX code segment seems malformed. 2407e6e66b03SRichard Henderson */ 2408e6e66b03SRichard Henderson if (!(flags & PAGE_WRITE)) { 2409e6e66b03SRichard Henderson error_setg(errp, "PT_LOAD with bss overlapping " 2410e6e66b03SRichard Henderson "non-writable page"); 2411e6e66b03SRichard Henderson return false; 2412e6e66b03SRichard Henderson } 2413e6e66b03SRichard Henderson 2414e6e66b03SRichard Henderson /* The page is already mapped and writable. */ 2415e6e66b03SRichard Henderson memset(g2h_untagged(start_bss), 0, align_bss - start_bss); 241631e31b8aSbellard } 2417f46e9a0bSTom Musta } 2418cf129f3aSRichard Henderson 2419e6e66b03SRichard Henderson if (align_bss < end_bss && 24202d385be6SRichard Henderson target_mmap(align_bss, end_bss - align_bss, prot, 2421e6e66b03SRichard Henderson MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == -1) { 2422e6e66b03SRichard Henderson error_setg_errno(errp, errno, "Error mapping bss"); 2423e6e66b03SRichard Henderson return false; 2424e6e66b03SRichard Henderson } 2425e6e66b03SRichard Henderson return true; 2426853d6f7aSbellard } 2427853d6f7aSbellard 2428d2796be6SMax Filippov #if defined(TARGET_ARM) 2429cf58affeSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec) 2430cf58affeSChristophe Lyon { 2431cf58affeSChristophe Lyon return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC; 2432cf58affeSChristophe Lyon } 2433d2796be6SMax Filippov #elif defined(TARGET_XTENSA) 2434d2796be6SMax Filippov static int elf_is_fdpic(struct elfhdr *exec) 2435d2796be6SMax Filippov { 2436d2796be6SMax Filippov return exec->e_ident[EI_OSABI] == ELFOSABI_XTENSA_FDPIC; 2437d2796be6SMax Filippov } 2438cf58affeSChristophe Lyon #else 2439a99856cdSChristophe Lyon /* Default implementation, always false. */ 2440a99856cdSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec) 2441a99856cdSChristophe Lyon { 2442a99856cdSChristophe Lyon return 0; 2443a99856cdSChristophe Lyon } 2444cf58affeSChristophe Lyon #endif 2445a99856cdSChristophe Lyon 24461af02e83SMike Frysinger static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp) 24471af02e83SMike Frysinger { 24481af02e83SMike Frysinger uint16_t n; 24491af02e83SMike Frysinger struct elf32_fdpic_loadseg *loadsegs = info->loadsegs; 24501af02e83SMike Frysinger 24511af02e83SMike Frysinger /* elf32_fdpic_loadseg */ 24521af02e83SMike Frysinger n = info->nsegs; 24531af02e83SMike Frysinger while (n--) { 24541af02e83SMike Frysinger sp -= 12; 24551af02e83SMike Frysinger put_user_u32(loadsegs[n].addr, sp+0); 24561af02e83SMike Frysinger put_user_u32(loadsegs[n].p_vaddr, sp+4); 24571af02e83SMike Frysinger put_user_u32(loadsegs[n].p_memsz, sp+8); 24581af02e83SMike Frysinger } 24591af02e83SMike Frysinger 24601af02e83SMike Frysinger /* elf32_fdpic_loadmap */ 24611af02e83SMike Frysinger sp -= 4; 24621af02e83SMike Frysinger put_user_u16(0, sp+0); /* version */ 24631af02e83SMike Frysinger put_user_u16(info->nsegs, sp+2); /* nsegs */ 24641af02e83SMike Frysinger 24651af02e83SMike Frysinger info->personality = PER_LINUX_FDPIC; 24661af02e83SMike Frysinger info->loadmap_addr = sp; 24671af02e83SMike Frysinger 24681af02e83SMike Frysinger return sp; 24691af02e83SMike Frysinger } 24701af02e83SMike Frysinger 2471992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, 247231e31b8aSbellard struct elfhdr *exec, 24738e62a717SRichard Henderson struct image_info *info, 24748e62a717SRichard Henderson struct image_info *interp_info) 247531e31b8aSbellard { 2476992f48a0Sblueswir1 abi_ulong sp; 24777c4ee5bcSRichard Henderson abi_ulong u_argc, u_argv, u_envp, u_auxv; 247853a5960aSpbrook int size; 247914322badSLaurent ALFONSI int i; 248014322badSLaurent ALFONSI abi_ulong u_rand_bytes; 248114322badSLaurent ALFONSI uint8_t k_rand_bytes[16]; 2482fcdc0ab4SJiaxun Yang abi_ulong u_platform, u_base_platform; 2483fcdc0ab4SJiaxun Yang const char *k_platform, *k_base_platform; 2484863cf0b7Sj_mayer const int n = sizeof(elf_addr_t); 248531e31b8aSbellard 248653a5960aSpbrook sp = p; 24871af02e83SMike Frysinger 24881af02e83SMike Frysinger /* Needs to be before we load the env/argc/... */ 24891af02e83SMike Frysinger if (elf_is_fdpic(exec)) { 24901af02e83SMike Frysinger /* Need 4 byte alignment for these structs */ 24911af02e83SMike Frysinger sp &= ~3; 24921af02e83SMike Frysinger sp = loader_build_fdpic_loadmap(info, sp); 24931af02e83SMike Frysinger info->other_info = interp_info; 24941af02e83SMike Frysinger if (interp_info) { 24951af02e83SMike Frysinger interp_info->other_info = info; 24961af02e83SMike Frysinger sp = loader_build_fdpic_loadmap(interp_info, sp); 24973cb10cfaSChristophe Lyon info->interpreter_loadmap_addr = interp_info->loadmap_addr; 24983cb10cfaSChristophe Lyon info->interpreter_pt_dynamic_addr = interp_info->pt_dynamic_addr; 24993cb10cfaSChristophe Lyon } else { 25003cb10cfaSChristophe Lyon info->interpreter_loadmap_addr = 0; 25013cb10cfaSChristophe Lyon info->interpreter_pt_dynamic_addr = 0; 25021af02e83SMike Frysinger } 25031af02e83SMike Frysinger } 25041af02e83SMike Frysinger 2505fcdc0ab4SJiaxun Yang u_base_platform = 0; 2506fcdc0ab4SJiaxun Yang k_base_platform = ELF_BASE_PLATFORM; 2507fcdc0ab4SJiaxun Yang if (k_base_platform) { 2508fcdc0ab4SJiaxun Yang size_t len = strlen(k_base_platform) + 1; 2509fcdc0ab4SJiaxun Yang if (STACK_GROWS_DOWN) { 2510fcdc0ab4SJiaxun Yang sp -= (len + n - 1) & ~(n - 1); 2511fcdc0ab4SJiaxun Yang u_base_platform = sp; 2512fcdc0ab4SJiaxun Yang /* FIXME - check return value of memcpy_to_target() for failure */ 2513fcdc0ab4SJiaxun Yang memcpy_to_target(sp, k_base_platform, len); 2514fcdc0ab4SJiaxun Yang } else { 2515fcdc0ab4SJiaxun Yang memcpy_to_target(sp, k_base_platform, len); 2516fcdc0ab4SJiaxun Yang u_base_platform = sp; 2517fcdc0ab4SJiaxun Yang sp += len + 1; 2518fcdc0ab4SJiaxun Yang } 2519fcdc0ab4SJiaxun Yang } 2520fcdc0ab4SJiaxun Yang 252153a5960aSpbrook u_platform = 0; 252215338fd7Sbellard k_platform = ELF_PLATFORM; 252315338fd7Sbellard if (k_platform) { 252415338fd7Sbellard size_t len = strlen(k_platform) + 1; 25257c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 252653a5960aSpbrook sp -= (len + n - 1) & ~(n - 1); 252753a5960aSpbrook u_platform = sp; 2528579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 252953a5960aSpbrook memcpy_to_target(sp, k_platform, len); 25307c4ee5bcSRichard Henderson } else { 25317c4ee5bcSRichard Henderson memcpy_to_target(sp, k_platform, len); 25327c4ee5bcSRichard Henderson u_platform = sp; 25337c4ee5bcSRichard Henderson sp += len + 1; 25347c4ee5bcSRichard Henderson } 25357c4ee5bcSRichard Henderson } 25367c4ee5bcSRichard Henderson 25377c4ee5bcSRichard Henderson /* Provide 16 byte alignment for the PRNG, and basic alignment for 25387c4ee5bcSRichard Henderson * the argv and envp pointers. 25397c4ee5bcSRichard Henderson */ 25407c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 25417c4ee5bcSRichard Henderson sp = QEMU_ALIGN_DOWN(sp, 16); 25427c4ee5bcSRichard Henderson } else { 25437c4ee5bcSRichard Henderson sp = QEMU_ALIGN_UP(sp, 16); 254415338fd7Sbellard } 254514322badSLaurent ALFONSI 254614322badSLaurent ALFONSI /* 2547c6a2377fSRichard Henderson * Generate 16 random bytes for userspace PRNG seeding. 254814322badSLaurent ALFONSI */ 2549c6a2377fSRichard Henderson qemu_guest_getrandom_nofail(k_rand_bytes, sizeof(k_rand_bytes)); 25507c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 255114322badSLaurent ALFONSI sp -= 16; 255214322badSLaurent ALFONSI u_rand_bytes = sp; 255314322badSLaurent ALFONSI /* FIXME - check return value of memcpy_to_target() for failure */ 255414322badSLaurent ALFONSI memcpy_to_target(sp, k_rand_bytes, 16); 25557c4ee5bcSRichard Henderson } else { 25567c4ee5bcSRichard Henderson memcpy_to_target(sp, k_rand_bytes, 16); 25577c4ee5bcSRichard Henderson u_rand_bytes = sp; 25587c4ee5bcSRichard Henderson sp += 16; 25597c4ee5bcSRichard Henderson } 256014322badSLaurent ALFONSI 256153a5960aSpbrook size = (DLINFO_ITEMS + 1) * 2; 2562fcdc0ab4SJiaxun Yang if (k_base_platform) 2563fcdc0ab4SJiaxun Yang size += 2; 256415338fd7Sbellard if (k_platform) 256553a5960aSpbrook size += 2; 2566f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS 256753a5960aSpbrook size += DLINFO_ARCH_ITEMS * 2; 2568f5155289Sbellard #endif 2569ad6919dcSPeter Maydell #ifdef ELF_HWCAP2 2570ad6919dcSPeter Maydell size += 2; 2571ad6919dcSPeter Maydell #endif 2572f516511eSPeter Maydell info->auxv_len = size * n; 2573f516511eSPeter Maydell 257453a5960aSpbrook size += envc + argc + 2; 2575b9329d4bSRichard Henderson size += 1; /* argc itself */ 257653a5960aSpbrook size *= n; 25777c4ee5bcSRichard Henderson 25787c4ee5bcSRichard Henderson /* Allocate space and finalize stack alignment for entry now. */ 25797c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 25807c4ee5bcSRichard Henderson u_argc = QEMU_ALIGN_DOWN(sp - size, STACK_ALIGNMENT); 25817c4ee5bcSRichard Henderson sp = u_argc; 25827c4ee5bcSRichard Henderson } else { 25837c4ee5bcSRichard Henderson u_argc = sp; 25847c4ee5bcSRichard Henderson sp = QEMU_ALIGN_UP(sp + size, STACK_ALIGNMENT); 25857c4ee5bcSRichard Henderson } 25867c4ee5bcSRichard Henderson 25877c4ee5bcSRichard Henderson u_argv = u_argc + n; 25887c4ee5bcSRichard Henderson u_envp = u_argv + (argc + 1) * n; 25897c4ee5bcSRichard Henderson u_auxv = u_envp + (envc + 1) * n; 25907c4ee5bcSRichard Henderson info->saved_auxv = u_auxv; 259160f1c801SRichard Henderson info->argc = argc; 259260f1c801SRichard Henderson info->envc = envc; 259360f1c801SRichard Henderson info->argv = u_argv; 259460f1c801SRichard Henderson info->envp = u_envp; 2595f5155289Sbellard 2596863cf0b7Sj_mayer /* This is correct because Linux defines 2597863cf0b7Sj_mayer * elf_addr_t as Elf32_Off / Elf64_Off 2598863cf0b7Sj_mayer */ 259953a5960aSpbrook #define NEW_AUX_ENT(id, val) do { \ 26007c4ee5bcSRichard Henderson put_user_ual(id, u_auxv); u_auxv += n; \ 26017c4ee5bcSRichard Henderson put_user_ual(val, u_auxv); u_auxv += n; \ 260253a5960aSpbrook } while(0) 26032f619698Sbellard 260482991bedSPeter Maydell #ifdef ARCH_DLINFO 260582991bedSPeter Maydell /* 260682991bedSPeter Maydell * ARCH_DLINFO must come first so platform specific code can enforce 260782991bedSPeter Maydell * special alignment requirements on the AUXV if necessary (eg. PPC). 260882991bedSPeter Maydell */ 260982991bedSPeter Maydell ARCH_DLINFO; 261082991bedSPeter Maydell #endif 2611f516511eSPeter Maydell /* There must be exactly DLINFO_ITEMS entries here, or the assert 2612f516511eSPeter Maydell * on info->auxv_len will trigger. 2613f516511eSPeter Maydell */ 26148e62a717SRichard Henderson NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff)); 2615992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); 2616992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); 261733143c44SLaurent Vivier if ((info->alignment & ~qemu_host_page_mask) != 0) { 261833143c44SLaurent Vivier /* Target doesn't support host page size alignment */ 261933143c44SLaurent Vivier NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE)); 262033143c44SLaurent Vivier } else { 262133143c44SLaurent Vivier NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE, 262233143c44SLaurent Vivier qemu_host_page_size))); 262333143c44SLaurent Vivier } 26248e62a717SRichard Henderson NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0)); 2625992f48a0Sblueswir1 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); 26268e62a717SRichard Henderson NEW_AUX_ENT(AT_ENTRY, info->entry); 2627992f48a0Sblueswir1 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); 2628992f48a0Sblueswir1 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); 2629992f48a0Sblueswir1 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); 2630992f48a0Sblueswir1 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); 2631992f48a0Sblueswir1 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); 2632a07c67dfSpbrook NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); 263314322badSLaurent ALFONSI NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes); 2634444cd5c3SMarco A L Barbosa NEW_AUX_ENT(AT_SECURE, (abi_ulong) qemu_getauxval(AT_SECURE)); 2635e0d1673dSLirong Yuan NEW_AUX_ENT(AT_EXECFN, info->file_string); 263614322badSLaurent ALFONSI 2637ad6919dcSPeter Maydell #ifdef ELF_HWCAP2 2638ad6919dcSPeter Maydell NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); 2639ad6919dcSPeter Maydell #endif 2640ad6919dcSPeter Maydell 2641fcdc0ab4SJiaxun Yang if (u_base_platform) { 2642fcdc0ab4SJiaxun Yang NEW_AUX_ENT(AT_BASE_PLATFORM, u_base_platform); 2643fcdc0ab4SJiaxun Yang } 26447c4ee5bcSRichard Henderson if (u_platform) { 264553a5960aSpbrook NEW_AUX_ENT(AT_PLATFORM, u_platform); 26467c4ee5bcSRichard Henderson } 26477c4ee5bcSRichard Henderson NEW_AUX_ENT (AT_NULL, 0); 2648f5155289Sbellard #undef NEW_AUX_ENT 2649f5155289Sbellard 2650f516511eSPeter Maydell /* Check that our initial calculation of the auxv length matches how much 2651f516511eSPeter Maydell * we actually put into it. 2652f516511eSPeter Maydell */ 2653f516511eSPeter Maydell assert(info->auxv_len == u_auxv - info->saved_auxv); 2654edf8e2afSMika Westerberg 26557c4ee5bcSRichard Henderson put_user_ual(argc, u_argc); 26567c4ee5bcSRichard Henderson 26577c4ee5bcSRichard Henderson p = info->arg_strings; 26587c4ee5bcSRichard Henderson for (i = 0; i < argc; ++i) { 26597c4ee5bcSRichard Henderson put_user_ual(p, u_argv); 26607c4ee5bcSRichard Henderson u_argv += n; 26617c4ee5bcSRichard Henderson p += target_strlen(p) + 1; 26627c4ee5bcSRichard Henderson } 26637c4ee5bcSRichard Henderson put_user_ual(0, u_argv); 26647c4ee5bcSRichard Henderson 26657c4ee5bcSRichard Henderson p = info->env_strings; 26667c4ee5bcSRichard Henderson for (i = 0; i < envc; ++i) { 26677c4ee5bcSRichard Henderson put_user_ual(p, u_envp); 26687c4ee5bcSRichard Henderson u_envp += n; 26697c4ee5bcSRichard Henderson p += target_strlen(p) + 1; 26707c4ee5bcSRichard Henderson } 26717c4ee5bcSRichard Henderson put_user_ual(0, u_envp); 26727c4ee5bcSRichard Henderson 267331e31b8aSbellard return sp; 267431e31b8aSbellard } 267531e31b8aSbellard 2676f5ef0e51SRichard Henderson #if defined(HI_COMMPAGE) 2677eee816c0SRichard Henderson #define LO_COMMPAGE -1 2678f5ef0e51SRichard Henderson #elif defined(LO_COMMPAGE) 267966346fafSRichard Henderson #define HI_COMMPAGE 0 2680f5ef0e51SRichard Henderson #else 2681f5ef0e51SRichard Henderson #define HI_COMMPAGE 0 2682eee816c0SRichard Henderson #define LO_COMMPAGE -1 2683d461b73eSRichard Henderson #ifndef INIT_GUEST_COMMPAGE 2684ee947430SAlex Bennée #define init_guest_commpage() true 2685ee947430SAlex Bennée #endif 2686d461b73eSRichard Henderson #endif 2687ee947430SAlex Bennée 268806f38c66SRichard Henderson /** 268906f38c66SRichard Henderson * pgb_try_mmap: 269006f38c66SRichard Henderson * @addr: host start address 269106f38c66SRichard Henderson * @addr_last: host last address 269206f38c66SRichard Henderson * @keep: do not unmap the probe region 269306f38c66SRichard Henderson * 269406f38c66SRichard Henderson * Return 1 if [@addr, @addr_last] is not mapped in the host, 269506f38c66SRichard Henderson * return 0 if it is not available to map, and -1 on mmap error. 269606f38c66SRichard Henderson * If @keep, the region is left mapped on success, otherwise unmapped. 269706f38c66SRichard Henderson */ 269806f38c66SRichard Henderson static int pgb_try_mmap(uintptr_t addr, uintptr_t addr_last, bool keep) 269906f38c66SRichard Henderson { 270006f38c66SRichard Henderson size_t size = addr_last - addr + 1; 270106f38c66SRichard Henderson void *p = mmap((void *)addr, size, PROT_NONE, 270206f38c66SRichard Henderson MAP_ANONYMOUS | MAP_PRIVATE | 270306f38c66SRichard Henderson MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); 270406f38c66SRichard Henderson int ret; 270506f38c66SRichard Henderson 270606f38c66SRichard Henderson if (p == MAP_FAILED) { 270706f38c66SRichard Henderson return errno == EEXIST ? 0 : -1; 270806f38c66SRichard Henderson } 270906f38c66SRichard Henderson ret = p == (void *)addr; 271006f38c66SRichard Henderson if (!keep || !ret) { 271106f38c66SRichard Henderson munmap(p, size); 271206f38c66SRichard Henderson } 271306f38c66SRichard Henderson return ret; 271406f38c66SRichard Henderson } 271506f38c66SRichard Henderson 271606f38c66SRichard Henderson /** 271706f38c66SRichard Henderson * pgb_try_mmap_skip_brk(uintptr_t addr, uintptr_t size, uintptr_t brk) 271806f38c66SRichard Henderson * @addr: host address 271906f38c66SRichard Henderson * @addr_last: host last address 272006f38c66SRichard Henderson * @brk: host brk 272106f38c66SRichard Henderson * 272206f38c66SRichard Henderson * Like pgb_try_mmap, but additionally reserve some memory following brk. 272306f38c66SRichard Henderson */ 272406f38c66SRichard Henderson static int pgb_try_mmap_skip_brk(uintptr_t addr, uintptr_t addr_last, 272506f38c66SRichard Henderson uintptr_t brk, bool keep) 272606f38c66SRichard Henderson { 272706f38c66SRichard Henderson uintptr_t brk_last = brk + 16 * MiB - 1; 272806f38c66SRichard Henderson 272906f38c66SRichard Henderson /* Do not map anything close to the host brk. */ 273006f38c66SRichard Henderson if (addr <= brk_last && brk <= addr_last) { 273106f38c66SRichard Henderson return 0; 273206f38c66SRichard Henderson } 273306f38c66SRichard Henderson return pgb_try_mmap(addr, addr_last, keep); 273406f38c66SRichard Henderson } 273506f38c66SRichard Henderson 273606f38c66SRichard Henderson /** 273706f38c66SRichard Henderson * pgb_try_mmap_set: 273806f38c66SRichard Henderson * @ga: set of guest addrs 273906f38c66SRichard Henderson * @base: guest_base 274006f38c66SRichard Henderson * @brk: host brk 274106f38c66SRichard Henderson * 274206f38c66SRichard Henderson * Return true if all @ga can be mapped by the host at @base. 274306f38c66SRichard Henderson * On success, retain the mapping at index 0 for reserved_va. 274406f38c66SRichard Henderson */ 274506f38c66SRichard Henderson 274606f38c66SRichard Henderson typedef struct PGBAddrs { 274706f38c66SRichard Henderson uintptr_t bounds[3][2]; /* start/last pairs */ 274806f38c66SRichard Henderson int nbounds; 274906f38c66SRichard Henderson } PGBAddrs; 275006f38c66SRichard Henderson 275106f38c66SRichard Henderson static bool pgb_try_mmap_set(const PGBAddrs *ga, uintptr_t base, uintptr_t brk) 275206f38c66SRichard Henderson { 275306f38c66SRichard Henderson for (int i = ga->nbounds - 1; i >= 0; --i) { 275406f38c66SRichard Henderson if (pgb_try_mmap_skip_brk(ga->bounds[i][0] + base, 275506f38c66SRichard Henderson ga->bounds[i][1] + base, 275606f38c66SRichard Henderson brk, i == 0 && reserved_va) <= 0) { 275706f38c66SRichard Henderson return false; 275806f38c66SRichard Henderson } 275906f38c66SRichard Henderson } 276006f38c66SRichard Henderson return true; 276106f38c66SRichard Henderson } 276206f38c66SRichard Henderson 276306f38c66SRichard Henderson /** 276406f38c66SRichard Henderson * pgb_addr_set: 276506f38c66SRichard Henderson * @ga: output set of guest addrs 276606f38c66SRichard Henderson * @guest_loaddr: guest image low address 276706f38c66SRichard Henderson * @guest_loaddr: guest image high address 276806f38c66SRichard Henderson * @identity: create for identity mapping 276906f38c66SRichard Henderson * 277006f38c66SRichard Henderson * Fill in @ga with the image, COMMPAGE and NULL page. 277106f38c66SRichard Henderson */ 277206f38c66SRichard Henderson static bool pgb_addr_set(PGBAddrs *ga, abi_ulong guest_loaddr, 277306f38c66SRichard Henderson abi_ulong guest_hiaddr, bool try_identity) 277406f38c66SRichard Henderson { 277506f38c66SRichard Henderson int n; 277606f38c66SRichard Henderson 277706f38c66SRichard Henderson /* 277806f38c66SRichard Henderson * With a low commpage, or a guest mapped very low, 277906f38c66SRichard Henderson * we may not be able to use the identity map. 278006f38c66SRichard Henderson */ 278106f38c66SRichard Henderson if (try_identity) { 278206f38c66SRichard Henderson if (LO_COMMPAGE != -1 && LO_COMMPAGE < mmap_min_addr) { 278306f38c66SRichard Henderson return false; 278406f38c66SRichard Henderson } 278506f38c66SRichard Henderson if (guest_loaddr != 0 && guest_loaddr < mmap_min_addr) { 278606f38c66SRichard Henderson return false; 278706f38c66SRichard Henderson } 278806f38c66SRichard Henderson } 278906f38c66SRichard Henderson 279006f38c66SRichard Henderson memset(ga, 0, sizeof(*ga)); 279106f38c66SRichard Henderson n = 0; 279206f38c66SRichard Henderson 279306f38c66SRichard Henderson if (reserved_va) { 279406f38c66SRichard Henderson ga->bounds[n][0] = try_identity ? mmap_min_addr : 0; 279506f38c66SRichard Henderson ga->bounds[n][1] = reserved_va; 279606f38c66SRichard Henderson n++; 279706f38c66SRichard Henderson /* LO_COMMPAGE and NULL handled by reserving from 0. */ 279806f38c66SRichard Henderson } else { 279906f38c66SRichard Henderson /* Add any LO_COMMPAGE or NULL page. */ 280006f38c66SRichard Henderson if (LO_COMMPAGE != -1) { 280106f38c66SRichard Henderson ga->bounds[n][0] = 0; 280206f38c66SRichard Henderson ga->bounds[n][1] = LO_COMMPAGE + TARGET_PAGE_SIZE - 1; 280306f38c66SRichard Henderson n++; 280406f38c66SRichard Henderson } else if (!try_identity) { 280506f38c66SRichard Henderson ga->bounds[n][0] = 0; 280606f38c66SRichard Henderson ga->bounds[n][1] = TARGET_PAGE_SIZE - 1; 280706f38c66SRichard Henderson n++; 280806f38c66SRichard Henderson } 280906f38c66SRichard Henderson 281006f38c66SRichard Henderson /* Add the guest image for ET_EXEC. */ 281106f38c66SRichard Henderson if (guest_loaddr) { 281206f38c66SRichard Henderson ga->bounds[n][0] = guest_loaddr; 281306f38c66SRichard Henderson ga->bounds[n][1] = guest_hiaddr; 281406f38c66SRichard Henderson n++; 281506f38c66SRichard Henderson } 281606f38c66SRichard Henderson } 281706f38c66SRichard Henderson 281806f38c66SRichard Henderson /* 281906f38c66SRichard Henderson * Temporarily disable 282006f38c66SRichard Henderson * "comparison is always false due to limited range of data type" 282106f38c66SRichard Henderson * due to comparison between unsigned and (possible) 0. 282206f38c66SRichard Henderson */ 282306f38c66SRichard Henderson #pragma GCC diagnostic push 282406f38c66SRichard Henderson #pragma GCC diagnostic ignored "-Wtype-limits" 282506f38c66SRichard Henderson 282606f38c66SRichard Henderson /* Add any HI_COMMPAGE not covered by reserved_va. */ 282706f38c66SRichard Henderson if (reserved_va < HI_COMMPAGE) { 282806f38c66SRichard Henderson ga->bounds[n][0] = HI_COMMPAGE & qemu_host_page_mask; 282906f38c66SRichard Henderson ga->bounds[n][1] = HI_COMMPAGE + TARGET_PAGE_SIZE - 1; 283006f38c66SRichard Henderson n++; 283106f38c66SRichard Henderson } 283206f38c66SRichard Henderson 283306f38c66SRichard Henderson #pragma GCC diagnostic pop 283406f38c66SRichard Henderson 283506f38c66SRichard Henderson ga->nbounds = n; 283606f38c66SRichard Henderson return true; 283706f38c66SRichard Henderson } 283806f38c66SRichard Henderson 2839ee947430SAlex Bennée static void pgb_fail_in_use(const char *image_name) 2840ee947430SAlex Bennée { 2841ee947430SAlex Bennée error_report("%s: requires virtual address space that is in use " 2842ee947430SAlex Bennée "(omit the -B option or choose a different value)", 2843ee947430SAlex Bennée image_name); 2844ee947430SAlex Bennée exit(EXIT_FAILURE); 2845ee947430SAlex Bennée } 2846ee947430SAlex Bennée 284706f38c66SRichard Henderson static void pgb_fixed(const char *image_name, uintptr_t guest_loaddr, 284806f38c66SRichard Henderson uintptr_t guest_hiaddr, uintptr_t align) 2849ee947430SAlex Bennée { 285006f38c66SRichard Henderson PGBAddrs ga; 285106f38c66SRichard Henderson uintptr_t brk = (uintptr_t)sbrk(0); 2852ee947430SAlex Bennée 2853ee947430SAlex Bennée if (!QEMU_IS_ALIGNED(guest_base, align)) { 28545ca870b9SRichard Henderson fprintf(stderr, "Requested guest base %p does not satisfy " 285506f38c66SRichard Henderson "host minimum alignment (0x%" PRIxPTR ")\n", 28565ca870b9SRichard Henderson (void *)guest_base, align); 2857ee947430SAlex Bennée exit(EXIT_FAILURE); 2858ee947430SAlex Bennée } 2859ee947430SAlex Bennée 286006f38c66SRichard Henderson if (!pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, !guest_base) 286106f38c66SRichard Henderson || !pgb_try_mmap_set(&ga, guest_base, brk)) { 2862ee947430SAlex Bennée pgb_fail_in_use(image_name); 2863ee947430SAlex Bennée } 2864ee947430SAlex Bennée } 2865ee947430SAlex Bennée 2866ad592e37SAlex Bennée /** 2867dd558855SRichard Henderson * pgb_find_fallback: 2868ad592e37SAlex Bennée * 2869dd558855SRichard Henderson * This is a fallback method for finding holes in the host address space 2870dd558855SRichard Henderson * if we don't have the benefit of being able to access /proc/self/map. 2871dd558855SRichard Henderson * It can potentially take a very long time as we can only dumbly iterate 2872dd558855SRichard Henderson * up the host address space seeing if the allocation would work. 2873ad592e37SAlex Bennée */ 2874dd558855SRichard Henderson static uintptr_t pgb_find_fallback(const PGBAddrs *ga, uintptr_t align, 2875dd558855SRichard Henderson uintptr_t brk) 2876ad592e37SAlex Bennée { 2877dd558855SRichard Henderson /* TODO: come up with a better estimate of how much to skip. */ 2878dd558855SRichard Henderson uintptr_t skip = sizeof(uintptr_t) == 4 ? MiB : GiB; 2879ad592e37SAlex Bennée 2880dd558855SRichard Henderson for (uintptr_t base = skip; ; base += skip) { 2881dd558855SRichard Henderson base = ROUND_UP(base, align); 2882dd558855SRichard Henderson if (pgb_try_mmap_set(ga, base, brk)) { 2883dd558855SRichard Henderson return base; 2884dd558855SRichard Henderson } 2885dd558855SRichard Henderson if (base >= -skip) { 2886dd558855SRichard Henderson return -1; 2887dd558855SRichard Henderson } 2888dd558855SRichard Henderson } 2889dd558855SRichard Henderson } 2890dd558855SRichard Henderson 2891dd558855SRichard Henderson static uintptr_t pgb_try_itree(const PGBAddrs *ga, uintptr_t base, 2892dd558855SRichard Henderson IntervalTreeRoot *root) 2893dd558855SRichard Henderson { 2894dd558855SRichard Henderson for (int i = ga->nbounds - 1; i >= 0; --i) { 2895dd558855SRichard Henderson uintptr_t s = base + ga->bounds[i][0]; 2896dd558855SRichard Henderson uintptr_t l = base + ga->bounds[i][1]; 2897dd558855SRichard Henderson IntervalTreeNode *n; 2898dd558855SRichard Henderson 2899dd558855SRichard Henderson if (l < s) { 2900dd558855SRichard Henderson /* Wraparound. Skip to advance S to mmap_min_addr. */ 2901dd558855SRichard Henderson return mmap_min_addr - s; 2902dd558855SRichard Henderson } 2903dd558855SRichard Henderson 2904dd558855SRichard Henderson n = interval_tree_iter_first(root, s, l); 2905dd558855SRichard Henderson if (n != NULL) { 2906dd558855SRichard Henderson /* Conflict. Skip to advance S to LAST + 1. */ 2907dd558855SRichard Henderson return n->last - s + 1; 2908dd558855SRichard Henderson } 2909dd558855SRichard Henderson } 2910dd558855SRichard Henderson return 0; /* success */ 2911dd558855SRichard Henderson } 2912dd558855SRichard Henderson 2913dd558855SRichard Henderson static uintptr_t pgb_find_itree(const PGBAddrs *ga, IntervalTreeRoot *root, 2914dd558855SRichard Henderson uintptr_t align, uintptr_t brk) 2915dd558855SRichard Henderson { 2916dd558855SRichard Henderson uintptr_t last = mmap_min_addr; 2917dd558855SRichard Henderson uintptr_t base, skip; 2918ad592e37SAlex Bennée 2919ad592e37SAlex Bennée while (true) { 2920dd558855SRichard Henderson base = ROUND_UP(last, align); 2921dd558855SRichard Henderson if (base < last) { 2922ad592e37SAlex Bennée return -1; 2923ad592e37SAlex Bennée } 2924dd558855SRichard Henderson 2925dd558855SRichard Henderson skip = pgb_try_itree(ga, base, root); 2926dd558855SRichard Henderson if (skip == 0) { 2927dd558855SRichard Henderson break; 29282667e069SAlex Bennée } 2929dd558855SRichard Henderson 2930dd558855SRichard Henderson last = base + skip; 2931dd558855SRichard Henderson if (last < base) { 2932dd558855SRichard Henderson return -1; 2933ad592e37SAlex Bennée } 2934ad592e37SAlex Bennée } 2935ad592e37SAlex Bennée 2936dd558855SRichard Henderson /* 2937dd558855SRichard Henderson * We've chosen 'base' based on holes in the interval tree, 2938dd558855SRichard Henderson * but we don't yet know if it is a valid host address. 2939dd558855SRichard Henderson * Because it is the first matching hole, if the host addresses 2940dd558855SRichard Henderson * are invalid we know there are no further matches. 2941dd558855SRichard Henderson */ 2942dd558855SRichard Henderson return pgb_try_mmap_set(ga, base, brk) ? base : -1; 2943dd558855SRichard Henderson } 2944dd558855SRichard Henderson 2945dd558855SRichard Henderson static void pgb_dynamic(const char *image_name, uintptr_t guest_loaddr, 2946dd558855SRichard Henderson uintptr_t guest_hiaddr, uintptr_t align) 2947ee947430SAlex Bennée { 2948dd558855SRichard Henderson IntervalTreeRoot *root; 2949dd558855SRichard Henderson uintptr_t brk, ret; 2950dd558855SRichard Henderson PGBAddrs ga; 2951ee947430SAlex Bennée 2952ee947430SAlex Bennée assert(QEMU_IS_ALIGNED(guest_loaddr, align)); 2953ee947430SAlex Bennée 2954dd558855SRichard Henderson /* Try the identity map first. */ 2955dd558855SRichard Henderson if (pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, true)) { 2956dd558855SRichard Henderson brk = (uintptr_t)sbrk(0); 2957dd558855SRichard Henderson if (pgb_try_mmap_set(&ga, 0, brk)) { 2958dd558855SRichard Henderson guest_base = 0; 2959dd558855SRichard Henderson return; 2960dd558855SRichard Henderson } 2961dd558855SRichard Henderson } 2962dd558855SRichard Henderson 2963dd558855SRichard Henderson /* 2964dd558855SRichard Henderson * Rebuild the address set for non-identity map. 2965dd558855SRichard Henderson * This differs in the mapping of the guest NULL page. 2966dd558855SRichard Henderson */ 2967dd558855SRichard Henderson pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, false); 2968dd558855SRichard Henderson 2969dd558855SRichard Henderson root = read_self_maps(); 2970ee947430SAlex Bennée 2971ee947430SAlex Bennée /* Read brk after we've read the maps, which will malloc. */ 2972ee947430SAlex Bennée brk = (uintptr_t)sbrk(0); 2973ee947430SAlex Bennée 2974dd558855SRichard Henderson if (!root) { 2975dd558855SRichard Henderson ret = pgb_find_fallback(&ga, align, brk); 2976ee947430SAlex Bennée } else { 2977ee947430SAlex Bennée /* 2978dd558855SRichard Henderson * Reserve the area close to the host brk. 2979dd558855SRichard Henderson * This will be freed with the rest of the tree. 2980ee947430SAlex Bennée */ 2981dd558855SRichard Henderson IntervalTreeNode *b = g_new0(IntervalTreeNode, 1); 2982dd558855SRichard Henderson b->start = brk; 2983dd558855SRichard Henderson b->last = brk + 16 * MiB - 1; 2984dd558855SRichard Henderson interval_tree_insert(b, root); 2985dd558855SRichard Henderson 2986dd558855SRichard Henderson ret = pgb_find_itree(&ga, root, align, brk); 2987dd558855SRichard Henderson free_self_maps(root); 2988ee947430SAlex Bennée } 2989ee947430SAlex Bennée 2990dd558855SRichard Henderson if (ret == -1) { 2991dd558855SRichard Henderson int w = TARGET_LONG_BITS / 4; 2992dd558855SRichard Henderson 2993dd558855SRichard Henderson error_report("%s: Unable to find a guest_base to satisfy all " 2994dd558855SRichard Henderson "guest address mapping requirements", image_name); 2995dd558855SRichard Henderson 2996dd558855SRichard Henderson for (int i = 0; i < ga.nbounds; ++i) { 2997dd558855SRichard Henderson error_printf(" %0*" PRIx64 "-%0*" PRIx64 "\n", 2998dd558855SRichard Henderson w, (uint64_t)ga.bounds[i][0], 2999dd558855SRichard Henderson w, (uint64_t)ga.bounds[i][1]); 3000dd558855SRichard Henderson } 3001ee947430SAlex Bennée exit(EXIT_FAILURE); 3002ee947430SAlex Bennée } 3003dd558855SRichard Henderson guest_base = ret; 3004ee947430SAlex Bennée } 3005ee947430SAlex Bennée 3006ee947430SAlex Bennée void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, 3007ee947430SAlex Bennée abi_ulong guest_hiaddr) 3008dce10401SMeador Inge { 300930ab9ef2SRichard Henderson /* In order to use host shmat, we must be able to honor SHMLBA. */ 3010ee947430SAlex Bennée uintptr_t align = MAX(SHMLBA, qemu_host_page_size); 3011dce10401SMeador Inge 30120c441aebSRichard Henderson /* Sanity check the guest binary. */ 30130c441aebSRichard Henderson if (reserved_va) { 30140c441aebSRichard Henderson if (guest_hiaddr > reserved_va) { 30150c441aebSRichard Henderson error_report("%s: requires more than reserved virtual " 30160c441aebSRichard Henderson "address space (0x%" PRIx64 " > 0x%lx)", 30170c441aebSRichard Henderson image_name, (uint64_t)guest_hiaddr, reserved_va); 30180c441aebSRichard Henderson exit(EXIT_FAILURE); 30190c441aebSRichard Henderson } 30200c441aebSRichard Henderson } else { 30210c441aebSRichard Henderson if (guest_hiaddr != (uintptr_t)guest_hiaddr) { 30220c441aebSRichard Henderson error_report("%s: requires more virtual address space " 30230c441aebSRichard Henderson "than the host can provide (0x%" PRIx64 ")", 30240c441aebSRichard Henderson image_name, (uint64_t)guest_hiaddr + 1); 30250c441aebSRichard Henderson exit(EXIT_FAILURE); 30260c441aebSRichard Henderson } 30270c441aebSRichard Henderson } 30280c441aebSRichard Henderson 3029ee947430SAlex Bennée if (have_guest_base) { 303006f38c66SRichard Henderson pgb_fixed(image_name, guest_loaddr, guest_hiaddr, align); 3031293f2060SLuke Shumaker } else { 3032dd558855SRichard Henderson pgb_dynamic(image_name, guest_loaddr, guest_hiaddr, align); 3033806d1021SMeador Inge } 3034806d1021SMeador Inge 3035ee947430SAlex Bennée /* Reserve and initialize the commpage. */ 3036ee947430SAlex Bennée if (!init_guest_commpage()) { 303706f38c66SRichard Henderson /* We have already probed for the commpage being free. */ 303806f38c66SRichard Henderson g_assert_not_reached(); 3039dce10401SMeador Inge } 3040dce10401SMeador Inge 3041ee947430SAlex Bennée assert(QEMU_IS_ALIGNED(guest_base, align)); 3042ee947430SAlex Bennée qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space " 3043ee947430SAlex Bennée "@ 0x%" PRIx64 "\n", (uint64_t)guest_base); 3044dce10401SMeador Inge } 3045dce10401SMeador Inge 304683f990ebSRichard Henderson enum { 304783f990ebSRichard Henderson /* The string "GNU\0" as a magic number. */ 304883f990ebSRichard Henderson GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16), 304983f990ebSRichard Henderson NOTE_DATA_SZ = 1 * KiB, 305083f990ebSRichard Henderson NOTE_NAME_SZ = 4, 305183f990ebSRichard Henderson ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8, 305283f990ebSRichard Henderson }; 305383f990ebSRichard Henderson 305483f990ebSRichard Henderson /* 305583f990ebSRichard Henderson * Process a single gnu_property entry. 305683f990ebSRichard Henderson * Return false for error. 305783f990ebSRichard Henderson */ 305883f990ebSRichard Henderson static bool parse_elf_property(const uint32_t *data, int *off, int datasz, 305983f990ebSRichard Henderson struct image_info *info, bool have_prev_type, 306083f990ebSRichard Henderson uint32_t *prev_type, Error **errp) 306183f990ebSRichard Henderson { 306283f990ebSRichard Henderson uint32_t pr_type, pr_datasz, step; 306383f990ebSRichard Henderson 306483f990ebSRichard Henderson if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) { 306583f990ebSRichard Henderson goto error_data; 306683f990ebSRichard Henderson } 306783f990ebSRichard Henderson datasz -= *off; 306883f990ebSRichard Henderson data += *off / sizeof(uint32_t); 306983f990ebSRichard Henderson 307083f990ebSRichard Henderson if (datasz < 2 * sizeof(uint32_t)) { 307183f990ebSRichard Henderson goto error_data; 307283f990ebSRichard Henderson } 307383f990ebSRichard Henderson pr_type = data[0]; 307483f990ebSRichard Henderson pr_datasz = data[1]; 307583f990ebSRichard Henderson data += 2; 307683f990ebSRichard Henderson datasz -= 2 * sizeof(uint32_t); 307783f990ebSRichard Henderson step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN); 307883f990ebSRichard Henderson if (step > datasz) { 307983f990ebSRichard Henderson goto error_data; 308083f990ebSRichard Henderson } 308183f990ebSRichard Henderson 308283f990ebSRichard Henderson /* Properties are supposed to be unique and sorted on pr_type. */ 308383f990ebSRichard Henderson if (have_prev_type && pr_type <= *prev_type) { 308483f990ebSRichard Henderson if (pr_type == *prev_type) { 308583f990ebSRichard Henderson error_setg(errp, "Duplicate property in PT_GNU_PROPERTY"); 308683f990ebSRichard Henderson } else { 308783f990ebSRichard Henderson error_setg(errp, "Unsorted property in PT_GNU_PROPERTY"); 308883f990ebSRichard Henderson } 308983f990ebSRichard Henderson return false; 309083f990ebSRichard Henderson } 309183f990ebSRichard Henderson *prev_type = pr_type; 309283f990ebSRichard Henderson 309383f990ebSRichard Henderson if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) { 309483f990ebSRichard Henderson return false; 309583f990ebSRichard Henderson } 309683f990ebSRichard Henderson 309783f990ebSRichard Henderson *off += 2 * sizeof(uint32_t) + step; 309883f990ebSRichard Henderson return true; 309983f990ebSRichard Henderson 310083f990ebSRichard Henderson error_data: 310183f990ebSRichard Henderson error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY"); 310283f990ebSRichard Henderson return false; 310383f990ebSRichard Henderson } 310483f990ebSRichard Henderson 310583f990ebSRichard Henderson /* Process NT_GNU_PROPERTY_TYPE_0. */ 31063bd02386SRichard Henderson static bool parse_elf_properties(const ImageSource *src, 310783f990ebSRichard Henderson struct image_info *info, 310883f990ebSRichard Henderson const struct elf_phdr *phdr, 310983f990ebSRichard Henderson Error **errp) 311083f990ebSRichard Henderson { 311183f990ebSRichard Henderson union { 311283f990ebSRichard Henderson struct elf_note nhdr; 311383f990ebSRichard Henderson uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)]; 311483f990ebSRichard Henderson } note; 311583f990ebSRichard Henderson 311683f990ebSRichard Henderson int n, off, datasz; 311783f990ebSRichard Henderson bool have_prev_type; 311883f990ebSRichard Henderson uint32_t prev_type; 311983f990ebSRichard Henderson 312083f990ebSRichard Henderson /* Unless the arch requires properties, ignore them. */ 312183f990ebSRichard Henderson if (!ARCH_USE_GNU_PROPERTY) { 312283f990ebSRichard Henderson return true; 312383f990ebSRichard Henderson } 312483f990ebSRichard Henderson 312583f990ebSRichard Henderson /* If the properties are crazy large, that's too bad. */ 312683f990ebSRichard Henderson n = phdr->p_filesz; 312783f990ebSRichard Henderson if (n > sizeof(note)) { 312883f990ebSRichard Henderson error_setg(errp, "PT_GNU_PROPERTY too large"); 312983f990ebSRichard Henderson return false; 313083f990ebSRichard Henderson } 313183f990ebSRichard Henderson if (n < sizeof(note.nhdr)) { 313283f990ebSRichard Henderson error_setg(errp, "PT_GNU_PROPERTY too small"); 313383f990ebSRichard Henderson return false; 313483f990ebSRichard Henderson } 313583f990ebSRichard Henderson 31363bd02386SRichard Henderson if (!imgsrc_read(¬e, phdr->p_offset, n, src, errp)) { 313783f990ebSRichard Henderson return false; 313883f990ebSRichard Henderson } 313983f990ebSRichard Henderson 314083f990ebSRichard Henderson /* 314183f990ebSRichard Henderson * The contents of a valid PT_GNU_PROPERTY is a sequence 314283f990ebSRichard Henderson * of uint32_t -- swap them all now. 314383f990ebSRichard Henderson */ 314483f990ebSRichard Henderson #ifdef BSWAP_NEEDED 314583f990ebSRichard Henderson for (int i = 0; i < n / 4; i++) { 314683f990ebSRichard Henderson bswap32s(note.data + i); 314783f990ebSRichard Henderson } 314883f990ebSRichard Henderson #endif 314983f990ebSRichard Henderson 315083f990ebSRichard Henderson /* 315183f990ebSRichard Henderson * Note that nhdr is 3 words, and that the "name" described by namesz 315283f990ebSRichard Henderson * immediately follows nhdr and is thus at the 4th word. Further, all 315383f990ebSRichard Henderson * of the inputs to the kernel's round_up are multiples of 4. 315483f990ebSRichard Henderson */ 315583f990ebSRichard Henderson if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 || 315683f990ebSRichard Henderson note.nhdr.n_namesz != NOTE_NAME_SZ || 315783f990ebSRichard Henderson note.data[3] != GNU0_MAGIC) { 315883f990ebSRichard Henderson error_setg(errp, "Invalid note in PT_GNU_PROPERTY"); 315983f990ebSRichard Henderson return false; 316083f990ebSRichard Henderson } 316183f990ebSRichard Henderson off = sizeof(note.nhdr) + NOTE_NAME_SZ; 316283f990ebSRichard Henderson 316383f990ebSRichard Henderson datasz = note.nhdr.n_descsz + off; 316483f990ebSRichard Henderson if (datasz > n) { 316583f990ebSRichard Henderson error_setg(errp, "Invalid note size in PT_GNU_PROPERTY"); 316683f990ebSRichard Henderson return false; 316783f990ebSRichard Henderson } 316883f990ebSRichard Henderson 316983f990ebSRichard Henderson have_prev_type = false; 317083f990ebSRichard Henderson prev_type = 0; 317183f990ebSRichard Henderson while (1) { 317283f990ebSRichard Henderson if (off == datasz) { 317383f990ebSRichard Henderson return true; /* end, exit ok */ 317483f990ebSRichard Henderson } 317583f990ebSRichard Henderson if (!parse_elf_property(note.data, &off, datasz, info, 317683f990ebSRichard Henderson have_prev_type, &prev_type, errp)) { 317783f990ebSRichard Henderson return false; 317883f990ebSRichard Henderson } 317983f990ebSRichard Henderson have_prev_type = true; 318083f990ebSRichard Henderson } 318183f990ebSRichard Henderson } 318283f990ebSRichard Henderson 31833bd02386SRichard Henderson /** 31843bd02386SRichard Henderson * load_elf_image: Load an ELF image into the address space. 31853bd02386SRichard Henderson * @image_name: the filename of the image, to use in error messages. 31863bd02386SRichard Henderson * @src: the ImageSource from which to read. 31873bd02386SRichard Henderson * @info: info collected from the loaded image. 31883bd02386SRichard Henderson * @ehdr: the ELF header, not yet bswapped. 31893bd02386SRichard Henderson * @pinterp_name: record any PT_INTERP string found. 31903bd02386SRichard Henderson * 31913bd02386SRichard Henderson * On return: @info values will be filled in, as necessary or available. 31923bd02386SRichard Henderson */ 319331e31b8aSbellard 31943bd02386SRichard Henderson static void load_elf_image(const char *image_name, const ImageSource *src, 319540d487eeSRichard Henderson struct image_info *info, struct elfhdr *ehdr, 31963bd02386SRichard Henderson char **pinterp_name) 319731e31b8aSbellard { 31983bd02386SRichard Henderson g_autofree struct elf_phdr *phdr = NULL; 31998e62a717SRichard Henderson abi_ulong load_addr, load_bias, loaddr, hiaddr, error; 32003bd02386SRichard Henderson int i, prot_exec; 3201c7f17e7bSRichard Henderson Error *err = NULL; 320231e31b8aSbellard 32033bd02386SRichard Henderson /* 32043bd02386SRichard Henderson * First of all, some simple consistency checks. 32053bd02386SRichard Henderson * Note that we rely on the bswapped ehdr staying in bprm_buf, 32063bd02386SRichard Henderson * for later use by load_elf_binary and create_elf_tables. 32073bd02386SRichard Henderson */ 32083bd02386SRichard Henderson if (!imgsrc_read(ehdr, 0, sizeof(*ehdr), src, &err)) { 32093bd02386SRichard Henderson goto exit_errmsg; 32103bd02386SRichard Henderson } 32118e62a717SRichard Henderson if (!elf_check_ident(ehdr)) { 3212c7f17e7bSRichard Henderson error_setg(&err, "Invalid ELF image for this architecture"); 32138e62a717SRichard Henderson goto exit_errmsg; 32148e62a717SRichard Henderson } 32158e62a717SRichard Henderson bswap_ehdr(ehdr); 32168e62a717SRichard Henderson if (!elf_check_ehdr(ehdr)) { 3217c7f17e7bSRichard Henderson error_setg(&err, "Invalid ELF image for this architecture"); 32188e62a717SRichard Henderson goto exit_errmsg; 321931e31b8aSbellard } 322031e31b8aSbellard 32213bd02386SRichard Henderson phdr = imgsrc_read_alloc(ehdr->e_phoff, 32223bd02386SRichard Henderson ehdr->e_phnum * sizeof(struct elf_phdr), 32233bd02386SRichard Henderson src, &err); 32243bd02386SRichard Henderson if (phdr == NULL) { 32253bd02386SRichard Henderson goto exit_errmsg; 322631e31b8aSbellard } 32278e62a717SRichard Henderson bswap_phdr(phdr, ehdr->e_phnum); 322809bfb054Sbellard 32291af02e83SMike Frysinger info->nsegs = 0; 32301af02e83SMike Frysinger info->pt_dynamic_addr = 0; 32311af02e83SMike Frysinger 323298c1076cSAlex Bennée mmap_lock(); 323398c1076cSAlex Bennée 32348a1a5274SRichard Henderson /* 32358a1a5274SRichard Henderson * Find the maximum size of the image and allocate an appropriate 32368a1a5274SRichard Henderson * amount of memory to handle that. Locate the interpreter, if any. 32378a1a5274SRichard Henderson */ 3238682674b8SRichard Henderson loaddr = -1, hiaddr = 0; 323933143c44SLaurent Vivier info->alignment = 0; 3240872f3d04SRichard Henderson info->exec_stack = EXSTACK_DEFAULT; 32418e62a717SRichard Henderson for (i = 0; i < ehdr->e_phnum; ++i) { 32424d9d535aSRichard Henderson struct elf_phdr *eppnt = phdr + i; 32434d9d535aSRichard Henderson if (eppnt->p_type == PT_LOAD) { 32444d9d535aSRichard Henderson abi_ulong a = eppnt->p_vaddr - eppnt->p_offset; 3245682674b8SRichard Henderson if (a < loaddr) { 3246682674b8SRichard Henderson loaddr = a; 3247682674b8SRichard Henderson } 3248a3a67f54SRichard Henderson a = eppnt->p_vaddr + eppnt->p_memsz - 1; 3249682674b8SRichard Henderson if (a > hiaddr) { 3250682674b8SRichard Henderson hiaddr = a; 3251682674b8SRichard Henderson } 32521af02e83SMike Frysinger ++info->nsegs; 32534d9d535aSRichard Henderson info->alignment |= eppnt->p_align; 32548a1a5274SRichard Henderson } else if (eppnt->p_type == PT_INTERP && pinterp_name) { 32558a1a5274SRichard Henderson g_autofree char *interp_name = NULL; 32568a1a5274SRichard Henderson 32578a1a5274SRichard Henderson if (*pinterp_name) { 3258c7f17e7bSRichard Henderson error_setg(&err, "Multiple PT_INTERP entries"); 32598a1a5274SRichard Henderson goto exit_errmsg; 32608a1a5274SRichard Henderson } 3261c7f17e7bSRichard Henderson 32623bd02386SRichard Henderson interp_name = imgsrc_read_alloc(eppnt->p_offset, eppnt->p_filesz, 32633bd02386SRichard Henderson src, &err); 32643bd02386SRichard Henderson if (interp_name == NULL) { 32653bd02386SRichard Henderson goto exit_errmsg; 32668a1a5274SRichard Henderson } 32678a1a5274SRichard Henderson if (interp_name[eppnt->p_filesz - 1] != 0) { 3268c7f17e7bSRichard Henderson error_setg(&err, "Invalid PT_INTERP entry"); 32698a1a5274SRichard Henderson goto exit_errmsg; 32708a1a5274SRichard Henderson } 32718a1a5274SRichard Henderson *pinterp_name = g_steal_pointer(&interp_name); 327283f990ebSRichard Henderson } else if (eppnt->p_type == PT_GNU_PROPERTY) { 32733bd02386SRichard Henderson if (!parse_elf_properties(src, info, eppnt, &err)) { 327483f990ebSRichard Henderson goto exit_errmsg; 327583f990ebSRichard Henderson } 3276872f3d04SRichard Henderson } else if (eppnt->p_type == PT_GNU_STACK) { 3277872f3d04SRichard Henderson info->exec_stack = eppnt->p_flags & PF_X; 3278682674b8SRichard Henderson } 3279682674b8SRichard Henderson } 3280682674b8SRichard Henderson 32811ea06dedSRichard Henderson load_addr = loaddr; 32821ea06dedSRichard Henderson 32836fd59449SRichard Henderson if (pinterp_name != NULL) { 32846fd59449SRichard Henderson if (ehdr->e_type == ET_EXEC) { 32856fd59449SRichard Henderson /* 32866fd59449SRichard Henderson * Make sure that the low address does not conflict with 32876fd59449SRichard Henderson * MMAP_MIN_ADDR or the QEMU application itself. 32886fd59449SRichard Henderson */ 32896fd59449SRichard Henderson probe_guest_base(image_name, loaddr, hiaddr); 3290ee947430SAlex Bennée } else { 32911ea06dedSRichard Henderson abi_ulong align; 32921ea06dedSRichard Henderson 3293ee947430SAlex Bennée /* 3294ee947430SAlex Bennée * The binary is dynamic, but we still need to 3295ee947430SAlex Bennée * select guest_base. In this case we pass a size. 3296ee947430SAlex Bennée */ 3297ee947430SAlex Bennée probe_guest_base(image_name, 0, hiaddr - loaddr); 32981ea06dedSRichard Henderson 32991ea06dedSRichard Henderson /* 33001ea06dedSRichard Henderson * Avoid collision with the loader by providing a different 33011ea06dedSRichard Henderson * default load address. 33021ea06dedSRichard Henderson */ 33031ea06dedSRichard Henderson load_addr += elf_et_dyn_base; 33041ea06dedSRichard Henderson 33051ea06dedSRichard Henderson /* 33061ea06dedSRichard Henderson * TODO: Better support for mmap alignment is desirable. 33071ea06dedSRichard Henderson * Since we do not have complete control over the guest 33081ea06dedSRichard Henderson * address space, we prefer the kernel to choose some address 33091ea06dedSRichard Henderson * rather than force the use of LOAD_ADDR via MAP_FIXED. 33101ea06dedSRichard Henderson * But without MAP_FIXED we cannot guarantee alignment, 33111ea06dedSRichard Henderson * only suggest it. 33121ea06dedSRichard Henderson */ 33131ea06dedSRichard Henderson align = pow2ceil(info->alignment); 33141ea06dedSRichard Henderson if (align) { 33151ea06dedSRichard Henderson load_addr &= -align; 33161ea06dedSRichard Henderson } 33176fd59449SRichard Henderson } 33186fd59449SRichard Henderson } 33196fd59449SRichard Henderson 33206fd59449SRichard Henderson /* 33216fd59449SRichard Henderson * Reserve address space for all of this. 33226fd59449SRichard Henderson * 3323ad25051bSRichard Henderson * In the case of ET_EXEC, we supply MAP_FIXED_NOREPLACE so that we get 3324ad25051bSRichard Henderson * exactly the address range that is required. Without reserved_va, 3325ad25051bSRichard Henderson * the guest address space is not isolated. We have attempted to avoid 3326ad25051bSRichard Henderson * conflict with the host program itself via probe_guest_base, but using 3327ad25051bSRichard Henderson * MAP_FIXED_NOREPLACE instead of MAP_FIXED provides an extra check. 33286fd59449SRichard Henderson * 33296fd59449SRichard Henderson * Otherwise this is ET_DYN, and we are searching for a location 33306fd59449SRichard Henderson * that can hold the memory space required. If the image is 33311ea06dedSRichard Henderson * pre-linked, LOAD_ADDR will be non-zero, and the kernel should 33326fd59449SRichard Henderson * honor that address if it happens to be free. 33336fd59449SRichard Henderson * 33346fd59449SRichard Henderson * In both cases, we will overwrite pages in this range with mappings 33356fd59449SRichard Henderson * from the executable. 33366fd59449SRichard Henderson */ 33371ea06dedSRichard Henderson load_addr = target_mmap(load_addr, (size_t)hiaddr - loaddr + 1, PROT_NONE, 33386fd59449SRichard Henderson MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | 3339ad25051bSRichard Henderson (ehdr->e_type == ET_EXEC ? MAP_FIXED_NOREPLACE : 0), 334009bfb054Sbellard -1, 0); 3341682674b8SRichard Henderson if (load_addr == -1) { 3342c7f17e7bSRichard Henderson goto exit_mmap; 334309bfb054Sbellard } 3344682674b8SRichard Henderson load_bias = load_addr - loaddr; 334509bfb054Sbellard 3346a99856cdSChristophe Lyon if (elf_is_fdpic(ehdr)) { 33471af02e83SMike Frysinger struct elf32_fdpic_loadseg *loadsegs = info->loadsegs = 33487267c094SAnthony Liguori g_malloc(sizeof(*loadsegs) * info->nsegs); 33491af02e83SMike Frysinger 33501af02e83SMike Frysinger for (i = 0; i < ehdr->e_phnum; ++i) { 33511af02e83SMike Frysinger switch (phdr[i].p_type) { 33521af02e83SMike Frysinger case PT_DYNAMIC: 33531af02e83SMike Frysinger info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias; 33541af02e83SMike Frysinger break; 33551af02e83SMike Frysinger case PT_LOAD: 33561af02e83SMike Frysinger loadsegs->addr = phdr[i].p_vaddr + load_bias; 33571af02e83SMike Frysinger loadsegs->p_vaddr = phdr[i].p_vaddr; 33581af02e83SMike Frysinger loadsegs->p_memsz = phdr[i].p_memsz; 33591af02e83SMike Frysinger ++loadsegs; 33601af02e83SMike Frysinger break; 33611af02e83SMike Frysinger } 33621af02e83SMike Frysinger } 33631af02e83SMike Frysinger } 33641af02e83SMike Frysinger 33658e62a717SRichard Henderson info->load_bias = load_bias; 3366dc12567aSJosh Kunz info->code_offset = load_bias; 3367dc12567aSJosh Kunz info->data_offset = load_bias; 33688e62a717SRichard Henderson info->load_addr = load_addr; 33698e62a717SRichard Henderson info->entry = ehdr->e_entry + load_bias; 33708e62a717SRichard Henderson info->start_code = -1; 33718e62a717SRichard Henderson info->end_code = 0; 33728e62a717SRichard Henderson info->start_data = -1; 33738e62a717SRichard Henderson info->end_data = 0; 33741f356e8cSHelge Deller /* Usual start for brk is after all sections of the main executable. */ 3375aec338d6SRichard Henderson info->brk = TARGET_PAGE_ALIGN(hiaddr + load_bias); 3376d8fd2954SPaul Brook info->elf_flags = ehdr->e_flags; 33778e62a717SRichard Henderson 3378e8384b37SRichard Henderson prot_exec = PROT_EXEC; 3379e8384b37SRichard Henderson #ifdef TARGET_AARCH64 3380e8384b37SRichard Henderson /* 3381e8384b37SRichard Henderson * If the BTI feature is present, this indicates that the executable 3382e8384b37SRichard Henderson * pages of the startup binary should be mapped with PROT_BTI, so that 3383e8384b37SRichard Henderson * branch targets are enforced. 3384e8384b37SRichard Henderson * 3385e8384b37SRichard Henderson * The startup binary is either the interpreter or the static executable. 3386e8384b37SRichard Henderson * The interpreter is responsible for all pages of a dynamic executable. 3387e8384b37SRichard Henderson * 3388e8384b37SRichard Henderson * Elf notes are backward compatible to older cpus. 3389e8384b37SRichard Henderson * Do not enable BTI unless it is supported. 3390e8384b37SRichard Henderson */ 3391e8384b37SRichard Henderson if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) 3392e8384b37SRichard Henderson && (pinterp_name == NULL || *pinterp_name == 0) 3393e8384b37SRichard Henderson && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) { 3394e8384b37SRichard Henderson prot_exec |= TARGET_PROT_BTI; 3395e8384b37SRichard Henderson } 3396e8384b37SRichard Henderson #endif 3397e8384b37SRichard Henderson 33988e62a717SRichard Henderson for (i = 0; i < ehdr->e_phnum; i++) { 33998e62a717SRichard Henderson struct elf_phdr *eppnt = phdr + i; 340031e31b8aSbellard if (eppnt->p_type == PT_LOAD) { 34015f4e5b34SRichard Henderson abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em; 340231e31b8aSbellard int elf_prot = 0; 340331e31b8aSbellard 3404e5eaf570SRichard Henderson if (eppnt->p_flags & PF_R) { 3405e5eaf570SRichard Henderson elf_prot |= PROT_READ; 3406e5eaf570SRichard Henderson } 3407e5eaf570SRichard Henderson if (eppnt->p_flags & PF_W) { 3408e5eaf570SRichard Henderson elf_prot |= PROT_WRITE; 3409e5eaf570SRichard Henderson } 3410e5eaf570SRichard Henderson if (eppnt->p_flags & PF_X) { 3411e8384b37SRichard Henderson elf_prot |= prot_exec; 3412e5eaf570SRichard Henderson } 341331e31b8aSbellard 3414682674b8SRichard Henderson vaddr = load_bias + eppnt->p_vaddr; 3415e3d97d5cSRichard Henderson vaddr_po = vaddr & ~TARGET_PAGE_MASK; 3416e3d97d5cSRichard Henderson vaddr_ps = vaddr & TARGET_PAGE_MASK; 341722d113b5SGiuseppe Musacchio 341822d113b5SGiuseppe Musacchio vaddr_ef = vaddr + eppnt->p_filesz; 341922d113b5SGiuseppe Musacchio vaddr_em = vaddr + eppnt->p_memsz; 3420682674b8SRichard Henderson 3421d87146bcSGiuseppe Musacchio /* 342222d113b5SGiuseppe Musacchio * Some segments may be completely empty, with a non-zero p_memsz 342322d113b5SGiuseppe Musacchio * but no backing file segment. 3424d87146bcSGiuseppe Musacchio */ 3425d87146bcSGiuseppe Musacchio if (eppnt->p_filesz != 0) { 34263bd02386SRichard Henderson error = imgsrc_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po, 34275f4e5b34SRichard Henderson elf_prot, MAP_PRIVATE | MAP_FIXED, 34283bd02386SRichard Henderson src, eppnt->p_offset - vaddr_po); 3429e89f07d3Spbrook if (error == -1) { 3430c7f17e7bSRichard Henderson goto exit_mmap; 343131e31b8aSbellard } 34325f4e5b34SRichard Henderson } 343331e31b8aSbellard 34345f4e5b34SRichard Henderson /* If the load segment requests extra zeros (e.g. bss), map it. */ 34355f4e5b34SRichard Henderson if (vaddr_ef < vaddr_em && 3436e6e66b03SRichard Henderson !zero_bss(vaddr_ef, vaddr_em, elf_prot, &err)) { 3437e6e66b03SRichard Henderson goto exit_errmsg; 3438682674b8SRichard Henderson } 34398e62a717SRichard Henderson 34408e62a717SRichard Henderson /* Find the full program boundaries. */ 34418e62a717SRichard Henderson if (elf_prot & PROT_EXEC) { 34428e62a717SRichard Henderson if (vaddr < info->start_code) { 34438e62a717SRichard Henderson info->start_code = vaddr; 3444cf129f3aSRichard Henderson } 34458e62a717SRichard Henderson if (vaddr_ef > info->end_code) { 34468e62a717SRichard Henderson info->end_code = vaddr_ef; 34478e62a717SRichard Henderson } 34488e62a717SRichard Henderson } 34498e62a717SRichard Henderson if (elf_prot & PROT_WRITE) { 34508e62a717SRichard Henderson if (vaddr < info->start_data) { 34518e62a717SRichard Henderson info->start_data = vaddr; 34528e62a717SRichard Henderson } 34538e62a717SRichard Henderson if (vaddr_ef > info->end_data) { 34548e62a717SRichard Henderson info->end_data = vaddr_ef; 34558e62a717SRichard Henderson } 34568a045188STimothy E Baldwin } 34575dd0db52SStefan Markovic #ifdef TARGET_MIPS 34585dd0db52SStefan Markovic } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) { 34595dd0db52SStefan Markovic Mips_elf_abiflags_v0 abiflags; 34603bd02386SRichard Henderson 34613bd02386SRichard Henderson if (!imgsrc_read(&abiflags, eppnt->p_offset, sizeof(abiflags), 34623bd02386SRichard Henderson src, &err)) { 34635dd0db52SStefan Markovic goto exit_errmsg; 34645dd0db52SStefan Markovic } 34655dd0db52SStefan Markovic bswap_mips_abiflags(&abiflags); 3466c94cb6c9SStefan Markovic info->fp_abi = abiflags.fp_abi; 34675dd0db52SStefan Markovic #endif 34688e62a717SRichard Henderson } 34698e62a717SRichard Henderson } 34708e62a717SRichard Henderson 34718e62a717SRichard Henderson if (info->end_data == 0) { 34728e62a717SRichard Henderson info->start_data = info->end_code; 34738e62a717SRichard Henderson info->end_data = info->end_code; 347431e31b8aSbellard } 347531e31b8aSbellard 3476682674b8SRichard Henderson if (qemu_log_enabled()) { 3477*86cf82dcSRichard Henderson load_symbols(ehdr, src, load_bias); 3478682674b8SRichard Henderson } 347931e31b8aSbellard 34803bd02386SRichard Henderson debuginfo_report_elf(image_name, src->fd, load_bias); 34817c10cb38SIlya Leoshkevich 348298c1076cSAlex Bennée mmap_unlock(); 348398c1076cSAlex Bennée 34843bd02386SRichard Henderson close(src->fd); 34858e62a717SRichard Henderson return; 348631e31b8aSbellard 3487c7f17e7bSRichard Henderson exit_mmap: 3488c7f17e7bSRichard Henderson error_setg_errno(&err, errno, "Error mapping file"); 3489c7f17e7bSRichard Henderson goto exit_errmsg; 34908e62a717SRichard Henderson exit_errmsg: 3491c7f17e7bSRichard Henderson error_reportf_err(err, "%s: ", image_name); 34928e62a717SRichard Henderson exit(-1); 34938e62a717SRichard Henderson } 34948e62a717SRichard Henderson 34958e62a717SRichard Henderson static void load_elf_interp(const char *filename, struct image_info *info, 34968e62a717SRichard Henderson char bprm_buf[BPRM_BUF_SIZE]) 34978e62a717SRichard Henderson { 349840d487eeSRichard Henderson struct elfhdr ehdr; 34993bd02386SRichard Henderson ImageSource src; 35008e62a717SRichard Henderson int fd, retval; 3501808f6563SRichard Henderson Error *err = NULL; 35028e62a717SRichard Henderson 35038e62a717SRichard Henderson fd = open(path(filename), O_RDONLY); 35048e62a717SRichard Henderson if (fd < 0) { 3505808f6563SRichard Henderson error_setg_file_open(&err, errno, filename); 3506808f6563SRichard Henderson error_report_err(err); 3507808f6563SRichard Henderson exit(-1); 35088e62a717SRichard Henderson } 35098e62a717SRichard Henderson 35108e62a717SRichard Henderson retval = read(fd, bprm_buf, BPRM_BUF_SIZE); 35118e62a717SRichard Henderson if (retval < 0) { 3512808f6563SRichard Henderson error_setg_errno(&err, errno, "Error reading file header"); 3513808f6563SRichard Henderson error_reportf_err(err, "%s: ", filename); 3514808f6563SRichard Henderson exit(-1); 35158e62a717SRichard Henderson } 3516808f6563SRichard Henderson 35173bd02386SRichard Henderson src.fd = fd; 35183bd02386SRichard Henderson src.cache = bprm_buf; 35193bd02386SRichard Henderson src.cache_size = retval; 35208e62a717SRichard Henderson 35213bd02386SRichard Henderson load_elf_image(filename, &src, info, &ehdr, NULL); 352231e31b8aSbellard } 352331e31b8aSbellard 352449918a75Spbrook static int symfind(const void *s0, const void *s1) 352549918a75Spbrook { 352649918a75Spbrook struct elf_sym *sym = (struct elf_sym *)s1; 3527b6235a75SRichard Henderson __typeof(sym->st_value) addr = *(uint64_t *)s0; 352849918a75Spbrook int result = 0; 3529b6235a75SRichard Henderson 3530c7c530cdSStefan Weil if (addr < sym->st_value) { 353149918a75Spbrook result = -1; 3532c7c530cdSStefan Weil } else if (addr >= sym->st_value + sym->st_size) { 353349918a75Spbrook result = 1; 353449918a75Spbrook } 353549918a75Spbrook return result; 353649918a75Spbrook } 353749918a75Spbrook 3538b6235a75SRichard Henderson static const char *lookup_symbolxx(struct syminfo *s, uint64_t orig_addr) 353949918a75Spbrook { 354049918a75Spbrook #if ELF_CLASS == ELFCLASS32 354149918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf32; 354249918a75Spbrook #else 354349918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf64; 354449918a75Spbrook #endif 354549918a75Spbrook 354649918a75Spbrook // binary search 354749918a75Spbrook struct elf_sym *sym; 354849918a75Spbrook 3549c7c530cdSStefan Weil sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind); 35507cba04f6SBlue Swirl if (sym != NULL) { 355149918a75Spbrook return s->disas_strtab + sym->st_name; 355249918a75Spbrook } 355349918a75Spbrook 355449918a75Spbrook return ""; 355549918a75Spbrook } 355649918a75Spbrook 355749918a75Spbrook /* FIXME: This should use elf_ops.h */ 355849918a75Spbrook static int symcmp(const void *s0, const void *s1) 355949918a75Spbrook { 356049918a75Spbrook struct elf_sym *sym0 = (struct elf_sym *)s0; 356149918a75Spbrook struct elf_sym *sym1 = (struct elf_sym *)s1; 356249918a75Spbrook return (sym0->st_value < sym1->st_value) 356349918a75Spbrook ? -1 356449918a75Spbrook : ((sym0->st_value > sym1->st_value) ? 1 : 0); 356549918a75Spbrook } 356649918a75Spbrook 3567689f936fSbellard /* Best attempt to load symbols from this ELF object. */ 3568*86cf82dcSRichard Henderson static void load_symbols(struct elfhdr *hdr, const ImageSource *src, 3569*86cf82dcSRichard Henderson abi_ulong load_bias) 3570689f936fSbellard { 3571682674b8SRichard Henderson int i, shnum, nsyms, sym_idx = 0, str_idx = 0; 3572*86cf82dcSRichard Henderson g_autofree struct elf_shdr *shdr = NULL; 3573b9475279SCédric VINCENT char *strings = NULL; 3574*86cf82dcSRichard Henderson struct elf_sym *syms = NULL; 3575*86cf82dcSRichard Henderson struct elf_sym *new_syms; 3576*86cf82dcSRichard Henderson uint64_t segsz; 357731e31b8aSbellard 3578682674b8SRichard Henderson shnum = hdr->e_shnum; 3579*86cf82dcSRichard Henderson shdr = imgsrc_read_alloc(hdr->e_shoff, shnum * sizeof(struct elf_shdr), 3580*86cf82dcSRichard Henderson src, NULL); 3581*86cf82dcSRichard Henderson if (shdr == NULL) { 3582689f936fSbellard return; 3583682674b8SRichard Henderson } 3584682674b8SRichard Henderson 3585682674b8SRichard Henderson bswap_shdr(shdr, shnum); 3586682674b8SRichard Henderson for (i = 0; i < shnum; ++i) { 3587682674b8SRichard Henderson if (shdr[i].sh_type == SHT_SYMTAB) { 3588682674b8SRichard Henderson sym_idx = i; 3589682674b8SRichard Henderson str_idx = shdr[i].sh_link; 3590689f936fSbellard goto found; 3591689f936fSbellard } 3592689f936fSbellard } 3593682674b8SRichard Henderson 3594682674b8SRichard Henderson /* There will be no symbol table if the file was stripped. */ 3595682674b8SRichard Henderson return; 3596689f936fSbellard 3597689f936fSbellard found: 3598689f936fSbellard /* Now know where the strtab and symtab are. Snarf them. */ 3599682674b8SRichard Henderson 36001e06262dSPeter Maydell segsz = shdr[str_idx].sh_size; 3601*86cf82dcSRichard Henderson strings = g_try_malloc(segsz); 3602*86cf82dcSRichard Henderson if (!strings) { 3603*86cf82dcSRichard Henderson goto give_up; 3604*86cf82dcSRichard Henderson } 3605*86cf82dcSRichard Henderson if (!imgsrc_read(strings, shdr[str_idx].sh_offset, segsz, src, NULL)) { 3606b9475279SCédric VINCENT goto give_up; 3607682674b8SRichard Henderson } 3608689f936fSbellard 36091e06262dSPeter Maydell segsz = shdr[sym_idx].sh_size; 36101e06262dSPeter Maydell if (segsz / sizeof(struct elf_sym) > INT_MAX) { 3611*86cf82dcSRichard Henderson /* 3612*86cf82dcSRichard Henderson * Implausibly large symbol table: give up rather than ploughing 3613*86cf82dcSRichard Henderson * on with the number of symbols calculation overflowing. 36141e06262dSPeter Maydell */ 36151e06262dSPeter Maydell goto give_up; 36161e06262dSPeter Maydell } 36171e06262dSPeter Maydell nsyms = segsz / sizeof(struct elf_sym); 3618*86cf82dcSRichard Henderson syms = g_try_malloc(segsz); 3619*86cf82dcSRichard Henderson if (!syms) { 3620*86cf82dcSRichard Henderson goto give_up; 3621*86cf82dcSRichard Henderson } 3622*86cf82dcSRichard Henderson if (!imgsrc_read(syms, shdr[sym_idx].sh_offset, segsz, src, NULL)) { 3623*86cf82dcSRichard Henderson goto give_up; 3624*86cf82dcSRichard Henderson } 3625*86cf82dcSRichard Henderson 3626682674b8SRichard Henderson for (i = 0; i < nsyms; ) { 362749918a75Spbrook bswap_sym(syms + i); 3628682674b8SRichard Henderson /* Throw away entries which we do not need. */ 3629682674b8SRichard Henderson if (syms[i].st_shndx == SHN_UNDEF 3630682674b8SRichard Henderson || syms[i].st_shndx >= SHN_LORESERVE 3631682674b8SRichard Henderson || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 3632682674b8SRichard Henderson if (i < --nsyms) { 363349918a75Spbrook syms[i] = syms[nsyms]; 363449918a75Spbrook } 3635682674b8SRichard Henderson } else { 363649918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS) 363749918a75Spbrook /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 363849918a75Spbrook syms[i].st_value &= ~(target_ulong)1; 363949918a75Spbrook #endif 3640682674b8SRichard Henderson syms[i].st_value += load_bias; 364149918a75Spbrook i++; 364249918a75Spbrook } 3643682674b8SRichard Henderson } 364449918a75Spbrook 3645b9475279SCédric VINCENT /* No "useful" symbol. */ 3646b9475279SCédric VINCENT if (nsyms == 0) { 3647b9475279SCédric VINCENT goto give_up; 3648b9475279SCédric VINCENT } 3649b9475279SCédric VINCENT 3650*86cf82dcSRichard Henderson /* 3651*86cf82dcSRichard Henderson * Attempt to free the storage associated with the local symbols 3652*86cf82dcSRichard Henderson * that we threw away. Whether or not this has any effect on the 3653*86cf82dcSRichard Henderson * memory allocation depends on the malloc implementation and how 3654*86cf82dcSRichard Henderson * many symbols we managed to discard. 3655*86cf82dcSRichard Henderson */ 36560ef9ea29SPeter Maydell new_syms = g_try_renew(struct elf_sym, syms, nsyms); 36578d79de6eSStefan Weil if (new_syms == NULL) { 3658b9475279SCédric VINCENT goto give_up; 36595d5c9930SRichard Henderson } 36608d79de6eSStefan Weil syms = new_syms; 36615d5c9930SRichard Henderson 366249918a75Spbrook qsort(syms, nsyms, sizeof(*syms), symcmp); 366349918a75Spbrook 3664*86cf82dcSRichard Henderson { 3665*86cf82dcSRichard Henderson struct syminfo *s = g_new(struct syminfo, 1); 3666*86cf82dcSRichard Henderson 3667*86cf82dcSRichard Henderson s->disas_strtab = strings; 366849918a75Spbrook s->disas_num_syms = nsyms; 366949918a75Spbrook #if ELF_CLASS == ELFCLASS32 367049918a75Spbrook s->disas_symtab.elf32 = syms; 367149918a75Spbrook #else 367249918a75Spbrook s->disas_symtab.elf64 = syms; 367349918a75Spbrook #endif 3674682674b8SRichard Henderson s->lookup_symbol = lookup_symbolxx; 3675e80cfcfcSbellard s->next = syminfos; 3676e80cfcfcSbellard syminfos = s; 3677*86cf82dcSRichard Henderson } 3678b9475279SCédric VINCENT return; 3679b9475279SCédric VINCENT 3680b9475279SCédric VINCENT give_up: 36810ef9ea29SPeter Maydell g_free(strings); 36820ef9ea29SPeter Maydell g_free(syms); 3683689f936fSbellard } 368431e31b8aSbellard 3685768fe76eSYunQiang Su uint32_t get_elf_eflags(int fd) 3686768fe76eSYunQiang Su { 3687768fe76eSYunQiang Su struct elfhdr ehdr; 3688768fe76eSYunQiang Su off_t offset; 3689768fe76eSYunQiang Su int ret; 3690768fe76eSYunQiang Su 3691768fe76eSYunQiang Su /* Read ELF header */ 3692768fe76eSYunQiang Su offset = lseek(fd, 0, SEEK_SET); 3693768fe76eSYunQiang Su if (offset == (off_t) -1) { 3694768fe76eSYunQiang Su return 0; 3695768fe76eSYunQiang Su } 3696768fe76eSYunQiang Su ret = read(fd, &ehdr, sizeof(ehdr)); 3697768fe76eSYunQiang Su if (ret < sizeof(ehdr)) { 3698768fe76eSYunQiang Su return 0; 3699768fe76eSYunQiang Su } 3700768fe76eSYunQiang Su offset = lseek(fd, offset, SEEK_SET); 3701768fe76eSYunQiang Su if (offset == (off_t) -1) { 3702768fe76eSYunQiang Su return 0; 3703768fe76eSYunQiang Su } 3704768fe76eSYunQiang Su 3705768fe76eSYunQiang Su /* Check ELF signature */ 3706768fe76eSYunQiang Su if (!elf_check_ident(&ehdr)) { 3707768fe76eSYunQiang Su return 0; 3708768fe76eSYunQiang Su } 3709768fe76eSYunQiang Su 3710768fe76eSYunQiang Su /* check header */ 3711768fe76eSYunQiang Su bswap_ehdr(&ehdr); 3712768fe76eSYunQiang Su if (!elf_check_ehdr(&ehdr)) { 3713768fe76eSYunQiang Su return 0; 3714768fe76eSYunQiang Su } 3715768fe76eSYunQiang Su 3716768fe76eSYunQiang Su /* return architecture id */ 3717768fe76eSYunQiang Su return ehdr.e_flags; 3718768fe76eSYunQiang Su } 3719768fe76eSYunQiang Su 3720f0116c54SWill Newton int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) 372131e31b8aSbellard { 372240d487eeSRichard Henderson /* 372340d487eeSRichard Henderson * We need a copy of the elf header for passing to create_elf_tables. 372440d487eeSRichard Henderson * We will have overwritten the original when we re-use bprm->buf 372540d487eeSRichard Henderson * while loading the interpreter. Allocate the storage for this now 372640d487eeSRichard Henderson * and let elf_load_image do any swapping that may be required. 372740d487eeSRichard Henderson */ 372840d487eeSRichard Henderson struct elfhdr ehdr; 37298e62a717SRichard Henderson struct image_info interp_info; 37308e62a717SRichard Henderson char *elf_interpreter = NULL; 373159baae9aSStefan Brüns char *scratch; 373231e31b8aSbellard 3733abcac736SDaniel Santos memset(&interp_info, 0, sizeof(interp_info)); 3734abcac736SDaniel Santos #ifdef TARGET_MIPS 3735abcac736SDaniel Santos interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN; 3736abcac736SDaniel Santos #endif 3737abcac736SDaniel Santos 37383bd02386SRichard Henderson load_elf_image(bprm->filename, &bprm->src, info, &ehdr, &elf_interpreter); 373931e31b8aSbellard 374059baae9aSStefan Brüns /* Do this so that we can load the interpreter, if need be. We will 374159baae9aSStefan Brüns change some of these later */ 374259baae9aSStefan Brüns bprm->p = setup_arg_pages(bprm, info); 374359baae9aSStefan Brüns 374459baae9aSStefan Brüns scratch = g_new0(char, TARGET_PAGE_SIZE); 37457c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 374659baae9aSStefan Brüns bprm->p = copy_elf_strings(1, &bprm->filename, scratch, 374759baae9aSStefan Brüns bprm->p, info->stack_limit); 37487c4ee5bcSRichard Henderson info->file_string = bprm->p; 374959baae9aSStefan Brüns bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch, 375059baae9aSStefan Brüns bprm->p, info->stack_limit); 37517c4ee5bcSRichard Henderson info->env_strings = bprm->p; 375259baae9aSStefan Brüns bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch, 375359baae9aSStefan Brüns bprm->p, info->stack_limit); 37547c4ee5bcSRichard Henderson info->arg_strings = bprm->p; 37557c4ee5bcSRichard Henderson } else { 37567c4ee5bcSRichard Henderson info->arg_strings = bprm->p; 37577c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch, 37587c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 37597c4ee5bcSRichard Henderson info->env_strings = bprm->p; 37607c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch, 37617c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 37627c4ee5bcSRichard Henderson info->file_string = bprm->p; 37637c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(1, &bprm->filename, scratch, 37647c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 37657c4ee5bcSRichard Henderson } 37667c4ee5bcSRichard Henderson 376759baae9aSStefan Brüns g_free(scratch); 376859baae9aSStefan Brüns 3769e5fe0c52Spbrook if (!bprm->p) { 3770bf858897SRichard Henderson fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG)); 377131e31b8aSbellard exit(-1); 37729955ffacSRichard Henderson } 3773379f6698SPaul Brook 37748e62a717SRichard Henderson if (elf_interpreter) { 37758e62a717SRichard Henderson load_elf_interp(elf_interpreter, &interp_info, bprm->buf); 377631e31b8aSbellard 37771f356e8cSHelge Deller /* 37781f356e8cSHelge Deller * While unusual because of ELF_ET_DYN_BASE, if we are unlucky 37791f356e8cSHelge Deller * with the mappings the interpreter can be loaded above but 37801f356e8cSHelge Deller * near the main executable, which can leave very little room 37811f356e8cSHelge Deller * for the heap. 37821f356e8cSHelge Deller * If the current brk has less than 16MB, use the end of the 37831f356e8cSHelge Deller * interpreter. 37841f356e8cSHelge Deller */ 37851f356e8cSHelge Deller if (interp_info.brk > info->brk && 37861f356e8cSHelge Deller interp_info.load_bias - info->brk < 16 * MiB) { 37871f356e8cSHelge Deller info->brk = interp_info.brk; 37881f356e8cSHelge Deller } 37891f356e8cSHelge Deller 37908e62a717SRichard Henderson /* If the program interpreter is one of these two, then assume 37918e62a717SRichard Henderson an iBCS2 image. Otherwise assume a native linux image. */ 379231e31b8aSbellard 37938e62a717SRichard Henderson if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0 37948e62a717SRichard Henderson || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) { 37958e62a717SRichard Henderson info->personality = PER_SVR4; 37968e62a717SRichard Henderson 379731e31b8aSbellard /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 37988e62a717SRichard Henderson and some applications "depend" upon this behavior. Since 37998e62a717SRichard Henderson we do not have the power to recompile these, we emulate 38008e62a717SRichard Henderson the SVr4 behavior. Sigh. */ 38018e62a717SRichard Henderson target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, 380268754b44SPeter Maydell MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 380331e31b8aSbellard } 3804c94cb6c9SStefan Markovic #ifdef TARGET_MIPS 3805c94cb6c9SStefan Markovic info->interp_fp_abi = interp_info.fp_abi; 3806c94cb6c9SStefan Markovic #endif 38078e62a717SRichard Henderson } 380831e31b8aSbellard 3809db2af69dSRichard Henderson /* 3810db2af69dSRichard Henderson * TODO: load a vdso, which would also contain the signal trampolines. 3811db2af69dSRichard Henderson * Otherwise, allocate a private page to hold them. 3812db2af69dSRichard Henderson */ 3813db2af69dSRichard Henderson if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) { 3814802ae45eSLaurent Vivier abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE, 3815db2af69dSRichard Henderson PROT_READ | PROT_WRITE, 3816db2af69dSRichard Henderson MAP_PRIVATE | MAP_ANON, -1, 0); 3817802ae45eSLaurent Vivier if (tramp_page == -1) { 3818802ae45eSLaurent Vivier return -errno; 3819802ae45eSLaurent Vivier } 3820802ae45eSLaurent Vivier 3821db2af69dSRichard Henderson setup_sigtramp(tramp_page); 3822db2af69dSRichard Henderson target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC); 3823db2af69dSRichard Henderson } 3824db2af69dSRichard Henderson 382540d487eeSRichard Henderson bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr, 38268e62a717SRichard Henderson info, (elf_interpreter ? &interp_info : NULL)); 38278e62a717SRichard Henderson info->start_stack = bprm->p; 38288e62a717SRichard Henderson 38298e62a717SRichard Henderson /* If we have an interpreter, set that as the program's entry point. 38308e78064eSRichard Henderson Copy the load_bias as well, to help PPC64 interpret the entry 38318e62a717SRichard Henderson point as a function descriptor. Do this after creating elf tables 38328e62a717SRichard Henderson so that we copy the original program entry point into the AUXV. */ 38338e62a717SRichard Henderson if (elf_interpreter) { 38348e78064eSRichard Henderson info->load_bias = interp_info.load_bias; 38358e62a717SRichard Henderson info->entry = interp_info.entry; 38362b323087SPhilippe Mathieu-Daudé g_free(elf_interpreter); 38378e62a717SRichard Henderson } 383831e31b8aSbellard 3839edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 3840edf8e2afSMika Westerberg bprm->core_dump = &elf_core_dump; 3841edf8e2afSMika Westerberg #endif 3842edf8e2afSMika Westerberg 384331e31b8aSbellard return 0; 384431e31b8aSbellard } 384531e31b8aSbellard 3846edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 3847edf8e2afSMika Westerberg /* 3848edf8e2afSMika Westerberg * Definitions to generate Intel SVR4-like core files. 3849a2547a13SLaurent Desnogues * These mostly have the same names as the SVR4 types with "target_elf_" 3850edf8e2afSMika Westerberg * tacked on the front to prevent clashes with linux definitions, 3851edf8e2afSMika Westerberg * and the typedef forms have been avoided. This is mostly like 3852edf8e2afSMika Westerberg * the SVR4 structure, but more Linuxy, with things that Linux does 3853edf8e2afSMika Westerberg * not support and which gdb doesn't really use excluded. 3854edf8e2afSMika Westerberg * 3855edf8e2afSMika Westerberg * Fields we don't dump (their contents is zero) in linux-user qemu 3856edf8e2afSMika Westerberg * are marked with XXX. 3857edf8e2afSMika Westerberg * 3858edf8e2afSMika Westerberg * Core dump code is copied from linux kernel (fs/binfmt_elf.c). 3859edf8e2afSMika Westerberg * 3860edf8e2afSMika Westerberg * Porting ELF coredump for target is (quite) simple process. First you 3861dd0a3651SNathan Froyd * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for 3862edf8e2afSMika Westerberg * the target resides): 3863edf8e2afSMika Westerberg * 3864edf8e2afSMika Westerberg * #define USE_ELF_CORE_DUMP 3865edf8e2afSMika Westerberg * 3866edf8e2afSMika Westerberg * Next you define type of register set used for dumping. ELF specification 3867edf8e2afSMika Westerberg * says that it needs to be array of elf_greg_t that has size of ELF_NREG. 3868edf8e2afSMika Westerberg * 3869c227f099SAnthony Liguori * typedef <target_regtype> target_elf_greg_t; 3870edf8e2afSMika Westerberg * #define ELF_NREG <number of registers> 3871c227f099SAnthony Liguori * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; 3872edf8e2afSMika Westerberg * 3873edf8e2afSMika Westerberg * Last step is to implement target specific function that copies registers 3874edf8e2afSMika Westerberg * from given cpu into just specified register set. Prototype is: 3875edf8e2afSMika Westerberg * 3876c227f099SAnthony Liguori * static void elf_core_copy_regs(taret_elf_gregset_t *regs, 38779349b4f9SAndreas Färber * const CPUArchState *env); 3878edf8e2afSMika Westerberg * 3879edf8e2afSMika Westerberg * Parameters: 3880edf8e2afSMika Westerberg * regs - copy register values into here (allocated and zeroed by caller) 3881edf8e2afSMika Westerberg * env - copy registers from here 3882edf8e2afSMika Westerberg * 3883edf8e2afSMika Westerberg * Example for ARM target is provided in this file. 3884edf8e2afSMika Westerberg */ 3885edf8e2afSMika Westerberg 3886edf8e2afSMika Westerberg /* An ELF note in memory */ 3887edf8e2afSMika Westerberg struct memelfnote { 3888edf8e2afSMika Westerberg const char *name; 3889edf8e2afSMika Westerberg size_t namesz; 3890edf8e2afSMika Westerberg size_t namesz_rounded; 3891edf8e2afSMika Westerberg int type; 3892edf8e2afSMika Westerberg size_t datasz; 389380f5ce75SLaurent Vivier size_t datasz_rounded; 3894edf8e2afSMika Westerberg void *data; 3895edf8e2afSMika Westerberg size_t notesz; 3896edf8e2afSMika Westerberg }; 3897edf8e2afSMika Westerberg 3898a2547a13SLaurent Desnogues struct target_elf_siginfo { 3899f8fd4fc4SPaolo Bonzini abi_int si_signo; /* signal number */ 3900f8fd4fc4SPaolo Bonzini abi_int si_code; /* extra code */ 3901f8fd4fc4SPaolo Bonzini abi_int si_errno; /* errno */ 3902edf8e2afSMika Westerberg }; 3903edf8e2afSMika Westerberg 3904a2547a13SLaurent Desnogues struct target_elf_prstatus { 3905a2547a13SLaurent Desnogues struct target_elf_siginfo pr_info; /* Info associated with signal */ 39061ddd592fSPaolo Bonzini abi_short pr_cursig; /* Current signal */ 3907ca98ac83SPaolo Bonzini abi_ulong pr_sigpend; /* XXX */ 3908ca98ac83SPaolo Bonzini abi_ulong pr_sighold; /* XXX */ 3909c227f099SAnthony Liguori target_pid_t pr_pid; 3910c227f099SAnthony Liguori target_pid_t pr_ppid; 3911c227f099SAnthony Liguori target_pid_t pr_pgrp; 3912c227f099SAnthony Liguori target_pid_t pr_sid; 3913edf8e2afSMika Westerberg struct target_timeval pr_utime; /* XXX User time */ 3914edf8e2afSMika Westerberg struct target_timeval pr_stime; /* XXX System time */ 3915edf8e2afSMika Westerberg struct target_timeval pr_cutime; /* XXX Cumulative user time */ 3916edf8e2afSMika Westerberg struct target_timeval pr_cstime; /* XXX Cumulative system time */ 3917c227f099SAnthony Liguori target_elf_gregset_t pr_reg; /* GP registers */ 3918f8fd4fc4SPaolo Bonzini abi_int pr_fpvalid; /* XXX */ 3919edf8e2afSMika Westerberg }; 3920edf8e2afSMika Westerberg 3921edf8e2afSMika Westerberg #define ELF_PRARGSZ (80) /* Number of chars for args */ 3922edf8e2afSMika Westerberg 3923a2547a13SLaurent Desnogues struct target_elf_prpsinfo { 3924edf8e2afSMika Westerberg char pr_state; /* numeric process state */ 3925edf8e2afSMika Westerberg char pr_sname; /* char for pr_state */ 3926edf8e2afSMika Westerberg char pr_zomb; /* zombie */ 3927edf8e2afSMika Westerberg char pr_nice; /* nice val */ 3928ca98ac83SPaolo Bonzini abi_ulong pr_flag; /* flags */ 3929c227f099SAnthony Liguori target_uid_t pr_uid; 3930c227f099SAnthony Liguori target_gid_t pr_gid; 3931c227f099SAnthony Liguori target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; 3932edf8e2afSMika Westerberg /* Lots missing */ 3933d7eb2b92SAlistair Francis char pr_fname[16] QEMU_NONSTRING; /* filename of executable */ 3934edf8e2afSMika Westerberg char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ 3935edf8e2afSMika Westerberg }; 3936edf8e2afSMika Westerberg 3937edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */ 3938edf8e2afSMika Westerberg struct elf_thread_status { 393972cf2d4fSBlue Swirl QTAILQ_ENTRY(elf_thread_status) ets_link; 3940a2547a13SLaurent Desnogues struct target_elf_prstatus prstatus; /* NT_PRSTATUS */ 3941edf8e2afSMika Westerberg #if 0 3942edf8e2afSMika Westerberg elf_fpregset_t fpu; /* NT_PRFPREG */ 3943edf8e2afSMika Westerberg struct task_struct *thread; 3944edf8e2afSMika Westerberg elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */ 3945edf8e2afSMika Westerberg #endif 3946edf8e2afSMika Westerberg struct memelfnote notes[1]; 3947edf8e2afSMika Westerberg int num_notes; 3948edf8e2afSMika Westerberg }; 3949edf8e2afSMika Westerberg 3950edf8e2afSMika Westerberg struct elf_note_info { 3951edf8e2afSMika Westerberg struct memelfnote *notes; 3952a2547a13SLaurent Desnogues struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */ 3953a2547a13SLaurent Desnogues struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */ 3954edf8e2afSMika Westerberg 3955b58deb34SPaolo Bonzini QTAILQ_HEAD(, elf_thread_status) thread_list; 3956edf8e2afSMika Westerberg #if 0 3957edf8e2afSMika Westerberg /* 3958edf8e2afSMika Westerberg * Current version of ELF coredump doesn't support 3959edf8e2afSMika Westerberg * dumping fp regs etc. 3960edf8e2afSMika Westerberg */ 3961edf8e2afSMika Westerberg elf_fpregset_t *fpu; 3962edf8e2afSMika Westerberg elf_fpxregset_t *xfpu; 3963edf8e2afSMika Westerberg int thread_status_size; 3964edf8e2afSMika Westerberg #endif 3965edf8e2afSMika Westerberg int notes_size; 3966edf8e2afSMika Westerberg int numnote; 3967edf8e2afSMika Westerberg }; 3968edf8e2afSMika Westerberg 3969edf8e2afSMika Westerberg struct vm_area_struct { 39701a1c4db9SMikhail Ilyin target_ulong vma_start; /* start vaddr of memory region */ 39711a1c4db9SMikhail Ilyin target_ulong vma_end; /* end vaddr of memory region */ 3972edf8e2afSMika Westerberg abi_ulong vma_flags; /* protection etc. flags for the region */ 397372cf2d4fSBlue Swirl QTAILQ_ENTRY(vm_area_struct) vma_link; 3974edf8e2afSMika Westerberg }; 3975edf8e2afSMika Westerberg 3976edf8e2afSMika Westerberg struct mm_struct { 397772cf2d4fSBlue Swirl QTAILQ_HEAD(, vm_area_struct) mm_mmap; 3978edf8e2afSMika Westerberg int mm_count; /* number of mappings */ 3979edf8e2afSMika Westerberg }; 3980edf8e2afSMika Westerberg 3981edf8e2afSMika Westerberg static struct mm_struct *vma_init(void); 3982edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *); 39831a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *, target_ulong, 39841a1c4db9SMikhail Ilyin target_ulong, abi_ulong); 3985edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *); 3986edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *); 3987edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *); 3988edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *); 39891a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end, 3990edf8e2afSMika Westerberg unsigned long flags); 3991edf8e2afSMika Westerberg 3992edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); 3993edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int, 3994edf8e2afSMika Westerberg unsigned int, void *); 3995a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); 3996a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); 3997edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *); 3998edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); 3999edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *); 4000edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *); 40019349b4f9SAndreas Färber static int fill_note_info(struct elf_note_info *, long, const CPUArchState *); 40029349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *, const CPUArchState *); 4003edf8e2afSMika Westerberg 4004edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t); 4005edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int); 4006edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int); 4007edf8e2afSMika Westerberg 4008edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 4009a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus) 4010edf8e2afSMika Westerberg { 4011ca98ac83SPaolo Bonzini prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo); 4012ca98ac83SPaolo Bonzini prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code); 4013ca98ac83SPaolo Bonzini prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno); 4014edf8e2afSMika Westerberg prstatus->pr_cursig = tswap16(prstatus->pr_cursig); 4015ca98ac83SPaolo Bonzini prstatus->pr_sigpend = tswapal(prstatus->pr_sigpend); 4016ca98ac83SPaolo Bonzini prstatus->pr_sighold = tswapal(prstatus->pr_sighold); 4017edf8e2afSMika Westerberg prstatus->pr_pid = tswap32(prstatus->pr_pid); 4018edf8e2afSMika Westerberg prstatus->pr_ppid = tswap32(prstatus->pr_ppid); 4019edf8e2afSMika Westerberg prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp); 4020edf8e2afSMika Westerberg prstatus->pr_sid = tswap32(prstatus->pr_sid); 4021edf8e2afSMika Westerberg /* cpu times are not filled, so we skip them */ 4022edf8e2afSMika Westerberg /* regs should be in correct format already */ 4023edf8e2afSMika Westerberg prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid); 4024edf8e2afSMika Westerberg } 4025edf8e2afSMika Westerberg 4026a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) 4027edf8e2afSMika Westerberg { 4028ca98ac83SPaolo Bonzini psinfo->pr_flag = tswapal(psinfo->pr_flag); 4029edf8e2afSMika Westerberg psinfo->pr_uid = tswap16(psinfo->pr_uid); 4030edf8e2afSMika Westerberg psinfo->pr_gid = tswap16(psinfo->pr_gid); 4031edf8e2afSMika Westerberg psinfo->pr_pid = tswap32(psinfo->pr_pid); 4032edf8e2afSMika Westerberg psinfo->pr_ppid = tswap32(psinfo->pr_ppid); 4033edf8e2afSMika Westerberg psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp); 4034edf8e2afSMika Westerberg psinfo->pr_sid = tswap32(psinfo->pr_sid); 4035edf8e2afSMika Westerberg } 4036991f8f0cSRichard Henderson 4037991f8f0cSRichard Henderson static void bswap_note(struct elf_note *en) 4038991f8f0cSRichard Henderson { 4039991f8f0cSRichard Henderson bswap32s(&en->n_namesz); 4040991f8f0cSRichard Henderson bswap32s(&en->n_descsz); 4041991f8f0cSRichard Henderson bswap32s(&en->n_type); 4042991f8f0cSRichard Henderson } 4043991f8f0cSRichard Henderson #else 4044991f8f0cSRichard Henderson static inline void bswap_prstatus(struct target_elf_prstatus *p) { } 4045991f8f0cSRichard Henderson static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {} 4046991f8f0cSRichard Henderson static inline void bswap_note(struct elf_note *en) { } 4047edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 4048edf8e2afSMika Westerberg 4049edf8e2afSMika Westerberg /* 4050edf8e2afSMika Westerberg * Minimal support for linux memory regions. These are needed 4051edf8e2afSMika Westerberg * when we are finding out what memory exactly belongs to 4052edf8e2afSMika Westerberg * emulated process. No locks needed here, as long as 4053edf8e2afSMika Westerberg * thread that received the signal is stopped. 4054edf8e2afSMika Westerberg */ 4055edf8e2afSMika Westerberg 4056edf8e2afSMika Westerberg static struct mm_struct *vma_init(void) 4057edf8e2afSMika Westerberg { 4058edf8e2afSMika Westerberg struct mm_struct *mm; 4059edf8e2afSMika Westerberg 40607267c094SAnthony Liguori if ((mm = g_malloc(sizeof (*mm))) == NULL) 4061edf8e2afSMika Westerberg return (NULL); 4062edf8e2afSMika Westerberg 4063edf8e2afSMika Westerberg mm->mm_count = 0; 406472cf2d4fSBlue Swirl QTAILQ_INIT(&mm->mm_mmap); 4065edf8e2afSMika Westerberg 4066edf8e2afSMika Westerberg return (mm); 4067edf8e2afSMika Westerberg } 4068edf8e2afSMika Westerberg 4069edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm) 4070edf8e2afSMika Westerberg { 4071edf8e2afSMika Westerberg struct vm_area_struct *vma; 4072edf8e2afSMika Westerberg 4073edf8e2afSMika Westerberg while ((vma = vma_first(mm)) != NULL) { 407472cf2d4fSBlue Swirl QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link); 40757267c094SAnthony Liguori g_free(vma); 4076edf8e2afSMika Westerberg } 40777267c094SAnthony Liguori g_free(mm); 4078edf8e2afSMika Westerberg } 4079edf8e2afSMika Westerberg 40801a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *mm, target_ulong start, 40811a1c4db9SMikhail Ilyin target_ulong end, abi_ulong flags) 4082edf8e2afSMika Westerberg { 4083edf8e2afSMika Westerberg struct vm_area_struct *vma; 4084edf8e2afSMika Westerberg 40857267c094SAnthony Liguori if ((vma = g_malloc0(sizeof (*vma))) == NULL) 4086edf8e2afSMika Westerberg return (-1); 4087edf8e2afSMika Westerberg 4088edf8e2afSMika Westerberg vma->vma_start = start; 4089edf8e2afSMika Westerberg vma->vma_end = end; 4090edf8e2afSMika Westerberg vma->vma_flags = flags; 4091edf8e2afSMika Westerberg 409272cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link); 4093edf8e2afSMika Westerberg mm->mm_count++; 4094edf8e2afSMika Westerberg 4095edf8e2afSMika Westerberg return (0); 4096edf8e2afSMika Westerberg } 4097edf8e2afSMika Westerberg 4098edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm) 4099edf8e2afSMika Westerberg { 410072cf2d4fSBlue Swirl return (QTAILQ_FIRST(&mm->mm_mmap)); 4101edf8e2afSMika Westerberg } 4102edf8e2afSMika Westerberg 4103edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma) 4104edf8e2afSMika Westerberg { 410572cf2d4fSBlue Swirl return (QTAILQ_NEXT(vma, vma_link)); 4106edf8e2afSMika Westerberg } 4107edf8e2afSMika Westerberg 4108edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm) 4109edf8e2afSMika Westerberg { 4110edf8e2afSMika Westerberg return (mm->mm_count); 4111edf8e2afSMika Westerberg } 4112edf8e2afSMika Westerberg 4113edf8e2afSMika Westerberg /* 4114edf8e2afSMika Westerberg * Calculate file (dump) size of given memory region. 4115edf8e2afSMika Westerberg */ 4116edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma) 4117edf8e2afSMika Westerberg { 4118edf8e2afSMika Westerberg /* if we cannot even read the first page, skip it */ 4119c7169b02SRichard Henderson if (!access_ok_untagged(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE)) 4120edf8e2afSMika Westerberg return (0); 4121edf8e2afSMika Westerberg 4122edf8e2afSMika Westerberg /* 4123edf8e2afSMika Westerberg * Usually we don't dump executable pages as they contain 4124edf8e2afSMika Westerberg * non-writable code that debugger can read directly from 4125edf8e2afSMika Westerberg * target library etc. However, thread stacks are marked 4126edf8e2afSMika Westerberg * also executable so we read in first page of given region 4127edf8e2afSMika Westerberg * and check whether it contains elf header. If there is 4128edf8e2afSMika Westerberg * no elf header, we dump it. 4129edf8e2afSMika Westerberg */ 4130edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) { 4131edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 4132edf8e2afSMika Westerberg 4133022625a8SPeter Maydell if (copy_from_user(page, vma->vma_start, sizeof (page))) { 4134022625a8SPeter Maydell return 0; 4135022625a8SPeter Maydell } 4136edf8e2afSMika Westerberg if ((page[EI_MAG0] == ELFMAG0) && 4137edf8e2afSMika Westerberg (page[EI_MAG1] == ELFMAG1) && 4138edf8e2afSMika Westerberg (page[EI_MAG2] == ELFMAG2) && 4139edf8e2afSMika Westerberg (page[EI_MAG3] == ELFMAG3)) { 4140edf8e2afSMika Westerberg /* 4141edf8e2afSMika Westerberg * Mappings are possibly from ELF binary. Don't dump 4142edf8e2afSMika Westerberg * them. 4143edf8e2afSMika Westerberg */ 4144edf8e2afSMika Westerberg return (0); 4145edf8e2afSMika Westerberg } 4146edf8e2afSMika Westerberg } 4147edf8e2afSMika Westerberg 4148edf8e2afSMika Westerberg return (vma->vma_end - vma->vma_start); 4149edf8e2afSMika Westerberg } 4150edf8e2afSMika Westerberg 41511a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end, 4152edf8e2afSMika Westerberg unsigned long flags) 4153edf8e2afSMika Westerberg { 4154edf8e2afSMika Westerberg struct mm_struct *mm = (struct mm_struct *)priv; 4155edf8e2afSMika Westerberg 4156edf8e2afSMika Westerberg vma_add_mapping(mm, start, end, flags); 4157edf8e2afSMika Westerberg return (0); 4158edf8e2afSMika Westerberg } 4159edf8e2afSMika Westerberg 4160edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type, 4161edf8e2afSMika Westerberg unsigned int sz, void *data) 4162edf8e2afSMika Westerberg { 4163edf8e2afSMika Westerberg unsigned int namesz; 4164edf8e2afSMika Westerberg 4165edf8e2afSMika Westerberg namesz = strlen(name) + 1; 4166edf8e2afSMika Westerberg note->name = name; 4167edf8e2afSMika Westerberg note->namesz = namesz; 4168edf8e2afSMika Westerberg note->namesz_rounded = roundup(namesz, sizeof (int32_t)); 4169edf8e2afSMika Westerberg note->type = type; 417080f5ce75SLaurent Vivier note->datasz = sz; 417180f5ce75SLaurent Vivier note->datasz_rounded = roundup(sz, sizeof (int32_t)); 417280f5ce75SLaurent Vivier 4173edf8e2afSMika Westerberg note->data = data; 4174edf8e2afSMika Westerberg 4175edf8e2afSMika Westerberg /* 4176edf8e2afSMika Westerberg * We calculate rounded up note size here as specified by 4177edf8e2afSMika Westerberg * ELF document. 4178edf8e2afSMika Westerberg */ 4179edf8e2afSMika Westerberg note->notesz = sizeof (struct elf_note) + 418080f5ce75SLaurent Vivier note->namesz_rounded + note->datasz_rounded; 4181edf8e2afSMika Westerberg } 4182edf8e2afSMika Westerberg 4183edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, 4184edf8e2afSMika Westerberg uint32_t flags) 4185edf8e2afSMika Westerberg { 4186edf8e2afSMika Westerberg (void) memset(elf, 0, sizeof(*elf)); 4187edf8e2afSMika Westerberg 4188edf8e2afSMika Westerberg (void) memcpy(elf->e_ident, ELFMAG, SELFMAG); 4189edf8e2afSMika Westerberg elf->e_ident[EI_CLASS] = ELF_CLASS; 4190edf8e2afSMika Westerberg elf->e_ident[EI_DATA] = ELF_DATA; 4191edf8e2afSMika Westerberg elf->e_ident[EI_VERSION] = EV_CURRENT; 4192edf8e2afSMika Westerberg elf->e_ident[EI_OSABI] = ELF_OSABI; 4193edf8e2afSMika Westerberg 4194edf8e2afSMika Westerberg elf->e_type = ET_CORE; 4195edf8e2afSMika Westerberg elf->e_machine = machine; 4196edf8e2afSMika Westerberg elf->e_version = EV_CURRENT; 4197edf8e2afSMika Westerberg elf->e_phoff = sizeof(struct elfhdr); 4198edf8e2afSMika Westerberg elf->e_flags = flags; 4199edf8e2afSMika Westerberg elf->e_ehsize = sizeof(struct elfhdr); 4200edf8e2afSMika Westerberg elf->e_phentsize = sizeof(struct elf_phdr); 4201edf8e2afSMika Westerberg elf->e_phnum = segs; 4202edf8e2afSMika Westerberg 4203edf8e2afSMika Westerberg bswap_ehdr(elf); 4204edf8e2afSMika Westerberg } 4205edf8e2afSMika Westerberg 4206edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) 4207edf8e2afSMika Westerberg { 4208edf8e2afSMika Westerberg phdr->p_type = PT_NOTE; 4209edf8e2afSMika Westerberg phdr->p_offset = offset; 4210edf8e2afSMika Westerberg phdr->p_vaddr = 0; 4211edf8e2afSMika Westerberg phdr->p_paddr = 0; 4212edf8e2afSMika Westerberg phdr->p_filesz = sz; 4213edf8e2afSMika Westerberg phdr->p_memsz = 0; 4214edf8e2afSMika Westerberg phdr->p_flags = 0; 4215edf8e2afSMika Westerberg phdr->p_align = 0; 4216edf8e2afSMika Westerberg 4217991f8f0cSRichard Henderson bswap_phdr(phdr, 1); 4218edf8e2afSMika Westerberg } 4219edf8e2afSMika Westerberg 4220edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note) 4221edf8e2afSMika Westerberg { 4222edf8e2afSMika Westerberg return (note->notesz); 4223edf8e2afSMika Westerberg } 4224edf8e2afSMika Westerberg 4225a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus, 4226edf8e2afSMika Westerberg const TaskState *ts, int signr) 4227edf8e2afSMika Westerberg { 4228edf8e2afSMika Westerberg (void) memset(prstatus, 0, sizeof (*prstatus)); 4229edf8e2afSMika Westerberg prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 4230edf8e2afSMika Westerberg prstatus->pr_pid = ts->ts_tid; 4231edf8e2afSMika Westerberg prstatus->pr_ppid = getppid(); 4232edf8e2afSMika Westerberg prstatus->pr_pgrp = getpgrp(); 4233edf8e2afSMika Westerberg prstatus->pr_sid = getsid(0); 4234edf8e2afSMika Westerberg 4235edf8e2afSMika Westerberg bswap_prstatus(prstatus); 4236edf8e2afSMika Westerberg } 4237edf8e2afSMika Westerberg 4238a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) 4239edf8e2afSMika Westerberg { 4240900cfbcaSJim Meyering char *base_filename; 4241edf8e2afSMika Westerberg unsigned int i, len; 4242edf8e2afSMika Westerberg 4243edf8e2afSMika Westerberg (void) memset(psinfo, 0, sizeof (*psinfo)); 4244edf8e2afSMika Westerberg 42455f779a3aSIlya Leoshkevich len = ts->info->env_strings - ts->info->arg_strings; 4246edf8e2afSMika Westerberg if (len >= ELF_PRARGSZ) 4247edf8e2afSMika Westerberg len = ELF_PRARGSZ - 1; 42485f779a3aSIlya Leoshkevich if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_strings, len)) { 4249edf8e2afSMika Westerberg return -EFAULT; 42505f779a3aSIlya Leoshkevich } 4251edf8e2afSMika Westerberg for (i = 0; i < len; i++) 4252edf8e2afSMika Westerberg if (psinfo->pr_psargs[i] == 0) 4253edf8e2afSMika Westerberg psinfo->pr_psargs[i] = ' '; 4254edf8e2afSMika Westerberg psinfo->pr_psargs[len] = 0; 4255edf8e2afSMika Westerberg 4256edf8e2afSMika Westerberg psinfo->pr_pid = getpid(); 4257edf8e2afSMika Westerberg psinfo->pr_ppid = getppid(); 4258edf8e2afSMika Westerberg psinfo->pr_pgrp = getpgrp(); 4259edf8e2afSMika Westerberg psinfo->pr_sid = getsid(0); 4260edf8e2afSMika Westerberg psinfo->pr_uid = getuid(); 4261edf8e2afSMika Westerberg psinfo->pr_gid = getgid(); 4262edf8e2afSMika Westerberg 4263900cfbcaSJim Meyering base_filename = g_path_get_basename(ts->bprm->filename); 4264900cfbcaSJim Meyering /* 4265900cfbcaSJim Meyering * Using strncpy here is fine: at max-length, 4266900cfbcaSJim Meyering * this field is not NUL-terminated. 4267900cfbcaSJim Meyering */ 4268edf8e2afSMika Westerberg (void) strncpy(psinfo->pr_fname, base_filename, 4269edf8e2afSMika Westerberg sizeof(psinfo->pr_fname)); 4270edf8e2afSMika Westerberg 4271900cfbcaSJim Meyering g_free(base_filename); 4272edf8e2afSMika Westerberg bswap_psinfo(psinfo); 4273edf8e2afSMika Westerberg return (0); 4274edf8e2afSMika Westerberg } 4275edf8e2afSMika Westerberg 4276edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) 4277edf8e2afSMika Westerberg { 4278edf8e2afSMika Westerberg elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; 4279edf8e2afSMika Westerberg elf_addr_t orig_auxv = auxv; 4280edf8e2afSMika Westerberg void *ptr; 4281125b0f55SAlexander Graf int len = ts->info->auxv_len; 4282edf8e2afSMika Westerberg 4283edf8e2afSMika Westerberg /* 4284edf8e2afSMika Westerberg * Auxiliary vector is stored in target process stack. It contains 4285edf8e2afSMika Westerberg * {type, value} pairs that we need to dump into note. This is not 4286edf8e2afSMika Westerberg * strictly necessary but we do it here for sake of completeness. 4287edf8e2afSMika Westerberg */ 4288edf8e2afSMika Westerberg 4289edf8e2afSMika Westerberg /* read in whole auxv vector and copy it to memelfnote */ 4290edf8e2afSMika Westerberg ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); 4291edf8e2afSMika Westerberg if (ptr != NULL) { 4292edf8e2afSMika Westerberg fill_note(note, "CORE", NT_AUXV, len, ptr); 4293edf8e2afSMika Westerberg unlock_user(ptr, auxv, len); 4294edf8e2afSMika Westerberg } 4295edf8e2afSMika Westerberg } 4296edf8e2afSMika Westerberg 4297edf8e2afSMika Westerberg /* 4298edf8e2afSMika Westerberg * Constructs name of coredump file. We have following convention 4299edf8e2afSMika Westerberg * for the name: 4300edf8e2afSMika Westerberg * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core 4301edf8e2afSMika Westerberg * 430268af19adSDaniel P. Berrangé * Returns the filename 4303edf8e2afSMika Westerberg */ 430468af19adSDaniel P. Berrangé static char *core_dump_filename(const TaskState *ts) 4305edf8e2afSMika Westerberg { 430668af19adSDaniel P. Berrangé g_autoptr(GDateTime) now = g_date_time_new_now_local(); 430768af19adSDaniel P. Berrangé g_autofree char *nowstr = g_date_time_format(now, "%Y%m%d-%H%M%S"); 430868af19adSDaniel P. Berrangé g_autofree char *base_filename = g_path_get_basename(ts->bprm->filename); 4309edf8e2afSMika Westerberg 431068af19adSDaniel P. Berrangé return g_strdup_printf("qemu_%s_%s_%d.core", 431168af19adSDaniel P. Berrangé base_filename, nowstr, (int)getpid()); 4312edf8e2afSMika Westerberg } 4313edf8e2afSMika Westerberg 4314edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size) 4315edf8e2afSMika Westerberg { 4316edf8e2afSMika Westerberg const char *bufp = (const char *)ptr; 4317edf8e2afSMika Westerberg ssize_t bytes_written, bytes_left; 4318edf8e2afSMika Westerberg struct rlimit dumpsize; 4319edf8e2afSMika Westerberg off_t pos; 4320edf8e2afSMika Westerberg 4321edf8e2afSMika Westerberg bytes_written = 0; 4322edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 4323edf8e2afSMika Westerberg if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { 4324edf8e2afSMika Westerberg if (errno == ESPIPE) { /* not a seekable stream */ 4325edf8e2afSMika Westerberg bytes_left = size; 4326edf8e2afSMika Westerberg } else { 4327edf8e2afSMika Westerberg return pos; 4328edf8e2afSMika Westerberg } 4329edf8e2afSMika Westerberg } else { 4330edf8e2afSMika Westerberg if (dumpsize.rlim_cur <= pos) { 4331edf8e2afSMika Westerberg return -1; 4332edf8e2afSMika Westerberg } else if (dumpsize.rlim_cur == RLIM_INFINITY) { 4333edf8e2afSMika Westerberg bytes_left = size; 4334edf8e2afSMika Westerberg } else { 4335edf8e2afSMika Westerberg size_t limit_left=dumpsize.rlim_cur - pos; 4336edf8e2afSMika Westerberg bytes_left = limit_left >= size ? size : limit_left ; 4337edf8e2afSMika Westerberg } 4338edf8e2afSMika Westerberg } 4339edf8e2afSMika Westerberg 4340edf8e2afSMika Westerberg /* 4341edf8e2afSMika Westerberg * In normal conditions, single write(2) should do but 4342edf8e2afSMika Westerberg * in case of socket etc. this mechanism is more portable. 4343edf8e2afSMika Westerberg */ 4344edf8e2afSMika Westerberg do { 4345edf8e2afSMika Westerberg bytes_written = write(fd, bufp, bytes_left); 4346edf8e2afSMika Westerberg if (bytes_written < 0) { 4347edf8e2afSMika Westerberg if (errno == EINTR) 4348edf8e2afSMika Westerberg continue; 4349edf8e2afSMika Westerberg return (-1); 4350edf8e2afSMika Westerberg } else if (bytes_written == 0) { /* eof */ 4351edf8e2afSMika Westerberg return (-1); 4352edf8e2afSMika Westerberg } 4353edf8e2afSMika Westerberg bufp += bytes_written; 4354edf8e2afSMika Westerberg bytes_left -= bytes_written; 4355edf8e2afSMika Westerberg } while (bytes_left > 0); 4356edf8e2afSMika Westerberg 4357edf8e2afSMika Westerberg return (0); 4358edf8e2afSMika Westerberg } 4359edf8e2afSMika Westerberg 4360edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd) 4361edf8e2afSMika Westerberg { 4362edf8e2afSMika Westerberg struct elf_note en; 4363edf8e2afSMika Westerberg 4364edf8e2afSMika Westerberg en.n_namesz = men->namesz; 4365edf8e2afSMika Westerberg en.n_type = men->type; 4366edf8e2afSMika Westerberg en.n_descsz = men->datasz; 4367edf8e2afSMika Westerberg 4368edf8e2afSMika Westerberg bswap_note(&en); 4369edf8e2afSMika Westerberg 4370edf8e2afSMika Westerberg if (dump_write(fd, &en, sizeof(en)) != 0) 4371edf8e2afSMika Westerberg return (-1); 4372edf8e2afSMika Westerberg if (dump_write(fd, men->name, men->namesz_rounded) != 0) 4373edf8e2afSMika Westerberg return (-1); 437480f5ce75SLaurent Vivier if (dump_write(fd, men->data, men->datasz_rounded) != 0) 4375edf8e2afSMika Westerberg return (-1); 4376edf8e2afSMika Westerberg 4377edf8e2afSMika Westerberg return (0); 4378edf8e2afSMika Westerberg } 4379edf8e2afSMika Westerberg 43809349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env) 4381edf8e2afSMika Westerberg { 438229a0af61SRichard Henderson CPUState *cpu = env_cpu((CPUArchState *)env); 43830429a971SAndreas Färber TaskState *ts = (TaskState *)cpu->opaque; 4384edf8e2afSMika Westerberg struct elf_thread_status *ets; 4385edf8e2afSMika Westerberg 43867267c094SAnthony Liguori ets = g_malloc0(sizeof (*ets)); 4387edf8e2afSMika Westerberg ets->num_notes = 1; /* only prstatus is dumped */ 4388edf8e2afSMika Westerberg fill_prstatus(&ets->prstatus, ts, 0); 4389edf8e2afSMika Westerberg elf_core_copy_regs(&ets->prstatus.pr_reg, env); 4390edf8e2afSMika Westerberg fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus), 4391edf8e2afSMika Westerberg &ets->prstatus); 4392edf8e2afSMika Westerberg 439372cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link); 4394edf8e2afSMika Westerberg 4395edf8e2afSMika Westerberg info->notes_size += note_size(&ets->notes[0]); 4396edf8e2afSMika Westerberg } 4397edf8e2afSMika Westerberg 43986afafa86SPeter Maydell static void init_note_info(struct elf_note_info *info) 43996afafa86SPeter Maydell { 44006afafa86SPeter Maydell /* Initialize the elf_note_info structure so that it is at 44016afafa86SPeter Maydell * least safe to call free_note_info() on it. Must be 44026afafa86SPeter Maydell * called before calling fill_note_info(). 44036afafa86SPeter Maydell */ 44046afafa86SPeter Maydell memset(info, 0, sizeof (*info)); 44056afafa86SPeter Maydell QTAILQ_INIT(&info->thread_list); 44066afafa86SPeter Maydell } 44076afafa86SPeter Maydell 4408edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info, 44099349b4f9SAndreas Färber long signr, const CPUArchState *env) 4410edf8e2afSMika Westerberg { 4411edf8e2afSMika Westerberg #define NUMNOTES 3 441229a0af61SRichard Henderson CPUState *cpu = env_cpu((CPUArchState *)env); 44130429a971SAndreas Färber TaskState *ts = (TaskState *)cpu->opaque; 4414edf8e2afSMika Westerberg int i; 4415edf8e2afSMika Westerberg 4416c78d65e8SMarkus Armbruster info->notes = g_new0(struct memelfnote, NUMNOTES); 4417edf8e2afSMika Westerberg if (info->notes == NULL) 4418edf8e2afSMika Westerberg return (-ENOMEM); 44197267c094SAnthony Liguori info->prstatus = g_malloc0(sizeof (*info->prstatus)); 4420edf8e2afSMika Westerberg if (info->prstatus == NULL) 4421edf8e2afSMika Westerberg return (-ENOMEM); 44227267c094SAnthony Liguori info->psinfo = g_malloc0(sizeof (*info->psinfo)); 4423edf8e2afSMika Westerberg if (info->prstatus == NULL) 4424edf8e2afSMika Westerberg return (-ENOMEM); 4425edf8e2afSMika Westerberg 4426edf8e2afSMika Westerberg /* 4427edf8e2afSMika Westerberg * First fill in status (and registers) of current thread 4428edf8e2afSMika Westerberg * including process info & aux vector. 4429edf8e2afSMika Westerberg */ 4430edf8e2afSMika Westerberg fill_prstatus(info->prstatus, ts, signr); 4431edf8e2afSMika Westerberg elf_core_copy_regs(&info->prstatus->pr_reg, env); 4432edf8e2afSMika Westerberg fill_note(&info->notes[0], "CORE", NT_PRSTATUS, 4433edf8e2afSMika Westerberg sizeof (*info->prstatus), info->prstatus); 4434edf8e2afSMika Westerberg fill_psinfo(info->psinfo, ts); 4435edf8e2afSMika Westerberg fill_note(&info->notes[1], "CORE", NT_PRPSINFO, 4436edf8e2afSMika Westerberg sizeof (*info->psinfo), info->psinfo); 4437edf8e2afSMika Westerberg fill_auxv_note(&info->notes[2], ts); 4438edf8e2afSMika Westerberg info->numnote = 3; 4439edf8e2afSMika Westerberg 4440edf8e2afSMika Westerberg info->notes_size = 0; 4441edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 4442edf8e2afSMika Westerberg info->notes_size += note_size(&info->notes[i]); 4443edf8e2afSMika Westerberg 4444edf8e2afSMika Westerberg /* read and fill status of all threads */ 4445370ed600SJamie Iles WITH_QEMU_LOCK_GUARD(&qemu_cpu_list_lock) { 4446bdc44640SAndreas Färber CPU_FOREACH(cpu) { 4447a2247f8eSAndreas Färber if (cpu == thread_cpu) { 4448edf8e2afSMika Westerberg continue; 4449182735efSAndreas Färber } 4450b77af26eSRichard Henderson fill_thread_info(info, cpu_env(cpu)); 4451edf8e2afSMika Westerberg } 4452370ed600SJamie Iles } 4453edf8e2afSMika Westerberg 4454edf8e2afSMika Westerberg return (0); 4455edf8e2afSMika Westerberg } 4456edf8e2afSMika Westerberg 4457edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info) 4458edf8e2afSMika Westerberg { 4459edf8e2afSMika Westerberg struct elf_thread_status *ets; 4460edf8e2afSMika Westerberg 446172cf2d4fSBlue Swirl while (!QTAILQ_EMPTY(&info->thread_list)) { 446272cf2d4fSBlue Swirl ets = QTAILQ_FIRST(&info->thread_list); 446372cf2d4fSBlue Swirl QTAILQ_REMOVE(&info->thread_list, ets, ets_link); 44647267c094SAnthony Liguori g_free(ets); 4465edf8e2afSMika Westerberg } 4466edf8e2afSMika Westerberg 44677267c094SAnthony Liguori g_free(info->prstatus); 44687267c094SAnthony Liguori g_free(info->psinfo); 44697267c094SAnthony Liguori g_free(info->notes); 4470edf8e2afSMika Westerberg } 4471edf8e2afSMika Westerberg 4472edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd) 4473edf8e2afSMika Westerberg { 4474edf8e2afSMika Westerberg struct elf_thread_status *ets; 4475edf8e2afSMika Westerberg int i, error = 0; 4476edf8e2afSMika Westerberg 4477edf8e2afSMika Westerberg /* write prstatus, psinfo and auxv for current thread */ 4478edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 4479edf8e2afSMika Westerberg if ((error = write_note(&info->notes[i], fd)) != 0) 4480edf8e2afSMika Westerberg return (error); 4481edf8e2afSMika Westerberg 4482edf8e2afSMika Westerberg /* write prstatus for each thread */ 448352a53afeSEmilio G. Cota QTAILQ_FOREACH(ets, &info->thread_list, ets_link) { 4484edf8e2afSMika Westerberg if ((error = write_note(&ets->notes[0], fd)) != 0) 4485edf8e2afSMika Westerberg return (error); 4486edf8e2afSMika Westerberg } 4487edf8e2afSMika Westerberg 4488edf8e2afSMika Westerberg return (0); 4489edf8e2afSMika Westerberg } 4490edf8e2afSMika Westerberg 4491edf8e2afSMika Westerberg /* 4492edf8e2afSMika Westerberg * Write out ELF coredump. 4493edf8e2afSMika Westerberg * 4494edf8e2afSMika Westerberg * See documentation of ELF object file format in: 4495edf8e2afSMika Westerberg * http://www.caldera.com/developers/devspecs/gabi41.pdf 4496edf8e2afSMika Westerberg * 4497edf8e2afSMika Westerberg * Coredump format in linux is following: 4498edf8e2afSMika Westerberg * 4499edf8e2afSMika Westerberg * 0 +----------------------+ \ 4500edf8e2afSMika Westerberg * | ELF header | ET_CORE | 4501edf8e2afSMika Westerberg * +----------------------+ | 4502edf8e2afSMika Westerberg * | ELF program headers | |--- headers 4503edf8e2afSMika Westerberg * | - NOTE section | | 4504edf8e2afSMika Westerberg * | - PT_LOAD sections | | 4505edf8e2afSMika Westerberg * +----------------------+ / 4506edf8e2afSMika Westerberg * | NOTEs: | 4507edf8e2afSMika Westerberg * | - NT_PRSTATUS | 4508edf8e2afSMika Westerberg * | - NT_PRSINFO | 4509edf8e2afSMika Westerberg * | - NT_AUXV | 4510edf8e2afSMika Westerberg * +----------------------+ <-- aligned to target page 4511edf8e2afSMika Westerberg * | Process memory dump | 4512edf8e2afSMika Westerberg * : : 4513edf8e2afSMika Westerberg * . . 4514edf8e2afSMika Westerberg * : : 4515edf8e2afSMika Westerberg * | | 4516edf8e2afSMika Westerberg * +----------------------+ 4517edf8e2afSMika Westerberg * 4518edf8e2afSMika Westerberg * NT_PRSTATUS -> struct elf_prstatus (per thread) 4519edf8e2afSMika Westerberg * NT_PRSINFO -> struct elf_prpsinfo 4520edf8e2afSMika Westerberg * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()). 4521edf8e2afSMika Westerberg * 4522edf8e2afSMika Westerberg * Format follows System V format as close as possible. Current 4523edf8e2afSMika Westerberg * version limitations are as follows: 4524edf8e2afSMika Westerberg * - no floating point registers are dumped 4525edf8e2afSMika Westerberg * 4526edf8e2afSMika Westerberg * Function returns 0 in case of success, negative errno otherwise. 4527edf8e2afSMika Westerberg * 4528edf8e2afSMika Westerberg * TODO: make this work also during runtime: it should be 4529edf8e2afSMika Westerberg * possible to force coredump from running process and then 4530edf8e2afSMika Westerberg * continue processing. For example qemu could set up SIGUSR2 4531edf8e2afSMika Westerberg * handler (provided that target process haven't registered 4532edf8e2afSMika Westerberg * handler for that) that does the dump when signal is received. 4533edf8e2afSMika Westerberg */ 45349349b4f9SAndreas Färber static int elf_core_dump(int signr, const CPUArchState *env) 4535edf8e2afSMika Westerberg { 453629a0af61SRichard Henderson const CPUState *cpu = env_cpu((CPUArchState *)env); 45370429a971SAndreas Färber const TaskState *ts = (const TaskState *)cpu->opaque; 4538edf8e2afSMika Westerberg struct vm_area_struct *vma = NULL; 453968af19adSDaniel P. Berrangé g_autofree char *corefile = NULL; 4540edf8e2afSMika Westerberg struct elf_note_info info; 4541edf8e2afSMika Westerberg struct elfhdr elf; 4542edf8e2afSMika Westerberg struct elf_phdr phdr; 4543edf8e2afSMika Westerberg struct rlimit dumpsize; 4544edf8e2afSMika Westerberg struct mm_struct *mm = NULL; 4545edf8e2afSMika Westerberg off_t offset = 0, data_offset = 0; 4546edf8e2afSMika Westerberg int segs = 0; 4547edf8e2afSMika Westerberg int fd = -1; 4548edf8e2afSMika Westerberg 45496afafa86SPeter Maydell init_note_info(&info); 45506afafa86SPeter Maydell 4551edf8e2afSMika Westerberg errno = 0; 4552edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 4553edf8e2afSMika Westerberg if (dumpsize.rlim_cur == 0) 4554edf8e2afSMika Westerberg return 0; 4555edf8e2afSMika Westerberg 455668af19adSDaniel P. Berrangé corefile = core_dump_filename(ts); 4557edf8e2afSMika Westerberg 4558edf8e2afSMika Westerberg if ((fd = open(corefile, O_WRONLY | O_CREAT, 4559edf8e2afSMika Westerberg S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) 4560edf8e2afSMika Westerberg return (-errno); 4561edf8e2afSMika Westerberg 4562edf8e2afSMika Westerberg /* 4563edf8e2afSMika Westerberg * Walk through target process memory mappings and 4564edf8e2afSMika Westerberg * set up structure containing this information. After 4565edf8e2afSMika Westerberg * this point vma_xxx functions can be used. 4566edf8e2afSMika Westerberg */ 4567edf8e2afSMika Westerberg if ((mm = vma_init()) == NULL) 4568edf8e2afSMika Westerberg goto out; 4569edf8e2afSMika Westerberg 4570edf8e2afSMika Westerberg walk_memory_regions(mm, vma_walker); 4571edf8e2afSMika Westerberg segs = vma_get_mapping_count(mm); 4572edf8e2afSMika Westerberg 4573edf8e2afSMika Westerberg /* 4574edf8e2afSMika Westerberg * Construct valid coredump ELF header. We also 4575edf8e2afSMika Westerberg * add one more segment for notes. 4576edf8e2afSMika Westerberg */ 4577edf8e2afSMika Westerberg fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0); 4578edf8e2afSMika Westerberg if (dump_write(fd, &elf, sizeof (elf)) != 0) 4579edf8e2afSMika Westerberg goto out; 4580edf8e2afSMika Westerberg 4581b6af0975SDaniel P. Berrange /* fill in the in-memory version of notes */ 4582edf8e2afSMika Westerberg if (fill_note_info(&info, signr, env) < 0) 4583edf8e2afSMika Westerberg goto out; 4584edf8e2afSMika Westerberg 4585edf8e2afSMika Westerberg offset += sizeof (elf); /* elf header */ 4586edf8e2afSMika Westerberg offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */ 4587edf8e2afSMika Westerberg 4588edf8e2afSMika Westerberg /* write out notes program header */ 4589edf8e2afSMika Westerberg fill_elf_note_phdr(&phdr, info.notes_size, offset); 4590edf8e2afSMika Westerberg 4591edf8e2afSMika Westerberg offset += info.notes_size; 4592edf8e2afSMika Westerberg if (dump_write(fd, &phdr, sizeof (phdr)) != 0) 4593edf8e2afSMika Westerberg goto out; 4594edf8e2afSMika Westerberg 4595edf8e2afSMika Westerberg /* 4596edf8e2afSMika Westerberg * ELF specification wants data to start at page boundary so 4597edf8e2afSMika Westerberg * we align it here. 4598edf8e2afSMika Westerberg */ 459980f5ce75SLaurent Vivier data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE); 4600edf8e2afSMika Westerberg 4601edf8e2afSMika Westerberg /* 4602edf8e2afSMika Westerberg * Write program headers for memory regions mapped in 4603edf8e2afSMika Westerberg * the target process. 4604edf8e2afSMika Westerberg */ 4605edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 4606edf8e2afSMika Westerberg (void) memset(&phdr, 0, sizeof (phdr)); 4607edf8e2afSMika Westerberg 4608edf8e2afSMika Westerberg phdr.p_type = PT_LOAD; 4609edf8e2afSMika Westerberg phdr.p_offset = offset; 4610edf8e2afSMika Westerberg phdr.p_vaddr = vma->vma_start; 4611edf8e2afSMika Westerberg phdr.p_paddr = 0; 4612edf8e2afSMika Westerberg phdr.p_filesz = vma_dump_size(vma); 4613edf8e2afSMika Westerberg offset += phdr.p_filesz; 4614edf8e2afSMika Westerberg phdr.p_memsz = vma->vma_end - vma->vma_start; 4615edf8e2afSMika Westerberg phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0; 4616edf8e2afSMika Westerberg if (vma->vma_flags & PROT_WRITE) 4617edf8e2afSMika Westerberg phdr.p_flags |= PF_W; 4618edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) 4619edf8e2afSMika Westerberg phdr.p_flags |= PF_X; 4620edf8e2afSMika Westerberg phdr.p_align = ELF_EXEC_PAGESIZE; 4621edf8e2afSMika Westerberg 462280f5ce75SLaurent Vivier bswap_phdr(&phdr, 1); 4623772034b6SPeter Maydell if (dump_write(fd, &phdr, sizeof(phdr)) != 0) { 4624772034b6SPeter Maydell goto out; 4625772034b6SPeter Maydell } 4626edf8e2afSMika Westerberg } 4627edf8e2afSMika Westerberg 4628edf8e2afSMika Westerberg /* 4629edf8e2afSMika Westerberg * Next we write notes just after program headers. No 4630edf8e2afSMika Westerberg * alignment needed here. 4631edf8e2afSMika Westerberg */ 4632edf8e2afSMika Westerberg if (write_note_info(&info, fd) < 0) 4633edf8e2afSMika Westerberg goto out; 4634edf8e2afSMika Westerberg 4635edf8e2afSMika Westerberg /* align data to page boundary */ 4636edf8e2afSMika Westerberg if (lseek(fd, data_offset, SEEK_SET) != data_offset) 4637edf8e2afSMika Westerberg goto out; 4638edf8e2afSMika Westerberg 4639edf8e2afSMika Westerberg /* 4640edf8e2afSMika Westerberg * Finally we can dump process memory into corefile as well. 4641edf8e2afSMika Westerberg */ 4642edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 4643edf8e2afSMika Westerberg abi_ulong addr; 4644edf8e2afSMika Westerberg abi_ulong end; 4645edf8e2afSMika Westerberg 4646edf8e2afSMika Westerberg end = vma->vma_start + vma_dump_size(vma); 4647edf8e2afSMika Westerberg 4648edf8e2afSMika Westerberg for (addr = vma->vma_start; addr < end; 4649edf8e2afSMika Westerberg addr += TARGET_PAGE_SIZE) { 4650edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 4651edf8e2afSMika Westerberg int error; 4652edf8e2afSMika Westerberg 4653edf8e2afSMika Westerberg /* 4654edf8e2afSMika Westerberg * Read in page from target process memory and 4655edf8e2afSMika Westerberg * write it to coredump file. 4656edf8e2afSMika Westerberg */ 4657edf8e2afSMika Westerberg error = copy_from_user(page, addr, sizeof (page)); 4658edf8e2afSMika Westerberg if (error != 0) { 465949995e17SAurelien Jarno (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n", 4660edf8e2afSMika Westerberg addr); 4661edf8e2afSMika Westerberg errno = -error; 4662edf8e2afSMika Westerberg goto out; 4663edf8e2afSMika Westerberg } 4664edf8e2afSMika Westerberg if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0) 4665edf8e2afSMika Westerberg goto out; 4666edf8e2afSMika Westerberg } 4667edf8e2afSMika Westerberg } 4668edf8e2afSMika Westerberg 4669edf8e2afSMika Westerberg out: 4670edf8e2afSMika Westerberg free_note_info(&info); 4671edf8e2afSMika Westerberg if (mm != NULL) 4672edf8e2afSMika Westerberg vma_delete(mm); 4673edf8e2afSMika Westerberg (void) close(fd); 4674edf8e2afSMika Westerberg 4675edf8e2afSMika Westerberg if (errno != 0) 4676edf8e2afSMika Westerberg return (-errno); 4677edf8e2afSMika Westerberg return (0); 4678edf8e2afSMika Westerberg } 4679edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 4680edf8e2afSMika Westerberg 4681e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) 4682e5fe0c52Spbrook { 4683e5fe0c52Spbrook init_thread(regs, infop); 4684e5fe0c52Spbrook } 4685