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,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;
@@ -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 {
@@ -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 */
@@ -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)