[RFA,v2,16/17] Convert dwarf_expr_context_funcs to methods

Message ID 87a8dyhetz.fsf@tromey.com
State New, archived
Headers

Commit Message

Tom Tromey Oct. 20, 2016, 9:48 p.m. UTC
  Pedro> Should we remove the parens throughout?

Tom> I made this change.

Here's the updated version of this patch.
It also fixes some "CTX" comments.

Tom
  

Comments

Pedro Alves Oct. 20, 2016, 9:56 p.m. UTC | #1
On 10/20/2016 10:48 PM, Tom Tromey wrote:
> Pedro> Should we remove the parens throughout?
> 
> Tom> I made this change.
> 
> Here's the updated version of this patch.
> It also fixes some "CTX" comments.

Thanks!  This is OK.
  
Pedro Alves Oct. 28, 2016, 1:35 p.m. UTC | #2
On 10/20/2016 10:48 PM, Tom Tromey wrote:
> Pedro> Should we remove the parens throughout?
> 
> Tom> I made this change.
> 
> Here's the updated version of this patch.
> It also fixes some "CTX" comments.

Unfortunately, this caused regressions:

 https://sourceware.org/ml/gdb-testers/2016-q4/msg01382.html

*** Diff to previous build ***
============================
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: bt
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p &regparam@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: bt
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p i
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p i@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p j
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: tailcall: p j@entry
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: ambiguous: bt
PASS -> FAIL: gdb.arch/amd64-entry-value.exp: self: bt
PASS -> FAIL: gdb.arch/amd64-tailcall-noret.exp: bt
PASS -> FAIL: gdb.dwarf2/dw2-op-call.exp: p arraycallnoloc
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:29
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of x at typeddwarf.c:29
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of y at typeddwarf.c:29
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:53
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of x at typeddwarf.c:53
PASS -> FAIL: gdb.dwarf2/typeddwarf.exp: check value of y at typeddwarf.c:53
============================

I've confirmed that going back to the commit before 
192ca6d8eac4 ("Convert dwarf_expr_context_funcs to methods"),
the FAILs disappear.

Comparing before/after logs, I see:

~~~
-#0  reference (regparam=@0x7fffffffd344: 21, regparam@entry=@0x7fffffffd344: 1, nodataparam=@0x60202c: 22, r3=r3@entry=3, r4=r4@entry=4, r5=r5@entry=5, r6=r6@entry=6, stackparam1=@0x7fffffffd348: 31, stackparam2=@0x7fffffffd34c: 32) at gdb.arch/amd64-entry-value.cc:155
+#0  reference (regparam=@0x7fffffffcf14: 32767, regparam@entry=@0x7fffffffcf54: 1, nodataparam=@0x60202c: 22, r3=r3@entry=3, r4=r4@entry=4, r5=r5@entry=5, r6=r6@entry=6, stackparam1=@0x7fffffffcf58: 31, stackparam2=@0x7fffffffcf5c: 32) at gdb.arch/amd64-entry-value.cc:155
 #1  0x00000000004005d0 in main () at gdb.arch/amd64-entry-value.cc:222
-(gdb) PASS: gdb.arch/amd64-entry-value.exp: entry_reference: bt
+(gdb) FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: bt

-$14 = (int &) @0x7fffffffd344: 21
-(gdb) PASS: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam
+$14 = (int &) @0x7fffffffcf14: 32767
+(gdb) FAIL: gdb.arch/amd64-entry-value.exp: entry_reference: p regparam
~~~

"32767" looks a lot like maybe some unitialized field in one of the classes.

~~~
-Breakpoint 2, d (i=71, i@entry=70, j=73.5, j@entry=72.5) at gdb.arch/amd64-entry-value.cc:34
+Breakpoint 2, d (i=<error reading variable: DWARF-2 expression error: Loop detected (257).>, j=<error reading variable: DWARF-2 expression error: Loop detected (257).>) at
~~~

Many instances of that loop error, actually.

~~~
-$26 = 1
-(gdb) PASS: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:53
+DW_OP_GNU_const_type has different sizes for type and data
+(gdb) FAIL: gdb.dwarf2/typeddwarf.exp: check value of w at typeddwarf.c:53
~~~

~~~
 p arraycallnoloc
-Asked for position 0 of stack, stack only has 0 elements on it.
-(gdb) PASS: gdb.dwarf2/dw2-op-call.exp: p arraycallnoloc
-testcase /home/pedro/gdb/mygit/cxx-convertion/src/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp completed in 1 seconds
+DW_OP_GNU_implicit_pointer is invalid in this context
+(gdb) FAIL: gdb.dwarf2/dw2-op-call.exp: p arraycallnoloc
+testcase /home/pedro/gdb/mygit/cxx-convertion/src/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp completed in 0 seconds
~~~

Could you take a look?  Maybe it'll be obvious to you what
the problem is.

Thanks,
Pedro Alves
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 296c2fe..b2a9844 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,58 @@ 
 2016-10-20  Tom Tromey  <tom@tromey.com>
 
