From 3ba21e5f007a81b42be194a663cb6f15f150b245 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 2 Nov 2021 09:55:07 -0700 Subject: [PATCH] target/riscv: calloc() memory per register. This replaces a static array with 8 bytes per register. When there are vector registers larger than 8 bytes, they would end up clobbering each other's values. I can't believe I didn't catch this earlier. See https://github.com/riscv/riscv-openocd/pull/658 Change-Id: I9df4eaf05617a2c8df3140fff9fe53f61ab2b261 Signed-off-by: Tim Newsome Reviewed-on: https://review.openocd.org/c/openocd/+/6775 Tested-by: jenkins Reviewed-by: Antonio Borneo Reviewed-by: Tomas Vanek --- src/target/riscv/riscv.c | 8 +++++--- src/target/riscv/riscv.h | 5 ----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 407b7e279..c9840fe50 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -476,6 +476,8 @@ static void riscv_free_registers(struct target *target) /* Free the ones we allocated separately. */ for (unsigned i = GDB_REGNO_COUNT; i < target->reg_cache->num_regs; i++) free(target->reg_cache->reg_list[i].arch_info); + for (unsigned int i = 0; i < target->reg_cache->num_regs; i++) + free(target->reg_cache->reg_list[i].value); free(target->reg_cache->reg_list); } free(target->reg_cache); @@ -1749,8 +1751,8 @@ static int riscv_get_gdb_reg_list_internal(struct target *target, enum target_register_class reg_class, bool read) { RISCV_INFO(r); - LOG_DEBUG("current_hartid=%d, reg_class=%d, read=%d", - r->current_hartid, reg_class, read); + LOG_DEBUG("[%s] {%d} reg_class=%d, read=%d", + target_name(target), r->current_hartid, reg_class, read); if (!target->reg_cache) { LOG_ERROR("Target not initialized. Return ERROR_FAIL."); @@ -4479,7 +4481,7 @@ int riscv_init_registers(struct target *target) assert(reg_name < info->reg_names + target->reg_cache->num_regs * max_reg_name_len); } - r->value = info->reg_cache_values[number]; + r->value = calloc(1, DIV_ROUND_UP(r->size, 8)); } return ERROR_OK; diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index d0f4f6ec0..0ae8945da 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -96,11 +96,6 @@ typedef struct { * every function than an actual */ int current_hartid; - /* OpenOCD's register cache points into here. This is not per-hart because - * we just invalidate the entire cache when we change which hart is - * selected. Use an array of 8 uint8_t per register. */ - uint8_t reg_cache_values[RISCV_MAX_REGISTERS][8]; - /* Single buffer that contains all register names, instead of calling * malloc for each register. Needs to be freed when reg_list is freed. */ char *reg_names;