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 { 515992f48a0Sblueswir1 abi_ulong pos = infop->start_stack; 516992f48a0Sblueswir1 abi_ulong tmp; 517e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 518992f48a0Sblueswir1 abi_ulong entry, toc; 51984409ddbSj_mayer #endif 520e5fe0c52Spbrook 52167867308Sbellard _regs->gpr[1] = infop->start_stack; 522e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 52384409ddbSj_mayer entry = ldq_raw(infop->entry) + infop->load_addr; 52484409ddbSj_mayer toc = ldq_raw(infop->entry + 8) + infop->load_addr; 52584409ddbSj_mayer _regs->gpr[2] = toc; 52684409ddbSj_mayer infop->entry = entry; 52784409ddbSj_mayer #endif 52867867308Sbellard _regs->nip = infop->entry; 529e5fe0c52Spbrook /* Note that isn't exactly what regular kernel does 530e5fe0c52Spbrook * but this is what the ABI wants and is needed to allow 531e5fe0c52Spbrook * execution of PPC BSD programs. 532e5fe0c52Spbrook */ 5332f619698Sbellard /* FIXME - what to for failure of get_user()? */ 5342f619698Sbellard get_user_ual(_regs->gpr[3], pos); 535992f48a0Sblueswir1 pos += sizeof(abi_ulong); 536e5fe0c52Spbrook _regs->gpr[4] = pos; 537992f48a0Sblueswir1 for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong)) 538e5fe0c52Spbrook tmp = ldl(pos); 539e5fe0c52Spbrook _regs->gpr[5] = pos; 54067867308Sbellard } 54167867308Sbellard 542e2f3e741SNathan Froyd /* See linux kernel: arch/powerpc/include/asm/elf.h. */ 543e2f3e741SNathan Froyd #define ELF_NREG 48 544e2f3e741SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 545e2f3e741SNathan Froyd 546e2f3e741SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 547e2f3e741SNathan Froyd { 548e2f3e741SNathan Froyd int i; 549e2f3e741SNathan Froyd target_ulong ccr = 0; 550e2f3e741SNathan Froyd 551e2f3e741SNathan Froyd for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { 552e2f3e741SNathan Froyd (*regs)[i] = tswapl(env->gpr[i]); 553e2f3e741SNathan Froyd } 554e2f3e741SNathan Froyd 555e2f3e741SNathan Froyd (*regs)[32] = tswapl(env->nip); 556e2f3e741SNathan Froyd (*regs)[33] = tswapl(env->msr); 557e2f3e741SNathan Froyd (*regs)[35] = tswapl(env->ctr); 558e2f3e741SNathan Froyd (*regs)[36] = tswapl(env->lr); 559e2f3e741SNathan Froyd (*regs)[37] = tswapl(env->xer); 560e2f3e741SNathan Froyd 561e2f3e741SNathan Froyd for (i = 0; i < ARRAY_SIZE(env->crf); i++) { 562e2f3e741SNathan Froyd ccr |= env->crf[i] << (32 - ((i + 1) * 4)); 563e2f3e741SNathan Froyd } 564e2f3e741SNathan Froyd (*regs)[38] = tswapl(ccr); 565e2f3e741SNathan Froyd } 566e2f3e741SNathan Froyd 567e2f3e741SNathan Froyd #define USE_ELF_CORE_DUMP 56867867308Sbellard #define ELF_EXEC_PAGESIZE 4096 56967867308Sbellard 57067867308Sbellard #endif 57167867308Sbellard 572048f6b4dSbellard #ifdef TARGET_MIPS 573048f6b4dSbellard 574048f6b4dSbellard #define ELF_START_MMAP 0x80000000 575048f6b4dSbellard 576048f6b4dSbellard #define elf_check_arch(x) ( (x) == EM_MIPS ) 577048f6b4dSbellard 578388bb21aSths #ifdef TARGET_MIPS64 579388bb21aSths #define ELF_CLASS ELFCLASS64 580388bb21aSths #else 581048f6b4dSbellard #define ELF_CLASS ELFCLASS32 582388bb21aSths #endif 583048f6b4dSbellard #ifdef TARGET_WORDS_BIGENDIAN 584048f6b4dSbellard #define ELF_DATA ELFDATA2MSB 585048f6b4dSbellard #else 586048f6b4dSbellard #define ELF_DATA ELFDATA2LSB 587048f6b4dSbellard #endif 588048f6b4dSbellard #define ELF_ARCH EM_MIPS 589048f6b4dSbellard 590048f6b4dSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 591048f6b4dSbellard { 592623a930eSths regs->cp0_status = 2 << CP0St_KSU; 593048f6b4dSbellard regs->cp0_epc = infop->entry; 594048f6b4dSbellard regs->regs[29] = infop->start_stack; 595048f6b4dSbellard } 596048f6b4dSbellard 59751e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/elf.h. */ 59851e52606SNathan Froyd #define ELF_NREG 45 59951e52606SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 60051e52606SNathan Froyd 60151e52606SNathan Froyd /* See linux kernel: arch/mips/include/asm/reg.h. */ 60251e52606SNathan Froyd enum { 60351e52606SNathan Froyd #ifdef TARGET_MIPS64 60451e52606SNathan Froyd TARGET_EF_R0 = 0, 60551e52606SNathan Froyd #else 60651e52606SNathan Froyd TARGET_EF_R0 = 6, 60751e52606SNathan Froyd #endif 60851e52606SNathan Froyd TARGET_EF_R26 = TARGET_EF_R0 + 26, 60951e52606SNathan Froyd TARGET_EF_R27 = TARGET_EF_R0 + 27, 61051e52606SNathan Froyd TARGET_EF_LO = TARGET_EF_R0 + 32, 61151e52606SNathan Froyd TARGET_EF_HI = TARGET_EF_R0 + 33, 61251e52606SNathan Froyd TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34, 61351e52606SNathan Froyd TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35, 61451e52606SNathan Froyd TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36, 61551e52606SNathan Froyd TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37 61651e52606SNathan Froyd }; 61751e52606SNathan Froyd 61851e52606SNathan Froyd /* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */ 61951e52606SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 62051e52606SNathan Froyd { 62151e52606SNathan Froyd int i; 62251e52606SNathan Froyd 62351e52606SNathan Froyd for (i = 0; i < TARGET_EF_R0; i++) { 62451e52606SNathan Froyd (*regs)[i] = 0; 62551e52606SNathan Froyd } 62651e52606SNathan Froyd (*regs)[TARGET_EF_R0] = 0; 62751e52606SNathan Froyd 62851e52606SNathan Froyd for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { 62951e52606SNathan Froyd (*regs)[TARGET_EF_R0 + i] = tswapl(env->active_tc.gpr[i]); 63051e52606SNathan Froyd } 63151e52606SNathan Froyd 63251e52606SNathan Froyd (*regs)[TARGET_EF_R26] = 0; 63351e52606SNathan Froyd (*regs)[TARGET_EF_R27] = 0; 63451e52606SNathan Froyd (*regs)[TARGET_EF_LO] = tswapl(env->active_tc.LO[0]); 63551e52606SNathan Froyd (*regs)[TARGET_EF_HI] = tswapl(env->active_tc.HI[0]); 63651e52606SNathan Froyd (*regs)[TARGET_EF_CP0_EPC] = tswapl(env->active_tc.PC); 63751e52606SNathan Froyd (*regs)[TARGET_EF_CP0_BADVADDR] = tswapl(env->CP0_BadVAddr); 63851e52606SNathan Froyd (*regs)[TARGET_EF_CP0_STATUS] = tswapl(env->CP0_Status); 63951e52606SNathan Froyd (*regs)[TARGET_EF_CP0_CAUSE] = tswapl(env->CP0_Cause); 64051e52606SNathan Froyd } 64151e52606SNathan Froyd 64251e52606SNathan Froyd #define USE_ELF_CORE_DUMP 643388bb21aSths #define ELF_EXEC_PAGESIZE 4096 644388bb21aSths 645048f6b4dSbellard #endif /* TARGET_MIPS */ 646048f6b4dSbellard 647b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 648b779e29eSEdgar E. Iglesias 649b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000 650b779e29eSEdgar E. Iglesias 651b779e29eSEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE ) 652b779e29eSEdgar E. Iglesias 653b779e29eSEdgar E. Iglesias #define ELF_CLASS ELFCLASS32 654b779e29eSEdgar E. Iglesias #define ELF_DATA ELFDATA2MSB 6550ddbc96eSMike Frysinger #define ELF_ARCH EM_XILINX_MICROBLAZE 656b779e29eSEdgar E. Iglesias 657b779e29eSEdgar E. Iglesias static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 658b779e29eSEdgar E. Iglesias { 659b779e29eSEdgar E. Iglesias regs->pc = infop->entry; 660b779e29eSEdgar E. Iglesias regs->r1 = infop->start_stack; 661b779e29eSEdgar E. Iglesias 662b779e29eSEdgar E. Iglesias } 663b779e29eSEdgar E. Iglesias 664b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE 4096 665b779e29eSEdgar E. Iglesias 666b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */ 667b779e29eSEdgar E. Iglesias 668fdf9b3e8Sbellard #ifdef TARGET_SH4 669fdf9b3e8Sbellard 670fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000 671fdf9b3e8Sbellard 672fdf9b3e8Sbellard #define elf_check_arch(x) ( (x) == EM_SH ) 673fdf9b3e8Sbellard 674fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32 675fdf9b3e8Sbellard #define ELF_DATA ELFDATA2LSB 676fdf9b3e8Sbellard #define ELF_ARCH EM_SH 677fdf9b3e8Sbellard 678fdf9b3e8Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 679fdf9b3e8Sbellard { 680fdf9b3e8Sbellard /* Check other registers XXXXX */ 681fdf9b3e8Sbellard regs->pc = infop->entry; 682072ae847Sths regs->regs[15] = infop->start_stack; 683fdf9b3e8Sbellard } 684fdf9b3e8Sbellard 6857631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/elf.h. */ 6867631c97eSNathan Froyd #define ELF_NREG 23 6877631c97eSNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 6887631c97eSNathan Froyd 6897631c97eSNathan Froyd /* See linux kernel: arch/sh/include/asm/ptrace.h. */ 6907631c97eSNathan Froyd enum { 6917631c97eSNathan Froyd TARGET_REG_PC = 16, 6927631c97eSNathan Froyd TARGET_REG_PR = 17, 6937631c97eSNathan Froyd TARGET_REG_SR = 18, 6947631c97eSNathan Froyd TARGET_REG_GBR = 19, 6957631c97eSNathan Froyd TARGET_REG_MACH = 20, 6967631c97eSNathan Froyd TARGET_REG_MACL = 21, 6977631c97eSNathan Froyd TARGET_REG_SYSCALL = 22 6987631c97eSNathan Froyd }; 6997631c97eSNathan Froyd 7007631c97eSNathan Froyd static inline void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 7017631c97eSNathan Froyd { 7027631c97eSNathan Froyd int i; 7037631c97eSNathan Froyd 7047631c97eSNathan Froyd for (i = 0; i < 16; i++) { 7057631c97eSNathan Froyd (*regs[i]) = tswapl(env->gregs[i]); 7067631c97eSNathan Froyd } 7077631c97eSNathan Froyd 7087631c97eSNathan Froyd (*regs)[TARGET_REG_PC] = tswapl(env->pc); 7097631c97eSNathan Froyd (*regs)[TARGET_REG_PR] = tswapl(env->pr); 7107631c97eSNathan Froyd (*regs)[TARGET_REG_SR] = tswapl(env->sr); 7117631c97eSNathan Froyd (*regs)[TARGET_REG_GBR] = tswapl(env->gbr); 7127631c97eSNathan Froyd (*regs)[TARGET_REG_MACH] = tswapl(env->mach); 7137631c97eSNathan Froyd (*regs)[TARGET_REG_MACL] = tswapl(env->macl); 7147631c97eSNathan Froyd (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */ 7157631c97eSNathan Froyd } 7167631c97eSNathan Froyd 7177631c97eSNathan Froyd #define USE_ELF_CORE_DUMP 718fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE 4096 719fdf9b3e8Sbellard 720fdf9b3e8Sbellard #endif 721fdf9b3e8Sbellard 72248733d19Sths #ifdef TARGET_CRIS 72348733d19Sths 72448733d19Sths #define ELF_START_MMAP 0x80000000 72548733d19Sths 72648733d19Sths #define elf_check_arch(x) ( (x) == EM_CRIS ) 72748733d19Sths 72848733d19Sths #define ELF_CLASS ELFCLASS32 72948733d19Sths #define ELF_DATA ELFDATA2LSB 73048733d19Sths #define ELF_ARCH EM_CRIS 73148733d19Sths 73248733d19Sths static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 73348733d19Sths { 73448733d19Sths regs->erp = infop->entry; 73548733d19Sths } 73648733d19Sths 73748733d19Sths #define ELF_EXEC_PAGESIZE 8192 73848733d19Sths 73948733d19Sths #endif 74048733d19Sths 741e6e5906bSpbrook #ifdef TARGET_M68K 742e6e5906bSpbrook 743e6e5906bSpbrook #define ELF_START_MMAP 0x80000000 744e6e5906bSpbrook 745e6e5906bSpbrook #define elf_check_arch(x) ( (x) == EM_68K ) 746e6e5906bSpbrook 747e6e5906bSpbrook #define ELF_CLASS ELFCLASS32 748e6e5906bSpbrook #define ELF_DATA ELFDATA2MSB 749e6e5906bSpbrook #define ELF_ARCH EM_68K 750e6e5906bSpbrook 751e6e5906bSpbrook /* ??? Does this need to do anything? 752e6e5906bSpbrook #define ELF_PLAT_INIT(_r) */ 753e6e5906bSpbrook 754e6e5906bSpbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 755e6e5906bSpbrook { 756e6e5906bSpbrook regs->usp = infop->start_stack; 757e6e5906bSpbrook regs->sr = 0; 758e6e5906bSpbrook regs->pc = infop->entry; 759e6e5906bSpbrook } 760e6e5906bSpbrook 7617a93cc55SNathan Froyd /* See linux kernel: arch/m68k/include/asm/elf.h. */ 7627a93cc55SNathan Froyd #define ELF_NREG 20 7637a93cc55SNathan Froyd typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 7647a93cc55SNathan Froyd 7657a93cc55SNathan Froyd static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 7667a93cc55SNathan Froyd { 7677a93cc55SNathan Froyd (*regs)[0] = tswapl(env->dregs[1]); 7687a93cc55SNathan Froyd (*regs)[1] = tswapl(env->dregs[2]); 7697a93cc55SNathan Froyd (*regs)[2] = tswapl(env->dregs[3]); 7707a93cc55SNathan Froyd (*regs)[3] = tswapl(env->dregs[4]); 7717a93cc55SNathan Froyd (*regs)[4] = tswapl(env->dregs[5]); 7727a93cc55SNathan Froyd (*regs)[5] = tswapl(env->dregs[6]); 7737a93cc55SNathan Froyd (*regs)[6] = tswapl(env->dregs[7]); 7747a93cc55SNathan Froyd (*regs)[7] = tswapl(env->aregs[0]); 7757a93cc55SNathan Froyd (*regs)[8] = tswapl(env->aregs[1]); 7767a93cc55SNathan Froyd (*regs)[9] = tswapl(env->aregs[2]); 7777a93cc55SNathan Froyd (*regs)[10] = tswapl(env->aregs[3]); 7787a93cc55SNathan Froyd (*regs)[11] = tswapl(env->aregs[4]); 7797a93cc55SNathan Froyd (*regs)[12] = tswapl(env->aregs[5]); 7807a93cc55SNathan Froyd (*regs)[13] = tswapl(env->aregs[6]); 7817a93cc55SNathan Froyd (*regs)[14] = tswapl(env->dregs[0]); 7827a93cc55SNathan Froyd (*regs)[15] = tswapl(env->aregs[7]); 7837a93cc55SNathan Froyd (*regs)[16] = tswapl(env->dregs[0]); /* FIXME: orig_d0 */ 7847a93cc55SNathan Froyd (*regs)[17] = tswapl(env->sr); 7857a93cc55SNathan Froyd (*regs)[18] = tswapl(env->pc); 7867a93cc55SNathan Froyd (*regs)[19] = 0; /* FIXME: regs->format | regs->vector */ 7877a93cc55SNathan Froyd } 7887a93cc55SNathan Froyd 7897a93cc55SNathan Froyd #define USE_ELF_CORE_DUMP 790e6e5906bSpbrook #define ELF_EXEC_PAGESIZE 8192 791e6e5906bSpbrook 792e6e5906bSpbrook #endif 793e6e5906bSpbrook 7947a3148a9Sj_mayer #ifdef TARGET_ALPHA 7957a3148a9Sj_mayer 7967a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL) 7977a3148a9Sj_mayer 7987a3148a9Sj_mayer #define elf_check_arch(x) ( (x) == ELF_ARCH ) 7997a3148a9Sj_mayer 8007a3148a9Sj_mayer #define ELF_CLASS ELFCLASS64 8017a3148a9Sj_mayer #define ELF_DATA ELFDATA2MSB 8027a3148a9Sj_mayer #define ELF_ARCH EM_ALPHA 8037a3148a9Sj_mayer 8047a3148a9Sj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 8057a3148a9Sj_mayer { 8067a3148a9Sj_mayer regs->pc = infop->entry; 8077a3148a9Sj_mayer regs->ps = 8; 8087a3148a9Sj_mayer regs->usp = infop->start_stack; 8097a3148a9Sj_mayer } 8107a3148a9Sj_mayer 8117a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE 8192 8127a3148a9Sj_mayer 8137a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 8147a3148a9Sj_mayer 81515338fd7Sbellard #ifndef ELF_PLATFORM 81615338fd7Sbellard #define ELF_PLATFORM (NULL) 81715338fd7Sbellard #endif 81815338fd7Sbellard 81915338fd7Sbellard #ifndef ELF_HWCAP 82015338fd7Sbellard #define ELF_HWCAP 0 82115338fd7Sbellard #endif 82215338fd7Sbellard 823992f48a0Sblueswir1 #ifdef TARGET_ABI32 824cb33da57Sblueswir1 #undef ELF_CLASS 825992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32 826cb33da57Sblueswir1 #undef bswaptls 827cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr) 828cb33da57Sblueswir1 #endif 829cb33da57Sblueswir1 83031e31b8aSbellard #include "elf.h" 83109bfb054Sbellard 83209bfb054Sbellard struct exec 83309bfb054Sbellard { 83409bfb054Sbellard unsigned int a_info; /* Use macros N_MAGIC, etc for access */ 83509bfb054Sbellard unsigned int a_text; /* length of text, in bytes */ 83609bfb054Sbellard unsigned int a_data; /* length of data, in bytes */ 83709bfb054Sbellard unsigned int a_bss; /* length of uninitialized data area, in bytes */ 83809bfb054Sbellard unsigned int a_syms; /* length of symbol table data in file, in bytes */ 83909bfb054Sbellard unsigned int a_entry; /* start address */ 84009bfb054Sbellard unsigned int a_trsize; /* length of relocation info for text, in bytes */ 84109bfb054Sbellard unsigned int a_drsize; /* length of relocation info for data, in bytes */ 84209bfb054Sbellard }; 84309bfb054Sbellard 84409bfb054Sbellard 84509bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff) 84609bfb054Sbellard #define OMAGIC 0407 84709bfb054Sbellard #define NMAGIC 0410 84809bfb054Sbellard #define ZMAGIC 0413 84909bfb054Sbellard #define QMAGIC 0314 85009bfb054Sbellard 85109bfb054Sbellard /* max code+data+bss space allocated to elf interpreter */ 85209bfb054Sbellard #define INTERP_MAP_SIZE (32 * 1024 * 1024) 85309bfb054Sbellard 85409bfb054Sbellard /* max code+data+bss+brk space allocated to ET_DYN executables */ 85509bfb054Sbellard #define ET_DYN_MAP_SIZE (128 * 1024 * 1024) 85609bfb054Sbellard 85731e31b8aSbellard /* Necessary parameters */ 85854936004Sbellard #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE 85954936004Sbellard #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) 86054936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) 86131e31b8aSbellard 86231e31b8aSbellard #define INTERPRETER_NONE 0 86331e31b8aSbellard #define INTERPRETER_AOUT 1 86431e31b8aSbellard #define INTERPRETER_ELF 2 86531e31b8aSbellard 86615338fd7Sbellard #define DLINFO_ITEMS 12 86731e31b8aSbellard 86809bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) 86909bfb054Sbellard { 87009bfb054Sbellard memcpy(to, from, n); 87109bfb054Sbellard } 87209bfb054Sbellard 87331e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd); 87431e31b8aSbellard 87531e31b8aSbellard #ifdef BSWAP_NEEDED 87692a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr) 87731e31b8aSbellard { 87831e31b8aSbellard bswap16s(&ehdr->e_type); /* Object file type */ 87931e31b8aSbellard bswap16s(&ehdr->e_machine); /* Architecture */ 88031e31b8aSbellard bswap32s(&ehdr->e_version); /* Object file version */ 88192a31b1fSbellard bswaptls(&ehdr->e_entry); /* Entry point virtual address */ 88292a31b1fSbellard bswaptls(&ehdr->e_phoff); /* Program header table file offset */ 88392a31b1fSbellard bswaptls(&ehdr->e_shoff); /* Section header table file offset */ 88431e31b8aSbellard bswap32s(&ehdr->e_flags); /* Processor-specific flags */ 88531e31b8aSbellard bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ 88631e31b8aSbellard bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ 88731e31b8aSbellard bswap16s(&ehdr->e_phnum); /* Program header table entry count */ 88831e31b8aSbellard bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ 88931e31b8aSbellard bswap16s(&ehdr->e_shnum); /* Section header table entry count */ 89031e31b8aSbellard bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ 89131e31b8aSbellard } 89231e31b8aSbellard 89392a31b1fSbellard static void bswap_phdr(struct elf_phdr *phdr) 89431e31b8aSbellard { 89531e31b8aSbellard bswap32s(&phdr->p_type); /* Segment type */ 89692a31b1fSbellard bswaptls(&phdr->p_offset); /* Segment file offset */ 89792a31b1fSbellard bswaptls(&phdr->p_vaddr); /* Segment virtual address */ 89892a31b1fSbellard bswaptls(&phdr->p_paddr); /* Segment physical address */ 89992a31b1fSbellard bswaptls(&phdr->p_filesz); /* Segment size in file */ 90092a31b1fSbellard bswaptls(&phdr->p_memsz); /* Segment size in memory */ 90131e31b8aSbellard bswap32s(&phdr->p_flags); /* Segment flags */ 90292a31b1fSbellard bswaptls(&phdr->p_align); /* Segment alignment */ 90331e31b8aSbellard } 904689f936fSbellard 90592a31b1fSbellard static void bswap_shdr(struct elf_shdr *shdr) 906689f936fSbellard { 907689f936fSbellard bswap32s(&shdr->sh_name); 908689f936fSbellard bswap32s(&shdr->sh_type); 90992a31b1fSbellard bswaptls(&shdr->sh_flags); 91092a31b1fSbellard bswaptls(&shdr->sh_addr); 91192a31b1fSbellard bswaptls(&shdr->sh_offset); 91292a31b1fSbellard bswaptls(&shdr->sh_size); 913689f936fSbellard bswap32s(&shdr->sh_link); 914689f936fSbellard bswap32s(&shdr->sh_info); 91592a31b1fSbellard bswaptls(&shdr->sh_addralign); 91692a31b1fSbellard bswaptls(&shdr->sh_entsize); 917689f936fSbellard } 918689f936fSbellard 9197a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym) 920689f936fSbellard { 921689f936fSbellard bswap32s(&sym->st_name); 9227a3148a9Sj_mayer bswaptls(&sym->st_value); 9237a3148a9Sj_mayer bswaptls(&sym->st_size); 924689f936fSbellard bswap16s(&sym->st_shndx); 925689f936fSbellard } 92631e31b8aSbellard #endif 92731e31b8aSbellard 928edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 929edf8e2afSMika Westerberg static int elf_core_dump(int, const CPUState *); 930edf8e2afSMika Westerberg 931edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 932edf8e2afSMika Westerberg static void bswap_note(struct elf_note *en) 933edf8e2afSMika Westerberg { 9349fdca5aaSmalc bswap32s(&en->n_namesz); 9359fdca5aaSmalc bswap32s(&en->n_descsz); 9369fdca5aaSmalc bswap32s(&en->n_type); 937edf8e2afSMika Westerberg } 938edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 939edf8e2afSMika Westerberg 940edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 941edf8e2afSMika Westerberg 94231e31b8aSbellard /* 943e5fe0c52Spbrook * 'copy_elf_strings()' copies argument/envelope strings from user 94431e31b8aSbellard * memory to free pages in kernel mem. These are in a format ready 94531e31b8aSbellard * to be put directly into the top of new user memory. 94631e31b8aSbellard * 94731e31b8aSbellard */ 948992f48a0Sblueswir1 static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, 949992f48a0Sblueswir1 abi_ulong p) 95031e31b8aSbellard { 95131e31b8aSbellard char *tmp, *tmp1, *pag = NULL; 95231e31b8aSbellard int len, offset = 0; 95331e31b8aSbellard 95431e31b8aSbellard if (!p) { 95531e31b8aSbellard return 0; /* bullet-proofing */ 95631e31b8aSbellard } 95731e31b8aSbellard while (argc-- > 0) { 958edf779ffSbellard tmp = argv[argc]; 959edf779ffSbellard if (!tmp) { 96031e31b8aSbellard fprintf(stderr, "VFS: argc is wrong"); 96131e31b8aSbellard exit(-1); 96231e31b8aSbellard } 963edf779ffSbellard tmp1 = tmp; 964edf779ffSbellard while (*tmp++); 96531e31b8aSbellard len = tmp - tmp1; 96631e31b8aSbellard if (p < len) { /* this shouldn't happen - 128kB */ 96731e31b8aSbellard return 0; 96831e31b8aSbellard } 96931e31b8aSbellard while (len) { 97031e31b8aSbellard --p; --tmp; --len; 97131e31b8aSbellard if (--offset < 0) { 97254936004Sbellard offset = p % TARGET_PAGE_SIZE; 97344a91caeSbellard pag = (char *)page[p/TARGET_PAGE_SIZE]; 97444a91caeSbellard if (!pag) { 97553a5960aSpbrook pag = (char *)malloc(TARGET_PAGE_SIZE); 9764118a970Sj_mayer memset(pag, 0, TARGET_PAGE_SIZE); 97753a5960aSpbrook page[p/TARGET_PAGE_SIZE] = pag; 97844a91caeSbellard if (!pag) 97931e31b8aSbellard return 0; 98031e31b8aSbellard } 98131e31b8aSbellard } 98231e31b8aSbellard if (len == 0 || offset == 0) { 983edf779ffSbellard *(pag + offset) = *tmp; 98431e31b8aSbellard } 98531e31b8aSbellard else { 98631e31b8aSbellard int bytes_to_copy = (len > offset) ? offset : len; 98731e31b8aSbellard tmp -= bytes_to_copy; 98831e31b8aSbellard p -= bytes_to_copy; 98931e31b8aSbellard offset -= bytes_to_copy; 99031e31b8aSbellard len -= bytes_to_copy; 99131e31b8aSbellard memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); 99231e31b8aSbellard } 99331e31b8aSbellard } 99431e31b8aSbellard } 99531e31b8aSbellard return p; 99631e31b8aSbellard } 99731e31b8aSbellard 998992f48a0Sblueswir1 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, 99931e31b8aSbellard struct image_info *info) 100031e31b8aSbellard { 1001992f48a0Sblueswir1 abi_ulong stack_base, size, error; 100231e31b8aSbellard int i; 100331e31b8aSbellard 100431e31b8aSbellard /* Create enough stack to hold everything. If we don't use 100531e31b8aSbellard * it for args, we'll use it for something else... 100631e31b8aSbellard */ 100709bfb054Sbellard size = x86_stack_size; 100854936004Sbellard if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) 100954936004Sbellard size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; 101054936004Sbellard error = target_mmap(0, 101183fb7adfSbellard size + qemu_host_page_size, 101231e31b8aSbellard PROT_READ | PROT_WRITE, 101309bfb054Sbellard MAP_PRIVATE | MAP_ANONYMOUS, 101409bfb054Sbellard -1, 0); 101509bfb054Sbellard if (error == -1) { 101631e31b8aSbellard perror("stk mmap"); 101731e31b8aSbellard exit(-1); 101831e31b8aSbellard } 101909bfb054Sbellard /* we reserve one extra page at the top of the stack as guard */ 102083fb7adfSbellard target_mprotect(error + size, qemu_host_page_size, PROT_NONE); 102131e31b8aSbellard 102254936004Sbellard stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; 102309bfb054Sbellard p += stack_base; 102409bfb054Sbellard 102531e31b8aSbellard for (i = 0 ; i < MAX_ARG_PAGES ; i++) { 102631e31b8aSbellard if (bprm->page[i]) { 102731e31b8aSbellard info->rss++; 1028579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 102953a5960aSpbrook memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); 103053a5960aSpbrook free(bprm->page[i]); 103131e31b8aSbellard } 103254936004Sbellard stack_base += TARGET_PAGE_SIZE; 103331e31b8aSbellard } 103431e31b8aSbellard return p; 103531e31b8aSbellard } 103631e31b8aSbellard 1037992f48a0Sblueswir1 static void set_brk(abi_ulong start, abi_ulong end) 103831e31b8aSbellard { 103931e31b8aSbellard /* page-align the start and end addresses... */ 104054936004Sbellard start = HOST_PAGE_ALIGN(start); 104154936004Sbellard end = HOST_PAGE_ALIGN(end); 104231e31b8aSbellard if (end <= start) 104331e31b8aSbellard return; 104454936004Sbellard if(target_mmap(start, end - start, 104531e31b8aSbellard PROT_READ | PROT_WRITE | PROT_EXEC, 104631e31b8aSbellard MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) { 104731e31b8aSbellard perror("cannot mmap brk"); 104831e31b8aSbellard exit(-1); 104931e31b8aSbellard } 105031e31b8aSbellard } 105131e31b8aSbellard 105231e31b8aSbellard 1053853d6f7aSbellard /* We need to explicitly zero any fractional pages after the data 1054853d6f7aSbellard section (i.e. bss). This would contain the junk from the file that 1055853d6f7aSbellard should not be in memory. */ 1056992f48a0Sblueswir1 static void padzero(abi_ulong elf_bss, abi_ulong last_bss) 105731e31b8aSbellard { 1058992f48a0Sblueswir1 abi_ulong nbyte; 105931e31b8aSbellard 1060768a4a36Sths if (elf_bss >= last_bss) 1061768a4a36Sths return; 1062768a4a36Sths 1063853d6f7aSbellard /* XXX: this is really a hack : if the real host page size is 1064853d6f7aSbellard smaller than the target page size, some pages after the end 1065853d6f7aSbellard of the file may not be mapped. A better fix would be to 1066853d6f7aSbellard patch target_mmap(), but it is more complicated as the file 1067853d6f7aSbellard size must be known */ 106883fb7adfSbellard if (qemu_real_host_page_size < qemu_host_page_size) { 1069992f48a0Sblueswir1 abi_ulong end_addr, end_addr1; 107083fb7adfSbellard end_addr1 = (elf_bss + qemu_real_host_page_size - 1) & 107183fb7adfSbellard ~(qemu_real_host_page_size - 1); 1072853d6f7aSbellard end_addr = HOST_PAGE_ALIGN(elf_bss); 1073853d6f7aSbellard if (end_addr1 < end_addr) { 1074863cf0b7Sj_mayer mmap((void *)g2h(end_addr1), end_addr - end_addr1, 1075853d6f7aSbellard PROT_READ|PROT_WRITE|PROT_EXEC, 1076853d6f7aSbellard MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 1077853d6f7aSbellard } 1078853d6f7aSbellard } 1079853d6f7aSbellard 108083fb7adfSbellard nbyte = elf_bss & (qemu_host_page_size-1); 108131e31b8aSbellard if (nbyte) { 108283fb7adfSbellard nbyte = qemu_host_page_size - nbyte; 108331e31b8aSbellard do { 10842f619698Sbellard /* FIXME - what to do if put_user() fails? */ 10852f619698Sbellard put_user_u8(0, elf_bss); 108653a5960aSpbrook elf_bss++; 108731e31b8aSbellard } while (--nbyte); 108831e31b8aSbellard } 108931e31b8aSbellard } 109031e31b8aSbellard 109153a5960aSpbrook 1092992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, 109331e31b8aSbellard struct elfhdr * exec, 1094992f48a0Sblueswir1 abi_ulong load_addr, 1095992f48a0Sblueswir1 abi_ulong load_bias, 1096992f48a0Sblueswir1 abi_ulong interp_load_addr, int ibcs, 109731e31b8aSbellard struct image_info *info) 109831e31b8aSbellard { 1099992f48a0Sblueswir1 abi_ulong sp; 110053a5960aSpbrook int size; 1101992f48a0Sblueswir1 abi_ulong u_platform; 110215338fd7Sbellard const char *k_platform; 1103863cf0b7Sj_mayer const int n = sizeof(elf_addr_t); 110431e31b8aSbellard 110553a5960aSpbrook sp = p; 110653a5960aSpbrook u_platform = 0; 110715338fd7Sbellard k_platform = ELF_PLATFORM; 110815338fd7Sbellard if (k_platform) { 110915338fd7Sbellard size_t len = strlen(k_platform) + 1; 111053a5960aSpbrook sp -= (len + n - 1) & ~(n - 1); 111153a5960aSpbrook u_platform = sp; 1112579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 111353a5960aSpbrook memcpy_to_target(sp, k_platform, len); 111415338fd7Sbellard } 111553a5960aSpbrook /* 111653a5960aSpbrook * Force 16 byte _final_ alignment here for generality. 111753a5960aSpbrook */ 1118992f48a0Sblueswir1 sp = sp &~ (abi_ulong)15; 111953a5960aSpbrook size = (DLINFO_ITEMS + 1) * 2; 112015338fd7Sbellard if (k_platform) 112153a5960aSpbrook size += 2; 1122f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS 112353a5960aSpbrook size += DLINFO_ARCH_ITEMS * 2; 1124f5155289Sbellard #endif 112553a5960aSpbrook size += envc + argc + 2; 112653a5960aSpbrook size += (!ibcs ? 3 : 1); /* argc itself */ 112753a5960aSpbrook size *= n; 112853a5960aSpbrook if (size & 15) 112953a5960aSpbrook sp -= 16 - (size & 15); 1130f5155289Sbellard 1131863cf0b7Sj_mayer /* This is correct because Linux defines 1132863cf0b7Sj_mayer * elf_addr_t as Elf32_Off / Elf64_Off 1133863cf0b7Sj_mayer */ 113453a5960aSpbrook #define NEW_AUX_ENT(id, val) do { \ 11352f619698Sbellard sp -= n; put_user_ual(val, sp); \ 11362f619698Sbellard sp -= n; put_user_ual(id, sp); \ 113753a5960aSpbrook } while(0) 11382f619698Sbellard 11390bccf03dSbellard NEW_AUX_ENT (AT_NULL, 0); 1140f5155289Sbellard 11410bccf03dSbellard /* There must be exactly DLINFO_ITEMS entries here. */ 1142992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff)); 1143992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); 1144992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); 1145992f48a0Sblueswir1 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE)); 1146992f48a0Sblueswir1 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr)); 1147992f48a0Sblueswir1 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); 11480bccf03dSbellard NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry); 1149992f48a0Sblueswir1 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); 1150992f48a0Sblueswir1 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); 1151992f48a0Sblueswir1 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); 1152992f48a0Sblueswir1 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); 1153992f48a0Sblueswir1 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); 1154a07c67dfSpbrook NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); 115515338fd7Sbellard if (k_platform) 115653a5960aSpbrook NEW_AUX_ENT(AT_PLATFORM, u_platform); 1157f5155289Sbellard #ifdef ARCH_DLINFO 1158f5155289Sbellard /* 1159f5155289Sbellard * ARCH_DLINFO must come last so platform specific code can enforce 1160f5155289Sbellard * special alignment requirements on the AUXV if necessary (eg. PPC). 1161f5155289Sbellard */ 1162f5155289Sbellard ARCH_DLINFO; 1163f5155289Sbellard #endif 1164f5155289Sbellard #undef NEW_AUX_ENT 1165f5155289Sbellard 1166edf8e2afSMika Westerberg info->saved_auxv = sp; 1167edf8e2afSMika Westerberg 1168e5fe0c52Spbrook sp = loader_build_argptr(envc, argc, sp, p, !ibcs); 116931e31b8aSbellard return sp; 117031e31b8aSbellard } 117131e31b8aSbellard 117231e31b8aSbellard 1173992f48a0Sblueswir1 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, 117431e31b8aSbellard int interpreter_fd, 1175992f48a0Sblueswir1 abi_ulong *interp_load_addr) 117631e31b8aSbellard { 117731e31b8aSbellard struct elf_phdr *elf_phdata = NULL; 117831e31b8aSbellard struct elf_phdr *eppnt; 1179992f48a0Sblueswir1 abi_ulong load_addr = 0; 118031e31b8aSbellard int load_addr_set = 0; 118131e31b8aSbellard int retval; 1182992f48a0Sblueswir1 abi_ulong last_bss, elf_bss; 1183992f48a0Sblueswir1 abi_ulong error; 118431e31b8aSbellard int i; 118531e31b8aSbellard 118631e31b8aSbellard elf_bss = 0; 118731e31b8aSbellard last_bss = 0; 118831e31b8aSbellard error = 0; 118931e31b8aSbellard 1190644c433cSbellard #ifdef BSWAP_NEEDED 1191644c433cSbellard bswap_ehdr(interp_elf_ex); 1192644c433cSbellard #endif 119331e31b8aSbellard /* First of all, some simple consistency checks */ 119431e31b8aSbellard if ((interp_elf_ex->e_type != ET_EXEC && 119531e31b8aSbellard interp_elf_ex->e_type != ET_DYN) || 119631e31b8aSbellard !elf_check_arch(interp_elf_ex->e_machine)) { 1197992f48a0Sblueswir1 return ~((abi_ulong)0UL); 119831e31b8aSbellard } 119931e31b8aSbellard 1200644c433cSbellard 120131e31b8aSbellard /* Now read in all of the header information */ 120231e31b8aSbellard 120354936004Sbellard if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE) 1204992f48a0Sblueswir1 return ~(abi_ulong)0UL; 120531e31b8aSbellard 120631e31b8aSbellard elf_phdata = (struct elf_phdr *) 120731e31b8aSbellard malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 120831e31b8aSbellard 120931e31b8aSbellard if (!elf_phdata) 1210992f48a0Sblueswir1 return ~((abi_ulong)0UL); 121131e31b8aSbellard 121231e31b8aSbellard /* 121331e31b8aSbellard * If the size of this structure has changed, then punt, since 121431e31b8aSbellard * we will be doing the wrong thing. 121531e31b8aSbellard */ 121609bfb054Sbellard if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { 121731e31b8aSbellard free(elf_phdata); 1218992f48a0Sblueswir1 return ~((abi_ulong)0UL); 121931e31b8aSbellard } 122031e31b8aSbellard 122131e31b8aSbellard retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET); 122231e31b8aSbellard if(retval >= 0) { 122331e31b8aSbellard retval = read(interpreter_fd, 122431e31b8aSbellard (char *) elf_phdata, 122531e31b8aSbellard sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 122631e31b8aSbellard } 122731e31b8aSbellard if (retval < 0) { 122831e31b8aSbellard perror("load_elf_interp"); 122931e31b8aSbellard exit(-1); 123031e31b8aSbellard free (elf_phdata); 123131e31b8aSbellard return retval; 123231e31b8aSbellard } 123331e31b8aSbellard #ifdef BSWAP_NEEDED 123431e31b8aSbellard eppnt = elf_phdata; 123531e31b8aSbellard for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { 123631e31b8aSbellard bswap_phdr(eppnt); 123731e31b8aSbellard } 123831e31b8aSbellard #endif 123909bfb054Sbellard 124009bfb054Sbellard if (interp_elf_ex->e_type == ET_DYN) { 1241e91c8a77Sths /* in order to avoid hardcoding the interpreter load 124209bfb054Sbellard address in qemu, we allocate a big enough memory zone */ 124354936004Sbellard error = target_mmap(0, INTERP_MAP_SIZE, 124409bfb054Sbellard PROT_NONE, MAP_PRIVATE | MAP_ANON, 124509bfb054Sbellard -1, 0); 124609bfb054Sbellard if (error == -1) { 124709bfb054Sbellard perror("mmap"); 124809bfb054Sbellard exit(-1); 124909bfb054Sbellard } 125009bfb054Sbellard load_addr = error; 125109bfb054Sbellard load_addr_set = 1; 125209bfb054Sbellard } 125309bfb054Sbellard 125431e31b8aSbellard eppnt = elf_phdata; 125531e31b8aSbellard for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) 125631e31b8aSbellard if (eppnt->p_type == PT_LOAD) { 125731e31b8aSbellard int elf_type = MAP_PRIVATE | MAP_DENYWRITE; 125831e31b8aSbellard int elf_prot = 0; 1259992f48a0Sblueswir1 abi_ulong vaddr = 0; 1260992f48a0Sblueswir1 abi_ulong k; 126131e31b8aSbellard 126231e31b8aSbellard if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; 126331e31b8aSbellard if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 126431e31b8aSbellard if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 126531e31b8aSbellard if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) { 126631e31b8aSbellard elf_type |= MAP_FIXED; 126731e31b8aSbellard vaddr = eppnt->p_vaddr; 126831e31b8aSbellard } 126954936004Sbellard error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr), 127054936004Sbellard eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr), 127131e31b8aSbellard elf_prot, 127231e31b8aSbellard elf_type, 127331e31b8aSbellard interpreter_fd, 127454936004Sbellard eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr)); 127531e31b8aSbellard 1276e89f07d3Spbrook if (error == -1) { 127731e31b8aSbellard /* Real error */ 127831e31b8aSbellard close(interpreter_fd); 127931e31b8aSbellard free(elf_phdata); 1280992f48a0Sblueswir1 return ~((abi_ulong)0UL); 128131e31b8aSbellard } 128231e31b8aSbellard 128331e31b8aSbellard if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { 128431e31b8aSbellard load_addr = error; 128531e31b8aSbellard load_addr_set = 1; 128631e31b8aSbellard } 128731e31b8aSbellard 128831e31b8aSbellard /* 128931e31b8aSbellard * Find the end of the file mapping for this phdr, and keep 129031e31b8aSbellard * track of the largest address we see for this. 129131e31b8aSbellard */ 129231e31b8aSbellard k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; 129331e31b8aSbellard if (k > elf_bss) elf_bss = k; 129431e31b8aSbellard 129531e31b8aSbellard /* 129631e31b8aSbellard * Do the same thing for the memory mapping - between 129731e31b8aSbellard * elf_bss and last_bss is the bss section. 129831e31b8aSbellard */ 129931e31b8aSbellard k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; 130031e31b8aSbellard if (k > last_bss) last_bss = k; 130131e31b8aSbellard } 130231e31b8aSbellard 130331e31b8aSbellard /* Now use mmap to map the library into memory. */ 130431e31b8aSbellard 130531e31b8aSbellard close(interpreter_fd); 130631e31b8aSbellard 130731e31b8aSbellard /* 130831e31b8aSbellard * Now fill out the bss section. First pad the last page up 130931e31b8aSbellard * to the page boundary, and then perform a mmap to make sure 131031e31b8aSbellard * that there are zeromapped pages up to and including the last 131131e31b8aSbellard * bss page. 131231e31b8aSbellard */ 1313768a4a36Sths padzero(elf_bss, last_bss); 131483fb7adfSbellard elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */ 131531e31b8aSbellard 131631e31b8aSbellard /* Map the last of the bss segment */ 131731e31b8aSbellard if (last_bss > elf_bss) { 131854936004Sbellard target_mmap(elf_bss, last_bss-elf_bss, 131931e31b8aSbellard PROT_READ|PROT_WRITE|PROT_EXEC, 132031e31b8aSbellard MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 132131e31b8aSbellard } 132231e31b8aSbellard free(elf_phdata); 132331e31b8aSbellard 132431e31b8aSbellard *interp_load_addr = load_addr; 1325992f48a0Sblueswir1 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr; 132631e31b8aSbellard } 132731e31b8aSbellard 132849918a75Spbrook static int symfind(const void *s0, const void *s1) 132949918a75Spbrook { 133049918a75Spbrook struct elf_sym *key = (struct elf_sym *)s0; 133149918a75Spbrook struct elf_sym *sym = (struct elf_sym *)s1; 133249918a75Spbrook int result = 0; 133349918a75Spbrook if (key->st_value < sym->st_value) { 133449918a75Spbrook result = -1; 1335ec822001SLaurent Desnogues } else if (key->st_value >= sym->st_value + sym->st_size) { 133649918a75Spbrook result = 1; 133749918a75Spbrook } 133849918a75Spbrook return result; 133949918a75Spbrook } 134049918a75Spbrook 134149918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr) 134249918a75Spbrook { 134349918a75Spbrook #if ELF_CLASS == ELFCLASS32 134449918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf32; 134549918a75Spbrook #else 134649918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf64; 134749918a75Spbrook #endif 134849918a75Spbrook 134949918a75Spbrook // binary search 135049918a75Spbrook struct elf_sym key; 135149918a75Spbrook struct elf_sym *sym; 135249918a75Spbrook 135349918a75Spbrook key.st_value = orig_addr; 135449918a75Spbrook 135549918a75Spbrook sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind); 13567cba04f6SBlue Swirl if (sym != NULL) { 135749918a75Spbrook return s->disas_strtab + sym->st_name; 135849918a75Spbrook } 135949918a75Spbrook 136049918a75Spbrook return ""; 136149918a75Spbrook } 136249918a75Spbrook 136349918a75Spbrook /* FIXME: This should use elf_ops.h */ 136449918a75Spbrook static int symcmp(const void *s0, const void *s1) 136549918a75Spbrook { 136649918a75Spbrook struct elf_sym *sym0 = (struct elf_sym *)s0; 136749918a75Spbrook struct elf_sym *sym1 = (struct elf_sym *)s1; 136849918a75Spbrook return (sym0->st_value < sym1->st_value) 136949918a75Spbrook ? -1 137049918a75Spbrook : ((sym0->st_value > sym1->st_value) ? 1 : 0); 137149918a75Spbrook } 137249918a75Spbrook 1373689f936fSbellard /* Best attempt to load symbols from this ELF object. */ 1374689f936fSbellard static void load_symbols(struct elfhdr *hdr, int fd) 1375689f936fSbellard { 137649918a75Spbrook unsigned int i, nsyms; 1377689f936fSbellard struct elf_shdr sechdr, symtab, strtab; 1378689f936fSbellard char *strings; 1379e80cfcfcSbellard struct syminfo *s; 138049918a75Spbrook struct elf_sym *syms; 138131e31b8aSbellard 1382689f936fSbellard lseek(fd, hdr->e_shoff, SEEK_SET); 1383689f936fSbellard for (i = 0; i < hdr->e_shnum; i++) { 1384689f936fSbellard if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) 1385689f936fSbellard return; 1386689f936fSbellard #ifdef BSWAP_NEEDED 1387689f936fSbellard bswap_shdr(&sechdr); 1388689f936fSbellard #endif 1389689f936fSbellard if (sechdr.sh_type == SHT_SYMTAB) { 1390689f936fSbellard symtab = sechdr; 1391689f936fSbellard lseek(fd, hdr->e_shoff 1392689f936fSbellard + sizeof(sechdr) * sechdr.sh_link, SEEK_SET); 1393689f936fSbellard if (read(fd, &strtab, sizeof(strtab)) 1394689f936fSbellard != sizeof(strtab)) 1395689f936fSbellard return; 1396689f936fSbellard #ifdef BSWAP_NEEDED 1397689f936fSbellard bswap_shdr(&strtab); 1398689f936fSbellard #endif 1399689f936fSbellard goto found; 1400689f936fSbellard } 1401689f936fSbellard } 1402689f936fSbellard return; /* Shouldn't happen... */ 1403689f936fSbellard 1404689f936fSbellard found: 1405689f936fSbellard /* Now know where the strtab and symtab are. Snarf them. */ 1406e80cfcfcSbellard s = malloc(sizeof(*s)); 140749918a75Spbrook syms = malloc(symtab.sh_size); 140849918a75Spbrook if (!syms) 140949918a75Spbrook return; 1410e80cfcfcSbellard s->disas_strtab = strings = malloc(strtab.sh_size); 141149918a75Spbrook if (!s->disas_strtab) 1412689f936fSbellard return; 1413689f936fSbellard 1414689f936fSbellard lseek(fd, symtab.sh_offset, SEEK_SET); 141549918a75Spbrook if (read(fd, syms, symtab.sh_size) != symtab.sh_size) 1416689f936fSbellard return; 1417689f936fSbellard 141849918a75Spbrook nsyms = symtab.sh_size / sizeof(struct elf_sym); 1419689f936fSbellard 142049918a75Spbrook i = 0; 142149918a75Spbrook while (i < nsyms) { 142249918a75Spbrook #ifdef BSWAP_NEEDED 142349918a75Spbrook bswap_sym(syms + i); 14240774bed1Sblueswir1 #endif 142549918a75Spbrook // Throw away entries which we do not need. 142649918a75Spbrook if (syms[i].st_shndx == SHN_UNDEF || 142749918a75Spbrook syms[i].st_shndx >= SHN_LORESERVE || 142849918a75Spbrook ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 142949918a75Spbrook nsyms--; 143049918a75Spbrook if (i < nsyms) { 143149918a75Spbrook syms[i] = syms[nsyms]; 143249918a75Spbrook } 143349918a75Spbrook continue; 143449918a75Spbrook } 143549918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS) 143649918a75Spbrook /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 143749918a75Spbrook syms[i].st_value &= ~(target_ulong)1; 143849918a75Spbrook #endif 143949918a75Spbrook i++; 144049918a75Spbrook } 144149918a75Spbrook syms = realloc(syms, nsyms * sizeof(*syms)); 144249918a75Spbrook 144349918a75Spbrook qsort(syms, nsyms, sizeof(*syms), symcmp); 144449918a75Spbrook 1445689f936fSbellard lseek(fd, strtab.sh_offset, SEEK_SET); 1446689f936fSbellard if (read(fd, strings, strtab.sh_size) != strtab.sh_size) 1447689f936fSbellard return; 144849918a75Spbrook s->disas_num_syms = nsyms; 144949918a75Spbrook #if ELF_CLASS == ELFCLASS32 145049918a75Spbrook s->disas_symtab.elf32 = syms; 1451*9f9f0309SPaul Brook s->lookup_symbol = lookup_symbolxx; 145249918a75Spbrook #else 145349918a75Spbrook s->disas_symtab.elf64 = syms; 1454*9f9f0309SPaul Brook s->lookup_symbol = lookup_symbolxx; 145549918a75Spbrook #endif 1456e80cfcfcSbellard s->next = syminfos; 1457e80cfcfcSbellard syminfos = s; 1458689f936fSbellard } 145931e31b8aSbellard 1460e5fe0c52Spbrook int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, 146131e31b8aSbellard struct image_info * info) 146231e31b8aSbellard { 146331e31b8aSbellard struct elfhdr elf_ex; 146431e31b8aSbellard struct elfhdr interp_elf_ex; 146531e31b8aSbellard struct exec interp_ex; 146631e31b8aSbellard int interpreter_fd = -1; /* avoid warning */ 1467992f48a0Sblueswir1 abi_ulong load_addr, load_bias; 146831e31b8aSbellard int load_addr_set = 0; 146931e31b8aSbellard unsigned int interpreter_type = INTERPRETER_NONE; 147031e31b8aSbellard unsigned char ibcs2_interpreter; 147131e31b8aSbellard int i; 1472992f48a0Sblueswir1 abi_ulong mapped_addr; 147331e31b8aSbellard struct elf_phdr * elf_ppnt; 147431e31b8aSbellard struct elf_phdr *elf_phdata; 1475992f48a0Sblueswir1 abi_ulong elf_bss, k, elf_brk; 147631e31b8aSbellard int retval; 147731e31b8aSbellard char * elf_interpreter; 1478992f48a0Sblueswir1 abi_ulong elf_entry, interp_load_addr = 0; 147931e31b8aSbellard int status; 1480992f48a0Sblueswir1 abi_ulong start_code, end_code, start_data, end_data; 1481992f48a0Sblueswir1 abi_ulong reloc_func_desc = 0; 1482992f48a0Sblueswir1 abi_ulong elf_stack; 148331e31b8aSbellard char passed_fileno[6]; 148431e31b8aSbellard 148531e31b8aSbellard ibcs2_interpreter = 0; 148631e31b8aSbellard status = 0; 148731e31b8aSbellard load_addr = 0; 148809bfb054Sbellard load_bias = 0; 148931e31b8aSbellard elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ 149031e31b8aSbellard #ifdef BSWAP_NEEDED 149131e31b8aSbellard bswap_ehdr(&elf_ex); 149231e31b8aSbellard #endif 149331e31b8aSbellard 149431e31b8aSbellard /* First of all, some simple consistency checks */ 149531e31b8aSbellard if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || 149631e31b8aSbellard (! elf_check_arch(elf_ex.e_machine))) { 149731e31b8aSbellard return -ENOEXEC; 149831e31b8aSbellard } 149931e31b8aSbellard 1500e5fe0c52Spbrook bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); 1501e5fe0c52Spbrook bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); 1502e5fe0c52Spbrook bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); 1503e5fe0c52Spbrook if (!bprm->p) { 1504e5fe0c52Spbrook retval = -E2BIG; 1505e5fe0c52Spbrook } 1506e5fe0c52Spbrook 150731e31b8aSbellard /* Now read in all of the header information */ 150831e31b8aSbellard elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); 150931e31b8aSbellard if (elf_phdata == NULL) { 151031e31b8aSbellard return -ENOMEM; 151131e31b8aSbellard } 151231e31b8aSbellard 151331e31b8aSbellard retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET); 151431e31b8aSbellard if(retval > 0) { 151531e31b8aSbellard retval = read(bprm->fd, (char *) elf_phdata, 151631e31b8aSbellard elf_ex.e_phentsize * elf_ex.e_phnum); 151731e31b8aSbellard } 151831e31b8aSbellard 151931e31b8aSbellard if (retval < 0) { 152031e31b8aSbellard perror("load_elf_binary"); 152131e31b8aSbellard exit(-1); 152231e31b8aSbellard free (elf_phdata); 152331e31b8aSbellard return -errno; 152431e31b8aSbellard } 152531e31b8aSbellard 1526b17780d5Sbellard #ifdef BSWAP_NEEDED 1527b17780d5Sbellard elf_ppnt = elf_phdata; 1528b17780d5Sbellard for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) { 1529b17780d5Sbellard bswap_phdr(elf_ppnt); 1530b17780d5Sbellard } 1531b17780d5Sbellard #endif 153231e31b8aSbellard elf_ppnt = elf_phdata; 153331e31b8aSbellard 153431e31b8aSbellard elf_bss = 0; 153531e31b8aSbellard elf_brk = 0; 153631e31b8aSbellard 153731e31b8aSbellard 1538992f48a0Sblueswir1 elf_stack = ~((abi_ulong)0UL); 153931e31b8aSbellard elf_interpreter = NULL; 1540992f48a0Sblueswir1 start_code = ~((abi_ulong)0UL); 154131e31b8aSbellard end_code = 0; 1542863cf0b7Sj_mayer start_data = 0; 154331e31b8aSbellard end_data = 0; 154498448f58Sblueswir1 interp_ex.a_info = 0; 154531e31b8aSbellard 154631e31b8aSbellard for(i=0;i < elf_ex.e_phnum; i++) { 154731e31b8aSbellard if (elf_ppnt->p_type == PT_INTERP) { 154831e31b8aSbellard if ( elf_interpreter != NULL ) 154931e31b8aSbellard { 155031e31b8aSbellard free (elf_phdata); 155131e31b8aSbellard free(elf_interpreter); 155231e31b8aSbellard close(bprm->fd); 155331e31b8aSbellard return -EINVAL; 155431e31b8aSbellard } 155531e31b8aSbellard 155631e31b8aSbellard /* This is the program interpreter used for 155731e31b8aSbellard * shared libraries - for now assume that this 155831e31b8aSbellard * is an a.out format binary 155931e31b8aSbellard */ 156031e31b8aSbellard 156132ce6337Sbellard elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); 156231e31b8aSbellard 156331e31b8aSbellard if (elf_interpreter == NULL) { 156431e31b8aSbellard free (elf_phdata); 156531e31b8aSbellard close(bprm->fd); 156631e31b8aSbellard return -ENOMEM; 156731e31b8aSbellard } 156831e31b8aSbellard 156931e31b8aSbellard retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); 157031e31b8aSbellard if(retval >= 0) { 157132ce6337Sbellard retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); 157231e31b8aSbellard } 157331e31b8aSbellard if(retval < 0) { 157431e31b8aSbellard perror("load_elf_binary2"); 157531e31b8aSbellard exit(-1); 157631e31b8aSbellard } 157731e31b8aSbellard 157831e31b8aSbellard /* If the program interpreter is one of these two, 157931e31b8aSbellard then assume an iBCS2 image. Otherwise assume 158031e31b8aSbellard a native linux image. */ 158131e31b8aSbellard 158231e31b8aSbellard /* JRP - Need to add X86 lib dir stuff here... */ 158331e31b8aSbellard 158431e31b8aSbellard if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || 158531e31b8aSbellard strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) { 158631e31b8aSbellard ibcs2_interpreter = 1; 158731e31b8aSbellard } 158831e31b8aSbellard 158931e31b8aSbellard #if 0 15903bc0bdcaSPaul Bolle printf("Using ELF interpreter %s\n", path(elf_interpreter)); 159131e31b8aSbellard #endif 159231e31b8aSbellard if (retval >= 0) { 159332ce6337Sbellard retval = open(path(elf_interpreter), O_RDONLY); 159431e31b8aSbellard if(retval >= 0) { 159531e31b8aSbellard interpreter_fd = retval; 159631e31b8aSbellard } 159731e31b8aSbellard else { 159831e31b8aSbellard perror(elf_interpreter); 159931e31b8aSbellard exit(-1); 160031e31b8aSbellard /* retval = -errno; */ 160131e31b8aSbellard } 160231e31b8aSbellard } 160331e31b8aSbellard 160431e31b8aSbellard if (retval >= 0) { 160531e31b8aSbellard retval = lseek(interpreter_fd, 0, SEEK_SET); 160631e31b8aSbellard if(retval >= 0) { 160731e31b8aSbellard retval = read(interpreter_fd,bprm->buf,128); 160831e31b8aSbellard } 160931e31b8aSbellard } 161031e31b8aSbellard if (retval >= 0) { 161131e31b8aSbellard interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */ 161231e31b8aSbellard interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */ 161331e31b8aSbellard } 161431e31b8aSbellard if (retval < 0) { 161531e31b8aSbellard perror("load_elf_binary3"); 161631e31b8aSbellard exit(-1); 161731e31b8aSbellard free (elf_phdata); 161831e31b8aSbellard free(elf_interpreter); 161931e31b8aSbellard close(bprm->fd); 162031e31b8aSbellard return retval; 162131e31b8aSbellard } 162231e31b8aSbellard } 162331e31b8aSbellard elf_ppnt++; 162431e31b8aSbellard } 162531e31b8aSbellard 162631e31b8aSbellard /* Some simple consistency checks for the interpreter */ 162731e31b8aSbellard if (elf_interpreter){ 162831e31b8aSbellard interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; 162931e31b8aSbellard 163031e31b8aSbellard /* Now figure out which format our binary is */ 163131e31b8aSbellard if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && 163231e31b8aSbellard (N_MAGIC(interp_ex) != QMAGIC)) { 163331e31b8aSbellard interpreter_type = INTERPRETER_ELF; 163431e31b8aSbellard } 163531e31b8aSbellard 163631e31b8aSbellard if (interp_elf_ex.e_ident[0] != 0x7f || 1637b55266b5Sblueswir1 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) { 163831e31b8aSbellard interpreter_type &= ~INTERPRETER_ELF; 163931e31b8aSbellard } 164031e31b8aSbellard 164131e31b8aSbellard if (!interpreter_type) { 164231e31b8aSbellard free(elf_interpreter); 164331e31b8aSbellard free(elf_phdata); 164431e31b8aSbellard close(bprm->fd); 164531e31b8aSbellard return -ELIBBAD; 164631e31b8aSbellard } 164731e31b8aSbellard } 164831e31b8aSbellard 164931e31b8aSbellard /* OK, we are done with that, now set up the arg stuff, 165031e31b8aSbellard and then start this sucker up */ 165131e31b8aSbellard 1652e5fe0c52Spbrook { 165331e31b8aSbellard char * passed_p; 165431e31b8aSbellard 165531e31b8aSbellard if (interpreter_type == INTERPRETER_AOUT) { 1656eba2af63Sbellard snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd); 165731e31b8aSbellard passed_p = passed_fileno; 165831e31b8aSbellard 165931e31b8aSbellard if (elf_interpreter) { 1660e5fe0c52Spbrook bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p); 166131e31b8aSbellard bprm->argc++; 166231e31b8aSbellard } 166331e31b8aSbellard } 166431e31b8aSbellard if (!bprm->p) { 166531e31b8aSbellard if (elf_interpreter) { 166631e31b8aSbellard free(elf_interpreter); 166731e31b8aSbellard } 166831e31b8aSbellard free (elf_phdata); 166931e31b8aSbellard close(bprm->fd); 167031e31b8aSbellard return -E2BIG; 167131e31b8aSbellard } 167231e31b8aSbellard } 167331e31b8aSbellard 167431e31b8aSbellard /* OK, This is the point of no return */ 167531e31b8aSbellard info->end_data = 0; 167631e31b8aSbellard info->end_code = 0; 1677992f48a0Sblueswir1 info->start_mmap = (abi_ulong)ELF_START_MMAP; 167831e31b8aSbellard info->mmap = 0; 1679992f48a0Sblueswir1 elf_entry = (abi_ulong) elf_ex.e_entry; 168031e31b8aSbellard 1681379f6698SPaul Brook #if defined(CONFIG_USE_GUEST_BASE) 1682379f6698SPaul Brook /* 1683379f6698SPaul Brook * In case where user has not explicitly set the guest_base, we 1684379f6698SPaul Brook * probe here that should we set it automatically. 1685379f6698SPaul Brook */ 1686379f6698SPaul Brook if (!have_guest_base) { 1687379f6698SPaul Brook /* 1688379f6698SPaul Brook * Go through ELF program header table and find out whether 1689379f6698SPaul Brook * any of the segments drop below our current mmap_min_addr and 1690379f6698SPaul Brook * in that case set guest_base to corresponding address. 1691379f6698SPaul Brook */ 1692379f6698SPaul Brook for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; 1693379f6698SPaul Brook i++, elf_ppnt++) { 1694379f6698SPaul Brook if (elf_ppnt->p_type != PT_LOAD) 1695379f6698SPaul Brook continue; 1696379f6698SPaul Brook if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) { 1697379f6698SPaul Brook guest_base = HOST_PAGE_ALIGN(mmap_min_addr); 1698379f6698SPaul Brook break; 1699379f6698SPaul Brook } 1700379f6698SPaul Brook } 1701379f6698SPaul Brook } 1702379f6698SPaul Brook #endif /* CONFIG_USE_GUEST_BASE */ 1703379f6698SPaul Brook 170431e31b8aSbellard /* Do this so that we can load the interpreter, if need be. We will 170531e31b8aSbellard change some of these later */ 170631e31b8aSbellard info->rss = 0; 170731e31b8aSbellard bprm->p = setup_arg_pages(bprm->p, bprm, info); 170831e31b8aSbellard info->start_stack = bprm->p; 170931e31b8aSbellard 171031e31b8aSbellard /* Now we do a little grungy work by mmaping the ELF image into 171131e31b8aSbellard * the correct location in memory. At this point, we assume that 171231e31b8aSbellard * the image should be loaded at fixed address, not at a variable 171331e31b8aSbellard * address. 171431e31b8aSbellard */ 171531e31b8aSbellard 171631e31b8aSbellard for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { 171731e31b8aSbellard int elf_prot = 0; 171809bfb054Sbellard int elf_flags = 0; 1719992f48a0Sblueswir1 abi_ulong error; 172009bfb054Sbellard 172109bfb054Sbellard if (elf_ppnt->p_type != PT_LOAD) 172209bfb054Sbellard continue; 172309bfb054Sbellard 172431e31b8aSbellard if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; 172531e31b8aSbellard if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 172631e31b8aSbellard if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 172709bfb054Sbellard elf_flags = MAP_PRIVATE | MAP_DENYWRITE; 172809bfb054Sbellard if (elf_ex.e_type == ET_EXEC || load_addr_set) { 172909bfb054Sbellard elf_flags |= MAP_FIXED; 173009bfb054Sbellard } else if (elf_ex.e_type == ET_DYN) { 173109bfb054Sbellard /* Try and get dynamic programs out of the way of the default mmap 173209bfb054Sbellard base, as well as whatever program they might try to exec. This 173309bfb054Sbellard is because the brk will follow the loader, and is not movable. */ 173409bfb054Sbellard /* NOTE: for qemu, we do a big mmap to get enough space 1735e91c8a77Sths without hardcoding any address */ 173654936004Sbellard error = target_mmap(0, ET_DYN_MAP_SIZE, 173709bfb054Sbellard PROT_NONE, MAP_PRIVATE | MAP_ANON, 173809bfb054Sbellard -1, 0); 173909bfb054Sbellard if (error == -1) { 174009bfb054Sbellard perror("mmap"); 174109bfb054Sbellard exit(-1); 174209bfb054Sbellard } 174354936004Sbellard load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); 174409bfb054Sbellard } 174531e31b8aSbellard 174654936004Sbellard error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), 174731e31b8aSbellard (elf_ppnt->p_filesz + 174854936004Sbellard TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), 174931e31b8aSbellard elf_prot, 175031e31b8aSbellard (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), 175131e31b8aSbellard bprm->fd, 175231e31b8aSbellard (elf_ppnt->p_offset - 175354936004Sbellard TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); 175409bfb054Sbellard if (error == -1) { 175531e31b8aSbellard perror("mmap"); 175631e31b8aSbellard exit(-1); 175731e31b8aSbellard } 175831e31b8aSbellard 175931e31b8aSbellard #ifdef LOW_ELF_STACK 176054936004Sbellard if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) 176154936004Sbellard elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr); 176231e31b8aSbellard #endif 176331e31b8aSbellard 176431e31b8aSbellard if (!load_addr_set) { 176531e31b8aSbellard load_addr_set = 1; 176609bfb054Sbellard load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; 176709bfb054Sbellard if (elf_ex.e_type == ET_DYN) { 176809bfb054Sbellard load_bias += error - 176954936004Sbellard TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); 177009bfb054Sbellard load_addr += load_bias; 177184409ddbSj_mayer reloc_func_desc = load_bias; 177209bfb054Sbellard } 177331e31b8aSbellard } 177431e31b8aSbellard k = elf_ppnt->p_vaddr; 177509bfb054Sbellard if (k < start_code) 177609bfb054Sbellard start_code = k; 1777863cf0b7Sj_mayer if (start_data < k) 1778863cf0b7Sj_mayer start_data = k; 177931e31b8aSbellard k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; 178009bfb054Sbellard if (k > elf_bss) 178109bfb054Sbellard elf_bss = k; 178231e31b8aSbellard if ((elf_ppnt->p_flags & PF_X) && end_code < k) 178331e31b8aSbellard end_code = k; 178409bfb054Sbellard if (end_data < k) 178509bfb054Sbellard end_data = k; 178631e31b8aSbellard k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; 178731e31b8aSbellard if (k > elf_brk) elf_brk = k; 178831e31b8aSbellard } 178909bfb054Sbellard 179009bfb054Sbellard elf_entry += load_bias; 179109bfb054Sbellard elf_bss += load_bias; 179209bfb054Sbellard elf_brk += load_bias; 179309bfb054Sbellard start_code += load_bias; 179409bfb054Sbellard end_code += load_bias; 1795863cf0b7Sj_mayer start_data += load_bias; 179609bfb054Sbellard end_data += load_bias; 179731e31b8aSbellard 179831e31b8aSbellard if (elf_interpreter) { 179931e31b8aSbellard if (interpreter_type & 1) { 180031e31b8aSbellard elf_entry = load_aout_interp(&interp_ex, interpreter_fd); 180131e31b8aSbellard } 180231e31b8aSbellard else if (interpreter_type & 2) { 180331e31b8aSbellard elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, 180431e31b8aSbellard &interp_load_addr); 180531e31b8aSbellard } 180684409ddbSj_mayer reloc_func_desc = interp_load_addr; 180731e31b8aSbellard 180831e31b8aSbellard close(interpreter_fd); 180931e31b8aSbellard free(elf_interpreter); 181031e31b8aSbellard 1811992f48a0Sblueswir1 if (elf_entry == ~((abi_ulong)0UL)) { 181231e31b8aSbellard printf("Unable to load interpreter\n"); 181331e31b8aSbellard free(elf_phdata); 181431e31b8aSbellard exit(-1); 181531e31b8aSbellard return 0; 181631e31b8aSbellard } 181731e31b8aSbellard } 181831e31b8aSbellard 181931e31b8aSbellard free(elf_phdata); 182031e31b8aSbellard 182193fcfe39Saliguori if (qemu_log_enabled()) 1822689f936fSbellard load_symbols(&elf_ex, bprm->fd); 1823689f936fSbellard 182431e31b8aSbellard if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); 182531e31b8aSbellard info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); 182631e31b8aSbellard 182731e31b8aSbellard #ifdef LOW_ELF_STACK 182831e31b8aSbellard info->start_stack = bprm->p = elf_stack - 4; 182931e31b8aSbellard #endif 183053a5960aSpbrook bprm->p = create_elf_tables(bprm->p, 183131e31b8aSbellard bprm->argc, 183231e31b8aSbellard bprm->envc, 1833a1516e92Sbellard &elf_ex, 183409bfb054Sbellard load_addr, load_bias, 183531e31b8aSbellard interp_load_addr, 183631e31b8aSbellard (interpreter_type == INTERPRETER_AOUT ? 0 : 1), 183731e31b8aSbellard info); 183892a343daSj_mayer info->load_addr = reloc_func_desc; 183931e31b8aSbellard info->start_brk = info->brk = elf_brk; 184031e31b8aSbellard info->end_code = end_code; 184131e31b8aSbellard info->start_code = start_code; 1842863cf0b7Sj_mayer info->start_data = start_data; 184331e31b8aSbellard info->end_data = end_data; 184431e31b8aSbellard info->start_stack = bprm->p; 184531e31b8aSbellard 184631e31b8aSbellard /* Calling set_brk effectively mmaps the pages that we need for the bss and break 184731e31b8aSbellard sections */ 184831e31b8aSbellard set_brk(elf_bss, elf_brk); 184931e31b8aSbellard 1850768a4a36Sths padzero(elf_bss, elf_brk); 185131e31b8aSbellard 185231e31b8aSbellard #if 0 185331e31b8aSbellard printf("(start_brk) %x\n" , info->start_brk); 185431e31b8aSbellard printf("(end_code) %x\n" , info->end_code); 185531e31b8aSbellard printf("(start_code) %x\n" , info->start_code); 185631e31b8aSbellard printf("(end_data) %x\n" , info->end_data); 185731e31b8aSbellard printf("(start_stack) %x\n" , info->start_stack); 185831e31b8aSbellard printf("(brk) %x\n" , info->brk); 185931e31b8aSbellard #endif 186031e31b8aSbellard 186131e31b8aSbellard if ( info->personality == PER_SVR4 ) 186231e31b8aSbellard { 186331e31b8aSbellard /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 186431e31b8aSbellard and some applications "depend" upon this behavior. 186531e31b8aSbellard Since we do not have the power to recompile these, we 186631e31b8aSbellard emulate the SVr4 behavior. Sigh. */ 186783fb7adfSbellard mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, 186831e31b8aSbellard MAP_FIXED | MAP_PRIVATE, -1, 0); 186931e31b8aSbellard } 187031e31b8aSbellard 187131e31b8aSbellard info->entry = elf_entry; 187231e31b8aSbellard 1873edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 1874edf8e2afSMika Westerberg bprm->core_dump = &elf_core_dump; 1875edf8e2afSMika Westerberg #endif 1876edf8e2afSMika Westerberg 187731e31b8aSbellard return 0; 187831e31b8aSbellard } 187931e31b8aSbellard 1880edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 1881edf8e2afSMika Westerberg 1882edf8e2afSMika Westerberg /* 1883edf8e2afSMika Westerberg * Definitions to generate Intel SVR4-like core files. 1884a2547a13SLaurent Desnogues * These mostly have the same names as the SVR4 types with "target_elf_" 1885edf8e2afSMika Westerberg * tacked on the front to prevent clashes with linux definitions, 1886edf8e2afSMika Westerberg * and the typedef forms have been avoided. This is mostly like 1887edf8e2afSMika Westerberg * the SVR4 structure, but more Linuxy, with things that Linux does 1888edf8e2afSMika Westerberg * not support and which gdb doesn't really use excluded. 1889edf8e2afSMika Westerberg * 1890edf8e2afSMika Westerberg * Fields we don't dump (their contents is zero) in linux-user qemu 1891edf8e2afSMika Westerberg * are marked with XXX. 1892edf8e2afSMika Westerberg * 1893edf8e2afSMika Westerberg * Core dump code is copied from linux kernel (fs/binfmt_elf.c). 1894edf8e2afSMika Westerberg * 1895edf8e2afSMika Westerberg * Porting ELF coredump for target is (quite) simple process. First you 1896dd0a3651SNathan Froyd * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for 1897edf8e2afSMika Westerberg * the target resides): 1898edf8e2afSMika Westerberg * 1899edf8e2afSMika Westerberg * #define USE_ELF_CORE_DUMP 1900edf8e2afSMika Westerberg * 1901edf8e2afSMika Westerberg * Next you define type of register set used for dumping. ELF specification 1902edf8e2afSMika Westerberg * says that it needs to be array of elf_greg_t that has size of ELF_NREG. 1903edf8e2afSMika Westerberg * 1904c227f099SAnthony Liguori * typedef <target_regtype> target_elf_greg_t; 1905edf8e2afSMika Westerberg * #define ELF_NREG <number of registers> 1906c227f099SAnthony Liguori * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1907edf8e2afSMika Westerberg * 1908edf8e2afSMika Westerberg * Last step is to implement target specific function that copies registers 1909edf8e2afSMika Westerberg * from given cpu into just specified register set. Prototype is: 1910edf8e2afSMika Westerberg * 1911c227f099SAnthony Liguori * static void elf_core_copy_regs(taret_elf_gregset_t *regs, 1912a2547a13SLaurent Desnogues * const CPUState *env); 1913edf8e2afSMika Westerberg * 1914edf8e2afSMika Westerberg * Parameters: 1915edf8e2afSMika Westerberg * regs - copy register values into here (allocated and zeroed by caller) 1916edf8e2afSMika Westerberg * env - copy registers from here 1917edf8e2afSMika Westerberg * 1918edf8e2afSMika Westerberg * Example for ARM target is provided in this file. 1919edf8e2afSMika Westerberg */ 1920edf8e2afSMika Westerberg 1921edf8e2afSMika Westerberg /* An ELF note in memory */ 1922edf8e2afSMika Westerberg struct memelfnote { 1923edf8e2afSMika Westerberg const char *name; 1924edf8e2afSMika Westerberg size_t namesz; 1925edf8e2afSMika Westerberg size_t namesz_rounded; 1926edf8e2afSMika Westerberg int type; 1927edf8e2afSMika Westerberg size_t datasz; 1928edf8e2afSMika Westerberg void *data; 1929edf8e2afSMika Westerberg size_t notesz; 1930edf8e2afSMika Westerberg }; 1931edf8e2afSMika Westerberg 1932a2547a13SLaurent Desnogues struct target_elf_siginfo { 1933edf8e2afSMika Westerberg int si_signo; /* signal number */ 1934edf8e2afSMika Westerberg int si_code; /* extra code */ 1935edf8e2afSMika Westerberg int si_errno; /* errno */ 1936edf8e2afSMika Westerberg }; 1937edf8e2afSMika Westerberg 1938a2547a13SLaurent Desnogues struct target_elf_prstatus { 1939a2547a13SLaurent Desnogues struct target_elf_siginfo pr_info; /* Info associated with signal */ 1940edf8e2afSMika Westerberg short pr_cursig; /* Current signal */ 1941edf8e2afSMika Westerberg target_ulong pr_sigpend; /* XXX */ 1942edf8e2afSMika Westerberg target_ulong pr_sighold; /* XXX */ 1943c227f099SAnthony Liguori target_pid_t pr_pid; 1944c227f099SAnthony Liguori target_pid_t pr_ppid; 1945c227f099SAnthony Liguori target_pid_t pr_pgrp; 1946c227f099SAnthony Liguori target_pid_t pr_sid; 1947edf8e2afSMika Westerberg struct target_timeval pr_utime; /* XXX User time */ 1948edf8e2afSMika Westerberg struct target_timeval pr_stime; /* XXX System time */ 1949edf8e2afSMika Westerberg struct target_timeval pr_cutime; /* XXX Cumulative user time */ 1950edf8e2afSMika Westerberg struct target_timeval pr_cstime; /* XXX Cumulative system time */ 1951c227f099SAnthony Liguori target_elf_gregset_t pr_reg; /* GP registers */ 1952edf8e2afSMika Westerberg int pr_fpvalid; /* XXX */ 1953edf8e2afSMika Westerberg }; 1954edf8e2afSMika Westerberg 1955edf8e2afSMika Westerberg #define ELF_PRARGSZ (80) /* Number of chars for args */ 1956edf8e2afSMika Westerberg 1957a2547a13SLaurent Desnogues struct target_elf_prpsinfo { 1958edf8e2afSMika Westerberg char pr_state; /* numeric process state */ 1959edf8e2afSMika Westerberg char pr_sname; /* char for pr_state */ 1960edf8e2afSMika Westerberg char pr_zomb; /* zombie */ 1961edf8e2afSMika Westerberg char pr_nice; /* nice val */ 1962edf8e2afSMika Westerberg target_ulong pr_flag; /* flags */ 1963c227f099SAnthony Liguori target_uid_t pr_uid; 1964c227f099SAnthony Liguori target_gid_t pr_gid; 1965c227f099SAnthony Liguori target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; 1966edf8e2afSMika Westerberg /* Lots missing */ 1967edf8e2afSMika Westerberg char pr_fname[16]; /* filename of executable */ 1968edf8e2afSMika Westerberg char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ 1969edf8e2afSMika Westerberg }; 1970edf8e2afSMika Westerberg 1971edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */ 1972edf8e2afSMika Westerberg struct elf_thread_status { 197372cf2d4fSBlue Swirl QTAILQ_ENTRY(elf_thread_status) ets_link; 1974a2547a13SLaurent Desnogues struct target_elf_prstatus prstatus; /* NT_PRSTATUS */ 1975edf8e2afSMika Westerberg #if 0 1976edf8e2afSMika Westerberg elf_fpregset_t fpu; /* NT_PRFPREG */ 1977edf8e2afSMika Westerberg struct task_struct *thread; 1978edf8e2afSMika Westerberg elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */ 1979edf8e2afSMika Westerberg #endif 1980edf8e2afSMika Westerberg struct memelfnote notes[1]; 1981edf8e2afSMika Westerberg int num_notes; 1982edf8e2afSMika Westerberg }; 1983edf8e2afSMika Westerberg 1984edf8e2afSMika Westerberg struct elf_note_info { 1985edf8e2afSMika Westerberg struct memelfnote *notes; 1986a2547a13SLaurent Desnogues struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */ 1987a2547a13SLaurent Desnogues struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */ 1988edf8e2afSMika Westerberg 198972cf2d4fSBlue Swirl QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list; 1990edf8e2afSMika Westerberg #if 0 1991edf8e2afSMika Westerberg /* 1992edf8e2afSMika Westerberg * Current version of ELF coredump doesn't support 1993edf8e2afSMika Westerberg * dumping fp regs etc. 1994edf8e2afSMika Westerberg */ 1995edf8e2afSMika Westerberg elf_fpregset_t *fpu; 1996edf8e2afSMika Westerberg elf_fpxregset_t *xfpu; 1997edf8e2afSMika Westerberg int thread_status_size; 1998edf8e2afSMika Westerberg #endif 1999edf8e2afSMika Westerberg int notes_size; 2000edf8e2afSMika Westerberg int numnote; 2001edf8e2afSMika Westerberg }; 2002edf8e2afSMika Westerberg 2003edf8e2afSMika Westerberg struct vm_area_struct { 2004edf8e2afSMika Westerberg abi_ulong vma_start; /* start vaddr of memory region */ 2005edf8e2afSMika Westerberg abi_ulong vma_end; /* end vaddr of memory region */ 2006edf8e2afSMika Westerberg abi_ulong vma_flags; /* protection etc. flags for the region */ 200772cf2d4fSBlue Swirl QTAILQ_ENTRY(vm_area_struct) vma_link; 2008edf8e2afSMika Westerberg }; 2009edf8e2afSMika Westerberg 2010edf8e2afSMika Westerberg struct mm_struct { 201172cf2d4fSBlue Swirl QTAILQ_HEAD(, vm_area_struct) mm_mmap; 2012edf8e2afSMika Westerberg int mm_count; /* number of mappings */ 2013edf8e2afSMika Westerberg }; 2014edf8e2afSMika Westerberg 2015edf8e2afSMika Westerberg static struct mm_struct *vma_init(void); 2016edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *); 2017edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *, abi_ulong, 2018edf8e2afSMika Westerberg abi_ulong, abi_ulong); 2019edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *); 2020edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *); 2021edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *); 2022edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *); 2023edf8e2afSMika Westerberg static int vma_walker(void *priv, unsigned long start, unsigned long end, 2024edf8e2afSMika Westerberg unsigned long flags); 2025edf8e2afSMika Westerberg 2026edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); 2027edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int, 2028edf8e2afSMika Westerberg unsigned int, void *); 2029a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); 2030a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); 2031edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *); 2032edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); 2033edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *); 2034edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *); 2035edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *, long, const CPUState *); 2036edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *, const CPUState *); 2037edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t); 2038edf8e2afSMika Westerberg 2039edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t); 2040edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int); 2041edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int); 2042edf8e2afSMika Westerberg 2043edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2044a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *); 2045a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *); 2046edf8e2afSMika Westerberg 2047a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus) 2048edf8e2afSMika Westerberg { 2049edf8e2afSMika Westerberg prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo); 2050edf8e2afSMika Westerberg prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code); 2051edf8e2afSMika Westerberg prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno); 2052edf8e2afSMika Westerberg prstatus->pr_cursig = tswap16(prstatus->pr_cursig); 2053edf8e2afSMika Westerberg prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend); 2054edf8e2afSMika Westerberg prstatus->pr_sighold = tswapl(prstatus->pr_sighold); 2055edf8e2afSMika Westerberg prstatus->pr_pid = tswap32(prstatus->pr_pid); 2056edf8e2afSMika Westerberg prstatus->pr_ppid = tswap32(prstatus->pr_ppid); 2057edf8e2afSMika Westerberg prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp); 2058edf8e2afSMika Westerberg prstatus->pr_sid = tswap32(prstatus->pr_sid); 2059edf8e2afSMika Westerberg /* cpu times are not filled, so we skip them */ 2060edf8e2afSMika Westerberg /* regs should be in correct format already */ 2061edf8e2afSMika Westerberg prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid); 2062edf8e2afSMika Westerberg } 2063edf8e2afSMika Westerberg 2064a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) 2065edf8e2afSMika Westerberg { 2066edf8e2afSMika Westerberg psinfo->pr_flag = tswapl(psinfo->pr_flag); 2067edf8e2afSMika Westerberg psinfo->pr_uid = tswap16(psinfo->pr_uid); 2068edf8e2afSMika Westerberg psinfo->pr_gid = tswap16(psinfo->pr_gid); 2069edf8e2afSMika Westerberg psinfo->pr_pid = tswap32(psinfo->pr_pid); 2070edf8e2afSMika Westerberg psinfo->pr_ppid = tswap32(psinfo->pr_ppid); 2071edf8e2afSMika Westerberg psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp); 2072edf8e2afSMika Westerberg psinfo->pr_sid = tswap32(psinfo->pr_sid); 2073edf8e2afSMika Westerberg } 2074edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 2075edf8e2afSMika Westerberg 2076edf8e2afSMika Westerberg /* 2077edf8e2afSMika Westerberg * Minimal support for linux memory regions. These are needed 2078edf8e2afSMika Westerberg * when we are finding out what memory exactly belongs to 2079edf8e2afSMika Westerberg * emulated process. No locks needed here, as long as 2080edf8e2afSMika Westerberg * thread that received the signal is stopped. 2081edf8e2afSMika Westerberg */ 2082edf8e2afSMika Westerberg 2083edf8e2afSMika Westerberg static struct mm_struct *vma_init(void) 2084edf8e2afSMika Westerberg { 2085edf8e2afSMika Westerberg struct mm_struct *mm; 2086edf8e2afSMika Westerberg 2087edf8e2afSMika Westerberg if ((mm = qemu_malloc(sizeof (*mm))) == NULL) 2088edf8e2afSMika Westerberg return (NULL); 2089edf8e2afSMika Westerberg 2090edf8e2afSMika Westerberg mm->mm_count = 0; 209172cf2d4fSBlue Swirl QTAILQ_INIT(&mm->mm_mmap); 2092edf8e2afSMika Westerberg 2093edf8e2afSMika Westerberg return (mm); 2094edf8e2afSMika Westerberg } 2095edf8e2afSMika Westerberg 2096edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm) 2097edf8e2afSMika Westerberg { 2098edf8e2afSMika Westerberg struct vm_area_struct *vma; 2099edf8e2afSMika Westerberg 2100edf8e2afSMika Westerberg while ((vma = vma_first(mm)) != NULL) { 210172cf2d4fSBlue Swirl QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link); 2102edf8e2afSMika Westerberg qemu_free(vma); 2103edf8e2afSMika Westerberg } 2104edf8e2afSMika Westerberg qemu_free(mm); 2105edf8e2afSMika Westerberg } 2106edf8e2afSMika Westerberg 2107edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *mm, abi_ulong start, 2108edf8e2afSMika Westerberg abi_ulong end, abi_ulong flags) 2109edf8e2afSMika Westerberg { 2110edf8e2afSMika Westerberg struct vm_area_struct *vma; 2111edf8e2afSMika Westerberg 2112edf8e2afSMika Westerberg if ((vma = qemu_mallocz(sizeof (*vma))) == NULL) 2113edf8e2afSMika Westerberg return (-1); 2114edf8e2afSMika Westerberg 2115edf8e2afSMika Westerberg vma->vma_start = start; 2116edf8e2afSMika Westerberg vma->vma_end = end; 2117edf8e2afSMika Westerberg vma->vma_flags = flags; 2118edf8e2afSMika Westerberg 211972cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link); 2120edf8e2afSMika Westerberg mm->mm_count++; 2121edf8e2afSMika Westerberg 2122edf8e2afSMika Westerberg return (0); 2123edf8e2afSMika Westerberg } 2124edf8e2afSMika Westerberg 2125edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm) 2126edf8e2afSMika Westerberg { 212772cf2d4fSBlue Swirl return (QTAILQ_FIRST(&mm->mm_mmap)); 2128edf8e2afSMika Westerberg } 2129edf8e2afSMika Westerberg 2130edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma) 2131edf8e2afSMika Westerberg { 213272cf2d4fSBlue Swirl return (QTAILQ_NEXT(vma, vma_link)); 2133edf8e2afSMika Westerberg } 2134edf8e2afSMika Westerberg 2135edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm) 2136edf8e2afSMika Westerberg { 2137edf8e2afSMika Westerberg return (mm->mm_count); 2138edf8e2afSMika Westerberg } 2139edf8e2afSMika Westerberg 2140edf8e2afSMika Westerberg /* 2141edf8e2afSMika Westerberg * Calculate file (dump) size of given memory region. 2142edf8e2afSMika Westerberg */ 2143edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma) 2144edf8e2afSMika Westerberg { 2145edf8e2afSMika Westerberg /* if we cannot even read the first page, skip it */ 2146edf8e2afSMika Westerberg if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE)) 2147edf8e2afSMika Westerberg return (0); 2148edf8e2afSMika Westerberg 2149edf8e2afSMika Westerberg /* 2150edf8e2afSMika Westerberg * Usually we don't dump executable pages as they contain 2151edf8e2afSMika Westerberg * non-writable code that debugger can read directly from 2152edf8e2afSMika Westerberg * target library etc. However, thread stacks are marked 2153edf8e2afSMika Westerberg * also executable so we read in first page of given region 2154edf8e2afSMika Westerberg * and check whether it contains elf header. If there is 2155edf8e2afSMika Westerberg * no elf header, we dump it. 2156edf8e2afSMika Westerberg */ 2157edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) { 2158edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 2159edf8e2afSMika Westerberg 2160edf8e2afSMika Westerberg copy_from_user(page, vma->vma_start, sizeof (page)); 2161edf8e2afSMika Westerberg if ((page[EI_MAG0] == ELFMAG0) && 2162edf8e2afSMika Westerberg (page[EI_MAG1] == ELFMAG1) && 2163edf8e2afSMika Westerberg (page[EI_MAG2] == ELFMAG2) && 2164edf8e2afSMika Westerberg (page[EI_MAG3] == ELFMAG3)) { 2165edf8e2afSMika Westerberg /* 2166edf8e2afSMika Westerberg * Mappings are possibly from ELF binary. Don't dump 2167edf8e2afSMika Westerberg * them. 2168edf8e2afSMika Westerberg */ 2169edf8e2afSMika Westerberg return (0); 2170edf8e2afSMika Westerberg } 2171edf8e2afSMika Westerberg } 2172edf8e2afSMika Westerberg 2173edf8e2afSMika Westerberg return (vma->vma_end - vma->vma_start); 2174edf8e2afSMika Westerberg } 2175edf8e2afSMika Westerberg 2176edf8e2afSMika Westerberg static int vma_walker(void *priv, unsigned long start, unsigned long end, 2177edf8e2afSMika Westerberg unsigned long flags) 2178edf8e2afSMika Westerberg { 2179edf8e2afSMika Westerberg struct mm_struct *mm = (struct mm_struct *)priv; 2180edf8e2afSMika Westerberg 2181edf8e2afSMika Westerberg /* 2182edf8e2afSMika Westerberg * Don't dump anything that qemu has reserved for internal use. 2183edf8e2afSMika Westerberg */ 2184edf8e2afSMika Westerberg if (flags & PAGE_RESERVED) 2185edf8e2afSMika Westerberg return (0); 2186edf8e2afSMika Westerberg 2187edf8e2afSMika Westerberg vma_add_mapping(mm, start, end, flags); 2188edf8e2afSMika Westerberg return (0); 2189edf8e2afSMika Westerberg } 2190edf8e2afSMika Westerberg 2191edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type, 2192edf8e2afSMika Westerberg unsigned int sz, void *data) 2193edf8e2afSMika Westerberg { 2194edf8e2afSMika Westerberg unsigned int namesz; 2195edf8e2afSMika Westerberg 2196edf8e2afSMika Westerberg namesz = strlen(name) + 1; 2197edf8e2afSMika Westerberg note->name = name; 2198edf8e2afSMika Westerberg note->namesz = namesz; 2199edf8e2afSMika Westerberg note->namesz_rounded = roundup(namesz, sizeof (int32_t)); 2200edf8e2afSMika Westerberg note->type = type; 2201edf8e2afSMika Westerberg note->datasz = roundup(sz, sizeof (int32_t));; 2202edf8e2afSMika Westerberg note->data = data; 2203edf8e2afSMika Westerberg 2204edf8e2afSMika Westerberg /* 2205edf8e2afSMika Westerberg * We calculate rounded up note size here as specified by 2206edf8e2afSMika Westerberg * ELF document. 2207edf8e2afSMika Westerberg */ 2208edf8e2afSMika Westerberg note->notesz = sizeof (struct elf_note) + 2209edf8e2afSMika Westerberg note->namesz_rounded + note->datasz; 2210edf8e2afSMika Westerberg } 2211edf8e2afSMika Westerberg 2212edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, 2213edf8e2afSMika Westerberg uint32_t flags) 2214edf8e2afSMika Westerberg { 2215edf8e2afSMika Westerberg (void) memset(elf, 0, sizeof(*elf)); 2216edf8e2afSMika Westerberg 2217edf8e2afSMika Westerberg (void) memcpy(elf->e_ident, ELFMAG, SELFMAG); 2218edf8e2afSMika Westerberg elf->e_ident[EI_CLASS] = ELF_CLASS; 2219edf8e2afSMika Westerberg elf->e_ident[EI_DATA] = ELF_DATA; 2220edf8e2afSMika Westerberg elf->e_ident[EI_VERSION] = EV_CURRENT; 2221edf8e2afSMika Westerberg elf->e_ident[EI_OSABI] = ELF_OSABI; 2222edf8e2afSMika Westerberg 2223edf8e2afSMika Westerberg elf->e_type = ET_CORE; 2224edf8e2afSMika Westerberg elf->e_machine = machine; 2225edf8e2afSMika Westerberg elf->e_version = EV_CURRENT; 2226edf8e2afSMika Westerberg elf->e_phoff = sizeof(struct elfhdr); 2227edf8e2afSMika Westerberg elf->e_flags = flags; 2228edf8e2afSMika Westerberg elf->e_ehsize = sizeof(struct elfhdr); 2229edf8e2afSMika Westerberg elf->e_phentsize = sizeof(struct elf_phdr); 2230edf8e2afSMika Westerberg elf->e_phnum = segs; 2231edf8e2afSMika Westerberg 2232edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2233edf8e2afSMika Westerberg bswap_ehdr(elf); 2234edf8e2afSMika Westerberg #endif 2235edf8e2afSMika Westerberg } 2236edf8e2afSMika Westerberg 2237edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) 2238edf8e2afSMika Westerberg { 2239edf8e2afSMika Westerberg phdr->p_type = PT_NOTE; 2240edf8e2afSMika Westerberg phdr->p_offset = offset; 2241edf8e2afSMika Westerberg phdr->p_vaddr = 0; 2242edf8e2afSMika Westerberg phdr->p_paddr = 0; 2243edf8e2afSMika Westerberg phdr->p_filesz = sz; 2244edf8e2afSMika Westerberg phdr->p_memsz = 0; 2245edf8e2afSMika Westerberg phdr->p_flags = 0; 2246edf8e2afSMika Westerberg phdr->p_align = 0; 2247edf8e2afSMika Westerberg 2248edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2249edf8e2afSMika Westerberg bswap_phdr(phdr); 2250edf8e2afSMika Westerberg #endif 2251edf8e2afSMika Westerberg } 2252edf8e2afSMika Westerberg 2253edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note) 2254edf8e2afSMika Westerberg { 2255edf8e2afSMika Westerberg return (note->notesz); 2256edf8e2afSMika Westerberg } 2257edf8e2afSMika Westerberg 2258a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus, 2259edf8e2afSMika Westerberg const TaskState *ts, int signr) 2260edf8e2afSMika Westerberg { 2261edf8e2afSMika Westerberg (void) memset(prstatus, 0, sizeof (*prstatus)); 2262edf8e2afSMika Westerberg prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 2263edf8e2afSMika Westerberg prstatus->pr_pid = ts->ts_tid; 2264edf8e2afSMika Westerberg prstatus->pr_ppid = getppid(); 2265edf8e2afSMika Westerberg prstatus->pr_pgrp = getpgrp(); 2266edf8e2afSMika Westerberg prstatus->pr_sid = getsid(0); 2267edf8e2afSMika Westerberg 2268edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2269edf8e2afSMika Westerberg bswap_prstatus(prstatus); 2270edf8e2afSMika Westerberg #endif 2271edf8e2afSMika Westerberg } 2272edf8e2afSMika Westerberg 2273a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) 2274edf8e2afSMika Westerberg { 2275edf8e2afSMika Westerberg char *filename, *base_filename; 2276edf8e2afSMika Westerberg unsigned int i, len; 2277edf8e2afSMika Westerberg 2278edf8e2afSMika Westerberg (void) memset(psinfo, 0, sizeof (*psinfo)); 2279edf8e2afSMika Westerberg 2280edf8e2afSMika Westerberg len = ts->info->arg_end - ts->info->arg_start; 2281edf8e2afSMika Westerberg if (len >= ELF_PRARGSZ) 2282edf8e2afSMika Westerberg len = ELF_PRARGSZ - 1; 2283edf8e2afSMika Westerberg if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len)) 2284edf8e2afSMika Westerberg return -EFAULT; 2285edf8e2afSMika Westerberg for (i = 0; i < len; i++) 2286edf8e2afSMika Westerberg if (psinfo->pr_psargs[i] == 0) 2287edf8e2afSMika Westerberg psinfo->pr_psargs[i] = ' '; 2288edf8e2afSMika Westerberg psinfo->pr_psargs[len] = 0; 2289edf8e2afSMika Westerberg 2290edf8e2afSMika Westerberg psinfo->pr_pid = getpid(); 2291edf8e2afSMika Westerberg psinfo->pr_ppid = getppid(); 2292edf8e2afSMika Westerberg psinfo->pr_pgrp = getpgrp(); 2293edf8e2afSMika Westerberg psinfo->pr_sid = getsid(0); 2294edf8e2afSMika Westerberg psinfo->pr_uid = getuid(); 2295edf8e2afSMika Westerberg psinfo->pr_gid = getgid(); 2296edf8e2afSMika Westerberg 2297edf8e2afSMika Westerberg filename = strdup(ts->bprm->filename); 2298edf8e2afSMika Westerberg base_filename = strdup(basename(filename)); 2299edf8e2afSMika Westerberg (void) strncpy(psinfo->pr_fname, base_filename, 2300edf8e2afSMika Westerberg sizeof(psinfo->pr_fname)); 2301edf8e2afSMika Westerberg free(base_filename); 2302edf8e2afSMika Westerberg free(filename); 2303edf8e2afSMika Westerberg 2304edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2305edf8e2afSMika Westerberg bswap_psinfo(psinfo); 2306edf8e2afSMika Westerberg #endif 2307edf8e2afSMika Westerberg return (0); 2308edf8e2afSMika Westerberg } 2309edf8e2afSMika Westerberg 2310edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) 2311edf8e2afSMika Westerberg { 2312edf8e2afSMika Westerberg elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; 2313edf8e2afSMika Westerberg elf_addr_t orig_auxv = auxv; 2314edf8e2afSMika Westerberg abi_ulong val; 2315edf8e2afSMika Westerberg void *ptr; 2316edf8e2afSMika Westerberg int i, len; 2317edf8e2afSMika Westerberg 2318edf8e2afSMika Westerberg /* 2319edf8e2afSMika Westerberg * Auxiliary vector is stored in target process stack. It contains 2320edf8e2afSMika Westerberg * {type, value} pairs that we need to dump into note. This is not 2321edf8e2afSMika Westerberg * strictly necessary but we do it here for sake of completeness. 2322edf8e2afSMika Westerberg */ 2323edf8e2afSMika Westerberg 2324edf8e2afSMika Westerberg /* find out lenght of the vector, AT_NULL is terminator */ 2325edf8e2afSMika Westerberg i = len = 0; 2326edf8e2afSMika Westerberg do { 2327edf8e2afSMika Westerberg get_user_ual(val, auxv); 2328edf8e2afSMika Westerberg i += 2; 2329edf8e2afSMika Westerberg auxv += 2 * sizeof (elf_addr_t); 2330edf8e2afSMika Westerberg } while (val != AT_NULL); 2331edf8e2afSMika Westerberg len = i * sizeof (elf_addr_t); 2332edf8e2afSMika Westerberg 2333edf8e2afSMika Westerberg /* read in whole auxv vector and copy it to memelfnote */ 2334edf8e2afSMika Westerberg ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); 2335edf8e2afSMika Westerberg if (ptr != NULL) { 2336edf8e2afSMika Westerberg fill_note(note, "CORE", NT_AUXV, len, ptr); 2337edf8e2afSMika Westerberg unlock_user(ptr, auxv, len); 2338edf8e2afSMika Westerberg } 2339edf8e2afSMika Westerberg } 2340edf8e2afSMika Westerberg 2341edf8e2afSMika Westerberg /* 2342edf8e2afSMika Westerberg * Constructs name of coredump file. We have following convention 2343edf8e2afSMika Westerberg * for the name: 2344edf8e2afSMika Westerberg * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core 2345edf8e2afSMika Westerberg * 2346edf8e2afSMika Westerberg * Returns 0 in case of success, -1 otherwise (errno is set). 2347edf8e2afSMika Westerberg */ 2348edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf, 2349edf8e2afSMika Westerberg size_t bufsize) 2350edf8e2afSMika Westerberg { 2351edf8e2afSMika Westerberg char timestamp[64]; 2352edf8e2afSMika Westerberg char *filename = NULL; 2353edf8e2afSMika Westerberg char *base_filename = NULL; 2354edf8e2afSMika Westerberg struct timeval tv; 2355edf8e2afSMika Westerberg struct tm tm; 2356edf8e2afSMika Westerberg 2357edf8e2afSMika Westerberg assert(bufsize >= PATH_MAX); 2358edf8e2afSMika Westerberg 2359edf8e2afSMika Westerberg if (gettimeofday(&tv, NULL) < 0) { 2360edf8e2afSMika Westerberg (void) fprintf(stderr, "unable to get current timestamp: %s", 2361edf8e2afSMika Westerberg strerror(errno)); 2362edf8e2afSMika Westerberg return (-1); 2363edf8e2afSMika Westerberg } 2364edf8e2afSMika Westerberg 2365edf8e2afSMika Westerberg filename = strdup(ts->bprm->filename); 2366edf8e2afSMika Westerberg base_filename = strdup(basename(filename)); 2367edf8e2afSMika Westerberg (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", 2368edf8e2afSMika Westerberg localtime_r(&tv.tv_sec, &tm)); 2369edf8e2afSMika Westerberg (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", 2370edf8e2afSMika Westerberg base_filename, timestamp, (int)getpid()); 2371edf8e2afSMika Westerberg free(base_filename); 2372edf8e2afSMika Westerberg free(filename); 2373edf8e2afSMika Westerberg 2374edf8e2afSMika Westerberg return (0); 2375edf8e2afSMika Westerberg } 2376edf8e2afSMika Westerberg 2377edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size) 2378edf8e2afSMika Westerberg { 2379edf8e2afSMika Westerberg const char *bufp = (const char *)ptr; 2380edf8e2afSMika Westerberg ssize_t bytes_written, bytes_left; 2381edf8e2afSMika Westerberg struct rlimit dumpsize; 2382edf8e2afSMika Westerberg off_t pos; 2383edf8e2afSMika Westerberg 2384edf8e2afSMika Westerberg bytes_written = 0; 2385edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 2386edf8e2afSMika Westerberg if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { 2387edf8e2afSMika Westerberg if (errno == ESPIPE) { /* not a seekable stream */ 2388edf8e2afSMika Westerberg bytes_left = size; 2389edf8e2afSMika Westerberg } else { 2390edf8e2afSMika Westerberg return pos; 2391edf8e2afSMika Westerberg } 2392edf8e2afSMika Westerberg } else { 2393edf8e2afSMika Westerberg if (dumpsize.rlim_cur <= pos) { 2394edf8e2afSMika Westerberg return -1; 2395edf8e2afSMika Westerberg } else if (dumpsize.rlim_cur == RLIM_INFINITY) { 2396edf8e2afSMika Westerberg bytes_left = size; 2397edf8e2afSMika Westerberg } else { 2398edf8e2afSMika Westerberg size_t limit_left=dumpsize.rlim_cur - pos; 2399edf8e2afSMika Westerberg bytes_left = limit_left >= size ? size : limit_left ; 2400edf8e2afSMika Westerberg } 2401edf8e2afSMika Westerberg } 2402edf8e2afSMika Westerberg 2403edf8e2afSMika Westerberg /* 2404edf8e2afSMika Westerberg * In normal conditions, single write(2) should do but 2405edf8e2afSMika Westerberg * in case of socket etc. this mechanism is more portable. 2406edf8e2afSMika Westerberg */ 2407edf8e2afSMika Westerberg do { 2408edf8e2afSMika Westerberg bytes_written = write(fd, bufp, bytes_left); 2409edf8e2afSMika Westerberg if (bytes_written < 0) { 2410edf8e2afSMika Westerberg if (errno == EINTR) 2411edf8e2afSMika Westerberg continue; 2412edf8e2afSMika Westerberg return (-1); 2413edf8e2afSMika Westerberg } else if (bytes_written == 0) { /* eof */ 2414edf8e2afSMika Westerberg return (-1); 2415edf8e2afSMika Westerberg } 2416edf8e2afSMika Westerberg bufp += bytes_written; 2417edf8e2afSMika Westerberg bytes_left -= bytes_written; 2418edf8e2afSMika Westerberg } while (bytes_left > 0); 2419edf8e2afSMika Westerberg 2420edf8e2afSMika Westerberg return (0); 2421edf8e2afSMika Westerberg } 2422edf8e2afSMika Westerberg 2423edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd) 2424edf8e2afSMika Westerberg { 2425edf8e2afSMika Westerberg struct elf_note en; 2426edf8e2afSMika Westerberg 2427edf8e2afSMika Westerberg en.n_namesz = men->namesz; 2428edf8e2afSMika Westerberg en.n_type = men->type; 2429edf8e2afSMika Westerberg en.n_descsz = men->datasz; 2430edf8e2afSMika Westerberg 2431edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2432edf8e2afSMika Westerberg bswap_note(&en); 2433edf8e2afSMika Westerberg #endif 2434edf8e2afSMika Westerberg 2435edf8e2afSMika Westerberg if (dump_write(fd, &en, sizeof(en)) != 0) 2436edf8e2afSMika Westerberg return (-1); 2437edf8e2afSMika Westerberg if (dump_write(fd, men->name, men->namesz_rounded) != 0) 2438edf8e2afSMika Westerberg return (-1); 2439edf8e2afSMika Westerberg if (dump_write(fd, men->data, men->datasz) != 0) 2440edf8e2afSMika Westerberg return (-1); 2441edf8e2afSMika Westerberg 2442edf8e2afSMika Westerberg return (0); 2443edf8e2afSMika Westerberg } 2444edf8e2afSMika Westerberg 2445edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *info, const CPUState *env) 2446edf8e2afSMika Westerberg { 2447edf8e2afSMika Westerberg TaskState *ts = (TaskState *)env->opaque; 2448edf8e2afSMika Westerberg struct elf_thread_status *ets; 2449edf8e2afSMika Westerberg 2450edf8e2afSMika Westerberg ets = qemu_mallocz(sizeof (*ets)); 2451edf8e2afSMika Westerberg ets->num_notes = 1; /* only prstatus is dumped */ 2452edf8e2afSMika Westerberg fill_prstatus(&ets->prstatus, ts, 0); 2453edf8e2afSMika Westerberg elf_core_copy_regs(&ets->prstatus.pr_reg, env); 2454edf8e2afSMika Westerberg fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus), 2455edf8e2afSMika Westerberg &ets->prstatus); 2456edf8e2afSMika Westerberg 245772cf2d4fSBlue Swirl QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link); 2458edf8e2afSMika Westerberg 2459edf8e2afSMika Westerberg info->notes_size += note_size(&ets->notes[0]); 2460edf8e2afSMika Westerberg } 2461edf8e2afSMika Westerberg 2462edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info, 2463edf8e2afSMika Westerberg long signr, const CPUState *env) 2464edf8e2afSMika Westerberg { 2465edf8e2afSMika Westerberg #define NUMNOTES 3 2466edf8e2afSMika Westerberg CPUState *cpu = NULL; 2467edf8e2afSMika Westerberg TaskState *ts = (TaskState *)env->opaque; 2468edf8e2afSMika Westerberg int i; 2469edf8e2afSMika Westerberg 2470edf8e2afSMika Westerberg (void) memset(info, 0, sizeof (*info)); 2471edf8e2afSMika Westerberg 247272cf2d4fSBlue Swirl QTAILQ_INIT(&info->thread_list); 2473edf8e2afSMika Westerberg 2474edf8e2afSMika Westerberg info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote)); 2475edf8e2afSMika Westerberg if (info->notes == NULL) 2476edf8e2afSMika Westerberg return (-ENOMEM); 2477edf8e2afSMika Westerberg info->prstatus = qemu_mallocz(sizeof (*info->prstatus)); 2478edf8e2afSMika Westerberg if (info->prstatus == NULL) 2479edf8e2afSMika Westerberg return (-ENOMEM); 2480edf8e2afSMika Westerberg info->psinfo = qemu_mallocz(sizeof (*info->psinfo)); 2481edf8e2afSMika Westerberg if (info->prstatus == NULL) 2482edf8e2afSMika Westerberg return (-ENOMEM); 2483edf8e2afSMika Westerberg 2484edf8e2afSMika Westerberg /* 2485edf8e2afSMika Westerberg * First fill in status (and registers) of current thread 2486edf8e2afSMika Westerberg * including process info & aux vector. 2487edf8e2afSMika Westerberg */ 2488edf8e2afSMika Westerberg fill_prstatus(info->prstatus, ts, signr); 2489edf8e2afSMika Westerberg elf_core_copy_regs(&info->prstatus->pr_reg, env); 2490edf8e2afSMika Westerberg fill_note(&info->notes[0], "CORE", NT_PRSTATUS, 2491edf8e2afSMika Westerberg sizeof (*info->prstatus), info->prstatus); 2492edf8e2afSMika Westerberg fill_psinfo(info->psinfo, ts); 2493edf8e2afSMika Westerberg fill_note(&info->notes[1], "CORE", NT_PRPSINFO, 2494edf8e2afSMika Westerberg sizeof (*info->psinfo), info->psinfo); 2495edf8e2afSMika Westerberg fill_auxv_note(&info->notes[2], ts); 2496edf8e2afSMika Westerberg info->numnote = 3; 2497edf8e2afSMika Westerberg 2498edf8e2afSMika Westerberg info->notes_size = 0; 2499edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 2500edf8e2afSMika Westerberg info->notes_size += note_size(&info->notes[i]); 2501edf8e2afSMika Westerberg 2502edf8e2afSMika Westerberg /* read and fill status of all threads */ 2503edf8e2afSMika Westerberg cpu_list_lock(); 2504edf8e2afSMika Westerberg for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { 2505edf8e2afSMika Westerberg if (cpu == thread_env) 2506edf8e2afSMika Westerberg continue; 2507edf8e2afSMika Westerberg fill_thread_info(info, cpu); 2508edf8e2afSMika Westerberg } 2509edf8e2afSMika Westerberg cpu_list_unlock(); 2510edf8e2afSMika Westerberg 2511edf8e2afSMika Westerberg return (0); 2512edf8e2afSMika Westerberg } 2513edf8e2afSMika Westerberg 2514edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info) 2515edf8e2afSMika Westerberg { 2516edf8e2afSMika Westerberg struct elf_thread_status *ets; 2517edf8e2afSMika Westerberg 251872cf2d4fSBlue Swirl while (!QTAILQ_EMPTY(&info->thread_list)) { 251972cf2d4fSBlue Swirl ets = QTAILQ_FIRST(&info->thread_list); 252072cf2d4fSBlue Swirl QTAILQ_REMOVE(&info->thread_list, ets, ets_link); 2521edf8e2afSMika Westerberg qemu_free(ets); 2522edf8e2afSMika Westerberg } 2523edf8e2afSMika Westerberg 2524edf8e2afSMika Westerberg qemu_free(info->prstatus); 2525edf8e2afSMika Westerberg qemu_free(info->psinfo); 2526edf8e2afSMika Westerberg qemu_free(info->notes); 2527edf8e2afSMika Westerberg } 2528edf8e2afSMika Westerberg 2529edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd) 2530edf8e2afSMika Westerberg { 2531edf8e2afSMika Westerberg struct elf_thread_status *ets; 2532edf8e2afSMika Westerberg int i, error = 0; 2533edf8e2afSMika Westerberg 2534edf8e2afSMika Westerberg /* write prstatus, psinfo and auxv for current thread */ 2535edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 2536edf8e2afSMika Westerberg if ((error = write_note(&info->notes[i], fd)) != 0) 2537edf8e2afSMika Westerberg return (error); 2538edf8e2afSMika Westerberg 2539edf8e2afSMika Westerberg /* write prstatus for each thread */ 2540edf8e2afSMika Westerberg for (ets = info->thread_list.tqh_first; ets != NULL; 2541edf8e2afSMika Westerberg ets = ets->ets_link.tqe_next) { 2542edf8e2afSMika Westerberg if ((error = write_note(&ets->notes[0], fd)) != 0) 2543edf8e2afSMika Westerberg return (error); 2544edf8e2afSMika Westerberg } 2545edf8e2afSMika Westerberg 2546edf8e2afSMika Westerberg return (0); 2547edf8e2afSMika Westerberg } 2548edf8e2afSMika Westerberg 2549edf8e2afSMika Westerberg /* 2550edf8e2afSMika Westerberg * Write out ELF coredump. 2551edf8e2afSMika Westerberg * 2552edf8e2afSMika Westerberg * See documentation of ELF object file format in: 2553edf8e2afSMika Westerberg * http://www.caldera.com/developers/devspecs/gabi41.pdf 2554edf8e2afSMika Westerberg * 2555edf8e2afSMika Westerberg * Coredump format in linux is following: 2556edf8e2afSMika Westerberg * 2557edf8e2afSMika Westerberg * 0 +----------------------+ \ 2558edf8e2afSMika Westerberg * | ELF header | ET_CORE | 2559edf8e2afSMika Westerberg * +----------------------+ | 2560edf8e2afSMika Westerberg * | ELF program headers | |--- headers 2561edf8e2afSMika Westerberg * | - NOTE section | | 2562edf8e2afSMika Westerberg * | - PT_LOAD sections | | 2563edf8e2afSMika Westerberg * +----------------------+ / 2564edf8e2afSMika Westerberg * | NOTEs: | 2565edf8e2afSMika Westerberg * | - NT_PRSTATUS | 2566edf8e2afSMika Westerberg * | - NT_PRSINFO | 2567edf8e2afSMika Westerberg * | - NT_AUXV | 2568edf8e2afSMika Westerberg * +----------------------+ <-- aligned to target page 2569edf8e2afSMika Westerberg * | Process memory dump | 2570edf8e2afSMika Westerberg * : : 2571edf8e2afSMika Westerberg * . . 2572edf8e2afSMika Westerberg * : : 2573edf8e2afSMika Westerberg * | | 2574edf8e2afSMika Westerberg * +----------------------+ 2575edf8e2afSMika Westerberg * 2576edf8e2afSMika Westerberg * NT_PRSTATUS -> struct elf_prstatus (per thread) 2577edf8e2afSMika Westerberg * NT_PRSINFO -> struct elf_prpsinfo 2578edf8e2afSMika Westerberg * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()). 2579edf8e2afSMika Westerberg * 2580edf8e2afSMika Westerberg * Format follows System V format as close as possible. Current 2581edf8e2afSMika Westerberg * version limitations are as follows: 2582edf8e2afSMika Westerberg * - no floating point registers are dumped 2583edf8e2afSMika Westerberg * 2584edf8e2afSMika Westerberg * Function returns 0 in case of success, negative errno otherwise. 2585edf8e2afSMika Westerberg * 2586edf8e2afSMika Westerberg * TODO: make this work also during runtime: it should be 2587edf8e2afSMika Westerberg * possible to force coredump from running process and then 2588edf8e2afSMika Westerberg * continue processing. For example qemu could set up SIGUSR2 2589edf8e2afSMika Westerberg * handler (provided that target process haven't registered 2590edf8e2afSMika Westerberg * handler for that) that does the dump when signal is received. 2591edf8e2afSMika Westerberg */ 2592edf8e2afSMika Westerberg static int elf_core_dump(int signr, const CPUState *env) 2593edf8e2afSMika Westerberg { 2594edf8e2afSMika Westerberg const TaskState *ts = (const TaskState *)env->opaque; 2595edf8e2afSMika Westerberg struct vm_area_struct *vma = NULL; 2596edf8e2afSMika Westerberg char corefile[PATH_MAX]; 2597edf8e2afSMika Westerberg struct elf_note_info info; 2598edf8e2afSMika Westerberg struct elfhdr elf; 2599edf8e2afSMika Westerberg struct elf_phdr phdr; 2600edf8e2afSMika Westerberg struct rlimit dumpsize; 2601edf8e2afSMika Westerberg struct mm_struct *mm = NULL; 2602edf8e2afSMika Westerberg off_t offset = 0, data_offset = 0; 2603edf8e2afSMika Westerberg int segs = 0; 2604edf8e2afSMika Westerberg int fd = -1; 2605edf8e2afSMika Westerberg 2606edf8e2afSMika Westerberg errno = 0; 2607edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 2608edf8e2afSMika Westerberg if (dumpsize.rlim_cur == 0) 2609edf8e2afSMika Westerberg return 0; 2610edf8e2afSMika Westerberg 2611edf8e2afSMika Westerberg if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0) 2612edf8e2afSMika Westerberg return (-errno); 2613edf8e2afSMika Westerberg 2614edf8e2afSMika Westerberg if ((fd = open(corefile, O_WRONLY | O_CREAT, 2615edf8e2afSMika Westerberg S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) 2616edf8e2afSMika Westerberg return (-errno); 2617edf8e2afSMika Westerberg 2618edf8e2afSMika Westerberg /* 2619edf8e2afSMika Westerberg * Walk through target process memory mappings and 2620edf8e2afSMika Westerberg * set up structure containing this information. After 2621edf8e2afSMika Westerberg * this point vma_xxx functions can be used. 2622edf8e2afSMika Westerberg */ 2623edf8e2afSMika Westerberg if ((mm = vma_init()) == NULL) 2624edf8e2afSMika Westerberg goto out; 2625edf8e2afSMika Westerberg 2626edf8e2afSMika Westerberg walk_memory_regions(mm, vma_walker); 2627edf8e2afSMika Westerberg segs = vma_get_mapping_count(mm); 2628edf8e2afSMika Westerberg 2629edf8e2afSMika Westerberg /* 2630edf8e2afSMika Westerberg * Construct valid coredump ELF header. We also 2631edf8e2afSMika Westerberg * add one more segment for notes. 2632edf8e2afSMika Westerberg */ 2633edf8e2afSMika Westerberg fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0); 2634edf8e2afSMika Westerberg if (dump_write(fd, &elf, sizeof (elf)) != 0) 2635edf8e2afSMika Westerberg goto out; 2636edf8e2afSMika Westerberg 2637edf8e2afSMika Westerberg /* fill in in-memory version of notes */ 2638edf8e2afSMika Westerberg if (fill_note_info(&info, signr, env) < 0) 2639edf8e2afSMika Westerberg goto out; 2640edf8e2afSMika Westerberg 2641edf8e2afSMika Westerberg offset += sizeof (elf); /* elf header */ 2642edf8e2afSMika Westerberg offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */ 2643edf8e2afSMika Westerberg 2644edf8e2afSMika Westerberg /* write out notes program header */ 2645edf8e2afSMika Westerberg fill_elf_note_phdr(&phdr, info.notes_size, offset); 2646edf8e2afSMika Westerberg 2647edf8e2afSMika Westerberg offset += info.notes_size; 2648edf8e2afSMika Westerberg if (dump_write(fd, &phdr, sizeof (phdr)) != 0) 2649edf8e2afSMika Westerberg goto out; 2650edf8e2afSMika Westerberg 2651edf8e2afSMika Westerberg /* 2652edf8e2afSMika Westerberg * ELF specification wants data to start at page boundary so 2653edf8e2afSMika Westerberg * we align it here. 2654edf8e2afSMika Westerberg */ 2655edf8e2afSMika Westerberg offset = roundup(offset, ELF_EXEC_PAGESIZE); 2656edf8e2afSMika Westerberg 2657edf8e2afSMika Westerberg /* 2658edf8e2afSMika Westerberg * Write program headers for memory regions mapped in 2659edf8e2afSMika Westerberg * the target process. 2660edf8e2afSMika Westerberg */ 2661edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 2662edf8e2afSMika Westerberg (void) memset(&phdr, 0, sizeof (phdr)); 2663edf8e2afSMika Westerberg 2664edf8e2afSMika Westerberg phdr.p_type = PT_LOAD; 2665edf8e2afSMika Westerberg phdr.p_offset = offset; 2666edf8e2afSMika Westerberg phdr.p_vaddr = vma->vma_start; 2667edf8e2afSMika Westerberg phdr.p_paddr = 0; 2668edf8e2afSMika Westerberg phdr.p_filesz = vma_dump_size(vma); 2669edf8e2afSMika Westerberg offset += phdr.p_filesz; 2670edf8e2afSMika Westerberg phdr.p_memsz = vma->vma_end - vma->vma_start; 2671edf8e2afSMika Westerberg phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0; 2672edf8e2afSMika Westerberg if (vma->vma_flags & PROT_WRITE) 2673edf8e2afSMika Westerberg phdr.p_flags |= PF_W; 2674edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) 2675edf8e2afSMika Westerberg phdr.p_flags |= PF_X; 2676edf8e2afSMika Westerberg phdr.p_align = ELF_EXEC_PAGESIZE; 2677edf8e2afSMika Westerberg 2678edf8e2afSMika Westerberg dump_write(fd, &phdr, sizeof (phdr)); 2679edf8e2afSMika Westerberg } 2680edf8e2afSMika Westerberg 2681edf8e2afSMika Westerberg /* 2682edf8e2afSMika Westerberg * Next we write notes just after program headers. No 2683edf8e2afSMika Westerberg * alignment needed here. 2684edf8e2afSMika Westerberg */ 2685edf8e2afSMika Westerberg if (write_note_info(&info, fd) < 0) 2686edf8e2afSMika Westerberg goto out; 2687edf8e2afSMika Westerberg 2688edf8e2afSMika Westerberg /* align data to page boundary */ 2689edf8e2afSMika Westerberg data_offset = lseek(fd, 0, SEEK_CUR); 2690edf8e2afSMika Westerberg data_offset = TARGET_PAGE_ALIGN(data_offset); 2691edf8e2afSMika Westerberg if (lseek(fd, data_offset, SEEK_SET) != data_offset) 2692edf8e2afSMika Westerberg goto out; 2693edf8e2afSMika Westerberg 2694edf8e2afSMika Westerberg /* 2695edf8e2afSMika Westerberg * Finally we can dump process memory into corefile as well. 2696edf8e2afSMika Westerberg */ 2697edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 2698edf8e2afSMika Westerberg abi_ulong addr; 2699edf8e2afSMika Westerberg abi_ulong end; 2700edf8e2afSMika Westerberg 2701edf8e2afSMika Westerberg end = vma->vma_start + vma_dump_size(vma); 2702edf8e2afSMika Westerberg 2703edf8e2afSMika Westerberg for (addr = vma->vma_start; addr < end; 2704edf8e2afSMika Westerberg addr += TARGET_PAGE_SIZE) { 2705edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 2706edf8e2afSMika Westerberg int error; 2707edf8e2afSMika Westerberg 2708edf8e2afSMika Westerberg /* 2709edf8e2afSMika Westerberg * Read in page from target process memory and 2710edf8e2afSMika Westerberg * write it to coredump file. 2711edf8e2afSMika Westerberg */ 2712edf8e2afSMika Westerberg error = copy_from_user(page, addr, sizeof (page)); 2713edf8e2afSMika Westerberg if (error != 0) { 271449995e17SAurelien Jarno (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n", 2715edf8e2afSMika Westerberg addr); 2716edf8e2afSMika Westerberg errno = -error; 2717edf8e2afSMika Westerberg goto out; 2718edf8e2afSMika Westerberg } 2719edf8e2afSMika Westerberg if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0) 2720edf8e2afSMika Westerberg goto out; 2721edf8e2afSMika Westerberg } 2722edf8e2afSMika Westerberg } 2723edf8e2afSMika Westerberg 2724edf8e2afSMika Westerberg out: 2725edf8e2afSMika Westerberg free_note_info(&info); 2726edf8e2afSMika Westerberg if (mm != NULL) 2727edf8e2afSMika Westerberg vma_delete(mm); 2728edf8e2afSMika Westerberg (void) close(fd); 2729edf8e2afSMika Westerberg 2730edf8e2afSMika Westerberg if (errno != 0) 2731edf8e2afSMika Westerberg return (-errno); 2732edf8e2afSMika Westerberg return (0); 2733edf8e2afSMika Westerberg } 2734edf8e2afSMika Westerberg 2735edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 2736edf8e2afSMika Westerberg 273731e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd) 273831e31b8aSbellard { 273931e31b8aSbellard printf("a.out interpreter not yet supported\n"); 274031e31b8aSbellard return(0); 274131e31b8aSbellard } 274231e31b8aSbellard 2743e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) 2744e5fe0c52Spbrook { 2745e5fe0c52Spbrook init_thread(regs, infop); 2746e5fe0c52Spbrook } 2747