@@ -1,3 +1,13 @@
+2016-08-02 David Taylor <dtaylor@emc.com>
+
+ * ax-gdb.c (gen_expr): Add support for assignment to more than
+ just trace state variables.
+ (gen_expr_binop_rest): Ditto.
+ * ax-general.c (ax_setreg): New function.
+ * ax.h (ax_setreg): Declare it.
+ * common/ax.def (setmem8, setmem16, setmem32, setmem64, setreg):
+ New agent bytecodes.
+
2016-08-01 Joel Brobecker <brobecker@adacore.com>
* NEWS: Create a new section for the next release branch.
@@ -1895,6 +1895,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
(*pc) += 3;
gen_expr (exp, pc, ax, value);
+ require_rvalue (ax, value);
tsv = find_trace_state_variable (name);
if (tsv)
{
@@ -1903,11 +1904,62 @@ gen_expr (struct expression *exp, union exp_element **pc,
ax_tsv (ax, aop_tracev, tsv->number);
}
else
- error (_("$%s is not a trace state variable, "
- "may not assign to it"), name);
+ error (_("$%s is convenience variable, not a trace state variable, "
+ "You may not assign to it."), name);
+ }
+ else if ((*pc)[0].opcode == OP_VAR_VALUE)
+ {
+ int len;
+ enum agent_op opcode;
+ struct type *type = check_typedef (SYMBOL_TYPE ((*pc)[2].symbol));
+
+ len = TYPE_LENGTH (type);
+
+ if (len == 1)
+ opcode = aop_setmem8;
+ else if (len == 2)
+ opcode = aop_setmem16;
+ else if (len == 4)
+ opcode = aop_setmem32;
+ else if (len == 8)
+ opcode = aop_setmem64;
+ else
+ error (_("Unsupported OP_VAR_VALUE of length %d"), len);
+
+ gen_expr (exp, pc, ax, &value1);
+
+ if (value1.kind != axs_lvalue_register)
+ {
+ if (ax->tracing)
+ ax_trace_quick (ax, len); /* record original value */
+ }
+
+ gen_expr (exp, pc, ax, value);
+ gen_usual_unary (exp, ax, value);
+ require_rvalue (ax, value);
+
+ if (value1.kind == axs_lvalue_register)
+ {
+ ax_reg_mask (ax, value1.u.reg);
+ ax_setreg (ax, value1.u.reg);
+ }
+ else
+ ax_simple (ax, opcode);
+ }
+ else if ((*pc)[0].opcode == OP_REGISTER)
+ {
+ gen_expr (exp, pc, ax, &value1);
+
+ gen_expr (exp, pc, ax, value);
+ gen_usual_unary (exp, ax, value);
+ require_rvalue (ax, value);
+
+ ax_reg_mask (ax, value1.u.reg);
+ ax_setreg (ax, value1.u.reg);
}
else
- error (_("May only assign to trace state variables"));
+ error (_("Opcode %s unsupported for agent expressions"),
+ op_name_standard ((*pc)[0].opcode));
break;
case BINOP_ASSIGN_MODIFY:
@@ -1939,8 +1991,74 @@ gen_expr (struct expression *exp, union exp_element **pc,
ax_tsv (ax, aop_tracev, tsv->number);
}
else
- error (_("$%s is not a trace state variable, "
- "may not assign to it"), name);
+ error (_("Convenience variables such as '$%s' are known only to the debugger and "
+ "you may not assign to them in an action."), name);
+ }
+ else if ((*pc)[0].opcode == OP_VAR_VALUE)
+ {
+ int len;
+ enum agent_op opcode;
+ struct type *type;
+ struct axs_value saved_value;
+
+ gen_expr (exp, pc, ax, value);
+ type = check_typedef (value->type);
+ len = TYPE_LENGTH (type);
+
+ if (len == 1)
+ opcode = aop_setmem8;
+ else if (len == 2)
+ opcode = aop_setmem16;
+ else if (len == 4)
+ opcode = aop_setmem32;
+ else if (len == 8)
+ opcode = aop_setmem64;
+ else
+ error (_("Unsupported OP_VAR_VALUE of length %d"), len);
+
+ if (value->kind != axs_lvalue_register)
+ {
+ ax_simple (ax, aop_dup); /* keep the address around */
+
+ if (ax->tracing)
+ ax_trace_quick (ax, len); /* record original value */
+ }
+
+ value1.kind = value->kind;
+ value1.type = value->type;
+ value1.u.reg = value->u.reg;
+
+ /* gen_expr_binop_rest will set value, value1, and value2.
+ And typically value for value, value1 ends up as
+ axs_rvalue. We need to remember whether it was a
+ register and, if so, which register */
+ saved_value.kind = value->kind;
+ saved_value.u.reg = value->u.reg;
+
+ /* Now do right half of expression. */
+ gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
+
+ /* We have the result of the binary op, set the variable */
+ if (saved_value.kind == axs_lvalue_register)
+ {
+ ax_reg_mask (ax, saved_value.u.reg);
+ ax_setreg (ax, saved_value.u.reg);
+ }
+ else
+ ax_simple (ax, opcode);
+ }
+ else if ((*pc)[0].opcode == OP_REGISTER)
+ {
+ gen_expr (exp, pc, ax, value);
+
+ value1.kind = value->kind;
+ value1.type = value->type;
+ value1.u.reg = value->u.reg;
+
+ /* Now do right half of expression. */
+ gen_expr_binop_rest (exp, op2, pc, ax, value, &value1, &value2);
+
+ ax_setreg (ax, value->u.reg);
}
else
error (_("May only assign to trace state variables"));
@@ -2246,6 +2364,7 @@ gen_expr_binop_rest (struct expression *exp,
{
struct type *int_type = builtin_type (exp->gdbarch)->builtin_int;
+ require_rvalue (ax, value1);
gen_expr (exp, pc, ax, value2);
gen_usual_unary (exp, ax, value2);
gen_usual_arithmetic (exp, ax, value1, value2);
@@ -323,6 +323,28 @@ ax_reg (struct agent_expr *x, int reg)
}
}
+/* Assemble code to pop the top of stack and set register number REG
+ to its value. */
+
+void
+ax_setreg (struct agent_expr *x, int reg)
+{
+ if (reg >= gdbarch_num_regs (x->gdbarch))
+ error (_("register number '%d' is a pseudo register or is out of range"), reg);
+ else
+ {
+ /* Make sure the register number is in range. */
+ if (reg < 0 || reg > 0xffff)
+ error (_("GDB bug: ax-general.c (ax_reg): "
+ "register number out of range"));
+ grow_expr (x, 3);
+ x->buf[x->len] = aop_setreg;
+ x->buf[x->len + 1] = (reg >> 8) & 0xff;
+ x->buf[x->len + 2] = (reg) & 0xff;
+ x->len += 3;
+ }
+}
+
/* Assemble code to operate on a trace state variable. */
void
@@ -234,6 +234,11 @@ extern void ax_const_d (struct agent_expr *EXPR, LONGEST d);
stack. */
extern void ax_reg (struct agent_expr *EXPR, int REG);
+/* Assemble code to pop the top of stack and set register number REG
+ to its value. */
+
+extern void ax_setreg (struct agent_expr *EXPR, int REG);
+
/* Add the given register to the register mask of the expression. */
extern void ax_reg_mask (struct agent_expr *ax, int reg);
@@ -95,3 +95,9 @@ DEFOP (pick, 1, 0, 0, 1, 0x32)
DEFOP (rot, 0, 0, 3, 3, 0x33)
/* Both the argument and consumed numbers are dynamic for this one. */
DEFOP (printf, 0, 0, 0, 0, 0x34)
+/* The following five operands are not yet implemented. */
+DEFOP (setmem8, 0, 8, 2, 1, 0x35)
+DEFOP (setmem16, 0, 16, 2, 1, 0x36)
+DEFOP (setmem32, 0, 32, 2, 1, 0x37)
+DEFOP (setmem64, 0, 64, 2, 1, 0x38)
+DEFOP (setreg, 2, 0, 1, 1, 0x39)
@@ -1,3 +1,8 @@
+2016-08-02 David Taylor <dtaylor@emc.com>
+
+ * agentexpr.texi (Bytecode Descriptions): Add descriptions of
+ bytecodes setmem8, setmem16, setmem32, setmem64, and setreg.
+
2016-07-25 Tim Wiederhake <tim.wiederhake@intel.com>
* gdb.texinfo: Resume btrace on reconnect.
@@ -515,6 +515,25 @@ stack. If the purpose of the expression was to compute an lvalue or a
range of memory, then the next-to-top of the stack is the lvalue's
address, and the top of the stack is the lvalue's size, in bytes.
+@item @code{setmem8} (0x35): @var{addr} @var{value} @result{} @var{value}
+@itemx @code{setmem16} (0x36): @var{addr} @var{value} @result{} @var{value}
+@itemx @code{setmem32} (0x37): @var{addr} @var{value} @result{} @var{value}
+@itemx @code{setmem64} (0x38): @var{addr} @var{value} @result{} @var{value}
+For bytecode @code{setmem}@var{n}, set an @var{n}-bit value at
+@var{addr}, using the @var{n}-bit least significant bits of @var{value}
+and natural target endianness. The address @var{addr} is popped off the
+stack; the value @var{value} is left on the stack.
+
+If attempting to write memory at @var{addr} would cause a processor
+exception of some sort, terminate with an error.
+
+@item @code{setreg} (0x39) @var{regnum}: @var{value} @result{} @var{value}
+Set register @var{regnum} to @var{value}. The value @var{value} is left
+on the stack.
+
+If the register is read-only or if attempting to write @var{value} to it
+would cause a processor exception of some sort, terminate with an error.
+
@end table
@@ -1,3 +1,11 @@
+2016-08-02 David Taylor <dtaylor@emc.com>
+
+ * ax.c (compile_bytecodes): Add cases for new bytecodes (setmem8,
+ setmem16, setmem32, setmem64, and setreg).
+ * tracepoint.c (write_inferior_memory, agent_mem_write): New
+ functions.
+ * tracepoint.h (agent_mem_write): Declare.
+
2016-08-02 Yao Qi <yao.qi@linaro.org>
* thread-db.c (struct thread_db) <td_ta_event_getmsg_p>: Remove.
@@ -736,6 +736,26 @@ compile_bytecodes (struct agent_expr *aexpr)
UNHANDLED;
break;
+ case gdb_agent_op_setmem8:
+ UNHANDLED;
+ break;
+
+ case gdb_agent_op_setmem16:
+ UNHANDLED;
+ break;
+
+ case gdb_agent_op_setmem32:
+ UNHANDLED;
+ break;
+
+ case gdb_agent_op_setmem64:
+ UNHANDLED;
+ break;
+
+ case gdb_agent_op_setreg:
+ UNHANDLED;
+ break;
+
/* GDB never (currently) generates any of these ops. */
case gdb_agent_op_float:
case gdb_agent_op_ref_float:
@@ -1322,6 +1342,53 @@ gdb_eval_agent_expr (struct eval_agent_expr_context *ctx,
}
break;
+ /* for the setmem{8,16,32,64} opcodes, we leave the value on
+ the stack (in top), but the address written to is popped
+ from the stack */
+ case gdb_agent_op_setmem8:
+ cnv.u8.val = (unsigned char) top;
+ agent_mem_write (ctx, cnv.u8.bytes, stack[sp--], 1);
+ break;
+
+ case gdb_agent_op_setmem16:
+ cnv.u16.val = (unsigned short) top;
+ agent_mem_write (ctx, cnv.u16.bytes, stack[sp--], 2);
+ break;
+
+ case gdb_agent_op_setmem32:
+ cnv.u32.val = (unsigned int) top;
+ agent_mem_write (ctx, cnv.u32.bytes, stack[sp--], 4);
+ break;
+
+ case gdb_agent_op_setmem64:
+ cnv.u64.val = (ULONGEST) top;
+ agent_mem_write (ctx, cnv.u64.bytes, stack[sp--], 8);
+ break;
+
+ case gdb_agent_op_setreg:
+ arg = aexpr->bytes[pc++];
+ arg = (arg << 8) + aexpr->bytes[pc++];
+ switch (register_size (ctx->regcache->tdesc, arg))
+ {
+ case 8:
+ cnv.u8.val = (unsigned char) top;
+ break;
+ case 16:
+ cnv.u16.val = (unsigned short) top;
+ break;
+ case 32:
+ cnv.u32.val = (unsigned int) top;
+ break;
+ case 64:
+ cnv.u64.val = (ULONGEST) top;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ "unhandled register size");
+ }
+ supply_register (ctx->regcache, arg, &cnv);
+ break;
+
/* GDB never (currently) generates any of these ops. */
case gdb_agent_op_float:
case gdb_agent_op_ref_float:
@@ -357,6 +357,13 @@ read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
return 0;
}
+int
+write_inferior_memory (CORE_ADDR memaddr, unsigned char const *myaddr, int len)
+{
+ memcpy ((void *) (uintptr_t) memaddr, myaddr, len);
+ return 0;
+}
+
/* Call this in the functions where GDBserver places a breakpoint, so
that the compiler doesn't try to be clever and skip calling the
function at all. This is necessary, even if we tell the compiler
@@ -4948,6 +4955,14 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
}
/* Do memory copies for bytecodes. */
+int
+agent_mem_write (struct eval_agent_expr_context *ctx,
+ unsigned char *from, CORE_ADDR to, ULONGEST len)
+{
+ return write_inferior_memory (to, from, len);
+}
+
+/* Do memory copies for bytecodes. */
/* Do the recording of memory blocks for actions and bytecodes. */
int
@@ -154,6 +154,10 @@ int agent_mem_read (struct eval_agent_expr_context *ctx,
unsigned char *to, CORE_ADDR from,
ULONGEST len);
+int agent_mem_write (struct eval_agent_expr_context *ctx,
+ unsigned char *from, CORE_ADDR to,
+ ULONGEST len);
+
LONGEST agent_get_trace_state_variable_value (int num);
void agent_set_trace_state_variable_value (int num, LONGEST val);
@@ -1,3 +1,10 @@
+2016-08-02 David Taylor <dtaylor@emc.com>
+
+ * gdb.trace/actions.c: (get_int_test): New variable.
+ (struct GDB_STRUCT_TEST): New int field.
+ (gdb_c_test): Assign values to new variable and struct member.
+ * gdb.trace/ax.exp: Add new tests.
+
2016-08-01 Yao Qi <yao.qi@linaro.org>
* gdb.threads/process-dies-while-detaching.exp (do_test): Set
@@ -25,12 +25,14 @@
static char gdb_char_test;
static short gdb_short_test;
+static int gdb_int_test;
static long gdb_long_test;
static char gdb_arr_test[25];
static struct GDB_STRUCT_TEST
{
char c;
short s;
+ int i;
long l;
int bfield : 11; /* collect bitfield */
char arr[25];
@@ -97,6 +99,7 @@ unsigned long gdb_c_test( unsigned long *parm )
gdb_char_test = gdb_struct1_test.c = (char) ((long) parm[1] & 0xff);
gdb_short_test = gdb_struct1_test.s = (short) ((long) parm[2] & 0xffff);
+ gdb_int_test = gdb_struct1_test.i = (int) ((long) parm[3] & 0xffffffff);
gdb_long_test = gdb_struct1_test.l = (long) ((long) parm[3] & 0xffffffff);
gdb_union1_test.l = (long) parm[4];
gdb_arr_test[0] = gdb_struct1_test.arr[0] = (char) ((long) parm[1] & 0xff);
@@ -113,7 +116,7 @@ unsigned long gdb_c_test( unsigned long *parm )
gdb_recursion_test_ptr (3, (long) parm[1], (long) parm[2], (long) parm[3],
(long) parm[4], (long) parm[5], (long) parm[6]);
- gdb_char_test = gdb_short_test = gdb_long_test = 0;
+ gdb_char_test = gdb_short_test = gdb_int_test = gdb_long_test = 0;
gdb_structp_test = (void *) 0;
gdb_structpp_test = (void *) 0;
memset ((char *) &gdb_struct1_test, 0, sizeof (gdb_struct1_test));
@@ -82,6 +82,17 @@ gdb_test "maint agent &gdb_long_test < &gdb_short_test" "" "maint agent &gdb_lon
gdb_test "maint agent (unsigned char)1L" ".*ext 8.*" "maint agent (unsigned char)1L"
+gdb_test "maint agent long_long = 12" "" "maint agent long_long = 12"
+
+gdb_test "maint agent gdb_char_test = 19" "" "maint agent gdb_char_test = 19"
+
+gdb_test "maint agent gdb_short_test = 24" "" "maint agent gdb_short_test = 24"
+
+gdb_test "maint agent gdb_int_test = 35" "" "maint agent gdb_int_test = 35"
+
+gdb_test "maint agent gdb_long_test = 45" "" "maint agent gdb_long_test = 45"
+
+gdb_test "maint agent -at gdb_recursion_test, depth = 100" "" "maint agent -at gdb_recursion_test, depth = 100"
# Now test eval version of agent expressions.
gdb_test "maint agent-eval 12" ".*const8 12.*end.*" "maint agent-eval 12"
@@ -130,3 +141,15 @@ gdb_test "maint agent-eval &gdb_long_test == &gdb_short_test" ".*equal.*end.*" "
gdb_test "maint agent-eval &gdb_long_test < &gdb_short_test" "" "maint agent-eval &gdb_long_test < &gdb_short_test"
+
+gdb_test "maint agent-eval long_long = 12" "" "maint agent long_long = 12"
+
+gdb_test "maint agent-eval gdb_char_test = 19" "" "maint agent gdb_char_test = 19"
+
+gdb_test "maint agent-eval gdb_short_test = 24" "" "maint agent gdb_short_test = 24"
+
+gdb_test "maint agent-eval gdb_int_test = 35" "" "maint agent gdb_int_test = 35"
+
+gdb_test "maint agent-eval gdb_long_test = 45" "" "maint agent gdb_long_test = 45"
+
+gdb_test "maint agent-eval -at gdb_recursion_test, depth = 100" "" "maint agent -at gdb_recursion_test, depth = 100"