[PATCH] Handle GNU extension opcodes in dwarf_getlocation

Petr Machata pmachata at redhat.com
Tue Oct 9 00:27:51 UTC 2012


This is just for low-level byte munching support, so that libdw knows
how to decode the opcode stream, and doesn't fail when it encounters one
of the new opcodes.

The context is that I'm reviving locstat.  The test binary that I have
on hand uses some of these opcodes.  locstat mostly doesn't care what
exact location expression describes location of variable on any
particular address.  It just cares that there is at least one.  So
what's below actually fixes the problem for locstat, even if there are
no higher-level interfaces for grokking the extensions.

OK to push this?

Thanks,
PM

---
 libdw/ChangeLog           |    7 +++++++
 libdw/dwarf_getlocation.c |   26 ++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index 416a16f..0e65da8 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,10 @@
+2012-10-09  Petr Machata  <pmachata at redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle
+	DW_OP_GNU_parameter_ref, DW_OP_GNU_convert, DW_OP_GNU_reinterpret,
+	DW_OP_GNU_regval_type, DW_OP_GNU_entry_value,
+	DW_OP_GNU_deref_type, DW_OP_GNU_const_type.
+
 2012-08-24  Mark Wielaard  <mjw at redhat.com>
 
 	* dwarf_begin_elf.c (check_section): Only probe for dwz multi files
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index dfaa742..daeff2d 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -339,6 +339,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
 
 	case DW_OP_const4s:
 	case DW_OP_call4:
+	case DW_OP_GNU_parameter_ref:
 	  if (unlikely (data + 4 > end_data))
 	    goto invalid;
 
@@ -363,6 +364,8 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
 	case DW_OP_plus_uconst:
 	case DW_OP_regx:
 	case DW_OP_piece:
+	case DW_OP_GNU_convert:
+	case DW_OP_GNU_reinterpret:
 	  /* XXX Check size.  */
 	  get_uleb128 (newloc->number, data);
 	  break;
@@ -381,12 +384,14 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
 	  break;
 
 	case DW_OP_bit_piece:
+	case DW_OP_GNU_regval_type:
 	  /* XXX Check size.  */
 	  get_uleb128 (newloc->number, data);
 	  get_uleb128 (newloc->number2, data);
 	  break;
 
 	case DW_OP_implicit_value:
+	case DW_OP_GNU_entry_value:
 	  /* This cannot be used in a CFI expression.  */
 	  if (unlikely (dbg == NULL))
 	    goto invalid;
@@ -408,6 +413,27 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
 	  get_uleb128 (newloc->number2, data); /* Byte offset.  */
 	  break;
 
+	case DW_OP_GNU_deref_type:
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  newloc->number = *data++;
+	  get_uleb128 (newloc->number2, data);
+	  break;
+
+	case DW_OP_GNU_const_type:
+	  /* XXX Check size.  */
+	  get_uleb128 (newloc->number, data);
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  newloc->number2 = *data++; /* Block length.  */
+	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number2))
+	    goto invalid;
+	  /* The third operand is relative block offset:
+		newloc->number3 = data - block->data;
+	     We don't support this at this point.  */
+	  data += newloc->number2;		/* Skip the block.  */
+	  break;
+
 	default:
 	  goto invalid;
 	}
-- 
1.7.6.5



More information about the elfutils-devel mailing list