From 5d8a142703e9c6871e5fe6ab3bdf348561d215a5 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 3 Nov 2025 08:50:32 +0100 Subject: [PATCH] target/armv4_5: mark registers as 'save-restore' gdb uses this mark when creating a dummy frame for manual call of a function by gdb command. With the original setting all registers as caller_save = false call command in gdb always clobbers r0, r1 and pc and some other registers depending on the called function. Set 'save-restore' for all registers but banked ones. Change-Id: I16c49e4bf8001e38d18ce8861ca65988b08ccc88 Signed-off-by: Tomas Vanek Reviewed-on: https://review.openocd.org/c/openocd/+/9208 Reviewed-by: Antonio Borneo Tested-by: jenkins --- src/target/armv4_5.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index e1a46bad3..1b3ca0cdb 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -691,8 +691,6 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) && arm->core_type != ARM_CORE_TYPE_VIRT_EXT) continue; - /* REVISIT handle Cortex-M, which only shadows R13/SP */ - reg_arch_info[i].num = arm_core_regs[i].cookie; reg_arch_info[i].mode = arm_core_regs[i].mode; reg_arch_info[i].target = target; @@ -706,9 +704,6 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) reg_list[i].arch_info = ®_arch_info[i]; reg_list[i].exist = true; - /* This really depends on the calling convention in use */ - reg_list[i].caller_save = false; - /* Registers data type, as used by GDB target description */ reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type)); switch (arm_core_regs[i].cookie) { @@ -729,9 +724,16 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) if (reg_list[i].number <= 15 || reg_list[i].number == 25) { reg_list[i].feature->name = "org.gnu.gdb.arm.core"; reg_list[i].group = "general"; + /* Registers which should be preserved across GDB inferior function calls. + * Avoid saving banked registers as GDB (version 16.2 in time of writing) + * does not take the current mode into account and messes the value + * by restoring both the not banked register and the banked alias of it + * in the current mode. */ + reg_list[i].caller_save = true; } else { reg_list[i].feature->name = "net.sourceforge.openocd.banked"; reg_list[i].group = "banked"; + reg_list[i].caller_save = false; } cache->num_regs++; @@ -751,7 +753,8 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm) reg_list[i].arch_info = ®_arch_info[i]; reg_list[i].exist = true; - reg_list[i].caller_save = false; + /* Mark d0 - d31 and fpscr as save-restore for GDB */ + reg_list[i].caller_save = true; reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type)); reg_list[i].reg_data_type->type = arm_vfp_v3_regs[j].type;