Commit cb33da57aaa368d575825d80d734374e3ef8c472

Authored by blueswir1
1 parent bf367b54

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
Changelog
... ... @@ -13,6 +13,7 @@
13 13 - Read-only support for Parallels disk images (Alex Beregszaszi)
14 14 - SVM (x86 virtualization) support (Alexander Graf)
15 15 - CRIS emulation (Edgar E. Iglesias)
  16 + - SPARC32PLUS execution support (Blue Swirl)
16 17  
17 18 version 0.9.0:
18 19  
... ...
Makefile.target
... ... @@ -254,6 +254,10 @@ LIBS+= $(AIOLIBS)
254 254 ifdef TARGET_HAS_BFLT
255 255 OBJS+= flatload.o
256 256 endif
  257 +ifdef TARGET_HAS_ELFLOAD32
  258 +OBJS+= elfload32.o
  259 +elfload32.o: elfload.c
  260 +endif
257 261  
258 262 ifeq ($(TARGET_ARCH), i386)
259 263 OBJS+= vm86.o
... ...
configure
... ... @@ -999,6 +999,7 @@ echo "include ../config-host.mak" >> $config_mak
999 999 echo "#include \"../config-host.h\"" >> $config_h
1000 1000  
1001 1001 bflt="no"
  1002 +elfload32="no"
1002 1003 interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
1003 1004 echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
1004 1005  
... ... @@ -1023,6 +1024,7 @@ elif test "$target_cpu" = "sparc64" ; then
1023 1024 echo "#define TARGET_ARCH \"sparc64\"" >> $config_h
1024 1025 echo "#define TARGET_SPARC 1" >> $config_h
1025 1026 echo "#define TARGET_SPARC64 1" >> $config_h
  1027 + elfload32="yes"
1026 1028 elif test "$target_cpu" = "ppc" ; then
1027 1029 echo "TARGET_ARCH=ppc" >> $config_mak
1028 1030 echo "#define TARGET_ARCH \"ppc\"" >> $config_h
... ... @@ -1112,6 +1114,11 @@ if test "$target_user_only" = "yes" -a "$bflt" = "yes"; then
1112 1114 echo "TARGET_HAS_BFLT=yes" >> $config_mak
1113 1115 echo "#define TARGET_HAS_BFLT 1" >> $config_h
1114 1116 fi
  1117 +# 32 bit ELF loader in addition to native 64 bit loader?
  1118 +if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
  1119 + echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak
  1120 + echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h
  1121 +fi
1115 1122 # sdl defines
1116 1123  
1117 1124 if test "$target_user_only" = "no"; then
... ...
linux-user/elfload.c
... ... @@ -12,6 +12,66 @@
12 12 #include "qemu.h"
13 13 #include "disas.h"
14 14  
  15 +/* from personality.h */
  16 +
  17 +/*
  18 + * Flags for bug emulation.
  19 + *
  20 + * These occupy the top three bytes.
  21 + */
  22 +enum {
  23 + ADDR_NO_RANDOMIZE = 0x0040000, /* disable randomization of VA space */
  24 + FDPIC_FUNCPTRS = 0x0080000, /* userspace function ptrs point to descriptors
  25 + * (signal handling)
  26 + */
  27 + MMAP_PAGE_ZERO = 0x0100000,
  28 + ADDR_COMPAT_LAYOUT = 0x0200000,
  29 + READ_IMPLIES_EXEC = 0x0400000,
  30 + ADDR_LIMIT_32BIT = 0x0800000,
  31 + SHORT_INODE = 0x1000000,
  32 + WHOLE_SECONDS = 0x2000000,
  33 + STICKY_TIMEOUTS = 0x4000000,
  34 + ADDR_LIMIT_3GB = 0x8000000,
  35 +};
  36 +
  37 +/*
  38 + * Personality types.
  39 + *
  40 + * These go in the low byte. Avoid using the top bit, it will
  41 + * conflict with error returns.
  42 + */
  43 +enum {
  44 + PER_LINUX = 0x0000,
  45 + PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT,
  46 + PER_LINUX_FDPIC = 0x0000 | FDPIC_FUNCPTRS,
  47 + PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
  48 + PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
  49 + PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS |
  50 + WHOLE_SECONDS | SHORT_INODE,
  51 + PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
  52 + PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
  53 + PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS,
  54 + PER_BSD = 0x0006,
  55 + PER_SUNOS = 0x0006 | STICKY_TIMEOUTS,
  56 + PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
  57 + PER_LINUX32 = 0x0008,
  58 + PER_LINUX32_3GB = 0x0008 | ADDR_LIMIT_3GB,
  59 + PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
  60 + PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
  61 + PER_IRIX64 = 0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
  62 + PER_RISCOS = 0x000c,
  63 + PER_SOLARIS = 0x000d | STICKY_TIMEOUTS,
  64 + PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
  65 + PER_OSF4 = 0x000f, /* OSF/1 v4 */
  66 + PER_HPUX = 0x0010,
  67 + PER_MASK = 0x00ff,
  68 +};
  69 +
  70 +/*
  71 + * Return the base personality without flags.
  72 + */
  73 +#define personality(pers) (pers & PER_MASK)
  74 +
15 75 /* this flag is uneffective under linux too, should be deleted */
16 76 #ifndef MAP_DENYWRITE
17 77 #define MAP_DENYWRITE 0
... ... @@ -154,7 +214,7 @@ enum
154 214  
155 215 #define ELF_START_MMAP 0x80000000
156 216  
157   -#define elf_check_arch(x) ( (x) == EM_SPARCV9 )
  217 +#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
158 218  
159 219 #define ELF_CLASS ELFCLASS64
160 220 #define ELF_DATA ELFDATA2MSB
... ... @@ -168,7 +228,10 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
168 228 regs->pc = infop->entry;
169 229 regs->npc = regs->pc + 4;
170 230 regs->y = 0;
171   - regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
  231 + if (personality(infop->personality) == PER_LINUX32)
  232 + regs->u_regs[14] = infop->start_stack - 16 * 4;
  233 + else
  234 + regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
172 235 }
173 236  
174 237 #else
... ... @@ -412,6 +475,13 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
412 475 #define ELF_HWCAP 0
413 476 #endif
414 477  
  478 +#ifdef OVERRIDE_ELF_CLASS
  479 +#undef ELF_CLASS
  480 +#define ELF_CLASS OVERRIDE_ELF_CLASS
  481 +#undef bswaptls
  482 +#define bswaptls(ptr) bswap32s(ptr)
  483 +#endif
  484 +
415 485 #include "elf.h"
416 486  
417 487 struct exec
... ... @@ -439,25 +509,6 @@ struct exec
439 509 /* max code+data+bss+brk space allocated to ET_DYN executables */
440 510 #define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
441 511  
442   -/* from personality.h */
443   -
444   -/* Flags for bug emulation. These occupy the top three bytes. */
445   -#define STICKY_TIMEOUTS 0x4000000
446   -#define WHOLE_SECONDS 0x2000000
447   -
448   -/* Personality types. These go in the low byte. Avoid using the top bit,
449   - * it will conflict with error returns.
450   - */
451   -#define PER_MASK (0x00ff)
452   -#define PER_LINUX (0x0000)
453   -#define PER_SVR4 (0x0001 | STICKY_TIMEOUTS)
454   -#define PER_SVR3 (0x0002 | STICKY_TIMEOUTS)
455   -#define PER_SCOSVR3 (0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS)
456   -#define PER_WYSEV386 (0x0004 | STICKY_TIMEOUTS)
457   -#define PER_ISCR4 (0x0005 | STICKY_TIMEOUTS)
458   -#define PER_BSD (0x0006)
459   -#define PER_XENIX (0x0007 | STICKY_TIMEOUTS)
460   -
461 512 /* Necessary parameters */
462 513 #define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
463 514 #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,
587 638 return p;
588 639 }
589 640  
590   -target_ulong setup_arg_pages(target_ulong p, struct linux_binprm * bprm,
591   - struct image_info * info)
  641 +static target_ulong setup_arg_pages(target_ulong p, struct linux_binprm *bprm,
  642 + struct image_info *info)
