+2012-04-27 Sergio Durigan Junior <sergiodj@redhat.com>
+ Tom Tromey <tromey@redhat.com>
+
+ * ax-gdb.c (gen_expr): Clean up code to handle internal variables
+ and to compile agent expressions.
+ * infrun.c (siginfo_make_value): New argument `ignore'.
+ (siginfo_funcs): New struct.
+ (_initialize_infrun): New argument when calling
+ `create_internalvar_type_lazy'.
+ * thread.c (thread_id_make_value): New argument `ignore'.
+ (thread_funcs): New struct.
+ (_initialize_thread): New argument when calling
+ `create_internalvar_type_lazy'.
+ * tracepoint.c (sdata_make_value): New argument `ignore'.
+ (sdata_funcs): New struct.
+ (_initialize_tracepoint): New argument when calling
+ `create_internalvar_type_lazy'.
+ * value.c (make_value): New struct.
+ (create_internalvar_type_lazy): New argument `data'.
+ (compile_internalvar_to_ax): New function.
+ (value_of_internalvar): Properly handling `make_value' case.
+ (clear_internalvar): Likewise.
+ (show_convenience): Adding `TRY_CATCH' block.
+ * value.h (internalvar_make_value): Delete, replace by...
+ (struct internalvar_funcs): ... this.
+ (create_internalvar_type_lazy) <fun>: Delete argument.
+ (create_internalvar_type_lazy) <funcs>, <data>: New arguments.
+ (compile_internalvar_to_ax): New function.
+ * windows-tdep.c (tlb_make_value): New argument `ignore'.
+ (tlb_funcs): New struct.
+ (_initialize_windows_tdep): New argument when calling
+ `create_internalvar_type_lazy'.
+
2012-04-27 Mark Wielaard <mjw@redhat.com>
* dwarf2read.c (dwarf2_get_pc_bounds): Check DW_AT_high_pc form to
case OP_INTERNALVAR:
{
- const char *name = internalvar_name ((*pc)[1].internalvar);
+ struct internalvar *var = (*pc)[1].internalvar;
+ const char *name = internalvar_name (var);
struct trace_state_variable *tsv;
(*pc) += 3;
value->kind = axs_rvalue;
value->type = builtin_type (exp->gdbarch)->builtin_long_long;
}
- else
+ else if (! compile_internalvar_to_ax (var, ax, value))
error (_("$%s is not a trace state variable; GDB agent "
"expressions cannot use convenience variables."), name);
}
if there's no object available. */
static struct value *
-siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+siginfo_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+ void *ignore)
{
if (target_has_stack
&& !ptid_equal (inferior_ptid, null_ptid)
"of all processes is %s.\n"), value);
}
+/* Implementation of `siginfo' variable. */
+
+static const struct internalvar_funcs siginfo_funcs =
+{
+ siginfo_make_value,
+ NULL,
+ NULL
+};
+
void
_initialize_infrun (void)
{
value with a void typed value, and when we get here, gdbarch
isn't initialized yet. At this point, we're quite sure there
isn't another convenience variable of the same name. */
- create_internalvar_type_lazy ("_siginfo", siginfo_make_value);
+ create_internalvar_type_lazy ("_siginfo", &siginfo_funcs, NULL);
add_setshow_boolean_cmd ("observer", no_class,
&observer_mode_1, _("\
no thread is selected, or no threads exist. */
static struct value *
-thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+ void *ignore)
{
struct thread_info *tp = find_thread_ptid (inferior_ptid);
/* Commands with a prefix of `thread'. */
struct cmd_list_element *thread_cmd_list = NULL;
+/* Implementation of `thread' variable. */
+
+static const struct internalvar_funcs thread_funcs =
+{
+ thread_id_make_value,
+ NULL,
+ NULL
+};
+
void
_initialize_thread (void)
{
show_print_thread_events,
&setprintlist, &showprintlist);
- create_internalvar_type_lazy ("_thread", thread_id_make_value);
+ create_internalvar_type_lazy ("_thread", &thread_funcs, NULL);
}
available. */
static struct value *
-sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
+ void *ignore)
{
LONGEST size;
gdb_byte *buf;
return 0;
}
+/* Implementation of `sdata' variable. */
+
+static const struct internalvar_funcs sdata_funcs =
+{
+ sdata_make_value,
+ NULL,
+ NULL
+};
+
/* module initialization */
void
_initialize_tracepoint (void)
value with a void typed value, and when we get here, gdbarch
isn't initialized yet. At this point, we're quite sure there
isn't another convenience variable of the same name. */
- create_internalvar_type_lazy ("_sdata", sdata_make_value);
+ create_internalvar_type_lazy ("_sdata", &sdata_funcs, NULL);
traceframe_number = -1;
tracepoint_number = -1;
struct value *value;
/* The call-back routine used with INTERNALVAR_MAKE_VALUE. */
- internalvar_make_value make_value;
+ struct
+ {
+ /* The functions to call. */
+ const struct internalvar_funcs *functions;
+
+ /* The function's user-data. */
+ void *data;
+ } make_value;
/* The internal function used with INTERNALVAR_FUNCTION. */
struct
/* Create an internal variable with name NAME and register FUN as the
function that value_of_internalvar uses to create a value whenever
this variable is referenced. NAME should not normally include a
- dollar sign. */
+ dollar sign. DATA is passed uninterpreted to FUN when it is
+ called. CLEANUP, if not NULL, is called when the internal variable
+ is destroyed. It is passed DATA as its only argument. */
struct internalvar *
-create_internalvar_type_lazy (char *name, internalvar_make_value fun)
+create_internalvar_type_lazy (const char *name,
+ const struct internalvar_funcs *funcs,
+ void *data)
{
struct internalvar *var = create_internalvar (name);
var->kind = INTERNALVAR_MAKE_VALUE;
- var->u.make_value = fun;
+ var->u.make_value.functions = funcs;
+ var->u.make_value.data = data;
return var;
}
+/* See documentation in value.h. */
+
+int
+compile_internalvar_to_ax (struct internalvar *var,
+ struct agent_expr *expr,
+ struct axs_value *value)
+{
+ if (var->kind != INTERNALVAR_MAKE_VALUE
+ || var->u.make_value.functions->compile_to_ax == NULL)
+ return 0;
+
+ var->u.make_value.functions->compile_to_ax (var, expr, value,
+ var->u.make_value.data);
+ return 1;
+}
+
/* Look up an internal variable with name NAME. NAME should not
normally include a dollar sign.
break;
case INTERNALVAR_MAKE_VALUE:
- val = (*var->u.make_value) (gdbarch, var);
+ val = (*var->u.make_value.functions->make_value) (gdbarch, var,
+ var->u.make_value.data);
break;
default:
xfree (var->u.string);
break;
+ case INTERNALVAR_MAKE_VALUE:
+ if (var->u.make_value.functions->destroy != NULL)
+ var->u.make_value.functions->destroy (var->u.make_value.data);
+ break;
+
default:
break;
}
extern struct internalvar *create_internalvar (const char *name);
-typedef struct value * (*internalvar_make_value) (struct gdbarch *,
- struct internalvar *);
+/* An internalvar can be dynamically computed by supplying a vector of
+ function pointers to perform various operations. */
+
+struct internalvar_funcs
+{
+ /* Compute the value of the variable. The DATA argument passed to
+ the function is the same argument that was passed to
+ `create_internalvar_type_lazy'. */
+
+ struct value *(*make_value) (struct gdbarch *arch,
+ struct internalvar *var,
+ void *data);
+
+ /* Update the agent expression EXPR with bytecode to compute the
+ value. VALUE is the agent value we are updating. The DATA
+ argument passed to this function is the same argument that was
+ passed to `create_internalvar_type_lazy'. If this pointer is
+ NULL, then the internalvar cannot be compiled to an agent
+ expression. */
+
+ void (*compile_to_ax) (struct internalvar *var,
+ struct agent_expr *expr,
+ struct axs_value *value,
+ void *data);
+
+ /* If non-NULL, this is called to destroy DATA. The DATA argument
+ passed to this function is the same argument that was passed to
+ `create_internalvar_type_lazy'. */
+
+ void (*destroy) (void *data);
+};
+
extern struct internalvar *
- create_internalvar_type_lazy (char *name, internalvar_make_value fun);
+create_internalvar_type_lazy (const char *name,
+ const struct internalvar_funcs *funcs,
+ void *data);
+
+/* Compile an internal variable to an agent expression. VAR is the
+ variable to compile; EXPR and VALUE are the agent expression we are
+ updating. This will return 0 if there is no known way to compile
+ VAR, and 1 if VAR was successfully compiled. It may also throw an
+ exception on error. */
+
+extern int compile_internalvar_to_ax (struct internalvar *var,
+ struct agent_expr *expr,
+ struct axs_value *value);
extern struct internalvar *lookup_internalvar (const char *name);
if there's no object available. */
static struct value *
-tlb_make_value (struct gdbarch *gdbarch, struct internalvar *var)
+tlb_make_value (struct gdbarch *gdbarch, struct internalvar *var, void *ignore)
{
if (target_has_stack && !ptid_equal (inferior_ptid, null_ptid))
{
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_windows_tdep;
+/* Implementation of `tlb' variable. */
+
+static const struct internalvar_funcs tlb_funcs =
+{
+ tlb_make_value,
+ NULL,
+ NULL
+};
+
void
_initialize_windows_tdep (void)
{
value with a void typed value, and when we get here, gdbarch
isn't initialized yet. At this point, we're quite sure there
isn't another convenience variable of the same name. */
- create_internalvar_type_lazy ("_tlb", tlb_make_value);
+ create_internalvar_type_lazy ("_tlb", &tlb_funcs, NULL);
}