Commit d691f66983c0b36689400e9e9137d72bd3be8e72

Authored by bellard
1 parent 386405f7

glibc2.2 fixes - more command line options - misc doc fixes


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@46 c046a42c-6fe2-441c-8c8c-71466251a162
Changelog
  1 +version 0.1.1:
  2 +
  3 + - glibc 2.2 compilation fixes
  4 + - added -s and -L options
  5 + - binary distribution of x86 glibc and wine
  6 +
1 version 0.1: 7 version 0.1:
2 8
3 - initial public release. 9 - initial public release.
Makefile
@@ -118,6 +118,15 @@ tar: @@ -118,6 +118,15 @@ tar:
118 ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) ) 118 ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) )
119 rm -rf /tmp/$(FILE) 119 rm -rf /tmp/$(FILE)
120 120
  121 +# generate a binary distribution including the test binary environnment
  122 +BINPATH=/usr/local/qemu-i386
  123 +
  124 +tarbin:
  125 + tar zcvf /tmp/qemu-i386-glibc21.tar.gz \
  126 + $(BINPATH)/etc $(BINPATH)/lib $(BINPATH)/bin
  127 + tar zcvf /tmp/qemu-i386-wine.tar.gz \
  128 + $(BINPATH)/X11R6 $(BINPATH)/wine
  129 +
121 ifneq ($(wildcard .depend),) 130 ifneq ($(wildcard .depend),)
122 include .depend 131 include .depend
123 endif 132 endif
@@ -15,8 +15,22 @@ Type @@ -15,8 +15,22 @@ Type
15 15
16 make install 16 make install
17 17
18 -to install qemu in /usr/local/bin 18 +to install QEMU in /usr/local/bin
19 19
  20 +* On x86 you should be able to launch any program by using the
  21 +libraries installed on your PC. For example:
  22 +
  23 + ./qemu -L / /bin/ls
  24 +
  25 +* On non x86 CPUs, you need first to download at least an x86 glibc
  26 +(qemu-i386-glibc21.tar.gz on the qemu web page). Then you can launch
  27 +the precompiled 'ls' x86 executable:
  28 +
  29 + ./qemu /usr/local/qemu-i386/bin/ls
  30 +
  31 +You can look at /usr/local/qemu-i386/bin/qemu-conf.sh so that QEMU is
  32 +automatically launched by the Linux kernel when you try to launch x86
  33 +executables.
20 34
21 Documentation 35 Documentation
22 ------------- 36 -------------
1 -0.1  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +0.1.1
cpu-i386.h
@@ -406,7 +406,7 @@ void cpu_x86_close(CPUX86State *s); @@ -406,7 +406,7 @@ void cpu_x86_close(CPUX86State *s);
406 /* needed to load some predefinied segment registers */ 406 /* needed to load some predefinied segment registers */
407 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); 407 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
408 408
409 -/* you can call these signal handler from you SIGBUS and SIGSEGV 409 +/* you can call this signal handler from your SIGBUS and SIGSEGV
410 signal handlers to inform the virtual CPU of exceptions. non zero 410 signal handlers to inform the virtual CPU of exceptions. non zero
411 is returned if the signal was handled by the virtual CPU. */ 411 is returned if the signal was handled by the virtual CPU. */
412 struct siginfo; 412 struct siginfo;
exec-i386.c
@@ -485,6 +485,10 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, @@ -485,6 +485,10 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
485 unsigned long pc; 485 unsigned long pc;
486 sigset_t *pold_set; 486 sigset_t *pold_set;
487 487
  488 +#ifndef REG_EIP
  489 +/* for glibc 2.1 */
  490 +#define REG_EIP EIP
  491 +#endif
488 pc = uc->uc_mcontext.gregs[EIP]; 492 pc = uc->uc_mcontext.gregs[EIP];
489 pold_set = &uc->uc_sigmask; 493 pold_set = &uc->uc_sigmask;
490 return handle_cpu_signal(pc, pold_set); 494 return handle_cpu_signal(pc, pold_set);
linux-user/elfload.c
@@ -42,8 +42,7 @@ @@ -42,8 +42,7 @@
42 #define DLINFO_ITEMS 12 42 #define DLINFO_ITEMS 12
43 43
44 /* Where we find X86 libraries... */ 44 /* Where we find X86 libraries... */
45 -//#define X86_DEFAULT_LIB_DIR "/usr/x86/"  
46 -#define X86_DEFAULT_LIB_DIR "/" 45 +
47 46
48 //extern void * mmap4k(); 47 //extern void * mmap4k();
49 #define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f) 48 #define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
@@ -638,7 +637,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r @@ -638,7 +637,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
638 * is an a.out format binary 637 * is an a.out format binary
639 */ 638 */
640 639
641 - elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+strlen(X86_DEFAULT_LIB_DIR)); 640 + elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+
  641 + strlen(bprm->interp_prefix));
