Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640)
@ 2009-09-20 12:37 Jan Kratochvil
  2009-10-12 20:43 ` Tom Tromey
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2009-09-20 12:37 UTC (permalink / raw)
  To: gdb-patches

Hi,

as GCC discusses its use in PR41343 the patch implements it for GDB.

Tried first to follow the #if0-ed prototype get_subr but it was inconvenient
at least because for LOC_STATIC we would need to evaluation-time construct new
artificial DWARF block.

It has some new overhead due to symbol_hash for all symbol DIEs.  Did not
measure it but I am not aware much how it could be avoided as GDB does not
parse the DWARF blocks while reading them in.

No regressions on {x86_64,x86_64-m32,i686}-fedora11-linux-gnu.


Thanks,
Jan


gdb/
2009-09-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Fix PR 10640.
	* dwarf2-frame.c (no_get_tls_address): New comment.
	(no_dwarf_call): New function.
	(execute_stack_op): Set CTX->DWARF_CALL.
	* dwarf2expr.c (execute_stack_op <DW_OP_call2>)
	(execute_stack_op <DW_OP_call4>): New.
	* dwarf2expr.h (struct dwarf_expr_context <dwarf_call>): New.
	(struct dwarf_expr_context <get_subr>): Remove the #if0-ed field.
	* dwarf2loc.c (struct dwarf_expr_baton <objfile>): Remove.
	(struct dwarf_expr_baton <per_cu>): New.
	(dwarf_expr_tls_address): Use PER_CU instead of OBJFILE now.
	(per_cu_dwarf_call, dwarf_expr_dwarf_call): New functions.
	(dwarf2_evaluate_loc_desc): Drop initialization of BATON.OBJFILE.
	Initialize new BATON.PER_CU.  Adjust CTX->GDBARCH initialization for
	this change.  Initialize CTX->DWARF_CALL.
	(struct needs_frame_baton <per_cu>): New field.
	(needs_frame_dwarf_call, locexpr_dwarf_call): New function.
	(dwarf2_loc_desc_needs_frame): Initialize new BATON.PER_CU.  Initialize
	CTX->DWARF_CALL.
	(dwarf2_locexpr_funcs): Include locexpr_dwarf_call.
	* dwarf2loc.h (dwarf2_per_cu_get_die_symbol): New declaration.
	* dwarf2read.c (struct dwarf2_per_cu_data <symbol_hash>): New.
	(set_die_symbol): New function.
	(new_symbol): Call set_die_symbol.
	(struct dwarf2_offset_and_type): Move it above set_die_type.
	(offset_and_type_hash): Rename to ...
	(offset_hash): ... and make it reference only the offset.
	(offset_and_type_eq): Rename to ...
	(offset_eq): ... and make it reference only the offset.
	(set_die_type): Reference the new function names.
	(struct dwarf2_offset_and_symbol, set_die_symbol)
	(dwarf2_per_cu_get_die_symbol): New.
	* symtab.h (struct dwarf_expr_context): New opaque declaration.
	(struct symbol_computed_ops <dwarf_call>): New.

gdb/testsuite/
2009-09-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Test PR 10640.
	* gdb.dwarf2/dw2-op-call.exp, gdb.dwarf2/dw2-op-call.S: New.

--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -318,6 +318,8 @@ no_get_frame_cfa (void *baton)
 		  _("Support for DW_OP_call_frame_cfa is unimplemented"));
 }
 
+/* Helper function for execute_stack_op.  */
+
 static CORE_ADDR
 no_get_tls_address (void *baton, CORE_ADDR offset)
 {
@@ -325,6 +327,15 @@ no_get_tls_address (void *baton, CORE_ADDR offset)
 		  _("Support for DW_OP_GNU_push_tls_address is unimplemented"));
 }
 
+/* Helper function for execute_stack_op.  */
+
+static void
+no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+  internal_error (__FILE__, __LINE__,
+		  _("Support for DW_OP_call* is invalid in CFI"));
+}
+
 /* Execute the required actions for both the DW_CFA_restore and
 DW_CFA_restore_extended instructions.  */
 static void
@@ -375,6 +386,7 @@ execute_stack_op (gdb_byte *exp, ULONGEST len, int addr_size,
   ctx->get_frame_base = no_get_frame_base;
   ctx->get_frame_cfa = no_get_frame_cfa;
   ctx->get_tls_address = no_get_tls_address;
+  ctx->dwarf_call = no_dwarf_call;
 
   dwarf_expr_push (ctx, initial, initial_in_stack_memory);
   dwarf_expr_eval (ctx, exp, len);
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -848,6 +848,18 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  ctx->initialized = 0;
 	  goto no_push;
 
+	case DW_OP_call2:
+	  result = extract_unsigned_integer (op_ptr, 2, byte_order);
+	  op_ptr += 2;
+	  ctx->dwarf_call (ctx, result);
+	  goto no_push;
+
+	case DW_OP_call4:
+	  result = extract_unsigned_integer (op_ptr, 4, byte_order);
+	  op_ptr += 4;
+	  ctx->dwarf_call (ctx, result);
+	  goto no_push;
+
 	default:
 	  error (_("Unhandled dwarf expression opcode 0x%x"), op);
 	}
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -94,15 +94,14 @@ struct dwarf_expr_context
      DW_OP_GNU_push_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, size_t die_offset);
+
 #if 0
   /* Not yet implemented.  */
 
-  /* Return the location expression for the dwarf expression
-     subroutine in the die at OFFSET in the current compilation unit.
-     The result must be live until the current expression evaluation
-     is complete.  */
-  unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length);
-
   /* Return the `object address' for DW_OP_push_object_address.  */
   CORE_ADDR (*get_object_address) (void *baton);
 #endif
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -115,7 +115,7 @@ find_location_expression (struct dwarf2_loclist_baton *baton,
 struct dwarf_expr_baton
 {
   struct frame_info *frame;
-  struct objfile *objfile;
+  struct dwarf2_per_cu_data *per_cu;
 };
 
 /* Helper functions for dwarf2_evaluate_loc_desc.  */
@@ -211,8 +211,51 @@ 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 (debaton->objfile, offset);
+  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).  Pass to it and return from it CTX.
+
+   We ignore any failures as DWARF says "If there is no such attribute, then
+   there is no effect." and it would be difficult to distinguish valid and
+   invalid DWARF cases after the DWARF symbol has been read in.  */
+
+static void
+per_cu_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset,
+		   struct dwarf2_per_cu_data *per_cu)
+{
+  struct symbol *sym = dwarf2_per_cu_get_die_symbol (die_offset, per_cu);
+
+  if (sym == NULL)
+    return;
+
+  switch (SYMBOL_CLASS (sym))
+    {
+    case LOC_COMPUTED:
+      if (SYMBOL_COMPUTED_OPS (sym)->dwarf_call == NULL)
+      	error (_("Symbol class of \"%s\" does not support DW_OP_call*"),
+	       SYMBOL_PRINT_NAME (sym));
+
+      SYMBOL_COMPUTED_OPS (sym)->dwarf_call (sym, ctx);
+      break;
+      
+    case LOC_STATIC:
+      dwarf_expr_push (ctx, SYMBOL_VALUE_ADDRESS (sym), 0);
+      break;
+    }
+}
+
+/* Helper interface of per_cu_dwarf_call for dwarf2_evaluate_loc_desc.  */
+
+static void
+dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+  struct dwarf_expr_baton *debaton = ctx->baton;
+
+  return per_cu_dwarf_call (ctx, die_offset, debaton->per_cu);
 }
 
 struct piece_closure
@@ -395,12 +438,12 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
     }
 
   baton.frame = frame;
-  baton.objfile = dwarf2_per_cu_objfile (per_cu);
+  baton.per_cu = per_cu;
 
   ctx = new_dwarf_expr_context ();
   old_chain = make_cleanup_free_dwarf_expr_context (ctx);
 
