Commit 4c3a88a284b288e0ed3c097de7fc07111d848003
1 parent
d6b49367
gdb stub breakpoints support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@332 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
11 changed files
with
151 additions
and
25 deletions
cpu-all.h
| @@ -313,9 +313,12 @@ extern CPUState *cpu_single_env; | @@ -313,9 +313,12 @@ extern CPUState *cpu_single_env; | ||
| 313 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ | 313 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ |
| 314 | void cpu_interrupt(CPUState *s, int mask); | 314 | void cpu_interrupt(CPUState *s, int mask); |
| 315 | 315 | ||
| 316 | +int cpu_breakpoint_insert(CPUState *env, uint32_t pc); | ||
| 317 | +int cpu_breakpoint_remove(CPUState *env, uint32_t pc); | ||
| 318 | + | ||
| 316 | /* gdb stub API */ | 319 | /* gdb stub API */ |
| 317 | extern int gdbstub_fd; | 320 | extern int gdbstub_fd; |
| 318 | CPUState *cpu_gdbstub_get_env(void *opaque); | 321 | CPUState *cpu_gdbstub_get_env(void *opaque); |
| 319 | -int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port); | 322 | +int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port); |
| 320 | 323 | ||
| 321 | #endif /* CPU_ALL_H */ | 324 | #endif /* CPU_ALL_H */ |
cpu-exec.c
| @@ -280,7 +280,7 @@ int cpu_exec(CPUState *env1) | @@ -280,7 +280,7 @@ int cpu_exec(CPUState *env1) | ||
| 280 | tb->tc_ptr = tc_ptr; | 280 | tb->tc_ptr = tc_ptr; |
| 281 | tb->cs_base = (unsigned long)cs_base; | 281 | tb->cs_base = (unsigned long)cs_base; |
| 282 | tb->flags = flags; | 282 | tb->flags = flags; |
| 283 | - ret = cpu_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size); | 283 | + ret = cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); |
| 284 | #if defined(TARGET_I386) | 284 | #if defined(TARGET_I386) |
| 285 | /* XXX: suppress that, this is incorrect */ | 285 | /* XXX: suppress that, this is incorrect */ |
| 286 | /* if invalid instruction, signal it */ | 286 | /* if invalid instruction, signal it */ |
cpu-i386.h
| @@ -155,6 +155,9 @@ | @@ -155,6 +155,9 @@ | ||
| 155 | 155 | ||
| 156 | #define EXCP_INTERRUPT 256 /* async interruption */ | 156 | #define EXCP_INTERRUPT 256 /* async interruption */ |
| 157 | #define EXCP_HLT 257 /* hlt instruction reached */ | 157 | #define EXCP_HLT 257 /* hlt instruction reached */ |
| 158 | +#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */ | ||
| 159 | + | ||
| 160 | +#define MAX_BREAKPOINTS 32 | ||
| 158 | 161 | ||
| 159 | enum { | 162 | enum { |
| 160 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ | 163 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ |
| @@ -270,6 +273,9 @@ typedef struct CPUX86State { | @@ -270,6 +273,9 @@ typedef struct CPUX86State { | ||
| 270 | uint32_t dr[8]; /* debug registers */ | 273 | uint32_t dr[8]; /* debug registers */ |
| 271 | int interrupt_request; | 274 | int interrupt_request; |
| 272 | int user_mode_only; /* user mode only simulation */ | 275 | int user_mode_only; /* user mode only simulation */ |
| 276 | + | ||
| 277 | + uint32_t breakpoints[MAX_BREAKPOINTS]; | ||
| 278 | + int nb_breakpoints; | ||
| 273 | 279 | ||
| 274 | /* user data */ | 280 | /* user data */ |
| 275 | void *opaque; | 281 | void *opaque; |
exec.c
| @@ -617,6 +617,48 @@ static void tb_reset_jump_recursive(TranslationBlock *tb) | @@ -617,6 +617,48 @@ static void tb_reset_jump_recursive(TranslationBlock *tb) | ||
| 617 | tb_reset_jump_recursive2(tb, 1); | 617 | tb_reset_jump_recursive2(tb, 1); |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | +/* add a breakpoint */ | ||
| 621 | +int cpu_breakpoint_insert(CPUState *env, uint32_t pc) | ||
| 622 | +{ | ||
| 623 | +#if defined(TARGET_I386) | ||
| 624 | + int i; | ||
| 625 | + | ||
| 626 | + for(i = 0; i < env->nb_breakpoints; i++) { | ||
| 627 | + if (env->breakpoints[i] == pc) | ||
| 628 | + return 0; | ||
| 629 | + } | ||
| 630 | + | ||
| 631 | + if (env->nb_breakpoints >= MAX_BREAKPOINTS) | ||
| 632 | + return -1; | ||
| 633 | + env->breakpoints[env->nb_breakpoints++] = pc; | ||
| 634 | + tb_invalidate_page(pc); | ||
| 635 | + return 0; | ||
| 636 | +#else | ||
| 637 | + return -1; | ||
| 638 | +#endif | ||
| 639 | +} | ||
| 640 | + | ||
| 641 | +/* remove a breakpoint */ | ||
| 642 | +int cpu_breakpoint_remove(CPUState *env, uint32_t pc) | ||
| 643 | +{ | ||
| 644 | +#if defined(TARGET_I386) | ||
| 645 | + int i; | ||
| 646 | + for(i = 0; i < env->nb_breakpoints; i++) { | ||
| 647 | + if (env->breakpoints[i] == pc) | ||
| 648 | + goto found; | ||
| 649 | + } | ||
| 650 | + return -1; | ||
| 651 | + found: | ||
| 652 | + memmove(&env->breakpoints[i], &env->breakpoints[i + 1], | ||
| 653 | + (env->nb_breakpoints - (i + 1)) * sizeof(env->breakpoints[0])); | ||
| 654 | + env->nb_breakpoints--; | ||
| 655 | + tb_invalidate_page(pc); | ||
| 656 | + return 0; | ||
| 657 | +#else | ||
| 658 | + return -1; | ||
| 659 | +#endif | ||
| 660 | +} | ||
| 661 | + | ||
| 620 | /* mask must never be zero */ | 662 | /* mask must never be zero */ |
| 621 | void cpu_interrupt(CPUState *env, int mask) | 663 | void cpu_interrupt(CPUState *env, int mask) |
| 622 | { | 664 | { |
exec.h
| @@ -58,10 +58,10 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | @@ -58,10 +58,10 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | ||
| 58 | extern FILE *logfile; | 58 | extern FILE *logfile; |
| 59 | extern int loglevel; | 59 | extern int loglevel; |
| 60 | 60 | ||
| 61 | -int gen_intermediate_code(struct TranslationBlock *tb); | ||
| 62 | -int gen_intermediate_code_pc(struct TranslationBlock *tb); | 61 | +int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb); |
| 62 | +int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb); | ||
| 63 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf); | 63 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf); |
| 64 | -int cpu_gen_code(struct TranslationBlock *tb, | 64 | +int cpu_gen_code(CPUState *env, struct TranslationBlock *tb, |
| 65 | int max_code_size, int *gen_code_size_ptr); | 65 | int max_code_size, int *gen_code_size_ptr); |
| 66 | int cpu_restore_state(struct TranslationBlock *tb, | 66 | int cpu_restore_state(struct TranslationBlock *tb, |
| 67 | CPUState *env, unsigned long searched_pc); | 67 | CPUState *env, unsigned long searched_pc); |
gdbstub.c
| @@ -37,7 +37,7 @@ | @@ -37,7 +37,7 @@ | ||
| 37 | #include "thunk.h" | 37 | #include "thunk.h" |
| 38 | #include "exec.h" | 38 | #include "exec.h" |
| 39 | 39 | ||
| 40 | -//#define DEBUG_GDB | 40 | +#define DEBUG_GDB |
| 41 | 41 | ||
| 42 | int gdbstub_fd = -1; | 42 | int gdbstub_fd = -1; |
| 43 | 43 | ||
| @@ -283,11 +283,11 @@ static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write) | @@ -283,11 +283,11 @@ static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write) | ||
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | /* port = 0 means default port */ | 285 | /* port = 0 means default port */ |
| 286 | -int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | 286 | +int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) |
| 287 | { | 287 | { |
| 288 | CPUState *env; | 288 | CPUState *env; |
| 289 | const char *p; | 289 | const char *p; |
| 290 | - int ret, ch, nb_regs, i; | 290 | + int ret, ch, nb_regs, i, type; |
| 291 | char buf[4096]; | 291 | char buf[4096]; |
| 292 | uint8_t mem_buf[2000]; | 292 | uint8_t mem_buf[2000]; |
| 293 | uint32_t *registers; | 293 | uint32_t *registers; |
| @@ -309,8 +309,19 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | @@ -309,8 +309,19 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | ||
| 309 | put_packet(buf); | 309 | put_packet(buf); |
| 310 | break; | 310 | break; |
| 311 | case 'c': | 311 | case 'c': |
| 312 | - main_loop(opaque); | ||
| 313 | - snprintf(buf, sizeof(buf), "S%02x", 0); | 312 | + if (*p != '\0') { |
| 313 | + addr = strtoul(p, (char **)&p, 16); | ||
| 314 | + env = cpu_gdbstub_get_env(opaque); | ||
| 315 | +#if defined(TARGET_I386) | ||
| 316 | + env->eip = addr; | ||
| 317 | +#endif | ||
| 318 | + } | ||
| 319 | + ret = main_loop(opaque); | ||
| 320 | + if (ret == EXCP_DEBUG) | ||
| 321 | + ret = SIGTRAP; | ||
| 322 | + else | ||
| 323 | + ret = 0; | ||
| 324 | + snprintf(buf, sizeof(buf), "S%02x", ret); | ||
| 314 | put_packet(buf); | 325 | put_packet(buf); |
| 315 | break; | 326 | break; |
| 316 | case 'g': | 327 | case 'g': |
| @@ -379,6 +390,40 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | @@ -379,6 +390,40 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | ||
| 379 | else | 390 | else |
| 380 | put_packet("OK"); | 391 | put_packet("OK"); |
| 381 | break; | 392 | break; |
| 393 | + case 'Z': | ||
| 394 | + type = strtoul(p, (char **)&p, 16); | ||
| 395 | + if (*p == ',') | ||
| 396 | + p++; | ||
| 397 | + addr = strtoul(p, (char **)&p, 16); | ||
| 398 | + if (*p == ',') | ||
| 399 | + p++; | ||
| 400 | + len = strtoul(p, (char **)&p, 16); | ||
| 401 | + if (type == 0 || type == 1) { | ||
| 402 | + env = cpu_gdbstub_get_env(opaque); | ||
| 403 | + if (cpu_breakpoint_insert(env, addr) < 0) | ||
| 404 | + goto breakpoint_error; | ||
| 405 | + put_packet("OK"); | ||
| 406 | + } else { | ||
| 407 | + breakpoint_error: | ||
| 408 | + put_packet("ENN"); | ||
| 409 | + } | ||
| 410 | + break; | ||
| 411 | + case 'z': | ||
| 412 | + type = strtoul(p, (char **)&p, 16); | ||
| 413 | + if (*p == ',') | ||
| 414 | + p++; | ||
| 415 | + addr = strtoul(p, (char **)&p, 16); | ||
| 416 | + if (*p == ',') | ||
| 417 | + p++; | ||
| 418 | + len = strtoul(p, (char **)&p, 16); | ||
| 419 | + if (type == 0 || type == 1) { | ||
| 420 | + env = cpu_gdbstub_get_env(opaque); | ||
| 421 | + cpu_breakpoint_remove(env, addr); | ||
| 422 | + put_packet("OK"); | ||
| 423 | + } else { | ||
| 424 | + goto breakpoint_error; | ||
| 425 | + } | ||
| 426 | + break; | ||
| 382 | default: | 427 | default: |
| 383 | /* put empty packet */ | 428 | /* put empty packet */ |
| 384 | buf[0] = '\0'; | 429 | buf[0] = '\0'; |
op-i386.c
| @@ -471,6 +471,12 @@ void OPPROTO op_hlt(void) | @@ -471,6 +471,12 @@ void OPPROTO op_hlt(void) | ||
| 471 | cpu_loop_exit(); | 471 | cpu_loop_exit(); |
| 472 | } | 472 | } |
| 473 | 473 | ||
| 474 | +void OPPROTO op_debug(void) | ||
| 475 | +{ | ||
| 476 | + env->exception_index = EXCP_DEBUG; | ||
| 477 | + cpu_loop_exit(); | ||
| 478 | +} | ||
| 479 | + | ||
| 474 | void OPPROTO op_raise_interrupt(void) | 480 | void OPPROTO op_raise_interrupt(void) |
| 475 | { | 481 | { |
| 476 | int intno; | 482 | int intno; |
translate-arm.c
| @@ -786,7 +786,9 @@ static void disas_arm_insn(DisasContext *s) | @@ -786,7 +786,9 @@ static void disas_arm_insn(DisasContext *s) | ||
| 786 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for | 786 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
| 787 | basic block 'tb'. If search_pc is TRUE, also generate PC | 787 | basic block 'tb'. If search_pc is TRUE, also generate PC |
| 788 | information for each intermediate instruction. */ | 788 | information for each intermediate instruction. */ |
| 789 | -static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc) | 789 | +static inline int gen_intermediate_code_internal(CPUState *env, |
| 790 | + TranslationBlock *tb, | ||
| 791 | + int search_pc) | ||
| 790 | { | 792 | { |
| 791 | DisasContext dc1, *dc = &dc1; | 793 | DisasContext dc1, *dc = &dc1; |
| 792 | uint16_t *gen_opc_end; | 794 | uint16_t *gen_opc_end; |
| @@ -853,14 +855,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -853,14 +855,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
| 853 | return 0; | 855 | return 0; |
| 854 | } | 856 | } |
| 855 | 857 | ||
| 856 | -int gen_intermediate_code(TranslationBlock *tb) | 858 | +int gen_intermediate_code(CPUState *env, TranslationBlock *tb) |
| 857 | { | 859 | { |
| 858 | - return gen_intermediate_code_internal(tb, 0); | 860 | + return gen_intermediate_code_internal(env, tb, 0); |
| 859 | } | 861 | } |
| 860 | 862 | ||
| 861 | -int gen_intermediate_code_pc(TranslationBlock *tb) | 863 | +int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) |
| 862 | { | 864 | { |
| 863 | - return gen_intermediate_code_internal(tb, 1); | 865 | + return gen_intermediate_code_internal(env, tb, 1); |
| 864 | } | 866 | } |
| 865 | 867 | ||
| 866 | CPUARMState *cpu_arm_init(void) | 868 | CPUARMState *cpu_arm_init(void) |
translate-i386.c
| @@ -1463,6 +1463,15 @@ static void gen_interrupt(DisasContext *s, int intno, | @@ -1463,6 +1463,15 @@ static void gen_interrupt(DisasContext *s, int intno, | ||
| 1463 | s->is_jmp = 1; | 1463 | s->is_jmp = 1; |
| 1464 | } | 1464 | } |
| 1465 | 1465 | ||
| 1466 | +static void gen_debug(DisasContext *s, unsigned int cur_eip) | ||
| 1467 | +{ | ||
| 1468 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
| 1469 | + gen_op_set_cc_op(s->cc_op); | ||
| 1470 | + gen_op_jmp_im(cur_eip); | ||
| 1471 | + gen_op_debug(); | ||
| 1472 | + s->is_jmp = 1; | ||
| 1473 | +} | ||
| 1474 | + | ||
| 1466 | /* generate a jump to eip. No segment change must happen before as a | 1475 | /* generate a jump to eip. No segment change must happen before as a |
| 1467 | direct call to the next block may occur */ | 1476 | direct call to the next block may occur */ |
| 1468 | static void gen_jmp(DisasContext *s, unsigned int eip) | 1477 | static void gen_jmp(DisasContext *s, unsigned int eip) |
| @@ -4080,7 +4089,9 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | @@ -4080,7 +4089,9 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | ||
| 4080 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for | 4089 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
| 4081 | basic block 'tb'. If search_pc is TRUE, also generate PC | 4090 | basic block 'tb'. If search_pc is TRUE, also generate PC |
| 4082 | information for each intermediate instruction. */ | 4091 | information for each intermediate instruction. */ |
| 4083 | -static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc) | 4092 | +static inline int gen_intermediate_code_internal(CPUState *env, |
| 4093 | + TranslationBlock *tb, | ||
| 4094 | + int search_pc) | ||
| 4084 | { | 4095 | { |
| 4085 | DisasContext dc1, *dc = &dc1; | 4096 | DisasContext dc1, *dc = &dc1; |
| 4086 | uint8_t *pc_ptr; | 4097 | uint8_t *pc_ptr; |
| @@ -4116,6 +4127,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -4116,6 +4127,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
| 4116 | pc_ptr = pc_start; | 4127 | pc_ptr = pc_start; |
| 4117 | lj = -1; | 4128 | lj = -1; |
| 4118 | do { | 4129 | do { |
| 4130 | + if (env->nb_breakpoints > 0) { | ||
| 4131 | + for(j = 0; j < env->nb_breakpoints; j++) { | ||
| 4132 | + if (env->breakpoints[j] == (unsigned long)pc_ptr) { | ||
| 4133 | + gen_debug(dc, pc_ptr - dc->cs_base); | ||
| 4134 | + goto the_end; | ||
| 4135 | + } | ||
| 4136 | + } | ||
| 4137 | + } | ||
| 4119 | if (search_pc) { | 4138 | if (search_pc) { |
| 4120 | j = gen_opc_ptr - gen_opc_buf; | 4139 | j = gen_opc_ptr - gen_opc_buf; |
| 4121 | if (lj < j) { | 4140 | if (lj < j) { |
| @@ -4160,6 +4179,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -4160,6 +4179,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
| 4160 | if (dc->tf) { | 4179 | if (dc->tf) { |
| 4161 | gen_op_raise_exception(EXCP01_SSTP); | 4180 | gen_op_raise_exception(EXCP01_SSTP); |
| 4162 | } | 4181 | } |
| 4182 | + the_end: | ||
| 4163 | if (dc->is_jmp != DISAS_TB_JUMP) { | 4183 | if (dc->is_jmp != DISAS_TB_JUMP) { |
| 4164 | /* indicate that the hash table must be used to find the next TB */ | 4184 | /* indicate that the hash table must be used to find the next TB */ |
| 4165 | gen_op_movl_T0_0(); | 4185 | gen_op_movl_T0_0(); |
| @@ -4202,14 +4222,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -4202,14 +4222,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
| 4202 | return 0; | 4222 | return 0; |
| 4203 | } | 4223 | } |
| 4204 | 4224 | ||
| 4205 | -int gen_intermediate_code(TranslationBlock *tb) | 4225 | +int gen_intermediate_code(CPUState *env, TranslationBlock *tb) |
| 4206 | { | 4226 | { |
| 4207 | - return gen_intermediate_code_internal(tb, 0); | 4227 | + return gen_intermediate_code_internal(env, tb, 0); |
| 4208 | } | 4228 | } |
| 4209 | 4229 | ||
| 4210 | -int gen_intermediate_code_pc(TranslationBlock *tb) | 4230 | +int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) |
| 4211 | { | 4231 | { |
| 4212 | - return gen_intermediate_code_internal(tb, 1); | 4232 | + return gen_intermediate_code_internal(env, tb, 1); |
| 4213 | } | 4233 | } |
| 4214 | 4234 | ||
| 4215 | CPUX86State *cpu_x86_init(void) | 4235 | CPUX86State *cpu_x86_init(void) |
translate.c
| @@ -107,13 +107,13 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | @@ -107,13 +107,13 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | ||
| 107 | '*gen_code_size_ptr' contains the size of the generated code (host | 107 | '*gen_code_size_ptr' contains the size of the generated code (host |
| 108 | code). | 108 | code). |
| 109 | */ | 109 | */ |
| 110 | -int cpu_gen_code(TranslationBlock *tb, | 110 | +int cpu_gen_code(CPUState *env, TranslationBlock *tb, |
| 111 | int max_code_size, int *gen_code_size_ptr) | 111 | int max_code_size, int *gen_code_size_ptr) |
| 112 | { | 112 | { |
| 113 | uint8_t *gen_code_buf; | 113 | uint8_t *gen_code_buf; |
| 114 | int gen_code_size; | 114 | int gen_code_size; |
| 115 | 115 | ||
| 116 | - if (gen_intermediate_code(tb) < 0) | 116 | + if (gen_intermediate_code(env, tb) < 0) |
| 117 | return -1; | 117 | return -1; |
| 118 | 118 | ||
| 119 | /* generate machine code */ | 119 | /* generate machine code */ |
| @@ -154,7 +154,7 @@ int cpu_restore_state(TranslationBlock *tb, | @@ -154,7 +154,7 @@ int cpu_restore_state(TranslationBlock *tb, | ||
| 154 | unsigned long tc_ptr; | 154 | unsigned long tc_ptr; |
| 155 | uint16_t *opc_ptr; | 155 | uint16_t *opc_ptr; |
| 156 | 156 | ||
| 157 | - if (gen_intermediate_code_pc(tb) < 0) | 157 | + if (gen_intermediate_code_pc(env, tb) < 0) |
| 158 | return -1; | 158 | return -1; |
| 159 | 159 | ||
| 160 | /* find opc index corresponding to search_pc */ | 160 | /* find opc index corresponding to search_pc */ |
vl.c
| @@ -2540,7 +2540,7 @@ CPUState *cpu_gdbstub_get_env(void *opaque) | @@ -2540,7 +2540,7 @@ CPUState *cpu_gdbstub_get_env(void *opaque) | ||
| 2540 | return global_env; | 2540 | return global_env; |
| 2541 | } | 2541 | } |
| 2542 | 2542 | ||
| 2543 | -void main_loop(void *opaque) | 2543 | +int main_loop(void *opaque) |
| 2544 | { | 2544 | { |
| 2545 | struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd, *gdb_ufd; | 2545 | struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd, *gdb_ufd; |
| 2546 | int ret, n, timeout; | 2546 | int ret, n, timeout; |
| @@ -2552,7 +2552,8 @@ void main_loop(void *opaque) | @@ -2552,7 +2552,8 @@ void main_loop(void *opaque) | ||
| 2552 | ret = cpu_x86_exec(env); | 2552 | ret = cpu_x86_exec(env); |
| 2553 | if (reset_requested) | 2553 | if (reset_requested) |
| 2554 | break; | 2554 | break; |
| 2555 | - | 2555 | + if (ret == EXCP_DEBUG) |
| 2556 | + return EXCP_DEBUG; | ||
| 2556 | /* if hlt instruction, we wait until the next IRQ */ | 2557 | /* if hlt instruction, we wait until the next IRQ */ |
| 2557 | if (ret == EXCP_HLT) | 2558 | if (ret == EXCP_HLT) |
| 2558 | timeout = 10; | 2559 | timeout = 10; |
| @@ -2618,6 +2619,7 @@ void main_loop(void *opaque) | @@ -2618,6 +2619,7 @@ void main_loop(void *opaque) | ||
| 2618 | timer_irq_pending = 0; | 2619 | timer_irq_pending = 0; |
| 2619 | } | 2620 | } |
| 2620 | } | 2621 | } |
| 2622 | + return EXCP_INTERRUPT; | ||
| 2621 | } | 2623 | } |
| 2622 | 2624 | ||
| 2623 | void help(void) | 2625 | void help(void) |