gdb/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 9 Oct 2011 19:34:19 +0000 (19:34 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Sun, 9 Oct 2011 19:34:19 +0000 (19:34 +0000)
Display @entry parameter values (without references).
* dwarf2expr.c (dwarf_block_to_fb_offset, dwarf_block_to_sp_offset):
New functions.
* dwarf2expr.h (dwarf_block_to_fb_offset, dwarf_block_to_sp_offset):
New declarations.
* dwarf2loc.c (dwarf2_find_location_expression): Support location list
entry record.
(dwarf_entry_parameter_to_value, value_of_dwarf_reg_entry)
(value_of_dwarf_block_entry, locexpr_read_variable_at_entry): New
functions.
(dwarf2_locexpr_funcs): Install locexpr_read_variable_at_entry.
(loclist_read_variable_at_entry): New function.
(dwarf2_loclist_funcs): Install loclist_read_variable_at_entry.
* dwarf2read.c (read_call_site_scope): Support also DW_OP_fbreg in
DW_AT_location, call dwarf_block_to_sp_offset for it.
* frame.h (print_entry_values_no, print_entry_values_only)
(print_entry_values_preferred, print_entry_values_if_needed)
(print_entry_values_both, print_entry_values_compact)
(print_entry_values_default, print_entry_values): New declarations.
(struct frame_arg): New field entry_kind.
(read_frame_arg): New parameter entryargp.
* mi/mi-cmd-stack.c (list_arg_or_local): New gdb_assert for
arg->entry_kind.  Optionally print the `@entry' suffix.
(list_args_or_locals): New variable entryarg, initialize it.
Initialize also entry_kind of arg and entryarg.  Conditionalize
list_arg_or_local for arg, add list_arg_or_local for entryarg.  Call
xfree for entryarg.error.
* stack.c (print_entry_values_no, print_entry_values_only)
(print_entry_values_preferred, print_entry_values_if_needed)
(print_entry_values_both, print_entry_values_compact)
(print_entry_values_default, print_entry_values_choices)
(print_entry_values): New variables.
(print_frame_arg): New gdb_assert for arg->entry_kind.  Optionally
print the `@entry' suffix, possibly in combination for
print_entry_values_compact.
(read_frame_arg): New parameter entryargp, new variables entryval,
entryval_error and val_equal.  Read in also entryargp, respect
print_entry_values, compare the values using val_equal, fill in also
argp->entry_kind (together with entryargp->entry_kind).
(print_frame_args): New variable entryarg, initialize it.
Conditionalize print_frame_arg for arg, add print_frame_arg for
entryarg.  Call xfree for entryarg.error.
(_initialize_stack): Call add_setshow_enum_cmd for `entry-values'.
* symtab.h (struct symbol_computed_ops): New field
read_variable_at_entry.

gdb/doc/
Display @entry parameter values (without references).
* gdb.texinfo (Tail Call Frames): Add anchor.  Add self tail call
example.
(Print Settings): New description of set print entry-values and show
print entry-values.

gdb/testsuite/
Display @entry parameter values (without references).
* gdb.arch/amd64-entry-value.cc (locexpr, stacktest, data, data2)
(different, validity, invalid): New functions.
(main): Call them.
* gdb.arch/amd64-entry-value.exp: New breakpoints breakhere_locexpr,
stacktest, breakhere_stacktest, different, breakhere_different,
breakhere_validity and breakhere_invalid.
(entry: bt): Update for @entry.
(entry_locexpr: *, entry_stack: *, entry_equal: *, entry_different: *)
(entry_validity: *, entry_invalid: *): Many new tests.
* gdb.base/break.exp
(run until breakpoint set at small function, optimized file): Accept
also the @entry suffix.
* gdb.mi/Makefile.in (PROGS): Add mi2-amd64-entry-value.
* gdb.mi/mi2-amd64-entry-value.c: New files.
* gdb.mi/mi2-amd64-entry-value.exp: New files.

18 files changed:
gdb/ChangeLog
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/dwarf2expr.c
gdb/dwarf2expr.h
gdb/dwarf2loc.c
gdb/dwarf2read.c
gdb/frame.h
gdb/mi/mi-cmd-stack.c
gdb/stack.c
gdb/symtab.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.arch/amd64-entry-value.cc
gdb/testsuite/gdb.arch/amd64-entry-value.exp
gdb/testsuite/gdb.base/break.exp
gdb/testsuite/gdb.mi/Makefile.in
gdb/testsuite/gdb.mi/mi2-amd64-entry-value.c [new file with mode: 0644]
gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp [new file with mode: 0644]

index 959c4c7..0dc93bf 100644 (file)
@@ -1,5 +1,53 @@
 2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
+       Display @entry parameter values (without references).
+       * dwarf2expr.c (dwarf_block_to_fb_offset, dwarf_block_to_sp_offset):
+       New functions.
+       * dwarf2expr.h (dwarf_block_to_fb_offset, dwarf_block_to_sp_offset):
+       New declarations.
+       * dwarf2loc.c (dwarf2_find_location_expression): Support location list
+       entry record.
+       (dwarf_entry_parameter_to_value, value_of_dwarf_reg_entry)
+       (value_of_dwarf_block_entry, locexpr_read_variable_at_entry): New
+       functions.
+       (dwarf2_locexpr_funcs): Install locexpr_read_variable_at_entry.
+       (loclist_read_variable_at_entry): New function.
+       (dwarf2_loclist_funcs): Install loclist_read_variable_at_entry.
+       * dwarf2read.c (read_call_site_scope): Support also DW_OP_fbreg in
+       DW_AT_location, call dwarf_block_to_sp_offset for it.
+       * frame.h (print_entry_values_no, print_entry_values_only)
+       (print_entry_values_preferred, print_entry_values_if_needed)
+       (print_entry_values_both, print_entry_values_compact)
+       (print_entry_values_default, print_entry_values): New declarations.
+       (struct frame_arg): New field entry_kind.
+       (read_frame_arg): New parameter entryargp.
+       * mi/mi-cmd-stack.c (list_arg_or_local): New gdb_assert for
+       arg->entry_kind.  Optionally print the `@entry' suffix.
+       (list_args_or_locals): New variable entryarg, initialize it.
+       Initialize also entry_kind of arg and entryarg.  Conditionalize
+       list_arg_or_local for arg, add list_arg_or_local for entryarg.  Call
+       xfree for entryarg.error.
+       * stack.c (print_entry_values_no, print_entry_values_only)
+       (print_entry_values_preferred, print_entry_values_if_needed)
+       (print_entry_values_both, print_entry_values_compact)
+       (print_entry_values_default, print_entry_values_choices)
+       (print_entry_values): New variables.
+       (print_frame_arg): New gdb_assert for arg->entry_kind.  Optionally
+       print the `@entry' suffix, possibly in combination for
+       print_entry_values_compact.
+       (read_frame_arg): New parameter entryargp, new variables entryval,
+       entryval_error and val_equal.  Read in also entryargp, respect
+       print_entry_values, compare the values using val_equal, fill in also
+       argp->entry_kind (together with entryargp->entry_kind).
+       (print_frame_args): New variable entryarg, initialize it.
+       Conditionalize print_frame_arg for arg, add print_frame_arg for
+       entryarg.  Call xfree for entryarg.error.
+       (_initialize_stack): Call add_setshow_enum_cmd for `entry-values'.
+       * symtab.h (struct symbol_computed_ops): New field
+       read_variable_at_entry.
+
+2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
        Code reshuffle.
        * frame.h (struct frame_arg): New definition.
        (read_frame_arg): New declaration.
index 8c9d9b5..7763cce 100644 (file)
@@ -1,6 +1,15 @@
 2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
            Eli Zaretskii  <eliz@gnu.org>
 
+       Display @entry parameter values (without references).
+       * gdb.texinfo (Tail Call Frames): Add anchor.  Add self tail call
+       example.
+       (Print Settings): New description of set print entry-values and show
+       print entry-values.
+
+2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
+           Eli Zaretskii  <eliz@gnu.org>
+
        Recognize virtual tail call frames.
        * gdb.texinfo (Optimized Code): Add reference to Tail Call Frames.
        (Tail Call Frames): New node.
index fdf66c3..9de96c1 100644 (file)
@@ -7941,6 +7941,120 @@ thus speeding up the display of each Ada frame.
 @item show print frame-arguments
 Show how the value of arguments should be displayed when printing a frame.
 
+@item set print entry-values @var{value}
+@kindex set print entry-values
+Set printing of frame argument values at function entry.  In some cases
+@value{GDBN} can determine the value of function argument which was passed by
+the function caller, even if the value was modified inside the called function
+and therefore is different.  With optimized code, the current value could be
+unavailable, but the entry value may still be known.
+
+The default value is @code{default} (see below for its description).  Older
+@value{GDBN} behaved as with the setting @code{no}.  Compilers not supporting
+this feature will behave in the @code{default} setting the same way as with the
+@code{no} setting.
+
+This functionality is currently supported only by DWARF 2 debugging format and
+the compiler has to produce @samp{DW_TAG_GNU_call_site} tags.  With
+@value{NGCC}, you need to specify @option{-O -g} during compilation, to get
+this information.
+
+The @var{value} parameter can be one of the following:
+
+@table @code
+@item no
+Print only actual parameter values, never print values from function entry
+point.
+@smallexample
+#0  equal (val=5)
+#0  different (val=6)
+#0  lost (val=<optimized out>)
+#0  born (val=10)
+#0  invalid (val=<optimized out>)
+@end smallexample
+
+@item only
+Print only parameter values from function entry point.  The actual parameter
+values are never printed.
+@smallexample
+#0  equal (val@@entry=5)
+#0  different (val@@entry=5)
+#0  lost (val@@entry=5)
+#0  born (val@@entry=<optimized out>)
+#0  invalid (val@@entry=<optimized out>)
+@end smallexample
+
+@item preferred
+Print only parameter values from function entry point.  If value from function
+entry point is not known while the actual value is known, print the actual
+value for such parameter.
+@smallexample
+#0  equal (val@@entry=5)
+#0  different (val@@entry=5)
+#0  lost (val@@entry=5)
+#0  born (val=10)
+#0  invalid (val@@entry=<optimized out>)
+@end smallexample
+
+@item if-needed
+Print actual parameter values.  If actual parameter value is not known while
+value from function entry point is known, print the entry point value for such
+parameter.
+@smallexample
+#0  equal (val=5)
+#0  different (val=6)
+#0  lost (val@@entry=5)
+#0  born (val=10)
+#0  invalid (val=<optimized out>)
+@end smallexample
+
+@item both
+Always print both the actual parameter value and its value from function entry
+point, even if values of one or both are not available due to compiler
+optimizations.
+@smallexample
+#0  equal (val=5, val@@entry=5)
+#0  different (val=6, val@@entry=5)
+#0  lost (val=<optimized out>, val@@entry=5)
+#0  born (val=10, val@@entry=<optimized out>)
+#0  invalid (val=<optimized out>, val@@entry=<optimized out>)
+@end smallexample
+
+@item compact
+Print the actual parameter value if it is known and also its value from
+function entry point if it is known.  If neither is known, print for the actual
+value @code{<optimized out>}.  If not in MI mode (@pxref{GDB/MI}) and if both
+values are known and identical, print the shortened
+@code{param=param@@entry=VALUE} notation.
+@smallexample
+#0  equal (val=val@@entry=5)
+#0  different (val=6, val@@entry=5)
+#0  lost (val@@entry=5)
+#0  born (val=10)
+#0  invalid (val=<optimized out>)
+@end smallexample
+
+@item default
+Always print the actual parameter value.  Print also its value from function
+entry point, but only if it is known.  If not in MI mode (@pxref{GDB/MI}) and
+if both values are known and identical, print the shortened
+@code{param=param@@entry=VALUE} notation.
+@smallexample
+#0  equal (val=val@@entry=5)
+#0  different (val=6, val@@entry=5)
+#0  lost (val=<optimized out>, val@@entry=5)
+#0  born (val=10)
+#0  invalid (val=<optimized out>)
+@end smallexample
+@end table
+
+For analysis messages on possible failures of frame argument values at function
+entry resolution see @ref{set debug entry-values}.
+
+@item show print entry-values
+Show the method being used for printing of frame argument values at function
+entry.
+
 @item set print repeats
 @cindex repeated array elements
 Set the threshold for suppressing display of repeated array
@@ -9600,6 +9714,7 @@ tries to show at least all the unambiguous top tail callers and all the
 unambiguous bottom tail calees, if any.
 
 @table @code
+@anchor{set debug entry-values}
 @item set debug entry-values
 @kindex set debug entry-values
 When set to on, enables printing of analysis messages for both frame argument
@@ -9675,6 +9790,32 @@ also ambigous.  The only non-ambiguous frame is the one for function @code{a},
 therefore this one is displayed to the user while the ambiguous frames are
 omitted.
 
+There can be also reasons why printing of frame argument values at function
+entry may fail:
+
+@smallexample
+int v;
+static void __attribute__((noinline, noclone)) c (int i) @{ v++; @}
+static void __attribute__((noinline, noclone)) a (int i);
+static void __attribute__((noinline, noclone)) b (int i) @{ a (i); @}
+static void __attribute__((noinline, noclone)) a (int i)
+@{ if (i) b (i - 1); else c (0); @}
+int main (void) @{ a (5); return 0; @}
+
+(gdb) bt
+#0  c (i=i@@entry=0) at t.c:2
+#1  0x0000000000400428 in a (DW_OP_GNU_entry_value resolving has found
+function "a" at 0x400420 can call itself via tail calls
+i=<optimized out>) at t.c:6
+#2  0x000000000040036e in main () at t.c:7
+@end smallexample
+
+@value{GDBN} cannot find out from the inferior state if and how many times did
+function @code{a} call itself (via function @code{b}) as these calls would be
+tail calls.  Such tail calls would modify thue @code{i} variable, therefore
+@value{GDBN} cannot be sure the value it knows would be right - @value{GDBN}
+prints @code{<optimized out>} instead.
+
 @node Macros
 @chapter C Preprocessor Macros
 
