This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch 00/12] entryval#2: Fix x86_64 <optimized out> parameters, virtual tail call frames


Hi,

re-post of the series:
	[patch 00/12] entryval: Fix x86_64 <optimized out> parameters, virtual tail call frames
	http://sourceware.org/ml/gdb-patches/2011-07/msg00430.html

particular excerpt:
The patches are available (merged only) in GIT for more convenience at:
	http://sourceware.org/gdb/wiki/ArcherBranchManagement
	archer-jankratochvil-entryval


Here is attached a diff against the previous patch series.  The changes are:
  New `set print entry-values' setting.
  Printed now for any frame arguments printing (not just during `bt full').
  $sp shift is simulated in the tail call frames.
  There is new NO_ENTRY_VALUE_ERROR (NOT_FOUND_ERROR is no longer reused).
  [patch 07/12] const/non-const dropped thanks to new lval_funcs->coerce_ref.
  Entry values are attempted even for non-loclist DWARF expressions.
  MI is supported now, no specific MI protocol changes were needed.

Reviews were replied before.  I will check it in if no new issues appear.


Thanks,
Jan


--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -772,7 +772,7 @@ cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h cli/cli-utils.h \
 cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
 gnulib/string.in.h gnulib/str-two-way.h \
 gnulib/stdint.in.h remote.h gdb.h sparc-nat.h \
-gdbthread.h dwarf2-frame.h nbsd-nat.h dcache.h \
+gdbthread.h dwarf2-frame.h dwarf2-frame-tailcall.h nbsd-nat.h dcache.h \
 amd64-nat.h s390-tdep.h arm-linux-tdep.h exceptions.h macroscope.h \
 gdbarch.h bsd-uthread.h gdb_stat.h memory-map.h	memrange.h \
 mdebugread.h m88k-tdep.h stabsread.h hppa-linux-offsets.h linux-fork.h \
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -93,6 +93,19 @@ info auto-load-scripts [REGEXP]
   begin, assuming that tracepoints will be enabled as needed while the trace
   is running.
 
+* New options
+
+set print entry-values (both|compact|default|if-needed|no|only|preferred)
+show print entry-values
+  Set printing of frame arguments values at function entry.  In some cases
+  GDB can determine the value of function argument which was passed by the
+  function caller, despite the argument value may be already modified.
+
+set debug tailcall
+show debug tailcall
+  Control display of debugging info for determining virtual tail call frames,
+  present in inferior debug info together with the @entry values.
+
 * New remote packets
 
 QTEnable
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -164,7 +164,8 @@ extern void ada_print_typedef (struct type *type, struct symbol *new_symbol,
 			       struct ui_file *stream);
 
 extern int ada_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
