From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22909 invoked by alias); 18 Jul 2011 20:19:42 -0000 Received: (qmail 22888 invoked by uid 22791); 18 Jul 2011 20:19:34 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_CP 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, 18 Jul 2011 20:19:00 +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 p6IKIxFQ001002 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 18 Jul 2011 16:19:00 -0400 Received: from host1.jankratochvil.net (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p6IKIr53000378 for ; Mon, 18 Jul 2011 16:18:54 -0400 Received: from host1.jankratochvil.net (localhost [127.0.0.1]) by host1.jankratochvil.net (8.14.4/8.14.4) with ESMTP id p6IKIr1K015535 for ; Mon, 18 Jul 2011 22:18:53 +0200 Received: (from jkratoch@localhost) by host1.jankratochvil.net (8.14.4/8.14.4/Submit) id p6IKIreh015534 for gdb-patches@sourceware.org; Mon, 18 Jul 2011 22:18:53 +0200 Date: Mon, 18 Jul 2011 20:21:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: [RFC 06/12] entryval: Display @entry parameters in bt full Message-ID: <20110718201852.GG30496@host1.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) 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-07/txt/msg00438.txt.bz2 Hi, this is a first kind of access to the entry values. A (non-testcase) demo is: #8 0x000000000048c50d in execute_command (p=0x22b573b "", from_tty=1) at top.c:438 p@entry = 0x22b5720 "maintenance internal-error " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ arg = cleanup = 0x28333b0 c = 0x24996d0 flang = warned = 0 line = 0x22b5720 "maintenance internal-error " p@entry is not particularly useful here because the `line' local variable contains the same. One can imagine in other real world applications it can be useful - for a backtrace sent by user where you do not have a reproducer and/or the core file (the case of ABRT bugreports). The parameter@entry lines are not displayed if they are not useful. Therefore if they would display the same value as the current parameter value or if GDB cannot successfully determine the entry value. It is displayed by `bt full' and `info args'. RFC is whether it is not too verbose and/or if it should not be displayed some way even with normal `bt'. Also whether there should be some `set' variable to forget about @entry values. Thanks, Jan gdb/ 2011-07-18 Jan Kratochvil Display @entry parameter values (without references). * doc/gdb.texinfo (backtrace full, info args): Mention @entry suffix. * dwarf2expr.c (dwarf_block_to_fb_offset): New function. * dwarf2expr.h (dwarf_block_to_fb_offset): New declaration. * dwarf2loc.c (dwarf2_find_location_expression): Support location list entry record. (dwarf_entry_parameter_to_value): New function. (dwarf2_locexpr_funcs): New NULL for read_variable_at_entry. (value_of_dwarf_reg_entry, loclist_read_variable_at_entry): New functions. (dwarf2_loclist_funcs): Install loclist_read_variable_at_entry. * f-valprint.c (info_common_command): Add PVAVD_IS_NOT_ARGUMENT to the print_variable_and_value call. * printcmd.c (print_variable_and_value): New parameter print_argument, describe it. Print @entry parameter value when appropriate. * stack.c (struct print_variable_and_value_data): New field print_argument. (do_print_variable_and_value): Pass the print_argument parameter. (print_frame_local_vars): Change the parameter num_tabs to from_frame. Print @entry parameters if FROM_FRAME. (print_frame_arg_vars): Specify PVAVD_ARGUMENT_PRINT_BOTH. * symtab.h (struct symbol_computed_ops): New field read_variable_at_entry. * value.h (enum print_argument): New. (print_variable_and_value): New parameter print_argument. gdb/testsuite/ 2011-07-18 Jan Kratochvil Display @entry parameter values (without references). * gdb.arch/amd64-entry-value.cc (stacktest, reference): New functions. (main): New variable refvar, call stacktest and reference. * gdb.arch/amd64-entry-value.exp: New breakpoints stacktest, breakhere_stacktest, reference and breakhere_reference. (entry: bt full): Update for @entry. (entry_stack: stacktest, entry_stack: bt full at entry) (entry_stack: breakhere_stacktest, entry_stack: bt full) (entry_stack: p s1, entry_stack: p s2, entry_reference: reference) (entry_reference: bt full at entry) (entry_reference: breakhere_reference, entry_reference: bt full) (entry_reference: ptype refparam, entry_reference: p refparam) (entry_reference: p refcopy): New tests. --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -5947,8 +5947,13 @@ Similar, but print only the outermost @var{n} frames. @itemx bt full @itemx bt full @var{n} @itemx bt full -@var{n} -Print the values of the local variables also. @var{n} specifies the -number of frames to print, as described above. +Print the values of the local variables also. + +Names with appended @code{@@entry} show values of function parameters at the +time the function got called. The @code{@@entry} parameter line is not shown +when the entry value is not available. + +@var{n} specifies the number of frames to print, as described above. @end table @kindex where @@ -6223,6 +6228,10 @@ architectures) that you specify in the @code{frame} command. @item info args Print the arguments of the selected frame, each on a separate line. +Names with appended @code{@@entry} show values of function parameters at the +time the function got called. The @code{@@entry} parameter line is not shown +when the entry value is not available. + @item info locals @kindex info locals Print the local variables of the selected frame, each on a separate --- a/gdb/dwarf2expr.c +++ b/gdb/dwarf2expr.c @@ -602,6 +602,30 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf, return 1; } +/* If = low && pc < high) { *locexpr_length = length; @@ -913,6 +931,35 @@ dwarf_entry_parameter_to_block (struct call_site_parameter *parameter, return parameter->call_site_data_value; } +/* Return value for PARAMETER matching DEREF_SIZE, see + dwarf_entry_parameter_to_block for the description of these parameters. + + TYPE and CALLER_FRAME specify how to evaluate the DWARF block into returned + struct value. + + Function always returns non-NULL, non-optimized out value. It throws + NOT_FOUND_ERROR if it cannot resolve the value for any reason. */ + +static struct value * +dwarf_entry_parameter_to_value (struct call_site_parameter *parameter, + CORE_ADDR deref_size, struct type *type, + struct frame_info *caller_frame) +{ + struct dwarf2_locexpr_baton *dwarf_block; + gdb_byte *data; + + dwarf_block = dwarf_entry_parameter_to_block (parameter, deref_size); + + /* DW_AT_GNU_call_site_value is a DWARF expression, not a DWARF + location. */ + data = alloca (dwarf_block->size + 1); + memcpy (data, dwarf_block->data, dwarf_block->size); + data[dwarf_block->size] = DW_OP_stack_value; + + return dwarf2_evaluate_loc_desc (type, caller_frame, data, + dwarf_block->size + 1, dwarf_block->per_cu); +} + /* Execute DWARF_BLOCK for caller of the CTX's frame. CTX must be of dwarf_expr_ctx_funcs kind. See DWARF_REG, FB_OFFSET and DEREF_SIZE description at struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value. @@ -3500,6 +3547,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, evaluator. */ const struct symbol_computed_ops dwarf2_locexpr_funcs = { locexpr_read_variable, + NULL, /* read_variable_at_entry */ locexpr_read_needs_frame, locexpr_describe_location, locexpr_tracepoint_var_ref @@ -3530,6 +3578,64 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame) return val; } +/* Return value of parameter of TYPE at (callee) FRAME which at function entry + point. Parameter has been passed in DWARF_REG or FB_OFFSET, see their + description at struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value. + + Function always returns non-NULL, non-optimized out value. It throws + NOT_FOUND_ERROR if it cannot resolve the value for any reason. */ + +static struct value * +value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame, + int dwarf_reg, CORE_ADDR fb_offset) +{ + struct frame_info *caller_frame = get_prev_frame (frame); + struct call_site_parameter *parameter; + + parameter = dwarf_expr_dwarf_reg_entry_value (frame, dwarf_reg, fb_offset); + + return dwarf_entry_parameter_to_value (parameter, -1 /* deref_size */, type, + caller_frame); +} + +/* Read variable SYMBOL like loclist_read_variable at (callee) FRAME's function + entry. SYMBOL should be a function parameter, otherwise NOT_FOUND_ERROR + will be thrown. + + Function always returns non-NULL value, it may be marked optimized out if + inferior frame information is not available. It throws NOT_FOUND_ERROR if + it cannot resolve the parameter for any reason. */ + +static struct value * +loclist_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame) +{ + struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + struct value *val; + const gdb_byte *data; + size_t size; + int dwarf_reg; + CORE_ADDR deref_size, pc, fb_offset; + + if (frame == NULL || !get_frame_func_if_available (frame, &pc)) + return allocate_optimized_out_value (SYMBOL_TYPE (symbol)); + + data = dwarf2_find_location_expression (dlbaton, &size, pc); + if (data == NULL) + return allocate_optimized_out_value (SYMBOL_TYPE (symbol)); + + dwarf_reg = dwarf_block_to_dwarf_reg (data, data + size); + if (dwarf_reg != -1) + return value_of_dwarf_reg_entry (SYMBOL_TYPE (symbol), frame, dwarf_reg, + 0 /* unused */); + + if (dwarf_block_to_fb_offset (data, data + size, &fb_offset)) + return value_of_dwarf_reg_entry (SYMBOL_TYPE (symbol), frame, -1, + fb_offset); + + error (_("DWARF-2 expression error: DW_OP_GNU_entry_value is supported only " + "for single DW_OP_reg* or for DW_OP_fbreg(*)")); +} + /* Return non-zero iff we need a frame to evaluate SYMBOL. */ static int loclist_read_needs_frame (struct symbol *symbol) @@ -3649,6 +3755,7 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, evaluator and location lists. */ const struct symbol_computed_ops dwarf2_loclist_funcs = { loclist_read_variable, + loclist_read_variable_at_entry, loclist_read_needs_frame, loclist_describe_location, loclist_tracepoint_var_ref --- a/gdb/f-valprint.c +++ b/gdb/f-valprint.c @@ -610,7 +610,8 @@ info_common_command (char *comname, int from_tty) while (entry != NULL) { - print_variable_and_value (NULL, entry->symbol, fi, gdb_stdout, 0); + print_variable_and_value (NULL, entry->symbol, fi, gdb_stdout, 0, + PVAVD_IS_NOT_ARGUMENT); entry = entry->next; } } --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -1939,32 +1939,74 @@ clear_dangling_display_expressions (struct so_list *solib) struct symbol. NAME is the name to print; if NULL then VAR's print name will be used. STREAM is the ui_file on which to print the value. INDENT specifies the number of indent levels to print - before printing the variable name. */ + before printing the variable name. PRINT_ARGUMENT specifies whether @entry + kind of function parameters should be printed. */ void print_variable_and_value (const char *name, struct symbol *var, struct frame_info *frame, - struct ui_file *stream, int indent) + struct ui_file *stream, int indent, + enum print_argument print_argument) { volatile struct gdb_exception except; if (!name) name = SYMBOL_PRINT_NAME (var); - fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name); TRY_CATCH (except, RETURN_MASK_ERROR) { - struct value *val; + struct value *val, *entryval = NULL; struct value_print_options opts; val = read_var_value (var, frame); get_user_print_options (&opts); - common_val_print (val, stream, indent, &opts, current_language); + + if (print_argument != PVAVD_IS_NOT_ARGUMENT + && SYMBOL_CLASS (var) == LOC_COMPUTED + && SYMBOL_COMPUTED_OPS (var)->read_variable_at_entry != NULL) + { + const struct symbol_computed_ops *ops; + unsigned len = TYPE_LENGTH (value_type (val)); + volatile struct gdb_exception entryval_ex; + + ops = SYMBOL_COMPUTED_OPS (var); + + TRY_CATCH (entryval_ex, RETURN_MASK_ERROR) + { + entryval = ops->read_variable_at_entry (var, frame); + } + + if (entryval_ex.reason < 0 || value_optimized_out (entryval)) + entryval = NULL; + else + { + if (!value_optimized_out (val) && value_lazy (val)) + value_fetch_lazy (val); + if (!value_optimized_out (val) && value_lazy (entryval)) + value_fetch_lazy (entryval); + if (!value_optimized_out (val) + && value_available_contents_eq (val, 0, entryval, 0, len)) + entryval = NULL; + } + } + + if (print_argument != PVAVD_ARGUMENT_PRINT_ENTRYVAL_ONLY) + { + fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name); + common_val_print (val, stream, indent, &opts, current_language); + fputc_filtered ('\n', stream); + } + if (entryval) + { + fprintf_filtered (stream, "%s%s@entry = ", n_spaces (2 * indent), + name); + common_val_print (entryval, stream, indent, &opts, current_language); + fputc_filtered ('\n', stream); + } } if (except.reason < 0) - fprintf_filtered(stream, "", name, - except.message); - fprintf_filtered (stream, "\n"); + fprintf_filtered (stream, "%s%s = \n", + n_spaces (2 * indent), name, name, except.message); } /* printf "printf format string" ARG to STREAM. */ --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1609,6 +1609,7 @@ struct print_variable_and_value_data int num_tabs; struct ui_file *stream; int values_printed; + enum print_argument print_argument; }; /* The callback for the locals and args iterators. */ @@ -1620,13 +1621,17 @@ do_print_variable_and_value (const char *print_name, { struct print_variable_and_value_data *p = cb_data; - print_variable_and_value (print_name, sym, - p->frame, p->stream, p->num_tabs); + print_variable_and_value (print_name, sym, p->frame, p->stream, p->num_tabs, + p->print_argument); p->values_printed = 1; } +/* Show function local variables at FRAME. FROM_FRAME is 1 if the local + variables are printed after the function frame (parameter values) have been + printed, it is 0 otherwise. Print them to STREAM. */ + static void -print_frame_local_vars (struct frame_info *frame, int num_tabs, +print_frame_local_vars (struct frame_info *frame, int from_frame, struct ui_file *stream) { struct print_variable_and_value_data cb_data; @@ -1648,10 +1653,24 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs, } cb_data.frame = frame; - cb_data.num_tabs = 4 * num_tabs; + cb_data.num_tabs = from_frame ? 4 : 0; cb_data.stream = stream; cb_data.values_printed = 0; + if (from_frame) + { + /* For the variables we display them from the innermost block. But for + parameters we need to fetch the outermost block still in the same + function. Stop at the first inlined function boundary, if any. */ + struct symbol *func = get_frame_function (frame); + + cb_data.print_argument = PVAVD_ARGUMENT_PRINT_ENTRYVAL_ONLY; + if (func) + iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func), + do_print_variable_and_value, &cb_data); + } + + cb_data.print_argument = PVAVD_IS_NOT_ARGUMENT; iterate_over_block_local_vars (block, do_print_variable_and_value, &cb_data); @@ -1811,6 +1830,7 @@ print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream) cb_data.stream = gdb_stdout; cb_data.values_printed = 0; + cb_data.print_argument = PVAVD_ARGUMENT_PRINT_BOTH; iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func), do_print_variable_and_value, &cb_data); --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -533,6 +533,12 @@ struct symbol_computed_ops struct value *(*read_variable) (struct symbol * symbol, struct frame_info * frame); + /* Read variable SYMBOL like read_variable at (callee) FRAME's function + entry. SYMBOL should be a function parameter, otherwise NOT_FOUND_ERROR + will be thrown. */ + struct value *(*read_variable_at_entry) (struct symbol *symbol, + struct frame_info *frame); + /* Return non-zero if we need a frame to find the value of the SYMBOL. */ int (*read_needs_frame) (struct symbol * symbol); --- a/gdb/testsuite/gdb.arch/amd64-entry-value.cc +++ b/gdb/testsuite/gdb.arch/amd64-entry-value.cc @@ -113,10 +113,37 @@ self (int i) } } +static void __attribute__((noinline, noclone)) +stacktest (int r1, int r2, int r3, int r4, int r5, int r6, int s1, int s2) +{ + s1 = 3; + s2 = 4; + e (v); +asm ("breakhere_stacktest:"); + e (v); +} + +static void __attribute__((noinline, noclone)) +reference (int &refparam) +{ + int refcopy = refparam; + + refparam = 10; +asm ("breakhere_reference:"); + e (v); +} + int main () { + int refvar; + d (30); + stacktest (1, 2, 3, 4, 5, 6, 11, 12); + + refvar = 5; + reference (refvar); + if (v) a (1); else --- a/gdb/testsuite/gdb.arch/amd64-entry-value.exp +++ b/gdb/testsuite/gdb.arch/amd64-entry-value.exp @@ -35,6 +35,10 @@ if ![runto_main] { } gdb_breakpoint "breakhere" +gdb_breakpoint "stacktest" +gdb_breakpoint "breakhere_stacktest" +gdb_breakpoint "reference" +gdb_breakpoint "breakhere_reference" # Test @entry values for register passed parameters. @@ -43,12 +47,68 @@ gdb_continue_to_breakpoint "entry: breakhere" # (gdb) bt full # #0 d (i=31) at gdb.arch/amd64-entry-value.cc:33 +# i@entry = 30 # #1 0x00000000004003da in main () at gdb.arch/amd64-entry-value.cc:56 -gdb_test "bt full" "^bt full\r\n#0 +d *\\(i=31\\) \[^\r\n\]*\r\nNo locals\\.\r\n#1 +0x\[0-9a-f\]+ in main .*" \ +gdb_test "bt full" "^bt full\r\n#0 +d *\\(i=31\\) \[^\r\n\]*\r\n\[ \t\]*i@entry = 30\r\n#1 +0x\[0-9a-f\]+ in main .*" \ "entry: bt full" gdb_test "p i" " = 31" "entry: p i" +# Test @entry values for stack passed parameters. + +gdb_continue_to_breakpoint "entry_stack: stacktest" + +# (gdb) bt full +# #0 stacktest (r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=11, s2=12) at gdb.arch/amd64-entry-value.cc:121 +# #1 0x0000000000400412 in main () at gdb.arch/amd64-entry-value.cc:142 +# Check s1 and s2 are suppressed: +gdb_test "bt full" "^bt full\r\n#0 +stacktest *\\(r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=11, s2=12\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main .*" \ + "entry_stack: bt full at entry" + +gdb_continue_to_breakpoint "entry_stack: breakhere_stacktest" + +# (gdb) bt full +# #0 stacktest (r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=3, s2=4) at gdb.arch/amd64-entry-value.cc:123 +# s1@entry = 11 +# s2@entry = 12 +# #1 0x0000000000400412 in main () at gdb.arch/amd64-entry-value.cc:130 +# Check s1 and s2 are present: +gdb_test "bt full" "^bt full\r\n#0 +stacktest *\\(r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=3, s2=4\\) \[^\r\n\]*\r\n\[ \t\]*s1@entry = 11\r\n\[ \t\]*s2@entry = 12\r\n#1 +0x\[0-9a-f\]+ in main .*" \ + "entry_stack: bt full" + +gdb_test "p s1" " = 3" "entry_stack: p s1" +gdb_test "p s2" " = 4" "entry_stack: p s2" + + +# Test @entry values for DW_AT_GNU_call_site_data_value parameters. + +gdb_continue_to_breakpoint "entry_reference: reference" + +# (gdb) bt full +# #0 reference (refparam=@0x7fffffffdc3c) at gdb.arch/amd64-entry-value.cc:131 +# refcopy = 5 +# #1 0x0000000000400424 in main () at gdb.arch/amd64-entry-value.cc:145 +# refvar = 5 +# Check refparam@entry is suppressed: +gdb_test "bt full" "#0 +reference \\(refparam=@0x\[0-9a-f\]+\\) \[^\r\n\]*\r\n\[ \t\]*refcopy = 5\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*\r\n\[ \t\]*refvar = 5" \ + "entry_reference: bt full at entry" + +gdb_continue_to_breakpoint "entry_reference: breakhere_reference" + +# (gdb) bt full +# #0 reference (refparam=@0x7fffffffdc3c) at gdb.arch/amd64-entry-value.cc:133 +# refcopy = 5 +# #1 0x0000000000400424 in main () at gdb.arch/amd64-entry-value.cc:145 +# refvar = 10 +# Check refparam@entry is present: +gdb_test "bt full" "#0 +reference \\(refparam=@0x\[0-9a-f\]+\\) \[^\r\n\]*\r\n\[ \t\]*refcopy = 5\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*\r\n\[ \t\]*refvar = 10" \ + "entry_reference: bt full" +gdb_test "ptype refparam" " = int &" "entry_reference: ptype refparam" + +gdb_test "p refparam" { = \(int &\) @0x[0-9a-f]+: 10} "entry_reference: p refparam" +gdb_test "p refcopy" " = 5" "entry_reference: p refcopy" + + # Test virtual tail call frames. gdb_continue_to_breakpoint "tailcall: breakhere" --- a/gdb/value.h +++ b/gdb/value.h @@ -801,11 +801,28 @@ extern int val_print_string (struct type *elttype, const char *encoding, struct ui_file *stream, const struct value_print_options *options); +/* Specify how the @entry kind of function parameters should be printed. */ +enum print_argument +{ + /* Symbol is not a function parameter - it is a variable. */ + PVAVD_IS_NOT_ARGUMENT, + + /* Symbol is a function parameter, print only its @entry value if it is not + redundant together with the normal symbol printed value. */ + PVAVD_ARGUMENT_PRINT_ENTRYVAL_ONLY, + + /* Symbol is a function parameter, print its normal value. Print also its + @entry value if it is not redundant together with its normal printed + value. */ + PVAVD_ARGUMENT_PRINT_BOTH +}; + extern void print_variable_and_value (const char *name, struct symbol *var, struct frame_info *frame, struct ui_file *stream, - int indent); + int indent, + enum print_argument print_argument); extern int check_field (struct type *, const char *);