From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR04-DB3-obe.outbound.protection.outlook.com (mail-eopbgr60074.outbound.protection.outlook.com [40.107.6.74]) by sourceware.org (Postfix) with ESMTPS id 80F2C385843E for ; Thu, 31 Mar 2022 13:53:21 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 80F2C385843E Received: from AM6PR04CA0034.eurprd04.prod.outlook.com (2603:10a6:20b:92::47) by VI1PR0802MB2527.eurprd08.prod.outlook.com (2603:10a6:800:b0::13) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5102.17; Thu, 31 Mar 2022 13:53:14 +0000 Received: from VE1EUR03FT020.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:92:cafe::4a) by AM6PR04CA0034.outlook.office365.com (2603:10a6:20b:92::47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5123.20 via Frontend Transport; Thu, 31 Mar 2022 13:53:14 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by VE1EUR03FT020.mail.protection.outlook.com (10.152.18.242) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5123.19 via Frontend Transport; Thu, 31 Mar 2022 13:53:13 +0000 Received: ("Tessian outbound 78191104f1b7:v118"); Thu, 31 Mar 2022 13:53:13 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 35b59b17f6a4b4fe X-CR-MTA-TID: 64aa7808 Received: from f75374da104e.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 2D2A63B3-1D91-417A-A1E9-FBCB559E987D.1; Thu, 31 Mar 2022 13:53:06 +0000 Received: from EUR03-VE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id f75374da104e.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Thu, 31 Mar 2022 13:53:06 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ZGPn0EFWoe+yMTHwKNVGYbM9A7evtSozrPdtiKzdLcR2p/HNY377u396cixYoeRCzZB8KFKLEXi3nwV32x6xJK4O3pVbWNQTtpVqMiqUTQTlWaY2WXmPqXc0A1e3YT5aEOhkasMbRF/v6xXXeVcI5HVjGTTwdt8o4BaUG8VQwEwoJu6FIgyg2CKr1HYFqpGz8rEp54zXX7GnfAqINgMFvgyqNwrcCYP6vzhgRLbQYKUETtW+VER8AU92MtsRZH4V2gFOzbX6vGm0Jlz2OXmYFPukUsxquZ9Gti0kVB0tEyIdTg/gq3SocYx2KVhGibuIijDAt+CzA4s04Kik2kogGQ== 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=JQeIU6/iP1FpPbOrTYFadqVTp6og7GZwSbQ65Ldp0Ak=; b=MBH1H6SJBfsj5YZikliYfMpeMYQ0BMQa1+0WXyqvCMSqzHi+XjCaEXPFyupyRgM9NSJ3OwUarYIRKMG+0q3AlmZpKaKhRQecmR6lIoZCmYKIa1ksFaMfnOFjuklFoMoUL2R8NIDRvFz3249pzUEnf557mLILtnzRT2eCh0tbILqouUWtfmL2/FThuKXh5FmUoQRxjPs0lzfBXhpw6VApwe2+sy5EczlBKB7Re7OGBPdvfjF46CzKUz1zK2zwoEP32bf1i4/1Xq8Vvv5AZK4Q9yvApLsOsdFWZ5N+0z2iCt7Q2InKBUg0QXWwUPctPIOdo2Grnecz/evS/s+8j5ObMg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=sourceware.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=none (message not signed); arc=none Received: from AM6PR01CA0055.eurprd01.prod.exchangelabs.com (2603:10a6:20b:e0::32) by VI1PR08MB4525.eurprd08.prod.outlook.com (2603:10a6:803:101::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5123.21; Thu, 31 Mar 2022 13:53:03 +0000 Received: from VE1EUR03FT038.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:e0:cafe::51) by AM6PR01CA0055.outlook.office365.com (2603:10a6:20b:e0::32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5123.13 via Frontend Transport; Thu, 31 Mar 2022 13:53:03 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; Received: from nebula.arm.com (40.67.248.234) by VE1EUR03FT038.mail.protection.outlook.com (10.152.19.112) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.5123.19 via Frontend Transport; Thu, 31 Mar 2022 13:53:01 +0000 Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2308.27; Thu, 31 Mar 2022 13:53:01 +0000 Received: from e129171.cambridge.arm.com (10.2.80.38) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2308.27 via Frontend Transport; Thu, 31 Mar 2022 13:53:01 +0000 From: Luis Machado To: Subject: [PATCH, v2] Fix reverse stepping multiple contiguous PC ranges over the line table Date: Thu, 31 Mar 2022 14:52:46 +0100 Message-ID: <20220331135246.7913-1-luis.machado@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <7a429c919395db6ec4642803badca5dbb97bff66.camel@us.ibm.com> References: <7a429c919395db6ec4642803badca5dbb97bff66.camel@us.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-EOPAttributedMessage: 1 X-MS-Office365-Filtering-Correlation-Id: 8abdff4d-2654-4f8a-3d24-08da131dcd00 X-MS-TrafficTypeDiagnostic: VI1PR08MB4525:EE_|VE1EUR03FT020:EE_|VI1PR0802MB2527:EE_ X-Microsoft-Antispam-PRVS: x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: /N/XaG9RTQsIG2BOZKPmEu8eeiskdBU24b7ac7DvhTpi822gdpBonyKoSx2S8YCSN5WwSO651Hm/bT6GeUrK3vlxjRzUYEShnZ6km+OMrLwsuPa1rOH45dy6Qx+iwtSkohvPxHksYFnVUFEsZMmx+hulbw5+6CK5PmRHwwafU8SSE3bpDwGFZ7rdXhOAdZaa34PlsJaMNEQAmUMDoBI8m7bWDyu4mz5Gh21J6vfmF2zhVlcThi7hvIaLkGmsrLg6B7O4EDGTYZjLzYoihz+hBZua1nrc1C8Muw0jtvtpA6sZ4ZxaF6S6QDnCYRbNHHZT+Abms5MMtobjl4LYCU4ORl1zv8apxmzM9opTcldtqr6/zcdFPmzSNEdWsrGpzqn6JH34ICUF+ZCoe9kZaXsGRMCVTSOoCwJVQkoMnzEa73Oda+OSjGVqCIw1dqQfOBMMgAWFktaIM8wIi5m8qNfx3GZwGu1EE1xVD3fxXIvh8RU4YylO8/7vLdfx8BOexI5l0E6QD7imIyZNlVnPLmgCSvT9gWjFwCmMa+hMU7zJtEg0Ok6cAMIkNpl1tQ2XIgKwf+WTVEV3Htn6sMzvDOe46FG35v/FGegtRKGJ67fA+XIP085UTMAzzKHNAoEaPcqGk2Eptw/AhG6bSXGbhBbyjUpP6AkN8rI5XTNJXoOm+jSvRVvIajsqOJDnzbDbQLA7STjmoj/tK39ZJbrg1c0iYIyXJ5f0hmdJw3jxBvyf9bDAODddF9mVmoR/1vmeM5B45JRNqUErvUMVXt3lkw0ImNtNR31rZZWRjKZ/00qpYZE= X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:nebula.arm.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230001)(4636009)(40470700004)(36840700001)(46966006)(4326008)(8676002)(86362001)(26005)(186003)(1076003)(36860700001)(84970400001)(82310400004)(83380400001)(70206006)(70586007)(47076005)(316002)(426003)(336012)(44832011)(40460700003)(5660300002)(508600001)(356005)(6666004)(81166007)(36756003)(7696005)(2616005)(2906002)(6916009)(30864003)(8936002)(36900700001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR08MB4525 X-MS-Exchange-Transport-CrossTenantHeadersStripped: VE1EUR03FT020.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: a1f7602f-f3d8-41ec-62fc-08da131dc549 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: QHJ0UKPnCUuDR//oUIfHbAoXZB76MT9N74eu5F5JzHcFoIswCa7eixeh8gqTxi1kuq8sv08brOtl/dPmIH5bMA8Vd/Q9bYpTwpt93+aPH/xnnJgRdvrIDPp/laHRKO5lx8eLrdlgA/Tq45ypx9gdFJjp7Ttwxs6CE5CpZF/Z5FvxkfhU7SArbX7R7yRZjQqMiffICOdrd8fZnfEYIWgiZ8gIWcgkOKie0N+HTtwecdseOB1uGzh+z13cK2UUmU50J0KQjGI/nqhUaDoB0FSTAppTi3NDXRPBDU4zBE8+lo6/eMYwjf7dBkauNWhH3yNVf7vOhZefpuOaJ5NOL5bkeen+A05tpFP+O8PynddUMTIF0DQgRRNnmS8MrPZeNw9sz0hcg+bog5vB5XvVzqYcZoO1ygXRkO6T8wvgw/1J1X/SyCM0T57038gnINUE9AtKuNY8Gu9pRHxSpcwACLelJjDo9+1D4D22L2TIPWd16IbHC/nlj5dZQ64IMrPDfKrDfbQzKK/0zZDhFdPf32C3GotQIL1hHVeYns/Hv31Ku/QYIu7AME2XKyuHQjgxUsVR1EXFwfzA6VWT0F4P3aMYiZrAyHKYZ8hgeLFRfQjOb8n/c6nOVKEBxDnh08c0KoDzrVquDxgTRwz8nEWM0xRgTufk5ph15tI6h5T84iQEPybDGcwrzOIReXAe/x2i48IF9areYUmMb0wYc8d1GyFePzePLhk7Z+BZ9D2a4ZxCFABZiTjs0qNPO3MW2AndCGlPwxxk37G4ns1MMBtiimkzZQ== X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230001)(4636009)(40470700004)(46966006)(36840700001)(8936002)(81166007)(2906002)(84970400001)(426003)(2616005)(26005)(44832011)(36756003)(40460700003)(86362001)(336012)(186003)(1076003)(7696005)(36860700001)(70206006)(508600001)(83380400001)(6916009)(6666004)(8676002)(30864003)(5660300002)(82310400004)(4326008)(47076005)(70586007)(316002); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Mar 2022 13:53:13.9264 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8abdff4d-2654-4f8a-3d24-08da131dcd00 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: VE1EUR03FT020.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0802MB2527 X-Spam-Status: No, score=-12.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: Thu, 31 Mar 2022 13:53:25 -0000 v2: - Check if both the line and symtab match for a particular line table entry. -- When running GDB's testsuite on aarch64-linux/Ubuntu 20.04 (also spotted on the ppc backend), I noticed some failures in gdb.reverse/solib-precsave.exp and gdb.reverse/solib-reverse.exp. The failure happens around the following code: 38 b[1] = shr2(17); /* middle part two */ 40 b[0] = 6; b[1] = 9; /* generic statement, end part two */ 42 shr1 ("message 1\n"); /* shr1 one */ Normal execution: - step from line 38 will land on line 40. - step from line 40 will land on line 42. Reverse execution: - step from line 42 will land on line 40. - step from line 40 will land on line 40. - step from line 40 will land on line 38. The problem here is that line 40 contains two contiguous but distinct PC ranges in the line table, like so: Line 40 - [0x7ec ~ 0x7f4] Line 40 - [0x7f4 ~ 0x7fc] The two distinct ranges are generated because GCC started outputting source column information, which GDB doesn't take into account at the moment. When stepping forward from line 40, we skip both of these ranges and land on line 42. When stepping backward from line 42, we stop at the start PC of the second (or first, going backwards) range of line 40. This happens because we have this check in infrun.c:process_event_stop_test: /* When stepping backward, stop at beginning of line range (unless it's the function entry point, in which case keep going back to the call point). */ CORE_ADDR stop_pc = ecs->event_thread->stop_pc (); if (stop_pc == ecs->event_thread->control.step_range_start && stop_pc != ecs->stop_func_start && execution_direction == EXEC_REVERSE) end_stepping_range (ecs); else keep_going (ecs); Since we've reached ecs->event_thread->control.step_range_start, we stop stepping backwards. The right thing to do is to look for adjacent PC ranges for the same line, until we notice a line change. Then we take that as the start PC of the range. Another solution I thought about is to merge the contiguous ranges when we are reading the line tables. Though I'm not sure if we really want to process that data as opposed to keeping it as the compiler created, and then working around that. In any case, the following patch addresses this problem. I'm not particularly happy with how we go back in the ranges (using "pc - 1"). Feedback would be welcome. Validated on aarch64-linux/Ubuntu 20.04/18.04. Carl Love has verified that it does fix a similar issue on ppc. Ubuntu 18.04 doesn't actually run into these failures because the compiler doesn't generate distinct PC ranges for the same line. I see similar failures on x86_64 in the gdb.reverse tests (gdb.reverse/step-reverse.exp and gdb.reverse/step-reverse.exp). Those are also fixed by this patch, although Carl's testcase doesn't fail for x86_64. There seems to be a corner case where a line table has only one instruction, and while stepping that doesn't take the same path through infrun. I think it needs some more investigation. Therefore this is a tentative patch for now. Co-authored-by: Carl Love --- gdb/infrun.c | 51 +++++++- gdb/symtab.c | 49 ++++++++ gdb/symtab.h | 16 +++ gdb/testsuite/gdb.reverse/map-to-same-line.c | 30 +++++ .../gdb.reverse/map-to-same-line.exp | 114 ++++++++++++++++++ 5 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 gdb/testsuite/gdb.reverse/map-to-same-line.c create mode 100644 gdb/testsuite/gdb.reverse/map-to-same-line.exp diff --git a/gdb/infrun.c b/gdb/infrun.c index dbd82775595..cec55b0a5d7 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -6716,6 +6716,11 @@ process_event_stop_test (struct execution_control_state *ecs) through a function epilogue and therefore must detect when the current-frame changes in the middle of a line. */ + infrun_debug_printf + ("STEPPING RANGE [%s-%s]", + paddress (gdbarch, ecs->event_thread->control.step_range_start), + paddress (gdbarch, ecs->event_thread->control.step_range_end)); + if (pc_in_thread_step_range (ecs->event_thread->stop_pc (), ecs->event_thread) && (execution_direction != EXEC_REVERSE @@ -6723,7 +6728,7 @@ process_event_stop_test (struct execution_control_state *ecs) ecs->event_thread->control.step_frame_id))) { infrun_debug_printf - ("stepping inside range [%s-%s]", + ("STILL INSIDE range [%s-%s]", paddress (gdbarch, ecs->event_thread->control.step_range_start), paddress (gdbarch, ecs->event_thread->control.step_range_end)); @@ -6732,11 +6737,31 @@ process_event_stop_test (struct execution_control_state *ecs) have software watchpoints). */ ecs->event_thread->control.may_range_step = 1; + /* When we are stepping inside a particular line range, in reverse, + and we are sitting at the first address of that range, we need to + check if this address also shows up in another line range as the + end address. + + If so, we need to check what line such a step range points to. + If it points to the same line as the current step range, that + means we need to keep going in order to reach the first address + of the line range. We repeat this until we eventually get to the + first address of a particular line we're stepping through. */ + CORE_ADDR range_start = ecs->event_thread->control.step_range_start; + if (execution_direction == EXEC_REVERSE) + { + gdb::optional real_range_start + = find_line_range_start (ecs->event_thread->stop_pc ()); + + if (real_range_start.has_value ()) + range_start = *real_range_start; + } + /* When stepping backward, stop at beginning of line range (unless it's the function entry point, in which case keep going back to the call point). */ CORE_ADDR stop_pc = ecs->event_thread->stop_pc (); - if (stop_pc == ecs->event_thread->control.step_range_start + if (stop_pc == range_start && stop_pc != ecs->stop_func_start && execution_direction == EXEC_REVERSE) end_stepping_range (ecs); @@ -7237,6 +7262,28 @@ process_event_stop_test (struct execution_control_state *ecs) } } + CORE_ADDR range_start = ecs->event_thread->control.step_range_start; + infrun_debug_printf ("RANGE START is at %s", paddress (gdbarch, range_start)); + if (execution_direction == EXEC_REVERSE) + { + gdb::optional real_range_start + = find_line_range_start (ecs->event_thread->stop_pc ()); + + if (real_range_start.has_value ()) + { + range_start = *real_range_start; + infrun_debug_printf ("NEW RANGE START is at %s", paddress (gdbarch, range_start)); + } + + /* When stepping backward, stop at beginning of line range + (unless it's the function entry point, in which case + keep going back to the call point). */ + CORE_ADDR stop_pc = ecs->event_thread->stop_pc (); + if (stop_pc == range_start + && stop_pc != ecs->stop_func_start) + end_stepping_range (ecs); + } + /* We aren't done stepping. Optimize by setting the stepping range to the line. diff --git a/gdb/symtab.c b/gdb/symtab.c index 804b88284eb..99abf7bd2b7 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -3425,6 +3425,55 @@ find_pc_line (CORE_ADDR pc, int notcurrent) return sal; } +/* Compare two symtab_and_line entries. Return true if both have + the same line number and the same symtab pointer. That means we + are dealing with two entries from the same line and from the same + source file. + + Return false otherwise. */ + +static bool +sal_line_symtab_matches_p (const symtab_and_line &sal1, + const symtab_and_line &sal2) +{ + return (sal1.line == sal2.line && sal1.symtab == sal2.symtab); +} + +/* See symtah.h. */ + +gdb::optional +find_line_range_start (CORE_ADDR pc) +{ + struct symtab_and_line current_sal = find_pc_line (pc, 0); + + if (current_sal.line == 0) + return {}; + + struct symtab_and_line prev_sal = find_pc_line (current_sal.pc - 1, 0); + + /* If the previous entry is for a different line, that means we are already + at the entry with the start PC for this line. */ + if (!sal_line_symtab_matches_p (prev_sal, current_sal)) + return current_sal.pc; + + /* Otherwise, keep looking for entries for the same line but with + smaller PC's. */ + bool done = false; + CORE_ADDR prev_pc; + while (!done) + { + prev_pc = prev_sal.pc; + + prev_sal = find_pc_line (prev_pc - 1, 0); + + /* Did we notice a line change? If so, we are done with the search. */ + if (!sal_line_symtab_matches_p (prev_sal, current_sal)) + done = true; + } + + return prev_pc; +} + /* See symtab.h. */ struct symtab * diff --git a/gdb/symtab.h b/gdb/symtab.h index d12eee6e9d8..4d893a8a3b8 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -2149,6 +2149,22 @@ extern struct symtab_and_line find_pc_line (CORE_ADDR, int); extern struct symtab_and_line find_pc_sect_line (CORE_ADDR, struct obj_section *, int); +/* Given PC, and assuming it is part of a range of addresses that is part of a + line, go back through the linetable and find the starting PC of that + line. + + For example, suppose we have 3 PC ranges for line X: + + Line X - [0x0 - 0x8] + Line X - [0x8 - 0x10] + Line X - [0x10 - 0x18] + + If we call the function with PC == 0x14, we want to return 0x0, as that is + the starting PC of line X, and the ranges are contiguous. +*/ + +extern gdb::optional find_line_range_start (CORE_ADDR pc); + /* Wrapper around find_pc_line to just return the symtab. */ extern struct symtab *find_pc_line_symtab (CORE_ADDR); diff --git a/gdb/testsuite/gdb.reverse/map-to-same-line.c b/gdb/testsuite/gdb.reverse/map-to-same-line.c new file mode 100644 index 00000000000..d35838eccc9 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/map-to-same-line.c @@ -0,0 +1,30 @@ + + +/* The purpose of this test is to create a DWARF line table that says there + are two assignment statements on the same line. The expect test checks to + make sure gdb reverse steps over each statements individulally. The test + makes sure a single reverse step doesn't step over both assignment + statements in the line. The expect file generates the DWARF assembly + statements will create a line table that with j = 3 and k = 4 listed as + being on the same source code line even though they actually are on + different lines in this source code below. Have to put them on separate + lines to be able to identify them and add them to the line table. */ +int +main (){ /* TAG: main prologue */ + asm ("main_label: .globl main_label"); + asm ("loop_start: .globl loop_start"); + int i, j, k, l, m; + + asm ("i_assignment: .globl i_assignment"); + i = 1; /* TAG: assignment i */ + asm ("j_assignment: .globl j_assignment"); + j = 3; /* TAG: assignment j */ + asm ("k_assignment: .globl k_assignment"); + k = 4; /* TAG: assignment k */ + asm ("l_assignment: .globl l_assignment"); + l = 10; /* TAG: assignment l */ + asm ("m_assignment: .globl m_assignment"); + m = 11; /* TAG: assignment m */ + asm ("main_return: .globl main_return"); + return 0; /* TAG: end of main */ +} diff --git a/gdb/testsuite/gdb.reverse/map-to-same-line.exp b/gdb/testsuite/gdb.reverse/map-to-same-line.exp new file mode 100644 index 00000000000..da407b50e94 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/map-to-same-line.exp @@ -0,0 +1,114 @@ + +# The purpose of this test is to create a DWARF line table that says the +# two assignment statements are on the same line. The expect test checks +# to make sure gdb reverse steps over each statement individually, i.e. +# not over the line containing both assignments. */ + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +if {![dwarf2_support]} { + unsupported "dwarf2 support required for this test" + return 0 +} + +if [get_compiler_info] { + return -1 +} + +# The DWARF assembler requires the gcc compiler. +if {!$gcc_compiled} { + unsupported "gcc is required for this test" + return 0 +} + +standard_testfile .c .S + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return -1 +} + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + global srcdir subdir srcfile + declare_labels integer_label L + + # Find start address and length of program + lassign [function_range main [list ${srcdir}/${subdir}/$srcfile]] \ + main_start main_len + set main_end "$main_start + $main_len" + + cu {} { + compile_unit { + {language @DW_LANG_C} + {name map-to-same-line.c} + {stmt_list $L DW_FORM_sec_offset} + {low_pc 0 addr} + } { + subprogram { + {external 1 flag} + {name main} + {low_pc $main_start addr} + {high_pc $main_len DW_FORM_data4} + } + } + } + + lines {version 2 default_is_stmt 1} L { + include_dir "${srcdir}/${subdir}" + file_name "$srcfile" 1 + + # Generate the line table program with the assignments to j and k + # are listed on the same source line in the table. + program { + {DW_LNE_set_address $main_start} + {line [gdb_get_line_number "TAG: main prologue"]} + {DW_LNS_copy} + + {DW_LNE_set_address i_assignment} + {line [gdb_get_line_number "TAG: assignment i"]} + {DW_LNS_copy} + + {DW_LNE_set_address j_assignment} + {line [gdb_get_line_number "TAG: assignment j"]} + {DW_LNS_copy} + + {DW_LNE_set_address k_assignment} + {line [gdb_get_line_number "TAG: assignment j"]} + {DW_LNS_copy} + + {DW_LNE_set_address l_assignment} + {line [gdb_get_line_number "TAG: assignment l"]} + {DW_LNS_copy} + + {DW_LNE_set_address m_assignment} + {line [gdb_get_line_number "TAG: assignment m"]} + {DW_LNS_copy} + + {DW_LNE_end_sequence} + } + } +} + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {nodebug} ] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +if [supports_process_record] { + # Activate process record/replay + gdb_test_no_output "record" "turn on process record" +} + +set break_at_l [gdb_get_line_number "TAG: assignment l" ] + +gdb_test "tbreak $break_at_l" "Temporary breakpoint .*" "breakpoint l = 10" + +gdb_test "continue" "Temporary breakpoint .*" "run to l = 10" +# j = 3 and k = 4 are on the same line. The reverse step stops at j = 3 +gdb_test "reverse-step" ".* j = 3;.*" "reverse-step to j = 3" +gdb_test "reverse-step" ".* i = 1;.*" "reverse-step to i = 1" -- 2.25.1