+	* dwarf2loc.c (struct dwarf_expr_context_funcs): Don't declare.
+	(dwarf_expr_read_addr_from_reg, dwarf_expr_get_reg_value)
+	(dwarf_expr_read_mem, dwarf_expr_frame_base): Rename; turn into
+	methods.
+	(get_frame_pc_for_per_cu_dwarf_call): New function.
+	(dwarf_expr_frame_cfa, dwarf_expr_frame_pc)
+	(dwarf_expr_tls_address): Rename; turn into methods.
+	(per_cu_dwarf_call): Remove arguments.  Use
+	get_frame_pc_for_per_cu_dwarf_call.
+	(dwarf_evaluate_loc_desc): New class.
+	(dwarf_expr_dwarf_call, dwarf_expr_context)
+	(dwarf_expr_push_dwarf_reg_entry_value)
+	(dwarf_expr_get_addr_index, dwarf_expr_get_obj_addr): Rename; turn
+	into methods.
+	(dwarf_expr_ctx_funcs): Remove.
+	(dwarf2_evaluate_loc_desc_full): Update.
+	(dwarf2_locexpr_baton_eval): Update.
+	(symbol_needs_eval_context): New class.
+	(symbol_needs_read_addr_from_reg, symbol_needs_get_reg_value)
+	(symbol_needs_read_mem, symbol_needs_frame_base)
+	(symbol_needs_frame_cfa, symbol_needs_tls_address)
+	(symbol_needs_dwarf_call, needs_dwarf_reg_entry_value): Rename;
+	turn into methods.
+	(needs_get_addr_index, needs_get_obj_addr): Remove; turn into
+	methods.
+	(symbol_needs_ctx_funcs): Remove.
+	(dwarf2_loc_desc_get_symbol_read_needs): Update.
+	* dwarf2expr.h (struct dwarf_expr_context_funcs): Remove; turn
+	contents into methods.
+	(struct dwarf_expr_context) <baton, funcs>: Remove.
+	<read_addr_from_reg, get_reg_value, read_mem, get_frame_base,
+	get_frame_cfa, get_frame_pc, get_tls_address, dwarf_call,
+	impl_get_base_type, push_dwarf_block_entry_value, get_addr_index,
+	get_object_address>: Declare new methods.
+	(ctx_no_get_frame_base, ctx_no_get_frame_cfa)
+	(ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call)
+	(ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value)
+	(ctx_no_get_addr_index): Don't declare.
+	* dwarf2expr.c (get_base_type): Use impl_get_base_type.
+	(execute_stack_op): Update.
+	(ctx_no_get_frame_base, ctx_no_get_frame_cfa)
+	(ctx_no_get_frame_pc, ctx_no_get_tls_address, ctx_no_dwarf_call)
+	(ctx_no_get_base_type, ctx_no_push_dwarf_reg_entry_value)
+	(ctx_no_get_addr_index): Remove; now methods on
+	dwarf_expr_context.
+	* dwarf2-frame.c (read_addr_from_reg): Take a frame_info, not a
+	baton.
+	(class dwarf_expr_executor): New class.
+	(get_reg_value, read_mem): Rename, turn into methods.
+	(execute_stack_op): Use dwarf_expr_executor.
+
+2016-10-20  Tom Tromey  <tom@tromey.com>
+
 	* dwarf2loc.c (per_cu_dwarf_call)
 	(dwarf_expr_push_dwarf_reg_entry_value)
 	(dwarf2_evaluate_loc_desc_full, dwarf2_locexpr_baton_eval)
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index c93c362..c9962e1 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -288,33 +288,14 @@  dwarf2_frame_state_free (void *p)
 /* Helper functions for execute_stack_op.  */
 
 static CORE_ADDR
-read_addr_from_reg (void *baton, int reg)
+read_addr_from_reg (struct frame_info *this_frame, int reg)
 {
-  struct frame_info *this_frame = (struct frame_info *) baton;
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
 
   return address_from_register (regnum, this_frame);
 }
 
-/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback.  */
-
-static struct value *
-get_reg_value (void *baton, struct type *type, int reg)
-{
-  struct frame_info *this_frame = (struct frame_info *) baton;
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
-
-  return value_from_register (type, regnum, this_frame);
-}
-
-static void
-read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
-  read_memory (addr, buf, len);
-}
-
 /* Execute the required actions for both the DW_CFA_restore and
 DW_CFA_restore_extended instructions.  */
 static void
@@ -347,21 +328,29 @@  register %s (#%d) at %s"),
     }
 }
 
-/* Virtual method table for execute_stack_op below.  */
-
-static const struct dwarf_expr_context_funcs dwarf2_frame_ctx_funcs =
+class dwarf_expr_executor : public dwarf_expr_context
 {
-  read_addr_from_reg,
-  get_reg_value,
-  read_mem,
-  ctx_no_get_frame_base,
-  ctx_no_get_frame_cfa,
-  ctx_no_get_frame_pc,
-  ctx_no_get_tls_address,
-  ctx_no_dwarf_call,
-  ctx_no_get_base_type,
-  ctx_no_push_dwarf_reg_entry_value,
-  ctx_no_get_addr_index
+ public:
+
+  struct frame_info *this_frame;
+
+  CORE_ADDR read_addr_from_reg (int reg) OVERRIDE
+  {
+    return ::read_addr_from_reg (this_frame, reg);
+  }
+
+  struct value *get_reg_value (struct type *type, int reg) OVERRIDE
+  {
+    struct gdbarch *gdbarch = get_frame_arch (this_frame);
+    int regnum = dwarf_reg_to_regnum_or_error (gdbarch, reg);
+
+    return value_from_register (type, regnum, this_frame);
+  }
+
+  void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) OVERRIDE
+  {
+    read_memory (addr, buf, len);
+  }
 };
 
 static CORE_ADDR
@@ -372,15 +361,14 @@  execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
   CORE_ADDR result;
   struct cleanup *old_chain;
 
-  dwarf_expr_context ctx;
+  dwarf_expr_executor ctx;
   old_chain = make_cleanup_value_free_to_mark (value_mark ());
 
+  ctx.this_frame = this_frame;
   ctx.gdbarch = get_frame_arch (this_frame);
   ctx.addr_size = addr_size;
   ctx.ref_addr_size = -1;
   ctx.offset = offset;
-  ctx.baton = this_frame;
-  ctx.funcs = &dwarf2_frame_ctx_funcs;
 
   ctx.push_address (initial, initial_in_stack_memory);
   ctx.eval (exp, len);
@@ -388,8 +376,7 @@  execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
   if (ctx.location == DWARF_VALUE_MEMORY)
     result = ctx.fetch_address (0);
   else if (ctx.location == DWARF_VALUE_REGISTER)
-    result = read_addr_from_reg (this_frame,
-				 value_as_long (ctx.fetch (0)));
+    result = ctx.read_addr_from_reg (value_as_long (ctx.fetch (0)));
   else
     {
       /* This is actually invalid DWARF, but if we ever do run across
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index 1aa6afc..a01d6d8 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -414,20 +414,11 @@  base_types_equal_p (struct type *t1, struct type *t2)
 struct type *
 dwarf_expr_context::get_base_type (cu_offset die, int size)
 {
-  struct type *result;
-
-  if (this->funcs->get_base_type)
-    {
-      result = this->funcs->get_base_type (this, die);
-      if (result == NULL)
-	error (_("Could not find type for DW_OP_GNU_const_type"));
-      if (size != 0 && TYPE_LENGTH (result) != size)
-	error (_("DW_OP_GNU_const_type has different sizes for type and data"));
-    }
-  else
-    /* Anything will do.  */
-    result = builtin_type (this->gdbarch)->builtin_int;
-
+  struct type *result = this->impl_get_base_type (die);
+  if (result == NULL)
+    error (_("Could not find type for DW_OP_GNU_const_type"));
+  if (size != 0 && TYPE_LENGTH (result) != size)
+    error (_("DW_OP_GNU_const_type has different sizes for type and data"));
   return result;
 }
 
@@ -698,13 +689,13 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	case DW_OP_GNU_addr_index:
 	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
-	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
+	  result = this->get_addr_index (uoffset);
 	  result += this->offset;
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 	case DW_OP_GNU_const_index:
 	  op_ptr = safe_read_uleb128 (op_ptr, op_end, &uoffset);