-                          struct ui_file *, int, struct value *,
+                          struct ui_file *, int,
+			  const struct value *,
 			  const struct value_print_options *);
 
 extern int ada_value_print (struct value *, struct ui_file *,
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -37,18 +37,23 @@
 #include "objfiles.h"
 
 static void print_record (struct type *, const gdb_byte *, int,
-			  struct ui_file *, int, struct value *,
+			  struct ui_file *,
+			  int,
+			  const struct value *,
 			  const struct value_print_options *);
 
 static int print_field_values (struct type *, const gdb_byte *,
-			       int, struct ui_file *, int, struct value *,
+			       int,
+			       struct ui_file *, int,
+			       const struct value *,
 			       const struct value_print_options *,
 			       int, struct type *, int);
 
 static void adjust_type_signedness (struct type *);
 
 static int ada_val_print_1 (struct type *, const gdb_byte *, int, CORE_ADDR,
-			    struct ui_file *, int, struct value *,
+			    struct ui_file *, int,
+			    const struct value *,
 			    const struct value_print_options *);
 
 
@@ -568,7 +573,8 @@ ada_printstr (struct ui_file *stream, struct type *type,
 int
 ada_val_print (struct type *type, const gdb_byte *valaddr,
 	       int embedded_offset, CORE_ADDR address,
-	       struct ui_file *stream, int recurse, struct value *val,
+	       struct ui_file *stream, int recurse,
+	       const struct value *val,
 	       const struct value_print_options *options)
 {
   volatile struct gdb_exception except;
@@ -595,7 +601,8 @@ ada_val_print (struct type *type, const gdb_byte *valaddr,
 static int
 ada_val_print_array (struct type *type, const gdb_byte *valaddr,
 		     int offset, CORE_ADDR address,
-		     struct ui_file *stream, int recurse, struct value *val,
+		     struct ui_file *stream, int recurse,
+		     const struct value *val,
 		     const struct value_print_options *options)
 {
   int result = 0;
@@ -663,7 +670,7 @@ static int
 ada_val_print_1 (struct type *type, const gdb_byte *valaddr,
 		 int offset, CORE_ADDR address,
 		 struct ui_file *stream, int recurse,
-		 struct value *original_value,
+		 const struct value *original_value,
 		 const struct value_print_options *options)
 {
   unsigned int len;
@@ -892,23 +899,14 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr,
       if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
         {
           CORE_ADDR deref_val_int;
+	  struct value *deref_val;
 
-	  if (VALUE_LVAL (original_value) == lval_computed)
+	  deref_val = coerce_ref_if_computed (original_value);
+	  if (deref_val)
 	    {
-	      const struct lval_funcs *funcs;
-	      
-	      funcs = value_computed_funcs (original_value);
-	      if (funcs->indirect)
-	        {
-		  struct value *result = funcs->indirect (original_value);
-
-		  if (result)
-		    {
-		      common_val_print (result, stream, recurse,
-					options, current_language);
-		      return 0;
-		    }
-	        }
+	      common_val_print (deref_val, stream, recurse + 1, options,
+				current_language);
+	      return 0;
 	    }
 
           deref_val_int = unpack_pointer (type, valaddr + offset_aligned);
@@ -940,7 +938,8 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr,
 static int
 print_variant_part (struct type *type, int field_num,
 		    const gdb_byte *valaddr, int offset,
-		    struct ui_file *stream, int recurse, struct value *val,
+		    struct ui_file *stream, int recurse,
+		    const struct value *val,
 		    const struct value_print_options *options,
 		    int comma_needed,
 		    struct type *outer_type, int outer_offset)
@@ -1014,7 +1013,8 @@ ada_value_print (struct value *val0, struct ui_file *stream,
 static void
 print_record (struct type *type, const gdb_byte *valaddr,
 	      int offset,
-	      struct ui_file *stream, int recurse, struct value *val,
+	      struct ui_file *stream, int recurse,
+	      const struct value *val,
 	      const struct value_print_options *options)
 {
   type = ada_check_typedef (type);
@@ -1050,7 +1050,7 @@ print_record (struct type *type, const gdb_byte *valaddr,
 static int
 print_field_values (struct type *type, const gdb_byte *valaddr,
 		    int offset, struct ui_file *stream, int recurse,
-		    struct value *val,
+		    const struct value *val,
 		    const struct value_print_options *options,
 		    int comma_needed,
 		    struct type *outer_type, int outer_offset)
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -73,7 +73,8 @@ extern void c_print_typedef (struct type *,
 
 extern int c_val_print (struct type *, const gdb_byte *,
 			int, CORE_ADDR,
-			struct ui_file *, int, struct value *,
+			struct ui_file *, int,
+			const struct value *,
 			const struct value_print_options *);
 
 extern int c_value_print (struct value *, struct ui_file *,
@@ -118,13 +119,15 @@ extern void cp_print_class_member (const gdb_byte *, struct type *,
 
 extern void cp_print_value_fields (struct type *, struct type *,
 				   const gdb_byte *, int, CORE_ADDR,
-				   struct ui_file *, int, struct value *,
+				   struct ui_file *, int,
+				   const struct value *,
 				   const struct value_print_options *,
 				   struct type **, int);
 
 extern void cp_print_value_fields_rtti (struct type *,
 					const gdb_byte *, int, CORE_ADDR,
-					struct ui_file *, int, struct value *,
+					struct ui_file *, int,
+					const struct value *,
 					const struct value_print_options *,
 					struct type **, int);
 
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -149,7 +149,8 @@ c_textual_element_type (struct type *type, char format)
 int
 c_val_print (struct type *type, const gdb_byte *valaddr,
 	     int embedded_offset, CORE_ADDR address,
-	     struct ui_file *stream, int recurse, struct value *original_value,
+	     struct ui_file *stream, int recurse,
+	     const struct value *original_value,
 	     const struct value_print_options *options)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -381,22 +382,12 @@ c_val_print (struct type *type, const gdb_byte *valaddr,
 	    {
 	      struct value *deref_val;
 
-	      if (VALUE_LVAL (original_value) == lval_computed)
+	      deref_val = coerce_ref_if_computed (original_value);
+	      if (deref_val)
 		{
-		  const struct lval_funcs *funcs;
-		  
-		  funcs = value_computed_funcs (original_value);
-		  if (funcs->indirect)
-		    {
-		      struct value *result = funcs->indirect (original_value);
-
-		      if (result)
-			{
-			  common_val_print (result, stream, recurse,
-					    options, current_language);
-			  return 0;
-			}
-		    }
+		  common_val_print (deref_val, stream, recurse, options,
+				    current_language);
+		  return 0;
 		}
 
 	      deref_val = value_at (TYPE_TARGET_TYPE (type),
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -85,7 +85,7 @@ static void cp_print_static_field (struct type *, struct value *,
 static void cp_print_value (struct type *, struct type *,
 			    const gdb_byte *, int,
 			    CORE_ADDR, struct ui_file *,
-			    int, struct value *,
+			    int, const struct value *,
 			    const struct value_print_options *,
 			    struct type **);
 
@@ -159,7 +159,7 @@ void
 cp_print_value_fields (struct type *type, struct type *real_type,
 		       const gdb_byte *valaddr, int offset,
 		       CORE_ADDR address, struct ui_file *stream,
-		       int recurse, struct value *val,
+		       int recurse, const struct value *val,
 		       const struct value_print_options *options,
 		       struct type **dont_print_vb,
 		       int dont_print_statmem)
@@ -432,7 +432,7 @@ cp_print_value_fields_rtti (struct type *type,
 			    const gdb_byte *valaddr, int offset,
 			    CORE_ADDR address,
 			    struct ui_file *stream, int recurse,
-			    struct value *val,
+			    const struct value *val,
 			    const struct value_print_options *options,
 			    struct type **dont_print_vb, 
 			    int dont_print_statmem)
@@ -471,7 +471,7 @@ static void
 cp_print_value (struct type *type, struct type *real_type,
 		const gdb_byte *valaddr, int offset,
 		CORE_ADDR address, struct ui_file *stream,
-		int recurse, struct value *val,
+		int recurse, const struct value *val,
 		const struct value_print_options *options,
 		struct type **dont_print_vb)
 {
@@ -498,7 +498,7 @@ cp_print_value (struct type *type, struct type *real_type,
       struct type *baseclass = check_typedef (TYPE_BASECLASS (type, i));
       char *basename = TYPE_NAME (baseclass);
       const gdb_byte *base_valaddr = NULL;
-      struct value *base_val = NULL;
+      const struct value *base_val = NULL;
       volatile struct gdb_exception ex;
 
       if (BASETYPE_VIA_VIRTUAL (type, i))
--- a/gdb/d-lang.h
+++ b/gdb/d-lang.h
@@ -27,7 +27,8 @@ extern char *d_demangle (const char *mangled, int options);
 
 extern int d_val_print (struct type *type, const gdb_byte *valaddr,
 			int embedded_offset, CORE_ADDR address,
-			struct ui_file *stream, int recurse, struct value *val,
+			struct ui_file *stream, int recurse,
+			const struct value *val,
 			const struct value_print_options *options);
 
 #endif /* !defined (D_LANG_H) */
--- a/gdb/d-valprint.c
+++ b/gdb/d-valprint.c
@@ -72,7 +72,8 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr,
 int
 d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
              CORE_ADDR address, struct ui_file *stream, int recurse,
-	     struct value *val, const struct value_print_options *options)
+	     const struct value *val,
+             const struct value_print_options *options)
 {
   int ret;
 
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -5947,13 +5947,8 @@ Similar, but print only the outermost @var{n} frames.
 @itemx bt full
 @itemx bt full @var{n}
 @itemx bt full -@var{n}
-Print the values of the local variables also.
-
-Names with appended @code{@@entry} show values of function parameters at the
-time the function got called.  The @code{@@entry} parameter line is not shown
-when the entry value is not available.
-
-@var{n} specifies the number of frames to print, as described above.
+Print the values of the local variables also.  @var{n} specifies the
+number of frames to print, as described above.
 @end table
 
 @kindex where
@@ -6228,10 +6223,6 @@ architectures) that you specify in the @code{frame} command.
 @item info args
 Print the arguments of the selected frame, each on a separate line.
 
-Names with appended @code{@@entry} show values of function parameters at the
-time the function got called.  The @code{@@entry} parameter line is not shown
-when the entry value is not available.
-
 @item info locals
 @kindex info locals
 Print the local variables of the selected frame, each on a separate
@@ -7286,10 +7277,9 @@ 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
+If you append @kbd{@@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.
+error message is printed.  Entry values are available only with some compilers.
 
 @smallexample
 Breakpoint 1, d (i=30) at gdb.base/entry-value.c:29
@@ -7966,6 +7956,118 @@ 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 arguments values at function entry.  In some cases
+@value{GDBN} can determine the value of function argument which was passed by
+the function caller, despite the argument value may be already modified by the
+current function and therefore different.  For optimized code also the current
+value may be possibly not available and the entry value may be still known,
+which aids the debugging of production code.
+
+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 default @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.  For example for
+@value{NGCC} additionally optimization and debugging compilation options must
+be enabled (@option{-O -g}).  Still even with the required debug info there
+exist many reasons why the code path analysis by @value{GDBN} may fail in
+specific cases.
+
+@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
+set print entry-values 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 at least 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@@entry=<optimized out>)
+#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 at least the entry point 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 both
+set print entry-values both
+Always print both the actual parameter value and its value from function entry
+point.  Still print both even if one of them or both are @code{<optimized out>}.
+@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 know 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 they are equal 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 they are equal 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
+
+@item show print entry-values
+Show printing of frame arguments values at function entry.
+
 @item set print repeats
 @cindex repeated array elements
 Set the threshold for suppressing display of repeated array
@@ -9511,6 +9613,7 @@ please report it to us as a bug (including a test case!).
 
 @menu
 * Inline Functions::            How @value{GDBN} presents inlining
+* Tail Call Frames::            @value{GDBN} analysis of jumps to functions
 @end menu
 
 @node Inline Functions
@@ -9578,6 +9681,60 @@ and print a variable where your program stored the return value.
 
 @end itemize
 
+@node Tail Call Frames
+@section Tail Call Frames
+@cindex tail call frames, debugging
+
+Function @code{B} can call function @code{C} by its very last statement.  In
+unoptimized compilation the call of @code{C} is immediately followed by return
+instruction at the end of @code{B} code.  Optimizing compiler may replace the
+call and return in function @code{B} into one jump to function @code{C}
+instead.  Such use of a jump instruction is called tail call.
+
+During execution of function @code{C} there will remain no indication it has
+been tail called from function @code{B}.  If function @code{A} regularly calls
+function @code{B} which tail calls function @code{C} then @value{GDBN} sees as
+the caller of function @code{C} the function @code{A}.  @value{GDBN} can in
+some cases search all the possible code paths and if it determintes there
+exists an unambiguous code path it will create call frames for it (in this case
+a frame with @code{$pc} in function @code{B}).  The virtual return address into
+such tail call frame will be pointing pointing right after the jump instruction
+(as if it would be a call instructions).
+
+This functionality is currently supported only by DWARF 2 debugging format and
+the compiler has to produce @samp{DW_TAG_GNU_call_site} tags.  For example for
+@value{NGCC} additionally optimization and debugging compilation options must
+be enabled (@option{-O -g}).  Still even with the required debug info there
+exist many reasons why the code path analysis by @value{GDBN} may fail in
+specific cases.
+
+@kbd{info frame} command (@pxref{Frame Info}) will indicate the tail call frame
+kind by text @code{tail call frame}.
+
+The detection of all the possible code path executions can find them ambiguous.
+There is no execution history stored (possible @ref{Reverse Execution} is never
+used for this purpose) and the last known caller could have reached the known
+callee by multiple different jump sequences.  In such case @value{GDBN} still
+tries to show at least all the unambiguous top tail callers and all the
+unambiguous bottom tail calees, if any.
+
+@kbd{set verbose} command (@pxref{Messages/Warnings, ,Optional Warnings and
+Messages}.) can show some reasons why the complete code path analysis did not
+succeed in a specific case.
+
+@table @code
+@item set debug tailcall
+@kindex set debug tailcall
+When set to on, enables tail calls analysis messages printing.  It will show
+all the possible valid tail calls code paths it has considered.  It will also
+print the intersection of them with the final unambiguous (possibly partial or
+even empty) code path result.
+
+@item show debug tailcall
+@kindex show debug tailcall
+Show the current state of tail calls analysis messages.
+@end table
+
 
 @node Macros
 @chapter C Preprocessor Macros
@@ -23078,6 +23235,13 @@ inferior function call.
 A frame representing an inlined function.  The function was inlined
 into a @code{gdb.NORMAL_FRAME} that is older than this one.
 
+@item gdb.TAILCALL_FRAME
+A frame representing a tail call.  Tail calls are used if the last statement of
+an inferior function is a call of a (usually different) function.  Such call
+immediately followed by return instruction is in optimized code converted to
+just one jump instruction.  @value{GDBN} can in some cases guess such jump has
+been executed and it creates a @code{gdb.TAILCALL_FRAME} for it.
+
 @item gdb.SIGTRAMP_FRAME
 A signal trampoline frame.  This is the frame created by the OS when
 it calls into a signal handler.
--- a/gdb/dwarf2-frame-tailcall.c
+++ b/gdb/dwarf2-frame-tailcall.c
@@ -27,13 +27,15 @@
 #include "hashtab.h"
 #include "exceptions.h"
 #include "gdbtypes.h"
-
+#include "regcache.h"
+#include "value.h"
 
 /* Contains struct tailcall_cache indexed by next_bottom_frame.  */
 static htab_t cache_htab;
 
-/* Associated structure of the unwinder for call_site_chain.  */
-
+/* Associate structure of the unwinder to call_site_chain.  Lifetime of this
+   structure is maintained by REFC decremented by dealloc_cache, all of them
+   get deleted during reinit_frame_cache.  */
 struct tailcall_cache
 {
   /* It must be the first one of this struct.  It is the furthest callee.  */
@@ -51,8 +53,15 @@ struct tailcall_cache
 
   /* Unwound PC from the top (caller) frame, as it is not contained
      in CHAIN.  */
-
   CORE_ADDR prev_pc;
+
+  /* Compensate SP in caller frames appropriately.  prev_sp and
+     entry_cfa_sp_offset are valid only if PREV_SP_P.  PREV_SP is SP at the top
+     (caller) frame.  ENTRY_CFA_SP_OFFSET is shift of SP in tail call frames
+     against next_bottom_frame SP.  */
+  unsigned prev_sp_p : 1;
+  CORE_ADDR prev_sp;
+  LONGEST entry_cfa_sp_offset;
 };
 
 /* hash_f for htab_create_alloc of cache_htab.  */
@@ -86,7 +95,7 @@ cache_new_ref1 (struct frame_info *next_bottom_frame)
   struct tailcall_cache *cache;
   void **slot;
 
-  cache = xmalloc (sizeof (*cache));
+  cache = xzalloc (sizeof (*cache));
 
   cache->next_bottom_frame = next_bottom_frame;
   cache->refc = 1;
@@ -205,16 +214,14 @@ tailcall_frame_this_id (struct frame_info *this_frame, void **this_cache,
 {
   struct tailcall_cache *cache = *this_cache;
   struct frame_info *next_frame;
-  CORE_ADDR this_frame_base;
 
   /* Tail call does not make sense for a sentinel frame.  */
   next_frame = get_next_frame (this_frame);
   gdb_assert (next_frame != NULL);
 
-  /* SP does not change during tail calls.  */
-  this_frame_base = get_frame_base (next_frame);
-
-  (*this_id) = frame_id_build (this_frame_base, get_frame_pc (this_frame));
+  *this_id = get_frame_id (next_frame);
+  (*this_id).code_addr = get_frame_pc (this_frame);
+  (*this_id).code_addr_p = 1;
   (*this_id).inline_depth = (cache->chain_levels
 			     - existing_next_levels (this_frame, cache));
   gdb_assert ((*this_id).inline_depth > 0);
@@ -251,20 +258,53 @@ pretend_pc (struct frame_info *this_frame, struct tailcall_cache *cache)
   return cache->prev_pc;
 }
 
-/* Implementation of frame_prev_register_ftype.  Register set of virtual tail
-   call frames is assumed to be the one of the top (caller) frame.  Only PC
-   value can be different for virtual tail call frames.  */
+/* Implementation of frame_prev_register_ftype.  If no specific register
+   override is supplied NULL is returned (this is incompatible with
+   frame_prev_register_ftype semantics).  next_bottom_frame and tail call
+   frames unwind the NULL case differently.  */
+
+struct value *
+dwarf2_tailcall_prev_register_first (struct frame_info *this_frame,
+				     void **tailcall_cachep, int regnum)
+{
+  struct gdbarch *this_gdbarch = get_frame_arch (this_frame);
+  struct tailcall_cache *cache = *tailcall_cachep;
+  CORE_ADDR addr;
+
+  if (regnum == gdbarch_pc_regnum (this_gdbarch))
+    addr = pretend_pc (this_frame, cache);
+  else if (cache->prev_sp_p && regnum == gdbarch_sp_regnum (this_gdbarch))
+    {
+      int next_levels = existing_next_levels (this_frame, cache);
+
+      if (next_levels == cache->chain_levels - 1)
+	addr = cache->prev_sp;
+      else
+	addr = get_frame_base (this_frame) - cache->entry_cfa_sp_offset;
+    }
+  else
+    return NULL;
+
+  return frame_unwind_got_address (this_frame, regnum, addr);
+}
+
+/* Implementation of frame_prev_register_ftype for tail call frames.  Register
+   set of virtual tail call frames is assumed to be the one of the top (caller)
+   frame - assume unchanged register value for NULL from
+   dwarf2_tailcall_prev_register_first.  */
 
 static struct value *
 tailcall_frame_prev_register (struct frame_info *this_frame,
 			       void **this_cache, int regnum)
 {
-  struct gdbarch *this_gdbarch = get_frame_arch (this_frame);
   struct tailcall_cache *cache = *this_cache;
+  struct value *val;
 
-  if (regnum == gdbarch_pc_regnum (this_gdbarch))
-    return frame_unwind_got_constant (this_frame, regnum,
-				      pretend_pc (this_frame, cache));
+  gdb_assert (this_frame != cache->next_bottom_frame);
+
+  val = dwarf2_tailcall_prev_register_first (this_frame, this_cache, regnum);
+  if (val)
+    return val;
 
   return frame_unwind_got_register (this_frame, regnum, regnum);
 }
@@ -312,19 +352,25 @@ tailcall_frame_sniffer (const struct frame_unwind *self,
 /* The initial "sniffer" whether THIS_FRAME is a bottom (callee) frame of a new
    chain to create.  Keep TAILCALL_CACHEP NULL if it did not find any chain,
    initialize it otherwise.  No tail call chain is created if there are no
-   unambiguous virtual tail call frames to report.  */
+   unambiguous virtual tail call frames to report.
+   
+   ENTRY_CFA_SP_OFFSETP is NULL if no special SP handling is possible,
+   otherwise *ENTRY_CFA_SP_OFFSETP is the number of bytes to subtract from tail
+   call frames frame base to get the SP value there - to simulate return
+   address pushed on the stack.  */
 
 void
 dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
-			       void **tailcall_cachep)
+			       void **tailcall_cachep,
+			       const LONGEST *entry_cfa_sp_offsetp)
 {
-  CORE_ADDR prev_pc = 0;	/* GCC warning.  */
+  CORE_ADDR prev_pc = 0, prev_sp = 0;	/* GCC warning.  */
+  int prev_sp_p = 0;
   CORE_ADDR this_pc, pc;
   struct gdbarch *prev_gdbarch;
   struct call_site_chain *chain = NULL;
   struct frame_info *fi;
   struct tailcall_cache *cache;
-  int pc_regnum;
   volatile struct gdb_exception except;
 
   gdb_assert (*tailcall_cachep == NULL);
@@ -334,6 +380,8 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
   /* Catch any unwinding errors.  */
   TRY_CATCH (except, RETURN_MASK_ERROR)
     {
+      int pc_regnum, sp_regnum;
+
       prev_gdbarch = frame_unwind_arch (this_frame);
       pc_regnum = gdbarch_pc_regnum (prev_gdbarch);
       if (pc_regnum == -1)
@@ -346,6 +394,14 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
 
       /* call_site_find_chain can throw an exception.  */
       chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc);
+
+      if (entry_cfa_sp_offsetp == NULL)
+	break;
+      sp_regnum = gdbarch_sp_regnum (prev_gdbarch);
+      if (sp_regnum == -1)
+	break;
+      prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum);
+      prev_sp_p = 1;
     }
   if (except.reason < 0)
     return;
@@ -362,6 +418,12 @@ dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
   cache->chain = chain;
   cache->prev_pc = prev_pc;
   cache->chain_levels = pretended_chain_levels (chain);
+  cache->prev_sp_p = prev_sp_p;
+  if (cache->prev_sp_p)
+    {
+      cache->prev_sp = prev_sp;
+      cache->entry_cfa_sp_offset = *entry_cfa_sp_offsetp;
+    }
   gdb_assert (cache->chain_levels > 0);
 }
 
--- a/gdb/dwarf2-frame-tailcall.h
+++ b/gdb/dwarf2-frame-tailcall.h
@@ -25,8 +25,14 @@ struct frame_unwind;
 
 /* The tail call frame unwinder.  */
 
-extern void dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
-					   void **tailcall_cachep);
+extern void
+  dwarf2_tailcall_sniffer_first (struct frame_info *this_frame,
+				 void **tailcall_cachep,
+				 const LONGEST *entry_cfa_sp_offsetp);
+
+extern struct value *
+  dwarf2_tailcall_prev_register_first (struct frame_info *this_frame,
+				       void **tailcall_cachep, int regnum);
 
 extern const struct frame_unwind dwarf2_tailcall_frame_unwind;
 
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -313,16 +313,6 @@ read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
   read_memory (addr, buf, len);
 }
 
-/* Helper function for execute_stack_op.  */
-
-static void
-no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, int dwarf_reg,
-			       CORE_ADDR fb_offset, CORE_ADDR deref_size)
-{
-  internal_error (__FILE__, __LINE__,
-		  _("Support for DW_OP_GNU_entry_value is unimplemented"));
-}
-
 /* Execute the required actions for both the DW_CFA_restore and
 DW_CFA_restore_extended instructions.  */
 static void
@@ -365,7 +355,7 @@ static const struct dwarf_expr_context_funcs dwarf2_frame_ctx_funcs =
   ctx_no_get_tls_address,
   ctx_no_dwarf_call,
   ctx_no_get_base_type,
-  no_push_dwarf_reg_entry_value
+  ctx_no_push_dwarf_reg_entry_value
 };
 
 static CORE_ADDR
@@ -409,7 +399,11 @@ Not implemented: computing unwound register using explicit value operator"));
 }
 
 
-static void
+/* Execute FDE program from INSN_PTR possibly up to INSN_END or up to inferior
+   PC.  Modify FS state accordingly.  Return current INSN_PTR where the
+   execution has stopped, one can resume it on the next call.  */
+
+static const gdb_byte *
 execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr,
 		     const gdb_byte *insn_end, struct gdbarch *gdbarch,
 		     CORE_ADDR pc, struct dwarf2_frame_state *fs)
@@ -692,9 +686,14 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"),
 	}
     }
 
-  /* Don't allow remember/restore between CIE and FDE programs.  */
-  dwarf2_frame_state_free_regs (fs->regs.prev);
-  fs->regs.prev = NULL;
+  if (fs->initial.reg == NULL)
+    {
+      /* Don't allow remember/restore between CIE and FDE programs.  */
+      dwarf2_frame_state_free_regs (fs->regs.prev);
+      fs->regs.prev = NULL;
+    }
+
+  return insn_ptr;
 }
 
 
@@ -1006,6 +1005,10 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
   struct dwarf2_frame_state *fs;
   struct dwarf2_fde *fde;
   volatile struct gdb_exception ex;
+  CORE_ADDR entry_pc;
+  LONGEST entry_cfa_sp_offset;
+  int entry_cfa_sp_offset_p = 0;
+  const gdb_byte *instr;
 
   if (*this_cache)
     return *this_cache;
@@ -1057,8 +1060,25 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
   fs->initial = fs->regs;
   fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs);
 
+  if (get_frame_func_if_available (this_frame, &entry_pc))
+    {
+      /* Decode the insns in the FDE up to the entry PC.  */
+      instr = execute_cfa_program (fde, fde->instructions, fde->end, gdbarch,
+				   entry_pc, fs);
+
+      if (fs->regs.cfa_how == CFA_REG_OFFSET
+	  && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg)
+	      == gdbarch_sp_regnum (gdbarch)))
+	{
+	  entry_cfa_sp_offset = fs->regs.cfa_offset;
+	  entry_cfa_sp_offset_p = 1;
+	}
+    }
+  else
+    instr = fde->instructions;
+
   /* Then decode the insns in the FDE up to our target PC.  */
-  execute_cfa_program (fde, fde->instructions, fde->end, gdbarch,
+  execute_cfa_program (fde, instr, fde->end, gdbarch,
 		       get_frame_pc (this_frame), fs);
 
   TRY_CATCH (ex, RETURN_MASK_ERROR)
@@ -1201,7 +1221,9 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"),
 
   /* Try to find a virtual tail call frames chain with bottom (callee) frame
      starting at THIS_FRAME.  */
-  dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache);
+  dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
+				 (entry_cfa_sp_offset_p
+				  ? &entry_cfa_sp_offset : NULL));
 
   return cache;
 }
@@ -1248,14 +1270,21 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache,
   CORE_ADDR addr;
   int realnum;
 
-  /* Virtual tail call frames report different values only for PC.  Non-bottom
-     frames of a virtual tail call frames chain use
+  /* Non-bottom frames of a virtual tail call frames chain use
      dwarf2_tailcall_frame_unwind unwinder so this code does not apply for
-     them.  */
-  if (cache->tailcall_cache && regnum == gdbarch_pc_regnum (gdbarch))
-    return dwarf2_tailcall_frame_unwind.prev_register (this_frame,
-						       &cache->tailcall_cache,
-						       regnum);
+     them.  If dwarf2_tailcall_prev_register_first does not have specific value
+     unwind the register, tail call frames are assumed to have the register set
+     of the top caller.  */
+  if (cache->tailcall_cache)
+    {
+      struct value *val;
+      
+      val = dwarf2_tailcall_prev_register_first (this_frame,
+						 &cache->tailcall_cache,
+						 regnum);
+      if (val)
+	return val;
+    }
 
   switch (cache->reg[regnum].how)
     {
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -371,7 +371,7 @@ dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr,
 
 /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
    by R, and return the new value of BUF.  Verify that it doesn't extend
-   past BUF_END.  */
+   past BUF_END.  R can be NULL, the constant is then only skipped.  */
 
 const gdb_byte *
 read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r)
@@ -391,13 +391,14 @@ read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r)
 	break;
       shift += 7;
     }
-  *r = result;
+  if (r)
+    *r = result;
   return buf;
 }
 
 /* Decode the signed LEB128 constant at BUF into the variable pointed to
    by R, and return the new value of BUF.  Verify that it doesn't extend
-   past BUF_END.  */
+   past BUF_END.  R can be NULL, the constant is then only skipped.  */
 
 const gdb_byte *
 read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r)