-  ctx->gdbarch = get_objfile_arch (baton.objfile);
+  ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu));
   ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx->baton = &baton;
   ctx->read_reg = dwarf_expr_read_reg;
@@ -408,6 +451,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
   ctx->get_frame_base = dwarf_expr_frame_base;
   ctx->get_frame_cfa = dwarf_expr_frame_cfa;
   ctx->get_tls_address = dwarf_expr_tls_address;
+  ctx->dwarf_call = dwarf_expr_dwarf_call;
 
   dwarf_expr_eval (ctx, data, size);
   if (ctx->num_pieces > 0)
@@ -496,6 +540,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
 struct needs_frame_baton
 {
   int needs_frame;
+  struct dwarf2_per_cu_data *per_cu;
 };
 
 /* Reads from registers do require a frame.  */
@@ -546,6 +591,16 @@ needs_frame_tls_address (void *baton, CORE_ADDR offset)
   return 1;
 }
 
+/* Helper interface of per_cu_dwarf_call for dwarf2_loc_desc_needs_frame.  */
+
+static void
+needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+  struct needs_frame_baton *nf_baton = ctx->baton;
+
+  return per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu);
+}
+
 /* Return non-zero iff the location expression at DATA (length SIZE)
    requires a frame to evaluate.  */
 
@@ -559,6 +614,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
   struct cleanup *old_chain;
 
   baton.needs_frame = 0;
+  baton.per_cu = per_cu;
 
   ctx = new_dwarf_expr_context ();
   old_chain = make_cleanup_free_dwarf_expr_context (ctx);
@@ -571,6 +627,7 @@ dwarf2_loc_desc_needs_frame (gdb_byte *data, unsigned short size,
   ctx->get_frame_base = needs_frame_frame_base;
   ctx->get_frame_cfa = needs_frame_frame_cfa;
   ctx->get_tls_address = needs_frame_tls_address;
+  ctx->dwarf_call = needs_frame_dwarf_call;
 
   dwarf_expr_eval (ctx, data, size);
 
@@ -758,13 +815,28 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
 			     dlbaton->data, dlbaton->size);
 }
 
+/* Execute DWARF DW_AT_location block of SYMBOL for STACK of CTX.  */
+
+static void
+locexpr_dwarf_call (struct symbol *symbol, struct dwarf_expr_context *ctx)
+{
+  struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+  struct objfile *objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
+
+  gdb_assert (ctx->gdbarch == get_objfile_arch (objfile));
+  gdb_assert (ctx->addr_size == dwarf2_per_cu_addr_size (dlbaton->per_cu));
+
+  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
+}
+
 /* The set of location functions used with the DWARF-2 expression
    evaluator.  */
 const struct symbol_computed_ops dwarf2_locexpr_funcs = {
   locexpr_read_variable,
   locexpr_read_needs_frame,
   locexpr_describe_location,
-  locexpr_tracepoint_var_ref
+  locexpr_tracepoint_var_ref,
+  locexpr_dwarf_call
 };
 
 
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -33,6 +33,9 @@ struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu);
 /* Return the address size given in the compilation unit header for CU.  */
 CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu);
 
+struct symbol *dwarf2_per_cu_get_die_symbol (size_t die_offset,
+					     struct dwarf2_per_cu_data *per_cu);
+
 /* The symbol location baton types used by the DWARF-2 reader (i.e.
    SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol).  "struct
    dwarf2_locexpr_baton" is for a symbol with a single location
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -377,6 +377,9 @@ struct dwarf2_per_cu_data
      it.  */
   htab_t type_hash;
 
+  /* Like type_hash above but map DIE offsets to `struct symbol's.  */
+  htab_t symbol_hash;
+
   /* The partial symbol table associated with this compilation unit,
      or NULL for partial units (which do not have an associated
      symtab).  */
@@ -1151,6 +1154,9 @@ static void free_one_cached_comp_unit (void *);
 static struct type *set_die_type (struct die_info *, struct type *,
 				  struct dwarf2_cu *);
 
+static void set_die_symbol (struct die_info *die, struct symbol *symbol,
+			    struct dwarf2_cu *cu);
+
 static void create_all_comp_units (struct objfile *);
 
 static void load_full_comp_unit (struct dwarf2_per_cu_data *,
@@ -8340,6 +8346,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	    }
 	}
 
+      set_die_symbol (die, sym, cu);
+
       switch (die->tag)
 	{
 	case DW_TAG_label:
@@ -11634,35 +11642,39 @@ dwarf2_free_objfile (struct objfile *objfile)
   /* Everything else should be on the objfile obstack.  */
 }
 
-/* A pair of DIE offset and GDB type pointer.  We store these
-   in a hash table separate from the DIEs, and preserve them
-   when the DIEs are flushed out of cache.  */
-
-struct dwarf2_offset_and_type
-{
-  unsigned int offset;
-  struct type *type;
-};
-
-/* Hash function for a dwarf2_offset_and_type.  */
+/* Hash function for a structure containing `unsigned int' DIE offset as its
+   very first element.  */
 
 static hashval_t
-offset_and_type_hash (const void *item)
+offset_hash (const void *item)
 {
-  const struct dwarf2_offset_and_type *ofs = item;
-  return ofs->offset;
+  const unsigned int *offsetp = item;
+
+  return *offsetp;
 }
 
-/* Equality function for a dwarf2_offset_and_type.  */
+/* Equality function for a structure containing `unsigned int' DIE offset as
+   its very first element.  */
 
 static int
-offset_and_type_eq (const void *item_lhs, const void *item_rhs)
+offset_eq (const void *item_lhs, const void *item_rhs)
 {
-  const struct dwarf2_offset_and_type *ofs_lhs = item_lhs;
-  const struct dwarf2_offset_and_type *ofs_rhs = item_rhs;
-  return ofs_lhs->offset == ofs_rhs->offset;
+  const unsigned int *offsetp_lhs = item_lhs;
+  const unsigned int *offsetp_rhs = item_rhs;
+
+  return *offsetp_lhs == *offsetp_rhs;
 }
 
+/* A pair of DIE offset and GDB type pointer.  We store these
+   in a hash table separate from the DIEs, and preserve them
+   when the DIEs are flushed out of cache.  */
+
+struct dwarf2_offset_and_type
+{
+  unsigned int offset;
+  struct type *type;
+};
+
 /* Set the type associated with DIE to TYPE.  Save it in CU's hash
    table if necessary.  For convenience, return TYPE.  */
 
@@ -11676,8 +11688,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
       gdb_assert (cu->per_cu != NULL);
       cu->per_cu->type_hash
 	= htab_create_alloc_ex (cu->header.length / 24,
-				offset_and_type_hash,
-				offset_and_type_eq,
+				offset_hash,
+				offset_eq,
 				NULL,
 				&cu->objfile->objfile_obstack,
 				hashtab_obstack_allocate,
@@ -11694,6 +11706,64 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
   return type;
 }
 