-	  result = (this->funcs->get_addr_index) (this->baton, uoffset);
+	  result = this->get_addr_index (uoffset);
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -888,8 +879,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	case DW_OP_breg31:
 	  {
 	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
-	    result = (this->funcs->read_addr_from_reg) (this->baton,
-						       op - DW_OP_breg0);
+	    result = this->read_addr_from_reg (op - DW_OP_breg0);
 	    result += offset;
 	    result_val = value_from_ulongest (address_type, result);
 	  }
@@ -898,7 +888,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  {
 	    op_ptr = safe_read_uleb128 (op_ptr, op_end, &reg);
 	    op_ptr = safe_read_sleb128 (op_ptr, op_end, &offset);
-	    result = (this->funcs->read_addr_from_reg) (this->baton, reg);
+	    result = this->read_addr_from_reg (reg);
 	    result += offset;
 	    result_val = value_from_ulongest (address_type, result);
 	  }
@@ -918,14 +908,12 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    /* FIXME: cagney/2003-03-26: This code should be using
                get_frame_base_address(), and then implement a dwarf2
                specific this_base method.  */
-	    (this->funcs->get_frame_base) (this->baton, &datastart, &datalen);
+	    this->get_frame_base (&datastart, &datalen);
 	    eval (datastart, datalen);
 	    if (this->location == DWARF_VALUE_MEMORY)
 	      result = fetch_address (0);
 	    else if (this->location == DWARF_VALUE_REGISTER)
-	      result = (this->funcs->read_addr_from_reg)
-			  (this->baton,
-			   value_as_long (fetch (0)));
+	      result = this->read_addr_from_reg (value_as_long (fetch (0)));
 	    else
 	      error (_("Not implemented: computing frame "
 		       "base using explicit value operator"));
@@ -1011,7 +999,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    else
 	      type = address_type;
 
-	    (this->funcs->read_mem) (this->baton, buf, addr, addr_size);
+	    this->read_mem (buf, addr, addr_size);
 
 	    /* If the size of the object read from memory is different
 	       from the type length, we need to zero-extend it.  */
@@ -1220,7 +1208,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  break;
 
 	case DW_OP_call_frame_cfa:
-	  result = (this->funcs->get_frame_cfa) (this->baton);
+	  result = this->get_frame_cfa ();
 	  result_val = value_from_ulongest (address_type, result);
 	  in_stack_memory = 1;
 	  break;
@@ -1237,7 +1225,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	  returned.  */
 	  result = value_as_long (fetch (0));
 	  pop ();
-	  result = (this->funcs->get_tls_address) (this->baton, result);
+	  result = this->get_tls_address (result);
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -1313,7 +1301,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	    offset.cu_off = extract_unsigned_integer (op_ptr, 2, byte_order);
 	    op_ptr += 2;
-	    this->funcs->dwarf_call (this, offset);
+	    this->dwarf_call (offset);
 	  }
 	  goto no_push;
 
@@ -1323,7 +1311,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	    offset.cu_off = extract_unsigned_integer (op_ptr, 4, byte_order);
 	    op_ptr += 4;
-	    this->funcs->dwarf_call (this, offset);
+	    this->dwarf_call (offset);
 	  }
 	  goto no_push;
 	
@@ -1341,10 +1329,9 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    if (kind_u.dwarf_reg != -1)
 	      {
 		op_ptr += len;
-		this->funcs->push_dwarf_reg_entry_value (this,
-						  CALL_SITE_PARAMETER_DWARF_REG,
-							kind_u,
-							-1 /* deref_size */);
+		this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG,
+						  kind_u,
+						  -1 /* deref_size */);
 		goto no_push;
 	      }
 
@@ -1356,9 +1343,8 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 		if (deref_size == -1)
 		  deref_size = this->addr_size;
 		op_ptr += len;
-		this->funcs->push_dwarf_reg_entry_value (this,
-						  CALL_SITE_PARAMETER_DWARF_REG,
-							kind_u, deref_size);
+		this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_DWARF_REG,
+						  kind_u, deref_size);
 		goto no_push;
 	      }
 
@@ -1374,10 +1360,9 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    kind_u.param_offset.cu_off = extract_unsigned_integer (op_ptr, 4,
 								   byte_order);
 	    op_ptr += 4;
-	    this->funcs->push_dwarf_reg_entry_value (this,
-					       CALL_SITE_PARAMETER_PARAM_OFFSET,
-						    kind_u,
-						    -1 /* deref_size */);
+	    this->push_dwarf_reg_entry_value (CALL_SITE_PARAMETER_PARAM_OFFSET,
+					      kind_u,
+					      -1 /* deref_size */);
 	  }
 	  goto no_push;
 
@@ -1409,7 +1394,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 	    type_die.cu_off = uoffset;
 
 	    type = get_base_type (type_die, 0);
-	    result_val = this->funcs->get_reg_value (this->baton, type, reg);
+	    result_val = this->get_reg_value (type, reg);
 	  }
 	  break;
 
@@ -1448,7 +1433,7 @@  dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
 
 	case DW_OP_push_object_address:
 	  /* Return the address of the object we are currently observing.  */
-	  result = (this->funcs->get_object_address) (this->baton);
+	  result = this->get_object_address ();
 	  result_val = value_from_ulongest (address_type, result);
 	  break;
 
@@ -1474,75 +1459,6 @@  abort_expression:
   gdb_assert (this->recursion_depth >= 0);
 }
 
-/* Stub dwarf_expr_context_funcs.get_frame_base implementation.  */
-
-void
-ctx_no_get_frame_base (void *baton, const gdb_byte **start, size_t *length)
-{
-  error (_("%s is invalid in this context"), "DW_OP_fbreg");
-}
-
-/* Stub dwarf_expr_context_funcs.get_frame_cfa implementation.  */
-
-CORE_ADDR
-ctx_no_get_frame_cfa (void *baton)
-{
-  error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa");
-}
-
-/* Stub dwarf_expr_context_funcs.get_frame_pc implementation.  */
-
-CORE_ADDR
-ctx_no_get_frame_pc (void *baton)
-{
-  error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer");
-}
-
-/* Stub dwarf_expr_context_funcs.get_tls_address implementation.  */
-
-CORE_ADDR
-ctx_no_get_tls_address (void *baton, CORE_ADDR offset)
-{
-  error (_("%s is invalid in this context"), "DW_OP_form_tls_address");
-}
-
-/* Stub dwarf_expr_context_funcs.dwarf_call implementation.  */
-
-void
-ctx_no_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
-{
-  error (_("%s is invalid in this context"), "DW_OP_call*");
-}
-
-/* Stub dwarf_expr_context_funcs.get_base_type implementation.  */
-
-struct type *
-ctx_no_get_base_type (struct dwarf_expr_context *ctx, cu_offset 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,
-				   enum call_site_parameter_kind kind,
-				   union call_site_parameter_u kind_u,
-				   int deref_size)
-{
-  internal_error (__FILE__, __LINE__,
-		  _("Support for DW_OP_GNU_entry_value is unimplemented"));
-}
-
-/* Stub dwarf_expr_context_funcs.get_addr_index implementation.  */
-
-CORE_ADDR
-ctx_no_get_addr_index (void *baton, unsigned int index)
-{
-  error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index");
-}
-
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_dwarf2expr;
 
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 4706bb3..63bdc6e 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -25,69 +25,6 @@ 
 #include "leb128.h"
 #include "gdbtypes.h"
 