642 642
643 if (elf_interpreter == NULL) { 643 if (elf_interpreter == NULL) {
644 free (elf_phdata); 644 free (elf_phdata);
@@ -646,11 +646,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r @@ -646,11 +646,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
646 return -ENOMEM; 646 return -ENOMEM;
647 } 647 }
648 648
649 - strcpy(elf_interpreter, X86_DEFAULT_LIB_DIR); 649 + strcpy(elf_interpreter, bprm->interp_prefix);
650 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); 650 retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
651 if(retval >= 0) { 651 if(retval >= 0) {
652 retval = read(bprm->fd, 652 retval = read(bprm->fd,
653 - elf_interpreter+strlen(X86_DEFAULT_LIB_DIR), 653 + elf_interpreter+strlen(bprm->interp_prefix),
654 elf_ppnt->p_filesz); 654 elf_ppnt->p_filesz);
655 } 655 }
656 if(retval < 0) { 656 if(retval < 0) {
@@ -911,7 +911,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r @@ -911,7 +911,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
911 911
912 912
913 913
914 -int elf_exec(const char * filename, char ** argv, char ** envp, 914 +int elf_exec(const char *interp_prefix,
  915 + const char * filename, char ** argv, char ** envp,
915 struct target_pt_regs * regs, struct image_info *infop) 916 struct target_pt_regs * regs, struct image_info *infop)
916 { 917 {
917 struct linux_binprm bprm; 918 struct linux_binprm bprm;
@@ -930,6 +931,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, @@ -930,6 +931,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp,
930 else { 931 else {
931 bprm.fd = retval; 932 bprm.fd = retval;
932 } 933 }
  934 + bprm.interp_prefix = (char *)interp_prefix;
933 bprm.filename = (char *)filename; 935 bprm.filename = (char *)filename;
934 bprm.sh_bang = 0; 936 bprm.sh_bang = 0;
935 bprm.loader = 0; 937 bprm.loader = 0;
linux-user/main.c
@@ -32,6 +32,7 @@ @@ -32,6 +32,7 @@
32 32
33 FILE *logfile = NULL; 33 FILE *logfile = NULL;
34 int loglevel; 34 int loglevel;
  35 +const char *interp_prefix = CONFIG_QEMU_PREFIX "/qemu-i386";
35 36
36 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so 37 /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
37 we allocate a bigger stack. Need a better solution, for example 38 we allocate a bigger stack. Need a better solution, for example
@@ -172,9 +173,16 @@ void cpu_loop(struct CPUX86State *env) @@ -172,9 +173,16 @@ void cpu_loop(struct CPUX86State *env)
172 void usage(void) 173 void usage(void)
173 { 174 {
174 printf("qemu version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" 175 printf("qemu version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
175 - "usage: qemu [-d] program [arguments...]\n" 176 + "usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n"
176 "Linux x86 emulator\n" 177 "Linux x86 emulator\n"
177 - ); 178 + "\n"
  179 + "-h print this help\n"
  180 + "-d activate log (logfile=%s)\n"
  181 + "-L path set the x86 elf interpreter prefix (default=%s)\n"
  182 + "-s size set the x86 stack size in bytes (default=%ld)\n",
  183 + DEBUG_LOGFILE,
  184 + interp_prefix,
  185 + x86_stack_size);
178 exit(1); 186 exit(1);
179 } 187 }
180 188
@@ -188,15 +196,41 @@ int main(int argc, char **argv) @@ -188,15 +196,41 @@ int main(int argc, char **argv)
188 struct image_info info1, *info = &info1; 196 struct image_info info1, *info = &info1;
189 CPUX86State *env; 197 CPUX86State *env;
190 int optind; 198 int optind;
191 - 199 + const char *r;
  200 +
192 if (argc <= 1) 201 if (argc <= 1)
193 usage(); 202 usage();
194 loglevel = 0; 203 loglevel = 0;
195 optind = 1; 204 optind = 1;
196 - if (argv[optind] && !strcmp(argv[optind], "-d")) {  
197 - loglevel = 1; 205 + for(;;) {
  206 + if (optind >= argc)
  207 + break;
  208 + r = argv[optind];
  209 + if (r[0] != '-')
  210 + break;
198 optind++; 211 optind++;
  212 + r++;
  213 + if (!strcmp(r, "-")) {
  214 + break;
  215 + } else if (!strcmp(r, "d")) {
  216 + loglevel = 1;
  217 + } else if (!strcmp(r, "s")) {
  218 + r = argv[optind++];
  219 + x86_stack_size = strtol(r, (char **)&r, 0);
  220 + if (x86_stack_size <= 0)
  221 + usage();
  222 + if (*r == 'M')
  223 + x86_stack_size *= 1024 * 1024;
  224 + else if (*r == 'k' || *r == 'K')
  225 + x86_stack_size *= 1024;
  226 + } else if (!strcmp(r, "L")) {
  227 + interp_prefix = argv[optind++];
  228 + } else {
  229 + usage();
  230 + }
199 } 231 }
  232 + if (optind >= argc)
  233 + usage();
200 filename = argv[optind]; 234 filename = argv[optind];
201 235
202 /* init debug */ 236 /* init debug */
@@ -215,7 +249,7 @@ int main(int argc, char **argv) @@ -215,7 +249,7 @@ int main(int argc, char **argv)
215 /* Zero out image_info */ 249 /* Zero out image_info */
216 memset(info, 0, sizeof(struct image_info)); 250 memset(info, 0, sizeof(struct image_info));
217 251
218 - if(elf_exec(filename, argv+optind, environ, regs, info) != 0) { 252 + if(elf_exec(interp_prefix, filename, argv+optind, environ, regs, info) != 0) {
219 printf("Error loading %s\n", filename); 253 printf("Error loading %s\n", filename);
220 exit(1); 254 exit(1);
221 } 255 }
linux-user/qemu.h
@@ -33,7 +33,8 @@ struct image_info { @@ -33,7 +33,8 @@ struct image_info {
33 int personality; 33 int personality;
34 }; 34 };
35 35
36 -int elf_exec(const char * filename, char ** argv, char ** envp, 36 +int elf_exec(const char *interp_prefix,
  37 + const char * filename, char ** argv, char ** envp,
37 struct target_pt_regs * regs, struct image_info *infop); 38 struct target_pt_regs * regs, struct image_info *infop);
38 39
39 void target_set_brk(char *new_brk); 40 void target_set_brk(char *new_brk);
opreg_template.h
1 -/* templates for various register related operations */  
2 - 1 +/*
  2 + * i386 micro operations (templates for various register related
  3 + * operations)
  4 + *
  5 + * Copyright (c) 2003 Fabrice Bellard
  6 + *
  7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
  11 + *
  12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * Lesser General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
3 void OPPROTO glue(op_movl_A0,REGNAME)(void) 21 void OPPROTO glue(op_movl_A0,REGNAME)(void)
4 { 22 {
5 A0 = REG; 23 A0 = REG;
ops_template.h
@@ -4,21 +4,20 @@ @@ -4,21 +4,20 @@
4 * 4 *
5 * Copyright (c) 2003 Fabrice Bellard 5 * Copyright (c) 2003 Fabrice Bellard
6 * 6 *
7 - * This program is free software; you can redistribute it and/or modify  
8 - * it under the terms of the GNU General Public License as published by  
9 - * the Free Software Foundation; either version 2 of the License, or  
10 - * (at your option) any later version. 7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
11 * 11 *
12 - * This program is distributed in the hope that it will be useful,  
13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of  
14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the  
15 - * GNU General Public License for more details. 12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * Lesser General Public License for more details.
16 * 16 *
17 - * You should have received a copy of the GNU General Public License  
18 - * along with this program; if not, write to the Free Software  
19 - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */ 20 */
21 -  
22 #define DATA_BITS (1 << (3 + SHIFT)) 21 #define DATA_BITS (1 << (3 + SHIFT))
23 #define SHIFT_MASK (DATA_BITS - 1) 22 #define SHIFT_MASK (DATA_BITS - 1)
24 #define SIGN_MASK (1 << (DATA_BITS - 1)) 23 #define SIGN_MASK (1 << (DATA_BITS - 1))
qemu-doc.texi
@@ -73,26 +73,53 @@ maximum performances. @@ -73,26 +73,53 @@ maximum performances.
73 73
74 @chapter Invocation 74 @chapter Invocation
75 75
  76 +@section Quick Start
  77 +
76 In order to launch a Linux process, QEMU needs the process executable 78 In order to launch a Linux process, QEMU needs the process executable
77 -itself and all the target (x86) dynamic libraries used by it. Currently,  
78 -QEMU is not distributed with the necessary packages so that you can test  
79 -it easily on non x86 CPUs. 79 +itself and all the target (x86) dynamic libraries used by it.
  80 +
  81 +@itemize
80 82
81 -However, the statically x86 binary 'tests/hello' can be used to do a  
82 -first test: 83 +@item On x86, you can just try to launch any process by using the native
  84 +libraries:
83 85
84 @example 86 @example
85 -qemu tests/hello 87 +qemu -L / /bin/ls
86 @end example 88 @end example
87 89
88 -@code{Hello world} should be printed on the terminal. 90 +@code{-L /} tells that the x86 dynamic linker must be searched with a
  91 +@file{/} prefix.
89 92
90 -If you are testing it on a x86 CPU, then you can test it on any process:  
91 93
92 -@example  
93 -qemu /bin/ls -l 94 +@item On non x86 CPUs, you need first to download at least an x86 glibc
  95 +(@file{qemu-i386-glibc21.tar.gz} on the QEMU web page). Then you can
  96 +launch the precompiled @file{ls} x86 executable:
  97 +@example
  98 +qemu /usr/local/qemu-i386/bin/ls
  99 +@end example
  100 +You can look at @file{/usr/local/qemu-i386/bin/qemu-conf.sh} so that QEMU is automatically
  101 +launched by the Linux kernel when you try to launch x86 executables. It
  102 +requires the @code{binfmt_misc} module in the Linux kernel.
  103 +
  104 +@end itemize
  105 +
  106 +@section Command line options
  107 +
  108 +@example
  109 +usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]
94 @end example 110 @end example
95 111
  112 +@table @samp
  113 +@item -h
  114 +Print the help
  115 +@item -d
  116 +Activate log (logfile=/tmp/qemu.log)
  117 +@item -L path
  118 +Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386)
  119 +@item -s size
  120 +Set the x86 stack size in bytes (default=524288)
  121 +@end table
  122 +
96 @chapter QEMU Internals 123 @chapter QEMU Internals
97 124
98 @section QEMU compared to other emulators 125 @section QEMU compared to other emulators
tests/Makefile
@@ -28,7 +28,7 @@ testthread: testthread.c @@ -28,7 +28,7 @@ testthread: testthread.c
28 # i386 emulation test (test various opcodes) */ 28 # i386 emulation test (test various opcodes) */
29 test-i386: test-i386.c test-i386-code16.S \ 29 test-i386: test-i386.c test-i386-code16.S \
30 test-i386.h test-i386-shift.h test-i386-muldiv.h 30 test-i386.h test-i386-shift.h test-i386-muldiv.h
31 - $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ test-i386.c test-i386-code16.S -lm 31 + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test-i386.c test-i386-code16.S -lm
32 32
33 test: test-i386 33 test: test-i386
34 ifeq ($(ARCH),i386) 34 ifeq ($(ARCH),i386)
tests/testsig.c
@@ -15,21 +15,34 @@ void alarm_handler(int sig) @@ -15,21 +15,34 @@ void alarm_handler(int sig)
15 alarm(1); 15 alarm(1);
16 } 16 }
17 17
  18 +#ifndef REG_EAX
  19 +#define REG_EAX EAX
  20 +#define REG_EBX EBX
  21 +#define REG_ECX ECX
  22 +#define REG_EDX EDX
  23 +#define REG_ESI ESI
  24 +#define REG_EDI EDI
  25 +#define REG_EBP EBP
  26 +#define REG_ESP ESP
  27 +#define REG_EIP EIP
  28 +#define REG_EFL EFL
  29 +#endif
  30 +
