~ubuntu-support-team/binutils/+git/binutils-gdb:users/zoran/allow-location-description-on-dwarf-stack

Last commit made on 2020-12-08
Get this branch:
git clone -b users/zoran/allow-location-description-on-dwarf-stack https://git.launchpad.net/~ubuntu-support-team/binutils/+git/binutils-gdb

Branch merges

Branch information

Name:
users/zoran/allow-location-description-on-dwarf-stack
Repository:
lp:~ubuntu-support-team/binutils/+git/binutils-gdb

Recent commits

1127a49... by Zoran Zaric <email address hidden>

Add support for nested composite locations

After allowing a location description to be placed on a DWARF stack,
in an effort to achieve a full composability of the DWARF expression,
it is necessary to enable forming of a nested composite location
descriptions.

To be able do this, a new operation DW_OP_LLVM_piece_end needs to be
introduced, along with some additional rules on the way how the
composite location description is formed using the existing DW_OP_piece
and DW_OP_bit_piece operations. These new rules are fully compatible
with the composite forming rules from the DWARF 5 standard.

More details on the new operation and added rules can be found here:

https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html

gdb/ChangeLog:

 * compile/compile-loc2c.c (compute_stack_depth_worker): Add new
 DW_OP_LLVM_piece_end operation support.
 * dwarf2/expr.c (class dwarf_value): Add copy constructor.
 (class dwarf_location): Add copy constructor.
 (class dwarf_undefined): Add copy constructor.
 (class dwarf_memory): Add copy constructor.
 (class dwarf_register): Add copy constructor.
 (class dwarf_implicit): Add copy constructor.
 (class dwarf_implicit_pointer): Add copy constructor.
 (class dwarf_composite): Add copy constructor.
 (read_from_location): Add composite completed check.
 (write_to_location): Add composite completed check.
 (read_value_contents_from_location): New function.
 (dwarf_entry_factory::copy_entry): New method.
 (rw_closure_value): Now calls read_value_contents_from_location
 function.
 (dwarf_expr_context::add_piece): Use new composite forming
 rules.
 (dwarf_expr_context::execute_stack_op): Add new
 DW_OP_LLVM_piece_end operation support.
 * dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add new
 DW_OP_LLVM_piece_end operation support.

include/ChangeLog:

 * dwarf2.def (DW_OP_DUP): Add new DW_OP_LLVM_piece_end
          enumeration.

gdb/testsuite/ChangeLog:

 * gdb.dwarf2/dw2-llvm-piece-end.exp: New test.

Change-Id: Ib0b25e5de3f23df89d7d9e86aad56029c7d173df

dab5aee... by Zoran Zaric <email address hidden>

Add support for DW_OP_LLVM_undefined operation

For the DW_OP_piece and DW_OP_bit_piece operations, in the DWARF 5
standard, it is stated that if the location description (of that piece)
is empty, then the piece is describing an undefined location
description.

The act of allowing any location description to be placed on a DWARF
stack means that now a new operations can be defined which could pop
more then one location description from a DWARF stack.

This means that the old rule is not really applicable any more and a
new operation that explicitly pushes an undefined location description
on the DWARF stack is needed.

This new rule however is fully backward compatibility as described
in the document found on:

https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html

Under the new definitions for the DW_OP_piece and DW_OP_bit_piece
operations.

gdb/ChangeLog:

 * compile/compile-loc2c.c (compute_stack_depth_worker): Add
 support for new DW_OP_LLVM_undefined operations.
 * dwarf2/expr.c (dwarf_expr_context::execute_stack_op): Add
 support for new DW_OP_LLVM_undefined operations.
 * dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add support
 for new DW_OP_LLVM_undefined operations.

include/ChangeLog:

 * dwarf2.def (DW_OP): New DW_OP_LLVM_undefined operations
 enumeration.

gdb/testsuite/ChangeLog:

 * gdb.dwarf2/dw2-llvm-undefined.exp: New test.

Change-Id: I2064c8fa3c7bc6488a226082b807e802d6d943ab

a85f752... by Zoran Zaric <email address hidden>

Add DWARF operations for byte and bit offset

Currently in DWARF, there are only two ways to specify an offset for a
location description.