-struct dwarf_expr_context;
-
-/* Virtual method table for struct dwarf_expr_context below.  */
-
-struct dwarf_expr_context_funcs
-{
-  /* Return the value of register number REGNUM (a DWARF register number),
-     read as an address.  */
-  CORE_ADDR (*read_addr_from_reg) (void *baton, int regnum);
-
-  /* Return a value of type TYPE, stored in register number REGNUM
-     of the frame associated to the given BATON.
-
-     REGNUM is a DWARF register number.  */
-  struct value *(*get_reg_value) (void *baton, struct type *type, int regnum);
-
-  /* Read LENGTH bytes at ADDR into BUF.  */
-  void (*read_mem) (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t length);
-
-  /* Return the location expression for the frame base attribute, in
-     START and LENGTH.  The result must be live until the current
-     expression evaluation is complete.  */
-  void (*get_frame_base) (void *baton, const gdb_byte **start, size_t *length);
-
-  /* Return the CFA for the frame.  */
-  CORE_ADDR (*get_frame_cfa) (void *baton);
-
-  /* Return the PC for the frame.  */
-  CORE_ADDR (*get_frame_pc) (void *baton);
-
-  /* Return the thread-local storage address for
-     DW_OP_GNU_push_tls_address or DW_OP_form_tls_address.  */
-  CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset);
-
-  /* Execute DW_AT_location expression for the DWARF expression subroutine in
-     the DIE at DIE_OFFSET in the CU from CTX.  Do not touch STACK while it
-     being passed to and returned from the called DWARF subroutine.  */
-  void (*dwarf_call) (struct dwarf_expr_context *ctx, cu_offset die_offset);
-
-  /* Return the base type given by the indicated DIE.  This can throw
-     an exception if the DIE is invalid or does not represent a base
-     type.  If can also be NULL in the special case where the
-     callbacks are not performing evaluation, and thus it is
-     meaningful to substitute a stub type of the correct size.  */
-  struct type *(*get_base_type) (struct dwarf_expr_context *ctx, cu_offset die);
-
-  /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's
-     parameter matching KIND and KIND_U at the caller of specified BATON.
-     If DEREF_SIZE is not -1 then use 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,
-				      enum call_site_parameter_kind kind,
-				      union call_site_parameter_u kind_u,
-				      int deref_size);
-
-  /* Return the address indexed by DW_OP_GNU_addr_index.
-     This can throw an exception if the index is out of range.  */
-  CORE_ADDR (*get_addr_index) (void *baton, unsigned int index);
-
-  /* Return the `object address' for DW_OP_push_object_address.  */
-  CORE_ADDR (*get_object_address) (void *baton);
-};
-
 /* The location of a value.  */
 enum dwarf_value_location
 {
@@ -159,13 +96,6 @@  struct dwarf_expr_context
   /* Offset used to relocate DW_OP_addr and DW_OP_GNU_addr_index arguments.  */
   CORE_ADDR offset;
 
-  /* An opaque argument provided by the caller, which will be passed
-     to all of the callback functions.  */
-  void *baton;
-
-  /* Callback functions.  */
-  const struct dwarf_expr_context_funcs *funcs;
-
   /* The current depth of dwarf expression recursion, via DW_OP_call*,
      DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum
      depth we'll tolerate before raising an error.  */
@@ -210,6 +140,93 @@  struct dwarf_expr_context
   int num_pieces;
   struct dwarf_expr_piece *pieces;
 
+  /* Return the value of register number REGNUM (a DWARF register number),
+     read as an address.  */
+  virtual CORE_ADDR read_addr_from_reg (int regnum) = 0;
+
+  /* Return a value of type TYPE, stored in register number REGNUM
+     of the frame associated to the given BATON.
+
+     REGNUM is a DWARF register number.  */
+  virtual struct value *get_reg_value (struct type *type, int regnum) = 0;
+
+  /* Read LENGTH bytes at ADDR into BUF.  */
+  virtual void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t length) = 0;
+
+  /* Return the location expression for the frame base attribute, in
+     START and LENGTH.  The result must be live until the current
+     expression evaluation is complete.  */
+  virtual void get_frame_base (const gdb_byte **start, size_t *length)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_fbreg");
+  }
+
+  /* Return the CFA for the frame.  */
+  virtual CORE_ADDR get_frame_cfa ()
+  {
+    error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa");
+  }
+
+  /* Return the PC for the frame.  */
+  virtual CORE_ADDR get_frame_pc ()
+  {
+    error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer");
+  }
+
+  /* Return the thread-local storage address for
+     DW_OP_GNU_push_tls_address or DW_OP_form_tls_address.  */
+  virtual CORE_ADDR get_tls_address (CORE_ADDR offset)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_form_tls_address");
+  }
+
+  /* Execute DW_AT_location expression for the DWARF expression
+     subroutine in the DIE at DIE_OFFSET in the CU.  Do not touch
+     STACK while it being passed to and returned from the called DWARF
+     subroutine.  */
+  virtual void dwarf_call (cu_offset die_offset)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_call*");
+  }
+
+  /* Return the base type given by the indicated DIE.  This can throw
+     an exception if the DIE is invalid or does not represent a base
+     type.  If can also be NULL in the special case where the
+     callbacks are not performing evaluation, and thus it is
+     meaningful to substitute a stub type of the correct size.  */
+  virtual struct type *impl_get_base_type (cu_offset die)
+  {
+    /* Anything will do.  */
+    return builtin_type (this->gdbarch)->builtin_int;
+  }
+
+  /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's
+     parameter matching KIND and KIND_U at the caller of specified BATON.
+     If DEREF_SIZE is not -1 then use DW_AT_GNU_call_site_data_value instead of
+     DW_AT_GNU_call_site_value.  */
+  virtual void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+					   union call_site_parameter_u kind_u,
+					   int deref_size)
+  {
+    internal_error (__FILE__, __LINE__,
+		    _("Support for DW_OP_GNU_entry_value is unimplemented"));
+  }
+
+  /* Return the address indexed by DW_OP_GNU_addr_index.
+     This can throw an exception if the index is out of range.  */
+  virtual CORE_ADDR get_addr_index (unsigned int index)
+  {
+    error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index");
+  }
+
+  /* Return the `object address' for DW_OP_push_object_address.  */
+  virtual CORE_ADDR get_object_address ()
+  {
+    internal_error (__FILE__, __LINE__,
+		    _("Support for DW_OP_push_object_address "
+		      "is unimplemented"));
+  }
+
 private:
 
   struct type *address_type () const;
