aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2020-12-14 12:39:00 -0800
committerGitHub <noreply@github.com>2020-12-14 12:39:00 -0800
commitf72e5bb0d82e5feb05efbcbb07c326f28d3e3cdf (patch)
tree82558a4b609b22e50adbcb978725b59e4df101a2
parent5d0543cc1c7749a9bf3538328397a5e817275fb9 (diff)
downloadriscv-openocd-f72e5bb0d82e5feb05efbcbb07c326f28d3e3cdf.zip
riscv-openocd-f72e5bb0d82e5feb05efbcbb07c326f28d3e3cdf.tar.gz
riscv-openocd-f72e5bb0d82e5feb05efbcbb07c326f28d3e3cdf.tar.bz2
Fix error handling in read_memory_progbuf_one(). (#560)
* Fix error handling in read_memory_progbuf_one(). Be sure to restore mstatus/s0 even if there is a failure during the operation. Fixes #559. Change-Id: Ib86ca2c7455bad4a668f34703566060a782116db Signed-off-by: Tim Newsome <tim@sifive.com> * Style fix suggested in review. Change-Id: I444112a9dffea483b7d0e5f96ef7bbdaf58d249f Signed-off-by: Tim Newsome <tim@sifive.com>
-rw-r--r--src/target/riscv/riscv-013.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index e458602..c727101 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -3339,9 +3339,10 @@ static int read_memory_progbuf_one(struct target *target, target_addr_t address,
return ERROR_FAIL;
uint64_t s0;
+ int result = ERROR_FAIL;
if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK)
- return ERROR_FAIL;
+ goto restore_mstatus;
/* Write the program (load, increment) */
struct riscv_program program;
@@ -3363,40 +3364,42 @@ static int read_memory_progbuf_one(struct target *target, target_addr_t address,
break;
default:
LOG_ERROR("Unsupported size: %d", size);
- return ERROR_FAIL;
+ goto restore_mstatus;
}
if (riscv_enable_virtual && has_sufficient_progbuf(target, 5) && get_field(mstatus, MSTATUS_MPRV))
riscv_program_csrrci(&program, GDB_REGNO_ZERO, CSR_DCSR_MPRVEN, GDB_REGNO_DCSR);
if (riscv_program_ebreak(&program) != ERROR_OK)
- return ERROR_FAIL;
+ goto restore_mstatus;
if (riscv_program_write(&program) != ERROR_OK)
- return ERROR_FAIL;
+ goto restore_mstatus;
/* Write address to S0, and execute buffer. */
if (write_abstract_arg(target, 0, address, riscv_xlen(target)) != ERROR_OK)
- return ERROR_FAIL;
+ goto restore_mstatus;
uint32_t command = access_register_command(target, GDB_REGNO_S0,
riscv_xlen(target), AC_ACCESS_REGISTER_WRITE |
AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC);
if (execute_abstract_command(target, command) != ERROR_OK)
- return ERROR_FAIL;
+ goto restore_s0;
uint64_t value;
if (register_read(target, &value, GDB_REGNO_S0) != ERROR_OK)
- return ERROR_FAIL;
+ goto restore_s0;
buf_set_u64(buffer, 0, 8 * size, value);
log_memory_access(address, value, size, true);
+ result = ERROR_OK;
+restore_s0:
if (riscv_set_register(target, GDB_REGNO_S0, s0) != ERROR_OK)
- return ERROR_FAIL;
+ result = ERROR_FAIL;
- /* Restore MSTATUS */
+restore_mstatus:
if (mstatus != mstatus_old)
if (register_write_direct(target, GDB_REGNO_MSTATUS, mstatus_old))
- return ERROR_FAIL;
+ result = ERROR_FAIL;
- return ERROR_OK;
+ return result;
}
/**