index 2eb9d08..4fccc26 100644 (file)
@@ -518,6 +518,68 @@ dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end)
   return dwarf_reg;
 }
 
+/* If <BUF..BUF_END] contains DW_FORM_block* with single DW_OP_fbreg(X) fill
+   in FB_OFFSET_RETURN with the X offset and return 1.  Otherwise return 0.  */
+
+int
+dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end,
+                         CORE_ADDR *fb_offset_return)
+{
+  LONGEST fb_offset;
+
+  if (buf_end <= buf)
+    return 0;
+
+  if (*buf != DW_OP_fbreg)
+    return 0;
+  buf++;
+
+  buf = read_sleb128 (buf, buf_end, &fb_offset);
+  *fb_offset_return = fb_offset;
+  if (buf != buf_end || fb_offset != (LONGEST) *fb_offset_return)
+    return 0;
+
+  return 1;
+}
+
+/* If <BUF..BUF_END] contains DW_FORM_block* with single DW_OP_bregSP(X) fill
+   in SP_OFFSET_RETURN with the X offset and return 1.  Otherwise return 0.
+   The matched SP register number depends on GDBARCH.  */
+
+int
+dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
+                         const gdb_byte *buf_end, CORE_ADDR *sp_offset_return)
+{
+  ULONGEST dwarf_reg;
+  LONGEST sp_offset;
+
+  if (buf_end <= buf)
+    return 0;
+  if (*buf >= DW_OP_breg0 && *buf <= DW_OP_breg31)
+    {
+      dwarf_reg = *buf - DW_OP_breg0;
+      buf++;
+    }
+  else
+    {
+      if (*buf != DW_OP_bregx)
+       return 0;
+      buf++;
+      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+    }
+
+  if (gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_reg)
+      != gdbarch_sp_regnum (gdbarch))
+    return 0;
+
+  buf = read_sleb128 (buf, buf_end, &sp_offset);
+  *sp_offset_return = sp_offset;
+  if (buf != buf_end || sp_offset != (LONGEST) *sp_offset_return)
+    return 0;
+
+  return 1;
+}
+
 /* The engine for the expression evaluator.  Using the context in CTX,
    evaluate the expression between OP_PTR and OP_END.  */
 