@@ -273,22 +290,6 @@  struct dwarf_expr_piece
 void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *,
 				     const char *);
 
-/* Stub dwarf_expr_context_funcs implementations.  */
-
-void ctx_no_get_frame_base (void *baton, const gdb_byte **start,
-			    size_t *length);
-CORE_ADDR ctx_no_get_frame_cfa (void *baton);
-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, cu_offset die_offset);
-struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx,
-				   cu_offset die);
-void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-					enum call_site_parameter_kind kind,
-					union call_site_parameter_u kind_u,
-					int deref_size);
-CORE_ADDR ctx_no_get_addr_index (void *baton, unsigned int index);
-
 int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end);
 
 int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf,
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 1f946df..6f25314 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -43,8 +43,6 @@ 
 
 extern int dwarf_always_disassemble;
 
-extern const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs;
-
 static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
 						    struct frame_info *frame,
 						    const gdb_byte *data,
@@ -52,6 +50,12 @@  static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
 						    struct dwarf2_per_cu_data *per_cu,
 						    LONGEST byte_offset);
 
+static struct call_site_parameter *dwarf_expr_reg_to_entry_parameter
+    (struct frame_info *frame,
+     enum call_site_parameter_kind kind,
+     union call_site_parameter_u kind_u,
+     struct dwarf2_per_cu_data **per_cu_return);
+
 /* Until these have formal names, we define these here.
    ref: http://gcc.gnu.org/wiki/DebugFission
    Each entry in .debug_loc.dwo begins with a byte that describes the entry,
@@ -311,71 +315,6 @@  struct dwarf_expr_baton
   CORE_ADDR obj_address;
 };
 
-/* Helper functions for dwarf2_evaluate_loc_desc.  */
-
-/* Using the frame specified in BATON, return the value of register
-   REGNUM, treated as a pointer.  */
-static CORE_ADDR
-dwarf_expr_read_addr_from_reg (void *baton, int dwarf_regnum)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct gdbarch *gdbarch = get_frame_arch (debaton->frame);
-  int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
-  return address_from_register (regnum, debaton->frame);
-}
-
-/* Implement struct dwarf_expr_context_funcs' "get_reg_value" callback.  */
-
-static struct value *
-dwarf_expr_get_reg_value (void *baton, struct type *type, int dwarf_regnum)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct gdbarch *gdbarch = get_frame_arch (debaton->frame);
-  int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
-
-  return value_from_register (type, regnum, debaton->frame);
-}
-
-/* Read memory at ADDR (length LEN) into BUF.  */
-
-static void
-dwarf_expr_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
-  read_memory (addr, buf, len);
-}
-
-/* Using the frame specified in BATON, find the location expression
-   describing the frame base.  Return a pointer to it in START and
-   its length in LENGTH.  */
-static void
-dwarf_expr_frame_base (void *baton, const gdb_byte **start, size_t * length)
-{
-  /* FIXME: cagney/2003-03-26: This code should be using
-     get_frame_base_address(), and then implement a dwarf2 specific
-     this_base method.  */
-  struct symbol *framefunc;
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  const struct block *bl = get_frame_block (debaton->frame, NULL);
-
-  if (bl == NULL)
-    error (_("frame address is not available."));
-
-  /* Use block_linkage_function, which returns a real (not inlined)
-     function, instead of get_frame_function, which may return an
-     inlined function.  */
-  framefunc = block_linkage_function (bl);
-
-  /* If we found a frame-relative symbol then it was certainly within
-     some function associated with a frame. If we can't find the frame,
-     something has gone wrong.  */
-  gdb_assert (framefunc != NULL);
-
-  func_get_frame_base_dwarf_block (framefunc,
-				   get_frame_address_in_block (debaton->frame),
-				   start, length);
-}
-
 /* Implement find_frame_base_location method for LOC_BLOCK functions using
    DWARF expression for its DW_AT_frame_base.  */
 
@@ -511,52 +450,23 @@  func_get_frame_base_dwarf_block (struct symbol *framefunc, CORE_ADDR pc,
 	   SYMBOL_NATURAL_NAME (framefunc));
 }
 
-/* Helper function for dwarf2_evaluate_loc_desc.  Computes the CFA for
-   the frame in BATON.  */
-
-static CORE_ADDR
-dwarf_expr_frame_cfa (void *baton)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  return dwarf2_frame_cfa (debaton->frame);
-}
-
-/* Helper function for dwarf2_evaluate_loc_desc.  Computes the PC for
-   the frame in BATON.  */
-
-static CORE_ADDR
-dwarf_expr_frame_pc (void *baton)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  return get_frame_address_in_block (debaton->frame);
-}
-
-/* Using the objfile specified in BATON, find the address for the
-   current thread's thread-local storage with offset OFFSET.  */
 static CORE_ADDR
-dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
+get_frame_pc_for_per_cu_dwarf_call (void *baton)
 {
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct objfile *objfile = dwarf2_per_cu_objfile (debaton->per_cu);
+  dwarf_expr_context *ctx = (dwarf_expr_context *) baton;
 
-  return target_translate_tls_address (objfile, offset);
+  return ctx->get_frame_pc ();
 }
 
-/* Call DWARF subroutine from DW_AT_location of DIE at DIE_OFFSET in
-   current CU (as is PER_CU).  State of the CTX is not affected by the
-   call and return.  */
-
 static void
 per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset,
-		   struct dwarf2_per_cu_data *per_cu,
-		   CORE_ADDR (*get_frame_pc) (void *baton),
-		   void *baton)
+		   struct dwarf2_per_cu_data *per_cu)
 {
   struct dwarf2_locexpr_baton block;
 
-  block = dwarf2_fetch_die_loc_cu_off (die_offset, per_cu, get_frame_pc, baton);
+  block = dwarf2_fetch_die_loc_cu_off (die_offset, per_cu,
+				       get_frame_pc_for_per_cu_dwarf_call,
+				       ctx);
 
   /* DW_OP_call_ref is currently not supported.  */
   gdb_assert (block.per_cu == per_cu);
@@ -564,27 +474,173 @@  per_cu_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset,
   ctx->eval (block.data, block.size);
 }
 