+/* A pair of DIE offset and GDB symbol pointer.  We store these
+   in a hash table separate from the DIEs, and preserve them
+   when the DIEs are flushed out of cache.  */
+
+struct dwarf2_offset_and_symbol
+{
+  unsigned int offset;
+  struct symbol *symbol;
+};
+
+/* Set the symbol associated with DIE to SYMBOL.  Save it in PER_CU's hash
+   table.  */
+
+static void
+set_die_symbol (struct die_info *die, struct symbol *symbol, struct dwarf2_cu *cu)
+{
+  struct dwarf2_per_cu_data *per_cu = cu->per_cu;
+  struct dwarf2_offset_and_symbol **slot, ofs;
+
+  gdb_assert (per_cu != NULL);
+
+  if (per_cu->symbol_hash == NULL)
+    per_cu->symbol_hash = htab_create_alloc_ex (cu->header.length / 24,
+						offset_hash,
+						offset_eq,
+						NULL,
+						&cu->objfile->objfile_obstack,
+						hashtab_obstack_allocate,
+						dummy_obstack_deallocate);
+
+  ofs.offset = die->offset;
+  ofs.symbol = symbol;
+  slot = (struct dwarf2_offset_and_symbol **)
+    htab_find_slot_with_hash (per_cu->symbol_hash, &ofs, ofs.offset, INSERT);
+  *slot = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (**slot));
+  **slot = ofs;
+}
+
+/* Find the symbol for DIE at DIE_OFFSET in PER_CU's symbol_hash, or return
+   NULL if DIE does not have a saved symbol.  */
+
+struct symbol *
+dwarf2_per_cu_get_die_symbol (size_t die_offset, struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_offset_and_symbol *slot, ofs;
+  htab_t symbol_hash = per_cu->symbol_hash;
+
+  if (symbol_hash == NULL)
+    return NULL;
+
+  ofs.offset = die_offset;
+  slot = htab_find_with_hash (symbol_hash, &ofs, ofs.offset);
+  if (slot)
+    return slot->symbol;
+  else
+    return NULL;
+}
+
 /* Find the type for DIE in CU's type_hash, or return NULL if DIE does
    not have a saved type.  */
 
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -32,6 +32,7 @@ struct block;
 struct blockvector;
 struct axs_value;
 struct agent_expr;
+struct dwarf_expr_context;
 
 /* Some of the structures in this file are space critical.
    The space-critical structures are:
@@ -529,6 +530,11 @@ struct symbol_computed_ops
 
   void (*tracepoint_var_ref) (struct symbol *symbol, struct gdbarch *gdbarch,
 			      struct agent_expr *ax, struct axs_value *value);
+
+  /* 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 symbol *symbol, struct dwarf_expr_context *ctx);
 };
 
 /* Functions used with LOC_REGISTER and LOC_REGPARM_ADDR.  */
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.S
@@ -0,0 +1,119 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.  */
+
+	.section .data
+array1:	.2byte	1
+array2:	.2byte	2
+array3:	.2byte	3
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.ascii	"file1.txt\0"			/* DW_AT_name */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	2				/* DW_LANG_C (C) */
+
+.L2byte_type:
+	.uleb128	2			/* Abbrev: DW_TAG_base_type */
+	.ascii		"2byte\0"		/* DW_AT_name */
+	.byte		2			/* DW_AT_byte_size */
+	.byte		7			/* DW_AT_encoding: DW_ATE_unsigned */
+
+.Larray1:
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array1\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		3			/*   DW_OP_addr */
+	.4byte		array			/*     <addr> */
+2:
+
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array2\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		0x98			/*   DW_OP_call2 */
+	.2byte		.Larray1-.Lcu1_begin	/*     <current CU offset> */
+	.byte		0x23			/*   DW_OP_plus_uconst */
+	.uleb128	array2-array1		/*     <uconst> */
+2:
+
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array3\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		0x99			/*   DW_OP_call4 */
+	.4byte		.Larray1-.Lcu1_begin	/*     <current CU offset> */
+	.byte		0x23			/*   DW_OP_plus_uconst */
+	.uleb128	array3-array1		/*     <uconst> */
+2:
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x24			/* DW_TAG_base_type */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0xb			/* DW_AT_byte_size */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3e			/* DW_AT_encoding */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x2			/* DW_AT_location */
+	.uleb128	0xa			/* DW_FORM_block1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
@@ -0,0 +1,41 @@
+# Copyright 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+
+set testfile "dw2-op-call"
+set srcfile ${testfile}.S
+set executable ${testfile}.x
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${executable}" object {nodebug}] != "" } {
+    return -1
+}
+
+clean_restart $executable
+
+gdb_test "p array1" " = 1"
+gdb_test "p array2" " = 2" "array2 using DW_OP_call2"
+gdb_test "p array3" " = 3" "array3 using DW_OP_call4"


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640)
  2009-09-20 12:37 [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640) Jan Kratochvil
@ 2009-10-12 20:43 ` Tom Tromey
  2009-10-12 20:49   ` Tom Tromey
  2009-10-12 21:08   ` Daniel Jacobowitz
  0 siblings, 2 replies; 11+ messages in thread
From: Tom Tromey @ 2009-10-12 20:43 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> as GCC discusses its use in PR41343 the patch implements it for GDB.

Thanks.

Jan> It has some new overhead due to symbol_hash for all symbol DIEs.
Jan> Did not measure it but I am not aware much how it could be avoided
Jan> as GDB does not parse the DWARF blocks while reading them in.

Yeah, I could not think of a way to avoid it either.  I think parsing
the DWARF while reading would be worse than what you have now, because
(IIUC) it would negatively impact performance.

I thought of one way to reduce the overhead a bit, but it is fairly
gross.  We could have dwarf2read.c make symbols like:

struct dwarf_symbol
{
  struct symbol base;
  int offset;
};

Then, where it matters, "downcast" from symbol to dwarf_symbol and find
the offset.  symbol_hash would just directly hold dwarf_symbols, no need
for struct dwarf2_offset_and_symbol.

This would save a pointer per symbol.

That said, I probably would not bother with this until we know that
space is an issue.  I know that symtab.h claims that symbol size is a
problem, but I am not sure that this is really true -- I suspect it is
only the case with -readnow, which most people don't use.

The ugliness here is that it assumes that no other part of gdb cares
about the size of a symbol.  This is probably true but also a fragile
assumption.

Jan> 2009-09-20  Jan Kratochvil  <jan.kratochvil@redhat.com>
Jan> 	Fix PR 10640.
[...]

Ok.

Tom


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640)
  2009-10-12 20:43 ` Tom Tromey
@ 2009-10-12 20:49   ` Tom Tromey
  2010-06-07 11:56     ` [patch 1/2] DW_OP_call: Provide per_cu in the batons Jan Kratochvil
                       ` (2 more replies)
  2009-10-12 21:08   ` Daniel Jacobowitz
  1 sibling, 3 replies; 11+ messages in thread
From: Tom Tromey @ 2009-10-12 20:49 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

Jan> as GCC discusses its use in PR41343 the patch implements it for GDB.

Also, I forgot to ask -- why not DW_OP_call_ref as well?

Tom


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640)
  2009-10-12 20:43 ` Tom Tromey
  2009-10-12 20:49   ` Tom Tromey
@ 2009-10-12 21:08   ` Daniel Jacobowitz
  1 sibling, 0 replies; 11+ messages in thread
From: Daniel Jacobowitz @ 2009-10-12 21:08 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Jan Kratochvil, gdb-patches

On Mon, Oct 12, 2009 at 02:43:04PM -0600, Tom Tromey wrote:
> Yeah, I could not think of a way to avoid it either.  I think parsing
> the DWARF while reading would be worse than what you have now, because
> (IIUC) it would negatively impact performance.

This is all part of inter-CU references.  You can't (always) parse it
as you read it in; there can be dependency loops.

I'm confused as to why the "struct symbol" comes into this though.
We're just using it to look up its DWARF location again.  Can we do
this directly off the target DIE?  We don't free up the loaded
.debug_info (partly to support DW_FORM_string).  And we have
infrastructure to load a given CU's dies whenever we need them.

IIUC this would require a different implementation of the baton
for DIEs without a symbol.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 2/2] DW_OP_call: Support DW_OP_call2 and DW_OP_call4
  2009-10-12 20:49   ` Tom Tromey
  2010-06-07 11:56     ` [patch 1/2] DW_OP_call: Provide per_cu in the batons Jan Kratochvil
@ 2010-06-07 11:56     ` Jan Kratochvil
  2010-06-07 18:13       ` Tom Tromey
  2010-06-07 11:56     ` [patch 0/2] DW_OP_call: Re: [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640) Jan Kratochvil
  2 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2010-06-07 11:56 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi,

the main functionality.


Thanks,
Jan


gdb/
2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Fix PR 10640.
	* dwarf2-frame.c (no_dwarf_call): New function.
	(execute_stack_op): Set CTX->DWARF_CALL.
	* dwarf2expr.c (execute_stack_op) <DW_OP_call2, DW_OP_call4>: New.
	* dwarf2expr.h (struct dwarf_expr_context) <dwarf_call>: New.
	(struct dwarf_expr_context) <get_subr>: Remove the #if0-ed field.
	* dwarf2loc.c (per_cu_dwarf_call, dwarf_expr_dwarf_call): New functions.
	(dwarf2_evaluate_loc_desc): Initialize CTX->DWARF_CALL.
	(needs_frame_dwarf_call): New function.
	(dwarf2_loc_desc_needs_frame): Initialize CTX->DWARF_CALL.
	* dwarf2read.c (follow_die_offset): Based on former follow_die_ref.
	Update the comment.  Move variables die, offset and error call to ...
	(follow_die_ref): ... a new function.
	(fetch_die_location_block): New function.
	* symtab.h (fetch_die_location_block): New prototype.

gdb/testsuite/
2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>

	Test PR 10640.
	* gdb.dwarf2/dw2-op-call.exp, gdb.dwarf2/dw2-op-call.S: New.

--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -328,6 +328,15 @@ no_get_tls_address (void *baton, CORE_ADDR offset)
 		  _("Support for DW_OP_GNU_push_tls_address is unimplemented"));
 }
 
+/* Helper function for execute_stack_op.  */
+
+static void
+no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+  internal_error (__FILE__, __LINE__,
+		  _("Support for DW_OP_call* is invalid in CFI"));
+}
+
 /* Execute the required actions for both the DW_CFA_restore and
 DW_CFA_restore_extended instructions.  */
 static void
