aboutsummaryrefslogtreecommitdiff
path: root/gdb
diff options
context:
space:
mode:
authorLuis Machado <luisgpm@br.ibm.com>2012-02-24 15:13:37 +0000
committerLuis Machado <luisgpm@br.ibm.com>2012-02-24 15:13:37 +0000
commit5e1dc496746ac407cad3b99d2a89e776d08ee326 (patch)
tree3ada297578919b328456428ec2b7f805c180eae8 /gdb
parentb775012e845380ed4c7421a1b87caf7bfae39f5f (diff)
downloadgdb-5e1dc496746ac407cad3b99d2a89e776d08ee326.zip
gdb-5e1dc496746ac407cad3b99d2a89e776d08ee326.tar.gz
gdb-5e1dc496746ac407cad3b99d2a89e776d08ee326.tar.bz2
2012-02-24 Luis Machado <lgustavo@codesourcery>
* server.h: Include tracepoint.h. (agent_mem_read, agent_get_trace_state_variable_value, agent_set_trace_state_variable_value, agent_tsv_read, agent_mem_read_string, get_get_tsv_func_addr, get_set_tsv_func_addr): New prototypes. * ax.h: New include file. * ax.c: New source file. * tracepoint.c: Include ax.h. (gdb_agent_op, gdb_agent_op_names, gdb_agent_op_sizes, agent_expr, eval_result_type): Move to ax.h. (parse_agent_expr): Rename to ... (gdb_parse_agent_expr): ... this, make it non-static and move to ax.h. (unparse_agent_expr) Rename to ... (gdb_unparse_agent_expr): ... this, make it non-static and move to ax.h. (eval_agent_expr): Rename to ... (eval_tracepoint_agent_expr): ... this. (agent_mem_read, agent_mem_read_string, agent_tsv_read): Remove forward declarations. (add_tracepoint_action): Call gdb_parse_agent_expr (...). (agent_get_trace_state_variable_value): New function. (agent_set_trace_state_variable_value): New function. (cmd_qtdp): Call gdb_parse_agent_expr (...). (response_tracepoint): Call gdb_unparse_agent_expr (...). (do_action_at_tracepoint): Call eval_tracepoint_agent_expr (...). (condition_true_at_tracepoint): Likewise. (parse_agent_expr): Rename to ... (gdb_parse_agent_expr): ... this and move to ax.c. (unparse_agent_expr): Rename to ... (gdb_unparse_agent_expr): ... this and move to ax.c. (gdb_agent_op_name): Move to ax.c. (eval_agent_expr): Rename to ... (gdb_eval_agent_expr): ... this, use regcache passed as parameter and move to ax.c. (eval_tracepoint_agent_expr): New function. (agent_mem_read, agent_mem_read_string, agent_tsv_read): Make non-static. (current_insn_ptr, emit_error, struct bytecode_address): Move to ax.c. (emit_prologue, emit_epilogue, emit_add, emit_sub, emit_mul, emit_lsh, emit_rsh_signed, emit_rsh_unsigned, emit_ext, emit_log_not, emit_bit_and, emit_bit_or, emit_bit_xor, emit_bit_not, emit_equal, emit_less_signed, emit_less_unsigned, emit_ref, emit_if_goto, emit_goto, write_goto_address, emit_const, emit_reg, emit_pop, emit_stack, emit_zero_ext, emit_swap, emit_stack_adjust, emit_int_call_1, emit_void_call_2, emit_eq_goto, emit_ne_goto, emit_lt_goto, emit_ge_goto, emit_gt_goto, emit_le_goto): Move to ax.c. (get_get_tsv_func_addr, get_set_tsv_func_addr): New functions. (compile_bytecodes): Remove forward declaration. (is_goto_target): Move to ax.c. (compile_bytecodes): Move to ax.c and call agent_get_trace_state_variable_value (...) and agent_set_trace_state_variable_value (...). * Makefile.in: Update ax.c and IPA dependencies.
Diffstat (limited to 'gdb')
-rw-r--r--gdb/gdbserver/ChangeLog61
-rw-r--r--gdb/gdbserver/Makefile.in14
-rw-r--r--gdb/gdbserver/server.h32
-rw-r--r--gdb/gdbserver/tracepoint.c1239
4 files changed, 146 insertions, 1200 deletions
diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog
index aa9f556..c1baa96 100644
--- a/gdb/gdbserver/ChangeLog
+++ b/gdb/gdbserver/ChangeLog
@@ -1,3 +1,64 @@
+2012-02-24 Luis Machado <lgustavo@codesourcery>
+
+ * server.h: Include tracepoint.h.
+ (agent_mem_read, agent_get_trace_state_variable_value,
+ agent_set_trace_state_variable_value,
+ agent_tsv_read, agent_mem_read_string, get_get_tsv_func_addr,
+ get_set_tsv_func_addr): New prototypes.
+
+ * ax.h: New include file.
+ * ax.c: New source file.
+
+ * tracepoint.c: Include ax.h.
+ (gdb_agent_op, gdb_agent_op_names, gdb_agent_op_sizes,
+ agent_expr, eval_result_type): Move to ax.h.
+ (parse_agent_expr): Rename to ...
+ (gdb_parse_agent_expr): ... this, make it non-static and move
+ to ax.h.
+ (unparse_agent_expr) Rename to ...
+ (gdb_unparse_agent_expr): ... this, make it non-static and move
+ to ax.h.
+ (eval_agent_expr): Rename to ...
+ (eval_tracepoint_agent_expr): ... this.
+ (agent_mem_read, agent_mem_read_string, agent_tsv_read): Remove
+ forward declarations.
+ (add_tracepoint_action): Call gdb_parse_agent_expr (...).
+ (agent_get_trace_state_variable_value): New function.
+ (agent_set_trace_state_variable_value): New function.
+ (cmd_qtdp): Call gdb_parse_agent_expr (...).
+ (response_tracepoint): Call gdb_unparse_agent_expr (...).
+ (do_action_at_tracepoint): Call eval_tracepoint_agent_expr (...).
+ (condition_true_at_tracepoint): Likewise.
+ (parse_agent_expr): Rename to ...
+ (gdb_parse_agent_expr): ... this and move to ax.c.
+ (unparse_agent_expr): Rename to ...
+ (gdb_unparse_agent_expr): ... this and move to ax.c.
+ (gdb_agent_op_name): Move to ax.c.
+ (eval_agent_expr): Rename to ...
+ (gdb_eval_agent_expr): ... this, use regcache passed as parameter
+ and move to ax.c.
+ (eval_tracepoint_agent_expr): New function.
+ (agent_mem_read, agent_mem_read_string, agent_tsv_read): Make
+ non-static.
+ (current_insn_ptr, emit_error, struct bytecode_address): Move to
+ ax.c.
+ (emit_prologue, emit_epilogue, emit_add, emit_sub, emit_mul, emit_lsh,
+ emit_rsh_signed, emit_rsh_unsigned, emit_ext, emit_log_not,
+ emit_bit_and, emit_bit_or, emit_bit_xor, emit_bit_not, emit_equal,
+ emit_less_signed, emit_less_unsigned, emit_ref, emit_if_goto,
+ emit_goto, write_goto_address, emit_const, emit_reg, emit_pop,
+ emit_stack, emit_zero_ext, emit_swap, emit_stack_adjust,
+ emit_int_call_1, emit_void_call_2, emit_eq_goto, emit_ne_goto,
+ emit_lt_goto, emit_ge_goto, emit_gt_goto, emit_le_goto): Move to ax.c.
+ (get_get_tsv_func_addr, get_set_tsv_func_addr): New functions.
+ (compile_bytecodes): Remove forward declaration.
+ (is_goto_target): Move to ax.c.
+ (compile_bytecodes): Move to ax.c and call
+ agent_get_trace_state_variable_value (...) and
+ agent_set_trace_state_variable_value (...).
+
+ * Makefile.in: Update ax.c and IPA dependencies.
+
2012-02-24 Pedro Alves <palves@redhat.com>
* tracepoint.c (cmd_bigqtbuffer): Rename as ...
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index c6a8bff..b4d2006 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -134,7 +134,7 @@ LIBOBJS = @LIBOBJS@
SOURCES = $(SFILES)
TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
-OBS = inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
+OBS = ax.o inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
utils.o version.o \
mem-break.o hostio.o event-loop.o tracepoint.o \
xml-utils.o common-utils.o ptid.o buffer.o \
@@ -237,7 +237,7 @@ gdbreplay$(EXEEXT): $(GDBREPLAY_OBS)
${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \
$(XM_CLIBS)
-IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o common-utils-ipa.o ${IPA_DEPFILES}
+IPA_OBJS=ax-ipa.o tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o common-utils-ipa.o ${IPA_DEPFILES}
IPA_LIB=libinproctrace.so
@@ -336,6 +336,7 @@ regcache_h = $(srcdir)/regcache.h
signals_def = $(srcdir)/../../include/gdb/signals.def
signals_h = $(srcdir)/../../include/gdb/signals.h $(signals_def)
ptid_h = $(srcdir)/../common/ptid.h
+ax_h = $(srcdir)/ax.h
linux_osdata_h = $(srcdir)/../common/linux-osdata.h
server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h \
$(srcdir)/mem-break.h $(srcdir)/../common/gdb_signals.h \
@@ -368,7 +369,9 @@ IPAGENT_CFLAGS = $(CPPFLAGS) $(INTERNAL_CFLAGS) $(UST_CFLAGS) \
-fvisibility=hidden
# In-process agent object rules
-tracepoint-ipa.o: tracepoint.c $(server_h) $(srcdir)/../common/ax.def
+ax-ipa.o: ax.c $(server_h) $(ax_h) $(srcdir)/../common/ax.def
+ $(CC) -c $(IPAGENT_CFLAGS) $< -o ax-ipa.o
+tracepoint-ipa.o: tracepoint.c $(server_h) ${ax_h}
$(CC) -c $(IPAGENT_CFLAGS) $< -o tracepoint-ipa.o
utils-ipa.o: utils.c $(server_h)
$(CC) -c $(IPAGENT_CFLAGS) $< -o utils-ipa.o
@@ -387,11 +390,12 @@ linux-amd64-ipa.o: linux-amd64-ipa.c $(server_h)
amd64-linux-ipa.o : amd64-linux.c $(regdef_h)
$(CC) -c $(IPAGENT_CFLAGS) $< -o amd64-linux-ipa.o
+ax.o: ax.c $(server_h) $(ax_h) $(srcdir)/../common/ax.def
event-loop.o: event-loop.c $(server_h)
hostio.o: hostio.c $(server_h)
hostio-errno.o: hostio-errno.c $(server_h)
inferiors.o: inferiors.c $(server_h)
-mem-break.o: mem-break.c $(server_h)
+mem-break.o: mem-break.c $(server_h) $(ax_h)
proc-service.o: proc-service.c $(server_h) $(gdb_proc_service_h)
regcache.o: regcache.c $(server_h) $(regdef_h)
remote-utils.o: remote-utils.c terminal.h $(server_h)
@@ -399,7 +403,7 @@ server.o: server.c $(server_h)
target.o: target.c $(server_h)
thread-db.o: thread-db.c $(server_h) $(linux_low_h) $(gdb_proc_service_h) \
$(gdb_thread_db_h)
-tracepoint.o: tracepoint.c $(server_h) $(srcdir)/../common/ax.def
+tracepoint.o: tracepoint.c $(server_h) $(ax_h)
utils.o: utils.c $(server_h)
gdbreplay.o: gdbreplay.c config.h
dll.o: dll.c $(server_h)
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index d3b4463..30d608c 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -102,6 +102,12 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap);
#define _(String) (String)
#endif
+#ifdef IN_PROCESS_AGENT
+# define PROG "ipa"
+#else
+# define PROG "gdbserver"
+#endif
+
/* A type used for binary buffers. */
typedef unsigned char gdb_byte;
@@ -511,6 +517,26 @@ int claim_trampoline_space (ULONGEST used, CORE_ADDR *trampoline);
int have_fast_tracepoint_trampoline_buffer (char *msgbuf);
#endif
+struct traceframe;
+
+/* Do memory copies for bytecodes. */
+/* Do the recording of memory blocks for actions and bytecodes. */
+
+int agent_mem_read (struct traceframe *tframe,
+ unsigned char *to, CORE_ADDR from,
+ ULONGEST len);
+
+LONGEST agent_get_trace_state_variable_value (int num);
+void agent_set_trace_state_variable_value (int num, LONGEST val);
+
+/* Record the value of a trace state variable. */
+
+int agent_tsv_read (struct traceframe *tframe, int n);
+int agent_mem_read_string (struct traceframe *tframe,
+ unsigned char *to,
+ CORE_ADDR from,
+ ULONGEST len);
+
/* Bytecode compilation function vector. */
struct emit_ops
@@ -566,6 +592,12 @@ struct emit_ops
/* Returns the address of the get_raw_reg function in the IPA. */
CORE_ADDR get_raw_reg_func_addr (void);
+/* Returns the address of the get_trace_state_variable_value
+ function in the IPA. */
+CORE_ADDR get_get_tsv_func_addr (void);
+/* Returns the address of the set_trace_state_variable_value
+ function in the IPA. */
+CORE_ADDR get_set_tsv_func_addr (void);
CORE_ADDR current_insn_ptr;
int emit_error;
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index cd58c2d..dfa48a7 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -25,6 +25,7 @@
#if HAVE_STDINT_H
#include <stdint.h>
#endif
+#include "ax.h"
/* This file is built for both GDBserver, and the in-process
agent (IPA), a shared library that includes a tracing agent that is
@@ -63,18 +64,10 @@ trace_vdebug (const char *fmt, ...)
va_start (ap, fmt);
vsprintf (buf, fmt, ap);
-#ifdef IN_PROCESS_AGENT
- fprintf (stderr, "ipa/tracepoint: %s\n", buf);
-#else
- fprintf (stderr, "gdbserver/tracepoint: %s\n", buf);
-#endif
+ fprintf (stderr, PROG "/tracepoint: %s\n", buf);
va_end (ap);
}
-#ifdef IN_PROCESS_AGENT
-#define debug_threads debug_agent
-#endif
-
#define trace_debug_1(level, fmt, args...) \
do { \
if (level <= debug_threads) \
@@ -374,8 +367,6 @@ tracepoint_look_up_symbols (void)
GDBserver side. */
#ifdef IN_PROCESS_AGENT
-int debug_agent = 0;
-
int
read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
{
@@ -480,41 +471,6 @@ write_inferior_uinteger (CORE_ADDR symaddr, unsigned int val)
#endif
-/* 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,
-#include "ax.def"
-#undef DEFOP
- gdb_agent_op_last
- };
-
-static const char *gdb_agent_op_names [gdb_agent_op_last] =
- {
- "?undef?"
-#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) , # NAME
-#include "ax.def"
-#undef DEFOP
- };
-
-static const unsigned char gdb_agent_op_sizes [gdb_agent_op_last] =
- {
- 0
-#define DEFOP(NAME, SIZE, DATA_SIZE, CONSUMED, PRODUCED, VALUE) , SIZE
-#include "ax.def"
-#undef DEFOP
- };
-
-struct agent_expr
-{
- int length;
-
- unsigned char *bytes;
-};
-
/* Base action. Concrete actions inherit this. */
struct tracepoint_action
@@ -746,22 +702,6 @@ IP_AGENT_EXPORT struct tracepoint *stopping_tracepoint;
IP_AGENT_EXPORT int trace_buffer_is_full;
-/* Enumeration of the different kinds of things that can happen during
- agent expression evaluation. */
-
-enum eval_result_type
- {
- expr_eval_no_error,
- expr_eval_empty_expression,
- expr_eval_empty_stack,
- expr_eval_stack_overflow,
- expr_eval_stack_underflow,
- expr_eval_unhandled_opcode,
- expr_eval_unrecognized_opcode,
- expr_eval_divide_by_zero,
- expr_eval_invalid_goto
- };
-
static enum eval_result_type expr_eval_result = expr_eval_no_error;
#ifndef IN_PROCESS_AGENT
@@ -1245,21 +1185,11 @@ struct trap_tracepoint_ctx
#endif
-#ifndef IN_PROCESS_AGENT
-static struct agent_expr *parse_agent_expr (char **actparm);
-static char *unparse_agent_expr (struct agent_expr *aexpr);
-#endif
-static enum eval_result_type eval_agent_expr (struct tracepoint_hit_ctx *ctx,
- struct traceframe *tframe,
- struct agent_expr *aexpr,
- ULONGEST *rslt);
-
-static int agent_mem_read (struct traceframe *tframe,
- unsigned char *to, CORE_ADDR from, ULONGEST len);
-static int agent_mem_read_string (struct traceframe *tframe,
- unsigned char *to, CORE_ADDR from,
- ULONGEST len);
-static int agent_tsv_read (struct traceframe *tframe, int n);
+static enum eval_result_type
+eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx,
+ struct traceframe *tframe,
+ struct agent_expr *aexpr,
+ ULONGEST *rslt);
#ifndef IN_PROCESS_AGENT
static CORE_ADDR traceframe_get_pc (struct traceframe *tframe);
@@ -1892,7 +1822,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
action = &xaction->base;
trace_debug ("Want to evaluate expression");
- xaction->expr = parse_agent_expr (&act);
+ xaction->expr = gdb_parse_agent_expr (&act);
break;
}
default:
@@ -2036,6 +1966,18 @@ set_trace_state_variable_value (int num, LONGEST val)
tsv->value = val;
}
+LONGEST
+agent_get_trace_state_variable_value (int num)
+{
+ return get_trace_state_variable_value (num);
+}
+
+void
+agent_set_trace_state_variable_value (int num, LONGEST val)
+{
+ set_trace_state_variable_value (num, val);
+}
+
static void
set_trace_state_variable_name (int num, const char *name)
{
@@ -2412,7 +2354,7 @@ cmd_qtdp (char *own_buf)
else if (*packet == 'X')
{
actparm = (char *) packet;
- tpoint->cond = parse_agent_expr (&actparm);
+ tpoint->cond = gdb_parse_agent_expr (&actparm);
packet = actparm;
}
else if (*packet == '-')
@@ -3522,7 +3464,7 @@ response_tracepoint (char *packet, struct tracepoint *tpoint)
if (tpoint->cond)
{
- buf = unparse_agent_expr (tpoint->cond);
+ buf = gdb_unparse_agent_expr (tpoint->cond);
sprintf (packet + strlen (packet), ":X%x,%s",
tpoint->cond->length, buf);
free (buf);
@@ -4549,7 +4491,7 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
trace_debug ("Want to evaluate expression");
- err = eval_agent_expr (ctx, tframe, eaction->expr, NULL);
+ err = eval_tracepoint_agent_expr (ctx, tframe, eaction->expr, NULL);
if (err != expr_eval_no_error)
{
@@ -4602,7 +4544,7 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
else
#endif
- err = eval_agent_expr (ctx, NULL, tpoint->cond, &value);
+ err = eval_tracepoint_agent_expr (ctx, NULL, tpoint->cond, &value);
if (err != expr_eval_no_error)
{
@@ -4617,463 +4559,26 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
return (value ? 1 : 0);
}
-#ifndef IN_PROCESS_AGENT
-
-/* The packet form of an agent expression consists of an 'X', number
- of bytes in expression, a comma, and then the bytes. */
-
-static struct agent_expr *
-parse_agent_expr (char **actparm)
-{
- char *act = *actparm;
- ULONGEST xlen;
- struct agent_expr *aexpr;
-
- ++act; /* skip the X */
- act = unpack_varlen_hex (act, &xlen);
- ++act; /* skip a comma */
- aexpr = xmalloc (sizeof (struct agent_expr));
- aexpr->length = xlen;
- aexpr->bytes = xmalloc (xlen);
- convert_ascii_to_int (act, aexpr->bytes, xlen);
- *actparm = act + (xlen * 2);
- return aexpr;
-}
-
-/* Convert the bytes of an agent expression back into hex digits, so
- they can be printed or uploaded. This allocates the buffer,
- callers should free when they are done with it. */
-
-static char *
-unparse_agent_expr (struct agent_expr *aexpr)
-{
- char *rslt;
-
- rslt = xmalloc (2 * aexpr->length + 1);
- convert_int_to_ascii (aexpr->bytes, rslt, aexpr->length);
- return rslt;
-}
-
-#endif
-
-/* A wrapper for gdb_agent_op_names that does some bounds-checking. */
-
-static const char *
-gdb_agent_op_name (int op)
-{
- if (op < 0 || op >= gdb_agent_op_last || gdb_agent_op_names[op] == NULL)
- return "?undef?";
- return gdb_agent_op_names[op];
-}
-
-/* The agent expression evaluator, as specified by the GDB docs. It
- returns 0 if everything went OK, and a nonzero error code
- otherwise. */
+/* Evaluates a tracepoint agent expression with context CTX,
+ traceframe TFRAME, agent expression AEXPR and store the
+ result in RSLT. */
static enum eval_result_type
-eval_agent_expr (struct tracepoint_hit_ctx *ctx,
- struct traceframe *tframe,
- struct agent_expr *aexpr,
- ULONGEST *rslt)
-{
- int pc = 0;
-#define STACK_MAX 100
- ULONGEST stack[STACK_MAX], top;
- int sp = 0;
- unsigned char op;
- int arg;
-
- /* This union is a convenient way to convert representations. For
- now, assume a standard architecture where the hardware integer
- types have 8, 16, 32, 64 bit types. A more robust solution would
- be to import stdint.h from gnulib. */
- union
- {
- union
- {
- unsigned char bytes[1];
- unsigned char val;
- } u8;
- union
- {
- unsigned char bytes[2];
- unsigned short val;
- } u16;
- union
- {
- unsigned char bytes[4];
- unsigned int val;
- } u32;
- union
- {
- unsigned char bytes[8];
- ULONGEST val;
- } u64;
- } cnv;
-
- if (aexpr->length == 0)
- {
- trace_debug ("empty agent expression");
- return expr_eval_empty_expression;
- }
-
- /* Cache the stack top in its own variable. Much of the time we can
- operate on this variable, rather than dinking with the stack. It
- needs to be copied to the stack when sp changes. */
- top = 0;
-
- while (1)
- {
- op = aexpr->bytes[pc++];
-
- trace_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)
- {
- trace_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)
- {
- trace_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)
- {
- trace_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)
- {
- trace_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 (tframe,
- 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 (tframe, 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 (tframe, cnv.u8.bytes, (CORE_ADDR) top, 1);
- top = cnv.u8.val;
- break;
-
- case gdb_agent_op_ref16:
- agent_mem_read (tframe, cnv.u16.bytes, (CORE_ADDR) top, 2);
- top = cnv.u16.val;
- break;
-
- case gdb_agent_op_ref32:
- agent_mem_read (tframe, cnv.u32.bytes, (CORE_ADDR) top, 4);
- top = cnv.u32.val;
- break;
-
- case gdb_agent_op_ref64:
- agent_mem_read (tframe, 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;
-
- regcache = get_context_regcache (ctx);
-
- switch (register_size (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 (__FILE__, __LINE__,
- "unhandled register size");
- }
- }
- break;
-
- case gdb_agent_op_end:
- trace_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 */
- trace_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 = get_trace_state_variable_value (arg);
- break;
-
- case gdb_agent_op_setv:
- arg = aexpr->bytes[pc++];
- arg = (arg << 8) + aexpr->bytes[pc++];
- 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 (tframe, arg);
- break;
-
- case gdb_agent_op_tracenz:
- agent_mem_read_string (tframe, NULL, (CORE_ADDR) stack[--sp],
- (ULONGEST) top);
- if (--sp >= 0)
- top = stack[sp];
- 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:
- trace_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 1;
-
- default:
- trace_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))
- {
- trace_debug ("Expression stack overflow");
- return expr_eval_stack_overflow;
- }
-
- if (sp < 0)
- {
- trace_debug ("Expression stack underflow");
- return expr_eval_stack_underflow;
- }
+eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx,
+ struct traceframe *tframe,
+ struct agent_expr *aexpr,
+ ULONGEST *rslt)
+{
+ struct regcache *regcache;
+ regcache = get_context_regcache (ctx);
- trace_debug ("Op %s -> sp=%d, top=0x%s",
- gdb_agent_op_name (op), sp, pulongest (top));
- }
+ return gdb_eval_agent_expr (regcache, tframe, aexpr, rslt);
}
/* Do memory copies for bytecodes. */
/* Do the recording of memory blocks for actions and bytecodes. */
-static int
+int
agent_mem_read (struct traceframe *tframe,
unsigned char *to, CORE_ADDR from, ULONGEST len)
{
@@ -5115,7 +4620,7 @@ agent_mem_read (struct traceframe *tframe,
return 0;
}
-static int
+int
agent_mem_read_string (struct traceframe *tframe,
unsigned char *to, CORE_ADDR from, ULONGEST len)
{
@@ -5177,7 +4682,7 @@ agent_mem_read_string (struct traceframe *tframe,
/* Record the value of a trace state variable. */
-static int
+int
agent_tsv_read (struct traceframe *tframe, int n)
{
unsigned char *vspace;
@@ -5970,250 +5475,24 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
#ifndef IN_PROCESS_AGENT
-/* Bytecode compilation. */
-
-CORE_ADDR current_insn_ptr;
-
-int emit_error;
-
-struct bytecode_address
-{
- int pc;
- CORE_ADDR address;
- int goto_pc;
- /* Offset and size of field to be modified in the goto block. */
- int from_offset, from_size;
- struct bytecode_address *next;
-} *bytecode_address_table;
-
CORE_ADDR
get_raw_reg_func_addr (void)
{
return ipa_sym_addrs.addr_get_raw_reg;
}
-static void
-emit_prologue (void)
-{
- target_emit_ops ()->emit_prologue ();
-}
-
-static void
-emit_epilogue (void)
-{
- target_emit_ops ()->emit_epilogue ();
-}
-
-static void
-emit_add (void)
-{
- target_emit_ops ()->emit_add ();
-}
-
-static void
-emit_sub (void)
-{
- target_emit_ops ()->emit_sub ();
-}
-
-static void
-emit_mul (void)
-{
- target_emit_ops ()->emit_mul ();
-}
-
-static void
-emit_lsh (void)
-{
- target_emit_ops ()->emit_lsh ();
-}
-
-static void
-emit_rsh_signed (void)
-{
- target_emit_ops ()->emit_rsh_signed ();
-}
-
-static void
-emit_rsh_unsigned (void)
-{
- target_emit_ops ()->emit_rsh_unsigned ();
-}
-
-static void
-emit_ext (int arg)
-{
- target_emit_ops ()->emit_ext (arg);
-}
-
-static void
-emit_log_not (void)
-{
- target_emit_ops ()->emit_log_not ();
-}
-
-static void
-emit_bit_and (void)
-{
- target_emit_ops ()->emit_bit_and ();
-}
-
-static void
-emit_bit_or (void)
-{
- target_emit_ops ()->emit_bit_or ();
-}
-
-static void
-emit_bit_xor (void)
-{
- target_emit_ops ()->emit_bit_xor ();
-}
-
-static void
-emit_bit_not (void)
-{
- target_emit_ops ()->emit_bit_not ();
-}
-
-static void
-emit_equal (void)
-{
- target_emit_ops ()->emit_equal ();
-}
-
-static void
-emit_less_signed (void)
-{
- target_emit_ops ()->emit_less_signed ();
-}
-
-static void
-emit_less_unsigned (void)
-{
- target_emit_ops ()->emit_less_unsigned ();
-}
-
-static void
-emit_ref (int size)
-{
- target_emit_ops ()->emit_ref (size);
-}
-
-static void
-emit_if_goto (int *offset_p, int *size_p)
-{
- target_emit_ops ()->emit_if_goto (offset_p, size_p);
-}
-
-static void
-emit_goto (int *offset_p, int *size_p)
-{
- target_emit_ops ()->emit_goto (offset_p, size_p);
-}
-
-static void
-write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
-{
- target_emit_ops ()->write_goto_address (from, to, size);
-}
-
-static void
-emit_const (LONGEST num)
-{
- target_emit_ops ()->emit_const (num);
-}
-
-static void
-emit_reg (int reg)
-{
- target_emit_ops ()->emit_reg (reg);
-}
-
-static void
-emit_pop (void)
-{
- target_emit_ops ()->emit_pop ();
-}
-
-static void
-emit_stack_flush (void)
-{
- target_emit_ops ()->emit_stack_flush ();
-}
-
-static void
-emit_zero_ext (int arg)
-{
- target_emit_ops ()->emit_zero_ext (arg);
-}
-
-static void
-emit_swap (void)
-{
- target_emit_ops ()->emit_swap ();
-}
-
-static void
-emit_stack_adjust (int n)
-{
- target_emit_ops ()->emit_stack_adjust (n);
-}
-
-/* FN's prototype is `LONGEST(*fn)(int)'. */
-
-static void
-emit_int_call_1 (CORE_ADDR fn, int arg1)
-{
- target_emit_ops ()->emit_int_call_1 (fn, arg1);
-}
-
-/* FN's prototype is `void(*fn)(int,LONGEST)'. */
-
-static void
-emit_void_call_2 (CORE_ADDR fn, int arg1)
-{
- target_emit_ops ()->emit_void_call_2 (fn, arg1);
-}
-
-static void
-emit_eq_goto (int *offset_p, int *size_p)
-{
- target_emit_ops ()->emit_eq_goto (offset_p, size_p);
-}
-
-static void
-emit_ne_goto (int *offset_p, int *size_p)
-{
- target_emit_ops ()->emit_ne_goto (offset_p, size_p);
-}
-
-static void
-emit_lt_goto (int *offset_p, int *size_p)
-{
- target_emit_ops ()->emit_lt_goto (offset_p, size_p);
-}
-
-static void
-emit_ge_goto (int *offset_p, int *size_p)
-{
- target_emit_ops ()->emit_ge_goto (offset_p, size_p);
-}
-
-static void
-emit_gt_goto (int *offset_p, int *size_p)
+CORE_ADDR
+get_get_tsv_func_addr (void)
{
- target_emit_ops ()->emit_gt_goto (offset_p, size_p);
+ return ipa_sym_addrs.addr_get_trace_state_variable_value;
}
-static void
-emit_le_goto (int *offset_p, int *size_p)
+CORE_ADDR
+get_set_tsv_func_addr (void)
{
- target_emit_ops ()->emit_le_goto (offset_p, size_p);
+ return ipa_sym_addrs.addr_set_trace_state_variable_value;
}
-static enum eval_result_type compile_bytecodes (struct agent_expr *aexpr);
-
static void
compile_tracepoint_condition (struct tracepoint *tpoint,
CORE_ADDR *jump_entry)
@@ -6261,436 +5540,6 @@ compile_tracepoint_condition (struct tracepoint *tpoint,
*jump_entry += 16;
}
-/* Scan an agent expression for any evidence that the given PC is the
- target of a jump bytecode in the expression. */
-
-int
-is_goto_target (struct agent_expr *aexpr, int pc)
-{
- int i;
- unsigned char op;
-
- for (i = 0; i < aexpr->length; i += 1 + gdb_agent_op_sizes[op])
- {
- 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;
- }
- }
-
- return 0;
-}
-
-/* Given an agent expression, turn it into native code. */
-
-static enum eval_result_type
-compile_bytecodes (struct agent_expr *aexpr)
-{
- int pc = 0;
- int done = 0;
- unsigned char op, next_op;
- int arg;
- /* This is only used to build 64-bit value for constants. */
- ULONGEST top;
- struct bytecode_address *aentry, *aentry2;
-
-#define UNHANDLED \
- do \
- { \
- trace_debug ("Cannot compile op 0x%x\n", op); \
- return expr_eval_unhandled_opcode; \
- } while (0)
-
- if (aexpr->length == 0)
- {
- trace_debug ("empty agent expression\n");
- return expr_eval_empty_expression;
- }
-
- bytecode_address_table = NULL;
-
- while (!done)
- {
- op = aexpr->bytes[pc];
-
- trace_debug ("About to compile op 0x%x, pc=%d\n", op, pc);
-
- /* Record the compiled-code address of the bytecode, for use by
- jump instructions. */
- aentry = xmalloc (sizeof (struct bytecode_address));
- aentry->pc = pc;
- aentry->address = current_insn_ptr;
- aentry->goto_pc = -1;
- aentry->from_offset = aentry->from_size = 0;
- aentry->next = bytecode_address_table;
- bytecode_address_table = aentry;
-
- ++pc;
-
- 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)
- {
- trace_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)
- {
- trace_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))
- {
- trace_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))
- {
- trace_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:
- trace_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))
- {
- trace_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))
- {
- trace_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 (ipa_sym_addrs.addr_get_trace_state_variable_value,
- arg);
- break;
-
- case gdb_agent_op_setv:
- arg = aexpr->bytes[pc++];
- arg = (arg << 8) + aexpr->bytes[pc++];
- emit_void_call_2 (ipa_sym_addrs.addr_set_trace_state_variable_value,
- 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:
- trace_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)
- {
- trace_debug ("Error %d while emitting code for %s\n",
- emit_error, gdb_agent_op_name (op));
- return expr_eval_unhandled_opcode;
- }
-
- trace_debug ("Op %s compiled\n", gdb_agent_op_name (op));
- }
-
- /* Now fill in real addresses as goto destinations. */
- for (aentry = bytecode_address_table; aentry; aentry = aentry->next)
- {
- int written = 0;
-
- if (aentry->goto_pc < 0)
- 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)
- {
- trace_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)
- {
- trace_debug ("Destination of goto %d not found\n",
- aentry->goto_pc);
- return expr_eval_invalid_goto;
- }
- }
-
- return expr_eval_no_error;
-}
-
/* We'll need to adjust these when we consider bi-arch setups, and big
endian machines. */