18 void dump_regs(struct ucontext *uc) 31 void dump_regs(struct ucontext *uc)
19 { 32 {
20 printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" 33 printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
21 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" 34 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
22 "EFL=%08x EIP=%08x\n", 35 "EFL=%08x EIP=%08x\n",
23 - uc->uc_mcontext.gregs[EAX],  
24 - uc->uc_mcontext.gregs[EBX],  
25 - uc->uc_mcontext.gregs[ECX],  
26 - uc->uc_mcontext.gregs[EDX],  
27 - uc->uc_mcontext.gregs[ESI],  
28 - uc->uc_mcontext.gregs[EDI],  
29 - uc->uc_mcontext.gregs[EBP],  
30 - uc->uc_mcontext.gregs[ESP],  
31 - uc->uc_mcontext.gregs[EFL],  
32 - uc->uc_mcontext.gregs[EIP]); 36 + uc->uc_mcontext.gregs[REG_EAX],
  37 + uc->uc_mcontext.gregs[REG_EBX],
  38 + uc->uc_mcontext.gregs[REG_ECX],
  39 + uc->uc_mcontext.gregs[REG_EDX],
  40 + uc->uc_mcontext.gregs[REG_ESI],
  41 + uc->uc_mcontext.gregs[REG_EDI],
  42 + uc->uc_mcontext.gregs[REG_EBP],
  43 + uc->uc_mcontext.gregs[REG_ESP],
  44 + uc->uc_mcontext.gregs[REG_EFL],
  45 + uc->uc_mcontext.gregs[REG_EIP]);
33 } 46 }
34 47
35 void sig_handler(int sig, siginfo_t *info, void *puc) 48 void sig_handler(int sig, siginfo_t *info, void *puc)