Another complex DWARF expression operations, that are usefull for
SIMD/SIMT like architectures are: DW_OP_LLVM_overlay and
DW_OP_LLVM_bit_overlay. These operations pop four stack entries,
where the first must be an integral that represents an overlay size,
the second must be an integral that represents a starting point of the
overlay from the base location, the third must be a location
description that represents the overlay location description and the
forth must be a location description that represents the base location
description.
Resulting composite location description contains parts from base
location description, overlayed by the overlay location description,
starting from the overlay offset, ending at a sum of the overlay offset
and overlay size.
A new test in gdb.dwarf2 called dw2-llvm-overlay has been also added to
test the support for both operations.
Add support for DWARF location offset type that is larger than 64-bit
To support new DWARF extension restrictions for location handling a new
data type for representing an offset within a location has been added.
The new loc_offset type defines a separate handling of the byte and
sub_bit parts of the offset while enabling the byte part of the
information to utilize a full 64-bit range of values.
Second more complex DWARF expression operation, that is usefull for
SIMD/SIMT like architectures is DW_OP_LLVM_select_bit_piece. This
operation pops three stack entries, where the first must be an integral
type value that represents a bit mask, the second must be a location
description that represents the one-location description and the third
must be a location description that represents the zero-location
description.
Resulting composite location description contains a given number of
pieces of a given bit size, created with parts from either of the two
location description, based on the bit mask.
gdb/ChangeLog:
* compile/compile-loc2c.c (compute_stack_depth_worker): Add
new DW_OP_LLVM_select_bit_piece operation support.
* dwarf2/expr.c (dwarf_expr_context::create_select_composite):
New method that creates the select bit piece composite. (dwarf_location::slice): New method. (dwarf_composite::slice): New method. (dwarf_expr_context::execute_stack_op): Add new DW_OP_LLVM_select_bit_piece operation support.
* dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add new DW_OP_LLVM_select_bit_piece operation support. (disassemble_dwarf_expression): Add new DW_OP_LLVM_select_bit_piece operation support.
include/ChangeLog:
* dwarf2.def: Add new DW_OP_LLVM_select_bit_piece enumeration.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/dw2-llvm-select-bit-piece.exp: New test.
* lib/dwarf.exp: Add new DW_OP_LLVM_select_bit_piece operation
support.
Previous changes allow a new set of more complex DWARF expression
operations to be added which are very usefull for SIMD/SIMT like
architectures. First of which is the DW_OP_LLVM_extend operation
that pops one stack element (which must be a location description)
and treat it as a number of pieces of a new composite location
description.
This means that a resulting composite location contains a given
number of pieces of a given bit size, where all the pieces are
described by the same location description found on top of the stack.
gdb/ChangeLog:
* compile/compile-loc2c.c (compute_stack_depth_worker): Add
new DW_OP_LLVM_extend operation support.
* dwarf2/expr.c (dwarf_expr_context::create_extend_composite):
New method that creates the extend composite. (dwarf_expr_context::execute_stack_op): Add new DW_OP_LLVM_extend operation support.
* dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add new DW_OP_LLVM_extend operation support. (disassemble_dwarf_expression): Add new DW_OP_LLVM_extend
operation support.
include/ChangeLog:
* dwarf2.def: Add new DW_OP_LLVM_extend enumeration.
gdb/testsuite/ChangeLog:
* gdb.dwarf2/dw2-llvm-extend.exp: New test.
* lib/dwarf.exp: Add new DW_OP_LLVM_extend operation support.
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:
The dwarf_composite also needed to be modified to make a distinction
between completed composite locationd description and not completed
one.
This also mean that some DWARF expression operations can duplicate a
composite location description that is not completed and end up with
more then one different composite location description on the stack.
To be able to do this, classes that derive from a DWARF entry class
need to have a clone method.
gdb/ChangeLog:
* compile/compile-loc2c.c (compute_stack_depth_worker): Add
new DW_OP_LLVM_piece_end operation support.
* dwarf2/expr.c (dwarf_composite::m_completed): New data
member. (dwarf_entry::dwarf_entry): New copy constructor. (dwarf_location::dwarf_location): New copy constructor. (dwarf_value::dwarf_value): New copy constructor. (dwarf_undefined::dwarf_undefined): New copy constructor. (dwarf_memory::dwarf_memory): New copy constructor. (dwarf_register::dwarf_register): New copy constructor. (dwarf_implicit::dwarf_implicit): New method. (dwarf_implicit_pointer::dwarf_implicit_pointer): New copy constructor. (dwarf_composite::dwarf_composite): New copy constructor. (dwarf_entry::clone): New method. (dwarf_location::clone): New method. (dwarf_value::clone): New method. (dwarf_undefined::clone): New method. (dwarf_memory::clone): New method. (dwarf_register::clone): New method. (dwarf_implicit::clone): New method. (dwarf_implicit_pointer::clone): New method. (dwarf_composite::clone): New method. (dwarf_composite::is_completed): New method. (dwarf_composite::set_completed): New method. (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.
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:
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 new DW_OP_LLVM_undefined operation support.
include/ChangeLog:
* dwarf2.def (DW_OP): New DW_OP_LLVM_undefined operations
enumeration.
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:
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:
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 call.
* compile/compile-loc2c.c (compute_stack_depth_worker): Add new
DWARF operations support.
* dwarf2/expr.c (dwarf_register::to_gdb_value): Add bit offset
support. (dwarf_register::to_gdb_value): Add bit offset support.
(dwarf_register::to_gdb_value): Add source bit
offset argument to the value_contents_copy call.
(dwarf_expr_context::execute_stack_op): Add new DWARF
operations support.
* dwarf2/loc.c (dwarf2_get_symbol_read_needs): Add new DWARF
operation support. (disassemble_dwarf_expression): Add support for new DW_OP_LLVM_offset_constu operation.
* findvar.c (read_frame_register_value): Add source bit offset
argument to the value_contents_copy call.
* frame.c (get_frame_register_bytes): Takes into account a
potential unwound register struct value offset. (get_frame_register_bytes): Takes into account a potential
unwound register struct value offset.
* 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 call.
(value_slice): Add source bit offset argument to the
value_contents_copy 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 call.
(value_from_component): Add source bit offset argument to the
value_contents_copy 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.
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.
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, all operations are treated the same and
everything is composable, so there is no need for the previous
restrictions in the expression evaluator.
gdb/ChangeLog:
* dwarf2/expr.c (dwarf_expr_context::execute_stack_op): Remove
the use of dwarf_expr_require_composition.
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.