-/* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc.  */
-
-static void
-dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
+class dwarf_evaluate_loc_desc : public dwarf_expr_context
 {
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton;
+ public:
 
-  per_cu_dwarf_call (ctx, die_offset, debaton->per_cu,
-		     ctx->funcs->get_frame_pc, ctx->baton);
-}
+  struct frame_info *frame;
+  struct dwarf2_per_cu_data *per_cu;
+  CORE_ADDR obj_address;
 
-/* Callback function for dwarf2_evaluate_loc_desc.  */
+  /* Helper function for dwarf2_evaluate_loc_desc.  Computes the CFA for
+     the frame in BATON.  */
 
-static struct type *
-dwarf_expr_get_base_type (struct dwarf_expr_context *ctx,
-			  cu_offset die_offset)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) ctx->baton;
+  CORE_ADDR get_frame_cfa () OVERRIDE
+  {
+    return dwarf2_frame_cfa (frame);
+  }
 
-  return dwarf2_get_die_type (die_offset, debaton->per_cu);
-}
+  /* Helper function for dwarf2_evaluate_loc_desc.  Computes the PC for
+     the frame in BATON.  */
+
+  CORE_ADDR get_frame_pc () OVERRIDE
+  {
+    return get_frame_address_in_block (frame);
+  }
+
+  /* Using the objfile specified in BATON, find the address for the
+     current thread's thread-local storage with offset OFFSET.  */
+  CORE_ADDR get_tls_address (CORE_ADDR offset) OVERRIDE
+  {
+    struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
+
+    return target_translate_tls_address (objfile, offset);
+  }
+
+  /* Helper interface of per_cu_dwarf_call for
+     dwarf2_evaluate_loc_desc.  */
+
+  void dwarf_call (cu_offset die_offset) OVERRIDE
+  {
+    per_cu_dwarf_call (this, die_offset, per_cu);
+  }
+
+  /* Callback function for dwarf2_evaluate_loc_desc.  */
+  struct type *impl_get_base_type (cu_offset die_offset) OVERRIDE
+  {
+    return dwarf2_get_die_type (die_offset, per_cu);
+  }
+
+  /* Callback function for dwarf2_evaluate_loc_desc.
+     Fetch the address indexed by DW_OP_GNU_addr_index.  */
+
+  CORE_ADDR get_addr_index (unsigned int index) OVERRIDE
+  {
+    return dwarf2_read_addr_index (per_cu, index);
+  }
+
+  /* Callback function for get_object_address. Return the address of the VLA
+     object.  */
+
+  CORE_ADDR get_object_address () OVERRIDE
+  {
+    if (obj_address == 0)
+      error (_("Location address is not set."));
+    return obj_address;
+  }
+
+  /* Execute DWARF block of call_site_parameter which matches KIND and
+     KIND_U.  Choose DEREF_SIZE value of that parameter.  Search
+     caller of this objects's frame.
+
+     The 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.  */
+
+  void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+				   union call_site_parameter_u kind_u,
+				   int deref_size) OVERRIDE
+  {
+    struct frame_info *caller_frame;
+    struct dwarf2_per_cu_data *caller_per_cu;
+    struct dwarf_expr_baton baton_local;
+    struct call_site_parameter *parameter;
+    const gdb_byte *data_src;
+    size_t size;
+
+    caller_frame = get_prev_frame (frame);
+
+    parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
+						   &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 = caller_per_cu;
+    baton_local.obj_address = 0;
+
+    scoped_restore save_arch = make_scoped_restore (&this->gdbarch);
+    this->gdbarch
+      = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
+    scoped_restore save_addr_size = make_scoped_restore (&this->addr_size);
+    this->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
+    scoped_restore save_offset = make_scoped_restore (&this->offset);
+    this->offset = dwarf2_per_cu_text_offset (baton_local.per_cu);
+
+    this->eval (data_src, size);
+  }
+
+  /* Using the frame specified in BATON, find the location expression
+     describing the frame base.  Return a pointer to it in START and
+     its length in LENGTH.  */
+  void get_frame_base (const gdb_byte **start, size_t * length) OVERRIDE
+  {
+    /* FIXME: cagney/2003-03-26: This code should be using
+       get_frame_base_address(), and then implement a dwarf2 specific
+       this_base method.  */
+    struct symbol *framefunc;
+    const struct block *bl = get_frame_block (frame, NULL);
+
+    if (bl == NULL)
+      error (_("frame address is not available."));
+
+    /* Use block_linkage_function, which returns a real (not inlined)
+       function, instead of get_frame_function, which may return an
+       inlined function.  */
+    framefunc = block_linkage_function (bl);
+
+    /* If we found a frame-relative symbol then it was certainly within
+       some function associated with a frame. If we can't find the frame,
+       something has gone wrong.  */
+    gdb_assert (framefunc != NULL);
+
+    func_get_frame_base_dwarf_block (framefunc,
+				     get_frame_address_in_block (frame),
+				     start, length);
+  }
+
+  /* Read memory at ADDR (length LEN) into BUF.  */
+
+  void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) OVERRIDE
+  {
+    read_memory (addr, buf, len);
+  }
+
+  /* Using the frame specified in BATON, return the value of register
+     REGNUM, treated as a pointer.  */
+  CORE_ADDR read_addr_from_reg (int dwarf_regnum) OVERRIDE
+  {
+    struct gdbarch *gdbarch = get_frame_arch (frame);
+    int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
+
+    return address_from_register (regnum, frame);
+  }
+
+  /* Implement "get_reg_value" callback.  */
+
+  struct value *get_reg_value (struct type *type, int dwarf_regnum) OVERRIDE
+  {
+    struct gdbarch *gdbarch = get_frame_arch (frame);
+    int regnum = dwarf_reg_to_regnum_or_error (gdbarch, dwarf_regnum);
+
+    return value_from_register (type, regnum, frame);
+  }
+};
 
 /* See dwarf2loc.h.  */
 
@@ -1250,91 +1306,6 @@  dwarf_entry_parameter_to_value (struct call_site_parameter *parameter,
   return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu);
 }
 
