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, &reg_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, &reg_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) {