From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id JsXqIqJ9SGF+CwAAWB0awg (envelope-from ) for ; Mon, 20 Sep 2021 08:25:06 -0400 Received: by simark.ca (Postfix, from userid 112) id 7DE301EE25; Mon, 20 Sep 2021 08:25:06 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=MAILING_LIST_MULTI, NICE_REPLY_A autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 098DB1EE14 for ; Mon, 20 Sep 2021 08:25:05 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 58A713858C3A for ; Mon, 20 Sep 2021 12:25:04 +0000 (GMT) Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) by sourceware.org (Postfix) with ESMTPS id F0FFD3858C60 for ; Mon, 20 Sep 2021 12:24:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org F0FFD3858C60 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=palves.net Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f52.google.com with SMTP id q11so29121354wrr.9 for ; Mon, 20 Sep 2021 05:24:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:subject:from:to:cc:references:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=XC8OEHU0C+2d81IhFsGbnLud8duKqUnGcsirgV9rShw=; b=lS/gGCJ2OtlWa6/bujEWwwndCRht1fpGuEllNNefPjap+GnhJgCnkeDleOtNUNzS6F XlSfiH1bDF0bxRgefhw81d60pYbQhcbRxm6T+8SfM4Jg+B9x9rVZUJefrngL514Qwhej HQuP9KNWIKZ/d9+J2Ze3WLS3A0FaEfz4TFeU6YUgKh0V0KdTXH/0X1TIbZY3FOpkONV3 Ll99/iiNDhjn8TnlQNQFtpp78h8pirqHvSleMGj4ybra2HBN9CjmWvPMKc4ZenzzPFtj oBK7xFyN9neLuGo6nPATRX8KrtcL13SRAp2Fl/KDLChZlgnE4l+MC7YUa/+QHPE/yfnN EcIw== X-Gm-Message-State: AOAM532unjyatapjE3ZajpNIIfLz+haKE/ZdbhcE9NRN+6UVeZUTiEXo E2yxLNMBB0gGDRAjgwoIijQTwhOXncM= X-Google-Smtp-Source: ABdhPJy/ZbftHuqR0x4DruqHHVSs8BxwY8vrCSJkNCb3azFV7xT1agFJngbnUA2fc7i2L2fk/3oc0Q== X-Received: by 2002:adf:d08d:: with SMTP id y13mr28907679wrh.156.1632140691857; Mon, 20 Sep 2021 05:24:51 -0700 (PDT) Received: from ?IPv6:2001:8a0:f932:6a00:46bc:d03b:7b3a:2227? ([2001:8a0:f932:6a00:46bc:d03b:7b3a:2227]) by smtp.gmail.com with ESMTPSA id n68sm19723491wmn.13.2021.09.20.05.24.50 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 20 Sep 2021 05:24:51 -0700 (PDT) Subject: Re: [PATCHv5] gdb: prevent an assertion when computing the frame_id for an inline frame From: Pedro Alves To: Andrew Burgess , gdb-patches@sourceware.org References: <20210727101003.2910993-1-andrew.burgess@embecosm.com> <20210809154122.3468792-1-andrew.burgess@embecosm.com> Message-ID: Date: Mon, 20 Sep 2021 13:24:50 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.14.0 MIME-Version: 1.0 In-Reply-To: <20210809154122.3468792-1-andrew.burgess@embecosm.com> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" Hi Andrew, On 2021-08-09 4:41 p.m., Andrew Burgess wrote: > I've not heard anything from Pedro, but I'd like to move this patch > forward. > > My assumption is that Pedro doesn't like using exceptions to pass > around information for a case that maybe isn't that exceptional. As > Pedro was happy with v2, this new patch removes the use of exceptions. > > Simon's concerns with v1/v2 were, I think, summarised as: > > 1. What get_prev_frame_if_no_cycle does no longer matches the > function name, and > > 2. get_prev_frame_if_no_cycle was trying to figure out the callers > intention in order to change its behaviour. > > To try and address these two things I have: > > 1. Renamed get_prev_frame_if_no_cycle to hopefully make it clearer > that its result is not so clear cut, and > > 2. Changed the behaviour of get_prev_frame_if_no_cycle based on a > passed in parameter instead of "peeking" at various bits of state. > > My hope is that this might be more acceptable to everyone, but I'd > love to hear any thoughts, > To be honest, to me, the new "cycle_detection_p" argument seems pointless/redundant, since inside the function, you have the INLINE_FRAME assertion checks anyhow. I.e., putting: bool cycle_detection_p = get_frame_type (this_frame) != INLINE_FRAME; inside get_prev_frame_with_optional_cycle_detection yields the exact same, IIUC. So adding the argument is just adding scope for someone passing the wrong cycle_detection_p argument at some point, it seems to me. frame.c already has to know special things about inline frames, I mean, even get_prev_frame_always_1 already must know to bypass a bunch of tests for inline frames, like: /* If we are unwinding from an inline frame, all of the below tests were already performed when we unwound from the next non-inline frame. We must skip them, since we can not get THIS_FRAME's ID until we have unwound all the way down to the previous non-inline frame. */ if (get_frame_type (this_frame) == INLINE_FRAME) return get_prev_frame_if_no_cycle (this_frame); I'd remove the cycle_detection_p argument, replacing it said local: bool cycle_detection_p = get_frame_type (this_frame) != INLINE_FRAME; and rename get_prev_frame_if_no_cycle to, say, get_prev_frame_maybe_check_cycle. Like, e.g.: ~~~~ diff --git a/gdb/frame.c b/gdb/frame.c index 6433e9db788..2c9a324c93f 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -2051,16 +2051,14 @@ frame_register_unwind_location (struct frame_info *this_frame, int regnum, the previous frame is a duplicate and we return nullptr then we will be unable to calculate the frame_id of the inline frame, this in turn causes inline_frame_this_id() to fail. So for inline frames (and only - for inline frames) it is acceptable to pass CYCLE_DETECTION_P as false, - in that case the previous frame will always be returned, even when it + for inline frames), the previous frame will always be returned, even when it has a duplicate frame_id. We're not worried about cycles in the frame chain as, if the previous frame returned here has a duplicate frame_id, then the frame_id of the inline frame, calculated based off the frame_id of the previous frame, should also be a duplicate. */ static struct frame_info * -get_prev_frame_with_optional_cycle_detection (struct frame_info *this_frame, - bool cycle_detection_p) +get_prev_frame_maybe_check_cycle (struct frame_info *this_frame) { struct frame_info *prev_frame; @@ -2083,6 +2081,9 @@ get_prev_frame_with_optional_cycle_detection (struct frame_info *this_frame, are simpler. For these frames we immediately compute the frame_id, and so, for those frames, we will always reenter this function with the frame_id status of COMPUTING. */ + + bool cycle_detection_p = get_frame_type (this_frame) != INLINE_FRAME; + gdb_assert (cycle_detection_p || (get_frame_type (this_frame) == INLINE_FRAME && ((this_frame->level > 0 @@ -2193,7 +2194,7 @@ get_prev_frame_always_1 (struct frame_info *this_frame) until we have unwound all the way down to the previous non-inline frame. */ if (get_frame_type (this_frame) == INLINE_FRAME) - return get_prev_frame_with_optional_cycle_detection (this_frame, false); + return get_prev_frame_maybe_check_cycle (this_frame); /* If this_frame is the current frame, then compute and stash its frame id prior to fetching and computing the frame id of the @@ -2294,7 +2295,7 @@ get_prev_frame_always_1 (struct frame_info *this_frame) } } - return get_prev_frame_with_optional_cycle_detection (this_frame, true); + return get_prev_frame_maybe_check_cycle (this_frame); } /* Return a "struct frame_info" corresponding to the frame that called ~~~~ > --- a/gdb/inline-frame.c > +++ b/gdb/inline-frame.c > @@ -163,7 +163,10 @@ inline_frame_this_id (struct frame_info *this_frame, > function, there must be previous frames, so this is safe - as > long as we're careful not to create any cycles. See related > comments in get_prev_frame_always_1. */ > - *this_id = get_frame_id (get_prev_frame_always (this_frame)); > + frame_info *prev_frame = get_prev_frame_always (this_frame); > + if (prev_frame == nullptr) > + error ("failed to find previous frame when computing inline frame id"); Missing _(). But, is this a "just in case" check/error? As in, a softer gdb_assert? With the bug fixed, is this error call ever expected to trigger (modulo other gdb bugs)?