From patchwork Thu Feb 5 19:06:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Machado X-Patchwork-Id: 4928 Received: (qmail 5400 invoked by alias); 5 Feb 2015 19:07:06 -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 5385 invoked by uid 89); 5 Feb 2015 19:07:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: relay1.mentorg.com Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 05 Feb 2015 19:07:04 +0000 Received: from svr-orw-fem-02x.mgc.mentorg.com ([147.34.96.206] helo=SVR-ORW-FEM-02.mgc.mentorg.com) by relay1.mentorg.com with esmtp id 1YJRlV-0004DI-5j from Luis_Gustavo@mentor.com for gdb-patches@sourceware.org; Thu, 05 Feb 2015 11:07:01 -0800 Received: from [172.30.11.130] (147.34.91.1) by svr-orw-fem-02.mgc.mentorg.com (147.34.96.168) with Microsoft SMTP Server id 14.3.224.2; Thu, 5 Feb 2015 11:07:00 -0800 Message-ID: <54D3BF52.5070709@codesourcery.com> Date: Thu, 5 Feb 2015 17:06:58 -0200 From: Luis Machado Reply-To: User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: "'gdb-patches@sourceware.org'" Subject: [PATCH] Relax ARM prologue unwinder assumption X-IsSubscribed: yes Just recently i ran into a problem with a bare metal ARM target where GDB would not allow some registers to be changed after the PC was manually set to some other value. In reality the target had just started and one of its cores, out of four, was running the program, but the other ones were in some random state. The PC of one of the other 3 cores was then adjusted to point to a known function address. GDB's reaction to this change is to invalidate the regcache and frame and build a brand new chain and cache, while trying to retain the previously selected frame - #0 in this case. What i noticed is that GDB was selecting frame #1 instead of #0 due to unfortunate coincidences with both frames' SP's being 0. And we can't modify some registers on non-innermost frames for obvious reasons. Here's a brief log of what happens: [Switching to thread 2 (Thread 2)] #0 0x0093ff10 in ?? () (gdb) set $pc=functioncore2 (gdb) bt #0 functioncore2 () at test.c:32 #1 0x0000fc44 in ?? () (gdb) frame #1 0x0000fc44 in ?? () (gdb) set $sp=0x2030 Attempt to assign to an unmodifiable value. I tracked this problem down to this old (https://sourceware.org/ml/gdb-patches/2003-08/msg00526.html) piece of code in arm-tdep.c:arm_prologue_this_id: /* If we've hit a wall, stop. */ if (cache->prev_sp == 0) return; Due to the SP being 0 for this specific core, GDB returns early and does not set the frame's PC to the new value. That means we have a frame with PC==0x0 and SP==0x0, which ends up matching frame #1 in our case. But this is obviously wrong. I looked up the patch that introduced this chunk of code and did not find any reasonable explanation for this check. Though it may make sense for non-bare metal targets, a bare-metal board attached to a probe can be stopped at any random place, so we should be able to set its registers freely without worrying about unwinding assumptions. This is generic code after all. I understand a valid workaround is to make sure the proper frame is selected, but GDB should be smart enough not to confuse things. Therefore this "wall" described in the comment seems too strict to be in generic code. The attached patch removes this restriction and does not cause any regressions for ARM bare metal, but i'd like feedback. 2015-02-05 Luis Machado * arm-tdep.c (arm_prologue_this_id): Remove check for the stack pointer being 0. diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 8e9552a..771cbeb 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -2042,10 +2042,6 @@ arm_prologue_this_id (struct frame_info *this_frame, if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc) return; - /* If we've hit a wall, stop. */ - if (cache->prev_sp == 0) - return; - /* Use function start address as part of the frame ID. If we cannot identify the start address (due to missing symbol information), fall back to just using the current PC. */