From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) by sourceware.org (Postfix) with ESMTPS id 803573858D32 for ; Mon, 27 Feb 2023 16:09:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 803573858D32 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=us.ibm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=us.ibm.com Received: from pps.filterd (m0098409.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 31REZt5X032202; Mon, 27 Feb 2023 16:09:30 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=message-id : subject : from : to : cc : date : in-reply-to : references : content-type : content-transfer-encoding : mime-version; s=pp1; bh=4vk1DLVaLLYJJbLNq8Wei5/lhg4SNHgWQbqMlGvRVHI=; b=OZYGIJ2B0vg9u1e5iZfCxQTQUHeGM/JmH2CWt6hQlnx+F4+TlyfZDnfoAFS4Xk/nIizZ sqzxunZLlTi+ZoUFvi972497FxK6NaqBQDq54JeTMBL7QHVWpcifiL4LHf1WCrkNjvKv DPWyNPFzlppZ2rcQvA2klWnB3s2RxEGbqRd0e6mHOvB/S2dLCgO3o96kaXSHSNZ1mq0+ pwiDO58u3zAh2xZb+Jqc8Cr1DnOKeMz5Epuc0BlFypw9s6VVj1D3I0dFD+lGNupKALet QMuNV5ztayuZtR48aI+I3TTLj1W786uI/f4pWDVlICXfyk+AklbXJoQ4NTVWJFz0We+d IA== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3p0vk4p6f1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 27 Feb 2023 16:09:30 +0000 Received: from m0098409.ppops.net (m0098409.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 31RCm4ZG010456; Mon, 27 Feb 2023 16:09:29 GMT Received: from ppma05wdc.us.ibm.com (1b.90.2fa9.ip4.static.sl-reverse.com [169.47.144.27]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3p0vk4p6eg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 27 Feb 2023 16:09:29 +0000 Received: from pps.filterd (ppma05wdc.us.ibm.com [127.0.0.1]) by ppma05wdc.us.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 31RDiKmB024469; Mon, 27 Feb 2023 16:09:28 GMT Received: from smtprelay07.dal12v.mail.ibm.com ([9.208.130.99]) by ppma05wdc.us.ibm.com (PPS) with ESMTPS id 3nybe9c4me-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 27 Feb 2023 16:09:28 +0000 Received: from smtpav03.wdc07v.mail.ibm.com (smtpav03.wdc07v.mail.ibm.com [10.39.53.230]) by smtprelay07.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 31RG9QAm38339018 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 27 Feb 2023 16:09:26 GMT Received: from smtpav03.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2DB6D58066; Mon, 27 Feb 2023 16:09:26 +0000 (GMT) Received: from smtpav03.wdc07v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6ACEA5805A; Mon, 27 Feb 2023 16:09:25 +0000 (GMT) Received: from li-e362e14c-2378-11b2-a85c-87d605f3c641.ibm.com (unknown [9.211.67.183]) by smtpav03.wdc07v.mail.ibm.com (Postfix) with ESMTP; Mon, 27 Feb 2023 16:09:25 +0000 (GMT) Message-ID: <304e2d8b461d5540f79af1c87d288ba8551efbde.camel@us.ibm.com> Subject: [PING] Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp From: Carl Love To: Ulrich Weigand , "gdb-patches@sourceware.org" , Bruno Larsen , "tdevries@suse.de" , "pedro@palves.net" Cc: cel@us.ibm.com Date: Mon, 27 Feb 2023 08:09:24 -0800 In-Reply-To: <46c2c756475ba5923d7eed97996632a08285dd42.camel@us.ibm.com> References: <071f24ecf9b3a2bbbe8fee7db77492eb55c5f3ff.camel@us.ibm.com> <1d9b21914354bef6a290ac30673741e722e11757.camel@de.ibm.com> <3e3c9c40f07ab01c79fe10915e76ffa187c42ad9.camel@us.ibm.com> <122f5d2d3db9ef1979b0f8da927d005f32bba82c.camel@us.ibm.com> <011768e8-2b76-f8ed-1174-fbaa020b15e7@redhat.com> <78b464a1-e32e-c3da-85e4-7bfc322cc29f@redhat.com> <7848e9858b54e33e399b871774ffc0b5058c1736.camel@us.ibm.com> <65d44121-65f7-a212-79ec-07ce53c15ecb@suse.de> <9fe94c0979cb40979b0dea7693a901c2d9f66164.camel@us.ibm.com> <59417813-eb4a-baf8-4e5d-e225d6732f71@suse.de> <7a494157-494f-6adf-d533-bf373b0f054f@redhat.com> <71aa635593df0677811afb85409aa190bcfa4f6a.camel@us.ibm.com> <15864a6b87b25c93e99a28149f23138267735f2a.camel@us.ibm.com> <041f62e9f26fd4a536bc90c34f072985582e6237.camel@de.ibm.com> <46c2c756475ba5923d7eed97996632a08285dd42.camel@us.ibm.com> Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.28.5 (3.28.5-18.el8) X-TM-AS-GCONF: 00 X-Proofpoint-GUID: CTPwf9ybNaldV5ca3_r-td0UOC5o82E9 X-Proofpoint-ORIG-GUID: tY3yvCFyFcSwRnTtX8nHCm0HWziH4Xi0 Content-Transfer-Encoding: 7bit X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.219,Aquarius:18.0.930,Hydra:6.0.562,FMLib:17.11.170.22 definitions=2023-02-27_13,2023-02-27_01,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 clxscore=1015 phishscore=0 priorityscore=1501 impostorscore=0 malwarescore=0 adultscore=0 mlxlogscore=999 bulkscore=0 mlxscore=0 lowpriorityscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2212070000 definitions=main-2302270124 X-Spam-Status: No, score=-11.3 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_EF,GIT_PATCH_0,KAM_ASCII_DIVIDERS,KAM_SHORT,SPF_HELO_NONE,SPF_NONE,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 List-Id: Ulrich, Bruno, Tom, Pedro, GDB maintainers: Wondering if anyone has had a chance to review and test this patch? Would really like to make sure some can test it on an Intel Generation 5 or newer processor to make sure there are no issues with the tests gdb.btrace/rn-dl-bind.exp and gdb.btrace/tailcall.exp: reverse-next. Thanks for the time and effort looking at this patch. Carl ------------------------------------------------- On Mon, 2023-02-20 at 12:24 -0800, Carl Love wrote: > Ulrich, Bruno, GDB maintainers: > > Per the comments from Ulrich, I have updated the patch to address the > comments about the source code and the testcase. I updated the new > library procedure so it can be called from gdb_step_until. So > gdb_step_until is now just a variant of the new repeat_cmd_until > proceedure. > > The redundant if test has been removed. It was added to fix a > regression testing failure I saw on the gdb.btrace/tailcall.exp on > X86. > I went back and redid the testing, rebuilding everything from > scratch. > I am not able to reproduce the test failure without the redundant > check. Not sure why I initially saw the regression failure at this > point? Perhaps I hadn't re-enabled the > /proc/sys/kernel/perf_event_paranoid value? It must be 2 or lower > for > the test to run. Otherwise the test fails. Anyway, the regression > tests on X86 run without the redundant check are passing on my > laptop. > > I resolved the issues with the testing on X86 to make sure it isn't > missing failures when testing gdb.reverse/step-indirect-call- > thunk.exp. > As mentioned in the previous email, the test does not run on PowerPC > since the gcc command line options "-mindirect-branch=thunk" and "- > mfunction-return=thunk" are not supported on PowerPC. I disabled the > test on PowerPC in the updated patch. > > Retested on X86 generation 5 and PowerPC with no regressions found. > > Hopefully this version of the patch is acceptable. > > Carl > > ----------------------------------------------------- > > PowerPC: fix for gdb.reverse/finish-precsave.exp and > gdb.reverse/finish-reverse.exp > > PPC64 multiple entry points. When executing in reverse the function > finish_backward sets the break point at the alternate entry point, > known > as the global entry point (GEP) in PowerPC. However if the forward > execution enters via the normal entry point, known as the local entry > point (LEP) on PowerPC, reverse execution never sees the break point > at the > alternate entry point of the function. Reverse execution continues > until > the next break point is encountered thus stopping at the wrong place. > > This patch adds a new address to struct execution_control_state to > hold the > address of the alternate entry point (GEP). The finish_backwards > function > is updated, if the stopping point is between the normal entry point > (LEP) > and the end of the function, a breakpoint is set at the normal entry > point. > If the stopping point is between the entry points, a breakpoint is > set to > the alternate entry point. > > The patch fixes the behavior of the reverse-finish command on PowerPC > to > match the behavior of the command on other platforms, specifically > X86. > The patch does not change the behavior of the command on X86. > > A new test is added to verify the reverse-finish command on PowerPC > correctly stops at the instruction where the function call is > made. A new > test, finish-reverse-next.exp, is added to verify the correct > functionality > of the reverse-finish command. The reverse-finish comand is expected > to > stop on the instruction that jumps to the function. Procedure > proc_step_until from test gdb.reverse/step-indirect-call-thunk.exp is > moved > to lib/gdb.exp and renamed repeat_cmd_until. > > The patch fixes 11 regression errors in test gdb.reverse/finish- > precsave.exp > and 11 regression errors in test gdb.reverse/finish-reverse.exp. > > The patch has been tested on Power 10 and X86 processor with no new > regression failures. > --- > gdb/infcmd.c | 47 ++-- > gdb/infrun.c | 24 ++ > .../gdb.reverse/finish-reverse-next.c | 91 +++++++ > .../gdb.reverse/finish-reverse-next.exp | 224 > ++++++++++++++++++ > .../gdb.reverse/step-indirect-call-thunk.exp | 55 ++--- > gdb/testsuite/lib/gdb.exp | 49 +++- > 6 files changed, 421 insertions(+), 69 deletions(-) > create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.c > create mode 100644 gdb/testsuite/gdb.reverse/finish-reverse-next.exp > > diff --git a/gdb/infcmd.c b/gdb/infcmd.c > index 77206fcbfe8..0fa5719d38b 100644 > --- a/gdb/infcmd.c > +++ b/gdb/infcmd.c > @@ -1728,28 +1728,41 @@ finish_backward (struct finish_command_fsm > *sm) > no way that a function up the stack can have a return address > that's equal to its entry point. */ > > - if (sal.pc != pc) > - { > - frame_info_ptr frame = get_selected_frame (nullptr); > - struct gdbarch *gdbarch = get_frame_arch (frame); > + CORE_ADDR alt_entry_point = sal.pc; > + CORE_ADDR entry_point = alt_entry_point; > + frame_info_ptr frame = get_selected_frame (nullptr); > + struct gdbarch *gdbarch = get_frame_arch (frame); > + > + if (gdbarch_skip_entrypoint_p (gdbarch)) > + /* Some architectures, like PowerPC use local and global entry > points. > + There is only one Entry Point (GEP = LEP) for other > architectures. > + The GEP is an alternate entry point. The LEP is the normal > entry point. > + The value of entry_point was initialized to the alternate > entry point > + (GEP). It will be adjusted to the normal entry point if the > function > + has two entry points. */ > + entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc); > > - /* Set a step-resume at the function's entry point. Once > that's > - hit, we'll do one more step backwards. */ > + if ((pc < alt_entry_point) || (pc > entry_point)) > + { > + /* We are in the body of the function. Set a breakpoint to > backup to > + the normal entry point. */ > symtab_and_line sr_sal; > - sr_sal.pc = sal.pc; > + sr_sal.pc = entry_point; > sr_sal.pspace = get_frame_program_space (frame); > - insert_step_resume_breakpoint_at_sal (gdbarch, > - sr_sal, null_frame_id); > - > - proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); > + insert_step_resume_breakpoint_at_sal (gdbarch, sr_sal, > + null_frame_id); > } > + > else > - { > - /* We're almost there -- we just need to back up by one more > - single-step. */ > - tp->control.step_range_start = tp->control.step_range_end = 1; > - proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); > - } > + /* We are either at one of the entry points or between the entry > points. > + If we are not at the alt_entry point, go back to the > alt_entry_point > + If we at the normal entry point step back one instruction, > when we > + stop we will determine if we entered via the entry point or > the > + alternate entry point. If we are at the alternate entry > point, > + single step back to the function call. */ > + tp->control.step_range_start = tp->control.step_range_end = 1; > + > + proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT); > } > > /* finish_forward -- helper function for finish_command. FRAME is > the > diff --git a/gdb/infrun.c b/gdb/infrun.c > index 87ab73c47a4..987dbd16ea4 100644 > --- a/gdb/infrun.c > +++ b/gdb/infrun.c > @@ -1868,6 +1868,7 @@ struct execution_control_state > > struct target_waitstatus ws; > int stop_func_filled_in = 0; > + CORE_ADDR stop_func_alt_start = 0; > CORE_ADDR stop_func_start = 0; > CORE_ADDR stop_func_end = 0; > const char *stop_func_name = nullptr; > @@ -4680,6 +4681,11 @@ fill_in_stop_func (struct gdbarch *gdbarch, > ecs->stop_func_start > += gdbarch_deprecated_function_start_offset (gdbarch); > > + /* PowerPC functions have a Local Entry Point (LEP) and a > Global > + Entry Point (GEP). There is only one Entry Point (GEP = > LEP) for > + other architectures. */ > + ecs->stop_func_alt_start = ecs->stop_func_start; > + > if (gdbarch_skip_entrypoint_p (gdbarch)) > ecs->stop_func_start > = gdbarch_skip_entrypoint (gdbarch, ecs- > >stop_func_start); > @@ -7269,6 +7275,24 @@ process_event_stop_test (struct > execution_control_state *ecs) > } > } > > + if (execution_direction == EXEC_REVERSE > + && ecs->event_thread->control.proceed_to_finish > + && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start > + && ecs->event_thread->stop_pc () < ecs->stop_func_start) > + { > + /* We are executing the reverse-finish command. > + If the system supports multiple entry points and we are > finishing a > + function in reverse. If we are between the entry points > singe-step > + back to the alternate entry point. If we are at the alternate > entry > + point -- just need to back up by one more single-step, which > + should take us back to the function call. */ > + ecs->event_thread->control.step_range_start > + = ecs->event_thread->control.step_range_end = 1; > + keep_going (ecs); > + return; > + > + } > + > if (ecs->event_thread->control.step_range_end == 1) > { > /* It is stepi or nexti. We always want to stop stepping > after > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.c > b/gdb/testsuite/gdb.reverse/finish-reverse-next.c > new file mode 100644 > index 00000000000..e95ee8e33a6 > --- /dev/null > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.c > @@ -0,0 +1,91 @@ > +/* This testcase is part of GDB, the GNU debugger. > + > + Copyright 2012-2023 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 < > http://www.gnu.org/licenses/>. */ > + > +/* The reverse finish command should return from a function and stop > on > + the first instruction of the source line where the function call > is made. > + Specifically, the behavior should match doing a reverse next from > the > + first instruction in the function. GDB should only require one > reverse > + step or next statement to reach the previous source code line. > + > + This test verifies the fix for gdb bugzilla: > + > + https://sourceware.org/bugzilla/show_bug.cgi?id=29927 > + > + PowerPC supports two entry points to a function. The normal > entry point > + is called the local entry point (LEP). The alternate entry point > is called > + the global entry point (GEP). The GEP is only used if the table > of > + contents (TOC) value stored in register r2 needs to be setup > prior to > + execution starting at the LEP. A function call via a function > pointer > + will entry via the GEP. A normal function call will enter via > the LEP. > + > + This test has been expanded to include tests to verify the > reverse-finish > + command works properly if the function is called via the > GEP. The original > + test only verified the reverse-finish command for a normal call > that used > + the LEP. */ > + > +int > +function2 (int a, int b) > +{ > + int ret = 0; > + ret = ret + a + b; > + return ret; > +} > + > +int > +function1 (int a, int b) // FUNCTION1 > +{ > + int ret = 0; > + int (*funp) (int, int) = &function2; > + /* The assembly code for this function when compiled for PowerPC > is as > + follows: > + > + 0000000010000758 : > + 10000758: 02 10 40 3c lis r2,4098 <- GEP > + 1000075c: 00 7f 42 38 addi r2,r2,32512 > + 10000760: a6 02 08 7c mflr r0 <- LEP > + 10000764: 10 00 01 f8 std r0,16(r1) > + .... > + > + When the function is called on PowerPC with function1 (a, b) > the call > + enters at the Local Entry Point (LEP). When the function is > called via > + a function pointer, the Global Entry Point (GEP) for function1 > is used. > + The GEP sets up register 2 before reaching the LEP. > + */ > + ret = funp (a + 1, b + 2); > + return ret; > +} > + > +int > +main(int argc, char* argv[]) > +{ > + int a, b; > + int (*funp) (int, int) = &function1; > + > + /* Call function via Local Entry Point (LEP). */ > + > + a = 1; > + b = 5; > + > + function1 (a, b); // CALL VIA LEP > + > + /* Call function via Global Entry Point (GEP). */ > + a = 10; > + b = 50; > + > + funp (a, b); // CALL VIA GEP > + return 0; > +} > diff --git a/gdb/testsuite/gdb.reverse/finish-reverse-next.exp > b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp > new file mode 100644 > index 00000000000..1f53b649a7d > --- /dev/null > +++ b/gdb/testsuite/gdb.reverse/finish-reverse-next.exp > @@ -0,0 +1,224 @@ > +# Copyright 2008-2023 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 < > http://www.gnu.org/licenses/>. */ > + > +# This file is part of the GDB testsuite. It tests reverse > stepping. > +# Lots of code borrowed from "step-test.exp". > + > +# The reverse finish command should return from a function and stop > on > +# the first instruction of the source line where the function call > is made. > +# Specifically, the behavior should match doing a reverse next from > the > +# first instruction in the function. GDB should only take one > reverse step > +# or next statement to reach the previous source code line. > + > +# This testcase verifies the reverse-finish command stops at the > first > +# instruction in the source code line where the function was > called. There > +# are two scenarios that must be checked: > +# 1) gdb is at the entry point instruction for the function > +# 2) gdb is in the body of the function. > + > +# This test verifies the fix for gdb bugzilla: > +# https://sourceware.org/bugzilla/show_bug.cgi?id=29927 > + > +# PowerPC supports two entry points to a function. The normal entry > point > +# is called the local entry point (LEP). The alternate entry point > is called > +# the global entry point (GEP). A function call via a function > pointer > +# will entry via the GEP. A normal function call will enter via the > LEP. > +# > +# This test has been expanded to include tests to verify the > reverse-finish > +# command works properly if the function is called via the GEP. The > original > +# test only verified the reverse-finish command for a normal call > that used > +# the LEP. > + > +if ![supports_reverse] { > + return > +} > + > +standard_testfile > + > +if { [prepare_for_testing "failed to prepare" $testfile $srcfile] } > { > + return -1 > +} > + > +runto_main > +set target_remote [gdb_is_target_remote] > + > +if [supports_process_record] { > + # Activate process record/replay. > + gdb_test_no_output "record" "turn on process record for test1" > +} > + > + > +### TEST 1: reverse finish from the entry point instruction (LEP) in > +### function1 when called using the normal entry point (LEP). > + > +# Set breakpoint at call to function1 in main. > +set bp_LEP_test [gdb_get_line_number "CALL VIA LEP" $srcfile] > +gdb_breakpoint $srcfile:$bp_LEP_test temporary > + > +# Continue to break point at function1 call in main. > +gdb_continue_to_breakpoint \ > + "stopped at function1 entry point instruction to stepi into > function" \ > + ".*$srcfile:$bp_LEP_test\r\n.*" > + > +# stepi until we see "{" indicating we entered function1 > +repeat_cmd_until "stepi" "CALL VIA LEP" "{" "stepi into function1 > call" "100" > + > +# The reverse-finish command should stop on the function call > instruction > +# which is the last instruction in the source code line. A reverse- > next > +# instruction should then stop at the first instruction in the same > source > +# code line. Another revers-next instruction stops at the previous > source > +# code line. > +gdb_test "reverse-finish" ".*function1 \\(a, b\\); // CALL VIA > LEP.*" \ > + "reverse-finish function1 LEP call from LEP " > +gdb_test "reverse-next" ".*function1 \\(a, b\\); // CALL VIA LEP" > \ > + "reverse next 1 LEP entry point function call from LEP" > +gdb_test "reverse-next" ".*b = 5;.*" "reverse next 2, at b = 5, call > from LEP" > + > + > +gdb_test "reverse-continue" ".*" "setup for test 2" > + > +# Turn off record to clear logs and turn on again > +gdb_test "record stop" "Process record is stopped.*" \ > + "turn off process record for test1" > +gdb_test_no_output "record" "turn on process record for test2" > + > + > +### TEST 2: reverse finish from the body of function1. > + > +# Set breakpoint at call to function1 in main. > +gdb_breakpoint $srcfile:$bp_LEP_test temporary > + > +# Continue to break point at function1 call in main. > +gdb_continue_to_breakpoint \ > + "at function1 entry point instruction to step to body of > function" \ > + ".*$srcfile:$bp_LEP_test\r\n.*" > + > +# do a step instruction to get to the body of the function > +gdb_test "step" ".*int ret = 0;.*" "step test 1" > + > +# The reverse-finish command should stop on the function call > instruction > +# which is the last instruction in the source code line. A reverse- > next > +# instruction should then stop at the first instruction in the same > source > +# code line. Another revers-next instruction stops at the previous > source > +# code line. > +gdb_test "reverse-finish" ".*function1 \\(a, b\\); // CALL VIA > LEP.*" \ > + "reverse-finish function1 LEP call from function body" > +gdb_test "reverse-next" ".*function1 \\(a, b\\); // CALL VIA > LEP.*" \ > + "reverse next 1 LEP from function body" > +gdb_test "reverse-next" ".*b = 5;.*" \ > + "reverse next 2 at b = 5, from function body" > + > +gdb_test "reverse-continue" ".*" "setup for test 3" > + > +# Turn off record to clear logs and turn on again > +gdb_test "record stop" "Process record is stopped.*" \ > + "turn off process record for test2" > +gdb_test_no_output "record" "turn on process record for test3" > + > + > +### TEST 3: reverse finish from the alternate entry point > instruction (GEP) in > +### function1 when called using the alternate entry point (GEP). > + > +# Set breakpoint at call to funp in main. > +set bp_GEP_test [gdb_get_line_number "CALL VIA GEP" $srcfile] > +gdb_breakpoint $srcfile:$bp_GEP_test temporary > + > +# Continue to break point at funp call in main. > +gdb_continue_to_breakpoint \ > + "stopped at function1 entry point instruction to stepi into > funp" \ > + ".*$srcfile:$bp_GEP_test\r\n.*" > + > +# stepi until we see "{" indicating we entered function. > +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call" > + > +# The reverse-finish command should stop on the function call > instruction > +# which is the last instruction in the source code line. A reverse- > next > +# instruction should then stop at the first instruction in the same > source > +# code line. Another revers-next instruction stops at the previous > source > +# code line. > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \ > + "function1 GEP call call from GEP" > +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \ > + "reverse next 1 GEP entry point function call from GEP" > +gdb_test "reverse-next" ".*b = 50;.*" "reverse next 2 at b = 50, > call from GEP" > + > +gdb_test "reverse-continue" ".*" "setup for test 4" > + > +# Turn off record to clear logs and turn on again > +gdb_test "record stop" "Process record is stopped.*" \ > + "turn off process record for test3" > +gdb_test_no_output "record" "turn on process record for test4" > + > +### TEST 4: reverse finish from between the GEP and LEP in > +### function1 when called using the alternate entry point (GEP). > + > +# Set breakpoint at call to funp in main. > +set bp_GEP_test [gdb_get_line_number "CALL VIA GEP" $srcfile] > +gdb_breakpoint $srcfile:$bp_GEP_test temporary > + > +# Continue to break point at funp call in main. > +gdb_continue_to_breakpoint \ > + "stopped at function1 entry point instruction to stepi into funp > again" \ > + ".*$srcfile:$bp_GEP_test\r\n.*" > + > +# stepi until we see "{" indicating we entered function. > +repeat_cmd_until "stepi" "CALL VIA GEP" "{" "stepi into funp call > again" > + > +# do one more stepi so we are between the GEP and LEP. > +gdb_test "stepi" "{" "stepi to between GEP and LEP" > + > +# The reverse-finish command should stop on the function call > instruction > +# which is the last instruction in the source code line. A reverse- > next > +# instruction should then stop at the first instruction in the same > source > +# code line. Another revers-next instruction stops at the previous > source > +# code line. > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \ > + "function1 GEP call call from GEP again" > +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \ > + "reverse next 1 GEP entry point function call from GEP again" > +gdb_test "reverse-next" ".*b = 50;.*" \ > + "reverse next 2 at b = 50, call from GEP again" > + > +gdb_test "reverse-continue" ".*" "setup for test 5" > + > +# Turn off record to clear logs and turn on again > +gdb_test "record stop" "Process record is stopped.*" \ > + "turn off process record for test4" > +gdb_test_no_output "record" "turn on process record for test5" > + > + > +### TEST 5: reverse finish from the body of function 1 when calling > using the > +### alternate entrypoint (GEP). > +gdb_breakpoint $srcfile:$bp_GEP_test temporary > + > +# Continue to break point at funp call. > +gdb_continue_to_breakpoint \ > + "at function1 entry point instruction to step to body of funp > call" \ > + ".*$srcfile:$bp_GEP_test\r\n.*" > + > +# Step into body of funp, called via GEP. > +gdb_test "step" ".*int ret = 0;.*" "step test 2" > + > +# The reverse-finish command should stop on the function call > instruction > +# which is the last instruction in the source code line. A reverse- > next > +# instruction should then stop at the first instruction in the same > source > +# code line. Another revers-next instruction stops at the previous > source > +# code line. > +gdb_test "reverse-finish" ".*funp \\(a, b\\);.*" \ > + "reverse-finish function1 GEP call, from function body " > +gdb_test "reverse-next" ".*funp \\(a, b\\);.*" \ > + "reverse next 1 GEP call from function body" > +gdb_test "reverse-next" ".*b = 50;.*" \ > + "reverse next 2 at b = 50 from function body" > diff --git a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp > b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp > index 94292d5eb9b..61fb4974b8e 100644 > --- a/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp > +++ b/gdb/testsuite/gdb.reverse/step-indirect-call-thunk.exp > @@ -17,6 +17,12 @@ require supports_reverse > > standard_testfile > > +if { [istarget "powerpc*-*-linux*"] } { > + # GCC for PowerPC on linux does not support the -mindirect- > branch and > + # -mfunction-return command line options. > + return 0 > +} > + > set cflags {} > lappend cflags debug > lappend cflags additional_flags=-mindirect-branch=thunk > @@ -36,39 +42,6 @@ if { ![runto_main] } { > return -1 > } > > -# Do repeated stepping COMMANDs in order to reach TARGET from > CURRENT > -# > -# COMMAND is a stepping command > -# CURRENT is a string matching the current location > -# TARGET is a string matching the target location > -# TEST is the test name > -# > -# The function issues repeated COMMANDs as long as the location > matches > -# CURRENT up to a maximum of 100 steps. > -# > -# TEST passes if the resulting location matches TARGET and fails > -# otherwise. > -# > -proc step_until { command current target test } { > - global gdb_prompt > - > - set count 0 > - gdb_test_multiple "$command" "$test" { > - -re "$current.*$gdb_prompt $" { > - incr count > - if { $count < 100 } { > - send_gdb "$command\n" > - exp_continue > - } else { > - fail "$test" > - } > - } > - -re "$target.*$gdb_prompt $" { > - pass "$test" > - } > - } > -} > - > gdb_test_no_output "record" > gdb_test "next" ".*" "record trace" > > @@ -88,20 +61,20 @@ gdb_test "reverse-next" "apply\.2.*" \ > "reverse-step through thunks and over inc" > > # We can use instruction stepping to step into thunks. > -step_until "stepi" "apply\.2" "indirect_thunk" "stepi into call > thunk" > -step_until "stepi" "indirect_thunk" "inc" \ > +repeat_cmd_until "stepi" "apply\.2" "indirect_thunk" "stepi into > call thunk" > +repeat_cmd_until "stepi" "indirect_thunk" "inc" \ > "stepi out of call thunk into inc" > set alphanum_re "\[a-zA-Z0-9\]" > set pic_thunk_re "__$alphanum_re*\\.get_pc_thunk\\.$alphanum_re* > \\(\\)" > -step_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi into > return thunk" > -step_until "stepi" "return_thunk" "apply" \ > +repeat_cmd_until "stepi" "(inc|$pic_thunk_re)" "return_thunk" "stepi > into return thunk" > +repeat_cmd_until "stepi" "return_thunk" "apply" \ > "stepi out of return thunk back into apply" > > -step_until "reverse-stepi" "apply" "return_thunk" \ > +repeat_cmd_until "reverse-stepi" "apply" "return_thunk" \ > "reverse-stepi into return thunk" > -step_until "reverse-stepi" "return_thunk" "inc" \ > +repeat_cmd_until "reverse-stepi" "return_thunk" "inc" \ > "reverse-stepi out of return thunk into inc" > -step_until "reverse-stepi" "(inc|$pic_thunk_re)" "indirect_thunk" \ > +repeat_cmd_until "reverse-stepi" "(inc|$pic_thunk_re)" > "indirect_thunk" \ > "reverse-stepi into call thunk" > -step_until "reverse-stepi" "indirect_thunk" "apply" \ > +repeat_cmd_until "reverse-stepi" "indirect_thunk" "apply" \ > "reverse-stepi out of call thunk into apply" > diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp > index faa0ac05a9a..b10555fe5fb 100644 > --- a/gdb/testsuite/lib/gdb.exp > +++ b/gdb/testsuite/lib/gdb.exp > @@ -9267,31 +9267,58 @@ gdb_caching_proc arm_cc_for_target { > > # Step until the pattern REGEXP is found. Step at most > # MAX_STEPS times, but stop stepping once REGEXP is found. > -# > +# START matches current location > # If REGEXP is found then a single pass is emitted, otherwise, after > # MAX_STEPS steps, a single fail is emitted. > # > # TEST_NAME is the name used in the pass/fail calls. > > -proc gdb_step_until { regexp {test_name ""} {max_steps 10} } { > +proc gdb_step_until { regexp {test_name ""} {current ""} \ > + { max_steps 10 } } { > + if { $current == "" } { > + set current "\}" > + } > + if { $test_name == "" } { > + set test_name "stepping until regexp" > + } > + > + repeat_cmd_until "step" $current $regexp $test_name "10" > +} > + > +# Do repeated stepping COMMANDs in order to reach TARGET from > CURRENT > +# > +# COMMAND is a stepping command > +# CURRENT is a string matching the current location > +# TARGET is a string matching the target location > +# TEST is the test name > +# MAX_STEPS is number of steps attempted before fail is emitted > +# > +# The function issues repeated COMMANDs as long as the location > matches > +# CURRENT up to a maximum of 100 steps. > +# > +# TEST passes if the resulting location matches TARGET and fails > +# otherwise. > +# > +proc repeat_cmd_until { command current target test_name {max_steps > 100} } { > + global gdb_prompt > if { $test_name == "" } { > set test_name "stepping until regexp" > } > > set count 0 > - gdb_test_multiple "step" "$test_name" { > - -re "$regexp\r\n$::gdb_prompt $" { > - pass $test_name > - } > - -re ".*$::gdb_prompt $" { > - if {$count < $max_steps} { > - incr count > - send_gdb "step\n" > + gdb_test_multiple "$command" "$test_name" { > + -re "$current.*$gdb_prompt $" { > + incr count > + if { $count < $max_steps } { > + send_gdb "$command\n" > exp_continue > } else { > - fail $test_name > + fail "$test_name" > } > } > + -re "$target.*$gdb_prompt $" { > + pass "$test_name" > + } > } > } >