[prev in list] [next in list] [prev in thread] [next in thread]
List: openocd-development
Subject: [OpenOCD-devel] [PATCH]: 60249bf target/arc: introduce initial set/unset bp functions
From: gerrit () openocd ! org (gerrit)
Date: 2020-04-30 19:51:49
Message-ID: 20200430195149.8BEF34A02DA () mail ! openocd ! org
[Download RAW message or body]
This is an automated email from Gerrit.
Evgeniy Didin (didin@synopsys.com) just uploaded a new patch set to Gerrit, which you \
can find at http://openocd.zylin.com/5641
-- gerrit
commit 60249bfe35ec6666c307f4414480358e930bebe1
Author: Evgeniy Didin <didin@synopsys.com>
Date: Mon Mar 16 20:38:00 2020 +0300
target/arc: introduce initial set/unset bp functions
With this patch we introduce set/unset breakpoints
routines, which will be used in future.
Currently soft breakpoints are only supported.
Change-Id: Ib10ccdb02fd1606e4f407f012b1bee106a8ffccd
Signed-off-by: Evgeniy Didin <didin@synopsys.com>
diff --git a/src/target/arc.c b/src/target/arc.c
index b4c5f5d..2e053d0 100644
--- a/src/target/arc.c
+++ b/src/target/arc.c
@@ -1342,6 +1342,133 @@ int arc_read_instruction_u32(struct target *target, uint32_t \
address, return ERROR_OK;
}
+static int arc_set_breakpoint(struct target *target,
+ struct breakpoint *breakpoint)
+{
+
+ if (breakpoint->set) {
+ LOG_WARNING("breakpoint already set");
+ return ERROR_OK;
+ }
+
+ if (breakpoint->type == BKPT_SOFT) {
+ LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
+
+ if (breakpoint->length == 4) {
+ uint32_t verify = 0xffffffff;
+
+ CHECK_RETVAL(target_read_buffer(target, breakpoint->address, breakpoint->length,
+ breakpoint->orig_instr));
+
+ CHECK_RETVAL(arc_write_instruction_u32(target, breakpoint->address,
+ ARC_SDBBP_32));
+
+ CHECK_RETVAL(arc_read_instruction_u32(target, breakpoint->address, &verify));
+
+ if (verify != ARC_SDBBP_32) {
+ LOG_ERROR("Unable to set 32bit breakpoint at address @0x%" TARGET_PRIxADDR
+ " - check that memory is read/writable", breakpoint->address);
+ return ERROR_FAIL;
+ }
+ } else if (breakpoint->length == 2) {
+ uint16_t verify = 0xffff;
+
+ CHECK_RETVAL(target_read_buffer(target, breakpoint->address, breakpoint->length,
+ breakpoint->orig_instr));
+ CHECK_RETVAL(target_write_u16(target, breakpoint->address, ARC_SDBBP_16));
+
+ CHECK_RETVAL(target_read_u16(target, breakpoint->address, &verify));
+ if (verify != ARC_SDBBP_16) {
+ LOG_ERROR("Unable to set 16bit breakpoint at address @0x%" TARGET_PRIxADDR
+ " - check that memory is read/writable", breakpoint->address);
+ return ERROR_FAIL;
+ }
+ } else {
+ LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ breakpoint->set = 64; /* Any nice value but 0 */
+ } else if (breakpoint->type == BKPT_HARD) {
+ LOG_DEBUG("Hardware breakpoints are not supported yet!");
+ return ERROR_FAIL;
+ } else {
+ LOG_DEBUG("ERROR: setting unknown breakpoint type");
+ return ERROR_FAIL;
+ }
+ /* core instruction cache is now invalid,
+ * TODO: add cache invalidation function here (when implemented). */
+
+ return ERROR_OK;
+}
+
+static int arc_unset_breakpoint(struct target *target,
+ struct breakpoint *breakpoint)
+{
+ int retval = ERROR_OK;
+
+ if (!breakpoint->set) {
+ LOG_WARNING("breakpoint not set");
+ return ERROR_OK;
+ }
+
+ if (breakpoint->type == BKPT_SOFT) {
+ /* restore original instruction (kept in target endianness) */
+ LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
+ if (breakpoint->length == 4) {
+ uint32_t current_instr;
+
+ /* check that user program has not modified breakpoint instruction */
+ CHECK_RETVAL(arc_read_instruction_u32(target, breakpoint->address, \
¤t_instr)); +
+ if (current_instr == ARC_SDBBP_32) {
+ retval = target_write_buffer(target, breakpoint->address,
+ breakpoint->length, breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ } else {
+ LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR
+ " has been overwritten outside of debugger."
+ "Expected: @0x%" PRIx32 ", got: @0x%" PRIx32,
+ breakpoint->address, ARC_SDBBP_32, current_instr);
+ }
+ } else if (breakpoint->length == 2) {
+ uint16_t current_instr;
+
+ /* check that user program has not modified breakpoint instruction */
+ CHECK_RETVAL(target_read_u16(target, breakpoint->address, ¤t_instr));
+ if (current_instr == ARC_SDBBP_16) {
+ retval = target_write_buffer(target, breakpoint->address,
+ breakpoint->length, breakpoint->orig_instr);
+ if (retval != ERROR_OK)
+ return retval;
+ } else {
+ LOG_WARNING("Software breakpoint @0x%" TARGET_PRIxADDR
+ " has been overwritten outside of debugger. "
+ "Expected: 0x%04" PRIx16 ", got: 0x%04" PRIx16,
+ breakpoint->address, ARC_SDBBP_16, current_instr);
+ }
+ } else {
+ LOG_ERROR("Invalid breakpoint length: target supports only 2 or 4");
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+ breakpoint->set = 0;
+
+ } else if (breakpoint->type == BKPT_HARD) {
+ LOG_WARNING("Hardware breakpoints are not supported yet!");
+ return ERROR_FAIL;
+ } else {
+ LOG_DEBUG("ERROR: unsetting unknown breakpoint type");
+ return ERROR_FAIL;
+ }
+
+ /* core instruction cache is now invalid.
+ * TODO: Add cache invalidation function */
+
+ return retval;
+}
+
+
/* ARC v2 target */
struct target_type arcv2_target = {
.name = "arcv2",
diff --git a/src/target/arc.h b/src/target/arc.h
index d175738..0ce6d9c 100644
--- a/src/target/arc.h
+++ b/src/target/arc.h
@@ -49,6 +49,12 @@
/* Limit reg_type/reg_type_field name to 20 symbols */
#define REG_TYPE_MAX_NAME_LENGTH 20
+/* ARC 32bits opcodes */
+#define ARC_SDBBP_32 0x256F003F /* BRK */
+
+/* ARC 16bits opcodes */
+#define ARC_SDBBP_16 0x7FFF /* BRK_S */
+
struct arc_reg_bitfield {
struct reg_data_type_bitfield bitfield;
char name[REG_TYPE_MAX_NAME_LENGTH];
--
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic