TCF Agent: improved checks for invalid of defunct register IDs
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c
index 8db5a72..a2c1ade 100644
--- a/agent/tcf/framework/cpudefs.c
+++ b/agent/tcf/framework/cpudefs.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -33,6 +33,15 @@
#include <tcf/framework/cpudefs-ext.h>
+typedef struct ContextExtensionRegisters {
+ unsigned reg_seq;
+ unsigned reg_cnt;
+} ContextExtensionRegisters;
+
+static unsigned reg_defs_seq = 1;
+static size_t context_extension_offset = 0;
+#define EXT(ctx) ((ContextExtensionRegisters *)((char *)(ctx) + context_extension_offset))
+
void create_reg_children_refs(RegisterDefinition * defs) {
#if ENABLE_RegisterChildrenRefs
RegisterDefinition * r = NULL;
@@ -196,10 +205,27 @@
return tmp_printf("FP%d.%s", frame, ctx->id);
}
+static void update_reg_cnt(Context * ctx, RegisterDefinition * defs) {
+ ContextExtensionRegisters * ext = EXT(ctx);
+ assert(reg_defs_seq != 0);
+ if (ext->reg_seq != reg_defs_seq) {
+ ext->reg_cnt = 0;
+ if (defs != NULL) {
+ while (defs->name != NULL) {
+ ext->reg_cnt++;
+ defs++;
+ }
+ }
+ ext->reg_seq = reg_defs_seq;
+ }
+}
+
const char * register2id(Context * ctx, int frame, RegisterDefinition * reg) {
RegisterDefinition * defs = get_reg_definitions(ctx);
+ update_reg_cnt(ctx, defs);
assert(defs != NULL);
assert(reg >= defs);
+ assert(reg < defs + EXT(ctx)->reg_cnt);
if (frame < 0) return tmp_printf("R%d.%s", (int)(reg - defs), ctx->id);
return tmp_printf("R%d@%d.%s", (int)(reg - defs), frame, ctx->id);
}
@@ -209,7 +235,7 @@
*frame = STACK_TOP_FRAME;
*reg_num = 0;
if (*id++ != 'R') {
- errno = ERR_INV_CONTEXT;
+ errno = ERR_OTHER;
return -1;
}
while (*id != '.' && *id != '@') {
@@ -217,7 +243,7 @@
*reg_num = *reg_num * 10 + (*id++ - '0');
}
else {
- errno = ERR_INV_CONTEXT;
+ errno = ERR_OTHER;
return -1;
}
}
@@ -229,7 +255,7 @@
n = n * 10 + (*id++ - '0');
}
else {
- errno = ERR_INV_CONTEXT;
+ errno = ERR_OTHER;
return -1;
}
}
@@ -248,7 +274,10 @@
*ctx = NULL;
*reg_def = NULL;
- if (id2reg_num(id, &ctx_id, frame, ®_num) < 0) return -1;
+ if (id2reg_num(id, &ctx_id, frame, ®_num) < 0) {
+ if (errno == ERR_OTHER) set_errno(errno, "Malformed register ID");
+ return -1;
+ }
*ctx = id2ctx(ctx_id);
if (*ctx == NULL) {
@@ -264,10 +293,20 @@
set_errno(ERR_OTHER, "Context has no registers");
return -1;
}
+ update_reg_cnt(*ctx, defs);
+ if (reg_num >= EXT(*ctx)->reg_cnt) {
+ set_errno(ERR_OTHER, "Invalid register ID");
+ return -1;
+ }
*reg_def = defs + reg_num;
return 0;
}
+void invalidate_register_ids(void) {
+ do reg_defs_seq++;
+ while (reg_defs_seq == 0);
+}
+
static void location_expression_error(void) {
str_exception(ERR_OTHER, "Invalid location expression");
}
@@ -739,6 +778,7 @@
}
void ini_cpudefs(void) {
+ context_extension_offset = context_extension(sizeof(ContextExtensionRegisters));
#if defined(ENABLE_ini_cpudefs_mdep) && ENABLE_ini_cpudefs_mdep
ini_cpudefs_mdep();
#endif
diff --git a/agent/tcf/framework/cpudefs.h b/agent/tcf/framework/cpudefs.h
index a11a134..7289c4e 100644
--- a/agent/tcf/framework/cpudefs.h
+++ b/agent/tcf/framework/cpudefs.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2019 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -282,7 +282,7 @@
#endif
/* Get instruction pointer (PC) value.
-* Deprecated: use get_PC() */
+ * Deprecated: use get_PC() */
extern ContextAddress get_regs_PC(Context * ctx);
/* Set instruction pointer (PC) value.
@@ -308,6 +308,10 @@
extern int id2reg_num(const char * id, const char ** ctx_id, int * frame, unsigned * reg_num);
extern int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def);
+/* Invalidate register IDs.
+ * This function is called by the RunControl service when register definitions change. */
+extern void invalidate_register_ids(void);
+
/* Get breakpoint instruction code and size.
* Return NULL if the context does not support software breakpoints. */
extern uint8_t * get_break_instruction(Context * ctx, size_t * size);
diff --git a/agent/tcf/services/registers.c b/agent/tcf/services/registers.c
index 9afd7a6..40dcaa0 100644
--- a/agent/tcf/services/registers.c
+++ b/agent/tcf/services/registers.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2021 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.
@@ -442,6 +442,7 @@
}
void send_event_register_definitions_changed(void) {
+ invalidate_register_ids();
notify_definitions_changed = 1;
/* Delay notifications until cache transaction is committed */
if (cache_transaction_id() == 0) flush_notifications();