From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by sourceware.org (Postfix) with ESMTPS id 9167F3858D3C for ; Sun, 6 Feb 2022 16:18:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 9167F3858D3C Received: by mail-wr1-x42e.google.com with SMTP id c19so6030082wrb.10 for ; Sun, 06 Feb 2022 08:18:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=Uc+TXb9ZgTke0AUc2ebwSGc25m8oVmebF4DcxKXem7c=; b=gyO4N0ISW7juRQ9V9ks09xZNsn4gavVSu7T7VCQRzlbi3WbtmhObmbtrUG1eFpUUDM qsY/ZnQj3AOuF6qzkgyQQT0uj2qPOQNezveFe+G20mOvmTNPPyjVTBckUUQjeeNnYKzl OSvLVZc5hOnN4hKf3mIgkf+j4Svm2hwz0wt2BFmXNKyRIrlHv0xBrXvZ8wufhesV6Brb OP/9AbIiYfbfCs/PAKsmH9zstOCI9rw6R+xTOQQ1EY0VdIq1OGde4DQGT1sMoJ712wXs xklK7bOCC9g+23UFUozGFPCUGNoPo1zkij+oACGridUTkxqVD/fi0PUl1Cg1AxxnZhSK gHOw== X-Gm-Message-State: AOAM5309IwlSsaqr6N9OSf9JVYDDGXEZNhemN8XHqZu/UUJONhooHpK8 wlK/wYGNjMS0Q5Zd6wd5NIy5 X-Google-Smtp-Source: ABdhPJw1wMM+IpGFM1xdM492bRvD9JpqJmOlHEQCA+d9PAHTYKtRisFZfZkVHA7D3gNLt96/qj3Vzw== X-Received: by 2002:a5d:6d87:: with SMTP id l7mr4164435wrs.326.1644164333348; Sun, 06 Feb 2022 08:18:53 -0800 (PST) Received: from takamaka.home ([165.169.246.70]) by smtp.gmail.com with ESMTPSA id d7sm896422wrw.98.2022.02.06.08.18.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 06 Feb 2022 08:18:52 -0800 (PST) Received: by takamaka.home (Postfix, from userid 1000) id DC9BDA160D; Sun, 6 Feb 2022 20:18:48 +0400 (+04) Date: Sun, 6 Feb 2022 17:18:48 +0100 From: Joel Brobecker To: Christophe Lyon via Gdb-patches Cc: torbjorn.svensson@st.com, Joel Brobecker Subject: Re: [PATCH v2 5/5] gdb/arm: Extend arm_m_addr_is_magic to support FNC_RETURN, add unwind-ns-to-s command Message-ID: References: <20220127133247.440019-1-christophe.lyon@foss.st.com> <20220127133247.440019-5-christophe.lyon@foss.st.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20220127133247.440019-5-christophe.lyon@foss.st.com> X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org 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: , X-List-Received-Date: Sun, 06 Feb 2022 16:18:57 -0000 > This patch makes use of the support for several stack pointers > introduced by the previous patch to switch between them as needed > during unwinding. > > It introduces a new 'unwind-ns-to-s' arm command to enable/disable > mode switching during unwinding. It is enabled by default. > > It has been tested using an STM32L5 board (with cortex-m33) and the > sample applications shipped with the STM32Cube development > environment: GTZC_TZSC_MPCBB_TrustZone in > STM32CubeL5/Projects/NUCLEO-L552ZE-Q/Examples/GTZC. > > The test consisted in setting breakpoints in various places and check > that the backtrace is correct: SecureFault_Callback (Non-secure mode), > __gnu_cmse_nonsecure_call (before and after the vpush instruction), > SecureFault_Handler (Secure mode). > > This implies that we tested only some parts of this patch (only MSP* > were used), but remaining parts seem reasonable. Would it be possible to test this on an Arm-Linux system, for instance? I think it is important in this case, given the nature of the patch, and the code it touches. Note that the NEWS patch need a review from Eli Z. A few comments and questions. > > Co-Authored-By: Torbjorn Svensson > --- > gdb/NEWS | 5 + > gdb/arm-tdep.c | 341 ++++++++++++++++++++++++++++++++++++-------- > gdb/doc/gdb.texinfo | 11 ++ > 3 files changed, 295 insertions(+), 62 deletions(-) > > diff --git a/gdb/NEWS b/gdb/NEWS > index eeca1d39b10..0bfa2cfab78 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -4984,6 +4984,11 @@ show arm force-mode > the current CPSR value for instructions without symbols; previous > versions of GDB behaved as if "set arm fallback-mode arm". > > +set arm unwind-ns-to-s > + Enable unwinding from Non-secure to Secure mode on Cortex-M with > + Security extension. > + This can trigger security exception when unwinding exception stack. > + > set disable-randomization > show disable-randomization > Standalone programs run with the virtual address space randomization enabled > diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c > index db8316ea970..5dd26f772a5 100644 > --- a/gdb/arm-tdep.c > +++ b/gdb/arm-tdep.c > @@ -447,6 +447,36 @@ arm_cache_set_prev_sp (struct arm_prologue_cache *cache, arm_gdbarch_tdep *tdep, > gdb_assert_not_reached ("Invalid SP selection"); > } > > +static bool > +arm_cache_is_sp_register (struct arm_prologue_cache *cache, arm_gdbarch_tdep *tdep, int regnum) Can you add some documentation to all new functions introduced by this patch, please? > +{ > + if ((regnum == ARM_SP_REGNUM) > + || (regnum == tdep->m_profile_msp_regnum) > + || (regnum == tdep->m_profile_msp_s_regnum) > + || (regnum == tdep->m_profile_msp_ns_regnum) > + || (regnum == tdep->m_profile_psp_regnum) > + || (regnum == tdep->m_profile_psp_s_regnum) > + || (regnum == tdep->m_profile_psp_ns_regnum)) > + return true; > + else > + return false; > +} > + > +static void > +arm_cache_switch_prev_sp (struct arm_prologue_cache *cache, arm_gdbarch_tdep *tdep, > + int sp_regnum) > +{ > + gdb_assert (sp_regnum != ARM_SP_REGNUM); > + if (cache->have_sec_ext) > + gdb_assert (sp_regnum != tdep->m_profile_msp_regnum > + && sp_regnum != tdep->m_profile_psp_regnum); > + > + if (!arm_cache_is_sp_register (cache, tdep, sp_regnum)) > + gdb_assert_not_reached ("Invalid SP selection"); Why not use a simple gdb_assertt rather than an assert_not_reached inside an if condition. > + cache->active_sp_regnum = sp_regnum; > +} > + > namespace { > > /* Abstract class to read ARM instructions from memory. */ > @@ -483,6 +513,7 @@ static CORE_ADDR arm_analyze_prologue > /* See arm-tdep.h. */ > > bool arm_apcs_32 = true; > +bool arm_unwind_ns_to_s = true; > > /* Return the bit mask in ARM_PS_REGNUM that indicates Thumb mode. */ > > @@ -699,28 +730,43 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr) > 0xFFFFFFBC Return to Thread mode using the process stack. */ > > static int > -arm_m_addr_is_magic (CORE_ADDR addr) > -{ > - switch (addr) > - { > - /* Values from ARMv8-M Architecture Technical Reference. */ > - case 0xffffffb0: > - case 0xffffffb8: > - case 0xffffffbc: > - /* Values from Tables in B1.5.8 the EXC_RETURN definitions of > - the exception return behavior. */ > - case 0xffffffe1: > - case 0xffffffe9: > - case 0xffffffed: > - case 0xfffffff1: > - case 0xfffffff9: > - case 0xfffffffd: > - /* Address is magic. */ > - return 1; > +arm_m_addr_is_magic (struct gdbarch *gdbarch, CORE_ADDR addr) > +{ > + arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch); > + if (tdep->have_sec_ext) > + { > + switch ((addr & 0xff000000)) > + { > + case 0xff000000: /* EXC_RETURN pattern. */ > + case 0xfe000000: /* FNC_RETURN pattern. */ > + return 1; > + default: > + return 0; > + } > + } > + else > + { > + switch (addr) > + { > + /* Values from ARMv8-M Architecture Technical Reference. */ > + case 0xffffffb0: > + case 0xffffffb8: > + case 0xffffffbc: > + /* Values from Tables in B1.5.8 the EXC_RETURN definitions of > + the exception return behavior. */ > + case 0xffffffe1: > + case 0xffffffe9: > + case 0xffffffed: > + case 0xfffffff1: > + case 0xfffffff9: > + case 0xfffffffd: > + /* Address is magic. */ > + return 1; > > - default: > - /* Address is not magic. */ > - return 0; > + default: > + /* Address is not magic. */ > + return 0; > + } > } > } > > @@ -732,7 +778,7 @@ arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val) > > /* On M-profile devices, do not strip the low bit from EXC_RETURN > (the magic exception return address). */ > - if (tdep->is_m && arm_m_addr_is_magic (val)) > + if (tdep->is_m && arm_m_addr_is_magic (gdbarch, val)) > return val; > > if (arm_apcs_32) > @@ -2172,6 +2218,7 @@ arm_prologue_prev_register (struct frame_info *this_frame, > struct gdbarch *gdbarch = get_frame_arch (this_frame); > arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch); > struct arm_prologue_cache *cache; > + gdb::optional sp_value; > > if (*this_cache == NULL) > *this_cache = arm_make_prologue_cache (this_frame); > @@ -2198,6 +2245,12 @@ arm_prologue_prev_register (struct frame_info *this_frame, > return frame_unwind_got_constant (this_frame, prev_regnum, > arm_cache_get_prev_sp (cache, tdep)); > > + /* The value might be one of the alternative SP, if so, use the > + * value already constructed. */ The GNU Coding Standard say ask that we do not use the leading "*" in multiline comments. > + sp_value = arm_cache_get_sp_register (cache, tdep, prev_regnum); > + if (sp_value.has_value ()) > + return frame_unwind_got_constant (this_frame, prev_regnum, *sp_value); > + > /* The CPSR may have been changed by the call instruction and by the > called function. The only bit we can reconstruct is the T bit, > by checking the low bit of LR as of the call. This is a reliable > @@ -3188,16 +3241,20 @@ static struct arm_prologue_cache * > 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); > arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch); > + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); > struct arm_prologue_cache *cache; > CORE_ADDR lr; > + CORE_ADDR sp; > CORE_ADDR unwound_sp; > + uint32_t sp_r0_offset = 0; > LONGEST xpsr; > uint32_t exc_return; > - uint32_t process_stack_used; > + uint32_t fnc_return; > uint32_t extended_frame_used; > - uint32_t secure_stack_used; > + uint32_t secure_stack_used = 0; > + uint32_t default_callee_register_stacking = 0; > + uint32_t exception_domain_is_secure = 0; > > cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache); > arm_cache_init (cache, this_frame); > @@ -3207,35 +3264,124 @@ arm_m_exception_cache (struct frame_info *this_frame) > to the exception and if FPU is used (causing extended stack frame). */ > > lr = get_frame_register_unsigned (this_frame, ARM_LR_REGNUM); > + sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); > > - /* Check EXC_RETURN indicator bits. */ > - exc_return = (((lr >> 28) & 0xf) == 0xf); > + fnc_return = ((lr & 0xfffffffe) == 0xfefffffe); > + if (tdep->have_sec_ext && fnc_return) > + { > + int actual_sp; > + > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_msp_ns_regnum); > + arm_cache_set_prev_sp (cache, tdep, sp); > + if (lr & 1) > + actual_sp = tdep->m_profile_msp_s_regnum; > + else > + actual_sp = tdep->m_profile_msp_ns_regnum; > > - /* Check EXC_RETURN bit SPSEL if Main or Thread (process) stack used. */ > - process_stack_used = ((lr & (1 << 2)) != 0); > - if (exc_return && process_stack_used) > + arm_cache_switch_prev_sp (cache, tdep, actual_sp); > + sp = get_frame_register_unsigned (this_frame, actual_sp); > + > + cache->saved_regs[ARM_LR_REGNUM].set_addr (sp); > + > + arm_cache_set_prev_sp (cache, tdep, sp + 8); > + > + return cache; > + } > + > + /* Check EXC_RETURN indicator bits. */ > + exc_return = (((lr >> 24) & 0xff) == 0xff); Can you confirm that the use of 24 rather than 28 is deliberate (I don't know Arm that well)? > + if (exc_return) > { > - /* Thread (process) stack used, use PSP as SP. */ > - unwound_sp = get_frame_register_unsigned (this_frame, tdep->m_profile_psp_regnum); > + /* Check EXC_RETURN bit SPSEL if Main or Thread (process) stack used. */ > + uint32_t process_stack_used = ((lr & (1 << 2)) != 0); > + > + if (tdep->have_sec_ext) > + { > + secure_stack_used = ((lr & (1 << 6)) != 0); > + default_callee_register_stacking = ((lr & (1 << 5)) != 0); > + exception_domain_is_secure = ((lr & (1 << 0)) == 0); > + > + /* Unwinding from non-secure to secure can trip security > + * measures. In order to avoid the debugger to be > + * intrusive, rely on the user to configure the requested > + * mode. > + */ Same comment about the leading '*'. Also, can you put the closing '*/' on the same line as the last sentence? > + if (secure_stack_used && !exception_domain_is_secure > + && !arm_unwind_ns_to_s) > + { > + warning (_("Non-secure to secure stack unwinding disabled.")); > + > + /* Terminate any further stack unwinding by refer to self. */ > + arm_cache_set_prev_sp (cache, tdep, sp); > + return cache; > + } > + > + if (process_stack_used) > + { > + if (secure_stack_used) > + /* Secure thread (process) stack used, use PSP_S as SP. */ > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_psp_s_regnum); > + else > + /* Non-secure thread (process) stack used, use PSP_NS as SP. */ > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_psp_ns_regnum); > + } > + else > + { > + if (secure_stack_used) > + /* Secure main stack used, use MSP_S as SP. */ > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_msp_s_regnum); > + else > + /* Non-secure main stack used, use MSP_NS as SP. */ > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_msp_ns_regnum); > + } > + } > + else > + { > + if (process_stack_used) > + /* Thread (process) stack used, use PSP as SP. */ > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_psp_regnum); > + else > + /* Main stack used, use MSP as SP. */ > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_msp_regnum); > + } > } > else > { > /* Main stack used, use MSP as SP. */ > - unwound_sp = get_frame_register_unsigned (this_frame, tdep->m_profile_msp_regnum); > + arm_cache_switch_prev_sp (cache, tdep, tdep->m_profile_msp_regnum); > + } > + > + /* Fetch the SP to use for this frame. */ > + unwound_sp = arm_cache_get_prev_sp (cache, tdep); > + > + /* With the Security extension, the hardware saves R4..R11 too. */ > + if (exc_return && tdep->have_sec_ext && secure_stack_used > + && (!default_callee_register_stacking || exception_domain_is_secure)) > + { > + /* Read R4..R11 from the integer callee registers. */ > + cache->saved_regs[4].set_addr (unwound_sp + 0x08); > + cache->saved_regs[5].set_addr (unwound_sp + 0x0C); > + cache->saved_regs[6].set_addr (unwound_sp + 0x10); > + cache->saved_regs[7].set_addr (unwound_sp + 0x14); > + cache->saved_regs[8].set_addr (unwound_sp + 0x18); > + cache->saved_regs[9].set_addr (unwound_sp + 0x1C); > + cache->saved_regs[10].set_addr (unwound_sp + 0x20); > + cache->saved_regs[11].set_addr (unwound_sp + 0x24); > + sp_r0_offset = 0x28; > } > > /* 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 > "ARMv7-M Architecture Reference Manual". */ > - cache->saved_regs[0].set_addr (unwound_sp); > - cache->saved_regs[1].set_addr (unwound_sp + 4); > - cache->saved_regs[2].set_addr (unwound_sp + 8); > - cache->saved_regs[3].set_addr (unwound_sp + 12); > - cache->saved_regs[ARM_IP_REGNUM].set_addr (unwound_sp + 16); > - cache->saved_regs[ARM_LR_REGNUM].set_addr (unwound_sp + 20); > - cache->saved_regs[ARM_PC_REGNUM].set_addr (unwound_sp + 24); > - cache->saved_regs[ARM_PS_REGNUM].set_addr (unwound_sp + 28); > + cache->saved_regs[0].set_addr (unwound_sp + sp_r0_offset); > + cache->saved_regs[1].set_addr (unwound_sp + sp_r0_offset + 4); > + cache->saved_regs[2].set_addr (unwound_sp + sp_r0_offset + 8); > + cache->saved_regs[3].set_addr (unwound_sp + sp_r0_offset + 12); > + cache->saved_regs[ARM_IP_REGNUM].set_addr (unwound_sp + sp_r0_offset + 16); > + cache->saved_regs[ARM_LR_REGNUM].set_addr (unwound_sp + sp_r0_offset + 20); > + cache->saved_regs[ARM_PC_REGNUM].set_addr (unwound_sp + sp_r0_offset + 24); > + cache->saved_regs[ARM_PS_REGNUM].set_addr (unwound_sp + sp_r0_offset + 28); > > /* Check EXC_RETURN bit FTYPE if extended stack frame (FPU regs stored) > type used. */ > @@ -3254,41 +3400,43 @@ arm_m_exception_cache (struct frame_info *this_frame) > This register is located at address 0xE000EF34. */ > > /* Extended stack frame type used. */ > - fpu_regs_stack_offset = unwound_sp + 0x20; > + fpu_regs_stack_offset = unwound_sp + sp_r0_offset + 0x20; > for (i = 0; i < 16; i++) > { > cache->saved_regs[ARM_D0_REGNUM + i].set_addr (fpu_regs_stack_offset); > fpu_regs_stack_offset += 4; > } > - cache->saved_regs[ARM_FPSCR_REGNUM].set_addr (unwound_sp + 0x60); > + cache->saved_regs[ARM_FPSCR_REGNUM].set_addr (unwound_sp + sp_r0_offset + 0x60); > + fpu_regs_stack_offset += 4; > > - /* Offset 0x64 is reserved. */ > - arm_cache_set_prev_sp (cache, tdep, unwound_sp + 0x68); > + if (tdep->have_sec_ext && !default_callee_register_stacking) > + { > + /* Handle floating-point callee saved registers. */ > + fpu_regs_stack_offset = 0x90; > + for (i = 16; i < 32; i++) > + { > + cache->saved_regs[ARM_D0_REGNUM + i].set_addr (fpu_regs_stack_offset); > + fpu_regs_stack_offset += 4; > + } > + > + arm_cache_set_prev_sp (cache, tdep, unwound_sp + sp_r0_offset + 0xD0); > + } > + else > + { > + /* Offset 0x64 is reserved. */ > + arm_cache_set_prev_sp (cache, tdep, unwound_sp + sp_r0_offset + 0x68); > + } > } > else > { > /* Standard stack frame type used. */ > - arm_cache_set_prev_sp (cache, tdep, unwound_sp + 0x20); > - } > - > - /* Check EXC_RETURN bit S if Secure or Non-secure stack used. */ > - secure_stack_used = ((lr & (1 << 6)) != 0); > - if (exc_return && secure_stack_used) > - { > - /* ARMv8-M Exception and interrupt handling is not considered here. > - In the ARMv8-M architecture also EXC_RETURN bit S is controlling if > - the Secure or Non-secure stack was used. To separate Secure and > - Non-secure stacks, processors that are based on the ARMv8-M > - architecture support 4 stack pointers: MSP_S, PSP_S, MSP_NS, PSP_NS. > - In addition, a stack limit feature is provided using stack limit > - registers (accessible using MSR and MRS instructions) in Privileged > - level. */ > + arm_cache_set_prev_sp (cache, tdep, unwound_sp + sp_r0_offset + 0x20); > } > > /* If bit 9 of the saved xPSR is set, then there is a four-byte > aligner between the top of the 32-byte stack frame and the > previous context's stack pointer. */ > - if (safe_read_memory_integer (unwound_sp + 28, 4, byte_order, &xpsr) > + if (safe_read_memory_integer (unwound_sp + sp_r0_offset + 28, 4, byte_order, &xpsr) > && (xpsr & (1 << 9)) != 0) > arm_cache_set_prev_sp (cache, tdep, arm_cache_get_prev_sp (cache, tdep) + 4); > > @@ -3325,6 +3473,7 @@ arm_m_exception_prev_register (struct frame_info *this_frame, > int prev_regnum) > { > struct arm_prologue_cache *cache; > + gdb::optional sp_value; > > if (*this_cache == NULL) > *this_cache = arm_m_exception_cache (this_frame); > @@ -3337,6 +3486,21 @@ arm_m_exception_prev_register (struct frame_info *this_frame, > return frame_unwind_got_constant (this_frame, prev_regnum, > arm_cache_get_prev_sp (cache, tdep)); > > + /* The value might be one of the alternative SP, if so, use the > + * value already constructed. */ Same as above. > + sp_value = arm_cache_get_sp_register (cache, tdep, prev_regnum); > + if (sp_value.has_value ()) > + return frame_unwind_got_constant (this_frame, prev_regnum, *sp_value); > + > + if (prev_regnum == ARM_PC_REGNUM) > + { > + CORE_ADDR lr = frame_unwind_register_unsigned (this_frame, ARM_LR_REGNUM); > + struct gdbarch *gdbarch = get_frame_arch (this_frame); > + > + return frame_unwind_got_constant (this_frame, prev_regnum, > + arm_addr_bits_remove (gdbarch, lr)); > + } > + > return trad_frame_get_prev_register (this_frame, cache->saved_regs, > prev_regnum); > } > @@ -3349,13 +3513,14 @@ arm_m_exception_unwind_sniffer (const struct frame_unwind *self, > struct frame_info *this_frame, > void **this_prologue_cache) > { > + struct gdbarch *gdbarch = get_frame_arch (this_frame); > CORE_ADDR this_pc = get_frame_pc (this_frame); > > /* No need to check is_m; this sniffer is only registered for > M-profile architectures. */ > > /* Check if exception frame returns to a magic PC value. */ > - return arm_m_addr_is_magic (this_pc); > + return arm_m_addr_is_magic (gdbarch, this_pc); > } > > /* Frame unwinder for M-profile exceptions. */ > @@ -8771,6 +8936,15 @@ arm_show_force_mode (struct ui_file *file, int from_tty, > arm_force_mode_string); > } > > +static void > +arm_show_unwind_ns_to_s (struct ui_file *file, int from_tty, > + struct cmd_list_element *c, const char *value) > +{ > + fprintf_filtered (file, > + _("Usage of non-secure to secure exception stack unwinding is %s.\n"), > + arm_unwind_ns_to_s ? "on" : "off"); > +} > + > /* If the user changes the register disassembly style used for info > register and other commands, we have to also switch the style used > in opcodes for disassembly output. This function is run in the "set > @@ -9676,6 +9850,40 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) > } > > } > + feature = tdesc_find_feature (tdesc, > + "org.gnu.gdb.arm.secext"); > + if (feature != nullptr) > + { > + /* Secure/Non-secure stack pointers. */ > + /* MSP_NS */ > + valid_p = tdesc_numbered_register (feature, tdesc_data.get (), > + register_count, "msp_ns"); > + if (valid_p) > + m_profile_msp_ns_regnum = register_count++; > + > + /* PSP_NS */ > + valid_p = tdesc_numbered_register (feature, tdesc_data.get (), > + register_count, "psp_ns"); > + if (valid_p) > + m_profile_psp_ns_regnum = register_count++; > + > + /* MSP_S */ > + valid_p = tdesc_numbered_register (feature, tdesc_data.get (), > + register_count, "msp_s"); > + if (valid_p) > + m_profile_msp_s_regnum = register_count++; > + > + /* PSP_S */ > + valid_p = tdesc_numbered_register (feature, tdesc_data.get (), > + register_count, "psp_s"); > + if (valid_p) > + m_profile_psp_s_regnum = register_count++; > + > + if (!valid_p) > + return NULL; > + > + have_sec_ext = true; > + } > } > > /* If there is already a candidate, use it. */ > @@ -10150,6 +10358,15 @@ vfp - VFP co-processor."), > NULL, NULL, arm_show_force_mode, > &setarmcmdlist, &showarmcmdlist); > > + /* Add a command to stop triggering security exception when > + * unwinding exception stack. */ Same as above. > + add_setshow_boolean_cmd ("unwind-ns-to-s", no_class, &arm_unwind_ns_to_s, > + _("Set usage of non-secure to secure exception stack unwinding."), > + _("Show usage of non-secure to secure exception stack unwinding."), > + _("When on, the debugger can trigger memory access traps."), > + NULL, arm_show_unwind_ns_to_s, > + &setarmcmdlist, &showarmcmdlist); > + > /* Debugging flag. */ > add_setshow_boolean_cmd ("arm", class_maintenance, &arm_debug, > _("Set ARM debugging."), > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index 9d507795993..66912684379 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -24894,6 +24894,17 @@ of @samp{set arm fallback-mode}. > > @item show arm force-mode > Show the current forced instruction mode. > +Show the currently used ABI. > + > +@item set arm unwind-ns-to-s > +This command enables unwinding from Non-secure to Secure mode on > +Cortex-M with Security extension. > +This can trigger security exceptions when unwinding the exception > +stack. > +It is enabled by default. > + > +@item show arm unwind-ns-to-s > +Show whether unwind from Non-secure to Secure mode is enabled. > > @item set debug arm > Toggle whether to display ARM-specific debugging messages from the ARM > -- > 2.25.1 > -- Joel