diff options
author | Lancelot SIX <lancelot.six@amd.com> | 2022-02-25 23:41:47 +0000 |
---|---|---|
committer | Lancelot SIX <lancelot.six@amd.com> | 2022-04-04 23:03:32 +0100 |
commit | cc96ae7f8839bd63a943751d52af94db3b956c1f (patch) | |
tree | 52e84b6b5ac798fdc470e8011bc8bb050804bf46 /gdb/testsuite | |
parent | 6cacd78ba5bb705e127d60478c71955b37914c53 (diff) | |
download | gdb-cc96ae7f8839bd63a943751d52af94db3b956c1f.zip gdb-cc96ae7f8839bd63a943751d52af94db3b956c1f.tar.gz gdb-cc96ae7f8839bd63a943751d52af94db3b956c1f.tar.bz2 |
gdb: Add support for DW_LNS_set_prologue_end in line-table
Add support for DW_LNS_set_prologue_end when building line-tables. This
attribute can be set by the compiler to indicate that an instruction is
an adequate place to set a breakpoint just after the prologue of a
function.
The compiler might set multiple prologue_end, but considering how
current skip_prologue_using_sal works, this commit modifies it to accept
the first instruction with this marker (if any) to be the place where a
breakpoint should be placed to be at the end of the prologue.
The need for this support came from a problematic usecase generated by
hipcc (i.e. clang). The problem is as follows: There's a function
(lets call it foo) which covers PC from 0xa800 to 0xa950. The body of
foo begins with a call to an inlined function, covering from 0xa800 to
0xa94c. The issue is that when placing a breakpoint at 'foo', GDB
inserts the breakpoint at 0xa818. The 0x18 offset is what GDB thinks is
foo's first address past the prologue.
Later, when hitting the breakpoint, GDB reports the stop within the
inlined function because the PC falls in its range while the user
expects to stop in FOO.
Looking at the line-table for this location, we have:
INDEX LINE ADDRESS IS-STMT
[...]
14 293 0x000000000000a66c Y
15 END 0x000000000000a6e0 Y
16 287 0x000000000000a800 Y
17 END 0x000000000000a818 Y
18 287 0x000000000000a824 Y
[...]
For comparison, let's look at llvm-dwarfdump's output for this CU:
Address Line Column File ISA Discriminator Flags
------------------ ------ ------ ------ --- ------------- -------------
[...]
0x000000000000a66c 293 12 2 0 0 is_stmt
0x000000000000a6e0 96 43 82 0 0 is_stmt
0x000000000000a6f8 102 18 82 0 0 is_stmt
0x000000000000a70c 102 24 82 0 0
0x000000000000a710 102 18 82 0 0
0x000000000000a72c 101 16 82 0 0 is_stmt
0x000000000000a73c 2915 50 83 0 0 is_stmt
0x000000000000a74c 110 1 1 0 0 is_stmt
0x000000000000a750 110 1 1 0 0 is_stmt end_sequence
0x000000000000a800 107 0 1 0 0 is_stmt
0x000000000000a800 287 12 2 0 0 is_stmt prologue_end
0x000000000000a818 114 59 81 0 0 is_stmt
0x000000000000a824 287 12 2 0 0 is_stmt
0x000000000000a828 100 58 82 0 0 is_stmt
[...]
The main difference we are interested in here is that llvm-dwarfdump's
output tells us that 0xa800 is an adequate place to place a breakpoint
past a function prologue. Since we know that foo covers from 0xa800 to
0xa94c, 0xa800 is the address at which the breakpoint should be placed
if the user wants to break in foo.
This commit proposes to add support for the prologue_end flag in the
line-program processing.
The processing of this prologue_end flag is made in skip_prologue_sal,
before it calls gdbarch_skip_prologue_noexcept. The intent is that if
the compiler gave information on where the prologue ends, we should use
this information and not try to rely on architecture dependent logic to
guess it.
The testsuite have been executed using this patch on GNU/Linux x86_64.
Testcases have been compiled with both gcc/g++ (verison 9.4.0) and
clang/clang++ (version 10.0.0) since at the time of writing GCC does not
set the prologue_end marker. Tests done with GCC 11.2.0 (not over the
entire testsuite) show that it does not emit this flag either.
No regression have been observed with GCC or Clang. Note that when
using Clang, this patch fixes a failure in
gdb.opt/inline-small-func.exp.
Change-Id: I720449a8a9b2e1fb45b54c6095d3b1e9da9152f8
Diffstat (limited to 'gdb/testsuite')
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-out-of-range-end-of-seq.exp | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-prologue-end.c | 28 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp | 91 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp | 2 | ||||
-rw-r--r-- | gdb/testsuite/lib/dwarf.exp | 16 |
5 files changed, 132 insertions, 9 deletions
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-out-of-range-end-of-seq.exp b/gdb/testsuite/gdb.dwarf2/dw2-out-of-range-end-of-seq.exp index f60f622..23df111 100644 --- a/gdb/testsuite/gdb.dwarf2/dw2-out-of-range-end-of-seq.exp +++ b/gdb/testsuite/gdb.dwarf2/dw2-out-of-range-end-of-seq.exp @@ -86,10 +86,10 @@ if ![runto_main] { set test "END with address 1 eliminated" gdb_test_multiple "maint info line-table $srcfile$" $test { - -re -wrap "END *0x0*1 *Y \r\n.*" { + -re -wrap "END *0x0*1 *Y *\r\n.*" { fail $gdb_test_name } - -re -wrap "END *$hex *Y " { + -re -wrap "END *$hex *Y *" { pass $gdb_test_name } } diff --git a/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.c b/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.c new file mode 100644 index 0000000..d166540 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.c @@ -0,0 +1,28 @@ +/* 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/>. */ + + +int +main (void) +{ /* main prologue */ + asm ("main_label: .global main_label"); + int m = 42; /* main assign m */ + asm ("main_assign_n: .global main_assign_n"); + int n = 54; /* main assign n */ + asm ("main_end_prologue: .global main_end_prologue"); + int o = 96; /* main assign o */ + asm ("main_end: .global main_end"); /* main end */ + return m + n - o; +} diff --git a/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp b/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp new file mode 100644 index 0000000..0de13ae --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-prologue-end.exp @@ -0,0 +1,91 @@ +# 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/>. + +# Check that GDB can honor the prologue_end flag the compiler can place +# in the line-table data. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + return 0 +} + +standard_testfile .c .S + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + global srcdir subdir srcfile srcfile2 + declare_labels lines_label + + get_func_info main + + cu {} { + compile_unit { + {language @DW_LANG_C} + {name dw2-prologue-end.c} + {stmt_list ${lines_label} DW_FORM_sec_offset} + } { + subprogram { + {external 1 flag} + {name main} + {low_pc $main_start addr} + {high_pc "$main_start + $main_len" addr} + } + } + } + + lines {version 5} lines_label { + include_dir "${srcdir}/${subdir}" + file_name "$srcfile" 1 + + program { + {DW_LNE_set_address $main_start} + {line [gdb_get_line_number "main prologue"]} + {DW_LNS_copy} + + {DW_LNE_set_address main_label} + {line [gdb_get_line_number "main assign m"]} + {DW_LNS_copy} + + {DW_LNE_set_address main_assign_n} + {line [gdb_get_line_number "main assign n"]} + {DW_LNS_copy} + + {DW_LNE_set_address main_end_prologue} + {line [gdb_get_line_number "main assign o"]} + {DW_LNS_set_prologue_end} + {DW_LNS_copy} + + {DW_LNE_set_address main_end} + {line [gdb_get_line_number "main end"]} + {DW_LNS_copy} + + {DW_LNE_end_sequence} + } + } +} + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {nodebug}] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +set prologue_end_line [gdb_get_line_number "main assign o"] +gdb_test "frame" ".*main \\\(\\\) at \[^\r\n\]*:$prologue_end_line\r\n.*" diff --git a/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp b/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp index ae44dc4..ec31f1f 100644 --- a/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp +++ b/gdb/testsuite/gdb.dwarf2/dw2-ranges-base.exp @@ -183,7 +183,7 @@ gdb_test_multiple "maint info line-table gdb.dwarf2/dw2-ranges-base.c" \ -re ".*linetable: \\(\\(struct linetable \\*\\) 0x0\\):\r\nNo line table.\r\n" { exp_continue } - -re ".*linetable: \\(\\(struct linetable \\*\\) $hex\\):\r\nINDEX\[ \t\]+LINE\[ \t\]+ADDRESS\[ \t\]+IS-STMT *\r\n" { + -re ".*linetable: \\(\\(struct linetable \\*\\) $hex\\):\r\nINDEX\[ \t\]+LINE\[ \t\]+ADDRESS\[ \t\]+IS-STMT\[ \t\]PROLOGUE-END *\r\n" { exp_continue } } diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 6e8b1cc..ed7ad38 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -2269,14 +2269,13 @@ namespace eval Dwarf { _op .byte $_default_is_stmt "default_is_stmt" _op .byte 1 "line_base" _op .byte 1 "line_range" - _op .byte 10 "opcode_base" + _op .byte 11 "opcode_base" # The standard_opcode_lengths table. The number of arguments - # for each of the standard opcodes. Generating 9 entries here - # matches the use of 10 in the opcode_base above. These 9 - # entries match the 9 standard opcodes for DWARF2, making use - # of only 9 should be fine, even if we are generating DWARF3 - # or DWARF4. + # for each of the standard opcodes. Generating 10 entries here + # matches the use of 11 in the opcode_base above. These 10 + # entries match the 9 standard opcodes for DWARF2 plus + # DW_LNS_prologue_end from DWARF3. _op .byte 0 "standard opcode 1" _op .byte 1 "standard opcode 2" _op .byte 1 "standard opcode 3" @@ -2286,6 +2285,7 @@ namespace eval Dwarf { _op .byte 0 "standard opcode 7" _op .byte 0 "standard opcode 8" _op .byte 1 "standard opcode 9" + _op .byte 0 "standard opcode 10" proc include_dir {dirname} { variable _line_include_dirs @@ -2481,6 +2481,10 @@ namespace eval Dwarf { _op .byte 6 } + proc DW_LNS_set_prologue_end {} { + _op .byte 0x0a + } + proc DW_LNS_advance_pc {offset} { _op .byte 2 _op .uleb128 ${offset} |