aboutsummaryrefslogtreecommitdiffstats
path: root/linux-user/elfload.c
diff options
context:
space:
mode:
authorblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-09 16:34:29 +0000
committerblueswir1 <blueswir1@c046a42c-6fe2-441c-8c8c-71466251a162>2007-10-09 16:34:29 +0000
commitcb33da57aaa368d575825d80d734374e3ef8c472 (patch)
tree83f712d878ab36a28f997b9e9adafa083f8ad000 /linux-user/elfload.c
parentbf367b54092014edd36a64195697ea3959fba5cf (diff)
Support for executing 32 bit SPARC32PLUS files for Sparc64 user emulator
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3378 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'linux-user/elfload.c')
-rw-r--r--linux-user/elfload.c97
1 files changed, 74 insertions, 23 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 1db6bab5e..fbe7ddd84 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;