diff options
-rw-r--r-- | gdb/compile/compile-loc2c.c | 5 | ||||
-rw-r--r-- | gdb/dwarf2/expr.c | 78 | ||||
-rw-r--r-- | gdb/dwarf2/loc.c | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.c | 33 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-llvm-overlay.exp | 213 | ||||
-rw-r--r-- | include/dwarf2.def | 2 |
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) |