@@ -420,7 +421,8 @@ read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r)
   if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
     result |= -(((LONGEST) 1) << shift);
 
-  *r = result;
+  if (r)
+    *r = result;
   return buf;
 }
 
@@ -498,10 +500,19 @@ dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end)
       return *buf - DW_OP_reg0;
     }
 
-  if (*buf != DW_OP_regx)
+  if (*buf == DW_OP_GNU_regval_type)
+    {
+      buf++;
+      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+      buf = read_uleb128 (buf, buf_end, NULL);
+    }
+  else if (*buf == DW_OP_regx)
+    {
+      buf++;
+      buf = read_uleb128 (buf, buf_end, &dwarf_reg);
+    }
+  else
     return -1;
-  buf++;
-  buf = read_uleb128 (buf, buf_end, &dwarf_reg);
   if (buf != buf_end || (int) dwarf_reg != dwarf_reg)
     return -1;
   return dwarf_reg;
@@ -531,7 +542,7 @@ dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf, const gdb_byte *buf_end,
       buf++;
       buf = read_uleb128 (buf, buf_end, &dwarf_reg);
       if ((int) dwarf_reg != dwarf_reg)
-	return -1;
+       return -1;
     }
   else
     return -1;
@@ -552,7 +563,7 @@ dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf, const gdb_byte *buf_end,
     {
       buf++;
       if (buf >= buf_end)
-	return -1;
+       return -1;
       *deref_size_return = *buf++;
     }
   else
@@ -564,6 +575,30 @@ dwarf_block_to_dwarf_reg_deref (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.  */
@@ -585,7 +620,7 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
   else
     {
       if (*buf != DW_OP_bregx)
-	return 0;
+       return 0;
       buf++;
       buf = read_uleb128 (buf, buf_end, &dwarf_reg);
     }
@@ -602,30 +637,6 @@ dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
   return 1;
 }
 
-/* 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;
-}
-
 /* The engine for the expression evaluator.  Using the context in CTX,
    evaluate the expression between OP_PTR and OP_END.  */
 
@@ -1346,7 +1357,8 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	      {
 		op_ptr += len;
 		ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg,
-							0 /* unused */, -1);
+							0 /* unused */,
+							-1 /* deref_size */);
 		goto no_push;
 	      }
 
@@ -1511,6 +1523,18 @@ ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die)
   error (_("Support for typed DWARF is not supported in this context"));
 }
 
+/* Stub dwarf_expr_context_funcs.push_dwarf_block_entry_value
+   implementation.  */
+
+void
+ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
+				   int dwarf_reg, CORE_ADDR fb_offset,
+				   int deref_size)
+{
+  internal_error (__FILE__, __LINE__,
+		  _("Support for DW_OP_GNU_entry_value is unimplemented"));
+}
+
 void
 _initialize_dwarf2expr (void)
 {
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -71,7 +71,7 @@ struct dwarf_expr_context_funcs
      DW_AT_GNU_call_site_data_value instead of DW_AT_GNU_call_site_value.  */
   void (*push_dwarf_reg_entry_value) (struct dwarf_expr_context *ctx,
 				      int dwarf_reg, CORE_ADDR fb_offset,
-				      CORE_ADDR deref_size);
+				      int deref_size);
 
 #if 0
   /* Not yet implemented.  */
@@ -274,18 +274,21 @@ CORE_ADDR ctx_no_get_frame_pc (void *baton);
 CORE_ADDR ctx_no_get_tls_address (void *baton, CORE_ADDR offset);
 void ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset);
 struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die);
+void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
+					int dwarf_reg, CORE_ADDR fb_offset,
+					int deref_size);
 
 int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end);
 
-int dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf,
-			      const gdb_byte *buf_end,
-			      CORE_ADDR *sp_offset_return);
+int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf,
+				    const gdb_byte *buf_end,
+				    CORE_ADDR *deref_size_return);
 
 int dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end,
 			      CORE_ADDR *fb_offset_return);
 
-int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf,
-				    const gdb_byte *buf_end,
-				    CORE_ADDR *deref_size_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 */
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -332,7 +332,7 @@ show_tailcall_debug (struct ui_file *file, int from_tty,
 
 /* Find DW_TAG_GNU_call_site's DW_AT_GNU_call_site_target address.
    CALLER_FRAME (for registers) can be NULL if it is not known.  This function
-   always returns valid address or it throws NOT_FOUND_ERROR.  */
+   always returns valid address or it throws NO_ENTRY_VALUE_ERROR.  */
 
 static CORE_ADDR
 call_site_to_target_addr (struct call_site *call_site,
@@ -349,10 +349,10 @@ call_site_to_target_addr (struct call_site *call_site,
 
 	dwarf_block = FIELD_DWARF_BLOCK (call_site->target);
 	if (dwarf_block == NULL)
-	  throw_error (NOT_FOUND_ERROR,
+	  throw_error (NO_ENTRY_VALUE_ERROR,
 		       _("DW_AT_GNU_call_site_target is not specified"));
 	if (caller_frame == NULL)
-	  throw_error (NOT_FOUND_ERROR,
+	  throw_error (NO_ENTRY_VALUE_ERROR,
 		       _("DW_AT_GNU_call_site_target DWARF block resolving "
 			 "requires known frame which is currently not "
 			 "available"));
@@ -377,7 +377,7 @@ call_site_to_target_addr (struct call_site *call_site,
 	physname = FIELD_STATIC_PHYSNAME (call_site->target);
 	msym = lookup_minimal_symbol_text (physname, NULL);
 	if (msym == NULL)
-	  throw_error (NOT_FOUND_ERROR,
+	  throw_error (NO_ENTRY_VALUE_ERROR,
 		       _("Cannot find function \"%s\" for a call site target"),
 		       physname);
 	return SYMBOL_VALUE_ADDRESS (msym);
@@ -392,8 +392,8 @@ call_site_to_target_addr (struct call_site *call_site,
 }
 
 /* Convert function entry point exact address ADDR to the function which is
-   compliant with TAIL_CALL_LIST_COMPLETE condition.  Throw NOT_FOUND_ERROR
-   otherwise.  */
+   compliant with TAIL_CALL_LIST_COMPLETE condition.  Throw
+   NO_ENTRY_VALUE_ERROR otherwise.  */
 
 static struct symbol *
 func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
@@ -402,7 +402,7 @@ func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
   struct type *type;
 
   if (sym == NULL || BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) != addr)
-    throw_error (NOT_FOUND_ERROR,
+    throw_error (NO_ENTRY_VALUE_ERROR,
 		 _("DW_TAG_GNU_call_site resolving failed to find function "
 		   "name for address %s"),
 		 paddress (gdbarch, addr));
@@ -417,23 +417,9 @@ func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
 /* Define VEC (CORE_ADDR) functions.  */
 DEF_VEC_I (CORE_ADDR);
 
-/* Cleanup helper to free VEC (CORE_ADDR) **.  */
-
-static void
-free_addr_vecp (void *arg)
-{
-  VEC (CORE_ADDR) **vecp = arg;
-
-  if (*vecp)
-    {
-      VEC_free (CORE_ADDR, *vecp);
-      *vecp = NULL;
-    }
-}
-
 /* Verify function with entry point exact address ADDR can never call itself
-   via its tail calls (incl. transitively).  Throw NOT_FOUND_ERROR if it can
-   call itself via tail calls.
+   via its tail calls (incl. transitively).  Throw NO_ENTRY_VALUE_ERROR if it
+   can call itself via tail calls.
 
    If a funtion can tail call itself its entry value based parameters are
    unreliable.  There is no verification whether the value of some/all
@@ -461,7 +447,7 @@ func_verify_no_selftailcall (struct gdbarch *gdbarch, CORE_ADDR verify_addr)
 				    NULL);
   make_cleanup_htab_delete (addr_hash);
 
-  make_cleanup (free_addr_vecp, &todo);
+  make_cleanup (VEC_cleanup (CORE_ADDR), &todo);
 
   VEC_safe_push (CORE_ADDR, todo, verify_addr);
   while (!VEC_empty (CORE_ADDR, todo))
@@ -488,9 +474,10 @@ func_verify_no_selftailcall (struct gdbarch *gdbarch, CORE_ADDR verify_addr)
 	      struct minimal_symbol *msym;
 	      
 	      msym = lookup_minimal_symbol_by_pc (verify_addr);
-	      throw_error (NOT_FOUND_ERROR, _("DW_OP_GNU_entry_value resolving "
-					      "has found function \"%s\" at %s "
-					      "can call itself via tail calls"),
+	      throw_error (NO_ENTRY_VALUE_ERROR,
+			   _("DW_OP_GNU_entry_value resolving has found "
+			     "function \"%s\" at %s can call itself via tail "
+			     "calls"),
 			   msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym),
 			   paddress (gdbarch, verify_addr));
 	    }
@@ -625,26 +612,12 @@ chain_candidate (struct gdbarch *gdbarch, struct call_site_chain **resultp,
   gdb_assert (result->callers + result->callees < result->length);
 }
 
-/* Cleanup helper to free VEC (call_sitep) **.  */
-
-static void
-free_call_sitep_vecp (void *arg)
-{
-  VEC (call_sitep) **vecp = arg;
-
-  if (*vecp)
-    {
-      VEC_free (call_sitep, *vecp);
-      *vecp = NULL;
-    }
-}
-
 /* Create and return call_site_chain for CALLER_PC and CALLEE_PC.  All the
    assumed frames between them use GDBARCH.  Use depth first search so we can
    keep single CHAIN of call_site's back to CALLER_PC.  Function recursion
    would have needless GDB stack overhead.  Caller is responsible for xfree of
    the returned result.  Any unreliability results in thrown
-   NOT_FOUND_ERROR.  */
+   NO_ENTRY_VALUE_ERROR.  */
 
 static struct call_site_chain *
 call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
@@ -668,7 +641,7 @@ call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
   /* We are not interested in the specific PC inside the callee function.  */
   callee_pc = get_pc_function_start (callee_pc);
   if (callee_pc == 0)
-    throw_error (NOT_FOUND_ERROR, _("Unable to find function for PC %s"),
+    throw_error (NO_ENTRY_VALUE_ERROR, _("Unable to find function for PC %s"),
 		 paddress (gdbarch, callee_pc));
 
   back_to_retval = make_cleanup (free_current_contents, &retval);
@@ -680,7 +653,7 @@ call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
 				    NULL);
   make_cleanup_htab_delete (addr_hash);
 
-  make_cleanup (free_call_sitep_vecp, &chain);
+  make_cleanup (VEC_cleanup (call_sitep), &chain);
 
   /* Do not push CALL_SITE to CHAIN.  Push there only the first tail call site at
      the target's function.  All the possible tail call sites in the target's
@@ -766,7 +739,7 @@ call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
       
       msym_caller = lookup_minimal_symbol_by_pc (caller_pc);
       msym_callee = lookup_minimal_symbol_by_pc (callee_pc);
-      throw_error (NOT_FOUND_ERROR,
+      throw_error (NO_ENTRY_VALUE_ERROR,
 		   _("There are no unambiguously determinable intermediate "
 		     "callers or callees between caller function \"%s\" at %s "
 		     "and callee function \"%s\" at %s"),
@@ -801,7 +774,7 @@ call_site_find_chain (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
     }
   if (e.reason < 0)
     {
-      if (e.error == NOT_FOUND_ERROR)
+      if (e.error == NO_ENTRY_VALUE_ERROR)
 	{
 	  if (info_verbose)
 	    exception_print (gdb_stdout, e);
@@ -818,15 +791,17 @@ call_site_find_chain (struct gdbarch *gdbarch, CORE_ADDR caller_pc,
    callee.  See DWARF_REG and FB_OFFSET description at struct
    dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
 
-   Function always returns non-NULL, it throws NOT_FOUND_ERROR otherwise.  */
+   Function always returns non-NULL, it throws NO_ENTRY_VALUE_ERROR
+   otherwise.  */
 
 static struct call_site_parameter *
-dwarf_expr_dwarf_reg_entry_value (struct frame_info *frame, int dwarf_reg,
-				  CORE_ADDR fb_offset)
+dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg,
+				   CORE_ADDR fb_offset,
+				   struct dwarf2_per_cu_data **per_cu_return)
 {
   CORE_ADDR func_addr = get_frame_func (frame);
   CORE_ADDR caller_pc;
-  struct gdbarch *caller_gdbarch = frame_unwind_arch (frame);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   struct frame_info *caller_frame = get_prev_frame (frame);
   struct call_site *call_site;
   int iparams;
@@ -835,13 +810,27 @@ dwarf_expr_dwarf_reg_entry_value (struct frame_info *frame, int dwarf_reg,
   struct call_site_parameter *parameter;
   CORE_ADDR target_addr;
 
+  if (gdbarch != frame_unwind_arch (frame))
+    {
+      struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (func_addr);
+      struct gdbarch *caller_gdbarch = frame_unwind_arch (frame);
+
+      throw_error (NO_ENTRY_VALUE_ERROR,
+		   _("DW_OP_GNU_entry_value resolving callee gdbarch %s "
+		     "(of %s (%s)) does not match caller gdbarch %s"),
+		   gdbarch_bfd_arch_info (gdbarch)->printable_name,
+		   paddress (gdbarch, func_addr),
+		   msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym),
+		   gdbarch_bfd_arch_info (caller_gdbarch)->printable_name);
+    }
+
   if (caller_frame == NULL)
     {
       struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (func_addr);
 
-      throw_error (NOT_FOUND_ERROR, _("DW_OP_GNU_entry_value resolving "
-				      "requires caller of %s (%s)"),
-		   paddress (get_frame_arch (frame), func_addr),
+      throw_error (NO_ENTRY_VALUE_ERROR, _("DW_OP_GNU_entry_value resolving "
+					   "requires caller of %s (%s)"),
+		   paddress (gdbarch, func_addr),
 		   msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym));
     }
   caller_pc = get_frame_pc (caller_frame);
@@ -852,11 +841,11 @@ dwarf_expr_dwarf_reg_entry_value (struct frame_info *frame, int dwarf_reg,
       struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (caller_pc);
 
       /* DW_TAG_gnu_call_site will be missing just if GCC could not determine
-	 the call target.  So do not complain more than NOT_FOUND_ERROR.  */
-      throw_error (NOT_FOUND_ERROR,
+	 the call target.  */
+      throw_error (NO_ENTRY_VALUE_ERROR,
 		   _("DW_OP_GNU_entry_value resolving cannot find "
 		     "DW_TAG_GNU_call_site %s in %s"),
-		   paddress (caller_gdbarch, caller_pc),
+		   paddress (gdbarch, caller_pc),
 		   msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym));
     }
 
@@ -867,19 +856,19 @@ dwarf_expr_dwarf_reg_entry_value (struct frame_info *frame, int dwarf_reg,
 
       target_msym = lookup_minimal_symbol_by_pc (target_addr);
       func_msym = lookup_minimal_symbol_by_pc (func_addr);
-      throw_error (NOT_FOUND_ERROR,
+      throw_error (NO_ENTRY_VALUE_ERROR,
 		   _("DW_OP_GNU_entry_value resolving expects callee %s at %s "
 		     "but the called frame is for %s at %s"),
 		   (target_msym == NULL ? "???"
 					: SYMBOL_PRINT_NAME (target_msym)),
-		   paddress (caller_gdbarch, target_addr),
+		   paddress (gdbarch, target_addr),
 		   func_msym == NULL ? "???" : SYMBOL_PRINT_NAME (func_msym),
-		   paddress (caller_gdbarch, func_addr));
+		   paddress (gdbarch, func_addr));
     }
 
   /* No entry value based parameters would be reliable if this function can
      call itself via tail calls.  */
-  func_verify_no_selftailcall (caller_gdbarch, func_addr);
+  func_verify_no_selftailcall (gdbarch, func_addr);
 
   for (iparams = 0; iparams < call_site->parameter_count; iparams++)
     {
@@ -897,103 +886,94 @@ dwarf_expr_dwarf_reg_entry_value (struct frame_info *frame, int dwarf_reg,
       struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (caller_pc);
 
       /* DW_TAG_GNU_call_site_parameter will be missing just if GCC could not
-	 determine its value.  So do not complain more than NOT_FOUND_ERROR.  */
-      throw_error (NOT_FOUND_ERROR, _("Cannot find DWARF reg%d/fbreg(%s) at "
-				      "DW_TAG_GNU_call_site %s at %s"),
-		   dwarf_reg, paddress (caller_gdbarch, fb_offset),
-		   paddress (caller_gdbarch, caller_pc),
+	 determine its value.  */
+      throw_error (NO_ENTRY_VALUE_ERROR, _("Cannot find matching parameter "
+					   "at DW_TAG_GNU_call_site %s at %s"),
+		   paddress (gdbarch, caller_pc),
 		   msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); 
     }
 
+  *per_cu_return = call_site->per_cu;
   return parameter;
 }
 
-/* Return dwarf2_locexpr_baton for PARAMETER matching DEREF_SIZE.  If
-   DEREF_SIZE is -1, return the normal DW_AT_GNU_call_site_value block.
-   Otherwise return the DW_AT_GNU_call_site_data_value (dereferenced) block.
-
-   Function always returns non-NULL, it throws NOT_FOUND_ERROR if DEREF_SIZE
-   was not -1 and the DW_AT_GNU_call_site_data_value block is not defined by
-   PARAMETER.  */
-
-static struct dwarf2_locexpr_baton *
-dwarf_entry_parameter_to_block (struct call_site_parameter *parameter,
-				CORE_ADDR deref_size)
-{
-
-  if (deref_size == -1)
-    {
-      gdb_assert (parameter->call_site_value != NULL);
-      return parameter->call_site_value;
-    }
-
-  /* DEREF_SIZE size is not verified here.  */
-
-  if (parameter->call_site_data_value == NULL)
-    throw_error (NOT_FOUND_ERROR,
-		 _("Cannot resolve DW_AT_GNU_call_site_data_value"));
-
-  return parameter->call_site_data_value;
-}
-
-/* Return value for PARAMETER matching DEREF_SIZE, see
-   dwarf_entry_parameter_to_block for the description of these parameters.
+/* Return value for PARAMETER matching DEREF_SIZE.  If DEREF_SIZE is -1, return
+   the normal DW_AT_GNU_call_site_value block.  Otherwise return the
+   DW_AT_GNU_call_site_data_value (dereferenced) block.
 
    TYPE and CALLER_FRAME specify how to evaluate the DWARF block into returned
    struct value.
 
    Function always returns non-NULL, non-optimized out value.  It throws
-   NOT_FOUND_ERROR if it cannot resolve the value for any reason.  */
+   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,
 				CORE_ADDR deref_size, struct type *type,
-				struct frame_info *caller_frame)
+				struct frame_info *caller_frame,
+				struct dwarf2_per_cu_data *per_cu)
 {
-  struct dwarf2_locexpr_baton *dwarf_block;
+  const gdb_byte *data_src;
   gdb_byte *data;
+  size_t size;
 
-  dwarf_block = dwarf_entry_parameter_to_block (parameter, deref_size);
+  data_src = deref_size == -1 ? parameter->value : parameter->data_value;
+  size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
+
+  /* DEREF_SIZE size is not verified here.  */
+  if (data_src == NULL)
+    throw_error (NO_ENTRY_VALUE_ERROR,
+		 _("Cannot resolve DW_AT_GNU_call_site_data_value"));
 
   /* DW_AT_GNU_call_site_value is a DWARF expression, not a DWARF
-     location.  */
-  data = alloca (dwarf_block->size + 1);
-  memcpy (data, dwarf_block->data, dwarf_block->size);
-  data[dwarf_block->size] = DW_OP_stack_value;
+     location.  Postprocessing of DWARF_VALUE_MEMORY would lose the type from
+     DWARF block.  */
+  data = alloca (size + 1);
+  memcpy (data, data_src, size);
+  data[size] = DW_OP_stack_value;
 
-  return dwarf2_evaluate_loc_desc (type, caller_frame, data,
-				   dwarf_block->size + 1, dwarf_block->per_cu);
+  return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu);
 }
 
-/* Execute DWARF_BLOCK for caller of the CTX's frame.  CTX must be of
-   dwarf_expr_ctx_funcs kind.  See DWARF_REG, FB_OFFSET and DEREF_SIZE
-   description at struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
+/* Execute call_site_parameter's DWARF block matching DEREF_SIZE 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.
 
-   The CTX caller can be from a different CU - per_cu_dwarf_call is simpler as
-   it does not support cross-CU DWARF executions.  */
+   The CTX caller can be from a different CU - per_cu_dwarf_call implementation
+   can be more simple as it does not support cross-CU DWARF executions.  */
 
 static void
 dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
 				       int dwarf_reg, CORE_ADDR fb_offset,
-				       CORE_ADDR deref_size)
+				       int deref_size)
 {
   struct dwarf_expr_baton *debaton;
   struct frame_info *frame, *caller_frame;
-  struct dwarf2_locexpr_baton *dwarf_block;
+  struct dwarf2_per_cu_data *caller_per_cu;
   struct dwarf_expr_baton baton_local;
   struct dwarf_expr_context saved_ctx;
   struct call_site_parameter *parameter;
+  const gdb_byte *data_src;
+  size_t size;
 
   gdb_assert (ctx->funcs == &dwarf_expr_ctx_funcs);
   debaton = ctx->baton;
   frame = debaton->frame;
   caller_frame = get_prev_frame (frame);
 
-  parameter = dwarf_expr_dwarf_reg_entry_value (frame, dwarf_reg, fb_offset);
-  dwarf_block = dwarf_entry_parameter_to_block (parameter, deref_size);
+  parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset,
+						 &caller_per_cu);
+  data_src = deref_size == -1 ? parameter->value : parameter->data_value;
+  size = deref_size == -1 ? parameter->value_size : parameter->data_value_size;
+
+  /* DEREF_SIZE size is not verified here.  */
+  if (data_src == NULL)
+    throw_error (NO_ENTRY_VALUE_ERROR,
+		 _("Cannot resolve DW_AT_GNU_call_site_data_value"));
 
   baton_local.frame = caller_frame;
-  baton_local.per_cu = dwarf_block->per_cu;
+  baton_local.per_cu = caller_per_cu;
 
   saved_ctx.gdbarch = ctx->gdbarch;
   saved_ctx.addr_size = ctx->addr_size;
@@ -1004,7 +984,7 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
   ctx->offset = dwarf2_per_cu_text_offset (baton_local.per_cu);
   ctx->baton = &baton_local;
 
-  dwarf_expr_eval (ctx, dwarf_block->data, dwarf_block->size);
+  dwarf_expr_eval (ctx, data_src, size);
 
   ctx->gdbarch = saved_ctx.gdbarch;
   ctx->addr_size = saved_ctx.addr_size;
@@ -1012,6 +992,151 @@ dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
   ctx->baton = saved_ctx.baton;
 }
 
+/* VALUE must be of type lval_computed with entry_data_value_funcs.  Perform
+   the indirect method on it, that is use its stored target value, the sole
+   purpose of entry_data_value_funcs..  */
+
+static struct value *
+entry_data_value_coerce_ref (const struct value *value)
+{
+  struct type *checked_type = check_typedef (value_type (value));
+  struct value *target_val;
+
+  if (TYPE_CODE (checked_type) != TYPE_CODE_REF)
+    return NULL;
+
+  target_val = value_computed_closure (value);
+  value_incref (target_val);
+  return target_val;
+}
+
+/* Implement copy_closure.  */
+
+static void *
+entry_data_value_copy_closure (const struct value *v)
+{
+  struct value *target_val = value_computed_closure (v);
+
+  value_incref (target_val);
+  return target_val;
+}
+
+/* Implement free_closure.  */
+
+static void
+entry_data_value_free_closure (struct value *v)
+{
+  struct value *target_val = value_computed_closure (v);
+
+  value_free (target_val);
+}
+
+/* Vector for methods for an entry value reference where the referenced value
+   is stored in the caller.  On the first dereference use
+   DW_AT_GNU_call_site_data_value in the caller.  */
+
+static const struct lval_funcs entry_data_value_funcs =
+{
+  NULL,	/* read */
+  NULL,	/* write */
+  NULL,	/* check_validity */
+  NULL,	/* check_any_valid */
+  NULL,	/* indirect */
+  entry_data_value_coerce_ref,
+  NULL,	/* check_synthetic_pointer */
+  entry_data_value_copy_closure,
+  entry_data_value_free_closure
+};
+
+/* 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 type *checked_type = check_typedef (type);
+  struct type *target_type = TYPE_TARGET_TYPE (checked_type);
+  struct frame_info *caller_frame = get_prev_frame (frame);
+  struct value *outer_val, *target_val, *val;
+  struct call_site_parameter *parameter;
+  struct dwarf2_per_cu_data *caller_per_cu;
+  CORE_ADDR addr;
+
+  parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset,
+						 &caller_per_cu);
+
+  outer_val = dwarf_entry_parameter_to_value (parameter, -1 /* deref_size */,
+					      type, caller_frame,
+					      caller_per_cu);
+
+  /* Check if DW_AT_GNU_call_site_data_value cannot be used.  If it should be
+     used and it is not available do not fall back to OUTER_VAL - dereferencing
+     TYPE_CODE_REF with non-entry data value would give current value - not the
+     entry value.  */
+
+  if (TYPE_CODE (checked_type) != TYPE_CODE_REF
+      || TYPE_TARGET_TYPE (checked_type) == NULL)
+    return outer_val;
+
+  target_val = dwarf_entry_parameter_to_value (parameter,
+					       TYPE_LENGTH (target_type),
+					       target_type, caller_frame,
+					       caller_per_cu);
+
+  /* value_as_address dereferences TYPE_CODE_REF.  */
+  addr = extract_typed_address (value_contents (outer_val), checked_type);
+
+  /* The target entry value has artificial address of the entry value
+     reference.  */
+  VALUE_LVAL (target_val) = lval_memory;
+  set_value_address (target_val, addr);
+
+  release_value (target_val);
+  val = allocate_computed_value (type, &entry_data_value_funcs,
+				 target_val /* closure */);
+
+  /* Copy the referencing pointer to the new computed value.  */
+  memcpy (value_contents_raw (val), value_contents_raw (outer_val), TYPE_LENGTH (checked_type));
+  set_value_lazy (val, 0);
+
+  return val;
+}
+
+/* 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.  */
@@ -1780,6 +1905,7 @@ static const struct lval_funcs pieced_value_funcs = {
   check_pieced_value_validity,
   check_pieced_value_invalid,
   indirect_pieced_value,
+  NULL,	/* coerce_ref */
   check_pieced_synthetic_pointer,
   copy_pieced_value_closure,
   free_pieced_value_closure
@@ -1853,19 +1979,18 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
     }
   if (ex.reason < 0)
     {
-      do_cleanups (old_chain);
-
       if (ex.error == NOT_AVAILABLE_ERROR)
 	{
+	  do_cleanups (old_chain);
 	  retval = allocate_value (type);
 	  mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type));
 	  return retval;
 	}