index 8518f37..c014ce2 100644 (file)
@@ -281,4 +281,11 @@ void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
 
 int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end);
 
+int dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end,
+                             CORE_ADDR *fb_offset_return);
+
+int dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
+                             const gdb_byte *buf_end,
+                             CORE_ADDR *sp_offset_return);
+
 #endif /* dwarf2expr.h */
index fef0c6b..a44d3d2 100644 (file)
@@ -121,6 +121,24 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton,
       length = extract_unsigned_integer (loc_ptr, 2, byte_order);
       loc_ptr += 2;
 
+      if (low == high && pc == low)
+       {
+         /* This is entry PC record present only at entry point
+            of a function.  Verify it is really the function entry point.  */
+
+         struct block *pc_block = block_for_pc (pc);
+         struct symbol *pc_func = NULL;
+
+         if (pc_block)
+           pc_func = block_linkage_function (pc_block);
+
+         if (pc_func && pc == BLOCK_START (SYMBOL_BLOCK_VALUE (pc_func)))
+           {
+             *locexpr_length = length;
+             return loc_ptr;
+           }
+       }
+
       if (pc >= low && pc < high)
        {
          *locexpr_length = length;
@@ -892,6 +910,33 @@ dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg,
   return parameter;
 }
 
+/* Return value for PARAMETER for DW_AT_GNU_call_site_value.
+
+   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
+   NO_ENTRY_VALUE_ERROR if it cannot resolve the value for any reason.  */
+
+static struct value *
+dwarf_entry_parameter_to_value (struct call_site_parameter *parameter,
+                               struct type *type,
+                               struct frame_info *caller_frame,
+                               struct dwarf2_per_cu_data *per_cu)
+{
+  gdb_byte *data;
+
+  /* DW_AT_GNU_call_site_value is a DWARF expression, not a DWARF
+     location.  Postprocessing of DWARF_VALUE_MEMORY would lose the type from
+     DWARF block.  */
+  data = alloca (parameter->value_size + 1);
+  memcpy (data, parameter->value, parameter->value_size);
+  data[parameter->value_size] = DW_OP_stack_value;
+
+  return dwarf2_evaluate_loc_desc (type, caller_frame, data,
+                                  parameter->value_size + 1, per_cu);
+}
+
 /* Execute call_site_parameter's DWARF block for caller of the CTX's frame.
    CTX must be of dwarf_expr_ctx_funcs kind.  See DWARF_REG and FB_OFFSET
    description at struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
@@ -942,6 +987,58 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
   ctx->baton = saved_ctx.baton;
 }
 
+/* Read parameter of TYPE at (callee) FRAME's function entry.  DWARF_REG and
+   FB_OFFSET are used to match DW_AT_location at the caller's
+   DW_TAG_GNU_call_site_parameter.  See DWARF_REG and FB_OFFSET description at
+   struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
+
+   Function always returns non-NULL value.  It throws NO_ENTRY_VALUE_ERROR if it
+   cannot resolve the parameter 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;
+  struct dwarf2_per_cu_data *caller_per_cu;
+
+  parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset,
+                                                &caller_per_cu);
+
+  return dwarf_entry_parameter_to_value (parameter, type, caller_frame,
+                                        caller_per_cu);
+}
+
+/* Read parameter of TYPE at (callee) FRAME's function entry.  DATA and
+   SIZE are DWARF block used to match DW_AT_location at the caller's
+   DW_TAG_GNU_call_site_parameter.
+
+   Function always returns non-NULL value.  It throws NO_ENTRY_VALUE_ERROR if it
+   cannot resolve the parameter for any reason.  */
+
+static struct value *
+value_of_dwarf_block_entry (struct type *type, struct frame_info *frame,
+                           const gdb_byte *block, size_t block_len)
+{
+  int dwarf_reg;
+  CORE_ADDR fb_offset;
+
+  dwarf_reg = dwarf_block_to_dwarf_reg (block, block + block_len);
+  if (dwarf_reg != -1)
+    return value_of_dwarf_reg_entry (type, frame, dwarf_reg, 0 /* unused */);
+
+  if (dwarf_block_to_fb_offset (block, block + block_len, &fb_offset))
+    return value_of_dwarf_reg_entry (type, frame, -1, fb_offset);
+
+  /* This can normally happen - throw NO_ENTRY_VALUE_ERROR to get the message
+     suppressed during normal operation.  The expression can be arbitrary if
+     there is no caller-callee entry value binding expected.  */
+  throw_error (NO_ENTRY_VALUE_ERROR,
+              _("DWARF-2 expression error: DW_OP_GNU_entry_value is supported "
+                "only for single DW_OP_reg* or for DW_OP_fbreg(*)"));
+}
+
 struct piece_closure
 {
   /* Reference count.  */
@@ -2853,6 +2950,19 @@ locexpr_read_variable (struct symbol *symbol, struct frame_info *frame)
   return val;
 }
 
+/* Return the value of SYMBOL in FRAME at (callee) FRAME's function
+   entry.  SYMBOL should be a function parameter, otherwise NO_ENTRY_VALUE_ERROR
+   will be thrown.  */
+
+static struct value *
+locexpr_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame)
+{
+  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+
+  return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, dlbaton->data,
+                                    dlbaton->size);
+}
+
 /* Return non-zero iff we need a frame to evaluate SYMBOL.  */
 static int
 locexpr_read_needs_frame (struct symbol *symbol)
@@ -3494,6 +3604,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
    evaluator.  */
 const struct symbol_computed_ops dwarf2_locexpr_funcs = {
   locexpr_read_variable,
+  locexpr_read_variable_at_entry,
   locexpr_read_needs_frame,
   locexpr_describe_location,
   locexpr_tracepoint_var_ref
@@ -3524,6 +3635,32 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
   return val;
 }
 
+/* Read variable SYMBOL like loclist_read_variable at (callee) FRAME's function
+   entry.  SYMBOL should be a function parameter, otherwise NO_ENTRY_VALUE_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 NO_ENTRY_VALUE_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);
+  const gdb_byte *data;
+  size_t size;
+  CORE_ADDR pc;
+
+  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));
+
+  return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, data, size);
+}
+
 /* Return non-zero iff we need a frame to evaluate SYMBOL.  */
 static int
 loclist_read_needs_frame (struct symbol *symbol)
@@ -3643,6 +3780,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
index abc2163..695f341 100644 (file)
@@ -6346,10 +6346,13 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
        }
       parameter->dwarf_reg = dwarf_block_to_dwarf_reg (DW_BLOCK (attr)->data,
                                 &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size]);
