From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id AFB6D3858D33 for ; Tue, 28 Feb 2023 13:39:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org AFB6D3858D33 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1677591566; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L3J4zee9NGrCmT6HEGhrrm95YRVUtWOtqW3a701llcs=; b=HDrv33YQxtgq676EG2CfInTypddWhCP5ZQ1lBqSnVxx1l9uXfJATaOXZwBJ6jpZMr9jUGp d/2nepVyz8zmjshDwwYmGWi/pAJLfl59XFQhQuhcnv5kiJioy5t2IB3wz2iCaiIpN58BzJ f+r4ALKZjlC1K3BdmmdveepCo2ypwtI= Received: from mail-qt1-f197.google.com (mail-qt1-f197.google.com [209.85.160.197]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-390-Ch2xsb5ENECLbHbMLZi3mw-1; Tue, 28 Feb 2023 08:39:25 -0500 X-MC-Unique: Ch2xsb5ENECLbHbMLZi3mw-1 Received: by mail-qt1-f197.google.com with SMTP id k17-20020ac84751000000b003b9b4ec27c4so4600588qtp.19 for ; Tue, 28 Feb 2023 05:39:25 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; t=1677591564; h=content-transfer-encoding:in-reply-to:from:content-language :references:to:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=L3J4zee9NGrCmT6HEGhrrm95YRVUtWOtqW3a701llcs=; b=uk87ivplGYbUZ/vMCBI0F77Z7/wepCmv+vzBYrTkqY26GofTux4USOT4Jrnuq56xP/ usAhyhA1iVAZyl5mnYNzoxhP+fS3HiVgE3kq7D8tPF9Ay7D9yomWJ3LtlXjfITVSZ0Pt MtTpCp63MjLFzsDGi3YyZoskuz0RIh6NO7BPO4zeB4GqGYk35pWX7scWPvOPp9qb1M+S tr/wvw8WHhvFVsjBhYCZn53brBCwnK8C5urKZdQkusyvNV+vlSVV7+e+OB3RV9pElRi0 g/qLuUh+65GO0bR83nmdojFAcztAWIMCr5ihzmWsOuUqHwTBE5dEfXp8kbV9Np0eTWJ1 ZRIg== X-Gm-Message-State: AO0yUKXO74v1ec/eXjIrrQrG3tAlpj3giHAMbtNk0GBNcTTvVQ3m+F/T StlWfsXfMSHCUYOgeDHOENtDSuch8Yx5UiXyUnXBKdLdSphfdK9uu0stAY/vnC8ujH/o9s2hoX/ tQJgx6bmq288Q6420K1czKZlLOzk= X-Received: by 2002:ac8:5e0b:0:b0:3bf:d99c:8a9c with SMTP id h11-20020ac85e0b000000b003bfd99c8a9cmr4729881qtx.30.1677591564381; Tue, 28 Feb 2023 05:39:24 -0800 (PST) X-Google-Smtp-Source: AK7set+PscINY9qhpAJf9wEtvGPpAjEyWqzo3jUfr6wLMHLXr9aKib1WJBkvena+kQ9jzOqRIzdrIg== X-Received: by 2002:ac8:5e0b:0:b0:3bf:d99c:8a9c with SMTP id h11-20020ac85e0b000000b003bfd99c8a9cmr4729826qtx.30.1677591563754; Tue, 28 Feb 2023 05:39:23 -0800 (PST) Received: from [192.168.0.45] (ip-94-112-225-44.bb.vodafone.cz. [94.112.225.44]) by smtp.gmail.com with ESMTPSA id o134-20020a37418c000000b007429ee9482dsm4778101qka.134.2023.02.28.05.39.21 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 28 Feb 2023 05:39:23 -0800 (PST) Message-ID: Date: Tue, 28 Feb 2023 14:39:19 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.8.0 Subject: Re: [PATCH ] PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp To: Carl Love , Ulrich Weigand , "gdb-patches@sourceware.org" , "tdevries@suse.de" , "pedro@palves.net" References: <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> From: Bruno Larsen In-Reply-To: <46c2c756475ba5923d7eed97996632a08285dd42.camel@us.ibm.com> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_SHORT,NICE_REPLY_A,RCVD_IN_BARRACUDACENTRAL,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,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: On 20/02/2023 21:24, 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 Hi Carl, Sorry about the delay. I've tested the series and see no regressions. In particular, the tests you called out all passed on my machine. I have a minor wording nit in one comment, but regardless, you can add to the tag: Reviewed-By: Bruno Larsen > ----------------------------------------------------- > > 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 I would change backup for "return", or separate it to "back up", otherwise I personally think of data backups. -- Cheers, Bruno > + 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 . */ > + > +/* 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 . */ > + > +# 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" > + } > } > } >