[PATCH 2/2] gdb: Preserve is-stmt lines when switch between files

Bernd Edlinger bernd.edlinger@hotmail.de
Sat Apr 4 18:07:52 GMT 2020


Sorry, Andrew,

please hold this one.

This will definitely break all the step over inline
stuff that was already working.

Can we please go to the drawing board before we continue
from here?


Thanks
Bernd.

On 4/4/20 12:21 AM, Andrew Burgess wrote:
> 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.
> ---
>  gdb/ChangeLog                                     |  10 ++
>  gdb/dwarf2/read.c                                 |  47 +++++-
>  gdb/testsuite/ChangeLog                           |  11 ++
>  gdb/testsuite/gdb.cp/step-and-next-inline.exp     |   7 +
>  gdb/testsuite/gdb.dwarf2/dw2-inline-header-1.exp  | 156 ++++++++++++++++++
>  gdb/testsuite/gdb.dwarf2/dw2-inline-header-2.exp  | 179 ++++++++++++++++++++
>  gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp  | 192 ++++++++++++++++++++++
>  gdb/testsuite/gdb.dwarf2/dw2-inline-header-lbls.c |  46 ++++++
>  gdb/testsuite/gdb.dwarf2/dw2-inline-header.c      |  24 +++
>  gdb/testsuite/gdb.dwarf2/dw2-inline-header.h      |  24 +++
>  10 files changed, 693 insertions(+), 3 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-header-1.exp
>  create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-header-2.exp
>  create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp
>  create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-header-lbls.c
>  create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-header.c
>  create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-header.h
> 
> diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
> index f94c66b4f1b..261c8455424 100644
> --- a/gdb/dwarf2/read.c
> +++ b/gdb/dwarf2/read.c
> @@ -19327,6 +19327,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;
>  
> @@ -19520,14 +19529,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;
>  
> @@ -19546,6 +19575,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,
> @@ -19565,6 +19603,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_addr = 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..c683dc4bb8a
> --- /dev/null
> +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp
> @@ -0,0 +1,192 @@
> +# 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