131e31b8aSbellard /* This is the Linux kernel elf-loading code, ported into user space */ 2edf8e2afSMika Westerberg #include <sys/time.h> 3edf8e2afSMika Westerberg #include <sys/param.h> 431e31b8aSbellard 531e31b8aSbellard #include <stdio.h> 631e31b8aSbellard #include <sys/types.h> 731e31b8aSbellard #include <fcntl.h> 831e31b8aSbellard #include <errno.h> 931e31b8aSbellard #include <unistd.h> 1031e31b8aSbellard #include <sys/mman.h> 11edf8e2afSMika Westerberg #include <sys/resource.h> 1231e31b8aSbellard #include <stdlib.h> 1331e31b8aSbellard #include <string.h> 14edf8e2afSMika Westerberg #include <time.h> 1531e31b8aSbellard 163ef693a0Sbellard #include "qemu.h" 17689f936fSbellard #include "disas.h" 1831e31b8aSbellard 19e58ffeb3Smalc #ifdef _ARCH_PPC64 20a6cc84f4Smalc #undef ARCH_DLINFO 21a6cc84f4Smalc #undef ELF_PLATFORM 22a6cc84f4Smalc #undef ELF_HWCAP 23a6cc84f4Smalc #undef ELF_CLASS 24a6cc84f4Smalc #undef ELF_DATA 25a6cc84f4Smalc #undef ELF_ARCH 26a6cc84f4Smalc #endif 27a6cc84f4Smalc 28edf8e2afSMika Westerberg #define ELF_OSABI ELFOSABI_SYSV 29edf8e2afSMika Westerberg 30cb33da57Sblueswir1 /* from personality.h */ 31cb33da57Sblueswir1 32cb33da57Sblueswir1 /* 33cb33da57Sblueswir1 * Flags for bug emulation. 34cb33da57Sblueswir1 * 35cb33da57Sblueswir1 * These occupy the top three bytes. 36cb33da57Sblueswir1 */ 37cb33da57Sblueswir1 enum { 38cb33da57Sblueswir1 ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */ 39cb33da57Sblueswir1 FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors 40cb33da57Sblueswir1 * (signal handling) 41cb33da57Sblueswir1 */ 42cb33da57Sblueswir1 MMAP_PAGE_ZERO = 0x0100000, 43cb33da57Sblueswir1 ADDR_COMPAT_LAYOUT = 0x0200000, 44cb33da57Sblueswir1 READ_IMPLIES_EXEC = 0x0400000, 45cb33da57Sblueswir1 ADDR_LIMIT_32BIT = 0x0800000, 46cb33da57Sblueswir1 SHORT_INODE = 0x1000000, 47cb33da57Sblueswir1 WHOLE_SECONDS = 0x2000000, 48cb33da57Sblueswir1 STICKY_TIMEOUTS = 0x4000000, 49cb33da57Sblueswir1 ADDR_LIMIT_3GB = 0x8000000, 50cb33da57Sblueswir1 }; 51cb33da57Sblueswir1 52cb33da57Sblueswir1 /* 53cb33da57Sblueswir1 * Personality types. 54cb33da57Sblueswir1 * 55cb33da57Sblueswir1 * These go in the low byte. Avoid using the top bit, it will 56cb33da57Sblueswir1 * conflict with error returns. 57cb33da57Sblueswir1 */ 58cb33da57Sblueswir1 enum { 59cb33da57Sblueswir1 PER_LINUX = 0x0000, 60cb33da57Sblueswir1 PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, 61cb33da57Sblueswir1 PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS, 62cb33da57Sblueswir1 PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 63cb33da57Sblueswir1 PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, 64cb33da57Sblueswir1 PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | 65cb33da57Sblueswir1 WHOLE_SECONDS | SHORT_INODE, 66cb33da57Sblueswir1 PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, 67cb33da57Sblueswir1 PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, 68cb33da57Sblueswir1 PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, 69cb33da57Sblueswir1 PER_BSD = 0x0006, 70cb33da57Sblueswir1 PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, 71cb33da57Sblueswir1 PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, 72cb33da57Sblueswir1 PER_LINUX32 = 0x0008, 73cb33da57Sblueswir1 PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB, 74cb33da57Sblueswir1 PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */ 75cb33da57Sblueswir1 PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */ 76cb33da57Sblueswir1 PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */ 77cb33da57Sblueswir1 PER_RISCOS = 0x000c, 78cb33da57Sblueswir1 PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, 79cb33da57Sblueswir1 PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 80cb33da57Sblueswir1 PER_OSF4 = 0x000f, /* OSF/1 v4 */ 81cb33da57Sblueswir1 PER_HPUX = 0x0010, 82cb33da57Sblueswir1 PER_MASK = 0x00ff, 83cb33da57Sblueswir1 }; 84cb33da57Sblueswir1 85cb33da57Sblueswir1 /* 86cb33da57Sblueswir1 * Return the base personality without flags. 87cb33da57Sblueswir1 */ 88cb33da57Sblueswir1 #define personality(pers) (pers & PER_MASK) 89cb33da57Sblueswir1 9083fb7adfSbellard /* this flag is uneffective under linux too, should be deleted */ 9183fb7adfSbellard #ifndef MAP_DENYWRITE 9283fb7adfSbellard #define MAP_DENYWRITE 0 9383fb7adfSbellard #endif 9483fb7adfSbellard 9583fb7adfSbellard /* should probably go in elf.h */ 9683fb7adfSbellard #ifndef ELIBBAD 9783fb7adfSbellard #define ELIBBAD 80 9883fb7adfSbellard #endif 9983fb7adfSbellard 10021e807faSNathan Froyd typedef target_ulong target_elf_greg_t; 10121e807faSNathan Froyd #ifdef USE_UID16 10221e807faSNathan Froyd typedef uint16_t target_uid_t; 10321e807faSNathan Froyd typedef uint16_t target_gid_t; 10421e807faSNathan Froyd #else 10521e807faSNathan Froyd typedef uint32_t target_uid_t; 10621e807faSNathan Froyd typedef uint32_t target_gid_t; 10721e807faSNathan Froyd #endif 10821e807faSNathan Froyd typedef int32_t target_pid_t; 10921e807faSNathan Froyd 11030ac07d4Sbellard #ifdef TARGET_I386 11130ac07d4Sbellard 11215338fd7Sbellard #define ELF_PLATFORM get_elf_platform() 11315338fd7Sbellard 11415338fd7Sbellard static const char *get_elf_platform(void) 11515338fd7Sbellard { 11615338fd7Sbellard static char elf_platform[] = "i386"; 117d5975363Spbrook int family = (thread_env->cpuid_version >> 8) & 0xff; 11815338fd7Sbellard if (family > 6) 11915338fd7Sbellard family = 6; 12015338fd7Sbellard if (family >= 3) 12115338fd7Sbellard elf_platform[1] = '0' + family; 12215338fd7Sbellard return elf_platform; 12315338fd7Sbellard } 12415338fd7Sbellard 12515338fd7Sbellard #define ELF_HWCAP get_elf_hwcap() 12615338fd7Sbellard 12715338fd7Sbellard static uint32_t get_elf_hwcap(void) 12815338fd7Sbellard { 129d5975363Spbrook return thread_env->cpuid_features; 13015338fd7Sbellard } 13115338fd7Sbellard 13284409ddbSj_mayer #ifdef TARGET_X86_64 13384409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL 13484409ddbSj_mayer #define elf_check_arch(x) ( ((x) == ELF_ARCH) ) 13584409ddbSj_mayer 13684409ddbSj_mayer #define ELF_CLASS ELFCLASS64 13784409ddbSj_mayer #define ELF_DATA ELFDATA2LSB 13884409ddbSj_mayer #define ELF_ARCH EM_X86_64 13984409ddbSj_mayer 14084409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 14184409ddbSj_mayer { 14284409ddbSj_mayer regs->rax = 0; 14384409ddbSj_mayer regs->rsp = infop->start_stack; 14484409ddbSj_mayer regs->rip = infop->entry; 14584409ddbSj_mayer } 14684409ddbSj_mayer 1479edc5d79SMika Westerberg #define ELF_NREG 27 148c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1499edc5d79SMika Westerberg 1509edc5d79SMika Westerberg /* 1519edc5d79SMika Westerberg * Note that ELF_NREG should be 29 as there should be place for 1529edc5d79SMika Westerberg * TRAPNO and ERR "registers" as well but linux doesn't dump 1539edc5d79SMika Westerberg * those. 1549edc5d79SMika Westerberg * 1559edc5d79SMika Westerberg * See linux kernel: arch/x86/include/asm/elf.h 1569edc5d79SMika Westerberg */ 157c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 1589edc5d79SMika Westerberg { 1599edc5d79SMika Westerberg (*regs)[0] = env->regs[15]; 1609edc5d79SMika Westerberg (*regs)[1] = env->regs[14]; 1619edc5d79SMika Westerberg (*regs)[2] = env->regs[13]; 1629edc5d79SMika Westerberg (*regs)[3] = env->regs[12]; 1639edc5d79SMika Westerberg (*regs)[4] = env->regs[R_EBP]; 1649edc5d79SMika Westerberg (*regs)[5] = env->regs[R_EBX]; 1659edc5d79SMika Westerberg (*regs)[6] = env->regs[11]; 1669edc5d79SMika Westerberg (*regs)[7] = env->regs[10]; 1679edc5d79SMika Westerberg (*regs)[8] = env->regs[9]; 1689edc5d79SMika Westerberg (*regs)[9] = env->regs[8]; 1699edc5d79SMika Westerberg (*regs)[10] = env->regs[R_EAX]; 1709edc5d79SMika Westerberg (*regs)[11] = env->regs[R_ECX]; 1719edc5d79SMika Westerberg (*regs)[12] = env->regs[R_EDX]; 1729edc5d79SMika Westerberg (*regs)[13] = env->regs[R_ESI]; 1739edc5d79SMika Westerberg (*regs)[14] = env->regs[R_EDI]; 1749edc5d79SMika Westerberg (*regs)[15] = env->regs[R_EAX]; /* XXX */ 1759edc5d79SMika Westerberg (*regs)[16] = env->eip; 1769edc5d79SMika Westerberg (*regs)[17] = env->segs[R_CS].selector & 0xffff; 1779edc5d79SMika Westerberg (*regs)[18] = env->eflags; 1789edc5d79SMika Westerberg (*regs)[19] = env->regs[R_ESP]; 1799edc5d79SMika Westerberg (*regs)[20] = env->segs[R_SS].selector & 0xffff; 1809edc5d79SMika Westerberg (*regs)[21] = env->segs[R_FS].selector & 0xffff; 1819edc5d79SMika Westerberg (*regs)[22] = env->segs[R_GS].selector & 0xffff; 1829edc5d79SMika Westerberg (*regs)[23] = env->segs[R_DS].selector & 0xffff; 1839edc5d79SMika Westerberg (*regs)[24] = env->segs[R_ES].selector & 0xffff; 1849edc5d79SMika Westerberg (*regs)[25] = env->segs[R_FS].selector & 0xffff; 1859edc5d79SMika Westerberg (*regs)[26] = env->segs[R_GS].selector & 0xffff; 1869edc5d79SMika Westerberg } 1879edc5d79SMika Westerberg 18884409ddbSj_mayer #else 18984409ddbSj_mayer 19030ac07d4Sbellard #define ELF_START_MMAP 0x80000000 19130ac07d4Sbellard 19230ac07d4Sbellard /* 19330ac07d4Sbellard * This is used to ensure we don't load something for the wrong architecture. 19430ac07d4Sbellard */ 19530ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) 19630ac07d4Sbellard 19730ac07d4Sbellard /* 19830ac07d4Sbellard * These are used to set parameters in the core dumps. 19930ac07d4Sbellard */ 20030ac07d4Sbellard #define ELF_CLASS ELFCLASS32 20130ac07d4Sbellard #define ELF_DATA ELFDATA2LSB 20230ac07d4Sbellard #define ELF_ARCH EM_386 20330ac07d4Sbellard 204e5fe0c52Spbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 205e5fe0c52Spbrook { 206e5fe0c52Spbrook regs->esp = infop->start_stack; 207e5fe0c52Spbrook regs->eip = infop->entry; 208e5fe0c52Spbrook 20930ac07d4Sbellard /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program 21030ac07d4Sbellard starts %edx contains a pointer to a function which might be 21130ac07d4Sbellard registered using `atexit'. This provides a mean for the 21230ac07d4Sbellard dynamic linker to call DT_FINI functions for shared libraries 21330ac07d4Sbellard that have been loaded before the code runs. 21430ac07d4Sbellard 21530ac07d4Sbellard A value of 0 tells we have no such handler. */ 216e5fe0c52Spbrook regs->edx = 0; 217b346ff46Sbellard } 2189edc5d79SMika Westerberg 2199edc5d79SMika Westerberg #define ELF_NREG 17 220c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 2219edc5d79SMika Westerberg 2229edc5d79SMika Westerberg /* 2239edc5d79SMika Westerberg * Note that ELF_NREG should be 19 as there should be place for 2249edc5d79SMika Westerberg * TRAPNO and ERR "registers" as well but linux doesn't dump 2259edc5d79SMika Westerberg * those. 2269edc5d79SMika Westerberg * 2279edc5d79SMika Westerberg * See linux kernel: arch/x86/include/asm/elf.h 2289edc5d79SMika Westerberg */ 229c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 2309edc5d79SMika Westerberg { 2319edc5d79SMika Westerberg (*regs)[0] = env->regs[R_EBX]; 2329edc5d79SMika Westerberg (*regs)[1] = env->regs[R_ECX]; 2339edc5d79SMika Westerberg (*regs)[2] = env->regs[R_EDX]; 2349edc5d79SMika Westerberg (*regs)[3] = env->regs[R_ESI]; 2359edc5d79SMika Westerberg (*regs)[4] = env->regs[R_EDI]; 2369edc5d79SMika Westerberg (*regs)[5] = env->regs[R_EBP]; 2379edc5d79SMika Westerberg (*regs)[6] = env->regs[R_EAX]; 2389edc5d79SMika Westerberg (*regs)[7] = env->segs[R_DS].selector & 0xffff; 2399edc5d79SMika Westerberg (*regs)[8] = env->segs[R_ES].selector & 0xffff; 2409edc5d79SMika Westerberg (*regs)[9] = env->segs[R_FS].selector & 0xffff; 2419edc5d79SMika Westerberg (*regs)[10] = env->segs[R_GS].selector & 0xffff; 2429edc5d79SMika Westerberg (*regs)[11] = env->regs[R_EAX]; /* XXX */ 2439edc5d79SMika Westerberg (*regs)[12] = env->eip; 2449edc5d79SMika Westerberg (*regs)[13] = env->segs[R_CS].selector & 0xffff; 2459edc5d79SMika Westerberg (*regs)[14] = env->eflags; 2469edc5d79SMika Westerberg (*regs)[15] = env->regs[R_ESP]; 2479edc5d79SMika Westerberg (*regs)[16] = env->segs[R_SS].selector & 0xffff; 2489edc5d79SMika Westerberg } 24984409ddbSj_mayer #endif 250b346ff46Sbellard 2519edc5d79SMika Westerberg #define USE_ELF_CORE_DUMP 252b346ff46Sbellard #define ELF_EXEC_PAGESIZE 4096 253b346ff46Sbellard 254b346ff46Sbellard #endif 255b346ff46Sbellard 256b346ff46Sbellard #ifdef TARGET_ARM 257b346ff46Sbellard 258b346ff46Sbellard #define ELF_START_MMAP 0x80000000 259b346ff46Sbellard 260b346ff46Sbellard #define elf_check_arch(x) ( (x) == EM_ARM ) 261b346ff46Sbellard 262b346ff46Sbellard #define ELF_CLASS ELFCLASS32 263b346ff46Sbellard #ifdef TARGET_WORDS_BIGENDIAN 264b346ff46Sbellard #define ELF_DATA ELFDATA2MSB 265b346ff46Sbellard #else 266b346ff46Sbellard #define ELF_DATA ELFDATA2LSB 267b346ff46Sbellard #endif 268b346ff46Sbellard #define ELF_ARCH EM_ARM 269b346ff46Sbellard 270b346ff46Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 271b346ff46Sbellard { 272992f48a0Sblueswir1 abi_long stack = infop->start_stack; 273b346ff46Sbellard memset(regs, 0, sizeof(*regs)); 274b346ff46Sbellard regs->ARM_cpsr = 0x10; 2750240ded8Spbrook if (infop->entry & 1) 2760240ded8Spbrook regs->ARM_cpsr |= CPSR_T; 2770240ded8Spbrook regs->ARM_pc = infop->entry & 0xfffffffe; 278b346ff46Sbellard regs->ARM_sp = infop->start_stack; 2792f619698Sbellard /* FIXME - what to for failure of get_user()? */ 2802f619698Sbellard get_user_ual(regs->ARM_r2, stack + 8); /* envp */ 2812f619698Sbellard get_user_ual(regs->ARM_r1, stack + 4); /* envp */ 282a1516e92Sbellard /* XXX: it seems that r0 is zeroed after ! */ 283e5fe0c52Spbrook regs->ARM_r0 = 0; 284e5fe0c52Spbrook /* For uClinux PIC binaries. */ 285863cf0b7Sj_mayer /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ 286e5fe0c52Spbrook regs->ARM_r10 = infop->start_data; 287b346ff46Sbellard } 288b346ff46Sbellard 289edf8e2afSMika Westerberg #define ELF_NREG 18 290c227f099SAnthony Liguori typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 291edf8e2afSMika Westerberg 292c227f099SAnthony Liguori static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 293edf8e2afSMika Westerberg { 294d049e626SNathan Froyd (*regs)[0] = tswapl(env->regs[0]); 295d049e626SNathan Froyd (*regs)[1] = tswapl(env->regs[1]); 296d049e626SNathan Froyd (*regs)[2] = tswapl(env->regs[2]); 297d049e626SNathan Froyd (*regs)[3] = tswapl(env->regs[3]); 298d049e626SNathan Froyd (*regs)[4] = tswapl(env->regs[4]); 299d049e626SNathan Froyd (*regs)[5] = tswapl(env->regs[5]); 300d049e626SNathan Froyd (*regs)[6] = tswapl(env->regs[6]); 301d049e626SNathan Froyd (*regs)[7] = tswapl(env->regs[7]); 302d049e626SNathan Froyd (*regs)[8] = tswapl(env->regs[8]); 303d049e626SNathan Froyd (*regs)[9] = tswapl(env->regs[9]); 304d049e626SNathan Froyd (*regs)[10] = tswapl(env->regs[10]); 305d049e626SNathan Froyd (*regs)[11] = tswapl(env->regs[11]); 306d049e626SNathan Froyd (*regs)[12] = tswapl(env->regs[12]); 307d049e626SNathan Froyd (*regs)[13] = tswapl(env->regs[13]); 308d049e626SNathan Froyd (*regs)[14] = tswapl(env->regs[14]); 309d049e626SNathan Froyd (*regs)[15] = tswapl(env->regs[15]); 310edf8e2afSMika Westerberg 311d049e626SNathan Froyd (*regs)[16] = tswapl(cpsr_read((CPUState *)env)); 312d049e626SNathan Froyd (*regs)[17] = tswapl(env->regs[0]); /* XXX */ 313edf8e2afSMika Westerberg } 314edf8e2afSMika Westerberg 31530ac07d4Sbellard #define USE_ELF_CORE_DUMP 31630ac07d4Sbellard #define ELF_EXEC_PAGESIZE 4096 31730ac07d4Sbellard 318afce2927Sbellard enum 319afce2927Sbellard { 320afce2927Sbellard ARM_HWCAP_ARM_SWP = 1 << 0, 321afce2927Sbellard ARM_HWCAP_ARM_HALF = 1 << 1, 322afce2927Sbellard ARM_HWCAP_ARM_THUMB = 1 << 2, 323afce2927Sbellard ARM_HWCAP_ARM_26BIT = 1 << 3, 324afce2927Sbellard ARM_HWCAP_ARM_FAST_MULT = 1 << 4, 325afce2927Sbellard ARM_HWCAP_ARM_FPA = 1 << 5, 326afce2927Sbellard ARM_HWCAP_ARM_VFP = 1 << 6, 327afce2927Sbellard ARM_HWCAP_ARM_EDSP = 1 << 7, 328cf6de34aSRiku Voipio ARM_HWCAP_ARM_JAVA = 1 << 8, 329cf6de34aSRiku Voipio ARM_HWCAP_ARM_IWMMXT = 1 << 9, 330cf6de34aSRiku Voipio ARM_HWCAP_ARM_THUMBEE = 1 << 10, 331cf6de34aSRiku Voipio ARM_HWCAP_ARM_NEON = 1 << 11, 332cf6de34aSRiku Voipio ARM_HWCAP_ARM_VFPv3 = 1 << 12, 333cf6de34aSRiku Voipio ARM_HWCAP_ARM_VFPv3D16 = 1 << 13, 334afce2927Sbellard }; 335afce2927Sbellard 33615338fd7Sbellard #define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \ 337afce2927Sbellard | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \ 338cf6de34aSRiku Voipio | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP \ 339cf6de34aSRiku Voipio | ARM_HWCAP_ARM_NEON | ARM_HWCAP_ARM_VFPv3 ) 340afce2927Sbellard 34130ac07d4Sbellard #endif 34230ac07d4Sbellard 343853d6f7aSbellard #ifdef TARGET_SPARC 344a315a145Sbellard #ifdef TARGET_SPARC64 345853d6f7aSbellard 346853d6f7aSbellard #define ELF_START_MMAP 0x80000000 347853d6f7aSbellard 348992f48a0Sblueswir1 #ifndef TARGET_ABI32 349cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) 350992f48a0Sblueswir1 #else 351992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) 352992f48a0Sblueswir1 #endif 353853d6f7aSbellard 354a315a145Sbellard #define ELF_CLASS ELFCLASS64 355a315a145Sbellard #define ELF_DATA ELFDATA2MSB 3565ef54116Sbellard #define ELF_ARCH EM_SPARCV9 3575ef54116Sbellard 3585ef54116Sbellard #define STACK_BIAS 2047 359a315a145Sbellard 360a315a145Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 361a315a145Sbellard { 362992f48a0Sblueswir1 #ifndef TARGET_ABI32 363a315a145Sbellard regs->tstate = 0; 364992f48a0Sblueswir1 #endif 365a315a145Sbellard regs->pc = infop->entry; 366a315a145Sbellard regs->npc = regs->pc + 4; 367a315a145Sbellard regs->y = 0; 368992f48a0Sblueswir1 #ifdef TARGET_ABI32 369992f48a0Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 370992f48a0Sblueswir1 #else 371cb33da57Sblueswir1 if (personality(infop->personality) == PER_LINUX32) 372cb33da57Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 373cb33da57Sblueswir1 else 3745ef54116Sbellard regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; 375992f48a0Sblueswir1 #endif 376a315a145Sbellard } 377a315a145Sbellard 378a315a145Sbellard #else 379a315a145Sbellard #define ELF_START_MMAP 0x80000000 380a315a145Sbellard 381a315a145Sbellard #define elf_check_arch(x) ( (x) == EM_SPARC ) 382a315a145Sbellard 383853d6f7aSbellard #define ELF_CLASS ELFCLASS32 384853d6f7aSbellard #define ELF_DATA ELFDATA2MSB 385853d6f7aSbellard #define ELF_ARCH EM_SPARC 386853d6f7aSbellard 387853d6f7aSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 388853d6f7aSbellard { 389f5155289Sbellard regs->psr = 0; 390f5155289Sbellard regs->pc = infop->entry; 391f5155289Sbellard regs->npc = regs->pc + 4; 392f5155289Sbellard regs->y = 0; 393f5155289Sbellard regs->u_regs[14] = infop->start_stack - 16 * 4; 394853d6f7aSbellard } 395853d6f7aSbellard 396853d6f7aSbellard #endif 397a315a145Sbellard #endif 398853d6f7aSbellard 39967867308Sbellard #ifdef TARGET_PPC 40067867308Sbellard 40167867308Sbellard #define ELF_START_MMAP 0x80000000 40267867308Sbellard 403e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 40484409ddbSj_mayer 40584409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 ) 40684409ddbSj_mayer 40784409ddbSj_mayer #define ELF_CLASS ELFCLASS64 40884409ddbSj_mayer 40984409ddbSj_mayer #else 41084409ddbSj_mayer 41167867308Sbellard #define elf_check_arch(x) ( (x) == EM_PPC ) 41267867308Sbellard 41367867308Sbellard #define ELF_CLASS ELFCLASS32 41484409ddbSj_mayer 41584409ddbSj_mayer #endif 41684409ddbSj_mayer 41767867308Sbellard #ifdef TARGET_WORDS_BIGENDIAN 41867867308Sbellard #define ELF_DATA ELFDATA2MSB 41967867308Sbellard #else 42067867308Sbellard #define ELF_DATA ELFDATA2LSB 42167867308Sbellard #endif 42267867308Sbellard #define ELF_ARCH EM_PPC 42367867308Sbellard 424df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). 425df84e4f3SNathan Froyd See arch/powerpc/include/asm/cputable.h. */ 426df84e4f3SNathan Froyd enum { 4273efa9a67Smalc QEMU_PPC_FEATURE_32 = 0x80000000, 4283efa9a67Smalc QEMU_PPC_FEATURE_64 = 0x40000000, 4293efa9a67Smalc QEMU_PPC_FEATURE_601_INSTR = 0x20000000, 4303efa9a67Smalc QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000, 4313efa9a67Smalc QEMU_PPC_FEATURE_HAS_FPU = 0x08000000, 4323efa9a67Smalc QEMU_PPC_FEATURE_HAS_MMU = 0x04000000, 4333efa9a67Smalc QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000, 4343efa9a67Smalc QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000, 4353efa9a67Smalc QEMU_PPC_FEATURE_HAS_SPE = 0x00800000, 4363efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000, 4373efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000, 4383efa9a67Smalc QEMU_PPC_FEATURE_NO_TB = 0x00100000, 4393efa9a67Smalc QEMU_PPC_FEATURE_POWER4 = 0x00080000, 4403efa9a67Smalc QEMU_PPC_FEATURE_POWER5 = 0x00040000, 4413efa9a67Smalc QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000, 4423efa9a67Smalc QEMU_PPC_FEATURE_CELL = 0x00010000, 4433efa9a67Smalc QEMU_PPC_FEATURE_BOOKE = 0x00008000, 4443efa9a67Smalc QEMU_PPC_FEATURE_SMT = 0x00004000, 4453efa9a67Smalc QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000, 4463efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000, 4473efa9a67Smalc QEMU_PPC_FEATURE_PA6T = 0x00000800, 4483efa9a67Smalc QEMU_PPC_FEATURE_HAS_DFP = 0x00000400, 4493efa9a67Smalc QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200, 4503efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100, 4513efa9a67Smalc QEMU_PPC_FEATURE_HAS_VSX = 0x00000080, 4523efa9a67Smalc QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040, 453df84e4f3SNathan Froyd 4543efa9a67Smalc QEMU_PPC_FEATURE_TRUE_LE = 0x00000002, 4553efa9a67Smalc QEMU_PPC_FEATURE_PPC_LE = 0x00000001, 456df84e4f3SNathan Froyd }; 457df84e4f3SNathan Froyd 458df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap() 459df84e4f3SNathan Froyd 460df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void) 461df84e4f3SNathan Froyd { 462df84e4f3SNathan Froyd CPUState *e = thread_env; 463df84e4f3SNathan Froyd uint32_t features = 0; 464df84e4f3SNathan Froyd 465df84e4f3SNathan Froyd /* We don't have to be terribly complete here; the high points are 466df84e4f3SNathan Froyd Altivec/FP/SPE support. Anything else is just a bonus. */ 467df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature) \ 468df84e4f3SNathan Froyd do {if (e->insns_flags & flag) features |= feature; } while(0) 4693efa9a67Smalc GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); 4703efa9a67Smalc GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); 4713efa9a67Smalc GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); 4723efa9a67Smalc GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE); 4733efa9a67Smalc GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE); 4743efa9a67Smalc GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE); 4753efa9a67Smalc GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE); 4763efa9a67Smalc GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC); 477df84e4f3SNathan Froyd #undef GET_FEATURE 478df84e4f3SNathan Froyd 479df84e4f3SNathan Froyd return features; 480df84e4f3SNathan Froyd } 481df84e4f3SNathan Froyd 482f5155289Sbellard /* 483f5155289Sbellard * We need to put in some extra aux table entries to tell glibc what 484f5155289Sbellard * the cache block size is, so it can use the dcbz instruction safely. 485f5155289Sbellard */ 486f5155289Sbellard #define AT_DCACHEBSIZE 19 487f5155289Sbellard #define AT_ICACHEBSIZE 20 488f5155289Sbellard #define AT_UCACHEBSIZE 21 489f5155289Sbellard /* A special ignored type value for PPC, for glibc compatibility. */ 490f5155289Sbellard #define AT_IGNOREPPC 22 491f5155289Sbellard /* 492f5155289Sbellard * The requirements here are: 493f5155289Sbellard * - keep the final alignment of sp (sp & 0xf) 494f5155289Sbellard * - make sure the 32-bit value at the first 16 byte aligned position of 495f5155289Sbellard * AUXV is greater than 16 for glibc compatibility. 496f5155289Sbellard * AT_IGNOREPPC is used for that. 497f5155289Sbellard * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, 498f5155289Sbellard * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. 499f5155289Sbellard */ 5000bccf03dSbellard #define DLINFO_ARCH_ITEMS 5 501f5155289Sbellard #define ARCH_DLINFO \ 502f5155289Sbellard do { \ 5030bccf03dSbellard NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \ 5040bccf03dSbellard NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \ 5050bccf03dSbellard NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ 506f5155289Sbellard /* \ 507f5155289Sbellard * Now handle glibc compatibility. \ 508f5155289Sbellard */ \ 5090bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 5100bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 511f5155289Sbellard } while (0) 512f5155289Sbellard 51367867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) 51467867308Sbellard { 51567867308Sbellard _regs->gpr[1] = infop->start_stack; 516e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 5177983f435SRob Landley _regs->gpr[2] = ldq_raw(infop->entry + 8) + infop->load_addr; 5187983f435SRob Landley infop->entry = ldq_raw(infop->entry) + infop->load_addr; 51984409ddbSj_mayer #endif 52067867308Sbellard _regs->nip = infop->entry; 52167867308Sbellard } 52267867308Sbellard 523e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h. */ 524e2f3e741SNathan Froyd #define ELF_NREG 48 525e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 526e2f3e741SNathan Froyd 527e2f3e741SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 528e2f3e741SNathan Froyd { 529e2f3e741SNathan Froyd int i; 530e2f3e741SNathan Froyd target_ulong ccr = 0; 531e2f3e741SNathan Froyd 532e2f3e741SNathan Froyd for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 533e2f3e741SNathan Froyd (*regs)[i] = tswapl(env->gpr[i]); 534e2f3e741SNathan Froyd } 535e2f3e741SNathan Froyd 536e2f3e741SNathan Froyd (*regs)[32] = tswapl(env->nip); 537e2f3e741SNathan Froyd (*regs)[33] = tswapl(env->msr); 538e2f3e741SNathan Froyd (*regs)[35] = tswapl(env->ctr); 539e2f3e741SNathan Froyd (*regs)[36] = tswapl(env->lr); 540e2f3e741SNathan Froyd (*regs)[37] = tswapl(env->xer); 541e2f3e741SNathan Froyd 542e2f3e741SNathan Froyd for (i = 0; i < ARRAY_SIZE(env->crf); i++) { 543e2f3e741SNathan Froyd ccr |= env->crf[i] << (32 - ((i + 1) * 4)); 544e2f3e741SNathan Froyd } 545e2f3e741SNathan Froyd (*regs)[38] = tswapl(ccr); 546e2f3e741SNathan Froyd } 547e2f3e741SNathan Froyd 548e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP 54967867308Sbellard #define ELF_EXEC_PAGESIZE 4096 55067867308Sbellard 55167867308Sbellard #endif 55267867308Sbellard 553048f6b4dSbellard #ifdef TARGET_MIPS 554048f6b4dSbellard 555048f6b4dSbellard #define ELF_START_MMAP 0x80000000 556048f6b4dSbellard 557048f6b4dSbellard #define elf_check_arch(x) ( (x) == EM_MIPS ) 558048f6b4dSbellard 559388bb21aSths #ifdef TARGET_MIPS64 560388bb21aSths #define ELF_CLASS ELFCLASS64 561388bb21aSths #else 562048f6b4dSbellard #define ELF_CLASS ELFCLASS32 563388bb21aSths #endif 564048f6b4dSbellard #ifdef TARGET_WORDS_BIGENDIAN 565048f6b4dSbellard #define ELF_DATA ELFDATA2MSB 566048f6b4dSbellard #else 567048f6b4dSbellard #define ELF_DATA ELFDATA2LSB 568048f6b4dSbellard #endif 569048f6b4dSbellard #define ELF_ARCH EM_MIPS 570048f6b4dSbellard 571048f6b4dSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 572048f6b4dSbellard { 573623a930eSths regs->cp0_status = 2 << CP0St_KSU; 574048f6b4dSbellard regs->cp0_epc = infop->entry; 575048f6b4dSbellard regs->regs[29] = infop->start_stack; 576048f6b4dSbellard } 577048f6b4dSbellard 57851e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h. */ 57951e52606SNathan Froyd #define ELF_NREG 45 58051e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 58151e52606SNathan Froyd 58251e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h. */ 58351e52606SNathan Froyd enum { 58451e52606SNathan Froyd #ifdef TARGET_MIPS64 58551e52606SNathan Froyd TARGET_EF_R0 = 0, 58651e52606SNathan Froyd #else 58751e52606SNathan Froyd TARGET_EF_R0 = 6, 58851e52606SNathan Froyd #endif 58951e52606SNathan Froyd TARGET_EF_R26 = TARGET_EF_R0 + 26, 59051e52606SNathan Froyd TARGET_EF_R27 = TARGET_EF_R0 + 27, 59151e52606SNathan Froyd TARGET_EF_LO = TARGET_EF_R0 + 32, 59251e52606SNathan Froyd TARGET_EF_HI = TARGET_EF_R0 + 33, 59351e52606SNathan Froyd TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34, 59451e52606SNathan Froyd TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35, 59551e52606SNathan Froyd TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36, 59651e52606SNathan Froyd TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37 59751e52606SNathan Froyd }; 59851e52606SNathan Froyd 59951e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 60051e52606SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 60151e52606SNathan Froyd { 60251e52606SNathan Froyd int i; 60351e52606SNathan Froyd 60451e52606SNathan Froyd for (i = 0; i < TARGET_EF_R0; i++) { 60551e52606SNathan Froyd (*regs)[i] = 0; 60651e52606SNathan Froyd } 60751e52606SNathan Froyd (*regs)[TARGET_EF_R0] = 0; 60851e52606SNathan Froyd 60951e52606SNathan Froyd for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { 61051e52606SNathan Froyd (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]); 61151e52606SNathan Froyd } 61251e52606SNathan Froyd 61351e52606SNathan Froyd (*regs)[TARGET_EF_R26] = 0; 61451e52606SNathan Froyd (*regs)[TARGET_EF_R27] = 0; 61551e52606SNathan Froyd (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]); 61651e52606SNathan Froyd (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]); 61751e52606SNathan Froyd (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC); 61851e52606SNathan Froyd (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr); 61951e52606SNathan Froyd (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status); 62051e52606SNathan Froyd (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause); 62151e52606SNathan Froyd } 62251e52606SNathan Froyd 62351e52606SNathan Froyd #define USE_ELF_CORE_DUMP 624388bb21aSths #define ELF_EXEC_PAGESIZE 4096 625388bb21aSths 626048f6b4dSbellard #endif /* TARGET_MIPS */ 627048f6b4dSbellard 628b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 629b779e29eSEdgar E. Iglesias 630b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000 631b779e29eSEdgar E. Iglesias 632b779e29eSEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE ) 633b779e29eSEdgar E. Iglesias 634b779e29eSEdgar E. Iglesias #define ELF_CLASS ELFCLASS32 635b779e29eSEdgar E. Iglesias #define ELF_DATA ELFDATA2MSB 6360ddbc96eSMike Frysinger #define ELF_ARCH EM_XILINX_MICROBLAZE 637b779e29eSEdgar E. Iglesias 638b779e29eSEdgar E. Iglesias static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 639b779e29eSEdgar E. Iglesias { 640b779e29eSEdgar E. Iglesias regs->pc = infop->entry; 641b779e29eSEdgar E. Iglesias regs->r1 = infop->start_stack; 642b779e29eSEdgar E. Iglesias 643b779e29eSEdgar E. Iglesias } 644b779e29eSEdgar E. Iglesias 645b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE 4096 646b779e29eSEdgar E. Iglesias 647b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */ 648b779e29eSEdgar E. Iglesias 649fdf9b3e8Sbellard #ifdef TARGET_SH4 650fdf9b3e8Sbellard 651fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000 652fdf9b3e8Sbellard 653fdf9b3e8Sbellard #define elf_check_arch(x) ( (x) == EM_SH ) 654fdf9b3e8Sbellard 655fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32 656fdf9b3e8Sbellard #define ELF_DATA ELFDATA2LSB 657fdf9b3e8Sbellard #define ELF_ARCH EM_SH 658fdf9b3e8Sbellard 659fdf9b3e8Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 660fdf9b3e8Sbellard { 661fdf9b3e8Sbellard /* Check other registers XXXXX */ 662fdf9b3e8Sbellard regs->pc = infop->entry; 663072ae847Sths regs->regs[15] = infop->start_stack; 664fdf9b3e8Sbellard } 665fdf9b3e8Sbellard 6667631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h. */ 6677631c97eSNathan Froyd #define ELF_NREG 23 6687631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 6697631c97eSNathan Froyd 6707631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h. */ 6717631c97eSNathan Froyd enum { 6727631c97eSNathan Froyd TARGET_REG_PC = 16, 6737631c97eSNathan Froyd TARGET_REG_PR = 17, 6747631c97eSNathan Froyd TARGET_REG_SR = 18, 6757631c97eSNathan Froyd TARGET_REG_GBR = 19, 6767631c97eSNathan Froyd TARGET_REG_MACH = 20, 6777631c97eSNathan Froyd TARGET_REG_MACL = 21, 6787631c97eSNathan Froyd TARGET_REG_SYSCALL = 22 6797631c97eSNathan Froyd }; 6807631c97eSNathan Froyd 6817631c97eSNathan Froyd static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 6827631c97eSNathan Froyd { 6837631c97eSNathan Froyd int i; 6847631c97eSNathan Froyd 6857631c97eSNathan Froyd for (i = 0; i < 16; i++) { 6867631c97eSNathan Froyd (*regs[i]) = tswapl(env->gregs[i]); 6877631c97eSNathan Froyd } 6887631c97eSNathan Froyd 6897631c97eSNathan Froyd (*regs)[TARGET_REG_PC] = tswapl(env->pc); 6907631c97eSNathan Froyd (*regs)[TARGET_REG_PR] = tswapl(env->pr); 6917631c97eSNathan Froyd (*regs)[TARGET_REG_SR] = tswapl(env->sr); 6927631c97eSNathan Froyd (*regs)[TARGET_REG_GBR] = tswapl(env->gbr); 6937631c97eSNathan Froyd (*regs)[TARGET_REG_MACH] = tswapl(env->mach); 6947631c97eSNathan Froyd (*regs)[TARGET_REG_MACL] = tswapl(env->macl); 6957631c97eSNathan Froyd (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */ 6967631c97eSNathan Froyd } 6977631c97eSNathan Froyd 6987631c97eSNathan Froyd #define USE_ELF_CORE_DUMP 699fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE 4096 700fdf9b3e8Sbellard 701fdf9b3e8Sbellard #endif 702fdf9b3e8Sbellard 70348733d19Sths #ifdef TARGET_CRIS 70448733d19Sths 70548733d19Sths #define ELF_START_MMAP 0x80000000 70648733d19Sths 70748733d19Sths #define elf_check_arch(x) ( (x) == EM_CRIS ) 70848733d19Sths 70948733d19Sths #define ELF_CLASS ELFCLASS32 71048733d19Sths #define ELF_DATA ELFDATA2LSB 71148733d19Sths #define ELF_ARCH EM_CRIS 71248733d19Sths 71348733d19Sths static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 71448733d19Sths { 71548733d19Sths regs->erp = infop->entry; 71648733d19Sths } 71748733d19Sths 71848733d19Sths #define ELF_EXEC_PAGESIZE 8192 71948733d19Sths 72048733d19Sths #endif 72148733d19Sths 722e6e5906bSpbrook #ifdef TARGET_M68K 723e6e5906bSpbrook 724e6e5906bSpbrook #define ELF_START_MMAP 0x80000000 725e6e5906bSpbrook 726e6e5906bSpbrook #define elf_check_arch(x) ( (x) == EM_68K ) 727e6e5906bSpbrook 728e6e5906bSpbrook #define ELF_CLASS ELFCLASS32 729e6e5906bSpbrook #define ELF_DATA ELFDATA2MSB 730e6e5906bSpbrook #define ELF_ARCH EM_68K 731e6e5906bSpbrook 732e6e5906bSpbrook /* ??? Does this need to do anything? 733e6e5906bSpbrook #define ELF_PLAT_INIT(_r) */ 734e6e5906bSpbrook 735e6e5906bSpbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 736e6e5906bSpbrook { 737e6e5906bSpbrook regs->usp = infop->start_stack; 738e6e5906bSpbrook regs->sr = 0; 739e6e5906bSpbrook regs->pc = infop->entry; 740e6e5906bSpbrook } 741e6e5906bSpbrook 7427a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h. */ 7437a93cc55SNathan Froyd #define ELF_NREG 20 7447a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 7457a93cc55SNathan Froyd 7467a93cc55SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 7477a93cc55SNathan Froyd { 7487a93cc55SNathan Froyd (*regs)[0] = tswapl(env->dregs[1]); 7497a93cc55SNathan Froyd (*regs)[1] = tswapl(env->dregs[2]); 7507a93cc55SNathan Froyd (*regs)[2] = tswapl(env->dregs[3]); 7517a93cc55SNathan Froyd (*regs)[3] = tswapl(env->dregs[4]); 7527a93cc55SNathan Froyd (*regs)[4] = tswapl(env->dregs[5]); 7537a93cc55SNathan Froyd (*regs)[5] = tswapl(env->dregs[6]); 7547a93cc55SNathan Froyd (*regs)[6] = tswapl(env->dregs[7]); 7557a93cc55SNathan Froyd (*regs)[7] = tswapl(env->aregs[0]); 7567a93cc55SNathan Froyd (*regs)[8] = tswapl(env->aregs[1]); 7577a93cc55SNathan Froyd (*regs)[9] = tswapl(env->aregs[2]); 7587a93cc55SNathan Froyd (*regs)[10] = tswapl(env->aregs[3]); 7597a93cc55SNathan Froyd (*regs)[11] = tswapl(env->aregs[4]); 7607a93cc55SNathan Froyd (*regs)[12] = tswapl(env->aregs[5]); 7617a93cc55SNathan Froyd (*regs)[13] = tswapl(env->aregs[6]); 7627a93cc55SNathan Froyd (*regs)[14] = tswapl(env->dregs[0]); 7637a93cc55SNathan Froyd (*regs)[15] = tswapl(env->aregs[7]); 7647a93cc55SNathan Froyd (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */ 7657a93cc55SNathan Froyd (*regs)[17] = tswapl(env->sr); 7667a93cc55SNathan Froyd (*regs)[18] = tswapl(env->pc); 7677a93cc55SNathan Froyd (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */ 7687a93cc55SNathan Froyd } 7697a93cc55SNathan Froyd 7707a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP 771e6e5906bSpbrook #define ELF_EXEC_PAGESIZE 8192 772e6e5906bSpbrook 773e6e5906bSpbrook #endif 774e6e5906bSpbrook 7757a3148a9Sj_mayer #ifdef TARGET_ALPHA 7767a3148a9Sj_mayer 7777a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL) 7787a3148a9Sj_mayer 7797a3148a9Sj_mayer #define elf_check_arch(x) ( (x) == ELF_ARCH ) 7807a3148a9Sj_mayer 7817a3148a9Sj_mayer #define ELF_CLASS ELFCLASS64 7827a3148a9Sj_mayer #define ELF_DATA ELFDATA2MSB 7837a3148a9Sj_mayer #define ELF_ARCH EM_ALPHA 7847a3148a9Sj_mayer 7857a3148a9Sj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 7867a3148a9Sj_mayer { 7877a3148a9Sj_mayer regs->pc = infop->entry; 7887a3148a9Sj_mayer regs->ps = 8; 7897a3148a9Sj_mayer regs->usp = infop->start_stack; 7907a3148a9Sj_mayer } 7917a3148a9Sj_mayer 7927a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE 8192 7937a3148a9Sj_mayer 7947a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 7957a3148a9Sj_mayer 79615338fd7Sbellard #ifndef ELF_PLATFORM 79715338fd7Sbellard #define ELF_PLATFORM (NULL) 79815338fd7Sbellard #endif 79915338fd7Sbellard 80015338fd7Sbellard #ifndef ELF_HWCAP 80115338fd7Sbellard #define ELF_HWCAP 0 80215338fd7Sbellard #endif 80315338fd7Sbellard 804992f48a0Sblueswir1 #ifdef TARGET_ABI32 805cb33da57Sblueswir1 #undef ELF_CLASS 806992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32 807cb33da57Sblueswir1 #undef bswaptls 808cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr) 809cb33da57Sblueswir1 #endif 810cb33da57Sblueswir1 81131e31b8aSbellard #include "elf.h" 81209bfb054Sbellard 81309bfb054Sbellard struct exec 81409bfb054Sbellard { 81509bfb054Sbellard unsigned int a_info; /* Use macros N_MAGIC, etc for access */ 81609bfb054Sbellard unsigned int a_text; /* length of text, in bytes */ 81709bfb054Sbellard unsigned int a_data; /* length of data, in bytes */ 81809bfb054Sbellard unsigned int a_bss; /* length of uninitialized data area, in bytes */ 81909bfb054Sbellard unsigned int a_syms; /* length of symbol table data in file, in bytes */ 82009bfb054Sbellard unsigned int a_entry; /* start address */ 82109bfb054Sbellard unsigned int a_trsize; /* length of relocation info for text, in bytes */ 82209bfb054Sbellard unsigned int a_drsize; /* length of relocation info for data, in bytes */ 82309bfb054Sbellard }; 82409bfb054Sbellard 82509bfb054Sbellard 82609bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff) 82709bfb054Sbellard #define OMAGIC 0407 82809bfb054Sbellard #define NMAGIC 0410 82909bfb054Sbellard #define ZMAGIC 0413 83009bfb054Sbellard #define QMAGIC 0314 83109bfb054Sbellard 83209bfb054Sbellard /* max code+data+bss space allocated to elf interpreter */ 83309bfb054Sbellard #define INTERP_MAP_SIZE (32 * 1024 * 1024) 83409bfb054Sbellard 83509bfb054Sbellard /* max code+data+bss+brk space allocated to ET_DYN executables */ 83609bfb054Sbellard #define ET_DYN_MAP_SIZE (128 * 1024 * 1024) 83709bfb054Sbellard 83831e31b8aSbellard /* Necessary parameters */ 83954936004Sbellard #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE 84054936004Sbellard #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) 84154936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) 84231e31b8aSbellard 84331e31b8aSbellard #define INTERPRETER_NONE 0 84431e31b8aSbellard #define INTERPRETER_AOUT 1 84531e31b8aSbellard #define INTERPRETER_ELF 2 84631e31b8aSbellard 84715338fd7Sbellard #define DLINFO_ITEMS 12 84831e31b8aSbellard 84909bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) 85009bfb054Sbellard { 85109bfb054Sbellard memcpy(to, from, n); 85209bfb054Sbellard } 85309bfb054Sbellard 85431e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd); 85531e31b8aSbellard 85631e31b8aSbellard #ifdef BSWAP_NEEDED 85792a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr) 85831e31b8aSbellard { 85931e31b8aSbellard bswap16s(&ehdr->e_type); /* Object file type */ 86031e31b8aSbellard bswap16s(&ehdr->e_machine); /* Architecture */ 86131e31b8aSbellard bswap32s(&ehdr->e_version); /* Object file version */ 86292a31b1fSbellard bswaptls(&ehdr->e_entry); /* Entry point virtual address */ 86392a31b1fSbellard bswaptls(&ehdr->e_phoff); /* Program header table file offset */ 86492a31b1fSbellard bswaptls(&ehdr->e_shoff); /* Section header table file offset */ 86531e31b8aSbellard bswap32s(&ehdr->e_flags); /* Processor-specific flags */ 86631e31b8aSbellard bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ 86731e31b8aSbellard bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ 86831e31b8aSbellard bswap16s(&ehdr->e_phnum); /* Program header table entry count */ 86931e31b8aSbellard bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ 87031e31b8aSbellard bswap16s(&ehdr->e_shnum); /* Section header table entry count */ 87131e31b8aSbellard bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ 87231e31b8aSbellard } 87331e31b8aSbellard 87492a31b1fSbellard static void bswap_phdr(struct elf_phdr *phdr) 87531e31b8aSbellard { 87631e31b8aSbellard bswap32s(&phdr->p_type); /* Segment type */ 87792a31b1fSbellard bswaptls(&phdr->p_offset); /* Segment file offset */ 87892a31b1fSbellard bswaptls(&phdr->p_vaddr); /* Segment virtual address */ 87992a31b1fSbellard bswaptls(&phdr->p_paddr); /* Segment physical address */ 88092a31b1fSbellard bswaptls(&phdr->p_filesz); /* Segment size in file */ 88192a31b1fSbellard bswaptls(&phdr->p_memsz); /* Segment size in memory */ 88231e31b8aSbellard bswap32s(&phdr->p_flags); /* Segment flags */ 88392a31b1fSbellard bswaptls(&phdr->p_align); /* Segment alignment */ 88431e31b8aSbellard } 885689f936fSbellard 88692a31b1fSbellard static void bswap_shdr(struct elf_shdr *shdr) 887689f936fSbellard { 888689f936fSbellard bswap32s(&shdr->sh_name); 889689f936fSbellard bswap32s(&shdr->sh_type); 89092a31b1fSbellard bswaptls(&shdr->sh_flags); 89192a31b1fSbellard bswaptls(&shdr->sh_addr); 89292a31b1fSbellard bswaptls(&shdr->sh_offset); 89392a31b1fSbellard bswaptls(&shdr->sh_size); 894689f936fSbellard bswap32s(&shdr->sh_link); 895689f936fSbellard bswap32s(&shdr->sh_info); 89692a31b1fSbellard bswaptls(&shdr->sh_addralign); 89792a31b1fSbellard bswaptls(&shdr->sh_entsize); 898689f936fSbellard } 899689f936fSbellard 9007a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym) 901689f936fSbellard { 902689f936fSbellard bswap32s(&sym->st_name); 9037a3148a9Sj_mayer bswaptls(&sym->st_value); 9047a3148a9Sj_mayer bswaptls(&sym->st_size); 905689f936fSbellard bswap16s(&sym->st_shndx); 906689f936fSbellard } 90731e31b8aSbellard #endif 90831e31b8aSbellard 909edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 910edf8e2afSMika Westerberg static int elf_core_dump(int, const CPUState *); 911edf8e2afSMika Westerberg 912edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 913edf8e2afSMika Westerberg static void bswap_note(struct elf_note *en) 914edf8e2afSMika Westerberg { 9159fdca5aaSmalc bswap32s(&en->n_namesz); 9169fdca5aaSmalc bswap32s(&en->n_descsz); 9179fdca5aaSmalc bswap32s(&en->n_type); 918edf8e2afSMika Westerberg } 919edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 920edf8e2afSMika Westerberg 921edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 922edf8e2afSMika Westerberg 92331e31b8aSbellard /* 924e5fe0c52Spbrook * 'copy_elf_strings()' copies argument/envelope strings from user 92531e31b8aSbellard * memory to free pages in kernel mem. These are in a format ready 92631e31b8aSbellard * to be put directly into the top of new user memory. 92731e31b8aSbellard * 92831e31b8aSbellard */ 929992f48a0Sblueswir1 static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, 930992f48a0Sblueswir1 abi_ulong p) 93131e31b8aSbellard { 93231e31b8aSbellard char *tmp, *tmp1, *pag = NULL; 93331e31b8aSbellard int len, offset = 0; 93431e31b8aSbellard 93531e31b8aSbellard if (!p) { 93631e31b8aSbellard return 0; /* bullet-proofing */ 93731e31b8aSbellard } 93831e31b8aSbellard while (argc-- > 0) { 939edf779ffSbellard tmp = argv[argc]; 940edf779ffSbellard if (!tmp) { 94131e31b8aSbellard fprintf(stderr, "VFS: argc is wrong"); 94231e31b8aSbellard exit(-1); 94331e31b8aSbellard } 944edf779ffSbellard tmp1 = tmp; 945edf779ffSbellard while (*tmp++); 94631e31b8aSbellard len = tmp - tmp1; 94731e31b8aSbellard if (p < len) { /* this shouldn't happen - 128kB */ 94831e31b8aSbellard return 0; 94931e31b8aSbellard } 95031e31b8aSbellard while (len) { 95131e31b8aSbellard --p; --tmp; --len; 95231e31b8aSbellard if (--offset < 0) { 95354936004Sbellard offset = p % TARGET_PAGE_SIZE; 95444a91caeSbellard pag = (char *)page[p/TARGET_PAGE_SIZE]; 95544a91caeSbellard if (!pag) { 95653a5960aSpbrook pag = (char *)malloc(TARGET_PAGE_SIZE); 9574118a970Sj_mayer memset(pag, 0, TARGET_PAGE_SIZE); 95853a5960aSpbrook page[p/TARGET_PAGE_SIZE] = pag; 95944a91caeSbellard if (!pag) 96031e31b8aSbellard return 0; 96131e31b8aSbellard } 96231e31b8aSbellard } 96331e31b8aSbellard if (len == 0 || offset == 0) { 964edf779ffSbellard *(pag + offset) = *tmp; 96531e31b8aSbellard } 96631e31b8aSbellard else { 96731e31b8aSbellard int bytes_to_copy = (len > offset) ? offset : len; 96831e31b8aSbellard tmp -= bytes_to_copy; 96931e31b8aSbellard p -= bytes_to_copy; 97031e31b8aSbellard offset -= bytes_to_copy; 97131e31b8aSbellard len -= bytes_to_copy; 97231e31b8aSbellard memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); 97331e31b8aSbellard } 97431e31b8aSbellard } 97531e31b8aSbellard } 97631e31b8aSbellard return p; 97731e31b8aSbellard } 97831e31b8aSbellard 979992f48a0Sblueswir1 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, 98031e31b8aSbellard struct image_info *info) 98131e31b8aSbellard { 982992f48a0Sblueswir1 abi_ulong stack_base, size, error; 98331e31b8aSbellard int i; 98431e31b8aSbellard 98531e31b8aSbellard /* Create enough stack to hold everything. If we don't use 98631e31b8aSbellard * it for args, we'll use it for something else... 98731e31b8aSbellard */ 988703e0e89SRichard Henderson size = guest_stack_size; 98954936004Sbellard if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) 99054936004Sbellard size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; 99154936004Sbellard error = target_mmap(0, 99283fb7adfSbellard size + qemu_host_page_size, 99331e31b8aSbellard PROT_READ | PROT_WRITE, 99409bfb054Sbellard MAP_PRIVATE | MAP_ANONYMOUS, 99509bfb054Sbellard -1, 0); 99609bfb054Sbellard if (error == -1) { 99731e31b8aSbellard perror("stk mmap"); 99831e31b8aSbellard exit(-1); 99931e31b8aSbellard } 100009bfb054Sbellard /* we reserve one extra page at the top of the stack as guard */ 100183fb7adfSbellard target_mprotect(error + size, qemu_host_page_size, PROT_NONE); 100231e31b8aSbellard 100354936004Sbellard stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; 100409bfb054Sbellard p += stack_base; 100509bfb054Sbellard 100631e31b8aSbellard for (i = 0 ; i < MAX_ARG_PAGES ; i++) { 100731e31b8aSbellard if (bprm->page[i]) { 100831e31b8aSbellard info->rss++; 1009579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 101053a5960aSpbrook memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); 101153a5960aSpbrook free(bprm->page[i]); 101231e31b8aSbellard } 101354936004Sbellard stack_base += TARGET_PAGE_SIZE; 101431e31b8aSbellard } 101531e31b8aSbellard return p; 101631e31b8aSbellard } 101731e31b8aSbellard 1018992f48a0Sblueswir1 static void set_brk(abi_ulong start, abi_ulong end) 101931e31b8aSbellard { 102031e31b8aSbellard /* page-align the start and end addresses... */ 102154936004Sbellard start = HOST_PAGE_ALIGN(start); 102254936004Sbellard end = HOST_PAGE_ALIGN(end); 102331e31b8aSbellard if (end <= start) 102431e31b8aSbellard return; 102554936004Sbellard if(target_mmap(start, end - start, 102631e31b8aSbellard PROT_READ | PROT_WRITE | PROT_EXEC, 102731e31b8aSbellard MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) { 102831e31b8aSbellard perror("cannot mmap brk"); 102931e31b8aSbellard exit(-1); 103031e31b8aSbellard } 103131e31b8aSbellard } 103231e31b8aSbellard 103331e31b8aSbellard 1034853d6f7aSbellard /* We need to explicitly zero any fractional pages after the data 1035853d6f7aSbellard section (i.e. bss). This would contain the junk from the file that 1036853d6f7aSbellard should not be in memory. */ 1037992f48a0Sblueswir1 static void padzero(abi_ulong elf_bss, abi_ulong last_bss) 103831e31b8aSbellard { 1039992f48a0Sblueswir1 abi_ulong nbyte; 104031e31b8aSbellard 1041768a4a36Sths if (elf_bss >= last_bss) 1042768a4a36Sths return; 1043768a4a36Sths 1044853d6f7aSbellard /* XXX: this is really a hack : if the real host page size is 1045853d6f7aSbellard smaller than the target page size, some pages after the end 1046853d6f7aSbellard of the file may not be mapped. A better fix would be to 1047853d6f7aSbellard patch target_mmap(), but it is more complicated as the file 1048853d6f7aSbellard size must be known */ 104983fb7adfSbellard if (qemu_real_host_page_size < qemu_host_page_size) { 1050992f48a0Sblueswir1 abi_ulong end_addr, end_addr1; 105183fb7adfSbellard end_addr1 = (elf_bss + qemu_real_host_page_size - 1) & 105283fb7adfSbellard ~(qemu_real_host_page_size - 1); 1053853d6f7aSbellard end_addr = HOST_PAGE_ALIGN(elf_bss); 1054853d6f7aSbellard if (end_addr1 < end_addr) { 1055863cf0b7Sj_mayer mmap((void *)g2h(end_addr1), end_addr - end_addr1, 1056853d6f7aSbellard PROT_READ|PROT_WRITE|PROT_EXEC, 1057853d6f7aSbellard MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 1058853d6f7aSbellard } 1059853d6f7aSbellard } 1060853d6f7aSbellard 106183fb7adfSbellard nbyte = elf_bss & (qemu_host_page_size-1); 106231e31b8aSbellard if (nbyte) { 106383fb7adfSbellard nbyte = qemu_host_page_size - nbyte; 106431e31b8aSbellard do { 10652f619698Sbellard /* FIXME - what to do if put_user() fails? */ 10662f619698Sbellard put_user_u8(0, elf_bss); 106753a5960aSpbrook elf_bss++; 106831e31b8aSbellard } while (--nbyte); 106931e31b8aSbellard } 107031e31b8aSbellard } 107131e31b8aSbellard 107253a5960aSpbrook 1073992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, 107431e31b8aSbellard struct elfhdr * exec, 1075992f48a0Sblueswir1 abi_ulong load_addr, 1076992f48a0Sblueswir1 abi_ulong load_bias, 1077992f48a0Sblueswir1 abi_ulong interp_load_addr, int ibcs, 107831e31b8aSbellard struct image_info *info) 107931e31b8aSbellard { 1080992f48a0Sblueswir1 abi_ulong sp; 108153a5960aSpbrook int size; 1082992f48a0Sblueswir1 abi_ulong u_platform; 108315338fd7Sbellard const char *k_platform; 1084863cf0b7Sj_mayer const int n = sizeof(elf_addr_t); 108531e31b8aSbellard 108653a5960aSpbrook sp = p; 108753a5960aSpbrook u_platform = 0; 108815338fd7Sbellard k_platform = ELF_PLATFORM; 108915338fd7Sbellard if (k_platform) { 109015338fd7Sbellard size_t len = strlen(k_platform) + 1; 109153a5960aSpbrook sp -= (len + n - 1) & ~(n - 1); 109253a5960aSpbrook u_platform = sp; 1093579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 109453a5960aSpbrook memcpy_to_target(sp, k_platform, len); 109515338fd7Sbellard } 109653a5960aSpbrook /* 109753a5960aSpbrook * Force 16 byte _final_ alignment here for generality. 109853a5960aSpbrook */ 1099992f48a0Sblueswir1 sp = sp &~ (abi_ulong)15; 110053a5960aSpbrook size = (DLINFO_ITEMS + 1) * 2; 110115338fd7Sbellard if (k_platform) 110253a5960aSpbrook size += 2; 1103f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS 110453a5960aSpbrook size += DLINFO_ARCH_ITEMS * 2; 1105f5155289Sbellard #endif 110653a5960aSpbrook size += envc + argc + 2; 110753a5960aSpbrook size += (!ibcs ? 3 : 1); /* argc itself */ 110853a5960aSpbrook size *= n; 110953a5960aSpbrook if (size & 15) 111053a5960aSpbrook sp -= 16 - (size & 15); 1111f5155289Sbellard 1112863cf0b7Sj_mayer /* This is correct because Linux defines 1113863cf0b7Sj_mayer * elf_addr_t as Elf32_Off / Elf64_Off 1114863cf0b7Sj_mayer */ 111553a5960aSpbrook #define NEW_AUX_ENT(id, val) do { \ 11162f619698Sbellard sp -= n; put_user_ual(val, sp); \ 11172f619698Sbellard sp -= n; put_user_ual(id, sp); \ 111853a5960aSpbrook } while(0) 11192f619698Sbellard 11200bccf03dSbellard NEW_AUX_ENT (AT_NULL, 0); 1121f5155289Sbellard 11220bccf03dSbellard /* There must be exactly DLINFO_ITEMS entries here. */ 1123992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff)); 1124992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); 1125992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); 1126992f48a0Sblueswir1 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE)); 1127992f48a0Sblueswir1 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr)); 1128992f48a0Sblueswir1 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); 11290bccf03dSbellard NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry); 1130992f48a0Sblueswir1 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); 1131992f48a0Sblueswir1 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); 1132992f48a0Sblueswir1 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); 1133992f48a0Sblueswir1 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); 1134992f48a0Sblueswir1 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); 1135a07c67dfSpbrook NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); 113615338fd7Sbellard if (k_platform) 113753a5960aSpbrook NEW_AUX_ENT(AT_PLATFORM, u_platform); 1138f5155289Sbellard #ifdef ARCH_DLINFO 1139f5155289Sbellard /* 1140f5155289Sbellard * ARCH_DLINFO must come last so platform specific code can enforce 1141f5155289Sbellard * special alignment requirements on the AUXV if necessary (eg. PPC). 1142f5155289Sbellard */ 1143f5155289Sbellard ARCH_DLINFO; 1144f5155289Sbellard #endif 1145f5155289Sbellard #undef NEW_AUX_ENT 1146f5155289Sbellard 1147edf8e2afSMika Westerberg info->saved_auxv = sp; 1148edf8e2afSMika Westerberg 1149e5fe0c52Spbrook sp = loader_build_argptr(envc, argc, sp, p, !ibcs); 115031e31b8aSbellard return sp; 115131e31b8aSbellard } 115231e31b8aSbellard 115331e31b8aSbellard 1154992f48a0Sblueswir1 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, 115531e31b8aSbellard int interpreter_fd, 1156992f48a0Sblueswir1 abi_ulong *interp_load_addr) 115731e31b8aSbellard { 115831e31b8aSbellard struct elf_phdr *elf_phdata = NULL; 115931e31b8aSbellard struct elf_phdr *eppnt; 1160992f48a0Sblueswir1 abi_ulong load_addr = 0; 116131e31b8aSbellard int load_addr_set = 0; 116231e31b8aSbellard int retval; 1163992f48a0Sblueswir1 abi_ulong last_bss, elf_bss; 1164992f48a0Sblueswir1 abi_ulong error; 116531e31b8aSbellard int i; 116631e31b8aSbellard 116731e31b8aSbellard elf_bss = 0; 116831e31b8aSbellard last_bss = 0; 116931e31b8aSbellard error = 0; 117031e31b8aSbellard 1171644c433cSbellard #ifdef BSWAP_NEEDED 1172644c433cSbellard bswap_ehdr(interp_elf_ex); 1173644c433cSbellard #endif 117431e31b8aSbellard /* First of all, some simple consistency checks */ 117531e31b8aSbellard if ((interp_elf_ex->e_type != ET_EXEC && 117631e31b8aSbellard interp_elf_ex->e_type != ET_DYN) || 117731e31b8aSbellard !elf_check_arch(interp_elf_ex->e_machine)) { 1178992f48a0Sblueswir1 return ~((abi_ulong)0UL); 117931e31b8aSbellard } 118031e31b8aSbellard 1181644c433cSbellard 118231e31b8aSbellard /* Now read in all of the header information */ 118331e31b8aSbellard 118454936004Sbellard if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE) 1185992f48a0Sblueswir1 return ~(abi_ulong)0UL; 118631e31b8aSbellard 118731e31b8aSbellard elf_phdata = (struct elf_phdr *) 118831e31b8aSbellard malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 118931e31b8aSbellard 119031e31b8aSbellard if (!elf_phdata) 1191992f48a0Sblueswir1 return ~((abi_ulong)0UL); 119231e31b8aSbellard 119331e31b8aSbellard /* 119431e31b8aSbellard * If the size of this structure has changed, then punt, since 119531e31b8aSbellard * we will be doing the wrong thing. 119631e31b8aSbellard */ 119709bfb054Sbellard if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { 119831e31b8aSbellard free(elf_phdata); 1199992f48a0Sblueswir1 return ~((abi_ulong)0UL); 120031e31b8aSbellard } 120131e31b8aSbellard 120231e31b8aSbellard retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET); 120331e31b8aSbellard if(retval >= 0) { 120431e31b8aSbellard retval = read(interpreter_fd, 120531e31b8aSbellard (char *) elf_phdata, 120631e31b8aSbellard sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 120731e31b8aSbellard } 120831e31b8aSbellard if (retval < 0) { 120931e31b8aSbellard perror("load_elf_interp"); 121031e31b8aSbellard exit(-1); 121131e31b8aSbellard free (elf_phdata); 121231e31b8aSbellard return retval; 121331e31b8aSbellard } 121431e31b8aSbellard #ifdef BSWAP_NEEDED 121531e31b8aSbellard eppnt = elf_phdata; 121631e31b8aSbellard for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { 121731e31b8aSbellard bswap_phdr(eppnt); 121831e31b8aSbellard } 121931e31b8aSbellard #endif 122009bfb054Sbellard 122109bfb054Sbellard if (interp_elf_ex->e_type == ET_DYN) { 1222e91c8a77Sths /* in order to avoid hardcoding the interpreter load 122309bfb054Sbellard address in qemu, we allocate a big enough memory zone */ 122454936004Sbellard error = target_mmap(0, INTERP_MAP_SIZE, 122509bfb054Sbellard PROT_NONE, MAP_PRIVATE | MAP_ANON, 122609bfb054Sbellard -1, 0); 122709bfb054Sbellard if (error == -1) { 122809bfb054Sbellard perror("mmap"); 122909bfb054Sbellard exit(-1); 123009bfb054Sbellard } 123109bfb054Sbellard load_addr = error; 123209bfb054Sbellard load_addr_set = 1; 123309bfb054Sbellard } 123409bfb054Sbellard 123531e31b8aSbellard eppnt = elf_phdata; 123631e31b8aSbellard for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) 123731e31b8aSbellard if (eppnt->p_type == PT_LOAD) { 123831e31b8aSbellard int elf_type = MAP_PRIVATE | MAP_DENYWRITE; 123931e31b8aSbellard int elf_prot = 0; 1240992f48a0Sblueswir1 abi_ulong vaddr = 0; 1241992f48a0Sblueswir1 abi_ulong k; 124231e31b8aSbellard 124331e31b8aSbellard if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; 124431e31b8aSbellard if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 124531e31b8aSbellard if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 124631e31b8aSbellard if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) { 124731e31b8aSbellard elf_type |= MAP_FIXED; 124831e31b8aSbellard vaddr = eppnt->p_vaddr; 124931e31b8aSbellard } 125054936004Sbellard error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr), 125154936004Sbellard eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr), 125231e31b8aSbellard elf_prot, 125331e31b8aSbellard elf_type, 125431e31b8aSbellard interpreter_fd, 125554936004Sbellard eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr)); 125631e31b8aSbellard 1257e89f07d3Spbrook if (error == -1) { 125831e31b8aSbellard /* Real error */ 125931e31b8aSbellard close(interpreter_fd); 126031e31b8aSbellard free(elf_phdata); 1261992f48a0Sblueswir1 return ~((abi_ulong)0UL); 126231e31b8aSbellard } 126331e31b8aSbellard 126431e31b8aSbellard if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { 126531e31b8aSbellard load_addr = error; 126631e31b8aSbellard load_addr_set = 1; 126731e31b8aSbellard } 126831e31b8aSbellard 126931e31b8aSbellard /* 127031e31b8aSbellard * Find the end of the file mapping for this phdr, and keep 127131e31b8aSbellard * track of the largest address we see for this. 127231e31b8aSbellard */ 127331e31b8aSbellard k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; 127431e31b8aSbellard if (k > elf_bss) elf_bss = k; 127531e31b8aSbellard 127631e31b8aSbellard /* 127731e31b8aSbellard * Do the same thing for the memory mapping - between 127831e31b8aSbellard * elf_bss and last_bss is the bss section. 127931e31b8aSbellard */ 128031e31b8aSbellard k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; 128131e31b8aSbellard if (k > last_bss) last_bss = k; 128231e31b8aSbellard } 128331e31b8aSbellard 128431e31b8aSbellard /* Now use mmap to map the library into memory. */ 128531e31b8aSbellard 128631e31b8aSbellard close(interpreter_fd); 128731e31b8aSbellard 128831e31b8aSbellard /* 128931e31b8aSbellard * Now fill out the bss section. First pad the last page up 129031e31b8aSbellard * to the page boundary, and then perform a mmap to make sure 129131e31b8aSbellard * that there are zeromapped pages up to and including the last 129231e31b8aSbellard * bss page. 129331e31b8aSbellard */ 1294768a4a36Sths padzero(elf_bss, last_bss); 129583fb7adfSbellard elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */ 129631e31b8aSbellard 129731e31b8aSbellard /* Map the last of the bss segment */ 129831e31b8aSbellard if (last_bss > elf_bss) { 129954936004Sbellard target_mmap(elf_bss, last_bss-elf_bss, 130031e31b8aSbellard PROT_READ|PROT_WRITE|PROT_EXEC, 130131e31b8aSbellard MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 130231e31b8aSbellard } 130331e31b8aSbellard free(elf_phdata); 130431e31b8aSbellard 130531e31b8aSbellard *interp_load_addr = load_addr; 1306992f48a0Sblueswir1 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr; 130731e31b8aSbellard } 130831e31b8aSbellard 130949918a75Spbrook static int symfind(const void *s0, const void *s1) 131049918a75Spbrook { 131149918a75Spbrook struct elf_sym *key = (struct elf_sym *)s0; 131249918a75Spbrook struct elf_sym *sym = (struct elf_sym *)s1; 131349918a75Spbrook int result = 0; 131449918a75Spbrook if (key->st_value < sym->st_value) { 131549918a75Spbrook result = -1; 1316ec822001SLaurent Desnogues } else if (key->st_value >= sym->st_value + sym->st_size) { 131749918a75Spbrook result = 1; 131849918a75Spbrook } 131949918a75Spbrook return result; 132049918a75Spbrook } 132149918a75Spbrook 132249918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr) 132349918a75Spbrook { 132449918a75Spbrook #if ELF_CLASS == ELFCLASS32 132549918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf32; 132649918a75Spbrook #else 132749918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf64; 132849918a75Spbrook #endif 132949918a75Spbrook 133049918a75Spbrook // binary search 133149918a75Spbrook struct elf_sym key; 133249918a75Spbrook struct elf_sym *sym; 133349918a75Spbrook 133449918a75Spbrook key.st_value = orig_addr; 133549918a75Spbrook 133649918a75Spbrook sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind); 13377cba04f6SBlue Swirl if (sym != NULL) { 133849918a75Spbrook return s->disas_strtab + sym->st_name; 133949918a75Spbrook } 134049918a75Spbrook 134149918a75Spbrook return ""; 134249918a75Spbrook } 134349918a75Spbrook 134449918a75Spbrook /* FIXME: This should use elf_ops.h */ 134549918a75Spbrook static int symcmp(const void *s0, const void *s1) 134649918a75Spbrook { 134749918a75Spbrook struct elf_sym *sym0 = (struct elf_sym *)s0; 134849918a75Spbrook struct elf_sym *sym1 = (struct elf_sym *)s1; 134949918a75Spbrook return (sym0->st_value < sym1->st_value) 135049918a75Spbrook ? -1 135149918a75Spbrook : ((sym0->st_value > sym1->st_value) ? 1 : 0); 135249918a75Spbrook } 135349918a75Spbrook 1354689f936fSbellard /* Best attempt to load symbols from this ELF object. */ 1355689f936fSbellard static void load_symbols(struct elfhdr *hdr, int fd) 1356689f936fSbellard { 135749918a75Spbrook unsigned int i, nsyms; 1358689f936fSbellard struct elf_shdr sechdr, symtab, strtab; 1359689f936fSbellard char *strings; 1360e80cfcfcSbellard struct syminfo *s; 136149918a75Spbrook struct elf_sym *syms; 136231e31b8aSbellard 1363689f936fSbellard lseek(fd, hdr->e_shoff, SEEK_SET); 1364689f936fSbellard for (i = 0; i < hdr->e_shnum; i++) { 1365689f936fSbellard if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) 1366689f936fSbellard return; 1367689f936fSbellard #ifdef BSWAP_NEEDED 1368689f936fSbellard bswap_shdr(&sechdr); 1369689f936fSbellard #endif 1370689f936fSbellard if (sechdr.sh_type == SHT_SYMTAB) { 1371689f936fSbellard symtab = sechdr; 1372689f936fSbellard lseek(fd, hdr->e_shoff 1373689f936fSbellard + sizeof(sechdr) * sechdr.sh_link, SEEK_SET); 1374689f936fSbellard if (read(fd, &strtab, sizeof(strtab)) 1375689f936fSbellard != sizeof(strtab)) 1376689f936fSbellard return; 1377689f936fSbellard #ifdef BSWAP_NEEDED 1378689f936fSbellard bswap_shdr(&strtab); 1379689f936fSbellard #endif 1380689f936fSbellard goto found; 1381689f936fSbellard } 1382689f936fSbellard } 1383689f936fSbellard return; /* Shouldn't happen... */ 1384689f936fSbellard 1385689f936fSbellard found: 1386689f936fSbellard /* Now know where the strtab and symtab are. Snarf them. */ 1387e80cfcfcSbellard s = malloc(sizeof(*s)); 138849918a75Spbrook syms = malloc(symtab.sh_size); 138949918a75Spbrook if (!syms) 139049918a75Spbrook return; 1391e80cfcfcSbellard s->disas_strtab = strings = malloc(strtab.sh_size); 139249918a75Spbrook if (!s->disas_strtab) 1393689f936fSbellard return; 1394689f936fSbellard 1395689f936fSbellard lseek(fd, symtab.sh_offset, SEEK_SET); 139649918a75Spbrook if (read(fd, syms, symtab.sh_size) != symtab.sh_size) 1397689f936fSbellard return; 1398689f936fSbellard 139949918a75Spbrook nsyms = symtab.sh_size / sizeof(struct elf_sym); 1400689f936fSbellard 140149918a75Spbrook i = 0; 140249918a75Spbrook while (i < nsyms) { 140349918a75Spbrook #ifdef BSWAP_NEEDED 140449918a75Spbrook bswap_sym(syms + i); 14050774bed1Sblueswir1 #endif 140649918a75Spbrook // Throw away entries which we do not need. 140749918a75Spbrook if (syms[i].st_shndx == SHN_UNDEF || 140849918a75Spbrook syms[i].st_shndx >= SHN_LORESERVE || 140949918a75Spbrook ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 141049918a75Spbrook nsyms--; 141149918a75Spbrook if (i < nsyms) { 141249918a75Spbrook syms[i] = syms[nsyms]; 141349918a75Spbrook } 141449918a75Spbrook continue; 141549918a75Spbrook } 141649918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS) 141749918a75Spbrook /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 141849918a75Spbrook syms[i].st_value &= ~(target_ulong)1; 141949918a75Spbrook #endif 142049918a75Spbrook i++; 142149918a75Spbrook } 142249918a75Spbrook syms = realloc(syms, nsyms * sizeof(*syms)); 142349918a75Spbrook 142449918a75Spbrook qsort(syms, nsyms, sizeof(*syms), symcmp); 142549918a75Spbrook 1426689f936fSbellard lseek(fd, strtab.sh_offset, SEEK_SET); 1427689f936fSbellard if (read(fd, strings, strtab.sh_size) != strtab.sh_size) 1428689f936fSbellard return; 142949918a75Spbrook s->disas_num_syms = nsyms; 143049918a75Spbrook #if ELF_CLASS == ELFCLASS32 143149918a75Spbrook s->disas_symtab.elf32 = syms; 14329f9f0309SPaul Brook s->lookup_symbol = lookup_symbolxx; 143349918a75Spbrook #else 143449918a75Spbrook s->disas_symtab.elf64 = syms; 14359f9f0309SPaul Brook s->lookup_symbol = lookup_symbolxx; 143649918a75Spbrook #endif 1437e80cfcfcSbellard s->next = syminfos; 1438e80cfcfcSbellard syminfos = s; 1439689f936fSbellard } 144031e31b8aSbellard 1441e5fe0c52Spbrook int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, 144231e31b8aSbellard struct image_info * info) 144331e31b8aSbellard { 144431e31b8aSbellard struct elfhdr elf_ex; 144531e31b8aSbellard struct elfhdr interp_elf_ex; 144631e31b8aSbellard struct exec interp_ex; 144731e31b8aSbellard int interpreter_fd = -1; /* avoid warning */ 1448992f48a0Sblueswir1 abi_ulong load_addr, load_bias; 144931e31b8aSbellard int load_addr_set = 0; 145031e31b8aSbellard unsigned int interpreter_type = INTERPRETER_NONE; 145131e31b8aSbellard unsigned char ibcs2_interpreter; 145231e31b8aSbellard int i; 1453992f48a0Sblueswir1 abi_ulong mapped_addr; 145431e31b8aSbellard struct elf_phdr * elf_ppnt; 145531e31b8aSbellard struct elf_phdr *elf_phdata; 1456992f48a0Sblueswir1 abi_ulong elf_bss, k, elf_brk; 145731e31b8aSbellard int retval; 145831e31b8aSbellard char * elf_interpreter; 1459992f48a0Sblueswir1 abi_ulong elf_entry, interp_load_addr = 0; 146031e31b8aSbellard int status; 1461992f48a0Sblueswir1 abi_ulong start_code, end_code, start_data, end_data; 1462992f48a0Sblueswir1 abi_ulong reloc_func_desc = 0; 1463992f48a0Sblueswir1 abi_ulong elf_stack; 146431e31b8aSbellard char passed_fileno[6]; 146531e31b8aSbellard 146631e31b8aSbellard ibcs2_interpreter = 0; 146731e31b8aSbellard status = 0; 146831e31b8aSbellard load_addr = 0; 146909bfb054Sbellard load_bias = 0; 147031e31b8aSbellard elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ 147131e31b8aSbellard #ifdef BSWAP_NEEDED 147231e31b8aSbellard bswap_ehdr(&elf_ex); 147331e31b8aSbellard #endif 147431e31b8aSbellard 147531e31b8aSbellard /* First of all, some simple consistency checks */ 147631e31b8aSbellard if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || 147731e31b8aSbellard (! elf_check_arch(elf_ex.e_machine))) { 147831e31b8aSbellard return -ENOEXEC; 147931e31b8aSbellard } 148031e31b8aSbellard 1481e5fe0c52Spbrook bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); 1482e5fe0c52Spbrook bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); 1483e5fe0c52Spbrook bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); 1484e5fe0c52Spbrook if (!bprm->p) { 1485e5fe0c52Spbrook retval = -E2BIG; 1486e5fe0c52Spbrook } 1487e5fe0c52Spbrook 148831e31b8aSbellard /* Now read in all of the header information */ 148931e31b8aSbellard elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); 149031e31b8aSbellard if (elf_phdata == NULL) { 149131e31b8aSbellard return -ENOMEM; 149231e31b8aSbellard } 149331e31b8aSbellard 149431e31b8aSbellard retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET); 149531e31b8aSbellard if(retval > 0) { 149631e31b8aSbellard retval = read(bprm->fd, (char *) elf_phdata, 149731e31b8aSbellard elf_ex.e_phentsize * elf_ex.e_phnum); 149831e31b8aSbellard } 149931e31b8aSbellard 150031e31b8aSbellard if (retval < 0) { 150131e31b8aSbellard perror("load_elf_binary"); 150231e31b8aSbellard exit(-1); 150331e31b8aSbellard free (elf_phdata); 150431e31b8aSbellard return -errno; 150531e31b8aSbellard } 150631e31b8aSbellard 1507b17780d5Sbellard #ifdef BSWAP_NEEDED 1508b17780d5Sbellard elf_ppnt = elf_phdata; 1509b17780d5Sbellard for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) { 1510b17780d5Sbellard bswap_phdr(elf_ppnt); 1511b17780d5Sbellard } 1512b17780d5Sbellard #endif 151331e31b8aSbellard elf_ppnt = elf_phdata; 151431e31b8aSbellard 151531e31b8aSbellard elf_bss = 0; 151631e31b8aSbellard elf_brk = 0; 151731e31b8aSbellard 151831e31b8aSbellard 1519992f48a0Sblueswir1 elf_stack = ~((abi_ulong)0UL); 152031e31b8aSbellard elf_interpreter = NULL; 1521992f48a0Sblueswir1 start_code = ~((abi_ulong)0UL); 152231e31b8aSbellard end_code = 0; 1523863cf0b7Sj_mayer start_data = 0; 152431e31b8aSbellard end_data = 0; 152598448f58Sblueswir1 interp_ex.a_info = 0; 152631e31b8aSbellard 152731e31b8aSbellard for(i=0;i < elf_ex.e_phnum; i++) { 152831e31b8aSbellard if (elf_ppnt->p_type == PT_INTERP) { 152931e31b8aSbellard if ( elf_interpreter != NULL ) 153031e31b8aSbellard { 153131e31b8aSbellard free (elf_phdata); 153231e31b8aSbellard free(elf_interpreter); 153331e31b8aSbellard close(bprm->fd); 153431e31b8aSbellard return -EINVAL; 153531e31b8aSbellard } 153631e31b8aSbellard 153731e31b8aSbellard /* This is the program interpreter used for 153831e31b8aSbellard * shared libraries - for now assume that this 153931e31b8aSbellard * is an a.out format binary 154031e31b8aSbellard */ 154131e31b8aSbellard 154232ce6337Sbellard elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); 154331e31b8aSbellard 154431e31b8aSbellard if (elf_interpreter == NULL) { 154531e31b8aSbellard free (elf_phdata); 154631e31b8aSbellard close(bprm->fd); 154731e31b8aSbellard return -ENOMEM; 154831e31b8aSbellard } 154931e31b8aSbellard 155031e31b8aSbellard retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); 155131e31b8aSbellard if(retval >= 0) { 155232ce6337Sbellard retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); 155331e31b8aSbellard } 155431e31b8aSbellard if(retval < 0) { 155531e31b8aSbellard perror("load_elf_binary2"); 155631e31b8aSbellard exit(-1); 155731e31b8aSbellard } 155831e31b8aSbellard 155931e31b8aSbellard /* If the program interpreter is one of these two, 156031e31b8aSbellard then assume an iBCS2 image. Otherwise assume 156131e31b8aSbellard a native linux image. */ 156231e31b8aSbellard 156331e31b8aSbellard /* JRP - Need to add X86 lib dir stuff here... */ 156431e31b8aSbellard 156531e31b8aSbellard if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || 156631e31b8aSbellard strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) { 156731e31b8aSbellard ibcs2_interpreter = 1; 156831e31b8aSbellard } 156931e31b8aSbellard 157031e31b8aSbellard #if 0 15713bc0bdcaSPaul Bolle printf("Using ELF interpreter %s\n", path(elf_interpreter)); 157231e31b8aSbellard #endif 157331e31b8aSbellard if (retval >= 0) { 157432ce6337Sbellard retval = open(path(elf_interpreter), O_RDONLY); 157531e31b8aSbellard if(retval >= 0) { 157631e31b8aSbellard interpreter_fd = retval; 157731e31b8aSbellard } 157831e31b8aSbellard else { 157931e31b8aSbellard perror(elf_interpreter); 158031e31b8aSbellard exit(-1); 158131e31b8aSbellard /* retval = -errno; */ 158231e31b8aSbellard } 158331e31b8aSbellard } 158431e31b8aSbellard 158531e31b8aSbellard if (retval >= 0) { 158631e31b8aSbellard retval = lseek(interpreter_fd, 0, SEEK_SET); 158731e31b8aSbellard if(retval >= 0) { 158831e31b8aSbellard retval = read(interpreter_fd,bprm->buf,128); 158931e31b8aSbellard } 159031e31b8aSbellard } 159131e31b8aSbellard if (retval >= 0) { 159231e31b8aSbellard interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */ 159331e31b8aSbellard interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */ 159431e31b8aSbellard } 159531e31b8aSbellard if (retval < 0) { 159631e31b8aSbellard perror("load_elf_binary3"); 159731e31b8aSbellard exit(-1); 159831e31b8aSbellard free (elf_phdata); 159931e31b8aSbellard free(elf_interpreter); 160031e31b8aSbellard close(bprm->fd); 160131e31b8aSbellard return retval; 160231e31b8aSbellard } 160331e31b8aSbellard } 160431e31b8aSbellard elf_ppnt++; 160531e31b8aSbellard } 160631e31b8aSbellard 160731e31b8aSbellard /* Some simple consistency checks for the interpreter */ 160831e31b8aSbellard if (elf_interpreter){ 160931e31b8aSbellard interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; 161031e31b8aSbellard 161131e31b8aSbellard /* Now figure out which format our binary is */ 161231e31b8aSbellard if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && 161331e31b8aSbellard (N_MAGIC(interp_ex) != QMAGIC)) { 161431e31b8aSbellard interpreter_type = INTERPRETER_ELF; 161531e31b8aSbellard } 161631e31b8aSbellard 161731e31b8aSbellard if (interp_elf_ex.e_ident[0] != 0x7f || 1618b55266b5Sblueswir1 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) { 161931e31b8aSbellard interpreter_type &= ~INTERPRETER_ELF; 162031e31b8aSbellard } 162131e31b8aSbellard 162231e31b8aSbellard if (!interpreter_type) { 162331e31b8aSbellard free(elf_interpreter); 162431e31b8aSbellard free(elf_phdata); 162531e31b8aSbellard close(bprm->fd); 162631e31b8aSbellard return -ELIBBAD; 162731e31b8aSbellard } 162831e31b8aSbellard } 162931e31b8aSbellard 163031e31b8aSbellard /* OK, we are done with that, now set up the arg stuff, 163131e31b8aSbellard and then start this sucker up */ 163231e31b8aSbellard 1633e5fe0c52Spbrook { 163431e31b8aSbellard char * passed_p; 163531e31b8aSbellard 163631e31b8aSbellard if (interpreter_type == INTERPRETER_AOUT) { 1637eba2af63Sbellard snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd); 163831e31b8aSbellard passed_p = passed_fileno; 163931e31b8aSbellard 164031e31b8aSbellard if (elf_interpreter) { 1641e5fe0c52Spbrook bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p); 164231e31b8aSbellard bprm->argc++; 164331e31b8aSbellard } 164431e31b8aSbellard } 164531e31b8aSbellard if (!bprm->p) { 164631e31b8aSbellard if (elf_interpreter) { 164731e31b8aSbellard free(elf_interpreter); 164831e31b8aSbellard } 164931e31b8aSbellard free (elf_phdata); 165031e31b8aSbellard close(bprm->fd); 165131e31b8aSbellard return -E2BIG; 165231e31b8aSbellard } 165331e31b8aSbellard } 165431e31b8aSbellard 165531e31b8aSbellard /* OK, This is the point of no return */ 165631e31b8aSbellard info->end_data = 0; 165731e31b8aSbellard info->end_code = 0; 1658992f48a0Sblueswir1 info->start_mmap = (abi_ulong)ELF_START_MMAP; 165931e31b8aSbellard info->mmap = 0; 1660992f48a0Sblueswir1 elf_entry = (abi_ulong) elf_ex.e_entry; 166131e31b8aSbellard 1662379f6698SPaul Brook #if defined(CONFIG_USE_GUEST_BASE) 1663379f6698SPaul Brook /* 1664379f6698SPaul Brook * In case where user has not explicitly set the guest_base, we 1665379f6698SPaul Brook * probe here that should we set it automatically. 1666379f6698SPaul Brook */ 1667379f6698SPaul Brook if (!have_guest_base) { 1668379f6698SPaul Brook /* 1669*c581dedaSPaul Brook * Go through ELF program header table and find the address 1670*c581dedaSPaul Brook * range used by loadable segments. Check that this is available on 1671*c581dedaSPaul Brook * the host, and if not find a suitable value for guest_base. */ 1672*c581dedaSPaul Brook abi_ulong app_start = ~0; 1673*c581dedaSPaul Brook abi_ulong app_end = 0; 1674*c581dedaSPaul Brook abi_ulong addr; 1675*c581dedaSPaul Brook unsigned long host_start; 1676*c581dedaSPaul Brook unsigned long real_start; 1677*c581dedaSPaul Brook unsigned long host_size; 1678379f6698SPaul Brook for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; 1679379f6698SPaul Brook i++, elf_ppnt++) { 1680379f6698SPaul Brook if (elf_ppnt->p_type != PT_LOAD) 1681379f6698SPaul Brook continue; 1682*c581dedaSPaul Brook addr = elf_ppnt->p_vaddr; 1683*c581dedaSPaul Brook if (addr < app_start) { 1684*c581dedaSPaul Brook app_start = addr; 1685*c581dedaSPaul Brook } 1686*c581dedaSPaul Brook addr += elf_ppnt->p_memsz; 1687*c581dedaSPaul Brook if (addr > app_end) { 1688*c581dedaSPaul Brook app_end = addr; 1689*c581dedaSPaul Brook } 1690*c581dedaSPaul Brook } 1691*c581dedaSPaul Brook 1692*c581dedaSPaul Brook /* If we don't have any loadable segments then something 1693*c581dedaSPaul Brook is very wrong. */ 1694*c581dedaSPaul Brook assert(app_start < app_end); 1695*c581dedaSPaul Brook 1696*c581dedaSPaul Brook /* Round addresses to page boundaries. */ 1697*c581dedaSPaul Brook app_start = app_start & qemu_host_page_mask; 1698*c581dedaSPaul Brook app_end = HOST_PAGE_ALIGN(app_end); 1699*c581dedaSPaul Brook if (app_start < mmap_min_addr) { 1700*c581dedaSPaul Brook host_start = HOST_PAGE_ALIGN(mmap_min_addr); 1701*c581dedaSPaul Brook } else { 1702*c581dedaSPaul Brook host_start = app_start; 1703*c581dedaSPaul Brook if (host_start != app_start) { 1704*c581dedaSPaul Brook fprintf(stderr, "qemu: Address overflow loading ELF binary\n"); 1705*c581dedaSPaul Brook abort(); 1706*c581dedaSPaul Brook } 1707*c581dedaSPaul Brook } 1708*c581dedaSPaul Brook host_size = app_end - app_start; 1709*c581dedaSPaul Brook while (1) { 1710*c581dedaSPaul Brook /* Do not use mmap_find_vma here because that is limited to the 1711*c581dedaSPaul Brook guest address space. We are going to make the 1712*c581dedaSPaul Brook guest address space fit whatever we're given. */ 1713*c581dedaSPaul Brook real_start = (unsigned long)mmap((void *)host_start, host_size, 1714*c581dedaSPaul Brook PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0); 1715*c581dedaSPaul Brook if (real_start == (unsigned long)-1) { 1716*c581dedaSPaul Brook fprintf(stderr, "qemu: Virtual memory exausted\n"); 1717*c581dedaSPaul Brook abort(); 1718*c581dedaSPaul Brook } 1719*c581dedaSPaul Brook if (real_start == host_start) { 1720379f6698SPaul Brook break; 1721379f6698SPaul Brook } 1722*c581dedaSPaul Brook /* That address didn't work. Unmap and try a different one. 1723*c581dedaSPaul Brook The address the host picked because is typically 1724*c581dedaSPaul Brook right at the top of the host address space and leaves the 1725*c581dedaSPaul Brook guest with no usable address space. Resort to a linear search. 1726*c581dedaSPaul Brook We already compensated for mmap_min_addr, so this should not 1727*c581dedaSPaul Brook happen often. Probably means we got unlucky and host address 1728*c581dedaSPaul Brook space randomization put a shared library somewhere 1729*c581dedaSPaul Brook inconvenient. */ 1730*c581dedaSPaul Brook munmap((void *)real_start, host_size); 1731*c581dedaSPaul Brook host_start += qemu_host_page_size; 1732*c581dedaSPaul Brook if (host_start == app_start) { 1733*c581dedaSPaul Brook /* Theoretically possible if host doesn't have any 1734*c581dedaSPaul Brook suitably aligned areas. Normally the first mmap will 1735*c581dedaSPaul Brook fail. */ 1736*c581dedaSPaul Brook fprintf(stderr, "qemu: Unable to find space for application\n"); 1737*c581dedaSPaul Brook abort(); 1738379f6698SPaul Brook } 1739379f6698SPaul Brook } 1740*c581dedaSPaul Brook qemu_log("Relocating guest address space from 0x" TARGET_ABI_FMT_lx 1741*c581dedaSPaul Brook " to 0x%lx\n", app_start, real_start); 1742*c581dedaSPaul Brook guest_base = real_start - app_start; 1743*c581dedaSPaul Brook } 1744379f6698SPaul Brook #endif /* CONFIG_USE_GUEST_BASE */ 1745379f6698SPaul Brook 174631e31b8aSbellard /* Do this so that we can load the interpreter, if need be. We will 174731e31b8aSbellard change some of these later */ 174831e31b8aSbellard info->rss = 0; 174931e31b8aSbellard bprm->p = setup_arg_pages(bprm->p, bprm, info); 175031e31b8aSbellard info->start_stack = bprm->p; 175131e31b8aSbellard 175231e31b8aSbellard /* Now we do a little grungy work by mmaping the ELF image into 175331e31b8aSbellard * the correct location in memory. At this point, we assume that 175431e31b8aSbellard * the image should be loaded at fixed address, not at a variable 175531e31b8aSbellard * address. 175631e31b8aSbellard */ 175731e31b8aSbellard 175831e31b8aSbellard for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { 175931e31b8aSbellard int elf_prot = 0; 176009bfb054Sbellard int elf_flags = 0; 1761992f48a0Sblueswir1 abi_ulong error; 176209bfb054Sbellard 176309bfb054Sbellard if (elf_ppnt->p_type != PT_LOAD) 176409bfb054Sbellard continue; 176509bfb054Sbellard 176631e31b8aSbellard if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; 176731e31b8aSbellard if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 176831e31b8aSbellard if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 176909bfb054Sbellard elf_flags = MAP_PRIVATE | MAP_DENYWRITE; 177009bfb054Sbellard if (elf_ex.e_type == ET_EXEC || load_addr_set) { 177109bfb054Sbellard elf_flags |= MAP_FIXED; 177209bfb054Sbellard } else if (elf_ex.e_type == ET_DYN) { 177309bfb054Sbellard /* Try and get dynamic programs out of the way of the default mmap 177409bfb054Sbellard base, as well as whatever program they might try to exec. This 177509bfb054Sbellard is because the brk will follow the loader, and is not movable. */ 177609bfb054Sbellard /* NOTE: for qemu, we do a big mmap to get enough space 1777e91c8a77Sths without hardcoding any address */ 177854936004Sbellard error = target_mmap(0, ET_DYN_MAP_SIZE, 177909bfb054Sbellard PROT_NONE, MAP_PRIVATE | MAP_ANON, 178009bfb054Sbellard -1, 0); 178109bfb054Sbellard if (error == -1) { 178209bfb054Sbellard perror("mmap"); 178309bfb054Sbellard exit(-1); 178409bfb054Sbellard } 178554936004Sbellard load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); 178609bfb054Sbellard } 178731e31b8aSbellard 178854936004Sbellard error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), 178931e31b8aSbellard (elf_ppnt->p_filesz + 179054936004Sbellard TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), 179131e31b8aSbellard elf_prot, 179231e31b8aSbellard (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), 179331e31b8aSbellard bprm->fd, 179431e31b8aSbellard (elf_ppnt->p_offset - 179554936004Sbellard TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); 179609bfb054Sbellard if (error == -1) { 179731e31b8aSbellard perror("mmap"); 179831e31b8aSbellard exit(-1); 179931e31b8aSbellard } 180031e31b8aSbellard 180131e31b8aSbellard #ifdef LOW_ELF_STACK 180254936004Sbellard if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) 180354936004Sbellard elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr); 180431e31b8aSbellard #endif 180531e31b8aSbellard 180631e31b8aSbellard if (!load_addr_set) { 180731e31b8aSbellard load_addr_set = 1; 180809bfb054Sbellard load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; 180909bfb054Sbellard if (elf_ex.e_type == ET_DYN) { 181009bfb054Sbellard load_bias += error - 181154936004Sbellard TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); 181209bfb054Sbellard load_addr += load_bias; 181384409ddbSj_mayer reloc_func_desc = load_bias; 181409bfb054Sbellard } 181531e31b8aSbellard } 181631e31b8aSbellard k = elf_ppnt->p_vaddr; 181709bfb054Sbellard if (k < start_code) 181809bfb054Sbellard start_code = k; 1819863cf0b7Sj_mayer if (start_data < k) 1820863cf0b7Sj_mayer start_data = k; 182131e31b8aSbellard k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; 182209bfb054Sbellard if (k > elf_bss) 182309bfb054Sbellard elf_bss = k; 182431e31b8aSbellard if ((elf_ppnt->p_flags & PF_X) && end_code < k) 182531e31b8aSbellard end_code = k; 182609bfb054Sbellard if (end_data < k) 182709bfb054Sbellard end_data = k; 182831e31b8aSbellard k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; 182931e31b8aSbellard if (k > elf_brk) elf_brk = k; 183031e31b8aSbellard } 183109bfb054Sbellard 183209bfb054Sbellard elf_entry += load_bias; 183309bfb054Sbellard elf_bss += load_bias; 183409bfb054Sbellard elf_brk += load_bias; 183509bfb054Sbellard start_code += load_bias; 183609bfb054Sbellard end_code += load_bias; 1837863cf0b7Sj_mayer start_data += load_bias; 183809bfb054Sbellard end_data += load_bias; 183931e31b8aSbellard 184031e31b8aSbellard if (elf_interpreter) { 184131e31b8aSbellard if (interpreter_type & 1) { 184231e31b8aSbellard elf_entry = load_aout_interp(&interp_ex, interpreter_fd); 184331e31b8aSbellard } 184431e31b8aSbellard else if (interpreter_type & 2) { 184531e31b8aSbellard elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, 184631e31b8aSbellard &interp_load_addr); 184731e31b8aSbellard } 184884409ddbSj_mayer reloc_func_desc = interp_load_addr; 184931e31b8aSbellard 185031e31b8aSbellard close(interpreter_fd); 185131e31b8aSbellard free(elf_interpreter); 185231e31b8aSbellard 1853992f48a0Sblueswir1 if (elf_entry == ~((abi_ulong)0UL)) { 185431e31b8aSbellard printf("Unable to load interpreter\n"); 185531e31b8aSbellard free(elf_phdata); 185631e31b8aSbellard exit(-1); 185731e31b8aSbellard return 0; 185831e31b8aSbellard } 185931e31b8aSbellard } 186031e31b8aSbellard 186131e31b8aSbellard free(elf_phdata); 186231e31b8aSbellard 186393fcfe39Saliguori if (qemu_log_enabled()) 1864689f936fSbellard load_symbols(&elf_ex, bprm->fd); 1865689f936fSbellard 186631e31b8aSbellard if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); 186731e31b8aSbellard info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); 186831e31b8aSbellard 186931e31b8aSbellard #ifdef LOW_ELF_STACK 187031e31b8aSbellard info->start_stack = bprm->p = elf_stack - 4; 187131e31b8aSbellard #endif 187253a5960aSpbrook bprm->p = create_elf_tables(bprm->p, 187331e31b8aSbellard bprm->argc, 187431e31b8aSbellard bprm->envc, 1875a1516e92Sbellard &elf_ex, 187609bfb054Sbellard load_addr, load_bias, 187731e31b8aSbellard interp_load_addr, 187831e31b8aSbellard (interpreter_type == INTERPRETER_AOUT ? 0 : 1), 187931e31b8aSbellard info); 188092a343daSj_mayer info->load_addr = reloc_func_desc; 188131e31b8aSbellard info->start_brk = info->brk = elf_brk; 188231e31b8aSbellard info->end_code = end_code; 188331e31b8aSbellard info->start_code = start_code; 1884863cf0b7Sj_mayer info->start_data = start_data; 188531e31b8aSbellard info->end_data = end_data; 188631e31b8aSbellard info->start_stack = bprm->p; 188731e31b8aSbellard 188831e31b8aSbellard /* Calling set_brk effectively mmaps the pages that we need for the bss and break 188931e31b8aSbellard sections */ 189031e31b8aSbellard set_brk(elf_bss, elf_brk); 189131e31b8aSbellard 1892768a4a36Sths padzero(elf_bss, elf_brk); 189331e31b8aSbellard 189431e31b8aSbellard #if 0 189531e31b8aSbellard printf("(start_brk) %x\n" , info->start_brk); 189631e31b8aSbellard printf("(end_code) %x\n" , info->end_code); 189731e31b8aSbellard printf("(start_code) %x\n" , info->start_code); 189831e31b8aSbellard printf("(end_data) %x\n" , info->end_data); 189931e31b8aSbellard printf("(start_stack) %x\n" , info->start_stack); 190031e31b8aSbellard printf("(brk) %x\n" , info->brk); 190131e31b8aSbellard #endif 190231e31b8aSbellard 190331e31b8aSbellard if ( info->personality == PER_SVR4 ) 190431e31b8aSbellard { 190531e31b8aSbellard /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 190631e31b8aSbellard and some applications "depend" upon this behavior. 190731e31b8aSbellard Since we do not have the power to recompile these, we 190831e31b8aSbellard emulate the SVr4 behavior. Sigh. */ 190983fb7adfSbellard mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, 191031e31b8aSbellard MAP_FIXED | MAP_PRIVATE, -1, 0); 191131e31b8aSbellard } 191231e31b8aSbellard 191331e31b8aSbellard info->entry = elf_entry; 191431e31b8aSbellard 1915edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 1916edf8e2afSMika Westerberg bprm->core_dump = &elf_core_dump; 1917edf8e2afSMika Westerberg #endif 1918edf8e2afSMika Westerberg 191931e31b8aSbellard return 0; 192031e31b8aSbellard } 192131e31b8aSbellard 1922edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 1923edf8e2afSMika Westerberg 1924edf8e2afSMika Westerberg /* 1925edf8e2afSMika Westerberg * Definitions to generate Intel SVR4-like core files. 1926a2547a13SLaurent Desnogues * These mostly have the same names as the SVR4 types with "target_elf_" 1927edf8e2afSMika Westerberg * tacked on the front to prevent clashes with linux definitions, 1928edf8e2afSMika Westerberg * and the typedef forms have been avoided. This is mostly like 1929edf8e2afSMika Westerberg * the SVR4 structure, but more Linuxy, with things that Linux does 1930edf8e2afSMika Westerberg * not support and which gdb doesn't really use excluded. 1931edf8e2afSMika Westerberg * 1932edf8e2afSMika Westerberg * Fields we don't dump (their contents is zero) in linux-user qemu 1933edf8e2afSMika Westerberg * are marked with XXX. 1934edf8e2afSMika Westerberg * 1935edf8e2afSMika Westerberg * Core dump code is copied from linux kernel (fs/binfmt_elf.c). 1936edf8e2afSMika Westerberg * 1937edf8e2afSMika Westerberg * Porting ELF coredump for target is (quite) simple process. First you 1938dd0a3651SNathan Froyd * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for 1939edf8e2afSMika Westerberg * the target resides): 1940edf8e2afSMika Westerberg * 1941edf8e2afSMika Westerberg * #define USE_ELF_CORE_DUMP 1942edf8e2afSMika Westerberg * 1943edf8e2afSMika Westerberg * Next you define type of register set used for dumping. ELF specification 1944edf8e2afSMika Westerberg * says that it needs to be array of elf_greg_t that has size of ELF_NREG. 1945edf8e2afSMika Westerberg * 1946c227f099SAnthony Liguori * typedef <target_regtype> target_elf_greg_t; 1947edf8e2afSMika Westerberg * #define ELF_NREG <number of registers> 1948c227f099SAnthony Liguori * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1949edf8e2afSMika Westerberg * 1950edf8e2afSMika Westerberg * Last step is to implement target specific function that copies registers 1951edf8e2afSMika Westerberg * from given cpu into just specified register set. Prototype is: 1952edf8e2afSMika Westerberg * 1953c227f099SAnthony Liguori * static void elf_core_copy_regs(taret_elf_gregset_t *regs, 1954a2547a13SLaurent Desnogues * const CPUState *env); 1955edf8e2afSMika Westerberg * 1956edf8e2afSMika Westerberg * Parameters: 1957edf8e2afSMika Westerberg * regs - copy register values into here (allocated and zeroed by caller) 1958edf8e2afSMika Westerberg * env - copy registers from here 1959edf8e2afSMika Westerberg * 1960edf8e2afSMika Westerberg * Example for ARM target is provided in this file. 1961edf8e2afSMika Westerberg */ 1962edf8e2afSMika Westerberg 1963edf8e2afSMika Westerberg /* An ELF note in memory */ 1964edf8e2afSMika Westerberg struct memelfnote { 1965edf8e2afSMika Westerberg const char *name; 1966edf8e2afSMika Westerberg size_t namesz; 1967edf8e2afSMika Westerberg size_t namesz_rounded; 1968edf8e2afSMika Westerberg int type; 1969edf8e2afSMika Westerberg size_t datasz; 1970edf8e2afSMika Westerberg void *data; 1971edf8e2afSMika Westerberg size_t notesz; 1972edf8e2afSMika Westerberg }; 1973edf8e2afSMika Westerberg 1974a2547a13SLaurent Desnogues struct target_elf_siginfo { 1975edf8e2afSMika Westerberg int si_signo; /* signal number */ 1976edf8e2afSMika Westerberg int si_code; /* extra code */ 1977edf8e2afSMika Westerberg int si_errno; /* errno */ 1978edf8e2afSMika Westerberg }; 1979edf8e2afSMika Westerberg 1980a2547a13SLaurent Desnogues struct target_elf_prstatus { 1981a2547a13SLaurent Desnogues struct target_elf_siginfo pr_info; /* Info associated with signal */ 1982edf8e2afSMika Westerberg short pr_cursig; /* Current signal */ 1983edf8e2afSMika Westerberg target_ulong pr_sigpend; /* XXX */ 1984edf8e2afSMika Westerberg target_ulong pr_sighold; /* XXX */ 1985c227f099SAnthony Liguori target_pid_t pr_pid; 1986c227f099SAnthony Liguori target_pid_t pr_ppid; 1987c227f099SAnthony Liguori target_pid_t pr_pgrp; 1988c227f099SAnthony Liguori target_pid_t pr_sid; 1989edf8e2afSMika Westerberg struct target_timeval pr_utime; /* XXX User time */ 1990edf8e2afSMika Westerberg struct target_timeval pr_stime; /* XXX System time */ 1991edf8e2afSMika Westerberg struct target_timeval pr_cutime; /* XXX Cumulative user time */ 1992edf8e2afSMika Westerberg struct target_timeval pr_cstime; /* XXX Cumulative system time */ 1993c227f099SAnthony Liguori target_elf_gregset_t pr_reg; /* GP registers */ 1994edf8e2afSMika Westerberg int pr_fpvalid; /* XXX */ 1995edf8e2afSMika Westerberg }; 1996edf8e2afSMika Westerberg 1997edf8e2afSMika Westerberg #define ELF_PRARGSZ (80) /* Number of chars for args */ 1998edf8e2afSMika Westerberg 1999a2547a13SLaurent Desnogues struct target_elf_prpsinfo { 2000edf8e2afSMika Westerberg char pr_state; /* numeric process state */ 2001edf8e2afSMika Westerberg char pr_sname; /* char for pr_state */ 2002edf8e2afSMika Westerberg char pr_zomb; /* zombie */ 2003edf8e2afSMika Westerberg char pr_nice; /* nice val */ 2004edf8e2afSMika Westerberg target_ulong pr_flag; /* flags */ 2005c227f099SAnthony Liguori target_uid_t pr_uid; 2006c227f099SAnthony Liguori target_gid_t pr_gid; 2007c227f099SAnthony Liguori target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; 2008edf8e2afSMika Westerberg /* Lots missing */ 2009edf8e2afSMika Westerberg char pr_fname[16]; /* filename of executable */ 2010edf8e2afSMika Westerberg char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ 2011edf8e2afSMika Westerberg }; 2012edf8e2afSMika Westerberg 2013edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */ 2014edf8e2afSMika Westerberg struct elf_thread_status { 201572cf2d4fSBlue Swirl QTAILQ_ENTRY(elf_thread_status) ets_link; 2016a2547a13SLaurent Desnogues struct target_elf_prstatus prstatus; /* NT_PRSTATUS */ 2017edf8e2afSMika Westerberg #if 0 2018edf8e2afSMika Westerberg elf_fpregset_t fpu; /* NT_PRFPREG */ 2019edf8e2afSMika Westerberg struct task_struct *thread; 2020edf8e2afSMika Westerberg elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */ 2021edf8e2afSMika Westerberg #endif 2022edf8e2afSMika Westerberg struct memelfnote notes[1]; 2023edf8e2afSMika Westerberg int num_notes; 2024edf8e2afSMika Westerberg }; 2025edf8e2afSMika Westerberg 2026edf8e2afSMika Westerberg struct elf_note_info { 2027edf8e2afSMika Westerberg struct memelfnote *notes; 2028a2547a13SLaurent Desnogues struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */ 2029a2547a13SLaurent Desnogues struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */ 2030edf8e2afSMika Westerberg 203172cf2d4fSBlue Swirl QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list; 2032edf8e2afSMika Westerberg #if 0 2033edf8e2afSMika Westerberg /* 2034edf8e2afSMika Westerberg * Current version of ELF coredump doesn't support 2035edf8e2afSMika Westerberg * dumping fp regs etc. 2036edf8e2afSMika Westerberg */ 2037edf8e2afSMika Westerberg elf_fpregset_t *fpu; 2038edf8e2afSMika Westerberg elf_fpxregset_t *xfpu; 2039edf8e2afSMika Westerberg int thread_status_size; 2040edf8e2afSMika Westerberg #endif 2041edf8e2afSMika Westerberg int notes_size; 2042edf8e2afSMika Westerberg int numnote; 2043edf8e2afSMika Westerberg }; 2044edf8e2afSMika Westerberg 2045edf8e2afSMika Westerberg struct vm_area_struct { 2046edf8e2afSMika Westerberg abi_ulong vma_start; /* start vaddr of memory region */ 2047edf8e2afSMika Westerberg abi_ulong vma_end; /* end vaddr of memory region */ 2048edf8e2afSMika Westerberg abi_ulong vma_flags; /* protection etc. flags for the region */ 204972cf2d4fSBlue Swirl QTAILQ_ENTRY(vm_area_struct) vma_link; 2050edf8e2afSMika Westerberg }; 2051edf8e2afSMika Westerberg 2052edf8e2afSMika Westerberg struct mm_struct { 205372cf2d4fSBlue Swirl QTAILQ_HEAD(, vm_area_struct) mm_mmap; 2054edf8e2afSMika Westerberg int mm_count; /* number of mappings */ 2055edf8e2afSMika Westerberg }; 2056edf8e2afSMika Westerberg 2057edf8e2afSMika Westerberg static struct mm_struct *vma_init(void); 2058edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *); 2059edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *, abi_ulong, 2060edf8e2afSMika Westerberg abi_ulong, abi_ulong); 2061edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *); 2062edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *); 2063edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *); 2064edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *); 2065b480d9b7SPaul Brook static int vma_walker(void *priv, abi_ulong start, abi_ulong end, 2066edf8e2afSMika Westerberg unsigned long flags); 2067edf8e2afSMika Westerberg 2068edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); 2069edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int, 2070edf8e2afSMika Westerberg unsigned int, void *); 2071a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); 2072a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); 2073edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *); 2074edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); 2075edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *); 2076edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *); 2077edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *, long, const CPUState *); 2078edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *, const CPUState *); 2079edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t); 2080edf8e2afSMika Westerberg 2081edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t); 2082edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int); 2083edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int); 2084edf8e2afSMika Westerberg 2085edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2086a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *); 2087a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *); 2088edf8e2afSMika Westerberg 2089a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus) 2090edf8e2afSMika Westerberg { 2091edf8e2afSMika Westerberg prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo); 2092edf8e2afSMika Westerberg prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code); 2093edf8e2afSMika Westerberg prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno); 2094edf8e2afSMika Westerberg prstatus->pr_cursig = tswap16(prstatus->pr_cursig); 2095edf8e2afSMika Westerberg prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend); 2096edf8e2afSMika Westerberg prstatus->pr_sighold = tswapl(prstatus->pr_sighold); 2097edf8e2afSMika Westerberg prstatus->pr_pid = tswap32(prstatus->pr_pid); 2098edf8e2afSMika Westerberg prstatus->pr_ppid = tswap32(prstatus->pr_ppid); 2099edf8e2afSMika Westerberg prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp); 2100edf8e2afSMika Westerberg prstatus->pr_sid = tswap32(prstatus->pr_sid); 2101edf8e2afSMika Westerberg /* cpu times are not filled, so we skip them */ 2102edf8e2afSMika Westerberg /* regs should be in correct format already */ 2103edf8e2afSMika Westerberg prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid); 2104edf8e2afSMika Westerberg } 2105edf8e2afSMika Westerberg 2106a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) 2107edf8e2afSMika Westerberg { 2108edf8e2afSMika Westerberg psinfo->pr_flag = tswapl(psinfo->pr_flag); 2109edf8e2afSMika Westerberg psinfo->pr_uid = tswap16(psinfo->pr_uid); 2110edf8e2afSMika Westerberg psinfo->pr_gid = tswap16(psinfo->pr_gid); 2111edf8e2afSMika Westerberg psinfo->pr_pid = tswap32(psinfo->pr_pid); 2112edf8e2afSMika Westerberg psinfo->pr_ppid = tswap32(psinfo->pr_ppid); 2113edf8e2afSMika Westerberg psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp); 2114edf8e2afSMika Westerberg psinfo->pr_sid = tswap32(psinfo->pr_sid); 2115edf8e2afSMika Westerberg } 2116edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 2117edf8e2afSMika Westerberg 2118edf8e2afSMika Westerberg /* 2119edf8e2afSMika Westerberg * Minimal support for linux memory regions. These are needed 2120edf8e2afSMika Westerberg * when we are finding out what memory exactly belongs to 2121edf8e2afSMika Westerberg * emulated process. No locks needed here, as long as 2122edf8e2afSMika Westerberg * thread that received the signal is stopped. 2123edf8e2afSMika Westerberg */ 2124edf8e2afSMika Westerberg 2125edf8e2afSMika Westerberg static struct mm_struct *vma_init(void) 2126edf8e2afSMika Westerberg { 2127edf8e2afSMika Westerberg struct mm_struct *mm; 2128edf8e2afSMika Westerberg 2129edf8e2afSMika Westerberg if ((mm = qemu_malloc(sizeof (*mm))) == NULL) 2130edf8e2afSMika Westerberg return (NULL); 2131edf8e2afSMika Westerberg 2132edf8e2afSMika Westerberg mm->mm_count = 0; 213372cf2d4fSBlue Swirl QTAILQ_INIT(&mm->mm_mmap); 2134edf8e2afSMika Westerberg 2135edf8e2afSMika Westerberg return (mm); 2136edf8e2afSMika Westerberg } 2137edf8e2afSMika Westerberg 2138edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm) 2139edf8e2afSMika Westerberg { 2140edf8e2afSMika Westerberg struct vm_area_struct *vma; 2141edf8e2afSMika Westerberg 2142edf8e2afSMika Westerberg while ((vma = vma_first(mm)) != NULL) { 214372cf2d4fSBlue Swirl QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link); 2144edf8e2afSMika Westerberg qemu_free(vma); 2145edf8e2afSMika Westerberg } 2146edf8e2afSMika Westerberg qemu_free(mm); 2147edf8e2afSMika Westerberg } 2148edf8e2afSMika Westerberg 2149edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *mm, abi_ulong start, 2150edf8e2afSMika Westerberg abi_ulong end, abi_ulong flags) 2151edf8e2afSMika Westerberg { 2152edf8e2afSMika Westerberg struct vm_area_struct *vma; 2153edf8e2afSMika Westerberg 2154edf8e2afSMika Westerberg if ((vma = qemu_mallocz(sizeof (*vma))) == NULL) 2155edf8e2afSMika Westerberg return (-1); 2156edf8e2afSMika Westerberg 2157edf8e2afSMika Westerberg vma->vma_start = start; 2158edf8e2afSMika Westerberg vma->vma_end = end; 2159edf8e2afSMika Westerberg vma->vma_flags = flags; 2160edf8e2afSMika Westerberg 216172cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link); 2162edf8e2afSMika Westerberg mm->mm_count++; 2163edf8e2afSMika Westerberg 2164edf8e2afSMika Westerberg return (0); 2165edf8e2afSMika Westerberg } 2166edf8e2afSMika Westerberg 2167edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm) 2168edf8e2afSMika Westerberg { 216972cf2d4fSBlue Swirl return (QTAILQ_FIRST(&mm->mm_mmap)); 2170edf8e2afSMika Westerberg } 2171edf8e2afSMika Westerberg 2172edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma) 2173edf8e2afSMika Westerberg { 217472cf2d4fSBlue Swirl return (QTAILQ_NEXT(vma, vma_link)); 2175edf8e2afSMika Westerberg } 2176edf8e2afSMika Westerberg 2177edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm) 2178edf8e2afSMika Westerberg { 2179edf8e2afSMika Westerberg return (mm->mm_count); 2180edf8e2afSMika Westerberg } 2181edf8e2afSMika Westerberg 2182edf8e2afSMika Westerberg /* 2183edf8e2afSMika Westerberg * Calculate file (dump) size of given memory region. 2184edf8e2afSMika Westerberg */ 2185edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma) 2186edf8e2afSMika Westerberg { 2187edf8e2afSMika Westerberg /* if we cannot even read the first page, skip it */ 2188edf8e2afSMika Westerberg if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE)) 2189edf8e2afSMika Westerberg return (0); 2190edf8e2afSMika Westerberg 2191edf8e2afSMika Westerberg /* 2192edf8e2afSMika Westerberg * Usually we don't dump executable pages as they contain 2193edf8e2afSMika Westerberg * non-writable code that debugger can read directly from 2194edf8e2afSMika Westerberg * target library etc. However, thread stacks are marked 2195edf8e2afSMika Westerberg * also executable so we read in first page of given region 2196edf8e2afSMika Westerberg * and check whether it contains elf header. If there is 2197edf8e2afSMika Westerberg * no elf header, we dump it. 2198edf8e2afSMika Westerberg */ 2199edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) { 2200edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 2201edf8e2afSMika Westerberg 2202edf8e2afSMika Westerberg copy_from_user(page, vma->vma_start, sizeof (page)); 2203edf8e2afSMika Westerberg if ((page[EI_MAG0] == ELFMAG0) && 2204edf8e2afSMika Westerberg (page[EI_MAG1] == ELFMAG1) && 2205edf8e2afSMika Westerberg (page[EI_MAG2] == ELFMAG2) && 2206edf8e2afSMika Westerberg (page[EI_MAG3] == ELFMAG3)) { 2207edf8e2afSMika Westerberg /* 2208edf8e2afSMika Westerberg * Mappings are possibly from ELF binary. Don't dump 2209edf8e2afSMika Westerberg * them. 2210edf8e2afSMika Westerberg */ 2211edf8e2afSMika Westerberg return (0); 2212edf8e2afSMika Westerberg } 2213edf8e2afSMika Westerberg } 2214edf8e2afSMika Westerberg 2215edf8e2afSMika Westerberg return (vma->vma_end - vma->vma_start); 2216edf8e2afSMika Westerberg } 2217edf8e2afSMika Westerberg 2218b480d9b7SPaul Brook static int vma_walker(void *priv, abi_ulong start, abi_ulong end, 2219edf8e2afSMika Westerberg unsigned long flags) 2220edf8e2afSMika Westerberg { 2221edf8e2afSMika Westerberg struct mm_struct *mm = (struct mm_struct *)priv; 2222edf8e2afSMika Westerberg 2223edf8e2afSMika Westerberg vma_add_mapping(mm, start, end, flags); 2224edf8e2afSMika Westerberg return (0); 2225edf8e2afSMika Westerberg } 2226edf8e2afSMika Westerberg 2227edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type, 2228edf8e2afSMika Westerberg unsigned int sz, void *data) 2229edf8e2afSMika Westerberg { 2230edf8e2afSMika Westerberg unsigned int namesz; 2231edf8e2afSMika Westerberg 2232edf8e2afSMika Westerberg namesz = strlen(name) + 1; 2233edf8e2afSMika Westerberg note->name = name; 2234edf8e2afSMika Westerberg note->namesz = namesz; 2235edf8e2afSMika Westerberg note->namesz_rounded = roundup(namesz, sizeof (int32_t)); 2236edf8e2afSMika Westerberg note->type = type; 2237edf8e2afSMika Westerberg note->datasz = roundup(sz, sizeof (int32_t));; 2238edf8e2afSMika Westerberg note->data = data; 2239edf8e2afSMika Westerberg 2240edf8e2afSMika Westerberg /* 2241edf8e2afSMika Westerberg * We calculate rounded up note size here as specified by 2242edf8e2afSMika Westerberg * ELF document. 2243edf8e2afSMika Westerberg */ 2244edf8e2afSMika Westerberg note->notesz = sizeof (struct elf_note) + 2245edf8e2afSMika Westerberg note->namesz_rounded + note->datasz; 2246edf8e2afSMika Westerberg } 2247edf8e2afSMika Westerberg 2248edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, 2249edf8e2afSMika Westerberg uint32_t flags) 2250edf8e2afSMika Westerberg { 2251edf8e2afSMika Westerberg (void) memset(elf, 0, sizeof(*elf)); 2252edf8e2afSMika Westerberg 2253edf8e2afSMika Westerberg (void) memcpy(elf->e_ident, ELFMAG, SELFMAG); 2254edf8e2afSMika Westerberg elf->e_ident[EI_CLASS] = ELF_CLASS; 2255edf8e2afSMika Westerberg elf->e_ident[EI_DATA] = ELF_DATA; 2256edf8e2afSMika Westerberg elf->e_ident[EI_VERSION] = EV_CURRENT; 2257edf8e2afSMika Westerberg elf->e_ident[EI_OSABI] = ELF_OSABI; 2258edf8e2afSMika Westerberg 2259edf8e2afSMika Westerberg elf->e_type = ET_CORE; 2260edf8e2afSMika Westerberg elf->e_machine = machine; 2261edf8e2afSMika Westerberg elf->e_version = EV_CURRENT; 2262edf8e2afSMika Westerberg elf->e_phoff = sizeof(struct elfhdr); 2263edf8e2afSMika Westerberg elf->e_flags = flags; 2264edf8e2afSMika Westerberg elf->e_ehsize = sizeof(struct elfhdr); 2265edf8e2afSMika Westerberg elf->e_phentsize = sizeof(struct elf_phdr); 2266edf8e2afSMika Westerberg elf->e_phnum = segs; 2267edf8e2afSMika Westerberg 2268edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2269edf8e2afSMika Westerberg bswap_ehdr(elf); 2270edf8e2afSMika Westerberg #endif 2271edf8e2afSMika Westerberg } 2272edf8e2afSMika Westerberg 2273edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) 2274edf8e2afSMika Westerberg { 2275edf8e2afSMika Westerberg phdr->p_type = PT_NOTE; 2276edf8e2afSMika Westerberg phdr->p_offset = offset; 2277edf8e2afSMika Westerberg phdr->p_vaddr = 0; 2278edf8e2afSMika Westerberg phdr->p_paddr = 0; 2279edf8e2afSMika Westerberg phdr->p_filesz = sz; 2280edf8e2afSMika Westerberg phdr->p_memsz = 0; 2281edf8e2afSMika Westerberg phdr->p_flags = 0; 2282edf8e2afSMika Westerberg phdr->p_align = 0; 2283edf8e2afSMika Westerberg 2284edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2285edf8e2afSMika Westerberg bswap_phdr(phdr); 2286edf8e2afSMika Westerberg #endif 2287edf8e2afSMika Westerberg } 2288edf8e2afSMika Westerberg 2289edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note) 2290edf8e2afSMika Westerberg { 2291edf8e2afSMika Westerberg return (note->notesz); 2292edf8e2afSMika Westerberg } 2293edf8e2afSMika Westerberg 2294a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus, 2295edf8e2afSMika Westerberg const TaskState *ts, int signr) 2296edf8e2afSMika Westerberg { 2297edf8e2afSMika Westerberg (void) memset(prstatus, 0, sizeof (*prstatus)); 2298edf8e2afSMika Westerberg prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 2299edf8e2afSMika Westerberg prstatus->pr_pid = ts->ts_tid; 2300edf8e2afSMika Westerberg prstatus->pr_ppid = getppid(); 2301edf8e2afSMika Westerberg prstatus->pr_pgrp = getpgrp(); 2302edf8e2afSMika Westerberg prstatus->pr_sid = getsid(0); 2303edf8e2afSMika Westerberg 2304edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2305edf8e2afSMika Westerberg bswap_prstatus(prstatus); 2306edf8e2afSMika Westerberg #endif 2307edf8e2afSMika Westerberg } 2308edf8e2afSMika Westerberg 2309a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) 2310edf8e2afSMika Westerberg { 2311edf8e2afSMika Westerberg char *filename, *base_filename; 2312edf8e2afSMika Westerberg unsigned int i, len; 2313edf8e2afSMika Westerberg 2314edf8e2afSMika Westerberg (void) memset(psinfo, 0, sizeof (*psinfo)); 2315edf8e2afSMika Westerberg 2316edf8e2afSMika Westerberg len = ts->info->arg_end - ts->info->arg_start; 2317edf8e2afSMika Westerberg if (len >= ELF_PRARGSZ) 2318edf8e2afSMika Westerberg len = ELF_PRARGSZ - 1; 2319edf8e2afSMika Westerberg if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len)) 2320edf8e2afSMika Westerberg return -EFAULT; 2321edf8e2afSMika Westerberg for (i = 0; i < len; i++) 2322edf8e2afSMika Westerberg if (psinfo->pr_psargs[i] == 0) 2323edf8e2afSMika Westerberg psinfo->pr_psargs[i] = ' '; 2324edf8e2afSMika Westerberg psinfo->pr_psargs[len] = 0; 2325edf8e2afSMika Westerberg 2326edf8e2afSMika Westerberg psinfo->pr_pid = getpid(); 2327edf8e2afSMika Westerberg psinfo->pr_ppid = getppid(); 2328edf8e2afSMika Westerberg psinfo->pr_pgrp = getpgrp(); 2329edf8e2afSMika Westerberg psinfo->pr_sid = getsid(0); 2330edf8e2afSMika Westerberg psinfo->pr_uid = getuid(); 2331edf8e2afSMika Westerberg psinfo->pr_gid = getgid(); 2332edf8e2afSMika Westerberg 2333edf8e2afSMika Westerberg filename = strdup(ts->bprm->filename); 2334edf8e2afSMika Westerberg base_filename = strdup(basename(filename)); 2335edf8e2afSMika Westerberg (void) strncpy(psinfo->pr_fname, base_filename, 2336edf8e2afSMika Westerberg sizeof(psinfo->pr_fname)); 2337edf8e2afSMika Westerberg free(base_filename); 2338edf8e2afSMika Westerberg free(filename); 2339edf8e2afSMika Westerberg 2340edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2341edf8e2afSMika Westerberg bswap_psinfo(psinfo); 2342edf8e2afSMika Westerberg #endif 2343edf8e2afSMika Westerberg return (0); 2344edf8e2afSMika Westerberg } 2345edf8e2afSMika Westerberg 2346edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) 2347edf8e2afSMika Westerberg { 2348edf8e2afSMika Westerberg elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; 2349edf8e2afSMika Westerberg elf_addr_t orig_auxv = auxv; 2350edf8e2afSMika Westerberg abi_ulong val; 2351edf8e2afSMika Westerberg void *ptr; 2352edf8e2afSMika Westerberg int i, len; 2353edf8e2afSMika Westerberg 2354edf8e2afSMika Westerberg /* 2355edf8e2afSMika Westerberg * Auxiliary vector is stored in target process stack. It contains 2356edf8e2afSMika Westerberg * {type, value} pairs that we need to dump into note. This is not 2357edf8e2afSMika Westerberg * strictly necessary but we do it here for sake of completeness. 2358edf8e2afSMika Westerberg */ 2359edf8e2afSMika Westerberg 2360edf8e2afSMika Westerberg /* find out lenght of the vector, AT_NULL is terminator */ 2361edf8e2afSMika Westerberg i = len = 0; 2362edf8e2afSMika Westerberg do { 2363edf8e2afSMika Westerberg get_user_ual(val, auxv); 2364edf8e2afSMika Westerberg i += 2; 2365edf8e2afSMika Westerberg auxv += 2 * sizeof (elf_addr_t); 2366edf8e2afSMika Westerberg } while (val != AT_NULL); 2367edf8e2afSMika Westerberg len = i * sizeof (elf_addr_t); 2368edf8e2afSMika Westerberg 2369edf8e2afSMika Westerberg /* read in whole auxv vector and copy it to memelfnote */ 2370edf8e2afSMika Westerberg ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); 2371edf8e2afSMika Westerberg if (ptr != NULL) { 2372edf8e2afSMika Westerberg fill_note(note, "CORE", NT_AUXV, len, ptr); 2373edf8e2afSMika Westerberg unlock_user(ptr, auxv, len); 2374edf8e2afSMika Westerberg } 2375edf8e2afSMika Westerberg } 2376edf8e2afSMika Westerberg 2377edf8e2afSMika Westerberg /* 2378edf8e2afSMika Westerberg * Constructs name of coredump file. We have following convention 2379edf8e2afSMika Westerberg * for the name: 2380edf8e2afSMika Westerberg * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core 2381edf8e2afSMika Westerberg * 2382edf8e2afSMika Westerberg * Returns 0 in case of success, -1 otherwise (errno is set). 2383edf8e2afSMika Westerberg */ 2384edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf, 2385edf8e2afSMika Westerberg size_t bufsize) 2386edf8e2afSMika Westerberg { 2387edf8e2afSMika Westerberg char timestamp[64]; 2388edf8e2afSMika Westerberg char *filename = NULL; 2389edf8e2afSMika Westerberg char *base_filename = NULL; 2390edf8e2afSMika Westerberg struct timeval tv; 2391edf8e2afSMika Westerberg struct tm tm; 2392edf8e2afSMika Westerberg 2393edf8e2afSMika Westerberg assert(bufsize >= PATH_MAX); 2394edf8e2afSMika Westerberg 2395edf8e2afSMika Westerberg if (gettimeofday(&tv, NULL) < 0) { 2396edf8e2afSMika Westerberg (void) fprintf(stderr, "unable to get current timestamp: %s", 2397edf8e2afSMika Westerberg strerror(errno)); 2398edf8e2afSMika Westerberg return (-1); 2399edf8e2afSMika Westerberg } 2400edf8e2afSMika Westerberg 2401edf8e2afSMika Westerberg filename = strdup(ts->bprm->filename); 2402edf8e2afSMika Westerberg base_filename = strdup(basename(filename)); 2403edf8e2afSMika Westerberg (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", 2404edf8e2afSMika Westerberg localtime_r(&tv.tv_sec, &tm)); 2405edf8e2afSMika Westerberg (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", 2406edf8e2afSMika Westerberg base_filename, timestamp, (int)getpid()); 2407edf8e2afSMika Westerberg free(base_filename); 2408edf8e2afSMika Westerberg free(filename); 2409edf8e2afSMika Westerberg 2410edf8e2afSMika Westerberg return (0); 2411edf8e2afSMika Westerberg } 2412edf8e2afSMika Westerberg 2413edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size) 2414edf8e2afSMika Westerberg { 2415edf8e2afSMika Westerberg const char *bufp = (const char *)ptr; 2416edf8e2afSMika Westerberg ssize_t bytes_written, bytes_left; 2417edf8e2afSMika Westerberg struct rlimit dumpsize; 2418edf8e2afSMika Westerberg off_t pos; 2419edf8e2afSMika Westerberg 2420edf8e2afSMika Westerberg bytes_written = 0; 2421edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 2422edf8e2afSMika Westerberg if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { 2423edf8e2afSMika Westerberg if (errno == ESPIPE) { /* not a seekable stream */ 2424edf8e2afSMika Westerberg bytes_left = size; 2425edf8e2afSMika Westerberg } else { 2426edf8e2afSMika Westerberg return pos; 2427edf8e2afSMika Westerberg } 2428edf8e2afSMika Westerberg } else { 2429edf8e2afSMika Westerberg if (dumpsize.rlim_cur <= pos) { 2430edf8e2afSMika Westerberg return -1; 2431edf8e2afSMika Westerberg } else if (dumpsize.rlim_cur == RLIM_INFINITY) { 2432edf8e2afSMika Westerberg bytes_left = size; 2433edf8e2afSMika Westerberg } else { 2434edf8e2afSMika Westerberg size_t limit_left=dumpsize.rlim_cur - pos; 2435edf8e2afSMika Westerberg bytes_left = limit_left >= size ? size : limit_left ; 2436edf8e2afSMika Westerberg } 2437edf8e2afSMika Westerberg } 2438edf8e2afSMika Westerberg 2439edf8e2afSMika Westerberg /* 2440edf8e2afSMika Westerberg * In normal conditions, single write(2) should do but 2441edf8e2afSMika Westerberg * in case of socket etc. this mechanism is more portable. 2442edf8e2afSMika Westerberg */ 2443edf8e2afSMika Westerberg do { 2444edf8e2afSMika Westerberg bytes_written = write(fd, bufp, bytes_left); 2445edf8e2afSMika Westerberg if (bytes_written < 0) { 2446edf8e2afSMika Westerberg if (errno == EINTR) 2447edf8e2afSMika Westerberg continue; 2448edf8e2afSMika Westerberg return (-1); 2449edf8e2afSMika Westerberg } else if (bytes_written == 0) { /* eof */ 2450edf8e2afSMika Westerberg return (-1); 2451edf8e2afSMika Westerberg } 2452edf8e2afSMika Westerberg bufp += bytes_written; 2453edf8e2afSMika Westerberg bytes_left -= bytes_written; 2454edf8e2afSMika Westerberg } while (bytes_left > 0); 2455edf8e2afSMika Westerberg 2456edf8e2afSMika Westerberg return (0); 2457edf8e2afSMika Westerberg } 2458edf8e2afSMika Westerberg 2459edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd) 2460edf8e2afSMika Westerberg { 2461edf8e2afSMika Westerberg struct elf_note en; 2462edf8e2afSMika Westerberg 2463edf8e2afSMika Westerberg en.n_namesz = men->namesz; 2464edf8e2afSMika Westerberg en.n_type = men->type; 2465edf8e2afSMika Westerberg en.n_descsz = men->datasz; 2466edf8e2afSMika Westerberg 2467edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2468edf8e2afSMika Westerberg bswap_note(&en); 2469edf8e2afSMika Westerberg #endif 2470edf8e2afSMika Westerberg 2471edf8e2afSMika Westerberg if (dump_write(fd, &en, sizeof(en)) != 0) 2472edf8e2afSMika Westerberg return (-1); 2473edf8e2afSMika Westerberg if (dump_write(fd, men->name, men->namesz_rounded) != 0) 2474edf8e2afSMika Westerberg return (-1); 2475edf8e2afSMika Westerberg if (dump_write(fd, men->data, men->datasz) != 0) 2476edf8e2afSMika Westerberg return (-1); 2477edf8e2afSMika Westerberg 2478edf8e2afSMika Westerberg return (0); 2479edf8e2afSMika Westerberg } 2480edf8e2afSMika Westerberg 2481edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *info, const CPUState *env) 2482edf8e2afSMika Westerberg { 2483edf8e2afSMika Westerberg TaskState *ts = (TaskState *)env->opaque; 2484edf8e2afSMika Westerberg struct elf_thread_status *ets; 2485edf8e2afSMika Westerberg 2486edf8e2afSMika Westerberg ets = qemu_mallocz(sizeof (*ets)); 2487edf8e2afSMika Westerberg ets->num_notes = 1; /* only prstatus is dumped */ 2488edf8e2afSMika Westerberg fill_prstatus(&ets->prstatus, ts, 0); 2489edf8e2afSMika Westerberg elf_core_copy_regs(&ets->prstatus.pr_reg, env); 2490edf8e2afSMika Westerberg fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus), 2491edf8e2afSMika Westerberg &ets->prstatus); 2492edf8e2afSMika Westerberg 249372cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link); 2494edf8e2afSMika Westerberg 2495edf8e2afSMika Westerberg info->notes_size += note_size(&ets->notes[0]); 2496edf8e2afSMika Westerberg } 2497edf8e2afSMika Westerberg 2498edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info, 2499edf8e2afSMika Westerberg long signr, const CPUState *env) 2500edf8e2afSMika Westerberg { 2501edf8e2afSMika Westerberg #define NUMNOTES 3 2502edf8e2afSMika Westerberg CPUState *cpu = NULL; 2503edf8e2afSMika Westerberg TaskState *ts = (TaskState *)env->opaque; 2504edf8e2afSMika Westerberg int i; 2505edf8e2afSMika Westerberg 2506edf8e2afSMika Westerberg (void) memset(info, 0, sizeof (*info)); 2507edf8e2afSMika Westerberg 250872cf2d4fSBlue Swirl QTAILQ_INIT(&info->thread_list); 2509edf8e2afSMika Westerberg 2510edf8e2afSMika Westerberg info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote)); 2511edf8e2afSMika Westerberg if (info->notes == NULL) 2512edf8e2afSMika Westerberg return (-ENOMEM); 2513edf8e2afSMika Westerberg info->prstatus = qemu_mallocz(sizeof (*info->prstatus)); 2514edf8e2afSMika Westerberg if (info->prstatus == NULL) 2515edf8e2afSMika Westerberg return (-ENOMEM); 2516edf8e2afSMika Westerberg info->psinfo = qemu_mallocz(sizeof (*info->psinfo)); 2517edf8e2afSMika Westerberg if (info->prstatus == NULL) 2518edf8e2afSMika Westerberg return (-ENOMEM); 2519edf8e2afSMika Westerberg 2520edf8e2afSMika Westerberg /* 2521edf8e2afSMika Westerberg * First fill in status (and registers) of current thread 2522edf8e2afSMika Westerberg * including process info & aux vector. 2523edf8e2afSMika Westerberg */ 2524edf8e2afSMika Westerberg fill_prstatus(info->prstatus, ts, signr); 2525edf8e2afSMika Westerberg elf_core_copy_regs(&info->prstatus->pr_reg, env); 2526edf8e2afSMika Westerberg fill_note(&info->notes[0], "CORE", NT_PRSTATUS, 2527edf8e2afSMika Westerberg sizeof (*info->prstatus), info->prstatus); 2528edf8e2afSMika Westerberg fill_psinfo(info->psinfo, ts); 2529edf8e2afSMika Westerberg fill_note(&info->notes[1], "CORE", NT_PRPSINFO, 2530edf8e2afSMika Westerberg sizeof (*info->psinfo), info->psinfo); 2531edf8e2afSMika Westerberg fill_auxv_note(&info->notes[2], ts); 2532edf8e2afSMika Westerberg info->numnote = 3; 2533edf8e2afSMika Westerberg 2534edf8e2afSMika Westerberg info->notes_size = 0; 2535edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 2536edf8e2afSMika Westerberg info->notes_size += note_size(&info->notes[i]); 2537edf8e2afSMika Westerberg 2538edf8e2afSMika Westerberg /* read and fill status of all threads */ 2539edf8e2afSMika Westerberg cpu_list_lock(); 2540edf8e2afSMika Westerberg for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { 2541edf8e2afSMika Westerberg if (cpu == thread_env) 2542edf8e2afSMika Westerberg continue; 2543edf8e2afSMika Westerberg fill_thread_info(info, cpu); 2544edf8e2afSMika Westerberg } 2545edf8e2afSMika Westerberg cpu_list_unlock(); 2546edf8e2afSMika Westerberg 2547edf8e2afSMika Westerberg return (0); 2548edf8e2afSMika Westerberg } 2549edf8e2afSMika Westerberg 2550edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info) 2551edf8e2afSMika Westerberg { 2552edf8e2afSMika Westerberg struct elf_thread_status *ets; 2553edf8e2afSMika Westerberg 255472cf2d4fSBlue Swirl while (!QTAILQ_EMPTY(&info->thread_list)) { 255572cf2d4fSBlue Swirl ets = QTAILQ_FIRST(&info->thread_list); 255672cf2d4fSBlue Swirl QTAILQ_REMOVE(&info->thread_list, ets, ets_link); 2557edf8e2afSMika Westerberg qemu_free(ets); 2558edf8e2afSMika Westerberg } 2559edf8e2afSMika Westerberg 2560edf8e2afSMika Westerberg qemu_free(info->prstatus); 2561edf8e2afSMika Westerberg qemu_free(info->psinfo); 2562edf8e2afSMika Westerberg qemu_free(info->notes); 2563edf8e2afSMika Westerberg } 2564edf8e2afSMika Westerberg 2565edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd) 2566edf8e2afSMika Westerberg { 2567edf8e2afSMika Westerberg struct elf_thread_status *ets; 2568edf8e2afSMika Westerberg int i, error = 0; 2569edf8e2afSMika Westerberg 2570edf8e2afSMika Westerberg /* write prstatus, psinfo and auxv for current thread */ 2571edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 2572edf8e2afSMika Westerberg if ((error = write_note(&info->notes[i], fd)) != 0) 2573edf8e2afSMika Westerberg return (error); 2574edf8e2afSMika Westerberg 2575edf8e2afSMika Westerberg /* write prstatus for each thread */ 2576edf8e2afSMika Westerberg for (ets = info->thread_list.tqh_first; ets != NULL; 2577edf8e2afSMika Westerberg ets = ets->ets_link.tqe_next) { 2578edf8e2afSMika Westerberg if ((error = write_note(&ets->notes[0], fd)) != 0) 2579edf8e2afSMika Westerberg return (error); 2580edf8e2afSMika Westerberg } 2581edf8e2afSMika Westerberg 2582edf8e2afSMika Westerberg return (0); 2583edf8e2afSMika Westerberg } 2584edf8e2afSMika Westerberg 2585edf8e2afSMika Westerberg /* 2586edf8e2afSMika Westerberg * Write out ELF coredump. 2587edf8e2afSMika Westerberg * 2588edf8e2afSMika Westerberg * See documentation of ELF object file format in: 2589edf8e2afSMika Westerberg * http://www.caldera.com/developers/devspecs/gabi41.pdf 2590edf8e2afSMika Westerberg * 2591edf8e2afSMika Westerberg * Coredump format in linux is following: 2592edf8e2afSMika Westerberg * 2593edf8e2afSMika Westerberg * 0 +----------------------+ \ 2594edf8e2afSMika Westerberg * | ELF header | ET_CORE | 2595edf8e2afSMika Westerberg * +----------------------+ | 2596edf8e2afSMika Westerberg * | ELF program headers | |--- headers 2597edf8e2afSMika Westerberg * | - NOTE section | | 2598edf8e2afSMika Westerberg * | - PT_LOAD sections | | 2599edf8e2afSMika Westerberg * +----------------------+ / 2600edf8e2afSMika Westerberg * | NOTEs: | 2601edf8e2afSMika Westerberg * | - NT_PRSTATUS | 2602edf8e2afSMika Westerberg * | - NT_PRSINFO | 2603edf8e2afSMika Westerberg * | - NT_AUXV | 2604edf8e2afSMika Westerberg * +----------------------+ <-- aligned to target page 2605edf8e2afSMika Westerberg * | Process memory dump | 2606edf8e2afSMika Westerberg * : : 2607edf8e2afSMika Westerberg * . . 2608edf8e2afSMika Westerberg * : : 2609edf8e2afSMika Westerberg * | | 2610edf8e2afSMika Westerberg * +----------------------+ 2611edf8e2afSMika Westerberg * 2612edf8e2afSMika Westerberg * NT_PRSTATUS -> struct elf_prstatus (per thread) 2613edf8e2afSMika Westerberg * NT_PRSINFO -> struct elf_prpsinfo 2614edf8e2afSMika Westerberg * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()). 2615edf8e2afSMika Westerberg * 2616edf8e2afSMika Westerberg * Format follows System V format as close as possible. Current 2617edf8e2afSMika Westerberg * version limitations are as follows: 2618edf8e2afSMika Westerberg * - no floating point registers are dumped 2619edf8e2afSMika Westerberg * 2620edf8e2afSMika Westerberg * Function returns 0 in case of success, negative errno otherwise. 2621edf8e2afSMika Westerberg * 2622edf8e2afSMika Westerberg * TODO: make this work also during runtime: it should be 2623edf8e2afSMika Westerberg * possible to force coredump from running process and then 2624edf8e2afSMika Westerberg * continue processing. For example qemu could set up SIGUSR2 2625edf8e2afSMika Westerberg * handler (provided that target process haven't registered 2626edf8e2afSMika Westerberg * handler for that) that does the dump when signal is received. 2627edf8e2afSMika Westerberg */ 2628edf8e2afSMika Westerberg static int elf_core_dump(int signr, const CPUState *env) 2629edf8e2afSMika Westerberg { 2630edf8e2afSMika Westerberg const TaskState *ts = (const TaskState *)env->opaque; 2631edf8e2afSMika Westerberg struct vm_area_struct *vma = NULL; 2632edf8e2afSMika Westerberg char corefile[PATH_MAX]; 2633edf8e2afSMika Westerberg struct elf_note_info info; 2634edf8e2afSMika Westerberg struct elfhdr elf; 2635edf8e2afSMika Westerberg struct elf_phdr phdr; 2636edf8e2afSMika Westerberg struct rlimit dumpsize; 2637edf8e2afSMika Westerberg struct mm_struct *mm = NULL; 2638edf8e2afSMika Westerberg off_t offset = 0, data_offset = 0; 2639edf8e2afSMika Westerberg int segs = 0; 2640edf8e2afSMika Westerberg int fd = -1; 2641edf8e2afSMika Westerberg 2642edf8e2afSMika Westerberg errno = 0; 2643edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 2644edf8e2afSMika Westerberg if (dumpsize.rlim_cur == 0) 2645edf8e2afSMika Westerberg return 0; 2646edf8e2afSMika Westerberg 2647edf8e2afSMika Westerberg if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0) 2648edf8e2afSMika Westerberg return (-errno); 2649edf8e2afSMika Westerberg 2650edf8e2afSMika Westerberg if ((fd = open(corefile, O_WRONLY | O_CREAT, 2651edf8e2afSMika Westerberg S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) 2652edf8e2afSMika Westerberg return (-errno); 2653edf8e2afSMika Westerberg 2654edf8e2afSMika Westerberg /* 2655edf8e2afSMika Westerberg * Walk through target process memory mappings and 2656edf8e2afSMika Westerberg * set up structure containing this information. After 2657edf8e2afSMika Westerberg * this point vma_xxx functions can be used. 2658edf8e2afSMika Westerberg */ 2659edf8e2afSMika Westerberg if ((mm = vma_init()) == NULL) 2660edf8e2afSMika Westerberg goto out; 2661edf8e2afSMika Westerberg 2662edf8e2afSMika Westerberg walk_memory_regions(mm, vma_walker); 2663edf8e2afSMika Westerberg segs = vma_get_mapping_count(mm); 2664edf8e2afSMika Westerberg 2665edf8e2afSMika Westerberg /* 2666edf8e2afSMika Westerberg * Construct valid coredump ELF header. We also 2667edf8e2afSMika Westerberg * add one more segment for notes. 2668edf8e2afSMika Westerberg */ 2669edf8e2afSMika Westerberg fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0); 2670edf8e2afSMika Westerberg if (dump_write(fd, &elf, sizeof (elf)) != 0) 2671edf8e2afSMika Westerberg goto out; 2672edf8e2afSMika Westerberg 2673edf8e2afSMika Westerberg /* fill in in-memory version of notes */ 2674edf8e2afSMika Westerberg if (fill_note_info(&info, signr, env) < 0) 2675edf8e2afSMika Westerberg goto out; 2676edf8e2afSMika Westerberg 2677edf8e2afSMika Westerberg offset += sizeof (elf); /* elf header */ 2678edf8e2afSMika Westerberg offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */ 2679edf8e2afSMika Westerberg 2680edf8e2afSMika Westerberg /* write out notes program header */ 2681edf8e2afSMika Westerberg fill_elf_note_phdr(&phdr, info.notes_size, offset); 2682edf8e2afSMika Westerberg 2683edf8e2afSMika Westerberg offset += info.notes_size; 2684edf8e2afSMika Westerberg if (dump_write(fd, &phdr, sizeof (phdr)) != 0) 2685edf8e2afSMika Westerberg goto out; 2686edf8e2afSMika Westerberg 2687edf8e2afSMika Westerberg /* 2688edf8e2afSMika Westerberg * ELF specification wants data to start at page boundary so 2689edf8e2afSMika Westerberg * we align it here. 2690edf8e2afSMika Westerberg */ 2691edf8e2afSMika Westerberg offset = roundup(offset, ELF_EXEC_PAGESIZE); 2692edf8e2afSMika Westerberg 2693edf8e2afSMika Westerberg /* 2694edf8e2afSMika Westerberg * Write program headers for memory regions mapped in 2695edf8e2afSMika Westerberg * the target process. 2696edf8e2afSMika Westerberg */ 2697edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 2698edf8e2afSMika Westerberg (void) memset(&phdr, 0, sizeof (phdr)); 2699edf8e2afSMika Westerberg 2700edf8e2afSMika Westerberg phdr.p_type = PT_LOAD; 2701edf8e2afSMika Westerberg phdr.p_offset = offset; 2702edf8e2afSMika Westerberg phdr.p_vaddr = vma->vma_start; 2703edf8e2afSMika Westerberg phdr.p_paddr = 0; 2704edf8e2afSMika Westerberg phdr.p_filesz = vma_dump_size(vma); 2705edf8e2afSMika Westerberg offset += phdr.p_filesz; 2706edf8e2afSMika Westerberg phdr.p_memsz = vma->vma_end - vma->vma_start; 2707edf8e2afSMika Westerberg phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0; 2708edf8e2afSMika Westerberg if (vma->vma_flags & PROT_WRITE) 2709edf8e2afSMika Westerberg phdr.p_flags |= PF_W; 2710edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) 2711edf8e2afSMika Westerberg phdr.p_flags |= PF_X; 2712edf8e2afSMika Westerberg phdr.p_align = ELF_EXEC_PAGESIZE; 2713edf8e2afSMika Westerberg 2714edf8e2afSMika Westerberg dump_write(fd, &phdr, sizeof (phdr)); 2715edf8e2afSMika Westerberg } 2716edf8e2afSMika Westerberg 2717edf8e2afSMika Westerberg /* 2718edf8e2afSMika Westerberg * Next we write notes just after program headers. No 2719edf8e2afSMika Westerberg * alignment needed here. 2720edf8e2afSMika Westerberg */ 2721edf8e2afSMika Westerberg if (write_note_info(&info, fd) < 0) 2722edf8e2afSMika Westerberg goto out; 2723edf8e2afSMika Westerberg 2724edf8e2afSMika Westerberg /* align data to page boundary */ 2725edf8e2afSMika Westerberg data_offset = lseek(fd, 0, SEEK_CUR); 2726edf8e2afSMika Westerberg data_offset = TARGET_PAGE_ALIGN(data_offset); 2727edf8e2afSMika Westerberg if (lseek(fd, data_offset, SEEK_SET) != data_offset) 2728edf8e2afSMika Westerberg goto out; 2729edf8e2afSMika Westerberg 2730edf8e2afSMika Westerberg /* 2731edf8e2afSMika Westerberg * Finally we can dump process memory into corefile as well. 2732edf8e2afSMika Westerberg */ 2733edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 2734edf8e2afSMika Westerberg abi_ulong addr; 2735edf8e2afSMika Westerberg abi_ulong end; 2736edf8e2afSMika Westerberg 2737edf8e2afSMika Westerberg end = vma->vma_start + vma_dump_size(vma); 2738edf8e2afSMika Westerberg 2739edf8e2afSMika Westerberg for (addr = vma->vma_start; addr < end; 2740edf8e2afSMika Westerberg addr += TARGET_PAGE_SIZE) { 2741edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 2742edf8e2afSMika Westerberg int error; 2743edf8e2afSMika Westerberg 2744edf8e2afSMika Westerberg /* 2745edf8e2afSMika Westerberg * Read in page from target process memory and 2746edf8e2afSMika Westerberg * write it to coredump file. 2747edf8e2afSMika Westerberg */ 2748edf8e2afSMika Westerberg error = copy_from_user(page, addr, sizeof (page)); 2749edf8e2afSMika Westerberg if (error != 0) { 275049995e17SAurelien Jarno (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n", 2751edf8e2afSMika Westerberg addr); 2752edf8e2afSMika Westerberg errno = -error; 2753edf8e2afSMika Westerberg goto out; 2754edf8e2afSMika Westerberg } 2755edf8e2afSMika Westerberg if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0) 2756edf8e2afSMika Westerberg goto out; 2757edf8e2afSMika Westerberg } 2758edf8e2afSMika Westerberg } 2759edf8e2afSMika Westerberg 2760edf8e2afSMika Westerberg out: 2761edf8e2afSMika Westerberg free_note_info(&info); 2762edf8e2afSMika Westerberg if (mm != NULL) 2763edf8e2afSMika Westerberg vma_delete(mm); 2764edf8e2afSMika Westerberg (void) close(fd); 2765edf8e2afSMika Westerberg 2766edf8e2afSMika Westerberg if (errno != 0) 2767edf8e2afSMika Westerberg return (-errno); 2768edf8e2afSMika Westerberg return (0); 2769edf8e2afSMika Westerberg } 2770edf8e2afSMika Westerberg 2771edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 2772edf8e2afSMika Westerberg 277331e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd) 277431e31b8aSbellard { 277531e31b8aSbellard printf("a.out interpreter not yet supported\n"); 277631e31b8aSbellard return(0); 277731e31b8aSbellard } 277831e31b8aSbellard 2779e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) 2780e5fe0c52Spbrook { 2781e5fe0c52Spbrook init_thread(regs, infop); 2782e5fe0c52Spbrook } 2783