diff options
-rw-r--r-- | gdb/ChangeLog | 33 | ||||
-rw-r--r-- | gdb/ax-gdb.c | 5 | ||||
-rw-r--r-- | gdb/infrun.c | 14 | ||||
-rw-r--r-- | gdb/thread.c | 14 | ||||
-rw-r--r-- | gdb/tracepoint.c | 14 | ||||
-rw-r--r-- | gdb/value.c | 44 | ||||
-rw-r--r-- | gdb/value.h | 48 | ||||
-rw-r--r-- | gdb/windows-tdep.c | 13 |
8 files changed, 167 insertions, 18 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e6b04dd..22883eb 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,36 @@ +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 diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index aaefed6..eebe61a 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -2038,7 +2038,8 @@ gen_expr (struct expression *exp, union exp_element **pc, 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; @@ -2052,7 +2053,7 @@ gen_expr (struct expression *exp, union exp_element **pc, 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); } diff --git a/gdb/infrun.c b/gdb/infrun.c index 854ab01..4425413 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -6602,7 +6602,8 @@ static const struct lval_funcs siginfo_value_funcs = 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) @@ -7024,6 +7025,15 @@ show_schedule_multiple (struct ui_file *file, int from_tty, "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) { @@ -7312,7 +7322,7 @@ enabled by default on some platforms."), 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, _("\ diff --git a/gdb/thread.c b/gdb/thread.c index 97f283c..d361dd8 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1439,7 +1439,8 @@ update_thread_list (void) 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); @@ -1450,6 +1451,15 @@ thread_id_make_value (struct gdbarch *gdbarch, struct internalvar *var) /* 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) { @@ -1495,5 +1505,5 @@ Show printing of thread events (such as thread start and exit)."), NULL, show_print_thread_events, &setprintlist, &showprintlist); - create_internalvar_type_lazy ("_thread", thread_id_make_value); + create_internalvar_type_lazy ("_thread", &thread_funcs, NULL); } diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 86b6cfa..c213374 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -4944,7 +4944,8 @@ info_static_tracepoint_markers_command (char *arg, int from_tty) 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; @@ -5123,6 +5124,15 @@ traceframe_available_memory (VEC(mem_range_s) **result, return 0; } +/* Implementation of `sdata' variable. */ + +static const struct internalvar_funcs sdata_funcs = +{ + sdata_make_value, + NULL, + NULL +}; + /* module initialization */ void _initialize_tracepoint (void) @@ -5133,7 +5143,7 @@ _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; diff --git a/gdb/value.c b/gdb/value.c index eae3e2d..d498289 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -1629,7 +1629,14 @@ struct internalvar 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 @@ -1728,18 +1735,39 @@ create_internalvar (const char *name) /* 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. @@ -1812,7 +1840,8 @@ value_of_internalvar (struct gdbarch *gdbarch, struct internalvar *var) 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: @@ -2008,6 +2037,11 @@ clear_internalvar (struct internalvar *var) 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; } diff --git a/gdb/value.h b/gdb/value.h index 03aa5fd..76c8e85 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -764,10 +764,52 @@ extern struct internalvar *lookup_only_internalvar (const char *name); 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); diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c index 6b84eff..a704599 100644 --- a/gdb/windows-tdep.c +++ b/gdb/windows-tdep.c @@ -268,7 +268,7 @@ static const struct lval_funcs tlb_value_funcs = 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)) { @@ -428,6 +428,15 @@ init_w32_command_list (void) /* 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) { @@ -454,5 +463,5 @@ even if their meaning is unknown."), 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); } |