-/* Execute DWARF block of call_site_parameter which matches KIND and KIND_U.
-   Choose DEREF_SIZE value of that parameter.  Search caller of the CTX's
-   frame.  CTX must be of dwarf_expr_ctx_funcs kind.
-
-   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,
-				       enum call_site_parameter_kind kind,
-				       union call_site_parameter_u kind_u,
-				       int deref_size)
-{
-  struct dwarf_expr_baton *debaton;
-  struct frame_info *frame, *caller_frame;
-  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 = (struct dwarf_expr_baton *) ctx->baton;
-  frame = debaton->frame;
-  caller_frame = get_prev_frame (frame);
-
-  parameter = dwarf_expr_reg_to_entry_parameter (frame, kind, kind_u,
-						 &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 = caller_per_cu;
-  baton_local.obj_address = 0;
-
-  saved_ctx.gdbarch = ctx->gdbarch;
-  saved_ctx.addr_size = ctx->addr_size;
-  saved_ctx.offset = ctx->offset;
-  saved_ctx.baton = ctx->baton;
-  ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu));
-  ctx->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu);
-  ctx->offset = dwarf2_per_cu_text_offset (baton_local.per_cu);
-  ctx->baton = &baton_local;
-
-  ctx->eval (data_src, size);
-
-  ctx->gdbarch = saved_ctx.gdbarch;
-  ctx->addr_size = saved_ctx.addr_size;
-  ctx->offset = saved_ctx.offset;
-  ctx->baton = saved_ctx.baton;
-}
-
-/* Callback function for dwarf2_evaluate_loc_desc.
-   Fetch the address indexed by DW_OP_GNU_addr_index.  */
-
-static CORE_ADDR
-dwarf_expr_get_addr_index (void *baton, unsigned int index)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  return dwarf2_read_addr_index (debaton->per_cu, index);
-}
-
-/* Callback function for get_object_address. Return the address of the VLA
-   object.  */
-
-static CORE_ADDR
-dwarf_expr_get_obj_addr (void *baton)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-
-  gdb_assert (debaton != NULL);
-
-  if (debaton->obj_address == 0)
-    error (_("Location address is not set."));
-
-  return debaton->obj_address;
-}
-
 /* 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..  */
@@ -2263,24 +2234,6 @@  static const struct lval_funcs pieced_value_funcs = {
   free_pieced_value_closure
 };
 
-/* Virtual method table for dwarf2_evaluate_loc_desc_full below.  */
-
-const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs =
-{
-  dwarf_expr_read_addr_from_reg,
-  dwarf_expr_get_reg_value,
-  dwarf_expr_read_mem,
-  dwarf_expr_frame_base,
-  dwarf_expr_frame_cfa,
-  dwarf_expr_frame_pc,
-  dwarf_expr_tls_address,
-  dwarf_expr_dwarf_call,
-  dwarf_expr_get_base_type,
-  dwarf_expr_push_dwarf_reg_entry_value,
-  dwarf_expr_get_addr_index,
-  dwarf_expr_get_obj_addr
-};
-
 /* Evaluate a location description, starting at DATA and with length
    SIZE, to find the current location of variable of TYPE in the
    context of FRAME.  BYTE_OFFSET is applied after the contents are
@@ -2293,7 +2246,6 @@  dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 			       LONGEST byte_offset)
 {
   struct value *retval;
-  struct dwarf_expr_baton baton;
   struct cleanup *value_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
@@ -2303,19 +2255,17 @@  dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
   if (size == 0)
     return allocate_optimized_out_value (type);
 
-  baton.frame = frame;
-  baton.per_cu = per_cu;
-  baton.obj_address = 0;
+  dwarf_evaluate_loc_desc ctx;
+  ctx.frame = frame;
+  ctx.per_cu = per_cu;
+  ctx.obj_address = 0;
 
-  dwarf_expr_context ctx;
   value_chain = make_cleanup_value_free_to_mark (value_mark ());
 
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
   ctx.offset = dwarf2_per_cu_text_offset (per_cu);
-  ctx.baton = &baton;
-  ctx.funcs = &dwarf_expr_ctx_funcs;
 
   TRY
     {
@@ -2537,18 +2487,17 @@  dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
 			   CORE_ADDR addr,
 			   CORE_ADDR *valp)
 {
-  struct dwarf_expr_baton baton;
   struct objfile *objfile;
   struct cleanup *cleanup;
 
   if (dlbaton == NULL || dlbaton->size == 0)
     return 0;
 
-  dwarf_expr_context ctx;
+  dwarf_evaluate_loc_desc ctx;
 
-  baton.frame = frame;
-  baton.per_cu = dlbaton->per_cu;
-  baton.obj_address = addr;
+  ctx.frame = frame;
+  ctx.per_cu = dlbaton->per_cu;
+  ctx.obj_address = addr;
 
   objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
 
@@ -2556,8 +2505,6 @@  dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
   ctx.addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
   ctx.offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
-  ctx.funcs = &dwarf_expr_ctx_funcs;
-  ctx.baton = &baton;
 
   ctx.eval (dlbaton->data, dlbaton->size);
 
@@ -2568,7 +2515,7 @@  dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
     case DWARF_VALUE_STACK:
       *valp = ctx.fetch_address (0);
       if (ctx.location == DWARF_VALUE_REGISTER)
-	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
+	*valp = ctx.read_addr_from_reg (*valp);
       return 1;
     case DWARF_VALUE_LITERAL:
       *valp = extract_signed_integer (ctx.data, ctx.len,
@@ -2713,140 +2660,97 @@  dwarf2_compile_property_to_c (struct ui_file *stream,
 
 /* Helper functions and baton for dwarf2_loc_desc_get_symbol_read_needs.  */
 