-      if (parameter->dwarf_reg == -1)
+      if (parameter->dwarf_reg == -1
+         && !dwarf_block_to_sp_offset (gdbarch, DW_BLOCK (attr)->data,
+                                 &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size],
+                                       &parameter->fb_offset))
        {
          complaint (&symfile_complaints,
-                    _("Only single DW_OP_reg is supported "
+                    _("Only single DW_OP_reg or DW_OP_fbreg is supported "
                       "for DW_FORM_block* DW_AT_location for "
                       "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
                     child_die->offset, cu->objfile->name);
index 3850e11..f5866bd 100644 (file)
@@ -712,6 +712,15 @@ extern int frame_register_read (struct frame_info *frame, int regnum,
 
 /* From stack.c.  */
 
+extern const char print_entry_values_no[];
+extern const char print_entry_values_only[];
+extern const char print_entry_values_preferred[];
+extern const char print_entry_values_if_needed[];
+extern const char print_entry_values_both[];
+extern const char print_entry_values_compact[];
+extern const char print_entry_values_default[];
+extern const char *print_entry_values;
+
 /* Inferior function parameter value read in from a frame.  */
 
 struct frame_arg
@@ -726,10 +735,22 @@ struct frame_arg
   /* String containing the error message, it is more usually NULL indicating no
      error occured reading this parameter.  */
   char *error;
+
+  /* One of the print_entry_values_* entries as appropriate specifically for
+     this frame_arg.  It will be different from print_entry_values.  With
+     print_entry_values_no this frame_arg should be printed as a normal
+     parameter.  print_entry_values_only says it should be printed as entry
+     value parameter.  print_entry_values_compact says it should be printed as
+     both as a normal parameter and entry values parameter having the same
+     value - print_entry_values_compact is not permitted fi ui_out_is_mi_like_p
+     (in such case print_entry_values_no and print_entry_values_only is used
+     for each parameter kind specifically.  */
+  const char *entry_kind;
 };
 
 extern void read_frame_arg (struct symbol *sym, struct frame_info *frame,
-                           struct frame_arg *argp);
+                           struct frame_arg *argp,
+                           struct frame_arg *entryargp);
 
 extern void args_info (char *, int);
 
index 2e32eff..e1393f0 100644 (file)
@@ -256,11 +256,17 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
              || values == PRINT_SIMPLE_VALUES
              || (values == PRINT_ALL_VALUES
                  && (arg->val != NULL || arg->error != NULL)));
+  gdb_assert (arg->entry_kind == print_entry_values_no
+             || (arg->entry_kind == print_entry_values_only
+                 && (arg->val || arg->error)));
 
   if (values != PRINT_NO_VALUES || what == all)
     cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
 
-  ui_out_field_string (uiout, "name", SYMBOL_PRINT_NAME (arg->sym));
+  fputs_filtered (SYMBOL_PRINT_NAME (arg->sym), stb->stream);
+  if (arg->entry_kind == print_entry_values_only)
+    fputs_filtered ("@entry", stb->stream);
+  ui_out_field_stream (uiout, "name", stb);
 
   if (what == all && SYMBOL_IS_ARGUMENT (arg->sym))
     ui_out_field_int (uiout, "arg", 1);
@@ -380,7 +386,7 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
          if (print_me)
            {
              struct symbol *sym2;
-             struct frame_arg arg;
+             struct frame_arg arg, entryarg;
 
              if (SYMBOL_IS_ARGUMENT (sym))
                sym2 = lookup_symbol (SYMBOL_NATURAL_NAME (sym),
@@ -391,6 +397,10 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 
              memset (&arg, 0, sizeof (arg));
              arg.sym = sym2;
+             arg.entry_kind = print_entry_values_no;
+             memset (&entryarg, 0, sizeof (entryarg));
+             entryarg.sym = sym2;
+             entryarg.entry_kind = print_entry_values_no;
 
              switch (values)
                {
@@ -401,13 +411,17 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
                      && TYPE_CODE (type) != TYPE_CODE_UNION)
                    {
                case PRINT_ALL_VALUES:
-                     read_frame_arg (sym2, fi, &arg);
+                     read_frame_arg (sym2, fi, &arg, &entryarg);
                    }
                  break;
                }
 
-             list_arg_or_local (&arg, what, values);
+             if (arg.entry_kind != print_entry_values_only)
+               list_arg_or_local (&arg, what, values);
+             if (entryarg.entry_kind != print_entry_values_no)
+               list_arg_or_local (&entryarg, what, values);
              xfree (arg.error);
+             xfree (entryarg.error);
            }
        }
       if (BLOCK_FUNCTION (block))
index bdc3b01..276dd2b 100644 (file)
@@ -64,6 +64,29 @@ static const char *print_frame_arguments_choices[] =
   {"all", "scalars", "none", NULL};
 static const char *print_frame_arguments = "scalars";
 
+/* The possible choices of "set print entry-values", and the value
+   of this setting.  */
+
+const char print_entry_values_no[] = "no";
+const char print_entry_values_only[] = "only";
+const char print_entry_values_preferred[] = "preferred";
+const char print_entry_values_if_needed[] = "if-needed";
+const char print_entry_values_both[] = "both";
+const char print_entry_values_compact[] = "compact";
+const char print_entry_values_default[] = "default";
+static const char *print_entry_values_choices[] =
+{
+  print_entry_values_no,
+  print_entry_values_only,
+  print_entry_values_preferred,
+  print_entry_values_if_needed,
+  print_entry_values_both,
+  print_entry_values_compact,
+  print_entry_values_default,
+  NULL
+};
+const char *print_entry_values = print_entry_values_default;
+
 /* Prototypes for local functions.  */
 
 static void print_frame_local_vars (struct frame_info *, int,
@@ -180,12 +203,29 @@ print_frame_arg (const struct frame_arg *arg)
   old_chain = make_cleanup_ui_out_stream_delete (stb);
 
   gdb_assert (!arg->val || !arg->error);
+  gdb_assert (arg->entry_kind == print_entry_values_no
+             || arg->entry_kind == print_entry_values_only
+             || (!ui_out_is_mi_like_p (uiout)
+                 && arg->entry_kind == print_entry_values_compact));
 
   annotate_arg_begin ();
 
   make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
   fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (arg->sym),
                           SYMBOL_LANGUAGE (arg->sym), DMGL_PARAMS | DMGL_ANSI);
+  if (arg->entry_kind == print_entry_values_compact)
+    {
+      /* It is OK to provide invalid MI-like stream as with
+        PRINT_ENTRY_VALUE_COMPACT we never use MI.  */
+      fputs_filtered ("=", stb->stream);
+
+      fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (arg->sym),
+                              SYMBOL_LANGUAGE (arg->sym),
+                              DMGL_PARAMS | DMGL_ANSI);
+    }
+  if (arg->entry_kind == print_entry_values_only
+      || arg->entry_kind == print_entry_values_compact)
+    fputs_filtered ("@entry", stb->stream);
   ui_out_field_stream (uiout, "name", stb);
   annotate_arg_name_end ();
   ui_out_text (uiout, "=");
@@ -248,25 +288,138 @@ print_frame_arg (const struct frame_arg *arg)
 
 void
 read_frame_arg (struct symbol *sym, struct frame_info *frame,
-               struct frame_arg *argp)
+               struct frame_arg *argp, struct frame_arg *entryargp)
 {
-  struct value *val = NULL;
-  char *val_error = NULL;
+  struct value *val = NULL, *entryval = NULL;
+  char *val_error = NULL, *entryval_error = NULL;
+  int val_equal = 0;
   volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ERROR)
+  if (print_entry_values != print_entry_values_only
+      && print_entry_values != print_entry_values_preferred)
+    {
+      TRY_CATCH (except, RETURN_MASK_ERROR)
+       {
+         val = read_var_value (sym, frame);
+       }
+      if (!val)
+       {
+         val_error = alloca (strlen (except.message) + 1);
+         strcpy (val_error, except.message);
+       }
+    }
+
+  if (SYMBOL_CLASS (sym) == LOC_COMPUTED
+      && print_entry_values != print_entry_values_no
+      && (print_entry_values != print_entry_values_if_needed
+         || !val || value_optimized_out (val)))
+    {
+      TRY_CATCH (except, RETURN_MASK_ERROR)
+       {
+         const struct symbol_computed_ops *ops;
+
+         ops = SYMBOL_COMPUTED_OPS (sym);
+         entryval = ops->read_variable_at_entry (sym, frame);
+       }
+      if (!entryval)
+       {
+         entryval_error = alloca (strlen (except.message) + 1);
+         strcpy (entryval_error, except.message);
+       }
+
+      if (except.error == NO_ENTRY_VALUE_ERROR
+         || (entryval && value_optimized_out (entryval)))
+       {
+         entryval = NULL;
+         entryval_error = NULL;
+       }
+
+      if (print_entry_values == print_entry_values_compact
+         || print_entry_values == print_entry_values_default)
+       {
+         /* For MI do not try to use print_entry_values_compact for ARGP.  */
+
+         if (val && entryval && !ui_out_is_mi_like_p (current_uiout))
+           {
+             unsigned len = TYPE_LENGTH (value_type (val));
+
+             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;
+                 val_equal = 1;
+               }
+           }
+
+         /* Try to remove possibly duplicate error message for ENTRYARGP even
+            in MI mode.  */
+
+         if (val_error && entryval_error
+             && strcmp (val_error, entryval_error) == 0)
+           {
+             entryval_error = NULL;
+
+             /* Do not se VAL_EQUAL as the same error message may be shown for
+                the entry value even if no entry values are present in the
+                inferior.  */
+           }
+       }
+    }
+
+  if (entryval == NULL)
     {
-      val = read_var_value (sym, frame);
+      if (print_entry_values == print_entry_values_preferred)
+       {
+         TRY_CATCH (except, RETURN_MASK_ERROR)
+           {
+             val = read_var_value (sym, frame);
+           }
+         if (!val)
+           {
+             val_error = alloca (strlen (except.message) + 1);
+             strcpy (val_error, except.message);
+           }
+       }
+      if (print_entry_values == print_entry_values_only
+         || print_entry_values == print_entry_values_both
+         || (print_entry_values == print_entry_values_preferred
+             && (!val || value_optimized_out (val))))
+       entryval = allocate_optimized_out_value (SYMBOL_TYPE (sym));
     }
-  if (!val)
+  if ((print_entry_values == print_entry_values_compact
+       || print_entry_values == print_entry_values_if_needed
+       || print_entry_values == print_entry_values_preferred)
+      && (!val || value_optimized_out (val)) && entryval != NULL)
     {
-      val_error = alloca (strlen (except.message) + 1);
-      strcpy (val_error, except.message);
+      val = NULL;
+      val_error = NULL;
     }
 
   argp->sym = sym;
   argp->val = val;
   argp->error = val_error ? xstrdup (val_error) : NULL;
