From patchwork Mon Jul 31 22:21:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 21833 Received: (qmail 8980 invoked by alias); 31 Jul 2017 22:22:15 -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 8895 invoked by uid 89); 31 Jul 2017 22:22:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=201602, H*r:sk:static. X-HELO: mail-it0-f45.google.com Received: from mail-it0-f45.google.com (HELO mail-it0-f45.google.com) (209.85.214.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 31 Jul 2017 22:22:12 +0000 Received: by mail-it0-f45.google.com with SMTP id h199so2018069ith.0 for ; Mon, 31 Jul 2017 15:22:12 -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:subject:date:message-id:in-reply-to :references; bh=vTvxrKE6h/6B95FehiwzgseF4ASL42hv/+ndvFmZjL0=; b=n4ysWVEDK8k81Ler0dBPyRSg3wlKVJfmKmHEL2msS4eJ0bK+5mfMBxV5w5mMpUS5WC Qj+qbAJEGAvQuzy2eKrH9ojYgbAnD4SRCxaSsLUE0U5K9t3Qw8mmEkDq9xKWn3+/EkMo s9Lg/t48gCJ/3GJIffInwz6eE+cqSiqAu29DoVdhl8yUephua757MfdhVL1g8A7JMyCm 8RmYZV+65VjwIagd6lLuB1Pg7TpIJe9vmU3jI8fp449RDmjUapC5Aw5r2EPNpl6bKDDI 9e0mV3ROgA/lpv8z7nhgsjcl9czI5CAYBT4ZWGH12+iT6wqdRTJOqdU0PJ+JENHSsSAx cx3g== X-Gm-Message-State: AIVw1115gCWxC/XWsgG6k1oau9SmSXPd9JdSf22lUqbMBFA8Jn8uxG+T dl+JXDPjE7VnhScp X-Received: by 10.36.159.194 with SMTP id c185mr20106281ite.31.1501539730635; Mon, 31 Jul 2017 15:22:10 -0700 (PDT) Received: from E107787-LIN.Home (static.42.136.251.148.clients.your-server.de. [148.251.136.42]) by smtp.gmail.com with ESMTPSA id s204sm5963117itd.34.2017.07.31.15.22.09 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 31 Jul 2017 15:22:10 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 5/9] Handle unwinding exceptions Date: Mon, 31 Jul 2017 23:21:51 +0100 Message-Id: <1501539715-8049-6-git-send-email-yao.qi@linaro.org> In-Reply-To: <1501539715-8049-1-git-send-email-yao.qi@linaro.org> References: <1501539715-8049-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes unwinder methods (sniffer, this_id, stop_reason, etc) can throw exceptions, at least when some data is unavailable during examining traceframes. We deal with this problem by catching exceptions in each unwinders, dwarf unwinders and different arch-specific prologue unwinders. done by https://www.sourceware.org/ml/gdb-patches/2011-02/msg00611.html This requires each arch-specific prologue unwinder needs to catch exceptions. This patch centralizes the exception handling in the callers of unwinders methods, and the following patches remove the exception handling in each arch prologue unwinders. This patch is a follow-up to discussion https://sourceware.org/ml/gdb-patches/2016-02/msg00778.html This patch not only catches exceptions from unwinder methods, but also catches exceptions from frame_base methods, because they call arch-specific prologue analyzer, which can throw exceptions. gdb: 2017-07-27 Yao Qi * frame.c (compute_frame_id): Catch exception, if it is NOT_AVAILABLE_ERROR, call frame_id_build_unavailable_stack, otherwise throw the exception again. (frame_unwind_register_value): Catch exception from unwind->prev_register, if it is NOT_AVAILABLE_ERROR, set value unavailable, otherwise throw the exception again. (get_prev_frame_always_1): Catch exception from unwind->stop_reason, if it is NOT_AVAILABLE_ERROR, set stop_reason to UNWIND_UNAVAILABLE, otherwise throw the exception. (get_frame_locals_address): Catch exception base->this_locals. (get_frame_args_address): Likewise. --- gdb/frame.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 16 deletions(-) diff --git a/gdb/frame.c b/gdb/frame.c index 30e4aea..f5037d5 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -502,7 +502,32 @@ compute_frame_id (struct frame_info *fi) /* Find THIS frame's ID. */ /* Default to outermost if no ID is found. */ fi->this_id.value = outer_frame_id; - fi->unwind->this_id (fi, &fi->prologue_cache, &fi->this_id.value); + + TRY + { + fi->unwind->this_id (fi, &fi->prologue_cache, &fi->this_id.value); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error == NOT_AVAILABLE_ERROR) + { + CORE_ADDR pc; + + /* Use function start address as part of the frame ID. If we + can't find the start address (due to missing symbol + information), faill back to just using the current PC. If + PC isn't available, we can't construct any meaningful frame + ID, so do nothing here, and the frame id is + outer_frame_id. */ + if ((get_frame_func_if_available (fi, &pc) && pc != 0) + || get_frame_pc_if_available (fi, &pc)) + fi->this_id.value = frame_id_build_unavailable_stack (pc); + } + else + throw_exception (ex); + } + END_CATCH + gdb_assert (frame_id_p (fi->this_id.value)); fi->this_id.p = 1; if (frame_debug) @@ -1196,8 +1221,25 @@ frame_unwind_register_value (struct frame_info *frame, int regnum) if (frame->unwind == NULL) frame_unwind_find_by_frame (frame, &frame->prologue_cache); - /* Ask this frame to unwind its register. */ - value = frame->unwind->prev_register (frame, &frame->prologue_cache, regnum); + TRY + { + /* Ask this frame to unwind its register. */ + value = frame->unwind->prev_register (frame, &frame->prologue_cache, + regnum); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error == NOT_AVAILABLE_ERROR) + { + value = frame_unwind_got_register (frame, regnum, regnum); + set_value_lazy (value, 0); + mark_value_bytes_unavailable (value, 0, + TYPE_LENGTH (value_type (value))); + } + else + throw_exception (ex); + } + END_CATCH if (frame_debug) { @@ -2009,9 +2051,20 @@ get_prev_frame_always_1 (struct frame_info *this_frame) /* Check that this frame is unwindable. If it isn't, don't try to unwind to the prev frame. */ - this_frame->stop_reason - = this_frame->unwind->stop_reason (this_frame, - &this_frame->prologue_cache); + TRY + { + this_frame->stop_reason + = this_frame->unwind->stop_reason (this_frame, + &this_frame->prologue_cache); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error == NOT_AVAILABLE_ERROR) + this_frame->stop_reason = UNWIND_UNAVAILABLE; + else + throw_exception (ex); + } + END_CATCH if (this_frame->stop_reason != UNWIND_NO_REASON) { @@ -2596,11 +2649,23 @@ get_frame_locals_address (struct frame_info *fi) /* If there isn't a frame address method, find it. */ if (fi->base == NULL) fi->base = frame_base_find_by_frame (fi); - /* Sneaky: If the low-level unwind and high-level base code share a - common unwinder, let them share the prologue cache. */ - if (fi->base->unwind == fi->unwind) - return fi->base->this_locals (fi, &fi->prologue_cache); - return fi->base->this_locals (fi, &fi->base_cache); + + TRY + { + /* Sneaky: If the low-level unwind and high-level base code share a + common unwinder, let them share the prologue cache. */ + if (fi->base->unwind == fi->unwind) + return fi->base->this_locals (fi, &fi->prologue_cache); + return fi->base->this_locals (fi, &fi->base_cache); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + } + END_CATCH + + return 0; } CORE_ADDR @@ -2611,11 +2676,23 @@ get_frame_args_address (struct frame_info *fi) /* If there isn't a frame address method, find it. */ if (fi->base == NULL) fi->base = frame_base_find_by_frame (fi); - /* Sneaky: If the low-level unwind and high-level base code share a - common unwinder, let them share the prologue cache. */ - if (fi->base->unwind == fi->unwind) - return fi->base->this_args (fi, &fi->prologue_cache); - return fi->base->this_args (fi, &fi->base_cache); + + TRY + { + /* Sneaky: If the low-level unwind and high-level base code share a + common unwinder, let them share the prologue cache. */ + if (fi->base->unwind == fi->unwind) + return fi->base->this_args (fi, &fi->prologue_cache); + return fi->base->this_args (fi, &fi->base_cache); + } + CATCH (ex, RETURN_MASK_ERROR) + { + if (ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + } + END_CATCH + + return 0; } /* Return true if the frame unwinder for frame FI is UNWINDER; false