aboutsummaryrefslogtreecommitdiff
path: root/gdb/dwarf2loc.c
diff options
context:
space:
mode:
authorAndreas Arnez <arnez@linux.vnet.ibm.com>2017-03-16 19:50:24 +0100
committerAndreas Arnez <arnez@linux.vnet.ibm.com>2017-03-16 19:50:24 +0100
commit7942e96e435d1cf4d4dbf58c47bb28d9f628c9e6 (patch)
treef09fed51fefa8ee276a87a786374ba95f4e2ece6 /gdb/dwarf2loc.c
parent6ebac3fbacebaebd9e2c9393da3b612342d953a9 (diff)
downloadgdb-7942e96e435d1cf4d4dbf58c47bb28d9f628c9e6.zip
gdb-7942e96e435d1cf4d4dbf58c47bb28d9f628c9e6.tar.gz
gdb-7942e96e435d1cf4d4dbf58c47bb28d9f628c9e6.tar.bz2
Big-endian targets: Don't ignore offset into DW_OP_stack_value
Recently I fixed a bug that caused a DW_OP_implicit_pointer with non-zero offset into a DW_OP_implicit_value to be handled incorrectly on big-endian targets. GDB ignored the offset and copied the wrong bytes: https://sourceware.org/ml/gdb-patches/2017-01/msg00251.html But there is still a similar issue when a DW_OP_implicit_pointer points into a DW_OP_stack_value instead; and again, the offset is ignored. There is an important difference, though: While implicit values are treated like blocks of data and anchored at the lowest-addressed byte, stack values traditionally contain integer numbers and are anchored at the *least significant* byte. Also, stack values do not come in varying sizes, but are cut down appropriately when used. Thus, on big-endian targets the scenario looks like this (higher addresses shown right): |<- - - - - Stack value - - - - - - ->| | | |<- original object ->| | | offset ->|####| ^^^^ de-referenced implicit pointer (Note how the original object's size influences the position of the de-referenced implicit pointer within the stack value. This is not the case for little-endian targets, where the original object starts at offset zero within the stack value.) This patch implements the logic indicated in the above diagram and adds an appropriate test case. A new function dwarf2_fetch_die_type_sect_off is added; it is used for retrieving the original object's type, so its size can be determined. That type is passed to dwarf2_evaluate_loc_desc_full via a new parameter. gdb/ChangeLog: * dwarf2loc.c (indirect_synthetic_pointer): Get data type of pointed-to DIE and pass it to dwarf2_evaluate_loc_desc_full. (dwarf2_evaluate_loc_desc_full): New parameter subobj_type; rename byte_offset to subobj_byte_offset. Fix the handling of DWARF_VALUE_STACK on big-endian targets when coming via an implicit pointer. (dwarf2_evaluate_loc_desc): Adjust call to dwarf2_evaluate_loc_desc_full. * dwarf2loc.h (dwarf2_fetch_die_type_sect_off): New declaration. * dwarf2read.c (dwarf2_fetch_die_type_sect_off): New function. gdb/testsuite/ChangeLog: * lib/dwarf.exp: Add support for DW_OP_implicit_pointer. * gdb.dwarf2/nonvar-access.exp: Add test for stack value location and implicit pointer into such a location.
Diffstat (limited to 'gdb/dwarf2loc.c')
-rw-r--r--gdb/dwarf2loc.c99
1 files changed, 56 insertions, 43 deletions
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 4393c1f..bc7665f 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -50,7 +50,8 @@ static struct value *dwarf2_evaluate_loc_desc_full (struct type *type,
const gdb_byte *data,
size_t size,
struct dwarf2_per_cu_data *per_cu,
- LONGEST byte_offset);
+ struct type *subobj_type,
+ LONGEST subobj_byte_offset);
static struct call_site_parameter *dwarf_expr_reg_to_entry_parameter
(struct frame_info *frame,
@@ -2163,12 +2164,18 @@ indirect_synthetic_pointer (sect_offset die, LONGEST byte_offset,
= dwarf2_fetch_die_loc_sect_off (die, per_cu,
get_frame_address_in_block_wrapper, frame);
+ /* Get type of pointed-to DIE. */
+ struct type *orig_type = dwarf2_fetch_die_type_sect_off (die, per_cu);
+ if (orig_type == NULL)
+ invalid_synthetic_pointer ();
+
/* If pointed-to DIE has a DW_AT_location, evaluate it and return the
resulting value. Otherwise, it may have a DW_AT_const_value instead,
or it may've been optimized out. */
if (baton.data != NULL)
- return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame,
- baton.data, baton.size, baton.per_cu,
+ return dwarf2_evaluate_loc_desc_full (orig_type, frame, baton.data,
+ baton.size, baton.per_cu,
+ TYPE_TARGET_TYPE (type),
byte_offset);
else
return fetch_const_value_from_synthetic_pointer (die, byte_offset, per_cu,
@@ -2327,23 +2334,30 @@ static const struct lval_funcs pieced_value_funcs = {
/* Evaluate a location description, starting at DATA and with length
SIZE, to find the current location of variable of TYPE in the
- context of FRAME. BYTE_OFFSET is applied after the contents are
- computed. */
+ context of FRAME. If SUBOBJ_TYPE is non-NULL, return instead the
+ location of the subobject of type SUBOBJ_TYPE at byte offset
+ SUBOBJ_BYTE_OFFSET within the variable of type TYPE. */
static struct value *
dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
const gdb_byte *data, size_t size,
struct dwarf2_per_cu_data *per_cu,
- LONGEST byte_offset)
+ struct type *subobj_type,
+ LONGEST subobj_byte_offset)
{
struct value *retval;
struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
- if (byte_offset < 0)
+ if (subobj_type == NULL)
+ {
+ subobj_type = type;
+ subobj_byte_offset = 0;
+ }
+ else if (subobj_byte_offset < 0)
invalid_synthetic_pointer ();
if (size == 0)
- return allocate_optimized_out_value (type);
+ return allocate_optimized_out_value (subobj_type);
dwarf_evaluate_loc_desc ctx;
ctx.frame = frame;
@@ -2366,8 +2380,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
if (ex.error == NOT_AVAILABLE_ERROR)
{
free_values.free_to_mark ();
- retval = allocate_value (type);
- mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type));
+ retval = allocate_value (subobj_type);
+ mark_value_bytes_unavailable (retval, 0,
+ TYPE_LENGTH (subobj_type));
return retval;
}
else if (ex.error == NO_ENTRY_VALUE_ERROR)
@@ -2375,7 +2390,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
if (entry_values_debug)
exception_print (gdb_stdout, ex);
free_values.free_to_mark ();
- return allocate_optimized_out_value (type);
+ return allocate_optimized_out_value (subobj_type);
}
else
throw_exception (ex);
@@ -2390,7 +2405,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
for (i = 0; i < ctx.num_pieces; ++i)
bit_size += ctx.pieces[i].size;
- if (8 * (byte_offset + TYPE_LENGTH (type)) > bit_size)
+ if (8 * (subobj_byte_offset + TYPE_LENGTH (subobj_type)) > bit_size)
invalid_synthetic_pointer ();
c = allocate_piece_closure (per_cu, ctx.num_pieces, ctx.pieces,
@@ -2398,8 +2413,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
/* We must clean up the value chain after creating the piece
closure but before allocating the result. */
free_values.free_to_mark ();
- retval = allocate_computed_value (type, &pieced_value_funcs, c);
- set_value_offset (retval, byte_offset);
+ retval = allocate_computed_value (subobj_type,
+ &pieced_value_funcs, c);
+ set_value_offset (retval, subobj_byte_offset);
}
else
{
@@ -2412,10 +2428,10 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
= longest_to_int (value_as_long (ctx.fetch (0)));
int gdb_regnum = dwarf_reg_to_regnum_or_error (arch, dwarf_regnum);
- if (byte_offset != 0)
+ if (subobj_byte_offset != 0)
error (_("cannot use offset on synthetic pointer to register"));
free_values.free_to_mark ();
- retval = value_from_register (type, gdb_regnum, frame);
+ retval = value_from_register (subobj_type, gdb_regnum, frame);
if (value_optimized_out (retval))
{
struct value *tmp;
@@ -2426,8 +2442,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
inspecting a register ($pc, $sp, etc.), return a
generic optimized out value instead, so that we show
<optimized out> instead of <not saved>. */
- tmp = allocate_value (type);
- value_contents_copy (tmp, 0, retval, 0, TYPE_LENGTH (type));
+ tmp = allocate_value (subobj_type);
+ value_contents_copy (tmp, 0, retval, 0,
+ TYPE_LENGTH (subobj_type));
retval = tmp;
}
}
@@ -2447,7 +2464,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
the operation. Therefore, we do the conversion here
since the type is readily available. */
- switch (TYPE_CODE (type))
+ switch (TYPE_CODE (subobj_type))
{
case TYPE_CODE_FUNC:
case TYPE_CODE_METHOD:
@@ -2460,7 +2477,8 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
address = value_as_address (value_from_pointer (ptr_type, address));
free_values.free_to_mark ();
- retval = value_at_lazy (type, address + byte_offset);
+ retval = value_at_lazy (subobj_type,
+ address + subobj_byte_offset);
if (in_stack_memory)
set_value_stack (retval, 1);
}
@@ -2469,18 +2487,15 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
case DWARF_VALUE_STACK:
{
struct value *value = ctx.fetch (0);
- gdb_byte *contents;
- const gdb_byte *val_bytes;
size_t n = TYPE_LENGTH (value_type (value));
+ size_t len = TYPE_LENGTH (subobj_type);
+ size_t max = TYPE_LENGTH (type);
+ struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
struct cleanup *cleanup;
- if (byte_offset + TYPE_LENGTH (type) > n)
+ if (subobj_byte_offset + len > max)
invalid_synthetic_pointer ();
- val_bytes = value_contents_all (value);
- val_bytes += byte_offset;
- n -= byte_offset;
-
/* Preserve VALUE because we are going to free values back
to the mark, but we still need the value contents
below. */
@@ -2488,17 +2503,14 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
free_values.free_to_mark ();
cleanup = make_cleanup_value_free (value);
- retval = allocate_value (type);
- contents = value_contents_raw (retval);
- if (n > TYPE_LENGTH (type))
- {
- struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
+ retval = allocate_value (subobj_type);
- if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG)
- val_bytes += n - TYPE_LENGTH (type);
- n = TYPE_LENGTH (type);
- }
- memcpy (contents, val_bytes, n);
+ /* The given offset is relative to the actual object. */
+ if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG)
+ subobj_byte_offset += n - max;
+
+ memcpy (value_contents_raw (retval),
+ value_contents_all (value) + subobj_byte_offset, len);
do_cleanups (cleanup);
}
@@ -2507,21 +2519,21 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
case DWARF_VALUE_LITERAL:
{
bfd_byte *contents;
- size_t n = TYPE_LENGTH (type);
+ size_t n = TYPE_LENGTH (subobj_type);
- if (byte_offset + n > ctx.len)
+ if (subobj_byte_offset + n > ctx.len)
invalid_synthetic_pointer ();
free_values.free_to_mark ();
- retval = allocate_value (type);
+ retval = allocate_value (subobj_type);
contents = value_contents_raw (retval);
- memcpy (contents, ctx.data + byte_offset, n);
+ memcpy (contents, ctx.data + subobj_byte_offset, n);
}
break;
case DWARF_VALUE_OPTIMIZED_OUT:
free_values.free_to_mark ();
- retval = allocate_optimized_out_value (type);
+ retval = allocate_optimized_out_value (subobj_type);
break;
/* DWARF_VALUE_IMPLICIT_POINTER was converted to a pieced
@@ -2547,7 +2559,8 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
const gdb_byte *data, size_t size,
struct dwarf2_per_cu_data *per_cu)
{
- return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0);
+ return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu,
+ NULL, 0);
}
/* Evaluates a dwarf expression and stores the result in VAL, expecting