提交 d691f669 编写于 作者: B 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
上级 386405f7
version 0.1.1:
- glibc 2.2 compilation fixes
- added -s and -L options
- binary distribution of x86 glibc and wine
version 0.1: version 0.1:
- initial public release. - initial public release.
...@@ -118,6 +118,15 @@ tar: ...@@ -118,6 +118,15 @@ tar:
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) ) ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) )
rm -rf /tmp/$(FILE) rm -rf /tmp/$(FILE)
# generate a binary distribution including the test binary environnment
BINPATH=/usr/local/qemu-i386
tarbin:
tar zcvf /tmp/qemu-i386-glibc21.tar.gz \
$(BINPATH)/etc $(BINPATH)/lib $(BINPATH)/bin
tar zcvf /tmp/qemu-i386-wine.tar.gz \
$(BINPATH)/X11R6 $(BINPATH)/wine
ifneq ($(wildcard .depend),) ifneq ($(wildcard .depend),)
include .depend include .depend
endif endif
...@@ -15,8 +15,22 @@ Type ...@@ -15,8 +15,22 @@ Type
make install make install
to install qemu in /usr/local/bin to install QEMU in /usr/local/bin
* On x86 you should be able to launch any program by using the
libraries installed on your PC. For example:
./qemu -L / /bin/ls
* On non x86 CPUs, you need first to download at least an x86 glibc
(qemu-i386-glibc21.tar.gz on the qemu web page). Then you can launch
the precompiled 'ls' x86 executable:
./qemu /usr/local/qemu-i386/bin/ls
You can look at /usr/local/qemu-i386/bin/qemu-conf.sh so that QEMU is
automatically launched by the Linux kernel when you try to launch x86
executables.
Documentation Documentation
------------- -------------
......
0.1 0.1.1
\ No newline at end of file
...@@ -406,7 +406,7 @@ void cpu_x86_close(CPUX86State *s); ...@@ -406,7 +406,7 @@ void cpu_x86_close(CPUX86State *s);
/* needed to load some predefinied segment registers */ /* needed to load some predefinied segment registers */
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
/* you can call these signal handler from you SIGBUS and SIGSEGV /* you can call this signal handler from your SIGBUS and SIGSEGV
signal handlers to inform the virtual CPU of exceptions. non zero signal handlers to inform the virtual CPU of exceptions. non zero
is returned if the signal was handled by the virtual CPU. */ is returned if the signal was handled by the virtual CPU. */
struct siginfo; struct siginfo;
......
...@@ -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,
unsigned long pc; unsigned long pc;
sigset_t *pold_set; sigset_t *pold_set;
#ifndef REG_EIP
/* for glibc 2.1 */
#define REG_EIP EIP
#endif
pc = uc->uc_mcontext.gregs[EIP]; pc = uc->uc_mcontext.gregs[EIP];
pold_set = &uc->uc_sigmask; pold_set = &uc->uc_sigmask;
return handle_cpu_signal(pc, pold_set); return handle_cpu_signal(pc, pold_set);
......
...@@ -42,8 +42,7 @@ ...@@ -42,8 +42,7 @@
#define DLINFO_ITEMS 12 #define DLINFO_ITEMS 12
/* Where we find X86 libraries... */ /* Where we find X86 libraries... */
//#define X86_DEFAULT_LIB_DIR "/usr/x86/"
#define X86_DEFAULT_LIB_DIR "/"
//extern void * mmap4k(); //extern void * mmap4k();
#define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f) #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
* is an a.out format binary * is an a.out format binary
*/ */
elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+strlen(X86_DEFAULT_LIB_DIR)); elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+
strlen(bprm->interp_prefix));
if (elf_interpreter == NULL) { if (elf_interpreter == NULL) {
free (elf_phdata); 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
return -ENOMEM; return -ENOMEM;
} }
strcpy(elf_interpreter, X86_DEFAULT_LIB_DIR); strcpy(elf_interpreter, bprm->interp_prefix);
retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET); retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
if(retval >= 0) { if(retval >= 0) {
retval = read(bprm->fd, retval = read(bprm->fd,
elf_interpreter+strlen(X86_DEFAULT_LIB_DIR), elf_interpreter+strlen(bprm->interp_prefix),
elf_ppnt->p_filesz); elf_ppnt->p_filesz);
} }
if(retval < 0) { 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
int elf_exec(const char * filename, char ** argv, char ** envp, int elf_exec(const char *interp_prefix,
const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs, struct image_info *infop) struct target_pt_regs * regs, struct image_info *infop)
{ {
struct linux_binprm bprm; 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,
else { else {
bprm.fd = retval; bprm.fd = retval;
} }
bprm.interp_prefix = (char *)interp_prefix;
bprm.filename = (char *)filename; bprm.filename = (char *)filename;
bprm.sh_bang = 0; bprm.sh_bang = 0;
bprm.loader = 0; bprm.loader = 0;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
FILE *logfile = NULL; FILE *logfile = NULL;
int loglevel; int loglevel;
const char *interp_prefix = CONFIG_QEMU_PREFIX "/qemu-i386";
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
we allocate a bigger stack. Need a better solution, for example 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)
void usage(void) void usage(void)
{ {
printf("qemu version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n" printf("qemu version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
"usage: qemu [-d] program [arguments...]\n" "usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n"
"Linux x86 emulator\n" "Linux x86 emulator\n"
); "\n"
"-h print this help\n"
"-d activate log (logfile=%s)\n"
"-L path set the x86 elf interpreter prefix (default=%s)\n"
"-s size set the x86 stack size in bytes (default=%ld)\n",
DEBUG_LOGFILE,
interp_prefix,
x86_stack_size);
exit(1); exit(1);
} }
...@@ -188,15 +196,41 @@ int main(int argc, char **argv) ...@@ -188,15 +196,41 @@ int main(int argc, char **argv)
struct image_info info1, *info = &info1; struct image_info info1, *info = &info1;
CPUX86State *env; CPUX86State *env;
int optind; int optind;
const char *r;
if (argc <= 1) if (argc <= 1)
usage(); usage();
loglevel = 0; loglevel = 0;
optind = 1; optind = 1;
if (argv[optind] && !strcmp(argv[optind], "-d")) { for(;;) {
loglevel = 1; if (optind >= argc)
break;
r = argv[optind];
if (r[0] != '-')
break;
optind++; optind++;
r++;
if (!strcmp(r, "-")) {
break;
} else if (!strcmp(r, "d")) {
loglevel = 1;
} else if (!strcmp(r, "s")) {
r = argv[optind++];
x86_stack_size = strtol(r, (char **)&r, 0);
if (x86_stack_size <= 0)
usage();
if (*r == 'M')
x86_stack_size *= 1024 * 1024;
else if (*r == 'k' || *r == 'K')
x86_stack_size *= 1024;
} else if (!strcmp(r, "L")) {
interp_prefix = argv[optind++];
} else {
usage();
} }
}
if (optind >= argc)
usage();
filename = argv[optind]; filename = argv[optind];
/* init debug */ /* init debug */
...@@ -215,7 +249,7 @@ int main(int argc, char **argv) ...@@ -215,7 +249,7 @@ int main(int argc, char **argv)
/* Zero out image_info */ /* Zero out image_info */
memset(info, 0, sizeof(struct image_info)); memset(info, 0, sizeof(struct image_info));
if(elf_exec(filename, argv+optind, environ, regs, info) != 0) { if(elf_exec(interp_prefix, filename, argv+optind, environ, regs, info) != 0) {
printf("Error loading %s\n", filename); printf("Error loading %s\n", filename);
exit(1); exit(1);
} }
......
...@@ -33,7 +33,8 @@ struct image_info { ...@@ -33,7 +33,8 @@ struct image_info {
int personality; int personality;
}; };
int elf_exec(const char * filename, char ** argv, char ** envp, int elf_exec(const char *interp_prefix,
const char * filename, char ** argv, char ** envp,
struct target_pt_regs * regs, struct image_info *infop); struct target_pt_regs * regs, struct image_info *infop);
void target_set_brk(char *new_brk); void target_set_brk(char *new_brk);
......
/* templates for various register related operations */ /*
* i386 micro operations (templates for various register related
* operations)
*
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
void OPPROTO glue(op_movl_A0,REGNAME)(void) void OPPROTO glue(op_movl_A0,REGNAME)(void)
{ {
A0 = REG; A0 = REG;
......
...@@ -4,21 +4,20 @@ ...@@ -4,21 +4,20 @@
* *
* Copyright (c) 2003 Fabrice Bellard * Copyright (c) 2003 Fabrice Bellard
* *
* This program is free software; you can redistribute it and/or modify * This library is free software; you can redistribute it and/or
* it under the terms of the GNU General Public License as published by * modify it under the terms of the GNU Lesser General Public
* the Free Software Foundation; either version 2 of the License, or * License as published by the Free Software Foundation; either
* (at your option) any later version. * version 2 of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* GNU General Public License for more details. * Lesser General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU Lesser General Public
* along with this program; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define DATA_BITS (1 << (3 + SHIFT)) #define DATA_BITS (1 << (3 + SHIFT))
#define SHIFT_MASK (DATA_BITS - 1) #define SHIFT_MASK (DATA_BITS - 1)
#define SIGN_MASK (1 << (DATA_BITS - 1)) #define SIGN_MASK (1 << (DATA_BITS - 1))
......
...@@ -73,25 +73,52 @@ maximum performances. ...@@ -73,25 +73,52 @@ maximum performances.
@chapter Invocation @chapter Invocation
@section Quick Start
In order to launch a Linux process, QEMU needs the process executable In order to launch a Linux process, QEMU needs the process executable
itself and all the target (x86) dynamic libraries used by it. Currently, itself and all the target (x86) dynamic libraries used by it.
QEMU is not distributed with the necessary packages so that you can test
it easily on non x86 CPUs. @itemize
However, the statically x86 binary 'tests/hello' can be used to do a @item On x86, you can just try to launch any process by using the native
first test: libraries:
@example @example
qemu tests/hello qemu -L / /bin/ls
@end example @end example
@code{Hello world} should be printed on the terminal. @code{-L /} tells that the x86 dynamic linker must be searched with a
@file{/} prefix.
If you are testing it on a x86 CPU, then you can test it on any process:
@item On non x86 CPUs, you need first to download at least an x86 glibc
(@file{qemu-i386-glibc21.tar.gz} on the QEMU web page). Then you can
launch the precompiled @file{ls} x86 executable:
@example @example
qemu /bin/ls -l qemu /usr/local/qemu-i386/bin/ls
@end example @end example
You can look at @file{/usr/local/qemu-i386/bin/qemu-conf.sh} so that QEMU is automatically
launched by the Linux kernel when you try to launch x86 executables. It
requires the @code{binfmt_misc} module in the Linux kernel.
@end itemize
@section Command line options
@example
usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]
@end example
@table @samp
@item -h
Print the help
@item -d
Activate log (logfile=/tmp/qemu.log)
@item -L path
Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386)
@item -s size
Set the x86 stack size in bytes (default=524288)
@end table
@chapter QEMU Internals @chapter QEMU Internals
......
...@@ -28,7 +28,7 @@ testthread: testthread.c ...@@ -28,7 +28,7 @@ testthread: testthread.c
# i386 emulation test (test various opcodes) */ # i386 emulation test (test various opcodes) */
test-i386: test-i386.c test-i386-code16.S \ test-i386: test-i386.c test-i386-code16.S \
test-i386.h test-i386-shift.h test-i386-muldiv.h test-i386.h test-i386-shift.h test-i386-muldiv.h
$(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ test-i386.c test-i386-code16.S -lm $(CC) $(CFLAGS) $(LDFLAGS) -o $@ test-i386.c test-i386-code16.S -lm
test: test-i386 test: test-i386
ifeq ($(ARCH),i386) ifeq ($(ARCH),i386)
......
...@@ -15,21 +15,34 @@ void alarm_handler(int sig) ...@@ -15,21 +15,34 @@ void alarm_handler(int sig)
alarm(1); alarm(1);
} }
#ifndef REG_EAX
#define REG_EAX EAX
#define REG_EBX EBX
#define REG_ECX ECX
#define REG_EDX EDX
#define REG_ESI ESI
#define REG_EDI EDI
#define REG_EBP EBP
#define REG_ESP ESP
#define REG_EIP EIP
#define REG_EFL EFL
#endif
void dump_regs(struct ucontext *uc) void dump_regs(struct ucontext *uc)
{ {
printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n" printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
"ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n" "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
"EFL=%08x EIP=%08x\n", "EFL=%08x EIP=%08x\n",
uc->uc_mcontext.gregs[EAX], uc->uc_mcontext.gregs[REG_EAX],
uc->uc_mcontext.gregs[EBX], uc->uc_mcontext.gregs[REG_EBX],
uc->uc_mcontext.gregs[ECX], uc->uc_mcontext.gregs[REG_ECX],
uc->uc_mcontext.gregs[EDX], uc->uc_mcontext.gregs[REG_EDX],
uc->uc_mcontext.gregs[ESI], uc->uc_mcontext.gregs[REG_ESI],
uc->uc_mcontext.gregs[EDI], uc->uc_mcontext.gregs[REG_EDI],
uc->uc_mcontext.gregs[EBP], uc->uc_mcontext.gregs[REG_EBP],
uc->uc_mcontext.gregs[ESP], uc->uc_mcontext.gregs[REG_ESP],
uc->uc_mcontext.gregs[EFL], uc->uc_mcontext.gregs[REG_EFL],
uc->uc_mcontext.gregs[EIP]); uc->uc_mcontext.gregs[REG_EIP]);
} }
void sig_handler(int sig, siginfo_t *info, void *puc) void sig_handler(int sig, siginfo_t *info, void *puc)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册