From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25504 invoked by alias); 18 Jul 2011 20:24:50 -0000 Received: (qmail 25494 invoked by uid 22791); 18 Jul 2011 20:24:48 -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_YY 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:24:13 +0000 Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p6IKODP4002574 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 18 Jul 2011 16:24:13 -0400 Received: from host1.jankratochvil.net (ovpn-116-20.ams2.redhat.com [10.36.116.20]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p6IKOC5O013467 for ; Mon, 18 Jul 2011 16:24:12 -0400 Received: from host1.jankratochvil.net (localhost [127.0.0.1]) by host1.jankratochvil.net (8.14.4/8.14.4) with ESMTP id p6IKOBkE015922 for ; Mon, 18 Jul 2011 22:24:11 +0200 Received: (from jkratoch@localhost) by host1.jankratochvil.net (8.14.4/8.14.4/Submit) id p6IKOAGV015921 for gdb-patches@sourceware.org; Mon, 18 Jul 2011 22:24:10 +0200 Date: Mon, 18 Jul 2011 20:56:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: [RFC 11/12] entryval: "@entry" in input expressions Message-ID: <20110718202410.GL30496@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/msg00443.txt.bz2 Hi, when GDB can now show: (gdb) bt full [...] param@entry = 5 it would be good if one can also: (gdb) print refparam@entry $1 = 5 I am not sure if the entry values should be really indicated by the @entry suffix. Also as @entry values are not not_lval it may be enough to display them either by `bt full' and `info args' or even by some new command: (gdb) entryval param #1 = 5 Also the @entry means the `@' operator and "entry" identifier to be overloaded. This way each supported GDB language needs its own *.y patch. I will implement some others - specifically Fortran - if this syntax gets agreed upon. It means that formerly valid @entry meant repeat left expression by the number of times stored in a variable named `entry' changes meaning but I do not think it is a problem. There is some risk of a clash with Koening operator parsing but I do not think this patch has any problem with it. Thanks, Jan gdb/ 2011-07-18 Jan Kratochvil Support @entry in input expressions. * c-exp.y (ENTRY, unknown_cpp_name): New. (exp: UNKNOWN_CPP_NAME): Change to `exp: unknown_cpp_name'. (unknown_cpp_name: UNKNOWN_CPP_NAME, unknown_cpp_name: ENTRY) (variable: name_not_typename '@' ENTRY, name: ENTRY) (name_not_typename: ENTRY): New. (yylex): Recognize ENTRY. * eval.c (evaluate_subexp_standard): Support also OP_VAR_ENTRY_VALUE. * expprint.c (print_subexp_standard, dump_subexp_body_standard): Likewise. * parse.c (operator_length_standard): Likewise. * std-operator.def: New operator OP_VAR_ENTRY_VALUE. gdb/doc/ 2011-07-18 Jan Kratochvil Support @entry in input expressions. * gdb.texinfo (Variables): Describe @entry names suffix. gdb/testsuite/ 2011-07-18 Jan Kratochvil Support @entry in input expressions. * gdb.arch/amd64-entry-value.exp (entry: p i@entry) (entry_stack: p s1@entry, entry_stack: p s2@entry): New tests. (entry_reference: p refparam): Catch $addr. (entry_reference: ptype refparam@entry) (entry_reference: p refparam@entry, entry_reference: p &refparam@entry) (tailcall: p i@entry): New tests. * gdb.cp/koenig.cc (A::entry): New function. (main): Call it. * gdb.cp/koenig.exp (p entry (c)): New test. --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -186,6 +186,7 @@ static struct stoken operator_stoken (const char *); %token STRING %token CHAR %token NAME /* BLOCKNAME defined below to give it higher precedence. */ +%token ENTRY %token UNKNOWN_CPP_NAME %token COMPLETE %token TYPENAME @@ -194,6 +195,9 @@ static struct stoken operator_stoken (const char *); %type name_not_typename %type typename +/* It is UNKNOWN_CPP_NAME or ENTRY, depending on the context. */ +%type unknown_cpp_name + /* A NAME_OR_INT is a symbol which is not known in the symbol table, but which would parse as a valid number in the current input radix. E.g. "c" when input_radix==16. Depending on the parse, it will be @@ -392,7 +396,7 @@ exp : exp '(' write_exp_elt_opcode (OP_FUNCALL); } ; -exp : UNKNOWN_CPP_NAME '(' +exp : unknown_cpp_name '(' { /* This could potentially be a an argument defined lookup function (Koenig). */ @@ -415,6 +419,10 @@ exp : UNKNOWN_CPP_NAME '(' } ; +unknown_cpp_name : UNKNOWN_CPP_NAME + | ENTRY + ; + lcurly : '{' { start_arglist (); } ; @@ -756,6 +764,21 @@ block : block COLONCOLON name $$ = SYMBOL_BLOCK_VALUE (tem); } ; +variable: name_not_typename '@' ENTRY + { struct symbol *sym = $1.sym; + + if (sym == NULL || !SYMBOL_IS_ARGUMENT (sym) + || !symbol_read_needs_frame (sym)) + error (_("@entry can be used only for function " + "parameters, not for \"%s\""), + copy_name ($1.stoken)); + + write_exp_elt_opcode (OP_VAR_ENTRY_VALUE); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_ENTRY_VALUE); + } + ; + variable: block COLONCOLON name { struct symbol *sym; sym = lookup_symbol (copy_name ($3), $1, @@ -1317,11 +1340,13 @@ name : NAME { $$ = $1.stoken; } | TYPENAME { $$ = $1.stoken; } | NAME_OR_INT { $$ = $1.stoken; } | UNKNOWN_CPP_NAME { $$ = $1.stoken; } + | ENTRY { $$ = $1.stoken; } | operator { $$ = $1; } ; name_not_typename : NAME | BLOCKNAME + | ENTRY /* These would be useful if name_not_typename was useful, but it is just a fake for "variable", so these cause reduce/reduce conflicts because the parser can't tell whether NAME_OR_INT is a name_not_typename (=variable, @@ -2525,6 +2550,11 @@ yylex (void) current.token = lex_one_token (); if (current.token == NAME) current.token = classify_name (expression_context_block); + if ((current.token == NAME || current.token == UNKNOWN_CPP_NAME) + && yylval.sval.length == strlen ("entry") + && strncmp (yylval.sval.ptr, "entry", strlen ("entry")) == 0) + current.token = ENTRY; + if (parse_language->la_language != language_cplus || (current.token != TYPENAME && current.token != COLONCOLON)) return current.token; --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -7286,6 +7286,22 @@ If you ask to print an object whose contents are unknown to by the debug information, @value{GDBN} will say @samp{}. @xref{Symbols, incomplete type}, for more about this. +If you append @code{@@entry} string to a function parameter name you get its +value at the time the function got called. If the value is not available an +error message is printed. Entry values are available only since @value{NGCC} +version 4.7. + +@smallexample +Breakpoint 1, d (i=30) at gdb.base/entry-value.c:29 +29 i++; +(gdb) next +30 e (i); +(gdb) print i +$1 = 31 +(gdb) print i@@entry +$2 = 30 +@end smallexample + Strings are identified as arrays of @code{char} values without specified signedness. Arrays of either @code{signed char} or @code{unsigned char} get printed as arrays of 1 byte sized integers. @code{-fsigned-char} or --- a/gdb/eval.c +++ b/gdb/eval.c @@ -860,6 +860,27 @@ evaluate_subexp_standard (struct type *expect_type, return ret; } + case OP_VAR_ENTRY_VALUE: + (*pos) += 2; + if (noside == EVAL_SKIP) + goto nosideret; + + { + struct symbol *sym = exp->elts[pc + 1].symbol; + struct frame_info *frame; + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (SYMBOL_TYPE (sym), not_lval); + + if (SYMBOL_CLASS (sym) != LOC_COMPUTED + || SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry == NULL) + error (_("Symbol \"%s\" does not have any specific entry value"), + SYMBOL_PRINT_NAME (sym)); + + frame = get_selected_frame (NULL); + return SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry (sym, frame); + } + case OP_LAST: (*pos) += 2; return --- a/gdb/expprint.c +++ b/gdb/expprint.c @@ -135,6 +135,16 @@ print_subexp_standard (struct expression *exp, int *pos, } return; + case OP_VAR_ENTRY_VALUE: + { + struct block *b; + + (*pos) += 2; + fprintf_filtered (stream, "%s@entry", + SYMBOL_PRINT_NAME (exp->elts[pc + 1].symbol)); + } + return; + case OP_LAST: (*pos) += 2; fprintf_filtered (stream, "$%d", @@ -853,6 +863,13 @@ dump_subexp_body_standard (struct expression *exp, SYMBOL_PRINT_NAME (exp->elts[elt + 1].symbol)); elt += 3; break; + case OP_VAR_ENTRY_VALUE: + fprintf_filtered (stream, "Entry value of symbol @"); + gdb_print_host_address (exp->elts[elt].symbol, stream); + fprintf_filtered (stream, " (%s)", + SYMBOL_PRINT_NAME (exp->elts[elt].symbol)); + elt += 2; + break; case OP_LAST: fprintf_filtered (stream, "History element %ld", (long) exp->elts[elt].longconst); --- a/gdb/parse.c +++ b/gdb/parse.c @@ -853,6 +853,7 @@ operator_length_standard (const struct expression *expr, int endpos, case OP_BOOL: case OP_LAST: case OP_INTERNALVAR: + case OP_VAR_ENTRY_VALUE: oplen = 3; break; --- a/gdb/std-operator.def +++ b/gdb/std-operator.def @@ -139,6 +139,12 @@ OP (OP_DOUBLE) use the selected frame. */ OP (OP_VAR_VALUE) +/* OP_VAR_ENTRY_VALUE takes one struct symbol * in the following element, + followed by another OP_VAR_ENTRY_VALUE, making three exp_elements. + somename@entry may mean parameter value as present at the entry of the + current function. Implemented via DW_OP_GNU_entry_value. */ +OP (OP_VAR_ENTRY_VALUE) + /* OP_LAST is followed by an integer in the next exp_element. The integer is zero for the last value printed, or it is the absolute number of a history element. --- a/gdb/testsuite/gdb.arch/amd64-entry-value.exp +++ b/gdb/testsuite/gdb.arch/amd64-entry-value.exp @@ -52,6 +52,7 @@ gdb_continue_to_breakpoint "entry: breakhere" 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" +gdb_test "p i@entry" " = 30" "entry: p i@entry" # Test @entry values for stack passed parameters. @@ -77,7 +78,9 @@ gdb_test "bt full" "^bt full\r\n#0 +stacktest *\\(r1=1, r2=2, r3=3, r4=4, r5=5, "entry_stack: bt full" gdb_test "p s1" " = 3" "entry_stack: p s1" +gdb_test "p s1@entry" " = 11" "entry_stack: p s1@entry" gdb_test "p s2" " = 4" "entry_stack: p s2" +gdb_test "p s2@entry" " = 12" "entry_stack: p s2@entry" # Test @entry values for DW_AT_GNU_call_site_data_value parameters. @@ -106,7 +109,18 @@ gdb_test "bt full" "#0 +reference \\(refparam=@0x\[0-9a-f\]+: 10\\) \[^\r\n\]*\r "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" +set test "entry_reference: p refparam" +set addr "" +gdb_test_multiple "p refparam" $test { + -re " = \\(int &\\) @(0x\[0-9a-f\]+): 10\r\n$gdb_prompt $" { + set addr $expect_out(1,string) + pass $test + } +} + +gdb_test "ptype refparam@entry" " = int &" "entry_reference: ptype refparam@entry" +gdb_test "p refparam@entry" " = \\(int &\\) @$addr: 5" "entry_reference: p refparam@entry" +gdb_test "p &refparam@entry" " = \\(int \\*\\) $addr" "entry_reference: p &refparam@entry" gdb_test "p refcopy" " = 5" "entry_reference: p refcopy" @@ -121,6 +135,7 @@ gdb_continue_to_breakpoint "tailcall: breakhere" gdb_test "bt" "^bt\r\n#0 +d *\\(i=71\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in c \\(i=7\\) \[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in b \\(i=5\\) \[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in main \[^\r\n\]*" \ "tailcall: bt" gdb_test "p i" " = 71" "tailcall: p i" +gdb_test "p i@entry" " = 70" "tailcall: p i@entry" # Test partial-ambiguous virtual tail call frames chain. --- a/gdb/testsuite/gdb.cp/koenig.cc +++ b/gdb/testsuite/gdb.cp/koenig.cc @@ -24,6 +24,11 @@ namespace A return 33; } + int + entry (C c) + { + return 44; + } } struct B @@ -245,6 +250,7 @@ main () A::first (c); first (0, c); second (0, 0, c, 0, 0); + entry (c); A::first (b.c); E::O eo; --- a/gdb/testsuite/gdb.cp/koenig.exp +++ b/gdb/testsuite/gdb.cp/koenig.exp @@ -33,6 +33,9 @@ gdb_test "p first(c)" "= 11" # the qualifying parameter gdb_test "p second(0,0,c,0,0)" "= 33" +# Test the name "entry" being used for `variablename@entry' entry values. +gdb_test "p entry (c)" " = 44" + # Test that koenig lookup finds correct function # even if it is overloaded gdb_test "p first(0,c)" "= 22"