-      else if (ex.error == NOT_FOUND_ERROR)
+      else if (ex.error == NO_ENTRY_VALUE_ERROR)
 	{
 	  if (info_verbose)
 	    exception_print (gdb_stdout, ex);
-
+	  do_cleanups (old_chain);
 	  return allocate_optimized_out_value (type);
 	}
       else
@@ -2098,8 +2223,8 @@ needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
 /* DW_OP_GNU_entry_value accesses require a caller, therefore a frame.  */
 
 static void
-needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, int dwarf_reg,
-			     CORE_ADDR fb_offset, CORE_ADDR deref_size)
+needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
+			     int dwarf_reg, CORE_ADDR fb_offset, int deref_size)
 {
   struct needs_frame_baton *nf_baton = ctx->baton;
 
@@ -2934,6 +3059,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)
@@ -3585,7 +3723,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
    evaluator.  */
 const struct symbol_computed_ops dwarf2_locexpr_funcs = {
   locexpr_read_variable,
-  NULL,				/* read_variable_at_entry */
+  locexpr_read_variable_at_entry,
   locexpr_read_needs_frame,
   locexpr_describe_location,
   locexpr_tracepoint_var_ref
@@ -3616,156 +3754,21 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
   return val;
 }
 
-/* VALUE must be of type lval_computed with entry_data_value_funcs.  Perform
-   the indirect method on it, that is use its stored target value, the sole
-   purpose of entry_data_value_funcs..  */
-
-struct value *
-entry_data_value_indirect (struct value *value)
-{
-  struct type *checked_type = check_typedef (value_type (value));
-  struct value *target_val = value_computed_closure (value);
-
-  gdb_assert (TYPE_CODE (checked_type) == TYPE_CODE_PTR
-	      || TYPE_CODE (checked_type) == TYPE_CODE_REF);
-
-  value_incref (target_val);
-  return target_val;
-}
-
-/* Implement copy_closure.  */
-
-static void *
-entry_data_value_copy_closure (const struct value *v)
-{
-  struct value *target_val = value_computed_closure (v);
-
-  value_incref (target_val);
-  return target_val;
-}
-
-/* Implement free_closure.  */
-
-static void
-entry_data_value_free_closure (struct value *v)
-{
-  struct value *target_val = value_computed_closure (v);
-
-  value_free (target_val);
-}
-
-/* Vector for methods for an entry value reference where the referenced value
-   is stored in the caller.  On the first dereference use
-   DW_AT_GNU_call_site_data_value in the caller.  */
-
-static struct lval_funcs entry_data_value_funcs =
-{
-  NULL,	/* read */
-  NULL,	/* write */
-  NULL,	/* check_validity */
-  NULL,	/* check_any_valid */
-  entry_data_value_indirect,
-  NULL,	/* check_synthetic_pointer */
-  entry_data_value_copy_closure,
-  entry_data_value_free_closure
-};
-
-/* Return value of parameter of TYPE at (callee) FRAME which at function entry
-   point.  Parameter has been passed in DWARF_REG or FB_OFFSET, see their
-   description at struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value.
-
-   Function always returns non-NULL, non-optimized out value.  It throws
-   NOT_FOUND_ERROR if it cannot resolve the value for any reason.  */
-
-static struct value *
-value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame,
-			  int dwarf_reg, CORE_ADDR fb_offset)
-{
-  struct type *checked_type = check_typedef (type);
-  struct frame_info *caller_frame = get_prev_frame (frame);
-  struct value *outer_val;
-  struct call_site_parameter *parameter;
-
-  parameter = dwarf_expr_dwarf_reg_entry_value (frame, dwarf_reg, fb_offset);
-
-  outer_val = dwarf_entry_parameter_to_value (parameter, -1 /* deref_size */,
-					      type, caller_frame);
-
-  /* Check if DW_AT_GNU_call_site_data_value cannot be used.  */
-
-  if ((TYPE_CODE (checked_type) == TYPE_CODE_PTR
-       || TYPE_CODE (checked_type) == TYPE_CODE_REF)
-      && TYPE_TARGET_TYPE (checked_type) != NULL)
-    {
-      struct type *target_type = TYPE_TARGET_TYPE (checked_type);
-      volatile struct gdb_exception e;
-      struct value *target_val;
-
-      TRY_CATCH (e, RETURN_MASK_ERROR)
-	{
-	  int target_length = TYPE_LENGTH (target_type);
-
-	  target_val = dwarf_entry_parameter_to_value (parameter, target_length,
-						       target_type,
-						       caller_frame);
-	}
-      if (e.reason < 0)
-	{
-	  if (e.error == NOT_FOUND_ERROR)
-	    {
-	      if (info_verbose)
-		exception_print (gdb_stdout, e);
-	    }
-	  else
-	    throw_exception (e);
-	}
-      else
-	{
-	  CORE_ADDR addr;
-	  struct value *val;
-
-	  /* value_as_address dereferences TYPE_CODE_REF.  */
-	  addr = extract_typed_address (value_contents (outer_val),
-					checked_type);
-
-	  /* The target entry value has artificial address of the entry value
-	     reference.  */
-	  VALUE_LVAL (target_val) = lval_memory;
-	  set_value_address (target_val, addr);
-
-	  release_value (target_val);
-	  val = allocate_computed_value (type, &entry_data_value_funcs,
-					 target_val /* closure */);
-
-	  /* Copy the referencing pointer to the new computed value.  */
-	  memcpy (value_contents_raw (val), value_contents_raw (outer_val),
-		  TYPE_LENGTH (checked_type));
-	  set_value_lazy (val, 0);
-
-	  return val;
-	}
-    }
-
-  return outer_val;
-}
-
 /* Read variable SYMBOL like loclist_read_variable at (callee) FRAME's function
-   entry.  SYMBOL should be a function parameter, otherwise NOT_FOUND_ERROR
+   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 NOT_FOUND_ERROR if
-   it cannot resolve the parameter for any reason.  */
+   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);
-  struct value *val;
   const gdb_byte *data;
   size_t size;
