aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog10
-rw-r--r--gdb/dwarf2/read.c47
-rw-r--r--gdb/testsuite/ChangeLog11
-rw-r--r--gdb/testsuite/gdb.cp/step-and-next-inline.exp7
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inline-header-1.exp186
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inline-header-2.exp189
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp193
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inline-header-lbls.c46
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inline-header.c24
-rw-r--r--gdb/testsuite/gdb.dwarf2/dw2-inline-header.h24
10 files changed, 734 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index c95c168..b74167e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,13 @@
+2020-06-01 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * 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.
+
2020-06-01 Samuel Thibault <samuel.thibault@ens-lyon.org>
* config/i386/i386gnu.mn [%_S.o %_U.o] (COMPILE.post): Add
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 4724738..e6566f9 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -20040,6 +20040,15 @@ private:
/* 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;
@@ -20233,14 +20242,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;
@@ -20259,6 +20288,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,
@@ -20278,6 +20316,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/ChangeLog b/gdb/testsuite/ChangeLog
index 8c5553e..ec6b24a 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2020-06-01 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * 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.
+
2020-05-30 Pedro Alves <palves@redhat.com>
* gdb.linespec/cp-replace-typedefs-ns-template.cc: New.
diff --git a/gdb/testsuite/gdb.cp/step-and-next-inline.exp b/gdb/testsuite/gdb.cp/step-and-next-inline.exp
index 3733fa7..a95e211 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 0000000..dc7ec92
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-1.exp
@@ -0,0 +1,186 @@
+# 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:
+#
+# | | | | | Inline | Inline |
+# | Addr | File | Line | Stmt | Rng A | Rng B |
+# |------|------|------|------|--------|--------|
+# | 1 | 1 | 16 | Y | | |
+# | 2 | 1 | 17 | Y | | |
+# | 3 | 2 | 21 | Y | X | |
+# | 4 | 2 | 22 | Y | X | |
+# | 4 | 1 | 18 | N | X | |
+# | 5 | 2 | 23 | N | X | X |
+# | 6 | 1 | 24 | Y | | |
+# | 7 | 1 | END | Y | | |
+# |------|------|------|------|--------|--------|
+#
+# Places a brekpoint at file 2, line 22. Previously GDB would discard
+# 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.
+#
+# The two inlined subroutine ranges 'A' and 'B' represent two possible
+# ways that a compiler might represent this siuatio in the DWARF.
+#
+# Range 'B' is something that has been seen in the wild using GCC 8.2.
+# In this case the compilers range information is clearly wrong, but
+# this shouldn't impact the main point of the test.
+#
+# Range 'A' is a hypothetical case of how the compiler might choose to
+# represent this range, this has never been seen in the wild, but is
+# an improved debug experiece over range 'B'. However, if we ever run
+# in to the situation where GDB can support the range 'A' test, or
+# support some real DWARF seen in the wild, then the range 'A' case
+# should be dropped in favour of supporting real world cases. This is
+# included here as it "just worked" once the range 'B' case was
+# working.
+
+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
+}
+
+# Prepare and run the test.
+proc do_test { start_label func_name tag } {
+ global srcfile srcfile2 srcfile3 srcfile4 testfile
+
+ standard_testfile dw2-inline-header-lbls.c dw2-inline-header-${tag}.S \
+ dw2-inline-header.c dw2-inline-header.h
+
+ set build_options {nodebug optimize=-O1}
+
+ set asm_file [standard_output_file $srcfile2]
+ Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile srcfile3 srcfile4 testfile
+ upvar build_options build_options
+ upvar start_label start_label
+ declare_labels lines_label callee_subprog_label
+
+ get_func_info main $build_options
+
+ 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 $start_label addr}
+ {high_pc line_label_6 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}-${tag} \
+ [list $srcfile $asm_file] $build_options] } {
+ 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 $func_name at \[^\r\n\]+${srcfile4}:22\\y.*" \
+ "info breakpoints, $tag"
+}
+
+do_test line_label_3 "callee" "range-a"
+do_test line_label_5 "main" "range-b"
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 0000000..9f09f35
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-2.exp
@@ -0,0 +1,189 @@
+# 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 | Inline |
+# |------|------|------|------|--------|
+# | 1 | 1 | 16 | Y | |
+# | 2 | 1 | 17 | Y | |
+# | 3 | 2 | 21 | Y | X |
+# | 4 | 2 | 22 | Y | X |
+# | 4 | 1 | 18 | N | X |
+# | 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.
+#
+# This test is designed to test GDB's internal behaviour with respect
+# to discarding particular line table entries. GCC and DWARF are
+# starting to introduce the idea of line table views. As the views
+# information becomes better supported within GDB it is likely that
+# this will become out of date. This is fine, the test will have
+# served its purpose by that point and can be deleted.
+#
+# [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 build_options {nodebug optimize=-O1}
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile srcfile3 srcfile4
+ global build_options
+ declare_labels lines_label callee_subprog_label
+
+ get_func_info main $build_options
+
+ 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_3 addr}
+ {high_pc line_label_5 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] $build_options] } {
+ 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 main 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 0000000..a3820f1
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-header-3.exp
@@ -0,0 +1,193 @@
+# 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 | Inline |
+# |------|------|------|------|--------|
+# | 1 | 1 | 16 | Y | |
+# | 2 | 1 | 17 | Y | |
+# | 3 | 2 | 21 | Y | X |
+# | 4 | 2 | 22 | Y | X |
+# | 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 build_options {nodebug optimize=-O1}
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+ global srcdir subdir srcfile srcfile3 srcfile4
+ global build_options
+ declare_labels lines_label callee_subprog_label
+
+ get_func_info main $build_options
+
+ 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_3 addr}
+ {high_pc line_label_5 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] $build_options] } {
+ 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 0000000..a1b7b17
--- /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 0000000..a833126
--- /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 0000000..7233acb
--- /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 */