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]

[RFA 22/22] Convert dwarf_expr_context_funcs to methods


This patch converts the function pointers in dwarf_expr_context_funcs
into methods on dwarf_expr_context, and then updates the various
implementations and callers to follow.

NB this patch uses "override" (which caught a couple of renaming bugs
during development) -- but this is C++11, so this patch at least has
to wait for Pedro's patch that adds the OVERRIDE macro.

After this patch it would be possible to do one more, that makes
various members of dwarf_expr_context "protected"; but I haven't done
this.

2016-09-26  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.
---
 gdb/ChangeLog      |  53 +++++
 gdb/dwarf2-frame.c |  65 +++---
 gdb/dwarf2expr.c   | 136 +++--------
 gdb/dwarf2expr.h   | 172 +++++++-------
 gdb/dwarf2loc.c    | 649 +++++++++++++++++++++++------------------------------
 5 files changed, 468 insertions(+), 607 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fbbd640..553ecda 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,58 @@
 2016-09-26  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-09-26  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..1988afb 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 2b22e0b..024c79b 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -416,20 +416,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;
 }
 
@@ -700,13 +691,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;
 
@@ -896,8 +887,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);
 	  }
@@ -906,7 +896,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);
 	  }
@@ -926,14 +916,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"));
@@ -1019,7 +1007,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.  */
@@ -1228,7 +1216,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;
@@ -1245,7 +1233,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;
 
@@ -1321,7 +1309,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;
 
@@ -1331,7 +1319,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;
 	
@@ -1349,10 +1337,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;
 	      }
 
@@ -1364,9 +1351,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;
 	      }
 
@@ -1382,10 +1368,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;
 
@@ -1417,7 +1402,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;
 
@@ -1456,7 +1441,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;
 
@@ -1482,75 +1467,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..37b3937 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,92 @@ 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 from CTX.  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 +289,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 d6ffd85..37daf08 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)
+get_frame_pc_for_per_cu_dwarf_call (void *baton)
 {
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
+  dwarf_expr_context *ctx = (dwarf_expr_context *) baton;
 
-  return dwarf2_frame_cfa (debaton->frame);
+  return ctx->get_frame_pc ();
 }
 
-/* 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)
-{
-  struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
-  struct objfile *objfile = dwarf2_per_cu_objfile (debaton->per_cu);
-
-  return target_translate_tls_address (objfile, offset);
-}
-
-/* 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,176 @@ 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);
-}
-
-/* Callback function for dwarf2_evaluate_loc_desc.  */
-
-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;
+  struct frame_info *frame;
+  struct dwarf2_per_cu_data *per_cu;
+  CORE_ADDR obj_address;
 
-  return dwarf2_get_die_type (die_offset, debaton->per_cu);
-}
+  /* Helper function for dwarf2_evaluate_loc_desc.  Computes the CFA for
+     the frame in BATON.  */
+
+  CORE_ADDR get_frame_cfa () override
+  {
+    return dwarf2_frame_cfa (frame);
+  }
+
+  /* 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 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.  */
+
+  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<struct gdbarch *> save_arch
+      (&this->gdbarch,
+       get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu)));
+    scoped_restore<int> save_addr_size
+      (&this->addr_size,
+       dwarf2_per_cu_addr_size (baton_local.per_cu));
+    scoped_restore<CORE_ADDR>
+      save_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 +1309,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 +2237,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 +2249,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 +2258,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 +2490,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 +2508,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 +2518,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 +2663,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;
+  /* 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;
 
-  nf_baton->needs = SYMBOL_NEEDS_FRAME;
+    /* The expression may require some stub values on DWARF stack.  */
+    push_address (0, 0);
+  }
 
-  /* 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.  */
 
-/* DW_OP_GNU_addr_index doesn't require a frame.  */
+   CORE_ADDR get_addr_index (unsigned int index) override
+   {
+     /* Nothing to do.  */
+     return 1;
+   }
 
-static CORE_ADDR
-needs_get_addr_index (void *baton, unsigned int index)
-{
-  /* Nothing to do.  */
-  return 1;
-}
+   /* DW_OP_push_object_address has a frame already passed through.  */
 
-/* DW_OP_push_object_address has a frame already passed through.  */
-
-static CORE_ADDR
-needs_get_obj_addr (void *baton)
-{
-  /* Nothing to do.  */
-  return 1;
-}
-
-/* Virtual method table for dwarf2_loc_desc_get_symbol_read_needs
-   below.  */
-
-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 +2763,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 +2797,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
-- 
2.7.4


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