This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils 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]

supporting DW_OP_{implicit,stack}_value


Hi,

Since the gcc vta branch now emits the new (Dwarf 4) DW_OP_stack_value
and DW_OP_implicit_value operands I looked into supporting them. This is
a little bit difficult since, especially DW_OP_implicit_value changes
some assumptions (at least some of mine).

Unlike what the current comment in dwarf.h says the value block of
DW_OP_implicit_value isn't carried in a DW_FORM, but uses the "raw
memory encoding of the target". At least that is what gcc seems to emit,
and reading the spec, that does seem what was meant to happen. This is
somewhat awkward since it means we don't have the context to interpret
the value at this point. You could see what points to the location
description and see what the type should be, but that might not always
be simple, so you have to depend on the caller knowing what to do with
the "raw memory encoding".

2009-07-19  Mark Wielaard  <mjw@redhat.com>

    * dwarf.h: Correct description of DW_OP_implicit_value encoding.

Making readelf support them isn't too hard. For DW_OP_stack_value it is
simply listing the new opcode. For DW_OP_implicit_value it means just
reading the length and the (non-encoded) value. The only difficult is
whether or not the try to print the value in a decoded form when the
length is known. My patch prints it decoded when it is [1,] 2, 4 or 8
bytes since it is most likely to be a value of a basic type, otherwise
it just dumps it as a hex bytes as is.

2009-07-19  Mark Wielaard  <mjw@redhat.com>

    * readelf.c (print_ops): Add handling of DW_OP_implicit_value
    and DW_OP_stack_value.

Then we come to libdw getlocation() and things get a bit harder. Again
DW_OP_stack_value isn't much trouble. It doesn't have any operands, so
just return it as is when interning. But DW_OP_implicit_value is a bit
of an issue, since we don't know the actual value (no DW_FORM, just raw
bytes), there is no convenient way to store it. Also it can be of
arbitrary length, and all we have are two Dwarf_Words. In theory we
could just pass the length and the offset (already there in the
Dwarf_Op) into the Dwarf_Block. But there are two issues with this.

First, the offset is to the start of the DW_OP and there is no
convenient way I know of for the caller to get the size of the length
encoding, so it is hard to determine the actual offset (we could store
the extra offset/length-size in the number2 Dwarf_Word though).

Secondly I don't actually understand how the caller would get a handle
to the Dwarf_Block the offset refers to. For dwarf_getlocation() it
would be easy, just call dwarf_formblock() on the Dwarf_Attribute. But
for dwarf_getlocation_addr() the caller would have to parse the location
list themselves and hope they do it in the same order/preference that
dwarf_getlocation_addr() does it. Or am I missing some simple method to
get at the Dwarf_Block that the Dwarf_Op array that
dwarf_getlocation_addr() returns refer to?

So for now I just store the length as number and the actual address into
the Dwarf_Block data where the raw memory representation starts into
number2. But this feels a bit like cheating, since it isn't really
interning the DW_OP data since it depends on having the pointer into the
data around.

2009-07-20  Mark Wielaard  <mjw@redhat.com>

    * dwarf_getlocation.c (__libdw_intern_expression): Handle
    DW_OP_stack_value and DW_OP_implicit_value.

Cheers,

Mark
>From a13c73f442fce818ff2941559ea88946e081f2d8 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Sun, 19 Jul 2009 16:01:57 +0200
Subject: [PATCH 1/3] Correct description of DW_implicit_value encoding comment.

---
 libdw/ChangeLog |    4 ++++
 libdw/dwarf.h   |    3 ++-
 2 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index cd30872..f24e4b5 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,7 @@
+2009-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Correct description of DW_OP_implicit_value encoding.
+
 2009-07-16  Roland McGrath  <roland@redhat.com>
 
 	* dwarf_formudata.c (__libdw_formptr): Handle DW_FORM_sec_offset,
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
index 196ef85..063309e 100644
--- a/libdw/dwarf.h
+++ b/libdw/dwarf.h
@@ -441,7 +441,8 @@ enum
     DW_OP_form_tls_address = 0x9b,/* TLS offset to address in current thread */
     DW_OP_call_frame_cfa = 0x9c,/* CFA as determined by CFI.  */
     DW_OP_bit_piece = 0x9d,	/* ULEB128 size and ULEB128 offset in bits.  */
-    DW_OP_implicit_value = 0x9e, /* DW_FORM_block follows opcode.  */
+    DW_OP_implicit_value = 0x9e, /* ULEB128 size, followed by size bytes
+				    in target memory representation.  */
     DW_OP_stack_value = 0x9f,	 /* No operands, special like DW_OP_piece.  */
 
     /* GNU extensions.  */
-- 
1.6.2.5

>From 84262060acd8b24c249d0a03fc143a4a10e77ea5 Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Sun, 19 Jul 2009 16:11:48 +0200
Subject: [PATCH 2/3] Add handling of DW_OP_implicit_value and DW_OP_stack_value to readelf -w.

---
 src/ChangeLog |    5 +++++
 src/readelf.c |   34 ++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 69f9a65..49dc689 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,8 @@
+2009-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Add handling of DW_OP_implicit_value
+	and DW_OP_stack_value.
+
 2009-07-14  Ulrich Drepper  <drepper@redhat.com>
 
 	* elflint.c (check_elf_header): Allow Linux ABI.
diff --git a/src/readelf.c b/src/readelf.c
index 2e8257f..20545f9 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -3880,6 +3880,8 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
       [DW_OP_form_tls_address] = "form_tls_address",
       [DW_OP_call_frame_cfa] = "call_frame_cfa",
       [DW_OP_bit_piece] = "bit_piece",
+      [DW_OP_implicit_value] = "implicit_value",
+      [DW_OP_stack_value] = "stack_value",
     };
 
   if (len == 0)
@@ -4092,6 +4094,38 @@ print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
 	  offset += 3;
 	  break;
 
+	case DW_OP_implicit_value:
+	  {
+	    const unsigned char *start_op = data;
+	    unsigned int ulen;
+	    get_uleb128 (ulen, data); /* XXX check overrun */
+	    printf ("%*s[%4" PRIuMAX "] %s %u (0x",
+		    indent, "", (uintmax_t) offset, known[op], ulen);
+	    NEED (ulen);
+	    /* Try to print out the value if in known size, otherwise
+	       just dump it out. */
+	    switch (ulen)
+	      {
+	      case 2:
+		printf("%" PRIx16, read_2ubyte_unaligned_inc (dbg, data));
+		break;
+	      case 4:
+		printf("%" PRIx32, read_4ubyte_unaligned_inc (dbg, data));
+		break;
+	      case 8:
+		printf("%" PRIx64, read_8ubyte_unaligned_inc (dbg, data));
+		break;
+	      default:
+		while (ulen-- > 0)
+		  printf("%x", *data++);
+		break;
+	      }
+	    printf(")\n");
+	    len -= (data - start_op);
+	    offset += 1 + (data - start_op);
+	    break;
+	  }
+
 	default:
 	  /* No Operand.  */
 	  if (op < sizeof known / sizeof known[0] && known[op] != NULL)
-- 
1.6.2.5

>From a8af48bd8fd482576a28fa94dfa7992351b9b70f Mon Sep 17 00:00:00 2001
From: Mark Wielaard <mjw@redhat.com>
Date: Mon, 20 Jul 2009 11:18:11 +0200
Subject: [PATCH 3/3] Handle DW_OP_stack_value and DW_OP_implicit_value in dwarf_getlocation.

---
 libdw/ChangeLog           |    5 +++++
 libdw/dwarf_getlocation.c |    9 +++++++++
 2 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/libdw/ChangeLog b/libdw/ChangeLog
index f24e4b5..bbfbcb7 100644
--- a/libdw/ChangeLog
+++ b/libdw/ChangeLog
@@ -1,3 +1,8 @@
+2009-07-20  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle
+	DW_OP_stack_value and DW_OP_implicit_value.
+
 2009-07-19  Mark Wielaard  <mjw@redhat.com>
 
 	* dwarf.h: Correct description of DW_OP_implicit_value encoding.
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
index c7f7a89..3785287 100644
--- a/libdw/dwarf_getlocation.c
+++ b/libdw/dwarf_getlocation.c
@@ -244,6 +244,7 @@ __libdw_intern_expression (Dwarf *dbg,
 	case DW_OP_push_object_address:
 	case DW_OP_call_ref:
 	case DW_OP_call_frame_cfa:
+	case DW_OP_stack_value:
 	case DW_OP_form_tls_address:
 	case DW_OP_GNU_push_tls_address:
 	  /* No operand.  */
@@ -344,6 +345,14 @@ __libdw_intern_expression (Dwarf *dbg,
 	  get_uleb128 (newloc->number2, data);
 	  break;
 
+	case DW_OP_implicit_value:
+	  /* XXX Check size. */
+	  get_uleb128 (newloc->number, data); /* length */
+	  /* pointer to raw memory representation of size length */
+	  newloc->number2 = (Dwarf_Word) (uintptr_t) data;
+	  data += newloc->number;
+	  break;
+
 	default:
 	  goto invalid;
 	}
-- 
1.6.2.5


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