@@ -378,6 +387,7 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size,
   ctx->get_frame_base = no_get_frame_base;
   ctx->get_frame_cfa = no_get_frame_cfa;
   ctx->get_tls_address = no_get_tls_address;
+  ctx->dwarf_call = no_dwarf_call;
 
   dwarf_expr_push (ctx, initial, initial_in_stack_memory);
   dwarf_expr_eval (ctx, exp, len);
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -911,6 +911,18 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  ctx->initialized = 0;
 	  goto no_push;
 
+	case DW_OP_call2:
+	  result = extract_unsigned_integer (op_ptr, 2, byte_order);
+	  op_ptr += 2;
+	  ctx->dwarf_call (ctx, result);
+	  goto no_push;
+
+	case DW_OP_call4:
+	  result = extract_unsigned_integer (op_ptr, 4, byte_order);
+	  op_ptr += 4;
+	  ctx->dwarf_call (ctx, result);
+	  goto no_push;
+
 	default:
 	  error (_("Unhandled dwarf expression opcode 0x%x"), op);
 	}
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -97,15 +97,14 @@ struct dwarf_expr_context
      DW_OP_GNU_push_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, size_t die_offset);
+
 #if 0
   /* Not yet implemented.  */
 
-  /* Return the location expression for the dwarf expression
-     subroutine in the die at OFFSET in the current compilation unit.
-     The result must be live until the current expression evaluation
-     is complete.  */
-  unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length);
-
   /* Return the `object address' for DW_OP_push_object_address.  */
   CORE_ADDR (*get_object_address) (void *baton);
 #endif
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -232,6 +232,33 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
   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, size_t die_offset,
+		   struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_locexpr_baton block;
+
+  block = fetch_die_location_block (die_offset, per_cu);
+
+  /* DW_OP_call_ref is currently not supported.  */
+  gdb_assert (block.per_cu == per_cu);
+
+  dwarf_expr_eval (ctx, 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, size_t die_offset)
+{
+  struct dwarf_expr_baton *debaton = ctx->baton;
+
+  return per_cu_dwarf_call (ctx, die_offset, debaton->per_cu);
+}
+
 struct piece_closure
 {
   /* Reference count.  */
@@ -815,6 +842,7 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
   ctx->get_frame_base = dwarf_expr_frame_base;
   ctx->get_frame_cfa = dwarf_expr_frame_cfa;
   ctx->get_tls_address = dwarf_expr_tls_address;
+  ctx->dwarf_call = dwarf_expr_dwarf_call;
 
   dwarf_expr_eval (ctx, data, size);
   if (ctx->num_pieces > 0)
@@ -962,6 +990,16 @@ needs_frame_tls_address (void *baton, CORE_ADDR offset)
   return 1;
 }
 
+/* Helper interface of per_cu_dwarf_call for dwarf2_loc_desc_needs_frame.  */
+
+static void
+needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+  struct needs_frame_baton *nf_baton = ctx->baton;
+
+  return per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu);
+}
+
 /* Return non-zero iff the location expression at DATA (length SIZE)
    requires a frame to evaluate.  */
 
@@ -988,6 +1026,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size,
   ctx->get_frame_base = needs_frame_frame_base;
   ctx->get_frame_cfa = needs_frame_frame_cfa;
   ctx->get_tls_address = needs_frame_tls_address;
+  ctx->dwarf_call = needs_frame_dwarf_call;
 
   dwarf_expr_eval (ctx, data, size);
 
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -10736,30 +10736,25 @@ follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
   return die;
 }
 
-/* Follow reference attribute ATTR of SRC_DIE.
-   On entry *REF_CU is the CU of SRC_DIE.
+/* Follow reference OFFSET.
+   On entry *REF_CU is the CU of source DIE referencing OFFSET.
    On exit *REF_CU is the CU of the result.  */
 
 static struct die_info *
-follow_die_ref (struct die_info *src_die, struct attribute *attr,
-		struct dwarf2_cu **ref_cu)
+follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu)
 {
-  struct die_info *die;
-  unsigned int offset;
   struct die_info temp_die;
   struct dwarf2_cu *target_cu, *cu = *ref_cu;
 
   gdb_assert (cu->per_cu != NULL);
 
-  offset = dwarf2_get_ref_die_offset (attr);
-
   if (cu->per_cu->from_debug_types)
     {
       /* .debug_types CUs cannot reference anything outside their CU.
 	 If they need to, they have to reference a signatured type via
 	 DW_FORM_sig8.  */
       if (! offset_in_cu_p (&cu->header, offset))
-	goto not_found;
+	return NULL;
       target_cu = cu;
     }
   else if (! offset_in_cu_p (&cu->header, offset))
@@ -10779,15 +10774,66 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
 
   *ref_cu = target_cu;
   temp_die.offset = offset;
-  die = htab_find_with_hash (target_cu->die_hash, &temp_die, offset);
-  if (die)
-    return die;
+  return htab_find_with_hash (target_cu->die_hash, &temp_die, offset);
+}
 
- not_found:
+/* Follow reference attribute ATTR of SRC_DIE.
+   On entry *REF_CU is the CU of SRC_DIE.
+   On exit *REF_CU is the CU of the result.  */
 
