[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] PATCH2 - evaluate breakpoint condition on target -
From: |
Anna Neiman |
Subject: |
[Qemu-devel] [PATCH] PATCH2 - evaluate breakpoint condition on target - functionality core ( without usage yet ) - translate gdb bytecode to TCG code for add to the translation block |
Date: |
Tue, 26 Feb 2013 15:51:56 +0200 |
Signed-off-by: Anna Neiman <address@hidden>
---
Makefile.target | 2 +-
translate-gdbagent.c | 919 ++++++++++++++++++++++++++++++++++++++++++++++++++
translate-gdbagent.h | 55 +++
3 files changed, 975 insertions(+), 1 deletion(-)
create mode 100644 translate-gdbagent.c
create mode 100644 translate-gdbagent.h
diff --git a/Makefile.target b/Makefile.target
index ca657b3..e2df631 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -66,7 +66,7 @@ all: $(PROGS) stap
#########################################################
# cpu emulator library
-obj-y = exec.o translate-all.o cpu-exec.o
+obj-y = exec.o translate-all.o translate-gdbagent.o cpu-exec.o
obj-y += tcg/tcg.o tcg/optimize.o
obj-$(CONFIG_TCG_INTERPRETER) += tci.o
obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o
diff --git a/translate-gdbagent.c b/translate-gdbagent.c
new file mode 100644
index 0000000..d959a47
--- /dev/null
+++ b/translate-gdbagent.c
@@ -0,0 +1,919 @@
+/*
+ * Translation GDB bytecode to TCG.
+ * Used for evaluation breakpoint condition on host.
+ *
+ * Copyright (c) 2013 Anna Neiman <address@hidden>
+ * Copyright (c) 2012 Mentor Graphics Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <assert.h>
+
+#include "config.h"
+
+#define NO_CPU_IO_DEFS
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "translate-gdbagent.h"
+#include "translate-all.h"
+#include "qemu/error-report.h"
+
+#if defined(TARGET_HAS_ICE)
+
+static TCGv_ptr bp_agent_stack_current_tcg ;
+static TCGv bp_agent_error_tcg ;
+
+
+/* functions for retrieve register contents - platform depend
+should be initialized inside gen_intermediate_code_internal
+for each supported platform*/
+CPUGetRegVarFuncType cpu_get_reg_var_func;
+CPUSetVarToEnvPtrFuncType cpu_set_var_to_env_ptr_func;
+
+
+static int inited;
+
+void bp_agent_init(void)
+{
+ if (!inited) {
+ inited = 1;
+ bp_agent_stack_current_tcg =
+ tcg_global_mem_new_ptr(TCG_AREG0,
+ offsetof(CPUArchState,
bp_agent_stack_current),
+ "bp_agent_stack_current");
+ bp_agent_error_tcg =
+ tcg_global_mem_new(TCG_AREG0,
+ offsetof(CPUArchState, bp_agent_error),
+ "bp_agent_error");
+ }
+}
+static void bp_agent_init_local(CPUArchState *env, int len)
+{
+ if (len > BP_AGENT_MAX_STACK_SIZE) {
+ fprintf(stderr,
+ "GDB agent: Condition length more then %d is unsupported.\n",
+ BP_AGENT_MAX_STACK_SIZE);
+ }
+
+ cpu_set_var_to_env_ptr_func ( bp_agent_stack_current_tcg,
offsetof(CPUArchState, bp_agent_stack));
+}
+
+static void increment_stack_ptr(CPUArchState *env)
+{
+ tcg_gen_addi_ptr(bp_agent_stack_current_tcg,
+ bp_agent_stack_current_tcg,
+ TARGET_LONG_SIZE);
+
+}
+static void decrement_stack_ptr(CPUArchState *env)
+{
+ tcg_gen_subi_ptr(bp_agent_stack_current_tcg,
+ bp_agent_stack_current_tcg,
+ TARGET_LONG_SIZE);
+}
+
+static int check_max_instr_num(TCGContext *s, int labels_num)
+{
+ return ((s->gen_opc_ptr - s->gen_opc_buf) <=
+ (OPC_MAX_SIZE - 20 - labels_num)) ;
+}
+
+static int bp_agent_stack_set_const(CPUArchState *env, target_long tmp)
+{
+ TCGv tmp2 = tcg_temp_new();
+ tcg_gen_movi_tl(tmp2, tmp);
+ tcg_gen_st_tl(tmp2, bp_agent_stack_current_tcg, 0);
+
+ tcg_temp_free(tmp2);
+ return 1;
+}
+static int bp_agent_stack_push_const(CPUArchState *env, target_long tmp)
+{
+ bp_agent_stack_set_const(env, tmp);
+
+ increment_stack_ptr(env);
+ return 1;
+}
+static int bp_agent_stack_push(CPUArchState *env, TCGv tmp)
+{
+ tcg_gen_st_tl(tmp, bp_agent_stack_current_tcg, 0);
+
+ increment_stack_ptr(env);
+ return 1;
+}
+
+static int bp_agent_stack_pop(CPUArchState *env, TCGv tmp)
+{
+ decrement_stack_ptr(env);
+ tcg_gen_ld_tl(tmp, bp_agent_stack_current_tcg, 0);
+ return 1;
+}
+
+static int bp_agent_brcond_top(CPUArchState *env, int condlabel)
+{
+ TCGv tmp = tcg_temp_local_new();
+ int loc_err_label = gen_new_label();
+
+ bp_agent_stack_pop(env, tmp);
+
+ /* if error - evaluate on host */
+ tcg_gen_brcondi_tl(TCG_COND_NE, bp_agent_error_tcg, 0, loc_err_label);
+
+ tcg_gen_brcondi_tl(TCG_COND_EQ, tmp, 0, condlabel);
+
+ gen_set_label(loc_err_label);
+
+ tcg_temp_free(tmp);
+
+ return 1;
+}
+
+typedef enum {
+ BYTECODE_FLOAT = 0x01,
+ BYTECODE_ADD = 0x02,
+ BYTECODE_SUB = 0x03,
+ BYTECODE_MUL = 0x04,
+ BYTECODE_DIV_SIGNED = 0x05,
+ BYTECODE_DIV_UNSIGNED = 0x06,
+ BYTECODE_REM_SIGNED = 0x07,
+ BYTECODE_REM_UNSIGNED = 0x08,
+ BYTECODE_LSH = 0x09,
+ BYTECODE_RSH_SIGNED = 0x0a,
+ BYTECODE_RSH_UNSIGNED = 0x0b,
+ BYTECODE_TRACE = 0x0c,
+ BYTECODE_TRACE_QUICK = 0x0d,
+ BYTECODE_LOG_NOT = 0x0e,
+ BYTECODE_BIT_AND = 0x0f,
+ BYTECODE_BIT_OR = 0x10,
+ BYTECODE_BIT_XOR = 0x11,
+ BYTECODE_BIT_NOT = 0x12,
+ BYTECODE_EQUAL = 0x13,
+ BYTECODE_LESS_SIGNED = 0x14,
+ BYTECODE_LESS_UNSIGNED = 0x15,
+ BYTECODE_EXT = 0x16,
+ BYTECODE_REF8 = 0x17,
+ BYTECODE_REF16 = 0x18,
+ BYTECODE_REF32 = 0x19,
+ BYTECODE_REF64 = 0x1a,
+ BYTECODE_REF_FLOAT = 0x1b,
+ BYTECODE_REF_DOUBLE = 0x1c,
+ BYTECODE_REF_LONG_DOUBLE = 0x1d,
+ BYTECODE_L_TO_D = 0x1e,
+ BYTECODE_D_TO_L = 0x1f,
+ BYTECODE_IF_GOTO = 0x20,
+ BYTECODE_GOTO = 0x21,
+ BYTECODE_CONST8 = 0x22,
+ BYTECODE_CONST16 = 0x23,
+ BYTECODE_CONST32 = 0x24,
+ BYTECODE_CONST64 = 0x25,
+ BYTECODE_REG = 0x26,
+ BYTECODE_END = 0x27,
+ BYTECODE_DUP = 0x28,
+ BYTECODE_POP = 0x29,
+ BYTECODE_ZERO_EXT = 0x2a,
+ BYTECODE_SWAP = 0x2b,
+ BYTECODE_TRACE16 = 0x30
+} BytecodeCommandsType;
+
+static const char *bytecode_commands_names[] = {
+ "", /*0x00*/
+ "float", /*0x01*/
+ "add", /*0x02*/
+ "sub", /*0x03*/
+ "mul", /*0x04*/
+ "div_signed", /*0x05*/
+ "div_unsigned", /*0x06*/
+ "rem_signed", /*0x07*/
+ "rem_unsigned", /*0x08*/
+ "lsh", /*0x09*/
+ "rsh_signed", /*0x0a*/
+ "rsh_unsigned", /*0x0b*/
+ "trace", /*0x0c*/
+ "trace_quick", /*0x0d*/
+ "log_not", /*0x0e*/
+ "bit_and", /*0x0f*/
+ "bit_or", /*0x10*/
+ "bit_xor", /*0x11*/
+ "bit_not ", /*0x12*/
+ "equal", /*0x13*/
+ "less_signed", /*0x14*/
+ "less_unsigned", /*0x15*/
+ "ext", /*0x16*/
+ "ref8", /*0x17*/
+ "ref16", /*0x18*/
+ "ref32", /*0x19*/
+ "ref64", /*0x1a*/
+ "ref_float", /*0x1b*/
+ "ref_double", /*0x1c*/
+ "ref_long_double", /*0x1d*/
+ "l_to_d", /*0x1e*/
+ "d_to_l", /*0x1f*/
+ "if_goto", /*0x20*/
+ "goto", /*0x21*/
+ "const8", /*0x22*/
+ "const16", /*0x23*/
+ "const32", /*0x24*/
+ "const64", /*0x25*/
+ "reg", /*0x26*/
+ "end", /*0x27*/
+ "dup", /*0x28*/
+ "pop", /*0x29*/
+ "zero_ext", /*0x2a*/
+ "swap", /*0x2b*/
+ "", /*0x2c*/
+ "", /*0x2d*/
+ "", /*0x2e*/
+ "", /*0x2f*/
+ "trace16" /*0x30*/
+};
+
+static target_long bp_agent_get_arg(const uint8_t *cond_exp,
+ int *bp_agent_instr_cnt, int num_bytes)
+{
+ target_long res = 0 ;
+ int ind = *bp_agent_instr_cnt;
+ switch (num_bytes) {
+ case 1:
+ ind++;
+ res = cond_exp[ind];
+ break;
+ case 2:
+ {
+ uint16_t val;
+ ind++;
+ val = (cond_exp[ind] << 8) + cond_exp[ind+1];
+ ind++;
+ bswap32(val);
+ res = val;
+ }
+ break;
+ case 8:
+ {
+#if TARGET_LONG_SIZE == 8
+ uint64_t val = 0;
+ int i = 0;
+ for (i = 0; i < 8; i++) {
+ ind++;
+ val = val + cond_exp[ind];
+ val = val << 8;
+ }
+ bswap64(val);
+ res = val;
+#else
+ fprintf(stderr,
+ "GDB agent: const 64 is not supported for 32 bit target
architecture.\n");
+#endif
+ break;
+ }
+ case 4:
+ default: /* shouldn't occur*/
+ {
+ uint32_t val;
+ ind++;
+ val =
+ (cond_exp[ind] << 24) + (cond_exp[ind+1] << 16) +
+ (cond_exp[ind+2] << 8) + cond_exp[ind+3];
+ ind += 3;
+ bswap32(val);
+ res = val;
+ }
+ break;
+ }
+ *bp_agent_instr_cnt = ind;
+ return res;
+}
+typedef int(*PrintFuncType)(const char *, ...)
+ __attribute__((__format__(__printf__, 1, 2)));
+
+static int bp_agent_pass_bytecode(int cond_len, const uint8_t *cond_exp,
+ int *label_tab, PrintFuncType prnt)
+/* returns number of labels */
+{
+ int ret = 0 ;
+ int i = 0 ;
+ target_long val = 0;
+ for (i = 0 ; i < cond_len; i++) {
+ BytecodeCommandsType command_type =
(BytecodeCommandsType)(cond_exp[i]);
+ switch (command_type) {
+ case BYTECODE_FLOAT: /*0x01*/
+ case BYTECODE_REF_FLOAT: /*0x1b */
+ case BYTECODE_REF_DOUBLE: /*0x1c */
+ case BYTECODE_REF_LONG_DOUBLE: /*0x1d */
+ case BYTECODE_L_TO_D: /*0x1e*/
+ case BYTECODE_D_TO_L: /*0x1f*/
+ case BYTECODE_TRACE: /*0x0c*/
+ if (prnt) {
+ prnt("\n\t%s",
+ bytecode_commands_names[(int)command_type]);
+ }
+ break;
+ case BYTECODE_TRACE_QUICK: /*0x0d*/
+ val = bp_agent_get_arg(cond_exp, &i, 1);
+ if (prnt) {
+ prnt("\n\t%s %x",
+ bytecode_commands_names[(int)command_type],
+ (unsigned int)val);
+ }
+ break;
+ case BYTECODE_TRACE16: /*0x30*/
+ val = bp_agent_get_arg(cond_exp, &i, 2);
+ if (prnt) {
+ prnt("\n\t%s %x",
+ bytecode_commands_names[(int)command_type],
+ (unsigned int)val);
+ }
+ break;
+ case BYTECODE_END: /*0x27*/
+ case BYTECODE_DUP: /*0x28*/
+ case BYTECODE_POP: /*0x29*/
+ case BYTECODE_SWAP: /*0x2b */
+ case BYTECODE_REF8: /*0x17*/
+ case BYTECODE_REF16: /*0x18 */
+ case BYTECODE_REF64: /*0x1a */
+ case BYTECODE_REF32: /*0x19*/
+ if (prnt) {
+ prnt("\n\t%s",
+ bytecode_commands_names[(int)command_type]);
+ }
+ break;
+ case BYTECODE_IF_GOTO: /*0x20*/
+ case BYTECODE_GOTO: /*0x21*/
+ val = bp_agent_get_arg(cond_exp, &i, 2);
+ if (prnt) {
+ prnt("\n\t%s %x",
+ bytecode_commands_names[(int)command_type],
+ (unsigned int)val);
+ }
+ if (label_tab != NULL && label_tab[val] == -1) {
+ label_tab[val] = gen_new_label();
+ ret++;
+ }
+ break;
+ case BYTECODE_CONST8: /*0x22*/
+ val = bp_agent_get_arg(cond_exp, &i, 1);
+ if (prnt) {
+ prnt("\n\t%s %x",
+ bytecode_commands_names[(int)command_type],
+ (unsigned int)val);
+ }
+ break;
+ case BYTECODE_CONST16: /*0x23*/
+ val = bp_agent_get_arg(cond_exp, &i, 2);
+ if (prnt) {
+ prnt("\n\t%s %x",
+ bytecode_commands_names[(int)command_type],
+ (unsigned int)val);
+ }
+ break;
+ case BYTECODE_CONST64: /*0x25*/
+ val = bp_agent_get_arg(cond_exp, &i, 8);
+#if TARGET_LONG_SIZE == 8
+ if (prnt) {
+ prnt("\n\t%s %llx",
+ bytecode_commands_names[(int)command_type],
+ (unsigned long long)val);
+ }
+#endif
+ break;
+ case BYTECODE_CONST32: /*0x24*/
+ val = bp_agent_get_arg(cond_exp, &i, 4);
+ if (prnt) {
+ prnt("\n\t%s %lx",
+ bytecode_commands_names[(int)command_type],
+ (unsigned long)val);
+ }
+ break;
+ case BYTECODE_REG: /*0x26*/
+ val = bp_agent_get_arg(cond_exp, &i, 2);
+ if (prnt) {
+ prnt("\n\t%s %x",
+ bytecode_commands_names[(int)command_type],
+ (unsigned int)val);
+ }
+ break;
+
+ case BYTECODE_LOG_NOT:/*0x0e*/
+ case BYTECODE_BIT_NOT: /*0x12*/
+ if (prnt) {
+ prnt("\n\t%s",
+ bytecode_commands_names[(int)command_type]);
+ }
+ break;
+ case BYTECODE_EXT: /*0x16*/
+ val = bp_agent_get_arg(cond_exp, &i, 1);
+ if (prnt) {
+ prnt("\n\text %x", (unsigned int) val);
+ }
+ break;
+ case BYTECODE_ZERO_EXT: /*0x2a */
+ val = bp_agent_get_arg(cond_exp, &i, 1);
+ if (prnt) {
+ prnt("\n\t%s %x",
+ bytecode_commands_names[(int)command_type],
+ (unsigned int)val);
+ }
+ break;
+ case BYTECODE_ADD: /*0x02*/
+ case BYTECODE_SUB: /*0x03*/
+ case BYTECODE_MUL: /*0x04*/
+ case BYTECODE_DIV_SIGNED: /*0x05*/
+ case BYTECODE_DIV_UNSIGNED: /*0x06*/
+ case BYTECODE_REM_SIGNED: /*0x07*/
+ case BYTECODE_REM_UNSIGNED: /*0x08*/
+ case BYTECODE_LSH: /*0x09*/
+ case BYTECODE_RSH_SIGNED: /*0x0a*/
+ case BYTECODE_RSH_UNSIGNED: /*0x0b*/
+ case BYTECODE_BIT_AND: /*0x0f*/
+ case BYTECODE_BIT_OR: /*0x10*/
+ case BYTECODE_BIT_XOR: /*0x11*/
+ case BYTECODE_EQUAL: /*0x13*/
+ case BYTECODE_LESS_SIGNED: /*0x14*/
+ case BYTECODE_LESS_UNSIGNED: /*0x15*/
+ if (prnt) {
+ prnt("\n\t%s",
+ bytecode_commands_names[(int)command_type]);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return ret;
+}
+void bp_agent_dump_bytecode(int cond_len, const uint8_t *cond_exp)
+/*called from gdbstub in debug mode */
+{
+ printf("\nBytecode :");
+ bp_agent_pass_bytecode(cond_len, cond_exp, NULL, printf);
+ printf("\nEnd of Bytecode :");
+}
+static int bp_agent_tcg_gen(CPUArchState *env, TCGContext *s,
+ int cond_len, const uint8_t *cond_exp)
+{
+ int i = 0 ;
+ target_long val = 0 ;
+
+ int ret = 1 ;
+ int labels_num = 0 ;
+
+
+ int *label_tab = (int *)g_malloc(sizeof(int) * cond_len);
+ for (i = 0; i < cond_len ; i++) {
+ label_tab[i] = -1; /* real label value can be 0*/
+ }
+
+ labels_num = bp_agent_pass_bytecode(cond_len, cond_exp, label_tab, NULL);
+ for (i = 0;
+ (i < cond_len) && (ret == 1) && check_max_instr_num(s, labels_num);
+ i++) {
+ BytecodeCommandsType command_type =
(BytecodeCommandsType)(cond_exp[i]);
+ if (label_tab[i] != -1) {
+ gen_set_label(label_tab[i]);
+ labels_num--;
+ }
+ switch (command_type) {
+ case BYTECODE_FLOAT: /*0x01 */
+ case BYTECODE_REF_FLOAT: /*0x1b */
+ case BYTECODE_REF_DOUBLE: /*0x1c */
+ case BYTECODE_REF_LONG_DOUBLE: /*0x1d */
+ case BYTECODE_L_TO_D: /*0x1e */
+ case BYTECODE_D_TO_L: /*0x1f */
+ printf("\n Command is not implemented in BP agent");
+ break;
+ case BYTECODE_TRACE: /*0x0c not need for bp condition */
+ break;
+ case BYTECODE_TRACE_QUICK: /*0x0d not need for bp condition */
+ val = bp_agent_get_arg(cond_exp, &i, 1);
+ break;
+ case BYTECODE_TRACE16: /*0x30 not need for bp condition */
+ val = bp_agent_get_arg(cond_exp, &i, 2);
+ break;
+ case BYTECODE_END: /*0x27 */
+ i = cond_len;
+ break;
+ case BYTECODE_DUP: /*0x28*/
+ {
+ TCGv tmp1 = tcg_temp_new();
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (ret) {
+ ret = bp_agent_stack_push(env, tmp1);
+ }
+ if (ret) {
+ ret = bp_agent_stack_push(env, tmp1);
+ }
+ tcg_temp_free(tmp1);
+ }
+ break;
+ case BYTECODE_POP: /*0x29*/
+ decrement_stack_ptr(env);
+ break;
+ case BYTECODE_SWAP: /*0x2b*/
+ {
+ TCGv tmp1 = tcg_temp_new();
+ TCGv tmp2 = tcg_temp_new();
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (ret) {
+ ret = bp_agent_stack_pop(env, tmp2);
+ }
+ if (ret) {
+ ret = bp_agent_stack_push(env, tmp1);
+ }
+ if (ret) {
+ ret = bp_agent_stack_push(env, tmp2);
+ }
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ }
+ break;
+ case BYTECODE_REF8: /*0x17*/
+ case BYTECODE_REF16: /*0x18*/
+ case BYTECODE_REF64: /*0x1a*/
+ case BYTECODE_REF32: /*0x19*/
+ {
+ TCGv tmp1 = tcg_temp_new();
+ TCGv tmp2 = tcg_temp_new();
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (ret) {
+ switch (command_type) {
+ case BYTECODE_REF8: /*0x17*/
+ tcg_gen_qemu_ld8u(tmp2, tmp1, 0);
+ break;
+ case BYTECODE_REF16: /*0x18*/
+ tcg_gen_qemu_ld16u(tmp2, tmp1, 0);
+ break;
+ case BYTECODE_REF64: /*0x1a*/
+#if TARGET_LONG_SIZE == 8
+ tcg_gen_qemu_ld64(tmp2, tmp1, 0);
+#else
+ tcg_gen_qemu_ld32u(tmp2, tmp1, 0);
+#endif
+ break;
+ case BYTECODE_REF32: /*0x19*/
+ tcg_gen_qemu_ld32u(tmp2, tmp1, 0);
+ break;
+ default:
+ break;
+ }
+ }
+ if (ret) {
+ ret = bp_agent_stack_push(env, tmp2);
+ }
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ }
+ break;
+ case BYTECODE_IF_GOTO: /*0x20*/
+ {
+ TCGv tmp1 = tcg_temp_new();
+ val = bp_agent_get_arg(cond_exp, &i, 2);
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (ret) {
+ tcg_gen_brcondi_tl(TCG_COND_NE, tmp1, 0, label_tab[val]);
+ }
+ tcg_temp_free(tmp1);
+ }
+ break;
+ case BYTECODE_GOTO: /*0x21*/
+ val = bp_agent_get_arg(cond_exp, &i, 2);
+ tcg_gen_br(label_tab[val]);
+ break;
+ case BYTECODE_CONST8: /*0x22*/
+ val = bp_agent_get_arg(cond_exp, &i, 1);
+ ret = bp_agent_stack_push_const(env, val);
+ break;
+ case BYTECODE_CONST16: /*0x23*/
+ val = bp_agent_get_arg(cond_exp, &i, 2) ;
+ ret = bp_agent_stack_push_const(env, val);
+ break;
+ case BYTECODE_CONST64: /*0x25*/
+ val = bp_agent_get_arg(cond_exp, &i, 8);
+#if TARGET_LONG_SIZE == 8
+ ret = bp_agent_stack_push_const(env, val);
+#endif
+ break;
+ case BYTECODE_CONST32: /*0x24*/
+ val = bp_agent_get_arg(cond_exp, &i, 4);
+ ret = bp_agent_stack_push_const(env, val);
+ break;
+ case BYTECODE_REG: /*0x26*/
+ {
+ val = bp_agent_get_arg(cond_exp, &i, 2) ;
+ if ( val < 0 || val >= 15 ) {
+ ret = 0;
+ } else {
+ TCGv tmp1 = tcg_temp_new();
+ cpu_get_reg_var_func(tmp1, val);
+ ret = bp_agent_stack_push(env, tmp1);
+ tcg_temp_free(tmp1);
+ }
+ }
+ break;
+ case BYTECODE_LOG_NOT:/*0x0e*/
+ {
+ TCGv tmp1 = tcg_temp_new();
+ TCGv tmp = tcg_temp_local_new();
+
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (!ret) {
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp);
+ break;
+ }
+ tcg_gen_setcondi_tl(TCG_COND_EQ, tmp, tmp1, 0);
+
+ ret = bp_agent_stack_push(env, tmp);
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp);
+ }
+ break;
+ case BYTECODE_BIT_NOT: /*0x12*/
+ {
+ TCGv tmp1 = tcg_temp_new();
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (ret) {
+ tcg_gen_not_tl(tmp1, tmp1);
+ ret = bp_agent_stack_push(env, tmp1);
+ }
+ tcg_temp_free(tmp1);
+ }
+ break;
+ case BYTECODE_EXT: /*0x16*/
+ case BYTECODE_ZERO_EXT: /*0x2a*/
+ val = bp_agent_get_arg(cond_exp, &i, 1) ;
+ if (val != 8 && val != 16 && val != 32) {
+ fprintf(stderr,
+ "\n GDB agent: non-aligned bit extension is not
supported.");
+ } else {
+ TCGv tmp = tcg_temp_new();
+ ret = bp_agent_stack_pop(env, tmp);
+ if (!ret) {
+ tcg_temp_free(tmp);
+ break;
+ }
+ switch (val) {
+ case 8:
+ if (command_type == BYTECODE_EXT) {
+ tcg_gen_ext8s_tl(tmp, tmp);
+ } else {
+ tcg_gen_ext8u_tl(tmp, tmp);
+ }
+ break;
+ case 16:
+ if (command_type == BYTECODE_EXT) {
+ tcg_gen_ext16s_tl(tmp, tmp);
+ } else {
+ tcg_gen_ext16u_tl(tmp, tmp);
+ }
+ break;
+ case 32:
+ if (command_type == BYTECODE_EXT) {
+ tcg_gen_ext32s_tl(tmp, tmp);
+ } else {
+ tcg_gen_ext32u_tl(tmp, tmp);
+ }
+ break;
+ }
+ ret = bp_agent_stack_push(env, tmp);
+ tcg_temp_free(tmp);
+ }
+ break;
+ case BYTECODE_SUB: /*0x03*/
+ case BYTECODE_ADD: /*0x02*/
+ case BYTECODE_MUL: /*0x04*/
+ case BYTECODE_DIV_SIGNED: /*0x05*/
+ case BYTECODE_REM_SIGNED: /*0x07*/
+ case BYTECODE_REM_UNSIGNED: /*0x08*/
+ case BYTECODE_BIT_AND: /*0x0f*/
+ case BYTECODE_BIT_OR: /*0x10*/
+ case BYTECODE_BIT_XOR: /*0x11*/
+ case BYTECODE_LSH: /*0x09*/
+ case BYTECODE_RSH_SIGNED: /*0x0a*/
+ case BYTECODE_RSH_UNSIGNED: /*0x0b*/
+ {
+ int is_divide_command =
+ (command_type == BYTECODE_DIV_SIGNED ||
+ command_type == BYTECODE_DIV_UNSIGNED ||
+ command_type == BYTECODE_REM_SIGNED ||
+ command_type == BYTECODE_REM_UNSIGNED);
+ int my_div_label1 = -1;
+ int my_div_label2 = -1;
+ TCGv tmp1 = (is_divide_command ?
+ tcg_temp_local_new() : tcg_temp_new());
+ TCGv tmp2 = (is_divide_command ?
+ tcg_temp_local_new() : tcg_temp_new());
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (!ret) {
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ break;
+ }
+ if (is_divide_command) { /* check for divide by zero*/
+ my_div_label1 = gen_new_label();
+ my_div_label2 = gen_new_label();
+ tcg_gen_brcondi_tl(TCG_COND_NE, tmp1, 0,
+ my_div_label1);
+ tcg_gen_movi_tl(bp_agent_error_tcg , 1);
+ tcg_gen_br(my_div_label2);
+ gen_set_label(my_div_label1);
+ }
+ ret = bp_agent_stack_pop(env, tmp2);
+ if (!ret) {
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ break;
+ }
+ switch (command_type) {
+ case BYTECODE_ADD:
+ tcg_gen_add_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_SUB:
+ tcg_gen_sub_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_MUL:
+ tcg_gen_mul_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_DIV_SIGNED:
+ tcg_gen_div_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_DIV_UNSIGNED:
+ tcg_gen_divu_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_REM_SIGNED:
+ tcg_gen_rem_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_REM_UNSIGNED:
+ tcg_gen_remu_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_BIT_AND:
+ tcg_gen_and_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_BIT_OR:
+ tcg_gen_or_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_BIT_XOR:
+ tcg_gen_xor_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_LSH:
+ tcg_gen_shl_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_RSH_SIGNED:
+ tcg_gen_sar_tl(tmp2, tmp2, tmp1);
+ break;
+ case BYTECODE_RSH_UNSIGNED:
+ tcg_gen_shr_tl(tmp2, tmp2, tmp1);
+ break;
+ default:
+ break;
+ }
+ ret = bp_agent_stack_push(env, tmp2);
+ if (is_divide_command) {
+ gen_set_label(my_div_label2);
+ }
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ }
+ break;
+ case BYTECODE_EQUAL: /*0x13*/
+ case BYTECODE_LESS_UNSIGNED: /*0x15*/
+ case BYTECODE_LESS_SIGNED: /*0x14*/
+ {
+ TCGv tmp1 = tcg_temp_new();
+ TCGv tmp2 = tcg_temp_new();
+ TCGv tmp = tcg_temp_local_new();
+
+ ret = bp_agent_stack_pop(env, tmp1);
+ if (!ret) {
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ tcg_temp_free(tmp);
+ break;
+ }
+ ret = bp_agent_stack_pop(env, tmp2);
+ if (!ret) {
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ tcg_temp_free(tmp);
+ break;
+ }
+ TCGCond cond ;
+ switch (command_type) {
+ case BYTECODE_EQUAL:
+ cond = TCG_COND_EQ;
+ break;
+ case BYTECODE_LESS_UNSIGNED:
+ cond = TCG_COND_LTU;
+ break;
+ case BYTECODE_LESS_SIGNED:
+ cond = TCG_COND_LT;
+ break;
+ default:
+ break;
+ }
+ tcg_gen_setcond_tl(cond, tmp, tmp2, tmp1);
+ ret = bp_agent_stack_push(env, tmp);
+
+ tcg_temp_free(tmp1);
+ tcg_temp_free(tmp2);
+ tcg_temp_free(tmp);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ /*for case error , ex.buffer overloading -
+ need to set labels anyway in order to avoid segmentation fault.
+ For example, it can be situation when goto operator
+ to the label "x" was generated,
+ but the error occured before generation label "x" itself*/
+ while (i < cond_len && labels_num > 0) {
+ if (label_tab[i] != -1) {
+ gen_set_label(label_tab[i]);
+ labels_num--;
+ }
+ i++;
+ }
+ g_free(label_tab);
+ return ret;
+}
+
+#define MSG_PRFX "qemu note: "
+#define GDB_AG_TRANS "GDB agent expression translation"
+#define COND_EXP "Conditional expression"
+#define NOT_SUPPORT "is not supported"
+
+#define ERR_OS "%s%s target evaluation %s for the current platform.\n"
+#define ERR_BIG "%sError in %s: %s is too big and will be evaluated on host.\n"
+#define ERR_INTERN "%sInternal error in %s - %s will be evaluated on host.\n"
+
+int tcg_gen_bp_cond(CPUArchState *env,
+ TCGContext *s,
+ CPUBreakpoint *bp,
+ int condlabel)
+/* returns 1 if OK, 0 in case error */
+{
+ int res = 1;
+ if (!bp_has_cond(bp)) {
+ return 0;
+ }
+ if (cpu_get_reg_var_func == NULL || cpu_set_var_to_env_ptr_func == NULL)
{
+ error_report(ERR_OS, MSG_PRFX, COND_EXP, NOT_SUPPORT);
+ return 0;
+ }
+ if (bp->cond_len > BP_AGENT_MAX_STACK_SIZE) {
+ error_report(ERR_BIG, MSG_PRFX, GDB_AG_TRANS, COND_EXP);
+ return 0;
+ }
+ bp_agent_init_local(env, bp->cond_len);
+ res = bp_agent_tcg_gen(env, s, bp->cond_len, bp->cond_exp);
+ if (!res || !check_max_instr_num(s, 0)) {
+ if (!check_max_instr_num(s, 0)) {
+ error_report(ERR_BIG, MSG_PRFX, GDB_AG_TRANS, COND_EXP);
+ } else {
+ error_report(ERR_INTERN, MSG_PRFX, GDB_AG_TRANS, COND_EXP);
+ }
+ return 0;
+ } else {
+ bp_agent_brcond_top(env, condlabel);
+ return 1;
+ }
+}
+
+#else
+int tcg_gen_bp_cond(CPUArchState *env,
+ TCGContext *s,
+ CPUBreakpoint *bp,
+ int condlabel)
+{
+ return 1;
+}
+void bp_agent_init(void)
+{
+}
+#endif
+int bp_has_cond(CPUBreakpoint *bp)
+{
+ return (bp != NULL && bp->cond_exp != NULL && bp->cond_len != 0);
+}
diff --git a/translate-gdbagent.h b/translate-gdbagent.h
new file mode 100644
index 0000000..76db4d2
--- /dev/null
+++ b/translate-gdbagent.h
@@ -0,0 +1,55 @@
+
+/*
+ * Translation GDB bytecode to TCG.
+ * Used for evaluation breakpoint condition on host.
+ *
+ * Copyright (c) 2013 Anna Neiman <address@hidden>
+ * Copyright (c) 2012 Mentor Graphics Corp.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef __TRANSLATE_GDBAGENT_H__
+#define __TRANSLATE_GDBAGENT_H__
+
+#include "tcg-op.h"
+
+struct TCGContext;
+int tcg_gen_bp_cond(CPUArchState *env,
+ struct TCGContext *s,
+ CPUBreakpoint *bp,
+ int condlabel);
+
+extern void cpu_get_reg_var(TCGv var, int reg);
+
+void bp_agent_dump_bytecode(int cond_len, const uint8_t *cond_exp);
+
+void bp_agent_init(void);
+
+typedef void(*CPUGetRegVarFuncType)(TCGv var, int reg);
+typedef void(*CPUSetVarToEnvPtrFuncType)
+ (TCGv_ptr var_ptr, int offset);
+
+/* functions for retrieve register contents - platform depend
+should be initialized inside gen_intermediate_code_internal
+for each supported platform*/
+extern CPUGetRegVarFuncType cpu_get_reg_var_func;
+extern CPUSetVarToEnvPtrFuncType cpu_set_var_to_env_ptr_func;
+
+#endif
--
1.7.9.5
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] PATCH2 - evaluate breakpoint condition on target - functionality core ( without usage yet ) - translate gdb bytecode to TCG code for add to the translation block,
Anna Neiman <=