* [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value
@ 2017-02-13 19:00 Andreas Arnez
2017-03-13 14:30 ` Ulrich Weigand
0 siblings, 1 reply; 7+ messages in thread
From: Andreas Arnez @ 2017-02-13 19:00 UTC (permalink / raw)
To: gdb-patches; +Cc: Jan Kratochvil
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): Add parameter 'orig_type'. 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:
Andreas Arnez <arnez@linux.vnet.ibm.com>
* gdb.dwarf2/nonvar-access.exp: Add test for stack value location
and implicit pointer into such a location.
---
gdb/dwarf2loc.c | 39 +++++++++++++++---------------
gdb/dwarf2loc.h | 3 +++
gdb/dwarf2read.c | 25 +++++++++++++++++++
gdb/testsuite/gdb.dwarf2/nonvar-access.exp | 26 +++++++++++++++++++-
4 files changed, 72 insertions(+), 21 deletions(-)
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index c1e02eb..65479d8 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);
+ LONGEST byte_offset,
+ struct type *orig_type);
static struct call_site_parameter *dwarf_expr_reg_to_entry_parameter
(struct frame_info *frame,
@@ -2098,13 +2099,16 @@ 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 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,
- byte_offset);
+ byte_offset, orig_type);
else
return fetch_const_value_from_synthetic_pointer (die, byte_offset, per_cu,
type);
@@ -2269,7 +2273,7 @@ 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)
+ LONGEST byte_offset, struct type *orig_type)
{
struct value *retval;
struct objfile *objfile = dwarf2_per_cu_objfile (per_cu);
@@ -2404,18 +2408,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 (type);
+ size_t max = orig_type ? TYPE_LENGTH (orig_type) : len;
+ struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
struct cleanup *cleanup;
- if (byte_offset + TYPE_LENGTH (type) > n)
+ if (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. */
@@ -2424,16 +2425,13 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
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);
- 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)
+ byte_offset += n - max;
+
+ memcpy (value_contents_raw (retval),
+ value_contents_all (value) + byte_offset, len);
do_cleanups (cleanup);
}
@@ -2482,7 +2480,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,
+ 0, NULL);
}
/* Evaluates a dwarf expression and stores the result in VAL, expecting
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index d6cdbd2..d669d1e 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -77,6 +77,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 774ed73..bdaac19 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -20258,6 +20258,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/gdb.dwarf2/nonvar-access.exp b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp
index 3cb5c49..633c6b3 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"}
@@ -162,6 +162,23 @@ Dwarf::assemble $asm_file {
GNU_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 {
+ GNU_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\\}"
--
2.5.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value
2017-02-13 19:00 [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value Andreas Arnez
@ 2017-03-13 14:30 ` Ulrich Weigand
2017-03-15 18:05 ` Andreas Arnez
0 siblings, 1 reply; 7+ messages in thread
From: Ulrich Weigand @ 2017-03-13 14:30 UTC (permalink / raw)
To: Andreas Arnez; +Cc: gdb-patches, Jan Kratochvil
Andreas Arnez wrote:
> 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.
This makes sense to me.
> @@ -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);
> + LONGEST byte_offset,
> + struct type *orig_type);
Please update the comment to indicate the precise meaning of the ORIG_TYPE
parameter, and when it has to be specified and when it may be omitted.
Thinking about this more, maybe it would be clearer to swap around the
two types, and have the semantics of the function be something like:
/* 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. 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. */
Otherwise the patch looks good to me.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value
2017-03-13 14:30 ` Ulrich Weigand
@ 2017-03-15 18:05 ` Andreas Arnez
2017-03-15 19:16 ` Ulrich Weigand
0 siblings, 1 reply; 7+ messages in thread
From: Andreas Arnez @ 2017-03-15 18:05 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches, Jan Kratochvil
On Mon, Mar 13 2017, Ulrich Weigand wrote:
> Andreas Arnez wrote:
>
[...]
>> @@ -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);
>> + LONGEST byte_offset,
>> + struct type *orig_type);
>
> Please update the comment to indicate the precise meaning of the ORIG_TYPE
> parameter, and when it has to be specified and when it may be omitted.
>
> Thinking about this more, maybe it would be clearer to swap around the
> two types, and have the semantics of the function be something like:
>
> /* 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. 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. */
OK. Of course this increases the amount of change a bit. New patch
below.
Ready to apply?
--
Andreas
-- >8 --
Subject: [PATCH v2] 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:
* gdb.dwarf2/nonvar-access.exp: Add test for stack value location
and implicit pointer into such a location.
---
gdb/dwarf2loc.c | 97 +++++++++++++++++-------------
gdb/dwarf2loc.h | 3 +
gdb/dwarf2read.c | 25 ++++++++
gdb/testsuite/gdb.dwarf2/nonvar-access.exp | 26 +++++++-
4 files changed, 107 insertions(+), 44 deletions(-)
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 4393c1f..900278e 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,16 @@ 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 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 +2332,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 +2378,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 +2388,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 +2403,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 +2411,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 +2426,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 +2440,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 +2462,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 +2475,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 +2485,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 != NULL ? TYPE_LENGTH (type) : n;
+ 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 +2501,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 +2517,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 +2557,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/gdb.dwarf2/nonvar-access.exp b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp
index 3cb5c49..633c6b3 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"}
@@ -162,6 +162,23 @@ Dwarf::assemble $asm_file {
GNU_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 {
+ GNU_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\\}"
--
2.5.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value
2017-03-15 18:05 ` Andreas Arnez
@ 2017-03-15 19:16 ` Ulrich Weigand
2017-03-16 18:25 ` Andreas Arnez
0 siblings, 1 reply; 7+ messages in thread
From: Ulrich Weigand @ 2017-03-15 19:16 UTC (permalink / raw)
To: Andreas Arnez; +Cc: gdb-patches, Jan Kratochvil
Andreas Arnez wrote:
> On Mon, Mar 13 2017, Ulrich Weigand wrote:
> > Thinking about this more, maybe it would be clearer to swap around the
> > two types, and have the semantics of the function be something like:
> >
> > /* 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. 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. */
>
> OK. Of course this increases the amount of change a bit. New patch
> below.
Well, yes ... I still think it is clearer overall in the end.
> + /* Get type of pointed-to DIE. */
> + struct type *orig_type = dwarf2_fetch_die_type_sect_off (die, per_cu);
> +
> /* 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,
Can orig_type ever be NULL here? It probably would not be a good idea
to pass NULL as the type argument.
> - if (byte_offset != 0)
> + if (subobj_byte_offset != 0)
> error (_("cannot use offset on synthetic pointer to register"));
As an aside: now that we have the full object type, we may actually be able
to lift that restriction (do a value_from_register on the full type, and
then extract the subobject). Might be interesting to look into as a
follow-on change ...
> size_t n = TYPE_LENGTH (value_type (value));
> + size_t len = TYPE_LENGTH (subobj_type);
> + size_t max = type != NULL ? TYPE_LENGTH (type) : n;
As mentioned above, I don't think it makes sense to allow a NULL type here.
Otherwise, this looks good to me.
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value
2017-03-15 19:16 ` Ulrich Weigand
@ 2017-03-16 18:25 ` Andreas Arnez
2017-03-16 18:43 ` Ulrich Weigand
0 siblings, 1 reply; 7+ messages in thread
From: Andreas Arnez @ 2017-03-16 18:25 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches, Jan Kratochvil
On Wed, Mar 15 2017, Ulrich Weigand wrote:
> Andreas Arnez wrote:
[...]
>> + /* Get type of pointed-to DIE. */
>> + struct type *orig_type = dwarf2_fetch_die_type_sect_off (die, per_cu);
>> +
>> /* 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,
>
> Can orig_type ever be NULL here? It probably would not be a good idea
> to pass NULL as the type argument.
From looking at the code, it looks like it can. But only for very
special cases, it seems. For instance, in case of a missing DW_AT_TYPE
attribute for the pointed-to die we get the type "void" instead.
>
>> - if (byte_offset != 0)
>> + if (subobj_byte_offset != 0)
>> error (_("cannot use offset on synthetic pointer to register"));
>
> As an aside: now that we have the full object type, we may actually be able
> to lift that restriction (do a value_from_register on the full type, and
> then extract the subobject). Might be interesting to look into as a
> follow-on change ...
Right, I'll look into that.
>
>> size_t n = TYPE_LENGTH (value_type (value));
>> + size_t len = TYPE_LENGTH (subobj_type);
>> + size_t max = type != NULL ? TYPE_LENGTH (type) : n;
>
> As mentioned above, I don't think it makes sense to allow a NULL type here.
OK. I'll adjust the patch with the delta-patch below. Is that ready to
apply then?
--
Andreas
-- >8 --
1 file changed, 3 insertions(+), 1 deletion(-)
gdb/dwarf2loc.c | 4 +++-
modified gdb/dwarf2loc.c
@@ -2166,6 +2166,8 @@ indirect_synthetic_pointer (sect_offset die, LONGEST byte_offset,
/* 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,
@@ -2487,7 +2489,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
struct value *value = ctx.fetch (0);
size_t n = TYPE_LENGTH (value_type (value));
size_t len = TYPE_LENGTH (subobj_type);
- size_t max = type != NULL ? TYPE_LENGTH (type) : n;
+ size_t max = TYPE_LENGTH (type);
struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile);
struct cleanup *cleanup;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value
2017-03-16 18:25 ` Andreas Arnez
@ 2017-03-16 18:43 ` Ulrich Weigand
2017-03-16 18:52 ` Andreas Arnez
0 siblings, 1 reply; 7+ messages in thread
From: Ulrich Weigand @ 2017-03-16 18:43 UTC (permalink / raw)
To: Andreas Arnez; +Cc: gdb-patches, Jan Kratochvil
Andreas Arnez wrote:
> On Wed, Mar 15 2017, Ulrich Weigand wrote:
> > As mentioned above, I don't think it makes sense to allow a NULL type here.
>
> OK. I'll adjust the patch with the delta-patch below. Is that ready to
> apply then?
Yes, this is OK.
Thanks,
Ulrich
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value
2017-03-16 18:43 ` Ulrich Weigand
@ 2017-03-16 18:52 ` Andreas Arnez
0 siblings, 0 replies; 7+ messages in thread
From: Andreas Arnez @ 2017-03-16 18:52 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: gdb-patches, Jan Kratochvil
On Thu, Mar 16 2017, Ulrich Weigand wrote:
> Andreas Arnez wrote:
>> On Wed, Mar 15 2017, Ulrich Weigand wrote:
>> > As mentioned above, I don't think it makes sense to allow a NULL type here.
>>
>> OK. I'll adjust the patch with the delta-patch below. Is that ready to
>> apply then?
>
> Yes, this is OK.
Thanks, pushed.
--
Andreas
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-03-16 18:52 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-13 19:00 [PATCH] Big-endian targets: Don't ignore offset into DW_OP_stack_value Andreas Arnez
2017-03-13 14:30 ` Ulrich Weigand
2017-03-15 18:05 ` Andreas Arnez
2017-03-15 19:16 ` Ulrich Weigand
2017-03-16 18:25 ` Andreas Arnez
2017-03-16 18:43 ` Ulrich Weigand
2017-03-16 18:52 ` Andreas Arnez
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox