aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog1
-rw-r--r--Makefile.target4
-rwxr-xr-xconfigure7
-rw-r--r--linux-user/elfload.c97
-rwxr-xr-xlinux-user/elfload32.c30
-rw-r--r--linux-user/linuxload.c4
-rw-r--r--linux-user/main.c1
-rw-r--r--linux-user/qemu.h5
-rw-r--r--linux-user/sparc64/syscall_nr.h48
9 files changed, 149 insertions, 48 deletions
diff --git a/Changelog b/Changelog
index 26fc301f2e..4c7a1215c8 100644
--- a/Changelog
+++ b/Changelog
@@ -13,6 +13,7 @@
- Read-only support for Parallels disk images (Alex Beregszaszi)
- SVM (x86 virtualization) support (Alexander Graf)
- CRIS emulation (Edgar E. Iglesias)
+ - SPARC32PLUS execution support (Blue Swirl)
version 0.9.0:
diff --git a/Makefile.target b/Makefile.target
index fe0cf372a2..8ebe3c3c75 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -254,6 +254,10 @@ LIBS+= $(AIOLIBS)
ifdef TARGET_HAS_BFLT
OBJS+= flatload.o
endif
+ifdef TARGET_HAS_ELFLOAD32
+OBJS+= elfload32.o
+elfload32.o: elfload.c
+endif
ifeq ($(TARGET_ARCH), i386)
OBJS+= vm86.o
diff --git a/configure b/configure
index a8dbf85114..8e705e1b04 100755
--- a/configure
+++ b/configure
@@ -999,6 +999,7 @@ echo "include ../config-host.mak" >> $config_mak
echo "#include \"../config-host.h\"" >> $config_h
bflt="no"
+elfload32="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
@@ -1023,6 +1024,7 @@ elif test "$target_cpu" = "sparc64" ; then
echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
echo "#define TARGET_SPARC 1" >> $config_h
echo "#define TARGET_SPARC64 1" >> $config_h
+ elfload32="yes"
elif test "$target_cpu" = "ppc" ; then
echo "TARGET_ARCH=ppc" >> $config_mak
echo "#define TARGET_ARCH \"ppc\"" >> $config_h
@@ -1112,6 +1114,11 @@ if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
echo "TARGET_HAS_BFLT=yes" >> $config_mak
echo "#define TARGET_HAS_BFLT 1" >> $config_h
fi
+# 32 bit ELF loader in addition to native 64 bit loader?
+if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
+ echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak
+ echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h
+fi
# sdl defines
if test "$target_user_only" = "no"; then
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;
diff --git a/linux-user/elfload32.c b/linux-user/elfload32.c
new file mode 100755
index 0000000000..d1a15ff937
--- /dev/null
+++ b/linux-user/elfload32.c
@@ -0,0 +1,30 @@
+#define OVERRIDE_ELF_CLASS ELFCLASS32
+#define load_elf_binary load_elf_binary32
+#define do_init_thread do_init_thread32
+
+#include "elfload.c"
+
+#undef load_elf_binary
+#undef do_init_thread
+
+int load_elf_binary(struct linux_binprm *bprm, struct target_pt_regs *regs,
+ struct image_info *info);
+
+int load_elf_binary_multi(struct linux_binprm *bprm,
+ struct target_pt_regs *regs,
+ struct image_info *info)
+{
+ struct elfhdr *elf_ex;
+ int retval;
+
+ elf_ex = (struct elfhdr *) bprm->buf; /* exec-header */
+ if (elf_ex->e_ident[EI_CLASS] == ELFCLASS64) {
+ retval = load_elf_binary(bprm, regs, info);
+ } else {
+ retval = load_elf_binary32(bprm, regs, info);
+ if (personality(info->personality) == PER_LINUX)
+ info->personality = PER_LINUX32;
+ }
+
+ return retval;
+}
diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
index 0efbb76ce4..51f29531ca 100644
--- a/linux-user/linuxload.c
+++ b/linux-user/linuxload.c
@@ -169,7 +169,11 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
&& bprm.buf[1] == 'E'
&& bprm.buf[2] == 'L'
&& bprm.buf[3] == 'F') {
+#ifndef TARGET_HAS_ELFLOAD32
retval = load_elf_binary(&bprm,regs,infop);
+#else
+ retval = load_elf_binary_multi(&bprm, regs, infop);
+#endif
#if defined(TARGET_HAS_BFLT)
} else if (bprm.buf[0] == 'b'
&& bprm.buf[1] == 'F'
diff --git a/linux-user/main.c b/linux-user/main.c
index b4bc93da5f..7de7ff5a71 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -564,6 +564,7 @@ void cpu_loop (CPUSPARCState *env)
case 0x88:
case 0x90:
#else
+ case 0x110:
case 0x16d:
#endif
ret = do_syscall (env, env->gregs[1],
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 2c48e92311..8a7cb2479a 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -124,6 +124,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info);
int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
struct image_info * info);
+#ifdef TARGET_HAS_ELFLOAD32
+int load_elf_binary_multi(struct linux_binprm *bprm,
+ struct target_pt_regs *regs,
+ struct image_info *info);
+#endif
void memcpy_to_target(target_ulong dest, const void *src,
unsigned long len);
diff --git a/linux-user/sparc64/syscall_nr.h b/linux-user/sparc64/syscall_nr.h
index 53102945a0..70bee8080c 100644
--- a/linux-user/sparc64/syscall_nr.h
+++ b/linux-user/sparc64/syscall_nr.h
@@ -29,11 +29,11 @@
#define TARGET_NR_sigaltstack 28 /* Common */
#define TARGET_NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */
#define TARGET_NR_utime 30 /* Implemented via utimes() under SunOS */
-/* #define TARGET_NR_lchown32 31 Linux sparc32 specific */
-/* #define TARGET_NR_fchown32 32 Linux sparc32 specific */
+#define TARGET_NR_lchown32 31 /* Linux sparc32 specific */
+#define TARGET_NR_fchown32 32 /* Linux sparc32 specific */
#define TARGET_NR_access 33 /* Common */
#define TARGET_NR_nice 34 /* Implemented via get/setpriority() in SunOS */
-/* #define TARGET_NR_chown32 35 Linux sparc32 specific */
+#define TARGET_NR_chown32 35 /* Linux sparc32 specific */
#define TARGET_NR_sync 36 /* Common */
#define TARGET_NR_kill 37 /* Common */
#define TARGET_NR_stat 38 /* Common */
@@ -42,7 +42,7 @@
#define TARGET_NR_dup 41 /* Common */
#define TARGET_NR_pipe 42 /* Common */
#define TARGET_NR_times 43 /* Implemented via getrusage() in SunOS */
-/* #define TARGET_NR_getuid32 44 Linux sparc32 specific */
+#define TARGET_NR_getuid32 44 /* Linux sparc32 specific */
#define TARGET_NR_umount2 45 /* Linux Specific */
#define TARGET_NR_setgid 46 /* Implemented via setregid() in SunOS */
#define TARGET_NR_getgid 47 /* Common */
@@ -51,48 +51,48 @@
#define TARGET_NR_getegid 50 /* SunOS calls getgid() */
#define TARGET_NR_acct 51 /* Common */
#define TARGET_NR_memory_ordering 52 /* Linux Specific */
-/* #define TARGET_NR_getgid32 53 Linux sparc32 specific */
+#define TARGET_NR_getgid32 53 /* Linux sparc32 specific */
#define TARGET_NR_ioctl 54 /* Common */
#define TARGET_NR_reboot 55 /* Common */
-/* #define TARGET_NR_mmap2 56 Linux sparc32 Specific */
+#define TARGET_NR_mmap2 56 /* Linux sparc32 Specific */
#define TARGET_NR_symlink 57 /* Common */
#define TARGET_NR_readlink 58 /* Common */
#define TARGET_NR_execve 59 /* Common */
#define TARGET_NR_umask 60 /* Common */
#define TARGET_NR_chroot 61 /* Common */
#define TARGET_NR_fstat 62 /* Common */
-/* #define TARGET_NR_fstat64 63 Linux sparc32 Specific */
+#define TARGET_NR_fstat64 63 /* Linux sparc32 Specific */
#define TARGET_NR_getpagesize 64 /* Common */
#define TARGET_NR_msync 65 /* Common in newer 1.3.x revs... */
#define TARGET_NR_vfork 66 /* Common */
#define TARGET_NR_pread64 67 /* Linux Specific */
#define TARGET_NR_pwrite64 68 /* Linux Specific */
-/* #define TARGET_NR_geteuid32 69 Linux sparc32, sbrk under SunOS */
-/* #define TARGET_NR_getegid32 70 Linux sparc32, sstk under SunOS */
+#define TARGET_NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */
+#define TARGET_NR_getegid32 70 /* Linux sparc32, sstk under SunOS */
#define TARGET_NR_mmap 71 /* Common */
-/* #define TARGET_NR_setreuid32 72 Linux sparc32, vadvise under SunOS */
+#define TARGET_NR_setreuid32 72 /* Linux sparc32, vadvise under SunOS */
#define TARGET_NR_munmap 73 /* Common */
#define TARGET_NR_mprotect 74 /* Common */
#define TARGET_NR_madvise 75 /* Common */
#define TARGET_NR_vhangup 76 /* Common */
-/* #define TARGET_NR_truncate64 77 Linux sparc32 Specific */
+#define TARGET_NR_truncate64 77 /* Linux sparc32 Specific */
#define TARGET_NR_mincore 78 /* Common */
#define TARGET_NR_getgroups 79 /* Common */
#define TARGET_NR_setgroups 80 /* Common */
#define TARGET_NR_getpgrp 81 /* Common */
-/* #define TARGET_NR_setgroups32 82 Linux sparc32, setpgrp under SunOS */
+#define TARGET_NR_setgroups32 82 /* Linux sparc32, setpgrp under SunOS */
#define TARGET_NR_setitimer 83 /* Common */
-/* #define TARGET_NR_ftruncate64 84 Linux sparc32 Specific */
+#define TARGET_NR_ftruncate64 84 /* Linux sparc32 Specific */
#define TARGET_NR_swapon 85 /* Common */
#define TARGET_NR_getitimer 86 /* Common */
-/* #define TARGET_NR_setuid32 87 Linux sparc32, gethostname under SunOS */
+#define TARGET_NR_setuid32 87 /* Linux sparc32, gethostname under SunOS */
#define TARGET_NR_sethostname 88 /* Common */
-/* #define TARGET_NR_setgid32 89 Linux sparc32, getdtablesize under SunOS */
+#define TARGET_NR_setgid32 89 /* Linux sparc32, getdtablesize under SunOS */
#define TARGET_NR_dup2 90 /* Common */
-/* #define TARGET_NR_setfsuid32 91 Linux sparc32, getdopt under SunOS */
+#define TARGET_NR_setfsuid32 91 /* Linux sparc32, getdopt under SunOS */
#define TARGET_NR_fcntl 92 /* Common */
#define TARGET_NR_select 93 /* Common */
-/* #define TARGET_NR_setfsgid32 94 Linux sparc32, setdopt under SunOS */
+#define TARGET_NR_setfsgid32 94 /* Linux sparc32, setdopt under SunOS */
#define TARGET_NR_fsync 95 /* Common */
#define TARGET_NR_setpriority 96 /* Common */
#define TARGET_NR_socket 97 /* Common */
@@ -110,10 +110,10 @@
#define TARGET_NR_getresuid 109 /* Linux Specific, sigblock under SunOS */
#define TARGET_NR_setresgid 110 /* Linux Specific, sigsetmask under SunOS */
#define TARGET_NR_getresgid 111 /* Linux Specific, sigpause under SunOS */
-/* #define TARGET_NR_setregid32 75 Linux sparc32, sigstack under SunOS */
+/* #define TARGET_NR_setregid32 75 Linux sparc32, sigstack under SunOS */
#define TARGET_NR_recvmsg 113 /* Common */
#define TARGET_NR_sendmsg 114 /* Common */
-/* #define TARGET_NR_getgroups32 115 Linux sparc32, vtrace under SunOS */
+#define TARGET_NR_getgroups32 115 /* Linux sparc32, vtrace under SunOS */
#define TARGET_NR_gettimeofday 116 /* Common */
#define TARGET_NR_getrusage 117 /* Common */
#define TARGET_NR_getsockopt 118 /* Common */
@@ -130,14 +130,14 @@
#define TARGET_NR_truncate 129 /* Common */
#define TARGET_NR_ftruncate 130 /* Common */
#define TARGET_NR_flock 131 /* Common */
-/* #define TARGET_NR_lstat64 132 Linux sparc32 Specific */
+#define TARGET_NR_lstat64 132 /* Linux sparc32 Specific */
#define TARGET_NR_sendto 133 /* Common */
#define TARGET_NR_shutdown 134 /* Common */
#define TARGET_NR_socketpair 135 /* Common */
#define TARGET_NR_mkdir 136 /* Common */
#define TARGET_NR_rmdir 137 /* Common */
#define TARGET_NR_utimes 138 /* SunOS Specific */
-/* #define TARGET_NR_stat64 139 Linux sparc32 Specific */
+#define TARGET_NR_stat64 139 /* Linux sparc32 Specific */
#define TARGET_NR_sendfile64 140 /* adjtime under SunOS */
#define TARGET_NR_getpeername 141 /* Common */
#define TARGET_NR_futex 142 /* gethostid under SunOS */
@@ -153,7 +153,7 @@
/* #define TARGET_NR_putmsg 152 SunOS Specific */
#define TARGET_NR_poll 153 /* Common */
#define TARGET_NR_getdents64 154 /* Linux specific */
-/* #define TARGET_NR_fcntl64 155 Linux sparc32 Specific */
+#define TARGET_NR_fcntl64 155 /* Linux sparc32 Specific */
/* #define TARGET_NR_getdirentries 156 SunOS Specific */
#define TARGET_NR_statfs 157 /* Common */
#define TARGET_NR_fstatfs 158 /* Common */
@@ -229,9 +229,7 @@
#define TARGET_NR_setfsuid 228 /* Linux Specific */
#define TARGET_NR_setfsgid 229 /* Linux Specific */
#define TARGET_NR__newselect 230 /* Linux Specific */
-#ifdef __KERNEL__
-#define TARGET_NR_time 231 /* Linux sparc32 */
-#endif
+#define TARGET_NR_time 231 /* Linux sparc32 */
/* #define TARGET_NR_oldstat 232 Linux Specific */
#define TARGET_NR_stime 233 /* Linux Specific */
#define TARGET_NR_statfs64 234 /* Linux Specific */