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
This commit is contained in:
parent
386405f786
commit
d691f66983
@ -1,3 +1,9 @@
|
||||
version 0.1.1:
|
||||
|
||||
- glibc 2.2 compilation fixes
|
||||
- added -s and -L options
|
||||
- binary distribution of x86 glibc and wine
|
||||
|
||||
version 0.1:
|
||||
|
||||
- initial public release.
|
||||
|
9
Makefile
9
Makefile
@ -118,6 +118,15 @@ tar:
|
||||
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(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),)
|
||||
include .depend
|
||||
endif
|
||||
|
16
README
16
README
@ -15,8 +15,22 @@ Type
|
||||
|
||||
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
|
||||
-------------
|
||||
|
@ -406,7 +406,7 @@ void cpu_x86_close(CPUX86State *s);
|
||||
/* needed to load some predefinied segment registers */
|
||||
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
|
||||
is returned if the signal was handled by the virtual CPU. */
|
||||
struct siginfo;
|
||||
|
@ -485,6 +485,10 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
|
||||
unsigned long pc;
|
||||
sigset_t *pold_set;
|
||||
|
||||
#ifndef REG_EIP
|
||||
/* for glibc 2.1 */
|
||||
#define REG_EIP EIP
|
||||
#endif
|
||||
pc = uc->uc_mcontext.gregs[EIP];
|
||||
pold_set = &uc->uc_sigmask;
|
||||
return handle_cpu_signal(pc, pold_set);
|
||||
|
@ -42,8 +42,7 @@
|
||||
#define DLINFO_ITEMS 12
|
||||
|
||||
/* Where we find X86 libraries... */
|
||||
//#define X86_DEFAULT_LIB_DIR "/usr/x86/"
|
||||
#define X86_DEFAULT_LIB_DIR "/"
|
||||
|
||||
|
||||
//extern void * mmap4k();
|
||||
#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
|
||||
* 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) {
|
||||
free (elf_phdata);
|
||||
@ -646,11 +646,11 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
|
||||
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);
|
||||
if(retval >= 0) {
|
||||
retval = read(bprm->fd,
|
||||
elf_interpreter+strlen(X86_DEFAULT_LIB_DIR),
|
||||
elf_interpreter+strlen(bprm->interp_prefix),
|
||||
elf_ppnt->p_filesz);
|
||||
}
|
||||
if(retval < 0) {
|
||||
@ -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 linux_binprm bprm;
|
||||
@ -930,6 +931,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp,
|
||||
else {
|
||||
bprm.fd = retval;
|
||||
}
|
||||
bprm.interp_prefix = (char *)interp_prefix;
|
||||
bprm.filename = (char *)filename;
|
||||
bprm.sh_bang = 0;
|
||||
bprm.loader = 0;
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
FILE *logfile = NULL;
|
||||
int loglevel;
|
||||
const char *interp_prefix = CONFIG_QEMU_PREFIX "/qemu-i386";
|
||||
|
||||
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
|
||||
we allocate a bigger stack. Need a better solution, for example
|
||||
@ -172,9 +173,16 @@ void cpu_loop(struct CPUX86State *env)
|
||||
void usage(void)
|
||||
{
|
||||
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"
|
||||
);
|
||||
"\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);
|
||||
}
|
||||
|
||||
@ -188,15 +196,41 @@ int main(int argc, char **argv)
|
||||
struct image_info info1, *info = &info1;
|
||||
CPUX86State *env;
|
||||
int optind;
|
||||
const char *r;
|
||||
|
||||
if (argc <= 1)
|
||||
usage();
|
||||
loglevel = 0;
|
||||
optind = 1;
|
||||
if (argv[optind] && !strcmp(argv[optind], "-d")) {
|
||||
loglevel = 1;
|
||||
for(;;) {
|
||||
if (optind >= argc)
|
||||
break;
|
||||
r = argv[optind];
|
||||
if (r[0] != '-')
|
||||
break;
|
||||
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];
|
||||
|
||||
/* init debug */
|
||||
@ -215,7 +249,7 @@ int main(int argc, char **argv)
|
||||
/* Zero out 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);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -33,7 +33,8 @@ struct image_info {
|
||||
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);
|
||||
|
||||
void target_set_brk(char *new_brk);
|
||||
|
@ -1,5 +1,23 @@
|
||||
/* 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)
|
||||
{
|
||||
A0 = REG;
|
||||
|
@ -4,21 +4,20 @@
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 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 program 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 General Public License for more details.
|
||||
* 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 General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* 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
|
||||
*/
|
||||
|
||||
#define DATA_BITS (1 << (3 + SHIFT))
|
||||
#define SHIFT_MASK (DATA_BITS - 1)
|
||||
#define SIGN_MASK (1 << (DATA_BITS - 1))
|
||||
|
@ -73,26 +73,53 @@ maximum performances.
|
||||
|
||||
@chapter Invocation
|
||||
|
||||
@section Quick Start
|
||||
|
||||
In order to launch a Linux process, QEMU needs the process executable
|
||||
itself and all the target (x86) dynamic libraries used by it. Currently,
|
||||
QEMU is not distributed with the necessary packages so that you can test
|
||||
it easily on non x86 CPUs.
|
||||
itself and all the target (x86) dynamic libraries used by it.
|
||||
|
||||
However, the statically x86 binary 'tests/hello' can be used to do a
|
||||
first test:
|
||||
@itemize
|
||||
|
||||
@item On x86, you can just try to launch any process by using the native
|
||||
libraries:
|
||||
|
||||
@example
|
||||
qemu tests/hello
|
||||
qemu -L / /bin/ls
|
||||
@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
|
||||
qemu /usr/local/qemu-i386/bin/ls
|
||||
@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
|
||||
qemu /bin/ls -l
|
||||
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
|
||||
|
||||
@section QEMU compared to other emulators
|
||||
|
@ -28,7 +28,7 @@ testthread: testthread.c
|
||||
# i386 emulation test (test various opcodes) */
|
||||
test-i386: test-i386.c test-i386-code16.S \
|
||||
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
|
||||
ifeq ($(ARCH),i386)
|
||||
|
@ -15,21 +15,34 @@ void alarm_handler(int sig)
|
||||
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)
|
||||
{
|
||||
printf("EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
|
||||
"ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
|
||||
"EFL=%08x EIP=%08x\n",
|
||||
uc->uc_mcontext.gregs[EAX],
|
||||
uc->uc_mcontext.gregs[EBX],
|
||||
uc->uc_mcontext.gregs[ECX],
|
||||
uc->uc_mcontext.gregs[EDX],
|
||||
uc->uc_mcontext.gregs[ESI],
|
||||
uc->uc_mcontext.gregs[EDI],
|
||||
uc->uc_mcontext.gregs[EBP],
|
||||
uc->uc_mcontext.gregs[ESP],
|
||||
uc->uc_mcontext.gregs[EFL],
|
||||
uc->uc_mcontext.gregs[EIP]);
|
||||
uc->uc_mcontext.gregs[REG_EAX],
|
||||
uc->uc_mcontext.gregs[REG_EBX],
|
||||
uc->uc_mcontext.gregs[REG_ECX],
|
||||
uc->uc_mcontext.gregs[REG_EDX],
|
||||
uc->uc_mcontext.gregs[REG_ESI],
|
||||
uc->uc_mcontext.gregs[REG_EDI],
|
||||
uc->uc_mcontext.gregs[REG_EBP],
|
||||
uc->uc_mcontext.gregs[REG_ESP],
|
||||
uc->uc_mcontext.gregs[REG_EFL],
|
||||
uc->uc_mcontext.gregs[REG_EIP]);
|
||||
}
|
||||
|
||||
void sig_handler(int sig, siginfo_t *info, void *puc)
|
||||
|
Loading…
Reference in New Issue
Block a user