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 <[email protected]> * 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 <[email protected]> * 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 <[email protected]> * 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 <[email protected]> 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 <[email protected]> + + * dwarf.h: Correct description of DW_OP_implicit_value encoding. + 2009-07-16 Roland McGrath <[email protected]> * 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 <[email protected]> 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 <[email protected]> + + * readelf.c (print_ops): Add handling of DW_OP_implicit_value + and DW_OP_stack_value. + 2009-07-14 Ulrich Drepper <[email protected]> * 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 <[email protected]> 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 <[email protected]> + + * dwarf_getlocation.c (__libdw_intern_expression): Handle + DW_OP_stack_value and DW_OP_implicit_value. + 2009-07-19 Mark Wielaard <[email protected]> * 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
_______________________________________________ elfutils-devel mailing list [email protected] https://fedorahosted.org/mailman/listinfo/elfutils-devel