-  error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
-	 "at 0x%x [in module %s]"),
-	 offset, src_die->offset, cu->objfile->name);
+static struct die_info *
+follow_die_ref (struct die_info *src_die, struct attribute *attr,
+		struct dwarf2_cu **ref_cu)
+{
+  unsigned int offset = dwarf2_get_ref_die_offset (attr);
+  struct dwarf2_cu *cu = *ref_cu;
+  struct die_info *die;
+
+  die = follow_die_offset (offset, ref_cu);
+  if (!die)
+    error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
+	   "at 0x%x [in module %s]"),
+	   offset, src_die->offset, cu->objfile->name);
+
+  return die;
+}
+
+/* Return DWARF block and its CU referenced by OFFSET at PER_CU.  Returned
+   value is intended for DW_OP_call*.  */
+
+struct dwarf2_locexpr_baton
+fetch_die_location_block (unsigned int offset, struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_cu *cu = per_cu->cu;
+  struct die_info *die;
+  struct attribute *attr;
+  struct dwarf2_locexpr_baton retval;
+
+  die = follow_die_offset (offset, &cu);
+  if (!die)
+    error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
+	   offset, per_cu->cu->objfile->name);
+
+  attr = dwarf2_attr (die, DW_AT_location, cu);
+  if (!attr)
+    {
+      /* DWARF: "If there is no such attribute, then there is no effect.".  */
+
+      retval.data = NULL;
+      retval.size = 0;
+    }
+  else
+    {
+      if (!attr_form_is_block (attr))
+	error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
+		 "is neither DW_FORM_block* nor DW_FORM_exprloc"),
+	       offset, per_cu->cu->objfile->name);
+
+      retval.data = DW_BLOCK (attr)->data;
+      retval.size = DW_BLOCK (attr)->size;
+    }
+  retval.per_cu = cu->per_cu;
+  return retval;
 }
 
 /* Follow the signature attribute ATTR in SRC_DIE.
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -569,6 +569,10 @@ extern int dwarf2_has_info (struct objfile *);
 extern void dwarf2_build_psymtabs (struct objfile *);
 extern void dwarf2_build_frame_info (struct objfile *);
 
+struct dwarf2_per_cu_data;
+extern struct dwarf2_locexpr_baton fetch_die_location_block
+  (unsigned int offset, struct dwarf2_per_cu_data *per_cu);
+
 void dwarf2_free_objfile (struct objfile *);
 
 /* From mdebugread.c */
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.S
@@ -0,0 +1,119 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.  */
+
+	.section .data
+array1:	.2byte	1
+array2:	.2byte	2
+array3:	.2byte	3
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.ascii	"file1.txt\0"			/* DW_AT_name */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	2				/* DW_LANG_C (C) */
+
+.L2byte_type:
+	.uleb128	2			/* Abbrev: DW_TAG_base_type */
+	.ascii		"2byte\0"		/* DW_AT_name */
+	.byte		2			/* DW_AT_byte_size */
+	.byte		7			/* DW_AT_encoding: DW_ATE_unsigned */
+
+.Larray1:
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array1\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		3			/*   DW_OP_addr */
+	.4byte		array			/*     <addr> */
+2:
+
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array2\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		0x98			/*   DW_OP_call2 */
+	.2byte		.Larray1-.Lcu1_begin	/*     <current CU offset> */
+	.byte		0x23			/*   DW_OP_plus_uconst */
+	.uleb128	array2-array1		/*     <uconst> */
+2:
+
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array3\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		0x99			/*   DW_OP_call4 */
+	.4byte		.Larray1-.Lcu1_begin	/*     <current CU offset> */
+	.byte		0x23			/*   DW_OP_plus_uconst */
+	.uleb128	array3-array1		/*     <uconst> */
+2:
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x24			/* DW_TAG_base_type */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0xb			/* DW_AT_byte_size */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3e			/* DW_AT_encoding */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x2			/* DW_AT_location */
+	.uleb128	0xa			/* DW_FORM_block1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
@@ -0,0 +1,41 @@
+# Copyright 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+
+set testfile "dw2-op-call"
+set srcfile ${testfile}.S
+set executable ${testfile}.x
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${executable}" object {nodebug}] != "" } {
+    return -1
+}
+
+clean_restart $executable
+
+gdb_test "p array1" " = 1"
+gdb_test "p array2" " = 2" "array2 using DW_OP_call2"
+gdb_test "p array3" " = 3" "array3 using DW_OP_call4"


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 0/2] DW_OP_call: Re: [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640)
  2009-10-12 20:49   ` Tom Tromey
  2010-06-07 11:56     ` [patch 1/2] DW_OP_call: Provide per_cu in the batons Jan Kratochvil
  2010-06-07 11:56     ` [patch 2/2] DW_OP_call: Support DW_OP_call2 and DW_OP_call4 Jan Kratochvil
@ 2010-06-07 11:56     ` Jan Kratochvil
  2 siblings, 0 replies; 11+ messages in thread
From: Jan Kratochvil @ 2010-06-07 11:56 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Mon, 12 Oct 2009 22:49:23 +0200, Tom Tromey wrote:
> Jan> as GCC discusses its use in PR41343 the patch implements it for GDB.
> 
> Also, I forgot to ask -- why not DW_OP_call_ref as well?

DW_OP_call_ref currently was not requested and it may get more tricky due to
inter-CU references.


On Mon, 12 Oct 2009 23:08:44 +0200, Daniel Jacobowitz wrote:
> I'm confused as to why the "struct symbol" comes into this though.
> We're just using it to look up its DWARF location again.  Can we do
> this directly off the target DIE?  We don't free up the loaded
> .debug_info (partly to support DW_FORM_string).

I was not aware the DIEs are being held allocated for read-in CU.  Fixed the
comment there.


> And we have infrastructure to load a given CU's dies whenever we need them.

It should not be needed when only DW_OP_call{2,4} and not DW_OP_call_ref are
supported.


No regressions on {x86_64,x86_64-m32,i686}-fedora13-linux-gnu.

OK to check-in?


Thanks,
Jan


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [patch 1/2] DW_OP_call: Provide per_cu in the batons
  2009-10-12 20:49   ` Tom Tromey
@ 2010-06-07 11:56     ` Jan Kratochvil
  2010-06-07 17:44       ` Tom Tromey
  2010-06-07 11:56     ` [patch 2/2] DW_OP_call: Support DW_OP_call2 and DW_OP_call4 Jan Kratochvil
  2010-06-07 11:56     ` [patch 0/2] DW_OP_call: Re: [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640) Jan Kratochvil
  2 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2010-06-07 11:56 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi,

provide per_cu in the batons as required by the patch 2/2.


Thanks,
Jan


gdb/
2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* dwarf2loc.c (struct dwarf_expr_baton) Replace objfile by per_cu.
	(dwarf_expr_tls_address): Use per_cu instead of objfile.
	(dwarf2_evaluate_loc_desc): Drop initialization of BATON.OBJFILE.
	Initialize new BATON.PER_CU.  Adjust CTX->GDBARCH initialization for
	this change.
	(struct needs_frame_baton): New field per_cu.
	(dwarf2_loc_desc_needs_frame): Initialize new BATON.PER_CU.
	* dwarf2read.c (struct dwarf2_per_cu_data) <cu>: Extend the comment.

--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -122,7 +122,7 @@ find_location_expression (struct dwarf2_loclist_baton *baton,
 struct dwarf_expr_baton
 {
   struct frame_info *frame;
-  struct objfile *objfile;
+  struct dwarf2_per_cu_data *per_cu;
 };
 
 /* Helper functions for dwarf2_evaluate_loc_desc.  */
@@ -227,8 +227,9 @@ 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 (debaton->objfile, offset);
+  return target_translate_tls_address (objfile, offset);
 }
 
 struct piece_closure
@@ -801,12 +802,12 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
     }
 
   baton.frame = frame;
-  baton.objfile = dwarf2_per_cu_objfile (per_cu);
+  baton.per_cu = per_cu;
 
   ctx = new_dwarf_expr_context ();
   old_chain = make_cleanup_free_dwarf_expr_context (ctx);
 
-  ctx->gdbarch = get_objfile_arch (baton.objfile);
+  ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu));
   ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx->baton = &baton;
   ctx->read_reg = dwarf_expr_read_reg;
@@ -907,6 +908,7 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
 struct needs_frame_baton
 {
   int needs_frame;
+  struct dwarf2_per_cu_data *per_cu;
 };
 
 /* Reads from registers do require a frame.  */
@@ -973,6 +975,7 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size,
   struct cleanup *old_chain;
 
   baton.needs_frame = 0;
