From patchwork Sat Sep 20 22:47:07 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jon Burgess X-Patchwork-Id: 2935 Received: (qmail 16492 invoked by alias); 20 Sep 2014 22:47: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 16479 invoked by uid 89); 20 Sep 2014 22:47:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=BAYES_00, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-wg0-f42.google.com Received: from mail-wg0-f42.google.com (HELO mail-wg0-f42.google.com) (74.125.82.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Sat, 20 Sep 2014 22:47:12 +0000 Received: by mail-wg0-f42.google.com with SMTP id a1so1110180wgh.1 for ; Sat, 20 Sep 2014 15:47:09 -0700 (PDT) X-Received: by 10.194.188.110 with SMTP id fz14mr10509514wjc.70.1411253229089; Sat, 20 Sep 2014 15:47:09 -0700 (PDT) Received: from ?IPv6:2001:8b0:8e2:c166:21b:21ff:fe15:12e? (e.2.1.0.5.1.e.f.f.f.1.2.b.1.2.0.6.6.1.c.2.e.8.0.0.b.8.0.1.0.0.2.ip6.arpa. [2001:8b0:8e2:c166:21b:21ff:fe15:12e]) by mx.google.com with ESMTPSA id wp7sm6983901wjc.12.2014.09.20.15.47.07 for (version=SSLv3 cipher=RC4-SHA bits=128/128); Sat, 20 Sep 2014 15:47:08 -0700 (PDT) Message-ID: <1411253227.22117.27.camel@shark.nightingale.homedns.org> Subject: [RFC][PATCH] arm-tdep.c (arm_m_exception_cache): Handle stack switching to PSP during exception unwind. From: Jon Burgess To: gdb-patches@sourceware.org Date: Sat, 20 Sep 2014 23:47:07 +0100 Mime-Version: 1.0 X-IsSubscribed: yes The current GDB code sometimes unwinds the exception stack incorrectly on a Cortex-M3 based CPU (Atmel ATSAM3X8E). The problem is that the current stack unwinding code does not take into account that the stack pointer may switch from the main stack pointer (MSP) to the process stack pointer (PSP) when the exception returns. The result is that the code displayed as executing at the time of the exception is incorrect: (gdb) bt #0 delayMS (millis=300) at FreeRTOS_ARM/FreeRTOS_ARM.c:17 #1 errorBlink (n=n@entry=1) at FreeRTOS_ARM/FreeRTOS_ARM.c:32 #2 0x00085cd4 in HardFault_Handler () at FreeRTOS_ARM/FreeRTOS_ARM.c:44 #3 #4 0x0008684e in prvPortStartFirstTask () at FreeRTOS_ARM/utility/port.c:277 #5 0x00086a38 in xPortStartScheduler () at FreeRTOS_ARM/utility/port.c:356 #6 0xa5a5a5a4 in ?? () With the patch applied the code which accessed the bad pointer to trigger the exception is displayed instead: (gdb) bt #0 delayMS (millis=300) at FreeRTOS_ARM/FreeRTOS_ARM.c:17 #1 errorBlink (n=n@entry=1) at FreeRTOS_ARM/FreeRTOS_ARM.c:32 #2 0x00085cd4 in HardFault_Handler () at FreeRTOS_ARM/FreeRTOS_ARM.c:44 #3 #4 xQueueGenericReceive (xQueue=0xa5a5a5a5, pvBuffer=0x20082856, xTicksToWait=4294967295, xJustPeeking=0) at FreeRTOS_ARM/utility/queue.c:1193 #5 0x00085214 in BuzzerTask::task (this=0x2007f5c0) at BuzzerTask.cpp:68 #6 0x000818ec in Task::taskCaller (this=0x2007f5c0) at Task.cpp:78 #7 0x0008193e in Task::_task (self=) at Task.cpp:87 #8 0x000868bc in ulPortSetInterruptMask () at FreeRTOS_ARM/utility/port.c:423 I do not know the best way to access the PSP register to find the process stack pointer. It looks like that this has to go via the target description because it is not included in the default register list. In the patch I follow the mechanism that GDB uses to lookup the register number during "p $psp". This patch has only been tested on this single target running FreeRTOS. I used an Olimex ARM-USB-TINY-H with OpenOCD to attach to the device. This my first GDB patch submission and I have not been through this FSF copyright assignment process. 2014-09-20 Jon Burgess * arm-tdep.c (arm_m_exception_cache): Handle stack switching to PSP during exception unwind. @@ -3019,6 +3020,24 @@ arm_m_exception_cache (struct frame_info *this_frame) unwound_sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); + /* The EXC_RETURN address indicates what type of transition + the CPU makes when returning from the exception. A value + of 0xfffffffd causes the stack pointer to switch from + MSP to PSP. */ + if (this_pc == 0xfffffffd) { + int pspreg; + struct regcache *regcache; + struct value *pspval; + + pspreg = user_reg_map_name_to_regnum (gdbarch, "psp", 3); + gdb_assert (pspreg != -1); + + regcache = get_current_regcache (); + pspval = regcache_cooked_read_value (regcache, pspreg); + if (pspval && !value_lazy (pspval)) + unwound_sp = value_as_address (pspval); + } + /* The hardware saves eight 32-bit words, comprising xPSR, ReturnAddress, LR (R14), R12, R3, R2, R1, R0. See details in "B1.5.6 Exception entry behavior" in diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 5cdfc5b..66a0ae8 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -3010,6 +3010,7 @@ arm_m_exception_cache (struct frame_info *this_frame) struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct arm_prologue_cache *cache; + CORE_ADDR this_pc = get_frame_pc (this_frame); CORE_ADDR unwound_sp; LONGEST xpsr;