Signed-off-by: Anna Neiman <anna_nei...@mentor.com> --- exec.c | 16 ++++++++++++- gdbstub.c | 57 ++++++++++++++++++++++++++++++++++++++++++----- include/exec/cpu-all.h | 1 + include/exec/cpu-defs.h | 20 +++++++++++++++++ include/exec/exec-all.h | 2 +- target-i386/helper.c | 2 +- tcg/tcg-op.h | 10 +++++++++ tcg/tcg.h | 6 +++++ 8 files changed, 106 insertions(+), 8 deletions(-)
diff --git a/exec.c b/exec.c index a41bcb8..4289c87 100644 --- a/exec.c +++ b/exec.c @@ -398,6 +398,7 @@ void cpu_watchpoint_remove_all(CPUArchState *env, int mask) /* Add a breakpoint. */ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, + long cond_len, uint8_t *cond_exp, CPUBreakpoint **breakpoint) { #if defined(TARGET_HAS_ICE) @@ -407,6 +408,13 @@ int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, bp->pc = pc; bp->flags = flags; + bp->cond_len = cond_len; + if (cond_exp == NULL || cond_len == 0) { + bp->cond_exp = NULL; + } else { + bp->cond_exp = g_malloc(sizeof(uint8_t) * cond_len); + memcpy(bp->cond_exp, cond_exp, sizeof(uint8_t) * cond_len); + } /* keep all GDB-injected breakpoints in front */ if (flags & BP_GDB) @@ -450,6 +458,11 @@ void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint) breakpoint_invalidate(env, breakpoint->pc); + if (breakpoint->cond_len != 0 && breakpoint->cond_exp != NULL) { + g_free(breakpoint->cond_exp); + } + + g_free(breakpoint); #endif } @@ -551,7 +564,8 @@ CPUArchState *cpu_copy(CPUArchState *env) QTAILQ_INIT(&env->watchpoints); #if defined(TARGET_HAS_ICE) QTAILQ_FOREACH(bp, &env->breakpoints, entry) { - cpu_breakpoint_insert(new_env, bp->pc, bp->flags, NULL); + cpu_breakpoint_insert(new_env, bp->pc, bp->flags, + bp->cond_len, bp->cond_exp, NULL); } QTAILQ_FOREACH(wp, &env->watchpoints, entry) { cpu_watchpoint_insert(new_env, wp->vaddr, (~wp->len_mask) + 1, diff --git a/gdbstub.c b/gdbstub.c index 32dfea9..814f596 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1941,7 +1941,8 @@ static const int xlat_gdb_type[] = { }; #endif -static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) +static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type, + long cond_len, uint8_t *cond_exp) { CPUArchState *env; int err = 0; @@ -1953,7 +1954,8 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) case GDB_BREAKPOINT_SW: case GDB_BREAKPOINT_HW: for (env = first_cpu; env != NULL; env = env->next_cpu) { - err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL); + err = cpu_breakpoint_insert(env, addr, BP_GDB, + cond_len, cond_exp, NULL); if (err) break; } @@ -2089,6 +2091,10 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) uint8_t *registers; target_ulong addr, len; + uint8_t *bp_cond_expr = NULL; + int bp_cond_len = 0; + int i = 0 ; + #ifdef DEBUG_GDB printf("command='%s'\n", line_buf); #endif @@ -2310,16 +2316,54 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) if (*p == ',') p++; len = strtoull(p, (char **)&p, 16); - if (ch == 'Z') - res = gdb_breakpoint_insert(addr, len, type); - else + while (isspace(*p)) { + p++; + } + if (ch == 'Z' && *p == ';') { + p++; + while (isspace(*p)) { + p++; + } + if (*p == 'X') { + p++; + bp_cond_len = strtoul(p, (char **)&p, 16); + if (*p == ',') { + p++; + } + if (bp_cond_len > 0) { + int bp_cond_size = sizeof(uint8_t) * bp_cond_len; + bp_cond_expr = (uint8_t *)g_malloc(bp_cond_size); + memset(bp_cond_expr, 0, bp_cond_size); + + for (i = 0 ; i < bp_cond_len ; i++) { + if (!isxdigit(*p) || !isxdigit(*(p + 1))) { + bp_cond_len = 0 ; + g_free(bp_cond_expr); + bp_cond_expr = NULL; + error_report("Error in breakpoint condition"); + } else { + hextomem(bp_cond_expr+i, p, 1); + p += 2; + } + } + } + } + } + if (ch == 'Z') { + res = gdb_breakpoint_insert(addr, len, type, + bp_cond_len, bp_cond_expr); + } else { res = gdb_breakpoint_remove(addr, len, type); + } if (res >= 0) put_packet(s, "OK"); else if (res == -ENOSYS) put_packet(s, ""); else put_packet(s, "E22"); + if (bp_cond_expr != NULL) { + g_free(bp_cond_expr); + } break; case 'H': type = *p++; @@ -2445,6 +2489,9 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) #endif /* !CONFIG_USER_ONLY */ if (strncmp(p, "Supported", 9) == 0) { snprintf(buf, sizeof(buf), "PacketSize=%x", MAX_PACKET_LENGTH); + + /* conditional breakpoint evaluation on target*/ + pstrcat(buf, sizeof(buf), ";ConditionalBreakpoints+"); #ifdef GDB_CORE_XML pstrcat(buf, sizeof(buf), ";qXfer:features:read+"); #endif diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 249e046..383c4c1 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -448,6 +448,7 @@ void cpu_exit(CPUArchState *s); #define BP_CPU 0x20 int cpu_breakpoint_insert(CPUArchState *env, target_ulong pc, int flags, + long cond_len, uint8_t *cond_exp, CPUBreakpoint **breakpoint); int cpu_breakpoint_remove(CPUArchState *env, target_ulong pc, int flags); void cpu_breakpoint_remove_by_ref(CPUArchState *env, CPUBreakpoint *breakpoint); diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 3dc9656..0bf63c2 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -136,9 +136,13 @@ typedef struct icount_decr_u16 { typedef struct CPUBreakpoint { target_ulong pc; int flags; /* BP_* */ + int cond_len; + uint8_t *cond_exp; QTAILQ_ENTRY(CPUBreakpoint) entry; } CPUBreakpoint; +int bp_has_cond(CPUBreakpoint *bp); + typedef struct CPUWatchpoint { target_ulong vaddr; target_ulong len_mask; @@ -146,6 +150,18 @@ typedef struct CPUWatchpoint { QTAILQ_ENTRY(CPUWatchpoint) entry; } CPUWatchpoint; + + +typedef double target_double; + +typedef union BPAgentStackElementType { + target_long l; + target_double d; +} BPAgentStackElementType; + + +#define BP_AGENT_MAX_STACK_SIZE 1024 + #define CPU_TEMP_BUF_NLONGS 128 #define CPU_COMMON \ /* soft mmu support */ \ @@ -191,6 +207,10 @@ typedef struct CPUWatchpoint { /* user data */ \ void *opaque; \ \ + BPAgentStackElementType bp_agent_stack[BP_AGENT_MAX_STACK_SIZE]; \ + BPAgentStackElementType *bp_agent_stack_current; \ + /*bp_agent_stack_current is the current location in bp_agent_stack */ \ + int bp_agent_error; /* error in evaluation - ex., divide by zero*/ \ const char *cpu_model_str; #endif diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index e856191..db5a38c 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -59,7 +59,7 @@ typedef struct TranslationBlock TranslationBlock; * and up to 4 + N parameters on 64-bit archs * (N = number of input arguments + output arguments). */ #define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS)) -#define OPC_BUF_SIZE 640 +#define OPC_BUF_SIZE 2560 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR) /* Maximum size a TCG op can expand to. This is complicated because a diff --git a/target-i386/helper.c b/target-i386/helper.c index 82a731c..a0d9e93 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -984,7 +984,7 @@ void hw_breakpoint_insert(CPUX86State *env, int index) switch (hw_breakpoint_type(env->dr[7], index)) { case DR7_TYPE_BP_INST: if (hw_breakpoint_enabled(env->dr[7], index)) { - err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU, + err = cpu_breakpoint_insert(env, env->dr[index], BP_CPU, 0, NULL, &env->cpu_breakpoint[index]); } break; diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index d70b2eb..6c3353c 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -21,6 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + + +#ifndef __TCG_OP_H__ +#define __TCG_OP_H__ #include "tcg.h" int gen_new_label(void); @@ -2946,6 +2950,8 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) TCGV_PTR_TO_NAT(B)) #define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i32(TCGV_PTR_TO_NAT(R), \ TCGV_PTR_TO_NAT(A), (B)) +#define tcg_gen_subi_ptr(R, A, B) tcg_gen_subi_i32(TCGV_PTR_TO_NAT(R), \ + TCGV_PTR_TO_NAT(A), (B)) #define tcg_gen_ext_i32_ptr(R, A) tcg_gen_mov_i32(TCGV_PTR_TO_NAT(R), (A)) #else /* TCG_TARGET_REG_BITS == 32 */ #define tcg_gen_add_ptr(R, A, B) tcg_gen_add_i64(TCGV_PTR_TO_NAT(R), \ @@ -2953,5 +2959,9 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) TCGV_PTR_TO_NAT(B)) #define tcg_gen_addi_ptr(R, A, B) tcg_gen_addi_i64(TCGV_PTR_TO_NAT(R), \ TCGV_PTR_TO_NAT(A), (B)) +#define tcg_gen_subi_ptr(R, A, B) tcg_gen_subi_i64(TCGV_PTR_TO_NAT(R), \ + TCGV_PTR_TO_NAT(A), (B)) #define tcg_gen_ext_i32_ptr(R, A) tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A)) #endif /* TCG_TARGET_REG_BITS != 32 */ + +#endif /* __TCG_OP_H__ */ diff --git a/tcg/tcg.h b/tcg/tcg.h index b195396..b367406 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -21,6 +21,10 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + +#ifndef __TCG_H__ +#define __TCG_H__ + #include "qemu-common.h" /* Target word size (must be identical to pointer size). */ @@ -690,3 +694,5 @@ void tcg_register_jit(void *buf, size_t buf_size); /* Generate TB finalization at the end of block */ void tcg_out_tb_finalize(TCGContext *s); #endif + +#endif /* __TCG_H__*/ -- 1.7.9.5