-struct symbol_needs_baton
+class symbol_needs_eval_context : public dwarf_expr_context
 {
+ public:
+
   enum symbol_needs_kind needs;
   struct dwarf2_per_cu_data *per_cu;
-};
-
-/* Reads from registers do require a frame.  */
-static CORE_ADDR
-symbol_needs_read_addr_from_reg (void *baton, int regnum)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-  return 1;
-}
-
-/* struct dwarf_expr_context_funcs' "get_reg_value" callback:
-   Reads from registers do require a frame.  */
-
-static struct value *
-symbol_needs_get_reg_value (void *baton, struct type *type, int regnum)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-  return value_zero (type, not_lval);
-}
-
-/* Reads from memory do not require a frame.  */
-static void
-symbol_needs_read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len)
-{
-  memset (buf, 0, len);
-}
-
-/* Frame-relative accesses do require a frame.  */
-static void
-symbol_needs_frame_base (void *baton, const gdb_byte **start, size_t * length)
-{
-  static gdb_byte lit0 = DW_OP_lit0;
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  *start = &lit0;
-  *length = 1;
 
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-}
-
-/* CFA accesses require a frame.  */
-
-static CORE_ADDR
-symbol_needs_frame_cfa (void *baton)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-  return 1;
-}
-
-/* Thread-local accesses require registers, but not a frame.  */
-static CORE_ADDR
-symbol_needs_tls_address (void *baton, CORE_ADDR offset)
-{
-  struct symbol_needs_baton *nf_baton = (struct symbol_needs_baton *) baton;
-
-  if (nf_baton->needs <= SYMBOL_NEEDS_REGISTERS)
-    nf_baton->needs = SYMBOL_NEEDS_REGISTERS;
-  return 1;
-}
-
-/* Helper interface of per_cu_dwarf_call for
-   dwarf2_loc_desc_get_symbol_read_needs.  */
-
-static void
-symbol_needs_dwarf_call (struct dwarf_expr_context *ctx, cu_offset die_offset)
-{
-  struct symbol_needs_baton *nf_baton =
-    (struct symbol_needs_baton *) ctx->baton;
-
-  per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu,
-		     ctx->funcs->get_frame_pc, ctx->baton);
-}
-
-/* DW_OP_GNU_entry_value accesses require a caller, therefore a frame.  */
-
-static void
-needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
-			     enum call_site_parameter_kind kind,
-			     union call_site_parameter_u kind_u, int deref_size)
-{
-  struct symbol_needs_baton *nf_baton =
-    (struct symbol_needs_baton *) ctx->baton;
-
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
-
-  /* The expression may require some stub values on DWARF stack.  */
-  ctx->push_address (0, 0);
-}
-
-/* DW_OP_GNU_addr_index doesn't require a frame.  */
+  /* Reads from registers do require a frame.  */
+  CORE_ADDR read_addr_from_reg (int regnum) OVERRIDE
+  {
+    needs = SYMBOL_NEEDS_FRAME;
+    return 1;
+  }
+
+  /* "get_reg_value" callback: Reads from registers do require a
+     frame.  */
+
+  struct value *get_reg_value (struct type *type, int regnum) OVERRIDE
+  {
+    needs = SYMBOL_NEEDS_FRAME;
+    return value_zero (type, not_lval);
+  }
+
+  /* Reads from memory do not require a frame.  */
+  void read_mem (gdb_byte *buf, CORE_ADDR addr, size_t len) OVERRIDE
+  {
+    memset (buf, 0, len);
+  }
+
+  /* Frame-relative accesses do require a frame.  */
+  void get_frame_base (const gdb_byte **start, size_t *length) OVERRIDE
+  {
+    static gdb_byte lit0 = DW_OP_lit0;
+
+    *start = &lit0;
+    *length = 1;
+
+    needs = SYMBOL_NEEDS_FRAME;
+  }
+
+  /* CFA accesses require a frame.  */
+  CORE_ADDR get_frame_cfa () OVERRIDE
+  {
+    needs = SYMBOL_NEEDS_FRAME;
+    return 1;
+  }
+
+  /* Thread-local accesses require registers, but not a frame.  */
+  CORE_ADDR get_tls_address (CORE_ADDR offset) OVERRIDE
+  {
+    if (needs <= SYMBOL_NEEDS_REGISTERS)
+      needs = SYMBOL_NEEDS_REGISTERS;
+    return 1;
+  }
+
+  /* Helper interface of per_cu_dwarf_call for
+     dwarf2_loc_desc_get_symbol_read_needs.  */
+
+  void dwarf_call (cu_offset die_offset) OVERRIDE
+  {
+    per_cu_dwarf_call (this, die_offset, per_cu);
+  }
+
+  /* DW_OP_GNU_entry_value accesses require a caller, therefore a
+     frame.  */
+
+  void push_dwarf_reg_entry_value (enum call_site_parameter_kind kind,
+				   union call_site_parameter_u kind_u,
+				   int deref_size) OVERRIDE
+  {
+    needs = SYMBOL_NEEDS_FRAME;
 
-static CORE_ADDR
-needs_get_addr_index (void *baton, unsigned int index)
-{
-  /* Nothing to do.  */
-  return 1;
-}
+    /* The expression may require some stub values on DWARF stack.  */
+    push_address (0, 0);
+  }
 
-/* DW_OP_push_object_address has a frame already passed through.  */
+  /* DW_OP_GNU_addr_index doesn't require a frame.  */
 
-static CORE_ADDR
-needs_get_obj_addr (void *baton)
-{
-  /* Nothing to do.  */
-  return 1;
-}
+   CORE_ADDR get_addr_index (unsigned int index) OVERRIDE
+   {
+     /* Nothing to do.  */
+     return 1;
+   }
 
-/* Virtual method table for dwarf2_loc_desc_get_symbol_read_needs
-   below.  */
+   /* DW_OP_push_object_address has a frame already passed through.  */
 
-static const struct dwarf_expr_context_funcs symbol_needs_ctx_funcs =
-{
-  symbol_needs_read_addr_from_reg,
-  symbol_needs_get_reg_value,
-  symbol_needs_read_mem,
-  symbol_needs_frame_base,
-  symbol_needs_frame_cfa,
-  symbol_needs_frame_cfa,	/* get_frame_pc */
-  symbol_needs_tls_address,
-  symbol_needs_dwarf_call,
-  NULL,				/* get_base_type */
-  needs_dwarf_reg_entry_value,
-  needs_get_addr_index,
-  needs_get_obj_addr
+   CORE_ADDR get_object_address () OVERRIDE
+   {
+     /* Nothing to do.  */
+     return 1;
+   }
 };
 
 /* Compute the correct symbol_needs_kind value for the location
@@ -2856,23 +2760,21 @@  static enum symbol_needs_kind
 dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
 				       struct dwarf2_per_cu_data *per_cu)
 {
-  struct symbol_needs_baton baton;
   int in_reg;
   struct cleanup *old_chain;
   struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
 
-  baton.needs = SYMBOL_NEEDS_NONE;
-  baton.per_cu = per_cu;
+  symbol_needs_eval_context ctx;
+
+  ctx.needs = SYMBOL_NEEDS_NONE;
+  ctx.per_cu = per_cu;
 
-  dwarf_expr_context ctx;
   old_chain = make_cleanup_value_free_to_mark (value_mark ());
 
   ctx.gdbarch = get_objfile_arch (objfile);
   ctx.addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx.ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu);
   ctx.offset = dwarf2_per_cu_text_offset (per_cu);
-  ctx.baton = &baton;
-  ctx.funcs = &symbol_needs_ctx_funcs;
 
   ctx.eval (data, size);
 
@@ -2892,8 +2794,8 @@  dwarf2_loc_desc_get_symbol_read_needs (const gdb_byte *data, size_t size,
   do_cleanups (old_chain);
 
   if (in_reg)
-    baton.needs = SYMBOL_NEEDS_FRAME;
-  return baton.needs;
+    ctx.needs = SYMBOL_NEEDS_FRAME;
+  return ctx.needs;
 }
 
 /* A helper function that throws an unimplemented error mentioning a