592 643 {
593 644 target_ulong stack_base, size, error;
594 645 int i;
... ...
linux-user/elfload32.c 0 โ†’ 100755
  1 +#define OVERRIDE_ELF_CLASS ELFCLASS32
  2 +#define load_elf_binary load_elf_binary32
  3 +#define do_init_thread do_init_thread32
  4 +
  5 +#include "elfload.c"
  6 +
  7 +#undef load_elf_binary
  8 +#undef do_init_thread
  9 +
  10 +int load_elf_binary(struct linux_binprm *bprm, struct target_pt_regs *regs,
  11 + struct image_info *info);
  12 +
  13 +int load_elf_binary_multi(struct linux_binprm *bprm,
  14 + struct target_pt_regs *regs,
  15 + struct image_info *info)
  16 +{
  17 + struct elfhdr *elf_ex;
  18 + int retval;
  19 +
  20 + elf_ex = (struct elfhdr *) bprm->buf; /* exec-header */
  21 + if (elf_ex->e_ident[EI_CLASS] == ELFCLASS64) {
  22 + retval = load_elf_binary(bprm, regs, info);
  23 + } else {
  24 + retval = load_elf_binary32(bprm, regs, info);
  25 + if (personality(info->personality) == PER_LINUX)
  26 + info->personality = PER_LINUX32;
  27 + }
  28 +
  29 + return retval;
  30 +}
... ...
linux-user/linuxload.c
... ... @@ -169,7 +169,11 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
169 169 && bprm.buf[1] == 'E'
170 170 && bprm.buf[2] == 'L'
171 171 && bprm.buf[3] == 'F') {
  172 +#ifndef TARGET_HAS_ELFLOAD32
172 173 retval = load_elf_binary(&bprm,regs,infop);
  174 +#else
  175 + retval = load_elf_binary_multi(&bprm, regs, infop);
  176 +#endif
173 177 #if defined(TARGET_HAS_BFLT)
174 178 } else if (bprm.buf[0] == 'b'
175 179 && bprm.buf[1] == 'F'
... ...
linux-user/main.c
... ... @@ -564,6 +564,7 @@ void cpu_loop (CPUSPARCState *env)
564 564 case 0x88:
565 565 case 0x90:
566 566 #else
  567 + case 0x110:
567 568 case 0x16d:
568 569 #endif
569 570 ret = do_syscall (env, env->gregs[1],
... ...
linux-user/qemu.h
... ... @@ -124,6 +124,11 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
124 124 struct image_info * info);
125 125 int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
126 126 struct image_info * info);
  127 +#ifdef TARGET_HAS_ELFLOAD32
  128 +int load_elf_binary_multi(struct linux_binprm *bprm,
  129 + struct target_pt_regs *regs,
  130 + struct image_info *info);
  131 +#endif
127 132  
128 133 void memcpy_to_target(target_ulong dest, const void *src,
129 134 unsigned long len);
... ...
linux-user/sparc64/syscall_nr.h
... ... @@ -29,11 +29,11 @@
29 29 #define TARGET_NR_sigaltstack 28 /* Common */
30 30 #define TARGET_NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */
31 31 #define TARGET_NR_utime 30 /* Implemented via utimes() under SunOS */
32   -/* #define TARGET_NR_lchown32 31 Linux sparc32 specific */
33   -/* #define TARGET_NR_fchown32 32 Linux sparc32 specific */
  32 +#define TARGET_NR_lchown32 31 /* Linux sparc32 specific */
  33 +#define TARGET_NR_fchown32 32 /* Linux sparc32 specific */
34 34 #define TARGET_NR_access 33 /* Common */
35 35 #define TARGET_NR_nice 34 /* Implemented via get/setpriority() in SunOS */
36   -/* #define TARGET_NR_chown32 35 Linux sparc32 specific */
  36 +#define TARGET_NR_chown32 35 /* Linux sparc32 specific */
37 37 #define TARGET_NR_sync 36 /* Common */
38 38 #define TARGET_NR_kill 37 /* Common */
39 39 #define TARGET_NR_stat 38 /* Common */
... ... @@ -42,7 +42,7 @@
42 42 #define TARGET_NR_dup 41 /* Common */
43 43 #define TARGET_NR_pipe 42 /* Common */
44 44 #define TARGET_NR_times 43 /* Implemented via getrusage() in SunOS */
45   -/* #define TARGET_NR_getuid32 44 Linux sparc32 specific */
  45 +#define TARGET_NR_getuid32 44 /* Linux sparc32 specific */