-  int dwarf_reg;
-  CORE_ADDR deref_size, pc, fb_offset;
+  CORE_ADDR pc;
 
   if (frame == NULL || !get_frame_func_if_available (frame, &pc))
     return allocate_optimized_out_value (SYMBOL_TYPE (symbol));
@@ -3774,17 +3777,7 @@ loclist_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame)
   if (data == NULL)
     return allocate_optimized_out_value (SYMBOL_TYPE (symbol));
 
-  dwarf_reg = dwarf_block_to_dwarf_reg (data, data + size);
-  if (dwarf_reg != -1)
-    return value_of_dwarf_reg_entry (SYMBOL_TYPE (symbol), frame, dwarf_reg,
-				     0 /* unused */);
-
-  if (dwarf_block_to_fb_offset (data, data + size, &fb_offset))
-    return value_of_dwarf_reg_entry (SYMBOL_TYPE (symbol), frame, -1,
-				     fb_offset);
-
-  error (_("DWARF-2 expression error: DW_OP_GNU_entry_value is supported only "
-           "for single DW_OP_reg* or for DW_OP_fbreg(*)"));
+  return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, data, size);
 }
 
 /* Return non-zero iff we need a frame to evaluate SYMBOL.  */
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -6127,24 +6127,6 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   using_directives = new->using_directives;
 }
 
-/* Allocate a copy of BLK on CU's objfile_obstack (not comp_unit_obstack),
-   including a copy of the BLK DWARF code.  */
-
-static struct dwarf2_locexpr_baton *
-dlbaton_obstack_copy (const struct dwarf_block *blk, struct dwarf2_cu *cu)
-{
-  struct objfile *objfile = cu->objfile;
-  struct dwarf2_locexpr_baton *dlbaton;
-
-  dlbaton = obstack_alloc (&objfile->objfile_obstack, sizeof (*dlbaton));
-  dlbaton->data = obstack_copy (&objfile->objfile_obstack, blk->data,
-				blk->size);
-  dlbaton->size = blk->size;
-  dlbaton->per_cu = cu->per_cu;
-
-  return dlbaton;
-}
-
 /* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab.  */
 
 static void
@@ -6267,8 +6249,16 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (!attr || (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0))
     /* Keep NULL DWARF_BLOCK.  */;
   else if (attr_form_is_block (attr))
-    SET_FIELD_DWARF_BLOCK (call_site->target,
-			   dlbaton_obstack_copy (DW_BLOCK (attr), cu));
+    {
+      struct dwarf2_locexpr_baton *dlbaton;
+
+      dlbaton = obstack_alloc (&objfile->objfile_obstack, sizeof (*dlbaton));
+      dlbaton->data = DW_BLOCK (attr)->data;
+      dlbaton->size = DW_BLOCK (attr)->size;
+      dlbaton->per_cu = cu->per_cu;
+
+      SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton);
+    }
   else if (is_ref_attr (attr))
     {
       struct objfile *objfile = cu->objfile;
@@ -6310,6 +6300,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 		 "block nor reference, for DIE 0x%x [in module %s]"),
 	       die->offset, cu->objfile->name);
 
+  call_site->per_cu = cu->per_cu;
+
   for (child_die = die->child;
        child_die && child_die->tag;
        child_die = sibling_die (child_die))
@@ -6346,9 +6338,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 					&parameter->fb_offset))
 	{
 	  complaint (&symfile_complaints,
-		     _("Only single DW_OP_reg is supported for DW_FORM_block* "
-		       "DW_AT_location for DW_TAG_GNU_call_site "
-		       "child DIE 0x%x [in module %s]"),
+		     _("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);
 	  continue;
 	}
@@ -6362,10 +6354,12 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 		     child_die->offset, cu->objfile->name);
 	  continue;
 	}
-      parameter->call_site_value = dlbaton_obstack_copy (DW_BLOCK (attr), cu);
+      parameter->value = DW_BLOCK (attr)->data;
+      parameter->value_size = DW_BLOCK (attr)->size;
 
       /* Parameters are not pre-cleared by memset above.  */
-      parameter->call_site_data_value = NULL;
+      parameter->data_value = NULL;
+      parameter->data_value_size = 0;
       call_site->parameter_count++;
 
       attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
@@ -6377,8 +6371,10 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
 			 "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
 		       child_die->offset, cu->objfile->name);
 	  else
-	    parameter->call_site_data_value
-	      = dlbaton_obstack_copy (DW_BLOCK (attr), cu);
+	    {
+	      parameter->data_value = DW_BLOCK (attr)->data;
+	      parameter->data_value_size = DW_BLOCK (attr)->size;
+	    }
 	}
     }
 }
@@ -16599,14 +16595,6 @@ write_one_signatured_type (void **slot, void *d)
   return 1;
 }
 
-/* A cleanup function for an htab_t.  */
-
-static void
-cleanup_htab (void *arg)
-{
-  htab_delete (arg);
-}
-
 /* Create an index file for OBJFILE in the directory DIR.  */
 
 static void
@@ -16663,7 +16651,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
 
   psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer,
 				  NULL, xcalloc, xfree);
-  make_cleanup (cleanup_htab, psyms_seen);
+  make_cleanup_htab_delete (psyms_seen);
 
   /* While we're scanning CU's create a table that maps a psymtab pointer
      (which is what addrmap records) to its index (which is what is recorded
@@ -16673,7 +16661,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
 				     hash_psymtab_cu_index,
 				     eq_psymtab_cu_index,
 				     NULL, xcalloc, xfree);
-  make_cleanup (cleanup_htab, cu_index_htab);
+  make_cleanup_htab_delete (cu_index_htab);
   psymtab_cu_index_map = (struct psymtab_cu_index_map *)
     xmalloc (sizeof (struct psymtab_cu_index_map)
 	     * dwarf2_per_objfile->n_comp_units);
--- a/gdb/exceptions.h
+++ b/gdb/exceptions.h
@@ -85,6 +85,9 @@ enum errors {
      traceframe.  */
   NOT_AVAILABLE_ERROR,
 
+  /* DW_OP_GNU_entry_value resolving failed.  */
+  NO_ENTRY_VALUE_ERROR,
+
   /* Add more errors here.  */
   NR_ERRORS
 };
--- a/gdb/f-lang.h
+++ b/gdb/f-lang.h
@@ -29,7 +29,8 @@ extern void f_print_type (struct type *, const char *, struct ui_file *, int,
 			  int);
 
 extern int f_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
-			struct ui_file *, int, struct value *,
+			struct ui_file *, int,
+			const struct value *,
 			const struct value_print_options *);
 
 /* Language-specific data structures */
--- a/gdb/f-valprint.c
+++ b/gdb/f-valprint.c
@@ -165,7 +165,8 @@ static void
 f77_print_array_1 (int nss, int ndimensions, struct type *type,
 		   const gdb_byte *valaddr,
 		   int embedded_offset, CORE_ADDR address,
-		   struct ui_file *stream, int recurse, struct value *val,
+		   struct ui_file *stream, int recurse,
+		   const struct value *val,
 		   const struct value_print_options *options,
 		   int *elts)
 {
@@ -216,7 +217,8 @@ static void
 f77_print_array (struct type *type, const gdb_byte *valaddr,
 		 int embedded_offset,
 		 CORE_ADDR address, struct ui_file *stream,
-		 int recurse, struct value *val,
+		 int recurse,
+		 const struct value *val,
 		 const struct value_print_options *options)
 {
   int ndimensions;
@@ -247,7 +249,7 @@ Type node corrupt! F77 arrays cannot have %d subscripts (%d Max)"),
 int
 f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	     CORE_ADDR address, struct ui_file *stream, int recurse,
-	     struct value *original_value,
+	     const struct value *original_value,
 	     const struct value_print_options *options)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -346,22 +348,12 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	    {
 	      struct value *deref_val;
 
-	      if (VALUE_LVAL (original_value) == lval_computed)
+	      deref_val = coerce_ref_if_computed (original_value);
+	      if (deref_val)
 		{
-		  const struct lval_funcs *funcs;
-		  
-		  funcs = value_computed_funcs (original_value);
-		  if (funcs->indirect)
-		    {
-		      struct value *result = funcs->indirect (original_value);
-
-		      if (result)
-			{
-			  common_val_print (result, stream, recurse,
-					    options, current_language);
-			  return 0;
-			}
-		    }
+		  common_val_print (deref_val, stream, recurse, options,
+				    current_language);
+		  return 0;
 		}
 
 	      deref_val = value_at (TYPE_TARGET_TYPE (type),
@@ -627,8 +619,7 @@ info_common_command (char *comname, int from_tty)
 
       while (entry != NULL)
 	{
-	  print_variable_and_value (NULL, entry->symbol, fi, gdb_stdout, 0,
-				    PVAVD_IS_NOT_ARGUMENT);
+	  print_variable_and_value (NULL, entry->symbol, fi, gdb_stdout, 0);
 	  entry = entry->next;
 	}
     }
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -711,6 +711,47 @@ extern int frame_register_read (struct frame_info *frame, int regnum,
 				gdb_byte *buf);
 
 /* 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
+{
+  /* Symbol for this parameter used for example for its name.  */
+  struct symbol *sym;
+
+  /* Value of the parameter.  It is NULL if ERROR is not NULL; if both VAL and
+     ERROR are NULL this parameter's value should not be printed.  */
+  struct value *val;
+
+  /* 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 *entryargp);
+
 extern void args_info (char *, int);
 
 extern void locals_info (char *, int);
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -911,7 +911,7 @@ struct func_type
     struct call_site *tail_call_list;
   };
 
-/* A place where some function gets called from, represented by
+/* A place where a function gets called from, represented by
    DW_TAG_GNU_call_site.  It can be looked up from symtab->call_site_htab.  */
 
 struct call_site
@@ -937,6 +937,10 @@ struct call_site
     /* Size of the PARAMETER array.  */
     unsigned parameter_count;
 
+    /* CU of the function where the call is located.  It gets used for DWARF
+       blocks execution in the parameter array below.  */
+    struct dwarf2_per_cu_data *per_cu;
+
     /* Describe DW_TAG_GNU_call_site's DW_TAG_formal_parameter.  */
     struct call_site_parameter
       {
@@ -952,11 +956,13 @@ struct call_site
 
 	/* DW_TAG_formal_parameter's DW_AT_GNU_call_site_value.  It is never
 	   NULL.  */
-	struct dwarf2_locexpr_baton *call_site_value;
+	const gdb_byte *value;
+	size_t value_size;
 
 	/* DW_TAG_formal_parameter's DW_AT_GNU_call_site_data_value.  It may be
 	   NULL if not provided by DWARF.  */
-	struct dwarf2_locexpr_baton *call_site_data_value;
+	const gdb_byte *data_value;
+	size_t data_value_size;
       }
     parameter[1];
   };
--- a/gdb/jv-lang.h
+++ b/gdb/jv-lang.h
@@ -43,7 +43,8 @@ struct builtin_java_type
 extern const struct builtin_java_type *builtin_java_type (struct gdbarch *);
 
 extern int java_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
-			   struct ui_file *, int, struct value *,
+			   struct ui_file *, int,
+			   const struct value *,
 			   const struct value_print_options *);
 
 extern int java_value_print (struct value *, struct ui_file *,
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -264,7 +264,8 @@ static void
 java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 			 int offset,
 			 CORE_ADDR address, struct ui_file *stream,
-			 int recurse, struct value *val,
+			 int recurse,
+			 const struct value *val,
 			 const struct value_print_options *options)
 {
   int i, len, n_baseclasses;
@@ -481,7 +482,8 @@ java_print_value_fields (struct type *type, const gdb_byte *valaddr,
 int
 java_val_print (struct type *type, const gdb_byte *valaddr,
 		int embedded_offset, CORE_ADDR address,
-		struct ui_file *stream, int recurse, struct value *val,
+		struct ui_file *stream, int recurse,
+		const struct value *val,
 		const struct value_print_options *options)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -1118,7 +1118,7 @@ static int
 unk_lang_val_print (struct type *type, const gdb_byte *valaddr,
 		    int embedded_offset, CORE_ADDR address,
 		    struct ui_file *stream, int recurse,
-		    struct value *val,
+		    const struct value *val,
 		    const struct value_print_options *options)
 {
   error (_("internal error - unimplemented "
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -234,7 +234,7 @@ struct language_defn
 			 const gdb_byte *contents,
 			 int embedded_offset, CORE_ADDR address,
 			 struct ui_file *stream, int recurse,
-			 struct value *val,
+			 const struct value *val,
 			 const struct value_print_options *options);
 
     /* Print a top-level value using syntax appropriate for this language.  */
--- a/gdb/m2-lang.h
+++ b/gdb/m2-lang.h
@@ -33,7 +33,8 @@ extern int m2_is_long_set (struct type *type);
 extern int m2_is_unbounded_array (struct type *type);
 
 extern int m2_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
-			 struct ui_file *, int, struct value *,
+			 struct ui_file *, int,
+			 const struct value *,
 			 const struct value_print_options *);
 
 extern int get_long_set_bounds (struct type *type, LONGEST *low,
--- a/gdb/m2-valprint.c
+++ b/gdb/m2-valprint.c
@@ -38,7 +38,7 @@ static void
 m2_print_array_contents (struct type *type, const gdb_byte *valaddr,
 			 int embedded_offset, CORE_ADDR address,
 			 struct ui_file *stream, int recurse,
-			 struct value *val,
+			 const struct value *val,
 			 const struct value_print_options *options,
 			 int len);
 
@@ -279,7 +279,7 @@ static void
 m2_print_array_contents (struct type *type, const gdb_byte *valaddr,
 			 int embedded_offset, CORE_ADDR address,
 			 struct ui_file *stream, int recurse,
-			 struct value *val,
+			 const struct value *val,
 			 const struct value_print_options *options,
 			 int len)
 {
@@ -317,7 +317,7 @@ m2_print_array_contents (struct type *type, const gdb_byte *valaddr,
 int
 m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	      CORE_ADDR address, struct ui_file *stream, int recurse,
-	      struct value *original_value,
+	      const struct value *original_value,
 	      const struct value_print_options *options)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -236,6 +236,78 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc)
   list_args_or_locals (all, parse_print_values (argv[0]), frame);
 }
 
+/* Print single local or argument.  ARG must be already read in.  For WHAT and
+   VALUES see list_args_or_locals.
+
+   Errors are printed as if they would be the parameter value.  Use zeroed ARG
+   iff it should not be printed accoring to VALUES.  */
+
+static void
+list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
+		   enum print_values values)
+{
+  struct cleanup *cleanup_tuple = NULL;
+  struct ui_out *uiout = current_uiout;
+  struct ui_stream *stb = ui_out_stream_new (uiout);
+
+  gdb_assert (!arg->val || !arg->error);
+  gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL
+	       && arg->error == NULL)
+	      || 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);
+
+  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);
+
+  if (values == PRINT_SIMPLE_VALUES)
+    {
+      check_typedef (arg->sym->type);
+      type_print (arg->sym->type, "", stb->stream, -1);
+      ui_out_field_stream (uiout, "type", stb);
+    }
+
+  if (arg->val || arg->error)
+    {
+      volatile struct gdb_exception except;
+
+      if (arg->error)
+	except.message = arg->error;
+      else
+	{
+	  /* TRY_CATCH has two statements, wrap it in a block.  */
+
+	  TRY_CATCH (except, RETURN_MASK_ERROR)
+	    {
+	      struct value_print_options opts;
+
+	      get_raw_print_options (&opts);
+	      opts.deref_ref = 1;
+	      common_val_print (arg->val, stb->stream, 0, &opts,
+				language_def (SYMBOL_LANGUAGE (arg->sym)));
+	    }
+	}
+      if (except.message)
+	fprintf_filtered (stb->stream, _("<error reading variable: %s>"),
+			  except.message);
+      ui_out_field_stream (uiout, "value", stb);
+    }
+
+  ui_out_stream_delete (stb);
+  if (values != PRINT_NO_VALUES || what == all)
+    do_cleanups (cleanup_tuple);
+}
 
 /* Print a list of the locals or the arguments for the currently
    selected frame.  If the argument passed is 0, printonly the names
@@ -313,16 +385,8 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 	    }
 	  if (print_me)
 	    {
-	      struct cleanup *cleanup_tuple = NULL;
 	      struct symbol *sym2;
-	      struct value *val;
-
-	      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 (sym));
-	      if (what == all && SYMBOL_IS_ARGUMENT (sym))
-		ui_out_field_int (uiout, "arg", 1);
+	      struct frame_arg arg, entryarg;
 
 	      if (SYMBOL_IS_ARGUMENT (sym))
 		sym2 = lookup_symbol (SYMBOL_NATURAL_NAME (sym),
@@ -330,64 +394,34 @@ list_args_or_locals (enum what_to_list what, enum print_values values,
 				      (int *) NULL);
 	      else
 		sym2 = sym;
+
+	      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)
 		{
 		case PRINT_SIMPLE_VALUES:
 		  type = check_typedef (sym2->type);
-		  type_print (sym2->type, "", stb->stream, -1);
-		  ui_out_field_stream (uiout, "type", stb);
 		  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
 		      && TYPE_CODE (type) != TYPE_CODE_STRUCT
 		      && TYPE_CODE (type) != TYPE_CODE_UNION)
 		    {
-		      volatile struct gdb_exception except;
-
-		      TRY_CATCH (except, RETURN_MASK_ERROR)
-			{
-			  struct value_print_options opts;
-
-			  val = read_var_value (sym2, fi);
-			  get_raw_print_options (&opts);
-			  opts.deref_ref = 1;
-			  common_val_print
-			    (val, stb->stream, 0, &opts,
-			     language_def (SYMBOL_LANGUAGE (sym2)));
-			}
-		      if (except.reason < 0)
-			fprintf_filtered (stb->stream,
-					  _("<error reading variable: %s>"),
-					  except.message);
-
-		      ui_out_field_stream (uiout, "value", stb);
-		    }
-		  break;
 		case PRINT_ALL_VALUES:
-		  {
-		    volatile struct gdb_exception except;
-
-		    TRY_CATCH (except, RETURN_MASK_ERROR)
-		      {
-			struct value_print_options opts;
-
-			val = read_var_value (sym2, fi);
-			get_raw_print_options (&opts);
-			opts.deref_ref = 1;
-			common_val_print
-			  (val, stb->stream, 0, &opts,
-			   language_def (SYMBOL_LANGUAGE (sym2)));
-		      }
-		    if (except.reason < 0)
-		      fprintf_filtered (stb->stream,
-					_("<error reading variable: %s>"),
-					except.message);
-
-		    ui_out_field_stream (uiout, "value", stb);
-		  }
+		      read_frame_arg (sym2, fi, &arg, &entryarg);
+		    }
 		  break;
 		}
 
-	      if (values != PRINT_NO_VALUES || what == all)
-		do_cleanups (cleanup_tuple);
+	      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))
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -360,7 +360,8 @@ static const struct lval_funcs opencl_value_funcs =
     lval_func_write,
     lval_func_check_validity,
     lval_func_check_any_valid,
-    NULL,
+    NULL,	/* indirect */
+    NULL,	/* coerce_ref */
     lval_func_check_synthetic_pointer,
     lval_func_copy_closure,
     lval_func_free_closure
