184778508Sblueswir1 /* This is the Linux kernel elf-loading code, ported into user space */ 284778508Sblueswir1 32231197cSPeter Maydell #include "qemu/osdep.h" 484778508Sblueswir1 584778508Sblueswir1 #include "qemu.h" 676cad711SPaolo Bonzini #include "disas/disas.h" 7f348b6d1SVeronia Bahaa #include "qemu/path.h" 884778508Sblueswir1 9e58ffeb3Smalc #ifdef _ARCH_PPC64 1084778508Sblueswir1 #undef ARCH_DLINFO 1184778508Sblueswir1 #undef ELF_PLATFORM 1284778508Sblueswir1 #undef ELF_HWCAP 1384778508Sblueswir1 #undef ELF_CLASS 1484778508Sblueswir1 #undef ELF_DATA 1584778508Sblueswir1 #undef ELF_ARCH 1684778508Sblueswir1 #endif 1784778508Sblueswir1 1884778508Sblueswir1 /* from personality.h */ 1984778508Sblueswir1 2084778508Sblueswir1 /* 2184778508Sblueswir1 * Flags for bug emulation. 2284778508Sblueswir1 * 2384778508Sblueswir1 * These occupy the top three bytes. 2484778508Sblueswir1 */ 2584778508Sblueswir1 enum { 2684778508Sblueswir1 ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */ 2784778508Sblueswir1 FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors 2884778508Sblueswir1 * (signal handling) 2984778508Sblueswir1 */ 3084778508Sblueswir1 MMAP_PAGE_ZERO = 0x0100000, 3184778508Sblueswir1 ADDR_COMPAT_LAYOUT = 0x0200000, 3284778508Sblueswir1 READ_IMPLIES_EXEC = 0x0400000, 3384778508Sblueswir1 ADDR_LIMIT_32BIT = 0x0800000, 3484778508Sblueswir1 SHORT_INODE = 0x1000000, 3584778508Sblueswir1 WHOLE_SECONDS = 0x2000000, 3684778508Sblueswir1 STICKY_TIMEOUTS = 0x4000000, 3784778508Sblueswir1 ADDR_LIMIT_3GB = 0x8000000, 3884778508Sblueswir1 }; 3984778508Sblueswir1 4084778508Sblueswir1 /* 4184778508Sblueswir1 * Personality types. 4284778508Sblueswir1 * 4384778508Sblueswir1 * These go in the low byte. Avoid using the top bit, it will 4484778508Sblueswir1 * conflict with error returns. 4584778508Sblueswir1 */ 4684778508Sblueswir1 enum { 4784778508Sblueswir1 PER_LINUX = 0x0000, 4884778508Sblueswir1 PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, 4984778508Sblueswir1 PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS, 5084778508Sblueswir1 PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 5184778508Sblueswir1 PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, 5284778508Sblueswir1 PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | 5384778508Sblueswir1 WHOLE_SECONDS | SHORT_INODE, 5484778508Sblueswir1 PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, 5584778508Sblueswir1 PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, 5684778508Sblueswir1 PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, 5784778508Sblueswir1 PER_BSD = 0x0006, 5884778508Sblueswir1 PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, 5984778508Sblueswir1 PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, 6084778508Sblueswir1 PER_LINUX32 = 0x0008, 6184778508Sblueswir1 PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB, 6284778508Sblueswir1 PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */ 6384778508Sblueswir1 PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */ 6484778508Sblueswir1 PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */ 6584778508Sblueswir1 PER_RISCOS = 0x000c, 6684778508Sblueswir1 PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, 6784778508Sblueswir1 PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, 6884778508Sblueswir1 PER_OSF4 = 0x000f, /* OSF/1 v4 */ 6984778508Sblueswir1 PER_HPUX = 0x0010, 7084778508Sblueswir1 PER_MASK = 0x00ff, 7184778508Sblueswir1 }; 7284778508Sblueswir1 7384778508Sblueswir1 /* 7484778508Sblueswir1 * Return the base personality without flags. 7584778508Sblueswir1 */ 7684778508Sblueswir1 #define personality(pers) (pers & PER_MASK) 7784778508Sblueswir1 7884778508Sblueswir1 /* this flag is uneffective under linux too, should be deleted */ 7984778508Sblueswir1 #ifndef MAP_DENYWRITE 8084778508Sblueswir1 #define MAP_DENYWRITE 0 8184778508Sblueswir1 #endif 8284778508Sblueswir1 8384778508Sblueswir1 /* should probably go in elf.h */ 8484778508Sblueswir1 #ifndef ELIBBAD 8584778508Sblueswir1 #define ELIBBAD 80 8684778508Sblueswir1 #endif 8784778508Sblueswir1 8884778508Sblueswir1 #ifdef TARGET_I386 8984778508Sblueswir1 9084778508Sblueswir1 #define ELF_PLATFORM get_elf_platform() 9184778508Sblueswir1 9284778508Sblueswir1 static const char *get_elf_platform(void) 9384778508Sblueswir1 { 9484778508Sblueswir1 static char elf_platform[] = "i386"; 95dca1173cSAndreas Färber int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); 9684778508Sblueswir1 if (family > 6) 9784778508Sblueswir1 family = 6; 9884778508Sblueswir1 if (family >= 3) 9984778508Sblueswir1 elf_platform[1] = '0' + family; 10084778508Sblueswir1 return elf_platform; 10184778508Sblueswir1 } 10284778508Sblueswir1 10384778508Sblueswir1 #define ELF_HWCAP get_elf_hwcap() 10484778508Sblueswir1 10584778508Sblueswir1 static uint32_t get_elf_hwcap(void) 10684778508Sblueswir1 { 107dca1173cSAndreas Färber X86CPU *cpu = X86_CPU(thread_cpu); 108dca1173cSAndreas Färber 109dca1173cSAndreas Färber return cpu->env.features[FEAT_1_EDX]; 11084778508Sblueswir1 } 11184778508Sblueswir1 11284778508Sblueswir1 #ifdef TARGET_X86_64 11384778508Sblueswir1 #define ELF_START_MMAP 0x2aaaaab000ULL 11484778508Sblueswir1 #define elf_check_arch(x) ( ((x) == ELF_ARCH) ) 11584778508Sblueswir1 11684778508Sblueswir1 #define ELF_CLASS ELFCLASS64 11784778508Sblueswir1 #define ELF_DATA ELFDATA2LSB 11884778508Sblueswir1 #define ELF_ARCH EM_X86_64 11984778508Sblueswir1 12084778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 12184778508Sblueswir1 { 12284778508Sblueswir1 regs->rax = 0; 12384778508Sblueswir1 regs->rsp = infop->start_stack; 12484778508Sblueswir1 regs->rip = infop->entry; 12578cfb07fSJuergen Lock if (bsd_type == target_freebsd) { 12678cfb07fSJuergen Lock regs->rdi = infop->start_stack; 12778cfb07fSJuergen Lock } 12884778508Sblueswir1 } 12984778508Sblueswir1 13084778508Sblueswir1 #else 13184778508Sblueswir1 13284778508Sblueswir1 #define ELF_START_MMAP 0x80000000 13384778508Sblueswir1 13484778508Sblueswir1 /* 13584778508Sblueswir1 * This is used to ensure we don't load something for the wrong architecture. 13684778508Sblueswir1 */ 13784778508Sblueswir1 #define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) 13884778508Sblueswir1 13984778508Sblueswir1 /* 14084778508Sblueswir1 * These are used to set parameters in the core dumps. 14184778508Sblueswir1 */ 14284778508Sblueswir1 #define ELF_CLASS ELFCLASS32 14384778508Sblueswir1 #define ELF_DATA ELFDATA2LSB 14484778508Sblueswir1 #define ELF_ARCH EM_386 14584778508Sblueswir1 14684778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 14784778508Sblueswir1 { 14884778508Sblueswir1 regs->esp = infop->start_stack; 14984778508Sblueswir1 regs->eip = infop->entry; 15084778508Sblueswir1 15184778508Sblueswir1 /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program 15284778508Sblueswir1 starts %edx contains a pointer to a function which might be 15384778508Sblueswir1 registered using `atexit'. This provides a mean for the 15484778508Sblueswir1 dynamic linker to call DT_FINI functions for shared libraries 15584778508Sblueswir1 that have been loaded before the code runs. 15684778508Sblueswir1 15784778508Sblueswir1 A value of 0 tells we have no such handler. */ 15884778508Sblueswir1 regs->edx = 0; 15984778508Sblueswir1 } 16084778508Sblueswir1 #endif 16184778508Sblueswir1 16284778508Sblueswir1 #define USE_ELF_CORE_DUMP 16384778508Sblueswir1 #define ELF_EXEC_PAGESIZE 4096 16484778508Sblueswir1 16584778508Sblueswir1 #endif 16684778508Sblueswir1 16784778508Sblueswir1 #ifdef TARGET_ARM 16884778508Sblueswir1 16984778508Sblueswir1 #define ELF_START_MMAP 0x80000000 17084778508Sblueswir1 17184778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_ARM ) 17284778508Sblueswir1 17384778508Sblueswir1 #define ELF_CLASS ELFCLASS32 17484778508Sblueswir1 #ifdef TARGET_WORDS_BIGENDIAN 17584778508Sblueswir1 #define ELF_DATA ELFDATA2MSB 17684778508Sblueswir1 #else 17784778508Sblueswir1 #define ELF_DATA ELFDATA2LSB 17884778508Sblueswir1 #endif 17984778508Sblueswir1 #define ELF_ARCH EM_ARM 18084778508Sblueswir1 18184778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 18284778508Sblueswir1 { 18384778508Sblueswir1 abi_long stack = infop->start_stack; 18484778508Sblueswir1 memset(regs, 0, sizeof(*regs)); 18584778508Sblueswir1 regs->ARM_cpsr = 0x10; 18684778508Sblueswir1 if (infop->entry & 1) 18784778508Sblueswir1 regs->ARM_cpsr |= CPSR_T; 18884778508Sblueswir1 regs->ARM_pc = infop->entry & 0xfffffffe; 18984778508Sblueswir1 regs->ARM_sp = infop->start_stack; 19084778508Sblueswir1 /* FIXME - what to for failure of get_user()? */ 19184778508Sblueswir1 get_user_ual(regs->ARM_r2, stack + 8); /* envp */ 19284778508Sblueswir1 get_user_ual(regs->ARM_r1, stack + 4); /* envp */ 19384778508Sblueswir1 /* XXX: it seems that r0 is zeroed after ! */ 19484778508Sblueswir1 regs->ARM_r0 = 0; 19584778508Sblueswir1 /* For uClinux PIC binaries. */ 19684778508Sblueswir1 /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ 19784778508Sblueswir1 regs->ARM_r10 = infop->start_data; 19884778508Sblueswir1 } 19984778508Sblueswir1 20084778508Sblueswir1 #define USE_ELF_CORE_DUMP 20184778508Sblueswir1 #define ELF_EXEC_PAGESIZE 4096 20284778508Sblueswir1 20384778508Sblueswir1 enum 20484778508Sblueswir1 { 20584778508Sblueswir1 ARM_HWCAP_ARM_SWP = 1 << 0, 20684778508Sblueswir1 ARM_HWCAP_ARM_HALF = 1 << 1, 20784778508Sblueswir1 ARM_HWCAP_ARM_THUMB = 1 << 2, 20884778508Sblueswir1 ARM_HWCAP_ARM_26BIT = 1 << 3, 20984778508Sblueswir1 ARM_HWCAP_ARM_FAST_MULT = 1 << 4, 21084778508Sblueswir1 ARM_HWCAP_ARM_FPA = 1 << 5, 21184778508Sblueswir1 ARM_HWCAP_ARM_VFP = 1 << 6, 21284778508Sblueswir1 ARM_HWCAP_ARM_EDSP = 1 << 7, 21384778508Sblueswir1 }; 21484778508Sblueswir1 21584778508Sblueswir1 #define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF \ 21684778508Sblueswir1 | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT \ 21784778508Sblueswir1 | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP) 21884778508Sblueswir1 21984778508Sblueswir1 #endif 22084778508Sblueswir1 22184778508Sblueswir1 #ifdef TARGET_SPARC 22284778508Sblueswir1 #ifdef TARGET_SPARC64 22384778508Sblueswir1 22484778508Sblueswir1 #define ELF_START_MMAP 0x80000000 22584778508Sblueswir1 22684778508Sblueswir1 #ifndef TARGET_ABI32 22784778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) 22884778508Sblueswir1 #else 22984778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) 23084778508Sblueswir1 #endif 23184778508Sblueswir1 23284778508Sblueswir1 #define ELF_CLASS ELFCLASS64 23384778508Sblueswir1 #define ELF_DATA ELFDATA2MSB 23484778508Sblueswir1 #define ELF_ARCH EM_SPARCV9 23584778508Sblueswir1 23684778508Sblueswir1 #define STACK_BIAS 2047 23784778508Sblueswir1 23884778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 23984778508Sblueswir1 { 24084778508Sblueswir1 #ifndef TARGET_ABI32 24184778508Sblueswir1 regs->tstate = 0; 24284778508Sblueswir1 #endif 24384778508Sblueswir1 regs->pc = infop->entry; 24484778508Sblueswir1 regs->npc = regs->pc + 4; 24584778508Sblueswir1 regs->y = 0; 24684778508Sblueswir1 #ifdef TARGET_ABI32 24784778508Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 24884778508Sblueswir1 #else 24984778508Sblueswir1 if (personality(infop->personality) == PER_LINUX32) 25084778508Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 25178cfb07fSJuergen Lock else { 25284778508Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; 25378cfb07fSJuergen Lock if (bsd_type == target_freebsd) { 25478cfb07fSJuergen Lock regs->u_regs[8] = infop->start_stack; 25578cfb07fSJuergen Lock regs->u_regs[11] = infop->start_stack; 25678cfb07fSJuergen Lock } 25778cfb07fSJuergen Lock } 25884778508Sblueswir1 #endif 25984778508Sblueswir1 } 26084778508Sblueswir1 26184778508Sblueswir1 #else 26284778508Sblueswir1 #define ELF_START_MMAP 0x80000000 26384778508Sblueswir1 26484778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SPARC ) 26584778508Sblueswir1 26684778508Sblueswir1 #define ELF_CLASS ELFCLASS32 26784778508Sblueswir1 #define ELF_DATA ELFDATA2MSB 26884778508Sblueswir1 #define ELF_ARCH EM_SPARC 26984778508Sblueswir1 27084778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 27184778508Sblueswir1 { 27284778508Sblueswir1 regs->psr = 0; 27384778508Sblueswir1 regs->pc = infop->entry; 27484778508Sblueswir1 regs->npc = regs->pc + 4; 27584778508Sblueswir1 regs->y = 0; 27684778508Sblueswir1 regs->u_regs[14] = infop->start_stack - 16 * 4; 27784778508Sblueswir1 } 27884778508Sblueswir1 27984778508Sblueswir1 #endif 28084778508Sblueswir1 #endif 28184778508Sblueswir1 28284778508Sblueswir1 #ifdef TARGET_PPC 28384778508Sblueswir1 28484778508Sblueswir1 #define ELF_START_MMAP 0x80000000 28584778508Sblueswir1 28684778508Sblueswir1 #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 28784778508Sblueswir1 28884778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_PPC64 ) 28984778508Sblueswir1 29084778508Sblueswir1 #define ELF_CLASS ELFCLASS64 29184778508Sblueswir1 29284778508Sblueswir1 #else 29384778508Sblueswir1 29484778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_PPC ) 29584778508Sblueswir1 29684778508Sblueswir1 #define ELF_CLASS ELFCLASS32 29784778508Sblueswir1 29884778508Sblueswir1 #endif 29984778508Sblueswir1 30084778508Sblueswir1 #ifdef TARGET_WORDS_BIGENDIAN 30184778508Sblueswir1 #define ELF_DATA ELFDATA2MSB 30284778508Sblueswir1 #else 30384778508Sblueswir1 #define ELF_DATA ELFDATA2LSB 30484778508Sblueswir1 #endif 30584778508Sblueswir1 #define ELF_ARCH EM_PPC 30684778508Sblueswir1 30784778508Sblueswir1 /* 30884778508Sblueswir1 * We need to put in some extra aux table entries to tell glibc what 30984778508Sblueswir1 * the cache block size is, so it can use the dcbz instruction safely. 31084778508Sblueswir1 */ 31184778508Sblueswir1 #define AT_DCACHEBSIZE 19 31284778508Sblueswir1 #define AT_ICACHEBSIZE 20 31384778508Sblueswir1 #define AT_UCACHEBSIZE 21 31484778508Sblueswir1 /* A special ignored type value for PPC, for glibc compatibility. */ 31584778508Sblueswir1 #define AT_IGNOREPPC 22 31684778508Sblueswir1 /* 31784778508Sblueswir1 * The requirements here are: 31884778508Sblueswir1 * - keep the final alignment of sp (sp & 0xf) 31984778508Sblueswir1 * - make sure the 32-bit value at the first 16 byte aligned position of 32084778508Sblueswir1 * AUXV is greater than 16 for glibc compatibility. 32184778508Sblueswir1 * AT_IGNOREPPC is used for that. 32284778508Sblueswir1 * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, 32384778508Sblueswir1 * even if DLINFO_ARCH_ITEMS goes to zero or is undefined. 32484778508Sblueswir1 */ 32584778508Sblueswir1 #define DLINFO_ARCH_ITEMS 5 32684778508Sblueswir1 #define ARCH_DLINFO \ 32784778508Sblueswir1 do { \ 32884778508Sblueswir1 NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20); \ 32984778508Sblueswir1 NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20); \ 33084778508Sblueswir1 NEW_AUX_ENT(AT_UCACHEBSIZE, 0); \ 33184778508Sblueswir1 /* \ 33284778508Sblueswir1 * Now handle glibc compatibility. \ 33384778508Sblueswir1 */ \ 33484778508Sblueswir1 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 33584778508Sblueswir1 NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC); \ 33684778508Sblueswir1 } while (0) 33784778508Sblueswir1 33884778508Sblueswir1 static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) 33984778508Sblueswir1 { 34084778508Sblueswir1 abi_ulong pos = infop->start_stack; 34184778508Sblueswir1 abi_ulong tmp; 34284778508Sblueswir1 #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 34384778508Sblueswir1 abi_ulong entry, toc; 34484778508Sblueswir1 #endif 34584778508Sblueswir1 34684778508Sblueswir1 _regs->gpr[1] = infop->start_stack; 34784778508Sblueswir1 #if defined(TARGET_PPC64) && !defined(TARGET_ABI32) 348b8d6ac9fSPeter Maydell get_user_u64(entry, infop->entry); 349b8d6ac9fSPeter Maydell entry += infop->load_addr; 350b8d6ac9fSPeter Maydell get_user_u64(toc, infop->entry + 8); 351b8d6ac9fSPeter Maydell toc += infop->load_addr; 35284778508Sblueswir1 _regs->gpr[2] = toc; 35384778508Sblueswir1 infop->entry = entry; 35484778508Sblueswir1 #endif 35584778508Sblueswir1 _regs->nip = infop->entry; 35684778508Sblueswir1 /* Note that isn't exactly what regular kernel does 35784778508Sblueswir1 * but this is what the ABI wants and is needed to allow 35884778508Sblueswir1 * execution of PPC BSD programs. 35984778508Sblueswir1 */ 36084778508Sblueswir1 /* FIXME - what to for failure of get_user()? */ 36184778508Sblueswir1 get_user_ual(_regs->gpr[3], pos); 36284778508Sblueswir1 pos += sizeof(abi_ulong); 36384778508Sblueswir1 _regs->gpr[4] = pos; 364b8d6ac9fSPeter Maydell for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong)) { 365b8d6ac9fSPeter Maydell get_user_ual(tmp, pos); 366b8d6ac9fSPeter Maydell } 36784778508Sblueswir1 _regs->gpr[5] = pos; 36884778508Sblueswir1 } 36984778508Sblueswir1 37084778508Sblueswir1 #define USE_ELF_CORE_DUMP 37184778508Sblueswir1 #define ELF_EXEC_PAGESIZE 4096 37284778508Sblueswir1 37384778508Sblueswir1 #endif 37484778508Sblueswir1 37584778508Sblueswir1 #ifdef TARGET_MIPS 37684778508Sblueswir1 37784778508Sblueswir1 #define ELF_START_MMAP 0x80000000 37884778508Sblueswir1 37984778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_MIPS ) 38084778508Sblueswir1 38184778508Sblueswir1 #ifdef TARGET_MIPS64 38284778508Sblueswir1 #define ELF_CLASS ELFCLASS64 38384778508Sblueswir1 #else 38484778508Sblueswir1 #define ELF_CLASS ELFCLASS32 38584778508Sblueswir1 #endif 38684778508Sblueswir1 #ifdef TARGET_WORDS_BIGENDIAN 38784778508Sblueswir1 #define ELF_DATA ELFDATA2MSB 38884778508Sblueswir1 #else 38984778508Sblueswir1 #define ELF_DATA ELFDATA2LSB 39084778508Sblueswir1 #endif 39184778508Sblueswir1 #define ELF_ARCH EM_MIPS 39284778508Sblueswir1 39384778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 39484778508Sblueswir1 { 39584778508Sblueswir1 regs->cp0_status = 2 << CP0St_KSU; 39684778508Sblueswir1 regs->cp0_epc = infop->entry; 39784778508Sblueswir1 regs->regs[29] = infop->start_stack; 39884778508Sblueswir1 } 39984778508Sblueswir1 40084778508Sblueswir1 #define USE_ELF_CORE_DUMP 40184778508Sblueswir1 #define ELF_EXEC_PAGESIZE 4096 40284778508Sblueswir1 40384778508Sblueswir1 #endif /* TARGET_MIPS */ 40484778508Sblueswir1 40584778508Sblueswir1 #ifdef TARGET_SH4 40684778508Sblueswir1 40784778508Sblueswir1 #define ELF_START_MMAP 0x80000000 40884778508Sblueswir1 40984778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_SH ) 41084778508Sblueswir1 41184778508Sblueswir1 #define ELF_CLASS ELFCLASS32 41284778508Sblueswir1 #define ELF_DATA ELFDATA2LSB 41384778508Sblueswir1 #define ELF_ARCH EM_SH 41484778508Sblueswir1 41584778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 41684778508Sblueswir1 { 41784778508Sblueswir1 /* Check other registers XXXXX */ 41884778508Sblueswir1 regs->pc = infop->entry; 41984778508Sblueswir1 regs->regs[15] = infop->start_stack; 42084778508Sblueswir1 } 42184778508Sblueswir1 42284778508Sblueswir1 #define USE_ELF_CORE_DUMP 42384778508Sblueswir1 #define ELF_EXEC_PAGESIZE 4096 42484778508Sblueswir1 42584778508Sblueswir1 #endif 42684778508Sblueswir1 42784778508Sblueswir1 #ifdef TARGET_CRIS 42884778508Sblueswir1 42984778508Sblueswir1 #define ELF_START_MMAP 0x80000000 43084778508Sblueswir1 43184778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_CRIS ) 43284778508Sblueswir1 43384778508Sblueswir1 #define ELF_CLASS ELFCLASS32 43484778508Sblueswir1 #define ELF_DATA ELFDATA2LSB 43584778508Sblueswir1 #define ELF_ARCH EM_CRIS 43684778508Sblueswir1 43784778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 43884778508Sblueswir1 { 43984778508Sblueswir1 regs->erp = infop->entry; 44084778508Sblueswir1 } 44184778508Sblueswir1 44284778508Sblueswir1 #define USE_ELF_CORE_DUMP 44384778508Sblueswir1 #define ELF_EXEC_PAGESIZE 8192 44484778508Sblueswir1 44584778508Sblueswir1 #endif 44684778508Sblueswir1 44784778508Sblueswir1 #ifdef TARGET_M68K 44884778508Sblueswir1 44984778508Sblueswir1 #define ELF_START_MMAP 0x80000000 45084778508Sblueswir1 45184778508Sblueswir1 #define elf_check_arch(x) ( (x) == EM_68K ) 45284778508Sblueswir1 45384778508Sblueswir1 #define ELF_CLASS ELFCLASS32 45484778508Sblueswir1 #define ELF_DATA ELFDATA2MSB 45584778508Sblueswir1 #define ELF_ARCH EM_68K 45684778508Sblueswir1 45784778508Sblueswir1 /* ??? Does this need to do anything? 45884778508Sblueswir1 #define ELF_PLAT_INIT(_r) */ 45984778508Sblueswir1 46084778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 46184778508Sblueswir1 { 46284778508Sblueswir1 regs->usp = infop->start_stack; 46384778508Sblueswir1 regs->sr = 0; 46484778508Sblueswir1 regs->pc = infop->entry; 46584778508Sblueswir1 } 46684778508Sblueswir1 46784778508Sblueswir1 #define USE_ELF_CORE_DUMP 46884778508Sblueswir1 #define ELF_EXEC_PAGESIZE 8192 46984778508Sblueswir1 47084778508Sblueswir1 #endif 47184778508Sblueswir1 47284778508Sblueswir1 #ifdef TARGET_ALPHA 47384778508Sblueswir1 47484778508Sblueswir1 #define ELF_START_MMAP (0x30000000000ULL) 47584778508Sblueswir1 47684778508Sblueswir1 #define elf_check_arch(x) ( (x) == ELF_ARCH ) 47784778508Sblueswir1 47884778508Sblueswir1 #define ELF_CLASS ELFCLASS64 47984778508Sblueswir1 #define ELF_DATA ELFDATA2MSB 48084778508Sblueswir1 #define ELF_ARCH EM_ALPHA 48184778508Sblueswir1 48284778508Sblueswir1 static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) 48384778508Sblueswir1 { 48484778508Sblueswir1 regs->pc = infop->entry; 48584778508Sblueswir1 regs->ps = 8; 48684778508Sblueswir1 regs->usp = infop->start_stack; 48784778508Sblueswir1 regs->unique = infop->start_data; /* ? */ 48884778508Sblueswir1 printf("Set unique value to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n", 48984778508Sblueswir1 regs->unique, infop->start_data); 49084778508Sblueswir1 } 49184778508Sblueswir1 49284778508Sblueswir1 #define USE_ELF_CORE_DUMP 49384778508Sblueswir1 #define ELF_EXEC_PAGESIZE 8192 49484778508Sblueswir1 49584778508Sblueswir1 #endif /* TARGET_ALPHA */ 49684778508Sblueswir1 49784778508Sblueswir1 #ifndef ELF_PLATFORM 49884778508Sblueswir1 #define ELF_PLATFORM (NULL) 49984778508Sblueswir1 #endif 50084778508Sblueswir1 50184778508Sblueswir1 #ifndef ELF_HWCAP 50284778508Sblueswir1 #define ELF_HWCAP 0 50384778508Sblueswir1 #endif 50484778508Sblueswir1 50584778508Sblueswir1 #ifdef TARGET_ABI32 50684778508Sblueswir1 #undef ELF_CLASS 50784778508Sblueswir1 #define ELF_CLASS ELFCLASS32 50884778508Sblueswir1 #undef bswaptls 50984778508Sblueswir1 #define bswaptls(ptr) bswap32s(ptr) 51084778508Sblueswir1 #endif 51184778508Sblueswir1 51284778508Sblueswir1 #include "elf.h" 51384778508Sblueswir1 51484778508Sblueswir1 struct exec 51584778508Sblueswir1 { 51684778508Sblueswir1 unsigned int a_info; /* Use macros N_MAGIC, etc for access */ 51784778508Sblueswir1 unsigned int a_text; /* length of text, in bytes */ 51884778508Sblueswir1 unsigned int a_data; /* length of data, in bytes */ 51984778508Sblueswir1 unsigned int a_bss; /* length of uninitialized data area, in bytes */ 52084778508Sblueswir1 unsigned int a_syms; /* length of symbol table data in file, in bytes */ 52184778508Sblueswir1 unsigned int a_entry; /* start address */ 52284778508Sblueswir1 unsigned int a_trsize; /* length of relocation info for text, in bytes */ 52384778508Sblueswir1 unsigned int a_drsize; /* length of relocation info for data, in bytes */ 52484778508Sblueswir1 }; 52584778508Sblueswir1 52684778508Sblueswir1 52784778508Sblueswir1 #define N_MAGIC(exec) ((exec).a_info & 0xffff) 52884778508Sblueswir1 #define OMAGIC 0407 52984778508Sblueswir1 #define NMAGIC 0410 53084778508Sblueswir1 #define ZMAGIC 0413 53184778508Sblueswir1 #define QMAGIC 0314 53284778508Sblueswir1 53384778508Sblueswir1 /* max code+data+bss space allocated to elf interpreter */ 53484778508Sblueswir1 #define INTERP_MAP_SIZE (32 * 1024 * 1024) 53584778508Sblueswir1 53684778508Sblueswir1 /* max code+data+bss+brk space allocated to ET_DYN executables */ 53784778508Sblueswir1 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024) 53884778508Sblueswir1 53984778508Sblueswir1 /* Necessary parameters */ 54084778508Sblueswir1 #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE 54184778508Sblueswir1 #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) 54284778508Sblueswir1 #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) 54384778508Sblueswir1 54484778508Sblueswir1 #define INTERPRETER_NONE 0 54584778508Sblueswir1 #define INTERPRETER_AOUT 1 54684778508Sblueswir1 #define INTERPRETER_ELF 2 54784778508Sblueswir1 54884778508Sblueswir1 #define DLINFO_ITEMS 12 54984778508Sblueswir1 55084778508Sblueswir1 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) 55184778508Sblueswir1 { 55284778508Sblueswir1 memcpy(to, from, n); 55384778508Sblueswir1 } 55484778508Sblueswir1 55584778508Sblueswir1 static int load_aout_interp(void * exptr, int interp_fd); 55684778508Sblueswir1 55784778508Sblueswir1 #ifdef BSWAP_NEEDED 55884778508Sblueswir1 static void bswap_ehdr(struct elfhdr *ehdr) 55984778508Sblueswir1 { 56084778508Sblueswir1 bswap16s(&ehdr->e_type); /* Object file type */ 56184778508Sblueswir1 bswap16s(&ehdr->e_machine); /* Architecture */ 56284778508Sblueswir1 bswap32s(&ehdr->e_version); /* Object file version */ 56384778508Sblueswir1 bswaptls(&ehdr->e_entry); /* Entry point virtual address */ 56484778508Sblueswir1 bswaptls(&ehdr->e_phoff); /* Program header table file offset */ 56584778508Sblueswir1 bswaptls(&ehdr->e_shoff); /* Section header table file offset */ 56684778508Sblueswir1 bswap32s(&ehdr->e_flags); /* Processor-specific flags */ 56784778508Sblueswir1 bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ 56884778508Sblueswir1 bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ 56984778508Sblueswir1 bswap16s(&ehdr->e_phnum); /* Program header table entry count */ 57084778508Sblueswir1 bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ 57184778508Sblueswir1 bswap16s(&ehdr->e_shnum); /* Section header table entry count */ 57284778508Sblueswir1 bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ 57384778508Sblueswir1 } 57484778508Sblueswir1 57584778508Sblueswir1 static void bswap_phdr(struct elf_phdr *phdr) 57684778508Sblueswir1 { 57784778508Sblueswir1 bswap32s(&phdr->p_type); /* Segment type */ 57884778508Sblueswir1 bswaptls(&phdr->p_offset); /* Segment file offset */ 57984778508Sblueswir1 bswaptls(&phdr->p_vaddr); /* Segment virtual address */ 58084778508Sblueswir1 bswaptls(&phdr->p_paddr); /* Segment physical address */ 58184778508Sblueswir1 bswaptls(&phdr->p_filesz); /* Segment size in file */ 58284778508Sblueswir1 bswaptls(&phdr->p_memsz); /* Segment size in memory */ 58384778508Sblueswir1 bswap32s(&phdr->p_flags); /* Segment flags */ 58484778508Sblueswir1 bswaptls(&phdr->p_align); /* Segment alignment */ 58584778508Sblueswir1 } 58684778508Sblueswir1 58784778508Sblueswir1 static void bswap_shdr(struct elf_shdr *shdr) 58884778508Sblueswir1 { 58984778508Sblueswir1 bswap32s(&shdr->sh_name); 59084778508Sblueswir1 bswap32s(&shdr->sh_type); 59184778508Sblueswir1 bswaptls(&shdr->sh_flags); 59284778508Sblueswir1 bswaptls(&shdr->sh_addr); 59384778508Sblueswir1 bswaptls(&shdr->sh_offset); 59484778508Sblueswir1 bswaptls(&shdr->sh_size); 59584778508Sblueswir1 bswap32s(&shdr->sh_link); 59684778508Sblueswir1 bswap32s(&shdr->sh_info); 59784778508Sblueswir1 bswaptls(&shdr->sh_addralign); 59884778508Sblueswir1 bswaptls(&shdr->sh_entsize); 59984778508Sblueswir1 } 60084778508Sblueswir1 60184778508Sblueswir1 static void bswap_sym(struct elf_sym *sym) 60284778508Sblueswir1 { 60384778508Sblueswir1 bswap32s(&sym->st_name); 60484778508Sblueswir1 bswaptls(&sym->st_value); 60584778508Sblueswir1 bswaptls(&sym->st_size); 60684778508Sblueswir1 bswap16s(&sym->st_shndx); 60784778508Sblueswir1 } 60884778508Sblueswir1 #endif 60984778508Sblueswir1 61084778508Sblueswir1 /* 61184778508Sblueswir1 * 'copy_elf_strings()' copies argument/envelope strings from user 61284778508Sblueswir1 * memory to free pages in kernel mem. These are in a format ready 61384778508Sblueswir1 * to be put directly into the top of new user memory. 61484778508Sblueswir1 * 61584778508Sblueswir1 */ 61684778508Sblueswir1 static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, 61784778508Sblueswir1 abi_ulong p) 61884778508Sblueswir1 { 61984778508Sblueswir1 char *tmp, *tmp1, *pag = NULL; 62084778508Sblueswir1 int len, offset = 0; 62184778508Sblueswir1 62284778508Sblueswir1 if (!p) { 62384778508Sblueswir1 return 0; /* bullet-proofing */ 62484778508Sblueswir1 } 62584778508Sblueswir1 while (argc-- > 0) { 62684778508Sblueswir1 tmp = argv[argc]; 62784778508Sblueswir1 if (!tmp) { 6289bb93180SPeter Maydell fprintf(stderr, "VFS: argc is wrong"); 62984778508Sblueswir1 exit(-1); 63084778508Sblueswir1 } 63184778508Sblueswir1 tmp1 = tmp; 63284778508Sblueswir1 while (*tmp++); 63384778508Sblueswir1 len = tmp - tmp1; 63484778508Sblueswir1 if (p < len) { /* this shouldn't happen - 128kB */ 63584778508Sblueswir1 return 0; 63684778508Sblueswir1 } 63784778508Sblueswir1 while (len) { 63884778508Sblueswir1 --p; --tmp; --len; 63984778508Sblueswir1 if (--offset < 0) { 64084778508Sblueswir1 offset = p % TARGET_PAGE_SIZE; 64184778508Sblueswir1 pag = (char *)page[p/TARGET_PAGE_SIZE]; 64284778508Sblueswir1 if (!pag) { 643c580dee4SStefan Weil pag = g_try_malloc0(TARGET_PAGE_SIZE); 64484778508Sblueswir1 page[p/TARGET_PAGE_SIZE] = pag; 64584778508Sblueswir1 if (!pag) 64684778508Sblueswir1 return 0; 64784778508Sblueswir1 } 64884778508Sblueswir1 } 64984778508Sblueswir1 if (len == 0 || offset == 0) { 65084778508Sblueswir1 *(pag + offset) = *tmp; 65184778508Sblueswir1 } 65284778508Sblueswir1 else { 65384778508Sblueswir1 int bytes_to_copy = (len > offset) ? offset : len; 65484778508Sblueswir1 tmp -= bytes_to_copy; 65584778508Sblueswir1 p -= bytes_to_copy; 65684778508Sblueswir1 offset -= bytes_to_copy; 65784778508Sblueswir1 len -= bytes_to_copy; 65884778508Sblueswir1 memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); 65984778508Sblueswir1 } 66084778508Sblueswir1 } 66184778508Sblueswir1 } 66284778508Sblueswir1 return p; 66384778508Sblueswir1 } 66484778508Sblueswir1 66584778508Sblueswir1 static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, 66684778508Sblueswir1 struct image_info *info) 66784778508Sblueswir1 { 66884778508Sblueswir1 abi_ulong stack_base, size, error; 66984778508Sblueswir1 int i; 67084778508Sblueswir1 67184778508Sblueswir1 /* Create enough stack to hold everything. If we don't use 67284778508Sblueswir1 * it for args, we'll use it for something else... 67384778508Sblueswir1 */ 67484778508Sblueswir1 size = x86_stack_size; 67584778508Sblueswir1 if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) 67684778508Sblueswir1 size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; 67784778508Sblueswir1 error = target_mmap(0, 67884778508Sblueswir1 size + qemu_host_page_size, 67984778508Sblueswir1 PROT_READ | PROT_WRITE, 68084778508Sblueswir1 MAP_PRIVATE | MAP_ANON, 68184778508Sblueswir1 -1, 0); 68284778508Sblueswir1 if (error == -1) { 68384778508Sblueswir1 perror("stk mmap"); 68484778508Sblueswir1 exit(-1); 68584778508Sblueswir1 } 68684778508Sblueswir1 /* we reserve one extra page at the top of the stack as guard */ 68784778508Sblueswir1 target_mprotect(error + size, qemu_host_page_size, PROT_NONE); 68884778508Sblueswir1 68984778508Sblueswir1 stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; 69084778508Sblueswir1 p += stack_base; 69184778508Sblueswir1 69284778508Sblueswir1 for (i = 0 ; i < MAX_ARG_PAGES ; i++) { 69384778508Sblueswir1 if (bprm->page[i]) { 69484778508Sblueswir1 info->rss++; 69584778508Sblueswir1 /* FIXME - check return value of memcpy_to_target() for failure */ 69684778508Sblueswir1 memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); 697c580dee4SStefan Weil g_free(bprm->page[i]); 69884778508Sblueswir1 } 69984778508Sblueswir1 stack_base += TARGET_PAGE_SIZE; 70084778508Sblueswir1 } 70184778508Sblueswir1 return p; 70284778508Sblueswir1 } 70384778508Sblueswir1 70484778508Sblueswir1 static void set_brk(abi_ulong start, abi_ulong end) 70584778508Sblueswir1 { 70684778508Sblueswir1 /* page-align the start and end addresses... */ 70784778508Sblueswir1 start = HOST_PAGE_ALIGN(start); 70884778508Sblueswir1 end = HOST_PAGE_ALIGN(end); 70984778508Sblueswir1 if (end <= start) 71084778508Sblueswir1 return; 71184778508Sblueswir1 if(target_mmap(start, end - start, 71284778508Sblueswir1 PROT_READ | PROT_WRITE | PROT_EXEC, 71384778508Sblueswir1 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == -1) { 71484778508Sblueswir1 perror("cannot mmap brk"); 71584778508Sblueswir1 exit(-1); 71684778508Sblueswir1 } 71784778508Sblueswir1 } 71884778508Sblueswir1 71984778508Sblueswir1 72084778508Sblueswir1 /* We need to explicitly zero any fractional pages after the data 72184778508Sblueswir1 section (i.e. bss). This would contain the junk from the file that 72284778508Sblueswir1 should not be in memory. */ 72384778508Sblueswir1 static void padzero(abi_ulong elf_bss, abi_ulong last_bss) 72484778508Sblueswir1 { 72584778508Sblueswir1 abi_ulong nbyte; 72684778508Sblueswir1 72784778508Sblueswir1 if (elf_bss >= last_bss) 72884778508Sblueswir1 return; 72984778508Sblueswir1 73084778508Sblueswir1 /* XXX: this is really a hack : if the real host page size is 73184778508Sblueswir1 smaller than the target page size, some pages after the end 73284778508Sblueswir1 of the file may not be mapped. A better fix would be to 73384778508Sblueswir1 patch target_mmap(), but it is more complicated as the file 73484778508Sblueswir1 size must be known */ 73584778508Sblueswir1 if (qemu_real_host_page_size < qemu_host_page_size) { 73684778508Sblueswir1 abi_ulong end_addr, end_addr1; 7370c2d70c4SPaolo Bonzini end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss); 73884778508Sblueswir1 end_addr = HOST_PAGE_ALIGN(elf_bss); 73984778508Sblueswir1 if (end_addr1 < end_addr) { 740*3e8f1628SRichard Henderson mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1, 74184778508Sblueswir1 PROT_READ|PROT_WRITE|PROT_EXEC, 74284778508Sblueswir1 MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0); 74384778508Sblueswir1 } 74484778508Sblueswir1 } 74584778508Sblueswir1 74684778508Sblueswir1 nbyte = elf_bss & (qemu_host_page_size-1); 74784778508Sblueswir1 if (nbyte) { 74884778508Sblueswir1 nbyte = qemu_host_page_size - nbyte; 74984778508Sblueswir1 do { 75084778508Sblueswir1 /* FIXME - what to do if put_user() fails? */ 75184778508Sblueswir1 put_user_u8(0, elf_bss); 75284778508Sblueswir1 elf_bss++; 75384778508Sblueswir1 } while (--nbyte); 75484778508Sblueswir1 } 75584778508Sblueswir1 } 75684778508Sblueswir1 75784778508Sblueswir1 75884778508Sblueswir1 static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, 75984778508Sblueswir1 struct elfhdr * exec, 76084778508Sblueswir1 abi_ulong load_addr, 76184778508Sblueswir1 abi_ulong load_bias, 76284778508Sblueswir1 abi_ulong interp_load_addr, int ibcs, 76384778508Sblueswir1 struct image_info *info) 76484778508Sblueswir1 { 76584778508Sblueswir1 abi_ulong sp; 76684778508Sblueswir1 int size; 76784778508Sblueswir1 abi_ulong u_platform; 76884778508Sblueswir1 const char *k_platform; 76984778508Sblueswir1 const int n = sizeof(elf_addr_t); 77084778508Sblueswir1 77184778508Sblueswir1 sp = p; 77284778508Sblueswir1 u_platform = 0; 77384778508Sblueswir1 k_platform = ELF_PLATFORM; 77484778508Sblueswir1 if (k_platform) { 77584778508Sblueswir1 size_t len = strlen(k_platform) + 1; 77684778508Sblueswir1 sp -= (len + n - 1) & ~(n - 1); 77784778508Sblueswir1 u_platform = sp; 77884778508Sblueswir1 /* FIXME - check return value of memcpy_to_target() for failure */ 77984778508Sblueswir1 memcpy_to_target(sp, k_platform, len); 78084778508Sblueswir1 } 78184778508Sblueswir1 /* 78284778508Sblueswir1 * Force 16 byte _final_ alignment here for generality. 78384778508Sblueswir1 */ 78484778508Sblueswir1 sp = sp &~ (abi_ulong)15; 78584778508Sblueswir1 size = (DLINFO_ITEMS + 1) * 2; 78684778508Sblueswir1 if (k_platform) 78784778508Sblueswir1 size += 2; 78884778508Sblueswir1 #ifdef DLINFO_ARCH_ITEMS 78984778508Sblueswir1 size += DLINFO_ARCH_ITEMS * 2; 79084778508Sblueswir1 #endif 79184778508Sblueswir1 size += envc + argc + 2; 79284778508Sblueswir1 size += (!ibcs ? 3 : 1); /* argc itself */ 79384778508Sblueswir1 size *= n; 79484778508Sblueswir1 if (size & 15) 79584778508Sblueswir1 sp -= 16 - (size & 15); 79684778508Sblueswir1 79784778508Sblueswir1 /* This is correct because Linux defines 79884778508Sblueswir1 * elf_addr_t as Elf32_Off / Elf64_Off 79984778508Sblueswir1 */ 80084778508Sblueswir1 #define NEW_AUX_ENT(id, val) do { \ 80184778508Sblueswir1 sp -= n; put_user_ual(val, sp); \ 80284778508Sblueswir1 sp -= n; put_user_ual(id, sp); \ 80384778508Sblueswir1 } while(0) 80484778508Sblueswir1 80584778508Sblueswir1 NEW_AUX_ENT (AT_NULL, 0); 80684778508Sblueswir1 80784778508Sblueswir1 /* There must be exactly DLINFO_ITEMS entries here. */ 80884778508Sblueswir1 NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff)); 80984778508Sblueswir1 NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); 81084778508Sblueswir1 NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); 81184778508Sblueswir1 NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE)); 81284778508Sblueswir1 NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr)); 81384778508Sblueswir1 NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); 81484778508Sblueswir1 NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry); 81584778508Sblueswir1 NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); 81684778508Sblueswir1 NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); 81784778508Sblueswir1 NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); 81884778508Sblueswir1 NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); 81984778508Sblueswir1 NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); 82084778508Sblueswir1 NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); 82184778508Sblueswir1 if (k_platform) 82284778508Sblueswir1 NEW_AUX_ENT(AT_PLATFORM, u_platform); 82384778508Sblueswir1 #ifdef ARCH_DLINFO 82484778508Sblueswir1 /* 82584778508Sblueswir1 * ARCH_DLINFO must come last so platform specific code can enforce 82684778508Sblueswir1 * special alignment requirements on the AUXV if necessary (eg. PPC). 82784778508Sblueswir1 */ 82884778508Sblueswir1 ARCH_DLINFO; 82984778508Sblueswir1 #endif 83084778508Sblueswir1 #undef NEW_AUX_ENT 83184778508Sblueswir1 83284778508Sblueswir1 sp = loader_build_argptr(envc, argc, sp, p, !ibcs); 83384778508Sblueswir1 return sp; 83484778508Sblueswir1 } 83584778508Sblueswir1 83684778508Sblueswir1 83784778508Sblueswir1 static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex, 83884778508Sblueswir1 int interpreter_fd, 83984778508Sblueswir1 abi_ulong *interp_load_addr) 84084778508Sblueswir1 { 84184778508Sblueswir1 struct elf_phdr *elf_phdata = NULL; 84284778508Sblueswir1 struct elf_phdr *eppnt; 84384778508Sblueswir1 abi_ulong load_addr = 0; 84484778508Sblueswir1 int load_addr_set = 0; 84584778508Sblueswir1 int retval; 84684778508Sblueswir1 abi_ulong last_bss, elf_bss; 84784778508Sblueswir1 abi_ulong error; 84884778508Sblueswir1 int i; 84984778508Sblueswir1 85084778508Sblueswir1 elf_bss = 0; 85184778508Sblueswir1 last_bss = 0; 85284778508Sblueswir1 error = 0; 85384778508Sblueswir1 85484778508Sblueswir1 #ifdef BSWAP_NEEDED 85584778508Sblueswir1 bswap_ehdr(interp_elf_ex); 85684778508Sblueswir1 #endif 85784778508Sblueswir1 /* First of all, some simple consistency checks */ 85884778508Sblueswir1 if ((interp_elf_ex->e_type != ET_EXEC && 85984778508Sblueswir1 interp_elf_ex->e_type != ET_DYN) || 86084778508Sblueswir1 !elf_check_arch(interp_elf_ex->e_machine)) { 86184778508Sblueswir1 return ~((abi_ulong)0UL); 86284778508Sblueswir1 } 86384778508Sblueswir1 86484778508Sblueswir1 86584778508Sblueswir1 /* Now read in all of the header information */ 86684778508Sblueswir1 86784778508Sblueswir1 if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE) 86884778508Sblueswir1 return ~(abi_ulong)0UL; 86984778508Sblueswir1 87084778508Sblueswir1 elf_phdata = (struct elf_phdr *) 87184778508Sblueswir1 malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 87284778508Sblueswir1 87384778508Sblueswir1 if (!elf_phdata) 87484778508Sblueswir1 return ~((abi_ulong)0UL); 87584778508Sblueswir1 87684778508Sblueswir1 /* 87784778508Sblueswir1 * If the size of this structure has changed, then punt, since 87884778508Sblueswir1 * we will be doing the wrong thing. 87984778508Sblueswir1 */ 88084778508Sblueswir1 if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) { 88184778508Sblueswir1 free(elf_phdata); 88284778508Sblueswir1 return ~((abi_ulong)0UL); 88384778508Sblueswir1 } 88484778508Sblueswir1 88584778508Sblueswir1 retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET); 88684778508Sblueswir1 if(retval >= 0) { 88784778508Sblueswir1 retval = read(interpreter_fd, 88884778508Sblueswir1 (char *) elf_phdata, 88984778508Sblueswir1 sizeof(struct elf_phdr) * interp_elf_ex->e_phnum); 89084778508Sblueswir1 } 89184778508Sblueswir1 if (retval < 0) { 89284778508Sblueswir1 perror("load_elf_interp"); 89384778508Sblueswir1 exit(-1); 89484778508Sblueswir1 free (elf_phdata); 89584778508Sblueswir1 return retval; 89684778508Sblueswir1 } 89784778508Sblueswir1 #ifdef BSWAP_NEEDED 89884778508Sblueswir1 eppnt = elf_phdata; 89984778508Sblueswir1 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { 90084778508Sblueswir1 bswap_phdr(eppnt); 90184778508Sblueswir1 } 90284778508Sblueswir1 #endif 90384778508Sblueswir1 90484778508Sblueswir1 if (interp_elf_ex->e_type == ET_DYN) { 90584778508Sblueswir1 /* in order to avoid hardcoding the interpreter load 90684778508Sblueswir1 address in qemu, we allocate a big enough memory zone */ 90784778508Sblueswir1 error = target_mmap(0, INTERP_MAP_SIZE, 90884778508Sblueswir1 PROT_NONE, MAP_PRIVATE | MAP_ANON, 90984778508Sblueswir1 -1, 0); 91084778508Sblueswir1 if (error == -1) { 91184778508Sblueswir1 perror("mmap"); 91284778508Sblueswir1 exit(-1); 91384778508Sblueswir1 } 91484778508Sblueswir1 load_addr = error; 91584778508Sblueswir1 load_addr_set = 1; 91684778508Sblueswir1 } 91784778508Sblueswir1 91884778508Sblueswir1 eppnt = elf_phdata; 91984778508Sblueswir1 for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) 92084778508Sblueswir1 if (eppnt->p_type == PT_LOAD) { 92184778508Sblueswir1 int elf_type = MAP_PRIVATE | MAP_DENYWRITE; 92284778508Sblueswir1 int elf_prot = 0; 92384778508Sblueswir1 abi_ulong vaddr = 0; 92484778508Sblueswir1 abi_ulong k; 92584778508Sblueswir1 92684778508Sblueswir1 if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; 92784778508Sblueswir1 if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 92884778508Sblueswir1 if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 92984778508Sblueswir1 if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) { 93084778508Sblueswir1 elf_type |= MAP_FIXED; 93184778508Sblueswir1 vaddr = eppnt->p_vaddr; 93284778508Sblueswir1 } 93384778508Sblueswir1 error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr), 93484778508Sblueswir1 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr), 93584778508Sblueswir1 elf_prot, 93684778508Sblueswir1 elf_type, 93784778508Sblueswir1 interpreter_fd, 93884778508Sblueswir1 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr)); 93984778508Sblueswir1 94084778508Sblueswir1 if (error == -1) { 94184778508Sblueswir1 /* Real error */ 94284778508Sblueswir1 close(interpreter_fd); 94384778508Sblueswir1 free(elf_phdata); 94484778508Sblueswir1 return ~((abi_ulong)0UL); 94584778508Sblueswir1 } 94684778508Sblueswir1 94784778508Sblueswir1 if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { 94884778508Sblueswir1 load_addr = error; 94984778508Sblueswir1 load_addr_set = 1; 95084778508Sblueswir1 } 95184778508Sblueswir1 95284778508Sblueswir1 /* 95384778508Sblueswir1 * Find the end of the file mapping for this phdr, and keep 95484778508Sblueswir1 * track of the largest address we see for this. 95584778508Sblueswir1 */ 95684778508Sblueswir1 k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; 95784778508Sblueswir1 if (k > elf_bss) elf_bss = k; 95884778508Sblueswir1 95984778508Sblueswir1 /* 96084778508Sblueswir1 * Do the same thing for the memory mapping - between 96184778508Sblueswir1 * elf_bss and last_bss is the bss section. 96284778508Sblueswir1 */ 96384778508Sblueswir1 k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; 96484778508Sblueswir1 if (k > last_bss) last_bss = k; 96584778508Sblueswir1 } 96684778508Sblueswir1 96784778508Sblueswir1 /* Now use mmap to map the library into memory. */ 96884778508Sblueswir1 96984778508Sblueswir1 close(interpreter_fd); 97084778508Sblueswir1 97184778508Sblueswir1 /* 97284778508Sblueswir1 * Now fill out the bss section. First pad the last page up 97384778508Sblueswir1 * to the page boundary, and then perform a mmap to make sure 97484778508Sblueswir1 * that there are zeromapped pages up to and including the last 97584778508Sblueswir1 * bss page. 97684778508Sblueswir1 */ 97784778508Sblueswir1 padzero(elf_bss, last_bss); 97884778508Sblueswir1 elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */ 97984778508Sblueswir1 98084778508Sblueswir1 /* Map the last of the bss segment */ 98184778508Sblueswir1 if (last_bss > elf_bss) { 98284778508Sblueswir1 target_mmap(elf_bss, last_bss-elf_bss, 98384778508Sblueswir1 PROT_READ|PROT_WRITE|PROT_EXEC, 98484778508Sblueswir1 MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0); 98584778508Sblueswir1 } 98684778508Sblueswir1 free(elf_phdata); 98784778508Sblueswir1 98884778508Sblueswir1 *interp_load_addr = load_addr; 98984778508Sblueswir1 return ((abi_ulong) interp_elf_ex->e_entry) + load_addr; 99084778508Sblueswir1 } 99184778508Sblueswir1 99284778508Sblueswir1 static int symfind(const void *s0, const void *s1) 99384778508Sblueswir1 { 994c7c530cdSStefan Weil target_ulong addr = *(target_ulong *)s0; 99584778508Sblueswir1 struct elf_sym *sym = (struct elf_sym *)s1; 99684778508Sblueswir1 int result = 0; 997c7c530cdSStefan Weil if (addr < sym->st_value) { 99884778508Sblueswir1 result = -1; 999c7c530cdSStefan Weil } else if (addr >= sym->st_value + sym->st_size) { 100084778508Sblueswir1 result = 1; 100184778508Sblueswir1 } 100284778508Sblueswir1 return result; 100384778508Sblueswir1 } 100484778508Sblueswir1 100584778508Sblueswir1 static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr) 100684778508Sblueswir1 { 100784778508Sblueswir1 #if ELF_CLASS == ELFCLASS32 100884778508Sblueswir1 struct elf_sym *syms = s->disas_symtab.elf32; 100984778508Sblueswir1 #else 101084778508Sblueswir1 struct elf_sym *syms = s->disas_symtab.elf64; 101184778508Sblueswir1 #endif 101284778508Sblueswir1 101384778508Sblueswir1 // binary search 101484778508Sblueswir1 struct elf_sym *sym; 101584778508Sblueswir1 1016c7c530cdSStefan Weil sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind); 10177cba04f6SBlue Swirl if (sym != NULL) { 101884778508Sblueswir1 return s->disas_strtab + sym->st_name; 101984778508Sblueswir1 } 102084778508Sblueswir1 102184778508Sblueswir1 return ""; 102284778508Sblueswir1 } 102384778508Sblueswir1 102484778508Sblueswir1 /* FIXME: This should use elf_ops.h */ 102584778508Sblueswir1 static int symcmp(const void *s0, const void *s1) 102684778508Sblueswir1 { 102784778508Sblueswir1 struct elf_sym *sym0 = (struct elf_sym *)s0; 102884778508Sblueswir1 struct elf_sym *sym1 = (struct elf_sym *)s1; 102984778508Sblueswir1 return (sym0->st_value < sym1->st_value) 103084778508Sblueswir1 ? -1 103184778508Sblueswir1 : ((sym0->st_value > sym1->st_value) ? 1 : 0); 103284778508Sblueswir1 } 103384778508Sblueswir1 103484778508Sblueswir1 /* Best attempt to load symbols from this ELF object. */ 103584778508Sblueswir1 static void load_symbols(struct elfhdr *hdr, int fd) 103684778508Sblueswir1 { 103784778508Sblueswir1 unsigned int i, nsyms; 103884778508Sblueswir1 struct elf_shdr sechdr, symtab, strtab; 103984778508Sblueswir1 char *strings; 104084778508Sblueswir1 struct syminfo *s; 104129718712SStefan Weil struct elf_sym *syms, *new_syms; 104284778508Sblueswir1 104384778508Sblueswir1 lseek(fd, hdr->e_shoff, SEEK_SET); 104484778508Sblueswir1 for (i = 0; i < hdr->e_shnum; i++) { 104584778508Sblueswir1 if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr)) 104684778508Sblueswir1 return; 104784778508Sblueswir1 #ifdef BSWAP_NEEDED 104884778508Sblueswir1 bswap_shdr(&sechdr); 104984778508Sblueswir1 #endif 105084778508Sblueswir1 if (sechdr.sh_type == SHT_SYMTAB) { 105184778508Sblueswir1 symtab = sechdr; 105284778508Sblueswir1 lseek(fd, hdr->e_shoff 105384778508Sblueswir1 + sizeof(sechdr) * sechdr.sh_link, SEEK_SET); 105484778508Sblueswir1 if (read(fd, &strtab, sizeof(strtab)) 105584778508Sblueswir1 != sizeof(strtab)) 105684778508Sblueswir1 return; 105784778508Sblueswir1 #ifdef BSWAP_NEEDED 105884778508Sblueswir1 bswap_shdr(&strtab); 105984778508Sblueswir1 #endif 106084778508Sblueswir1 goto found; 106184778508Sblueswir1 } 106284778508Sblueswir1 } 106384778508Sblueswir1 return; /* Shouldn't happen... */ 106484778508Sblueswir1 106584778508Sblueswir1 found: 106684778508Sblueswir1 /* Now know where the strtab and symtab are. Snarf them. */ 106784778508Sblueswir1 s = malloc(sizeof(*s)); 106884778508Sblueswir1 syms = malloc(symtab.sh_size); 106929718712SStefan Weil if (!syms) { 107029718712SStefan Weil free(s); 107184778508Sblueswir1 return; 107229718712SStefan Weil } 107384778508Sblueswir1 s->disas_strtab = strings = malloc(strtab.sh_size); 107429718712SStefan Weil if (!s->disas_strtab) { 107529718712SStefan Weil free(s); 107629718712SStefan Weil free(syms); 107784778508Sblueswir1 return; 107829718712SStefan Weil } 107984778508Sblueswir1 108084778508Sblueswir1 lseek(fd, symtab.sh_offset, SEEK_SET); 108129718712SStefan Weil if (read(fd, syms, symtab.sh_size) != symtab.sh_size) { 108229718712SStefan Weil free(s); 108329718712SStefan Weil free(syms); 108429718712SStefan Weil free(strings); 108584778508Sblueswir1 return; 108629718712SStefan Weil } 108784778508Sblueswir1 108884778508Sblueswir1 nsyms = symtab.sh_size / sizeof(struct elf_sym); 108984778508Sblueswir1 109084778508Sblueswir1 i = 0; 109184778508Sblueswir1 while (i < nsyms) { 109284778508Sblueswir1 #ifdef BSWAP_NEEDED 109384778508Sblueswir1 bswap_sym(syms + i); 109484778508Sblueswir1 #endif 109584778508Sblueswir1 // Throw away entries which we do not need. 109684778508Sblueswir1 if (syms[i].st_shndx == SHN_UNDEF || 109784778508Sblueswir1 syms[i].st_shndx >= SHN_LORESERVE || 109884778508Sblueswir1 ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { 109984778508Sblueswir1 nsyms--; 110084778508Sblueswir1 if (i < nsyms) { 110184778508Sblueswir1 syms[i] = syms[nsyms]; 110284778508Sblueswir1 } 110384778508Sblueswir1 continue; 110484778508Sblueswir1 } 110584778508Sblueswir1 #if defined(TARGET_ARM) || defined (TARGET_MIPS) 110684778508Sblueswir1 /* The bottom address bit marks a Thumb or MIPS16 symbol. */ 110784778508Sblueswir1 syms[i].st_value &= ~(target_ulong)1; 110884778508Sblueswir1 #endif 110984778508Sblueswir1 i++; 111084778508Sblueswir1 } 111129718712SStefan Weil 111229718712SStefan Weil /* Attempt to free the storage associated with the local symbols 111329718712SStefan Weil that we threw away. Whether or not this has any effect on the 111429718712SStefan Weil memory allocation depends on the malloc implementation and how 111529718712SStefan Weil many symbols we managed to discard. */ 111629718712SStefan Weil new_syms = realloc(syms, nsyms * sizeof(*syms)); 111729718712SStefan Weil if (new_syms == NULL) { 111829718712SStefan Weil free(s); 111929718712SStefan Weil free(syms); 112029718712SStefan Weil free(strings); 112129718712SStefan Weil return; 112229718712SStefan Weil } 112329718712SStefan Weil syms = new_syms; 112484778508Sblueswir1 112584778508Sblueswir1 qsort(syms, nsyms, sizeof(*syms), symcmp); 112684778508Sblueswir1 112784778508Sblueswir1 lseek(fd, strtab.sh_offset, SEEK_SET); 112829718712SStefan Weil if (read(fd, strings, strtab.sh_size) != strtab.sh_size) { 112929718712SStefan Weil free(s); 113029718712SStefan Weil free(syms); 113129718712SStefan Weil free(strings); 113284778508Sblueswir1 return; 113329718712SStefan Weil } 113484778508Sblueswir1 s->disas_num_syms = nsyms; 113584778508Sblueswir1 #if ELF_CLASS == ELFCLASS32 113684778508Sblueswir1 s->disas_symtab.elf32 = syms; 1137032e51d7SBlue Swirl s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx; 113884778508Sblueswir1 #else 113984778508Sblueswir1 s->disas_symtab.elf64 = syms; 1140032e51d7SBlue Swirl s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx; 114184778508Sblueswir1 #endif 114284778508Sblueswir1 s->next = syminfos; 114384778508Sblueswir1 syminfos = s; 114484778508Sblueswir1 } 114584778508Sblueswir1 114684778508Sblueswir1 int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, 114784778508Sblueswir1 struct image_info * info) 114884778508Sblueswir1 { 114984778508Sblueswir1 struct elfhdr elf_ex; 115084778508Sblueswir1 struct elfhdr interp_elf_ex; 115184778508Sblueswir1 struct exec interp_ex; 115284778508Sblueswir1 int interpreter_fd = -1; /* avoid warning */ 115384778508Sblueswir1 abi_ulong load_addr, load_bias; 115484778508Sblueswir1 int load_addr_set = 0; 115584778508Sblueswir1 unsigned int interpreter_type = INTERPRETER_NONE; 115684778508Sblueswir1 unsigned char ibcs2_interpreter; 115784778508Sblueswir1 int i; 115884778508Sblueswir1 struct elf_phdr * elf_ppnt; 115984778508Sblueswir1 struct elf_phdr *elf_phdata; 116084778508Sblueswir1 abi_ulong elf_bss, k, elf_brk; 116184778508Sblueswir1 int retval; 116284778508Sblueswir1 char * elf_interpreter; 116384778508Sblueswir1 abi_ulong elf_entry, interp_load_addr = 0; 116484778508Sblueswir1 abi_ulong start_code, end_code, start_data, end_data; 116584778508Sblueswir1 abi_ulong reloc_func_desc = 0; 116671025956SPeter Maydell #ifdef LOW_ELF_STACK 116771025956SPeter Maydell abi_ulong elf_stack = ~((abi_ulong)0UL); 116871025956SPeter Maydell #endif 116984778508Sblueswir1 char passed_fileno[6]; 117084778508Sblueswir1 117184778508Sblueswir1 ibcs2_interpreter = 0; 117284778508Sblueswir1 load_addr = 0; 117384778508Sblueswir1 load_bias = 0; 117484778508Sblueswir1 elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */ 117584778508Sblueswir1 #ifdef BSWAP_NEEDED 117684778508Sblueswir1 bswap_ehdr(&elf_ex); 117784778508Sblueswir1 #endif 117884778508Sblueswir1 117984778508Sblueswir1 /* First of all, some simple consistency checks */ 118084778508Sblueswir1 if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) || 118184778508Sblueswir1 (! elf_check_arch(elf_ex.e_machine))) { 118284778508Sblueswir1 return -ENOEXEC; 118384778508Sblueswir1 } 118484778508Sblueswir1 118584778508Sblueswir1 bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); 118684778508Sblueswir1 bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); 118784778508Sblueswir1 bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); 118884778508Sblueswir1 if (!bprm->p) { 118984778508Sblueswir1 retval = -E2BIG; 119084778508Sblueswir1 } 119184778508Sblueswir1 119284778508Sblueswir1 /* Now read in all of the header information */ 119384778508Sblueswir1 elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum); 119484778508Sblueswir1 if (elf_phdata == NULL) { 119584778508Sblueswir1 return -ENOMEM; 119684778508Sblueswir1 } 119784778508Sblueswir1 119884778508Sblueswir1 retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET); 119984778508Sblueswir1 if(retval > 0) { 120084778508Sblueswir1 retval = read(bprm->fd, (char *) elf_phdata, 120184778508Sblueswir1 elf_ex.e_phentsize * elf_ex.e_phnum); 120284778508Sblueswir1 } 120384778508Sblueswir1 120484778508Sblueswir1 if (retval < 0) { 120584778508Sblueswir1 perror("load_elf_binary"); 120684778508Sblueswir1 exit(-1); 120784778508Sblueswir1 free (elf_phdata); 120884778508Sblueswir1 return -errno; 120984778508Sblueswir1 } 121084778508Sblueswir1 121184778508Sblueswir1 #ifdef BSWAP_NEEDED 121284778508Sblueswir1 elf_ppnt = elf_phdata; 121384778508Sblueswir1 for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) { 121484778508Sblueswir1 bswap_phdr(elf_ppnt); 121584778508Sblueswir1 } 121684778508Sblueswir1 #endif 121784778508Sblueswir1 elf_ppnt = elf_phdata; 121884778508Sblueswir1 121984778508Sblueswir1 elf_bss = 0; 122084778508Sblueswir1 elf_brk = 0; 122184778508Sblueswir1 122284778508Sblueswir1 122384778508Sblueswir1 elf_interpreter = NULL; 122484778508Sblueswir1 start_code = ~((abi_ulong)0UL); 122584778508Sblueswir1 end_code = 0; 122684778508Sblueswir1 start_data = 0; 122784778508Sblueswir1 end_data = 0; 122884778508Sblueswir1 interp_ex.a_info = 0; 122984778508Sblueswir1 123084778508Sblueswir1 for(i=0;i < elf_ex.e_phnum; i++) { 123184778508Sblueswir1 if (elf_ppnt->p_type == PT_INTERP) { 123284778508Sblueswir1 if ( elf_interpreter != NULL ) 123384778508Sblueswir1 { 123484778508Sblueswir1 free (elf_phdata); 123584778508Sblueswir1 free(elf_interpreter); 123684778508Sblueswir1 close(bprm->fd); 123784778508Sblueswir1 return -EINVAL; 123884778508Sblueswir1 } 123984778508Sblueswir1 124084778508Sblueswir1 /* This is the program interpreter used for 124184778508Sblueswir1 * shared libraries - for now assume that this 124284778508Sblueswir1 * is an a.out format binary 124384778508Sblueswir1 */ 124484778508Sblueswir1 124584778508Sblueswir1 elf_interpreter = (char *)malloc(elf_ppnt->p_filesz); 124684778508Sblueswir1 124784778508Sblueswir1 if (elf_interpreter == NULL) { 124884778508Sblueswir1 free (elf_phdata); 124984778508Sblueswir1 close(bprm->fd); 125084778508Sblueswir1 return -ENOMEM; 125184778508Sblueswir1 } 125284778508Sblueswir1 125384778508Sblueswir1 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); 125484778508Sblueswir1 if(retval >= 0) { 125584778508Sblueswir1 retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz); 125684778508Sblueswir1 } 125784778508Sblueswir1 if(retval < 0) { 125884778508Sblueswir1 perror("load_elf_binary2"); 125984778508Sblueswir1 exit(-1); 126084778508Sblueswir1 } 126184778508Sblueswir1 126284778508Sblueswir1 /* If the program interpreter is one of these two, 126384778508Sblueswir1 then assume an iBCS2 image. Otherwise assume 126484778508Sblueswir1 a native linux image. */ 126584778508Sblueswir1 126684778508Sblueswir1 /* JRP - Need to add X86 lib dir stuff here... */ 126784778508Sblueswir1 126884778508Sblueswir1 if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 || 126984778508Sblueswir1 strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) { 127084778508Sblueswir1 ibcs2_interpreter = 1; 127184778508Sblueswir1 } 127284778508Sblueswir1 127384778508Sblueswir1 #if 0 1274b7d43d03SPaul Bolle printf("Using ELF interpreter %s\n", path(elf_interpreter)); 127584778508Sblueswir1 #endif 127684778508Sblueswir1 if (retval >= 0) { 127784778508Sblueswir1 retval = open(path(elf_interpreter), O_RDONLY); 127884778508Sblueswir1 if(retval >= 0) { 127984778508Sblueswir1 interpreter_fd = retval; 128084778508Sblueswir1 } 128184778508Sblueswir1 else { 128284778508Sblueswir1 perror(elf_interpreter); 128384778508Sblueswir1 exit(-1); 128484778508Sblueswir1 /* retval = -errno; */ 128584778508Sblueswir1 } 128684778508Sblueswir1 } 128784778508Sblueswir1 128884778508Sblueswir1 if (retval >= 0) { 128984778508Sblueswir1 retval = lseek(interpreter_fd, 0, SEEK_SET); 129084778508Sblueswir1 if(retval >= 0) { 129184778508Sblueswir1 retval = read(interpreter_fd,bprm->buf,128); 129284778508Sblueswir1 } 129384778508Sblueswir1 } 129484778508Sblueswir1 if (retval >= 0) { 129584778508Sblueswir1 interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */ 129684778508Sblueswir1 interp_elf_ex = *((struct elfhdr *) bprm->buf); /* elf exec-header */ 129784778508Sblueswir1 } 129884778508Sblueswir1 if (retval < 0) { 129984778508Sblueswir1 perror("load_elf_binary3"); 130084778508Sblueswir1 exit(-1); 130184778508Sblueswir1 free (elf_phdata); 130284778508Sblueswir1 free(elf_interpreter); 130384778508Sblueswir1 close(bprm->fd); 130484778508Sblueswir1 return retval; 130584778508Sblueswir1 } 130684778508Sblueswir1 } 130784778508Sblueswir1 elf_ppnt++; 130884778508Sblueswir1 } 130984778508Sblueswir1 131084778508Sblueswir1 /* Some simple consistency checks for the interpreter */ 131184778508Sblueswir1 if (elf_interpreter){ 131284778508Sblueswir1 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT; 131384778508Sblueswir1 131484778508Sblueswir1 /* Now figure out which format our binary is */ 131584778508Sblueswir1 if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) && 131684778508Sblueswir1 (N_MAGIC(interp_ex) != QMAGIC)) { 131784778508Sblueswir1 interpreter_type = INTERPRETER_ELF; 131884778508Sblueswir1 } 131984778508Sblueswir1 132084778508Sblueswir1 if (interp_elf_ex.e_ident[0] != 0x7f || 1321fff2a02fSChristoph Egger strncmp((char *)&interp_elf_ex.e_ident[1], "ELF",3) != 0) { 132284778508Sblueswir1 interpreter_type &= ~INTERPRETER_ELF; 132384778508Sblueswir1 } 132484778508Sblueswir1 132584778508Sblueswir1 if (!interpreter_type) { 132684778508Sblueswir1 free(elf_interpreter); 132784778508Sblueswir1 free(elf_phdata); 132884778508Sblueswir1 close(bprm->fd); 132984778508Sblueswir1 return -ELIBBAD; 133084778508Sblueswir1 } 133184778508Sblueswir1 } 133284778508Sblueswir1 133384778508Sblueswir1 /* OK, we are done with that, now set up the arg stuff, 133484778508Sblueswir1 and then start this sucker up */ 133584778508Sblueswir1 133684778508Sblueswir1 { 133784778508Sblueswir1 char * passed_p; 133884778508Sblueswir1 133984778508Sblueswir1 if (interpreter_type == INTERPRETER_AOUT) { 134084778508Sblueswir1 snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd); 134184778508Sblueswir1 passed_p = passed_fileno; 134284778508Sblueswir1 134384778508Sblueswir1 if (elf_interpreter) { 134484778508Sblueswir1 bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p); 134584778508Sblueswir1 bprm->argc++; 134684778508Sblueswir1 } 134784778508Sblueswir1 } 134884778508Sblueswir1 if (!bprm->p) { 134984778508Sblueswir1 free(elf_interpreter); 135084778508Sblueswir1 free (elf_phdata); 135184778508Sblueswir1 close(bprm->fd); 135284778508Sblueswir1 return -E2BIG; 135384778508Sblueswir1 } 135484778508Sblueswir1 } 135584778508Sblueswir1 135684778508Sblueswir1 /* OK, This is the point of no return */ 135784778508Sblueswir1 info->end_data = 0; 135884778508Sblueswir1 info->end_code = 0; 135984778508Sblueswir1 info->start_mmap = (abi_ulong)ELF_START_MMAP; 136084778508Sblueswir1 info->mmap = 0; 136184778508Sblueswir1 elf_entry = (abi_ulong) elf_ex.e_entry; 136284778508Sblueswir1 13632fa5d9baSBlue Swirl /* 13642fa5d9baSBlue Swirl * In case where user has not explicitly set the guest_base, we 13652fa5d9baSBlue Swirl * probe here that should we set it automatically. 13662fa5d9baSBlue Swirl */ 13672fa5d9baSBlue Swirl if (!have_guest_base) { 13682fa5d9baSBlue Swirl /* 13692fa5d9baSBlue Swirl * Go through ELF program header table and find out whether 13702fa5d9baSBlue Swirl * any of the segments drop below our current mmap_min_addr and 13712fa5d9baSBlue Swirl * in that case set guest_base to corresponding address. 13722fa5d9baSBlue Swirl */ 13732fa5d9baSBlue Swirl for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; 13742fa5d9baSBlue Swirl i++, elf_ppnt++) { 13752fa5d9baSBlue Swirl if (elf_ppnt->p_type != PT_LOAD) 13762fa5d9baSBlue Swirl continue; 13772fa5d9baSBlue Swirl if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) { 13782fa5d9baSBlue Swirl guest_base = HOST_PAGE_ALIGN(mmap_min_addr); 13792fa5d9baSBlue Swirl break; 13802fa5d9baSBlue Swirl } 13812fa5d9baSBlue Swirl } 13822fa5d9baSBlue Swirl } 13832fa5d9baSBlue Swirl 138484778508Sblueswir1 /* Do this so that we can load the interpreter, if need be. We will 138584778508Sblueswir1 change some of these later */ 138684778508Sblueswir1 info->rss = 0; 138784778508Sblueswir1 bprm->p = setup_arg_pages(bprm->p, bprm, info); 138884778508Sblueswir1 info->start_stack = bprm->p; 138984778508Sblueswir1 139084778508Sblueswir1 /* Now we do a little grungy work by mmaping the ELF image into 139184778508Sblueswir1 * the correct location in memory. At this point, we assume that 139284778508Sblueswir1 * the image should be loaded at fixed address, not at a variable 139384778508Sblueswir1 * address. 139484778508Sblueswir1 */ 139584778508Sblueswir1 139684778508Sblueswir1 for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { 139784778508Sblueswir1 int elf_prot = 0; 139884778508Sblueswir1 int elf_flags = 0; 139984778508Sblueswir1 abi_ulong error; 140084778508Sblueswir1 140184778508Sblueswir1 if (elf_ppnt->p_type != PT_LOAD) 140284778508Sblueswir1 continue; 140384778508Sblueswir1 140484778508Sblueswir1 if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; 140584778508Sblueswir1 if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; 140684778508Sblueswir1 if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; 140784778508Sblueswir1 elf_flags = MAP_PRIVATE | MAP_DENYWRITE; 140884778508Sblueswir1 if (elf_ex.e_type == ET_EXEC || load_addr_set) { 140984778508Sblueswir1 elf_flags |= MAP_FIXED; 141084778508Sblueswir1 } else if (elf_ex.e_type == ET_DYN) { 141184778508Sblueswir1 /* Try and get dynamic programs out of the way of the default mmap 141284778508Sblueswir1 base, as well as whatever program they might try to exec. This 141384778508Sblueswir1 is because the brk will follow the loader, and is not movable. */ 141484778508Sblueswir1 /* NOTE: for qemu, we do a big mmap to get enough space 141584778508Sblueswir1 without hardcoding any address */ 141684778508Sblueswir1 error = target_mmap(0, ET_DYN_MAP_SIZE, 141784778508Sblueswir1 PROT_NONE, MAP_PRIVATE | MAP_ANON, 141884778508Sblueswir1 -1, 0); 141984778508Sblueswir1 if (error == -1) { 142084778508Sblueswir1 perror("mmap"); 142184778508Sblueswir1 exit(-1); 142284778508Sblueswir1 } 142384778508Sblueswir1 load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr); 142484778508Sblueswir1 } 142584778508Sblueswir1 142684778508Sblueswir1 error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr), 142784778508Sblueswir1 (elf_ppnt->p_filesz + 142884778508Sblueswir1 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)), 142984778508Sblueswir1 elf_prot, 143084778508Sblueswir1 (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE), 143184778508Sblueswir1 bprm->fd, 143284778508Sblueswir1 (elf_ppnt->p_offset - 143384778508Sblueswir1 TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr))); 143484778508Sblueswir1 if (error == -1) { 143584778508Sblueswir1 perror("mmap"); 143684778508Sblueswir1 exit(-1); 143784778508Sblueswir1 } 143884778508Sblueswir1 143984778508Sblueswir1 #ifdef LOW_ELF_STACK 144084778508Sblueswir1 if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack) 144184778508Sblueswir1 elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr); 144284778508Sblueswir1 #endif 144384778508Sblueswir1 144484778508Sblueswir1 if (!load_addr_set) { 144584778508Sblueswir1 load_addr_set = 1; 144684778508Sblueswir1 load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset; 144784778508Sblueswir1 if (elf_ex.e_type == ET_DYN) { 144884778508Sblueswir1 load_bias += error - 144984778508Sblueswir1 TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr); 145084778508Sblueswir1 load_addr += load_bias; 145184778508Sblueswir1 reloc_func_desc = load_bias; 145284778508Sblueswir1 } 145384778508Sblueswir1 } 145484778508Sblueswir1 k = elf_ppnt->p_vaddr; 145584778508Sblueswir1 if (k < start_code) 145684778508Sblueswir1 start_code = k; 145784778508Sblueswir1 if (start_data < k) 145884778508Sblueswir1 start_data = k; 145984778508Sblueswir1 k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz; 146084778508Sblueswir1 if (k > elf_bss) 146184778508Sblueswir1 elf_bss = k; 146284778508Sblueswir1 if ((elf_ppnt->p_flags & PF_X) && end_code < k) 146384778508Sblueswir1 end_code = k; 146484778508Sblueswir1 if (end_data < k) 146584778508Sblueswir1 end_data = k; 146684778508Sblueswir1 k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz; 146784778508Sblueswir1 if (k > elf_brk) elf_brk = k; 146884778508Sblueswir1 } 146984778508Sblueswir1 147084778508Sblueswir1 elf_entry += load_bias; 147184778508Sblueswir1 elf_bss += load_bias; 147284778508Sblueswir1 elf_brk += load_bias; 147384778508Sblueswir1 start_code += load_bias; 147484778508Sblueswir1 end_code += load_bias; 147584778508Sblueswir1 start_data += load_bias; 147684778508Sblueswir1 end_data += load_bias; 147784778508Sblueswir1 147884778508Sblueswir1 if (elf_interpreter) { 147984778508Sblueswir1 if (interpreter_type & 1) { 148084778508Sblueswir1 elf_entry = load_aout_interp(&interp_ex, interpreter_fd); 148184778508Sblueswir1 } 148284778508Sblueswir1 else if (interpreter_type & 2) { 148384778508Sblueswir1 elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd, 148484778508Sblueswir1 &interp_load_addr); 148584778508Sblueswir1 } 148684778508Sblueswir1 reloc_func_desc = interp_load_addr; 148784778508Sblueswir1 148884778508Sblueswir1 close(interpreter_fd); 148984778508Sblueswir1 free(elf_interpreter); 149084778508Sblueswir1 149184778508Sblueswir1 if (elf_entry == ~((abi_ulong)0UL)) { 149284778508Sblueswir1 printf("Unable to load interpreter\n"); 149384778508Sblueswir1 free(elf_phdata); 149484778508Sblueswir1 exit(-1); 149584778508Sblueswir1 return 0; 149684778508Sblueswir1 } 149784778508Sblueswir1 } 149884778508Sblueswir1 149984778508Sblueswir1 free(elf_phdata); 150084778508Sblueswir1 150193fcfe39Saliguori if (qemu_log_enabled()) 150284778508Sblueswir1 load_symbols(&elf_ex, bprm->fd); 150384778508Sblueswir1 150484778508Sblueswir1 if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd); 150584778508Sblueswir1 info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX); 150684778508Sblueswir1 150784778508Sblueswir1 #ifdef LOW_ELF_STACK 150884778508Sblueswir1 info->start_stack = bprm->p = elf_stack - 4; 150984778508Sblueswir1 #endif 151084778508Sblueswir1 bprm->p = create_elf_tables(bprm->p, 151184778508Sblueswir1 bprm->argc, 151284778508Sblueswir1 bprm->envc, 151384778508Sblueswir1 &elf_ex, 151484778508Sblueswir1 load_addr, load_bias, 151584778508Sblueswir1 interp_load_addr, 151684778508Sblueswir1 (interpreter_type == INTERPRETER_AOUT ? 0 : 1), 151784778508Sblueswir1 info); 151884778508Sblueswir1 info->load_addr = reloc_func_desc; 151984778508Sblueswir1 info->start_brk = info->brk = elf_brk; 152084778508Sblueswir1 info->end_code = end_code; 152184778508Sblueswir1 info->start_code = start_code; 152284778508Sblueswir1 info->start_data = start_data; 152384778508Sblueswir1 info->end_data = end_data; 152484778508Sblueswir1 info->start_stack = bprm->p; 152584778508Sblueswir1 152684778508Sblueswir1 /* Calling set_brk effectively mmaps the pages that we need for the bss and break 152784778508Sblueswir1 sections */ 152884778508Sblueswir1 set_brk(elf_bss, elf_brk); 152984778508Sblueswir1 153084778508Sblueswir1 padzero(elf_bss, elf_brk); 153184778508Sblueswir1 153284778508Sblueswir1 #if 0 153384778508Sblueswir1 printf("(start_brk) %x\n" , info->start_brk); 153484778508Sblueswir1 printf("(end_code) %x\n" , info->end_code); 153584778508Sblueswir1 printf("(start_code) %x\n" , info->start_code); 153684778508Sblueswir1 printf("(end_data) %x\n" , info->end_data); 153784778508Sblueswir1 printf("(start_stack) %x\n" , info->start_stack); 153884778508Sblueswir1 printf("(brk) %x\n" , info->brk); 153984778508Sblueswir1 #endif 154084778508Sblueswir1 154184778508Sblueswir1 if ( info->personality == PER_SVR4 ) 154284778508Sblueswir1 { 154384778508Sblueswir1 /* Why this, you ask??? Well SVr4 maps page 0 as read-only, 154484778508Sblueswir1 and some applications "depend" upon this behavior. 154584778508Sblueswir1 Since we do not have the power to recompile these, we 154684778508Sblueswir1 emulate the SVr4 behavior. Sigh. */ 154771025956SPeter Maydell target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, 154884778508Sblueswir1 MAP_FIXED | MAP_PRIVATE, -1, 0); 154984778508Sblueswir1 } 155084778508Sblueswir1 155184778508Sblueswir1 info->entry = elf_entry; 155284778508Sblueswir1 155384778508Sblueswir1 return 0; 155484778508Sblueswir1 } 155584778508Sblueswir1 155684778508Sblueswir1 static int load_aout_interp(void * exptr, int interp_fd) 155784778508Sblueswir1 { 155884778508Sblueswir1 printf("a.out interpreter not yet supported\n"); 155984778508Sblueswir1 return(0); 156084778508Sblueswir1 } 156184778508Sblueswir1 156284778508Sblueswir1 void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) 156384778508Sblueswir1 { 156484778508Sblueswir1 init_thread(regs, infop); 156584778508Sblueswir1 } 1566