46 46 #define TARGET_NR_umount2 45 /* Linux Specific */
47 47 #define TARGET_NR_setgid 46 /* Implemented via setregid() in SunOS */
48 48 #define TARGET_NR_getgid 47 /* Common */
... ... @@ -51,48 +51,48 @@
51 51 #define TARGET_NR_getegid 50 /* SunOS calls getgid() */
52 52 #define TARGET_NR_acct 51 /* Common */
53 53 #define TARGET_NR_memory_ordering 52 /* Linux Specific */
54   -/* #define TARGET_NR_getgid32 53 Linux sparc32 specific */
  54 +#define TARGET_NR_getgid32 53 /* Linux sparc32 specific */
55 55 #define TARGET_NR_ioctl 54 /* Common */
56 56 #define TARGET_NR_reboot 55 /* Common */
57   -/* #define TARGET_NR_mmap2 56 Linux sparc32 Specific */
  57 +#define TARGET_NR_mmap2 56 /* Linux sparc32 Specific */
58 58 #define TARGET_NR_symlink 57 /* Common */
59 59 #define TARGET_NR_readlink 58 /* Common */
60 60 #define TARGET_NR_execve 59 /* Common */
61 61 #define TARGET_NR_umask 60 /* Common */
62 62 #define TARGET_NR_chroot 61 /* Common */
63 63 #define TARGET_NR_fstat 62 /* Common */
64   -/* #define TARGET_NR_fstat64 63 Linux sparc32 Specific */
  64 +#define TARGET_NR_fstat64 63 /* Linux sparc32 Specific */
65 65 #define TARGET_NR_getpagesize 64 /* Common */
66 66 #define TARGET_NR_msync 65 /* Common in newer 1.3.x revs... */
67 67 #define TARGET_NR_vfork 66 /* Common */
68 68 #define TARGET_NR_pread64 67 /* Linux Specific */
69 69 #define TARGET_NR_pwrite64 68 /* Linux Specific */
70   -/* #define TARGET_NR_geteuid32 69 Linux sparc32, sbrk under SunOS */
71   -/* #define TARGET_NR_getegid32 70 Linux sparc32, sstk under SunOS */
  70 +#define TARGET_NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */
  71 +#define TARGET_NR_getegid32 70 /* Linux sparc32, sstk under SunOS */
72 72 #define TARGET_NR_mmap 71 /* Common */
73   -/* #define TARGET_NR_setreuid32 72 Linux sparc32, vadvise under SunOS */
  73 +#define TARGET_NR_setreuid32 72 /* Linux sparc32, vadvise under SunOS */
74 74 #define TARGET_NR_munmap 73 /* Common */
75 75 #define TARGET_NR_mprotect 74 /* Common */
76 76 #define TARGET_NR_madvise 75 /* Common */
77 77 #define TARGET_NR_vhangup 76 /* Common */
78   -/* #define TARGET_NR_truncate64 77 Linux sparc32 Specific */
  78 +#define TARGET_NR_truncate64 77 /* Linux sparc32 Specific */
79 79 #define TARGET_NR_mincore 78 /* Common */
80 80 #define TARGET_NR_getgroups 79 /* Common */
81 81 #define TARGET_NR_setgroups 80 /* Common */
82 82 #define TARGET_NR_getpgrp 81 /* Common */
83   -/* #define TARGET_NR_setgroups32 82 Linux sparc32, setpgrp under SunOS */
  83 +#define TARGET_NR_setgroups32 82 /* Linux sparc32, setpgrp under SunOS */
84 84 #define TARGET_NR_setitimer 83 /* Common */
85   -/* #define TARGET_NR_ftruncate64 84 Linux sparc32 Specific */
  85 +#define TARGET_NR_ftruncate64 84 /* Linux sparc32 Specific */
86 86 #define TARGET_NR_swapon 85 /* Common */
87 87 #define TARGET_NR_getitimer 86 /* Common */
88   -/* #define TARGET_NR_setuid32 87 Linux sparc32, gethostname under SunOS */
  88 +#define TARGET_NR_setuid32 87 /* Linux sparc32, gethostname under SunOS */
89 89 #define TARGET_NR_sethostname 88 /* Common */
90   -/* #define TARGET_NR_setgid32 89 Linux sparc32, getdtablesize under SunOS */
  90 +#define TARGET_NR_setgid32 89 /* Linux sparc32, getdtablesize under SunOS */
91 91 #define TARGET_NR_dup2 90 /* Common */
92   -/* #define TARGET_NR_setfsuid32 91 Linux sparc32, getdopt under SunOS */
  92 +#define TARGET_NR_setfsuid32 91 /* Linux sparc32, getdopt under SunOS */