+  baton.per_cu = per_cu;
 
   ctx = new_dwarf_expr_context ();
   old_chain = make_cleanup_free_dwarf_expr_context (ctx);
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -337,7 +337,8 @@ struct dwarf2_per_cu_data
      Otherwise it's from .debug_info.  */
   unsigned int from_debug_types : 1;
 
-  /* Set iff currently read in.  */
+  /* Set no non-NULL iff this CU is currently loaded.  When it gets freed out
+     of the CU cache it gets reset to NULL again.  */
   struct dwarf2_cu *cu;
 
   /* If full symbols for this CU have been read in, then this field


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 1/2] DW_OP_call: Provide per_cu in the batons
  2010-06-07 11:56     ` [patch 1/2] DW_OP_call: Provide per_cu in the batons Jan Kratochvil
@ 2010-06-07 17:44       ` Tom Tromey
  2010-06-07 19:44         ` Jan Kratochvil
  0 siblings, 1 reply; 11+ messages in thread
From: Tom Tromey @ 2010-06-07 17:44 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> provide per_cu in the batons as required by the patch 2/2.

Jan> 2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
Jan> 	* dwarf2loc.c (struct dwarf_expr_baton) Replace objfile by per_cu.
Jan> 	(dwarf_expr_tls_address): Use per_cu instead of objfile.
Jan> 	(dwarf2_evaluate_loc_desc): Drop initialization of BATON.OBJFILE.
Jan> 	Initialize new BATON.PER_CU.  Adjust CTX->GDBARCH initialization for
Jan> 	this change.
Jan> 	(struct needs_frame_baton): New field per_cu.
Jan> 	(dwarf2_loc_desc_needs_frame): Initialize new BATON.PER_CU.
Jan> 	* dwarf2read.c (struct dwarf2_per_cu_data) <cu>: Extend the comment.

Ok with one nit fixed:

Jan> +  /* Set no non-NULL iff this CU is currently loaded.  When it gets freed out

s/no/to/

thanks,
Tom


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 2/2] DW_OP_call: Support DW_OP_call2 and DW_OP_call4
  2010-06-07 11:56     ` [patch 2/2] DW_OP_call: Support DW_OP_call2 and DW_OP_call4 Jan Kratochvil
@ 2010-06-07 18:13       ` Tom Tromey
  2010-06-07 20:00         ` Jan Kratochvil
  0 siblings, 1 reply; 11+ messages in thread
From: Tom Tromey @ 2010-06-07 18:13 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> 	Fix PR 10640.

Would you mind filing a new PR for DW_OP_call_ref?
This is one of the few remaining unimplemented operators...

Jan> +struct dwarf2_locexpr_baton
Jan> +fetch_die_location_block (unsigned int offset, struct dwarf2_per_cu_data *per_cu)

I think this function name should have a dwarf2_ prefix.
Also it looks like this line wraps.

Jan> --- a/gdb/symfile.h
Jan> +++ b/gdb/symfile.h
Jan> @@ -569,6 +569,10 @@ extern int dwarf2_has_info (struct objfile *);
Jan>  extern void dwarf2_build_psymtabs (struct objfile *);
Jan>  extern void dwarf2_build_frame_info (struct objfile *);
 
Jan> +struct dwarf2_per_cu_data;
Jan> +extern struct dwarf2_locexpr_baton fetch_die_location_block
Jan> +  (unsigned int offset, struct dwarf2_per_cu_data *per_cu);

I think this should go in one of the dwarf headers, not symfile.h.
I think probably dwarf2loc.h, near the other functions taking a
dwarf2_per_cu_data.

Ok with these changes.  Thanks.

Tom


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 1/2] DW_OP_call: Provide per_cu in the batons
  2010-06-07 17:44       ` Tom Tromey
@ 2010-06-07 19:44         ` Jan Kratochvil
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Kratochvil @ 2010-06-07 19:44 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Mon, 07 Jun 2010 19:44:03 +0200, Tom Tromey wrote:
> Jan> +  /* Set no non-NULL iff this CU is currently loaded.  When it gets freed out
> 
> s/no/to/

Sorry, fixed.  Checked-in.


Thanks,
Jan


http://sourceware.org/ml/gdb-cvs/2010-06/msg00062.html

--- src/gdb/ChangeLog	2010/06/07 17:50:58	1.11883
+++ src/gdb/ChangeLog	2010/06/07 19:42:58	1.11884
@@ -1,3 +1,14 @@
+2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwarf2loc.c (struct dwarf_expr_baton) Replace objfile by per_cu.
+	(dwarf_expr_tls_address): Use per_cu instead of objfile.
+	(dwarf2_evaluate_loc_desc): Drop initialization of BATON.OBJFILE.
+	Initialize new BATON.PER_CU.  Adjust CTX->GDBARCH initialization for
+	this change.
+	(struct needs_frame_baton): New field per_cu.
+	(dwarf2_loc_desc_needs_frame): Initialize new BATON.PER_CU.
+	* dwarf2read.c (struct dwarf2_per_cu_data) <cu>: Extend the comment.
+
 2010-06-07  Sami Wagiaalla  <swagiaal@redhat.com>
 
 	* cp-support.c (make_symbol_overload_list_namespace): Only search
--- src/gdb/dwarf2loc.c	2010/06/04 02:39:16	1.86
+++ src/gdb/dwarf2loc.c	2010/06/07 19:42:58	1.87
@@ -122,7 +122,7 @@
 struct dwarf_expr_baton
 {
   struct frame_info *frame;
-  struct objfile *objfile;
+  struct dwarf2_per_cu_data *per_cu;
 };
 
 /* Helper functions for dwarf2_evaluate_loc_desc.  */
@@ -227,8 +227,9 @@
 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 (debaton->objfile, offset);
+  return target_translate_tls_address (objfile, offset);
 }
 
 struct piece_closure
@@ -801,12 +802,12 @@
     }
 
   baton.frame = frame;
-  baton.objfile = dwarf2_per_cu_objfile (per_cu);
+  baton.per_cu = per_cu;
 
   ctx = new_dwarf_expr_context ();
   old_chain = make_cleanup_free_dwarf_expr_context (ctx);
 
-  ctx->gdbarch = get_objfile_arch (baton.objfile);
+  ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (per_cu));
   ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
   ctx->baton = &baton;
   ctx->read_reg = dwarf_expr_read_reg;
@@ -907,6 +908,7 @@
 struct needs_frame_baton
 {
   int needs_frame;
+  struct dwarf2_per_cu_data *per_cu;
 };
 
 /* Reads from registers do require a frame.  */
@@ -973,6 +975,7 @@
   struct cleanup *old_chain;
 
   baton.needs_frame = 0;
+  baton.per_cu = per_cu;
 
   ctx = new_dwarf_expr_context ();
   old_chain = make_cleanup_free_dwarf_expr_context (ctx);
--- src/gdb/dwarf2read.c	2010/06/05 14:11:54	1.395
+++ src/gdb/dwarf2read.c	2010/06/07 19:42:58	1.396
@@ -337,7 +337,8 @@
      Otherwise it's from .debug_info.  */
   unsigned int from_debug_types : 1;
 
