From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM12-BN8-obe.outbound.protection.outlook.com (mail-bn8nam12on2084.outbound.protection.outlook.com [40.107.237.84]) by sourceware.org (Postfix) with ESMTPS id 95E813857001 for ; Wed, 27 Jul 2022 13:11:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 95E813857001 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=IJTPaFOmiU3Mtb0u5yOK5qpyEW4TMnPZtOOpg4F5S64s8c8YeLo2wpBw6GxcowJa9BBVrxOm1bcYtKzekyYMBqA+fffBuH/l/pkJY0CPUkuBFKppmJ+CGfP9Ltut2VuDNuoHQH6wamf9yQspcRGpAnFgIWaqeTl9czluB8854O5he2aRysHPG8nHfMrMgNyoLsYwpbhqPa7aUFtqY9q7hwPYyW6D1dXbsV6ollqvlxtYTtbOLrLhYxHVGTyGT7Ubh31TNBcP8I9f+7nCdByrFJsdsFVDZU66B59a8M9hv3rpX/5fxVGYW80S2LVcQ1Gl4IvRRXHzNfNNiLuafXK2XA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=7MLqKMDNJ9nj/Kr6rOlWDWkAtbHuiF3UdI2R+Apz4zA=; b=S0g5+mCtWy2DRzgarJKu3MbFpAwfw/6OmDINvyAhncF1gy2SwIS4+vro/G0Ti6ZQQZMLAHZeRCCzvUhhruPeUSVOOsKuxjJ0oAuI0b1dB/UFF7mP1TwfcX6i9GOedqdLAifjuDiXrBATuAiQRo4rsKV61ZPjcpqPeo/f1Pb8ZmK5enUdjrdmQ4Go/Xt9jd8Gf8Q9xDxAN17mn1lLIE1gkTQqbccCnN8LRKSxB4KHb1GGHbrwexU5HmqO/MoBh+0WFchneHrjrfwBLLHfRUCcvpiaepKJuqUgOYO8D0kaBpzzYpKfl4Crf+S0iQaWasZDnTwPRg0fRkw+iorT25LH/w== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=amd.com; dmarc=pass action=none header.from=amd.com; dkim=pass header.d=amd.com; arc=none Received: from DM4PR12MB5745.namprd12.prod.outlook.com (2603:10b6:8:5c::7) by IA1PR12MB6628.namprd12.prod.outlook.com (2603:10b6:208:3a0::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5458.25; Wed, 27 Jul 2022 13:11:39 +0000 Received: from DM4PR12MB5745.namprd12.prod.outlook.com ([fe80::e985:70a5:ecab:6ac0]) by DM4PR12MB5745.namprd12.prod.outlook.com ([fe80::e985:70a5:ecab:6ac0%3]) with mapi id 15.20.5458.025; Wed, 27 Jul 2022 13:11:39 +0000 From: "Six, Lancelot" To: "gdb-patches@sourceware.org" CC: "lsix@lancelotsix.com" , "Six, Lancelot" Subject: [PING] [PATCH] gdb/linespec: Improve sliding breakpoints Thread-Topic: [PING] [PATCH] gdb/linespec: Improve sliding breakpoints Thread-Index: AdihujimXp88u0O5R9eriJrjydiJOA== Date: Wed, 27 Jul 2022 13:11:39 +0000 Message-ID: Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: msip_labels: MSIP_Label_d4243a53-6221-4f75-8154-e4b33a5707a1_Enabled=true; MSIP_Label_d4243a53-6221-4f75-8154-e4b33a5707a1_SetDate=2022-07-27T13:09:48Z; MSIP_Label_d4243a53-6221-4f75-8154-e4b33a5707a1_Method=Privileged; MSIP_Label_d4243a53-6221-4f75-8154-e4b33a5707a1_Name=Public-AIP 2.0; MSIP_Label_d4243a53-6221-4f75-8154-e4b33a5707a1_SiteId=3dd8961f-e488-4e60-8e11-a82d994e183d; MSIP_Label_d4243a53-6221-4f75-8154-e4b33a5707a1_ActionId=5b779cb7-9354-4276-bcbd-8055fe4814e2; MSIP_Label_d4243a53-6221-4f75-8154-e4b33a5707a1_ContentBits=1 msip_label_d4243a53-6221-4f75-8154-e4b33a5707a1_enabled: true msip_label_d4243a53-6221-4f75-8154-e4b33a5707a1_setdate: 2022-07-27T13:11:34Z msip_label_d4243a53-6221-4f75-8154-e4b33a5707a1_method: Privileged msip_label_d4243a53-6221-4f75-8154-e4b33a5707a1_name: Public-AIP 2.0 msip_label_d4243a53-6221-4f75-8154-e4b33a5707a1_siteid: 3dd8961f-e488-4e60-8e11-a82d994e183d msip_label_d4243a53-6221-4f75-8154-e4b33a5707a1_actionid: 2695f60f-54c2-4b46-be56-c8453ed0f384 msip_label_d4243a53-6221-4f75-8154-e4b33a5707a1_contentbits: 0 x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 2bfbe395-3563-4da2-a67e-08da6fd18aff x-ms-traffictypediagnostic: IA1PR12MB6628:EE_ x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: X5d9wBQPx+a8P9B54Kugmk/vBr4ozC8/VRnd3EPJAH6twlmQn/Upv0DH080lFz1i6PBFovtr3QiOp8ZuQMxoJytE6tFKXDh5xJetnW5IxR5/K4kl/pQaOxDf0FehQp50nYPIn2idS1kJa0jH6wwX/6CrEFBXs36gY0yu7UmFt/VSuU/FggrTUlHAX2XDblrbhynQctTLCSJcBL6gpz2GOu651cwRmtl4NQvJqNpM6PH1dIuwOXI2zbbK1qPwtcs7OhldKK6+yIrcHTtYDnZl8HN/qHj+2KfFjcDjkLUwOO0+XhRuTBc7v0tXDb4GLlKVZsvQUHJmSg+IUDiabKIKSQvRY5KYmoXiq9uBbtV+qR4IlRja5VnYyMqkcdL03/u8v9/s3mB9yrmjA+qrKtJOEcjlejC/upmjX9Y5FCPyxZlae+emEzc4p1xb8slg4AITViaGl/b8y77s1gv36G8yzmYMTObbJSIQ2wi1+jyPZPQbxjlcMcsHNZiuyX5akLCp/m3C/CsKPADMdF6rMBH2RAO113ZGv8k3nx7Qk7vDTJ8UOLZgagJ9D+6iN+q488+7s0UyYJsKg0uWu96L7kMxr5dtA89RnJ2avBO6uTVx7JcsD8dHeE00Gh0K8iT2SvUrvPgJxOfg6CXJv9Zqtwzd/hWxZjEK84hteYDvVyLeggA818JjCUy3Icz4z6SQiEPhbtu3UzCGTacbTniijQ2nvOKZIQ2wJKLJ1e3VqjOaJAj4MW3FWn6W6hxoKD7nEM51XjPmEmIkKpiuXATsrfgcIhp63Ow/nfJfUcLWmnolNZE42bUp23RD2Cjpc1/lH2QxaCgFU4n6/2lNU6j3Yb2Xb/csbmpyNOegqniuSeyy3UY= x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:DM4PR12MB5745.namprd12.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230016)(4636009)(136003)(396003)(366004)(39860400002)(376002)(346002)(26005)(6506007)(6916009)(316002)(54906003)(122000001)(33656002)(2906002)(38100700002)(83380400001)(8936002)(478600001)(76116006)(5660300002)(30864003)(186003)(55016003)(8676002)(7696005)(41300700001)(71200400001)(66446008)(66476007)(4326008)(52536014)(66946007)(66556008)(38070700005)(9686003)(64756008)(53546011)(86362001)(966005)(2004002)(579004); DIR:OUT; SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?jNU4yafX8JxW3AliVTKVJ28YfQ862YloQFU7alNX8ap/DnHV0bxZE8RWcI6x?= =?us-ascii?Q?dpqbq/PsXRHfBYJpHluMNVuF9Y5GU0sYISyl0E9qZN04tAp9acQlJKnWvvgP?= =?us-ascii?Q?7MEMnkYOyvmAe+gb91P18Y1cK88/VgqGv86K2jdzfRb/bdqcjNL/A+EU0J5W?= =?us-ascii?Q?BAAidi1JAZ1bfLQg2aT/zwjC0nlBdwnpu7tWM1gZHxPewo5VY3C+IqIcGS01?= =?us-ascii?Q?iG4uNqdtkXahLK3eXORdjPP7e/jtfhLHouQcOysaQQR0MB0+Ru5N9TWI6RRp?= =?us-ascii?Q?EG1AlgpplYVY8PNe8tTeeXmmuQyr6VIjc7JVvd1rk3k4+MCP5FT5EwHkJx1Z?= =?us-ascii?Q?fwG9A3UyAdamTm7ovT2hPY6Nd1e/GThgiQMFW+FXybP4x+Sgk1yEHKkkb+Dd?= =?us-ascii?Q?/2TW95HfDthSwDFPcS44ghOC6v6A2d+KdNIVqh6dbUIRgNjTA+EZ0mBP1BoF?= =?us-ascii?Q?9q2HqRt7VQdDgBJYoFx35MQE5Mh91rYd0HPbJTMXsPWJiFiw6n/NhSeeqGtU?= =?us-ascii?Q?6atIAmH6/vEKEZtD0mR76RtfUTAD4IpL25KbKwQR7SdxmwIy/65V8ElwIHqz?= =?us-ascii?Q?g9vEopTtDoYH/pZhmK7OpqHeEZHas6rUia8/RA17dI8ONqeQP3Sqy0hjamhk?= =?us-ascii?Q?eTaBr5pPaDPW3764tNFgRBOXCJQnLnXuDtoN9+JxJeh18biypmBZRbQzKp5f?= =?us-ascii?Q?tBNUTxqddn9Kha6RwgZ1xZ9Uum8reFK9DrHUMp42jKBW+vjHsFmklIPMKROM?= =?us-ascii?Q?tCvyve/yCwtoTn9J/I+UNdOnNUjjEUug0COiI+NIcSNTMGmEtrjUCy72jVu3?= =?us-ascii?Q?922iPmcxwaxm3+/4ncodC22JRWQlcM2KpugrwFnnocc6FXqZkO6ckvjFZu/p?= =?us-ascii?Q?gU+G+5PUa3w3aSbQkX7cnaLqBEAlA4Zi2AzVam+yeMUybrfEHcr0Ae4UViKy?= =?us-ascii?Q?pjK1yKlLNrf5shODM8IPsLzTFe9ERIVpeizl1EKM5CrEXyJ7PJGtypf6XVB9?= =?us-ascii?Q?HpADqAn2r0MZYnq9Nt7XCNOYeq2YRTgep1Nhiqid1zqWaQRKKycFLFYsLOrC?= =?us-ascii?Q?8NugSx/tEEjGXpJM88KPP/VKF4r5Am2/0uIWMna6hNAYaKjqb0UH6MqDcolD?= =?us-ascii?Q?xAUCVOJiUsmeNbiyJ/ptyOzF9e45dXi0xDFMOsEnoc1lv2Qq1Lmrs8m1YDPd?= =?us-ascii?Q?HMH7FCqUIyZFbpZIJ5pRDd4mhewUqedrSexIqEVK27H4vNT0qWKjzyug9AF6?= =?us-ascii?Q?IGzVGJEGT8is63Ow2fpZagJgFJUB/3w3NS2l5aAQzjm+fXtWEnkjtRMeDHPt?= =?us-ascii?Q?/ZwfI8vT0D3LOvM4iez/g68eO6ccxWk5L67UVjkrtex4f1M9iGOopfc+6osW?= =?us-ascii?Q?uNIi+5sF2v/ZA7QVjzw9knL3ZDFHHqZapKq8bI2eYIU5sUR/BkDaqpzThlE5?= =?us-ascii?Q?f2R7cVd44rrE0Pgbtl3n/pkHMrc6DEFWICvKwC79NwgqnEjMl35oQHMR2+E1?= =?us-ascii?Q?yBUQHlv5VRlGBWg/lw4Rwf7UY+g7+PBhrtYecM5SdzQ5T8kMlN3IzMNd+ray?= =?us-ascii?Q?r3DOoEwT7ge2LSD/p0A=3D?= Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM4PR12MB5745.namprd12.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2bfbe395-3563-4da2-a67e-08da6fd18aff X-MS-Exchange-CrossTenant-originalarrivaltime: 27 Jul 2022 13:11:39.7048 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: AjxcKPnZ+kaNqjgHeRKnFLTPQaUvnYNW9wzulu9kMn6Dht2bENVaNlrNEmt+g1FxNfW5J0yKGHyKG33OuosW7Q== X-MS-Exchange-Transport-CrossTenantHeadersStamped: IA1PR12MB6628 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) 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, 27 Jul 2022 13:11:46 -0000 [Public] Hi I was wondering if anyone has comments and or opinions about the change pro= posed in this patch. Best, Lancelot. > -----Original Message----- > From: Six, Lancelot > Sent: 17 June 2022 17:08 > To: gdb-patches@sourceware.org > Cc: lsix@lancelotsix.com; Six, Lancelot > Subject: [PATCH] gdb/linespec: Improve sliding breakpoints >=20 > Hi, >=20 > Here is proposition to slightly update the breakpoint sliding algorithm > in GDB. >=20 > This patch must be applied on top of > https://sourceware.org/pipermail/gdb-patches/2022-April/187686.html > which was submitted by Simon Marchi a couple of months. This needs > small updates as the BLOCK_ENTRY_PC and SYMBOL_BLOCK_VALUE are no > longer used. As a consequence >=20 > BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) >=20 > should be replaced with >=20 > sym->value_block ()->entry_pc () >=20 > This patch have been regression tested on x86_64-Linux. All comments > and feedbacks are welcome. >=20 > Best, > Lancelot. >=20 > --- >=20 > The algorithm used to place a breakpoint by line approximately goes as > follow: >=20 > - Look for all the PCs which maps directly to the desired line > - If any PC is found, place a breakpoint at each found PC. > - If no PC maps to the desired line: > - Search for the lower line number in the line table which is higher > than the desired line, and has some object code associated to it. > - List all PCs which maps to this line number. > - Place a breakpoint at each PC in the list above. >=20 > There are situations where this heuristic is not sufficient. If we > consider the following c++ code: >=20 > 12 template > 13 T func (T a, T b) > 14 { > 15 /* Break here. */ > 16 if constexpr (std::is_integral_t) > 17 return a; > 18 else > 19 return b; > 20 } >=20 > Given the current algorithm, if the user tries to set a breakpoint at > line 15, here is what happens: >=20 > - Search PCs mapping to L15, there is none ; > - Search for the first line number above L16 with code, this is L17 ; > - List all PCs mapping to L17 and a breakpoints at insert a breakpoint at > each ; >=20 > Now lets suppose that this templated function has been instantiated both > for an integral type (int) and non-integral type (float). If we follow > the algorithm, no breakpoint will ever be inserted in func, > while there will be a breakpoint in func. >=20 > I came across a less obvious variation of this case where an inlined > function had different optimization opportunities for different instances= . > As a consequence, some instances had the first actual line of code > different than the other, making the breakpoint be missed and the user > confused. To add to the confusion, the instances which have code mapped > to the lowest line above the user specified linespec only appeared in a > shared library conditionally loaded, making the breakpoint stop depend on > whether or not the said shared library was loaded or not. >=20 > This patch is a proposition to adapt the algorithm in order to cover the > scenario exposed above. To do so, this patch ends up scanning > independently for the best candidate in the various blocks composing > the line table structures (a block being a succession of > linetable_entries terminated by an entry with line =3D=3D 0). >=20 > The line table for the example program above looks something like: >=20 > (gdb) maintenance info line-table missed > symtab: /[...]/missed_pb.cc ((struct symtab *) 0x6210000f0500) > linetable: ((struct linetable *) 0x6210001a1220): > INDEX LINE ADDRESS IS-STMT PROLOGUE-END > ... > 17 END 0x00000000000011d3 Y > 18 13 0x00000000000011d3 Y <-- func > 19 19 0x00000000000011e5 Y > 20 20 0x00000000000011ea Y > 21 END 0x00000000000011ec Y > 22 13 0x00000000000011ec Y <-- func > 23 17 0x00000000000011fa Y > 24 20 0x00000000000011fd Y > 25 END 0x00000000000011ff Y >=20 > The first block listed (starting at 0x11d3) is func, and the > second starting at 0x11ec is func. >=20 > The proposed algorithm analyzes each block independently. The first step > is to decide if a block contains the line the user is interested in (a.k.= a > the target). In our example, this is L15. A block is considered to matc= h > if it contains at least one instruction mapped to a line before the targe= t > and at least one instruction mapped to a line after the target. In other > words this means that will select all blocks where: >=20 > - there is at least one instruction mapped to a line L such as L <=3D tar= get > - there is at least one instruction mapped to a line M such as M >=3D tar= get >=20 > For each block which satisfies this condition, we select the lowest line > number above our target, and select all instructions mapping to this line > number (there might be multiple). In our example the func block > satisfies the condition (we have line 13 and 19), so we insert breakpoint= s > at the PCs mapped to L19. Similarly, the func block is selected > (thanks to L13 and L17), and we insert breakpoints at all PCs mapped to > L17. >=20 > The core of this heuristic is implemented in find_best_le_for_symtab_line= . >=20 > There are however some cases which are still problematic, where the > first line after the target is the first line of the block we are > looking for. In such situation the algorithm would find nothing where > we would want to select 0x11d3 and 0x11ec (both mapping to L13). In > order to solve this, the algorithm first looks for the lowest line > number following the user specified target as this is done before this > patch (here the first line with associated code following L12 which is > L13). Once this is figured out, this new target (L13) is passed to the > algorithm above (find_best_le_for_symtab_line). >=20 > This is safe to do because we know that there is no line between the user > target (included) and this new target. Therefore, whatever > find_best_le_for_symtab_line returns, it must map to lines numbers above > (inclusive) the new target. >=20 > Finally, the testsuite showed an interesting regression. Let's suppose > we have: >=20 > 1 struct Foo { Foo () {} }; > 2 Foo f1; > 3 void bar () > 4 { > 5 /* break here. */ > 6 do_something (); > 7 } > 8 Foo f2; >=20 > Inspecting the linetable, we have a code block containing L2 and L8 (so > over line 5). If a user was to insert a breakpoint somewhere in L5, the > algorithm shown above would also insert a breakpoint at L8. To solve > this, this patch uses the fact that L2 and L8 are, from dwarf's > perspective in a artificial block which corresponds to the static > initialization. So if among multiple candidates, some are part of a > virtual function and some are not, we only keep the ones in the non > virtual function. >=20 > This proposed new algorithm will not solve all possible cases. For > example, if the func function is inlined multiple times in the same block > for different template parameters, the lookup will process all of those a= s > part of the same scope. Solving such situation would require heavier > works. I think that this change, while not covering every scenarios is > still a step in the right direction. >=20 > All feedbacks and thoughts are welcome. >=20 > Regression tested on x86_64 GNU/Linux. >=20 > Change-Id: I8291f9e1a3522934a0f418dfc565cebb86cff730 > --- > gdb/linespec.c | 93 ++++++++++++++++++- > gdb/symtab.c | 45 +++++++++ > gdb/symtab.h | 14 +++ > .../gdb.linespec/breakpoint-sliding.cc | 70 ++++++++++++++ > .../gdb.linespec/breakpoint-sliding.exp | 82 ++++++++++++++++ > 5 files changed, 301 insertions(+), 3 deletions(-) > create mode 100644 gdb/testsuite/gdb.linespec/breakpoint-sliding.cc > create mode 100644 gdb/testsuite/gdb.linespec/breakpoint-sliding.exp >=20 > diff --git a/gdb/linespec.c b/gdb/linespec.c > index da9e35c5035..1e8679cd027 100644 > --- a/gdb/linespec.c > +++ b/gdb/linespec.c > @@ -2092,9 +2092,42 @@ create_sals_line_offset (struct linespec_state > *self, > if (intermediate_results.empty () && best_entry !=3D NULL) > { > was_exact =3D false; > - intermediate_results =3D decode_digits_ordinary (self, ls, > - best_entry->line, > - &best_entry); > + /* We did not find an exact match for the line we are looking for. > + As a consequence, we are now looking for the next best line. > + However, the next best line does not have to be the same across > + the entire program. If we consider the following code: > + > + 12 template > + 13 T select (T a, T b) > + 14 { > + 15 // Break here. > + 16 if constexpr (std::is_integral_t) > + 17 return a; > + 18 else > + 19 return b; > + 20 } > + > + For a function like the above, the next best line is L17 if T is > + an integral type, but should be L19 if T is not. As a > + consequence we try to search for the next best line independently > + in each code block (a code block being a contiguous section of a > + line table terminated by an entry with line =3D=3D 0). */ > + for (const auto &elt : ls->file_symtabs) > + { > + program_space *pspace =3D elt->compunit ()->objfile ()->pspace; > + for (const linetable_entry *le > + : find_best_le_for_symtab_line (elt->linetable (), > + best_entry->line)) > + { > + symtab_and_line sal; > + sal.pspace =3D pspace; > + sal.symtab =3D elt; > + sal.line =3D le->line; > + sal.explicit_line =3D true; > + sal.pc =3D le->pc; > + intermediate_results.push_back (std::move (sal)); > + } > + } > } >=20 > /* For optimized code, the compiler can scatter one source line > @@ -2110,6 +2143,25 @@ create_sals_line_offset (struct linespec_state > *self, > gdb::def_vector filter (intermediate_results.size ()); > gdb::def_vector blocks (intermediate_results.size (= )); >=20 > + /* Artificial code blocks can produce false positives. Consider > + > + 1 struct Foo { Foo () {} }; > + 2 Foo f1; > + 3 void bar () > + 4 { > + 5 // break here. > + 6 do_something (); > + 7 } > + 8 Foo f2; > + > + In this example, if the user asked for a breakpoint in L5, the above > + algorithm will select L6 and L8. L6 is selected because the we have > + an artificial block (marked by DW_AT_artificial) generated to cover > + the static initializations and this block covers code from line 2 to > + line 8. To avoid this false positive, reject candidates in artificial > + blocks if we also have candidates in non artificial blocks. */ > + bool any_nonartificial =3D false; > + > for (i =3D 0; i < intermediate_results.size (); ++i) > { > set_current_program_space (intermediate_results[i].pspace); > @@ -2117,6 +2169,13 @@ create_sals_line_offset (struct linespec_state > *self, > filter[i] =3D 1; > blocks[i] =3D block_for_pc_sect (intermediate_results[i].pc, > intermediate_results[i].section); > + > + if (!any_nonartificial && blocks[i] !=3D nullptr) > + { > + struct symbol *func =3D block_containing_function (blocks[i]); > + any_nonartificial > + =3D (func !=3D nullptr && !func->is_artificial ()); > + } > } >=20 > for (i =3D 0; i < intermediate_results.size (); ++i) > @@ -2171,6 +2230,34 @@ create_sals_line_offset (struct linespec_state > *self, > && val.line < sym->line ()) > continue; >=20 > + /* If we did not find an exact match, the above heuristic might > + find some false positives. > + > + Lets consider (with Foo having a non trivial ctor): > + > + 9 struct Foo { Foo () {} }; > + 10 Foo f1; > + 11 int bar () > + 12 { > + 13 // Break here. > + 14 return 42; > + 15 } > + 16 Foo f2; > + > + When the user tries to insert a breakpoint it L13, the > + algorithm sees a code path from L10 to L16 (in static > + initialization), and will consider L16 as a candidate. > + However the user clearly intended to break in bar. > Therefore, > + if we see that there is at least 1 breakpoint in a non > + artificial function (bar), ignore the hit in the static > + initialization. > + */ > + if (!was_exact > + && any_nonartificial > + && sym !=3D nullptr > + && sym->is_artificial ()) > + continue; > + > if (self->funfirstline) > skip_prologue_sal (sal); >=20 > diff --git a/gdb/symtab.c b/gdb/symtab.c > index 03aa2a96b87..1b03e6fce8e 100644 > --- a/gdb/symtab.c > +++ b/gdb/symtab.c > @@ -3541,6 +3541,51 @@ find_pcs_for_symtab_line (struct symtab > *symtab, int line, > return result; > } >=20 > +/* See symtab.h. */ > + > +std::vector > +find_best_le_for_symtab_line (struct linetable *lt, int line) > +{ > + std::vector res; > + > + if (lt =3D=3D nullptr || line < 0) > + return res; > + > + /* Tells if in the current block we found at least one PC mapping to a= line > + before LINE. */ > + bool found_preceding =3D false; > + const int nitems =3D lt->nitems; > + std::vector best_candidates; > + > + for (int i =3D 0; i < nitems; ++i) > + { > + struct linetable_entry &item =3D lt->item[i]; > + found_preceding > + =3D found_preceding || (item.line > 0 && item.line <=3D line); > + > + if (item.is_stmt && item.line >=3D line > + && (best_candidates.empty () > + || item.line <=3D best_candidates.front ()->line)) > + { > + if (!best_candidates.empty () > + && item.line < best_candidates.front ()->line) > + best_candidates.clear (); > + best_candidates.push_back (&item); > + } > + else if (item.line =3D=3D 0) > + { > + if (found_preceding) > + res.insert (res.end (), best_candidates.begin (), > + best_candidates.end ()); > + > + found_preceding =3D false; > + best_candidates.clear (); > + } > + } > + > + return res; > +} > + >=20 >=20 >=20 > /* Set the PC value for a given source file and line number and return t= rue. > Returns false for invalid line number (and sets the PC to 0). > diff --git a/gdb/symtab.h b/gdb/symtab.h > index ac902a4cbbe..94bea02cb43 100644 > --- a/gdb/symtab.h > +++ b/gdb/symtab.h > @@ -2624,6 +2624,20 @@ void iterate_over_symtabs (const char *name, > std::vector find_pcs_for_symtab_line > (struct symtab *symtab, int line, struct linetable_entry **best_entr= y); >=20 > +/* Given a linetable, look for entries which can map to line LINE. > + > + The result is the set of entries which: > + 1) Are part of a block (i.e. a sequence of entries terminated by an e= ntry > + with line =3D=3D 0) containing at least one statement entry with l= ine above > + or equal to LINE, and at least one statement entry with line below= or > + equal to LINE. > + 2) Are statement entries (is_stmt =3D=3D 1) > + 3) Have line equal to the lowest statement line number greater or equ= al to > + LINE within the block they are part of. */ > + > +std::vector find_best_le_for_symtab_line > + (struct linetable *lt, int line); > + > /* Prototype for callbacks for LA_ITERATE_OVER_SYMBOLS. The callback > is called once per matching symbol SYM. The callback should return > true to indicate that LA_ITERATE_OVER_SYMBOLS should continue > diff --git a/gdb/testsuite/gdb.linespec/breakpoint-sliding.cc > b/gdb/testsuite/gdb.linespec/breakpoint-sliding.cc > new file mode 100644 > index 00000000000..3ae6b563cdf > --- /dev/null > +++ b/gdb/testsuite/gdb.linespec/breakpoint-sliding.cc > @@ -0,0 +1,70 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright (C) 2022 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 .= */ > + > +#if __cplusplus >=3D 201703L > +#include > + > +template > +T > +foo (T a, T b) > +{ > + T ret; > + /* In foo break here. */ > + if constexpr (std::is_integral_v) > + ret =3D a; /* break in foo. */ > + else > + ret =3D b; /* break in foo. */ > + > + return ret; > +} > + > +struct NonIntegral > +{ > + int m; > +}; > + > +#endif > + > +struct St > +{ > + St () > + { /* Empty. */ } > +}; > + > +St st1; > + > +static int > +between_static_init () > +{ > + /* between_static_init break here. */ > + return 42; /* break in between_static_init. */ > +} > + > +St st2; > + > +int main () > +{ > + > +#if __cplusplus >=3D 201703L > + foo (1, 2); > + foo ({ 1 }, { 2 }); > +#endif > + > + between_static_init (); > + > + return 0; > +} > diff --git a/gdb/testsuite/gdb.linespec/breakpoint-sliding.exp > b/gdb/testsuite/gdb.linespec/breakpoint-sliding.exp > new file mode 100644 > index 00000000000..9b79c419e9b > --- /dev/null > +++ b/gdb/testsuite/gdb.linespec/breakpoint-sliding.exp > @@ -0,0 +1,82 @@ > +# Copyright (C) 2022 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 . > + > +# This testcase exercises breakpoint sliding when the user tries to set > +# a breakpoint at a line number which has no code associated to it. GDB > +# should then place breakpoint at the first line following the one given > +# by the user in each code block composing the program space, given that > +# the code block "covers" the line asked by the user. > + > +if { [skip_cplus_tests] } { > + return -1 > +} > + > +standard_testfile .cc > + > +# Part of the test require c++17. If the used compiler does not support > +# it, fallback only doing part of the tests. > +set skip_cpp17 0 > + > +if {[prepare_for_testing "failed to prepare with c++17" $testfile \ > + $srcfile {debug c++ additional_flags=3D-std=3Dc++17}]} { > + set skip_cpp17 1 > + if {[prepare_for_testing "failed to prepare" $testfile $srcfile \ > + {debug c++}]} { > + return -1 > + } > +} > + > +proc_with_prefix test_sliding_per_block {} { > + if {$::skip_cpp17} { > + return > + } > + > + set loc [gdb_get_line_number "In foo break here."] > + gdb_test "break $loc" \ > + "Breakpoint $::decimal.* \\(2 locations\\)" \ > + "slide to if constexpr" > + > + set loc_in_int_instance [gdb_get_line_number "break in foo"] > + set loc_in_struct_instance [gdb_get_line_number "break in > foo"] > + set seen_int_pb 0 > + set seen_struct_bp 0 > + gdb_test_multiple "info breakpoint" "info breakpoint" { > + -re "in foo\\(int, int\\) at > \[^\n\r\]*$::srcfile:$loc_in_int_instance" { > + set seen_int_pb 1 > + verbose -log "found int" > + exp_continue > + } > + -re "in foo\\(NonIntegral, NonIntegral\\) at > \[^\n\r\]*$::srcfile:$loc_in_struct_instance" { > + set seen_struct_bp 1 > + verbose -log "found struct" > + exp_continue > + } > + -re -wrap "" { > + gdb_assert {$seen_int_pb && $seen_struct_bp} $gdb_test_name > + } > + } > +} > + > +proc_with_prefix test_ignore_artificial_block {} { > + set loc [gdb_get_line_number "between_static_init break here"] > + set expected_loc [gdb_get_line_number "break in between_static_init.= "] > + gdb_test "break $loc" \ > + "Breakpoint $::decimal at $::hex: file .*/$::srcfile, line > $expected_loc\\." \ > + "ignore static block" > +} > + > +clean_restart $::binfile > +test_sliding_per_block > +test_ignore_artificial_block >=20 > base-commit: 5fb28d2607a8325559b44a5dc0c8760236c81218 > prerequisite-patch-id: 695c74160156ff2c66b3a88462be22a36c32f141 > -- > 2.25.1