diff options
Diffstat (limited to 'linux-user/elfload.c')
-rw-r--r-- | linux-user/elfload.c | 97 |
1 files changed, 74 insertions, 23 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 1db6bab5e8..fbe7ddd848 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -12,6 +12,66 @@ #include "qemu.h" #include "disas.h" +/* from personality.h */ + +/* + * Flags for bug emulation. + * + * These occupy the top three bytes. + */ +enum { + ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */ + FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors + * (signal handling) + */ + MMAP_PAGE_ZERO = 0x0100000, + ADDR_COMPAT_LAYOUT = 0x0200000, + READ_IMPLIES_EXEC = 0x0400000, + ADDR_LIMIT_32BIT = 0x0800000, + SHORT_INODE = 0x1000000, + WHOLE_SECONDS = 0x2000000, + STICKY_TIMEOUTS = 0x4000000, + ADDR_LIMIT_3GB = 0x8000000, +}; + +/* + * Personality types. + * + * These go in the low byte. Avoid using the top bit, it will + * conflict with error returns. + */ +enum { + PER_LINUX = 0x0000, + PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, + PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS, + PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, + PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, + PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | + WHOLE_SECONDS | SHORT_INODE, + PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, + PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, + PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, + PER_BSD = 0x0006, + PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, + PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, + PER_LINUX32 = 0x0008, + PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB, + PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */ + PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */ + PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */ + PER_RISCOS = 0x000c, + PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, + PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, + PER_OSF4 = 0x000f, /* OSF/1 v4 */ + PER_HPUX = 0x0010, + PER_MASK = 0x00ff, +}; + +/* + * Return the base personality without flags. + */ +#define personality(pers) (pers & PER_MASK) + /* this flag is uneffective under linux too, should be deleted */ #ifndef MAP_DENYWRITE #define MAP_DENYWRITE 0 @@ -154,7 +214,7 @@ enum #define ELF_START_MMAP 0x80000000 -#define elf_check_arch(x) ( (x) == EM_SPARCV9 ) +#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) #define ELF_CLASS ELFCLASS64 #define ELF_DATA ELFDATA2MSB @@ -168,7 +228,10 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i regs->pc = infop->entry; regs->npc = regs->pc + 4; regs->y = 0; - regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; + if (personality(infop->personality) == PER_LINUX32) + regs->u_regs[14] = infop->start_stack - 16 * 4; + else + regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; } #else @@ -412,6 +475,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i #define ELF_HWCAP 0 #endif +#ifdef OVERRIDE_ELF_CLASS +#undef ELF_CLASS +#define ELF_CLASS OVERRIDE_ELF_CLASS +#undef bswaptls +#define bswaptls(ptr) bswap32s(ptr) +#endif + #include "elf.h" struct exec @@ -439,25 +509,6 @@ struct exec /* max code+data+bss+brk space allocated to ET_DYN executables */ #define ET_DYN_MAP_SIZE (128 * 1024 * 1024) -/* from personality.h */ - -/* Flags for bug emulation. These occupy the top three bytes. */ -#define STICKY_TIMEOUTS 0x4000000 -#define WHOLE_SECONDS 0x2000000 - -/* Personality types. These go in the low byte. Avoid using the top bit, - * it will conflict with error returns. - */ -#define PER_MASK (0x00ff) -#define PER_LINUX (0x0000) -#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS) -#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS) -#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS) -#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS) -#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS) -#define PER_BSD (0x0006) -#define PER_XENIX (0x0007 | STICKY_TIMEOUTS) - /* Necessary parameters */ #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) @@ -587,8 +638,8 @@ static target_ulong copy_elf_strings(int argc,char ** argv, void **page, return p; } -target_ulong setup_arg_pages(target_ulong p, struct linux_binprm * bprm, - struct image_info * info) +static target_ulong setup_arg_pages(target_ulong p, struct linux_binprm *bprm, + struct image_info *info) { target_ulong stack_base, size, error; int i; |