diff options
author | Andreas Arnez <arnez@linux.vnet.ibm.com> | 2017-02-01 16:59:00 +0100 |
---|---|---|
committer | Andreas Arnez <arnez@linux.vnet.ibm.com> | 2017-02-01 16:59:00 +0100 |
commit | 7346ef59bb33e28161d78ab478c3476b3dab2e8e (patch) | |
tree | 9aa97840ceb8bb26016e1921210e6add8819f409 /gdb/dwarf2loc.c | |
parent | 787f00256b3eabe34b8599fca4df0243df80d5ca (diff) | |
download | gdb-7346ef59bb33e28161d78ab478c3476b3dab2e8e.zip gdb-7346ef59bb33e28161d78ab478c3476b3dab2e8e.tar.gz gdb-7346ef59bb33e28161d78ab478c3476b3dab2e8e.tar.bz2 |
Big-endian targets: Don't ignore offset into DW_OP_implicit_value
When a variable's location is expressed as DW_OP_implicit_value, but the
given value is longer than needed, which bytes should be used? GDB's
current logic was introduced with a patch from 2011 and uses the "least
significant" bytes:
https://sourceware.org/ml/gdb-patches/2011-08/msg00123.html
Now consider a sub-value from such a location at a given offset, accessed
through DW_OP_implicit_pointer. Which bytes should be used for that? The
patch above *always* uses the last bytes on big-endian targets, ignoring
the offset.
E.g., given the code snippet
const char foo[] = "Hello, world!";
const char *a = &foo[0];
const char *b = &foo[7];
assume that `foo' is described as DW_OP_implicit_value and `a' and `b'
each as DW_OP_implicit_pointer into that value. Then with current GDB
`*a' and `*b' yield the same result -- the string's zero terminator.
This patch basically reverts the portion of the patch above that deals
with DW_OP_implicit_value. This fixes the offset handling and also goes
back to dropping the last instead of the first bytes on big-endian targets
if the implicit value is longer than needed. The latter aspect of the
change probably doesn't matter for actual programs, but simplifies the
logic.
The patch also cleans up the original code a bit and adds appropriate test
cases.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/dw2-op-stack-value.exp: Adjust expected result of
taking a 2-byte value out of a 4-byte DWARF implicit value on
big-endian targets.
* gdb.dwarf2/nonvar-access.exp: Add more comments to existing
logic. Add test cases for DW_OP_implicit.
gdb/ChangeLog:
* dwarf2loc.c (dwarf2_evaluate_loc_desc_full): For
DWARF_VALUE_LITERAL, no longer ignore the offset on big-endian
targets. And if the implicit value is longer than needed, extract
the first bytes instead of the "least significant" ones.
Diffstat (limited to 'gdb/dwarf2loc.c')
-rw-r--r-- | gdb/dwarf2loc.c | 19 |
1 files changed, 3 insertions, 16 deletions
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 7fca76b..a592b66 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -2442,28 +2442,15 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, case DWARF_VALUE_LITERAL: { bfd_byte *contents; - const bfd_byte *ldata; - size_t n = ctx.len; + size_t n = TYPE_LENGTH (type); - if (byte_offset + TYPE_LENGTH (type) > n) + if (byte_offset + n > ctx.len) invalid_synthetic_pointer (); free_values.free_to_mark (); retval = allocate_value (type); contents = value_contents_raw (retval); - - ldata = ctx.data + byte_offset; - n -= byte_offset; - - if (n > TYPE_LENGTH (type)) - { - struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile); - - if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG) - ldata += n - TYPE_LENGTH (type); - n = TYPE_LENGTH (type); - } - memcpy (contents, ldata, n); + memcpy (contents, ctx.data + byte_offset, n); } break; |