From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x443.google.com (mail-wr1-x443.google.com [IPv6:2a00:1450:4864:20::443]) by sourceware.org (Postfix) with ESMTPS id 5A5E8388E832 for ; Mon, 1 Jun 2020 09:05:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 5A5E8388E832 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-x443.google.com with SMTP id l10so10654504wrr.10 for ; Mon, 01 Jun 2020 02:05:41 -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=1WVfFVklIwDrGpAdVASkSpm4qWP/YlCeeMbu5KBOBv8=; b=bEpbVuA5N+MN5G9XVj3ZUkDlpDH7k+1iRm+6JqI85nwhPvLyz4ustY7WHrNZsWjbTy xz00HIoIkPxrWmZaB4PGgJrWZ3vd8gcwHqKhbDHBD6znfx8W8suuY7wj1AObKC6uIkCi KiuHqV1nRfZlvFEst9xPhcBxxeHRKQOLjnEt6ffAvwCt1op87N7E4B4AmNCmk2i6YDwX 6xBF1xN9PbOKIoyLqCcRbhThzQW88wD1oOZRXhPRG+H4eGXNUUhafl+Dl3l6TuYpzwS6 ulk0cXfEQcLX9mYPLOxDlgCHzZ0zcj6VGQ5QYT21D19nXxRx39mAAmbOhnrTTszQPSle Kt9A== 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=1WVfFVklIwDrGpAdVASkSpm4qWP/YlCeeMbu5KBOBv8=; b=gmMxgfFSsy+vOyEfbLsAwjLq5wVg5hrqrLLhSpwIT+hKwBq9auCv72c+hn5nKOXNMD XroWFCPjeA1Q5J5jJB4VYnsqvv7QBIWLA3L4JCke4F0tg9F4eBbIWouFO6aTp9cHoEXy FpXaosVM52yB7ybriO+K4nvfQz3rmipnuNOcQt4kLL6OdumO68l8XnBjOBkIPUyAAjx5 tnrjGo7x9kshxSG+s7EBLhcPBgftwwMH0dfVmHPNnHTffZ/RO/K1ryV7Pa5RSN28j/EK 72fhNPXo4rn1gwBw01fczZQRqZOrEVF0PqFajeLrUPhY274bpNTVAWd6Lsjs4quhmn1M QtBQ== X-Gm-Message-State: AOAM532Q52OD84Y6thqc4nyYqb5W2TO9FQcvzPZ+roX25wxgkNDRAOXQ FkVhWN6GzSQsp8TZnSNsw7KHlGnltbY= X-Google-Smtp-Source: ABdhPJyPh0YP43WhYa6WLLWG3SDqAdR5TtLIq0aDONSiakBKvGy9gdO7VDp354sgscNKaJrI5G3RwQ== X-Received: by 2002:a5d:6a4b:: with SMTP id t11mr20631626wrw.404.1591002339523; Mon, 01 Jun 2020 02:05:39 -0700 (PDT) Received: from localhost (host86-128-12-16.range86-128.btcentralplus.com. [86.128.12.16]) by smtp.gmail.com with ESMTPSA id j190sm11865428wmb.33.2020.06.01.02.05.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 01 Jun 2020 02:05:38 -0700 (PDT) Date: Mon, 1 Jun 2020 10:05:37 +0100 From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Tom Tromey , Bernd Edlinger , Alexandre Oliva Subject: Re: [PATCH 2/2] gdb: Preserve is-stmt lines when switch between files Message-ID: <20200601090537.GX3522@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> <20200520182658.GU3522@embecosm.com> <20200527131022.GW3522@embecosm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200527131022.GW3522@embecosm.com> X-Operating-System: Linux/5.5.17-200.fc31.x86_64 (x86_64) X-Uptime: 10:04:11 up 41 days, 23:39, X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] X-Spam-Status: No, score=-12.1 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: Mon, 01 Jun 2020 09:05:45 -0000 * Andrew Burgess [2020-05-27 14:10:22 +0100]: > Below is an updated version of the previous work in progress patch. > I'm posting it here so there's a record, however, I don't think this > patch should be merged into upstream. While working on this solution > the problems with it became apparent to me. I've tried to describe my > issues with this approach in the commit message of the patch. > > It is now my intention to merge the patch I posted here: > > https://sourceware.org/pipermail/gdb-patches/2020-May/168611.html > > which I'll do in a couple of days unless anyone would like to discuss > this further. I have now merged the patch mentioned above. Tom - this should resolve the regression you are seeing in your MinGW test. Do let me know if you continue to see any problems related to this series. Thanks, Andrew > > Thanks, > Andrew > > --- > > commit 79719063c19b3906fda9d9e7fa0b8c009716b53a > Author: Andrew Burgess > Date: Wed May 20 19:16:05 2020 +0100 > > gdb: Don't delete empty lines when changing symtabs > > ***** NOT FOR MERGING INTO UPSTREAM ***** > > This patch is based on the work of Bernd Edlinger here: > > https://sourceware.org/pipermail/gdb-patches/2020-May/168591.html > > 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. > > In order to understand the solution presented here, we must first > remind ourselves why we delete line table entries that occur at the > same address as an END marker. > > The problem this (deleting lines) is trying to solve is that if the > last real line within a line table is empty (maybe due to > optimisation) then the line will be at the same address as the end > marker. If the user tries to place a breakpoint at this address then > we actually end up with a breakpoint at whatever is _after_ the > location of that empty line, which is likely some other random > function. > > However, when a line table switches subfiles we also insert end > markers, this is because the GDB internal line table is split > per-subfile, so the end markers allow us to see and "end" for the line > just before the switch. Without this, the line table entry just > before the we switch subfiles would appear to extend over the entire > region covered by the subfile we switch too. > > If we further consider the end markers inserted for switching > subfiles, there are two common cases when this can occur, these are, > first when one file is fully included inside another, and secondly > when a function from one (header) file is inlined within a function > in a different file. > > In the first of these situations GDB is exposed to the same risk as > for the classic end marker case, if the last line before the subfile > switch is empty, then when we switch subfiles we should be deleting > the empty line, otherwise a user placing a breakpoint on this line, > will end up with a breakpoint in a potentially different function. > > However, for the case of the inlined function the argument for > deleting lines is harder to make, indeed if we consider a function > inlined from another file compared to a function inlined from within > the same file then it is obvious that in the case where the inlined > callee is within the same file there will be no subfile switch, and > hence no end of sequence markers inserted, and as a consequence no > deleted line entries. > > It is tempting then to think that, when we switch subfiles as part of > an inlined function we would like to preserve line table entries where > possible. > > The problem is how to distinguish between the case of an inlined > function subfile switch, and a general inclusion subfile switch? > Though I'm sure we can solve this problem, I think it is worth > considering if this is even a problem worth solving. > > First, the act of deleting line table entries only occurs when entries > in the original debug information "pile up" and occur at the same > address, consider this imagined input line table: > > | Addr | File | Line | Stmt | > |------|------|------|------| > | 1 | 1 | 10 | Y | > | 2 | 2 | 100 | Y | > | 3 | 1 | 11 | Y | > > In this case no entries will be deleted, as every line table item > occurs at a separate address. Compare it to this: > > | Addr | File | Line | Stmt | > |------|------|------|------| > | 1 | 1 | 10 | Y | > | 1 | 2 | 100 | Y | > | 2 | 1 | 11 | Y | > > Here, the switch to subfile 2 will cause the line item from subfile > 1 (also at address 1) to be deleted. This kind of makes sense, the > debug is claiming the address 1 represents both file 1, line 10 and > file 2, line 100. If we stop at this address which line should GDB > report? If the same situation was imagined within a single subfile, > like this: > > | Addr | File | Line | Stmt | > |------|------|------|------| > | 1 | 1 | 10 | Y | > | 1 | 1 | 100 | Y | > | 2 | 1 | 11 | Y | > > GDB would report line 100 at address 1, and line 11 at address 2. By > deleting the line in the two subfile case we get the same behaviour, > but we protect against the empty line at the end of a subfile > problem. > > It is for this reason, that I think this commit should not be merged > with GDB. > > 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. Also the possibility of extending > GDB to handle GCC's broken debug information has been discussed. > > gdb/ChangeLog: > > * buildsym.c (buildsym_compunit::record_line): Extend header > comment. Add some static assertions. Handle different end of > sequence types. > * buildsym.h (struct buildsym_compunit) : New > constant. > : New constant. > * dwarf2/read.c (dwarf_finish_line): Add extra parameter, use this > to decide which end of sequence marker to send through as the line > number. > (lnp_state_machine::record_line): Pass extra parameter to > dwarf_finish_line. > * symtab.c (find_pc_sect_line): The previous line is better if it > was marked is-stmt, and the new possible best is not. > * symtab.h (struct linetable_entry) : Extend comment. > > gdb/testsuite/ChangeLog: > > * gdb.cp/step-and-next-inline.exp (do_test): Skip all tests in the > use_header case. > * gdb.dwarf2/dw2-inline-header-1.exp: New file. > * gdb.dwarf2/dw2-inline-header-2.exp: New file. > * gdb.dwarf2/dw2-inline-header-3.exp: New file. > * gdb.dwarf2/dw2-inline-header-lbls.c: New file. > * gdb.dwarf2/dw2-inline-header.c: New file. > * gdb.dwarf2/dw2-inline-header.h: New file. > > diff --git a/gdb/buildsym.c b/gdb/buildsym.c > index 33bf6523e90..37fec4f53b6 100644 > --- a/gdb/buildsym.c > +++ b/gdb/buildsym.c > @@ -663,7 +663,42 @@ 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. > + > + Pass the constant end_of_sequence for LINE when an end of sequence > + marker is encountered in the original debug information. If this case > + any previous line table entries already at this address will be deleted, > + these lines are by definition empty, and attempting to place a > + breakpoint at this address will result in a breakpoint being placed on > + whatever is next in the executable, which is never going to be the > + correct behaviour. > + > + Alternatively, pass the constant change_of_subfile for LINE to indicate > + that the original debug line table switched to a different subfile. > + This still results in an end of sequence marker being placed in GDB's > + internal line table, but in this case we don't delete previous line > + entries at this address. This case arises from two common situations, > + the most common is inlined functions, in this case the switching between > + subfiles occurs within a single function. If a real line entry and a > + subfile switch occur at the same address we don't want to delete the > + real line entry in this case as we end up loosing too much useful debug > + information. > + > + The other situation where a subfile switch is commonly seen is when one > + source file is included into another, in this case the original line > + table will include information for one subfile before switching to the > + second subfile. If the last line of the last function in the first > + subfile is at the same address as the subfile switch then it is possible > + that a breakpoint placed on this line would actually be placed in the > + subsequent function by mistake. > + > + We could improve on this second situation by entering all end of > + sequence markers here without deleting any line table entries, then > + cross check the line table with the list of function blocks, we would > + then delete any line table entries that occurred at an end of sequence > + marker that was also at the end of a function. Right now we don't do > + this, and live with the (small) risk of a breakpoint being misplaced; > + the benefit of preserving the extra line table entries is worth it. */ > > void > buildsym_compunit::record_line (struct subfile *subfile, int line, > @@ -671,6 +706,13 @@ buildsym_compunit::record_line (struct subfile *subfile, int line, > { > struct linetable_entry *e; > > + /* The END_OF_SEQUENCE must be 0 as the constant 0 is used when > + processing the line table as the magic end of sequence marker. The > + CHANGE_OF_SUBFILE marker must be less than 0 as any value greater than > + 0 is an actual line number. */ > + gdb_static_assert (buildsym_compunit::end_of_sequence == 0); > + gdb_static_assert (buildsym_compunit::change_of_subfile < 0); > + > /* Make sure line vector exists and is big enough. */ > if (!subfile->line_vector) > { > @@ -705,7 +747,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 == buildsym_compunit::end_of_sequence) > { > while (subfile->line_vector->nitems > 0) > { > @@ -715,8 +757,11 @@ buildsym_compunit::record_line (struct subfile *subfile, int line, > subfile->line_vector->nitems--; > } > } > + else if (line == buildsym_compunit::change_of_subfile) > + line = buildsym_compunit::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/buildsym.h b/gdb/buildsym.h > index c768a4c2dae..3e22d0b4494 100644 > --- a/gdb/buildsym.h > +++ b/gdb/buildsym.h > @@ -190,6 +190,14 @@ struct buildsym_compunit > void record_line (struct subfile *subfile, int line, CORE_ADDR pc, > bool is_stmt); > > + /* These two constants can be passed to RECORD_LINE as the value of LINE > + to indicate special events in the line table. END_OF_SEQUENCE marks > + an actual end of sequence marked in the original debug's line table, > + while CHANGE_OF_SUBFILE indicates an end marker due to switching > + between subfiles. */ > + static const int end_of_sequence = 0; > + static const int change_of_subfile = -1; > + > struct compunit_symtab *get_compunit_symtab () > { > return m_compunit_symtab; > diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c > index ec3844188ee..ed0f247b6a1 100644 > --- a/gdb/dwarf2/read.c > +++ b/gdb/dwarf2/read.c > @@ -20067,7 +20067,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; > @@ -20080,7 +20080,10 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile, > paddress (gdbarch, address)); > } > > - dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu); > + int lineno = (end_sequence > + ? buildsym_compunit::end_of_sequence > + : buildsym_compunit::change_of_subfile); > + dwarf_record_line_1 (gdbarch, subfile, lineno, address, true, cu); > } > > void > @@ -20113,7 +20116,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 5c4e282c024..f6ebae45b27 100644 > --- a/gdb/symtab.c > +++ b/gdb/symtab.c > @@ -3254,7 +3254,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 9972e8125ba..62bedb45de7 100644 > --- a/gdb/symtab.h > +++ b/gdb/symtab.h > @@ -1306,7 +1306,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. */ > 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 */