From patchwork Thu Feb 1 15:21:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Toby Lloyd Davies X-Patchwork-Id: 85137 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D06A83857C6B for ; Thu, 1 Feb 2024 15:24:03 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wm1-x334.google.com (mail-wm1-x334.google.com [IPv6:2a00:1450:4864:20::334]) by sourceware.org (Postfix) with ESMTPS id 04BC038582A1 for ; Thu, 1 Feb 2024 15:23:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 04BC038582A1 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=undo.io Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=undo.io ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 04BC038582A1 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::334 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706801009; cv=none; b=OBDlgthSgvUpsZAqtSw/JuwC/Cvm17SZPxkWCyh+A2cdIpgx2GYX85NATz1G8+uvEiVLTg01KNZLH/Ssccsm8b9U+SRxi8z9DBQEsgjSTOrYtSFLcasKeVInxXQ5juB2Org7E794yqttC9NFNCgEpCEIYjnH1YqcxkpF+L9qIjU= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706801009; c=relaxed/simple; bh=L2nEKK5Pikr2phEYBySOJNzJ5zXkYd9FSOLM2JiQCLE=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=qwWEpOYUVIaC5F/kFe6KF28yguDBzE7kFkPEXwQNsDW2htGgzv7Z02w5GpqmpCaHLc+EjMBm7Tw5AMFLDhGxV5Uw/bBY9vcMbWzjCPmj5XuyBn/O3foT5btC/LnwNaP9T+ezrn/bv5MwscJ+2dWu2m5MKy/BNhBi5QKGmOQBdcM= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wm1-x334.google.com with SMTP id 5b1f17b1804b1-40eacb4bfa0so9160655e9.1 for ; Thu, 01 Feb 2024 07:23:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=undo.io; s=google2; t=1706801005; x=1707405805; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=iCbQAH6KmvTp0dJp+EEs9BHy2FfmMPgsrq6opq7dIGk=; b=VRQ/yRgcCQEPO5BJNW0muykF5dq2vA5ZqS7ZWrh7pVZRxMjVVQOU0RfZNozlOoDWfl RO86Yr3I4r1FRvvjQRpcjiFgKZHwUPpBJibLqLE9afg76CetR1W1JSVPmZ7vqieqVnDd aDSnTrGK6hJ5Mk7R2pYlY/KUas1Ki54l2eH9RTUITDaNydjiZcuPKU+kX0jc4vUi/dYt rP3dCKsuFX3GqlJg7N1yvX+KdywoOIvGnxDXIegrU/vU4FyushNVwjtKNrmkK6DFSUaw +Z44uyaIRr8SCTQqxyN2W2bnmua8lnOjsMkJ01y9goRST/DrWLXw0YhrV6itf5iRYsxR x7+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706801005; x=1707405805; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=iCbQAH6KmvTp0dJp+EEs9BHy2FfmMPgsrq6opq7dIGk=; b=NbNoBoCFHZ+Fxn6NmMBB6UvHiq8NLR6K3ekzuDHy8U2J9mCMD3XKsjw0yA7OHpIdZl VYMxLXUgSAyXOTZUpJBAtOrCt+UOwv/OMbXgLAL8wGcgzDQrAKBM1mnHp6p4tJe4YZKB oeGMScT+ZbkmoV1WlnseTHmG8+STEXhfH/hL66XvN8/lBpxFcYkpTe2QUX9M8lxo+Npw Z318nxxXXDB5hYLpKvIVth8GTVrWl+/tI6RxWLGUtN3p/q0b7TM52ExG/SrC5Eh1/Mq1 YsfbebarO8IUMGS52XWRWpMJsLmJmqJ1e+xnlVcCJkfWpgNLNzcce8piRf+lEXjSB7Xx mYpQ== X-Gm-Message-State: AOJu0Yy/TvpU5s2tSNP375KRxnPALdCMKrK3FEvyCTWZAxChr5DJQC5m EMTmra7czG6aGfxdGCMtF/m5BXjzJA2IqYDGz4wGVVXpppaZxGxLF0iZ1L7mM3jswW1kTZezdUr 8HrjUmK7kDEjVtUiyLM1f2OB7nPCbsQ36w97Vm3STwCvQcSClv3fFtV2Kh8MILrPCoHwrKTa5j8 BHNv7oqZ3ks6H926hX+TUdWLFA0UkcysxlLG8sOGcTgQ0= X-Google-Smtp-Source: AGHT+IFZwdDEItY+xK0ZYNABBsVnfPybl48e3bnDUX+MrfwtwvidzATPK4uqSIKfPTG/gzuONaeD+A== X-Received: by 2002:a05:600c:1c06:b0:40e:46b6:bc48 with SMTP id j6-20020a05600c1c0600b0040e46b6bc48mr2107016wms.41.1706801005286; Thu, 01 Feb 2024 07:23:25 -0800 (PST) Received: from redhawk-thinkpad.home (cfbb000029.b.cam.camfibre.uk. [185.219.110.154]) by smtp.gmail.com with ESMTPSA id r2-20020a05600c320200b0040ef04987e7sm4598093wmp.16.2024.02.01.07.23.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Feb 2024 07:23:25 -0800 (PST) From: Toby Lloyd Davies To: gdb-patches@sourceware.org Cc: Toby Lloyd Davies Subject: [PATCH 2/3] gdb: Don't stop at non-statement line after stepping into inline function Date: Thu, 1 Feb 2024 15:21:17 +0000 Message-Id: <20240201152118.598375-3-tlloyddavies@undo.io> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240201152118.598375-1-tlloyddavies@undo.io> References: <20240201152118.598375-1-tlloyddavies@undo.io> MIME-Version: 1.0 X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Generally when stepping we only want to stop at lines that mark the beginning of a statement i.e. have is_stmt set. However, when we stepped into an inline function we would always stop regardless of whether is_stmt was set on first line of the inline function. Fix this in infrun.c:process_event_stop_test by not immediately stopping when entering an inline function. Then code later in the function will decide whether to stop based on whether is_stmt is set on the line. Additionally, check if is_stmt is set on the line after stepping from an inline callsite in infcmd.c:prepare_one_step. This fixes the bug when the step starts directly at the inline function callsite. --- gdb/infcmd.c | 3 +- gdb/infrun.c | 32 ++-- .../gdb.dwarf2/dw2-inline-stepping-3.c | 50 ++++++ .../gdb.dwarf2/dw2-inline-stepping-3.exp | 153 ++++++++++++++++++ 4 files changed, 226 insertions(+), 12 deletions(-) create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c create mode 100644 gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 5e5f75021f2..22ab4dbebbc 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -964,7 +964,8 @@ prepare_one_step (thread_info *tp, struct step_command_fsm *sm) fn = sym->print_name (); if (sal.line == 0 - || !function_name_is_marked_for_skip (fn, sal)) + || ((inline_skipped_frames (tp) || sal.is_stmt) + && !function_name_is_marked_for_skip (fn, sal))) { sm->count--; return prepare_one_step (tp, sm); diff --git a/gdb/infrun.c b/gdb/infrun.c index a782c115cad..927e464e479 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -8104,10 +8104,10 @@ process_event_stop_test (struct execution_control_state *ecs) if (ecs->event_thread->control.step_over_calls == STEP_OVER_ALL || inline_frame_is_marked_for_skip (false, ecs->event_thread)) - keep_going (ecs); - else - end_stepping_range (ecs); - return; + { + keep_going (ecs); + return; + } } /* Look for "calls" to inlined functions, part two. If the inline @@ -8122,25 +8122,35 @@ process_event_stop_test (struct execution_control_state *ecs) if (ecs->event_thread->control.step_over_calls != STEP_OVER_ALL) { - /* For "step", we're going to stop. But if the call site - for this inlined function is on the same source line as - we were previously stepping, go down into the function - first. Otherwise stop at the call site. */ + /* For "step", if the call site for this inlined function is on the + same source line as we were previously stepping, go down into the + function first before deciding whether to stop. Otherwise stop at + the call site. */ if (*curr_frame_id == original_frame_id && call_sal.line == ecs->event_thread->current_line && call_sal.symtab == ecs->event_thread->current_symtab) { step_into_inline_frame (ecs->event_thread); + frame = get_current_frame (); if (inline_frame_is_marked_for_skip (false, ecs->event_thread)) { keep_going (ecs); return; } + else if (inline_skipped_frames (ecs->event_thread)) + { + end_stepping_range (ecs); + return; + } + /* We are no longer at an inline function callsite. + We use the checks further down to determine whether to stop. */ + } + else + { + end_stepping_range (ecs); + return; } - - end_stepping_range (ecs); - return; } else { diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c new file mode 100644 index 00000000000..3b6bc84fb05 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.c @@ -0,0 +1,50 @@ +/* Copyright 2019-2024 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 test relies on foo and bar being inlined into main. */ + +volatile int global_var; + +static inline int __attribute__ ((always_inline)) +foo () +{ + asm ("foo_label: .globl foo_label"); + global_var++; /* foo inc global_var*/ + asm ("foo_label2: .globl foo_label2"); + return global_var; /* foo return global_var */ +} /* foo end */ + +static inline int __attribute__ ((always_inline)) +bar () +{ + asm ("bar_label: .globl bar_label"); + global_var++; /* bar inc global_var*/ + asm ("bar_label2: .globl bar_label2"); + return global_var; /* bar return global_var */ +} /* bar end */ + +int +main () +{ /* main prologue */ + int ans; + asm ("main_label: .globl main_label"); + global_var = 0; /* main set global_var */ + asm ("main_label2: .globl main_label2"); + ans = foo (); /* main call foo */ + asm ("main_label3: .globl main_label3"); + asm ("nop"); ans = bar (); /* main call bar */ + asm ("main_label4: .globl main_label4"); + return ans; +} /* main end */ diff --git a/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp new file mode 100644 index 00000000000..ef864d943b3 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp @@ -0,0 +1,153 @@ +# Copyright 2019-2024 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 test checks that we stop at an inline callsite when returning +# from a non-inlined function. Specifically when the first line of the +# inline function does not have is_stmt set. +# +# Additionally, we check that when stepping into the inline function we +# step past this first line without is_stmt set. We check two cases. One +# where the inline callsite line contains no instructions (i.e. it +# begins at the same address that the inline function begins). This +# exercices the codepath in infcmd.c:prepare_one_step. The other is +# when the inline callsite line contains one instruction. This exercises +# the codepath in infrun.c:prepare_one_step. + +load_lib dwarf.exp + +# This test can only be run on targets which support DWARF-2 and use gas. +require dwarf2_support + +# The .c files use __attribute__. +require is_c_compiler_gcc + +standard_testfile .c .S + +set asm_file [standard_output_file $srcfile2] +Dwarf::assemble $asm_file { + global srcdir subdir srcfile srcfile2 + declare_labels ranges_label lines_label foo_prog bar_prog + + lassign [function_range main [list ${srcdir}/${subdir}/$srcfile]] \ + main_start main_len + set main_end "$main_start + $main_len" + + set foo_call_line [gdb_get_line_number "main call foo"] + set bar_call_line [gdb_get_line_number "main call bar"] + + cu {} { + compile_unit { + {language @DW_LANG_C} + {name dw2-inline-stepping-2.c} + {low_pc 0 addr} + {stmt_list ${lines_label} DW_FORM_sec_offset} + {ranges ${ranges_label} DW_FORM_sec_offset} + } { + bar_prog: subprogram { + {name bar} + {inline 3 data1} + } + foo_prog: subprogram { + {name foo} + {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 %$foo_prog} + {low_pc main_label2 addr} + {high_pc main_label3 addr} + {call_file 1 data1} + {call_line $foo_call_line data1} + } + inlined_subroutine { + {abstract_origin %$bar_prog} + {low_pc bar_label addr} + {high_pc main_label4 addr} + {call_file 1 data1} + {call_line $bar_call_line data1} + } + } + } + } + + lines {version 2} lines_label { + include_dir "${srcdir}/${subdir}" + file_name "$srcfile" 1 + + program { + + DW_LNE_set_address main_label + line [gdb_get_line_number "main set global_var"] + DW_LNS_copy + + DW_LNE_set_address main_label2 + DW_LNS_negate_stmt + line [gdb_get_line_number "foo inc global_var"] + DW_LNS_copy + DW_LNS_negate_stmt + + DW_LNE_set_address foo_label2 + line [gdb_get_line_number "foo return global_var"] + DW_LNS_copy + + DW_LNE_set_address main_label3 + line [gdb_get_line_number "main call bar"] + DW_LNS_copy + + DW_LNE_set_address bar_label + DW_LNS_negate_stmt + line [gdb_get_line_number "bar inc global_var"] + DW_LNS_copy + DW_LNS_negate_stmt + + DW_LNE_set_address bar_label2 + line [gdb_get_line_number "bar return global_var"] + DW_LNS_copy + + DW_LNE_set_address main_label4 + line [gdb_get_line_number "return ans"] + DW_LNS_copy + + DW_LNE_set_address $main_end + DW_LNE_end_sequence + } + } + + ranges {is_64 [is_64_target]} { + ranges_label: sequence { + range ${main_start} ${main_end} + } + } +} + +if { [prepare_for_testing "failed to prepare" ${testfile} \ + [list $srcfile $asm_file] {nodebug}] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +gdb_test "next" ".* main call foo.*" "step to foo callsite" +gdb_test "step" ".* foo return global_var.*" "step to foo inc global_var" + +gdb_test "next" ".*main call bar.*" "step to bar callsite" +gdb_test "step" ".* bar return global_var.*" "step to bar inc global_var"