aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog13
-rw-r--r--gdb/dwarf2loc.c99
-rw-r--r--gdb/dwarf2loc.h3
-rw-r--r--gdb/dwarf2read.c25
-rw-r--r--gdb/testsuite/ChangeLog6
-rw-r--r--gdb/testsuite/gdb.dwarf2/nonvar-access.exp28
-rw-r--r--gdb/testsuite/lib/dwarf.exp3
7 files changed, 131 insertions, 46 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8bc3aec..d0d0f72 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,16 @@
+2017-03-16 Andreas Arnez <arnez@linux.vnet.ibm.com>
+
+ * 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.
+
2017-03-16 Yao Qi <yao.qi@linaro.org>
* arm-tdep.c (thumb_record_misc): Decode CBNZ, CBZ, REV16,
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
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index 1f3e20e..9063b6e 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -79,6 +79,9 @@ extern const gdb_byte *dwarf2_fetch_constant_bytes (sect_offset,
struct obstack *,
LONGEST *);
+struct type *dwarf2_fetch_die_type_sect_off (sect_offset,
+ struct dwarf2_per_cu_data *);
+
struct type *dwarf2_get_die_type (cu_offset die_offset,
struct dwarf2_per_cu_data *per_cu);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 40b99d9..da70884 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -20775,6 +20775,31 @@ dwarf2_fetch_constant_bytes (sect_offset offset,
return result;
}
+/* Return the type of the die at OFFSET in PER_CU. Return NULL if no
+ valid type for this die is found. */
+
+struct type *
+dwarf2_fetch_die_type_sect_off (sect_offset offset,
+ struct dwarf2_per_cu_data *per_cu)
+{
+ struct dwarf2_cu *cu;
+ struct die_info *die;
+
+ dw2_setup (per_cu->objfile);
+
+ if (per_cu->cu == NULL)
+ load_cu (per_cu);
+ cu = per_cu->cu;
+ if (!cu)
+ return NULL;
+
+ die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+ if (!die)
+ return NULL;
+
+ return die_type (die, cu);
+}
+
/* Return the type of the DIE at DIE_OFFSET in the CU named by
PER_CU. */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 8a3096f..018104c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-03-16 Andreas Arnez <arnez@linux.vnet.ibm.com>
+
+ * 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.
+
2017-03-16 Doug Evans <dje@google.com>
* gdb.python/py-lazy-string (pointer): Really add new typedef.
diff --git a/gdb/testsuite/gdb.dwarf2/nonvar-access.exp b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp
index 3cb5c49..99f63cc 100644
--- a/gdb/testsuite/gdb.dwarf2/nonvar-access.exp
+++ b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp
@@ -33,7 +33,7 @@ Dwarf::assemble $asm_file {
} {
declare_labels int_type_label char_type_label \
struct_s_label struct_t_label array_a9_label \
- char_ptr_label implicit_a_label
+ char_ptr_label implicit_a_label stack_b_label
int_type_label: base_type {
{name "int"}
@@ -159,7 +159,24 @@ Dwarf::assemble $asm_file {
{name implicit_a_ptr}
{type :$char_ptr_label}
{location {
- GNU_implicit_pointer $implicit_a_label 5
+ implicit_pointer $implicit_a_label 5
+ } SPECIAL_expr}
+ }
+ # Stack-value location.
+ stack_b_label: DW_TAG_variable {
+ {name def_stack_b}
+ {type :$struct_t_label}
+ {location {
+ const4u 0x1a2b3c4d
+ stack_value
+ } SPECIAL_expr}
+ }
+ # Implicit pointer into stack value.
+ DW_TAG_variable {
+ {name implicit_b_ptr}
+ {type :$char_ptr_label}
+ {location {
+ implicit_pointer $stack_b_label 1
} SPECIAL_expr}
}
}
@@ -194,6 +211,13 @@ gdb_test "print/x def_implicit_a" \
gdb_test "print/x def_implicit_a\[5\]" " = 0x56"
gdb_test "print/x *(char (*)\[5\]) implicit_a_ptr" \
" = \\{0x56, 0x67, 0x78, 0x89, 0x9a\\}"
+switch $endian {
+ big {set val "a = 52, b = 2833485"}
+ little {set val "a = 77, b = 857502"}
+}
+gdb_test "print def_stack_b" " = \\{$val\\}"
+switch $endian {big {set val 0x2b} little {set val 0x3c}}
+gdb_test "print/x *implicit_b_ptr" " = $val"
# Byte-aligned fields, pieced together from DWARF stack values.
gdb_test "print def_s" " = \\{a = 0, b = -1\\}"
diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp
index 1ccdc5d..989a717 100644
--- a/gdb/testsuite/lib/dwarf.exp
+++ b/gdb/testsuite/lib/dwarf.exp
@@ -946,9 +946,10 @@ namespace eval Dwarf {
define_label $l2
}
+ DW_OP_implicit_pointer -
DW_OP_GNU_implicit_pointer {
if {[llength $line] != 3} {
- error "usage: DW_OP_GNU_implicit_pointer LABEL OFFSET"
+ error "usage: $opcode LABEL OFFSET"
}
# Here label is a section offset.