-  /* Set iff currently read in.  */
+  /* Set to non-NULL iff this CU is currently loaded.  When it gets freed out
+     of the CU cache it gets reset to NULL again.  */
   struct dwarf2_cu *cu;
 
   /* If full symbols for this CU have been read in, then this field


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [patch 2/2] DW_OP_call: Support DW_OP_call2 and DW_OP_call4
  2010-06-07 18:13       ` Tom Tromey
@ 2010-06-07 20:00         ` Jan Kratochvil
  0 siblings, 0 replies; 11+ messages in thread
From: Jan Kratochvil @ 2010-06-07 20:00 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On Mon, 07 Jun 2010 20:12:58 +0200, Tom Tromey wrote:
> Would you mind filing a new PR for DW_OP_call_ref?

Filed now PR 11674.


> Jan> +struct dwarf2_locexpr_baton
> Jan> +fetch_die_location_block (unsigned int offset, struct dwarf2_per_cu_data *per_cu)
> 
> I think this function name should have a dwarf2_ prefix.
> Also it looks like this line wraps.

I agree, fixed, mistake while making it public.


> Jan> --- a/gdb/symfile.h
> Jan> +++ b/gdb/symfile.h
> Jan> +struct dwarf2_per_cu_data;
> Jan> +extern struct dwarf2_locexpr_baton fetch_die_location_block
> Jan> +  (unsigned int offset, struct dwarf2_per_cu_data *per_cu);
> 
> I think this should go in one of the dwarf headers, not symfile.h.
> I think probably dwarf2loc.h, near the other functions taking a
> dwarf2_per_cu_data.

I agree, moved there.


> Ok with these changes.  Thanks.

Checked-in.


Thanks,
Jan


http://sourceware.org/ml/gdb-cvs/2010-06/msg00063.html

--- src/gdb/ChangeLog	2010/06/07 19:42:58	1.11884
+++ src/gdb/ChangeLog	2010/06/07 19:55:33	1.11885
@@ -1,5 +1,23 @@
 2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
+	Fix PR 10640.
+	* dwarf2-frame.c (no_dwarf_call): New function.
+	(execute_stack_op): Set CTX->DWARF_CALL.
+	* dwarf2expr.c (execute_stack_op) <DW_OP_call2, DW_OP_call4>: New.
+	* dwarf2expr.h (struct dwarf_expr_context) <dwarf_call>: New.
+	(struct dwarf_expr_context) <get_subr>: Remove the #if0-ed field.
+	* dwarf2loc.c (per_cu_dwarf_call, dwarf_expr_dwarf_call): New functions.
+	(dwarf2_evaluate_loc_desc): Initialize CTX->DWARF_CALL.
+	(needs_frame_dwarf_call): New function.
+	(dwarf2_loc_desc_needs_frame): Initialize CTX->DWARF_CALL.
+	* dwarf2read.c (follow_die_offset): Based on former follow_die_ref.
+	Update the comment.  Move variables die, offset and error call to ...
+	(follow_die_ref): ... a new function.
+	(dwarf2_fetch_die_location_block): New function.
+	* dwarf2loc.h (dwarf2_fetch_die_location_block): New prototype.
+
+2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
 	* dwarf2loc.c (struct dwarf_expr_baton) Replace objfile by per_cu.
 	(dwarf_expr_tls_address): Use per_cu instead of objfile.
 	(dwarf2_evaluate_loc_desc): Drop initialization of BATON.OBJFILE.
--- src/gdb/dwarf2-frame.c	2010/05/25 16:41:45	1.111
+++ src/gdb/dwarf2-frame.c	2010/06/07 19:55:33	1.112
@@ -328,6 +328,15 @@
 		  _("Support for DW_OP_GNU_push_tls_address is unimplemented"));
 }
 
+/* Helper function for execute_stack_op.  */
+
+static void
+no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+  internal_error (__FILE__, __LINE__,
+		  _("Support for DW_OP_call* is invalid in CFI"));
+}
+
 /* Execute the required actions for both the DW_CFA_restore and
 DW_CFA_restore_extended instructions.  */
 static void
@@ -378,6 +387,7 @@
   ctx->get_frame_base = no_get_frame_base;
   ctx->get_frame_cfa = no_get_frame_cfa;
   ctx->get_tls_address = no_get_tls_address;
+  ctx->dwarf_call = no_dwarf_call;
 
   dwarf_expr_push (ctx, initial, initial_in_stack_memory);
   dwarf_expr_eval (ctx, exp, len);
--- src/gdb/dwarf2expr.c	2010/05/25 16:41:46	1.45
+++ src/gdb/dwarf2expr.c	2010/06/07 19:55:33	1.46
@@ -911,6 +911,18 @@
 	  ctx->initialized = 0;
 	  goto no_push;
 
+	case DW_OP_call2:
+	  result = extract_unsigned_integer (op_ptr, 2, byte_order);
+	  op_ptr += 2;
+	  ctx->dwarf_call (ctx, result);
+	  goto no_push;
+
+	case DW_OP_call4:
+	  result = extract_unsigned_integer (op_ptr, 4, byte_order);
+	  op_ptr += 4;
+	  ctx->dwarf_call (ctx, result);
+	  goto no_push;
+
 	default:
 	  error (_("Unhandled dwarf expression opcode 0x%x"), op);
 	}
--- src/gdb/dwarf2expr.h	2010/06/02 19:37:55	1.24
+++ src/gdb/dwarf2expr.h	2010/06/07 19:55:33	1.25
@@ -97,15 +97,14 @@
      DW_OP_GNU_push_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, size_t die_offset);
+
 #if 0
   /* Not yet implemented.  */
 
-  /* Return the location expression for the dwarf expression
-     subroutine in the die at OFFSET in the current compilation unit.
-     The result must be live until the current expression evaluation
-     is complete.  */
-  unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length);
-
   /* Return the `object address' for DW_OP_push_object_address.  */
   CORE_ADDR (*get_object_address) (void *baton);
 #endif
--- src/gdb/dwarf2loc.c	2010/06/07 19:42:58	1.87
+++ src/gdb/dwarf2loc.c	2010/06/07 19:55:33	1.88
@@ -232,6 +232,33 @@
   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, size_t die_offset,
+		   struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_locexpr_baton block;
+
+  block = dwarf2_fetch_die_location_block (die_offset, per_cu);
+
+  /* DW_OP_call_ref is currently not supported.  */
+  gdb_assert (block.per_cu == per_cu);
+
+  dwarf_expr_eval (ctx, 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, size_t die_offset)
+{
+  struct dwarf_expr_baton *debaton = ctx->baton;
+
+  return per_cu_dwarf_call (ctx, die_offset, debaton->per_cu);
+}
+
 struct piece_closure
 {
   /* Reference count.  */
@@ -815,6 +842,7 @@
   ctx->get_frame_base = dwarf_expr_frame_base;
   ctx->get_frame_cfa = dwarf_expr_frame_cfa;
   ctx->get_tls_address = dwarf_expr_tls_address;
+  ctx->dwarf_call = dwarf_expr_dwarf_call;
 
   dwarf_expr_eval (ctx, data, size);
   if (ctx->num_pieces > 0)
@@ -962,6 +990,16 @@
   return 1;
 }
 
+/* Helper interface of per_cu_dwarf_call for dwarf2_loc_desc_needs_frame.  */
+
+static void
+needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset)
+{
+  struct needs_frame_baton *nf_baton = ctx->baton;
+
+  return per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu);
+}
+
 /* Return non-zero iff the location expression at DATA (length SIZE)
    requires a frame to evaluate.  */
 
@@ -988,6 +1026,7 @@
   ctx->get_frame_base = needs_frame_frame_base;
   ctx->get_frame_cfa = needs_frame_frame_cfa;
   ctx->get_tls_address = needs_frame_tls_address;
+  ctx->dwarf_call = needs_frame_dwarf_call;
 
   dwarf_expr_eval (ctx, data, size);
 
--- src/gdb/dwarf2loc.h	2010/06/02 19:37:55	1.16
+++ src/gdb/dwarf2loc.h	2010/06/07 19:55:33	1.17
@@ -37,6 +37,9 @@
 /* Return the offset size given in the compilation unit header for CU.  */
 int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu);
 