+  if (!val && !val_error)
+    argp->entry_kind = print_entry_values_only;
+  else if ((print_entry_values == print_entry_values_compact
+          || print_entry_values == print_entry_values_default) && val_equal)
+    {
+      argp->entry_kind = print_entry_values_compact;
+      gdb_assert (!ui_out_is_mi_like_p (current_uiout));
+    }
+  else
+    argp->entry_kind = print_entry_values_no;
+
+  entryargp->sym = sym;
+  entryargp->val = entryval;
+  entryargp->error = entryval_error ? xstrdup (entryval_error) : NULL;
+  if (!entryval && !entryval_error)
+    entryargp->entry_kind = print_entry_values_no;
+  else
+    entryargp->entry_kind = print_entry_values_only;
 }
 
 /* Print the arguments of frame FRAME on STREAM, given the function
@@ -308,7 +461,7 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
 
       ALL_BLOCK_SYMBOLS (b, iter, sym)
         {
-         struct frame_arg arg;
+         struct frame_arg arg, entryarg;
 
          QUIT;
 
@@ -426,13 +579,30 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
            {
              memset (&arg, 0, sizeof (arg));
              arg.sym = sym;
+             arg.entry_kind = print_entry_values_no;
+             memset (&entryarg, 0, sizeof (entryarg));
+             entryarg.sym = sym;
+             entryarg.entry_kind = print_entry_values_no;
            }
          else
-           read_frame_arg (sym, frame, &arg);
+           read_frame_arg (sym, frame, &arg, &entryarg);
 
-         print_frame_arg (&arg);
+         if (arg.entry_kind != print_entry_values_only)
+           print_frame_arg (&arg);
+
+         if (entryarg.entry_kind != print_entry_values_no)
+           {
+             if (arg.entry_kind != print_entry_values_only)
+               {
+                 ui_out_text (uiout, ", ");
+                 ui_out_wrap_hint (uiout, "    ");
+               }
+
+             print_frame_arg (&entryarg);
+           }
 
          xfree (arg.error);
+         xfree (entryarg.error);
 
          first = 0;
        }
@@ -2313,4 +2483,17 @@ source line."),
                                show_disassemble_next_line,
                                &setlist, &showlist);
   disassemble_next_line = AUTO_BOOLEAN_FALSE;
+
+  add_setshow_enum_cmd ("entry-values", class_stack,
+                       print_entry_values_choices, &print_entry_values,
+                       _("Set printing of function arguments at function "
+                         "entry"),
+                       _("Show printing of function arguments at function "
+                         "entry"),
+                       _("\
+GDB can sometimes determine the values of function arguments at entry,\n\
+in addition to their current values.  This option tells GDB whether\n\
+to print the current value, the value at entry (marked as val@entry),\n\
+or both.  Note that one or both of these values may be <optimized out>."),
+                       NULL, NULL, &setprintlist, &showprintlist);
 }
index fe8880f..90a6fe4 100644 (file)
@@ -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
+     NO_ENTRY_VALUE_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);
 
index 86fe0e9..74826cf 100644 (file)
@@ -1,5 +1,24 @@
 2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
+       Display @entry parameter values (without references).
+       * gdb.arch/amd64-entry-value.cc (locexpr, stacktest, data, data2)
+       (different, validity, invalid): New functions.
+       (main): Call them.
+       * gdb.arch/amd64-entry-value.exp: New breakpoints breakhere_locexpr,
+       stacktest, breakhere_stacktest, different, breakhere_different,
+       breakhere_validity and breakhere_invalid.
+       (entry: bt): Update for @entry.
+       (entry_locexpr: *, entry_stack: *, entry_equal: *, entry_different: *)
+       (entry_validity: *, entry_invalid: *): Many new tests.
+       * gdb.base/break.exp
+       (run until breakpoint set at small function, optimized file): Accept
+       also the @entry suffix.
+       * gdb.mi/Makefile.in (PROGS): Add mi2-amd64-entry-value.
+       * gdb.mi/mi2-amd64-entry-value.c: New files.
+       * gdb.mi/mi2-amd64-entry-value.exp: New files.
+
+2011-10-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
        Protect entry values against self tail calls.
        * gdb.arch/amd64-entry-value.cc (self2, self): New.
        (main): Call self.
index 44b7564..7b7d050 100644 (file)
@@ -35,6 +35,13 @@ asm ("breakhere:");
 }
 
 static void __attribute__((noinline, noclone))
+locexpr (int i)
+{
+  i = i;
+asm ("breakhere_locexpr:");
+}
+
+static void __attribute__((noinline, noclone))
 c (int i, double j)
 {
   d (i * 10, j * 10);
@@ -114,10 +121,68 @@ 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,
+          double d1, double d2, double d3, double d4, double d5, double d6,
+          double d7, double d8, double d9, double da)
+{
+  s1 = 3;
+  s2 = 4;
+  d9 = 3.5;
+  da = 4.5;
+  e (v, v);
+asm ("breakhere_stacktest:");
+  e (v, v);
+}
+
+static int __attribute__((noinline, noclone))
+data (void)
+{
+  return 10;
+}
+
+static int __attribute__((noinline, noclone))
+data2 (void)
+{
+  return 20;
+}
+
+static int __attribute__((noinline, noclone))
+different (int val)
+{
+  val++;
+  e (val, val);
+asm ("breakhere_different:");
+  return val;
+}
+
+static int __attribute__((noinline, noclone))
+validity (int lost, int born)
+{
+  lost = data ();
+  e (0, 0.0);
+asm ("breakhere_validity:");
+  return born;
+}
+
+static void __attribute__((noinline, noclone))
+invalid (int inv)
+{
+  e (0, 0.0);
+asm ("breakhere_invalid:");
+}
+
 int
 main ()
 {
   d (30, 30.5);
+  locexpr (30);
+  stacktest (1, 2, 3, 4, 5, 6, 11, 12,
+            1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 11.5, 12.5);
+  different (5);
+  validity (5, data ());
+  invalid (data2 ());
+
   if (v)
     a (1, 1.25);
   else
index fdf8040..fcccdd8 100644 (file)
@@ -35,23 +35,128 @@ if ![runto_main] {
 }
 
 gdb_breakpoint "breakhere"
+gdb_breakpoint "breakhere_locexpr"
+gdb_breakpoint "stacktest"
+gdb_breakpoint "breakhere_stacktest"
+gdb_breakpoint "different"
+gdb_breakpoint "breakhere_different"
+gdb_breakpoint "breakhere_validity"
+gdb_breakpoint "breakhere_invalid"
 
 
 # Test @entry values for register passed parameters.
 
 gdb_continue_to_breakpoint "entry: breakhere"
 
-gdb_test "bt" "^bt\r\n#0 +d *\\(i=31, j=31\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main .*" \
+gdb_test "bt" "^bt\r\n#0 +d *\\(i=31, i@entry=30, j=31\\.5, j@entry=30\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main .*" \
         "entry: bt"
 gdb_test "p i" " = 31" "entry: p i"
 gdb_test "p j" { = 31\.5} "entry: p j"
 
 
+# Test @entry values when parameter in function is locexpr (and not loclist).
+
+gdb_continue_to_breakpoint "entry_locexpr: breakhere_locexpr"
+gdb_test "p i" " = 30" "entry_locexpr: p i"
+gdb_test_no_output "set variable i = 0" "entry_locexpr: set variable i = 0"
+gdb_test "bt" "^bt\r\n#0 +locexpr *\\(i=0, i@entry=30\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main .*" \
+        "entry_locexpr: bt"
+
+
+# Test @entry values for stack passed parameters.
+
+gdb_continue_to_breakpoint "entry_stack: stacktest"
+
+gdb_test "bt" "^bt\r\n#0 +stacktest *\\(r1=r1@entry=1, r2=r2@entry=2, \[^\r\n\]+, s1=s1@entry=11, s2=s2@entry=12, \[^\r\n\]+, d9=d9@entry=11\\.5, da=da@entry=12\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main .*" \
+        "entry_stack: bt at entry"
+
+gdb_continue_to_breakpoint "entry_stack: breakhere_stacktest"
+
+gdb_test "bt" "^bt\r\n#0 +stacktest *\\(r1=r1@entry=1, r2=r2@entry=2, \[^\r\n\]+, s1=3, s1@entry=11, s2=4, s2@entry=12, \[^\r\n\]+, d9=3\\.5, d9@entry=11\\.5, da=4\\.5, da@entry=12\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main .*" \
+        "entry_stack: bt"
+
+gdb_test "p s1" " = 3" "entry_stack: p s1"
+gdb_test "p s2" " = 4" "entry_stack: p s2"
+gdb_test "p d9" " = 3\\.5" "entry_stack: p d9"
+gdb_test "p da" " = 4\\.5" "entry_stack: p da"
+
+
+# Test various kinds of `set print entry-values'.
+
+gdb_continue_to_breakpoint "entry_equal: breakhere"
+
+gdb_test_no_output "set print entry-values no" "entry_equal: set print entry-values no"
+gdb_test "frame" {\(val=5\).*} "entry_equal: frame: no"
+gdb_test_no_output "set print entry-values only" "entry_equal: set print entry-values only"
+gdb_test "frame" {\(val@entry=5\).*} "entry_equal: frame: only"
+gdb_test_no_output "set print entry-values preferred" "entry_equal: set print entry-values preferred"
+gdb_test "frame" {\(val@entry=5\).*} "entry_equal: frame: preferred"
+gdb_test_no_output "set print entry-values if-needed" "entry_equal: set print entry-values if-needed"
+gdb_test "frame" {\(val=5\).*} "entry_equal: frame: if-needed"
+gdb_test_no_output "set print entry-values both" "entry_equal: set print entry-values both"
+gdb_test "frame" {\(val=5, val@entry=5\).*} "entry_equal: frame: both"
+gdb_test_no_output "set print entry-values compact" "entry_equal: set print entry-values compact"
+gdb_test "frame" {\(val=val@entry=5\).*} "entry_equal: frame: compact"
+gdb_test_no_output "set print entry-values default" "entry_equal: set print entry-values default"
+gdb_test "frame" {\(val=val@entry=5\).*} "entry_equal: frame: default"
+
+gdb_continue_to_breakpoint "entry_different: breakhere"
+
+gdb_test_no_output "set print entry-values no" "entry_different: set print entry-values no"
+gdb_test "frame" {\(val=6\).*} "entry_different: frame: no"
+gdb_test_no_output "set print entry-values only" "entry_different: set print entry-values only"
+gdb_test "frame" {\(val@entry=5\).*} "entry_different: frame: only"
+gdb_test_no_output "set print entry-values preferred" "entry_different: set print entry-values preferred"
+gdb_test "frame" {\(val@entry=5\).*} "entry_different: frame: preferred"
+gdb_test_no_output "set print entry-values if-needed" "entry_different: set print entry-values if-needed"
+gdb_test "frame" {\(val=6\).*} "entry_different: frame: if-needed"
+gdb_test_no_output "set print entry-values both" "entry_different: set print entry-values both"
+gdb_test "frame" {\(val=6, val@entry=5\).*} "entry_different: frame: both"
+gdb_test_no_output "set print entry-values compact" "entry_different: set print entry-values compact"
+gdb_test "frame" {\(val=6, val@entry=5\).*} "entry_different: frame: compact"
+gdb_test_no_output "set print entry-values default" "entry_different: set print entry-values default"
+gdb_test "frame" {\(val=6, val@entry=5\).*} "entry_different: frame: default"
+
+gdb_continue_to_breakpoint "entry_validity: breakhere"
+
+gdb_test_no_output "set print entry-values no" "entry_validity: set print entry-values no"
+gdb_test "frame" {\(lost=<optimized out>, born=10\).*} "entry_validity: frame: no"
+gdb_test_no_output "set print entry-values only" "entry_validity: set print entry-values only"
+gdb_test "frame" {\(lost@entry=5, born@entry=<optimized out>\).*} "entry_validity: frame: only"
+gdb_test_no_output "set print entry-values preferred" "entry_validity: set print entry-values preferred"
+gdb_test "frame" {\(lost@entry=5, born=10\).*} "entry_validity: frame: preferred"
+gdb_test_no_output "set print entry-values if-needed" "entry_validity: set print entry-values if-needed"
+gdb_test "frame" {\(lost@entry=5, born=10\).*} "entry_validity: frame: if-needed"
+gdb_test_no_output "set print entry-values both" "entry_validity: set print entry-values both"
+gdb_test "frame" {\(lost=<optimized out>, lost@entry=5, born=10, born@entry=<optimized out>\).*} "entry_validity: frame: both"
+gdb_test_no_output "set print entry-values compact" "entry_validity: set print entry-values compact"
+gdb_test "frame" {\(lost@entry=5, born=10\).*} "entry_validity: frame: compact"
+gdb_test_no_output "set print entry-values default" "entry_validity: set print entry-values default"
+gdb_test "frame" {\(lost=<optimized out>, lost@entry=5, born=10\).*} "entry_validity: frame: default"
+
+gdb_continue_to_breakpoint "entry_invalid: breakhere"
+
+gdb_test_no_output "set print entry-values no" "entry_invalid: set print entry-values no"
+gdb_test "frame" {\(inv=<optimized out>\).*} "entry_invalid: frame: no"
+gdb_test_no_output "set print entry-values only" "entry_invalid: set print entry-values only"
+gdb_test "frame" {\(inv@entry=<optimized out>\).*} "entry_invalid: frame: only"
+gdb_test_no_output "set print entry-values preferred" "entry_invalid: set print entry-values preferred"
+gdb_test "frame" {\(inv@entry=<optimized out>\).*} "entry_invalid: frame: preferred"
+gdb_test_no_output "set print entry-values if-needed" "entry_invalid: set print entry-values if-needed"
+gdb_test "frame" {\(inv=<optimized out>\).*} "entry_invalid: frame: if-needed"
+gdb_test_no_output "set print entry-values both" "entry_invalid: set print entry-values both"
+gdb_test "frame" {\(inv=<optimized out>, inv@entry=<optimized out>\).*} "entry_invalid: frame: both"
+gdb_test_no_output "set print entry-values compact" "entry_invalid: set print entry-values compact"
+gdb_test "frame" {\(inv=<optimized out>\).*} "entry_invalid: frame: compact"
+gdb_test_no_output "set print entry-values default" "entry_invalid: set print entry-values default"
+gdb_test "frame" {\(inv=<optimized out>\).*} "entry_invalid: frame: default"
+
+
 # Test virtual tail call frames.
 
 gdb_continue_to_breakpoint "tailcall: breakhere"
 
-gdb_test "bt" "^bt\r\n#0 +d *\\(i=71, j=73\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in c \\(i=7, j=7\\.25\\) \[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in b \\(i=5, j=5\\.25\\) \[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in main \[^\r\n\]*" \
+gdb_test "bt" "^bt\r\n#0 +d *\\(i=71, i@entry=70, j=73\\.5, j@entry=72\\.5\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in c \\(i=i@entry=7, j=j@entry=7\\.25\\) \[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in b \\(i=i@entry=5, j=j@entry=5\\.25\\) \[^\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 j" " = 73\\.5" "tailcall: p j"
@@ -71,7 +176,7 @@ gdb_test {p $sp0 + sizeof (void *) == $sp} " = true"
 
 gdb_continue_to_breakpoint "ambiguous: breakhere"
 
-gdb_test "bt" "^bt\r\n#0 +d \\(i=<optimized out>, j=<optimized out>\\)\[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in amb_z \\(i=<optimized out>\\)\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in amb_y \\(i=<optimized out>\\)\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in amb_x \\(i=<optimized out>\\)\[^\r\n\]*\r\n#4 +0x\[0-9a-f\]+ in amb_b \\(i=101\\)\[^\r\n\]*\r\n#5 +0x\[0-9a-f\]+ in amb_a \\(i=100\\)\[^\r\n\]*\r\n#6 +0x\[0-9a-f\]+ in main \\(\\)\[^\r\n\]*" \
+gdb_test "bt" "^bt\r\n#0 +d \\(i=<optimized out>, j=<optimized out>\\)\[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in amb_z \\(i=<optimized out>\\)\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in amb_y \\(i=<optimized out>\\)\[^\r\n\]*\r\n#3 +0x\[0-9a-f\]+ in amb_x \\(i=<optimized out>\\)\[^\r\n\]*\r\n#4 +0x\[0-9a-f\]+ in amb_b \\(i=i@entry=101\\)\[^\r\n\]*\r\n#5 +0x\[0-9a-f\]+ in amb_a \\(i=i@entry=100\\)\[^\r\n\]*\r\n#6 +0x\[0-9a-f\]+ in main \\(\\)\[^\r\n\]*" \
         "ambiguous: bt"
 
 
index 15227bc..92fcc69 100644 (file)
@@ -916,13 +916,13 @@ set bp_location14 [gdb_get_line_number "set breakpoint 14 here" $srcfile1]
 
 gdb_test_multiple "continue" \
     "run until breakpoint set at small function, optimized file" {
-       -re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile1:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
+       -re "Breakpoint $decimal, marker4 \\(d=(d@entry=)?177601976\\) at .*$srcfile1:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
            pass "run until breakpoint set at small function, optimized file"
        }
-       -re "Breakpoint $decimal, $hex in marker4 \\(d=177601976\\) at .*$srcfile1:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
+       -re "Breakpoint $decimal, $hex in marker4 \\(d=(d@entry=)?177601976\\) at .*$srcfile1:$bp_location13\[\r\n\]+$bp_location13\[\t \]+void marker4.*" {
            pass "run until breakpoint set at small function, optimized file"
        }
-       -re "Breakpoint $decimal, marker4 \\(d=177601976\\) at .*$srcfile1:$bp_location14\[\r\n\]+$bp_location14\[\t \]+void marker4.*" {
+       -re "Breakpoint $decimal, marker4 \\(d=(d@entry=)?177601976\\) at .*$srcfile1:$bp_location14\[\r\n\]+$bp_location14\[\t \]+void marker4.*" {
            # marker4() is defined at line 46 when compiled with -DPROTOTYPES
            pass "run until breakpoint set at small function, optimized file (line bp_location14)"
        }
index e8754f4..dc1f1a3 100644 (file)
@@ -9,7 +9,8 @@ PROGS = basics c_variable cpp_variable var-cmd dw2-ref-missing-frame    \
        mi-pending mi-pthreads mi-read-memory mi-regs mi-return         \
        mi-reverse mi-simplerun mi-stack mi-stepi mi-syn-frame          \
        mi-var-block mi-var-child mi-var-cmd mi-var-cp mi-var-display   \
-       mi-var-invalidate mi-var-invalidate_bis mi-watch mi2-basics     \
+       mi-var-invalidate mi-var-invalidate_bis mi-watch                \
+       mi2-amd64-entry-value mi2-basics                                \
        mi2-break mi2-cli mi2-disassemble mi2-eval mi2-file             \
        mi2-pthreads mi2-regs mi2-return mi2-simplerun mi2-stepi        \
        mi2-var-block mi2-var-child mi2-var-cmd mi2-var-display         \
diff --git a/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.c b/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.c
new file mode 100644 (file)
index 0000000..5c73a68
--- /dev/null
@@ -0,0 +1,70 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2011 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+static volatile int v;
+
+static void __attribute__((noinline, noclone))
+e (int i, double j)
+{
+  v = 0;
+}
+
+static int __attribute__((noinline, noclone))
+data (void)
+{
+  return 10;
+}
+
+static int __attribute__((noinline, noclone))
+data2 (void)
+{
+  return 20;
+}
+
+static int __attribute__((noinline, noclone))
+different (int val)
+{
+  val++;
+  e (val, val);
+asm ("breakhere_different:");
+  return val;
+}
+
+static int __attribute__((noinline, noclone))
+validity (int lost, int born)
+{
+  lost = data ();
+  e (0, 0.0);
+asm ("breakhere_validity:");
+  return born;
+}
+
+static void __attribute__((noinline, noclone))
+invalid (int inv)
+{
+  e (0, 0.0);
+asm ("breakhere_invalid:");
+}
+
+int
+main ()
+{
+  different (5);
+  validity (5, data ());
+  invalid (data2 ());
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp b/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp
new file mode 100644 (file)
index 0000000..6cfcabf
--- /dev/null
@@ -0,0 +1,171 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi2"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+set testfile mi2-amd64-entry-value
+set srcfile ${testfile}.s
+set opts {}
+
+if [info exists COMPILE] {
+    # make check RUNTESTFLAGS="gdb.mi/mi2-amd64-entry-value.exp COMPILE=1"
+    set srcfile ${testfile}.c
+    lappend opts debug optimize=-O2
+} elseif { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
+    verbose "Skipping mi2-amd64-entry-value."
+    return
+}
+
+set executable ${testfile}
+set binfile ${objdir}/${subdir}/${executable}
+
+if [build_executable ${testfile}.exp ${executable} ${srcfile} $opts] {
+    return -1
+}
+
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+foreach name {different breakhere_different breakhere_validity breakhere_invalid} {
+    mi_create_breakpoint $name .* .* .* .* .* .* "break $name"
+}
+
+
+# Test various kinds of `set print entry-values'.
+
+if {[mi_runto main] == -1} {
+    return -1
+}
+mi_gdb_test "-gdb-set print entry-values no" {\^done} "no: set print entry-values"
+mi_send_resuming_command "exec-continue" "no: entry_equal: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="5"}} .* .* {.* disp="keep"} "no: entry_equal: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="5"}\]} "no: entry_equal: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "no: entry_different: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="6"}} .* .* {.* disp="keep"} "no: entry_different: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="6"}\]} "no: entry_different: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "no: validity: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="lost",value="<optimized out>"},{name="born",value="10"}} .* .* {.* disp="keep"} "no: validity: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="lost",arg="1",value="<optimized out>"},{name="born",arg="1",value="10"}\]} "no: validity: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "no: invalid: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="inv",value="<optimized out>"}} .* .* {.* disp="keep"} "no: invalid: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="inv",arg="1",value="<optimized out>"}\]} "no: invalid: -stack-list-variables"
+
+if {[mi_runto main] == -1} {
+    return -1
+}
+mi_gdb_test "-gdb-set print entry-values only" {\^done} "only: set print entry-values"
+mi_send_resuming_command "exec-continue" "only: entry_equal: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val@entry",value="5"}} .* .* {.* disp="keep"} "only: entry_equal: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val@entry",arg="1",value="5"}\]} "only: entry_equal: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "only: entry_different: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val@entry",value="5"}} .* .* {.* disp="keep"} "only: entry_different: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val@entry",arg="1",value="5"}\]} "only: entry_different: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "only: validity: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="lost@entry",value="5"},{name="born@entry",value="<optimized out>"}} .* .* {.* disp="keep"} "only: validity: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="lost@entry",arg="1",value="5"},{name="born@entry",arg="1",value="<optimized out>"}\]} "only: validity: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "only: invalid: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="inv@entry",value="<optimized out>"}} .* .* {.* disp="keep"} "only: invalid: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="inv@entry",arg="1",value="<optimized out>"}\]} "only: invalid: -stack-list-variables"
+
+if {[mi_runto main] == -1} {
+    return -1
+}
+mi_gdb_test "-gdb-set print entry-values preferred" {\^done} "preferred: set print entry-values"
+mi_send_resuming_command "exec-continue" "preferred: entry_equal: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val@entry",value="5"}} .* .* {.* disp="keep"} "preferred: entry_equal: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val@entry",arg="1",value="5"}\]} "preferred: entry_equal: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "preferred: entry_different: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val@entry",value="5"}} .* .* {.* disp="keep"} "preferred: entry_different: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val@entry",arg="1",value="5"}\]} "preferred: entry_different: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "preferred: validity: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="lost@entry",value="5"},{name="born",value="10"}} .* .* {.* disp="keep"} "preferred: validity: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="lost@entry",arg="1",value="5"},{name="born",arg="1",value="10"}\]} "preferred: validity: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "preferred: invalid: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="inv@entry",value="<optimized out>"}} .* .* {.* disp="keep"} "preferred: invalid: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="inv@entry",arg="1",value="<optimized out>"}\]} "preferred: invalid: -stack-list-variables"
+
+if {[mi_runto main] == -1} {
+    return -1
+}
+mi_gdb_test "-gdb-set print entry-values if-needed" {\^done} "if-needed: set print entry-values"
+mi_send_resuming_command "exec-continue" "if-needed: entry_equal: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="5"}} .* .* {.* disp="keep"} "if-needed: entry_equal: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="5"}\]} "if-needed: entry_equal: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "if-needed: entry_different: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="6"}} .* .* {.* disp="keep"} "if-needed: entry_different: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="6"}\]} "if-needed: entry_different: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "if-needed: validity: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="lost@entry",value="5"},{name="born",value="10"}} .* .* {.* disp="keep"} "if-needed: validity: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="lost@entry",arg="1",value="5"},{name="born",arg="1",value="10"}\]} "if-needed: validity: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "if-needed: invalid: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="inv",value="<optimized out>"}} .* .* {.* disp="keep"} "if-needed: invalid: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="inv",arg="1",value="<optimized out>"}\]} "if-needed: invalid: -stack-list-variables"
+
+if {[mi_runto main] == -1} {
+    return -1
+}
+mi_gdb_test "-gdb-set print entry-values both" {\^done} "both: set print entry-values"
+mi_send_resuming_command "exec-continue" "both: entry_equal: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="5"},{name="val@entry",value="5"}} .* .* {.* disp="keep"} "both: entry_equal: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="5"},{name="val@entry",arg="1",value="5"}\]} "both: entry_equal: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "both: entry_different: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="6"},{name="val@entry",value="5"}} .* .* {.* disp="keep"} "both: entry_different: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="6"},{name="val@entry",arg="1",value="5"}\]} "both: entry_different: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "both: validity: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="lost",value="<optimized out>"},{name="lost@entry",value="5"},{name="born",value="10"},{name="born@entry",value="<optimized out>"}} .* .* {.* disp="keep"} "both: validity: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="lost",arg="1",value="<optimized out>"},{name="lost@entry",arg="1",value="5"},{name="born",arg="1",value="10"},{name="born@entry",arg="1",value="<optimized out>"}\]} "both: validity: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "both: invalid: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="inv",value="<optimized out>"},{name="inv@entry",value="<optimized out>"}} .* .* {.* disp="keep"} "both: invalid: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="inv",arg="1",value="<optimized out>"},{name="inv@entry",arg="1",value="<optimized out>"}\]} "both: invalid: -stack-list-variables"
+
+if {[mi_runto main] == -1} {
+    return -1
+}
+mi_gdb_test "-gdb-set print entry-values compact" {\^done} "compact: set print entry-values"
+mi_send_resuming_command "exec-continue" "compact: entry_equal: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="5"},{name="val@entry",value="5"}} .* .* {.* disp="keep"} "compact: entry_equal: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="5"},{name="val@entry",arg="1",value="5"}\]} "compact: entry_equal: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "compact: entry_different: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="6"},{name="val@entry",value="5"}} .* .* {.* disp="keep"} "compact: entry_different: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="6"},{name="val@entry",arg="1",value="5"}\]} "compact: entry_different: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "compact: validity: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="lost@entry",value="5"},{name="born",value="10"}} .* .* {.* disp="keep"} "compact: validity: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="lost@entry",arg="1",value="5"},{name="born",arg="1",value="10"}\]} "compact: validity: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "compact: invalid: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="inv",value="<optimized out>"}} .* .* {.* disp="keep"} "compact: invalid: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="inv",arg="1",value="<optimized out>"}\]} "compact: invalid: -stack-list-variables"
+
+if {[mi_runto main] == -1} {
+    return -1
+}
+mi_gdb_test "-gdb-set print entry-values default" {\^done} "default: set print entry-values"
+mi_send_resuming_command "exec-continue" "default: entry_equal: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="5"},{name="val@entry",value="5"}} .* .* {.* disp="keep"} "default: entry_equal: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="5"},{name="val@entry",arg="1",value="5"}\]} "default: entry_equal: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "default: entry_different: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="val",value="6"},{name="val@entry",value="5"}} .* .* {.* disp="keep"} "default: entry_different: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="val",arg="1",value="6"},{name="val@entry",arg="1",value="5"}\]} "default: entry_different: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "default: validity: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="lost",value="<optimized out>"},{name="lost@entry",value="5"},{name="born",value="10"}} .* .* {.* disp="keep"} "default: validity: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="lost",arg="1",value="<optimized out>"},{name="lost@entry",arg="1",value="5"},{name="born",arg="1",value="10"}\]} "default: validity: -stack-list-variables"
+mi_send_resuming_command "exec-continue" "default: invalid: continue"
+mi_expect_stop "breakpoint-hit" .* {{name="inv",value="<optimized out>"}} .* .* {.* disp="keep"} "default: invalid: stop"
+mi_gdb_test "-stack-list-variables --all-values" {\^done,variables=\[{name="inv",arg="1",value="<optimized out>"}\]} "default: invalid: -stack-list-variables"