From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x343.google.com (mail-wm1-x343.google.com [IPv6:2a00:1450:4864:20::343]) by sourceware.org (Postfix) with ESMTPS id F1E073972474 for ; Fri, 15 May 2020 14:46:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org F1E073972474 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-wm1-x343.google.com with SMTP id g12so2957424wmh.3 for ; Fri, 15 May 2020 07:46:32 -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=ih0g3gyWfQQ23rpSJ38Nejc0RM9qw3lfii7E7pLLUpM=; b=fAmdkc4QXAuzXSqWNiZChfbUz9x/Ti5KanBEzPz2w6vCKQEGmabL0Nw/Qr22bUQDlQ HeMb0gTkzEJofSelyjCfRI6ZmcY51M22EIbQysQEo/El74b64D4UU+KttPHio1+ncNU1 Z6adeAJ47Fn6+GKM0Ssg4U9wiF8hh+TP6mzKoKDWrrFuFoyEcLHLPC8VpdfByVy8P6Y4 Kx1d8a9vRmsdDb521pGRZUB9ueu1s0uA9L2Xk8NEGAvIfoFZMsOOKS0+70RXSPoHRJtv 59MstK0RlT4fy5SCam1nzx+g8I1J7Bo/cZWjdNqH2BycUvJCtUOiNzz0TXwGh/x1aEU8 xptw== 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=ih0g3gyWfQQ23rpSJ38Nejc0RM9qw3lfii7E7pLLUpM=; b=recap5WVIg9RhADrVlpk1aRBpBsTYt26AoCUsBaZxSgbGBqkgwVC621rW0TrbDDDbA DoaB147sfLtQjoTiuLyS83lUUmGwHF1Tr6FmR2M9UUj9rXi9E9R3IKQnK/e8SIT9Kzgo zvYeduW7TButxT3IoTeyyRB6zCy83r+emqUBTcie6WxWoQ+Q6IoAWTdrPjyx9AJlZlo5 raYVrdjDwWzTwnF+91vGWVneLzvVoTrSEf2bEJ5dkAezvP+3Rsd103CuV0FFmxIC6//S uw/pz23T8CZZnEEJeFeP+oQyRX+AL/Omuec18YI0EhFd4G1Myv9lCxoUO+AC2krbE7rY RJxQ== X-Gm-Message-State: AOAM532KvASnmHpqWUBfXOoDQE7KVYA3wMWqB3xt8p1ETZKe75Wiru6i YgOAF9FVDptndVPKFTBa35kXnQ== X-Google-Smtp-Source: ABdhPJxqLX+4RblCR98wYbQdGaCKlbg4AcnOEC2+zYVgoaq6jp4XxNMCP5Pe02qNtOCqOQaearSo7A== X-Received: by 2002:a1c:98c9:: with SMTP id a192mr4368489wme.48.1589553991656; Fri, 15 May 2020 07:46:31 -0700 (PDT) Received: from localhost (host86-128-12-16.range86-128.btcentralplus.com. [86.128.12.16]) by smtp.gmail.com with ESMTPSA id f8sm3832248wrm.8.2020.05.15.07.46.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2020 07:46:30 -0700 (PDT) Date: Fri, 15 May 2020 15:46:29 +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: <20200515144629.GT3522@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: 15:06:06 up 25 days, 3:51, X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] X-Spam-Status: No, score=-10.8 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: Fri, 15 May 2020 14:46:43 -0000 * Bernd Edlinger [2020-05-15 05:35:43 +0200]: > > Andrew, as far as I remember the range info of the > inlined subroutines were not correct, in your patch. Thanks for pointing this out, I eventually figured out the problem you'd seen and fixed this. > Can you please fix the range infos in your patch > and re-post it, before we decide how to proceed? Rebased and latest version of the patch is attached. As the bug fixes are minor I don't think we should spend much longer discussing this. > But I would say that I see a way how I can adjust my > patch to fix the issues which were raised by your test > case (I added the test case from your patch to mine, > and most of it seems to be fine with my latest patch, > one remaining issue is a bit nasty but fixable). > I'll attach the patch file where I am at here, so > you can see what I have now. > It fails only one test case in dw2-inline-header-3.exp > but I would like how it compares to your patch > when Tom would like to try it out on the > internal test cases, he mentioned. > > And, yes, of course my approach is that the debug info > is not optimal at all as it is emitted by gcc, but > gdb can probably work around it until it is fixed > which should happen when a new updated dwarf extension > is invented which tells us the view number where > the inlined subroutine ends. The line table program > has view numbers, but not the range info of the > subroutine. That is the deficiency in the dwarf > format I think causes the trouble, apart from the > fact that dwarf is already too complicate to understand. I think this is one of our sticking points. I agree 100% with you that adding view support to the range information would allow GCC to be more expressive. But I feel that, just because DWARF lacks a certain feature, this doesn't mean we can't build a valid debug picture with the features we do have. Sure, me may have to compromise, but we can still create something that is internally consistent. GCC isn't doing this right now. Maybe it is the opinion of the GCC devs that they'll not fix GCC until DWARF gains the extra features they'd like. That's something you'd have to take up on the GCC list. Adding support to work around compiler bugs is absolutely fine, so long as we understand exactly what issues we're working around, and that the issue (hopefully) will get fixed eventually, so any work around should be (I think) applied conservatively, only when we are sure the work around is appropriate (maybe based on producer strings, for example). > > On 5/15/20 12:39 AM, Andrew Burgess wrote: > > * Tom Tromey [2020-05-14 14:18:44 -0600]: > > > >>>>>>> "Andrew" == Andrew Burgess writes: > >> > >> Resurrecting this again ... we have some internal tests that have been > >> failing, and I want to land at least one of these patches to resolve > >> this. > >> > >> Andrew> After reading[2] I'd also be interest to understand what flaw in > >> Andrew> DWARF you feel makes a difference in this case. > >> > >> I also don't understand this. > >> > > When you only know where an inline function ends at the byte address. > You can habe line table entries at the same address from the inline > funcion and from the calling function. It is impossible to distinguish > between those, however there is a view number which would be different, > and as Alexandre explains it, these can be consider an extension to the > byte addresses, so if a range info would add a view number we would > know which line infos are from the subroutine and which are not, even > if the byte addresses are identical. Please correct me if I'm wrong, but as for view support in ranges, there's not even a GCC only extension for this yet (I did look, but could easily have missed something). I think we'd probably want to see this feature as at least a GCC extension, then we could add support in GDB. > > >> Andrew> I don't know how we address this without merging your patch, > >> Andrew> releasing GDB and seeing how it works in the wild. However, if we > >> Andrew> did decide to "just try it", I would still prefer we staged things > >> Andrew> as: > >> Andrew> (a) Merge my patch, targeted regression fix, then > >> Andrew> (b) Your patch, new functionality GCC/DWARF ranges work around. > >> Andrew> In this way, if we end up backing out some or all of (b) we still > >> Andrew> have (a) in place that fixes the regression. I'm more than happy > >> Andrew> for a rebase of (b) in include full removal of (a). > >> > >> I think landing your patch is safe to do while we discuss part (b). > >> How about we move forward with that part? Then if we come to agreement > >> on where the bug lies we can decide about that. > > > > I agree. I already rebased this and retested it. Unless someone > > shouts out between now and tomorrow I plan to merge my patch. > > > > Bernd (or anyone else) - I'm more than happy that if a better patch is > > put forward it can revert some or all of my patch, as needed. Like > > Tom, I'd like to see the regressions squashed. > > > > No, I am not able to do this once we decide that gcc's debug info > is impossible to implement, I will send a patch to the gcc-patches > which restores the gcc-7 debug info. I am certainly not suggesting, and having re-read many mails in this thread, I don't think anyone else is suggesting, that it is impossible to craft a work around for GCC's broken debug information. I think that all we're suggesting is that your work around patch isn't ready just yet, so instead of rushing that in to fix the is-stmt regression, lets just merge my conservative regression fix patch, then we can take our time and get your work around GCC patch correct. This would be an easy discussion if it wasn't for gdb.cp/step-and-next-inline.exp, which my regression fix patch breaks. That test is what motivated your original patch last year, so I completely understand why my breaking it leaves you feeling frustrated. My position here is that this test is really an example of the GCC broken debug issue and really should never have been merged with the is-stmt patch, as such I would like to see it disabled until your patch lands later. > My patch was based on the > assumption that there is a way to work around the issues, but if > that turns out to be a failure, I will not go back and revert > your patch again, since it seems to revert my work on that issue > completely No you've misunderstood, when your patch succeeds you will (maybe) revert this patch as part of your successful patch. If your patch were to never land (and I'm sure we _can_ get it over the line) then no, the patch I propose here wouldn't be reverted, but that's exactly the point of pushing this patch first. This patch is a low risk regression fix. You patch is (slightly) higher risk, new functionality. All Tom and I are suggesting is lets just merge them in that order, rather than rushing into the high risk fix. > (see how this patch breaks the step-and-next-inline.exp > test case). And once again, I feel not at all emotional, just that > I want the issue fixed, and next time I will try a completely > different approach which is gcc was wrong, and therefore we will > revert Alexandre Oliva's patch, since it is the least effort and > Alexandre already signaled he also had considered that already. > > Alexandre Oliva wrote on 11/19/19: > https://gcc.gnu.org/pipermail/gcc-patches/2019-November/534845.html > > Perhaps we should change our defaults, if the situation with GDB does > > not change :-( There is some view information emitted by GCC now, but for gdb.cp/step-and-next-inline.exp I don't think any of the view information would help even if we did consume it. The problem with that test is entirely GCC emitting broken DWARF. I interpret the last two paragraphs above as saying, it's easier to disable a broken feature in GCC than to merge a partially complete work around into GDB. And that's as it should be. If you can point to some non-broken DWARF that GDB doesn't currently parse correctly, that would help gdb.cp/step-and-next-inline.exp pass, then I would certainly be prepared to invest some time trying to help improve GDB in that area. Bernd, you asked for some time to follow up on this thread, but this issue has dragged on for long enough now I think. It is my intention to merge the patch below on Monday unless I hear a compelling argument against it. After that it should be trivial for your to rebase your patch and revert those parts of my patch you no longer need. Repost the update and we can discuss how to get it merged. Thanks, Andrew ---- >From c5d89ffa3032c401cc79c241097006a12b306d02 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Fri, 3 Apr 2020 20:32:38 +0100 Subject: [PATCH] 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) : New member variable. : 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.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 +++ 10 files changed, 734 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 ab21ab0d13a..fea980d0a33 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -19880,6 +19880,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; @@ -20073,14 +20082,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; @@ -20099,6 +20128,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, @@ -20118,6 +20156,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..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