From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1652) id 46B863857C49; Wed, 27 Apr 2022 14:51:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 46B863857C49 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Christophe Lyon To: gdb-cvs@sourceware.org Subject: [binutils-gdb] gdb/arm: Add support for multiple stack pointers on Cortex-M X-Act-Checkin: binutils-gdb X-Git-Author: Christophe Lyon X-Git-Refname: refs/heads/master X-Git-Oldrev: 0824193fd31467b6ff39132d0d72aaa9c01cc9aa X-Git-Newrev: ae7e2f45aa4798be449f282bbf75ad41e73f055e Message-Id: <20220427145132.46B863857C49@sourceware.org> Date: Wed, 27 Apr 2022 14:51:32 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Apr 2022 14:51:32 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3Dae7e2f45aa47= 98be449f282bbf75ad41e73f055e commit ae7e2f45aa4798be449f282bbf75ad41e73f055e Author: Christophe Lyon Date: Fri Apr 1 10:22:16 2022 +0100 gdb/arm: Add support for multiple stack pointers on Cortex-M =20 Armv8-M architecture with Security extension features four stack pointe= rs to handle Secure and Non-secure modes. =20 This patch adds support to switch between them as needed during unwinding, and replaces all updates of cache->prev_sp with calls to arm_cache_set_prev_sp. =20 Signed-off-by: Torbj=C3=B6rn Svensson Signed-off-by: Christophe Lyon Signed-off-by: Christophe Lyon Diff: --- gdb/arm-tdep.c | 261 ++++++++++++++++++++++++++++++++++++= +--- gdb/arm-tdep.h | 11 +- gdb/features/arm/arm-secext.c | 17 +++ gdb/features/arm/arm-secext.xml | 15 +++ 4 files changed, 284 insertions(+), 20 deletions(-) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index f393a3e4ad6..7a6c1e49125 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -276,7 +276,18 @@ struct arm_prologue_cache /* The stack pointer at the time this frame was created; i.e. the caller's stack pointer when this function was called. It is used to identify this frame. */ - CORE_ADDR prev_sp; + CORE_ADDR sp; + + /* Additional stack pointers used by M-profile with Security extension. = */ + /* Use msp_s / psp_s to hold the values of msp / psp when there is + no Security extension. */ + CORE_ADDR msp_s; + CORE_ADDR msp_ns; + CORE_ADDR psp_s; + CORE_ADDR psp_ns; + + /* Active stack pointer. */ + int active_sp_regnum; =20 /* The frame base for this frame is just prev_sp - frame size. FRAMESIZE is the distance from the frame pointer to the @@ -296,12 +307,28 @@ struct arm_prologue_cache arm_prologue_cache() =3D default; }; =20 +/* Initialize stack pointers, and flag the active one. */ + +static inline void +arm_cache_init_sp (int regnum, CORE_ADDR* member, + struct arm_prologue_cache *cache, + struct frame_info *frame) +{ + CORE_ADDR val =3D get_frame_register_unsigned (frame, regnum); + if (val =3D=3D cache->sp) + cache->active_sp_regnum =3D regnum; + + *member =3D val; +} + /* Initialize CACHE fields for which zero is not adequate (CACHE is expected to have been ZALLOC'ed before calling this function). */ =20 static void arm_cache_init (struct arm_prologue_cache *cache, struct gdbarch *gdbarch) { + cache->active_sp_regnum =3D ARM_SP_REGNUM; + cache->saved_regs =3D trad_frame_alloc_saved_regs (gdbarch); } =20 @@ -311,8 +338,109 @@ static void arm_cache_init (struct arm_prologue_cache *cache, struct frame_info *frame) { struct gdbarch *gdbarch =3D get_frame_arch (frame); + arm_gdbarch_tdep *tdep =3D (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch); =20 arm_cache_init (cache, gdbarch); + + if (tdep->have_sec_ext) + { + arm_cache_init_sp (tdep->m_profile_msp_s_regnum, &cache->msp_s, cach= e, frame); + arm_cache_init_sp (tdep->m_profile_psp_s_regnum, &cache->psp_s, cach= e, frame); + arm_cache_init_sp (tdep->m_profile_msp_ns_regnum, &cache->msp_ns, ca= che, frame); + arm_cache_init_sp (tdep->m_profile_psp_ns_regnum, &cache->psp_ns, ca= che, frame); + + /* Use MSP_S as default stack pointer. */ + if (cache->active_sp_regnum =3D=3D ARM_SP_REGNUM) + cache->active_sp_regnum =3D tdep->m_profile_msp_s_regnum; + } + else if (tdep->is_m) + { + arm_cache_init_sp (tdep->m_profile_msp_regnum, &cache->msp_s, cache,= frame); + arm_cache_init_sp (tdep->m_profile_psp_regnum, &cache->psp_s, cache,= frame); + } + else + arm_cache_init_sp (ARM_SP_REGNUM, &cache->msp_s, cache, frame); +} + +/* Return the requested stack pointer value (in REGNUM), taking into + account whether we have a Security extension or an M-profile + CPU. */ + +static CORE_ADDR +arm_cache_get_sp_register (struct arm_prologue_cache *cache, + arm_gdbarch_tdep *tdep, int regnum) +{ + if (regnum =3D=3D ARM_SP_REGNUM) + return cache->sp; + + if (tdep->have_sec_ext) + { + if (regnum =3D=3D tdep->m_profile_msp_s_regnum) + return cache->msp_s; + if (regnum =3D=3D tdep->m_profile_msp_ns_regnum) + return cache->msp_ns; + if (regnum =3D=3D tdep->m_profile_psp_s_regnum) + return cache->psp_s; + if (regnum =3D=3D tdep->m_profile_psp_ns_regnum) + return cache->psp_ns; + } + else if (tdep->is_m) + { + if (regnum =3D=3D tdep->m_profile_msp_regnum) + return cache->msp_s; + if (regnum =3D=3D tdep->m_profile_psp_regnum) + return cache->psp_s; + } + + gdb_assert_not_reached ("Invalid SP selection"); +} + +/* Return the previous stack address, depending on which SP register + is active. */ + +static CORE_ADDR +arm_cache_get_prev_sp_value (struct arm_prologue_cache *cache, arm_gdbarch= _tdep *tdep) +{ + CORE_ADDR val =3D arm_cache_get_sp_register (cache, tdep, cache->active_= sp_regnum); + return val; +} + +/* Set the active stack pointer to VAL. */ + +static void +arm_cache_set_active_sp_value (struct arm_prologue_cache *cache, + arm_gdbarch_tdep *tdep, CORE_ADDR val) +{ + if (cache->active_sp_regnum =3D=3D ARM_SP_REGNUM) + { + cache->sp =3D val; + return; + } + + if (tdep->have_sec_ext) + { + if (cache->active_sp_regnum =3D=3D tdep->m_profile_msp_s_regnum) + cache->msp_s =3D val; + else if (cache->active_sp_regnum =3D=3D tdep->m_profile_msp_ns_regnu= m) + cache->msp_ns =3D val; + else if (cache->active_sp_regnum =3D=3D tdep->m_profile_psp_s_regnum) + cache->psp_s =3D val; + else if (cache->active_sp_regnum =3D=3D tdep->m_profile_psp_ns_regnu= m) + cache->psp_ns =3D val; + + return; + } + else if (tdep->is_m) + { + if (cache->active_sp_regnum =3D=3D tdep->m_profile_msp_regnum) + cache->msp_s =3D val; + else if (cache->active_sp_regnum =3D=3D tdep->m_profile_psp_regnum) + cache->psp_s =3D val; + + return; + } + + gdb_assert_not_reached ("Invalid SP selection"); } =20 namespace { @@ -2010,14 +2138,17 @@ arm_make_prologue_cache (struct frame_info *this_fr= ame) if (unwound_fp =3D=3D 0) return cache; =20 - cache->prev_sp =3D unwound_fp + cache->framesize; + arm_gdbarch_tdep *tdep =3D + (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + + arm_cache_set_active_sp_value (cache, tdep, unwound_fp + cache->framesiz= e); =20 /* Calculate actual addresses of saved registers using offsets determined by arm_scan_prologue. */ for (reg =3D 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); re= g++) if (cache->saved_regs[reg].is_addr ()) cache->saved_regs[reg].set_addr (cache->saved_regs[reg].addr () - + cache->prev_sp); + + arm_cache_get_prev_sp_value (cache, tdep)); =20 return cache; } @@ -2043,7 +2174,7 @@ arm_prologue_unwind_stop_reason (struct frame_info *t= his_frame, return UNWIND_OUTERMOST; =20 /* If we've hit a wall, stop. */ - if (cache->prev_sp =3D=3D 0) + if (arm_cache_get_prev_sp_value (cache, tdep) =3D=3D 0) return UNWIND_OUTERMOST; =20 return UNWIND_NO_REASON; @@ -2065,6 +2196,9 @@ arm_prologue_this_id (struct frame_info *this_frame, *this_cache =3D arm_make_prologue_cache (this_frame); cache =3D (struct arm_prologue_cache *) *this_cache; =20 + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + /* 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. */ @@ -2073,7 +2207,7 @@ arm_prologue_this_id (struct frame_info *this_frame, if (!func) func =3D pc; =20 - id =3D frame_id_build (cache->prev_sp, func); + id =3D frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), func); *this_id =3D id; } =20 @@ -2114,7 +2248,8 @@ arm_prologue_prev_register (struct frame_info *this_f= rame, identified by the next frame's stack pointer at the time of the call. The value was already reconstructed into PREV_SP. */ if (prev_regnum =3D=3D ARM_SP_REGNUM) - return frame_unwind_got_constant (this_frame, prev_regnum, cache->prev= _sp); + return frame_unwind_got_constant (this_frame, prev_regnum, + arm_cache_get_prev_sp_value (cache, tdep)); =20 /* 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, @@ -2752,7 +2887,9 @@ arm_exidx_fill_cache (struct frame_info *this_frame, = gdb_byte *entry) =3D vsp - get_frame_register_unsigned (this_frame, cache->framereg); =20 /* We already got the previous SP. */ - cache->prev_sp =3D vsp; + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + arm_cache_set_active_sp_value (cache, tdep, vsp); =20 return cache; } @@ -2875,14 +3012,18 @@ arm_make_epilogue_frame_cache (struct frame_info *t= his_frame) arm_scan_prologue (this_frame, cache); =20 /* Since we are in epilogue, the SP has been restored. */ - cache->prev_sp =3D get_frame_register_unsigned (this_frame, ARM_SP_REGNU= M); + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + arm_cache_set_active_sp_value (cache, tdep, + get_frame_register_unsigned (this_frame, + ARM_SP_REGNUM)); =20 /* Calculate actual addresses of saved registers using offsets determined by arm_scan_prologue. */ for (reg =3D 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); re= g++) if (cache->saved_regs[reg].is_addr ()) cache->saved_regs[reg].set_addr (cache->saved_regs[reg].addr () - + cache->prev_sp); + + arm_cache_get_prev_sp_value (cache, tdep)); =20 return cache; } @@ -2910,7 +3051,9 @@ arm_epilogue_frame_this_id (struct frame_info *this_f= rame, if (func =3D=3D 0) func =3D pc; =20 - (*this_id) =3D frame_id_build (cache->prev_sp, pc); + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + *this_id =3D frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), = pc); } =20 /* Implementation of function hook 'prev_register' in @@ -3032,7 +3175,11 @@ arm_make_stub_cache (struct frame_info *this_frame) cache =3D FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache); arm_cache_init (cache, this_frame); =20 - cache->prev_sp =3D get_frame_register_unsigned (this_frame, ARM_SP_REGNU= M); + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + arm_cache_set_active_sp_value (cache, tdep, + get_frame_register_unsigned (this_frame, + ARM_SP_REGNUM)); =20 return cache; } @@ -3050,7 +3197,10 @@ arm_stub_this_id (struct frame_info *this_frame, *this_cache =3D arm_make_stub_cache (this_frame); cache =3D (struct arm_prologue_cache *) *this_cache; =20 - *this_id =3D frame_id_build (cache->prev_sp, get_frame_pc (this_frame)); + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + *this_id =3D frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), + get_frame_pc (this_frame)); } =20 static int @@ -3171,12 +3321,12 @@ arm_m_exception_cache (struct frame_info *this_fram= e) cache->saved_regs[ARM_FPSCR_REGNUM].set_addr (unwound_sp + 0x60); =20 /* Offset 0x64 is reserved. */ - cache->prev_sp =3D unwound_sp + 0x68; + arm_cache_set_active_sp_value (cache, tdep, unwound_sp + 0x68); } else { /* Standard stack frame type used. */ - cache->prev_sp =3D unwound_sp + 0x20; + arm_cache_set_active_sp_value (cache, tdep, unwound_sp + 0x20); } =20 /* Check EXC_RETURN bit S if Secure or Non-secure stack used. */ @@ -3198,7 +3348,8 @@ arm_m_exception_cache (struct frame_info *this_frame) previous context's stack pointer. */ if (safe_read_memory_integer (unwound_sp + 28, 4, byte_order, &xpsr) && (xpsr & (1 << 9)) !=3D 0) - cache->prev_sp +=3D 4; + arm_cache_set_active_sp_value (cache, tdep, + arm_cache_get_prev_sp_value (cache, tdep) + 4); =20 return cache; } @@ -3218,7 +3369,9 @@ arm_m_exception_this_id (struct frame_info *this_fram= e, cache =3D (struct arm_prologue_cache *) *this_cache; =20 /* Our frame ID for a stub frame is the current SP and LR. */ - *this_id =3D frame_id_build (cache->prev_sp, + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + *this_id =3D frame_id_build (arm_cache_get_prev_sp_value (cache, tdep), get_frame_pc (this_frame)); } =20 @@ -3237,9 +3390,11 @@ arm_m_exception_prev_register (struct frame_info *th= is_frame, cache =3D (struct arm_prologue_cache *) *this_cache; =20 /* The value was already reconstructed into PREV_SP. */ + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); if (prev_regnum =3D=3D ARM_SP_REGNUM) return frame_unwind_got_constant (this_frame, prev_regnum, - cache->prev_sp); + arm_cache_get_prev_sp_value (cache, tdep)); =20 return trad_frame_get_prev_register (this_frame, cache->saved_regs, prev_regnum); @@ -3284,7 +3439,9 @@ arm_normal_frame_base (struct frame_info *this_frame,= void **this_cache) *this_cache =3D arm_make_prologue_cache (this_frame); cache =3D (struct arm_prologue_cache *) *this_cache; =20 - return cache->prev_sp - cache->framesize; + arm_gdbarch_tdep *tdep + =3D (arm_gdbarch_tdep *) gdbarch_tdep (get_frame_arch (this_frame)); + return arm_cache_get_prev_sp_value (cache, tdep) - cache->framesize; } =20 struct frame_base arm_normal_base =3D { @@ -9249,6 +9406,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gd= barch_list *arches) tdesc_arch_data_up tdesc_data; int i; bool is_m =3D false; + bool have_sec_ext =3D false; int vfp_register_count =3D 0; bool have_s_pseudos =3D false, have_q_pseudos =3D false; bool have_wmmx_registers =3D false; @@ -9263,6 +9421,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct g= dbarch_list *arches) bool have_m_profile_msp =3D false; int m_profile_msp_regnum =3D -1; int m_profile_psp_regnum =3D -1; + int m_profile_msp_ns_regnum =3D -1; + int m_profile_psp_ns_regnum =3D -1; + int m_profile_msp_s_regnum =3D -1; + int m_profile_psp_s_regnum =3D -1; =20 /* If we have an object to base this architecture on, try to determine its ABI. */ @@ -9679,6 +9841,56 @@ arm_gdbarch_init (struct gdbarch_info info, struct g= dbarch_list *arches) keys. */ have_pacbti =3D true; } + + /* Do we have the Security extension? */ + feature =3D tdesc_find_feature (tdesc, + "org.gnu.gdb.arm.secext"); + if (feature !=3D nullptr) + { + /* Secure/Non-secure stack pointers. */ + /* MSP_NS */ + valid_p &=3D tdesc_numbered_register (feature, tdesc_data.get (), + register_count, "msp_ns"); + if (!valid_p) + { + warning (_("M-profile secext feature is missing required register msp_= ns.")); + return nullptr; + } + m_profile_msp_ns_regnum =3D register_count++; + + /* PSP_NS */ + valid_p &=3D tdesc_numbered_register (feature, tdesc_data.get (), + register_count, "psp_ns"); + if (!valid_p) + { + warning (_("M-profile secext feature is missing required register psp_= ns.")); + return nullptr; + } + m_profile_psp_ns_regnum =3D register_count++; + + /* MSP_S */ + valid_p &=3D tdesc_numbered_register (feature, tdesc_data.get (), + register_count, "msp_s"); + if (!valid_p) + { + warning (_("M-profile secext feature is missing required register msp_= s.")); + return nullptr; + } + m_profile_msp_s_regnum =3D register_count++; + + /* PSP_S */ + valid_p &=3D tdesc_numbered_register (feature, tdesc_data.get (), + register_count, "psp_s"); + if (!valid_p) + { + warning (_("M-profile secext feature is missing required register psp_= s.")); + return nullptr; + } + m_profile_psp_s_regnum =3D register_count++; + + have_sec_ext =3D true; + } + } } =20 @@ -9725,6 +9937,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gd= barch_list *arches) tdep->arm_abi =3D arm_abi; tdep->fp_model =3D fp_model; tdep->is_m =3D is_m; + tdep->have_sec_ext =3D have_sec_ext; tdep->have_fpa_registers =3D have_fpa_registers; tdep->have_wmmx_registers =3D have_wmmx_registers; gdb_assert (vfp_register_count =3D=3D 0 @@ -9750,6 +9963,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct g= dbarch_list *arches) { tdep->m_profile_msp_regnum =3D m_profile_msp_regnum; tdep->m_profile_psp_regnum =3D m_profile_psp_regnum; + tdep->m_profile_msp_ns_regnum =3D m_profile_msp_ns_regnum; + tdep->m_profile_psp_ns_regnum =3D m_profile_psp_ns_regnum; + tdep->m_profile_msp_s_regnum =3D m_profile_msp_s_regnum; + tdep->m_profile_psp_s_regnum =3D m_profile_psp_s_regnum; } =20 arm_register_g_packet_guesses (gdbarch); @@ -10041,6 +10258,14 @@ arm_dump_tdep (struct gdbarch *gdbarch, struct ui_= file *file) tdep->m_profile_msp_regnum); gdb_printf (file, _("arm_dump_tdep: m_profile_psp_regnum =3D %i\n"), tdep->m_profile_psp_regnum); + gdb_printf (file, _("arm_dump_tdep: m_profile_msp_ns_regnum =3D %i\n"), + tdep->m_profile_msp_ns_regnum); + gdb_printf (file, _("arm_dump_tdep: m_profile_psp_ns_regnum =3D %i\n"), + tdep->m_profile_psp_ns_regnum); + gdb_printf (file, _("arm_dump_tdep: m_profile_msp_s_regnum =3D %i\n"), + tdep->m_profile_msp_s_regnum); + gdb_printf (file, _("arm_dump_tdep: m_profile_psp_s_regnum =3D %i\n"), + tdep->m_profile_psp_s_regnum); gdb_printf (file, _("arm_dump_tdep: Lowest pc =3D 0x%lx\n"), (unsigned long) tdep->lowest_pc); gdb_printf (file, _("arm_dump_tdep: have_pacbti =3D %s\n"), diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h index 40170673fde..864406e98d2 100644 --- a/gdb/arm-tdep.h +++ b/gdb/arm-tdep.h @@ -125,10 +125,17 @@ struct arm_gdbarch_tdep : gdbarch_tdep register. */ int pacbti_pseudo_count =3D 0; /* Total number of PACBTI pseudo register= s. */ =20 - int m_profile_msp_regnum =3D 0; /* M-profile MSP register number. */ - int m_profile_psp_regnum =3D 0; /* M-profile PSP register number. */ + int m_profile_msp_regnum =3D ARM_SP_REGNUM; /* M-profile MSP register nu= mber. */ + int m_profile_psp_regnum =3D ARM_SP_REGNUM; /* M-profile PSP register nu= mber. */ + + /* Secure and Non-secure stack pointers with security extension. */ + int m_profile_msp_ns_regnum =3D ARM_SP_REGNUM; /* M-profile MSP_NS regis= ter number. */ + int m_profile_psp_ns_regnum =3D ARM_SP_REGNUM; /* M-profile PSP_NS regis= ter number. */ + int m_profile_msp_s_regnum =3D ARM_SP_REGNUM; /* M-profile MSP_S registe= r number. */ + int m_profile_psp_s_regnum =3D ARM_SP_REGNUM; /* M-profile PSP_S registe= r number. */ =20 bool is_m =3D false; /* Does the target follow the "M" profile. */ + bool have_sec_ext =3D false; /* Do we have security extensions? */ CORE_ADDR lowest_pc =3D 0; /* Lowest address at which instructions will appear. */ =20 diff --git a/gdb/features/arm/arm-secext.c b/gdb/features/arm/arm-secext.c new file mode 100644 index 00000000000..39ef4afb05f --- /dev/null +++ b/gdb/features/arm/arm-secext.c @@ -0,0 +1,17 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: arm-secext.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_arm_arm_m_system (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature =3D tdesc_create_feature (result, "org.gnu.gdb.arm.secext"); + tdesc_create_reg (feature, "msp_ns", regnum++, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "psp_ns", regnum++, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "msp_s", regnum++, 1, NULL, 32, "data_ptr"); + tdesc_create_reg (feature, "psp_s", regnum++, 1, NULL, 32, "data_ptr"); + return regnum; +} diff --git a/gdb/features/arm/arm-secext.xml b/gdb/features/arm/arm-secext.= xml new file mode 100644 index 00000000000..52b2c20a982 --- /dev/null +++ b/gdb/features/arm/arm-secext.xml @@ -0,0 +1,15 @@ + + + + + + + + + + +