Commit 4c3a88a284b288e0ed3c097de7fc07111d848003

Authored by bellard
1 parent d6b49367

gdb stub breakpoints support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@332 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
... ... @@ -313,9 +313,12 @@ extern CPUState *cpu_single_env;
313 313 #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
314 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 319 /* gdb stub API */
317 320 extern int gdbstub_fd;
318 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 324 #endif /* CPU_ALL_H */
... ...
cpu-exec.c
... ... @@ -280,7 +280,7 @@ int cpu_exec(CPUState *env1)
280 280 tb->tc_ptr = tc_ptr;
281 281 tb->cs_base = (unsigned long)cs_base;
282 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 284 #if defined(TARGET_I386)
285 285 /* XXX: suppress that, this is incorrect */
286 286 /* if invalid instruction, signal it */
... ...
cpu-i386.h
... ... @@ -155,6 +155,9 @@
155 155  
156 156 #define EXCP_INTERRUPT 256 /* async interruption */
157 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 162 enum {
160 163 CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */
... ... @@ -270,6 +273,9 @@ typedef struct CPUX86State {
270 273 uint32_t dr[8]; /* debug registers */
271 274 int interrupt_request;
272 275 int user_mode_only; /* user mode only simulation */
  276 +
  277 + uint32_t breakpoints[MAX_BREAKPOINTS];
  278 + int nb_breakpoints;
273 279  
274 280 /* user data */
275 281 void *opaque;
... ...
... ... @@ -617,6 +617,48 @@ static void tb_reset_jump_recursive(TranslationBlock *tb)
617 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 662 /* mask must never be zero */
621 663 void cpu_interrupt(CPUState *env, int mask)
622 664 {
... ...
... ... @@ -58,10 +58,10 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
58 58 extern FILE *logfile;
59 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 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 65 int max_code_size, int *gen_code_size_ptr);
66 66 int cpu_restore_state(struct TranslationBlock *tb,
67 67 CPUState *env, unsigned long searched_pc);
... ...
gdbstub.c
... ... @@ -37,7 +37,7 @@
37 37 #include "thunk.h"
38 38 #include "exec.h"
39 39  
40   -//#define DEBUG_GDB
  40 +#define DEBUG_GDB
41 41  
42 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 283 }
284 284  
285 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 288 CPUState *env;
289 289 const char *p;
290   - int ret, ch, nb_regs, i;
  290 + int ret, ch, nb_regs, i, type;
291 291 char buf[4096];
292 292 uint8_t mem_buf[2000];
293 293 uint32_t *registers;
... ... @@ -309,8 +309,19 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port)
309 309 put_packet(buf);
310 310 break;
311 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 325 put_packet(buf);
315 326 break;
316 327 case 'g':
... ... @@ -379,6 +390,40 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port)
379 390 else
380 391 put_packet("OK");
381 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 427 default:
383 428 /* put empty packet */
384 429 buf[0] = '\0';
... ...
op-i386.c
... ... @@ -471,6 +471,12 @@ void OPPROTO op_hlt(void)
471 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 480 void OPPROTO op_raise_interrupt(void)
475 481 {
476 482 int intno;
... ...
translate-arm.c
... ... @@ -786,7 +786,9 @@ static void disas_arm_insn(DisasContext *s)
786 786 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
787 787 basic block 'tb'. If search_pc is TRUE, also generate PC
788 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 793 DisasContext dc1, *dc = &dc1;
792 794 uint16_t *gen_opc_end;
... ... @@ -853,14 +855,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
853 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 868 CPUARMState *cpu_arm_init(void)
... ...
translate-i386.c
... ... @@ -1463,6 +1463,15 @@ static void gen_interrupt(DisasContext *s, int intno,
1463 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 1475 /* generate a jump to eip. No segment change must happen before as a
1467 1476 direct call to the next block may occur */
1468 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 4089 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
4081 4090 basic block 'tb'. If search_pc is TRUE, also generate PC
4082 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 4096 DisasContext dc1, *dc = &dc1;
4086 4097 uint8_t *pc_ptr;
... ... @@ -4116,6 +4127,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
4116 4127 pc_ptr = pc_start;
4117 4128 lj = -1;
4118 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 4138 if (search_pc) {
4120 4139 j = gen_opc_ptr - gen_opc_buf;
4121 4140 if (lj < j) {
... ... @@ -4160,6 +4179,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
4160 4179 if (dc->tf) {
4161 4180 gen_op_raise_exception(EXCP01_SSTP);
4162 4181 }
  4182 + the_end:
4163 4183 if (dc->is_jmp != DISAS_TB_JUMP) {
4164 4184 /* indicate that the hash table must be used to find the next TB */
4165 4185 gen_op_movl_T0_0();
... ... @@ -4202,14 +4222,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc
4202 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 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 107 '*gen_code_size_ptr' contains the size of the generated code (host
108 108 code).
109 109 */
110   -int cpu_gen_code(TranslationBlock *tb,
  110 +int cpu_gen_code(CPUState *env, TranslationBlock *tb,
111 111 int max_code_size, int *gen_code_size_ptr)
112 112 {
113 113 uint8_t *gen_code_buf;
114 114 int gen_code_size;
115 115  
116   - if (gen_intermediate_code(tb) < 0)
  116 + if (gen_intermediate_code(env, tb) < 0)
117 117 return -1;
118 118  
119 119 /* generate machine code */
... ... @@ -154,7 +154,7 @@ int cpu_restore_state(TranslationBlock *tb,
154 154 unsigned long tc_ptr;
155 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 158 return -1;
159 159  
160 160 /* find opc index corresponding to search_pc */
... ...
... ... @@ -2540,7 +2540,7 @@ CPUState *cpu_gdbstub_get_env(void *opaque)
2540 2540 return global_env;
2541 2541 }
2542 2542  
2543   -void main_loop(void *opaque)
  2543 +int main_loop(void *opaque)
2544 2544 {
2545 2545 struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd, *gdb_ufd;
2546 2546 int ret, n, timeout;
... ... @@ -2552,7 +2552,8 @@ void main_loop(void *opaque)
2552 2552 ret = cpu_x86_exec(env);
2553 2553 if (reset_requested)
2554 2554 break;
2555   -
  2555 + if (ret == EXCP_DEBUG)
  2556 + return EXCP_DEBUG;
2556 2557 /* if hlt instruction, we wait until the next IRQ */
2557 2558 if (ret == EXCP_HLT)
2558 2559 timeout = 10;
... ... @@ -2618,6 +2619,7 @@ void main_loop(void *opaque)
2618 2619 timer_irq_pending = 0;
2619 2620 }
2620 2621 }
  2622 + return EXCP_INTERRUPT;
2621 2623 }
2622 2624  
2623 2625 void help(void)
... ...