TCF Agent: added support for reading/writing context registers when the context is running
diff --git a/agent/tcf/framework/context.h b/agent/tcf/framework/context.h
index f2664ac..7363965 100644
--- a/agent/tcf/framework/context.h
+++ b/agent/tcf/framework/context.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2014 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007, 2015 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -57,6 +57,7 @@
Context * mem; /* context memory space */
int big_endian; /* 0 - little endian, 1 - big endian */
unsigned int mem_access; /* bit set of memory access types represented by this context */
+ unsigned int reg_access; /* bit set of register access types represented by this context */
unsigned int ref_count; /* reference count, see context_lock() and context_unlock() */
int stopped; /* OS kernel has stopped this context */
int stopped_by_bp; /* stopped by breakpoint instruction */
@@ -109,6 +110,12 @@
#define MEM_ACCESS_TLB 0x0200 /* Context is a TLB memory */
/*
+ * Values of "reg_access".
+ */
+#define REG_ACCESS_RD_RUNNING 0x0001 /* Context supports reading registers while running */
+#define REG_ACCESS_WR_RUNNING 0x0002 /* Context supports writing registers while running */
+
+/*
* MemoryErrorInfo is used to retrieve additional information about memory access error.
*/
typedef struct MemoryErrorInfo {
diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c
index f1f89ea..be3ca77 100644
--- a/agent/tcf/services/expressions.c
+++ b/agent/tcf/services/expressions.c
@@ -837,7 +837,7 @@
}
if (context_read_reg(ctx, def, 0, def->size, v->value) < 0) exception(errno);
}
- else if (!ctx->stopped) {
+ else if (!ctx->stopped && (ctx->reg_access & REG_ACCESS_RD_RUNNING) == 0) {
str_exception(ERR_IS_RUNNING, "Cannot read CPU register");
}
else if (frame == STACK_TOP_FRAME || frame == STACK_NO_FRAME) {
diff --git a/agent/tcf/services/registers.c b/agent/tcf/services/registers.c
index b764ed8..2fab977 100644
--- a/agent/tcf/services/registers.c
+++ b/agent/tcf/services/registers.c
@@ -399,8 +399,10 @@
if (id2register(args->id, &ctx, &frame, ®_def) < 0) exception(errno);
if (ctx->exited) exception(ERR_ALREADY_EXITED);
- if (context_has_state(ctx) && !ctx->stopped) exception(ERR_IS_RUNNING);
-
+ if ((ctx->reg_access & REG_ACCESS_RD_RUNNING) == 0) {
+ if (!ctx->stopped && context_has_state(ctx))
+ str_exception(ERR_IS_RUNNING, "Cannot read register if not stopped");
+ }
if (reg_def->size > bbf_len) {
bbf_len += 0x100 + reg_def->size;
bbf = (uint8_t *)loc_realloc(bbf, bbf_len);
@@ -461,7 +463,10 @@
if (id2register(args->id, &ctx, &frame, ®_def) < 0) exception(errno);
if (frame >= 0 && !is_top_frame(ctx, frame)) exception(ERR_INV_CONTEXT);
if (ctx->exited) exception(ERR_ALREADY_EXITED);
- if (context_has_state(ctx) && !ctx->stopped) exception(ERR_IS_RUNNING);
+ if ((ctx->reg_access & REG_ACCESS_WR_RUNNING) == 0) {
+ if (!ctx->stopped && context_has_state(ctx))
+ str_exception(ERR_IS_RUNNING, "Cannot write register if not stopped");
+ }
if ((size_t)args->data_len > reg_def->size) exception(ERR_INV_DATA_SIZE);
if (args->data_len > 0) {
if (context_write_reg(ctx, reg_def, 0, args->data_len, args->data) < 0) exception(errno);
@@ -557,7 +562,10 @@
if (id2register(loc->id, &loc->ctx, &loc->frame, &loc->reg_def) < 0) exception(errno);
if (loc->ctx->exited) exception(ERR_ALREADY_EXITED);
- if (context_has_state(loc->ctx) && !loc->ctx->stopped) exception(ERR_IS_RUNNING);
+ if ((loc->ctx->reg_access & setm ? REG_ACCESS_WR_RUNNING : REG_ACCESS_RD_RUNNING) == 0) {
+ if (!loc->ctx->stopped && context_has_state(loc->ctx))
+ str_fmt_exception(ERR_IS_RUNNING, "Cannot %s register if not stopped", setm ? "write" : "read");
+ }
if (loc->offs + loc->size > loc->reg_def->size) exception(ERR_INV_DATA_SIZE);
if (loc->frame < 0 || is_top_frame(loc->ctx, loc->frame)) continue;
diff --git a/agent/tcf/services/runctrl.c b/agent/tcf/services/runctrl.c
index b2a5d73..7c742cc 100644
--- a/agent/tcf/services/runctrl.c
+++ b/agent/tcf/services/runctrl.c
@@ -251,6 +251,23 @@
write_stream(out, ':');
json_write_long(out, context_word_size(ctx));
+ if (ctx->reg_access) {
+ unsigned cnt = 0;
+ write_stream(out, ',');
+ json_write_string(out, "RegAccessTypes");
+ write_stream(out, ':');
+ write_stream(out, '[');
+ if (ctx->mem_access & REG_ACCESS_RD_RUNNING) {
+ if (cnt++) write_stream(out, ',');
+ json_write_string(out, "rd-running");
+ }
+ if (ctx->mem_access & REG_ACCESS_WR_RUNNING) {
+ if (cnt++) write_stream(out, ',');
+ json_write_string(out, "wr-running");
+ }
+ write_stream(out, ']');
+ }
+
if (context_can_resume(ctx, RM_TERMINATE)) {
write_stream(out, ',');
json_write_string(out, "CanTerminate");
@@ -345,9 +362,8 @@
ext->pc_error = set_errno(ERR_OTHER, "Program counter register not found");
return;
}
- if (!ctx->stopped) {
- ext->pc_error = ERR_IS_RUNNING;
- return;
+ if ((ctx->reg_access & REG_ACCESS_RD_RUNNING) == 0) {
+ if (!ctx->stopped && context_has_state(ctx)) exception(ERR_IS_RUNNING);
}
assert(def->size <= sizeof(buf));
if (context_read_reg(ctx, def, 0, def->size, buf) < 0) {