Commit 586314f2aa62990dead8144e780c4c8c498eece6
1 parent
0ecfa993
better debug support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@18 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
113 additions
and
60 deletions
Makefile
| @@ -34,13 +34,10 @@ DEFINES+=-D_GNU_SOURCE | @@ -34,13 +34,10 @@ DEFINES+=-D_GNU_SOURCE | ||
| 34 | DEFINES+=-DCONFIG_PREFIX=\"/usr/local\" | 34 | DEFINES+=-DCONFIG_PREFIX=\"/usr/local\" |
| 35 | LDSCRIPT=$(ARCH).ld | 35 | LDSCRIPT=$(ARCH).ld |
| 36 | LIBS+=-ldl -lm | 36 | LIBS+=-ldl -lm |
| 37 | +VERSION=0.1 | ||
| 37 | 38 | ||
| 38 | -#DEFINES+= -DGEMU -DDOSEMU -DNO_TRACE_MSGS | ||
| 39 | -#OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \ | ||
| 40 | -# i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \ | ||
| 41 | -# i386/dis8086.o i386/emu-ldt.o | 39 | +OBJS= elfload.o main.o thunk.o syscall.o |
| 42 | OBJS+=translate-i386.o op-i386.o | 40 | OBJS+=translate-i386.o op-i386.o |
| 43 | -OBJS+= elfload.o main.o thunk.o syscall.o | ||
| 44 | # NOTE: the disassembler code is only needed for debugging | 41 | # NOTE: the disassembler code is only needed for debugging |
| 45 | OBJS+=i386-dis.o dis-buf.o | 42 | OBJS+=i386-dis.o dis-buf.o |
| 46 | SRCS = $(OBJS:.o=.c) | 43 | SRCS = $(OBJS:.o=.c) |
| @@ -53,15 +50,6 @@ gemu: $(OBJS) | @@ -53,15 +50,6 @@ gemu: $(OBJS) | ||
| 53 | depend: $(SRCS) | 50 | depend: $(SRCS) |
| 54 | $(CC) -MM $(CFLAGS) $^ 1>.depend | 51 | $(CC) -MM $(CFLAGS) $^ 1>.depend |
| 55 | 52 | ||
| 56 | -# old i386 emulator | ||
| 57 | -i386/interp_32_32.o: i386/interp_32_32.c i386/interp_gen.h | ||
| 58 | - | ||
| 59 | -i386/interp_gen.h: i386/gencode | ||
| 60 | - ./i386/gencode > $@ | ||
| 61 | - | ||
| 62 | -i386/gencode: i386/gencode.c | ||
| 63 | - $(CC) -O2 -Wall -g $< -o $@ | ||
| 64 | - | ||
| 65 | # new i386 emulator | 53 | # new i386 emulator |
| 66 | dyngen: dyngen.c | 54 | dyngen: dyngen.c |
| 67 | $(HOST_CC) -O2 -Wall -g $< -o $@ | 55 | $(HOST_CC) -O2 -Wall -g $< -o $@ |
| @@ -78,7 +66,7 @@ op-i386.o: op-i386.c opreg_template.h ops_template.h | @@ -78,7 +66,7 @@ op-i386.o: op-i386.c opreg_template.h ops_template.h | ||
| 78 | $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< | 66 | $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< |
| 79 | 67 | ||
| 80 | clean: | 68 | clean: |
| 81 | - rm -f *.o *~ i386/*.o i386/*~ gemu TAGS | 69 | + rm -f *.o *~ gemu dyngen TAGS |
| 82 | 70 | ||
| 83 | # various test targets | 71 | # various test targets |
| 84 | test speed: gemu | 72 | test speed: gemu |
| @@ -87,6 +75,26 @@ test speed: gemu | @@ -87,6 +75,26 @@ test speed: gemu | ||
| 87 | TAGS: | 75 | TAGS: |
| 88 | etags *.[ch] i386/*.[ch] | 76 | etags *.[ch] i386/*.[ch] |
| 89 | 77 | ||
| 78 | +FILES= \ | ||
| 79 | +COPYING.LIB dyngen.c ioctls.h ops_template.h syscall_types.h\ | ||
| 80 | +Makefile elf.h linux_bin.h segment.h thunk.c\ | ||
| 81 | +TODO elfload.c main.c signal.c thunk.h\ | ||
| 82 | +cpu-i386.h gemu.h op-i386.c syscall-i386.h translate-i386.c\ | ||
| 83 | +dis-asm.h gen-i386.h op-i386.h syscall.c\ | ||
| 84 | +dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\ | ||
| 85 | +i386.ld ppc.ld\ | ||
| 86 | +tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\ | ||
| 87 | +tests/test2.c tests/hello.c tests/sha1.c tests/test1.c | ||
| 88 | + | ||
| 89 | +FILE=gemu-$(VERSION) | ||
| 90 | + | ||
| 91 | +tar: | ||
| 92 | + rm -rf /tmp/$(FILE) | ||
| 93 | + mkdir -p /tmp/$(FILE) | ||
| 94 | + cp -P $(FILES) /tmp/$(FILE) | ||
| 95 | + ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) ) | ||
| 96 | + rm -rf /tmp/$(FILE) | ||
| 97 | + | ||
| 90 | ifneq ($(wildcard .depend),) | 98 | ifneq ($(wildcard .depend),) |
| 91 | include .depend | 99 | include .depend |
| 92 | endif | 100 | endif |
linux-user/main.c
| @@ -27,6 +27,11 @@ | @@ -27,6 +27,11 @@ | ||
| 27 | 27 | ||
| 28 | #include "cpu-i386.h" | 28 | #include "cpu-i386.h" |
| 29 | 29 | ||
| 30 | +#define DEBUG_LOGFILE "/tmp/gemu.log" | ||
| 31 | + | ||
| 32 | +FILE *logfile = NULL; | ||
| 33 | +int loglevel; | ||
| 34 | + | ||
| 30 | unsigned long x86_stack_size; | 35 | unsigned long x86_stack_size; |
| 31 | unsigned long stktop; | 36 | unsigned long stktop; |
| 32 | 37 | ||
| @@ -83,7 +88,7 @@ int cpu_x86_inl(int addr) | @@ -83,7 +88,7 @@ int cpu_x86_inl(int addr) | ||
| 83 | void usage(void) | 88 | void usage(void) |
| 84 | { | 89 | { |
| 85 | printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n" | 90 | printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n" |
| 86 | - "usage: gemu program [arguments...]\n" | 91 | + "usage: gemu [-d] program [arguments...]\n" |
| 87 | "Linux x86 emulator\n" | 92 | "Linux x86 emulator\n" |
| 88 | ); | 93 | ); |
| 89 | exit(1); | 94 | exit(1); |
| @@ -95,11 +100,27 @@ int main(int argc, char **argv) | @@ -95,11 +100,27 @@ int main(int argc, char **argv) | ||
| 95 | struct target_pt_regs regs1, *regs = ®s1; | 100 | struct target_pt_regs regs1, *regs = ®s1; |
| 96 | struct image_info info1, *info = &info1; | 101 | struct image_info info1, *info = &info1; |
| 97 | CPUX86State *env; | 102 | CPUX86State *env; |
| 103 | + int optind; | ||
| 98 | 104 | ||
| 99 | if (argc <= 1) | 105 | if (argc <= 1) |
| 100 | usage(); | 106 | usage(); |
| 101 | - | ||
| 102 | - filename = argv[1]; | 107 | + loglevel = 0; |
| 108 | + optind = 1; | ||
| 109 | + if (argv[optind] && !strcmp(argv[optind], "-d")) { | ||
| 110 | + loglevel = 1; | ||
| 111 | + optind++; | ||
| 112 | + } | ||
| 113 | + filename = argv[optind]; | ||
| 114 | + | ||
| 115 | + /* init debug */ | ||
| 116 | + if (loglevel) { | ||
| 117 | + logfile = fopen(DEBUG_LOGFILE, "w"); | ||
| 118 | + if (!logfile) { | ||
| 119 | + perror(DEBUG_LOGFILE); | ||
| 120 | + exit(1); | ||
| 121 | + } | ||
| 122 | + setvbuf(logfile, NULL, _IOLBF, 0); | ||
| 123 | + } | ||
| 103 | 124 | ||
| 104 | /* Zero out regs */ | 125 | /* Zero out regs */ |
| 105 | memset(regs, 0, sizeof(struct target_pt_regs)); | 126 | memset(regs, 0, sizeof(struct target_pt_regs)); |
op-i386.c
| 1 | +#define DEBUG_EXEC | ||
| 2 | + | ||
| 1 | typedef unsigned char uint8_t; | 3 | typedef unsigned char uint8_t; |
| 2 | typedef unsigned short uint16_t; | 4 | typedef unsigned short uint16_t; |
| 3 | typedef unsigned int uint32_t; | 5 | typedef unsigned int uint32_t; |
| @@ -10,6 +12,11 @@ typedef signed long long int64_t; | @@ -10,6 +12,11 @@ typedef signed long long int64_t; | ||
| 10 | 12 | ||
| 11 | #define NULL 0 | 13 | #define NULL 0 |
| 12 | 14 | ||
| 15 | +typedef struct FILE FILE; | ||
| 16 | +extern FILE *logfile; | ||
| 17 | +extern int loglevel; | ||
| 18 | +extern int fprintf(FILE *, const char *, ...); | ||
| 19 | + | ||
| 13 | #ifdef __i386__ | 20 | #ifdef __i386__ |
| 14 | register int T0 asm("esi"); | 21 | register int T0 asm("esi"); |
| 15 | register int T1 asm("ebx"); | 22 | register int T1 asm("ebx"); |
| @@ -1636,6 +1643,32 @@ void OPPROTO op_fcos(void) | @@ -1636,6 +1643,32 @@ void OPPROTO op_fcos(void) | ||
| 1636 | /* main execution loop */ | 1643 | /* main execution loop */ |
| 1637 | uint8_t code_gen_buffer[65536]; | 1644 | uint8_t code_gen_buffer[65536]; |
| 1638 | 1645 | ||
| 1646 | +#ifdef DEBUG_EXEC | ||
| 1647 | +static const char *cc_op_str[] = { | ||
| 1648 | + "DYNAMIC", | ||
| 1649 | + "EFLAGS", | ||
| 1650 | + "MUL", | ||
| 1651 | + "ADDB", | ||
| 1652 | + "ADDW", | ||
| 1653 | + "ADDL", | ||
| 1654 | + "SUBB", | ||
| 1655 | + "SUBW", | ||
| 1656 | + "SUBL", | ||
| 1657 | + "LOGICB", | ||
| 1658 | + "LOGICW", | ||
| 1659 | + "LOGICL", | ||
| 1660 | + "INCB", | ||
| 1661 | + "INCW", | ||
| 1662 | + "INCL", | ||
| 1663 | + "DECB", | ||
| 1664 | + "DECW", | ||
| 1665 | + "DECL", | ||
| 1666 | + "SHLB", | ||
| 1667 | + "SHLW", | ||
| 1668 | + "SHLL", | ||
| 1669 | +}; | ||
| 1670 | +#endif | ||
| 1671 | + | ||
| 1639 | int cpu_x86_exec(CPUX86State *env1) | 1672 | int cpu_x86_exec(CPUX86State *env1) |
| 1640 | { | 1673 | { |
| 1641 | int saved_T0, saved_T1, saved_A0; | 1674 | int saved_T0, saved_T1, saved_A0; |
| @@ -1653,6 +1686,17 @@ int cpu_x86_exec(CPUX86State *env1) | @@ -1653,6 +1686,17 @@ int cpu_x86_exec(CPUX86State *env1) | ||
| 1653 | /* prepare setjmp context for exception handling */ | 1686 | /* prepare setjmp context for exception handling */ |
| 1654 | if (setjmp(env->jmp_env) == 0) { | 1687 | if (setjmp(env->jmp_env) == 0) { |
| 1655 | for(;;) { | 1688 | for(;;) { |
| 1689 | +#ifdef DEBUG_EXEC | ||
| 1690 | + if (loglevel) { | ||
| 1691 | + fprintf(logfile, | ||
| 1692 | + "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n" | ||
| 1693 | + "ESI=%08x ESI=%08X EBP=%08x ESP=%08x\n" | ||
| 1694 | + "CCS=%08x CCD=%08x CCOP=%s\n", | ||
| 1695 | + env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX], | ||
| 1696 | + env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP], | ||
| 1697 | + env->cc_src, env->cc_dst, cc_op_str[env->cc_op]); | ||
| 1698 | + } | ||
| 1699 | +#endif | ||
| 1656 | cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); | 1700 | cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); |
| 1657 | /* execute the generated code */ | 1701 | /* execute the generated code */ |
| 1658 | gen_func = (void *)code_gen_buffer; | 1702 | gen_func = (void *)code_gen_buffer; |
translate-i386.c
| @@ -5,23 +5,21 @@ | @@ -5,23 +5,21 @@ | ||
| 5 | #include <inttypes.h> | 5 | #include <inttypes.h> |
| 6 | #include <assert.h> | 6 | #include <assert.h> |
| 7 | 7 | ||
| 8 | -/* dump all code */ | ||
| 9 | #define DEBUG_DISAS | 8 | #define DEBUG_DISAS |
| 10 | -#define DEBUG_LOGFILE "/tmp/gemu.log" | ||
| 11 | 9 | ||
| 10 | +#define IN_OP_I386 | ||
| 11 | +#include "cpu-i386.h" | ||
| 12 | + | ||
| 13 | +/* dump all code */ | ||
| 12 | #ifdef DEBUG_DISAS | 14 | #ifdef DEBUG_DISAS |
| 13 | #include "dis-asm.h" | 15 | #include "dis-asm.h" |
| 14 | #endif | 16 | #endif |
| 15 | 17 | ||
| 16 | -#define IN_OP_I386 | ||
| 17 | -#include "cpu-i386.h" | ||
| 18 | - | ||
| 19 | static uint8_t *gen_code_ptr; | 18 | static uint8_t *gen_code_ptr; |
| 20 | int __op_param1, __op_param2, __op_param3; | 19 | int __op_param1, __op_param2, __op_param3; |
| 21 | 20 | ||
| 22 | -#ifdef DEBUG_DISAS | ||
| 23 | -static FILE *logfile = NULL; | ||
| 24 | -#endif | 21 | +extern FILE *logfile; |
| 22 | +extern int loglevel; | ||
| 25 | 23 | ||
| 26 | /* supress that */ | 24 | /* supress that */ |
| 27 | static void error(const char *fmt, ...) | 25 | static void error(const char *fmt, ...) |
| @@ -716,9 +714,6 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -716,9 +714,6 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
| 716 | int reg1, reg2, opreg; | 714 | int reg1, reg2, opreg; |
| 717 | int mod, rm, code; | 715 | int mod, rm, code; |
| 718 | 716 | ||
| 719 | -#ifdef DEBUG_DISAS | ||
| 720 | - fprintf(logfile, "modrm=0x%x\n", modrm); | ||
| 721 | -#endif | ||
| 722 | mod = (modrm >> 6) & 3; | 717 | mod = (modrm >> 6) & 3; |
| 723 | rm = modrm & 7; | 718 | rm = modrm & 7; |
| 724 | 719 | ||
| @@ -731,9 +726,6 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | @@ -731,9 +726,6 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ | ||
| 731 | if (base == 4) { | 726 | if (base == 4) { |
| 732 | havesib = 1; | 727 | havesib = 1; |
| 733 | code = ldub(s->pc++); | 728 | code = ldub(s->pc++); |
| 734 | -#ifdef DEBUG_DISAS | ||
| 735 | - fprintf(logfile, "sib=0x%x\n", code); | ||
| 736 | -#endif | ||
| 737 | scale = (code >> 6) & 3; | 729 | scale = (code >> 6) & 3; |
| 738 | index = (code >> 3) & 7; | 730 | index = (code >> 3) & 7; |
| 739 | base = code & 7; | 731 | base = code & 7; |
| @@ -988,11 +980,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | @@ -988,11 +980,6 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) | ||
| 988 | // cur_pc = s->pc; /* for insn generation */ | 980 | // cur_pc = s->pc; /* for insn generation */ |
| 989 | next_byte: | 981 | next_byte: |
| 990 | b = ldub(s->pc); | 982 | b = ldub(s->pc); |
| 991 | -#ifdef DEBUG_DISAS | ||
| 992 | - fprintf(logfile, "ib=0x%02x\n", b); | ||
| 993 | -#endif | ||
| 994 | - if (b < 0) | ||
| 995 | - return -1; | ||
| 996 | s->pc++; | 983 | s->pc++; |
| 997 | /* check prefixes */ | 984 | /* check prefixes */ |
| 998 | switch (b) { | 985 | switch (b) { |
| @@ -2247,33 +2234,26 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, | @@ -2247,33 +2234,26 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, | ||
| 2247 | gen_start(); | 2234 | gen_start(); |
| 2248 | 2235 | ||
| 2249 | #ifdef DEBUG_DISAS | 2236 | #ifdef DEBUG_DISAS |
| 2250 | - if (!logfile) { | ||
| 2251 | - logfile = fopen(DEBUG_LOGFILE, "w"); | ||
| 2252 | - if (!logfile) { | ||
| 2253 | - perror(DEBUG_LOGFILE); | ||
| 2254 | - exit(1); | ||
| 2255 | - } | ||
| 2256 | - setvbuf(logfile, NULL, _IOLBF, 0); | ||
| 2257 | - } | ||
| 2258 | - | ||
| 2259 | - INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf); | ||
| 2260 | - disasm_info.buffer = pc_start; | ||
| 2261 | - disasm_info.buffer_vma = (unsigned long)pc_start; | ||
| 2262 | - disasm_info.buffer_length = 15; | 2237 | + if (loglevel) { |
| 2238 | + INIT_DISASSEMBLE_INFO(disasm_info, logfile, fprintf); | ||
| 2239 | + disasm_info.buffer = pc_start; | ||
| 2240 | + disasm_info.buffer_vma = (unsigned long)pc_start; | ||
| 2241 | + disasm_info.buffer_length = 15; | ||
| 2263 | #if 0 | 2242 | #if 0 |
| 2264 | - disasm_info.flavour = bfd_get_flavour (abfd); | ||
| 2265 | - disasm_info.arch = bfd_get_arch (abfd); | ||
| 2266 | - disasm_info.mach = bfd_get_mach (abfd); | 2243 | + disasm_info.flavour = bfd_get_flavour (abfd); |
| 2244 | + disasm_info.arch = bfd_get_arch (abfd); | ||
| 2245 | + disasm_info.mach = bfd_get_mach (abfd); | ||
| 2267 | #endif | 2246 | #endif |
| 2268 | #ifdef WORDS_BIGENDIAN | 2247 | #ifdef WORDS_BIGENDIAN |
| 2269 | - disasm_info.endian = BFD_ENDIAN_BIG; | 2248 | + disasm_info.endian = BFD_ENDIAN_BIG; |
| 2270 | #else | 2249 | #else |
| 2271 | - disasm_info.endian = BFD_ENDIAN_LITTLE; | 2250 | + disasm_info.endian = BFD_ENDIAN_LITTLE; |
| 2272 | #endif | 2251 | #endif |
| 2273 | - fprintf(logfile, "IN:\n"); | ||
| 2274 | - fprintf(logfile, "0x%08lx: ", (long)pc_start); | ||
| 2275 | - print_insn_i386((unsigned long)pc_start, &disasm_info); | ||
| 2276 | - fprintf(logfile, "\n\n"); | 2252 | + fprintf(logfile, "IN:\n"); |
| 2253 | + fprintf(logfile, "0x%08lx: ", (long)pc_start); | ||
| 2254 | + print_insn_i386((unsigned long)pc_start, &disasm_info); | ||
| 2255 | + fprintf(logfile, "\n\n"); | ||
| 2256 | + } | ||
| 2277 | #endif | 2257 | #endif |
| 2278 | is_jmp = 0; | 2258 | is_jmp = 0; |
| 2279 | ret = disas_insn(dc, pc_start, &is_jmp); | 2259 | ret = disas_insn(dc, pc_start, &is_jmp); |
| @@ -2290,7 +2270,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, | @@ -2290,7 +2270,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int *gen_code_size_ptr, | ||
| 2290 | *gen_code_size_ptr = gen_code_ptr - gen_code_buf; | 2270 | *gen_code_size_ptr = gen_code_ptr - gen_code_buf; |
| 2291 | 2271 | ||
| 2292 | #ifdef DEBUG_DISAS | 2272 | #ifdef DEBUG_DISAS |
| 2293 | - { | 2273 | + if (loglevel) { |
| 2294 | uint8_t *pc; | 2274 | uint8_t *pc; |
| 2295 | int count; | 2275 | int count; |
| 2296 | 2276 |