diff options
Diffstat (limited to 'gdbserver/ax.cc')
-rw-r--r-- | gdbserver/ax.cc | 1591 |
1 files changed, 791 insertions, 800 deletions
diff --git a/gdbserver/ax.cc b/gdbserver/ax.cc index 38ebfbb..76f2fa1 100644 --- a/gdbserver/ax.cc +++ b/gdbserver/ax.cc @@ -44,40 +44,38 @@ ax_vdebug (const char *fmt, ...) va_end (ap); } -#define ax_debug(fmt, args...) \ - do { \ - if (debug_threads) \ - ax_vdebug ((fmt), ##args); \ - } while (0) +#define ax_debug(fmt, args...) \ + do \ + { \ + if (debug_threads) \ + ax_vdebug ((fmt), ##args); \ + } \ + while (0) /* This enum must exactly match what is documented in gdb/doc/agentexpr.texi, including all the numerical values. */ enum gdb_agent_op - { -#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \ - gdb_agent_op_ ## NAME = VALUE, +{ +#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) \ + gdb_agent_op_##NAME = VALUE, #include "gdbsupport/ax.def" #undef DEFOP - gdb_agent_op_last - }; + gdb_agent_op_last +}; -static const char * const gdb_agent_op_names [gdb_agent_op_last] = - { - "?undef?" -#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) , # NAME +static const char *const gdb_agent_op_names[gdb_agent_op_last] = { "?undef?" +#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) , #NAME #include "gdbsupport/ax.def" #undef DEFOP - }; +}; #ifndef IN_PROCESS_AGENT -static const unsigned char gdb_agent_op_sizes [gdb_agent_op_last] = - { - 0 -#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) , SIZE +static const unsigned char gdb_agent_op_sizes[gdb_agent_op_last] = { 0 +#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) , SIZE #include "gdbsupport/ax.def" #undef DEFOP - }; +}; #endif /* A wrapper for gdb_agent_op_names that does some bounds-checking. */ @@ -102,9 +100,9 @@ gdb_parse_agent_expr (const char **actparm) ULONGEST xlen; struct agent_expr *aexpr; - ++act; /* skip the X */ + ++act; /* skip the X */ act = unpack_varlen_hex (act, &xlen); - ++act; /* skip a comma */ + ++act; /* skip a comma */ aexpr = XNEW (struct agent_expr); aexpr->length = xlen; aexpr->bytes = (unsigned char *) xmalloc (xlen); @@ -387,11 +385,11 @@ is_goto_target (struct agent_expr *aexpr, int pc) op = aexpr->bytes[i]; if (op == gdb_agent_op_goto || op == gdb_agent_op_if_goto) - { - int target = (aexpr->bytes[i + 1] << 8) + aexpr->bytes[i + 2]; - if (target == pc) - return 1; - } + { + int target = (aexpr->bytes[i + 1] << 8) + aexpr->bytes[i + 2]; + if (target == pc) + return 1; + } } return 0; @@ -410,12 +408,13 @@ compile_bytecodes (struct agent_expr *aexpr) ULONGEST top; struct bytecode_address *aentry, *aentry2; -#define UNHANDLED \ - do \ - { \ - ax_debug ("Cannot compile op 0x%x\n", op); \ - return expr_eval_unhandled_opcode; \ - } while (0) +#define UNHANDLED \ + do \ + { \ + ax_debug ("Cannot compile op 0x%x\n", op); \ + return expr_eval_unhandled_opcode; \ + } \ + while (0) if (aexpr->length == 0) { @@ -446,322 +445,318 @@ compile_bytecodes (struct agent_expr *aexpr) emit_error = 0; switch (op) - { - case gdb_agent_op_add: - emit_add (); - break; - - case gdb_agent_op_sub: - emit_sub (); - break; - - case gdb_agent_op_mul: - emit_mul (); - break; - - case gdb_agent_op_div_signed: - UNHANDLED; - break; - - case gdb_agent_op_div_unsigned: - UNHANDLED; - break; - - case gdb_agent_op_rem_signed: - UNHANDLED; - break; - - case gdb_agent_op_rem_unsigned: - UNHANDLED; - break; - - case gdb_agent_op_lsh: - emit_lsh (); - break; - - case gdb_agent_op_rsh_signed: - emit_rsh_signed (); - break; - - case gdb_agent_op_rsh_unsigned: - emit_rsh_unsigned (); - break; - - case gdb_agent_op_trace: - UNHANDLED; - break; - - case gdb_agent_op_trace_quick: - UNHANDLED; - break; - - case gdb_agent_op_log_not: - emit_log_not (); - break; - - case gdb_agent_op_bit_and: - emit_bit_and (); - break; - - case gdb_agent_op_bit_or: - emit_bit_or (); - break; - - case gdb_agent_op_bit_xor: - emit_bit_xor (); - break; - - case gdb_agent_op_bit_not: - emit_bit_not (); - break; - - case gdb_agent_op_equal: - next_op = aexpr->bytes[pc]; - if (next_op == gdb_agent_op_if_goto - && !is_goto_target (aexpr, pc) - && target_emit_ops ()->emit_eq_goto) - { - ax_debug ("Combining equal & if_goto"); - pc += 1; - aentry->pc = pc; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_eq_goto (&(aentry->from_offset), &(aentry->from_size)); - } - else if (next_op == gdb_agent_op_log_not - && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto) - && !is_goto_target (aexpr, pc + 1) - && target_emit_ops ()->emit_ne_goto) - { - ax_debug ("Combining equal & log_not & if_goto"); - pc += 2; - aentry->pc = pc; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_ne_goto (&(aentry->from_offset), &(aentry->from_size)); - } - else - emit_equal (); - break; - - case gdb_agent_op_less_signed: - next_op = aexpr->bytes[pc]; - if (next_op == gdb_agent_op_if_goto - && !is_goto_target (aexpr, pc)) - { - ax_debug ("Combining less_signed & if_goto"); - pc += 1; - aentry->pc = pc; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_lt_goto (&(aentry->from_offset), &(aentry->from_size)); - } - else if (next_op == gdb_agent_op_log_not - && !is_goto_target (aexpr, pc) - && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto) - && !is_goto_target (aexpr, pc + 1)) - { - ax_debug ("Combining less_signed & log_not & if_goto"); - pc += 2; - aentry->pc = pc; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_ge_goto (&(aentry->from_offset), &(aentry->from_size)); - } - else - emit_less_signed (); - break; - - case gdb_agent_op_less_unsigned: - emit_less_unsigned (); - break; - - case gdb_agent_op_ext: - arg = aexpr->bytes[pc++]; - if (arg < (sizeof (LONGEST) * 8)) - emit_ext (arg); - break; - - case gdb_agent_op_ref8: - emit_ref (1); - break; - - case gdb_agent_op_ref16: - emit_ref (2); - break; - - case gdb_agent_op_ref32: - emit_ref (4); - break; - - case gdb_agent_op_ref64: - emit_ref (8); - break; - - case gdb_agent_op_if_goto: - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_if_goto (&(aentry->from_offset), &(aentry->from_size)); - break; - - case gdb_agent_op_goto: - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_goto (&(aentry->from_offset), &(aentry->from_size)); - break; - - case gdb_agent_op_const8: - emit_stack_flush (); - top = aexpr->bytes[pc++]; - emit_const (top); - break; - - case gdb_agent_op_const16: - emit_stack_flush (); - top = aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - emit_const (top); - break; - - case gdb_agent_op_const32: - emit_stack_flush (); - top = aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - emit_const (top); - break; - - case gdb_agent_op_const64: - emit_stack_flush (); - top = aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - emit_const (top); - break; - - case gdb_agent_op_reg: - emit_stack_flush (); - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - emit_reg (arg); - break; - - case gdb_agent_op_end: - ax_debug ("At end of expression\n"); - - /* Assume there is one stack element left, and that it is + { + case gdb_agent_op_add: + emit_add (); + break; + + case gdb_agent_op_sub: + emit_sub (); + break; + + case gdb_agent_op_mul: + emit_mul (); + break; + + case gdb_agent_op_div_signed: + UNHANDLED; + break; + + case gdb_agent_op_div_unsigned: + UNHANDLED; + break; + + case gdb_agent_op_rem_signed: + UNHANDLED; + break; + + case gdb_agent_op_rem_unsigned: + UNHANDLED; + break; + + case gdb_agent_op_lsh: + emit_lsh (); + break; + + case gdb_agent_op_rsh_signed: + emit_rsh_signed (); + break; + + case gdb_agent_op_rsh_unsigned: + emit_rsh_unsigned (); + break; + + case gdb_agent_op_trace: + UNHANDLED; + break; + + case gdb_agent_op_trace_quick: + UNHANDLED; + break; + + case gdb_agent_op_log_not: + emit_log_not (); + break; + + case gdb_agent_op_bit_and: + emit_bit_and (); + break; + + case gdb_agent_op_bit_or: + emit_bit_or (); + break; + + case gdb_agent_op_bit_xor: + emit_bit_xor (); + break; + + case gdb_agent_op_bit_not: + emit_bit_not (); + break; + + case gdb_agent_op_equal: + next_op = aexpr->bytes[pc]; + if (next_op == gdb_agent_op_if_goto && !is_goto_target (aexpr, pc) + && target_emit_ops ()->emit_eq_goto) + { + ax_debug ("Combining equal & if_goto"); + pc += 1; + aentry->pc = pc; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_eq_goto (&(aentry->from_offset), &(aentry->from_size)); + } + else if (next_op == gdb_agent_op_log_not + && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto) + && !is_goto_target (aexpr, pc + 1) + && target_emit_ops ()->emit_ne_goto) + { + ax_debug ("Combining equal & log_not & if_goto"); + pc += 2; + aentry->pc = pc; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_ne_goto (&(aentry->from_offset), &(aentry->from_size)); + } + else + emit_equal (); + break; + + case gdb_agent_op_less_signed: + next_op = aexpr->bytes[pc]; + if (next_op == gdb_agent_op_if_goto && !is_goto_target (aexpr, pc)) + { + ax_debug ("Combining less_signed & if_goto"); + pc += 1; + aentry->pc = pc; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_lt_goto (&(aentry->from_offset), &(aentry->from_size)); + } + else if (next_op == gdb_agent_op_log_not + && !is_goto_target (aexpr, pc) + && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto) + && !is_goto_target (aexpr, pc + 1)) + { + ax_debug ("Combining less_signed & log_not & if_goto"); + pc += 2; + aentry->pc = pc; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_ge_goto (&(aentry->from_offset), &(aentry->from_size)); + } + else + emit_less_signed (); + break; + + case gdb_agent_op_less_unsigned: + emit_less_unsigned (); + break; + + case gdb_agent_op_ext: + arg = aexpr->bytes[pc++]; + if (arg < (sizeof (LONGEST) * 8)) + emit_ext (arg); + break; + + case gdb_agent_op_ref8: + emit_ref (1); + break; + + case gdb_agent_op_ref16: + emit_ref (2); + break; + + case gdb_agent_op_ref32: + emit_ref (4); + break; + + case gdb_agent_op_ref64: + emit_ref (8); + break; + + case gdb_agent_op_if_goto: + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_if_goto (&(aentry->from_offset), &(aentry->from_size)); + break; + + case gdb_agent_op_goto: + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_goto (&(aentry->from_offset), &(aentry->from_size)); + break; + + case gdb_agent_op_const8: + emit_stack_flush (); + top = aexpr->bytes[pc++]; + emit_const (top); + break; + + case gdb_agent_op_const16: + emit_stack_flush (); + top = aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + emit_const (top); + break; + + case gdb_agent_op_const32: + emit_stack_flush (); + top = aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + emit_const (top); + break; + + case gdb_agent_op_const64: + emit_stack_flush (); + top = aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + emit_const (top); + break; + + case gdb_agent_op_reg: + emit_stack_flush (); + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + emit_reg (arg); + break; + + case gdb_agent_op_end: + ax_debug ("At end of expression\n"); + + /* Assume there is one stack element left, and that it is cached in "top" where emit_epilogue can get to it. */ - emit_stack_adjust (1); - - done = 1; - break; - - case gdb_agent_op_dup: - /* In our design, dup is equivalent to stack flushing. */ - emit_stack_flush (); - break; - - case gdb_agent_op_pop: - emit_pop (); - break; - - case gdb_agent_op_zero_ext: - arg = aexpr->bytes[pc++]; - if (arg < (sizeof (LONGEST) * 8)) - emit_zero_ext (arg); - break; - - case gdb_agent_op_swap: - next_op = aexpr->bytes[pc]; - /* Detect greater-than comparison sequences. */ - if (next_op == gdb_agent_op_less_signed - && !is_goto_target (aexpr, pc) - && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto) - && !is_goto_target (aexpr, pc + 1)) - { - ax_debug ("Combining swap & less_signed & if_goto"); - pc += 2; - aentry->pc = pc; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_gt_goto (&(aentry->from_offset), &(aentry->from_size)); - } - else if (next_op == gdb_agent_op_less_signed - && !is_goto_target (aexpr, pc) - && (aexpr->bytes[pc + 1] == gdb_agent_op_log_not) - && !is_goto_target (aexpr, pc + 1) - && (aexpr->bytes[pc + 2] == gdb_agent_op_if_goto) - && !is_goto_target (aexpr, pc + 2)) - { - ax_debug ("Combining swap & less_signed & log_not & if_goto"); - pc += 3; - aentry->pc = pc; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - aentry->goto_pc = arg; - emit_le_goto (&(aentry->from_offset), &(aentry->from_size)); - } - else - emit_swap (); - break; - - case gdb_agent_op_getv: - emit_stack_flush (); - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - emit_int_call_1 (get_get_tsv_func_addr (), - arg); - break; - - case gdb_agent_op_setv: - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - emit_void_call_2 (get_set_tsv_func_addr (), - arg); - break; - - case gdb_agent_op_tracev: - UNHANDLED; - break; - - /* GDB never (currently) generates any of these ops. */ - case gdb_agent_op_float: - case gdb_agent_op_ref_float: - case gdb_agent_op_ref_double: - case gdb_agent_op_ref_long_double: - case gdb_agent_op_l_to_d: - case gdb_agent_op_d_to_l: - case gdb_agent_op_trace16: - UNHANDLED; - break; - - default: - ax_debug ("Agent expression op 0x%x not recognized\n", op); - /* Don't struggle on, things will just get worse. */ - return expr_eval_unrecognized_opcode; - } + emit_stack_adjust (1); + + done = 1; + break; + + case gdb_agent_op_dup: + /* In our design, dup is equivalent to stack flushing. */ + emit_stack_flush (); + break; + + case gdb_agent_op_pop: + emit_pop (); + break; + + case gdb_agent_op_zero_ext: + arg = aexpr->bytes[pc++]; + if (arg < (sizeof (LONGEST) * 8)) + emit_zero_ext (arg); + break; + + case gdb_agent_op_swap: + next_op = aexpr->bytes[pc]; + /* Detect greater-than comparison sequences. */ + if (next_op == gdb_agent_op_less_signed + && !is_goto_target (aexpr, pc) + && (aexpr->bytes[pc + 1] == gdb_agent_op_if_goto) + && !is_goto_target (aexpr, pc + 1)) + { + ax_debug ("Combining swap & less_signed & if_goto"); + pc += 2; + aentry->pc = pc; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_gt_goto (&(aentry->from_offset), &(aentry->from_size)); + } + else if (next_op == gdb_agent_op_less_signed + && !is_goto_target (aexpr, pc) + && (aexpr->bytes[pc + 1] == gdb_agent_op_log_not) + && !is_goto_target (aexpr, pc + 1) + && (aexpr->bytes[pc + 2] == gdb_agent_op_if_goto) + && !is_goto_target (aexpr, pc + 2)) + { + ax_debug ("Combining swap & less_signed & log_not & if_goto"); + pc += 3; + aentry->pc = pc; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + aentry->goto_pc = arg; + emit_le_goto (&(aentry->from_offset), &(aentry->from_size)); + } + else + emit_swap (); + break; + + case gdb_agent_op_getv: + emit_stack_flush (); + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + emit_int_call_1 (get_get_tsv_func_addr (), arg); + break; + + case gdb_agent_op_setv: + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + emit_void_call_2 (get_set_tsv_func_addr (), arg); + break; + + case gdb_agent_op_tracev: + UNHANDLED; + break; + + /* GDB never (currently) generates any of these ops. */ + case gdb_agent_op_float: + case gdb_agent_op_ref_float: + case gdb_agent_op_ref_double: + case gdb_agent_op_ref_long_double: + case gdb_agent_op_l_to_d: + case gdb_agent_op_d_to_l: + case gdb_agent_op_trace16: + UNHANDLED; + break; + + default: + ax_debug ("Agent expression op 0x%x not recognized\n", op); + /* Don't struggle on, things will just get worse. */ + return expr_eval_unrecognized_opcode; + } /* This catches errors that occur in target-specific code emission. */ if (emit_error) - { - ax_debug ("Error %d while emitting code for %s\n", - emit_error, gdb_agent_op_name (op)); - return expr_eval_unhandled_opcode; - } + { + ax_debug ("Error %d while emitting code for %s\n", emit_error, + gdb_agent_op_name (op)); + return expr_eval_unhandled_opcode; + } ax_debug ("Op %s compiled\n", gdb_agent_op_name (op)); } @@ -772,32 +767,31 @@ compile_bytecodes (struct agent_expr *aexpr) int written = 0; if (aentry->goto_pc < 0) - continue; + continue; /* Find the location that we are going to, and call back into target-specific code to write the actual address or displacement. */ for (aentry2 = bytecode_address_table; aentry2; aentry2 = aentry2->next) - { - if (aentry2->pc == aentry->goto_pc) - { - ax_debug ("Want to jump from %s to %s\n", - paddress (aentry->address), - paddress (aentry2->address)); - write_goto_address (aentry->address + aentry->from_offset, - aentry2->address, aentry->from_size); - written = 1; - break; - } - } + { + if (aentry2->pc == aentry->goto_pc) + { + ax_debug ("Want to jump from %s to %s\n", + paddress (aentry->address), + paddress (aentry2->address)); + write_goto_address (aentry->address + aentry->from_offset, + aentry2->address, aentry->from_size); + written = 1; + break; + } + } /* Error out if we didn't find a destination. */ if (!written) - { - ax_debug ("Destination of goto %d not found\n", - aentry->goto_pc); - return expr_eval_invalid_goto; - } + { + ax_debug ("Destination of goto %d not found\n", aentry->goto_pc); + return expr_eval_invalid_goto; + } } return expr_eval_no_error; @@ -813,8 +807,8 @@ compile_bytecodes (struct agent_expr *aexpr) in. */ static void -ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format, - int nargs, ULONGEST *args) +ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format, int nargs, + ULONGEST *args) { const char *f = format; int i; @@ -831,86 +825,86 @@ ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format, ++nargs_wanted; if (nargs != nargs_wanted) - error (_("Wrong number of arguments for specified format-string")); + error (_ ("Wrong number of arguments for specified format-string")); i = 0; for (auto &&piece : fpieces) { current_substring = piece.string; - ax_debug ("current substring is '%s', class is %d", - current_substring, piece.argclass); + ax_debug ("current substring is '%s', class is %d", current_substring, + piece.argclass); switch (piece.argclass) - { - case string_arg: - { - gdb_byte *str; - CORE_ADDR tem; - int j; - - tem = args[i]; - if (tem == 0) - { - printf (current_substring, "(null)"); - break; - } - - /* This is a %s argument. Find the length of the string. */ - for (j = 0;; j++) - { - gdb_byte c; - - read_inferior_memory (tem + j, &c, 1); - if (c == 0) - break; - } - - /* Copy the string contents into a string inside GDB. */ - str = (gdb_byte *) alloca (j + 1); - if (j != 0) - read_inferior_memory (tem, str, j); - str[j] = 0; - - printf (current_substring, (char *) str); - } - break; - - case long_long_arg: -#if defined (PRINTF_HAS_LONG_LONG) - { - long long val = args[i]; - - printf (current_substring, val); - break; - } + { + case string_arg: + { + gdb_byte *str; + CORE_ADDR tem; + int j; + + tem = args[i]; + if (tem == 0) + { + printf (current_substring, "(null)"); + break; + } + + /* This is a %s argument. Find the length of the string. */ + for (j = 0;; j++) + { + gdb_byte c; + + read_inferior_memory (tem + j, &c, 1); + if (c == 0) + break; + } + + /* Copy the string contents into a string inside GDB. */ + str = (gdb_byte *) alloca (j + 1); + if (j != 0) + read_inferior_memory (tem, str, j); + str[j] = 0; + + printf (current_substring, (char *) str); + } + break; + + case long_long_arg: +#if defined(PRINTF_HAS_LONG_LONG) + { + long long val = args[i]; + + printf (current_substring, val); + break; + } #else - error (_("long long not supported in agent printf")); + error (_ ("long long not supported in agent printf")); #endif - case int_arg: - { - int val = args[i]; + case int_arg: + { + int val = args[i]; - printf (current_substring, val); - break; - } + printf (current_substring, val); + break; + } - case long_arg: - { - long val = args[i]; + case long_arg: + { + long val = args[i]; - printf (current_substring, val); - break; - } + printf (current_substring, val); + break; + } - case size_t_arg: - { - size_t val = args[i]; + case size_t_arg: + { + size_t val = args[i]; - printf (current_substring, val); - break; - } + printf (current_substring, val); + break; + } - case literal_piece: - /* Print a portion of the format string that has no + case literal_piece: + /* Print a portion of the format string that has no directives. Note that this will not include any ordinary %-specs, but it might include "%%". That is why we use printf_filtered and not puts_filtered here. @@ -918,17 +912,17 @@ ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format, have modified GCC to include -Wformat-security by default, which will warn here if there is no argument. */ - printf (current_substring, 0); - break; + printf (current_substring, 0); + break; - default: - error (_("Format directive in '%s' not supported in agent printf"), - current_substring); - } + default: + error (_ ("Format directive in '%s' not supported in agent printf"), + current_substring); + } /* Maybe advance to the next argument. */ if (piece.argclass != literal_piece) - ++i; + ++i; } fflush (stdout); @@ -940,8 +934,7 @@ ax_printf (CORE_ADDR fn, CORE_ADDR chan, const char *format, enum eval_result_type gdb_eval_agent_expr (struct eval_agent_expr_context *ctx, - struct agent_expr *aexpr, - ULONGEST *rslt) + struct agent_expr *aexpr, ULONGEST *rslt) { int pc = 0; #define STACK_MAX 100 @@ -996,377 +989,375 @@ gdb_eval_agent_expr (struct eval_agent_expr_context *ctx, ax_debug ("About to interpret byte 0x%x", op); switch (op) - { - case gdb_agent_op_add: - top += stack[--sp]; - break; - - case gdb_agent_op_sub: - top = stack[--sp] - top; - break; - - case gdb_agent_op_mul: - top *= stack[--sp]; - break; - - case gdb_agent_op_div_signed: - if (top == 0) - { - ax_debug ("Attempted to divide by zero"); - return expr_eval_divide_by_zero; - } - top = ((LONGEST) stack[--sp]) / ((LONGEST) top); - break; - - case gdb_agent_op_div_unsigned: - if (top == 0) - { - ax_debug ("Attempted to divide by zero"); - return expr_eval_divide_by_zero; - } - top = stack[--sp] / top; - break; - - case gdb_agent_op_rem_signed: - if (top == 0) - { - ax_debug ("Attempted to divide by zero"); - return expr_eval_divide_by_zero; - } - top = ((LONGEST) stack[--sp]) % ((LONGEST) top); - break; - - case gdb_agent_op_rem_unsigned: - if (top == 0) - { - ax_debug ("Attempted to divide by zero"); - return expr_eval_divide_by_zero; - } - top = stack[--sp] % top; - break; - - case gdb_agent_op_lsh: - top = stack[--sp] << top; - break; - - case gdb_agent_op_rsh_signed: - top = ((LONGEST) stack[--sp]) >> top; - break; - - case gdb_agent_op_rsh_unsigned: - top = stack[--sp] >> top; - break; - - case gdb_agent_op_trace: - agent_mem_read (ctx, NULL, (CORE_ADDR) stack[--sp], - (ULONGEST) top); - if (--sp >= 0) - top = stack[sp]; - break; - - case gdb_agent_op_trace_quick: - arg = aexpr->bytes[pc++]; - agent_mem_read (ctx, NULL, (CORE_ADDR) top, (ULONGEST) arg); - break; - - case gdb_agent_op_log_not: - top = !top; - break; - - case gdb_agent_op_bit_and: - top &= stack[--sp]; - break; - - case gdb_agent_op_bit_or: - top |= stack[--sp]; - break; - - case gdb_agent_op_bit_xor: - top ^= stack[--sp]; - break; - - case gdb_agent_op_bit_not: - top = ~top; - break; - - case gdb_agent_op_equal: - top = (stack[--sp] == top); - break; - - case gdb_agent_op_less_signed: - top = (((LONGEST) stack[--sp]) < ((LONGEST) top)); - break; - - case gdb_agent_op_less_unsigned: - top = (stack[--sp] < top); - break; - - case gdb_agent_op_ext: - arg = aexpr->bytes[pc++]; - if (arg < (sizeof (LONGEST) * 8)) - { - LONGEST mask = 1 << (arg - 1); - top &= ((LONGEST) 1 << arg) - 1; - top = (top ^ mask) - mask; - } - break; - - case gdb_agent_op_ref8: - agent_mem_read (ctx, cnv.u8.bytes, (CORE_ADDR) top, 1); - top = cnv.u8.val; - break; - - case gdb_agent_op_ref16: - agent_mem_read (ctx, cnv.u16.bytes, (CORE_ADDR) top, 2); - top = cnv.u16.val; - break; - - case gdb_agent_op_ref32: - agent_mem_read (ctx, cnv.u32.bytes, (CORE_ADDR) top, 4); - top = cnv.u32.val; - break; - - case gdb_agent_op_ref64: - agent_mem_read (ctx, cnv.u64.bytes, (CORE_ADDR) top, 8); - top = cnv.u64.val; - break; - - case gdb_agent_op_if_goto: - if (top) - pc = (aexpr->bytes[pc] << 8) + (aexpr->bytes[pc + 1]); - else - pc += 2; - if (--sp >= 0) - top = stack[sp]; - break; - - case gdb_agent_op_goto: - pc = (aexpr->bytes[pc] << 8) + (aexpr->bytes[pc + 1]); - break; - - case gdb_agent_op_const8: - /* Flush the cached stack top. */ - stack[sp++] = top; - top = aexpr->bytes[pc++]; - break; - - case gdb_agent_op_const16: - /* Flush the cached stack top. */ - stack[sp++] = top; - top = aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - break; - - case gdb_agent_op_const32: - /* Flush the cached stack top. */ - stack[sp++] = top; - top = aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - break; - - case gdb_agent_op_const64: - /* Flush the cached stack top. */ - stack[sp++] = top; - top = aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - top = (top << 8) + aexpr->bytes[pc++]; - break; - - case gdb_agent_op_reg: - /* Flush the cached stack top. */ - stack[sp++] = top; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - { - int regnum = arg; - struct regcache *regcache = ctx->regcache; - - switch (register_size (regcache->tdesc, regnum)) - { - case 8: - collect_register (regcache, regnum, cnv.u64.bytes); - top = cnv.u64.val; - break; - case 4: - collect_register (regcache, regnum, cnv.u32.bytes); - top = cnv.u32.val; - break; - case 2: - collect_register (regcache, regnum, cnv.u16.bytes); - top = cnv.u16.val; - break; - case 1: - collect_register (regcache, regnum, cnv.u8.bytes); - top = cnv.u8.val; - break; - default: - internal_error ("unhandled register size"); - } - } - break; - - case gdb_agent_op_end: - ax_debug ("At end of expression, sp=%d, stack top cache=0x%s", - sp, pulongest (top)); - if (rslt) - { - if (sp <= 0) - { - /* This should be an error */ - ax_debug ("Stack is empty, nothing to return"); - return expr_eval_empty_stack; - } - *rslt = top; - } - return expr_eval_no_error; - - case gdb_agent_op_dup: - stack[sp++] = top; - break; - - case gdb_agent_op_pop: - if (--sp >= 0) - top = stack[sp]; - break; - - case gdb_agent_op_pick: - arg = aexpr->bytes[pc++]; - stack[sp] = top; - top = stack[sp - arg]; - ++sp; - break; - - case gdb_agent_op_rot: - { - ULONGEST tem = stack[sp - 1]; - - stack[sp - 1] = stack[sp - 2]; - stack[sp - 2] = top; - top = tem; - } - break; - - case gdb_agent_op_zero_ext: - arg = aexpr->bytes[pc++]; - if (arg < (sizeof (LONGEST) * 8)) - top &= ((LONGEST) 1 << arg) - 1; - break; - - case gdb_agent_op_swap: - /* Interchange top two stack elements, making sure top gets + { + case gdb_agent_op_add: + top += stack[--sp]; + break; + + case gdb_agent_op_sub: + top = stack[--sp] - top; + break; + + case gdb_agent_op_mul: + top *= stack[--sp]; + break; + + case gdb_agent_op_div_signed: + if (top == 0) + { + ax_debug ("Attempted to divide by zero"); + return expr_eval_divide_by_zero; + } + top = ((LONGEST) stack[--sp]) / ((LONGEST) top); + break; + + case gdb_agent_op_div_unsigned: + if (top == 0) + { + ax_debug ("Attempted to divide by zero"); + return expr_eval_divide_by_zero; + } + top = stack[--sp] / top; + break; + + case gdb_agent_op_rem_signed: + if (top == 0) + { + ax_debug ("Attempted to divide by zero"); + return expr_eval_divide_by_zero; + } + top = ((LONGEST) stack[--sp]) % ((LONGEST) top); + break; + + case gdb_agent_op_rem_unsigned: + if (top == 0) + { + ax_debug ("Attempted to divide by zero"); + return expr_eval_divide_by_zero; + } + top = stack[--sp] % top; + break; + + case gdb_agent_op_lsh: + top = stack[--sp] << top; + break; + + case gdb_agent_op_rsh_signed: + top = ((LONGEST) stack[--sp]) >> top; + break; + + case gdb_agent_op_rsh_unsigned: + top = stack[--sp] >> top; + break; + + case gdb_agent_op_trace: + agent_mem_read (ctx, NULL, (CORE_ADDR) stack[--sp], (ULONGEST) top); + if (--sp >= 0) + top = stack[sp]; + break; + + case gdb_agent_op_trace_quick: + arg = aexpr->bytes[pc++]; + agent_mem_read (ctx, NULL, (CORE_ADDR) top, (ULONGEST) arg); + break; + + case gdb_agent_op_log_not: + top = !top; + break; + + case gdb_agent_op_bit_and: + top &= stack[--sp]; + break; + + case gdb_agent_op_bit_or: + top |= stack[--sp]; + break; + + case gdb_agent_op_bit_xor: + top ^= stack[--sp]; + break; + + case gdb_agent_op_bit_not: + top = ~top; + break; + + case gdb_agent_op_equal: + top = (stack[--sp] == top); + break; + + case gdb_agent_op_less_signed: + top = (((LONGEST) stack[--sp]) < ((LONGEST) top)); + break; + + case gdb_agent_op_less_unsigned: + top = (stack[--sp] < top); + break; + + case gdb_agent_op_ext: + arg = aexpr->bytes[pc++]; + if (arg < (sizeof (LONGEST) * 8)) + { + LONGEST mask = 1 << (arg - 1); + top &= ((LONGEST) 1 << arg) - 1; + top = (top ^ mask) - mask; + } + break; + + case gdb_agent_op_ref8: + agent_mem_read (ctx, cnv.u8.bytes, (CORE_ADDR) top, 1); + top = cnv.u8.val; + break; + + case gdb_agent_op_ref16: + agent_mem_read (ctx, cnv.u16.bytes, (CORE_ADDR) top, 2); + top = cnv.u16.val; + break; + + case gdb_agent_op_ref32: + agent_mem_read (ctx, cnv.u32.bytes, (CORE_ADDR) top, 4); + top = cnv.u32.val; + break; + + case gdb_agent_op_ref64: + agent_mem_read (ctx, cnv.u64.bytes, (CORE_ADDR) top, 8); + top = cnv.u64.val; + break; + + case gdb_agent_op_if_goto: + if (top) + pc = (aexpr->bytes[pc] << 8) + (aexpr->bytes[pc + 1]); + else + pc += 2; + if (--sp >= 0) + top = stack[sp]; + break; + + case gdb_agent_op_goto: + pc = (aexpr->bytes[pc] << 8) + (aexpr->bytes[pc + 1]); + break; + + case gdb_agent_op_const8: + /* Flush the cached stack top. */ + stack[sp++] = top; + top = aexpr->bytes[pc++]; + break; + + case gdb_agent_op_const16: + /* Flush the cached stack top. */ + stack[sp++] = top; + top = aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + break; + + case gdb_agent_op_const32: + /* Flush the cached stack top. */ + stack[sp++] = top; + top = aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + break; + + case gdb_agent_op_const64: + /* Flush the cached stack top. */ + stack[sp++] = top; + top = aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + top = (top << 8) + aexpr->bytes[pc++]; + break; + + case gdb_agent_op_reg: + /* Flush the cached stack top. */ + stack[sp++] = top; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + { + int regnum = arg; + struct regcache *regcache = ctx->regcache; + + switch (register_size (regcache->tdesc, regnum)) + { + case 8: + collect_register (regcache, regnum, cnv.u64.bytes); + top = cnv.u64.val; + break; + case 4: + collect_register (regcache, regnum, cnv.u32.bytes); + top = cnv.u32.val; + break; + case 2: + collect_register (regcache, regnum, cnv.u16.bytes); + top = cnv.u16.val; + break; + case 1: + collect_register (regcache, regnum, cnv.u8.bytes); + top = cnv.u8.val; + break; + default: + internal_error ("unhandled register size"); + } + } + break; + + case gdb_agent_op_end: + ax_debug ("At end of expression, sp=%d, stack top cache=0x%s", sp, + pulongest (top)); + if (rslt) + { + if (sp <= 0) + { + /* This should be an error */ + ax_debug ("Stack is empty, nothing to return"); + return expr_eval_empty_stack; + } + *rslt = top; + } + return expr_eval_no_error; + + case gdb_agent_op_dup: + stack[sp++] = top; + break; + + case gdb_agent_op_pop: + if (--sp >= 0) + top = stack[sp]; + break; + + case gdb_agent_op_pick: + arg = aexpr->bytes[pc++]; + stack[sp] = top; + top = stack[sp - arg]; + ++sp; + break; + + case gdb_agent_op_rot: + { + ULONGEST tem = stack[sp - 1]; + + stack[sp - 1] = stack[sp - 2]; + stack[sp - 2] = top; + top = tem; + } + break; + + case gdb_agent_op_zero_ext: + arg = aexpr->bytes[pc++]; + if (arg < (sizeof (LONGEST) * 8)) + top &= ((LONGEST) 1 << arg) - 1; + break; + + case gdb_agent_op_swap: + /* Interchange top two stack elements, making sure top gets copied back onto stack. */ - stack[sp] = top; - top = stack[sp - 1]; - stack[sp - 1] = stack[sp]; - break; - - case gdb_agent_op_getv: - /* Flush the cached stack top. */ - stack[sp++] = top; - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - top = agent_get_trace_state_variable_value (arg); - break; - - case gdb_agent_op_setv: - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - agent_set_trace_state_variable_value (arg, top); - /* Note that we leave the value on the stack, for the + stack[sp] = top; + top = stack[sp - 1]; + stack[sp - 1] = stack[sp]; + break; + + case gdb_agent_op_getv: + /* Flush the cached stack top. */ + stack[sp++] = top; + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + top = agent_get_trace_state_variable_value (arg); + break; + + case gdb_agent_op_setv: + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + agent_set_trace_state_variable_value (arg, top); + /* Note that we leave the value on the stack, for the benefit of later/enclosing expressions. */ - break; - - case gdb_agent_op_tracev: - arg = aexpr->bytes[pc++]; - arg = (arg << 8) + aexpr->bytes[pc++]; - agent_tsv_read (ctx, arg); - break; - - case gdb_agent_op_tracenz: - agent_mem_read_string (ctx, NULL, (CORE_ADDR) stack[--sp], - (ULONGEST) top); - if (--sp >= 0) - top = stack[sp]; - break; - - case gdb_agent_op_printf: - { - int nargs, slen, i; - CORE_ADDR fn = 0, chan = 0; - /* Can't have more args than the entire size of the stack. */ - ULONGEST args[STACK_MAX]; - char *format; - - nargs = aexpr->bytes[pc++]; - slen = aexpr->bytes[pc++]; - slen = (slen << 8) + aexpr->bytes[pc++]; - format = (char *) &(aexpr->bytes[pc]); - pc += slen; - /* Pop function and channel. */ - fn = top; - if (--sp >= 0) - top = stack[sp]; - chan = top; - if (--sp >= 0) - top = stack[sp]; - /* Pop arguments into a dedicated array. */ - for (i = 0; i < nargs; ++i) - { - args[i] = top; - if (--sp >= 0) - top = stack[sp]; - } - - /* A bad format string means something is very wrong; give + break; + + case gdb_agent_op_tracev: + arg = aexpr->bytes[pc++]; + arg = (arg << 8) + aexpr->bytes[pc++]; + agent_tsv_read (ctx, arg); + break; + + case gdb_agent_op_tracenz: + agent_mem_read_string (ctx, NULL, (CORE_ADDR) stack[--sp], + (ULONGEST) top); + if (--sp >= 0) + top = stack[sp]; + break; + + case gdb_agent_op_printf: + { + int nargs, slen, i; + CORE_ADDR fn = 0, chan = 0; + /* Can't have more args than the entire size of the stack. */ + ULONGEST args[STACK_MAX]; + char *format; + + nargs = aexpr->bytes[pc++]; + slen = aexpr->bytes[pc++]; + slen = (slen << 8) + aexpr->bytes[pc++]; + format = (char *) &(aexpr->bytes[pc]); + pc += slen; + /* Pop function and channel. */ + fn = top; + if (--sp >= 0) + top = stack[sp]; + chan = top; + if (--sp >= 0) + top = stack[sp]; + /* Pop arguments into a dedicated array. */ + for (i = 0; i < nargs; ++i) + { + args[i] = top; + if (--sp >= 0) + top = stack[sp]; + } + + /* A bad format string means something is very wrong; give up immediately. */ - if (format[slen - 1] != '\0') - error (_("Unterminated format string in printf bytecode")); - - ax_printf (fn, chan, format, nargs, args); - } - break; - - /* GDB never (currently) generates any of these ops. */ - case gdb_agent_op_float: - case gdb_agent_op_ref_float: - case gdb_agent_op_ref_double: - case gdb_agent_op_ref_long_double: - case gdb_agent_op_l_to_d: - case gdb_agent_op_d_to_l: - case gdb_agent_op_trace16: - ax_debug ("Agent expression op 0x%x valid, but not handled", - op); - /* If ever GDB generates any of these, we don't have the + if (format[slen - 1] != '\0') + error (_ ("Unterminated format string in printf bytecode")); + + ax_printf (fn, chan, format, nargs, args); + } + break; + + /* GDB never (currently) generates any of these ops. */ + case gdb_agent_op_float: + case gdb_agent_op_ref_float: + case gdb_agent_op_ref_double: + case gdb_agent_op_ref_long_double: + case gdb_agent_op_l_to_d: + case gdb_agent_op_d_to_l: + case gdb_agent_op_trace16: + ax_debug ("Agent expression op 0x%x valid, but not handled", op); + /* If ever GDB generates any of these, we don't have the option of ignoring. */ - return expr_eval_unhandled_opcode; + return expr_eval_unhandled_opcode; - default: - ax_debug ("Agent expression op 0x%x not recognized", op); - /* Don't struggle on, things will just get worse. */ - return expr_eval_unrecognized_opcode; - } + default: + ax_debug ("Agent expression op 0x%x not recognized", op); + /* Don't struggle on, things will just get worse. */ + return expr_eval_unrecognized_opcode; + } /* Check for stack badness. */ if (sp >= (STACK_MAX - 1)) - { - ax_debug ("Expression stack overflow"); - return expr_eval_stack_overflow; - } + { + ax_debug ("Expression stack overflow"); + return expr_eval_stack_overflow; + } if (sp < 0) - { - ax_debug ("Expression stack underflow"); - return expr_eval_stack_underflow; - } + { + ax_debug ("Expression stack underflow"); + return expr_eval_stack_underflow; + } - ax_debug ("Op %s -> sp=%d, top=0x%s", - gdb_agent_op_name (op), sp, phex_nz (top, 0)); + ax_debug ("Op %s -> sp=%d, top=0x%s", gdb_agent_op_name (op), sp, + phex_nz (top, 0)); } } |