Commit d691f66983c0b36689400e9e9137d72bd3be8e72
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
Showing
14 changed files
with
178 additions
and
51 deletions
Changelog
Makefile
| ... | ... | @@ -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 | ... | ... |
README
| ... | ... | @@ -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 | ------------- | ... | ... |
VERSION
cpu-i386.h
| ... | ... | @@ -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; | ... | ... |
exec-i386.c
| ... | ... | @@ -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); | ... | ... |
linux-user/elfload.c
| ... | ... | @@ -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; | ... | ... |
linux-user/main.c
| ... | ... | @@ -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 | } | ... | ... |
linux-user/qemu.h
| ... | ... | @@ -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); | ... | ... |
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 | 21 | void OPPROTO glue(op_movl_A0,REGNAME)(void) |
| 4 | 22 | { |
| 5 | 23 | A0 = REG; | ... | ... |
ops_template.h
| ... | ... | @@ -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)) | ... | ... |
qemu-doc.texi
| ... | ... | @@ -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 | ... | ... |
tests/Makefile
| ... | ... | @@ -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) | ... | ... |
tests/testsig.c
| ... | ... | @@ -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) | ... | ... |