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 10030ac07d4Sbellard #ifdef TARGET_I386 10130ac07d4Sbellard 10215338fd7Sbellard #define ELF_PLATFORM get_elf_platform() 10315338fd7Sbellard 10415338fd7Sbellard static const char *get_elf_platform(void) 10515338fd7Sbellard { 10615338fd7Sbellard static char elf_platform[] = "i386"; 107d5975363Spbrook int family = (thread_env->cpuid_version >> 8) & 0xff; 10815338fd7Sbellard if (family > 6) 10915338fd7Sbellard family = 6; 11015338fd7Sbellard if (family >= 3) 11115338fd7Sbellard elf_platform[1] = '0' + family; 11215338fd7Sbellard return elf_platform; 11315338fd7Sbellard } 11415338fd7Sbellard 11515338fd7Sbellard #define ELF_HWCAP get_elf_hwcap() 11615338fd7Sbellard 11715338fd7Sbellard static uint32_t get_elf_hwcap(void) 11815338fd7Sbellard { 119d5975363Spbrook return thread_env->cpuid_features; 12015338fd7Sbellard } 12115338fd7Sbellard 12284409ddbSj_mayer #ifdef TARGET_X86_64 12384409ddbSj_mayer #define ELF_START_MMAP 0x2aaaaab000ULL 12484409ddbSj_mayer #define elf_check_arch(x) ( ((x) == ELF_ARCH) ) 12584409ddbSj_mayer 12684409ddbSj_mayer #define ELF_CLASS ELFCLASS64 12784409ddbSj_mayer #define ELF_DATA ELFDATA2LSB 12884409ddbSj_mayer #define ELF_ARCH EM_X86_64 12984409ddbSj_mayer 13084409ddbSj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 13184409ddbSj_mayer { 13284409ddbSj_mayer regs->rax = 0; 13384409ddbSj_mayer regs->rsp = infop->start_stack; 13484409ddbSj_mayer regs->rip = infop->entry; 13584409ddbSj_mayer } 13684409ddbSj_mayer 137a2547a13SLaurent Desnogues typedef target_ulong target_elf_greg_t; 1389edc5d79SMika Westerberg typedef uint32_t target_uid_t; 1399edc5d79SMika Westerberg typedef uint32_t target_gid_t; 1409edc5d79SMika Westerberg typedef int32_t target_pid_t; 1419edc5d79SMika Westerberg 1429edc5d79SMika Westerberg #define ELF_NREG 27 143a2547a13SLaurent Desnogues typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1449edc5d79SMika Westerberg 1459edc5d79SMika Westerberg /* 1469edc5d79SMika Westerberg * Note that ELF_NREG should be 29 as there should be place for 1479edc5d79SMika Westerberg * TRAPNO and ERR "registers" as well but linux doesn't dump 1489edc5d79SMika Westerberg * those. 1499edc5d79SMika Westerberg * 1509edc5d79SMika Westerberg * See linux kernel: arch/x86/include/asm/elf.h 1519edc5d79SMika Westerberg */ 152a2547a13SLaurent Desnogues static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 1539edc5d79SMika Westerberg { 1549edc5d79SMika Westerberg (*regs)[0] = env->regs[15]; 1559edc5d79SMika Westerberg (*regs)[1] = env->regs[14]; 1569edc5d79SMika Westerberg (*regs)[2] = env->regs[13]; 1579edc5d79SMika Westerberg (*regs)[3] = env->regs[12]; 1589edc5d79SMika Westerberg (*regs)[4] = env->regs[R_EBP]; 1599edc5d79SMika Westerberg (*regs)[5] = env->regs[R_EBX]; 1609edc5d79SMika Westerberg (*regs)[6] = env->regs[11]; 1619edc5d79SMika Westerberg (*regs)[7] = env->regs[10]; 1629edc5d79SMika Westerberg (*regs)[8] = env->regs[9]; 1639edc5d79SMika Westerberg (*regs)[9] = env->regs[8]; 1649edc5d79SMika Westerberg (*regs)[10] = env->regs[R_EAX]; 1659edc5d79SMika Westerberg (*regs)[11] = env->regs[R_ECX]; 1669edc5d79SMika Westerberg (*regs)[12] = env->regs[R_EDX]; 1679edc5d79SMika Westerberg (*regs)[13] = env->regs[R_ESI]; 1689edc5d79SMika Westerberg (*regs)[14] = env->regs[R_EDI]; 1699edc5d79SMika Westerberg (*regs)[15] = env->regs[R_EAX]; /* XXX */ 1709edc5d79SMika Westerberg (*regs)[16] = env->eip; 1719edc5d79SMika Westerberg (*regs)[17] = env->segs[R_CS].selector & 0xffff; 1729edc5d79SMika Westerberg (*regs)[18] = env->eflags; 1739edc5d79SMika Westerberg (*regs)[19] = env->regs[R_ESP]; 1749edc5d79SMika Westerberg (*regs)[20] = env->segs[R_SS].selector & 0xffff; 1759edc5d79SMika Westerberg (*regs)[21] = env->segs[R_FS].selector & 0xffff; 1769edc5d79SMika Westerberg (*regs)[22] = env->segs[R_GS].selector & 0xffff; 1779edc5d79SMika Westerberg (*regs)[23] = env->segs[R_DS].selector & 0xffff; 1789edc5d79SMika Westerberg (*regs)[24] = env->segs[R_ES].selector & 0xffff; 1799edc5d79SMika Westerberg (*regs)[25] = env->segs[R_FS].selector & 0xffff; 1809edc5d79SMika Westerberg (*regs)[26] = env->segs[R_GS].selector & 0xffff; 1819edc5d79SMika Westerberg } 1829edc5d79SMika Westerberg 18384409ddbSj_mayer #else 18484409ddbSj_mayer 18530ac07d4Sbellard #define ELF_START_MMAP 0x80000000 18630ac07d4Sbellard 18730ac07d4Sbellard /* 18830ac07d4Sbellard * This is used to ensure we don't load something for the wrong architecture. 18930ac07d4Sbellard */ 19030ac07d4Sbellard #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) 19130ac07d4Sbellard 19230ac07d4Sbellard /* 19330ac07d4Sbellard * These are used to set parameters in the core dumps. 19430ac07d4Sbellard */ 19530ac07d4Sbellard #define ELF_CLASS ELFCLASS32 19630ac07d4Sbellard #define ELF_DATA ELFDATA2LSB 19730ac07d4Sbellard #define ELF_ARCH EM_386 19830ac07d4Sbellard 199e5fe0c52Spbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 200e5fe0c52Spbrook { 201e5fe0c52Spbrook regs->esp = infop->start_stack; 202e5fe0c52Spbrook regs->eip = infop->entry; 203e5fe0c52Spbrook 20430ac07d4Sbellard /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program 20530ac07d4Sbellard starts %edx contains a pointer to a function which might be 20630ac07d4Sbellard registered using `atexit'. This provides a mean for the 20730ac07d4Sbellard dynamic linker to call DT_FINI functions for shared libraries 20830ac07d4Sbellard that have been loaded before the code runs. 20930ac07d4Sbellard 21030ac07d4Sbellard A value of 0 tells we have no such handler. */ 211e5fe0c52Spbrook regs->edx = 0; 212b346ff46Sbellard } 2139edc5d79SMika Westerberg 214a2547a13SLaurent Desnogues typedef target_ulong target_elf_greg_t; 2159edc5d79SMika Westerberg typedef uint16_t target_uid_t; 2169edc5d79SMika Westerberg typedef uint16_t target_gid_t; 2179edc5d79SMika Westerberg typedef int32_t target_pid_t; 2189edc5d79SMika Westerberg 2199edc5d79SMika Westerberg #define ELF_NREG 17 220a2547a13SLaurent Desnogues 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 */ 229a2547a13SLaurent Desnogues 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 289a2547a13SLaurent Desnogues typedef uint32_t target_elf_greg_t; 290edf8e2afSMika Westerberg typedef uint16_t target_uid_t; 291edf8e2afSMika Westerberg typedef uint16_t target_gid_t; 292edf8e2afSMika Westerberg typedef int32_t target_pid_t; 293edf8e2afSMika Westerberg 294edf8e2afSMika Westerberg #define ELF_NREG 18 295a2547a13SLaurent Desnogues typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; 296edf8e2afSMika Westerberg 297a2547a13SLaurent Desnogues static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env) 298edf8e2afSMika Westerberg { 299edf8e2afSMika Westerberg (*regs)[0] = env->regs[0]; 300edf8e2afSMika Westerberg (*regs)[1] = env->regs[1]; 301edf8e2afSMika Westerberg (*regs)[2] = env->regs[2]; 302edf8e2afSMika Westerberg (*regs)[3] = env->regs[3]; 303edf8e2afSMika Westerberg (*regs)[4] = env->regs[4]; 304edf8e2afSMika Westerberg (*regs)[5] = env->regs[5]; 305edf8e2afSMika Westerberg (*regs)[6] = env->regs[6]; 306edf8e2afSMika Westerberg (*regs)[7] = env->regs[7]; 307edf8e2afSMika Westerberg (*regs)[8] = env->regs[8]; 308edf8e2afSMika Westerberg (*regs)[9] = env->regs[9]; 309edf8e2afSMika Westerberg (*regs)[10] = env->regs[10]; 310edf8e2afSMika Westerberg (*regs)[11] = env->regs[11]; 311edf8e2afSMika Westerberg (*regs)[12] = env->regs[12]; 312edf8e2afSMika Westerberg (*regs)[13] = env->regs[13]; 313edf8e2afSMika Westerberg (*regs)[14] = env->regs[14]; 314edf8e2afSMika Westerberg (*regs)[15] = env->regs[15]; 315edf8e2afSMika Westerberg 316edf8e2afSMika Westerberg (*regs)[16] = cpsr_read((CPUState *)env); 317edf8e2afSMika Westerberg (*regs)[17] = env->regs[0]; /* XXX */ 318edf8e2afSMika Westerberg } 319edf8e2afSMika Westerberg 32030ac07d4Sbellard #define USE_ELF_CORE_DUMP 32130ac07d4Sbellard #define ELF_EXEC_PAGESIZE 4096 32230ac07d4Sbellard 323afce2927Sbellard enum 324afce2927Sbellard { 325afce2927Sbellard ARM_HWCAP_ARM_SWP = 1 << 0, 326afce2927Sbellard ARM_HWCAP_ARM_HALF = 1 << 1, 327afce2927Sbellard ARM_HWCAP_ARM_THUMB = 1 << 2, 328afce2927Sbellard ARM_HWCAP_ARM_26BIT = 1 << 3, 329afce2927Sbellard ARM_HWCAP_ARM_FAST_MULT = 1 << 4, 330afce2927Sbellard ARM_HWCAP_ARM_FPA = 1 << 5, 331afce2927Sbellard ARM_HWCAP_ARM_VFP = 1 << 6, 332afce2927Sbellard ARM_HWCAP_ARM_EDSP = 1 << 7, 333afce2927Sbellard }; 334afce2927Sbellard 33515338fd7Sbellard #define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \ 336afce2927Sbellard | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \ 337afce2927Sbellard | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP) 338afce2927Sbellard 33930ac07d4Sbellard #endif 34030ac07d4Sbellard 341853d6f7aSbellard #ifdef TARGET_SPARC 342a315a145Sbellard #ifdef TARGET_SPARC64 343853d6f7aSbellard 344853d6f7aSbellard #define ELF_START_MMAP 0x80000000 345853d6f7aSbellard 346992f48a0Sblueswir1 #ifndef TARGET_ABI32 347cb33da57Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) 348992f48a0Sblueswir1 #else 349992f48a0Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) 350992f48a0Sblueswir1 #endif 351853d6f7aSbellard 352a315a145Sbellard #define ELF_CLASS ELFCLASS64 353a315a145Sbellard #define ELF_DATA ELFDATA2MSB 3545ef54116Sbellard #define ELF_ARCH EM_SPARCV9 3555ef54116Sbellard 3565ef54116Sbellard #define STACK_BIAS 2047 357a315a145Sbellard 358a315a145Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 359a315a145Sbellard { 360992f48a0Sblueswir1 #ifndef TARGET_ABI32 361a315a145Sbellard regs->tstate = 0; 362992f48a0Sblueswir1 #endif 363a315a145Sbellard regs->pc = infop->entry; 364a315a145Sbellard regs->npc = regs->pc + 4; 365a315a145Sbellard regs->y = 0; 366992f48a0Sblueswir1 #ifdef TARGET_ABI32 367992f48a0Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 368992f48a0Sblueswir1 #else 369cb33da57Sblueswir1 if (personality(infop->personality) == PER_LINUX32) 370cb33da57Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 371cb33da57Sblueswir1 else 3725ef54116Sbellard regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; 373992f48a0Sblueswir1 #endif 374a315a145Sbellard } 375a315a145Sbellard 376a315a145Sbellard #else 377a315a145Sbellard #define ELF_START_MMAP 0x80000000 378a315a145Sbellard 379a315a145Sbellard #define elf_check_arch(x) ( (x) == EM_SPARC ) 380a315a145Sbellard 381853d6f7aSbellard #define ELF_CLASS ELFCLASS32 382853d6f7aSbellard #define ELF_DATA ELFDATA2MSB 383853d6f7aSbellard #define ELF_ARCH EM_SPARC 384853d6f7aSbellard 385853d6f7aSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 386853d6f7aSbellard { 387f5155289Sbellard regs->psr = 0; 388f5155289Sbellard regs->pc = infop->entry; 389f5155289Sbellard regs->npc = regs->pc + 4; 390f5155289Sbellard regs->y = 0; 391f5155289Sbellard regs->u_regs[14] = infop->start_stack - 16 * 4; 392853d6f7aSbellard } 393853d6f7aSbellard 394853d6f7aSbellard #endif 395a315a145Sbellard #endif 396853d6f7aSbellard 39767867308Sbellard #ifdef TARGET_PPC 39867867308Sbellard 39967867308Sbellard #define ELF_START_MMAP 0x80000000 40067867308Sbellard 401e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 40284409ddbSj_mayer 40384409ddbSj_mayer #define elf_check_arch(x) ( (x) == EM_PPC64 ) 40484409ddbSj_mayer 40584409ddbSj_mayer #define ELF_CLASS ELFCLASS64 40684409ddbSj_mayer 40784409ddbSj_mayer #else 40884409ddbSj_mayer 40967867308Sbellard #define elf_check_arch(x) ( (x) == EM_PPC ) 41067867308Sbellard 41167867308Sbellard #define ELF_CLASS ELFCLASS32 41284409ddbSj_mayer 41384409ddbSj_mayer #endif 41484409ddbSj_mayer 41567867308Sbellard #ifdef TARGET_WORDS_BIGENDIAN 41667867308Sbellard #define ELF_DATA ELFDATA2MSB 41767867308Sbellard #else 41867867308Sbellard #define ELF_DATA ELFDATA2LSB 41967867308Sbellard #endif 42067867308Sbellard #define ELF_ARCH EM_PPC 42167867308Sbellard 422df84e4f3SNathan Froyd /* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). 423df84e4f3SNathan Froyd See arch/powerpc/include/asm/cputable.h. */ 424df84e4f3SNathan Froyd enum { 425*3efa9a67Smalc QEMU_PPC_FEATURE_32 = 0x80000000, 426*3efa9a67Smalc QEMU_PPC_FEATURE_64 = 0x40000000, 427*3efa9a67Smalc QEMU_PPC_FEATURE_601_INSTR = 0x20000000, 428*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000, 429*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_FPU = 0x08000000, 430*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_MMU = 0x04000000, 431*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000, 432*3efa9a67Smalc QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000, 433*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_SPE = 0x00800000, 434*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000, 435*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000, 436*3efa9a67Smalc QEMU_PPC_FEATURE_NO_TB = 0x00100000, 437*3efa9a67Smalc QEMU_PPC_FEATURE_POWER4 = 0x00080000, 438*3efa9a67Smalc QEMU_PPC_FEATURE_POWER5 = 0x00040000, 439*3efa9a67Smalc QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000, 440*3efa9a67Smalc QEMU_PPC_FEATURE_CELL = 0x00010000, 441*3efa9a67Smalc QEMU_PPC_FEATURE_BOOKE = 0x00008000, 442*3efa9a67Smalc QEMU_PPC_FEATURE_SMT = 0x00004000, 443*3efa9a67Smalc QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000, 444*3efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000, 445*3efa9a67Smalc QEMU_PPC_FEATURE_PA6T = 0x00000800, 446*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_DFP = 0x00000400, 447*3efa9a67Smalc QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200, 448*3efa9a67Smalc QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100, 449*3efa9a67Smalc QEMU_PPC_FEATURE_HAS_VSX = 0x00000080, 450*3efa9a67Smalc QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040, 451df84e4f3SNathan Froyd 452*3efa9a67Smalc QEMU_PPC_FEATURE_TRUE_LE = 0x00000002, 453*3efa9a67Smalc QEMU_PPC_FEATURE_PPC_LE = 0x00000001, 454df84e4f3SNathan Froyd }; 455df84e4f3SNathan Froyd 456df84e4f3SNathan Froyd #define ELF_HWCAP get_elf_hwcap() 457df84e4f3SNathan Froyd 458df84e4f3SNathan Froyd static uint32_t get_elf_hwcap(void) 459df84e4f3SNathan Froyd { 460df84e4f3SNathan Froyd CPUState *e = thread_env; 461df84e4f3SNathan Froyd uint32_t features = 0; 462df84e4f3SNathan Froyd 463df84e4f3SNathan Froyd /* We don't have to be terribly complete here; the high points are 464df84e4f3SNathan Froyd Altivec/FP/SPE support. Anything else is just a bonus. */ 465df84e4f3SNathan Froyd #define GET_FEATURE(flag, feature) \ 466df84e4f3SNathan Froyd do {if (e->insns_flags & flag) features |= feature; } while(0) 467*3efa9a67Smalc GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); 468*3efa9a67Smalc GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); 469*3efa9a67Smalc GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); 470*3efa9a67Smalc GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE); 471*3efa9a67Smalc GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE); 472*3efa9a67Smalc GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE); 473*3efa9a67Smalc GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE); 474*3efa9a67Smalc GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC); 475df84e4f3SNathan Froyd #undef GET_FEATURE 476df84e4f3SNathan Froyd 477df84e4f3SNathan Froyd return features; 478df84e4f3SNathan Froyd } 479df84e4f3SNathan Froyd 480f5155289Sbellard /* 481f5155289Sbellard * We need to put in some extra aux table entries to tell glibc what 482f5155289Sbellard * the cache block size is, so it can use the dcbz instruction safely. 483f5155289Sbellard */ 484f5155289Sbellard #define AT_DCACHEBSIZE 19 485f5155289Sbellard #define AT_ICACHEBSIZE 20 486f5155289Sbellard #define AT_UCACHEBSIZE 21 487f5155289Sbellard /* A special ignored type value for PPC, for glibc compatibility. */ 488f5155289Sbellard #define AT_IGNOREPPC 22 489f5155289Sbellard /* 490f5155289Sbellard * The requirements here are: 491f5155289Sbellard * - keep the final alignment of sp (sp & 0xf) 492f5155289Sbellard * - make sure the 32-bit value at the first 16 byte aligned position of 493f5155289Sbellard * AUXV is greater than 16 for glibc compatibility. 494f5155289Sbellard * AT_IGNOREPPC is used for that. 495f5155289Sbellard * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, 496f5155289Sbellard * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. 497f5155289Sbellard */ 4980bccf03dSbellard #define DLINFO_ARCH_ITEMS 5 499f5155289Sbellard #define ARCH_DLINFO \ 500f5155289Sbellard do { \ 5010bccf03dSbellard NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \ 5020bccf03dSbellard NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \ 5030bccf03dSbellard NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ 504f5155289Sbellard /* \ 505f5155289Sbellard * Now handle glibc compatibility. \ 506f5155289Sbellard */ \ 5070bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 5080bccf03dSbellard NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 509f5155289Sbellard } while (0) 510f5155289Sbellard 51167867308Sbellard static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) 51267867308Sbellard { 513992f48a0Sblueswir1 abi_ulong pos = infop->start_stack; 514992f48a0Sblueswir1 abi_ulong tmp; 515e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 516992f48a0Sblueswir1 abi_ulong entry, toc; 51784409ddbSj_mayer #endif 518e5fe0c52Spbrook 51967867308Sbellard _regs->gpr[1] = infop->start_stack; 520e85e7c6eSj_mayer #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 52184409ddbSj_mayer entry = ldq_raw(infop->entry) + infop->load_addr; 52284409ddbSj_mayer toc = ldq_raw(infop->entry + 8) + infop->load_addr; 52384409ddbSj_mayer _regs->gpr[2] = toc; 52484409ddbSj_mayer infop->entry = entry; 52584409ddbSj_mayer #endif 52667867308Sbellard _regs->nip = infop->entry; 527e5fe0c52Spbrook /* Note that isn't exactly what regular kernel does 528e5fe0c52Spbrook * but this is what the ABI wants and is needed to allow 529e5fe0c52Spbrook * execution of PPC BSD programs. 530e5fe0c52Spbrook */ 5312f619698Sbellard /* FIXME - what to for failure of get_user()? */ 5322f619698Sbellard get_user_ual(_regs->gpr[3], pos); 533992f48a0Sblueswir1 pos += sizeof(abi_ulong); 534e5fe0c52Spbrook _regs->gpr[4] = pos; 535992f48a0Sblueswir1 for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong)) 536e5fe0c52Spbrook tmp = ldl(pos); 537e5fe0c52Spbrook _regs->gpr[5] = pos; 53867867308Sbellard } 53967867308Sbellard 54067867308Sbellard #define ELF_EXEC_PAGESIZE 4096 54167867308Sbellard 54267867308Sbellard #endif 54367867308Sbellard 544048f6b4dSbellard #ifdef TARGET_MIPS 545048f6b4dSbellard 546048f6b4dSbellard #define ELF_START_MMAP 0x80000000 547048f6b4dSbellard 548048f6b4dSbellard #define elf_check_arch(x) ( (x) == EM_MIPS ) 549048f6b4dSbellard 550388bb21aSths #ifdef TARGET_MIPS64 551388bb21aSths #define ELF_CLASS ELFCLASS64 552388bb21aSths #else 553048f6b4dSbellard #define ELF_CLASS ELFCLASS32 554388bb21aSths #endif 555048f6b4dSbellard #ifdef TARGET_WORDS_BIGENDIAN 556048f6b4dSbellard #define ELF_DATA ELFDATA2MSB 557048f6b4dSbellard #else 558048f6b4dSbellard #define ELF_DATA ELFDATA2LSB 559048f6b4dSbellard #endif 560048f6b4dSbellard #define ELF_ARCH EM_MIPS 561048f6b4dSbellard 562048f6b4dSbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 563048f6b4dSbellard { 564623a930eSths regs->cp0_status = 2 << CP0St_KSU; 565048f6b4dSbellard regs->cp0_epc = infop->entry; 566048f6b4dSbellard regs->regs[29] = infop->start_stack; 567048f6b4dSbellard } 568048f6b4dSbellard 569388bb21aSths #define ELF_EXEC_PAGESIZE 4096 570388bb21aSths 571048f6b4dSbellard #endif /* TARGET_MIPS */ 572048f6b4dSbellard 573b779e29eSEdgar E. Iglesias #ifdef TARGET_MICROBLAZE 574b779e29eSEdgar E. Iglesias 575b779e29eSEdgar E. Iglesias #define ELF_START_MMAP 0x80000000 576b779e29eSEdgar E. Iglesias 577b779e29eSEdgar E. Iglesias #define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE ) 578b779e29eSEdgar E. Iglesias 579b779e29eSEdgar E. Iglesias #define ELF_CLASS ELFCLASS32 580b779e29eSEdgar E. Iglesias #define ELF_DATA ELFDATA2MSB 581b779e29eSEdgar E. Iglesias #define ELF_ARCH EM_MIPS 582b779e29eSEdgar E. Iglesias 583b779e29eSEdgar E. Iglesias static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 584b779e29eSEdgar E. Iglesias { 585b779e29eSEdgar E. Iglesias regs->pc = infop->entry; 586b779e29eSEdgar E. Iglesias regs->r1 = infop->start_stack; 587b779e29eSEdgar E. Iglesias 588b779e29eSEdgar E. Iglesias } 589b779e29eSEdgar E. Iglesias 590b779e29eSEdgar E. Iglesias #define ELF_EXEC_PAGESIZE 4096 591b779e29eSEdgar E. Iglesias 592b779e29eSEdgar E. Iglesias #endif /* TARGET_MICROBLAZE */ 593b779e29eSEdgar E. Iglesias 594fdf9b3e8Sbellard #ifdef TARGET_SH4 595fdf9b3e8Sbellard 596fdf9b3e8Sbellard #define ELF_START_MMAP 0x80000000 597fdf9b3e8Sbellard 598fdf9b3e8Sbellard #define elf_check_arch(x) ( (x) == EM_SH ) 599fdf9b3e8Sbellard 600fdf9b3e8Sbellard #define ELF_CLASS ELFCLASS32 601fdf9b3e8Sbellard #define ELF_DATA ELFDATA2LSB 602fdf9b3e8Sbellard #define ELF_ARCH EM_SH 603fdf9b3e8Sbellard 604fdf9b3e8Sbellard static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 605fdf9b3e8Sbellard { 606fdf9b3e8Sbellard /* Check other registers XXXXX */ 607fdf9b3e8Sbellard regs->pc = infop->entry; 608072ae847Sths regs->regs[15] = infop->start_stack; 609fdf9b3e8Sbellard } 610fdf9b3e8Sbellard 611fdf9b3e8Sbellard #define ELF_EXEC_PAGESIZE 4096 612fdf9b3e8Sbellard 613fdf9b3e8Sbellard #endif 614fdf9b3e8Sbellard 61548733d19Sths #ifdef TARGET_CRIS 61648733d19Sths 61748733d19Sths #define ELF_START_MMAP 0x80000000 61848733d19Sths 61948733d19Sths #define elf_check_arch(x) ( (x) == EM_CRIS ) 62048733d19Sths 62148733d19Sths #define ELF_CLASS ELFCLASS32 62248733d19Sths #define ELF_DATA ELFDATA2LSB 62348733d19Sths #define ELF_ARCH EM_CRIS 62448733d19Sths 62548733d19Sths static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 62648733d19Sths { 62748733d19Sths regs->erp = infop->entry; 62848733d19Sths } 62948733d19Sths 63048733d19Sths #define ELF_EXEC_PAGESIZE 8192 63148733d19Sths 63248733d19Sths #endif 63348733d19Sths 634e6e5906bSpbrook #ifdef TARGET_M68K 635e6e5906bSpbrook 636e6e5906bSpbrook #define ELF_START_MMAP 0x80000000 637e6e5906bSpbrook 638e6e5906bSpbrook #define elf_check_arch(x) ( (x) == EM_68K ) 639e6e5906bSpbrook 640e6e5906bSpbrook #define ELF_CLASS ELFCLASS32 641e6e5906bSpbrook #define ELF_DATA ELFDATA2MSB 642e6e5906bSpbrook #define ELF_ARCH EM_68K 643e6e5906bSpbrook 644e6e5906bSpbrook /* ??? Does this need to do anything? 645e6e5906bSpbrook #define ELF_PLAT_INIT(_r) */ 646e6e5906bSpbrook 647e6e5906bSpbrook static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 648e6e5906bSpbrook { 649e6e5906bSpbrook regs->usp = infop->start_stack; 650e6e5906bSpbrook regs->sr = 0; 651e6e5906bSpbrook regs->pc = infop->entry; 652e6e5906bSpbrook } 653e6e5906bSpbrook 654e6e5906bSpbrook #define ELF_EXEC_PAGESIZE 8192 655e6e5906bSpbrook 656e6e5906bSpbrook #endif 657e6e5906bSpbrook 6587a3148a9Sj_mayer #ifdef TARGET_ALPHA 6597a3148a9Sj_mayer 6607a3148a9Sj_mayer #define ELF_START_MMAP (0x30000000000ULL) 6617a3148a9Sj_mayer 6627a3148a9Sj_mayer #define elf_check_arch(x) ( (x) == ELF_ARCH ) 6637a3148a9Sj_mayer 6647a3148a9Sj_mayer #define ELF_CLASS ELFCLASS64 6657a3148a9Sj_mayer #define ELF_DATA ELFDATA2MSB 6667a3148a9Sj_mayer #define ELF_ARCH EM_ALPHA 6677a3148a9Sj_mayer 6687a3148a9Sj_mayer static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 6697a3148a9Sj_mayer { 6707a3148a9Sj_mayer regs->pc = infop->entry; 6717a3148a9Sj_mayer regs->ps = 8; 6727a3148a9Sj_mayer regs->usp = infop->start_stack; 6737a3148a9Sj_mayer regs->unique = infop->start_data; /* ? */ 6747a3148a9Sj_mayer printf("Set unique value to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", 6757a3148a9Sj_mayer regs->unique, infop->start_data); 6767a3148a9Sj_mayer } 6777a3148a9Sj_mayer 6787a3148a9Sj_mayer #define ELF_EXEC_PAGESIZE 8192 6797a3148a9Sj_mayer 6807a3148a9Sj_mayer #endif /* TARGET_ALPHA */ 6817a3148a9Sj_mayer 68215338fd7Sbellard #ifndef ELF_PLATFORM 68315338fd7Sbellard #define ELF_PLATFORM (NULL) 68415338fd7Sbellard #endif 68515338fd7Sbellard 68615338fd7Sbellard #ifndef ELF_HWCAP 68715338fd7Sbellard #define ELF_HWCAP 0 68815338fd7Sbellard #endif 68915338fd7Sbellard 690992f48a0Sblueswir1 #ifdef TARGET_ABI32 691cb33da57Sblueswir1 #undef ELF_CLASS 692992f48a0Sblueswir1 #define ELF_CLASS ELFCLASS32 693cb33da57Sblueswir1 #undef bswaptls 694cb33da57Sblueswir1 #define bswaptls(ptr) bswap32s(ptr) 695cb33da57Sblueswir1 #endif 696cb33da57Sblueswir1 69731e31b8aSbellard #include "elf.h" 69809bfb054Sbellard 69909bfb054Sbellard struct exec 70009bfb054Sbellard { 70109bfb054Sbellard unsigned int a_info; /* Use macros N_MAGIC, etc for access */ 70209bfb054Sbellard unsigned int a_text; /* length of text, in bytes */ 70309bfb054Sbellard unsigned int a_data; /* length of data, in bytes */ 70409bfb054Sbellard unsigned int a_bss; /* length of uninitialized data area, in bytes */ 70509bfb054Sbellard unsigned int a_syms; /* length of symbol table data in file, in bytes */ 70609bfb054Sbellard unsigned int a_entry; /* start address */ 70709bfb054Sbellard unsigned int a_trsize; /* length of relocation info for text, in bytes */ 70809bfb054Sbellard unsigned int a_drsize; /* length of relocation info for data, in bytes */ 70909bfb054Sbellard }; 71009bfb054Sbellard 71109bfb054Sbellard 71209bfb054Sbellard #define N_MAGIC(exec) ((exec).a_info & 0xffff) 71309bfb054Sbellard #define OMAGIC 0407 71409bfb054Sbellard #define NMAGIC 0410 71509bfb054Sbellard #define ZMAGIC 0413 71609bfb054Sbellard #define QMAGIC 0314 71709bfb054Sbellard 71809bfb054Sbellard /* max code+data+bss space allocated to elf interpreter */ 71909bfb054Sbellard #define INTERP_MAP_SIZE (32 * 1024 * 1024) 72009bfb054Sbellard 72109bfb054Sbellard /* max code+data+bss+brk space allocated to ET_DYN executables */ 72209bfb054Sbellard #define ET_DYN_MAP_SIZE (128 * 1024 * 1024) 72309bfb054Sbellard 72431e31b8aSbellard /* Necessary parameters */ 72554936004Sbellard #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE 72654936004Sbellard #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) 72754936004Sbellard #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) 72831e31b8aSbellard 72931e31b8aSbellard #define INTERPRETER_NONE 0 73031e31b8aSbellard #define INTERPRETER_AOUT 1 73131e31b8aSbellard #define INTERPRETER_ELF 2 73231e31b8aSbellard 73315338fd7Sbellard #define DLINFO_ITEMS 12 73431e31b8aSbellard 73509bfb054Sbellard static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) 73609bfb054Sbellard { 73709bfb054Sbellard memcpy(to, from, n); 73809bfb054Sbellard } 73909bfb054Sbellard 74031e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd); 74131e31b8aSbellard 74231e31b8aSbellard #ifdef BSWAP_NEEDED 74392a31b1fSbellard static void bswap_ehdr(struct elfhdr *ehdr) 74431e31b8aSbellard { 74531e31b8aSbellard bswap16s(&ehdr->e_type); /* Object file type */ 74631e31b8aSbellard bswap16s(&ehdr->e_machine); /* Architecture */ 74731e31b8aSbellard bswap32s(&ehdr->e_version); /* Object file version */ 74892a31b1fSbellard bswaptls(&ehdr->e_entry); /* Entry point virtual address */ 74992a31b1fSbellard bswaptls(&ehdr->e_phoff); /* Program header table file offset */ 75092a31b1fSbellard bswaptls(&ehdr->e_shoff); /* Section header table file offset */ 75131e31b8aSbellard bswap32s(&ehdr->e_flags); /* Processor-specific flags */ 75231e31b8aSbellard bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ 75331e31b8aSbellard bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ 75431e31b8aSbellard bswap16s(&ehdr->e_phnum); /* Program header table entry count */ 75531e31b8aSbellard bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ 75631e31b8aSbellard bswap16s(&ehdr->e_shnum); /* Section header table entry count */ 75731e31b8aSbellard bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ 75831e31b8aSbellard } 75931e31b8aSbellard 76092a31b1fSbellard static void bswap_phdr(struct elf_phdr *phdr) 76131e31b8aSbellard { 76231e31b8aSbellard bswap32s(&phdr->p_type); /* Segment type */ 76392a31b1fSbellard bswaptls(&phdr->p_offset); /* Segment file offset */ 76492a31b1fSbellard bswaptls(&phdr->p_vaddr); /* Segment virtual address */ 76592a31b1fSbellard bswaptls(&phdr->p_paddr); /* Segment physical address */ 76692a31b1fSbellard bswaptls(&phdr->p_filesz); /* Segment size in file */ 76792a31b1fSbellard bswaptls(&phdr->p_memsz); /* Segment size in memory */ 76831e31b8aSbellard bswap32s(&phdr->p_flags); /* Segment flags */ 76992a31b1fSbellard bswaptls(&phdr->p_align); /* Segment alignment */ 77031e31b8aSbellard } 771689f936fSbellard 77292a31b1fSbellard static void bswap_shdr(struct elf_shdr *shdr) 773689f936fSbellard { 774689f936fSbellard bswap32s(&shdr->sh_name); 775689f936fSbellard bswap32s(&shdr->sh_type); 77692a31b1fSbellard bswaptls(&shdr->sh_flags); 77792a31b1fSbellard bswaptls(&shdr->sh_addr); 77892a31b1fSbellard bswaptls(&shdr->sh_offset); 77992a31b1fSbellard bswaptls(&shdr->sh_size); 780689f936fSbellard bswap32s(&shdr->sh_link); 781689f936fSbellard bswap32s(&shdr->sh_info); 78292a31b1fSbellard bswaptls(&shdr->sh_addralign); 78392a31b1fSbellard bswaptls(&shdr->sh_entsize); 784689f936fSbellard } 785689f936fSbellard 7867a3148a9Sj_mayer static void bswap_sym(struct elf_sym *sym) 787689f936fSbellard { 788689f936fSbellard bswap32s(&sym->st_name); 7897a3148a9Sj_mayer bswaptls(&sym->st_value); 7907a3148a9Sj_mayer bswaptls(&sym->st_size); 791689f936fSbellard bswap16s(&sym->st_shndx); 792689f936fSbellard } 79331e31b8aSbellard #endif 79431e31b8aSbellard 795edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 796edf8e2afSMika Westerberg static int elf_core_dump(int, const CPUState *); 797edf8e2afSMika Westerberg 798edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 799edf8e2afSMika Westerberg static void bswap_note(struct elf_note *en) 800edf8e2afSMika Westerberg { 801edf8e2afSMika Westerberg bswaptls(&en->n_namesz); 802edf8e2afSMika Westerberg bswaptls(&en->n_descsz); 803edf8e2afSMika Westerberg bswaptls(&en->n_type); 804edf8e2afSMika Westerberg } 805edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 806edf8e2afSMika Westerberg 807edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 808edf8e2afSMika Westerberg 80931e31b8aSbellard /* 810e5fe0c52Spbrook * 'copy_elf_strings()' copies argument/envelope strings from user 81131e31b8aSbellard * memory to free pages in kernel mem. These are in a format ready 81231e31b8aSbellard * to be put directly into the top of new user memory. 81331e31b8aSbellard * 81431e31b8aSbellard */ 815992f48a0Sblueswir1 static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, 816992f48a0Sblueswir1 abi_ulong p) 81731e31b8aSbellard { 81831e31b8aSbellard char *tmp, *tmp1, *pag = NULL; 81931e31b8aSbellard int len, offset = 0; 82031e31b8aSbellard 82131e31b8aSbellard if (!p) { 82231e31b8aSbellard return 0; /* bullet-proofing */ 82331e31b8aSbellard } 82431e31b8aSbellard while (argc-- > 0) { 825edf779ffSbellard tmp = argv[argc]; 826edf779ffSbellard if (!tmp) { 82731e31b8aSbellard fprintf(stderr, "VFS: argc is wrong"); 82831e31b8aSbellard exit(-1); 82931e31b8aSbellard } 830edf779ffSbellard tmp1 = tmp; 831edf779ffSbellard while (*tmp++); 83231e31b8aSbellard len = tmp - tmp1; 83331e31b8aSbellard if (p < len) { /* this shouldn't happen - 128kB */ 83431e31b8aSbellard return 0; 83531e31b8aSbellard } 83631e31b8aSbellard while (len) { 83731e31b8aSbellard --p; --tmp; --len; 83831e31b8aSbellard if (--offset < 0) { 83954936004Sbellard offset = p % TARGET_PAGE_SIZE; 84044a91caeSbellard pag = (char *)page[p/TARGET_PAGE_SIZE]; 84144a91caeSbellard if (!pag) { 84253a5960aSpbrook pag = (char *)malloc(TARGET_PAGE_SIZE); 8434118a970Sj_mayer memset(pag, 0, TARGET_PAGE_SIZE); 84453a5960aSpbrook page[p/TARGET_PAGE_SIZE] = pag; 84544a91caeSbellard if (!pag) 84631e31b8aSbellard return 0; 84731e31b8aSbellard } 84831e31b8aSbellard } 84931e31b8aSbellard if (len == 0 || offset == 0) { 850edf779ffSbellard *(pag + offset) = *tmp; 85131e31b8aSbellard } 85231e31b8aSbellard else { 85331e31b8aSbellard int bytes_to_copy = (len > offset) ? offset : len; 85431e31b8aSbellard tmp -= bytes_to_copy; 85531e31b8aSbellard p -= bytes_to_copy; 85631e31b8aSbellard offset -= bytes_to_copy; 85731e31b8aSbellard len -= bytes_to_copy; 85831e31b8aSbellard memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); 85931e31b8aSbellard } 86031e31b8aSbellard } 86131e31b8aSbellard } 86231e31b8aSbellard return p; 86331e31b8aSbellard } 86431e31b8aSbellard 865992f48a0Sblueswir1 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, 86631e31b8aSbellard struct image_info *info) 86731e31b8aSbellard { 868992f48a0Sblueswir1 abi_ulong stack_base, size, error; 86931e31b8aSbellard int i; 87031e31b8aSbellard 87131e31b8aSbellard /* Create enough stack to hold everything. If we don't use 87231e31b8aSbellard * it for args, we'll use it for something else... 87331e31b8aSbellard */ 87409bfb054Sbellard size = x86_stack_size; 87554936004Sbellard if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) 87654936004Sbellard size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; 87754936004Sbellard error = target_mmap(0, 87883fb7adfSbellard size + qemu_host_page_size, 87931e31b8aSbellard PROT_READ | PROT_WRITE, 88009bfb054Sbellard MAP_PRIVATE | MAP_ANONYMOUS, 88109bfb054Sbellard -1, 0); 88209bfb054Sbellard if (error == -1) { 88331e31b8aSbellard perror("stk mmap"); 88431e31b8aSbellard exit(-1); 88531e31b8aSbellard } 88609bfb054Sbellard /* we reserve one extra page at the top of the stack as guard */ 88783fb7adfSbellard target_mprotect(error + size, qemu_host_page_size, PROT_NONE); 88831e31b8aSbellard 88954936004Sbellard stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; 89009bfb054Sbellard p += stack_base; 89109bfb054Sbellard 89231e31b8aSbellard for (i = 0 ; i < MAX_ARG_PAGES ; i++) { 89331e31b8aSbellard if (bprm->page[i]) { 89431e31b8aSbellard info->rss++; 895579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 89653a5960aSpbrook memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); 89753a5960aSpbrook free(bprm->page[i]); 89831e31b8aSbellard } 89954936004Sbellard stack_base += TARGET_PAGE_SIZE; 90031e31b8aSbellard } 90131e31b8aSbellard return p; 90231e31b8aSbellard } 90331e31b8aSbellard 904992f48a0Sblueswir1 static void set_brk(abi_ulong start, abi_ulong end) 90531e31b8aSbellard { 90631e31b8aSbellard /* page-align the start and end addresses... */ 90754936004Sbellard start = HOST_PAGE_ALIGN(start); 90854936004Sbellard end = HOST_PAGE_ALIGN(end); 90931e31b8aSbellard if (end <= start) 91031e31b8aSbellard return; 91154936004Sbellard if(target_mmap(start, end - start, 91231e31b8aSbellard PROT_READ | PROT_WRITE | PROT_EXEC, 91331e31b8aSbellard MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) { 91431e31b8aSbellard perror("cannot mmap brk"); 91531e31b8aSbellard exit(-1); 91631e31b8aSbellard } 91731e31b8aSbellard } 91831e31b8aSbellard 91931e31b8aSbellard 920853d6f7aSbellard /* We need to explicitly zero any fractional pages after the data 921853d6f7aSbellard section (i.e. bss). This would contain the junk from the file that 922853d6f7aSbellard should not be in memory. */ 923992f48a0Sblueswir1 static void padzero(abi_ulong elf_bss, abi_ulong last_bss) 92431e31b8aSbellard { 925992f48a0Sblueswir1 abi_ulong nbyte; 92631e31b8aSbellard 927768a4a36Sths if (elf_bss >= last_bss) 928768a4a36Sths return; 929768a4a36Sths 930853d6f7aSbellard /* XXX: this is really a hack : if the real host page size is 931853d6f7aSbellard smaller than the target page size, some pages after the end 932853d6f7aSbellard of the file may not be mapped. A better fix would be to 933853d6f7aSbellard patch target_mmap(), but it is more complicated as the file 934853d6f7aSbellard size must be known */ 93583fb7adfSbellard if (qemu_real_host_page_size < qemu_host_page_size) { 936992f48a0Sblueswir1 abi_ulong end_addr, end_addr1; 93783fb7adfSbellard end_addr1 = (elf_bss + qemu_real_host_page_size - 1) & 93883fb7adfSbellard ~(qemu_real_host_page_size - 1); 939853d6f7aSbellard end_addr = HOST_PAGE_ALIGN(elf_bss); 940853d6f7aSbellard if (end_addr1 < end_addr) { 941863cf0b7Sj_mayer mmap((void *)g2h(end_addr1), end_addr - end_addr1, 942853d6f7aSbellard PROT_READ|PROT_WRITE|PROT_EXEC, 943853d6f7aSbellard MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 944853d6f7aSbellard } 945853d6f7aSbellard } 946853d6f7aSbellard 94783fb7adfSbellard nbyte = elf_bss & (qemu_host_page_size-1); 94831e31b8aSbellard if (nbyte) { 94983fb7adfSbellard nbyte = qemu_host_page_size - nbyte; 95031e31b8aSbellard do { 9512f619698Sbellard /* FIXME - what to do if put_user() fails? */ 9522f619698Sbellard put_user_u8(0, elf_bss); 95353a5960aSpbrook elf_bss++; 95431e31b8aSbellard } while (--nbyte); 95531e31b8aSbellard } 95631e31b8aSbellard } 95731e31b8aSbellard 95853a5960aSpbrook 959992f48a0Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, 96031e31b8aSbellard struct elfhdr * exec, 961992f48a0Sblueswir1 abi_ulong load_addr, 962992f48a0Sblueswir1 abi_ulong load_bias, 963992f48a0Sblueswir1 abi_ulong interp_load_addr, int ibcs, 96431e31b8aSbellard struct image_info *info) 96531e31b8aSbellard { 966992f48a0Sblueswir1 abi_ulong sp; 96753a5960aSpbrook int size; 968992f48a0Sblueswir1 abi_ulong u_platform; 96915338fd7Sbellard const char *k_platform; 970863cf0b7Sj_mayer const int n = sizeof(elf_addr_t); 97131e31b8aSbellard 97253a5960aSpbrook sp = p; 97353a5960aSpbrook u_platform = 0; 97415338fd7Sbellard k_platform = ELF_PLATFORM; 97515338fd7Sbellard if (k_platform) { 97615338fd7Sbellard size_t len = strlen(k_platform) + 1; 97753a5960aSpbrook sp -= (len + n - 1) & ~(n - 1); 97853a5960aSpbrook u_platform = sp; 979579a97f7Sbellard /* FIXME - check return value of memcpy_to_target() for failure */ 98053a5960aSpbrook memcpy_to_target(sp, k_platform, len); 98115338fd7Sbellard } 98253a5960aSpbrook /* 98353a5960aSpbrook * Force 16 byte _final_ alignment here for generality. 98453a5960aSpbrook */ 985992f48a0Sblueswir1 sp = sp &~ (abi_ulong)15; 98653a5960aSpbrook size = (DLINFO_ITEMS + 1) * 2; 98715338fd7Sbellard if (k_platform) 98853a5960aSpbrook size += 2; 989f5155289Sbellard #ifdef DLINFO_ARCH_ITEMS 99053a5960aSpbrook size += DLINFO_ARCH_ITEMS * 2; 991f5155289Sbellard #endif 99253a5960aSpbrook size += envc + argc + 2; 99353a5960aSpbrook size += (!ibcs ? 3 : 1); /* argc itself */ 99453a5960aSpbrook size *= n; 99553a5960aSpbrook if (size & 15) 99653a5960aSpbrook sp -= 16 - (size & 15); 997f5155289Sbellard 998863cf0b7Sj_mayer /* This is correct because Linux defines 999863cf0b7Sj_mayer * elf_addr_t as Elf32_Off / Elf64_Off 1000863cf0b7Sj_mayer */ 100153a5960aSpbrook #define NEW_AUX_ENT(id, val) do { \ 10022f619698Sbellard sp -= n; put_user_ual(val, sp); \ 10032f619698Sbellard sp -= n; put_user_ual(id, sp); \ 100453a5960aSpbrook } while(0) 10052f619698Sbellard 10060bccf03dSbellard NEW_AUX_ENT (AT_NULL, 0); 1007f5155289Sbellard 10080bccf03dSbellard /* There must be exactly DLINFO_ITEMS entries here. */ 1009992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff)); 1010992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); 1011992f48a0Sblueswir1 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); 1012992f48a0Sblueswir1 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE)); 1013992f48a0Sblueswir1 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr)); 1014992f48a0Sblueswir1 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); 10150bccf03dSbellard NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry); 1016992f48a0Sblueswir1 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); 1017992f48a0Sblueswir1 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); 1018992f48a0Sblueswir1 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); 1019992f48a0Sblueswir1 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); 1020992f48a0Sblueswir1 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); 1021a07c67dfSpbrook NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); 102215338fd7Sbellard if (k_platform) 102353a5960aSpbrook NEW_AUX_ENT(AT_PLATFORM, u_platform); 1024f5155289Sbellard #ifdef ARCH_DLINFO 1025f5155289Sbellard /* 1026f5155289Sbellard * ARCH_DLINFO must come last so platform specific code can enforce 1027f5155289Sbellard * special alignment requirements on the AUXV if necessary (eg. PPC). 1028f5155289Sbellard */ 1029f5155289Sbellard ARCH_DLINFO; 1030f5155289Sbellard #endif 1031f5155289Sbellard #undef NEW_AUX_ENT 1032f5155289Sbellard 1033edf8e2afSMika Westerberg info->saved_auxv = sp; 1034edf8e2afSMika Westerberg 1035e5fe0c52Spbrook sp = loader_build_argptr(envc, argc, sp, p, !ibcs); 103631e31b8aSbellard return sp; 103731e31b8aSbellard } 103831e31b8aSbellard 103931e31b8aSbellard 1040992f48a0Sblueswir1 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, 104131e31b8aSbellard int interpreter_fd, 1042992f48a0Sblueswir1 abi_ulong *interp_load_addr) 104331e31b8aSbellard { 104431e31b8aSbellard struct elf_phdr *elf_phdata = NULL; 104531e31b8aSbellard struct elf_phdr *eppnt; 1046992f48a0Sblueswir1 abi_ulong load_addr = 0; 104731e31b8aSbellard int load_addr_set = 0; 104831e31b8aSbellard int retval; 1049992f48a0Sblueswir1 abi_ulong last_bss, elf_bss; 1050992f48a0Sblueswir1 abi_ulong error; 105131e31b8aSbellard int i; 105231e31b8aSbellard 105331e31b8aSbellard elf_bss = 0; 105431e31b8aSbellard last_bss = 0; 105531e31b8aSbellard error = 0; 105631e31b8aSbellard 1057644c433cSbellard #ifdef BSWAP_NEEDED 1058644c433cSbellard bswap_ehdr(interp_elf_ex); 1059644c433cSbellard #endif 106031e31b8aSbellard /* First of all, some simple consistency checks */ 106131e31b8aSbellard if ((interp_elf_ex->e_type != ET_EXEC && 106231e31b8aSbellard interp_elf_ex->e_type != ET_DYN) || 106331e31b8aSbellard !elf_check_arch(interp_elf_ex->e_machine)) { 1064992f48a0Sblueswir1 return ~((abi_ulong)0UL); 106531e31b8aSbellard } 106631e31b8aSbellard 1067644c433cSbellard 106831e31b8aSbellard /* Now read in all of the header information */ 106931e31b8aSbellard 107054936004Sbellard if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE) 1071992f48a0Sblueswir1 return ~(abi_ulong)0UL; 107231e31b8aSbellard 107331e31b8aSbellard elf_phdata = (struct elf_phdr *) 107431e31b8aSbellard malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 107531e31b8aSbellard 107631e31b8aSbellard if (!elf_phdata) 1077992f48a0Sblueswir1 return ~((abi_ulong)0UL); 107831e31b8aSbellard 107931e31b8aSbellard /* 108031e31b8aSbellard * If the size of this structure has changed, then punt, since 108131e31b8aSbellard * we will be doing the wrong thing. 108231e31b8aSbellard */ 108309bfb054Sbellard if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { 108431e31b8aSbellard free(elf_phdata); 1085992f48a0Sblueswir1 return ~((abi_ulong)0UL); 108631e31b8aSbellard } 108731e31b8aSbellard 108831e31b8aSbellard retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET); 108931e31b8aSbellard if(retval >= 0) { 109031e31b8aSbellard retval = read(interpreter_fd, 109131e31b8aSbellard (char *) elf_phdata, 109231e31b8aSbellard sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 109331e31b8aSbellard } 109431e31b8aSbellard if (retval < 0) { 109531e31b8aSbellard perror("load_elf_interp"); 109631e31b8aSbellard exit(-1); 109731e31b8aSbellard free (elf_phdata); 109831e31b8aSbellard return retval; 109931e31b8aSbellard } 110031e31b8aSbellard #ifdef BSWAP_NEEDED 110131e31b8aSbellard eppnt = elf_phdata; 110231e31b8aSbellard for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { 110331e31b8aSbellard bswap_phdr(eppnt); 110431e31b8aSbellard } 110531e31b8aSbellard #endif 110609bfb054Sbellard 110709bfb054Sbellard if (interp_elf_ex->e_type == ET_DYN) { 1108e91c8a77Sths /* in order to avoid hardcoding the interpreter load 110909bfb054Sbellard address in qemu, we allocate a big enough memory zone */ 111054936004Sbellard error = target_mmap(0, INTERP_MAP_SIZE, 111109bfb054Sbellard PROT_NONE, MAP_PRIVATE | MAP_ANON, 111209bfb054Sbellard -1, 0); 111309bfb054Sbellard if (error == -1) { 111409bfb054Sbellard perror("mmap"); 111509bfb054Sbellard exit(-1); 111609bfb054Sbellard } 111709bfb054Sbellard load_addr = error; 111809bfb054Sbellard load_addr_set = 1; 111909bfb054Sbellard } 112009bfb054Sbellard 112131e31b8aSbellard eppnt = elf_phdata; 112231e31b8aSbellard for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) 112331e31b8aSbellard if (eppnt->p_type == PT_LOAD) { 112431e31b8aSbellard int elf_type = MAP_PRIVATE | MAP_DENYWRITE; 112531e31b8aSbellard int elf_prot = 0; 1126992f48a0Sblueswir1 abi_ulong vaddr = 0; 1127992f48a0Sblueswir1 abi_ulong k; 112831e31b8aSbellard 112931e31b8aSbellard if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; 113031e31b8aSbellard if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 113131e31b8aSbellard if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 113231e31b8aSbellard if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) { 113331e31b8aSbellard elf_type |= MAP_FIXED; 113431e31b8aSbellard vaddr = eppnt->p_vaddr; 113531e31b8aSbellard } 113654936004Sbellard error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr), 113754936004Sbellard eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr), 113831e31b8aSbellard elf_prot, 113931e31b8aSbellard elf_type, 114031e31b8aSbellard interpreter_fd, 114154936004Sbellard eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr)); 114231e31b8aSbellard 1143e89f07d3Spbrook if (error == -1) { 114431e31b8aSbellard /* Real error */ 114531e31b8aSbellard close(interpreter_fd); 114631e31b8aSbellard free(elf_phdata); 1147992f48a0Sblueswir1 return ~((abi_ulong)0UL); 114831e31b8aSbellard } 114931e31b8aSbellard 115031e31b8aSbellard if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { 115131e31b8aSbellard load_addr = error; 115231e31b8aSbellard load_addr_set = 1; 115331e31b8aSbellard } 115431e31b8aSbellard 115531e31b8aSbellard /* 115631e31b8aSbellard * Find the end of the file mapping for this phdr, and keep 115731e31b8aSbellard * track of the largest address we see for this. 115831e31b8aSbellard */ 115931e31b8aSbellard k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; 116031e31b8aSbellard if (k > elf_bss) elf_bss = k; 116131e31b8aSbellard 116231e31b8aSbellard /* 116331e31b8aSbellard * Do the same thing for the memory mapping - between 116431e31b8aSbellard * elf_bss and last_bss is the bss section. 116531e31b8aSbellard */ 116631e31b8aSbellard k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; 116731e31b8aSbellard if (k > last_bss) last_bss = k; 116831e31b8aSbellard } 116931e31b8aSbellard 117031e31b8aSbellard /* Now use mmap to map the library into memory. */ 117131e31b8aSbellard 117231e31b8aSbellard close(interpreter_fd); 117331e31b8aSbellard 117431e31b8aSbellard /* 117531e31b8aSbellard * Now fill out the bss section. First pad the last page up 117631e31b8aSbellard * to the page boundary, and then perform a mmap to make sure 117731e31b8aSbellard * that there are zeromapped pages up to and including the last 117831e31b8aSbellard * bss page. 117931e31b8aSbellard */ 1180768a4a36Sths padzero(elf_bss, last_bss); 118183fb7adfSbellard elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */ 118231e31b8aSbellard 118331e31b8aSbellard /* Map the last of the bss segment */ 118431e31b8aSbellard if (last_bss > elf_bss) { 118554936004Sbellard target_mmap(elf_bss, last_bss-elf_bss, 118631e31b8aSbellard PROT_READ|PROT_WRITE|PROT_EXEC, 118731e31b8aSbellard MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 118831e31b8aSbellard } 118931e31b8aSbellard free(elf_phdata); 119031e31b8aSbellard 119131e31b8aSbellard *interp_load_addr = load_addr; 1192992f48a0Sblueswir1 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr; 119331e31b8aSbellard } 119431e31b8aSbellard 119549918a75Spbrook static int symfind(const void *s0, const void *s1) 119649918a75Spbrook { 119749918a75Spbrook struct elf_sym *key = (struct elf_sym *)s0; 119849918a75Spbrook struct elf_sym *sym = (struct elf_sym *)s1; 119949918a75Spbrook int result = 0; 120049918a75Spbrook if (key->st_value < sym->st_value) { 120149918a75Spbrook result = -1; 120249918a75Spbrook } else if (key->st_value > sym->st_value + sym->st_size) { 120349918a75Spbrook result = 1; 120449918a75Spbrook } 120549918a75Spbrook return result; 120649918a75Spbrook } 120749918a75Spbrook 120849918a75Spbrook static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr) 120949918a75Spbrook { 121049918a75Spbrook #if ELF_CLASS == ELFCLASS32 121149918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf32; 121249918a75Spbrook #else 121349918a75Spbrook struct elf_sym *syms = s->disas_symtab.elf64; 121449918a75Spbrook #endif 121549918a75Spbrook 121649918a75Spbrook // binary search 121749918a75Spbrook struct elf_sym key; 121849918a75Spbrook struct elf_sym *sym; 121949918a75Spbrook 122049918a75Spbrook key.st_value = orig_addr; 122149918a75Spbrook 122249918a75Spbrook sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind); 122349918a75Spbrook if (sym != 0) { 122449918a75Spbrook return s->disas_strtab + sym->st_name; 122549918a75Spbrook } 122649918a75Spbrook 122749918a75Spbrook return ""; 122849918a75Spbrook } 122949918a75Spbrook 123049918a75Spbrook /* FIXME: This should use elf_ops.h */ 123149918a75Spbrook static int symcmp(const void *s0, const void *s1) 123249918a75Spbrook { 123349918a75Spbrook struct elf_sym *sym0 = (struct elf_sym *)s0; 123449918a75Spbrook struct elf_sym *sym1 = (struct elf_sym *)s1; 123549918a75Spbrook return (sym0->st_value < sym1->st_value) 123649918a75Spbrook ? -1 123749918a75Spbrook : ((sym0->st_value > sym1->st_value) ? 1 : 0); 123849918a75Spbrook } 123949918a75Spbrook 1240689f936fSbellard /* Best attempt to load symbols from this ELF object. */ 1241689f936fSbellard static void load_symbols(struct elfhdr *hdr, int fd) 1242689f936fSbellard { 124349918a75Spbrook unsigned int i, nsyms; 1244689f936fSbellard struct elf_shdr sechdr, symtab, strtab; 1245689f936fSbellard char *strings; 1246e80cfcfcSbellard struct syminfo *s; 124749918a75Spbrook struct elf_sym *syms; 124831e31b8aSbellard 1249689f936fSbellard lseek(fd, hdr->e_shoff, SEEK_SET); 1250689f936fSbellard for (i = 0; i < hdr->e_shnum; i++) { 1251689f936fSbellard if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) 1252689f936fSbellard return; 1253689f936fSbellard #ifdef BSWAP_NEEDED 1254689f936fSbellard bswap_shdr(&sechdr); 1255689f936fSbellard #endif 1256689f936fSbellard if (sechdr.sh_type == SHT_SYMTAB) { 1257689f936fSbellard symtab = sechdr; 1258689f936fSbellard lseek(fd, hdr->e_shoff 1259689f936fSbellard + sizeof(sechdr) * sechdr.sh_link, SEEK_SET); 1260689f936fSbellard if (read(fd, &strtab, sizeof(strtab)) 1261689f936fSbellard != sizeof(strtab)) 1262689f936fSbellard return; 1263689f936fSbellard #ifdef BSWAP_NEEDED 1264689f936fSbellard bswap_shdr(&strtab); 1265689f936fSbellard #endif 1266689f936fSbellard goto found; 1267689f936fSbellard } 1268689f936fSbellard } 1269689f936fSbellard return; /* Shouldn't happen... */ 1270689f936fSbellard 1271689f936fSbellard found: 1272689f936fSbellard /* Now know where the strtab and symtab are. Snarf them. */ 1273e80cfcfcSbellard s = malloc(sizeof(*s)); 127449918a75Spbrook syms = malloc(symtab.sh_size); 127549918a75Spbrook if (!syms) 127649918a75Spbrook return; 1277e80cfcfcSbellard s->disas_strtab = strings = malloc(strtab.sh_size); 127849918a75Spbrook if (!s->disas_strtab) 1279689f936fSbellard return; 1280689f936fSbellard 1281689f936fSbellard lseek(fd, symtab.sh_offset, SEEK_SET); 128249918a75Spbrook if (read(fd, syms, symtab.sh_size) != symtab.sh_size) 1283689f936fSbellard return; 1284689f936fSbellard 128549918a75Spbrook nsyms = symtab.sh_size / sizeof(struct elf_sym); 1286689f936fSbellard 128749918a75Spbrook i = 0; 128849918a75Spbrook while (i < nsyms) { 128949918a75Spbrook #ifdef BSWAP_NEEDED 129049918a75Spbrook bswap_sym(syms + i); 12910774bed1Sblueswir1 #endif 129249918a75Spbrook // Throw away entries which we do not need. 129349918a75Spbrook if (syms[i].st_shndx == SHN_UNDEF || 129449918a75Spbrook syms[i].st_shndx >= SHN_LORESERVE || 129549918a75Spbrook ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 129649918a75Spbrook nsyms--; 129749918a75Spbrook if (i < nsyms) { 129849918a75Spbrook syms[i] = syms[nsyms]; 129949918a75Spbrook } 130049918a75Spbrook continue; 130149918a75Spbrook } 130249918a75Spbrook #if defined(TARGET_ARM) || defined (TARGET_MIPS) 130349918a75Spbrook /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 130449918a75Spbrook syms[i].st_value &= ~(target_ulong)1; 130549918a75Spbrook #endif 130649918a75Spbrook i++; 130749918a75Spbrook } 130849918a75Spbrook syms = realloc(syms, nsyms * sizeof(*syms)); 130949918a75Spbrook 131049918a75Spbrook qsort(syms, nsyms, sizeof(*syms), symcmp); 131149918a75Spbrook 1312689f936fSbellard lseek(fd, strtab.sh_offset, SEEK_SET); 1313689f936fSbellard if (read(fd, strings, strtab.sh_size) != strtab.sh_size) 1314689f936fSbellard return; 131549918a75Spbrook s->disas_num_syms = nsyms; 131649918a75Spbrook #if ELF_CLASS == ELFCLASS32 131749918a75Spbrook s->disas_symtab.elf32 = syms; 131849918a75Spbrook s->lookup_symbol = lookup_symbolxx; 131949918a75Spbrook #else 132049918a75Spbrook s->disas_symtab.elf64 = syms; 132149918a75Spbrook s->lookup_symbol = lookup_symbolxx; 132249918a75Spbrook #endif 1323e80cfcfcSbellard s->next = syminfos; 1324e80cfcfcSbellard syminfos = s; 1325689f936fSbellard } 132631e31b8aSbellard 1327e5fe0c52Spbrook int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, 132831e31b8aSbellard struct image_info * info) 132931e31b8aSbellard { 133031e31b8aSbellard struct elfhdr elf_ex; 133131e31b8aSbellard struct elfhdr interp_elf_ex; 133231e31b8aSbellard struct exec interp_ex; 133331e31b8aSbellard int interpreter_fd = -1; /* avoid warning */ 1334992f48a0Sblueswir1 abi_ulong load_addr, load_bias; 133531e31b8aSbellard int load_addr_set = 0; 133631e31b8aSbellard unsigned int interpreter_type = INTERPRETER_NONE; 133731e31b8aSbellard unsigned char ibcs2_interpreter; 133831e31b8aSbellard int i; 1339992f48a0Sblueswir1 abi_ulong mapped_addr; 134031e31b8aSbellard struct elf_phdr * elf_ppnt; 134131e31b8aSbellard struct elf_phdr *elf_phdata; 1342992f48a0Sblueswir1 abi_ulong elf_bss, k, elf_brk; 134331e31b8aSbellard int retval; 134431e31b8aSbellard char * elf_interpreter; 1345992f48a0Sblueswir1 abi_ulong elf_entry, interp_load_addr = 0; 134631e31b8aSbellard int status; 1347992f48a0Sblueswir1 abi_ulong start_code, end_code, start_data, end_data; 1348992f48a0Sblueswir1 abi_ulong reloc_func_desc = 0; 1349992f48a0Sblueswir1 abi_ulong elf_stack; 135031e31b8aSbellard char passed_fileno[6]; 135131e31b8aSbellard 135231e31b8aSbellard ibcs2_interpreter = 0; 135331e31b8aSbellard status = 0; 135431e31b8aSbellard load_addr = 0; 135509bfb054Sbellard load_bias = 0; 135631e31b8aSbellard elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ 135731e31b8aSbellard #ifdef BSWAP_NEEDED 135831e31b8aSbellard bswap_ehdr(&elf_ex); 135931e31b8aSbellard #endif 136031e31b8aSbellard 136131e31b8aSbellard /* First of all, some simple consistency checks */ 136231e31b8aSbellard if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || 136331e31b8aSbellard (! elf_check_arch(elf_ex.e_machine))) { 136431e31b8aSbellard return -ENOEXEC; 136531e31b8aSbellard } 136631e31b8aSbellard 1367e5fe0c52Spbrook bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); 1368e5fe0c52Spbrook bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); 1369e5fe0c52Spbrook bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); 1370e5fe0c52Spbrook if (!bprm->p) { 1371e5fe0c52Spbrook retval = -E2BIG; 1372e5fe0c52Spbrook } 1373e5fe0c52Spbrook 137431e31b8aSbellard /* Now read in all of the header information */ 137531e31b8aSbellard elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); 137631e31b8aSbellard if (elf_phdata == NULL) { 137731e31b8aSbellard return -ENOMEM; 137831e31b8aSbellard } 137931e31b8aSbellard 138031e31b8aSbellard retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET); 138131e31b8aSbellard if(retval > 0) { 138231e31b8aSbellard retval = read(bprm->fd, (char *) elf_phdata, 138331e31b8aSbellard elf_ex.e_phentsize * elf_ex.e_phnum); 138431e31b8aSbellard } 138531e31b8aSbellard 138631e31b8aSbellard if (retval < 0) { 138731e31b8aSbellard perror("load_elf_binary"); 138831e31b8aSbellard exit(-1); 138931e31b8aSbellard free (elf_phdata); 139031e31b8aSbellard return -errno; 139131e31b8aSbellard } 139231e31b8aSbellard 1393b17780d5Sbellard #ifdef BSWAP_NEEDED 1394b17780d5Sbellard elf_ppnt = elf_phdata; 1395b17780d5Sbellard for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) { 1396b17780d5Sbellard bswap_phdr(elf_ppnt); 1397b17780d5Sbellard } 1398b17780d5Sbellard #endif 139931e31b8aSbellard elf_ppnt = elf_phdata; 140031e31b8aSbellard 140131e31b8aSbellard elf_bss = 0; 140231e31b8aSbellard elf_brk = 0; 140331e31b8aSbellard 140431e31b8aSbellard 1405992f48a0Sblueswir1 elf_stack = ~((abi_ulong)0UL); 140631e31b8aSbellard elf_interpreter = NULL; 1407992f48a0Sblueswir1 start_code = ~((abi_ulong)0UL); 140831e31b8aSbellard end_code = 0; 1409863cf0b7Sj_mayer start_data = 0; 141031e31b8aSbellard end_data = 0; 141198448f58Sblueswir1 interp_ex.a_info = 0; 141231e31b8aSbellard 141331e31b8aSbellard for(i=0;i < elf_ex.e_phnum; i++) { 141431e31b8aSbellard if (elf_ppnt->p_type == PT_INTERP) { 141531e31b8aSbellard if ( elf_interpreter != NULL ) 141631e31b8aSbellard { 141731e31b8aSbellard free (elf_phdata); 141831e31b8aSbellard free(elf_interpreter); 141931e31b8aSbellard close(bprm->fd); 142031e31b8aSbellard return -EINVAL; 142131e31b8aSbellard } 142231e31b8aSbellard 142331e31b8aSbellard /* This is the program interpreter used for 142431e31b8aSbellard * shared libraries - for now assume that this 142531e31b8aSbellard * is an a.out format binary 142631e31b8aSbellard */ 142731e31b8aSbellard 142832ce6337Sbellard elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); 142931e31b8aSbellard 143031e31b8aSbellard if (elf_interpreter == NULL) { 143131e31b8aSbellard free (elf_phdata); 143231e31b8aSbellard close(bprm->fd); 143331e31b8aSbellard return -ENOMEM; 143431e31b8aSbellard } 143531e31b8aSbellard 143631e31b8aSbellard retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); 143731e31b8aSbellard if(retval >= 0) { 143832ce6337Sbellard retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); 143931e31b8aSbellard } 144031e31b8aSbellard if(retval < 0) { 144131e31b8aSbellard perror("load_elf_binary2"); 144231e31b8aSbellard exit(-1); 144331e31b8aSbellard } 144431e31b8aSbellard 144531e31b8aSbellard /* If the program interpreter is one of these two, 144631e31b8aSbellard then assume an iBCS2 image. Otherwise assume 144731e31b8aSbellard a native linux image. */ 144831e31b8aSbellard 144931e31b8aSbellard /* JRP - Need to add X86 lib dir stuff here... */ 145031e31b8aSbellard 145131e31b8aSbellard if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || 145231e31b8aSbellard strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) { 145331e31b8aSbellard ibcs2_interpreter = 1; 145431e31b8aSbellard } 145531e31b8aSbellard 145631e31b8aSbellard #if 0 145731e31b8aSbellard printf("Using ELF interpreter %s\n", elf_interpreter); 145831e31b8aSbellard #endif 145931e31b8aSbellard if (retval >= 0) { 146032ce6337Sbellard retval = open(path(elf_interpreter), O_RDONLY); 146131e31b8aSbellard if(retval >= 0) { 146231e31b8aSbellard interpreter_fd = retval; 146331e31b8aSbellard } 146431e31b8aSbellard else { 146531e31b8aSbellard perror(elf_interpreter); 146631e31b8aSbellard exit(-1); 146731e31b8aSbellard /* retval = -errno; */ 146831e31b8aSbellard } 146931e31b8aSbellard } 147031e31b8aSbellard 147131e31b8aSbellard if (retval >= 0) { 147231e31b8aSbellard retval = lseek(interpreter_fd, 0, SEEK_SET); 147331e31b8aSbellard if(retval >= 0) { 147431e31b8aSbellard retval = read(interpreter_fd,bprm->buf,128); 147531e31b8aSbellard } 147631e31b8aSbellard } 147731e31b8aSbellard if (retval >= 0) { 147831e31b8aSbellard interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */ 147931e31b8aSbellard interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */ 148031e31b8aSbellard } 148131e31b8aSbellard if (retval < 0) { 148231e31b8aSbellard perror("load_elf_binary3"); 148331e31b8aSbellard exit(-1); 148431e31b8aSbellard free (elf_phdata); 148531e31b8aSbellard free(elf_interpreter); 148631e31b8aSbellard close(bprm->fd); 148731e31b8aSbellard return retval; 148831e31b8aSbellard } 148931e31b8aSbellard } 149031e31b8aSbellard elf_ppnt++; 149131e31b8aSbellard } 149231e31b8aSbellard 149331e31b8aSbellard /* Some simple consistency checks for the interpreter */ 149431e31b8aSbellard if (elf_interpreter){ 149531e31b8aSbellard interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; 149631e31b8aSbellard 149731e31b8aSbellard /* Now figure out which format our binary is */ 149831e31b8aSbellard if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && 149931e31b8aSbellard (N_MAGIC(interp_ex) != QMAGIC)) { 150031e31b8aSbellard interpreter_type = INTERPRETER_ELF; 150131e31b8aSbellard } 150231e31b8aSbellard 150331e31b8aSbellard if (interp_elf_ex.e_ident[0] != 0x7f || 1504b55266b5Sblueswir1 strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) { 150531e31b8aSbellard interpreter_type &= ~INTERPRETER_ELF; 150631e31b8aSbellard } 150731e31b8aSbellard 150831e31b8aSbellard if (!interpreter_type) { 150931e31b8aSbellard free(elf_interpreter); 151031e31b8aSbellard free(elf_phdata); 151131e31b8aSbellard close(bprm->fd); 151231e31b8aSbellard return -ELIBBAD; 151331e31b8aSbellard } 151431e31b8aSbellard } 151531e31b8aSbellard 151631e31b8aSbellard /* OK, we are done with that, now set up the arg stuff, 151731e31b8aSbellard and then start this sucker up */ 151831e31b8aSbellard 1519e5fe0c52Spbrook { 152031e31b8aSbellard char * passed_p; 152131e31b8aSbellard 152231e31b8aSbellard if (interpreter_type == INTERPRETER_AOUT) { 1523eba2af63Sbellard snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd); 152431e31b8aSbellard passed_p = passed_fileno; 152531e31b8aSbellard 152631e31b8aSbellard if (elf_interpreter) { 1527e5fe0c52Spbrook bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p); 152831e31b8aSbellard bprm->argc++; 152931e31b8aSbellard } 153031e31b8aSbellard } 153131e31b8aSbellard if (!bprm->p) { 153231e31b8aSbellard if (elf_interpreter) { 153331e31b8aSbellard free(elf_interpreter); 153431e31b8aSbellard } 153531e31b8aSbellard free (elf_phdata); 153631e31b8aSbellard close(bprm->fd); 153731e31b8aSbellard return -E2BIG; 153831e31b8aSbellard } 153931e31b8aSbellard } 154031e31b8aSbellard 154131e31b8aSbellard /* OK, This is the point of no return */ 154231e31b8aSbellard info->end_data = 0; 154331e31b8aSbellard info->end_code = 0; 1544992f48a0Sblueswir1 info->start_mmap = (abi_ulong)ELF_START_MMAP; 154531e31b8aSbellard info->mmap = 0; 1546992f48a0Sblueswir1 elf_entry = (abi_ulong) elf_ex.e_entry; 154731e31b8aSbellard 1548379f6698SPaul Brook #if defined(CONFIG_USE_GUEST_BASE) 1549379f6698SPaul Brook /* 1550379f6698SPaul Brook * In case where user has not explicitly set the guest_base, we 1551379f6698SPaul Brook * probe here that should we set it automatically. 1552379f6698SPaul Brook */ 1553379f6698SPaul Brook if (!have_guest_base) { 1554379f6698SPaul Brook /* 1555379f6698SPaul Brook * Go through ELF program header table and find out whether 1556379f6698SPaul Brook * any of the segments drop below our current mmap_min_addr and 1557379f6698SPaul Brook * in that case set guest_base to corresponding address. 1558379f6698SPaul Brook */ 1559379f6698SPaul Brook for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; 1560379f6698SPaul Brook i++, elf_ppnt++) { 1561379f6698SPaul Brook if (elf_ppnt->p_type != PT_LOAD) 1562379f6698SPaul Brook continue; 1563379f6698SPaul Brook if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) { 1564379f6698SPaul Brook guest_base = HOST_PAGE_ALIGN(mmap_min_addr); 1565379f6698SPaul Brook break; 1566379f6698SPaul Brook } 1567379f6698SPaul Brook } 1568379f6698SPaul Brook } 1569379f6698SPaul Brook #endif /* CONFIG_USE_GUEST_BASE */ 1570379f6698SPaul Brook 157131e31b8aSbellard /* Do this so that we can load the interpreter, if need be. We will 157231e31b8aSbellard change some of these later */ 157331e31b8aSbellard info->rss = 0; 157431e31b8aSbellard bprm->p = setup_arg_pages(bprm->p, bprm, info); 157531e31b8aSbellard info->start_stack = bprm->p; 157631e31b8aSbellard 157731e31b8aSbellard /* Now we do a little grungy work by mmaping the ELF image into 157831e31b8aSbellard * the correct location in memory. At this point, we assume that 157931e31b8aSbellard * the image should be loaded at fixed address, not at a variable 158031e31b8aSbellard * address. 158131e31b8aSbellard */ 158231e31b8aSbellard 158331e31b8aSbellard for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { 158431e31b8aSbellard int elf_prot = 0; 158509bfb054Sbellard int elf_flags = 0; 1586992f48a0Sblueswir1 abi_ulong error; 158709bfb054Sbellard 158809bfb054Sbellard if (elf_ppnt->p_type != PT_LOAD) 158909bfb054Sbellard continue; 159009bfb054Sbellard 159131e31b8aSbellard if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; 159231e31b8aSbellard if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 159331e31b8aSbellard if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 159409bfb054Sbellard elf_flags = MAP_PRIVATE | MAP_DENYWRITE; 159509bfb054Sbellard if (elf_ex.e_type == ET_EXEC || load_addr_set) { 159609bfb054Sbellard elf_flags |= MAP_FIXED; 159709bfb054Sbellard } else if (elf_ex.e_type == ET_DYN) { 159809bfb054Sbellard /* Try and get dynamic programs out of the way of the default mmap 159909bfb054Sbellard base, as well as whatever program they might try to exec. This 160009bfb054Sbellard is because the brk will follow the loader, and is not movable. */ 160109bfb054Sbellard /* NOTE: for qemu, we do a big mmap to get enough space 1602e91c8a77Sths without hardcoding any address */ 160354936004Sbellard error = target_mmap(0, ET_DYN_MAP_SIZE, 160409bfb054Sbellard PROT_NONE, MAP_PRIVATE | MAP_ANON, 160509bfb054Sbellard -1, 0); 160609bfb054Sbellard if (error == -1) { 160709bfb054Sbellard perror("mmap"); 160809bfb054Sbellard exit(-1); 160909bfb054Sbellard } 161054936004Sbellard load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); 161109bfb054Sbellard } 161231e31b8aSbellard 161354936004Sbellard error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), 161431e31b8aSbellard (elf_ppnt->p_filesz + 161554936004Sbellard TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), 161631e31b8aSbellard elf_prot, 161731e31b8aSbellard (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), 161831e31b8aSbellard bprm->fd, 161931e31b8aSbellard (elf_ppnt->p_offset - 162054936004Sbellard TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); 162109bfb054Sbellard if (error == -1) { 162231e31b8aSbellard perror("mmap"); 162331e31b8aSbellard exit(-1); 162431e31b8aSbellard } 162531e31b8aSbellard 162631e31b8aSbellard #ifdef LOW_ELF_STACK 162754936004Sbellard if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) 162854936004Sbellard elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr); 162931e31b8aSbellard #endif 163031e31b8aSbellard 163131e31b8aSbellard if (!load_addr_set) { 163231e31b8aSbellard load_addr_set = 1; 163309bfb054Sbellard load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; 163409bfb054Sbellard if (elf_ex.e_type == ET_DYN) { 163509bfb054Sbellard load_bias += error - 163654936004Sbellard TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); 163709bfb054Sbellard load_addr += load_bias; 163884409ddbSj_mayer reloc_func_desc = load_bias; 163909bfb054Sbellard } 164031e31b8aSbellard } 164131e31b8aSbellard k = elf_ppnt->p_vaddr; 164209bfb054Sbellard if (k < start_code) 164309bfb054Sbellard start_code = k; 1644863cf0b7Sj_mayer if (start_data < k) 1645863cf0b7Sj_mayer start_data = k; 164631e31b8aSbellard k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; 164709bfb054Sbellard if (k > elf_bss) 164809bfb054Sbellard elf_bss = k; 164931e31b8aSbellard if ((elf_ppnt->p_flags & PF_X) && end_code < k) 165031e31b8aSbellard end_code = k; 165109bfb054Sbellard if (end_data < k) 165209bfb054Sbellard end_data = k; 165331e31b8aSbellard k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; 165431e31b8aSbellard if (k > elf_brk) elf_brk = k; 165531e31b8aSbellard } 165609bfb054Sbellard 165709bfb054Sbellard elf_entry += load_bias; 165809bfb054Sbellard elf_bss += load_bias; 165909bfb054Sbellard elf_brk += load_bias; 166009bfb054Sbellard start_code += load_bias; 166109bfb054Sbellard end_code += load_bias; 1662863cf0b7Sj_mayer start_data += load_bias; 166309bfb054Sbellard end_data += load_bias; 166431e31b8aSbellard 166531e31b8aSbellard if (elf_interpreter) { 166631e31b8aSbellard if (interpreter_type & 1) { 166731e31b8aSbellard elf_entry = load_aout_interp(&interp_ex, interpreter_fd); 166831e31b8aSbellard } 166931e31b8aSbellard else if (interpreter_type & 2) { 167031e31b8aSbellard elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, 167131e31b8aSbellard &interp_load_addr); 167231e31b8aSbellard } 167384409ddbSj_mayer reloc_func_desc = interp_load_addr; 167431e31b8aSbellard 167531e31b8aSbellard close(interpreter_fd); 167631e31b8aSbellard free(elf_interpreter); 167731e31b8aSbellard 1678992f48a0Sblueswir1 if (elf_entry == ~((abi_ulong)0UL)) { 167931e31b8aSbellard printf("Unable to load interpreter\n"); 168031e31b8aSbellard free(elf_phdata); 168131e31b8aSbellard exit(-1); 168231e31b8aSbellard return 0; 168331e31b8aSbellard } 168431e31b8aSbellard } 168531e31b8aSbellard 168631e31b8aSbellard free(elf_phdata); 168731e31b8aSbellard 168893fcfe39Saliguori if (qemu_log_enabled()) 1689689f936fSbellard load_symbols(&elf_ex, bprm->fd); 1690689f936fSbellard 169131e31b8aSbellard if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); 169231e31b8aSbellard info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); 169331e31b8aSbellard 169431e31b8aSbellard #ifdef LOW_ELF_STACK 169531e31b8aSbellard info->start_stack = bprm->p = elf_stack - 4; 169631e31b8aSbellard #endif 169753a5960aSpbrook bprm->p = create_elf_tables(bprm->p, 169831e31b8aSbellard bprm->argc, 169931e31b8aSbellard bprm->envc, 1700a1516e92Sbellard &elf_ex, 170109bfb054Sbellard load_addr, load_bias, 170231e31b8aSbellard interp_load_addr, 170331e31b8aSbellard (interpreter_type == INTERPRETER_AOUT ? 0 : 1), 170431e31b8aSbellard info); 170592a343daSj_mayer info->load_addr = reloc_func_desc; 170631e31b8aSbellard info->start_brk = info->brk = elf_brk; 170731e31b8aSbellard info->end_code = end_code; 170831e31b8aSbellard info->start_code = start_code; 1709863cf0b7Sj_mayer info->start_data = start_data; 171031e31b8aSbellard info->end_data = end_data; 171131e31b8aSbellard info->start_stack = bprm->p; 171231e31b8aSbellard 171331e31b8aSbellard /* Calling set_brk effectively mmaps the pages that we need for the bss and break 171431e31b8aSbellard sections */ 171531e31b8aSbellard set_brk(elf_bss, elf_brk); 171631e31b8aSbellard 1717768a4a36Sths padzero(elf_bss, elf_brk); 171831e31b8aSbellard 171931e31b8aSbellard #if 0 172031e31b8aSbellard printf("(start_brk) %x\n" , info->start_brk); 172131e31b8aSbellard printf("(end_code) %x\n" , info->end_code); 172231e31b8aSbellard printf("(start_code) %x\n" , info->start_code); 172331e31b8aSbellard printf("(end_data) %x\n" , info->end_data); 172431e31b8aSbellard printf("(start_stack) %x\n" , info->start_stack); 172531e31b8aSbellard printf("(brk) %x\n" , info->brk); 172631e31b8aSbellard #endif 172731e31b8aSbellard 172831e31b8aSbellard if ( info->personality == PER_SVR4 ) 172931e31b8aSbellard { 173031e31b8aSbellard /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 173131e31b8aSbellard and some applications "depend" upon this behavior. 173231e31b8aSbellard Since we do not have the power to recompile these, we 173331e31b8aSbellard emulate the SVr4 behavior. Sigh. */ 173483fb7adfSbellard mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, 173531e31b8aSbellard MAP_FIXED | MAP_PRIVATE, -1, 0); 173631e31b8aSbellard } 173731e31b8aSbellard 173831e31b8aSbellard info->entry = elf_entry; 173931e31b8aSbellard 1740edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 1741edf8e2afSMika Westerberg bprm->core_dump = &elf_core_dump; 1742edf8e2afSMika Westerberg #endif 1743edf8e2afSMika Westerberg 174431e31b8aSbellard return 0; 174531e31b8aSbellard } 174631e31b8aSbellard 1747edf8e2afSMika Westerberg #ifdef USE_ELF_CORE_DUMP 1748edf8e2afSMika Westerberg 1749edf8e2afSMika Westerberg /* 1750edf8e2afSMika Westerberg * Definitions to generate Intel SVR4-like core files. 1751a2547a13SLaurent Desnogues * These mostly have the same names as the SVR4 types with "target_elf_" 1752edf8e2afSMika Westerberg * tacked on the front to prevent clashes with linux definitions, 1753edf8e2afSMika Westerberg * and the typedef forms have been avoided. This is mostly like 1754edf8e2afSMika Westerberg * the SVR4 structure, but more Linuxy, with things that Linux does 1755edf8e2afSMika Westerberg * not support and which gdb doesn't really use excluded. 1756edf8e2afSMika Westerberg * 1757edf8e2afSMika Westerberg * Fields we don't dump (their contents is zero) in linux-user qemu 1758edf8e2afSMika Westerberg * are marked with XXX. 1759edf8e2afSMika Westerberg * 1760edf8e2afSMika Westerberg * Core dump code is copied from linux kernel (fs/binfmt_elf.c). 1761edf8e2afSMika Westerberg * 1762edf8e2afSMika Westerberg * Porting ELF coredump for target is (quite) simple process. First you 1763edf8e2afSMika Westerberg * define ELF_USE_CORE_DUMP in target ELF code (where init_thread() for 1764edf8e2afSMika Westerberg * the target resides): 1765edf8e2afSMika Westerberg * 1766edf8e2afSMika Westerberg * #define USE_ELF_CORE_DUMP 1767edf8e2afSMika Westerberg * 1768edf8e2afSMika Westerberg * Next you define type of register set used for dumping. ELF specification 1769edf8e2afSMika Westerberg * says that it needs to be array of elf_greg_t that has size of ELF_NREG. 1770edf8e2afSMika Westerberg * 1771a2547a13SLaurent Desnogues * typedef <target_regtype> target_elf_greg_t; 1772edf8e2afSMika Westerberg * #define ELF_NREG <number of registers> 1773a2547a13SLaurent Desnogues * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; 1774edf8e2afSMika Westerberg * 1775edf8e2afSMika Westerberg * Then define following types to match target types. Actual types can 1776edf8e2afSMika Westerberg * be found from linux kernel (arch/<ARCH>/include/asm/posix_types.h): 1777edf8e2afSMika Westerberg * 1778edf8e2afSMika Westerberg * typedef <target_uid_type> target_uid_t; 1779edf8e2afSMika Westerberg * typedef <target_gid_type> target_gid_t; 1780edf8e2afSMika Westerberg * typedef <target_pid_type> target_pid_t; 1781edf8e2afSMika Westerberg * 1782edf8e2afSMika Westerberg * Last step is to implement target specific function that copies registers 1783edf8e2afSMika Westerberg * from given cpu into just specified register set. Prototype is: 1784edf8e2afSMika Westerberg * 1785a2547a13SLaurent Desnogues * static void elf_core_copy_regs(taret_elf_gregset_t *regs, 1786a2547a13SLaurent Desnogues * const CPUState *env); 1787edf8e2afSMika Westerberg * 1788edf8e2afSMika Westerberg * Parameters: 1789edf8e2afSMika Westerberg * regs - copy register values into here (allocated and zeroed by caller) 1790edf8e2afSMika Westerberg * env - copy registers from here 1791edf8e2afSMika Westerberg * 1792edf8e2afSMika Westerberg * Example for ARM target is provided in this file. 1793edf8e2afSMika Westerberg */ 1794edf8e2afSMika Westerberg 1795edf8e2afSMika Westerberg /* An ELF note in memory */ 1796edf8e2afSMika Westerberg struct memelfnote { 1797edf8e2afSMika Westerberg const char *name; 1798edf8e2afSMika Westerberg size_t namesz; 1799edf8e2afSMika Westerberg size_t namesz_rounded; 1800edf8e2afSMika Westerberg int type; 1801edf8e2afSMika Westerberg size_t datasz; 1802edf8e2afSMika Westerberg void *data; 1803edf8e2afSMika Westerberg size_t notesz; 1804edf8e2afSMika Westerberg }; 1805edf8e2afSMika Westerberg 1806a2547a13SLaurent Desnogues struct target_elf_siginfo { 1807edf8e2afSMika Westerberg int si_signo; /* signal number */ 1808edf8e2afSMika Westerberg int si_code; /* extra code */ 1809edf8e2afSMika Westerberg int si_errno; /* errno */ 1810edf8e2afSMika Westerberg }; 1811edf8e2afSMika Westerberg 1812a2547a13SLaurent Desnogues struct target_elf_prstatus { 1813a2547a13SLaurent Desnogues struct target_elf_siginfo pr_info; /* Info associated with signal */ 1814edf8e2afSMika Westerberg short pr_cursig; /* Current signal */ 1815edf8e2afSMika Westerberg target_ulong pr_sigpend; /* XXX */ 1816edf8e2afSMika Westerberg target_ulong pr_sighold; /* XXX */ 1817edf8e2afSMika Westerberg target_pid_t pr_pid; 1818edf8e2afSMika Westerberg target_pid_t pr_ppid; 1819edf8e2afSMika Westerberg target_pid_t pr_pgrp; 1820edf8e2afSMika Westerberg target_pid_t pr_sid; 1821edf8e2afSMika Westerberg struct target_timeval pr_utime; /* XXX User time */ 1822edf8e2afSMika Westerberg struct target_timeval pr_stime; /* XXX System time */ 1823edf8e2afSMika Westerberg struct target_timeval pr_cutime; /* XXX Cumulative user time */ 1824edf8e2afSMika Westerberg struct target_timeval pr_cstime; /* XXX Cumulative system time */ 1825a2547a13SLaurent Desnogues target_elf_gregset_t pr_reg; /* GP registers */ 1826edf8e2afSMika Westerberg int pr_fpvalid; /* XXX */ 1827edf8e2afSMika Westerberg }; 1828edf8e2afSMika Westerberg 1829edf8e2afSMika Westerberg #define ELF_PRARGSZ (80) /* Number of chars for args */ 1830edf8e2afSMika Westerberg 1831a2547a13SLaurent Desnogues struct target_elf_prpsinfo { 1832edf8e2afSMika Westerberg char pr_state; /* numeric process state */ 1833edf8e2afSMika Westerberg char pr_sname; /* char for pr_state */ 1834edf8e2afSMika Westerberg char pr_zomb; /* zombie */ 1835edf8e2afSMika Westerberg char pr_nice; /* nice val */ 1836edf8e2afSMika Westerberg target_ulong pr_flag; /* flags */ 1837edf8e2afSMika Westerberg target_uid_t pr_uid; 1838edf8e2afSMika Westerberg target_gid_t pr_gid; 1839edf8e2afSMika Westerberg target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; 1840edf8e2afSMika Westerberg /* Lots missing */ 1841edf8e2afSMika Westerberg char pr_fname[16]; /* filename of executable */ 1842edf8e2afSMika Westerberg char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ 1843edf8e2afSMika Westerberg }; 1844edf8e2afSMika Westerberg 1845edf8e2afSMika Westerberg /* Here is the structure in which status of each thread is captured. */ 1846edf8e2afSMika Westerberg struct elf_thread_status { 1847edf8e2afSMika Westerberg TAILQ_ENTRY(elf_thread_status) ets_link; 1848a2547a13SLaurent Desnogues struct target_elf_prstatus prstatus; /* NT_PRSTATUS */ 1849edf8e2afSMika Westerberg #if 0 1850edf8e2afSMika Westerberg elf_fpregset_t fpu; /* NT_PRFPREG */ 1851edf8e2afSMika Westerberg struct task_struct *thread; 1852edf8e2afSMika Westerberg elf_fpxregset_t xfpu; /* ELF_CORE_XFPREG_TYPE */ 1853edf8e2afSMika Westerberg #endif 1854edf8e2afSMika Westerberg struct memelfnote notes[1]; 1855edf8e2afSMika Westerberg int num_notes; 1856edf8e2afSMika Westerberg }; 1857edf8e2afSMika Westerberg 1858edf8e2afSMika Westerberg struct elf_note_info { 1859edf8e2afSMika Westerberg struct memelfnote *notes; 1860a2547a13SLaurent Desnogues struct target_elf_prstatus *prstatus; /* NT_PRSTATUS */ 1861a2547a13SLaurent Desnogues struct target_elf_prpsinfo *psinfo; /* NT_PRPSINFO */ 1862edf8e2afSMika Westerberg 1863edf8e2afSMika Westerberg TAILQ_HEAD(thread_list_head, elf_thread_status) thread_list; 1864edf8e2afSMika Westerberg #if 0 1865edf8e2afSMika Westerberg /* 1866edf8e2afSMika Westerberg * Current version of ELF coredump doesn't support 1867edf8e2afSMika Westerberg * dumping fp regs etc. 1868edf8e2afSMika Westerberg */ 1869edf8e2afSMika Westerberg elf_fpregset_t *fpu; 1870edf8e2afSMika Westerberg elf_fpxregset_t *xfpu; 1871edf8e2afSMika Westerberg int thread_status_size; 1872edf8e2afSMika Westerberg #endif 1873edf8e2afSMika Westerberg int notes_size; 1874edf8e2afSMika Westerberg int numnote; 1875edf8e2afSMika Westerberg }; 1876edf8e2afSMika Westerberg 1877edf8e2afSMika Westerberg struct vm_area_struct { 1878edf8e2afSMika Westerberg abi_ulong vma_start; /* start vaddr of memory region */ 1879edf8e2afSMika Westerberg abi_ulong vma_end; /* end vaddr of memory region */ 1880edf8e2afSMika Westerberg abi_ulong vma_flags; /* protection etc. flags for the region */ 1881edf8e2afSMika Westerberg TAILQ_ENTRY(vm_area_struct) vma_link; 1882edf8e2afSMika Westerberg }; 1883edf8e2afSMika Westerberg 1884edf8e2afSMika Westerberg struct mm_struct { 1885edf8e2afSMika Westerberg TAILQ_HEAD(, vm_area_struct) mm_mmap; 1886edf8e2afSMika Westerberg int mm_count; /* number of mappings */ 1887edf8e2afSMika Westerberg }; 1888edf8e2afSMika Westerberg 1889edf8e2afSMika Westerberg static struct mm_struct *vma_init(void); 1890edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *); 1891edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *, abi_ulong, 1892edf8e2afSMika Westerberg abi_ulong, abi_ulong); 1893edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *); 1894edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *); 1895edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *); 1896edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *); 1897edf8e2afSMika Westerberg static int vma_walker(void *priv, unsigned long start, unsigned long end, 1898edf8e2afSMika Westerberg unsigned long flags); 1899edf8e2afSMika Westerberg 1900edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); 1901edf8e2afSMika Westerberg static void fill_note(struct memelfnote *, const char *, int, 1902edf8e2afSMika Westerberg unsigned int, void *); 1903a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); 1904a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); 1905edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *, const TaskState *); 1906edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); 1907edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *); 1908edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *); 1909edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *, long, const CPUState *); 1910edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *, const CPUState *); 1911edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *, char *, size_t); 1912edf8e2afSMika Westerberg 1913edf8e2afSMika Westerberg static int dump_write(int, const void *, size_t); 1914edf8e2afSMika Westerberg static int write_note(struct memelfnote *, int); 1915edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *, int); 1916edf8e2afSMika Westerberg 1917edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 1918a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *); 1919a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *); 1920edf8e2afSMika Westerberg 1921a2547a13SLaurent Desnogues static void bswap_prstatus(struct target_elf_prstatus *prstatus) 1922edf8e2afSMika Westerberg { 1923edf8e2afSMika Westerberg prstatus->pr_info.si_signo = tswapl(prstatus->pr_info.si_signo); 1924edf8e2afSMika Westerberg prstatus->pr_info.si_code = tswapl(prstatus->pr_info.si_code); 1925edf8e2afSMika Westerberg prstatus->pr_info.si_errno = tswapl(prstatus->pr_info.si_errno); 1926edf8e2afSMika Westerberg prstatus->pr_cursig = tswap16(prstatus->pr_cursig); 1927edf8e2afSMika Westerberg prstatus->pr_sigpend = tswapl(prstatus->pr_sigpend); 1928edf8e2afSMika Westerberg prstatus->pr_sighold = tswapl(prstatus->pr_sighold); 1929edf8e2afSMika Westerberg prstatus->pr_pid = tswap32(prstatus->pr_pid); 1930edf8e2afSMika Westerberg prstatus->pr_ppid = tswap32(prstatus->pr_ppid); 1931edf8e2afSMika Westerberg prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp); 1932edf8e2afSMika Westerberg prstatus->pr_sid = tswap32(prstatus->pr_sid); 1933edf8e2afSMika Westerberg /* cpu times are not filled, so we skip them */ 1934edf8e2afSMika Westerberg /* regs should be in correct format already */ 1935edf8e2afSMika Westerberg prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid); 1936edf8e2afSMika Westerberg } 1937edf8e2afSMika Westerberg 1938a2547a13SLaurent Desnogues static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) 1939edf8e2afSMika Westerberg { 1940edf8e2afSMika Westerberg psinfo->pr_flag = tswapl(psinfo->pr_flag); 1941edf8e2afSMika Westerberg psinfo->pr_uid = tswap16(psinfo->pr_uid); 1942edf8e2afSMika Westerberg psinfo->pr_gid = tswap16(psinfo->pr_gid); 1943edf8e2afSMika Westerberg psinfo->pr_pid = tswap32(psinfo->pr_pid); 1944edf8e2afSMika Westerberg psinfo->pr_ppid = tswap32(psinfo->pr_ppid); 1945edf8e2afSMika Westerberg psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp); 1946edf8e2afSMika Westerberg psinfo->pr_sid = tswap32(psinfo->pr_sid); 1947edf8e2afSMika Westerberg } 1948edf8e2afSMika Westerberg #endif /* BSWAP_NEEDED */ 1949edf8e2afSMika Westerberg 1950edf8e2afSMika Westerberg /* 1951edf8e2afSMika Westerberg * Minimal support for linux memory regions. These are needed 1952edf8e2afSMika Westerberg * when we are finding out what memory exactly belongs to 1953edf8e2afSMika Westerberg * emulated process. No locks needed here, as long as 1954edf8e2afSMika Westerberg * thread that received the signal is stopped. 1955edf8e2afSMika Westerberg */ 1956edf8e2afSMika Westerberg 1957edf8e2afSMika Westerberg static struct mm_struct *vma_init(void) 1958edf8e2afSMika Westerberg { 1959edf8e2afSMika Westerberg struct mm_struct *mm; 1960edf8e2afSMika Westerberg 1961edf8e2afSMika Westerberg if ((mm = qemu_malloc(sizeof (*mm))) == NULL) 1962edf8e2afSMika Westerberg return (NULL); 1963edf8e2afSMika Westerberg 1964edf8e2afSMika Westerberg mm->mm_count = 0; 1965edf8e2afSMika Westerberg TAILQ_INIT(&mm->mm_mmap); 1966edf8e2afSMika Westerberg 1967edf8e2afSMika Westerberg return (mm); 1968edf8e2afSMika Westerberg } 1969edf8e2afSMika Westerberg 1970edf8e2afSMika Westerberg static void vma_delete(struct mm_struct *mm) 1971edf8e2afSMika Westerberg { 1972edf8e2afSMika Westerberg struct vm_area_struct *vma; 1973edf8e2afSMika Westerberg 1974edf8e2afSMika Westerberg while ((vma = vma_first(mm)) != NULL) { 1975edf8e2afSMika Westerberg TAILQ_REMOVE(&mm->mm_mmap, vma, vma_link); 1976edf8e2afSMika Westerberg qemu_free(vma); 1977edf8e2afSMika Westerberg } 1978edf8e2afSMika Westerberg qemu_free(mm); 1979edf8e2afSMika Westerberg } 1980edf8e2afSMika Westerberg 1981edf8e2afSMika Westerberg static int vma_add_mapping(struct mm_struct *mm, abi_ulong start, 1982edf8e2afSMika Westerberg abi_ulong end, abi_ulong flags) 1983edf8e2afSMika Westerberg { 1984edf8e2afSMika Westerberg struct vm_area_struct *vma; 1985edf8e2afSMika Westerberg 1986edf8e2afSMika Westerberg if ((vma = qemu_mallocz(sizeof (*vma))) == NULL) 1987edf8e2afSMika Westerberg return (-1); 1988edf8e2afSMika Westerberg 1989edf8e2afSMika Westerberg vma->vma_start = start; 1990edf8e2afSMika Westerberg vma->vma_end = end; 1991edf8e2afSMika Westerberg vma->vma_flags = flags; 1992edf8e2afSMika Westerberg 1993edf8e2afSMika Westerberg TAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link); 1994edf8e2afSMika Westerberg mm->mm_count++; 1995edf8e2afSMika Westerberg 1996edf8e2afSMika Westerberg return (0); 1997edf8e2afSMika Westerberg } 1998edf8e2afSMika Westerberg 1999edf8e2afSMika Westerberg static struct vm_area_struct *vma_first(const struct mm_struct *mm) 2000edf8e2afSMika Westerberg { 2001edf8e2afSMika Westerberg return (TAILQ_FIRST(&mm->mm_mmap)); 2002edf8e2afSMika Westerberg } 2003edf8e2afSMika Westerberg 2004edf8e2afSMika Westerberg static struct vm_area_struct *vma_next(struct vm_area_struct *vma) 2005edf8e2afSMika Westerberg { 2006edf8e2afSMika Westerberg return (TAILQ_NEXT(vma, vma_link)); 2007edf8e2afSMika Westerberg } 2008edf8e2afSMika Westerberg 2009edf8e2afSMika Westerberg static int vma_get_mapping_count(const struct mm_struct *mm) 2010edf8e2afSMika Westerberg { 2011edf8e2afSMika Westerberg return (mm->mm_count); 2012edf8e2afSMika Westerberg } 2013edf8e2afSMika Westerberg 2014edf8e2afSMika Westerberg /* 2015edf8e2afSMika Westerberg * Calculate file (dump) size of given memory region. 2016edf8e2afSMika Westerberg */ 2017edf8e2afSMika Westerberg static abi_ulong vma_dump_size(const struct vm_area_struct *vma) 2018edf8e2afSMika Westerberg { 2019edf8e2afSMika Westerberg /* if we cannot even read the first page, skip it */ 2020edf8e2afSMika Westerberg if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE)) 2021edf8e2afSMika Westerberg return (0); 2022edf8e2afSMika Westerberg 2023edf8e2afSMika Westerberg /* 2024edf8e2afSMika Westerberg * Usually we don't dump executable pages as they contain 2025edf8e2afSMika Westerberg * non-writable code that debugger can read directly from 2026edf8e2afSMika Westerberg * target library etc. However, thread stacks are marked 2027edf8e2afSMika Westerberg * also executable so we read in first page of given region 2028edf8e2afSMika Westerberg * and check whether it contains elf header. If there is 2029edf8e2afSMika Westerberg * no elf header, we dump it. 2030edf8e2afSMika Westerberg */ 2031edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) { 2032edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 2033edf8e2afSMika Westerberg 2034edf8e2afSMika Westerberg copy_from_user(page, vma->vma_start, sizeof (page)); 2035edf8e2afSMika Westerberg if ((page[EI_MAG0] == ELFMAG0) && 2036edf8e2afSMika Westerberg (page[EI_MAG1] == ELFMAG1) && 2037edf8e2afSMika Westerberg (page[EI_MAG2] == ELFMAG2) && 2038edf8e2afSMika Westerberg (page[EI_MAG3] == ELFMAG3)) { 2039edf8e2afSMika Westerberg /* 2040edf8e2afSMika Westerberg * Mappings are possibly from ELF binary. Don't dump 2041edf8e2afSMika Westerberg * them. 2042edf8e2afSMika Westerberg */ 2043edf8e2afSMika Westerberg return (0); 2044edf8e2afSMika Westerberg } 2045edf8e2afSMika Westerberg } 2046edf8e2afSMika Westerberg 2047edf8e2afSMika Westerberg return (vma->vma_end - vma->vma_start); 2048edf8e2afSMika Westerberg } 2049edf8e2afSMika Westerberg 2050edf8e2afSMika Westerberg static int vma_walker(void *priv, unsigned long start, unsigned long end, 2051edf8e2afSMika Westerberg unsigned long flags) 2052edf8e2afSMika Westerberg { 2053edf8e2afSMika Westerberg struct mm_struct *mm = (struct mm_struct *)priv; 2054edf8e2afSMika Westerberg 2055edf8e2afSMika Westerberg /* 2056edf8e2afSMika Westerberg * Don't dump anything that qemu has reserved for internal use. 2057edf8e2afSMika Westerberg */ 2058edf8e2afSMika Westerberg if (flags & PAGE_RESERVED) 2059edf8e2afSMika Westerberg return (0); 2060edf8e2afSMika Westerberg 2061edf8e2afSMika Westerberg vma_add_mapping(mm, start, end, flags); 2062edf8e2afSMika Westerberg return (0); 2063edf8e2afSMika Westerberg } 2064edf8e2afSMika Westerberg 2065edf8e2afSMika Westerberg static void fill_note(struct memelfnote *note, const char *name, int type, 2066edf8e2afSMika Westerberg unsigned int sz, void *data) 2067edf8e2afSMika Westerberg { 2068edf8e2afSMika Westerberg unsigned int namesz; 2069edf8e2afSMika Westerberg 2070edf8e2afSMika Westerberg namesz = strlen(name) + 1; 2071edf8e2afSMika Westerberg note->name = name; 2072edf8e2afSMika Westerberg note->namesz = namesz; 2073edf8e2afSMika Westerberg note->namesz_rounded = roundup(namesz, sizeof (int32_t)); 2074edf8e2afSMika Westerberg note->type = type; 2075edf8e2afSMika Westerberg note->datasz = roundup(sz, sizeof (int32_t));; 2076edf8e2afSMika Westerberg note->data = data; 2077edf8e2afSMika Westerberg 2078edf8e2afSMika Westerberg /* 2079edf8e2afSMika Westerberg * We calculate rounded up note size here as specified by 2080edf8e2afSMika Westerberg * ELF document. 2081edf8e2afSMika Westerberg */ 2082edf8e2afSMika Westerberg note->notesz = sizeof (struct elf_note) + 2083edf8e2afSMika Westerberg note->namesz_rounded + note->datasz; 2084edf8e2afSMika Westerberg } 2085edf8e2afSMika Westerberg 2086edf8e2afSMika Westerberg static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, 2087edf8e2afSMika Westerberg uint32_t flags) 2088edf8e2afSMika Westerberg { 2089edf8e2afSMika Westerberg (void) memset(elf, 0, sizeof(*elf)); 2090edf8e2afSMika Westerberg 2091edf8e2afSMika Westerberg (void) memcpy(elf->e_ident, ELFMAG, SELFMAG); 2092edf8e2afSMika Westerberg elf->e_ident[EI_CLASS] = ELF_CLASS; 2093edf8e2afSMika Westerberg elf->e_ident[EI_DATA] = ELF_DATA; 2094edf8e2afSMika Westerberg elf->e_ident[EI_VERSION] = EV_CURRENT; 2095edf8e2afSMika Westerberg elf->e_ident[EI_OSABI] = ELF_OSABI; 2096edf8e2afSMika Westerberg 2097edf8e2afSMika Westerberg elf->e_type = ET_CORE; 2098edf8e2afSMika Westerberg elf->e_machine = machine; 2099edf8e2afSMika Westerberg elf->e_version = EV_CURRENT; 2100edf8e2afSMika Westerberg elf->e_phoff = sizeof(struct elfhdr); 2101edf8e2afSMika Westerberg elf->e_flags = flags; 2102edf8e2afSMika Westerberg elf->e_ehsize = sizeof(struct elfhdr); 2103edf8e2afSMika Westerberg elf->e_phentsize = sizeof(struct elf_phdr); 2104edf8e2afSMika Westerberg elf->e_phnum = segs; 2105edf8e2afSMika Westerberg 2106edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2107edf8e2afSMika Westerberg bswap_ehdr(elf); 2108edf8e2afSMika Westerberg #endif 2109edf8e2afSMika Westerberg } 2110edf8e2afSMika Westerberg 2111edf8e2afSMika Westerberg static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) 2112edf8e2afSMika Westerberg { 2113edf8e2afSMika Westerberg phdr->p_type = PT_NOTE; 2114edf8e2afSMika Westerberg phdr->p_offset = offset; 2115edf8e2afSMika Westerberg phdr->p_vaddr = 0; 2116edf8e2afSMika Westerberg phdr->p_paddr = 0; 2117edf8e2afSMika Westerberg phdr->p_filesz = sz; 2118edf8e2afSMika Westerberg phdr->p_memsz = 0; 2119edf8e2afSMika Westerberg phdr->p_flags = 0; 2120edf8e2afSMika Westerberg phdr->p_align = 0; 2121edf8e2afSMika Westerberg 2122edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2123edf8e2afSMika Westerberg bswap_phdr(phdr); 2124edf8e2afSMika Westerberg #endif 2125edf8e2afSMika Westerberg } 2126edf8e2afSMika Westerberg 2127edf8e2afSMika Westerberg static size_t note_size(const struct memelfnote *note) 2128edf8e2afSMika Westerberg { 2129edf8e2afSMika Westerberg return (note->notesz); 2130edf8e2afSMika Westerberg } 2131edf8e2afSMika Westerberg 2132a2547a13SLaurent Desnogues static void fill_prstatus(struct target_elf_prstatus *prstatus, 2133edf8e2afSMika Westerberg const TaskState *ts, int signr) 2134edf8e2afSMika Westerberg { 2135edf8e2afSMika Westerberg (void) memset(prstatus, 0, sizeof (*prstatus)); 2136edf8e2afSMika Westerberg prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; 2137edf8e2afSMika Westerberg prstatus->pr_pid = ts->ts_tid; 2138edf8e2afSMika Westerberg prstatus->pr_ppid = getppid(); 2139edf8e2afSMika Westerberg prstatus->pr_pgrp = getpgrp(); 2140edf8e2afSMika Westerberg prstatus->pr_sid = getsid(0); 2141edf8e2afSMika Westerberg 2142edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2143edf8e2afSMika Westerberg bswap_prstatus(prstatus); 2144edf8e2afSMika Westerberg #endif 2145edf8e2afSMika Westerberg } 2146edf8e2afSMika Westerberg 2147a2547a13SLaurent Desnogues static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) 2148edf8e2afSMika Westerberg { 2149edf8e2afSMika Westerberg char *filename, *base_filename; 2150edf8e2afSMika Westerberg unsigned int i, len; 2151edf8e2afSMika Westerberg 2152edf8e2afSMika Westerberg (void) memset(psinfo, 0, sizeof (*psinfo)); 2153edf8e2afSMika Westerberg 2154edf8e2afSMika Westerberg len = ts->info->arg_end - ts->info->arg_start; 2155edf8e2afSMika Westerberg if (len >= ELF_PRARGSZ) 2156edf8e2afSMika Westerberg len = ELF_PRARGSZ - 1; 2157edf8e2afSMika Westerberg if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len)) 2158edf8e2afSMika Westerberg return -EFAULT; 2159edf8e2afSMika Westerberg for (i = 0; i < len; i++) 2160edf8e2afSMika Westerberg if (psinfo->pr_psargs[i] == 0) 2161edf8e2afSMika Westerberg psinfo->pr_psargs[i] = ' '; 2162edf8e2afSMika Westerberg psinfo->pr_psargs[len] = 0; 2163edf8e2afSMika Westerberg 2164edf8e2afSMika Westerberg psinfo->pr_pid = getpid(); 2165edf8e2afSMika Westerberg psinfo->pr_ppid = getppid(); 2166edf8e2afSMika Westerberg psinfo->pr_pgrp = getpgrp(); 2167edf8e2afSMika Westerberg psinfo->pr_sid = getsid(0); 2168edf8e2afSMika Westerberg psinfo->pr_uid = getuid(); 2169edf8e2afSMika Westerberg psinfo->pr_gid = getgid(); 2170edf8e2afSMika Westerberg 2171edf8e2afSMika Westerberg filename = strdup(ts->bprm->filename); 2172edf8e2afSMika Westerberg base_filename = strdup(basename(filename)); 2173edf8e2afSMika Westerberg (void) strncpy(psinfo->pr_fname, base_filename, 2174edf8e2afSMika Westerberg sizeof(psinfo->pr_fname)); 2175edf8e2afSMika Westerberg free(base_filename); 2176edf8e2afSMika Westerberg free(filename); 2177edf8e2afSMika Westerberg 2178edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2179edf8e2afSMika Westerberg bswap_psinfo(psinfo); 2180edf8e2afSMika Westerberg #endif 2181edf8e2afSMika Westerberg return (0); 2182edf8e2afSMika Westerberg } 2183edf8e2afSMika Westerberg 2184edf8e2afSMika Westerberg static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) 2185edf8e2afSMika Westerberg { 2186edf8e2afSMika Westerberg elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; 2187edf8e2afSMika Westerberg elf_addr_t orig_auxv = auxv; 2188edf8e2afSMika Westerberg abi_ulong val; 2189edf8e2afSMika Westerberg void *ptr; 2190edf8e2afSMika Westerberg int i, len; 2191edf8e2afSMika Westerberg 2192edf8e2afSMika Westerberg /* 2193edf8e2afSMika Westerberg * Auxiliary vector is stored in target process stack. It contains 2194edf8e2afSMika Westerberg * {type, value} pairs that we need to dump into note. This is not 2195edf8e2afSMika Westerberg * strictly necessary but we do it here for sake of completeness. 2196edf8e2afSMika Westerberg */ 2197edf8e2afSMika Westerberg 2198edf8e2afSMika Westerberg /* find out lenght of the vector, AT_NULL is terminator */ 2199edf8e2afSMika Westerberg i = len = 0; 2200edf8e2afSMika Westerberg do { 2201edf8e2afSMika Westerberg get_user_ual(val, auxv); 2202edf8e2afSMika Westerberg i += 2; 2203edf8e2afSMika Westerberg auxv += 2 * sizeof (elf_addr_t); 2204edf8e2afSMika Westerberg } while (val != AT_NULL); 2205edf8e2afSMika Westerberg len = i * sizeof (elf_addr_t); 2206edf8e2afSMika Westerberg 2207edf8e2afSMika Westerberg /* read in whole auxv vector and copy it to memelfnote */ 2208edf8e2afSMika Westerberg ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); 2209edf8e2afSMika Westerberg if (ptr != NULL) { 2210edf8e2afSMika Westerberg fill_note(note, "CORE", NT_AUXV, len, ptr); 2211edf8e2afSMika Westerberg unlock_user(ptr, auxv, len); 2212edf8e2afSMika Westerberg } 2213edf8e2afSMika Westerberg } 2214edf8e2afSMika Westerberg 2215edf8e2afSMika Westerberg /* 2216edf8e2afSMika Westerberg * Constructs name of coredump file. We have following convention 2217edf8e2afSMika Westerberg * for the name: 2218edf8e2afSMika Westerberg * qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core 2219edf8e2afSMika Westerberg * 2220edf8e2afSMika Westerberg * Returns 0 in case of success, -1 otherwise (errno is set). 2221edf8e2afSMika Westerberg */ 2222edf8e2afSMika Westerberg static int core_dump_filename(const TaskState *ts, char *buf, 2223edf8e2afSMika Westerberg size_t bufsize) 2224edf8e2afSMika Westerberg { 2225edf8e2afSMika Westerberg char timestamp[64]; 2226edf8e2afSMika Westerberg char *filename = NULL; 2227edf8e2afSMika Westerberg char *base_filename = NULL; 2228edf8e2afSMika Westerberg struct timeval tv; 2229edf8e2afSMika Westerberg struct tm tm; 2230edf8e2afSMika Westerberg 2231edf8e2afSMika Westerberg assert(bufsize >= PATH_MAX); 2232edf8e2afSMika Westerberg 2233edf8e2afSMika Westerberg if (gettimeofday(&tv, NULL) < 0) { 2234edf8e2afSMika Westerberg (void) fprintf(stderr, "unable to get current timestamp: %s", 2235edf8e2afSMika Westerberg strerror(errno)); 2236edf8e2afSMika Westerberg return (-1); 2237edf8e2afSMika Westerberg } 2238edf8e2afSMika Westerberg 2239edf8e2afSMika Westerberg filename = strdup(ts->bprm->filename); 2240edf8e2afSMika Westerberg base_filename = strdup(basename(filename)); 2241edf8e2afSMika Westerberg (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", 2242edf8e2afSMika Westerberg localtime_r(&tv.tv_sec, &tm)); 2243edf8e2afSMika Westerberg (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", 2244edf8e2afSMika Westerberg base_filename, timestamp, (int)getpid()); 2245edf8e2afSMika Westerberg free(base_filename); 2246edf8e2afSMika Westerberg free(filename); 2247edf8e2afSMika Westerberg 2248edf8e2afSMika Westerberg return (0); 2249edf8e2afSMika Westerberg } 2250edf8e2afSMika Westerberg 2251edf8e2afSMika Westerberg static int dump_write(int fd, const void *ptr, size_t size) 2252edf8e2afSMika Westerberg { 2253edf8e2afSMika Westerberg const char *bufp = (const char *)ptr; 2254edf8e2afSMika Westerberg ssize_t bytes_written, bytes_left; 2255edf8e2afSMika Westerberg struct rlimit dumpsize; 2256edf8e2afSMika Westerberg off_t pos; 2257edf8e2afSMika Westerberg 2258edf8e2afSMika Westerberg bytes_written = 0; 2259edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 2260edf8e2afSMika Westerberg if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { 2261edf8e2afSMika Westerberg if (errno == ESPIPE) { /* not a seekable stream */ 2262edf8e2afSMika Westerberg bytes_left = size; 2263edf8e2afSMika Westerberg } else { 2264edf8e2afSMika Westerberg return pos; 2265edf8e2afSMika Westerberg } 2266edf8e2afSMika Westerberg } else { 2267edf8e2afSMika Westerberg if (dumpsize.rlim_cur <= pos) { 2268edf8e2afSMika Westerberg return -1; 2269edf8e2afSMika Westerberg } else if (dumpsize.rlim_cur == RLIM_INFINITY) { 2270edf8e2afSMika Westerberg bytes_left = size; 2271edf8e2afSMika Westerberg } else { 2272edf8e2afSMika Westerberg size_t limit_left=dumpsize.rlim_cur - pos; 2273edf8e2afSMika Westerberg bytes_left = limit_left >= size ? size : limit_left ; 2274edf8e2afSMika Westerberg } 2275edf8e2afSMika Westerberg } 2276edf8e2afSMika Westerberg 2277edf8e2afSMika Westerberg /* 2278edf8e2afSMika Westerberg * In normal conditions, single write(2) should do but 2279edf8e2afSMika Westerberg * in case of socket etc. this mechanism is more portable. 2280edf8e2afSMika Westerberg */ 2281edf8e2afSMika Westerberg do { 2282edf8e2afSMika Westerberg bytes_written = write(fd, bufp, bytes_left); 2283edf8e2afSMika Westerberg if (bytes_written < 0) { 2284edf8e2afSMika Westerberg if (errno == EINTR) 2285edf8e2afSMika Westerberg continue; 2286edf8e2afSMika Westerberg return (-1); 2287edf8e2afSMika Westerberg } else if (bytes_written == 0) { /* eof */ 2288edf8e2afSMika Westerberg return (-1); 2289edf8e2afSMika Westerberg } 2290edf8e2afSMika Westerberg bufp += bytes_written; 2291edf8e2afSMika Westerberg bytes_left -= bytes_written; 2292edf8e2afSMika Westerberg } while (bytes_left > 0); 2293edf8e2afSMika Westerberg 2294edf8e2afSMika Westerberg return (0); 2295edf8e2afSMika Westerberg } 2296edf8e2afSMika Westerberg 2297edf8e2afSMika Westerberg static int write_note(struct memelfnote *men, int fd) 2298edf8e2afSMika Westerberg { 2299edf8e2afSMika Westerberg struct elf_note en; 2300edf8e2afSMika Westerberg 2301edf8e2afSMika Westerberg en.n_namesz = men->namesz; 2302edf8e2afSMika Westerberg en.n_type = men->type; 2303edf8e2afSMika Westerberg en.n_descsz = men->datasz; 2304edf8e2afSMika Westerberg 2305edf8e2afSMika Westerberg #ifdef BSWAP_NEEDED 2306edf8e2afSMika Westerberg bswap_note(&en); 2307edf8e2afSMika Westerberg #endif 2308edf8e2afSMika Westerberg 2309edf8e2afSMika Westerberg if (dump_write(fd, &en, sizeof(en)) != 0) 2310edf8e2afSMika Westerberg return (-1); 2311edf8e2afSMika Westerberg if (dump_write(fd, men->name, men->namesz_rounded) != 0) 2312edf8e2afSMika Westerberg return (-1); 2313edf8e2afSMika Westerberg if (dump_write(fd, men->data, men->datasz) != 0) 2314edf8e2afSMika Westerberg return (-1); 2315edf8e2afSMika Westerberg 2316edf8e2afSMika Westerberg return (0); 2317edf8e2afSMika Westerberg } 2318edf8e2afSMika Westerberg 2319edf8e2afSMika Westerberg static void fill_thread_info(struct elf_note_info *info, const CPUState *env) 2320edf8e2afSMika Westerberg { 2321edf8e2afSMika Westerberg TaskState *ts = (TaskState *)env->opaque; 2322edf8e2afSMika Westerberg struct elf_thread_status *ets; 2323edf8e2afSMika Westerberg 2324edf8e2afSMika Westerberg ets = qemu_mallocz(sizeof (*ets)); 2325edf8e2afSMika Westerberg ets->num_notes = 1; /* only prstatus is dumped */ 2326edf8e2afSMika Westerberg fill_prstatus(&ets->prstatus, ts, 0); 2327edf8e2afSMika Westerberg elf_core_copy_regs(&ets->prstatus.pr_reg, env); 2328edf8e2afSMika Westerberg fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus), 2329edf8e2afSMika Westerberg &ets->prstatus); 2330edf8e2afSMika Westerberg 2331edf8e2afSMika Westerberg TAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link); 2332edf8e2afSMika Westerberg 2333edf8e2afSMika Westerberg info->notes_size += note_size(&ets->notes[0]); 2334edf8e2afSMika Westerberg } 2335edf8e2afSMika Westerberg 2336edf8e2afSMika Westerberg static int fill_note_info(struct elf_note_info *info, 2337edf8e2afSMika Westerberg long signr, const CPUState *env) 2338edf8e2afSMika Westerberg { 2339edf8e2afSMika Westerberg #define NUMNOTES 3 2340edf8e2afSMika Westerberg CPUState *cpu = NULL; 2341edf8e2afSMika Westerberg TaskState *ts = (TaskState *)env->opaque; 2342edf8e2afSMika Westerberg int i; 2343edf8e2afSMika Westerberg 2344edf8e2afSMika Westerberg (void) memset(info, 0, sizeof (*info)); 2345edf8e2afSMika Westerberg 2346edf8e2afSMika Westerberg TAILQ_INIT(&info->thread_list); 2347edf8e2afSMika Westerberg 2348edf8e2afSMika Westerberg info->notes = qemu_mallocz(NUMNOTES * sizeof (struct memelfnote)); 2349edf8e2afSMika Westerberg if (info->notes == NULL) 2350edf8e2afSMika Westerberg return (-ENOMEM); 2351edf8e2afSMika Westerberg info->prstatus = qemu_mallocz(sizeof (*info->prstatus)); 2352edf8e2afSMika Westerberg if (info->prstatus == NULL) 2353edf8e2afSMika Westerberg return (-ENOMEM); 2354edf8e2afSMika Westerberg info->psinfo = qemu_mallocz(sizeof (*info->psinfo)); 2355edf8e2afSMika Westerberg if (info->prstatus == NULL) 2356edf8e2afSMika Westerberg return (-ENOMEM); 2357edf8e2afSMika Westerberg 2358edf8e2afSMika Westerberg /* 2359edf8e2afSMika Westerberg * First fill in status (and registers) of current thread 2360edf8e2afSMika Westerberg * including process info & aux vector. 2361edf8e2afSMika Westerberg */ 2362edf8e2afSMika Westerberg fill_prstatus(info->prstatus, ts, signr); 2363edf8e2afSMika Westerberg elf_core_copy_regs(&info->prstatus->pr_reg, env); 2364edf8e2afSMika Westerberg fill_note(&info->notes[0], "CORE", NT_PRSTATUS, 2365edf8e2afSMika Westerberg sizeof (*info->prstatus), info->prstatus); 2366edf8e2afSMika Westerberg fill_psinfo(info->psinfo, ts); 2367edf8e2afSMika Westerberg fill_note(&info->notes[1], "CORE", NT_PRPSINFO, 2368edf8e2afSMika Westerberg sizeof (*info->psinfo), info->psinfo); 2369edf8e2afSMika Westerberg fill_auxv_note(&info->notes[2], ts); 2370edf8e2afSMika Westerberg info->numnote = 3; 2371edf8e2afSMika Westerberg 2372edf8e2afSMika Westerberg info->notes_size = 0; 2373edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 2374edf8e2afSMika Westerberg info->notes_size += note_size(&info->notes[i]); 2375edf8e2afSMika Westerberg 2376edf8e2afSMika Westerberg /* read and fill status of all threads */ 2377edf8e2afSMika Westerberg cpu_list_lock(); 2378edf8e2afSMika Westerberg for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { 2379edf8e2afSMika Westerberg if (cpu == thread_env) 2380edf8e2afSMika Westerberg continue; 2381edf8e2afSMika Westerberg fill_thread_info(info, cpu); 2382edf8e2afSMika Westerberg } 2383edf8e2afSMika Westerberg cpu_list_unlock(); 2384edf8e2afSMika Westerberg 2385edf8e2afSMika Westerberg return (0); 2386edf8e2afSMika Westerberg } 2387edf8e2afSMika Westerberg 2388edf8e2afSMika Westerberg static void free_note_info(struct elf_note_info *info) 2389edf8e2afSMika Westerberg { 2390edf8e2afSMika Westerberg struct elf_thread_status *ets; 2391edf8e2afSMika Westerberg 2392edf8e2afSMika Westerberg while (!TAILQ_EMPTY(&info->thread_list)) { 2393edf8e2afSMika Westerberg ets = TAILQ_FIRST(&info->thread_list); 2394edf8e2afSMika Westerberg TAILQ_REMOVE(&info->thread_list, ets, ets_link); 2395edf8e2afSMika Westerberg qemu_free(ets); 2396edf8e2afSMika Westerberg } 2397edf8e2afSMika Westerberg 2398edf8e2afSMika Westerberg qemu_free(info->prstatus); 2399edf8e2afSMika Westerberg qemu_free(info->psinfo); 2400edf8e2afSMika Westerberg qemu_free(info->notes); 2401edf8e2afSMika Westerberg } 2402edf8e2afSMika Westerberg 2403edf8e2afSMika Westerberg static int write_note_info(struct elf_note_info *info, int fd) 2404edf8e2afSMika Westerberg { 2405edf8e2afSMika Westerberg struct elf_thread_status *ets; 2406edf8e2afSMika Westerberg int i, error = 0; 2407edf8e2afSMika Westerberg 2408edf8e2afSMika Westerberg /* write prstatus, psinfo and auxv for current thread */ 2409edf8e2afSMika Westerberg for (i = 0; i < info->numnote; i++) 2410edf8e2afSMika Westerberg if ((error = write_note(&info->notes[i], fd)) != 0) 2411edf8e2afSMika Westerberg return (error); 2412edf8e2afSMika Westerberg 2413edf8e2afSMika Westerberg /* write prstatus for each thread */ 2414edf8e2afSMika Westerberg for (ets = info->thread_list.tqh_first; ets != NULL; 2415edf8e2afSMika Westerberg ets = ets->ets_link.tqe_next) { 2416edf8e2afSMika Westerberg if ((error = write_note(&ets->notes[0], fd)) != 0) 2417edf8e2afSMika Westerberg return (error); 2418edf8e2afSMika Westerberg } 2419edf8e2afSMika Westerberg 2420edf8e2afSMika Westerberg return (0); 2421edf8e2afSMika Westerberg } 2422edf8e2afSMika Westerberg 2423edf8e2afSMika Westerberg /* 2424edf8e2afSMika Westerberg * Write out ELF coredump. 2425edf8e2afSMika Westerberg * 2426edf8e2afSMika Westerberg * See documentation of ELF object file format in: 2427edf8e2afSMika Westerberg * http://www.caldera.com/developers/devspecs/gabi41.pdf 2428edf8e2afSMika Westerberg * 2429edf8e2afSMika Westerberg * Coredump format in linux is following: 2430edf8e2afSMika Westerberg * 2431edf8e2afSMika Westerberg * 0 +----------------------+ \ 2432edf8e2afSMika Westerberg * | ELF header | ET_CORE | 2433edf8e2afSMika Westerberg * +----------------------+ | 2434edf8e2afSMika Westerberg * | ELF program headers | |--- headers 2435edf8e2afSMika Westerberg * | - NOTE section | | 2436edf8e2afSMika Westerberg * | - PT_LOAD sections | | 2437edf8e2afSMika Westerberg * +----------------------+ / 2438edf8e2afSMika Westerberg * | NOTEs: | 2439edf8e2afSMika Westerberg * | - NT_PRSTATUS | 2440edf8e2afSMika Westerberg * | - NT_PRSINFO | 2441edf8e2afSMika Westerberg * | - NT_AUXV | 2442edf8e2afSMika Westerberg * +----------------------+ <-- aligned to target page 2443edf8e2afSMika Westerberg * | Process memory dump | 2444edf8e2afSMika Westerberg * : : 2445edf8e2afSMika Westerberg * . . 2446edf8e2afSMika Westerberg * : : 2447edf8e2afSMika Westerberg * | | 2448edf8e2afSMika Westerberg * +----------------------+ 2449edf8e2afSMika Westerberg * 2450edf8e2afSMika Westerberg * NT_PRSTATUS -> struct elf_prstatus (per thread) 2451edf8e2afSMika Westerberg * NT_PRSINFO -> struct elf_prpsinfo 2452edf8e2afSMika Westerberg * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()). 2453edf8e2afSMika Westerberg * 2454edf8e2afSMika Westerberg * Format follows System V format as close as possible. Current 2455edf8e2afSMika Westerberg * version limitations are as follows: 2456edf8e2afSMika Westerberg * - no floating point registers are dumped 2457edf8e2afSMika Westerberg * 2458edf8e2afSMika Westerberg * Function returns 0 in case of success, negative errno otherwise. 2459edf8e2afSMika Westerberg * 2460edf8e2afSMika Westerberg * TODO: make this work also during runtime: it should be 2461edf8e2afSMika Westerberg * possible to force coredump from running process and then 2462edf8e2afSMika Westerberg * continue processing. For example qemu could set up SIGUSR2 2463edf8e2afSMika Westerberg * handler (provided that target process haven't registered 2464edf8e2afSMika Westerberg * handler for that) that does the dump when signal is received. 2465edf8e2afSMika Westerberg */ 2466edf8e2afSMika Westerberg static int elf_core_dump(int signr, const CPUState *env) 2467edf8e2afSMika Westerberg { 2468edf8e2afSMika Westerberg const TaskState *ts = (const TaskState *)env->opaque; 2469edf8e2afSMika Westerberg struct vm_area_struct *vma = NULL; 2470edf8e2afSMika Westerberg char corefile[PATH_MAX]; 2471edf8e2afSMika Westerberg struct elf_note_info info; 2472edf8e2afSMika Westerberg struct elfhdr elf; 2473edf8e2afSMika Westerberg struct elf_phdr phdr; 2474edf8e2afSMika Westerberg struct rlimit dumpsize; 2475edf8e2afSMika Westerberg struct mm_struct *mm = NULL; 2476edf8e2afSMika Westerberg off_t offset = 0, data_offset = 0; 2477edf8e2afSMika Westerberg int segs = 0; 2478edf8e2afSMika Westerberg int fd = -1; 2479edf8e2afSMika Westerberg 2480edf8e2afSMika Westerberg errno = 0; 2481edf8e2afSMika Westerberg getrlimit(RLIMIT_CORE, &dumpsize); 2482edf8e2afSMika Westerberg if (dumpsize.rlim_cur == 0) 2483edf8e2afSMika Westerberg return 0; 2484edf8e2afSMika Westerberg 2485edf8e2afSMika Westerberg if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0) 2486edf8e2afSMika Westerberg return (-errno); 2487edf8e2afSMika Westerberg 2488edf8e2afSMika Westerberg if ((fd = open(corefile, O_WRONLY | O_CREAT, 2489edf8e2afSMika Westerberg S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) 2490edf8e2afSMika Westerberg return (-errno); 2491edf8e2afSMika Westerberg 2492edf8e2afSMika Westerberg /* 2493edf8e2afSMika Westerberg * Walk through target process memory mappings and 2494edf8e2afSMika Westerberg * set up structure containing this information. After 2495edf8e2afSMika Westerberg * this point vma_xxx functions can be used. 2496edf8e2afSMika Westerberg */ 2497edf8e2afSMika Westerberg if ((mm = vma_init()) == NULL) 2498edf8e2afSMika Westerberg goto out; 2499edf8e2afSMika Westerberg 2500edf8e2afSMika Westerberg walk_memory_regions(mm, vma_walker); 2501edf8e2afSMika Westerberg segs = vma_get_mapping_count(mm); 2502edf8e2afSMika Westerberg 2503edf8e2afSMika Westerberg /* 2504edf8e2afSMika Westerberg * Construct valid coredump ELF header. We also 2505edf8e2afSMika Westerberg * add one more segment for notes. 2506edf8e2afSMika Westerberg */ 2507edf8e2afSMika Westerberg fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0); 2508edf8e2afSMika Westerberg if (dump_write(fd, &elf, sizeof (elf)) != 0) 2509edf8e2afSMika Westerberg goto out; 2510edf8e2afSMika Westerberg 2511edf8e2afSMika Westerberg /* fill in in-memory version of notes */ 2512edf8e2afSMika Westerberg if (fill_note_info(&info, signr, env) < 0) 2513edf8e2afSMika Westerberg goto out; 2514edf8e2afSMika Westerberg 2515edf8e2afSMika Westerberg offset += sizeof (elf); /* elf header */ 2516edf8e2afSMika Westerberg offset += (segs + 1) * sizeof (struct elf_phdr); /* program headers */ 2517edf8e2afSMika Westerberg 2518edf8e2afSMika Westerberg /* write out notes program header */ 2519edf8e2afSMika Westerberg fill_elf_note_phdr(&phdr, info.notes_size, offset); 2520edf8e2afSMika Westerberg 2521edf8e2afSMika Westerberg offset += info.notes_size; 2522edf8e2afSMika Westerberg if (dump_write(fd, &phdr, sizeof (phdr)) != 0) 2523edf8e2afSMika Westerberg goto out; 2524edf8e2afSMika Westerberg 2525edf8e2afSMika Westerberg /* 2526edf8e2afSMika Westerberg * ELF specification wants data to start at page boundary so 2527edf8e2afSMika Westerberg * we align it here. 2528edf8e2afSMika Westerberg */ 2529edf8e2afSMika Westerberg offset = roundup(offset, ELF_EXEC_PAGESIZE); 2530edf8e2afSMika Westerberg 2531edf8e2afSMika Westerberg /* 2532edf8e2afSMika Westerberg * Write program headers for memory regions mapped in 2533edf8e2afSMika Westerberg * the target process. 2534edf8e2afSMika Westerberg */ 2535edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 2536edf8e2afSMika Westerberg (void) memset(&phdr, 0, sizeof (phdr)); 2537edf8e2afSMika Westerberg 2538edf8e2afSMika Westerberg phdr.p_type = PT_LOAD; 2539edf8e2afSMika Westerberg phdr.p_offset = offset; 2540edf8e2afSMika Westerberg phdr.p_vaddr = vma->vma_start; 2541edf8e2afSMika Westerberg phdr.p_paddr = 0; 2542edf8e2afSMika Westerberg phdr.p_filesz = vma_dump_size(vma); 2543edf8e2afSMika Westerberg offset += phdr.p_filesz; 2544edf8e2afSMika Westerberg phdr.p_memsz = vma->vma_end - vma->vma_start; 2545edf8e2afSMika Westerberg phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0; 2546edf8e2afSMika Westerberg if (vma->vma_flags & PROT_WRITE) 2547edf8e2afSMika Westerberg phdr.p_flags |= PF_W; 2548edf8e2afSMika Westerberg if (vma->vma_flags & PROT_EXEC) 2549edf8e2afSMika Westerberg phdr.p_flags |= PF_X; 2550edf8e2afSMika Westerberg phdr.p_align = ELF_EXEC_PAGESIZE; 2551edf8e2afSMika Westerberg 2552edf8e2afSMika Westerberg dump_write(fd, &phdr, sizeof (phdr)); 2553edf8e2afSMika Westerberg } 2554edf8e2afSMika Westerberg 2555edf8e2afSMika Westerberg /* 2556edf8e2afSMika Westerberg * Next we write notes just after program headers. No 2557edf8e2afSMika Westerberg * alignment needed here. 2558edf8e2afSMika Westerberg */ 2559edf8e2afSMika Westerberg if (write_note_info(&info, fd) < 0) 2560edf8e2afSMika Westerberg goto out; 2561edf8e2afSMika Westerberg 2562edf8e2afSMika Westerberg /* align data to page boundary */ 2563edf8e2afSMika Westerberg data_offset = lseek(fd, 0, SEEK_CUR); 2564edf8e2afSMika Westerberg data_offset = TARGET_PAGE_ALIGN(data_offset); 2565edf8e2afSMika Westerberg if (lseek(fd, data_offset, SEEK_SET) != data_offset) 2566edf8e2afSMika Westerberg goto out; 2567edf8e2afSMika Westerberg 2568edf8e2afSMika Westerberg /* 2569edf8e2afSMika Westerberg * Finally we can dump process memory into corefile as well. 2570edf8e2afSMika Westerberg */ 2571edf8e2afSMika Westerberg for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { 2572edf8e2afSMika Westerberg abi_ulong addr; 2573edf8e2afSMika Westerberg abi_ulong end; 2574edf8e2afSMika Westerberg 2575edf8e2afSMika Westerberg end = vma->vma_start + vma_dump_size(vma); 2576edf8e2afSMika Westerberg 2577edf8e2afSMika Westerberg for (addr = vma->vma_start; addr < end; 2578edf8e2afSMika Westerberg addr += TARGET_PAGE_SIZE) { 2579edf8e2afSMika Westerberg char page[TARGET_PAGE_SIZE]; 2580edf8e2afSMika Westerberg int error; 2581edf8e2afSMika Westerberg 2582edf8e2afSMika Westerberg /* 2583edf8e2afSMika Westerberg * Read in page from target process memory and 2584edf8e2afSMika Westerberg * write it to coredump file. 2585edf8e2afSMika Westerberg */ 2586edf8e2afSMika Westerberg error = copy_from_user(page, addr, sizeof (page)); 2587edf8e2afSMika Westerberg if (error != 0) { 2588edf8e2afSMika Westerberg (void) fprintf(stderr, "unable to dump " TARGET_FMT_lx "\n", 2589edf8e2afSMika Westerberg addr); 2590edf8e2afSMika Westerberg errno = -error; 2591edf8e2afSMika Westerberg goto out; 2592edf8e2afSMika Westerberg } 2593edf8e2afSMika Westerberg if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0) 2594edf8e2afSMika Westerberg goto out; 2595edf8e2afSMika Westerberg } 2596edf8e2afSMika Westerberg } 2597edf8e2afSMika Westerberg 2598edf8e2afSMika Westerberg out: 2599edf8e2afSMika Westerberg free_note_info(&info); 2600edf8e2afSMika Westerberg if (mm != NULL) 2601edf8e2afSMika Westerberg vma_delete(mm); 2602edf8e2afSMika Westerberg (void) close(fd); 2603edf8e2afSMika Westerberg 2604edf8e2afSMika Westerberg if (errno != 0) 2605edf8e2afSMika Westerberg return (-errno); 2606edf8e2afSMika Westerberg return (0); 2607edf8e2afSMika Westerberg } 2608edf8e2afSMika Westerberg 2609edf8e2afSMika Westerberg #endif /* USE_ELF_CORE_DUMP */ 2610edf8e2afSMika Westerberg 261131e31b8aSbellard static int load_aout_interp(void * exptr, int interp_fd) 261231e31b8aSbellard { 261331e31b8aSbellard printf("a.out interpreter not yet supported\n"); 261431e31b8aSbellard return(0); 261531e31b8aSbellard } 261631e31b8aSbellard 2617e5fe0c52Spbrook void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) 2618e5fe0c52Spbrook { 2619e5fe0c52Spbrook init_thread(regs, infop); 2620e5fe0c52Spbrook } 2621