--- a/gdb/p-lang.h
+++ b/gdb/p-lang.h
@@ -38,7 +38,7 @@ extern void pascal_print_typedef (struct type *, struct symbol *,
 
 extern int pascal_val_print (struct type *, const gdb_byte *, int,
 			     CORE_ADDR, struct ui_file *, int,
-			     struct value *,
+			     const struct value *,
 			     const struct value_print_options *);
 
 extern int pascal_value_print (struct value *, struct ui_file *,
@@ -72,7 +72,8 @@ extern void
 extern void pascal_object_print_value_fields (struct type *, const gdb_byte *,
 					      int,
 					      CORE_ADDR, struct ui_file *,
-					      int, struct value *,
+					      int,
+					      const struct value *,
 					      const struct value_print_options *,
 					      struct type **, int);
 
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -49,7 +49,7 @@ int
 pascal_val_print (struct type *type, const gdb_byte *valaddr,
 		  int embedded_offset, CORE_ADDR address,
 		  struct ui_file *stream, int recurse,
-		  struct value *original_value,
+		  const struct value *original_value,
 		  const struct value_print_options *options)
 {
   struct gdbarch *gdbarch = get_type_arch (type);
@@ -274,22 +274,12 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr,
 	    {
 	      struct value *deref_val;
 
-	      if (VALUE_LVAL (original_value) == lval_computed)
+	      deref_val = coerce_ref_if_computed (original_value);
+	      if (deref_val)
 		{
-		  const struct lval_funcs *funcs;
-		  
-		  funcs = value_computed_funcs (original_value);
-		  if (funcs->indirect)
-		    {
-		      struct value *result = funcs->indirect (original_value);
-
-		      if (result)
-			{
-			  common_val_print (result, stream, recurse,
-					    options, current_language);
-			  return 0;
-			}
-		    }
+		  common_val_print (deref_val, stream, recurse + 1, options,
+				    current_language);
+		  return 0;
 		}
 
 	      deref_val = value_at (TYPE_TARGET_TYPE (type),
@@ -645,7 +635,7 @@ static void pascal_object_print_static_field (struct value *,
 static void pascal_object_print_value (struct type *, const gdb_byte *,
 				       int,
 				       CORE_ADDR, struct ui_file *, int,
-				       struct value *,
+				       const struct value *,
 				       const struct value_print_options *,
 				       struct type **);
 
@@ -704,7 +694,8 @@ void
 pascal_object_print_value_fields (struct type *type, const gdb_byte *valaddr,
 				  int offset,
 				  CORE_ADDR address, struct ui_file *stream,
-				  int recurse, struct value *val,
+				  int recurse,
+				  const struct value *val,
 				  const struct value_print_options *options,
 				  struct type **dont_print_vb,
 				  int dont_print_statmem)
@@ -898,7 +889,8 @@ static void
 pascal_object_print_value (struct type *type, const gdb_byte *valaddr,
 			   int offset,
 			   CORE_ADDR address, struct ui_file *stream,
-			   int recurse, struct value *val,
+			   int recurse,
+			   const struct value *val,
 			   const struct value_print_options *options,
 			   struct type **dont_print_vb)
 {
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1956,114 +1956,33 @@ clear_dangling_display_expressions (struct so_list *solib)
    struct symbol.  NAME is the name to print; if NULL then VAR's print
    name will be used.  STREAM is the ui_file on which to print the
    value.  INDENT specifies the number of indent levels to print
-   before printing the variable name.  PRINT_ARGUMENT specifies whether @entry
-   kind of function parameters should be printed.  */
+   before printing the variable name.  */
 
 void
 print_variable_and_value (const char *name, struct symbol *var,
 			  struct frame_info *frame,
-			  struct ui_file *stream, int indent,
-			  enum print_argument print_argument)
+			  struct ui_file *stream, int indent)
 {
   volatile struct gdb_exception except;
 
   if (!name)
     name = SYMBOL_PRINT_NAME (var);
 
+  fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name);
   TRY_CATCH (except, RETURN_MASK_ERROR)
     {
-      struct value *val, *entryval = NULL;
+      struct value *val;
       struct value_print_options opts;
 
       val = read_var_value (var, frame);
       get_user_print_options (&opts);
       opts.deref_ref = 1;
-
-      if (print_argument != PVAVD_IS_NOT_ARGUMENT
-	  && SYMBOL_CLASS (var) == LOC_COMPUTED
-	  && SYMBOL_COMPUTED_OPS (var)->read_variable_at_entry != NULL)
-	{
-	  const struct symbol_computed_ops *ops;
-	  unsigned len = TYPE_LENGTH (value_type (val));
-	  volatile struct gdb_exception entryval_ex;
-
-	  ops = SYMBOL_COMPUTED_OPS (var);
-
-	  TRY_CATCH (entryval_ex, RETURN_MASK_ERROR)
-	    {
-	      entryval = ops->read_variable_at_entry (var, frame);
-	    }
-
-	  if (entryval_ex.reason < 0 || value_optimized_out (entryval))
-	    entryval = NULL;
-	  else
-	    {
-	      if (!value_optimized_out (val) && value_lazy (val))
-		value_fetch_lazy (val);
-	      if (!value_optimized_out (val) && value_lazy (entryval))
-		value_fetch_lazy (entryval);
-	      if (!value_optimized_out (val)
-		  && value_available_contents_eq (val, 0, entryval, 0, len))
-		{
-		  volatile struct gdb_exception deref_ex;
-		  struct value *val_deref, *entryval_deref;
-
-		  /* DW_AT_GNU_call_site_value does match with the current
-		     value.  If it is a reference still try to verify if
-		     dereferenced DW_AT_GNU_call_site_data_value does not
-		     differ.  */
-
-		  TRY_CATCH (deref_ex, RETURN_MASK_ERROR)
-		    {
-		      unsigned len_deref;
-
-		      val_deref = coerce_ref (val);
-		      if (value_lazy (val_deref))
-			value_fetch_lazy (val_deref);
-		      len_deref = TYPE_LENGTH (value_type (val_deref));
-
-		      entryval_deref = coerce_ref (entryval);
-		      if (value_lazy (entryval_deref))
-			value_fetch_lazy (entryval_deref);
-
-		      /* If the reference addresses match but dereferenced
-		         content does not match print them.  */
-		      if (val != val_deref
-			  && value_available_contents_eq (val_deref, 0,
-							  entryval_deref, 0,
-							  len_deref))
-			entryval = NULL;
-		    }
-
-		  /* If the dereferenced content could not be fetch do not
-		     display anything.  */
-		  if (deref_ex.reason < 0)
-		    entryval = NULL;
-
-		  /* Value was not a reference; and its content matches.  */
-		  if (val == val_deref)
-		    entryval = NULL;
-		}
-	    }
-	}
-
-      if (print_argument != PVAVD_ARGUMENT_PRINT_ENTRYVAL_ONLY)
-	{
-	  fprintf_filtered (stream, "%s%s = ", n_spaces (2 * indent), name);
-	  common_val_print (val, stream, indent, &opts, current_language);
-	  fputc_filtered ('\n', stream);
-	}
-      if (entryval)
-	{
-	  fprintf_filtered (stream, "%s%s@entry = ", n_spaces (2 * indent),
-			    name);
-	  common_val_print (entryval, stream, indent, &opts, current_language);
-	  fputc_filtered ('\n', stream);
-	}
+      common_val_print (val, stream, indent, &opts, current_language);
     }
   if (except.reason < 0)
-    fprintf_filtered (stream, "%s%s = <error reading variable %s (%s)>\n",
-		      n_spaces (2 * indent), name, name, except.message);
+    fprintf_filtered(stream, "<error reading variable %s (%s)>", name,
+		     except.message);
+  fprintf_filtered (stream, "\n");
 }
 
 /* printf "printf format string" ARG to STREAM.  */
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -595,6 +595,7 @@ gdbpy_initialize_frames (void)
   PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME);
   PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME);
   PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME);
+  PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME", TAILCALL_FRAME);
   PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME);
   PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME);
   PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME);
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -29,6 +29,7 @@
 #include "language.h"
 #include "vec.h"
 #include "bcache.h"
+#include "dwarf2loc.h"
 
 typedef struct pyty_type_object
 {
@@ -822,6 +823,22 @@ check_types_equal (struct type *type1, struct type *type2,
 				    FIELD_STATIC_PHYSNAME (*field2)))
 		return Py_NE;
 	      break;
+	    case FIELD_LOC_KIND_DWARF_BLOCK:
+	      {
+		struct dwarf2_locexpr_baton *block1, *block2;
+
+		block1 = FIELD_DWARF_BLOCK (*field1);
+		block2 = FIELD_DWARF_BLOCK (*field2);
+		if (block1->per_cu != block2->per_cu
+		    || block1->size != block2->size
+		    || memcmp (block1->data, block2->data, block1->size) != 0)
+		return Py_NE;
+	      }
+	      break;
+	    default:
+	      internal_error (__FILE__, __LINE__, _("Unsupported field kind "
+						    "%d by check_types_equal"),
+			      FIELD_LOC_KIND (*field1));
 	    }
 
 	  entry.type1 = FIELD_TYPE (*field1);
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -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,
@@ -162,6 +185,285 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num,
     }
 }
 