For a memory location description, the location description can be
first converted to a DWARF value, after which an arithmetic operation
can be applied to it. This however, only works while there are no
address spaces involved, that are not mapped to a general address space
(CORE_ADDR). Another limitation is that there is no way to specify a
bit offset to that location description.

Second way of specifying an offset to a location description is more
universal and involves wrapping that location description in a
composite piece, where piece itself has a bit/byte offset defined. The
problem with this approach is that both DW_OP_piece and DW_OP_bit_piece
define an offset as a DWARF operation operand, which means that an
offset needs to be a constant value encoded into the DWARF expression.

By adding three new operations (DW_OP_LLVM_offset,
DW_OP_LLVM_offset_constu and DW_OP_LLVM_bit_offset) these restrictions
are now lifted.

Detailed descriptions of these new operations can be found here:

https://llvm.org/docs/AMDGPUDwarfExtensionsForHeterogeneousDebugging.html

The same document also explores an idea of extending the
DW_OP_push_object_address operation to allow pushing any location
description on the DWARF stack. This together with the new bit/byte
offset operations, generalizes DWARF to work with bit fields and could
replace the odd passed-in buffer mechanics in a more elegant way.

There seem to be a difference in views on what the big endian machine
register byte ordering should be. On one hand, some would expect for
a register to behave in the same way as memory, but on another, there
seems to be an existing implementation for (IBM big endian based
machines) which seems to be viewing registers differently, depending
if the register location description is part of a composite piece or
not. More on this topic can be found here:

https://sourceware.org/legacy-ml/gdb-patches/2017-04/msg00177.html

Unfortunately, the gdb current implementation favors the second option,
which feels like a target specific implementation.

Because of this, I've decided to not favor a specific implementation
in the added test for new DWARF operations (dw2-llvm-offset.exp), so
the test is restricted to only run on little endian platforms.

gdb/ChangeLog:

 * ada-lang.c (coerce_unspec_val_to_type): Add source bit offset
 argument to the value_contents_copy_raw call.
 * compile/compile-loc2c.c (compute_stack_depth_worker): Add new
 DWARF operations support.
 * dwarf2/expr.c (rw_closure_value): Add bit offset support.
 (dwarf_expr_context::dwarf_entry_to_gdb_value): Add source bit
 offset argument to the value_contents_copy_raw call.
 (dwarf_expr_context::execute_stack_op): Add new DWARF
 operations support.
 * dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add new DWARF
  operations support.
 * findvar.c (read_frame_register_value): Add source bit offset
 argument to the value_contents_copy_raw call.
 * valops.c (read_value_memory): Add bit offset support.
 (value_assign): Add bit offset support.
 (value_repeat): Add bit offset support.
 (value_array): Add source bit offset argument to the
 value_contents_copy_raw call.
 (value_slice): Add source bit offset argument to the
 value_contents_copy_raw call.
 * value.c (value_contents_copy_raw): Add source bit offset
 support.
 (value_contents_copy): Add source bit offset argument to
 value_contents_copy_raw call.
 (value_primitive_field): Add source bit offset argument to the
 value_contents_copy_raw call.
 (value_from_component): Add source bit offset argument to the
 value_contents_copy_raw call.
 (value_fetch_lazy_memory): Add bit offset argument to the
 read_value_memory call.
 (value_fetch_lazy_register): Add source bit offset argument to
 the value_contents_copy call.
 * value.h (value_contents_copy): Add source bit offset
 argument.

include/ChangeLog:

 * dwarf2.def (DW_OP_DUP): New DWARF operations enumeration.

gdb/testsuite/ChangeLog:

 * lib/dwarf.exp: Add support for new DW_OP_LLVM_offset_constu
 DWARF operation.
 * gdb.dwarf2/dw2-llvm-offset.exp: New test.

Change-Id: I2a6928c2a647debe50c59756be2197d60b6bc2df

a649191... by Zoran Zaric <email address hidden>

Add support for any location description in CFI

One of the main benefits of allowing location description to be on the
DWARF stack is that now CFI expression based register rules can be
defined using a location description operations. This allows a register
of one frame to be saved in any location, including any composite
location.

To fully support this feature, the execute_stack_op function in
dwarf2/frame.c needs to return a single struct value object instead of
just an address.

Function put_frame_register_bytes also needs to change to support any
location description.

This support is a one of the key features to truly support optimized
code.

gdb/ChangeLog:

 * dwarf2/frame.c (execute_stack_op): Change to return a struct
 value object.
 (dwarf2_frame_cache): Change to call new execute_stack_op
 definition.
 (dwarf2_frame_prev_register): Change to call new execute_stack_op
 definition.
 * frame.c (put_frame_register_bytes): Add support for writing to
 composite location description.

Change-Id: I0c23ba56310174a2f8e539be72a11ac554efcaca

07089ef... by Zoran Zaric <email address hidden>

Remove DWARF expression composition check

The dwarf_expr_require_composition function reports an error if the
last operation is not a leaf node of the DWARF expression. This was
previously used to prevent location description operations to be used
freely in the DWARF expression.

With the new approach, everything all operations are treated the same
and everything is composable, so there is no need for the previous
restriction in the expression evaluator.

gdb/ChangeLog:

 * dwarf2/expr.c (dwarf_expr_context::execute_stack_op): Remove
 the use of dwarf_expr_require_composition.

Change-Id: Ibcfd02dfec0cf7354cf2494a13ae1a5125c1233a

b96b712... by Zoran Zaric <email address hidden>

Add frame info check to DW_OP_reg operations

After enabling location description to be on a DWARF stack, it is now
needed to check the frame context information validity when creating a
register location description.

gdb/ChangeLog:

 * dwarf2/expr.c (dwarf_expr_context::execute_stack_op): Add
 check_frame_info call for DW_OP_reg operations.

Change-Id: I3e4a4d1eaba10b3b34be3c3bdbd1010a46ba4cd0

0a01457... by Zoran Zaric <email address hidden>

Move read_addr_from_reg function to frame.c

read_addr_from_reg function is now only called from frame.c file, this
means that the function can safely be moved there.

gdb/ChangeLog:

 * dwarf2/expr.c (read_addr_from_reg): Move function to frame.c.
 * dwarf2/expr.h (read_addr_from_reg): Remove function.
 * dwarf2/frame.c (read_addr_from_reg): Add function from
 expr.c.

Change-Id: I15c798d3e001f56cfd78a1e96dd0d6034c844b91

f7bc3a1... by Zoran Zaric <email address hidden>

Rename and update the piece_closure structure

Class that describes a computed_lval closure needs to be update to fit
better with the new dwarf_entry set of classes. This also means that a
pieced_value_funcs interface with that closure, needs to be renamed and
updated accordingly.

Considering that a closure is designed to describe a computed location
description, it makes sense to rename piece_closure to a
computed_closure.

gdb/ChangeLog:

 * dwarf2/expr.c (struct piece_closure): Change to
 computed_closure class.
 (allocate_piece_closure): Remove function.
 (rw_pieced_value): Rename to rw_closure_value and change to use
 computed_closure class.
 (read_pieced_value): Rename to read_closure_value and change to
 use computed_closure class.
 (write_pieced_value): Rename to write_closure_value and change
 to use computed_closure class.
 (check_pieced_synthetic_pointer): Rename to
 check_synthetic_pointer and change to use computed_closure
 class.
 (indirect_pieced_value): Rename to indirect_closure_value and
 change to use computed_closure class.
 (coerce_pieced_ref): Rename to coerce_closure_ref and change
 to use computed_closure class.
 (copy_pieced_value_closure): Rename to copy_value_closure and
 change to use computed_closure class.
 (free_pieced_value_closure): Rename to free_value_closure and
 change to use computed_closure class.
 (dwarf_expr_context::gdb_value_to_dwarf_entry): Change to use
 computed_closure class.
 (dwarf_expr_context::dwarf_entry_to_gdb_value): Change to use
 computed_closure class.

Change-Id: Ice1df6e01c852bb8a94ba74e683d66fe57838036

c12b925... by Zoran Zaric <email address hidden>

Remove dwarf_expr_context from expr.h interface

After the switch to the new evaluator implementation, it is now
possible to completely remove the dwarf_expr_context class from the
expr.h interface and encapsulate it inside the expr.c file.

The new interface consists of a new function called dwarf2_eval_exp
that takes a DWARF expression stream, initial DWARF stack elements (in
a form of a vector of a struct value objects), evaluation context and
expected result type information. Function returns an evaluation result
in a form of a struct value object.

Currently, there is ever only one initial stack element provided to the
evaluator and that element is always a memory address, so having a
vector of struct value object might seems like an overkill.

In reality this new flexibility allows implementation of a new DWARF
attribute extensions that could provide any number of initial stack
elements to describe any location description or value.

gdb/ChangeLog:

 * dwarf2/expr.c (dwarf2_eval_exp): New function.
 (struct dwarf_expr_context): Move from expr.h.
 (dwarf_expr_context::push_address): Remove function.
 * dwarf2/expr.h (struct dwarf_expr_context): Move to expr.c.
 * dwarf2/frame.c (execute_stack_op): Now calls dwarf2_eval_exp.
 * dwarf2/loc.c (dwarf2_evaluate_loc_desc_full): Now calls
 dwarf2_eval_exp.
 (dwarf2_locexpr_baton_eval): Now calls dwarf2_eval_exp.

Change-Id: I5b2cce5424546d48fd00fb95d53681e41478cd09

bedecfc... by Zoran Zaric <email address hidden>

Change DWARF stack to use new dwarf_entry classes

To replace existing DWARF stack element (dwarf_stack_value) with
dwarf_entry class based objects, a support for conversion between
struct value and the new classes is needed. The reason for this is
that dwarf_entry based classes are not designed to be visible outside
the expr.c file. This makes the DWARF expression evaluator more self
contained. This can be beneficial if there is ever a need to have a
DWARF support in gdbserver.

Once the conversion support is added, the current DWARF stack element
can easily be swapped out.

gdb/ChangeLog:

 * dwarf2/expr.c (dwarf_value_equal_op): New function.
 (dwarf_value_less_op): New function.
 (struct piece_closure): Change to use dwarf_entry based
 classes.
 (allocate_piece_closure): Change to use dwarf_entry based
 classes.
 (rw_pieced_value): Change to use dwarf_entry based classes.
 (check_pieced_synthetic_pointer): Change to use dwarf_entry
 based classes.
 (check_synthetic_pointer_location): New function.
 (indirect_pieced_value): Change to use dwarf_entry based
 classes.
 (indirect_from_location): New function.
 (coerce_pieced_ref): Change to use dwarf_entry based classes.
 (free_pieced_value_closure): Change to use dwarf_entry based
 classes.
 (dwarf_expr_context::~dwarf_expr_context): Instantiate
 dwarf_entry_factory object.
 (dwarf_expr_context::push): Change to use dwarf_entry based
 classes.
 (dwarf_expr_context::push_address): Change to use dwarf_entry
 based classes.
 (dwarf_expr_context::fetch): Change to use dwarf_entry based
 classes.
 (dwarf_expr_context::read_mem): Remove method.
 (dwarf_expr_context::fetch_result): Change to use dwarf_entry
 based classes.
 (dwarf_expr_context::dwarf_entry_deref): New method.
 (dwarf_expr_context::gdb_value_to_dwarf_entry): New method.
 (dwarf_expr_context::dwarf_entry_to_gdb_value): New method.
 (dwarf_expr_context::fetch_address): Change to use dwarf_entry
 based classes.
 (dwarf_expr_context::fetch_in_stack_memory): Change to use
 dwarf_entry based classes.
 (dwarf_expr_context::add_piece): Change to use dwarf_entry based
 classes.
 (dwarf_expr_context::execute_stack_op): Change to use dwarf_entry
 based classes.
 * dwarf2/expr.h (class dwarf_entry): New declaration.
 (class dwarf_entry_factory): New declaration.
 (enum dwarf_value_location): Remove enumeration.
 (struct dwarf_expr_piece): Remove structure.
 (struct dwarf_stack_value): Remove structure.
 (struct dwarf_expr_context): Change to use dwarf_entry based
 classes. Add dwarf_entry_factory object.

Change-Id: I828c9b087c8ab3f57d9b208b360bcf5688810586