From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x442.google.com (mail-wr1-x442.google.com [IPv6:2a00:1450:4864:20::442]) by sourceware.org (Postfix) with ESMTPS id A371F385DC32 for ; Wed, 20 May 2020 18:27:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org A371F385DC32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=embecosm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=andrew.burgess@embecosm.com Received: by mail-wr1-x442.google.com with SMTP id v12so4123111wrp.12 for ; Wed, 20 May 2020 11:27:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=nPMgJH6N6206REnDQw18X22+YczZoXO9Dz+r07V2Tfo=; b=Crg1ErQnak7x94Ufs/iYHXWDNV5VoPdF031SMA65UztD4IocCDKeLZQCR5k3onHjjG PxjUwhqer1G6YNbwim7NrfJMbO6ntp1Ej0H9jBV44tLEQp773KXfzmgpq+TLnVIz4dLs qZ0AgVPok7ELdu2LFbQcXgQZiLs87MJCgy5udCvESpEBqVvOs7FaVl8eK6jIM0ME1RzQ J6H7kUqWdvKO46+boyegieDHCG26/r58ym76ro5At2yzlZsxlsAkNP7F0Mn/hvGaq7nO 2kyGgYAb0NfCsru5EDCsOpqTPJhhGs8D8bJDNJzoNlHJu8x51zOvAlOLd2PE2yzbCate GgQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=nPMgJH6N6206REnDQw18X22+YczZoXO9Dz+r07V2Tfo=; b=CWVtU1BLLj6NiXGrrVi9uluSEHBf26M0ZCgcrSRLZ8Iz79yydMUzBJ1Tr2uZe/qem5 p43VrQgVTiqv4WGVKfHhvmbXNaPooE0UbLkqEOUivvQ6Tdpvfeg2LMeoBUHVWzwTW1E+ gdhpzn7np95cldEmU6hD36QpoPHWMQPfs/UfeS2nQ05S6b+NqXM8+SbhvdWz8X4UiPQX ixBXvzV0rnUJAqpNE4PYX7vEOlB3h3l9kSWxlDepgqyAD4WB71uLmlhCQ7PeWCI1p5W+ k6wFK/MnfHsJrG/aZDNOsXB4vlUWcv/5u+dWauvHD3dAQpQYGFop9wEQXY6bdnlbORXX 3wog== X-Gm-Message-State: AOAM533QYFgLVjVL/pxVB/krtVtkQwsNbmZtE9Rc8RrUQMwUyq4+Vi17 T+/vbs4wFz9LJXkRC7w8DBfz1Q== X-Google-Smtp-Source: ABdhPJwgN8RyVVuK/bJKPDd3jykRWpFOQxg2xcYvvPj/cXquIFwJPDNF9la6Obsj8Waoktnk7Zg55g== X-Received: by 2002:adf:fe89:: with SMTP id l9mr5164670wrr.400.1589999220589; Wed, 20 May 2020 11:27:00 -0700 (PDT) Received: from localhost (host86-128-12-16.range86-128.btcentralplus.com. [86.128.12.16]) by smtp.gmail.com with ESMTPSA id x1sm3483341wrt.86.2020.05.20.11.26.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 May 2020 11:26:59 -0700 (PDT) Date: Wed, 20 May 2020 19:26:58 +0100 From: Andrew Burgess To: Bernd Edlinger Cc: Tom Tromey , gdb-patches@sourceware.org, Alexandre Oliva Subject: Re: [PATCH 2/2] gdb: Preserve is-stmt lines when switch between files Message-ID: <20200520182658.GU3522@embecosm.com> References: <20200414112841.GC2366@embecosm.com> <20200416171809.GJ2366@embecosm.com> <87lfmnql4g.fsf@tromey.com> <20200427103418.GF3522@embecosm.com> <87r1vmuv6j.fsf@tromey.com> <20200514223925.GS3522@embecosm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: X-Operating-System: Linux/5.5.17-200.fc31.x86_64 (x86_64) X-Uptime: 19:20:14 up 30 days, 8:05, X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 20 May 2020 18:27:05 -0000 Bernd, Below is a first draft of a currently WIP patch that is an alternative to what I have previously proposed. This patch is based on parts of your patch, specifically, those bits related to having two different end-of-sequence type markers 0 or -1. I have fixed the issue that prevented my new dw2-inline-header-3.exp test from passing. This does not include any of the inline range handling changes you were proposing, but as this is a sub-set of your proposal, then I'm hoping you might feel .... less bad .... about this patch, adding the rest of your work should be much more building on top of this, rather than backing this out and starting again. The one contentious area where I have had to stick with my original patch is in the treatment of gdb.cp/step-and-next-inline.exp, this test still regresses with this patch, so I have still basically disabled this test. As we've discussed (at great length) I believe the regressions here are due to GCC bugs, which your patch when its completed will aim to address, so hopefully that will not be too much to accept for now. Like I said, this is still WIP, its just I'll likely not get to work on this until Friday or the weekend now, so I wanted to share this early so you could give me your thoughts. Look forward to your feedback, Thanks, Andrew ---- >From 009671f35e232d80f61fd7d86251a84be2d965db Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Wed, 20 May 2020 19:16:05 +0100 Subject: [PATCH] WIP: gdb: Don't delete empty lines when changing symtabs Based on Bernd's patch found here: https://sourceware.org/pipermail/gdb-patches/2020-May/168591.html TODO: - More testing, - Changelogs - Split out addition of linetable_entry::end_of_sequence --- gdb/buildsym.c | 24 ++- gdb/dwarf2/read.c | 8 +- gdb/symtab.c | 4 +- gdb/symtab.h | 16 +- gdb/testsuite/gdb.cp/step-and-next-inline.exp | 7 + .../gdb.dwarf2/dw2-inline-header-1.exp | 186 +++++++++++++++++ .../gdb.dwarf2/dw2-inline-header-2.exp | 189 +++++++++++++++++ .../gdb.dwarf2/dw2-inline-header-3.exp | 193 ++++++++++++++++++ .../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 +++ 11 files changed, 714 insertions(+), 7 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/buildsym.c b/gdb/buildsym.c index b9bcc33080a..2ff2a5455d0 100644 --- a/gdb/buildsym.c +++ b/gdb/buildsym.c @@ -662,7 +662,24 @@ buildsym_compunit::pop_subfile () } /* Add a linetable entry for line number LINE and address PC to the - line vector for SUBFILE. */ + line vector for SUBFILE. + + LINE is usually an integer greater than 0 representing the line number + within the file, however two special values also exist. Pass 0 to + indicate an end of sequence marker found within the actual line table, + or -1 to indicate an artificial end of sequence generated during + parsing of the line table to indicate a switch between subfiles. + + The difference between these values is how GDB treats apparently empty + lines at the end marker, with the end marker value 0 this function + deletes any empty lines at the same address as the end marker, while + when switching subfiles any empty lines are preserved. The reason is + that a 0 style end of sequence most likely means the end of a function, + so trying to place a breakpoint on any empty lines at this address will + result in a breakpoint being placed within the next function. A -1 + style end of sequence marker will appear within a function when code + has been inlined, in this case placing a breakpoint at the address of + an end of sequence should be fine. */ void buildsym_compunit::record_line (struct subfile *subfile, int line, @@ -704,7 +721,7 @@ buildsym_compunit::record_line (struct subfile *subfile, int line, end of sequence markers. All we lose is the ability to set breakpoints at some lines which contain no instructions anyway. */ - if (line == 0) + if (line == linetable_entry::end_of_sequence) { while (subfile->line_vector->nitems > 0) { @@ -714,8 +731,11 @@ buildsym_compunit::record_line (struct subfile *subfile, int line, subfile->line_vector->nitems--; } } + else if (line == linetable_entry::change_of_symtab) + line = linetable_entry::end_of_sequence; e = subfile->line_vector->item + subfile->line_vector->nitems++; + gdb_assert (line >= 0); e->line = line; e->is_stmt = is_stmt ? 1 : 0; e->pc = pc; diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index ab21ab0d13a..cbea38f9b1a 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -20031,7 +20031,7 @@ dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile, static void dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile, - CORE_ADDR address, struct dwarf2_cu *cu) + CORE_ADDR address, struct dwarf2_cu *cu, bool end_sequence) { if (subfile == NULL) return; @@ -20044,7 +20044,8 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile, paddress (gdbarch, address)); } - dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu); + dwarf_record_line_1 (gdbarch, subfile, end_sequence ? 0 : -1, address, + true, cu); } void @@ -20077,7 +20078,8 @@ lnp_state_machine::record_line (bool end_sequence) || end_sequence) { dwarf_finish_line (m_gdbarch, m_last_subfile, m_address, - m_currently_recording_lines ? m_cu : nullptr); + m_currently_recording_lines ? m_cu : nullptr, + end_sequence); } if (!end_sequence) diff --git a/gdb/symtab.c b/gdb/symtab.c index 2043d084140..070a3311a16 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3270,7 +3270,9 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent) save prev if it represents the end of a function (i.e. line number 0) instead of a real line. */ - if (prev && prev->line && (!best || prev->pc > best->pc)) + if (prev && prev->line && (!best || prev->pc > best->pc + || (prev->pc == best->pc && !best->is_stmt + && prev->is_stmt))) { best = prev; best_symtab = iter_s; diff --git a/gdb/symtab.h b/gdb/symtab.h index 764c567a90b..ebb0c818bc8 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1304,7 +1304,10 @@ struct rust_vtable_symbol : public symbol struct linetable_entry { - /* The line number for this entry. */ + /* The line number for this entry. This should be a value greater than + 0 to indicate an actual line number, or the magic value 0 is used to + indicate the end of a sequence of linetable_entry structures in a + list. */ int line; /* True if this PC is a good location to place a breakpoint for LINE. */ @@ -1312,6 +1315,17 @@ struct linetable_entry /* The address for this entry. */ CORE_ADDR pc; + + /* Constant value that can be placed into the LINE field to indicate the + end of a sequence of line table entries. */ + static const int end_of_sequence = 0; + + /* Constant that can be passed to buildsym_compunit::record_line when + creating the line table. This indicates an artificial end of sequence + and is transformed into END_OF_SEQUENCE before being stored into the + line table, consequently CHANGE_OF_SYMTAB will never actually appear + in the LINE field. */ + static const int change_of_symtab = -1; }; /* The order of entries in the linetable is significant. They should 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..dc7ec929236 --- /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 . + +# 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 00000000000..9f09f353273 --- /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 . + +# 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 00000000000..a3820f16d57 --- /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 . + +# 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 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 . */ + +/* 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 . */ + +/* 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 . */ + +/* 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 */ -- 2.25.4