From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28365 invoked by alias); 21 Sep 2005 18:18:12 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 28191 invoked by uid 22791); 21 Sep 2005 18:17:55 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Wed, 21 Sep 2005 18:17:55 +0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id j8LIHsAc004676 for ; Wed, 21 Sep 2005 14:17:54 -0400 Received: from potter.sfbay.redhat.com (potter.sfbay.redhat.com [172.16.27.15]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id j8LIHrV15351; Wed, 21 Sep 2005 14:17:53 -0400 Received: from [172.16.24.50] (bluegiant.sfbay.redhat.com [172.16.24.50]) by potter.sfbay.redhat.com (8.12.8/8.12.8) with ESMTP id j8LIHqx3027133; Wed, 21 Sep 2005 14:17:52 -0400 Message-ID: <4331A3CF.5080700@redhat.com> Date: Wed, 21 Sep 2005 18:18:00 -0000 From: Michael Snyder User-Agent: Mozilla Thunderbird (X11/20050322) MIME-Version: 1.0 To: GDB Patches , Stan Shebs Subject: RFC: reverse-finish Content-Type: multipart/mixed; boundary="------------050604070609060700020404" X-SW-Source: 2005-09/txt/msg00189.txt.bz2 This is a multi-part message in MIME format. --------------050604070609060700020404 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 641 Following on to my patch of 9/7 implementing reverse-step, reverse-next and reverse-continue, this patch is sufficient to implement reverse-finish. This is meant for discussion, not approval (I don't plan to check anything in right away). Again, this is based on a modular approach that assumes only a simple interface "get_exec_direction()". I haven't taken it down to the architecture level, but have simply assumed that every function has a single entry point (at its label), and that it is sufficient to continue backwards to that point, and (assuming the correct frame) do one more single-step to reach the call. Here's the patch: --------------050604070609060700020404 Content-Type: text/plain; name="finish.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="finish.txt" Content-length: 4756 Index: infcmd.c =================================================================== RCS file: /cvs/src/src/gdb/infcmd.c,v retrieving revision 1.123 diff -p -r1.123 infcmd.c *** infcmd.c 13 Sep 2004 18:26:28 -0000 1.123 --- infcmd.c 4 Sep 2005 23:08:10 -0000 *************** finish_command_continuation (struct cont *** 1181,1186 **** --- 1181,1188 ---- /* "finish": Set a temporary breakpoint at the place the selected frame will return to, then continue. */ + static void finish_backwards (struct symbol *); + static void finish_command (char *arg, int from_tty) { *************** finish_command (char *arg, int from_tty) *** 1223,1238 **** clear_proceed_status (); - sal = find_pc_line (get_frame_pc (frame), 0); - sal.pc = get_frame_pc (frame); - - breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish); - - if (!target_can_async_p ()) - old_chain = make_cleanup_delete_breakpoint (breakpoint); - else - old_chain = make_exec_cleanup_delete_breakpoint (breakpoint); - /* Find the function we will return from. */ function = find_pc_function (get_frame_pc (deprecated_selected_frame)); --- 1225,1230 ---- *************** finish_command (char *arg, int from_tty) *** 1241,1250 **** source. */ if (from_tty) { ! printf_filtered ("Run till exit from "); print_stack_frame (get_selected_frame (), 1, LOCATION); } /* If running asynchronously and the target support asynchronous execution, set things up for the rest of the finish command to be completed later on, when gdb has detected that the target has --- 1233,1263 ---- source. */ if (from_tty) { ! if (get_exec_direction () == EXEC_REVERSE) ! printf_filtered ("Run back to call of "); ! else ! printf_filtered ("Run till exit from "); ! print_stack_frame (get_selected_frame (), 1, LOCATION); } + if (get_exec_direction () == EXEC_REVERSE) + { + /* Split off at this point. */ + finish_backwards (function); + return; + } + + sal = find_pc_line (get_frame_pc (frame), 0); + sal.pc = get_frame_pc (frame); + + breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), bp_finish); + + if (!target_can_async_p ()) + old_chain = make_cleanup_delete_breakpoint (breakpoint); + else + old_chain = make_exec_cleanup_delete_breakpoint (breakpoint); + /* If running asynchronously and the target support asynchronous execution, set things up for the rest of the finish command to be completed later on, when gdb has detected that the target has *************** finish_command (char *arg, int from_tty) *** 1301,1306 **** --- 1314,1375 ---- do_cleanups (old_chain); } } + + static void + finish_backwards (struct symbol *function) + { + struct symtab_and_line sal; + struct breakpoint *breakpoint; + struct cleanup *old_chain; + CORE_ADDR func_addr; + + if (find_pc_partial_function (get_frame_pc (get_current_frame ()), + NULL, &func_addr, NULL) == 0) + internal_error (__FILE__, __LINE__, + "Finish: couldn't find function."); + + sal = find_pc_line (func_addr, 0); + + /* Let's cheat and not worry about async until later. */ + + /* We don't need a return value. */ + proceed_to_finish = 0; + /* Special case: if we're sitting at the function entry point, + then all we need to do is take a reverse singlestep. We + don't need to set a breakpoint, and indeed it would do us + no good to do so. + + Note that this can only happen at frame #0, since there's + no way that a function up the stack can have a return address + that's equal to its entry point. */ + + if (sal.pc != read_pc ()) + { + /* Set breakpoint and continue. */ + breakpoint = + set_momentary_breakpoint (sal, + get_frame_id (get_selected_frame ()), + bp_breakpoint); + /* Tell the breakpoint to keep quiet. */ + breakpoint_muzzle (breakpoint); + old_chain = make_cleanup_delete_breakpoint (breakpoint); + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); + /* We will be stopped when proceed returns. */ + if (bpstat_find_breakpoint (stop_bpstat, breakpoint) == NULL) + { + /* Didn't hit our breakpoint. */ + internal_error (__FILE__, __LINE__, + "Finish backwards missed its breakpoint."); + } + do_cleanups (old_chain); + } + /* We're almost there; just back up one step. */ + /* (Kludgy way of letting wait_for_inferior know...) */ + step_range_start = step_range_end = 1; + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); + return; + } + static void --------------050604070609060700020404--