From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22834 invoked by alias); 4 Apr 2011 03:08:45 -0000 Received: (qmail 22822 invoked by uid 22791); 4 Apr 2011 03:08:43 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,T_FILL_THIS_FORM_SHORT,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 04 Apr 2011 03:08:37 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p3438a8G011971 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 3 Apr 2011 23:08:36 -0400 Received: from psique (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p3438Y05013104; Sun, 3 Apr 2011 23:08:35 -0400 From: Sergio Durigan Junior To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 3/6] Modify internalvar mechanism Date: Mon, 04 Apr 2011 03:08:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.2 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-04/txt/msg00039.txt.bz2 Hi, This patch modifies the mechanism of internalvar. It basically adds more manipulation functions to them (`compile_to_ax' and `destroy'), and updates the definitions and pointers of existing internalvars. Regtested on the compile farm. Thanks, Sergio. --- gdb/ChangeLog | 32 ++++++++++++++++++++++++++++ gdb/ax-gdb.c | 5 ++- gdb/infrun.c | 14 ++++++++++- gdb/thread.c | 14 ++++++++++- gdb/tracepoint.c | 14 ++++++++++- gdb/value.c | 58 ++++++++++++++++++++++++++++++++++++++++++++------- gdb/value.h | 48 ++++++++++++++++++++++++++++++++++++++++-- gdb/windows-tdep.c | 13 +++++++++- 8 files changed, 177 insertions(+), 21 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f20653b..1fa276d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,37 @@ 2011-04-04 Tom Tromey + * 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) : Delete argument. + (create_internalvar_type_lazy) , : 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'. + +2011-04-04 Tom Tromey + * breakpoint.c (create_breakpoints_sal): Added code to handle pre-expanded sals. (create_breakpoint): Likewise. diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index d1736e1..3e54716 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -2001,7 +2001,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; @@ -2015,7 +2016,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 7cee7c8..77d8da8 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -6253,7 +6253,8 @@ static 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) @@ -6826,6 +6827,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) { @@ -7098,7 +7108,7 @@ Tells gdb whether to detach the child of a fork."), 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 6ad1807..aef9dce 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1438,7 +1438,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); @@ -1449,6 +1450,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 struct internalvar_funcs thread_funcs = +{ + thread_id_make_value, + NULL, + NULL +}; + void _initialize_thread (void) { @@ -1494,5 +1504,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 3ae35d0..12e1b80 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -4497,7 +4497,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; @@ -4676,6 +4677,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) @@ -4686,7 +4696,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 2acb1df..f2eb01d 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -1530,7 +1530,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 @@ -1629,18 +1636,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. @@ -1713,7 +1741,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: @@ -1909,6 +1938,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; } @@ -2080,14 +2114,22 @@ show_convenience (char *ignore, int from_tty) get_user_print_options (&opts); for (var = internalvars; var; var = var->next) { + volatile struct gdb_exception e; + if (!varseen) { varseen = 1; } printf_filtered (("$%s = "), var->name); - value_print (value_of_internalvar (gdbarch, var), gdb_stdout, - &opts); - printf_filtered (("\n")); + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + value_print (value_of_internalvar (gdbarch, var), gdb_stdout, + &opts); + printf_filtered (("\n")); + } + if (e.reason < 0) + printf_filtered (_("\n"), e.message); } if (!varseen) printf_unfiltered (_("No debugger convenience variables now defined.\n" diff --git a/gdb/value.h b/gdb/value.h index 0889cef..71c995c 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -697,10 +697,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 31ddd14..b319250 100644 --- a/gdb/windows-tdep.c +++ b/gdb/windows-tdep.c @@ -268,7 +268,7 @@ static 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)) { @@ -425,6 +425,15 @@ init_w32_command_list (void) } } +/* Implementation of `tlb' variable. */ + +static const struct internalvar_funcs tlb_funcs = +{ + tlb_make_value, + NULL, + NULL +}; + void _initialize_windows_tdep (void) { @@ -451,5 +460,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); }