[PATCH 2/2] gdb: Preserve is-stmt lines when switch between files
Bernd Edlinger
bernd.edlinger@hotmail.de
Tue Apr 14 11:41:00 GMT 2020
On 4/14/20 1:37 PM, Bernd Edlinger wrote:
>
>
> On 4/14/20 1:28 PM, Andrew Burgess wrote:
>> Bernd,
>>
>> As requested, rebased version of this patch for your feedback. Sorry
>> for the delay, I took a short break over Easter.
>>
>> Apologies for the previous build failure the fix you found was the
>> only issue, and was caused by a last second choice to rename
>> 'm_stmt_at_addr' to 'm_stmt_at_address', combined with me making a
>> dumb mistake generating the patch from a slightly broken tree. Please
>> be assured the patch was fully tested before I did the rename.
>>
>> The trailing blank lines I have no excuse for.
>>
>> Changes since previous version:
>>
>> - Rebase
>> - Fix m_stmt_at_addr typo
>> - Delete some trailing blank lines.
>>
>> I look forward to hearing your thoughts.
>>
>
> Did you look at fixing the subrouting ranges.
Sorry for typo, I blame my keyborad for it :)
I meant: subroutine ranges.
> My patch depends entirely on correct range info.
>
> It is probably not very difficult for you to fix.
>
>
> Thanks
> Bernd.
>
>> Thanks,
>> Andrew
>>
>> ---
>>
>> commit cf4bab4672356e190b166e063d2539ddad5eb542
>> Author: Andrew Burgess <andrew.burgess@embecosm.com>
>> Date: Fri Apr 3 20:32:38 2020 +0100
>>
>> gdb: Preserve is-stmt lines when switch between files
>>
>> After the is-stmt support commit:
>>
>> commit 8c95582da858ac981f689a6f599acacb8c5c490f
>> Date: Mon Dec 30 21:04:51 2019 +0000
>>
>> gdb: Add support for tracking the DWARF line table is-stmt field
>>
>> A regression was observed where a breakpoint could no longer be placed
>> in some cases.
>>
>> Consider a line table like this:
>>
>> File 1: test.c
>> File 2: test.h
>>
>> | Addr | File | Line | Stmt |
>> |------|------|------|------|
>> | 1 | 1 | 16 | Y |
>> | 2 | 1 | 17 | Y |
>> | 3 | 2 | 21 | Y |
>> | 4 | 2 | 22 | Y |
>> | 4 | 1 | 18 | N |
>> | 5 | 2 | 23 | N |
>> | 6 | 1 | 24 | Y |
>> | 7 | 1 | END | Y |
>> |------|------|------|------|
>>
>> Before the is-stmt patch GDB would ignore any non-stmt lines, so GDB
>> built two line table structures:
>>
>> File 1 File 2
>> ------ ------
>>
>> | Addr | Line | | Addr | Line |
>> |------|------| |------|------|
>> | 1 | 16 | | 3 | 21 |
>> | 2 | 17 | | 4 | 22 |
>> | 3 | END | | 6 | END |
>> | 6 | 24 | |------|------|
>> | 7 | END |
>> |------|------|
>>
>> After the is-stmt patch GDB now records non-stmt lines, so the
>> generated line table structures look like this:
>>
>> File 1 File 2
>> ------ ------
>>
>> | Addr | Line | Stmt | | Addr | Line | Stmt |
>> |------|------|------| |------|------|------|
>> | 1 | 16 | Y | | 3 | 21 | Y |
>> | 2 | 17 | Y | | 4 | 22 | Y |
>> | 3 | END | Y | | 4 | END | Y |
>> | 4 | 18 | N | | 5 | 23 | N |
>> | 5 | END | Y | | 6 | END | Y |
>> | 6 | 24 | Y | |------|------|------|
>> | 7 | END | Y |
>> |------|------|------|
>>
>> The problem is that in 'File 2', end END marker at address 4 causes
>> the previous line table entry to be discarded, so we actually end up
>> with this:
>>
>> File 2
>> ------
>>
>> | Addr | Line | Stmt |
>> |------|------|------|
>> | 3 | 21 | Y |
>> | 4 | END | Y |
>> | 5 | 23 | N |
>> | 6 | END | Y |
>> |------|------|------|
>>
>> When a user tries to place a breakpoint in file 2 at line 22, this is
>> no longer possible.
>>
>> The solution I propose here is that we ignore line table entries that
>> would trigger a change of file if:
>>
>> 1. The new line being added is at the same address as the previous
>> line, and
>>
>> 2. We have previously seen an is-stmt line at the current address.
>>
>> The result of this is that GDB switches file, and knows that some line
>> entry (or entries) are going to be discarded, prefer to keep is-stmt
>> lines and discard non-stmt lines.
>>
>> After this commit the lines tables are now:
>>
>> File 1 File 2
>> ------ ------
>>
>> | Addr | Line | Stmt | | Addr | Line | Stmt |
>> |------|------|------| |------|------|------|
>> | 1 | 16 | Y | | 3 | 21 | Y |
>> | 2 | 17 | Y | | 4 | 22 | Y |
>> | 3 | END | Y | | 5 | 23 | N |
>> | 5 | END | Y | | 6 | END | Y |
>> | 6 | 24 | Y | |------|------|------|
>> | 7 | END | Y |
>> |------|------|------|
>>
>> We've lost the non-stmt entry for file 1, line 18, but retained the
>> is-stmt entry for file 2, line 22. The user can now place a
>> breakpoint at that location.
>>
>> One problem that came from this commit was the test
>> gdb.cp/step-and-next-inline.exp, which broke in several places. After
>> looking at this test again I think that in some cases this test was
>> only ever passing by pure luck. The debug GCC is producing for this
>> test is pretty broken. I raised this GCC bug:
>>
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94474
>>
>> for this and disabled one entire half of the test. There are still
>> some cases in here that do pass, and if/when GCC is fixed it would be
>> great to enable this test again.
>>
>> gdb/ChangeLog:
>>
>> * dwarf2/read.c (class lnp_state_machine) <m_last_address>: New
>> member variable.
>> <m_stmt_at_address>: New member variable.
>> (lnp_state_machine::record_line): Don't record some lines, update
>> tracking of is_stmt at the same address.
>> (lnp_state_machine::lnp_state_machine): Initialise new member
>> variables.
>>
>> gdb/testsuite/ChangeLog:
>>
>> * gdb.cp/step-and-next-inline.exp (do_test): Skip all tests in the
>> use_header case.
>> * gdb.dwarf2/dw2-inline-header-1.exp: New file.
>> * gdb.dwarf2/dw2-inline-header-2.exp: New file.
>> * gdb.dwarf2/dw2-inline-header-3.exp: New file.
>> * gdb.dwarf2/dw2-inline-header-lbls.c: New file.
>> * gdb.dwarf2/dw2-inline-header.c: New file.
>> * gdb.dwarf2/dw2-inline-header.h: New file.
>>
>> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
>> index da702205c60..36e8b24a29a 100644
>> --- a/gdb/dwarf2/read.c
>> +++ b/gdb/dwarf2/read.c
>> @@ -19508,6 +19508,15 @@ class lnp_state_machine
>> /* The last file a line number was recorded for. */
>> struct subfile *m_last_subfile = NULL;
>>
>> + /* The address of the last line entry. */
>> + CORE_ADDR m_last_address;
>> +
>> + /* Set to true when a previous line at the same address (using
>> + m_last_address) had m_is_stmt true. This is reset to false when a
>> + line entry at a new address (m_address different to m_last_address) is
>> + processed. */
>> + bool m_stmt_at_address = false;
>> +
>> /* When true, record the lines we decode. */
>> bool m_currently_recording_lines = false;
>>
>> @@ -19701,14 +19710,34 @@ lnp_state_machine::record_line (bool end_sequence)
>> fe->included_p = 1;
>> if (m_record_lines_p)
>> {
>> - if (m_last_subfile != m_cu->get_builder ()->get_current_subfile ()
>> - || end_sequence)
>> + /* When we switch files we insert an end maker in the first file,
>> + switch to the second file and add a new line entry. The
>> + problem is that the end marker inserted in the first file will
>> + discard any previous line entries at the same address. If the
>> + line entries in the first file are marked as is-stmt, while
>> + the new line in the second file is non-stmt, then this means
>> + the end marker will discard is-stmt lines so we can have a
>> + non-stmt line. This means that there are less addresses at
>> + which the user can insert a breakpoint.
>> +
>> + To improve this we track the last address in m_last_address,
>> + and whether we have seen an is-stmt at this address. Then
>> + when switching files, if we have seen a stmt at the current
>> + address, and we are switching to create a non-stmt line, then
>> + discard the new line. */
>> + bool file_changed
>> + = m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
>> + bool ignore_this_line
>> + = (file_changed && !end_sequence && m_last_address == m_address
>> + && !m_is_stmt && m_stmt_at_address);
>> +
>> + if ((file_changed && !ignore_this_line) || end_sequence)
>> {
>> dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
>> m_currently_recording_lines ? m_cu : nullptr);
>> }
>>
>> - if (!end_sequence)
>> + if (!end_sequence && !ignore_this_line)
>> {
>> bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
>>
>> @@ -19727,6 +19756,15 @@ lnp_state_machine::record_line (bool end_sequence)
>> }
>> }
>> }
>> +
>> + /* Track whether we have seen any m_is_stmt true at m_address in case we
>> + have multiple line table entries all at m_address. */
>> + if (m_last_address != m_address)
>> + {
>> + m_stmt_at_address = false;
>> + m_last_address = m_address;
>> + }
>> + m_stmt_at_address |= m_is_stmt;
>> }
>>
>> lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
>> @@ -19746,6 +19784,9 @@ lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
>> m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0);
>> m_is_stmt = lh->default_is_stmt;
>> m_discriminator = 0;
>> +
>> + m_last_address = m_address;
>> + m_stmt_at_address = false;
>> }
>>
>> void
>> diff --git a/gdb/testsuite/gdb.cp/step-and-next-inline.exp b/gdb/testsuite/gdb.cp/step-and-next-inline.exp
>> index 3733fa75570..a95e21194f9 100644
>> --- a/gdb/testsuite/gdb.cp/step-and-next-inline.exp
>> +++ b/gdb/testsuite/gdb.cp/step-and-next-inline.exp
>> @@ -24,6 +24,13 @@ if { ![supports_statement_frontiers] } {
>> proc do_test { use_header } {
>> global srcfile testfile
>>
>> + if { $use_header } {
>> + # This test will not pass due to poor debug information
>> + # generated by GCC (at least upto 10.x). See
>> + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94474
>> + return
>> + }
>> +
>> set options {c++ debug nowarnings optimize=-O2\ -gstatement-frontiers}
>> if { $use_header } {
>> lappend options additional_flags=-DUSE_NEXT_INLINE_H
>> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-header-1.exp b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-1.exp
>> new file mode 100644
>> index 00000000000..6a1e990002c
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-1.exp
>> @@ -0,0 +1,156 @@
>> +# Copyright 2020 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/>.
>> +
>> +# Setup a line table where:
>> +#
>> +# | Addr | File | Line | Stmt |
>> +# |------|------|------|------|
>> +# | 1 | 1 | 16 | Y |
>> +# | 2 | 1 | 17 | Y |
>> +# | 3 | 2 | 21 | Y |
>> +# | 4 | 2 | 22 | Y |
>> +# | 4 | 1 | 18 | N |
>> +# | 5 | 2 | 23 | N |
>> +# | 6 | 1 | 24 | Y |
>> +# | 7 | 1 | END | Y |
>> +# |------|------|------|------|
>> +#
>> +# Places a brekpoint at file 2, line 22. Previously GDB would discrad
>> +# the line table entry for this line due to switching files for the
>> +# file 1, line 18 non-statement line. After patching however, GDB now
>> +# discards the file 1, line 18 entry instead, and the breakpoint at
>> +# line 22 should succeed.
>> +
>> +load_lib dwarf.exp
>> +
>> +# This test can only be run on targets which support DWARF-2 and use gas.
>> +if {![dwarf2_support]} {
>> + return 0
>> +}
>> +
>> +# The .c files use __attribute__.
>> +if [get_compiler_info] {
>> + return -1
>> +}
>> +if !$gcc_compiled {
>> + return 0
>> +}
>> +
>> +standard_testfile dw2-inline-header-lbls.c dw2-inline-header.S \
>> + dw2-inline-header.c dw2-inline-header.h
>> +
>> +set asm_file [standard_output_file $srcfile2]
>> +Dwarf::assemble $asm_file {
>> + global srcdir subdir srcfile srcfile3 srcfile4
>> + declare_labels lines_label callee_subprog_label
>> +
>> + get_func_info main
>> +
>> + cu {} {
>> + compile_unit {
>> + {producer "gcc" }
>> + {language @DW_LANG_C}
>> + {name ${srcfile3}}
>> + {low_pc 0 addr}
>> + {stmt_list ${lines_label} DW_FORM_sec_offset}
>> + } {
>> + callee_subprog_label: subprogram {
>> + {external 1 flag}
>> + {name callee}
>> + {inline 3 data1}
>> + }
>> + subprogram {
>> + {external 1 flag}
>> + {name main}
>> + {low_pc $main_start addr}
>> + {high_pc "$main_start + $main_len" addr}
>> + } {
>> + inlined_subroutine {
>> + {abstract_origin %$callee_subprog_label}
>> + {low_pc line_label_1 addr}
>> + {high_pc line_label_7 addr}
>> + {call_file 1 data1}
>> + {call_line 18 data1}
>> + }
>> + }
>> + }
>> + }
>> +
>> + lines {version 2 default_is_stmt 1} lines_label {
>> + include_dir "${srcdir}/${subdir}"
>> + file_name "$srcfile3" 1
>> + file_name "$srcfile4" 1
>> +
>> + program {
>> + {DW_LNE_set_address line_label_1}
>> + {DW_LNS_advance_line 15}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_2}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_set_file 2}
>> + {DW_LNE_set_address line_label_3}
>> + {DW_LNS_advance_line 4}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_4}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_advance_line -4}
>> + {DW_LNS_set_file 1}
>> + {DW_LNS_negate_stmt}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_set_file 2}
>> + {DW_LNE_set_address line_label_5}
>> + {DW_LNS_advance_line 5}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_negate_stmt}
>> + {DW_LNS_set_file 1}
>> + {DW_LNE_set_address line_label_6}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_7}
>> + {DW_LNE_end_sequence}
>> + }
>> + }
>> +}
>> +
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> + [list $srcfile $asm_file] {nodebug optimize=-O1}] } {
>> + return -1
>> +}
>> +
>> +if ![runto_main] {
>> + return -1
>> +}
>> +
>> +# Delete all breakpoints so that the output of "info breakpoints"
>> +# below will only contain a single breakpoint.
>> +delete_breakpoints
>> +
>> +# Place a breakpoint within the function in the header file.
>> +gdb_breakpoint "${srcfile4}:22"
>> +
>> +# Check that the breakpoint was placed where we expected. It should
>> +# appear at the requested line. When the bug in GDB was present the
>> +# breakpoint would be placed on one of the following lines instead.
>> +gdb_test "info breakpoints" \
>> + ".* in callee at \[^\r\n\]+${srcfile4}:22\\y.*"
>> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-header-2.exp b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-2.exp
>> new file mode 100644
>> index 00000000000..46499919a8b
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-2.exp
>> @@ -0,0 +1,179 @@
>> +# Copyright 2020 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/>.
>> +
>> +# Setup a line table where:
>> +#
>> +# | Addr | File | Line | Stmt |
>> +# |------|------|------|------|
>> +# | 1 | 1 | 16 | Y |
>> +# | 2 | 1 | 17 | Y |
>> +# | 3 | 2 | 21 | Y |
>> +# | 4 | 2 | 22 | Y |
>> +# | 4 | 1 | 18 | N |
>> +# | 5 | 1 | 19 | Y |
>> +# | 6 | 1 | 20 | Y |
>> +# | 7 | 1 | END | Y |
>> +# |------|------|------|------|
>> +#
>> +#
>> +# Place the first brekpoint at file 2, line 22 and a second breakpoint
>> +# at file 1, line 19. A third breakpoint is placed at file 1, line
>> +# 18, but as this line table entry will have been discarded[1] the
>> +# third breakpoint will actually be placed at the same location as the
>> +# second breakpoint.
>> +#
>> +# [1] The entry for file 1, line 18 is discarded because it is at the
>> +# same address as the previous entry, but the previous entry is-stmt,
>> +# while line 18 is a non-stmt.
>> +
>> +load_lib dwarf.exp
>> +
>> +# This test can only be run on targets which support DWARF-2 and use gas.
>> +if {![dwarf2_support]} {
>> + return 0
>> +}
>> +
>> +# The .c files use __attribute__.
>> +if [get_compiler_info] {
>> + return -1
>> +}
>> +if !$gcc_compiled {
>> + return 0
>> +}
>> +
>> +standard_testfile dw2-inline-header-lbls.c dw2-inline-header.S \
>> + dw2-inline-header.c dw2-inline-header.h
>> +
>> +set asm_file [standard_output_file $srcfile2]
>> +Dwarf::assemble $asm_file {
>> + global srcdir subdir srcfile srcfile3 srcfile4
>> + declare_labels lines_label callee_subprog_label
>> +
>> + get_func_info main
>> +
>> + cu {} {
>> + compile_unit {
>> + {producer "gcc" }
>> + {language @DW_LANG_C}
>> + {name ${srcfile3}}
>> + {low_pc 0 addr}
>> + {stmt_list ${lines_label} DW_FORM_sec_offset}
>> + } {
>> + callee_subprog_label: subprogram {
>> + {external 1 flag}
>> + {name callee}
>> + {inline 3 data1}
>> + }
>> + subprogram {
>> + {external 1 flag}
>> + {name main}
>> + {low_pc $main_start addr}
>> + {high_pc "$main_start + $main_len" addr}
>> + } {
>> + inlined_subroutine {
>> + {abstract_origin %$callee_subprog_label}
>> + {low_pc line_label_1 addr}
>> + {high_pc line_label_7 addr}
>> + {call_file 1 data1}
>> + {call_line 18 data1}
>> + }
>> + }
>> + }
>> + }
>> +
>> + lines {version 2 default_is_stmt 1} lines_label {
>> + include_dir "${srcdir}/${subdir}"
>> + file_name "$srcfile3" 1
>> + file_name "$srcfile4" 1
>> +
>> + program {
>> + {DW_LNE_set_address line_label_1}
>> + {DW_LNS_advance_line 15}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_2}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_set_file 2}
>> + {DW_LNE_set_address line_label_3}
>> + {DW_LNS_advance_line 4}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_4}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_advance_line -4}
>> + {DW_LNS_set_file 1}
>> + {DW_LNS_negate_stmt}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_5}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_negate_stmt}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_6}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_7}
>> + {DW_LNE_end_sequence}
>> + }
>> + }
>> +}
>> +
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> + [list $srcfile $asm_file] {nodebug optimize=-O1}] } {
>> + return -1
>> +}
>> +
>> +if ![runto_main] {
>> + return -1
>> +}
>> +
>> +# Delete all breakpoints so that the output of "info breakpoints"
>> +# below will only contain a single breakpoint.
>> +delete_breakpoints
>> +
>> +# Place a breakpoint within the function in the header file.
>> +gdb_breakpoint "${srcfile4}:22"
>> +
>> +# Check that the breakpoint was placed where we expected. It should
>> +# appear at the requested line. When the bug in GDB was present the
>> +# breakpoint would be placed on one of the following lines instead.
>> +gdb_test "info breakpoints" \
>> + ".* in callee at \[^\r\n\]+${srcfile4}:22\\y.*" \
>> + "check for breakpoint at ${srcfile4}"
>> +
>> +# Delete all breakpoints so that the output of "info breakpoints"
>> +# below will only contain a single breakpoint.
>> +delete_breakpoints
>> +
>> +# Place a breakpoint within the function in the header file.
>> +gdb_breakpoint "${srcfile3}:19"
>> +
>> +# Check that the breakpoint was placed where we expected. It should
>> +# appear at the requested line. When the bug in GDB was present the
>> +# breakpoint would be placed on one of the following lines instead.
>> +gdb_test "info breakpoints" \
>> + ".* in callee at \[^\r\n\]+${srcfile3}:19\\y.*" \
>> + "check for breakpoint at ${srcfile3}"
>> +
>> +# Line table entry for line 18 will have been discarded, so this
>> +# brekpoint will be at the same location as line 19.
>> +gdb_test "break ${srcfile3}:18" \
>> + "Note: breakpoint $decimal also set at pc $hex.*"
>> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp
>> new file mode 100644
>> index 00000000000..161a1fc2aea
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp
>> @@ -0,0 +1,190 @@
>> +# Copyright 2020 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/>.
>> +
>> +# Setup a line table where:
>> +#
>> +# | Addr | File | Line | Stmt |
>> +# |------|------|------|------|
>> +# | 1 | 1 | 16 | Y |
>> +# | 2 | 1 | 17 | Y |
>> +# | 3 | 2 | 21 | Y |
>> +# | 4 | 2 | 22 | Y |
>> +# | 4 | 1 | 18 | N |
>> +# | 5 | 1 | 19 | N |
>> +# | 6 | 1 | 20 | Y |
>> +# | 7 | 1 | END | Y |
>> +# |------|------|------|------|
>> +#
>> +# Break at file 2, line 22, then single instruction step forward. We
>> +# should pass through line 19 and then encounter line 20.
>> +#
>> +# Currently we don't expect GDB to see file 1, line 18, as this is a
>> +# non-stmt line in a different file at the same address as the
>> +# previous is-stmt line.
>> +
>> +load_lib dwarf.exp
>> +
>> +# This test can only be run on targets which support DWARF-2 and use gas.
>> +if {![dwarf2_support]} {
>> + return 0
>> +}
>> +
>> +# The .c files use __attribute__.
>> +if [get_compiler_info] {
>> + return -1
>> +}
>> +if !$gcc_compiled {
>> + return 0
>> +}
>> +
>> +standard_testfile dw2-inline-header-lbls.c dw2-inline-header.S \
>> + dw2-inline-header.c dw2-inline-header.h
>> +
>> +set asm_file [standard_output_file $srcfile2]
>> +Dwarf::assemble $asm_file {
>> + global srcdir subdir srcfile srcfile3 srcfile4
>> + declare_labels lines_label callee_subprog_label
>> +
>> + get_func_info main
>> +
>> + cu {} {
>> + compile_unit {
>> + {producer "gcc" }
>> + {language @DW_LANG_C}
>> + {name ${srcfile3}}
>> + {low_pc 0 addr}
>> + {stmt_list ${lines_label} DW_FORM_sec_offset}
>> + } {
>> + callee_subprog_label: subprogram {
>> + {external 1 flag}
>> + {name callee}
>> + {inline 3 data1}
>> + }
>> + subprogram {
>> + {external 1 flag}
>> + {name main}
>> + {low_pc $main_start addr}
>> + {high_pc "$main_start + $main_len" addr}
>> + } {
>> + inlined_subroutine {
>> + {abstract_origin %$callee_subprog_label}
>> + {low_pc line_label_1 addr}
>> + {high_pc line_label_7 addr}
>> + {call_file 1 data1}
>> + {call_line 18 data1}
>> + }
>> + }
>> + }
>> + }
>> +
>> + lines {version 2 default_is_stmt 1} lines_label {
>> + include_dir "${srcdir}/${subdir}"
>> + file_name "$srcfile3" 1
>> + file_name "$srcfile4" 1
>> +
>> + program {
>> + {DW_LNE_set_address line_label_1}
>> + {DW_LNS_advance_line 15}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_2}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_set_file 2}
>> + {DW_LNE_set_address line_label_3}
>> + {DW_LNS_advance_line 4}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_4}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNS_advance_line -4}
>> + {DW_LNS_set_file 1}
>> + {DW_LNS_negate_stmt}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_5}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_6}
>> + {DW_LNS_advance_line 1}
>> + {DW_LNS_negate_stmt}
>> + {DW_LNS_copy}
>> +
>> + {DW_LNE_set_address line_label_7}
>> + {DW_LNE_end_sequence}
>> + }
>> + }
>> +}
>> +
>> +if { [prepare_for_testing "failed to prepare" ${testfile} \
>> + [list $srcfile $asm_file] {nodebug optimize=-O1}] } {
>> + return -1
>> +}
>> +
>> +if ![runto_main] {
>> + return -1
>> +}
>> +
>> +# Delete all breakpoints so that the output of "info breakpoints"
>> +# below will only contain a single breakpoint.
>> +delete_breakpoints
>> +
>> +# Place a breakpoint within the function in the header file.
>> +gdb_breakpoint "${srcfile4}:22"
>> +
>> +# Check that the breakpoint was placed where we expected. It should
>> +# appear at the requested line. When the bug in GDB was present the
>> +# breakpoint would be placed on one of the following lines instead.
>> +gdb_test "info breakpoints" \
>> + ".* in callee at \[^\r\n\]+${srcfile4}:22\\y.*"
>> +
>> +gdb_continue_to_breakpoint "${srcfile4}:22" \
>> + ".* ${srcfile4} : 22 .*"
>> +
>> +# Now single instruction step forward. Eventually we should hit
>> +# ${srcfile3}:20, but before we do we should hit the non-statement
>> +# line ${srcfile3}:19.
>> +#
>> +# We don't know how many instructions we'll need to step, but 100
>> +# should be enough for everyone (surely), and this stops us looping
>> +# forever if something goes wrong.
>> +set found_line_19 0
>> +set found_line_20 0
>> +set keep_going 1
>> +for { set i 0 } { $i < 100 && $keep_going } { incr i } {
>> + set keep_going 0
>> + gdb_test_multiple "stepi" "stepi ${i}" {
>> + -re "${srcfile3} : 19 .*${gdb_prompt} " {
>> + set found_line_19 1
>> + set keep_going 1
>> + }
>> +
>> + -re "${srcfile3} : 20 .*${gdb_prompt} " {
>> + set found_line_20 1
>> + }
>> +
>> + -re "${srcfile4} : 22 .*${gdb_prompt} " {
>> + # Not left line 22 yet.
>> + set keep_going 1
>> + }
>> + }
>> +}
>> +
>> +gdb_assert { $found_line_19 && $found_line_20 } \
>> + "found line 19 and 20"
>> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-header-lbls.c b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-lbls.c
>> new file mode 100644
>> index 00000000000..a1b7b17cbeb
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-lbls.c
>> @@ -0,0 +1,46 @@
>> +/* Copyright 2020 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/>. */
>> +
>> +/* Used to insert labels with which we can build a fake line table. */
>> +#define LL(N) asm ("line_label_" #N ": .globl line_label_" #N)
>> +
>> +volatile int var;
>> +volatile int bar;
>> +
>> +/* Generate some code to take up some space. */
>> +#define FILLER do { \
>> + var = 99; \
>> +} while (0)
>> +
>> +int
>> +main ()
>> +{ /* main prologue */
>> + asm ("main_label: .globl main_label");
>> + LL (1); // F1, Ln 16
>> + FILLER;
>> + LL (2); // F1, Ln 17
>> + FILLER;
>> + LL (3); // F2, Ln 21
>> + FILLER;
>> + LL (4); // F2, Ln 22 // F1, Ln 18, !S
>> + FILLER;
>> + LL (5); // F1, Ln 19 !S
>> + FILLER;
>> + LL (6); // F1, Ln 20
>> + FILLER;
>> + LL (7);
>> + FILLER;
>> + return 0; /* main end */
>> +}
>> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-header.c b/gdb/testsuite/gdb.dwarf2/dw2-inline-header.c
>> new file mode 100644
>> index 00000000000..a8331268a09
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header.c
>> @@ -0,0 +1,24 @@
>> +/* Copyright 2020 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/>. */
>> +
>> +/* dw2-inline-header.c : 16 */
>> +/* dw2-inline-header.c : 17 */
>> +/* dw2-inline-header.c : 18 */
>> +/* dw2-inline-header.c : 19 */
>> +/* dw2-inline-header.c : 20 */
>> +/* dw2-inline-header.c : 21 */
>> +/* dw2-inline-header.c : 22 */
>> +/* dw2-inline-header.c : 23 */
>> +/* dw2-inline-header.c : 24 */
>> diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-header.h b/gdb/testsuite/gdb.dwarf2/dw2-inline-header.h
>> new file mode 100644
>> index 00000000000..7233acbcd76
>> --- /dev/null
>> +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header.h
>> @@ -0,0 +1,24 @@
>> +/* Copyright 2020 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/>. */
>> +
>> +/* dw2-inline-header.h : 16 */
>> +/* dw2-inline-header.h : 17 */
>> +/* dw2-inline-header.h : 18 */
>> +/* dw2-inline-header.h : 19 */
>> +/* dw2-inline-header.h : 20 */
>> +/* dw2-inline-header.h : 21 */
>> +/* dw2-inline-header.h : 22 */
>> +/* dw2-inline-header.h : 23 */
>> +/* dw2-inline-header.h : 24 */
>>
More information about the Gdb-patches
mailing list