From patchwork Thu Feb 1 15:43:25 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: 85151 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 6BCD9386480A for ; Thu, 1 Feb 2024 15:46:06 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 5EB45385E000 for ; Thu, 1 Feb 2024 15:45:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5EB45385E000 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 5EB45385E000 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::42e ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706802337; cv=none; b=eZ6asjtGmadta0Si88DV6ZqvnulKdW/6HY0SJWaoBFwuTu4VuFRL8qO0fb+J06XQGVm9oXpep8C1Eja76F6AYgGo+XrFkeYGNr3hE/be3Xc+pJi9q5o5ApNEwd6F85rQnVvsHQ3lhxl6umVaaEpAC1ujnVLgQWvoQlRxaY3hZHo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706802337; c=relaxed/simple; bh=Wj41wlfnR+VFZj/riVe1vogtrNF/Vo4OMLiqhm18/Mg=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=NvFpWLqa+x3Aqi4czeX8kLjqK6TFjtkls2Nbtw3HoOEUHO2fLwppV55A8ToOK2qintUu1qQWK0BTqXXTjVp/yxJ4gUxHGIPEVHBqXEmItYQICgD21/nR3Jf6gxS9iuRTbJ4pHD7GmDNfCPI1doaNrGHwriO+l+A4EwClGWQFvDQ= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wr1-x42e.google.com with SMTP id ffacd0b85a97d-33b13332ca7so653383f8f.2 for ; Thu, 01 Feb 2024 07:45:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=undo.io; s=google2; t=1706802332; x=1707407132; 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=zcp6Ih8JyoKt5+AHOxy90cPFf2T1EUFV0pMOGIpUWEQ=; b=Lzj9nyVVwttUlhH6Nx6guHUKU6Coc6Onll6yXjl4oxcfmZ8EYv9Fl7yR0XWbJOizyL si6ghtCBZsaRB1Tzx7Cm/tOfuD/aHzJszO/B3SK+RnGn86QihAGoRvVOfNsgggge1zFW xNn6OenZv+HbK0/fkd/WtQxq1qqKji/Kv1AAEEjdgoMefOdFNzQk1W6l2qLuJJEHAujC reEuFdl1wvkGwIc+erjJcBit5e5k3ykLr1UssBUstkuF8FNAjFBaFoIye8vfs37aYMRc I1B+qqA49nqtLkRQ25T4y6z2yS/jjdc0PQAKO7MvZFlVf7EpcGfgn2wwNsiHe0LvF2L4 7T1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706802332; x=1707407132; 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=zcp6Ih8JyoKt5+AHOxy90cPFf2T1EUFV0pMOGIpUWEQ=; b=mp+y+nbyUy4L79uKVZqM9l6iYojLoZtFhQA4b115kGHOYUR8I1gUUJZYtKJr0Xycfn he9S2cSOsP+20R/R+z6F1yYjz+c4KLXyKr3ke8H1yaZ+cGFemZcmoNlpMwR6oEDzsv0b CAupVMbdX3WyHx1XUOEmOOa7zrnrvyYNnL075qNJssBkzRVvmokdAXOZ1TGeJvl9RAvz 4+RP9RXLZdE0gMZ770V98NOMFKGCWMjo/4xCAAjhZ5PLPaj+BwUXWy2IaEijg/mfy/99 onnW0QGKEf6pIy+p0bVB3rVnel/e7b0QCet532NsiTrLD2pK0N1CJ7zDn7mAVWgBjcXq rZyA== X-Gm-Message-State: AOJu0YwBPiSsWhhD+SUcl9z1IiIXOeM+KElymwDzTgJXw5eTcpvFsq3G xzIuYGZnh8rrMk0pCMirdzNHgIx4IX17XBnU00l0uOFNgDps5OqXl+iyeVZSh1tbrj/E9otFVbU +vFSgETn9BwdEyIxeNl6bNn+8a9ilYy+fs62C1fdHYKrQpP7T+SzbrYm0dW9uHtjoH4ILm3kNl3 JDlzk6lnotKZfCMXEmzcqhXkS05SflM8lG+FHgfNp7BAM= X-Google-Smtp-Source: AGHT+IGnNL2WM0OuK7KQXXxHN3EB/YlRHC1FfM+6c30mU/u+QRXuw8VOG1y0mexLKqOMKtPaxQXLiA== X-Received: by 2002:adf:f110:0:b0:337:67e:a1ef with SMTP id r16-20020adff110000000b00337067ea1efmr1939912wro.7.1706802332071; Thu, 01 Feb 2024 07:45:32 -0800 (PST) Received: from redhawk-thinkpad.home (cfbb000029.b.cam.camfibre.uk. [185.219.110.154]) by smtp.gmail.com with ESMTPSA id x13-20020a5d54cd000000b0033b1c321070sm82607wrv.31.2024.02.01.07.45.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 01 Feb 2024 07:45:31 -0800 (PST) From: Toby Lloyd Davies To: gdb-patches@sourceware.org Cc: Toby Lloyd Davies Subject: [PATCH v2 2/3] gdb: Don't stop at non-statement line after stepping into inline function Date: Thu, 1 Feb 2024 15:43:25 +0000 Message-Id: <20240201154325.603608-1-tlloyddavies@undo.io> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240201152118.598375-3-tlloyddavies@undo.io> References: <20240201152118.598375-3-tlloyddavies@undo.io> MIME-Version: 1.0 X-Spam-Status: No, score=-12.2 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 | 149 ++++++++++++++++++ 4 files changed, 222 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..638c2635d5f --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-inline-stepping-3.exp @@ -0,0 +1,149 @@ +# 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 when stepping into an inline function we step past the +# first line if it does not have 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"