+/* Print single argument of inferior function.  ARG must be already
+   read in.
+
+   Errors are printed as if they would be the parameter value.  Use zeroed ARG
+   iff it should not be printed accoring to user settings.  */
+
+static void
+print_frame_arg (const struct frame_arg *arg)
+{
+  struct ui_out *uiout = current_uiout;
+  volatile struct gdb_exception except;
+  struct cleanup *old_chain;
+  struct ui_stream *stb;
+
+  stb = ui_out_stream_new (uiout);
+  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, "=");
+
+  if (!arg->val && !arg->error)
+    ui_out_text (uiout, "...");
+  else
+    {
+      if (arg->error)
+	except.message = arg->error;
+      else
+	{
+	  /* TRY_CATCH has two statements, wrap it in a block.  */
+
+	  TRY_CATCH (except, RETURN_MASK_ERROR)
+	    {
+	      const struct language_defn *language;
+	      struct value_print_options opts;
+
+	      /* Avoid value_print because it will deref ref parameters.  We
+		 just want to print their addresses.  Print ??? for args whose
+		 address we do not know.  We pass 2 as "recurse" to val_print
+		 because our standard indentation here is 4 spaces, and
+		 val_print indents 2 for each recurse.  */ 
+
+	      annotate_arg_value (value_type (arg->val));
+
+	      /* Use the appropriate language to display our symbol, unless the
+		 user forced the language to a specific language.  */
+	      if (language_mode == language_mode_auto)
+		language = language_def (SYMBOL_LANGUAGE (arg->sym));
+	      else
+		language = current_language;
+
+	      get_raw_print_options (&opts);
+	      opts.deref_ref = 1;
+
+	      /* True in "summary" mode, false otherwise.  */
+	      opts.summary = !strcmp (print_frame_arguments, "scalars");
+
+	      common_val_print (arg->val, stb->stream, 2, &opts, language);
+	    }
+	}
+      if (except.message)
+	fprintf_filtered (stb->stream, _("<error reading variable: %s>"),
+			  except.message);
+    }
+
+  ui_out_field_stream (uiout, "value", stb);
+
+  /* Aleo invoke ui_out_tuple_end.  */
+  do_cleanups (old_chain);
+
+  annotate_arg_end ();
+}
+
+/* Read in inferior function parameter SYM at FRAME into ARGP.  Caller is
+   responsible for xfree of ARGP->ERROR.  This function never throws an
+   exception.  */
+
+void
+read_frame_arg (struct symbol *sym, struct frame_info *frame,
+	        struct frame_arg *argp, struct frame_arg *entryargp)
+{
+  struct value *val = NULL, *entryval = NULL;
+  char *val_error = NULL, *entryval_error = NULL;
+  int val_equal = 0;
+  volatile struct gdb_exception except;
+
+  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))
+		{
+		  struct value *val_deref, *entryval_deref;
+
+		  /* DW_AT_GNU_call_site_value does match with the current
+		     value.  If it is a reference still try to verify if
+		     dereferenced DW_AT_GNU_call_site_data_value does not
+		     differ.  */
+
+		  TRY_CATCH (except, RETURN_MASK_ERROR)
+		    {
+		      unsigned len_deref;
+
+		      val_deref = coerce_ref (val);
+		      if (value_lazy (val_deref))
+			value_fetch_lazy (val_deref);
+		      len_deref = TYPE_LENGTH (value_type (val_deref));
+
+		      entryval_deref = coerce_ref (entryval);
+		      if (value_lazy (entryval_deref))
+			value_fetch_lazy (entryval_deref);
+
+		      /* If the reference addresses match but dereferenced
+			 content does not match print them.  */
+		      if (val != val_deref
+			  && value_available_contents_eq (val_deref, 0,
+							  entryval_deref, 0,
+							  len_deref))
+			val_equal = 1;
+		    }
+
+		  /* Value was not a reference; and its content matches.  */
+		  if (val == val_deref)
+		    val_equal = 1;
+		  /* If the dereferenced content could not be fetched do not
+		     display anything.  */
+		  else if (except.error == NO_ENTRY_VALUE_ERROR)
+		    val_equal = 1;
+		  else if (except.message)
+		    {
+		      entryval_error = alloca (strlen (except.message) + 1);
+		      strcpy (entryval_error, except.message);
+		    }
+
+		  if (val_equal)
+		    entryval = NULL;
+		}
+	    }
+
+	  /* 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)
+    {
+      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 ((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 = 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
    FUNC running in that frame (as a symbol), where NUM is the number
    of arguments according to the stack frame (or -1 if the number of
@@ -198,10 +500,11 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
       struct block *b = SYMBOL_BLOCK_VALUE (func);
       struct dict_iterator iter;
       struct symbol *sym;
-      struct value *val;
 
       ALL_BLOCK_SYMBOLS (b, iter, sym)
         {
+	  struct frame_arg arg, entryarg;
+
 	  QUIT;
 
 	  /* Keep track of the highest stack argument offset seen, and
@@ -314,65 +617,34 @@ print_frame_args (struct symbol *func, struct frame_info *frame,
 	    ui_out_text (uiout, ", ");
 	  ui_out_wrap_hint (uiout, "    ");
 
-	  annotate_arg_begin ();
-
-	  list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
-	  fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (sym),
-				   SYMBOL_LANGUAGE (sym),
-				   DMGL_PARAMS | DMGL_ANSI);
-	  ui_out_field_stream (uiout, "name", stb);
-	  annotate_arg_name_end ();
-	  ui_out_text (uiout, "=");
+	  if (!print_args)
+	    {
+	      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, &entryarg);
 
-          if (print_args)
-            {
-	      volatile struct gdb_exception except;
+	  if (arg.entry_kind != print_entry_values_only)
+	    print_frame_arg (&arg);
 
-	      TRY_CATCH (except, RETURN_MASK_ERROR)
-		{
-		  const struct language_defn *language;
-		  struct value_print_options opts;
-
-		  /* Avoid value_print because it will deref ref parameters.
-		     We just want to print their addresses.  Print ??? for
-		     args whose address we do not know.  We pass 2 as
-		     "recurse" to val_print because our standard indentation
-		     here is 4 spaces, and val_print indents 2 for each
-		     recurse.  */
-		  val = read_var_value (sym, frame);
-
-		  annotate_arg_value (value_type (val));
-
-		  /* Use the appropriate language to display our symbol,
-		     unless the user forced the language to a specific
-		     language.  */
-		  if (language_mode == language_mode_auto)
-		    language = language_def (SYMBOL_LANGUAGE (sym));
-		  else
-		    language = current_language;
-
-		  get_raw_print_options (&opts);
-		  opts.deref_ref = 1;
-		  opts.summary = summary;
-		  common_val_print (val, stb->stream, 2, &opts, language);
-		  ui_out_field_stream (uiout, "value", stb);
-		}
-	      if (except.reason < 0)
+	  if (entryarg.entry_kind != print_entry_values_no)
+	    {
+	      if (arg.entry_kind != print_entry_values_only)
 		{
-		  fprintf_filtered (stb->stream,
-				    _("<error reading variable: %s>"),
-				    except.message);
-		  ui_out_field_stream (uiout, "value", stb);
+		  ui_out_text (uiout, ", ");
+		  ui_out_wrap_hint (uiout, "    ");
 		}
-            }
-          else
-            ui_out_text (uiout, "...");
-
 
-	  /* Invoke ui_out_tuple_end.  */
-	  do_cleanups (list_chain);
+	      print_frame_arg (&entryarg);
+	    }
 
-	  annotate_arg_end ();
+	  xfree (arg.error);
+	  xfree (entryarg.error);
 
 	  first = 0;
 	}
@@ -1087,8 +1359,7 @@ frame_info (char *addr_exp, int from_tty)
 			 frame_stop_reason_string (reason));
     }
   else if (get_frame_type (fi) == TAILCALL_FRAME)
-    printf_filtered (" tail call frame %d",
-		     frame_relative_level (get_prev_frame (fi)));
+    puts_filtered (" tail call frame");
   else if (get_frame_type (fi) == INLINE_FRAME)
     printf_filtered (" inlined into frame %d",
 		     frame_relative_level (get_prev_frame (fi)));
@@ -1532,7 +1803,6 @@ struct print_variable_and_value_data
   int num_tabs;
   struct ui_file *stream;
   int values_printed;
-  enum print_argument print_argument;
 };
 
 /* The callback for the locals and args iterators.  */
@@ -1544,17 +1814,13 @@ do_print_variable_and_value (const char *print_name,
 {
   struct print_variable_and_value_data *p = cb_data;
 
-  print_variable_and_value (print_name, sym, p->frame, p->stream, p->num_tabs,
-			    p->print_argument);
+  print_variable_and_value (print_name, sym,
+			    p->frame, p->stream, p->num_tabs);
   p->values_printed = 1;
 }
 
-/* Show function local variables at FRAME.  FROM_FRAME is 1 if the local
-   variables are printed after the function frame (parameter values) have been
-   printed, it is 0 otherwise.  Print them to STREAM.  */
-
 static void
-print_frame_local_vars (struct frame_info *frame, int from_frame,
+print_frame_local_vars (struct frame_info *frame, int num_tabs,
 			struct ui_file *stream)
 {
   struct print_variable_and_value_data cb_data;
@@ -1576,24 +1842,10 @@ print_frame_local_vars (struct frame_info *frame, int from_frame,
     }
 
   cb_data.frame = frame;
-  cb_data.num_tabs = from_frame ? 4 : 0;
+  cb_data.num_tabs = 4 * num_tabs;
   cb_data.stream = stream;
   cb_data.values_printed = 0;
 
-  if (from_frame)
-    {
-      /* For the variables we display them from the innermost block.  But for
-         parameters we need to fetch the outermost block still in the same
-         function.  Stop at the first inlined function boundary, if any.  */
-      struct symbol *func = get_frame_function (frame);
-
-      cb_data.print_argument = PVAVD_ARGUMENT_PRINT_ENTRYVAL_ONLY;
-      if (func)
-	iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func),
-				     do_print_variable_and_value, &cb_data);
-    }
-
-  cb_data.print_argument = PVAVD_IS_NOT_ARGUMENT;
   iterate_over_block_local_vars (block,
 				 do_print_variable_and_value,
 				 &cb_data);
@@ -1753,7 +2005,6 @@ print_frame_arg_vars (struct frame_info *frame, struct ui_file *stream)
   cb_data.stream = gdb_stdout;
   cb_data.values_printed = 0;
 
-  cb_data.print_argument = PVAVD_ARGUMENT_PRINT_BOTH;
   iterate_over_block_arg_vars (SYMBOL_BLOCK_VALUE (func),
 			       do_print_variable_and_value, &cb_data);
 
@@ -2274,4 +2525,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 frame arguments values at function "
+			  "entry"),
+			_("Show printing of frame arguments values at function "
+			  "entry"),
+			_("\
+GDB can print in some cases besides frame arguments values also the values\n\
+they had at function entry (marked as `NAME@entry').  The value itself and/or\n\
+the entry value may be <optimized out>.  Which of this current or entry\n\
+values get printed in which case can be set by this option."),
+			NULL, NULL, &setprintlist, &showprintlist);
 }
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -534,8 +534,8 @@ struct symbol_computed_ops
 				  struct frame_info * frame);
 
   /* Read variable SYMBOL like read_variable at (callee) FRAME's function
-     entry.  SYMBOL should be a function parameter, otherwise NOT_FOUND_ERROR
-     will be thrown.  */
+     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);
 
--- a/gdb/testsuite/gdb.arch/amd64-entry-value.cc
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value.cc
@@ -18,43 +18,51 @@
 static volatile int v;
 
 static void __attribute__((noinline, noclone))
-e (int i)
+e (int i, double j)
 {
   v = 0;
 }
 
 static void __attribute__((noinline, noclone))
-d (int i)
+d (int i, double j)
 {
   i++;
-  e (i);
-  e (v);
+  j++;
+  e (i, j);
+  e (v, v);
 asm ("breakhere:");
-  e (v);
+  e (v, v);
 }
 
 static void __attribute__((noinline, noclone))
-c (int i)
+locexpr (int i)
 {
-  d (i * 10);
+  i = i;
+asm ("breakhere_locexpr:");
 }
 
 static void __attribute__((noinline, noclone))
-a (int i)
+c (int i, double j)
 {
-  c (i + 1);
+  d (i * 10, j * 10);
 }
 
 static void __attribute__((noinline, noclone))
-b (int i)
+a (int i, double j)
 {
-  c (i + 2);
+  c (i + 1, j + 1);
+}
+
+static void __attribute__((noinline, noclone))
+b (int i, double j)
+{
+  c (i + 2, j + 2);
 }
 
 static void __attribute__((noinline, noclone))
 amb_z (int i)
 {
-  d (i + 7);
+  d (i + 7, i + 7.5);
 }
 
 static void __attribute__((noinline, noclone))
@@ -108,46 +116,117 @@ self (int i)
     }
   else
     {
-      e (v);
-      d (i + 2);
+      e (v, v);
+      d (i + 2, i + 2.5);
     }
 }
 
 static void __attribute__((noinline, noclone))
-stacktest (int r1, int r2, int r3, int r4, int r5, int r6, int s1, int s2)
+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;
-  e (v);
+  d9 = 3.5;
+  da = 4.5;
+  e (v, v);
 asm ("breakhere_stacktest:");
-  e (v);
+  e (v, v);
 }
 
+/* nodataparam has DW_AT_GNU_call_site_value but it does not have
+   DW_AT_GNU_call_site_data_value.  GDB should not display dereferenced @entry
+   value for it.  */
+
 static void __attribute__((noinline, noclone))
-reference (int &refparam)
+reference (int &regparam, int &nodataparam, int r3, int r4, int r5, int r6,
+	   int &stackparam1, int &stackparam2)
 {
-  int refcopy = refparam;
+  int regcopy = regparam, nodatacopy = nodataparam;
+  int stackcopy1 = stackparam1, stackcopy2 = stackparam2;
 
-  refparam = 10;
+  regparam = 21;
+  nodataparam = 22;
+  stackparam1 = 31;
+  stackparam2 = 32;
+  e (v, v);
 asm ("breakhere_reference:");
-  e (v);
+  e (v, v);
+}
+
+static int *__attribute__((noinline, noclone))
+datap ()
+{
+  static int two = 2;
+
+  return &two;
+}
+
+static void __attribute__((noinline, noclone))
+datap_input (int *datap)
+{
+  (*datap)++;
+}
+
+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 ()
 {
-  int refvar;
-
-  d (30);
-  stacktest (1, 2, 3, 4, 5, 6, 11, 12);
+  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 ());
 
-  refvar = 5;
-  reference (refvar);
+  {
+    int regvar = 1, *nodatavarp = datap (), stackvar1 = 11, stackvar2 = 12;
+    reference (regvar, *nodatavarp, 3, 4, 5, 6, stackvar1, stackvar2);
+    datap_input (nodatavarp);
+  }
 
   if (v)
-    a (1);
+    a (1, 1.25);
   else
-    b (5);
+    b (5, 5.25);
   amb_a (100);
   self (200);
   return 0;
--- a/gdb/testsuite/gdb.arch/amd64-entry-value.exp
+++ b/gdb/testsuite/gdb.arch/amd64-entry-value.exp
@@ -35,8 +35,13 @@ 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"
 gdb_breakpoint "reference"
 gdb_breakpoint "breakhere_reference"
 
@@ -45,112 +50,175 @@ gdb_breakpoint "breakhere_reference"
 
 gdb_continue_to_breakpoint "entry: breakhere"
 
-# (gdb) bt full
-# #0  d (i=31) at gdb.arch/amd64-entry-value.cc:33
-#         i@entry = 30
-# #1  0x00000000004003da in main () at gdb.arch/amd64-entry-value.cc:56
-gdb_test "bt full" "^bt full\r\n#0 +d *\\(i=31\\) \[^\r\n\]*\r\n\[ \t\]*i@entry = 30\r\n#1 +0x\[0-9a-f\]+ in main .*" \
-	 "entry: bt full"
+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 i@entry" " = 30" "entry: p i@entry"
+gdb_test "p j" { = 31\.5} "entry: p j"
+gdb_test "p j@entry" { = 30\.5} "entry: p j@entry"
+
+
+# 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) bt full
-# #0  stacktest (r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=11, s2=12) at gdb.arch/amd64-entry-value.cc:121
-# #1  0x0000000000400412 in main () at gdb.arch/amd64-entry-value.cc:142
-# Check s1 and s2 are suppressed:
-gdb_test "bt full" "^bt full\r\n#0 +stacktest *\\(r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=11, s2=12\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main .*" \
-	 "entry_stack: bt full at entry"
+gdb_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) bt full
-# #0  stacktest (r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=3, s2=4) at gdb.arch/amd64-entry-value.cc:123
-#         s1@entry = 11
-#         s2@entry = 12
-# #1  0x0000000000400412 in main () at gdb.arch/amd64-entry-value.cc:130
-# Check s1 and s2 are present:
-gdb_test "bt full" "^bt full\r\n#0 +stacktest *\\(r1=1, r2=2, r3=3, r4=4, r5=5, r6=6, s1=3, s2=4\\) \[^\r\n\]*\r\n\[ \t\]*s1@entry = 11\r\n\[ \t\]*s2@entry = 12\r\n#1 +0x\[0-9a-f\]+ in main .*" \
-	 "entry_stack: bt full"
+gdb_test "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 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"
+gdb_test "p d9" " = 3\\.5" "entry_stack: p d9"
+gdb_test "p d9@entry" " = 11\\.5" "entry_stack: p d9@entry"
+gdb_test "p da" " = 4\\.5" "entry_stack: p da"
+gdb_test "p da@entry" " = 12\\.5" "entry_stack: p da@entry"
+
+
+# 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 @entry values for DW_AT_GNU_call_site_data_value parameters.
 
 gdb_continue_to_breakpoint "entry_reference: reference"
 
-# (gdb) bt full
-# #0  reference (refparam=@0x7fffffffdc3c: 5) at gdb.arch/amd64-entry-value.cc:131
-#         refcopy = 5
-# #1  0x0000000000400424 in main () at gdb.arch/amd64-entry-value.cc:145
-#         refvar = 5
-# Check refparam@entry is suppressed:
-gdb_test "bt full" "#0 +reference \\(refparam=@0x\[0-9a-f\]+: 5\\) \[^\r\n\]*\r\n\[ \t\]*refcopy = 5\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*\r\n\[ \t\]*refvar = 5" \
-	 "entry_reference: bt full at entry"
+# GCC PR debug/49980: Missing stackparam1@entry and stackparam2@entry.
+gdb_test "bt" "#0 +reference \\(regparam=regparam@entry=@0x\[0-9a-f\]+: 1, nodataparam=@0x\[0-9a-f\]+: 2, \[^\r\n\]+, stackparam1=@0x\[0-9a-f\]+: 11, stackparam2=@0x\[0-9a-f\]+: 12\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*" \
+	 "entry_reference: bt at entry"
 
 gdb_continue_to_breakpoint "entry_reference: breakhere_reference"
 