93 93 #define TARGET_NR_fcntl 92 /* Common */
94 94 #define TARGET_NR_select 93 /* Common */
95   -/* #define TARGET_NR_setfsgid32 94 Linux sparc32, setdopt under SunOS */
  95 +#define TARGET_NR_setfsgid32 94 /* Linux sparc32, setdopt under SunOS */
96 96 #define TARGET_NR_fsync 95 /* Common */
97 97 #define TARGET_NR_setpriority 96 /* Common */
98 98 #define TARGET_NR_socket 97 /* Common */
... ... @@ -110,10 +110,10 @@
110 110 #define TARGET_NR_getresuid 109 /* Linux Specific, sigblock under SunOS */
111 111 #define TARGET_NR_setresgid 110 /* Linux Specific, sigsetmask under SunOS */
112 112 #define TARGET_NR_getresgid 111 /* Linux Specific, sigpause under SunOS */
113   -/* #define TARGET_NR_setregid32 75 Linux sparc32, sigstack under SunOS */
  113 +/* #define TARGET_NR_setregid32 75 Linux sparc32, sigstack under SunOS */
114 114 #define TARGET_NR_recvmsg 113 /* Common */
115 115 #define TARGET_NR_sendmsg 114 /* Common */
116   -/* #define TARGET_NR_getgroups32 115 Linux sparc32, vtrace under SunOS */
  116 +#define TARGET_NR_getgroups32 115 /* Linux sparc32, vtrace under SunOS */
117 117 #define TARGET_NR_gettimeofday 116 /* Common */
118 118 #define TARGET_NR_getrusage 117 /* Common */
119 119 #define TARGET_NR_getsockopt 118 /* Common */
... ... @@ -130,14 +130,14 @@
130 130 #define TARGET_NR_truncate 129 /* Common */
131 131 #define TARGET_NR_ftruncate 130 /* Common */
132 132 #define TARGET_NR_flock 131 /* Common */
133   -/* #define TARGET_NR_lstat64 132 Linux sparc32 Specific */
  133 +#define TARGET_NR_lstat64 132 /* Linux sparc32 Specific */
134 134 #define TARGET_NR_sendto 133 /* Common */
135 135 #define TARGET_NR_shutdown 134 /* Common */
136 136 #define TARGET_NR_socketpair 135 /* Common */
137 137 #define TARGET_NR_mkdir 136 /* Common */
138 138 #define TARGET_NR_rmdir 137 /* Common */
139 139 #define TARGET_NR_utimes 138 /* SunOS Specific */
140   -/* #define TARGET_NR_stat64 139 Linux sparc32 Specific */
  140 +#define TARGET_NR_stat64 139 /* Linux sparc32 Specific */
141 141 #define TARGET_NR_sendfile64 140 /* adjtime under SunOS */
142 142 #define TARGET_NR_getpeername 141 /* Common */
143 143 #define TARGET_NR_futex 142 /* gethostid under SunOS */
... ... @@ -153,7 +153,7 @@
153 153 /* #define TARGET_NR_putmsg 152 SunOS Specific */
154 154 #define TARGET_NR_poll 153 /* Common */
155 155 #define TARGET_NR_getdents64 154 /* Linux specific */
156   -/* #define TARGET_NR_fcntl64 155 Linux sparc32 Specific */
  156 +#define TARGET_NR_fcntl64 155 /* Linux sparc32 Specific */
157 157 /* #define TARGET_NR_getdirentries 156 SunOS Specific */
158 158 #define TARGET_NR_statfs 157 /* Common */
159 159 #define TARGET_NR_fstatfs 158 /* Common */
... ... @@ -229,9 +229,7 @@
229 229 #define TARGET_NR_setfsuid 228 /* Linux Specific */
230 230 #define TARGET_NR_setfsgid 229 /* Linux Specific */
231 231 #define TARGET_NR__newselect 230 /* Linux Specific */
232   -#ifdef __KERNEL__
233   -#define TARGET_NR_time 231 /* Linux sparc32 */
234   -#endif
  232 +#define TARGET_NR_time 231 /* Linux sparc32 */
235 233 /* #define TARGET_NR_oldstat 232 Linux Specific */
236 234 #define TARGET_NR_stime 233 /* Linux Specific */
237 235 #define TARGET_NR_statfs64 234 /* Linux Specific */
... ...