From patchwork Sat May 19 22:08:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 27341 Received: (qmail 74399 invoked by alias); 19 May 2018 22:09:25 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 74379 invoked by uid 89); 19 May 2018 22:09:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.1 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Frame, prepare, 20197, 23203 X-HELO: mail-wr0-f194.google.com Received: from mail-wr0-f194.google.com (HELO mail-wr0-f194.google.com) (209.85.128.194) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 19 May 2018 22:09:20 +0000 Received: by mail-wr0-f194.google.com with SMTP id w15-v6so4902269wrp.8 for ; Sat, 19 May 2018 15:09:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=YFCls3dLM4jovqUxp3ZnHTxX8FBZ0TLba37O8YEdgVM=; b=VLpW9HgqzoSzYWi5e0WDpdxq9bqfuPfzDLgIp38CMMAIEvf5ltBvNcVfv6W2jtsmvz zvhHwHdwkDPeW3/wYcCT4XQ2Pyj8p/2MBkB12yVVVQOB5WbI4DbxWwFPjDL+lWrz9w2Y evEa0MfV6pfxfzNenGopZvrrXfRBtoQn1dG6+bHTn9eQn0TT8Y7lXBL6CJAGVTIT+uHP AnS0KkW4VnxS9sOljyDk2zdRIly+Xzhz/jJ7LN1DmPVoIomydz5/2hgvxIHAV7hoectM qhxiJRvGjyE9ivl7I2o0Bas9pc06vxKNi5HGizoZ1VH9BD5LU1I2EPX4KH5RKKZPAuC+ DNdA== X-Gm-Message-State: ALKqPweQsCLnD/cka6N1BSkgmDWTfSeO1461IpXiM1nvYduG58kxB/Kx ZZhLdUCLTw9riALhTzcMoeZK1i9b X-Google-Smtp-Source: AB8JxZrGYc2xz8RXMzDWfdWtm/TnUcpIJn5xjiY7uEkLVvfaiRmnnjnjd1UDG8WkuEV6M5xlkKwczw== X-Received: by 2002:adf:8644:: with SMTP id 4-v6mr12422590wrw.73.1526767757997; Sat, 19 May 2018 15:09:17 -0700 (PDT) Received: from localhost (host86-164-85-144.range86-164.btcentralplus.com. [86.164.85.144]) by smtp.gmail.com with ESMTPSA id b66-v6sm14044460wma.48.2018.05.19.15.09.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 19 May 2018 15:09:17 -0700 (PDT) From: Andrew Burgess To: gdb-patches@sourceware.org Cc: Andrew Burgess Subject: [PATCH] gdb: Restore selected frame in print_frame_local_vars Date: Sat, 19 May 2018 23:08:31 +0100 Message-Id: <20180519220831.14412-1-andrew.burgess@embecosm.com> X-IsSubscribed: yes PR gdb/23203 reports 'bt full' causing the currently selected frame to change, this issue is fixed in this commit. Add a new class scoped_restore_selected_frame that saves and restores the selected frame. Make use of this in print_frame_local_vars to restore the selected frame on exit. gdb/ChangeLog: PR gdb/23203 * frame.c (scoped_restore_selected_frame::scoped_restore_selected_frame): Define. (scoped_restore_selected_frame::~scoped_restore_selected_frame): Define. * frame.h (class scoped_restore_selected_frame): New class. * stack.c (print_frame_local_vars): Remove catching and rethrowing of any exception, use scoped_restore_selected_frame to restore the frame instead. gdb/testsuite/ChangeLog: PR gdb/23203 * gdb.base/bt-full.c: New file. * gdb.base/bt-full.exp: New file. --- gdb/ChangeLog | 13 +++++++++ gdb/frame.c | 16 ++++++++++ gdb/frame.h | 16 ++++++++++ gdb/stack.c | 24 +++------------ gdb/testsuite/ChangeLog | 6 ++++ gdb/testsuite/gdb.base/bt-full.c | 35 ++++++++++++++++++++++ gdb/testsuite/gdb.base/bt-full.exp | 60 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 150 insertions(+), 20 deletions(-) create mode 100644 gdb/testsuite/gdb.base/bt-full.c create mode 100644 gdb/testsuite/gdb.base/bt-full.exp diff --git a/gdb/frame.c b/gdb/frame.c index 07fa2bc77d6..3e42aa82398 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -269,6 +269,22 @@ frame_stash_invalidate (void) htab_empty (frame_stash); } +/* Save the currently selected frame. */ +scoped_restore_selected_frame::scoped_restore_selected_frame () +{ + m_fid = get_frame_id (get_selected_frame (NULL)); +} + +/* Restore the currently selected frame. */ +scoped_restore_selected_frame::~scoped_restore_selected_frame () +{ + frame_info *frame = frame_find_by_id (m_fid); + if (frame == NULL) + warning (_("Unable to restore previously selected frame.")); + else + select_frame (frame); +} + /* Flag to control debugging. */ unsigned int frame_debug; diff --git a/gdb/frame.h b/gdb/frame.h index d5800b78c25..2c8f815a4ae 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -164,6 +164,22 @@ struct frame_id int artificial_depth; }; +/* Save and restore the currently selected frame. */ + +class scoped_restore_selected_frame +{ +public: + scoped_restore_selected_frame (); + ~scoped_restore_selected_frame (); + + DISABLE_COPY_AND_ASSIGN (scoped_restore_selected_frame); + +private: + + /* The ID of the previously selected frame. */ + struct frame_id m_fid; +}; + /* Methods for constructing and comparing Frame IDs. */ /* For convenience. All fields are zero. This means "there is no frame". */ diff --git a/gdb/stack.c b/gdb/stack.c index ecf1ee83793..7e377764865 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2019,7 +2019,6 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs, struct print_variable_and_value_data cb_data; const struct block *block; CORE_ADDR pc; - struct gdb_exception except = exception_none; if (!get_frame_pc_if_available (frame, &pc)) { @@ -2043,27 +2042,12 @@ print_frame_local_vars (struct frame_info *frame, int num_tabs, /* Temporarily change the selected frame to the given FRAME. This allows routines that rely on the selected frame instead of being given a frame as parameter to use the correct frame. */ + scoped_restore_selected_frame restore_selected_frame; select_frame (frame); - TRY - { - iterate_over_block_local_vars (block, - do_print_variable_and_value, - &cb_data); - } - CATCH (ex, RETURN_MASK_ALL) - { - except = ex; - } - END_CATCH - - /* Restore the selected frame, and then rethrow if there was a problem. */ - select_frame (frame_find_by_id (cb_data.frame_id)); - if (except.reason < 0) - throw_exception (except); - - /* do_print_variable_and_value invalidates FRAME. */ - frame = NULL; + iterate_over_block_local_vars (block, + do_print_variable_and_value, + &cb_data); if (!cb_data.values_printed) fprintf_filtered (stream, _("No locals.\n")); diff --git a/gdb/testsuite/gdb.base/bt-full.c b/gdb/testsuite/gdb.base/bt-full.c new file mode 100644 index 00000000000..708dc69b250 --- /dev/null +++ b/gdb/testsuite/gdb.base/bt-full.c @@ -0,0 +1,35 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2018 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 . */ + +void +breakpt () +{ + asm ("" ::: "memory"); +} + +void +func () +{ + breakpt (); +} + +int +main () +{ + func (); + return 0; +} diff --git a/gdb/testsuite/gdb.base/bt-full.exp b/gdb/testsuite/gdb.base/bt-full.exp new file mode 100644 index 00000000000..7b64293dcfb --- /dev/null +++ b/gdb/testsuite/gdb.base/bt-full.exp @@ -0,0 +1,60 @@ +# Copyright 2018 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 . + +standard_testfile + +if { [prepare_for_testing "failed to prepare" $testfile $srcfile debug] } { + return -1 +} + +if ![runto_main] then { + fail "can't run to main" + return 0 +} + +gdb_breakpoint "breakpt" +gdb_continue_to_breakpoint "breakpt" + +# Return the frame number for the currently selected frame +proc get_current_frame_number {{test_name ""}} { + global gdb_prompt + + if { $test_name == "" } { + set test_name "get current frame number" + } + set frame_num -1 + gdb_test_multiple "frame" $test_name { + -re "#(\[0-9\]+) .*$gdb_prompt $" { + set frame_num $expect_out(1,string) + } + } + return $frame_num +} + +# Visit each frame in the stack and ensure that 'bt full' doesn't +# change the selected stack frame. +for {set i 0} {$i < 3} {incr i} { + if { $i == 0 } { + gdb_assert {[get_current_frame_number] == $i} "check frame $i is selected" + } else { + gdb_test "frame $i" "#$i .*" "select frame $i" + } + + gdb_test "bt full" "#0 \[^\n\r\]+\[\n\r\]+No locals\.\[\n\r\]+#1 \[^\n\r\]+\[\n\r\]+No locals\.\[\n\r\]+#2 \[^\n\r\]+\[\n\r\]+No locals\.\[\n\r\]+" \ + "perform 'bt full' in frame $i" + + gdb_assert {[get_current_frame_number] == $i} "check frame $i is still selected" +} +