Révision | d691f66983c0b36689400e9e9137d72bd3be8e72 (tree) |
---|---|
l'heure | 2003-03-25 06:58:34 |
Auteur | bellard <bellard@c046...> |
Commiter | bellard |
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
@@ -1,3 +1,9 @@ | ||
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 | 7 | version 0.1: |
2 | 8 | |
3 | 9 | - initial public release. |
@@ -118,6 +118,15 @@ tar: | ||
118 | 118 | ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) ) |
119 | 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 | 130 | ifneq ($(wildcard .depend),) |
122 | 131 | include .depend |
123 | 132 | endif |
@@ -15,8 +15,22 @@ Type | ||
15 | 15 | |
16 | 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 | 35 | Documentation |
22 | 36 | ------------- |
@@ -1 +1 @@ | ||
1 | -0.1 | |
\ No newline at end of file | ||
1 | +0.1.1 |
@@ -406,7 +406,7 @@ void cpu_x86_close(CPUX86State *s); | ||
406 | 406 | /* needed to load some predefinied segment registers */ |
407 | 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 | 410 | signal handlers to inform the virtual CPU of exceptions. non zero |
411 | 411 | is returned if the signal was handled by the virtual CPU. */ |
412 | 412 | struct siginfo; |
@@ -485,6 +485,10 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, | ||
485 | 485 | unsigned long pc; |
486 | 486 | sigset_t *pold_set; |
487 | 487 | |
488 | +#ifndef REG_EIP | |
489 | +/* for glibc 2.1 */ | |
490 | +#define REG_EIP EIP | |
491 | +#endif | |
488 | 492 | pc = uc->uc_mcontext.gregs[EIP]; |
489 | 493 | pold_set = &uc->uc_sigmask; |
490 | 494 | return handle_cpu_signal(pc, pold_set); |
@@ -42,8 +42,7 @@ | ||
42 | 42 | #define DLINFO_ITEMS 12 |
43 | 43 | |
44 | 44 | /* Where we find X86 libraries... */ |
45 | -//#define X86_DEFAULT_LIB_DIR "/usr/x86/" | |
46 | -#define X86_DEFAULT_LIB_DIR "/" | |
45 | + | |
47 | 46 | |
48 | 47 | //extern void * mmap4k(); |
49 | 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 | 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 | 643 | if (elf_interpreter == NULL) { |
644 | 644 | free (elf_phdata); |
@@ -646,11 +646,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r | ||
646 | 646 | return -ENOMEM; |
647 | 647 | } |
648 | 648 | |
649 | - strcpy(elf_interpreter, X86_DEFAULT_LIB_DIR); | |
649 | + strcpy(elf_interpreter, bprm->interp_prefix); | |
650 | 650 | retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); |
651 | 651 | if(retval >= 0) { |
652 | 652 | retval = read(bprm->fd, |
653 | - elf_interpreter+strlen(X86_DEFAULT_LIB_DIR), | |
653 | + elf_interpreter+strlen(bprm->interp_prefix), | |
654 | 654 | elf_ppnt->p_filesz); |
655 | 655 | } |
656 | 656 | if(retval < 0) { |
@@ -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 | 916 | struct target_pt_regs * regs, struct image_info *infop) |
916 | 917 | { |
917 | 918 | struct linux_binprm bprm; |
@@ -930,6 +931,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, | ||
930 | 931 | else { |
931 | 932 | bprm.fd = retval; |
932 | 933 | } |
934 | + bprm.interp_prefix = (char *)interp_prefix; | |
933 | 935 | bprm.filename = (char *)filename; |
934 | 936 | bprm.sh_bang = 0; |
935 | 937 | bprm.loader = 0; |
@@ -32,6 +32,7 @@ | ||
32 | 32 | |
33 | 33 | FILE *logfile = NULL; |
34 | 34 | int loglevel; |
35 | +const char *interp_prefix = CONFIG_QEMU_PREFIX "/qemu-i386"; | |
35 | 36 | |
36 | 37 | /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so |
37 | 38 | we allocate a bigger stack. Need a better solution, for example |
@@ -172,9 +173,16 @@ void cpu_loop(struct CPUX86State *env) | ||
172 | 173 | void usage(void) |
173 | 174 | { |
174 | 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 | 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 | 186 | exit(1); |
179 | 187 | } |
180 | 188 |
@@ -188,15 +196,41 @@ int main(int argc, char **argv) | ||
188 | 196 | struct image_info info1, *info = &info1; |
189 | 197 | CPUX86State *env; |
190 | 198 | int optind; |
191 | - | |
199 | + const char *r; | |
200 | + | |
192 | 201 | if (argc <= 1) |
193 | 202 | usage(); |
194 | 203 | loglevel = 0; |
195 | 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 | 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 | 234 | filename = argv[optind]; |
201 | 235 | |
202 | 236 | /* init debug */ |
@@ -215,7 +249,7 @@ int main(int argc, char **argv) | ||
215 | 249 | /* Zero out image_info */ |
216 | 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 | 253 | printf("Error loading %s\n", filename); |
220 | 254 | exit(1); |
221 | 255 | } |
@@ -33,7 +33,8 @@ struct image_info { | ||
33 | 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 | 38 | struct target_pt_regs * regs, struct image_info *infop); |
38 | 39 | |
39 | 40 | void target_set_brk(char *new_brk); |
@@ -1,5 +1,23 @@ | ||
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 | 21 | void OPPROTO glue(op_movl_A0,REGNAME)(void) |
4 | 22 | { |
5 | 23 | A0 = REG; |
@@ -4,21 +4,20 @@ | ||
4 | 4 | * |
5 | 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 | 21 | #define DATA_BITS (1 << (3 + SHIFT)) |
23 | 22 | #define SHIFT_MASK (DATA_BITS - 1) |
24 | 23 | #define SIGN_MASK (1 << (DATA_BITS - 1)) |
@@ -73,26 +73,53 @@ maximum performances. | ||
73 | 73 | |
74 | 74 | @chapter Invocation |
75 | 75 | |
76 | +@section Quick Start | |
77 | + | |
76 | 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 | 86 | @example |
85 | -qemu tests/hello | |
87 | +qemu -L / /bin/ls | |
86 | 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 | 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 | 123 | @chapter QEMU Internals |
97 | 124 | |
98 | 125 | @section QEMU compared to other emulators |
@@ -28,7 +28,7 @@ testthread: testthread.c | ||
28 | 28 | # i386 emulation test (test various opcodes) */ |
29 | 29 | test-i386: test-i386.c test-i386-code16.S \ |
30 | 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 | 33 | test: test-i386 |
34 | 34 | ifeq ($(ARCH),i386) |
@@ -15,21 +15,34 @@ void alarm_handler(int sig) | ||
15 | 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 | 31 | void dump_regs(struct ucontext *uc) |
19 | 32 | { |
20 | 33 | printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" |
21 | 34 | "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" |
22 | 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 | 48 | void sig_handler(int sig, siginfo_t *info, void *puc) |