From 5e1dc496746ac407cad3b99d2a89e776d08ee326 Mon Sep 17 00:00:00 2001 From: Luis Machado Date: Fri, 24 Feb 2012 15:13:37 +0000 Subject: [PATCH] 2012-02-24 Luis Machado * 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. --- gdb/gdbserver/ChangeLog | 61 ++ gdb/gdbserver/Makefile.in | 14 +- gdb/gdbserver/server.h | 32 + gdb/gdbserver/tracepoint.c | 1239 ++---------------------------------- 4 files changed, 146 insertions(+), 1200 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index aa9f556297e..c1baa9604b1 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,64 @@ +2012-02-24 Luis Machado + + * 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 * tracepoint.c (cmd_bigqtbuffer): Rename as ... diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index c6a8bff7cbc..b4d2006ee85 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 d3b4463a2ad..30d608cec07 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 cd58c2d0d44..dfa48a72e1e 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -25,6 +25,7 @@ #if HAVE_STDINT_H #include #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. */ -- 2.30.2