-# (gdb) bt full
-# #0  reference (refparam=@0x7fffffffdc3c: 10) at gdb.arch/amd64-entry-value.cc:133
-#         refparam@entry = @0x7fffffffdc3c: 5
-#         refcopy = 5
-# #1  0x0000000000400424 in main () at gdb.arch/amd64-entry-value.cc:145
-#         refvar = 10
-# Check refparam@entry is present:
-gdb_test "bt full" "#0 +reference \\(refparam=@0x\[0-9a-f\]+: 10\\) \[^\r\n\]*\r\n\[ \t\]*refparam@entry = @0x\[0-9a-f\]+: 5\r\n\[ \t\]*refcopy = 5\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*\r\n\[ \t\]*refvar = 10" \
-	 "entry_reference: bt full"
-gdb_test "ptype refparam" " = int &" "entry_reference: ptype refparam"
-
-set test "entry_reference: p refparam"
+# GCC PR debug/49980: Missing stackparam1@entry and stackparam2@entry.
+gdb_test "bt" "#0 +reference \\(regparam=@0x\[0-9a-f\]+: 21, regparam@entry=@0x\[0-9a-f\]+: 1, nodataparam=@0x\[0-9a-f\]+: 22, \[^\r\n\]+, stackparam1=@0x\[0-9a-f\]+: 31, stackparam2=@0x\[0-9a-f\]+: 32\\) \[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in main \\(\\) \[^\r\n\]*" \
+	 "entry_reference: bt"
+gdb_test "ptype regparam" " = int &" "entry_reference: ptype regparam"
+
+set test "entry_reference: p regparam"
 set addr ""
-gdb_test_multiple "p refparam" $test {
-    -re " = \\(int &\\) @(0x\[0-9a-f\]+): 10\r\n$gdb_prompt $" {
+gdb_test_multiple "p regparam" $test {
+    -re " = \\(int &\\) @(0x\[0-9a-f\]+): 21\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"
+gdb_test "ptype regparam@entry" " = int &" "entry_reference: ptype regparam@entry"
+gdb_test "p regparam@entry" " = \\(int &\\) @$addr: 1" "entry_reference: p regparam@entry"
+gdb_test "p &regparam@entry" " = \\(int \\*\\) $addr" "entry_reference: p &regparam@entry"
+gdb_test "p regcopy" " = 1" "entry_reference: p regcopy"
+gdb_test "p nodataparam" " = \\(int &\\) @0x\[0-9a-f\]+: 22" "entry_reference: p nodataparam"
+gdb_test "p nodataparam@entry" "Cannot resolve DW_AT_GNU_call_site_data_value" "entry_reference: p nodataparam@entry"
 
 
 # Test virtual tail call frames.
 
 gdb_continue_to_breakpoint "tailcall: breakhere"
 
-# #0  d (i=71) at gdb.arch/amd64-entry-value.cc:33
-# #1  0x0000000000400527 in c (i=7) at gdb.arch/amd64-entry-value.cc:38
-# #2  0x0000000000400545 in b (i=5) at gdb.arch/amd64-entry-value.cc:50
-# #3  0x00000000004003ee in main () at gdb.arch/amd64-entry-value.cc:60
-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\]*" \
+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 i@entry" " = 70" "tailcall: p i@entry"
+gdb_test "p j" " = 73\\.5" "tailcall: p j"
+gdb_test "p j@entry" " = 72\\.5" "tailcall: p j@entry"
+
+# Test $sp simulation for tail call frames.
+#gdb_test {p/x $sp} " = 0x.*"
+#gdb_test {p/x $pc} " = 0x.*"
+gdb_test_no_output {set $sp0=$sp}
+gdb_test "up" "\r\n#1 .*"
+#gdb_test {p/x $sp} " = 0x.*"
+gdb_test {p $sp0 == $sp} " = true"
+gdb_test "frame 3" "\r\n#3 .*"
+gdb_test {p $sp0 + sizeof (void *) == $sp} " = true"
 
 
 # Test partial-ambiguous virtual tail call frames chain.
 
 gdb_continue_to_breakpoint "ambiguous: breakhere"
 
-# #0  d (i=<optimized out>) at gdb.arch/amd64-entry-value.cc:33
-# #1  0x0000000000400555 in amb_z (i=<optimized out>) at gdb.arch/amd64-entry-value.cc:56
-# #2  0x0000000000400565 in amb_y (i=<optimized out>) at gdb.arch/amd64-entry-value.cc:62
-# #3  0x0000000000400575 in amb_x (i=<optimized out>) at gdb.arch/amd64-entry-value.cc:68
-# --- here is missing a frame for ambiguous PC in amb ().
-# #4  0x0000000000400595 in amb_b (i=101) at gdb.arch/amd64-entry-value.cc:83
-# #5  0x00000000004005a5 in amb_a (i=100) at gdb.arch/amd64-entry-value.cc:89
-# #6  0x00000000004003f8 in main () at gdb.arch/amd64-entry-value.cc:100
-gdb_test "bt" "^bt\r\n#0 +d \\(i=<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"
 
 
@@ -159,10 +227,7 @@ gdb_test "bt" "^bt\r\n#0 +d \\(i=<optimized out>\\)\[^\r\n\]*\r\n#1 +0x\[0-9a-f\
 
 gdb_continue_to_breakpoint "self: breakhere"
 
-# #0  d (i=<optimized out>) at gdb.arch/amd64-entry-value.cc:33
-# #1  0x00000000004005df in self (i=<optimized out>) at gdb.arch/amd64-entry-value.cc:111
-# #2  0x0000000000400406 in main () at gdb.arch/amd64-entry-value.cc:124
-gdb_test "bt" "^bt\r\n#0 +d \\(i=<optimized out>\\)\[^\r\n\]*\r\n#1 +0x\[0-9a-f\]+ in self \\(i=<optimized out>\\)\[^\r\n\]*\r\n#2 +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 self \\(i=<optimized out>\\)\[^\r\n\]*\r\n#2 +0x\[0-9a-f\]+ in main \\(\\)\[^\r\n\]*" \
 	 "self: bt"
 
 gdb_test_no_output "set verbose on"
--- a/gdb/testsuite/gdb.base/break.exp
+++ b/gdb/testsuite/gdb.base/break.exp
@@ -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)"
 	}
--- a/gdb/testsuite/gdb.mi/Makefile.in
+++ b/gdb/testsuite/gdb.mi/Makefile.in
@@ -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		\
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.c
@@ -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;
+}
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi2-amd64-entry-value.exp
@@ -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 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"
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1740,22 +1740,22 @@ value_ind (struct value *arg1)
 
   base_type = check_typedef (value_type (arg1));
 
-  if (TYPE_CODE (base_type) == TYPE_CODE_PTR)
+  if (VALUE_LVAL (arg1) == lval_computed)
     {
-      struct type *enc_type;
+      const struct lval_funcs *funcs = value_computed_funcs (arg1);
 
-      if (VALUE_LVAL (arg1) == lval_computed)
+      if (funcs->indirect)
 	{
-	  const struct lval_funcs *funcs = value_computed_funcs (arg1);
+	  struct value *result = funcs->indirect (arg1);
 
-	  if (funcs->indirect)
-	    {
-	      struct value *result = funcs->indirect (arg1);
-
-	      if (result)
-		return result;
-	    }
+	  if (result)
+	    return result;
 	}
+    }
+
+  if (TYPE_CODE (base_type) == TYPE_CODE_PTR)
+    {
+      struct type *enc_type;
 
       /* We may be pointing to something embedded in a larger object.
          Get the real type of the enclosing object.  */
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -340,7 +340,7 @@ val_print_invalid_address (struct ui_file *stream)
 int
 val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 	   CORE_ADDR address, struct ui_file *stream, int recurse,
-	   struct value *val,
+	   const struct value *val,
 	   const struct value_print_options *options,
 	   const struct language_defn *language)
 {
@@ -555,7 +555,7 @@ val_print_type_code_flags (struct type *type, const gdb_byte *valaddr,
 void
 val_print_scalar_formatted (struct type *type,
 			    const gdb_byte *valaddr, int embedded_offset,
-			    struct value *val,
+			    const struct value *val,
 			    const struct value_print_options *options,
 			    int size,
 			    struct ui_file *stream)
@@ -1189,7 +1189,8 @@ void
 val_print_array_elements (struct type *type,
 			  const gdb_byte *valaddr, int embedded_offset,
 			  CORE_ADDR address, struct ui_file *stream,
-			  int recurse, struct value *val,
+			  int recurse,
+			  const struct value *val,
 			  const struct value_print_options *options,
 			  unsigned int i)
 {
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -115,7 +115,7 @@ extern void maybe_print_array_index (struct type *index_type, LONGEST index,
 
 extern void val_print_array_elements (struct type *, const gdb_byte *, int,
 				      CORE_ADDR, struct ui_file *, int,
-				      struct value *,
+				      const struct value *,
 				      const struct value_print_options *,
 				      unsigned int);
 
@@ -127,7 +127,8 @@ extern void val_print_type_code_flags (struct type *type,
 				       struct ui_file *stream);
 
 extern void val_print_scalar_formatted (struct type *,
-					const gdb_byte *, int, struct value *,
+					const gdb_byte *, int,
+					const struct value *,
 					const struct value_print_options *,
 					int,
 					struct ui_file *);
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -1063,9 +1063,9 @@ set_value_pointed_to_offset (struct value *value, int val)
 }
 
 const struct lval_funcs *
-value_computed_funcs (struct value *v)
+value_computed_funcs (const struct value *v)
 {
-  gdb_assert (VALUE_LVAL (v) == lval_computed);
+  gdb_assert (value_lval_const (v) == lval_computed);
 
   return v->location.computed.funcs;
 }
@@ -1084,6 +1084,12 @@ deprecated_value_lval_hack (struct value *value)
   return &value->lval;
 }
 
+enum lval_type
+value_lval_const (const struct value *value)
+{
+  return value->lval;
+}
+
 CORE_ADDR
 value_address (const struct value *value)
 {
@@ -3083,26 +3089,36 @@ value_from_history_ref (char *h, char **endp)
 }
 
 struct value *
+coerce_ref_if_computed (const struct value *arg)
+{
+  const struct lval_funcs *funcs;
+
+  if (TYPE_CODE (check_typedef (value_type (arg))) != TYPE_CODE_REF)
+    return NULL;
+
+  if (value_lval_const (arg) != lval_computed)
+    return NULL;
+
+  funcs = value_computed_funcs (arg);
+  if (funcs->coerce_ref == NULL)
+    return NULL;
+
+  return funcs->coerce_ref (arg);
+}
+
+struct value *
 coerce_ref (struct value *arg)
 {
   struct type *value_type_arg_tmp = check_typedef (value_type (arg));
+  struct value *retval;
+
+  retval = coerce_ref_if_computed (arg);
+  if (retval)
+    return retval;
 
   if (TYPE_CODE (value_type_arg_tmp) != TYPE_CODE_REF)
     return arg;
 
-  if (VALUE_LVAL (arg) == lval_computed)
-    {
-      const struct lval_funcs *funcs = value_computed_funcs (arg);
-
-      if (funcs->indirect)
-	{
-	  struct value *result = funcs->indirect (arg);
-
-	  if (result)
-	    return result;
-	}
-    }
-
   return value_at_lazy (TYPE_TARGET_TYPE (value_type_arg_tmp),
 			unpack_pointer (value_type (arg),
 					value_contents (arg)));
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -175,14 +175,16 @@ struct lval_funcs
   /* Return 1 if any bit in VALUE is valid, 0 if they are all invalid.  */
   int (*check_any_valid) (const struct value *value);
 
-  /* If non-NULL, this is used to implement pointer and/or reference
-     indirection for this value.  This method may return NULL, in which case
-     value_ind will fall back to ordinary indirection.
-
-     TYPE_CODE (check_typedef (value)) specifies which operation should be
-     done.  It is always either TYPE_CODE_PTR or TYPE_CODE_REF.  */
+  /* If non-NULL, this is used to implement pointer indirection for
+     this value.  This method may return NULL, in which case value_ind
+     will fall back to ordinary indirection.  */
   struct value *(*indirect) (struct value *value);
 
+  /* If non-NULL, this is used to implement reference resolving for
+     this value.  This method may return NULL, in which case coerce_ref
+     will fall back to ordinary references resolving.  */
+  struct value *(*coerce_ref) (const struct value *value);
+
   /* If non-NULL, this is used to determine whether the indicated bits
      of VALUE are a synthetic pointer.  */
   int (*check_synthetic_pointer) (const struct value *value,
@@ -216,7 +218,7 @@ extern struct value *allocate_optimized_out_value (struct type *type);
 
 /* If VALUE is lval_computed, return its lval_funcs structure.  */
 
-extern const struct lval_funcs *value_computed_funcs (struct value *value);
+extern const struct lval_funcs *value_computed_funcs (const struct value *);
 
 /* If VALUE is lval_computed, return its closure.  The meaning of the
    returned value depends on the functions VALUE uses.  */
@@ -317,6 +319,9 @@ extern void set_value_component_location (struct value *component,
 extern enum lval_type *deprecated_value_lval_hack (struct value *);
 #define VALUE_LVAL(val) (*deprecated_value_lval_hack (val))
 
+/* Like VALUE_LVAL, except the parameter can be const.  */
+extern enum lval_type value_lval_const (const struct value *value);
+
 /* If lval == lval_memory, return the address in the inferior.  If
    lval == lval_register, return the byte offset into the registers
    structure.  Otherwise, return 0.  The returned address
@@ -343,6 +348,11 @@ extern struct frame_id *deprecated_value_frame_id_hack (struct value *);
 extern short *deprecated_value_regnum_hack (struct value *);
 #define VALUE_REGNUM(val) (*deprecated_value_regnum_hack (val))
 
+/* Return value after lval_funcs->coerce_ref (after check_typedef).  Return
+   NULL if lval_funcs->coerce_ref is not applicable for whatever reason.  */
+
+extern struct value *coerce_ref_if_computed (const struct value *arg);
+
 /* Convert a REF to the object referenced.  */
 
 extern struct value *coerce_ref (struct value *value);
@@ -793,7 +803,7 @@ extern struct value *value_release_to_mark (struct value *mark);
 extern int val_print (struct type *type, const gdb_byte *valaddr,
 		      int embedded_offset, CORE_ADDR address,
 		      struct ui_file *stream, int recurse,
-		      struct value *val,
+		      const struct value *val,
 		      const struct value_print_options *options,
 		      const struct language_defn *language);
 
@@ -807,28 +817,11 @@ extern int val_print_string (struct type *elttype, const char *encoding,
 			     struct ui_file *stream,
 			     const struct value_print_options *options);
 
-/* Specify how the @entry kind of function parameters should be printed.  */
-enum print_argument
-{
-  /* Symbol is not a function parameter - it is a variable.  */
-  PVAVD_IS_NOT_ARGUMENT,
-
-  /* Symbol is a function parameter, print only its @entry value if it is not
-     redundant together with the normal symbol printed value.  */
-  PVAVD_ARGUMENT_PRINT_ENTRYVAL_ONLY,
-
-  /* Symbol is a function parameter, print its normal value.  Print also its
-     @entry value if it is not redundant together with its normal printed
-     value.  */
-  PVAVD_ARGUMENT_PRINT_BOTH
-};
-
 extern void print_variable_and_value (const char *name,
 				      struct symbol *var,
 				      struct frame_info *frame,
 				      struct ui_file *stream,
-				      int indent,
-				      enum print_argument print_argument);
+				      int indent);
 
 extern int check_field (struct type *, const char *);
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]