+struct dwarf2_locexpr_baton dwarf2_fetch_die_location_block
+  (unsigned int offset, struct dwarf2_per_cu_data *per_cu);
+
 /* The symbol location baton types used by the DWARF-2 reader (i.e.
    SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol).  "struct
    dwarf2_locexpr_baton" is for a symbol with a single location
--- src/gdb/dwarf2read.c	2010/06/07 19:42:58	1.396
+++ src/gdb/dwarf2read.c	2010/06/07 19:55:33	1.397
@@ -10736,30 +10736,25 @@
   return die;
 }
 
-/* Follow reference attribute ATTR of SRC_DIE.
-   On entry *REF_CU is the CU of SRC_DIE.
+/* Follow reference OFFSET.
+   On entry *REF_CU is the CU of source DIE referencing OFFSET.
    On exit *REF_CU is the CU of the result.  */
 
 static struct die_info *
-follow_die_ref (struct die_info *src_die, struct attribute *attr,
-		struct dwarf2_cu **ref_cu)
+follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu)
 {
-  struct die_info *die;
-  unsigned int offset;
   struct die_info temp_die;
   struct dwarf2_cu *target_cu, *cu = *ref_cu;
 
   gdb_assert (cu->per_cu != NULL);
 
-  offset = dwarf2_get_ref_die_offset (attr);
-
   if (cu->per_cu->from_debug_types)
     {
       /* .debug_types CUs cannot reference anything outside their CU.
 	 If they need to, they have to reference a signatured type via
 	 DW_FORM_sig8.  */
       if (! offset_in_cu_p (&cu->header, offset))
-	goto not_found;
+	return NULL;
       target_cu = cu;
     }
   else if (! offset_in_cu_p (&cu->header, offset))
@@ -10779,15 +10774,67 @@
 
   *ref_cu = target_cu;
   temp_die.offset = offset;
-  die = htab_find_with_hash (target_cu->die_hash, &temp_die, offset);
-  if (die)
-    return die;
+  return htab_find_with_hash (target_cu->die_hash, &temp_die, offset);
+}
 
- not_found:
+/* Follow reference attribute ATTR of SRC_DIE.
+   On entry *REF_CU is the CU of SRC_DIE.
+   On exit *REF_CU is the CU of the result.  */
 
-  error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
-	 "at 0x%x [in module %s]"),
-	 offset, src_die->offset, cu->objfile->name);
+static struct die_info *
+follow_die_ref (struct die_info *src_die, struct attribute *attr,
+		struct dwarf2_cu **ref_cu)
+{
+  unsigned int offset = dwarf2_get_ref_die_offset (attr);
+  struct dwarf2_cu *cu = *ref_cu;
+  struct die_info *die;
+
+  die = follow_die_offset (offset, ref_cu);
+  if (!die)
+    error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
+	   "at 0x%x [in module %s]"),
+	   offset, src_die->offset, cu->objfile->name);
+
+  return die;
+}
+
+/* Return DWARF block and its CU referenced by OFFSET at PER_CU.  Returned
+   value is intended for DW_OP_call*.  */
+
+struct dwarf2_locexpr_baton
+dwarf2_fetch_die_location_block (unsigned int offset,
+				 struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf2_cu *cu = per_cu->cu;
+  struct die_info *die;
+  struct attribute *attr;
+  struct dwarf2_locexpr_baton retval;
+
+  die = follow_die_offset (offset, &cu);
+  if (!die)
+    error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
+	   offset, per_cu->cu->objfile->name);
+
+  attr = dwarf2_attr (die, DW_AT_location, cu);
+  if (!attr)
+    {
+      /* DWARF: "If there is no such attribute, then there is no effect.".  */
+
+      retval.data = NULL;
+      retval.size = 0;
+    }
+  else
+    {
+      if (!attr_form_is_block (attr))
+	error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
+		 "is neither DW_FORM_block* nor DW_FORM_exprloc"),
+	       offset, per_cu->cu->objfile->name);
+
+      retval.data = DW_BLOCK (attr)->data;
+      retval.size = DW_BLOCK (attr)->size;
+    }
+  retval.per_cu = cu->per_cu;
+  return retval;
 }
 
 /* Follow the signature attribute ATTR in SRC_DIE.
--- src/gdb/testsuite/ChangeLog	2010/06/07 16:11:33	1.2320
+++ src/gdb/testsuite/ChangeLog	2010/06/07 19:55:33	1.2321
@@ -1,3 +1,8 @@
+2010-06-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Test PR 10640.
+	* gdb.dwarf2/dw2-op-call.exp, gdb.dwarf2/dw2-op-call.S: New.
+
 2010-06-07  Sami Wagiaalla  <swagiaal@redhat.com>
 
 	* gdb.cp/koenig.exp: Test for ADL operators.
--- src/gdb/testsuite/gdb.dwarf2/dw2-op-call.S
+++ src/gdb/testsuite/gdb.dwarf2/dw2-op-call.S	2010-06-07 19:56:46.801150000 +0000
@@ -0,0 +1,119 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.  */
+
+	.section .data
+array1:	.2byte	1
+array2:	.2byte	2
+array3:	.2byte	3
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.ascii	"file1.txt\0"			/* DW_AT_name */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	2				/* DW_LANG_C (C) */
+
+.L2byte_type:
+	.uleb128	2			/* Abbrev: DW_TAG_base_type */
+	.ascii		"2byte\0"		/* DW_AT_name */
+	.byte		2			/* DW_AT_byte_size */
+	.byte		7			/* DW_AT_encoding: DW_ATE_unsigned */
+
+.Larray1:
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array1\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		3			/*   DW_OP_addr */
+	.4byte		array			/*     <addr> */
+2:
+
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array2\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		0x98			/*   DW_OP_call2 */
+	.2byte		.Larray1-.Lcu1_begin	/*     <current CU offset> */
+	.byte		0x23			/*   DW_OP_plus_uconst */
+	.uleb128	array2-array1		/*     <uconst> */
+2:
+
+	.uleb128	3			/* Abbrev: DW_TAG_variable */
+	.ascii		"array3\0"		/* DW_AT_name */
+	.4byte		.L2byte_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		0x99			/*   DW_OP_call4 */
+	.4byte		.Larray1-.Lcu1_begin	/*     <current CU offset> */
+	.byte		0x23			/*   DW_OP_plus_uconst */
+	.uleb128	array3-array1		/*     <uconst> */
+2:
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x24			/* DW_TAG_base_type */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0xb			/* DW_AT_byte_size */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3e			/* DW_AT_encoding */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x2			/* DW_AT_location */
+	.uleb128	0xa			/* DW_FORM_block1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
--- src/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp
+++ src/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp	2010-06-07 19:56:47.302709000 +0000
@@ -0,0 +1,41 @@
+# Copyright 2009 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+
+set testfile "dw2-op-call"
+set srcfile ${testfile}.S
+set executable ${testfile}.x
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${executable}" object {nodebug}] != "" } {
+    return -1
+}
+
+clean_restart $executable
+
+gdb_test "p array1" " = 1"
+gdb_test "p array2" " = 2" "array2 using DW_OP_call2"
+gdb_test "p array3" " = 3" "array3 using DW_OP_call4"


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-06-07 20:00 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-20 12:37 [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640) Jan Kratochvil
2009-10-12 20:43 ` Tom Tromey
2009-10-12 20:49   ` Tom Tromey
2010-06-07 11:56     ` [patch 1/2] DW_OP_call: Provide per_cu in the batons Jan Kratochvil
2010-06-07 17:44       ` Tom Tromey
2010-06-07 19:44         ` Jan Kratochvil
2010-06-07 11:56     ` [patch 2/2] DW_OP_call: Support DW_OP_call2 and DW_OP_call4 Jan Kratochvil
2010-06-07 18:13       ` Tom Tromey
2010-06-07 20:00         ` Jan Kratochvil
2010-06-07 11:56     ` [patch 0/2] DW_OP_call: Re: [patch] Support DW_OP_call2 and DW_OP_call4 (PR 10640) Jan Kratochvil
2009-10-12 21:08   ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox