summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZoran Zaric <zoran.zaric@amd.com>2022-10-25 14:33:36 +0100
committerZoran Zaric <zoran.zaric@amd.com>2022-10-26 10:43:27 +0100
commitb7383d64e7184470d19132831abb6f5b893d7b6e (patch)
tree5ca1643c9f2c7a01ad879aa0654d0b03655de8b7
parenta50f771b91791dcdd17aabd62ee83d76d6229c75 (diff)
downloadbinutils-gdb-users/zaric/location_on_dwarf_stack.tar.gz
Add support for new DWARF overlay operationsusers/zaric/location_on_dwarf_stack
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.
-rw-r--r--gdb/compile/compile-loc2c.c5
-rw-r--r--gdb/dwarf2/expr.c78
-rw-r--r--gdb/dwarf2/loc.c2
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.c33
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.exp213
-rw-r--r--include/dwarf2.def2
6 files changed, 333 insertions, 0 deletions
diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c
index 83863276b4c..c3de7e7980d 100644
--- a/gdb/compile/compile-loc2c.c
+++ b/gdb/compile/compile-loc2c.c
@@ -370,6 +370,11 @@ compute_stack_depth_worker (int start, int *need_tempvar,
stack_depth -= 2;
break;
+ case DW_OP_LLVM_overlay:
+ case DW_OP_LLVM_bit_overlay:
+ stack_depth -= 3;
+ break;
+
case DW_OP_LLVM_extend:
case DW_OP_LLVM_piece_end:
case DW_OP_LLVM_offset_constu:
diff --git a/gdb/dwarf2/expr.c b/gdb/dwarf2/expr.c
index 66bb8dd89b5..c9c8f3ad0a2 100644
--- a/gdb/dwarf2/expr.c
+++ b/gdb/dwarf2/expr.c
@@ -2837,6 +2837,21 @@ private:
void create_select_composite (const loc_offset &piece_size,
ULONGEST pieces_count);
+ /* It pops two stack entries. First must be a location description
+ that represents the overlay location description. The Second
+ must be a location description that represents the base location
+ description. The OVERLAY_SIZE represents the size of the overlay
+ piece of the composite and the OVERLAY_OFFSET represent a starting
+ point of the overlay from the base location.
+
+ A complete composite location description created with 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, is pushed
+ on top of the DWARF stack. */
+ void create_overlay_composite (loc_offset overlay_size,
+ loc_offset overlay_offset);
+
/* The engine for the expression evaluator. Using the context in this
object, evaluate the expression between OP_PTR and OP_END. */
void execute_stack_op (const gdb_byte *op_ptr, const gdb_byte *op_end);
@@ -3279,6 +3294,38 @@ dwarf_expr_context::create_select_composite (const loc_offset &piece_size,
}
void
+dwarf_expr_context::create_overlay_composite (loc_offset overlay_size,
+ loc_offset overlay_offset)
+{
+ gdbarch *arch = this->m_per_objfile->objfile->arch ();
+
+ if (stack_empty_p ())
+ ill_formed_expression ();
+
+ dwarf_location_up overlay = to_location (pop (), arch);
+
+ if (stack_empty_p ())
+ ill_formed_expression ();
+
+ dwarf_location_up base = to_location (pop (), arch);
+
+ std::unique_ptr<dwarf_composite> composite
+ = make_unique<dwarf_composite> (arch, this->m_per_cu);
+
+ composite->add_piece (std::move (base->slice (0, overlay_offset)),
+ overlay_offset);
+ composite->add_piece (std::move (overlay), overlay_size);
+
+ loc_offset end_offset = overlay_offset + overlay_size;
+ loc_offset end_size = base->size () - end_offset;
+
+ composite->add_piece
+ (std::move (base->slice (end_offset, end_size)), end_size);
+ composite->set_completed (true);
+ push (std::move (composite));
+}
+
+void
dwarf_expr_context::eval (const gdb_byte *addr, size_t len)
{
int old_recursion_depth = this->m_recursion_depth;
@@ -4540,6 +4587,37 @@ dwarf_expr_context::execute_stack_op (const gdb_byte *op_ptr,
break;
}
+ case DW_OP_LLVM_overlay:
+ case DW_OP_LLVM_bit_overlay:
+ {
+ if (stack_empty_p ())
+ ill_formed_expression ();
+
+ dwarf_value_up overlay_size_val
+ = to_value (pop (), address_type);
+ dwarf_require_integral (overlay_size_val->type ());
+ LONGEST overlay_size = overlay_size_val->to_long ();
+
+ if (stack_empty_p () || overlay_size < 0)
+ ill_formed_expression ();
+
+ dwarf_value_up overlay_offset_val
+ = to_value (pop (), address_type);
+ dwarf_require_integral (overlay_offset_val->type ());
+ LONGEST overlay_offset = overlay_offset_val->to_long ();
+
+ if (overlay_offset < 0)
+ ill_formed_expression ();
+
+ if (op == DW_OP_LLVM_overlay)
+ create_overlay_composite ({(ULONGEST) overlay_size, 0},
+ {(ULONGEST) overlay_offset, 0});
+ else
+ create_overlay_composite ((ULONGEST) overlay_size,
+ (ULONGEST) overlay_offset);
+ break;
+ }
+
default:
error (_("Unhandled dwarf expression opcode 0x%x"), op);
}
diff --git a/gdb/dwarf2/loc.c b/gdb/dwarf2/loc.c
index 071baad76d1..c7aa8ded118 100644
--- a/gdb/dwarf2/loc.c
+++ b/gdb/dwarf2/loc.c
@@ -1928,6 +1928,8 @@ dwarf2_get_symbol_read_needs (gdb::array_view<const gdb_byte> expr,
case DW_OP_LLVM_bit_offset:
case DW_OP_LLVM_undefined:
case DW_OP_LLVM_piece_end:
+ case DW_OP_LLVM_overlay:
+ case DW_OP_LLVM_bit_overlay:
break;
case DW_OP_form_tls_address:
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.c b/gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.c
new file mode 100644
index 00000000000..be496bd070c
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.c
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2022 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+unsigned buff[] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+void foo (unsigned dst[], unsigned src[], int len)
+{
+ asm volatile ("foo_label: .globl foo_label");
+ for (int i = 0; i < len; ++i)
+ dst[i] += src[i];
+}
+
+int
+main (void)
+{
+ asm volatile ("main_label: .globl main_label");
+ foo (buff, buff, 1);
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.exp b/gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.exp
new file mode 100644
index 00000000000..c8407453abb
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.exp
@@ -0,0 +1,213 @@
+# Copyright (C) 2022 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Test the new DW_OP_LLVM_overlay operation.
+#
+# The test uses a composite location description, where variable buff
+# address is used as a base location and a reg1 is used as an overlay
+# location.
+
+load_lib dwarf.exp
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+if {![dwarf2_support]} {
+ return 0
+}
+
+# Choose suitable integer registers for the test.
+
+set dwarf_regnum {0 1}
+
+if { [is_aarch64_target] } {
+ set regname {x0 x1}
+} elseif { [is_aarch32_target]
+ || [istarget "s390*-*-*" ]
+ || [istarget "powerpc*-*-*"]
+ || [istarget "rs6000*-*-aix*"] } {
+ set regname {r0 r1}
+} elseif { [is_x86_like_target] } {
+ set regname {eax ecx}
+} elseif { [is_amd64_regs_target] } {
+ set regname {rax rdx}
+} else {
+ verbose "Skipping $gdb_test_file_name."
+ return
+}
+
+standard_testfile .c -dw.S
+
+# Make some DWARF for the test.
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global dwarf_regnum regname srcdir subdir srcfile
+ set buff_src [gdb_target_symbol buff]
+
+ set foo_result [function_range foo ${srcdir}/${subdir}/${srcfile}]
+ set foo_start [lindex $foo_result 0]
+ set foo_length [lindex $foo_result 1]
+
+ cu {} {
+ DW_TAG_compile_unit {
+ {DW_AT_name $srcfile}
+ {DW_AT_comp_dir /tmp}
+ } {
+ declare_labels int_type_label uint_type_label array_type_label
+
+ uint_type_label: DW_TAG_base_type {
+ {DW_AT_name "uint32_t"}
+ {DW_AT_encoding @DW_ATE_unsigned}
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ }
+
+ int_type_label: DW_TAG_base_type {
+ {DW_AT_name "int"}
+ {DW_AT_encoding @DW_ATE_signed}
+ {DW_AT_byte_size 4 DW_FORM_sdata}
+ }
+
+ array_type_label: DW_TAG_array_type {
+ {DW_AT_type :$uint_type_label}
+ } {
+ DW_TAG_subrange_type {
+ {DW_AT_type :$int_type_label}
+ {DW_AT_upper_bound 7 DW_FORM_udata}
+ }
+ }
+
+ DW_TAG_subprogram {
+ {DW_AT_name foo}
+ {DW_AT_low_pc $foo_start addr}
+ {DW_AT_high_pc $foo_length data8}
+ } {
+
+ DW_TAG_variable {
+ {DW_AT_name dst_v1}
+ {DW_AT_type :$array_type_label}
+ {DW_AT_location {
+ # 1. Memory location description of dst elements located in memory:
+ DW_OP_addr $buff_src
+
+ # 2. Register location description of element dst\[i\] is located in a register:
+ DW_OP_regx [lindex $dwarf_regnum 1]
+
+ # 3. Offset of the register within the memory of dst:
+ DW_OP_bregx [lindex $dwarf_regnum 0] 0
+ DW_OP_lit4
+ DW_OP_mul
+
+ # 4. The size of the register element:
+ DW_OP_lit4
+
+ # 5. Make a composite location description for dst that is the memory #1 with
+ # the register #2 positioned as an overlay at offset #3 of size #4:
+ DW_OP_LLVM_overlay
+ } SPECIAL_expr}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name dst_v2}
+ {DW_AT_type :$array_type_label}
+ {DW_AT_location {
+ # 1. Memory location description of dst elements located in memory:
+ DW_OP_addr $buff_src
+
+ # 2. Register location description of element dst\[i\] is located in a register:
+ DW_OP_regx [lindex $dwarf_regnum 1]
+
+ # 3. Offset of the register within the memory of dst:
+ DW_OP_bregx [lindex $dwarf_regnum 0] 0
+ DW_OP_lit4
+ DW_OP_mul
+
+ # 4. The size of the register element:
+ DW_OP_lit4
+
+ # 5. Make a composite location description for dst that is the memory #1 with
+ # the register #2 positioned as an overlay at offset #3 of size #4:
+ DW_OP_LLVM_bit_overlay
+ } SPECIAL_expr}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name src}
+ {DW_AT_type :$array_type_label}
+ {DW_AT_location {
+ DW_OP_addr $buff_src
+ } SPECIAL_expr}
+ }
+
+ DW_TAG_variable {
+ {DW_AT_name i}
+ {DW_AT_type :$int_type_label}
+ {DW_AT_location {
+ DW_OP_regx [lindex $dwarf_regnum 0]
+ } SPECIAL_expr}
+ }
+ }
+ }
+ }
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} \
+ [list $srcfile $asm_file] {nodebug}] } {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+gdb_test "break foo" "Breakpoint.*at.*" "break at function foo"
+gdb_test "continue" "Continuing\\..*Breakpoint \[0-9\]+,.*foo \\(\\).*" \
+ "continue to foo"
+
+gdb_test_no_output "set var \$[lindex $regname 0] = 0x0" "init reg 0"
+gdb_test_no_output "set var \$[lindex $regname 1] = 0xdeadbeef" "init reg 1"
+
+# gdb_interact
+
+# Determine byte order.
+set endian [get_endianness]
+
+switch $endian {
+ little {set val_v1 "0xdeadbeef, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7"}
+ big {set val_v1 "0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0xdeadbeef"}
+}
+
+gdb_test "print/x dst_v1" " = \\{${val_v1}\\}" "dst_v1 print i = 0"
+
+switch $endian {
+ little {set val_v2 "0xf, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7"}
+ big {set val_v2 "0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0xf"}
+}
+
+gdb_test "print/x dst_v2" " = \\{${val_v2}\\}" "dst_v2 print i = 0"
+
+gdb_test_no_output "set var i = 0x2" "init reg 0 to 2"
+
+switch $endian {
+ little {set val_v1 "0x0, 0x1, 0xdeadbeef, 0x3, 0x4, 0x5, 0x6, 0x7"}
+ big {set val_v1 "0x7, 0x6, 0x5, 0x4, 0x3, 0xdeadbeef, 0x1, 0x0"}
+}
+
+gdb_test "print/x dst_v1" " = \\{${val_v1}\\}" "dst_v1 print i = 2"
+
+switch $endian {
+ little {set val_v2 "0xf00, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7"}
+ big {set val_v2 "0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0xf00"}
+}
+
+gdb_test "print/x dst_v2" " = \\{${val_v2}\\}" "dst_v2 print i = 2"
diff --git a/include/dwarf2.def b/include/dwarf2.def
index abc1125df2c..df91a0e0fe9 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -712,6 +712,8 @@ DW_OP (DW_OP_LLVM_undefined, 0xe7)
DW_OP_DUP (DW_OP_LLVM_piece_end, 0xea)
DW_OP (DW_OP_LLVM_extend, 0xeb)
DW_OP (DW_OP_LLVM_select_bit_piece, 0xec)
+DW_OP (DW_OP_LLVM_bit_overlay, 0xed)
+DW_OP (DW_OP_LLVM_overlay, 0xee)
DW_END_OP
DW_FIRST_ATE (DW_ATE_void, 0x0)