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 */ 2204682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias); 2205edf8e2afSMika Westerberg 22069058abddSRichard Henderson /* Verify the portions of EHDR within E_IDENT for the target. 22079058abddSRichard Henderson This can be performed before bswapping the entire header. */ 22089058abddSRichard Henderson static bool elf_check_ident(struct elfhdr *ehdr) 22099058abddSRichard Henderson { 22109058abddSRichard Henderson return (ehdr->e_ident[EI_MAG0] == ELFMAG0 22119058abddSRichard Henderson && ehdr->e_ident[EI_MAG1] == ELFMAG1 22129058abddSRichard Henderson && ehdr->e_ident[EI_MAG2] == ELFMAG2 22139058abddSRichard Henderson && ehdr->e_ident[EI_MAG3] == ELFMAG3 22149058abddSRichard Henderson && ehdr->e_ident[EI_CLASS] == ELF_CLASS 22159058abddSRichard Henderson && ehdr->e_ident[EI_DATA] == ELF_DATA 22169058abddSRichard Henderson && ehdr->e_ident[EI_VERSION] == EV_CURRENT); 22179058abddSRichard Henderson } 22189058abddSRichard Henderson 22199058abddSRichard Henderson /* Verify the portions of EHDR outside of E_IDENT for the target. 22209058abddSRichard Henderson This has to wait until after bswapping the header. */ 22219058abddSRichard Henderson static bool elf_check_ehdr(struct elfhdr *ehdr) 22229058abddSRichard Henderson { 22239058abddSRichard Henderson return (elf_check_arch(ehdr->e_machine) 2224ace3d654SCarlo Marcelo Arenas Belón && elf_check_abi(ehdr->e_flags) 22259058abddSRichard Henderson && ehdr->e_ehsize == sizeof(struct elfhdr) 22269058abddSRichard Henderson && ehdr->e_phentsize == sizeof(struct elf_phdr) 22279058abddSRichard Henderson && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)); 22289058abddSRichard Henderson } 22299058abddSRichard Henderson 223031e31b8aSbellard /* 2231e5fe0c52Spbrook * 'copy_elf_strings()' copies argument/envelope strings from user 223231e31b8aSbellard * memory to free pages in kernel mem. These are in a format ready 223331e31b8aSbellard * to be put directly into the top of new user memory. 223431e31b8aSbellard * 223531e31b8aSbellard */ 223659baae9aSStefan Brüns static abi_ulong copy_elf_strings(int argc, char **argv, char *scratch, 223759baae9aSStefan Brüns abi_ulong p, abi_ulong stack_limit) 223831e31b8aSbellard { 223959baae9aSStefan Brüns char *tmp; 22407c4ee5bcSRichard Henderson int len, i; 224159baae9aSStefan Brüns abi_ulong top = p; 224231e31b8aSbellard 224331e31b8aSbellard if (!p) { 224431e31b8aSbellard return 0; /* bullet-proofing */ 224531e31b8aSbellard } 224659baae9aSStefan Brüns 22477c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 22487c4ee5bcSRichard Henderson int offset = ((p - 1) % TARGET_PAGE_SIZE) + 1; 22497c4ee5bcSRichard Henderson for (i = argc - 1; i >= 0; --i) { 22507c4ee5bcSRichard Henderson tmp = argv[i]; 2251edf779ffSbellard if (!tmp) { 225231e31b8aSbellard fprintf(stderr, "VFS: argc is wrong"); 225331e31b8aSbellard exit(-1); 225431e31b8aSbellard } 225559baae9aSStefan Brüns len = strlen(tmp) + 1; 225659baae9aSStefan Brüns tmp += len; 225759baae9aSStefan Brüns 225859baae9aSStefan Brüns if (len > (p - stack_limit)) { 225931e31b8aSbellard return 0; 226031e31b8aSbellard } 226131e31b8aSbellard while (len) { 226231e31b8aSbellard int bytes_to_copy = (len > offset) ? offset : len; 226331e31b8aSbellard tmp -= bytes_to_copy; 226431e31b8aSbellard p -= bytes_to_copy; 226531e31b8aSbellard offset -= bytes_to_copy; 226631e31b8aSbellard len -= bytes_to_copy; 226759baae9aSStefan Brüns 226859baae9aSStefan Brüns memcpy_fromfs(scratch + offset, tmp, bytes_to_copy); 226959baae9aSStefan Brüns 227059baae9aSStefan Brüns if (offset == 0) { 227159baae9aSStefan Brüns memcpy_to_target(p, scratch, top - p); 227259baae9aSStefan Brüns top = p; 227359baae9aSStefan Brüns offset = TARGET_PAGE_SIZE; 227431e31b8aSbellard } 227531e31b8aSbellard } 227631e31b8aSbellard } 22777c4ee5bcSRichard Henderson if (p != top) { 227859baae9aSStefan Brüns memcpy_to_target(p, scratch + offset, top - p); 227959baae9aSStefan Brüns } 22807c4ee5bcSRichard Henderson } else { 22817c4ee5bcSRichard Henderson int remaining = TARGET_PAGE_SIZE - (p % TARGET_PAGE_SIZE); 22827c4ee5bcSRichard Henderson for (i = 0; i < argc; ++i) { 22837c4ee5bcSRichard Henderson tmp = argv[i]; 22847c4ee5bcSRichard Henderson if (!tmp) { 22857c4ee5bcSRichard Henderson fprintf(stderr, "VFS: argc is wrong"); 22867c4ee5bcSRichard Henderson exit(-1); 22877c4ee5bcSRichard Henderson } 22887c4ee5bcSRichard Henderson len = strlen(tmp) + 1; 22897c4ee5bcSRichard Henderson if (len > (stack_limit - p)) { 22907c4ee5bcSRichard Henderson return 0; 22917c4ee5bcSRichard Henderson } 22927c4ee5bcSRichard Henderson while (len) { 22937c4ee5bcSRichard Henderson int bytes_to_copy = (len > remaining) ? remaining : len; 22947c4ee5bcSRichard Henderson 22957c4ee5bcSRichard Henderson memcpy_fromfs(scratch + (p - top), tmp, bytes_to_copy); 22967c4ee5bcSRichard Henderson 22977c4ee5bcSRichard Henderson tmp += bytes_to_copy; 22987c4ee5bcSRichard Henderson remaining -= bytes_to_copy; 22997c4ee5bcSRichard Henderson p += bytes_to_copy; 23007c4ee5bcSRichard Henderson len -= bytes_to_copy; 23017c4ee5bcSRichard Henderson 23027c4ee5bcSRichard Henderson if (remaining == 0) { 23037c4ee5bcSRichard Henderson memcpy_to_target(top, scratch, p - top); 23047c4ee5bcSRichard Henderson top = p; 23057c4ee5bcSRichard Henderson remaining = TARGET_PAGE_SIZE; 23067c4ee5bcSRichard Henderson } 23077c4ee5bcSRichard Henderson } 23087c4ee5bcSRichard Henderson } 23097c4ee5bcSRichard Henderson if (p != top) { 23107c4ee5bcSRichard Henderson memcpy_to_target(top, scratch, p - top); 23117c4ee5bcSRichard Henderson } 23127c4ee5bcSRichard Henderson } 231359baae9aSStefan Brüns 231431e31b8aSbellard return p; 231531e31b8aSbellard } 231631e31b8aSbellard 231759baae9aSStefan Brüns /* Older linux kernels provide up to MAX_ARG_PAGES (default: 32) of 231859baae9aSStefan Brüns * argument/environment space. Newer kernels (>2.6.33) allow more, 231959baae9aSStefan Brüns * dependent on stack size, but guarantee at least 32 pages for 232059baae9aSStefan Brüns * backwards compatibility. 232159baae9aSStefan Brüns */ 232259baae9aSStefan Brüns #define STACK_LOWER_LIMIT (32 * TARGET_PAGE_SIZE) 232359baae9aSStefan Brüns 232459baae9aSStefan Brüns static abi_ulong setup_arg_pages(struct linux_binprm *bprm, 232531e31b8aSbellard struct image_info *info) 232631e31b8aSbellard { 232759baae9aSStefan Brüns abi_ulong size, error, guard; 2328872f3d04SRichard Henderson int prot; 232931e31b8aSbellard 2330703e0e89SRichard Henderson size = guest_stack_size; 233159baae9aSStefan Brüns if (size < STACK_LOWER_LIMIT) { 233259baae9aSStefan Brüns size = STACK_LOWER_LIMIT; 233360dcbcb5SRichard Henderson } 2334f4388205SHelge Deller 2335f4388205SHelge Deller if (STACK_GROWS_DOWN) { 233660dcbcb5SRichard Henderson guard = TARGET_PAGE_SIZE; 23378e3b0cbbSMarc-André Lureau if (guard < qemu_real_host_page_size()) { 23388e3b0cbbSMarc-André Lureau guard = qemu_real_host_page_size(); 233960dcbcb5SRichard Henderson } 2340f4388205SHelge Deller } else { 2341f4388205SHelge Deller /* no guard page for hppa target where stack grows upwards. */ 2342f4388205SHelge Deller guard = 0; 2343f4388205SHelge Deller } 234460dcbcb5SRichard Henderson 2345872f3d04SRichard Henderson prot = PROT_READ | PROT_WRITE; 2346872f3d04SRichard Henderson if (info->exec_stack) { 2347872f3d04SRichard Henderson prot |= PROT_EXEC; 2348872f3d04SRichard Henderson } 2349872f3d04SRichard Henderson error = target_mmap(0, size + guard, prot, 235060dcbcb5SRichard Henderson MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 235109bfb054Sbellard if (error == -1) { 235260dcbcb5SRichard Henderson perror("mmap stack"); 235331e31b8aSbellard exit(-1); 235431e31b8aSbellard } 235531e31b8aSbellard 235660dcbcb5SRichard Henderson /* We reserve one extra page at the top of the stack as guard. */ 23577c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 235860dcbcb5SRichard Henderson target_mprotect(error, guard, PROT_NONE); 235960dcbcb5SRichard Henderson info->stack_limit = error + guard; 236059baae9aSStefan Brüns return info->stack_limit + size - sizeof(void *); 23617c4ee5bcSRichard Henderson } else { 23627c4ee5bcSRichard Henderson info->stack_limit = error + size; 23637c4ee5bcSRichard Henderson return error; 23647c4ee5bcSRichard Henderson } 236531e31b8aSbellard } 236631e31b8aSbellard 23672d385be6SRichard Henderson /** 23682d385be6SRichard Henderson * zero_bss: 23692d385be6SRichard Henderson * 23702d385be6SRichard Henderson * Map and zero the bss. We need to explicitly zero any fractional pages 23712d385be6SRichard Henderson * after the data section (i.e. bss). Return false on mapping failure. 23722d385be6SRichard Henderson */ 2373e6e66b03SRichard Henderson static bool zero_bss(abi_ulong start_bss, abi_ulong end_bss, 2374e6e66b03SRichard Henderson int prot, Error **errp) 237531e31b8aSbellard { 23762d385be6SRichard Henderson abi_ulong align_bss; 2377cf129f3aSRichard Henderson 2378e6e66b03SRichard Henderson /* We only expect writable bss; the code segment shouldn't need this. */ 2379e6e66b03SRichard Henderson if (!(prot & PROT_WRITE)) { 2380e6e66b03SRichard Henderson error_setg(errp, "PT_LOAD with non-writable bss"); 2381e6e66b03SRichard Henderson return false; 2382e6e66b03SRichard Henderson } 2383e6e66b03SRichard Henderson 23842d385be6SRichard Henderson align_bss = TARGET_PAGE_ALIGN(start_bss); 23852d385be6SRichard Henderson end_bss = TARGET_PAGE_ALIGN(end_bss); 2386cf129f3aSRichard Henderson 23872d385be6SRichard Henderson if (start_bss < align_bss) { 23882d385be6SRichard Henderson int flags = page_get_flags(start_bss); 2389cf129f3aSRichard Henderson 2390e6e66b03SRichard Henderson if (!(flags & PAGE_BITS)) { 2391e6e66b03SRichard Henderson /* 2392e6e66b03SRichard Henderson * The whole address space of the executable was reserved 2393e6e66b03SRichard Henderson * at the start, therefore all pages will be VALID. 2394e6e66b03SRichard Henderson * But assuming there are no PROT_NONE PT_LOAD segments, 2395e6e66b03SRichard Henderson * a PROT_NONE page means no data all bss, and we can 2396e6e66b03SRichard Henderson * simply extend the new anon mapping back to the start 2397e6e66b03SRichard Henderson * of the page of bss. 2398e6e66b03SRichard Henderson */ 23992d385be6SRichard Henderson align_bss -= TARGET_PAGE_SIZE; 24002d385be6SRichard Henderson } else { 2401e6e66b03SRichard Henderson /* 2402e6e66b03SRichard Henderson * The start of the bss shares a page with something. 2403e6e66b03SRichard Henderson * The only thing that we expect is the data section, 2404e6e66b03SRichard Henderson * which would already be marked writable. 2405e6e66b03SRichard Henderson * Overlapping the RX code segment seems malformed. 2406e6e66b03SRichard Henderson */ 2407e6e66b03SRichard Henderson if (!(flags & PAGE_WRITE)) { 2408e6e66b03SRichard Henderson error_setg(errp, "PT_LOAD with bss overlapping " 2409e6e66b03SRichard Henderson "non-writable page"); 2410e6e66b03SRichard Henderson return false; 2411e6e66b03SRichard Henderson } 2412e6e66b03SRichard Henderson 2413e6e66b03SRichard Henderson /* The page is already mapped and writable. */ 2414e6e66b03SRichard Henderson memset(g2h_untagged(start_bss), 0, align_bss - start_bss); 241531e31b8aSbellard } 2416f46e9a0bSTom Musta } 2417cf129f3aSRichard Henderson 2418e6e66b03SRichard Henderson if (align_bss < end_bss && 24192d385be6SRichard Henderson target_mmap(align_bss, end_bss - align_bss, prot, 2420e6e66b03SRichard Henderson MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == -1) { 2421e6e66b03SRichard Henderson error_setg_errno(errp, errno, "Error mapping bss"); 2422e6e66b03SRichard Henderson return false; 2423e6e66b03SRichard Henderson } 2424e6e66b03SRichard Henderson return true; 2425853d6f7aSbellard } 2426853d6f7aSbellard 2427d2796be6SMax Filippov #if defined(TARGET_ARM) 2428cf58affeSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec) 2429cf58affeSChristophe Lyon { 2430cf58affeSChristophe Lyon return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC; 2431cf58affeSChristophe Lyon } 2432d2796be6SMax Filippov #elif defined(TARGET_XTENSA) 2433d2796be6SMax Filippov static int elf_is_fdpic(struct elfhdr *exec) 2434d2796be6SMax Filippov { 2435d2796be6SMax Filippov return exec->e_ident[EI_OSABI] == ELFOSABI_XTENSA_FDPIC; 2436d2796be6SMax Filippov } 2437cf58affeSChristophe Lyon #else 2438a99856cdSChristophe Lyon /* Default implementation, always false. */ 2439a99856cdSChristophe Lyon static int elf_is_fdpic(struct elfhdr *exec) 2440a99856cdSChristophe Lyon { 2441a99856cdSChristophe Lyon return 0; 2442a99856cdSChristophe Lyon } 2443cf58affeSChristophe Lyon #endif 2444a99856cdSChristophe Lyon 24451af02e83SMike Frysinger static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp) 24461af02e83SMike Frysinger { 24471af02e83SMike Frysinger uint16_t n; 24481af02e83SMike Frysinger struct elf32_fdpic_loadseg *loadsegs = info->loadsegs; 24491af02e83SMike Frysinger 24501af02e83SMike Frysinger /* elf32_fdpic_loadseg */ 24511af02e83SMike Frysinger n = info->nsegs; 24521af02e83SMike Frysinger while (n--) { 24531af02e83SMike Frysinger sp -= 12; 24541af02e83SMike Frysinger put_user_u32(loadsegs[n].addr, sp+0); 24551af02e83SMike Frysinger put_user_u32(loadsegs[n].p_vaddr, sp+4); 24561af02e83SMike Frysinger put_user_u32(loadsegs[n].p_memsz, sp+8); 24571af02e83SMike Frysinger } 24581af02e83SMike Frysinger 24591af02e83SMike Frysinger /* elf32_fdpic_loadmap */ 24601af02e83SMike Frysinger sp -= 4; 24611af02e83SMike Frysinger put_user_u16(0, sp+0); /* version */ 24621af02e83SMike Frysinger put_user_u16(info->nsegs, sp+2); /* nsegs */ 24631af02e83SMike Frysinger 24641af02e83SMike Frysinger info->personality = PER_LINUX_FDPIC; 24651af02e83SMike Frysinger info->loadmap_addr = sp; 24661af02e83SMike Frysinger 24671af02e83SMike Frysinger return sp; 24681af02e83SMike Frysinger } 24691af02e83SMike Frysinger 2470992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, 247131e31b8aSbellard struct elfhdr *exec, 24728e62a717SRichard Henderson struct image_info *info, 24738e62a717SRichard Henderson struct image_info *interp_info) 247431e31b8aSbellard { 2475992f48a0Sblueswir1 abi_ulong sp; 24767c4ee5bcSRichard Henderson abi_ulong u_argc, u_argv, u_envp, u_auxv; 247753a5960aSpbrook int size; 247814322badSLaurent ALFONSI int i; 247914322badSLaurent ALFONSI abi_ulong u_rand_bytes; 248014322badSLaurent ALFONSI uint8_t k_rand_bytes[16]; 2481fcdc0ab4SJiaxun Yang abi_ulong u_platform, u_base_platform; 2482fcdc0ab4SJiaxun Yang const char *k_platform, *k_base_platform; 2483863cf0b7Sj_mayer const int n = sizeof(elf_addr_t); 248431e31b8aSbellard 248553a5960aSpbrook sp = p; 24861af02e83SMike Frysinger 24871af02e83SMike Frysinger /* Needs to be before we load the env/argc/... */ 24881af02e83SMike Frysinger if (elf_is_fdpic(exec)) { 24891af02e83SMike Frysinger /* Need 4 byte alignment for these structs */ 24901af02e83SMike Frysinger sp &= ~3; 24911af02e83SMike Frysinger sp = loader_build_fdpic_loadmap(info, sp); 24921af02e83SMike Frysinger info->other_info = interp_info; 24931af02e83SMike Frysinger if (interp_info) { 24941af02e83SMike Frysinger interp_info->other_info = info; 24951af02e83SMike Frysinger sp = loader_build_fdpic_loadmap(interp_info, sp); 24963cb10cfaSChristophe Lyon info->interpreter_loadmap_addr = interp_info->loadmap_addr; 24973cb10cfaSChristophe Lyon info->interpreter_pt_dynamic_addr = interp_info->pt_dynamic_addr; 24983cb10cfaSChristophe Lyon } else { 24993cb10cfaSChristophe Lyon info->interpreter_loadmap_addr = 0; 25003cb10cfaSChristophe Lyon info->interpreter_pt_dynamic_addr = 0; 25011af02e83SMike Frysinger } 25021af02e83SMike Frysinger } 25031af02e83SMike Frysinger 2504fcdc0ab4SJiaxun Yang u_base_platform = 0; 2505fcdc0ab4SJiaxun Yang k_base_platform = ELF_BASE_PLATFORM; 2506fcdc0ab4SJiaxun Yang if (k_base_platform) { 2507fcdc0ab4SJiaxun Yang size_t len = strlen(k_base_platform) + 1; 2508fcdc0ab4SJiaxun Yang if (STACK_GROWS_DOWN) { 2509fcdc0ab4SJiaxun Yang sp -= (len + n - 1) & ~(n - 1); 2510fcdc0ab4SJiaxun Yang u_base_platform = sp; 2511fcdc0ab4SJiaxun Yang /* FIXME - check return value of memcpy_to_target() for failure */ 2512fcdc0ab4SJiaxun Yang memcpy_to_target(sp, k_base_platform, len); 2513fcdc0ab4SJiaxun Yang } else { 2514fcdc0ab4SJiaxun Yang memcpy_to_target(sp, k_base_platform, len); 2515fcdc0ab4SJiaxun Yang u_base_platform = sp; 2516fcdc0ab4SJiaxun Yang sp += len + 1; 2517fcdc0ab4SJiaxun Yang } 2518fcdc0ab4SJiaxun Yang } 2519fcdc0ab4SJiaxun Yang 252053a5960aSpbrook u_platform = 0; 252115338fd7Sbellard k_platform = ELF_PLATFORM; 252215338fd7Sbellard if (k_platform) { 252315338fd7Sbellard size_t len = strlen(k_platform) + 1; 25247c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 252553a5960aSpbrook sp -= (len + n - 1) & ~(n - 1); 252653a5960aSpbrook u_platform = sp; 2527579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 252853a5960aSpbrook memcpy_to_target(sp, k_platform, len); 25297c4ee5bcSRichard Henderson } else { 25307c4ee5bcSRichard Henderson memcpy_to_target(sp, k_platform, len); 25317c4ee5bcSRichard Henderson u_platform = sp; 25327c4ee5bcSRichard Henderson sp += len + 1; 25337c4ee5bcSRichard Henderson } 25347c4ee5bcSRichard Henderson } 25357c4ee5bcSRichard Henderson 25367c4ee5bcSRichard Henderson /* Provide 16 byte alignment for the PRNG, and basic alignment for 25377c4ee5bcSRichard Henderson * the argv and envp pointers. 25387c4ee5bcSRichard Henderson */ 25397c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 25407c4ee5bcSRichard Henderson sp = QEMU_ALIGN_DOWN(sp, 16); 25417c4ee5bcSRichard Henderson } else { 25427c4ee5bcSRichard Henderson sp = QEMU_ALIGN_UP(sp, 16); 254315338fd7Sbellard } 254414322badSLaurent ALFONSI 254514322badSLaurent ALFONSI /* 2546c6a2377fSRichard Henderson * Generate 16 random bytes for userspace PRNG seeding. 254714322badSLaurent ALFONSI */ 2548c6a2377fSRichard Henderson qemu_guest_getrandom_nofail(k_rand_bytes, sizeof(k_rand_bytes)); 25497c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 255014322badSLaurent ALFONSI sp -= 16; 255114322badSLaurent ALFONSI u_rand_bytes = sp; 255214322badSLaurent ALFONSI /* FIXME - check return value of memcpy_to_target() for failure */ 255314322badSLaurent ALFONSI memcpy_to_target(sp, k_rand_bytes, 16); 25547c4ee5bcSRichard Henderson } else { 25557c4ee5bcSRichard Henderson memcpy_to_target(sp, k_rand_bytes, 16); 25567c4ee5bcSRichard Henderson u_rand_bytes = sp; 25577c4ee5bcSRichard Henderson sp += 16; 25587c4ee5bcSRichard Henderson } 255914322badSLaurent ALFONSI 256053a5960aSpbrook size = (DLINFO_ITEMS + 1) * 2; 2561fcdc0ab4SJiaxun Yang if (k_base_platform) 2562fcdc0ab4SJiaxun Yang size += 2; 256315338fd7Sbellard if (k_platform) 256453a5960aSpbrook size += 2; 2565f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS 256653a5960aSpbrook size += DLINFO_ARCH_ITEMS * 2; 2567f5155289Sbellard #endif 2568ad6919dcSPeter Maydell #ifdef ELF_HWCAP2 2569ad6919dcSPeter Maydell size += 2; 2570ad6919dcSPeter Maydell #endif 2571f516511eSPeter Maydell info->auxv_len = size * n; 2572f516511eSPeter Maydell 257353a5960aSpbrook size += envc + argc + 2; 2574b9329d4bSRichard Henderson size += 1; /* argc itself */ 257553a5960aSpbrook size *= n; 25767c4ee5bcSRichard Henderson 25777c4ee5bcSRichard Henderson /* Allocate space and finalize stack alignment for entry now. */ 25787c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 25797c4ee5bcSRichard Henderson u_argc = QEMU_ALIGN_DOWN(sp - size, STACK_ALIGNMENT); 25807c4ee5bcSRichard Henderson sp = u_argc; 25817c4ee5bcSRichard Henderson } else { 25827c4ee5bcSRichard Henderson u_argc = sp; 25837c4ee5bcSRichard Henderson sp = QEMU_ALIGN_UP(sp + size, STACK_ALIGNMENT); 25847c4ee5bcSRichard Henderson } 25857c4ee5bcSRichard Henderson 25867c4ee5bcSRichard Henderson u_argv = u_argc + n; 25877c4ee5bcSRichard Henderson u_envp = u_argv + (argc + 1) * n; 25887c4ee5bcSRichard Henderson u_auxv = u_envp + (envc + 1) * n; 25897c4ee5bcSRichard Henderson info->saved_auxv = u_auxv; 259060f1c801SRichard Henderson info->argc = argc; 259160f1c801SRichard Henderson info->envc = envc; 259260f1c801SRichard Henderson info->argv = u_argv; 259360f1c801SRichard Henderson info->envp = u_envp; 2594f5155289Sbellard 2595863cf0b7Sj_mayer /* This is correct because Linux defines 2596863cf0b7Sj_mayer * elf_addr_t as Elf32_Off / Elf64_Off 2597863cf0b7Sj_mayer */ 259853a5960aSpbrook #define NEW_AUX_ENT(id, val) do { \ 25997c4ee5bcSRichard Henderson put_user_ual(id, u_auxv); u_auxv += n; \ 26007c4ee5bcSRichard Henderson put_user_ual(val, u_auxv); u_auxv += n; \ 260153a5960aSpbrook } while(0) 26022f619698Sbellard 260382991bedSPeter Maydell #ifdef ARCH_DLINFO 260482991bedSPeter Maydell /* 260582991bedSPeter Maydell * ARCH_DLINFO must come first so platform specific code can enforce 260682991bedSPeter Maydell * special alignment requirements on the AUXV if necessary (eg. PPC). 260782991bedSPeter Maydell */ 260882991bedSPeter Maydell ARCH_DLINFO; 260982991bedSPeter Maydell #endif 2610f516511eSPeter Maydell /* There must be exactly DLINFO_ITEMS entries here, or the assert 2611f516511eSPeter Maydell * on info->auxv_len will trigger. 2612f516511eSPeter Maydell */ 26138e62a717SRichard Henderson NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff)); 2614992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); 2615992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); 261633143c44SLaurent Vivier if ((info->alignment & ~qemu_host_page_mask) != 0) { 261733143c44SLaurent Vivier /* Target doesn't support host page size alignment */ 261833143c44SLaurent Vivier NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE)); 261933143c44SLaurent Vivier } else { 262033143c44SLaurent Vivier NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE, 262133143c44SLaurent Vivier qemu_host_page_size))); 262233143c44SLaurent Vivier } 26238e62a717SRichard Henderson NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0)); 2624992f48a0Sblueswir1 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); 26258e62a717SRichard Henderson NEW_AUX_ENT(AT_ENTRY, info->entry); 2626992f48a0Sblueswir1 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); 2627992f48a0Sblueswir1 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); 2628992f48a0Sblueswir1 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); 2629992f48a0Sblueswir1 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); 2630992f48a0Sblueswir1 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); 2631a07c67dfSpbrook NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); 263214322badSLaurent ALFONSI NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes); 2633444cd5c3SMarco A L Barbosa NEW_AUX_ENT(AT_SECURE, (abi_ulong) qemu_getauxval(AT_SECURE)); 2634e0d1673dSLirong Yuan NEW_AUX_ENT(AT_EXECFN, info->file_string); 263514322badSLaurent ALFONSI 2636ad6919dcSPeter Maydell #ifdef ELF_HWCAP2 2637ad6919dcSPeter Maydell NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); 2638ad6919dcSPeter Maydell #endif 2639ad6919dcSPeter Maydell 2640fcdc0ab4SJiaxun Yang if (u_base_platform) { 2641fcdc0ab4SJiaxun Yang NEW_AUX_ENT(AT_BASE_PLATFORM, u_base_platform); 2642fcdc0ab4SJiaxun Yang } 26437c4ee5bcSRichard Henderson if (u_platform) { 264453a5960aSpbrook NEW_AUX_ENT(AT_PLATFORM, u_platform); 26457c4ee5bcSRichard Henderson } 26467c4ee5bcSRichard Henderson NEW_AUX_ENT (AT_NULL, 0); 2647f5155289Sbellard #undef NEW_AUX_ENT 2648f5155289Sbellard 2649f516511eSPeter Maydell /* Check that our initial calculation of the auxv length matches how much 2650f516511eSPeter Maydell * we actually put into it. 2651f516511eSPeter Maydell */ 2652f516511eSPeter Maydell assert(info->auxv_len == u_auxv - info->saved_auxv); 2653edf8e2afSMika Westerberg 26547c4ee5bcSRichard Henderson put_user_ual(argc, u_argc); 26557c4ee5bcSRichard Henderson 26567c4ee5bcSRichard Henderson p = info->arg_strings; 26577c4ee5bcSRichard Henderson for (i = 0; i < argc; ++i) { 26587c4ee5bcSRichard Henderson put_user_ual(p, u_argv); 26597c4ee5bcSRichard Henderson u_argv += n; 26607c4ee5bcSRichard Henderson p += target_strlen(p) + 1; 26617c4ee5bcSRichard Henderson } 26627c4ee5bcSRichard Henderson put_user_ual(0, u_argv); 26637c4ee5bcSRichard Henderson 26647c4ee5bcSRichard Henderson p = info->env_strings; 26657c4ee5bcSRichard Henderson for (i = 0; i < envc; ++i) { 26667c4ee5bcSRichard Henderson put_user_ual(p, u_envp); 26677c4ee5bcSRichard Henderson u_envp += n; 26687c4ee5bcSRichard Henderson p += target_strlen(p) + 1; 26697c4ee5bcSRichard Henderson } 26707c4ee5bcSRichard Henderson put_user_ual(0, u_envp); 26717c4ee5bcSRichard Henderson 267231e31b8aSbellard return sp; 267331e31b8aSbellard } 267431e31b8aSbellard 2675f5ef0e51SRichard Henderson #if defined(HI_COMMPAGE) 2676eee816c0SRichard Henderson #define LO_COMMPAGE -1 2677f5ef0e51SRichard Henderson #elif defined(LO_COMMPAGE) 267866346fafSRichard Henderson #define HI_COMMPAGE 0 2679f5ef0e51SRichard Henderson #else 2680f5ef0e51SRichard Henderson #define HI_COMMPAGE 0 2681eee816c0SRichard Henderson #define LO_COMMPAGE -1 2682d461b73eSRichard Henderson #ifndef INIT_GUEST_COMMPAGE 2683ee947430SAlex Bennée #define init_guest_commpage() true 2684ee947430SAlex Bennée #endif 2685d461b73eSRichard Henderson #endif 2686ee947430SAlex Bennée 268706f38c66SRichard Henderson /** 268806f38c66SRichard Henderson * pgb_try_mmap: 268906f38c66SRichard Henderson * @addr: host start address 269006f38c66SRichard Henderson * @addr_last: host last address 269106f38c66SRichard Henderson * @keep: do not unmap the probe region 269206f38c66SRichard Henderson * 269306f38c66SRichard Henderson * Return 1 if [@addr, @addr_last] is not mapped in the host, 269406f38c66SRichard Henderson * return 0 if it is not available to map, and -1 on mmap error. 269506f38c66SRichard Henderson * If @keep, the region is left mapped on success, otherwise unmapped. 269606f38c66SRichard Henderson */ 269706f38c66SRichard Henderson static int pgb_try_mmap(uintptr_t addr, uintptr_t addr_last, bool keep) 269806f38c66SRichard Henderson { 269906f38c66SRichard Henderson size_t size = addr_last - addr + 1; 270006f38c66SRichard Henderson void *p = mmap((void *)addr, size, PROT_NONE, 270106f38c66SRichard Henderson MAP_ANONYMOUS | MAP_PRIVATE | 270206f38c66SRichard Henderson MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); 270306f38c66SRichard Henderson int ret; 270406f38c66SRichard Henderson 270506f38c66SRichard Henderson if (p == MAP_FAILED) { 270606f38c66SRichard Henderson return errno == EEXIST ? 0 : -1; 270706f38c66SRichard Henderson } 270806f38c66SRichard Henderson ret = p == (void *)addr; 270906f38c66SRichard Henderson if (!keep || !ret) { 271006f38c66SRichard Henderson munmap(p, size); 271106f38c66SRichard Henderson } 271206f38c66SRichard Henderson return ret; 271306f38c66SRichard Henderson } 271406f38c66SRichard Henderson 271506f38c66SRichard Henderson /** 271606f38c66SRichard Henderson * pgb_try_mmap_skip_brk(uintptr_t addr, uintptr_t size, uintptr_t brk) 271706f38c66SRichard Henderson * @addr: host address 271806f38c66SRichard Henderson * @addr_last: host last address 271906f38c66SRichard Henderson * @brk: host brk 272006f38c66SRichard Henderson * 272106f38c66SRichard Henderson * Like pgb_try_mmap, but additionally reserve some memory following brk. 272206f38c66SRichard Henderson */ 272306f38c66SRichard Henderson static int pgb_try_mmap_skip_brk(uintptr_t addr, uintptr_t addr_last, 272406f38c66SRichard Henderson uintptr_t brk, bool keep) 272506f38c66SRichard Henderson { 272606f38c66SRichard Henderson uintptr_t brk_last = brk + 16 * MiB - 1; 272706f38c66SRichard Henderson 272806f38c66SRichard Henderson /* Do not map anything close to the host brk. */ 272906f38c66SRichard Henderson if (addr <= brk_last && brk <= addr_last) { 273006f38c66SRichard Henderson return 0; 273106f38c66SRichard Henderson } 273206f38c66SRichard Henderson return pgb_try_mmap(addr, addr_last, keep); 273306f38c66SRichard Henderson } 273406f38c66SRichard Henderson 273506f38c66SRichard Henderson /** 273606f38c66SRichard Henderson * pgb_try_mmap_set: 273706f38c66SRichard Henderson * @ga: set of guest addrs 273806f38c66SRichard Henderson * @base: guest_base 273906f38c66SRichard Henderson * @brk: host brk 274006f38c66SRichard Henderson * 274106f38c66SRichard Henderson * Return true if all @ga can be mapped by the host at @base. 274206f38c66SRichard Henderson * On success, retain the mapping at index 0 for reserved_va. 274306f38c66SRichard Henderson */ 274406f38c66SRichard Henderson 274506f38c66SRichard Henderson typedef struct PGBAddrs { 274606f38c66SRichard Henderson uintptr_t bounds[3][2]; /* start/last pairs */ 274706f38c66SRichard Henderson int nbounds; 274806f38c66SRichard Henderson } PGBAddrs; 274906f38c66SRichard Henderson 275006f38c66SRichard Henderson static bool pgb_try_mmap_set(const PGBAddrs *ga, uintptr_t base, uintptr_t brk) 275106f38c66SRichard Henderson { 275206f38c66SRichard Henderson for (int i = ga->nbounds - 1; i >= 0; --i) { 275306f38c66SRichard Henderson if (pgb_try_mmap_skip_brk(ga->bounds[i][0] + base, 275406f38c66SRichard Henderson ga->bounds[i][1] + base, 275506f38c66SRichard Henderson brk, i == 0 && reserved_va) <= 0) { 275606f38c66SRichard Henderson return false; 275706f38c66SRichard Henderson } 275806f38c66SRichard Henderson } 275906f38c66SRichard Henderson return true; 276006f38c66SRichard Henderson } 276106f38c66SRichard Henderson 276206f38c66SRichard Henderson /** 276306f38c66SRichard Henderson * pgb_addr_set: 276406f38c66SRichard Henderson * @ga: output set of guest addrs 276506f38c66SRichard Henderson * @guest_loaddr: guest image low address 276606f38c66SRichard Henderson * @guest_loaddr: guest image high address 276706f38c66SRichard Henderson * @identity: create for identity mapping 276806f38c66SRichard Henderson * 276906f38c66SRichard Henderson * Fill in @ga with the image, COMMPAGE and NULL page. 277006f38c66SRichard Henderson */ 277106f38c66SRichard Henderson static bool pgb_addr_set(PGBAddrs *ga, abi_ulong guest_loaddr, 277206f38c66SRichard Henderson abi_ulong guest_hiaddr, bool try_identity) 277306f38c66SRichard Henderson { 277406f38c66SRichard Henderson int n; 277506f38c66SRichard Henderson 277606f38c66SRichard Henderson /* 277706f38c66SRichard Henderson * With a low commpage, or a guest mapped very low, 277806f38c66SRichard Henderson * we may not be able to use the identity map. 277906f38c66SRichard Henderson */ 278006f38c66SRichard Henderson if (try_identity) { 278106f38c66SRichard Henderson if (LO_COMMPAGE != -1 && LO_COMMPAGE < mmap_min_addr) { 278206f38c66SRichard Henderson return false; 278306f38c66SRichard Henderson } 278406f38c66SRichard Henderson if (guest_loaddr != 0 && guest_loaddr < mmap_min_addr) { 278506f38c66SRichard Henderson return false; 278606f38c66SRichard Henderson } 278706f38c66SRichard Henderson } 278806f38c66SRichard Henderson 278906f38c66SRichard Henderson memset(ga, 0, sizeof(*ga)); 279006f38c66SRichard Henderson n = 0; 279106f38c66SRichard Henderson 279206f38c66SRichard Henderson if (reserved_va) { 279306f38c66SRichard Henderson ga->bounds[n][0] = try_identity ? mmap_min_addr : 0; 279406f38c66SRichard Henderson ga->bounds[n][1] = reserved_va; 279506f38c66SRichard Henderson n++; 279606f38c66SRichard Henderson /* LO_COMMPAGE and NULL handled by reserving from 0. */ 279706f38c66SRichard Henderson } else { 279806f38c66SRichard Henderson /* Add any LO_COMMPAGE or NULL page. */ 279906f38c66SRichard Henderson if (LO_COMMPAGE != -1) { 280006f38c66SRichard Henderson ga->bounds[n][0] = 0; 280106f38c66SRichard Henderson ga->bounds[n][1] = LO_COMMPAGE + TARGET_PAGE_SIZE - 1; 280206f38c66SRichard Henderson n++; 280306f38c66SRichard Henderson } else if (!try_identity) { 280406f38c66SRichard Henderson ga->bounds[n][0] = 0; 280506f38c66SRichard Henderson ga->bounds[n][1] = TARGET_PAGE_SIZE - 1; 280606f38c66SRichard Henderson n++; 280706f38c66SRichard Henderson } 280806f38c66SRichard Henderson 280906f38c66SRichard Henderson /* Add the guest image for ET_EXEC. */ 281006f38c66SRichard Henderson if (guest_loaddr) { 281106f38c66SRichard Henderson ga->bounds[n][0] = guest_loaddr; 281206f38c66SRichard Henderson ga->bounds[n][1] = guest_hiaddr; 281306f38c66SRichard Henderson n++; 281406f38c66SRichard Henderson } 281506f38c66SRichard Henderson } 281606f38c66SRichard Henderson 281706f38c66SRichard Henderson /* 281806f38c66SRichard Henderson * Temporarily disable 281906f38c66SRichard Henderson * "comparison is always false due to limited range of data type" 282006f38c66SRichard Henderson * due to comparison between unsigned and (possible) 0. 282106f38c66SRichard Henderson */ 282206f38c66SRichard Henderson #pragma GCC diagnostic push 282306f38c66SRichard Henderson #pragma GCC diagnostic ignored "-Wtype-limits" 282406f38c66SRichard Henderson 282506f38c66SRichard Henderson /* Add any HI_COMMPAGE not covered by reserved_va. */ 282606f38c66SRichard Henderson if (reserved_va < HI_COMMPAGE) { 282706f38c66SRichard Henderson ga->bounds[n][0] = HI_COMMPAGE & qemu_host_page_mask; 282806f38c66SRichard Henderson ga->bounds[n][1] = HI_COMMPAGE + TARGET_PAGE_SIZE - 1; 282906f38c66SRichard Henderson n++; 283006f38c66SRichard Henderson } 283106f38c66SRichard Henderson 283206f38c66SRichard Henderson #pragma GCC diagnostic pop 283306f38c66SRichard Henderson 283406f38c66SRichard Henderson ga->nbounds = n; 283506f38c66SRichard Henderson return true; 283606f38c66SRichard Henderson } 283706f38c66SRichard Henderson 2838ee947430SAlex Bennée static void pgb_fail_in_use(const char *image_name) 2839ee947430SAlex Bennée { 2840ee947430SAlex Bennée error_report("%s: requires virtual address space that is in use " 2841ee947430SAlex Bennée "(omit the -B option or choose a different value)", 2842ee947430SAlex Bennée image_name); 2843ee947430SAlex Bennée exit(EXIT_FAILURE); 2844ee947430SAlex Bennée } 2845ee947430SAlex Bennée 284606f38c66SRichard Henderson static void pgb_fixed(const char *image_name, uintptr_t guest_loaddr, 284706f38c66SRichard Henderson uintptr_t guest_hiaddr, uintptr_t align) 2848ee947430SAlex Bennée { 284906f38c66SRichard Henderson PGBAddrs ga; 285006f38c66SRichard Henderson uintptr_t brk = (uintptr_t)sbrk(0); 2851ee947430SAlex Bennée 2852ee947430SAlex Bennée if (!QEMU_IS_ALIGNED(guest_base, align)) { 28535ca870b9SRichard Henderson fprintf(stderr, "Requested guest base %p does not satisfy " 285406f38c66SRichard Henderson "host minimum alignment (0x%" PRIxPTR ")\n", 28555ca870b9SRichard Henderson (void *)guest_base, align); 2856ee947430SAlex Bennée exit(EXIT_FAILURE); 2857ee947430SAlex Bennée } 2858ee947430SAlex Bennée 285906f38c66SRichard Henderson if (!pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, !guest_base) 286006f38c66SRichard Henderson || !pgb_try_mmap_set(&ga, guest_base, brk)) { 2861ee947430SAlex Bennée pgb_fail_in_use(image_name); 2862ee947430SAlex Bennée } 2863ee947430SAlex Bennée } 2864ee947430SAlex Bennée 2865ad592e37SAlex Bennée /** 2866dd558855SRichard Henderson * pgb_find_fallback: 2867ad592e37SAlex Bennée * 2868dd558855SRichard Henderson * This is a fallback method for finding holes in the host address space 2869dd558855SRichard Henderson * if we don't have the benefit of being able to access /proc/self/map. 2870dd558855SRichard Henderson * It can potentially take a very long time as we can only dumbly iterate 2871dd558855SRichard Henderson * up the host address space seeing if the allocation would work. 2872ad592e37SAlex Bennée */ 2873dd558855SRichard Henderson static uintptr_t pgb_find_fallback(const PGBAddrs *ga, uintptr_t align, 2874dd558855SRichard Henderson uintptr_t brk) 2875ad592e37SAlex Bennée { 2876dd558855SRichard Henderson /* TODO: come up with a better estimate of how much to skip. */ 2877dd558855SRichard Henderson uintptr_t skip = sizeof(uintptr_t) == 4 ? MiB : GiB; 2878ad592e37SAlex Bennée 2879dd558855SRichard Henderson for (uintptr_t base = skip; ; base += skip) { 2880dd558855SRichard Henderson base = ROUND_UP(base, align); 2881dd558855SRichard Henderson if (pgb_try_mmap_set(ga, base, brk)) { 2882dd558855SRichard Henderson return base; 2883dd558855SRichard Henderson } 2884dd558855SRichard Henderson if (base >= -skip) { 2885dd558855SRichard Henderson return -1; 2886dd558855SRichard Henderson } 2887dd558855SRichard Henderson } 2888dd558855SRichard Henderson } 2889dd558855SRichard Henderson 2890dd558855SRichard Henderson static uintptr_t pgb_try_itree(const PGBAddrs *ga, uintptr_t base, 2891dd558855SRichard Henderson IntervalTreeRoot *root) 2892dd558855SRichard Henderson { 2893dd558855SRichard Henderson for (int i = ga->nbounds - 1; i >= 0; --i) { 2894dd558855SRichard Henderson uintptr_t s = base + ga->bounds[i][0]; 2895dd558855SRichard Henderson uintptr_t l = base + ga->bounds[i][1]; 2896dd558855SRichard Henderson IntervalTreeNode *n; 2897dd558855SRichard Henderson 2898dd558855SRichard Henderson if (l < s) { 2899dd558855SRichard Henderson /* Wraparound. Skip to advance S to mmap_min_addr. */ 2900dd558855SRichard Henderson return mmap_min_addr - s; 2901dd558855SRichard Henderson } 2902dd558855SRichard Henderson 2903dd558855SRichard Henderson n = interval_tree_iter_first(root, s, l); 2904dd558855SRichard Henderson if (n != NULL) { 2905dd558855SRichard Henderson /* Conflict. Skip to advance S to LAST + 1. */ 2906dd558855SRichard Henderson return n->last - s + 1; 2907dd558855SRichard Henderson } 2908dd558855SRichard Henderson } 2909dd558855SRichard Henderson return 0; /* success */ 2910dd558855SRichard Henderson } 2911dd558855SRichard Henderson 2912dd558855SRichard Henderson static uintptr_t pgb_find_itree(const PGBAddrs *ga, IntervalTreeRoot *root, 2913dd558855SRichard Henderson uintptr_t align, uintptr_t brk) 2914dd558855SRichard Henderson { 2915dd558855SRichard Henderson uintptr_t last = mmap_min_addr; 2916dd558855SRichard Henderson uintptr_t base, skip; 2917ad592e37SAlex Bennée 2918ad592e37SAlex Bennée while (true) { 2919dd558855SRichard Henderson base = ROUND_UP(last, align); 2920dd558855SRichard Henderson if (base < last) { 2921ad592e37SAlex Bennée return -1; 2922ad592e37SAlex Bennée } 2923dd558855SRichard Henderson 2924dd558855SRichard Henderson skip = pgb_try_itree(ga, base, root); 2925dd558855SRichard Henderson if (skip == 0) { 2926dd558855SRichard Henderson break; 29272667e069SAlex Bennée } 2928dd558855SRichard Henderson 2929dd558855SRichard Henderson last = base + skip; 2930dd558855SRichard Henderson if (last < base) { 2931dd558855SRichard Henderson return -1; 2932ad592e37SAlex Bennée } 2933ad592e37SAlex Bennée } 2934ad592e37SAlex Bennée 2935dd558855SRichard Henderson /* 2936dd558855SRichard Henderson * We've chosen 'base' based on holes in the interval tree, 2937dd558855SRichard Henderson * but we don't yet know if it is a valid host address. 2938dd558855SRichard Henderson * Because it is the first matching hole, if the host addresses 2939dd558855SRichard Henderson * are invalid we know there are no further matches. 2940dd558855SRichard Henderson */ 2941dd558855SRichard Henderson return pgb_try_mmap_set(ga, base, brk) ? base : -1; 2942dd558855SRichard Henderson } 2943dd558855SRichard Henderson 2944dd558855SRichard Henderson static void pgb_dynamic(const char *image_name, uintptr_t guest_loaddr, 2945dd558855SRichard Henderson uintptr_t guest_hiaddr, uintptr_t align) 2946ee947430SAlex Bennée { 2947dd558855SRichard Henderson IntervalTreeRoot *root; 2948dd558855SRichard Henderson uintptr_t brk, ret; 2949dd558855SRichard Henderson PGBAddrs ga; 2950ee947430SAlex Bennée 2951ee947430SAlex Bennée assert(QEMU_IS_ALIGNED(guest_loaddr, align)); 2952ee947430SAlex Bennée 2953dd558855SRichard Henderson /* Try the identity map first. */ 2954dd558855SRichard Henderson if (pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, true)) { 2955dd558855SRichard Henderson brk = (uintptr_t)sbrk(0); 2956dd558855SRichard Henderson if (pgb_try_mmap_set(&ga, 0, brk)) { 2957dd558855SRichard Henderson guest_base = 0; 2958dd558855SRichard Henderson return; 2959dd558855SRichard Henderson } 2960dd558855SRichard Henderson } 2961dd558855SRichard Henderson 2962dd558855SRichard Henderson /* 2963dd558855SRichard Henderson * Rebuild the address set for non-identity map. 2964dd558855SRichard Henderson * This differs in the mapping of the guest NULL page. 2965dd558855SRichard Henderson */ 2966dd558855SRichard Henderson pgb_addr_set(&ga, guest_loaddr, guest_hiaddr, false); 2967dd558855SRichard Henderson 2968dd558855SRichard Henderson root = read_self_maps(); 2969ee947430SAlex Bennée 2970ee947430SAlex Bennée /* Read brk after we've read the maps, which will malloc. */ 2971ee947430SAlex Bennée brk = (uintptr_t)sbrk(0); 2972ee947430SAlex Bennée 2973dd558855SRichard Henderson if (!root) { 2974dd558855SRichard Henderson ret = pgb_find_fallback(&ga, align, brk); 2975ee947430SAlex Bennée } else { 2976ee947430SAlex Bennée /* 2977dd558855SRichard Henderson * Reserve the area close to the host brk. 2978dd558855SRichard Henderson * This will be freed with the rest of the tree. 2979ee947430SAlex Bennée */ 2980dd558855SRichard Henderson IntervalTreeNode *b = g_new0(IntervalTreeNode, 1); 2981dd558855SRichard Henderson b->start = brk; 2982dd558855SRichard Henderson b->last = brk + 16 * MiB - 1; 2983dd558855SRichard Henderson interval_tree_insert(b, root); 2984dd558855SRichard Henderson 2985dd558855SRichard Henderson ret = pgb_find_itree(&ga, root, align, brk); 2986dd558855SRichard Henderson free_self_maps(root); 2987ee947430SAlex Bennée } 2988ee947430SAlex Bennée 2989dd558855SRichard Henderson if (ret == -1) { 2990dd558855SRichard Henderson int w = TARGET_LONG_BITS / 4; 2991dd558855SRichard Henderson 2992dd558855SRichard Henderson error_report("%s: Unable to find a guest_base to satisfy all " 2993dd558855SRichard Henderson "guest address mapping requirements", image_name); 2994dd558855SRichard Henderson 2995dd558855SRichard Henderson for (int i = 0; i < ga.nbounds; ++i) { 2996dd558855SRichard Henderson error_printf(" %0*" PRIx64 "-%0*" PRIx64 "\n", 2997dd558855SRichard Henderson w, (uint64_t)ga.bounds[i][0], 2998dd558855SRichard Henderson w, (uint64_t)ga.bounds[i][1]); 2999dd558855SRichard Henderson } 3000ee947430SAlex Bennée exit(EXIT_FAILURE); 3001ee947430SAlex Bennée } 3002dd558855SRichard Henderson guest_base = ret; 3003ee947430SAlex Bennée } 3004ee947430SAlex Bennée 3005ee947430SAlex Bennée void probe_guest_base(const char *image_name, abi_ulong guest_loaddr, 3006ee947430SAlex Bennée abi_ulong guest_hiaddr) 3007dce10401SMeador Inge { 300830ab9ef2SRichard Henderson /* In order to use host shmat, we must be able to honor SHMLBA. */ 3009ee947430SAlex Bennée uintptr_t align = MAX(SHMLBA, qemu_host_page_size); 3010dce10401SMeador Inge 30110c441aebSRichard Henderson /* Sanity check the guest binary. */ 30120c441aebSRichard Henderson if (reserved_va) { 30130c441aebSRichard Henderson if (guest_hiaddr > reserved_va) { 30140c441aebSRichard Henderson error_report("%s: requires more than reserved virtual " 30150c441aebSRichard Henderson "address space (0x%" PRIx64 " > 0x%lx)", 30160c441aebSRichard Henderson image_name, (uint64_t)guest_hiaddr, reserved_va); 30170c441aebSRichard Henderson exit(EXIT_FAILURE); 30180c441aebSRichard Henderson } 30190c441aebSRichard Henderson } else { 30200c441aebSRichard Henderson if (guest_hiaddr != (uintptr_t)guest_hiaddr) { 30210c441aebSRichard Henderson error_report("%s: requires more virtual address space " 30220c441aebSRichard Henderson "than the host can provide (0x%" PRIx64 ")", 30230c441aebSRichard Henderson image_name, (uint64_t)guest_hiaddr + 1); 30240c441aebSRichard Henderson exit(EXIT_FAILURE); 30250c441aebSRichard Henderson } 30260c441aebSRichard Henderson } 30270c441aebSRichard Henderson 3028ee947430SAlex Bennée if (have_guest_base) { 302906f38c66SRichard Henderson pgb_fixed(image_name, guest_loaddr, guest_hiaddr, align); 3030293f2060SLuke Shumaker } else { 3031dd558855SRichard Henderson pgb_dynamic(image_name, guest_loaddr, guest_hiaddr, align); 3032806d1021SMeador Inge } 3033806d1021SMeador Inge 3034ee947430SAlex Bennée /* Reserve and initialize the commpage. */ 3035ee947430SAlex Bennée if (!init_guest_commpage()) { 303606f38c66SRichard Henderson /* We have already probed for the commpage being free. */ 303706f38c66SRichard Henderson g_assert_not_reached(); 3038dce10401SMeador Inge } 3039dce10401SMeador Inge 3040ee947430SAlex Bennée assert(QEMU_IS_ALIGNED(guest_base, align)); 3041ee947430SAlex Bennée qemu_log_mask(CPU_LOG_PAGE, "Locating guest address space " 3042ee947430SAlex Bennée "@ 0x%" PRIx64 "\n", (uint64_t)guest_base); 3043dce10401SMeador Inge } 3044dce10401SMeador Inge 304583f990ebSRichard Henderson enum { 304683f990ebSRichard Henderson /* The string "GNU\0" as a magic number. */ 304783f990ebSRichard Henderson GNU0_MAGIC = const_le32('G' | 'N' << 8 | 'U' << 16), 304883f990ebSRichard Henderson NOTE_DATA_SZ = 1 * KiB, 304983f990ebSRichard Henderson NOTE_NAME_SZ = 4, 305083f990ebSRichard Henderson ELF_GNU_PROPERTY_ALIGN = ELF_CLASS == ELFCLASS32 ? 4 : 8, 305183f990ebSRichard Henderson }; 305283f990ebSRichard Henderson 305383f990ebSRichard Henderson /* 305483f990ebSRichard Henderson * Process a single gnu_property entry. 305583f990ebSRichard Henderson * Return false for error. 305683f990ebSRichard Henderson */ 305783f990ebSRichard Henderson static bool parse_elf_property(const uint32_t *data, int *off, int datasz, 305883f990ebSRichard Henderson struct image_info *info, bool have_prev_type, 305983f990ebSRichard Henderson uint32_t *prev_type, Error **errp) 306083f990ebSRichard Henderson { 306183f990ebSRichard Henderson uint32_t pr_type, pr_datasz, step; 306283f990ebSRichard Henderson 306383f990ebSRichard Henderson if (*off > datasz || !QEMU_IS_ALIGNED(*off, ELF_GNU_PROPERTY_ALIGN)) { 306483f990ebSRichard Henderson goto error_data; 306583f990ebSRichard Henderson } 306683f990ebSRichard Henderson datasz -= *off; 306783f990ebSRichard Henderson data += *off / sizeof(uint32_t); 306883f990ebSRichard Henderson 306983f990ebSRichard Henderson if (datasz < 2 * sizeof(uint32_t)) { 307083f990ebSRichard Henderson goto error_data; 307183f990ebSRichard Henderson } 307283f990ebSRichard Henderson pr_type = data[0]; 307383f990ebSRichard Henderson pr_datasz = data[1]; 307483f990ebSRichard Henderson data += 2; 307583f990ebSRichard Henderson datasz -= 2 * sizeof(uint32_t); 307683f990ebSRichard Henderson step = ROUND_UP(pr_datasz, ELF_GNU_PROPERTY_ALIGN); 307783f990ebSRichard Henderson if (step > datasz) { 307883f990ebSRichard Henderson goto error_data; 307983f990ebSRichard Henderson } 308083f990ebSRichard Henderson 308183f990ebSRichard Henderson /* Properties are supposed to be unique and sorted on pr_type. */ 308283f990ebSRichard Henderson if (have_prev_type && pr_type <= *prev_type) { 308383f990ebSRichard Henderson if (pr_type == *prev_type) { 308483f990ebSRichard Henderson error_setg(errp, "Duplicate property in PT_GNU_PROPERTY"); 308583f990ebSRichard Henderson } else { 308683f990ebSRichard Henderson error_setg(errp, "Unsorted property in PT_GNU_PROPERTY"); 308783f990ebSRichard Henderson } 308883f990ebSRichard Henderson return false; 308983f990ebSRichard Henderson } 309083f990ebSRichard Henderson *prev_type = pr_type; 309183f990ebSRichard Henderson 309283f990ebSRichard Henderson if (!arch_parse_elf_property(pr_type, pr_datasz, data, info, errp)) { 309383f990ebSRichard Henderson return false; 309483f990ebSRichard Henderson } 309583f990ebSRichard Henderson 309683f990ebSRichard Henderson *off += 2 * sizeof(uint32_t) + step; 309783f990ebSRichard Henderson return true; 309883f990ebSRichard Henderson 309983f990ebSRichard Henderson error_data: 310083f990ebSRichard Henderson error_setg(errp, "Ill-formed property in PT_GNU_PROPERTY"); 310183f990ebSRichard Henderson return false; 310283f990ebSRichard Henderson } 310383f990ebSRichard Henderson 310483f990ebSRichard Henderson /* Process NT_GNU_PROPERTY_TYPE_0. */ 3105*3bd02386SRichard Henderson static bool parse_elf_properties(const ImageSource *src, 310683f990ebSRichard Henderson struct image_info *info, 310783f990ebSRichard Henderson const struct elf_phdr *phdr, 310883f990ebSRichard Henderson Error **errp) 310983f990ebSRichard Henderson { 311083f990ebSRichard Henderson union { 311183f990ebSRichard Henderson struct elf_note nhdr; 311283f990ebSRichard Henderson uint32_t data[NOTE_DATA_SZ / sizeof(uint32_t)]; 311383f990ebSRichard Henderson } note; 311483f990ebSRichard Henderson 311583f990ebSRichard Henderson int n, off, datasz; 311683f990ebSRichard Henderson bool have_prev_type; 311783f990ebSRichard Henderson uint32_t prev_type; 311883f990ebSRichard Henderson 311983f990ebSRichard Henderson /* Unless the arch requires properties, ignore them. */ 312083f990ebSRichard Henderson if (!ARCH_USE_GNU_PROPERTY) { 312183f990ebSRichard Henderson return true; 312283f990ebSRichard Henderson } 312383f990ebSRichard Henderson 312483f990ebSRichard Henderson /* If the properties are crazy large, that's too bad. */ 312583f990ebSRichard Henderson n = phdr->p_filesz; 312683f990ebSRichard Henderson if (n > sizeof(note)) { 312783f990ebSRichard Henderson error_setg(errp, "PT_GNU_PROPERTY too large"); 312883f990ebSRichard Henderson return false; 312983f990ebSRichard Henderson } 313083f990ebSRichard Henderson if (n < sizeof(note.nhdr)) { 313183f990ebSRichard Henderson error_setg(errp, "PT_GNU_PROPERTY too small"); 313283f990ebSRichard Henderson return false; 313383f990ebSRichard Henderson } 313483f990ebSRichard Henderson 3135*3bd02386SRichard Henderson if (!imgsrc_read(¬e, phdr->p_offset, n, src, errp)) { 313683f990ebSRichard Henderson return false; 313783f990ebSRichard Henderson } 313883f990ebSRichard Henderson 313983f990ebSRichard Henderson /* 314083f990ebSRichard Henderson * The contents of a valid PT_GNU_PROPERTY is a sequence 314183f990ebSRichard Henderson * of uint32_t -- swap them all now. 314283f990ebSRichard Henderson */ 314383f990ebSRichard Henderson #ifdef BSWAP_NEEDED 314483f990ebSRichard Henderson for (int i = 0; i < n / 4; i++) { 314583f990ebSRichard Henderson bswap32s(note.data + i); 314683f990ebSRichard Henderson } 314783f990ebSRichard Henderson #endif 314883f990ebSRichard Henderson 314983f990ebSRichard Henderson /* 315083f990ebSRichard Henderson * Note that nhdr is 3 words, and that the "name" described by namesz 315183f990ebSRichard Henderson * immediately follows nhdr and is thus at the 4th word. Further, all 315283f990ebSRichard Henderson * of the inputs to the kernel's round_up are multiples of 4. 315383f990ebSRichard Henderson */ 315483f990ebSRichard Henderson if (note.nhdr.n_type != NT_GNU_PROPERTY_TYPE_0 || 315583f990ebSRichard Henderson note.nhdr.n_namesz != NOTE_NAME_SZ || 315683f990ebSRichard Henderson note.data[3] != GNU0_MAGIC) { 315783f990ebSRichard Henderson error_setg(errp, "Invalid note in PT_GNU_PROPERTY"); 315883f990ebSRichard Henderson return false; 315983f990ebSRichard Henderson } 316083f990ebSRichard Henderson off = sizeof(note.nhdr) + NOTE_NAME_SZ; 316183f990ebSRichard Henderson 316283f990ebSRichard Henderson datasz = note.nhdr.n_descsz + off; 316383f990ebSRichard Henderson if (datasz > n) { 316483f990ebSRichard Henderson error_setg(errp, "Invalid note size in PT_GNU_PROPERTY"); 316583f990ebSRichard Henderson return false; 316683f990ebSRichard Henderson } 316783f990ebSRichard Henderson 316883f990ebSRichard Henderson have_prev_type = false; 316983f990ebSRichard Henderson prev_type = 0; 317083f990ebSRichard Henderson while (1) { 317183f990ebSRichard Henderson if (off == datasz) { 317283f990ebSRichard Henderson return true; /* end, exit ok */ 317383f990ebSRichard Henderson } 317483f990ebSRichard Henderson if (!parse_elf_property(note.data, &off, datasz, info, 317583f990ebSRichard Henderson have_prev_type, &prev_type, errp)) { 317683f990ebSRichard Henderson return false; 317783f990ebSRichard Henderson } 317883f990ebSRichard Henderson have_prev_type = true; 317983f990ebSRichard Henderson } 318083f990ebSRichard Henderson } 318183f990ebSRichard Henderson 3182*3bd02386SRichard Henderson /** 3183*3bd02386SRichard Henderson * load_elf_image: Load an ELF image into the address space. 3184*3bd02386SRichard Henderson * @image_name: the filename of the image, to use in error messages. 3185*3bd02386SRichard Henderson * @src: the ImageSource from which to read. 3186*3bd02386SRichard Henderson * @info: info collected from the loaded image. 3187*3bd02386SRichard Henderson * @ehdr: the ELF header, not yet bswapped. 3188*3bd02386SRichard Henderson * @pinterp_name: record any PT_INTERP string found. 3189*3bd02386SRichard Henderson * 3190*3bd02386SRichard Henderson * On return: @info values will be filled in, as necessary or available. 3191*3bd02386SRichard Henderson */ 319231e31b8aSbellard 3193*3bd02386SRichard Henderson static void load_elf_image(const char *image_name, const ImageSource *src, 319440d487eeSRichard Henderson struct image_info *info, struct elfhdr *ehdr, 3195*3bd02386SRichard Henderson char **pinterp_name) 319631e31b8aSbellard { 3197*3bd02386SRichard Henderson g_autofree struct elf_phdr *phdr = NULL; 31988e62a717SRichard Henderson abi_ulong load_addr, load_bias, loaddr, hiaddr, error; 3199*3bd02386SRichard Henderson int i, prot_exec; 3200c7f17e7bSRichard Henderson Error *err = NULL; 320131e31b8aSbellard 3202*3bd02386SRichard Henderson /* 3203*3bd02386SRichard Henderson * First of all, some simple consistency checks. 3204*3bd02386SRichard Henderson * Note that we rely on the bswapped ehdr staying in bprm_buf, 3205*3bd02386SRichard Henderson * for later use by load_elf_binary and create_elf_tables. 3206*3bd02386SRichard Henderson */ 3207*3bd02386SRichard Henderson if (!imgsrc_read(ehdr, 0, sizeof(*ehdr), src, &err)) { 3208*3bd02386SRichard Henderson goto exit_errmsg; 3209*3bd02386SRichard Henderson } 32108e62a717SRichard Henderson if (!elf_check_ident(ehdr)) { 3211c7f17e7bSRichard Henderson error_setg(&err, "Invalid ELF image for this architecture"); 32128e62a717SRichard Henderson goto exit_errmsg; 32138e62a717SRichard Henderson } 32148e62a717SRichard Henderson bswap_ehdr(ehdr); 32158e62a717SRichard Henderson if (!elf_check_ehdr(ehdr)) { 3216c7f17e7bSRichard Henderson error_setg(&err, "Invalid ELF image for this architecture"); 32178e62a717SRichard Henderson goto exit_errmsg; 321831e31b8aSbellard } 321931e31b8aSbellard 3220*3bd02386SRichard Henderson phdr = imgsrc_read_alloc(ehdr->e_phoff, 3221*3bd02386SRichard Henderson ehdr->e_phnum * sizeof(struct elf_phdr), 3222*3bd02386SRichard Henderson src, &err); 3223*3bd02386SRichard Henderson if (phdr == NULL) { 3224*3bd02386SRichard Henderson goto exit_errmsg; 322531e31b8aSbellard } 32268e62a717SRichard Henderson bswap_phdr(phdr, ehdr->e_phnum); 322709bfb054Sbellard 32281af02e83SMike Frysinger info->nsegs = 0; 32291af02e83SMike Frysinger info->pt_dynamic_addr = 0; 32301af02e83SMike Frysinger 323198c1076cSAlex Bennée mmap_lock(); 323298c1076cSAlex Bennée 32338a1a5274SRichard Henderson /* 32348a1a5274SRichard Henderson * Find the maximum size of the image and allocate an appropriate 32358a1a5274SRichard Henderson * amount of memory to handle that. Locate the interpreter, if any. 32368a1a5274SRichard Henderson */ 3237682674b8SRichard Henderson loaddr = -1, hiaddr = 0; 323833143c44SLaurent Vivier info->alignment = 0; 3239872f3d04SRichard Henderson info->exec_stack = EXSTACK_DEFAULT; 32408e62a717SRichard Henderson for (i = 0; i < ehdr->e_phnum; ++i) { 32414d9d535aSRichard Henderson struct elf_phdr *eppnt = phdr + i; 32424d9d535aSRichard Henderson if (eppnt->p_type == PT_LOAD) { 32434d9d535aSRichard Henderson abi_ulong a = eppnt->p_vaddr - eppnt->p_offset; 3244682674b8SRichard Henderson if (a < loaddr) { 3245682674b8SRichard Henderson loaddr = a; 3246682674b8SRichard Henderson } 3247a3a67f54SRichard Henderson a = eppnt->p_vaddr + eppnt->p_memsz - 1; 3248682674b8SRichard Henderson if (a > hiaddr) { 3249682674b8SRichard Henderson hiaddr = a; 3250682674b8SRichard Henderson } 32511af02e83SMike Frysinger ++info->nsegs; 32524d9d535aSRichard Henderson info->alignment |= eppnt->p_align; 32538a1a5274SRichard Henderson } else if (eppnt->p_type == PT_INTERP && pinterp_name) { 32548a1a5274SRichard Henderson g_autofree char *interp_name = NULL; 32558a1a5274SRichard Henderson 32568a1a5274SRichard Henderson if (*pinterp_name) { 3257c7f17e7bSRichard Henderson error_setg(&err, "Multiple PT_INTERP entries"); 32588a1a5274SRichard Henderson goto exit_errmsg; 32598a1a5274SRichard Henderson } 3260c7f17e7bSRichard Henderson 3261*3bd02386SRichard Henderson interp_name = imgsrc_read_alloc(eppnt->p_offset, eppnt->p_filesz, 3262*3bd02386SRichard Henderson src, &err); 3263*3bd02386SRichard Henderson if (interp_name == NULL) { 3264*3bd02386SRichard Henderson goto exit_errmsg; 32658a1a5274SRichard Henderson } 32668a1a5274SRichard Henderson if (interp_name[eppnt->p_filesz - 1] != 0) { 3267c7f17e7bSRichard Henderson error_setg(&err, "Invalid PT_INTERP entry"); 32688a1a5274SRichard Henderson goto exit_errmsg; 32698a1a5274SRichard Henderson } 32708a1a5274SRichard Henderson *pinterp_name = g_steal_pointer(&interp_name); 327183f990ebSRichard Henderson } else if (eppnt->p_type == PT_GNU_PROPERTY) { 3272*3bd02386SRichard Henderson if (!parse_elf_properties(src, info, eppnt, &err)) { 327383f990ebSRichard Henderson goto exit_errmsg; 327483f990ebSRichard Henderson } 3275872f3d04SRichard Henderson } else if (eppnt->p_type == PT_GNU_STACK) { 3276872f3d04SRichard Henderson info->exec_stack = eppnt->p_flags & PF_X; 3277682674b8SRichard Henderson } 3278682674b8SRichard Henderson } 3279682674b8SRichard Henderson 32801ea06dedSRichard Henderson load_addr = loaddr; 32811ea06dedSRichard Henderson 32826fd59449SRichard Henderson if (pinterp_name != NULL) { 32836fd59449SRichard Henderson if (ehdr->e_type == ET_EXEC) { 32846fd59449SRichard Henderson /* 32856fd59449SRichard Henderson * Make sure that the low address does not conflict with 32866fd59449SRichard Henderson * MMAP_MIN_ADDR or the QEMU application itself. 32876fd59449SRichard Henderson */ 32886fd59449SRichard Henderson probe_guest_base(image_name, loaddr, hiaddr); 3289ee947430SAlex Bennée } else { 32901ea06dedSRichard Henderson abi_ulong align; 32911ea06dedSRichard Henderson 3292ee947430SAlex Bennée /* 3293ee947430SAlex Bennée * The binary is dynamic, but we still need to 3294ee947430SAlex Bennée * select guest_base. In this case we pass a size. 3295ee947430SAlex Bennée */ 3296ee947430SAlex Bennée probe_guest_base(image_name, 0, hiaddr - loaddr); 32971ea06dedSRichard Henderson 32981ea06dedSRichard Henderson /* 32991ea06dedSRichard Henderson * Avoid collision with the loader by providing a different 33001ea06dedSRichard Henderson * default load address. 33011ea06dedSRichard Henderson */ 33021ea06dedSRichard Henderson load_addr += elf_et_dyn_base; 33031ea06dedSRichard Henderson 33041ea06dedSRichard Henderson /* 33051ea06dedSRichard Henderson * TODO: Better support for mmap alignment is desirable. 33061ea06dedSRichard Henderson * Since we do not have complete control over the guest 33071ea06dedSRichard Henderson * address space, we prefer the kernel to choose some address 33081ea06dedSRichard Henderson * rather than force the use of LOAD_ADDR via MAP_FIXED. 33091ea06dedSRichard Henderson * But without MAP_FIXED we cannot guarantee alignment, 33101ea06dedSRichard Henderson * only suggest it. 33111ea06dedSRichard Henderson */ 33121ea06dedSRichard Henderson align = pow2ceil(info->alignment); 33131ea06dedSRichard Henderson if (align) { 33141ea06dedSRichard Henderson load_addr &= -align; 33151ea06dedSRichard Henderson } 33166fd59449SRichard Henderson } 33176fd59449SRichard Henderson } 33186fd59449SRichard Henderson 33196fd59449SRichard Henderson /* 33206fd59449SRichard Henderson * Reserve address space for all of this. 33216fd59449SRichard Henderson * 3322ad25051bSRichard Henderson * In the case of ET_EXEC, we supply MAP_FIXED_NOREPLACE so that we get 3323ad25051bSRichard Henderson * exactly the address range that is required. Without reserved_va, 3324ad25051bSRichard Henderson * the guest address space is not isolated. We have attempted to avoid 3325ad25051bSRichard Henderson * conflict with the host program itself via probe_guest_base, but using 3326ad25051bSRichard Henderson * MAP_FIXED_NOREPLACE instead of MAP_FIXED provides an extra check. 33276fd59449SRichard Henderson * 33286fd59449SRichard Henderson * Otherwise this is ET_DYN, and we are searching for a location 33296fd59449SRichard Henderson * that can hold the memory space required. If the image is 33301ea06dedSRichard Henderson * pre-linked, LOAD_ADDR will be non-zero, and the kernel should 33316fd59449SRichard Henderson * honor that address if it happens to be free. 33326fd59449SRichard Henderson * 33336fd59449SRichard Henderson * In both cases, we will overwrite pages in this range with mappings 33346fd59449SRichard Henderson * from the executable. 33356fd59449SRichard Henderson */ 33361ea06dedSRichard Henderson load_addr = target_mmap(load_addr, (size_t)hiaddr - loaddr + 1, PROT_NONE, 33376fd59449SRichard Henderson MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | 3338ad25051bSRichard Henderson (ehdr->e_type == ET_EXEC ? MAP_FIXED_NOREPLACE : 0), 333909bfb054Sbellard -1, 0); 3340682674b8SRichard Henderson if (load_addr == -1) { 3341c7f17e7bSRichard Henderson goto exit_mmap; 334209bfb054Sbellard } 3343682674b8SRichard Henderson load_bias = load_addr - loaddr; 334409bfb054Sbellard 3345a99856cdSChristophe Lyon if (elf_is_fdpic(ehdr)) { 33461af02e83SMike Frysinger struct elf32_fdpic_loadseg *loadsegs = info->loadsegs = 33477267c094SAnthony Liguori g_malloc(sizeof(*loadsegs) * info->nsegs); 33481af02e83SMike Frysinger 33491af02e83SMike Frysinger for (i = 0; i < ehdr->e_phnum; ++i) { 33501af02e83SMike Frysinger switch (phdr[i].p_type) { 33511af02e83SMike Frysinger case PT_DYNAMIC: 33521af02e83SMike Frysinger info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias; 33531af02e83SMike Frysinger break; 33541af02e83SMike Frysinger case PT_LOAD: 33551af02e83SMike Frysinger loadsegs->addr = phdr[i].p_vaddr + load_bias; 33561af02e83SMike Frysinger loadsegs->p_vaddr = phdr[i].p_vaddr; 33571af02e83SMike Frysinger loadsegs->p_memsz = phdr[i].p_memsz; 33581af02e83SMike Frysinger ++loadsegs; 33591af02e83SMike Frysinger break; 33601af02e83SMike Frysinger } 33611af02e83SMike Frysinger } 33621af02e83SMike Frysinger } 33631af02e83SMike Frysinger 33648e62a717SRichard Henderson info->load_bias = load_bias; 3365dc12567aSJosh Kunz info->code_offset = load_bias; 3366dc12567aSJosh Kunz info->data_offset = load_bias; 33678e62a717SRichard Henderson info->load_addr = load_addr; 33688e62a717SRichard Henderson info->entry = ehdr->e_entry + load_bias; 33698e62a717SRichard Henderson info->start_code = -1; 33708e62a717SRichard Henderson info->end_code = 0; 33718e62a717SRichard Henderson info->start_data = -1; 33728e62a717SRichard Henderson info->end_data = 0; 33731f356e8cSHelge Deller /* Usual start for brk is after all sections of the main executable. */ 3374aec338d6SRichard Henderson info->brk = TARGET_PAGE_ALIGN(hiaddr + load_bias); 3375d8fd2954SPaul Brook info->elf_flags = ehdr->e_flags; 33768e62a717SRichard Henderson 3377e8384b37SRichard Henderson prot_exec = PROT_EXEC; 3378e8384b37SRichard Henderson #ifdef TARGET_AARCH64 3379e8384b37SRichard Henderson /* 3380e8384b37SRichard Henderson * If the BTI feature is present, this indicates that the executable 3381e8384b37SRichard Henderson * pages of the startup binary should be mapped with PROT_BTI, so that 3382e8384b37SRichard Henderson * branch targets are enforced. 3383e8384b37SRichard Henderson * 3384e8384b37SRichard Henderson * The startup binary is either the interpreter or the static executable. 3385e8384b37SRichard Henderson * The interpreter is responsible for all pages of a dynamic executable. 3386e8384b37SRichard Henderson * 3387e8384b37SRichard Henderson * Elf notes are backward compatible to older cpus. 3388e8384b37SRichard Henderson * Do not enable BTI unless it is supported. 3389e8384b37SRichard Henderson */ 3390e8384b37SRichard Henderson if ((info->note_flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) 3391e8384b37SRichard Henderson && (pinterp_name == NULL || *pinterp_name == 0) 3392e8384b37SRichard Henderson && cpu_isar_feature(aa64_bti, ARM_CPU(thread_cpu))) { 3393e8384b37SRichard Henderson prot_exec |= TARGET_PROT_BTI; 3394e8384b37SRichard Henderson } 3395e8384b37SRichard Henderson #endif 3396e8384b37SRichard Henderson 33978e62a717SRichard Henderson for (i = 0; i < ehdr->e_phnum; i++) { 33988e62a717SRichard Henderson struct elf_phdr *eppnt = phdr + i; 339931e31b8aSbellard if (eppnt->p_type == PT_LOAD) { 34005f4e5b34SRichard Henderson abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em; 340131e31b8aSbellard int elf_prot = 0; 340231e31b8aSbellard 3403e5eaf570SRichard Henderson if (eppnt->p_flags & PF_R) { 3404e5eaf570SRichard Henderson elf_prot |= PROT_READ; 3405e5eaf570SRichard Henderson } 3406e5eaf570SRichard Henderson if (eppnt->p_flags & PF_W) { 3407e5eaf570SRichard Henderson elf_prot |= PROT_WRITE; 3408e5eaf570SRichard Henderson } 3409e5eaf570SRichard Henderson if (eppnt->p_flags & PF_X) { 3410e8384b37SRichard Henderson elf_prot |= prot_exec; 3411e5eaf570SRichard Henderson } 341231e31b8aSbellard 3413682674b8SRichard Henderson vaddr = load_bias + eppnt->p_vaddr; 3414e3d97d5cSRichard Henderson vaddr_po = vaddr & ~TARGET_PAGE_MASK; 3415e3d97d5cSRichard Henderson vaddr_ps = vaddr & TARGET_PAGE_MASK; 341622d113b5SGiuseppe Musacchio 341722d113b5SGiuseppe Musacchio vaddr_ef = vaddr + eppnt->p_filesz; 341822d113b5SGiuseppe Musacchio vaddr_em = vaddr + eppnt->p_memsz; 3419682674b8SRichard Henderson 3420d87146bcSGiuseppe Musacchio /* 342122d113b5SGiuseppe Musacchio * Some segments may be completely empty, with a non-zero p_memsz 342222d113b5SGiuseppe Musacchio * but no backing file segment. 3423d87146bcSGiuseppe Musacchio */ 3424d87146bcSGiuseppe Musacchio if (eppnt->p_filesz != 0) { 3425*3bd02386SRichard Henderson error = imgsrc_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po, 34265f4e5b34SRichard Henderson elf_prot, MAP_PRIVATE | MAP_FIXED, 3427*3bd02386SRichard Henderson src, eppnt->p_offset - vaddr_po); 3428e89f07d3Spbrook if (error == -1) { 3429c7f17e7bSRichard Henderson goto exit_mmap; 343031e31b8aSbellard } 34315f4e5b34SRichard Henderson } 343231e31b8aSbellard 34335f4e5b34SRichard Henderson /* If the load segment requests extra zeros (e.g. bss), map it. */ 34345f4e5b34SRichard Henderson if (vaddr_ef < vaddr_em && 3435e6e66b03SRichard Henderson !zero_bss(vaddr_ef, vaddr_em, elf_prot, &err)) { 3436e6e66b03SRichard Henderson goto exit_errmsg; 3437682674b8SRichard Henderson } 34388e62a717SRichard Henderson 34398e62a717SRichard Henderson /* Find the full program boundaries. */ 34408e62a717SRichard Henderson if (elf_prot & PROT_EXEC) { 34418e62a717SRichard Henderson if (vaddr < info->start_code) { 34428e62a717SRichard Henderson info->start_code = vaddr; 3443cf129f3aSRichard Henderson } 34448e62a717SRichard Henderson if (vaddr_ef > info->end_code) { 34458e62a717SRichard Henderson info->end_code = vaddr_ef; 34468e62a717SRichard Henderson } 34478e62a717SRichard Henderson } 34488e62a717SRichard Henderson if (elf_prot & PROT_WRITE) { 34498e62a717SRichard Henderson if (vaddr < info->start_data) { 34508e62a717SRichard Henderson info->start_data = vaddr; 34518e62a717SRichard Henderson } 34528e62a717SRichard Henderson if (vaddr_ef > info->end_data) { 34538e62a717SRichard Henderson info->end_data = vaddr_ef; 34548e62a717SRichard Henderson } 34558a045188STimothy E Baldwin } 34565dd0db52SStefan Markovic #ifdef TARGET_MIPS 34575dd0db52SStefan Markovic } else if (eppnt->p_type == PT_MIPS_ABIFLAGS) { 34585dd0db52SStefan Markovic Mips_elf_abiflags_v0 abiflags; 3459*3bd02386SRichard Henderson 3460*3bd02386SRichard Henderson if (!imgsrc_read(&abiflags, eppnt->p_offset, sizeof(abiflags), 3461*3bd02386SRichard Henderson src, &err)) { 34625dd0db52SStefan Markovic goto exit_errmsg; 34635dd0db52SStefan Markovic } 34645dd0db52SStefan Markovic bswap_mips_abiflags(&abiflags); 3465c94cb6c9SStefan Markovic info->fp_abi = abiflags.fp_abi; 34665dd0db52SStefan Markovic #endif 34678e62a717SRichard Henderson } 34688e62a717SRichard Henderson } 34698e62a717SRichard Henderson 34708e62a717SRichard Henderson if (info->end_data == 0) { 34718e62a717SRichard Henderson info->start_data = info->end_code; 34728e62a717SRichard Henderson info->end_data = info->end_code; 347331e31b8aSbellard } 347431e31b8aSbellard 3475682674b8SRichard Henderson if (qemu_log_enabled()) { 3476*3bd02386SRichard Henderson load_symbols(ehdr, src->fd, load_bias); 3477682674b8SRichard Henderson } 347831e31b8aSbellard 3479*3bd02386SRichard Henderson debuginfo_report_elf(image_name, src->fd, load_bias); 34807c10cb38SIlya Leoshkevich 348198c1076cSAlex Bennée mmap_unlock(); 348298c1076cSAlex Bennée 3483*3bd02386SRichard Henderson close(src->fd); 34848e62a717SRichard Henderson return; 348531e31b8aSbellard 3486c7f17e7bSRichard Henderson exit_mmap: 3487c7f17e7bSRichard Henderson error_setg_errno(&err, errno, "Error mapping file"); 3488c7f17e7bSRichard Henderson goto exit_errmsg; 34898e62a717SRichard Henderson exit_errmsg: 3490c7f17e7bSRichard Henderson error_reportf_err(err, "%s: ", image_name); 34918e62a717SRichard Henderson exit(-1); 34928e62a717SRichard Henderson } 34938e62a717SRichard Henderson 34948e62a717SRichard Henderson static void load_elf_interp(const char *filename, struct image_info *info, 34958e62a717SRichard Henderson char bprm_buf[BPRM_BUF_SIZE]) 34968e62a717SRichard Henderson { 349740d487eeSRichard Henderson struct elfhdr ehdr; 3498*3bd02386SRichard Henderson ImageSource src; 34998e62a717SRichard Henderson int fd, retval; 3500808f6563SRichard Henderson Error *err = NULL; 35018e62a717SRichard Henderson 35028e62a717SRichard Henderson fd = open(path(filename), O_RDONLY); 35038e62a717SRichard Henderson if (fd < 0) { 3504808f6563SRichard Henderson error_setg_file_open(&err, errno, filename); 3505808f6563SRichard Henderson error_report_err(err); 3506808f6563SRichard Henderson exit(-1); 35078e62a717SRichard Henderson } 35088e62a717SRichard Henderson 35098e62a717SRichard Henderson retval = read(fd, bprm_buf, BPRM_BUF_SIZE); 35108e62a717SRichard Henderson if (retval < 0) { 3511808f6563SRichard Henderson error_setg_errno(&err, errno, "Error reading file header"); 3512808f6563SRichard Henderson error_reportf_err(err, "%s: ", filename); 3513808f6563SRichard Henderson exit(-1); 35148e62a717SRichard Henderson } 3515808f6563SRichard Henderson 3516*3bd02386SRichard Henderson src.fd = fd; 3517*3bd02386SRichard Henderson src.cache = bprm_buf; 3518*3bd02386SRichard Henderson src.cache_size = retval; 35198e62a717SRichard Henderson 3520*3bd02386SRichard Henderson load_elf_image(filename, &src, info, &ehdr, NULL); 352131e31b8aSbellard } 352231e31b8aSbellard 352349918a75Spbrook static int symfind(const void *s0, const void *s1) 352449918a75Spbrook { 352549918a75Spbrook struct elf_sym *sym = (struct elf_sym *)s1; 3526b6235a75SRichard Henderson __typeof(sym->st_value) addr = *(uint64_t *)s0; 352749918a75Spbrook int result = 0; 3528b6235a75SRichard Henderson 3529c7c530cdSStefan Weil if (addr < sym->st_value) { 353049918a75Spbrook result = -1; 3531c7c530cdSStefan Weil } else if (addr >= sym->st_value + sym->st_size) { 353249918a75Spbrook result = 1; 353349918a75Spbrook } 353449918a75Spbrook return result; 353549918a75Spbrook } 353649918a75Spbrook 3537b6235a75SRichard Henderson static const char *lookup_symbolxx(struct syminfo *s, uint64_t orig_addr) 353849918a75Spbrook { 353949918a75Spbrook #if ELF_CLASS == ELFCLASS32 354049918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf32; 354149918a75Spbrook #else 354249918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf64; 354349918a75Spbrook #endif 354449918a75Spbrook 354549918a75Spbrook // binary search 354649918a75Spbrook struct elf_sym *sym; 354749918a75Spbrook 3548c7c530cdSStefan Weil sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind); 35497cba04f6SBlue Swirl if (sym != NULL) { 355049918a75Spbrook return s->disas_strtab + sym->st_name; 355149918a75Spbrook } 355249918a75Spbrook 355349918a75Spbrook return ""; 355449918a75Spbrook } 355549918a75Spbrook 355649918a75Spbrook /* FIXME: This should use elf_ops.h */ 355749918a75Spbrook static int symcmp(const void *s0, const void *s1) 355849918a75Spbrook { 355949918a75Spbrook struct elf_sym *sym0 = (struct elf_sym *)s0; 356049918a75Spbrook struct elf_sym *sym1 = (struct elf_sym *)s1; 356149918a75Spbrook return (sym0->st_value < sym1->st_value) 356249918a75Spbrook ? -1 356349918a75Spbrook : ((sym0->st_value > sym1->st_value) ? 1 : 0); 356449918a75Spbrook } 356549918a75Spbrook 3566689f936fSbellard /* Best attempt to load symbols from this ELF object. */ 3567682674b8SRichard Henderson static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) 3568689f936fSbellard { 3569682674b8SRichard Henderson int i, shnum, nsyms, sym_idx = 0, str_idx = 0; 35701e06262dSPeter Maydell uint64_t segsz; 3571682674b8SRichard Henderson struct elf_shdr *shdr; 3572b9475279SCédric VINCENT char *strings = NULL; 3573b9475279SCédric VINCENT struct syminfo *s = NULL; 3574b9475279SCédric VINCENT struct elf_sym *new_syms, *syms = NULL; 357531e31b8aSbellard 3576682674b8SRichard Henderson shnum = hdr->e_shnum; 3577682674b8SRichard Henderson i = shnum * sizeof(struct elf_shdr); 3578682674b8SRichard Henderson shdr = (struct elf_shdr *)alloca(i); 3579682674b8SRichard Henderson if (pread(fd, shdr, i, hdr->e_shoff) != i) { 3580689f936fSbellard return; 3581682674b8SRichard Henderson } 3582682674b8SRichard Henderson 3583682674b8SRichard Henderson bswap_shdr(shdr, shnum); 3584682674b8SRichard Henderson for (i = 0; i < shnum; ++i) { 3585682674b8SRichard Henderson if (shdr[i].sh_type == SHT_SYMTAB) { 3586682674b8SRichard Henderson sym_idx = i; 3587682674b8SRichard Henderson str_idx = shdr[i].sh_link; 3588689f936fSbellard goto found; 3589689f936fSbellard } 3590689f936fSbellard } 3591682674b8SRichard Henderson 3592682674b8SRichard Henderson /* There will be no symbol table if the file was stripped. */ 3593682674b8SRichard Henderson return; 3594689f936fSbellard 3595689f936fSbellard found: 3596689f936fSbellard /* Now know where the strtab and symtab are. Snarf them. */ 35970ef9ea29SPeter Maydell s = g_try_new(struct syminfo, 1); 3598682674b8SRichard Henderson if (!s) { 3599b9475279SCédric VINCENT goto give_up; 3600682674b8SRichard Henderson } 3601682674b8SRichard Henderson 36021e06262dSPeter Maydell segsz = shdr[str_idx].sh_size; 36031e06262dSPeter Maydell s->disas_strtab = strings = g_try_malloc(segsz); 36041e06262dSPeter Maydell if (!strings || 36051e06262dSPeter Maydell pread(fd, strings, segsz, shdr[str_idx].sh_offset) != segsz) { 3606b9475279SCédric VINCENT goto give_up; 3607682674b8SRichard Henderson } 3608689f936fSbellard 36091e06262dSPeter Maydell segsz = shdr[sym_idx].sh_size; 36101e06262dSPeter Maydell syms = g_try_malloc(segsz); 36111e06262dSPeter Maydell if (!syms || pread(fd, syms, segsz, shdr[sym_idx].sh_offset) != segsz) { 3612b9475279SCédric VINCENT goto give_up; 3613682674b8SRichard Henderson } 3614689f936fSbellard 36151e06262dSPeter Maydell if (segsz / sizeof(struct elf_sym) > INT_MAX) { 36161e06262dSPeter Maydell /* Implausibly large symbol table: give up rather than ploughing 36171e06262dSPeter Maydell * on with the number of symbols calculation overflowing 36181e06262dSPeter Maydell */ 36191e06262dSPeter Maydell goto give_up; 36201e06262dSPeter Maydell } 36211e06262dSPeter Maydell nsyms = segsz / sizeof(struct elf_sym); 3622682674b8SRichard Henderson for (i = 0; i < nsyms; ) { 362349918a75Spbrook bswap_sym(syms + i); 3624682674b8SRichard Henderson /* Throw away entries which we do not need. */ 3625682674b8SRichard Henderson if (syms[i].st_shndx == SHN_UNDEF 3626682674b8SRichard Henderson || syms[i].st_shndx >= SHN_LORESERVE 3627682674b8SRichard Henderson || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 3628682674b8SRichard Henderson if (i < --nsyms) { 362949918a75Spbrook syms[i] = syms[nsyms]; 363049918a75Spbrook } 3631682674b8SRichard Henderson } else { 363249918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS) 363349918a75Spbrook /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 363449918a75Spbrook syms[i].st_value &= ~(target_ulong)1; 363549918a75Spbrook #endif 3636682674b8SRichard Henderson syms[i].st_value += load_bias; 363749918a75Spbrook i++; 363849918a75Spbrook } 3639682674b8SRichard Henderson } 364049918a75Spbrook 3641b9475279SCédric VINCENT /* No "useful" symbol. */ 3642b9475279SCédric VINCENT if (nsyms == 0) { 3643b9475279SCédric VINCENT goto give_up; 3644b9475279SCédric VINCENT } 3645b9475279SCédric VINCENT 36465d5c9930SRichard Henderson /* Attempt to free the storage associated with the local symbols 36475d5c9930SRichard Henderson that we threw away. Whether or not this has any effect on the 36485d5c9930SRichard Henderson memory allocation depends on the malloc implementation and how 36495d5c9930SRichard Henderson many symbols we managed to discard. */ 36500ef9ea29SPeter Maydell new_syms = g_try_renew(struct elf_sym, syms, nsyms); 36518d79de6eSStefan Weil if (new_syms == NULL) { 3652b9475279SCédric VINCENT goto give_up; 36535d5c9930SRichard Henderson } 36548d79de6eSStefan Weil syms = new_syms; 36555d5c9930SRichard Henderson 365649918a75Spbrook qsort(syms, nsyms, sizeof(*syms), symcmp); 365749918a75Spbrook 365849918a75Spbrook s->disas_num_syms = nsyms; 365949918a75Spbrook #if ELF_CLASS == ELFCLASS32 366049918a75Spbrook s->disas_symtab.elf32 = syms; 366149918a75Spbrook #else 366249918a75Spbrook s->disas_symtab.elf64 = syms; 366349918a75Spbrook #endif 3664682674b8SRichard Henderson s->lookup_symbol = lookup_symbolxx; 3665e80cfcfcSbellard s->next = syminfos; 3666e80cfcfcSbellard syminfos = s; 3667b9475279SCédric VINCENT 3668b9475279SCédric VINCENT return; 3669b9475279SCédric VINCENT 3670b9475279SCédric VINCENT give_up: 36710ef9ea29SPeter Maydell g_free(s); 36720ef9ea29SPeter Maydell g_free(strings); 36730ef9ea29SPeter Maydell g_free(syms); 3674689f936fSbellard } 367531e31b8aSbellard 3676768fe76eSYunQiang Su uint32_t get_elf_eflags(int fd) 3677768fe76eSYunQiang Su { 3678768fe76eSYunQiang Su struct elfhdr ehdr; 3679768fe76eSYunQiang Su off_t offset; 3680768fe76eSYunQiang Su int ret; 3681768fe76eSYunQiang Su 3682768fe76eSYunQiang Su /* Read ELF header */ 3683768fe76eSYunQiang Su offset = lseek(fd, 0, SEEK_SET); 3684768fe76eSYunQiang Su if (offset == (off_t) -1) { 3685768fe76eSYunQiang Su return 0; 3686768fe76eSYunQiang Su } 3687768fe76eSYunQiang Su ret = read(fd, &ehdr, sizeof(ehdr)); 3688768fe76eSYunQiang Su if (ret < sizeof(ehdr)) { 3689768fe76eSYunQiang Su return 0; 3690768fe76eSYunQiang Su } 3691768fe76eSYunQiang Su offset = lseek(fd, offset, SEEK_SET); 3692768fe76eSYunQiang Su if (offset == (off_t) -1) { 3693768fe76eSYunQiang Su return 0; 3694768fe76eSYunQiang Su } 3695768fe76eSYunQiang Su 3696768fe76eSYunQiang Su /* Check ELF signature */ 3697768fe76eSYunQiang Su if (!elf_check_ident(&ehdr)) { 3698768fe76eSYunQiang Su return 0; 3699768fe76eSYunQiang Su } 3700768fe76eSYunQiang Su 3701768fe76eSYunQiang Su /* check header */ 3702768fe76eSYunQiang Su bswap_ehdr(&ehdr); 3703768fe76eSYunQiang Su if (!elf_check_ehdr(&ehdr)) { 3704768fe76eSYunQiang Su return 0; 3705768fe76eSYunQiang Su } 3706768fe76eSYunQiang Su 3707768fe76eSYunQiang Su /* return architecture id */ 3708768fe76eSYunQiang Su return ehdr.e_flags; 3709768fe76eSYunQiang Su } 3710768fe76eSYunQiang Su 3711f0116c54SWill Newton int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) 371231e31b8aSbellard { 371340d487eeSRichard Henderson /* 371440d487eeSRichard Henderson * We need a copy of the elf header for passing to create_elf_tables. 371540d487eeSRichard Henderson * We will have overwritten the original when we re-use bprm->buf 371640d487eeSRichard Henderson * while loading the interpreter. Allocate the storage for this now 371740d487eeSRichard Henderson * and let elf_load_image do any swapping that may be required. 371840d487eeSRichard Henderson */ 371940d487eeSRichard Henderson struct elfhdr ehdr; 37208e62a717SRichard Henderson struct image_info interp_info; 37218e62a717SRichard Henderson char *elf_interpreter = NULL; 372259baae9aSStefan Brüns char *scratch; 372331e31b8aSbellard 3724abcac736SDaniel Santos memset(&interp_info, 0, sizeof(interp_info)); 3725abcac736SDaniel Santos #ifdef TARGET_MIPS 3726abcac736SDaniel Santos interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN; 3727abcac736SDaniel Santos #endif 3728abcac736SDaniel Santos 3729*3bd02386SRichard Henderson load_elf_image(bprm->filename, &bprm->src, info, &ehdr, &elf_interpreter); 373031e31b8aSbellard 373159baae9aSStefan Brüns /* Do this so that we can load the interpreter, if need be. We will 373259baae9aSStefan Brüns change some of these later */ 373359baae9aSStefan Brüns bprm->p = setup_arg_pages(bprm, info); 373459baae9aSStefan Brüns 373559baae9aSStefan Brüns scratch = g_new0(char, TARGET_PAGE_SIZE); 37367c4ee5bcSRichard Henderson if (STACK_GROWS_DOWN) { 373759baae9aSStefan Brüns bprm->p = copy_elf_strings(1, &bprm->filename, scratch, 373859baae9aSStefan Brüns bprm->p, info->stack_limit); 37397c4ee5bcSRichard Henderson info->file_string = bprm->p; 374059baae9aSStefan Brüns bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch, 374159baae9aSStefan Brüns bprm->p, info->stack_limit); 37427c4ee5bcSRichard Henderson info->env_strings = bprm->p; 374359baae9aSStefan Brüns bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch, 374459baae9aSStefan Brüns bprm->p, info->stack_limit); 37457c4ee5bcSRichard Henderson info->arg_strings = bprm->p; 37467c4ee5bcSRichard Henderson } else { 37477c4ee5bcSRichard Henderson info->arg_strings = bprm->p; 37487c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch, 37497c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 37507c4ee5bcSRichard Henderson info->env_strings = bprm->p; 37517c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch, 37527c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 37537c4ee5bcSRichard Henderson info->file_string = bprm->p; 37547c4ee5bcSRichard Henderson bprm->p = copy_elf_strings(1, &bprm->filename, scratch, 37557c4ee5bcSRichard Henderson bprm->p, info->stack_limit); 37567c4ee5bcSRichard Henderson } 37577c4ee5bcSRichard Henderson 375859baae9aSStefan Brüns g_free(scratch); 375959baae9aSStefan Brüns 3760e5fe0c52Spbrook if (!bprm->p) { 3761bf858897SRichard Henderson fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG)); 376231e31b8aSbellard exit(-1); 37639955ffacSRichard Henderson } 3764379f6698SPaul Brook 37658e62a717SRichard Henderson if (elf_interpreter) { 37668e62a717SRichard Henderson load_elf_interp(elf_interpreter, &interp_info, bprm->buf); 376731e31b8aSbellard 37681f356e8cSHelge Deller /* 37691f356e8cSHelge Deller * While unusual because of ELF_ET_DYN_BASE, if we are unlucky 37701f356e8cSHelge Deller * with the mappings the interpreter can be loaded above but 37711f356e8cSHelge Deller * near the main executable, which can leave very little room 37721f356e8cSHelge Deller * for the heap. 37731f356e8cSHelge Deller * If the current brk has less than 16MB, use the end of the 37741f356e8cSHelge Deller * interpreter. 37751f356e8cSHelge Deller */ 37761f356e8cSHelge Deller if (interp_info.brk > info->brk && 37771f356e8cSHelge Deller interp_info.load_bias - info->brk < 16 * MiB) { 37781f356e8cSHelge Deller info->brk = interp_info.brk; 37791f356e8cSHelge Deller } 37801f356e8cSHelge Deller 37818e62a717SRichard Henderson /* If the program interpreter is one of these two, then assume 37828e62a717SRichard Henderson an iBCS2 image. Otherwise assume a native linux image. */ 378331e31b8aSbellard 37848e62a717SRichard Henderson if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0 37858e62a717SRichard Henderson || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) { 37868e62a717SRichard Henderson info->personality = PER_SVR4; 37878e62a717SRichard Henderson 378831e31b8aSbellard /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 37898e62a717SRichard Henderson and some applications "depend" upon this behavior. Since 37908e62a717SRichard Henderson we do not have the power to recompile these, we emulate 37918e62a717SRichard Henderson the SVr4 behavior. Sigh. */ 37928e62a717SRichard Henderson target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, 379368754b44SPeter Maydell MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 379431e31b8aSbellard } 3795c94cb6c9SStefan Markovic #ifdef TARGET_MIPS 3796c94cb6c9SStefan Markovic info->interp_fp_abi = interp_info.fp_abi; 3797c94cb6c9SStefan Markovic #endif 37988e62a717SRichard Henderson } 379931e31b8aSbellard 3800db2af69dSRichard Henderson /* 3801db2af69dSRichard Henderson * TODO: load a vdso, which would also contain the signal trampolines. 3802db2af69dSRichard Henderson * Otherwise, allocate a private page to hold them. 3803db2af69dSRichard Henderson */ 3804db2af69dSRichard Henderson if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) { 3805802ae45eSLaurent Vivier abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE, 3806db2af69dSRichard Henderson PROT_READ | PROT_WRITE, 3807db2af69dSRichard Henderson MAP_PRIVATE | MAP_ANON, -1, 0); 3808802ae45eSLaurent Vivier if (tramp_page == -1) { 3809802ae45eSLaurent Vivier return -errno; 3810802ae45eSLaurent Vivier } 3811802ae45eSLaurent Vivier 3812db2af69dSRichard Henderson setup_sigtramp(tramp_page); 3813db2af69dSRichard Henderson target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC); 3814db2af69dSRichard Henderson } 3815db2af69dSRichard Henderson 381640d487eeSRichard Henderson bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &ehdr, 38178e62a717SRichard Henderson info, (elf_interpreter ? &interp_info : NULL)); 38188e62a717SRichard Henderson info->start_stack = bprm->p; 38198e62a717SRichard Henderson 38208e62a717SRichard Henderson /* If we have an interpreter, set that as the program's entry point. 38218e78064eSRichard Henderson Copy the load_bias as well, to help PPC64 interpret the entry 38228e62a717SRichard Henderson point as a function descriptor. Do this after creating elf tables 38238e62a717SRichard Henderson so that we copy the original program entry point into the AUXV. */ 38248e62a717SRichard Henderson if (elf_interpreter) { 38258e78064eSRichard Henderson info->load_bias = interp_info.load_bias; 38268e62a717SRichard Henderson info->entry = interp_info.entry; 38272b323087SPhilippe Mathieu-Daudé g_free(elf_interpreter); 38288e62a717SRichard Henderson } 382931e31b8aSbellard 3830edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 3831edf8e2afSMika Westerberg bprm->core_dump = &elf_core_dump; 3832edf8e2afSMika Westerberg #endif 3833edf8e2afSMika Westerberg 383431e31b8aSbellard return 0; 383531e31b8aSbellard } 383631e31b8aSbellard 3837edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 3838edf8e2afSMika Westerberg /* 3839edf8e2afSMika Westerberg * Definitions to generate Intel SVR4-like core files. 3840a2547a13SLaurent Desnogues * These mostly have the same names as the SVR4 types with "target_elf_" 3841edf8e2afSMika Westerberg * tacked on the front to prevent clashes with linux definitions, 3842edf8e2afSMika Westerberg * and the typedef forms have been avoided. This is mostly like 3843edf8e2afSMika Westerberg * the SVR4 structure, but more Linuxy, with things that Linux does 3844edf8e2afSMika Westerberg * not support and which gdb doesn't really use excluded. 3845edf8e2afSMika Westerberg * 3846edf8e2afSMika Westerberg * Fields we don't dump (their contents is zero) in linux-user qemu 3847edf8e2afSMika Westerberg * are marked with XXX. 3848edf8e2afSMika Westerberg * 3849edf8e2afSMika Westerberg * Core dump code is copied from linux kernel (fs/binfmt_elf.c). 3850edf8e2afSMika Westerberg * 3851edf8e2afSMika Westerberg * Porting ELF coredump for target is (quite) simple process. First you 3852dd0a3651SNathan Froyd * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for 3853edf8e2afSMika Westerberg * the target resides): 3854edf8e2afSMika Westerberg * 3855edf8e2afSMika Westerberg * #define USE_ELF_CORE_DUMP 3856edf8e2afSMika Westerberg * 3857edf8e2afSMika Westerberg * Next you define type of register set used for dumping. ELF specification 3858edf8e2afSMika Westerberg * says that it needs to be array of elf_greg_t that has size of ELF_NREG. 3859edf8e2afSMika Westerberg * 3860c227f099SAnthony Liguori * typedef <target_regtype> target_elf_greg_t; 3861edf8e2afSMika Westerberg * #define ELF_NREG <number of registers> 3862c227f099SAnthony Liguori * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; 3863edf8e2afSMika Westerberg * 3864edf8e2afSMika Westerberg * Last step is to implement target specific function that copies registers 3865edf8e2afSMika Westerberg * from given cpu into just specified register set. Prototype is: 3866edf8e2afSMika Westerberg * 3867c227f099SAnthony Liguori * static void elf_core_copy_regs(taret_elf_gregset_t *regs, 38689349b4f9SAndreas Färber * const CPUArchState *env); 3869edf8e2afSMika Westerberg * 3870edf8e2afSMika Westerberg * Parameters: 3871edf8e2afSMika Westerberg * regs - copy register values into here (allocated and zeroed by caller) 3872edf8e2afSMika Westerberg * env - copy registers from here 3873edf8e2afSMika Westerberg * 3874edf8e2afSMika Westerberg * Example for ARM target is provided in this file. 3875edf8e2afSMika Westerberg */ 3876edf8e2afSMika Westerberg 3877edf8e2afSMika Westerberg /* An ELF note in memory */ 3878edf8e2afSMika Westerberg struct memelfnote { 3879edf8e2afSMika Westerberg const char *name; 3880edf8e2afSMika Westerberg size_t namesz; 3881edf8e2afSMika Westerberg size_t namesz_rounded; 3882edf8e2afSMika Westerberg int type; 3883edf8e2afSMika Westerberg size_t datasz; 388480f5ce75SLaurent Vivier size_t datasz_rounded; 3885edf8e2afSMika Westerberg void *data; 3886edf8e2afSMika Westerberg size_t notesz; 3887edf8e2afSMika Westerberg }; 3888edf8e2afSMika Westerberg 3889a2547a13SLaurent Desnogues struct target_elf_siginfo { 3890f8fd4fc4SPaolo Bonzini abi_int si_signo; /* signal number */ 3891f8fd4fc4SPaolo Bonzini abi_int si_code; /* extra code */ 3892f8fd4fc4SPaolo Bonzini abi_int si_errno; /* errno */ 3893edf8e2afSMika Westerberg }; 3894edf8e2afSMika Westerberg 3895a2547a13SLaurent Desnogues struct target_elf_prstatus { 3896a2547a13SLaurent Desnogues struct target_elf_siginfo pr_info; /* Info associated with signal */ 38971ddd592fSPaolo Bonzini abi_short pr_cursig; /* Current signal */ 3898ca98ac83SPaolo Bonzini abi_ulong pr_sigpend; /* XXX */ 3899ca98ac83SPaolo Bonzini abi_ulong pr_sighold; /* XXX */ 3900c227f099SAnthony Liguori target_pid_t pr_pid; 3901c227f099SAnthony Liguori target_pid_t pr_ppid; 3902c227f099SAnthony Liguori target_pid_t pr_pgrp; 3903c227f099SAnthony Liguori target_pid_t pr_sid; 3904edf8e2afSMika Westerberg struct target_timeval pr_utime; /* XXX User time */ 3905edf8e2afSMika Westerberg struct target_timeval pr_stime; /* XXX System time */ 3906edf8e2afSMika Westerberg struct target_timeval pr_cutime; /* XXX Cumulative user time */ 3907edf8e2afSMika Westerberg struct target_timeval pr_cstime; /* XXX Cumulative system time */ 3908c227f099SAnthony Liguori target_elf_gregset_t pr_reg; /* GP registers */ 3909f8fd4fc4SPaolo Bonzini abi_int pr_fpvalid; /* XXX */ 3910edf8e2afSMika Westerberg }; 3911edf8e2afSMika Westerberg 3912edf8e2afSMika Westerberg #define ELF_PRARGSZ (80) /* Number of chars for args */ 3913edf8e2afSMika Westerberg 3914a2547a13SLaurent Desnogues struct target_elf_prpsinfo { 3915edf8e2afSMika Westerberg char pr_state; /* numeric process state */ 3916edf8e2afSMika Westerberg char pr_sname; /* char for pr_state */ 3917edf8e2afSMika Westerberg char pr_zomb; /* zombie */ 3918edf8e2afSMika Westerberg char pr_nice; /* nice val */ 3919ca98ac83SPaolo Bonzini abi_ulong pr_flag; /* flags */ 3920c227f099SAnthony Liguori target_uid_t pr_uid; 3921c227f099SAnthony Liguori target_gid_t pr_gid; 3922c227f099SAnthony Liguori target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; 3923edf8e2afSMika Westerberg /* Lots missing */ 3924d7eb2b92SAlistair Francis char pr_fname[16] QEMU_NONSTRING; /* filename of executable */ 3925edf8e2afSMika Westerberg char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ 3926edf8e2afSMika Westerberg }; 3927edf8e2afSMika Westerberg 3928edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */ 3929edf8e2afSMika Westerberg struct elf_thread_status { 393072cf2d4fSBlue Swirl QTAILQ_ENTRY(elf_thread_status) ets_link; 3931a2547a13SLaurent Desnogues struct target_elf_prstatus prstatus; /* NT_PRSTATUS */ 3932edf8e2afSMika Westerberg #if 0 3933edf8e2afSMika Westerberg elf_fpregset_t fpu; /* NT_PRFPREG */ 3934edf8e2afSMika Westerberg struct task_struct *thread; 3935edf8e2afSMika Westerberg elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */ 3936edf8e2afSMika Westerberg #endif 3937edf8e2afSMika Westerberg struct memelfnote notes[1]; 3938edf8e2afSMika Westerberg int num_notes; 3939edf8e2afSMika Westerberg }; 3940edf8e2afSMika Westerberg 3941edf8e2afSMika Westerberg struct elf_note_info { 3942edf8e2afSMika Westerberg struct memelfnote *notes; 3943a2547a13SLaurent Desnogues struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */ 3944a2547a13SLaurent Desnogues struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */ 3945edf8e2afSMika Westerberg 3946b58deb34SPaolo Bonzini QTAILQ_HEAD(, elf_thread_status) thread_list; 3947edf8e2afSMika Westerberg #if 0 3948edf8e2afSMika Westerberg /* 3949edf8e2afSMika Westerberg * Current version of ELF coredump doesn't support 3950edf8e2afSMika Westerberg * dumping fp regs etc. 3951edf8e2afSMika Westerberg */ 3952edf8e2afSMika Westerberg elf_fpregset_t *fpu; 3953edf8e2afSMika Westerberg elf_fpxregset_t *xfpu; 3954edf8e2afSMika Westerberg int thread_status_size; 3955edf8e2afSMika Westerberg #endif 3956edf8e2afSMika Westerberg int notes_size; 3957edf8e2afSMika Westerberg int numnote; 3958edf8e2afSMika Westerberg }; 3959edf8e2afSMika Westerberg 3960edf8e2afSMika Westerberg struct vm_area_struct { 39611a1c4db9SMikhail Ilyin target_ulong vma_start; /* start vaddr of memory region */ 39621a1c4db9SMikhail Ilyin target_ulong vma_end; /* end vaddr of memory region */ 3963edf8e2afSMika Westerberg abi_ulong vma_flags; /* protection etc. flags for the region */ 396472cf2d4fSBlue Swirl QTAILQ_ENTRY(vm_area_struct) vma_link; 3965edf8e2afSMika Westerberg }; 3966edf8e2afSMika Westerberg 3967edf8e2afSMika Westerberg struct mm_struct { 396872cf2d4fSBlue Swirl QTAILQ_HEAD(, vm_area_struct) mm_mmap; 3969edf8e2afSMika Westerberg int mm_count; /* number of mappings */ 3970edf8e2afSMika Westerberg }; 3971edf8e2afSMika Westerberg 3972edf8e2afSMika Westerberg static struct mm_struct *vma_init(void); 3973edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *); 39741a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *, target_ulong, 39751a1c4db9SMikhail Ilyin target_ulong, abi_ulong); 3976edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *); 3977edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *); 3978edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *); 3979edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *); 39801a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end, 3981edf8e2afSMika Westerberg unsigned long flags); 3982edf8e2afSMika Westerberg 3983edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); 3984edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int, 3985edf8e2afSMika Westerberg unsigned int, void *); 3986a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); 3987a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); 3988edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *); 3989edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); 3990edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *); 3991edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *); 39929349b4f9SAndreas Färber static int fill_note_info(struct elf_note_info *, long, const CPUArchState *); 39939349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *, const CPUArchState *); 3994edf8e2afSMika Westerberg 3995edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t); 3996edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int); 3997edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int); 3998edf8e2afSMika Westerberg 3999edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 4000a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus) 4001edf8e2afSMika Westerberg { 4002ca98ac83SPaolo Bonzini prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo); 4003ca98ac83SPaolo Bonzini prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code); 4004ca98ac83SPaolo Bonzini prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno); 4005edf8e2afSMika Westerberg prstatus->pr_cursig = tswap16(prstatus->pr_cursig); 4006ca98ac83SPaolo Bonzini prstatus->pr_sigpend = tswapal(prstatus->pr_sigpend); 4007ca98ac83SPaolo Bonzini prstatus->pr_sighold = tswapal(prstatus->pr_sighold); 4008edf8e2afSMika Westerberg prstatus->pr_pid = tswap32(prstatus->pr_pid); 4009edf8e2afSMika Westerberg prstatus->pr_ppid = tswap32(prstatus->pr_ppid); 4010edf8e2afSMika Westerberg prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp); 4011edf8e2afSMika Westerberg prstatus->pr_sid = tswap32(prstatus->pr_sid); 4012edf8e2afSMika Westerberg /* cpu times are not filled, so we skip them */ 4013edf8e2afSMika Westerberg /* regs should be in correct format already */ 4014edf8e2afSMika Westerberg prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid); 4015edf8e2afSMika Westerberg } 4016edf8e2afSMika Westerberg 4017a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) 4018edf8e2afSMika Westerberg { 4019ca98ac83SPaolo Bonzini psinfo->pr_flag = tswapal(psinfo->pr_flag); 4020edf8e2afSMika Westerberg psinfo->pr_uid = tswap16(psinfo->pr_uid); 4021edf8e2afSMika Westerberg psinfo->pr_gid = tswap16(psinfo->pr_gid); 4022edf8e2afSMika Westerberg psinfo->pr_pid = tswap32(psinfo->pr_pid); 4023edf8e2afSMika Westerberg psinfo->pr_ppid = tswap32(psinfo->pr_ppid); 4024edf8e2afSMika Westerberg psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp); 4025edf8e2afSMika Westerberg psinfo->pr_sid = tswap32(psinfo->pr_sid); 4026edf8e2afSMika Westerberg } 4027991f8f0cSRichard Henderson 4028991f8f0cSRichard Henderson static void bswap_note(struct elf_note *en) 4029991f8f0cSRichard Henderson { 4030991f8f0cSRichard Henderson bswap32s(&en->n_namesz); 4031991f8f0cSRichard Henderson bswap32s(&en->n_descsz); 4032991f8f0cSRichard Henderson bswap32s(&en->n_type); 4033991f8f0cSRichard Henderson } 4034991f8f0cSRichard Henderson #else 4035991f8f0cSRichard Henderson static inline void bswap_prstatus(struct target_elf_prstatus *p) { } 4036991f8f0cSRichard Henderson static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {} 4037991f8f0cSRichard Henderson static inline void bswap_note(struct elf_note *en) { } 4038edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 4039edf8e2afSMika Westerberg 4040edf8e2afSMika Westerberg /* 4041edf8e2afSMika Westerberg * Minimal support for linux memory regions. These are needed 4042edf8e2afSMika Westerberg * when we are finding out what memory exactly belongs to 4043edf8e2afSMika Westerberg * emulated process. No locks needed here, as long as 4044edf8e2afSMika Westerberg * thread that received the signal is stopped. 4045edf8e2afSMika Westerberg */ 4046edf8e2afSMika Westerberg 4047edf8e2afSMika Westerberg static struct mm_struct *vma_init(void) 4048edf8e2afSMika Westerberg { 4049edf8e2afSMika Westerberg struct mm_struct *mm; 4050edf8e2afSMika Westerberg 40517267c094SAnthony Liguori if ((mm = g_malloc(sizeof (*mm))) == NULL) 4052edf8e2afSMika Westerberg return (NULL); 4053edf8e2afSMika Westerberg 4054edf8e2afSMika Westerberg mm->mm_count = 0; 405572cf2d4fSBlue Swirl QTAILQ_INIT(&mm->mm_mmap); 4056edf8e2afSMika Westerberg 4057edf8e2afSMika Westerberg return (mm); 4058edf8e2afSMika Westerberg } 4059edf8e2afSMika Westerberg 4060edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm) 4061edf8e2afSMika Westerberg { 4062edf8e2afSMika Westerberg struct vm_area_struct *vma; 4063edf8e2afSMika Westerberg 4064edf8e2afSMika Westerberg while ((vma = vma_first(mm)) != NULL) { 406572cf2d4fSBlue Swirl QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link); 40667267c094SAnthony Liguori g_free(vma); 4067edf8e2afSMika Westerberg } 40687267c094SAnthony Liguori g_free(mm); 4069edf8e2afSMika Westerberg } 4070edf8e2afSMika Westerberg 40711a1c4db9SMikhail Ilyin static int vma_add_mapping(struct mm_struct *mm, target_ulong start, 40721a1c4db9SMikhail Ilyin target_ulong end, abi_ulong flags) 4073edf8e2afSMika Westerberg { 4074edf8e2afSMika Westerberg struct vm_area_struct *vma; 4075edf8e2afSMika Westerberg 40767267c094SAnthony Liguori if ((vma = g_malloc0(sizeof (*vma))) == NULL) 4077edf8e2afSMika Westerberg return (-1); 4078edf8e2afSMika Westerberg 4079edf8e2afSMika Westerberg vma->vma_start = start; 4080edf8e2afSMika Westerberg vma->vma_end = end; 4081edf8e2afSMika Westerberg vma->vma_flags = flags; 4082edf8e2afSMika Westerberg 408372cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link); 4084edf8e2afSMika Westerberg mm->mm_count++; 4085edf8e2afSMika Westerberg 4086edf8e2afSMika Westerberg return (0); 4087edf8e2afSMika Westerberg } 4088edf8e2afSMika Westerberg 4089edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm) 4090edf8e2afSMika Westerberg { 409172cf2d4fSBlue Swirl return (QTAILQ_FIRST(&mm->mm_mmap)); 4092edf8e2afSMika Westerberg } 4093edf8e2afSMika Westerberg 4094edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma) 4095edf8e2afSMika Westerberg { 409672cf2d4fSBlue Swirl return (QTAILQ_NEXT(vma, vma_link)); 4097edf8e2afSMika Westerberg } 4098edf8e2afSMika Westerberg 4099edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm) 4100edf8e2afSMika Westerberg { 4101edf8e2afSMika Westerberg return (mm->mm_count); 4102edf8e2afSMika Westerberg } 4103edf8e2afSMika Westerberg 4104edf8e2afSMika Westerberg /* 4105edf8e2afSMika Westerberg * Calculate file (dump) size of given memory region. 4106edf8e2afSMika Westerberg */ 4107edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma) 4108edf8e2afSMika Westerberg { 4109edf8e2afSMika Westerberg /* if we cannot even read the first page, skip it */ 4110c7169b02SRichard Henderson if (!access_ok_untagged(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE)) 4111edf8e2afSMika Westerberg return (0); 4112edf8e2afSMika Westerberg 4113edf8e2afSMika Westerberg /* 4114edf8e2afSMika Westerberg * Usually we don't dump executable pages as they contain 4115edf8e2afSMika Westerberg * non-writable code that debugger can read directly from 4116edf8e2afSMika Westerberg * target library etc. However, thread stacks are marked 4117edf8e2afSMika Westerberg * also executable so we read in first page of given region 4118edf8e2afSMika Westerberg * and check whether it contains elf header. If there is 4119edf8e2afSMika Westerberg * no elf header, we dump it. 4120edf8e2afSMika Westerberg */ 4121edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) { 4122edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 4123edf8e2afSMika Westerberg 4124022625a8SPeter Maydell if (copy_from_user(page, vma->vma_start, sizeof (page))) { 4125022625a8SPeter Maydell return 0; 4126022625a8SPeter Maydell } 4127edf8e2afSMika Westerberg if ((page[EI_MAG0] == ELFMAG0) && 4128edf8e2afSMika Westerberg (page[EI_MAG1] == ELFMAG1) && 4129edf8e2afSMika Westerberg (page[EI_MAG2] == ELFMAG2) && 4130edf8e2afSMika Westerberg (page[EI_MAG3] == ELFMAG3)) { 4131edf8e2afSMika Westerberg /* 4132edf8e2afSMika Westerberg * Mappings are possibly from ELF binary. Don't dump 4133edf8e2afSMika Westerberg * them. 4134edf8e2afSMika Westerberg */ 4135edf8e2afSMika Westerberg return (0); 4136edf8e2afSMika Westerberg } 4137edf8e2afSMika Westerberg } 4138edf8e2afSMika Westerberg 4139edf8e2afSMika Westerberg return (vma->vma_end - vma->vma_start); 4140edf8e2afSMika Westerberg } 4141edf8e2afSMika Westerberg 41421a1c4db9SMikhail Ilyin static int vma_walker(void *priv, target_ulong start, target_ulong end, 4143edf8e2afSMika Westerberg unsigned long flags) 4144edf8e2afSMika Westerberg { 4145edf8e2afSMika Westerberg struct mm_struct *mm = (struct mm_struct *)priv; 4146edf8e2afSMika Westerberg 4147edf8e2afSMika Westerberg vma_add_mapping(mm, start, end, flags); 4148edf8e2afSMika Westerberg return (0); 4149edf8e2afSMika Westerberg } 4150edf8e2afSMika Westerberg 4151edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type, 4152edf8e2afSMika Westerberg unsigned int sz, void *data) 4153edf8e2afSMika Westerberg { 4154edf8e2afSMika Westerberg unsigned int namesz; 4155edf8e2afSMika Westerberg 4156edf8e2afSMika Westerberg namesz = strlen(name) + 1; 4157edf8e2afSMika Westerberg note->name = name; 4158edf8e2afSMika Westerberg note->namesz = namesz; 4159edf8e2afSMika Westerberg note->namesz_rounded = roundup(namesz, sizeof (int32_t)); 4160edf8e2afSMika Westerberg note->type = type; 416180f5ce75SLaurent Vivier note->datasz = sz; 416280f5ce75SLaurent Vivier note->datasz_rounded = roundup(sz, sizeof (int32_t)); 416380f5ce75SLaurent Vivier 4164edf8e2afSMika Westerberg note->data = data; 4165edf8e2afSMika Westerberg 4166edf8e2afSMika Westerberg /* 4167edf8e2afSMika Westerberg * We calculate rounded up note size here as specified by 4168edf8e2afSMika Westerberg * ELF document. 4169edf8e2afSMika Westerberg */ 4170edf8e2afSMika Westerberg note->notesz = sizeof (struct elf_note) + 417180f5ce75SLaurent Vivier note->namesz_rounded + note->datasz_rounded; 4172edf8e2afSMika Westerberg } 4173edf8e2afSMika Westerberg 4174edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, 4175edf8e2afSMika Westerberg uint32_t flags) 4176edf8e2afSMika Westerberg { 4177edf8e2afSMika Westerberg (void) memset(elf, 0, sizeof(*elf)); 4178edf8e2afSMika Westerberg 4179edf8e2afSMika Westerberg (void) memcpy(elf->e_ident, ELFMAG, SELFMAG); 4180edf8e2afSMika Westerberg elf->e_ident[EI_CLASS] = ELF_CLASS; 4181edf8e2afSMika Westerberg elf->e_ident[EI_DATA] = ELF_DATA; 4182edf8e2afSMika Westerberg elf->e_ident[EI_VERSION] = EV_CURRENT; 4183edf8e2afSMika Westerberg elf->e_ident[EI_OSABI] = ELF_OSABI; 4184edf8e2afSMika Westerberg 4185edf8e2afSMika Westerberg elf->e_type = ET_CORE; 4186edf8e2afSMika Westerberg elf->e_machine = machine; 4187edf8e2afSMika Westerberg elf->e_version = EV_CURRENT; 4188edf8e2afSMika Westerberg elf->e_phoff = sizeof(struct elfhdr); 4189edf8e2afSMika Westerberg elf->e_flags = flags; 4190edf8e2afSMika Westerberg elf->e_ehsize = sizeof(struct elfhdr); 4191edf8e2afSMika Westerberg elf->e_phentsize = sizeof(struct elf_phdr); 4192edf8e2afSMika Westerberg elf->e_phnum = segs; 4193edf8e2afSMika Westerberg 4194edf8e2afSMika Westerberg bswap_ehdr(elf); 4195edf8e2afSMika Westerberg } 4196edf8e2afSMika Westerberg 4197edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) 4198edf8e2afSMika Westerberg { 4199edf8e2afSMika Westerberg phdr->p_type = PT_NOTE; 4200edf8e2afSMika Westerberg phdr->p_offset = offset; 4201edf8e2afSMika Westerberg phdr->p_vaddr = 0; 4202edf8e2afSMika Westerberg phdr->p_paddr = 0; 4203edf8e2afSMika Westerberg phdr->p_filesz = sz; 4204edf8e2afSMika Westerberg phdr->p_memsz = 0; 4205edf8e2afSMika Westerberg phdr->p_flags = 0; 4206edf8e2afSMika Westerberg phdr->p_align = 0; 4207edf8e2afSMika Westerberg 4208991f8f0cSRichard Henderson bswap_phdr(phdr, 1); 4209edf8e2afSMika Westerberg } 4210edf8e2afSMika Westerberg 4211edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note) 4212edf8e2afSMika Westerberg { 4213edf8e2afSMika Westerberg return (note->notesz); 4214edf8e2afSMika Westerberg } 4215edf8e2afSMika Westerberg 4216a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus, 4217edf8e2afSMika Westerberg const TaskState *ts, int signr) 4218edf8e2afSMika Westerberg { 4219edf8e2afSMika Westerberg (void) memset(prstatus, 0, sizeof (*prstatus)); 4220edf8e2afSMika Westerberg prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 4221edf8e2afSMika Westerberg prstatus->pr_pid = ts->ts_tid; 4222edf8e2afSMika Westerberg prstatus->pr_ppid = getppid(); 4223edf8e2afSMika Westerberg prstatus->pr_pgrp = getpgrp(); 4224edf8e2afSMika Westerberg prstatus->pr_sid = getsid(0); 4225edf8e2afSMika Westerberg 4226edf8e2afSMika Westerberg bswap_prstatus(prstatus); 4227edf8e2afSMika Westerberg } 4228edf8e2afSMika Westerberg 4229a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) 4230edf8e2afSMika Westerberg { 4231900cfbcaSJim Meyering char *base_filename; 4232edf8e2afSMika Westerberg unsigned int i, len; 4233edf8e2afSMika Westerberg 4234edf8e2afSMika Westerberg (void) memset(psinfo, 0, sizeof (*psinfo)); 4235edf8e2afSMika Westerberg 42365f779a3aSIlya Leoshkevich len = ts->info->env_strings - ts->info->arg_strings; 4237edf8e2afSMika Westerberg if (len >= ELF_PRARGSZ) 4238edf8e2afSMika Westerberg len = ELF_PRARGSZ - 1; 42395f779a3aSIlya Leoshkevich if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_strings, len)) { 4240edf8e2afSMika Westerberg return -EFAULT; 42415f779a3aSIlya Leoshkevich } 4242edf8e2afSMika Westerberg for (i = 0; i < len; i++) 4243edf8e2afSMika Westerberg if (psinfo->pr_psargs[i] == 0) 4244edf8e2afSMika Westerberg psinfo->pr_psargs[i] = ' '; 4245edf8e2afSMika Westerberg psinfo->pr_psargs[len] = 0; 4246edf8e2afSMika Westerberg 4247edf8e2afSMika Westerberg psinfo->pr_pid = getpid(); 4248edf8e2afSMika Westerberg psinfo->pr_ppid = getppid(); 4249edf8e2afSMika Westerberg psinfo->pr_pgrp = getpgrp(); 4250edf8e2afSMika Westerberg psinfo->pr_sid = getsid(0); 4251edf8e2afSMika Westerberg psinfo->pr_uid = getuid(); 4252edf8e2afSMika Westerberg psinfo->pr_gid = getgid(); 4253edf8e2afSMika Westerberg 4254900cfbcaSJim Meyering base_filename = g_path_get_basename(ts->bprm->filename); 4255900cfbcaSJim Meyering /* 4256900cfbcaSJim Meyering * Using strncpy here is fine: at max-length, 4257900cfbcaSJim Meyering * this field is not NUL-terminated. 4258900cfbcaSJim Meyering */ 4259edf8e2afSMika Westerberg (void) strncpy(psinfo->pr_fname, base_filename, 4260edf8e2afSMika Westerberg sizeof(psinfo->pr_fname)); 4261edf8e2afSMika Westerberg 4262900cfbcaSJim Meyering g_free(base_filename); 4263edf8e2afSMika Westerberg bswap_psinfo(psinfo); 4264edf8e2afSMika Westerberg return (0); 4265edf8e2afSMika Westerberg } 4266edf8e2afSMika Westerberg 4267edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) 4268edf8e2afSMika Westerberg { 4269edf8e2afSMika Westerberg elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; 4270edf8e2afSMika Westerberg elf_addr_t orig_auxv = auxv; 4271edf8e2afSMika Westerberg void *ptr; 4272125b0f55SAlexander Graf int len = ts->info->auxv_len; 4273edf8e2afSMika Westerberg 4274edf8e2afSMika Westerberg /* 4275edf8e2afSMika Westerberg * Auxiliary vector is stored in target process stack. It contains 4276edf8e2afSMika Westerberg * {type, value} pairs that we need to dump into note. This is not 4277edf8e2afSMika Westerberg * strictly necessary but we do it here for sake of completeness. 4278edf8e2afSMika Westerberg */ 4279edf8e2afSMika Westerberg 4280edf8e2afSMika Westerberg /* read in whole auxv vector and copy it to memelfnote */ 4281edf8e2afSMika Westerberg ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); 4282edf8e2afSMika Westerberg if (ptr != NULL) { 4283edf8e2afSMika Westerberg fill_note(note, "CORE", NT_AUXV, len, ptr); 4284edf8e2afSMika Westerberg unlock_user(ptr, auxv, len); 4285edf8e2afSMika Westerberg } 4286edf8e2afSMika Westerberg } 4287edf8e2afSMika Westerberg 4288edf8e2afSMika Westerberg /* 4289edf8e2afSMika Westerberg * Constructs name of coredump file. We have following convention 4290edf8e2afSMika Westerberg * for the name: 4291edf8e2afSMika Westerberg * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core 4292edf8e2afSMika Westerberg * 429368af19adSDaniel P. Berrangé * Returns the filename 4294edf8e2afSMika Westerberg */ 429568af19adSDaniel P. Berrangé static char *core_dump_filename(const TaskState *ts) 4296edf8e2afSMika Westerberg { 429768af19adSDaniel P. Berrangé g_autoptr(GDateTime) now = g_date_time_new_now_local(); 429868af19adSDaniel P. Berrangé g_autofree char *nowstr = g_date_time_format(now, "%Y%m%d-%H%M%S"); 429968af19adSDaniel P. Berrangé g_autofree char *base_filename = g_path_get_basename(ts->bprm->filename); 4300edf8e2afSMika Westerberg 430168af19adSDaniel P. Berrangé return g_strdup_printf("qemu_%s_%s_%d.core", 430268af19adSDaniel P. Berrangé base_filename, nowstr, (int)getpid()); 4303edf8e2afSMika Westerberg } 4304edf8e2afSMika Westerberg 4305edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size) 4306edf8e2afSMika Westerberg { 4307edf8e2afSMika Westerberg const char *bufp = (const char *)ptr; 4308edf8e2afSMika Westerberg ssize_t bytes_written, bytes_left; 4309edf8e2afSMika Westerberg struct rlimit dumpsize; 4310edf8e2afSMika Westerberg off_t pos; 4311edf8e2afSMika Westerberg 4312edf8e2afSMika Westerberg bytes_written = 0; 4313edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 4314edf8e2afSMika Westerberg if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { 4315edf8e2afSMika Westerberg if (errno == ESPIPE) { /* not a seekable stream */ 4316edf8e2afSMika Westerberg bytes_left = size; 4317edf8e2afSMika Westerberg } else { 4318edf8e2afSMika Westerberg return pos; 4319edf8e2afSMika Westerberg } 4320edf8e2afSMika Westerberg } else { 4321edf8e2afSMika Westerberg if (dumpsize.rlim_cur <= pos) { 4322edf8e2afSMika Westerberg return -1; 4323edf8e2afSMika Westerberg } else if (dumpsize.rlim_cur == RLIM_INFINITY) { 4324edf8e2afSMika Westerberg bytes_left = size; 4325edf8e2afSMika Westerberg } else { 4326edf8e2afSMika Westerberg size_t limit_left=dumpsize.rlim_cur - pos; 4327edf8e2afSMika Westerberg bytes_left = limit_left >= size ? size : limit_left ; 4328edf8e2afSMika Westerberg } 4329edf8e2afSMika Westerberg } 4330edf8e2afSMika Westerberg 4331edf8e2afSMika Westerberg /* 4332edf8e2afSMika Westerberg * In normal conditions, single write(2) should do but 4333edf8e2afSMika Westerberg * in case of socket etc. this mechanism is more portable. 4334edf8e2afSMika Westerberg */ 4335edf8e2afSMika Westerberg do { 4336edf8e2afSMika Westerberg bytes_written = write(fd, bufp, bytes_left); 4337edf8e2afSMika Westerberg if (bytes_written < 0) { 4338edf8e2afSMika Westerberg if (errno == EINTR) 4339edf8e2afSMika Westerberg continue; 4340edf8e2afSMika Westerberg return (-1); 4341edf8e2afSMika Westerberg } else if (bytes_written == 0) { /* eof */ 4342edf8e2afSMika Westerberg return (-1); 4343edf8e2afSMika Westerberg } 4344edf8e2afSMika Westerberg bufp += bytes_written; 4345edf8e2afSMika Westerberg bytes_left -= bytes_written; 4346edf8e2afSMika Westerberg } while (bytes_left > 0); 4347edf8e2afSMika Westerberg 4348edf8e2afSMika Westerberg return (0); 4349edf8e2afSMika Westerberg } 4350edf8e2afSMika Westerberg 4351edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd) 4352edf8e2afSMika Westerberg { 4353edf8e2afSMika Westerberg struct elf_note en; 4354edf8e2afSMika Westerberg 4355edf8e2afSMika Westerberg en.n_namesz = men->namesz; 4356edf8e2afSMika Westerberg en.n_type = men->type; 4357edf8e2afSMika Westerberg en.n_descsz = men->datasz; 4358edf8e2afSMika Westerberg 4359edf8e2afSMika Westerberg bswap_note(&en); 4360edf8e2afSMika Westerberg 4361edf8e2afSMika Westerberg if (dump_write(fd, &en, sizeof(en)) != 0) 4362edf8e2afSMika Westerberg return (-1); 4363edf8e2afSMika Westerberg if (dump_write(fd, men->name, men->namesz_rounded) != 0) 4364edf8e2afSMika Westerberg return (-1); 436580f5ce75SLaurent Vivier if (dump_write(fd, men->data, men->datasz_rounded) != 0) 4366edf8e2afSMika Westerberg return (-1); 4367edf8e2afSMika Westerberg 4368edf8e2afSMika Westerberg return (0); 4369edf8e2afSMika Westerberg } 4370edf8e2afSMika Westerberg 43719349b4f9SAndreas Färber static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env) 4372edf8e2afSMika Westerberg { 437329a0af61SRichard Henderson CPUState *cpu = env_cpu((CPUArchState *)env); 43740429a971SAndreas Färber TaskState *ts = (TaskState *)cpu->opaque; 4375edf8e2afSMika Westerberg struct elf_thread_status *ets; 4376edf8e2afSMika Westerberg 43777267c094SAnthony Liguori ets = g_malloc0(sizeof (*ets)); 4378edf8e2afSMika Westerberg ets->num_notes = 1; /* only prstatus is dumped */ 4379edf8e2afSMika Westerberg fill_prstatus(&ets->prstatus, ts, 0); 4380edf8e2afSMika Westerberg elf_core_copy_regs(&ets->prstatus.pr_reg, env); 4381edf8e2afSMika Westerberg fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus), 4382edf8e2afSMika Westerberg &ets->prstatus); 4383edf8e2afSMika Westerberg 438472cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link); 4385edf8e2afSMika Westerberg 4386edf8e2afSMika Westerberg info->notes_size += note_size(&ets->notes[0]); 4387edf8e2afSMika Westerberg } 4388edf8e2afSMika Westerberg 43896afafa86SPeter Maydell static void init_note_info(struct elf_note_info *info) 43906afafa86SPeter Maydell { 43916afafa86SPeter Maydell /* Initialize the elf_note_info structure so that it is at 43926afafa86SPeter Maydell * least safe to call free_note_info() on it. Must be 43936afafa86SPeter Maydell * called before calling fill_note_info(). 43946afafa86SPeter Maydell */ 43956afafa86SPeter Maydell memset(info, 0, sizeof (*info)); 43966afafa86SPeter Maydell QTAILQ_INIT(&info->thread_list); 43976afafa86SPeter Maydell } 43986afafa86SPeter Maydell 4399edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info, 44009349b4f9SAndreas Färber long signr, const CPUArchState *env) 4401edf8e2afSMika Westerberg { 4402edf8e2afSMika Westerberg #define NUMNOTES 3 440329a0af61SRichard Henderson CPUState *cpu = env_cpu((CPUArchState *)env); 44040429a971SAndreas Färber TaskState *ts = (TaskState *)cpu->opaque; 4405edf8e2afSMika Westerberg int i; 4406edf8e2afSMika Westerberg 4407c78d65e8SMarkus Armbruster info->notes = g_new0(struct memelfnote, NUMNOTES); 4408edf8e2afSMika Westerberg if (info->notes == NULL) 4409edf8e2afSMika Westerberg return (-ENOMEM); 44107267c094SAnthony Liguori info->prstatus = g_malloc0(sizeof (*info->prstatus)); 4411edf8e2afSMika Westerberg if (info->prstatus == NULL) 4412edf8e2afSMika Westerberg return (-ENOMEM); 44137267c094SAnthony Liguori info->psinfo = g_malloc0(sizeof (*info->psinfo)); 4414edf8e2afSMika Westerberg if (info->prstatus == NULL) 4415edf8e2afSMika Westerberg return (-ENOMEM); 4416edf8e2afSMika Westerberg 4417edf8e2afSMika Westerberg /* 4418edf8e2afSMika Westerberg * First fill in status (and registers) of current thread 4419edf8e2afSMika Westerberg * including process info & aux vector. 4420edf8e2afSMika Westerberg */ 4421edf8e2afSMika Westerberg fill_prstatus(info->prstatus, ts, signr); 4422edf8e2afSMika Westerberg elf_core_copy_regs(&info->prstatus->pr_reg, env); 4423edf8e2afSMika Westerberg fill_note(&info->notes[0], "CORE", NT_PRSTATUS, 4424edf8e2afSMika Westerberg sizeof (*info->prstatus), info->prstatus); 4425edf8e2afSMika Westerberg fill_psinfo(info->psinfo, ts); 4426edf8e2afSMika Westerberg fill_note(&info->notes[1], "CORE", NT_PRPSINFO, 4427edf8e2afSMika Westerberg sizeof (*info->psinfo), info->psinfo); 4428edf8e2afSMika Westerberg fill_auxv_note(&info->notes[2], ts); 4429edf8e2afSMika Westerberg info->numnote = 3; 4430edf8e2afSMika Westerberg 4431edf8e2afSMika Westerberg info->notes_size = 0; 4432edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 4433edf8e2afSMika Westerberg info->notes_size += note_size(&info->notes[i]); 4434edf8e2afSMika Westerberg 4435edf8e2afSMika Westerberg /* read and fill status of all threads */ 4436370ed600SJamie Iles WITH_QEMU_LOCK_GUARD(&qemu_cpu_list_lock) { 4437bdc44640SAndreas Färber CPU_FOREACH(cpu) { 4438a2247f8eSAndreas Färber if (cpu == thread_cpu) { 4439edf8e2afSMika Westerberg continue; 4440182735efSAndreas Färber } 4441b77af26eSRichard Henderson fill_thread_info(info, cpu_env(cpu)); 4442edf8e2afSMika Westerberg } 4443370ed600SJamie Iles } 4444edf8e2afSMika Westerberg 4445edf8e2afSMika Westerberg return (0); 4446edf8e2afSMika Westerberg } 4447edf8e2afSMika Westerberg 4448edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info) 4449edf8e2afSMika Westerberg { 4450edf8e2afSMika Westerberg struct elf_thread_status *ets; 4451edf8e2afSMika Westerberg 445272cf2d4fSBlue Swirl while (!QTAILQ_EMPTY(&info->thread_list)) { 445372cf2d4fSBlue Swirl ets = QTAILQ_FIRST(&info->thread_list); 445472cf2d4fSBlue Swirl QTAILQ_REMOVE(&info->thread_list, ets, ets_link); 44557267c094SAnthony Liguori g_free(ets); 4456edf8e2afSMika Westerberg } 4457edf8e2afSMika Westerberg 44587267c094SAnthony Liguori g_free(info->prstatus); 44597267c094SAnthony Liguori g_free(info->psinfo); 44607267c094SAnthony Liguori g_free(info->notes); 4461edf8e2afSMika Westerberg } 4462edf8e2afSMika Westerberg 4463edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd) 4464edf8e2afSMika Westerberg { 4465edf8e2afSMika Westerberg struct elf_thread_status *ets; 4466edf8e2afSMika Westerberg int i, error = 0; 4467edf8e2afSMika Westerberg 4468edf8e2afSMika Westerberg /* write prstatus, psinfo and auxv for current thread */ 4469edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 4470edf8e2afSMika Westerberg if ((error = write_note(&info->notes[i], fd)) != 0) 4471edf8e2afSMika Westerberg return (error); 4472edf8e2afSMika Westerberg 4473edf8e2afSMika Westerberg /* write prstatus for each thread */ 447452a53afeSEmilio G. Cota QTAILQ_FOREACH(ets, &info->thread_list, ets_link) { 4475edf8e2afSMika Westerberg if ((error = write_note(&ets->notes[0], fd)) != 0) 4476edf8e2afSMika Westerberg return (error); 4477edf8e2afSMika Westerberg } 4478edf8e2afSMika Westerberg 4479edf8e2afSMika Westerberg return (0); 4480edf8e2afSMika Westerberg } 4481edf8e2afSMika Westerberg 4482edf8e2afSMika Westerberg /* 4483edf8e2afSMika Westerberg * Write out ELF coredump. 4484edf8e2afSMika Westerberg * 4485edf8e2afSMika Westerberg * See documentation of ELF object file format in: 4486edf8e2afSMika Westerberg * http://www.caldera.com/developers/devspecs/gabi41.pdf 4487edf8e2afSMika Westerberg * 4488edf8e2afSMika Westerberg * Coredump format in linux is following: 4489edf8e2afSMika Westerberg * 4490edf8e2afSMika Westerberg * 0 +----------------------+ \ 4491edf8e2afSMika Westerberg * | ELF header | ET_CORE | 4492edf8e2afSMika Westerberg * +----------------------+ | 4493edf8e2afSMika Westerberg * | ELF program headers | |--- headers 4494edf8e2afSMika Westerberg * | - NOTE section | | 4495edf8e2afSMika Westerberg * | - PT_LOAD sections | | 4496edf8e2afSMika Westerberg * +----------------------+ / 4497edf8e2afSMika Westerberg * | NOTEs: | 4498edf8e2afSMika Westerberg * | - NT_PRSTATUS | 4499edf8e2afSMika Westerberg * | - NT_PRSINFO | 4500edf8e2afSMika Westerberg * | - NT_AUXV | 4501edf8e2afSMika Westerberg * +----------------------+ <-- aligned to target page 4502edf8e2afSMika Westerberg * | Process memory dump | 4503edf8e2afSMika Westerberg * : : 4504edf8e2afSMika Westerberg * . . 4505edf8e2afSMika Westerberg * : : 4506edf8e2afSMika Westerberg * | | 4507edf8e2afSMika Westerberg * +----------------------+ 4508edf8e2afSMika Westerberg * 4509edf8e2afSMika Westerberg * NT_PRSTATUS -> struct elf_prstatus (per thread) 4510edf8e2afSMika Westerberg * NT_PRSINFO -> struct elf_prpsinfo 4511edf8e2afSMika Westerberg * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()). 4512edf8e2afSMika Westerberg * 4513edf8e2afSMika Westerberg * Format follows System V format as close as possible. Current 4514edf8e2afSMika Westerberg * version limitations are as follows: 4515edf8e2afSMika Westerberg * - no floating point registers are dumped 4516edf8e2afSMika Westerberg * 4517edf8e2afSMika Westerberg * Function returns 0 in case of success, negative errno otherwise. 4518edf8e2afSMika Westerberg * 4519edf8e2afSMika Westerberg * TODO: make this work also during runtime: it should be 4520edf8e2afSMika Westerberg * possible to force coredump from running process and then 4521edf8e2afSMika Westerberg * continue processing. For example qemu could set up SIGUSR2 4522edf8e2afSMika Westerberg * handler (provided that target process haven't registered 4523edf8e2afSMika Westerberg * handler for that) that does the dump when signal is received. 4524edf8e2afSMika Westerberg */ 45259349b4f9SAndreas Färber static int elf_core_dump(int signr, const CPUArchState *env) 4526edf8e2afSMika Westerberg { 452729a0af61SRichard Henderson const CPUState *cpu = env_cpu((CPUArchState *)env); 45280429a971SAndreas Färber const TaskState *ts = (const TaskState *)cpu->opaque; 4529edf8e2afSMika Westerberg struct vm_area_struct *vma = NULL; 453068af19adSDaniel P. Berrangé g_autofree char *corefile = NULL; 4531edf8e2afSMika Westerberg struct elf_note_info info; 4532edf8e2afSMika Westerberg struct elfhdr elf; 4533edf8e2afSMika Westerberg struct elf_phdr phdr; 4534edf8e2afSMika Westerberg struct rlimit dumpsize; 4535edf8e2afSMika Westerberg struct mm_struct *mm = NULL; 4536edf8e2afSMika Westerberg off_t offset = 0, data_offset = 0; 4537edf8e2afSMika Westerberg int segs = 0; 4538edf8e2afSMika Westerberg int fd = -1; 4539edf8e2afSMika Westerberg 45406afafa86SPeter Maydell init_note_info(&info); 45416afafa86SPeter Maydell 4542edf8e2afSMika Westerberg errno = 0; 4543edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 4544edf8e2afSMika Westerberg if (dumpsize.rlim_cur == 0) 4545edf8e2afSMika Westerberg return 0; 4546edf8e2afSMika Westerberg 454768af19adSDaniel P. Berrangé corefile = core_dump_filename(ts); 4548edf8e2afSMika Westerberg 4549edf8e2afSMika Westerberg if ((fd = open(corefile, O_WRONLY | O_CREAT, 4550edf8e2afSMika Westerberg S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) 4551edf8e2afSMika Westerberg return (-errno); 4552edf8e2afSMika Westerberg 4553edf8e2afSMika Westerberg /* 4554edf8e2afSMika Westerberg * Walk through target process memory mappings and 4555edf8e2afSMika Westerberg * set up structure containing this information. After 4556edf8e2afSMika Westerberg * this point vma_xxx functions can be used. 4557edf8e2afSMika Westerberg */ 4558edf8e2afSMika Westerberg if ((mm = vma_init()) == NULL) 4559edf8e2afSMika Westerberg goto out; 4560edf8e2afSMika Westerberg 4561edf8e2afSMika Westerberg walk_memory_regions(mm, vma_walker); 4562edf8e2afSMika Westerberg segs = vma_get_mapping_count(mm); 4563edf8e2afSMika Westerberg 4564edf8e2afSMika Westerberg /* 4565edf8e2afSMika Westerberg * Construct valid coredump ELF header. We also 4566edf8e2afSMika Westerberg * add one more segment for notes. 4567edf8e2afSMika Westerberg */ 4568edf8e2afSMika Westerberg fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0); 4569edf8e2afSMika Westerberg if (dump_write(fd, &elf, sizeof (elf)) != 0) 4570edf8e2afSMika Westerberg goto out; 4571edf8e2afSMika Westerberg 4572b6af0975SDaniel P. Berrange /* fill in the in-memory version of notes */ 4573edf8e2afSMika Westerberg if (fill_note_info(&info, signr, env) < 0) 4574edf8e2afSMika Westerberg goto out; 4575edf8e2afSMika Westerberg 4576edf8e2afSMika Westerberg offset += sizeof (elf); /* elf header */ 4577edf8e2afSMika Westerberg offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */ 4578edf8e2afSMika Westerberg 4579edf8e2afSMika Westerberg /* write out notes program header */ 4580edf8e2afSMika Westerberg fill_elf_note_phdr(&phdr, info.notes_size, offset); 4581edf8e2afSMika Westerberg 4582edf8e2afSMika Westerberg offset += info.notes_size; 4583edf8e2afSMika Westerberg if (dump_write(fd, &phdr, sizeof (phdr)) != 0) 4584edf8e2afSMika Westerberg goto out; 4585edf8e2afSMika Westerberg 4586edf8e2afSMika Westerberg /* 4587edf8e2afSMika Westerberg * ELF specification wants data to start at page boundary so 4588edf8e2afSMika Westerberg * we align it here. 4589edf8e2afSMika Westerberg */ 459080f5ce75SLaurent Vivier data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE); 4591edf8e2afSMika Westerberg 4592edf8e2afSMika Westerberg /* 4593edf8e2afSMika Westerberg * Write program headers for memory regions mapped in 4594edf8e2afSMika Westerberg * the target process. 4595edf8e2afSMika Westerberg */ 4596edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 4597edf8e2afSMika Westerberg (void) memset(&phdr, 0, sizeof (phdr)); 4598edf8e2afSMika Westerberg 4599edf8e2afSMika Westerberg phdr.p_type = PT_LOAD; 4600edf8e2afSMika Westerberg phdr.p_offset = offset; 4601edf8e2afSMika Westerberg phdr.p_vaddr = vma->vma_start; 4602edf8e2afSMika Westerberg phdr.p_paddr = 0; 4603edf8e2afSMika Westerberg phdr.p_filesz = vma_dump_size(vma); 4604edf8e2afSMika Westerberg offset += phdr.p_filesz; 4605edf8e2afSMika Westerberg phdr.p_memsz = vma->vma_end - vma->vma_start; 4606edf8e2afSMika Westerberg phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0; 4607edf8e2afSMika Westerberg if (vma->vma_flags & PROT_WRITE) 4608edf8e2afSMika Westerberg phdr.p_flags |= PF_W; 4609edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) 4610edf8e2afSMika Westerberg phdr.p_flags |= PF_X; 4611edf8e2afSMika Westerberg phdr.p_align = ELF_EXEC_PAGESIZE; 4612edf8e2afSMika Westerberg 461380f5ce75SLaurent Vivier bswap_phdr(&phdr, 1); 4614772034b6SPeter Maydell if (dump_write(fd, &phdr, sizeof(phdr)) != 0) { 4615772034b6SPeter Maydell goto out; 4616772034b6SPeter Maydell } 4617edf8e2afSMika Westerberg } 4618edf8e2afSMika Westerberg 4619edf8e2afSMika Westerberg /* 4620edf8e2afSMika Westerberg * Next we write notes just after program headers. No 4621edf8e2afSMika Westerberg * alignment needed here. 4622edf8e2afSMika Westerberg */ 4623edf8e2afSMika Westerberg if (write_note_info(&info, fd) < 0) 4624edf8e2afSMika Westerberg goto out; 4625edf8e2afSMika Westerberg 4626edf8e2afSMika Westerberg /* align data to page boundary */ 4627edf8e2afSMika Westerberg if (lseek(fd, data_offset, SEEK_SET) != data_offset) 4628edf8e2afSMika Westerberg goto out; 4629edf8e2afSMika Westerberg 4630edf8e2afSMika Westerberg /* 4631edf8e2afSMika Westerberg * Finally we can dump process memory into corefile as well. 4632edf8e2afSMika Westerberg */ 4633edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 4634edf8e2afSMika Westerberg abi_ulong addr; 4635edf8e2afSMika Westerberg abi_ulong end; 4636edf8e2afSMika Westerberg 4637edf8e2afSMika Westerberg end = vma->vma_start + vma_dump_size(vma); 4638edf8e2afSMika Westerberg 4639edf8e2afSMika Westerberg for (addr = vma->vma_start; addr < end; 4640edf8e2afSMika Westerberg addr += TARGET_PAGE_SIZE) { 4641edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 4642edf8e2afSMika Westerberg int error; 4643edf8e2afSMika Westerberg 4644edf8e2afSMika Westerberg /* 4645edf8e2afSMika Westerberg * Read in page from target process memory and 4646edf8e2afSMika Westerberg * write it to coredump file. 4647edf8e2afSMika Westerberg */ 4648edf8e2afSMika Westerberg error = copy_from_user(page, addr, sizeof (page)); 4649edf8e2afSMika Westerberg if (error != 0) { 465049995e17SAurelien Jarno (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n", 4651edf8e2afSMika Westerberg addr); 4652edf8e2afSMika Westerberg errno = -error; 4653edf8e2afSMika Westerberg goto out; 4654edf8e2afSMika Westerberg } 4655edf8e2afSMika Westerberg if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0) 4656edf8e2afSMika Westerberg goto out; 4657edf8e2afSMika Westerberg } 4658edf8e2afSMika Westerberg } 4659edf8e2afSMika Westerberg 4660edf8e2afSMika Westerberg out: 4661edf8e2afSMika Westerberg free_note_info(&info); 4662edf8e2afSMika Westerberg if (mm != NULL) 4663edf8e2afSMika Westerberg vma_delete(mm); 4664edf8e2afSMika Westerberg (void) close(fd); 4665edf8e2afSMika Westerberg 4666edf8e2afSMika Westerberg if (errno != 0) 4667edf8e2afSMika Westerberg return (-errno); 4668edf8e2afSMika Westerberg return (0); 4669edf8e2afSMika Westerberg } 4670edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 4671edf8e2afSMika Westerberg 4672e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) 4673e5fe0c52Spbrook { 4674e5fe0c52Spbrook init_thread(regs, infop); 4675e5fe0c52Spbrook } 4676