[RFC 11/12] entryval: "@entry" in input expressions
Jan Kratochvil
jan.kratochvil@redhat.com
Mon Jul 18 20:56:00 GMT 2011
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 <jan.kratochvil@redhat.com>
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 <jan.kratochvil@redhat.com>
Support @entry in input expressions.
* gdb.texinfo (Variables): Describe @entry names suffix.
gdb/testsuite/
2011-07-18 Jan Kratochvil <jan.kratochvil@redhat.com>
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 <tsval> STRING
%token <tsval> CHAR
%token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> ENTRY
%token <ssym> UNKNOWN_CPP_NAME
%token <voidval> COMPLETE
%token <tsym> TYPENAME
@@ -194,6 +195,9 @@ static struct stoken operator_stoken (const char *);
%type <ssym> name_not_typename
%type <tsym> typename
+/* It is UNKNOWN_CPP_NAME or ENTRY, depending on the context. */
+%type <ssym> 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{<incomplete
type>}. @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"
More information about the Gdb-patches
mailing list