Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'agent/tcf/framework/cpudefs.c')
-rw-r--r--agent/tcf/framework/cpudefs.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c
new file mode 100644
index 00000000..fbdfa28a
--- /dev/null
+++ b/agent/tcf/framework/cpudefs.c
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 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.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ * You may elect to redistribute this code under either of these licenses.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * This module contains definitions of target CPU registers and stack frames.
+ */
+
+#include <config.h>
+
+#if ENABLE_DebugContext
+
+#include <stddef.h>
+#include <stdio.h>
+#include <assert.h>
+#include <framework/cpudefs.h>
+#include <framework/errors.h>
+#include <framework/context.h>
+#include <framework/myalloc.h>
+#include <framework/exceptions.h>
+#include <services/symbols.h>
+#include <machine/cpudefs-ext.h>
+
+int read_reg_value(StackFrame * frame, RegisterDefinition * reg_def, uint64_t * value) {
+ uint8_t buf[8];
+ if (reg_def == NULL) {
+ set_errno(ERR_INV_CONTEXT, "Invalid register");
+ return -1;
+ }
+ if (frame == NULL) {
+ set_errno(ERR_INV_CONTEXT, "Invalid stack frame");
+ return -1;
+ }
+ if (reg_def->size > sizeof(buf)) {
+ errno = ERR_INV_DATA_SIZE;
+ return -1;
+ }
+ if (read_reg_bytes(frame, reg_def, 0, reg_def->size, buf) < 0) return -1;
+ if (value != NULL) {
+ size_t i;
+ uint64_t n = 0;
+ for (i = 0; i < reg_def->size; i++) {
+ n = n << 8;
+ n |= buf[reg_def->big_endian ? i : reg_def->size - i - 1];
+ }
+ *value = n;
+ }
+ return 0;
+}
+
+int write_reg_value(StackFrame * frame, RegisterDefinition * reg_def, uint64_t value) {
+ size_t i;
+ uint8_t buf[8];
+ if (reg_def == NULL) {
+ set_errno(ERR_INV_CONTEXT, "Invalid register");
+ return -1;
+ }
+ if (frame == NULL) {
+ set_errno(ERR_INV_CONTEXT, "Invalid stack frame");
+ return -1;
+ }
+ if (reg_def->size > sizeof(buf)) {
+ errno = ERR_INV_DATA_SIZE;
+ return -1;
+ }
+ for (i = 0; i < reg_def->size; i++) {
+ buf[reg_def->big_endian ? reg_def->size - i - 1 : i] = (uint8_t)value;
+ value = value >> 8;
+ }
+ if (write_reg_bytes(frame, reg_def, 0, reg_def->size, buf) < 0) return -1;
+ if (!frame->is_top_frame) frame->has_reg_data = 1;
+ return 0;
+}
+
+ContextAddress get_regs_PC(Context * ctx) {
+ size_t i;
+ uint8_t buf[8];
+ ContextAddress pc = 0;
+ RegisterDefinition * def = get_PC_definition(ctx);
+ if (def == NULL) return 0;
+ assert(def->size <= sizeof(buf));
+ if (context_read_reg(ctx, def, 0, def->size, buf) < 0) return 0;
+ for (i = 0; i < def->size; i++) {
+ pc = pc << 8;
+ pc |= buf[def->big_endian ? i : def->size - i - 1];
+ }
+ return pc;
+}
+
+void set_regs_PC(Context * ctx, ContextAddress pc) {
+ size_t i;
+ uint8_t buf[8];
+ RegisterDefinition * def = get_PC_definition(ctx);
+ if (def == NULL) return;
+ assert(def->size <= sizeof(buf));
+ for (i = 0; i < def->size; i++) {
+ buf[def->big_endian ? def->size - i - 1 : i] = (uint8_t)pc;
+ pc = pc >> 8;
+ }
+ context_write_reg(ctx, def, 0, def->size, buf);
+}
+
+int id2frame(const char * id, Context ** ctx, int * frame) {
+ int f = 0;
+ Context * c = NULL;
+
+ if (*id++ != 'F') {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ if (*id++ != 'P') {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ while (*id != '.') {
+ if (*id < '0' || *id > '9') {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ f = f * 10 + (*id++ - '0');
+ }
+ id++;
+ c = id2ctx(id);
+ if (c == NULL) {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ *ctx = c;
+ *frame = f;
+ return 0;
+}
+
+const char * frame2id(Context * ctx, int frame) {
+ static char id[256];
+
+ assert(frame >= 0);
+ if (!context_has_state(ctx)) {
+ errno = ERR_INV_CONTEXT;
+ return NULL;
+ }
+ snprintf(id, sizeof(id), "FP%d.%s", frame, ctx->id);
+ return id;
+}
+
+const char * register2id(Context * ctx, int frame, RegisterDefinition * reg) {
+ static char id[256];
+ RegisterDefinition * defs = get_reg_definitions(ctx);
+ if (frame < 0) {
+ snprintf(id, sizeof(id), "R%d.%s", (int)(reg - defs), ctx->id);
+ }
+ else {
+ snprintf(id, sizeof(id), "R%d@%d.%s", (int)(reg - defs), frame, ctx->id);
+ }
+ return id;
+}
+
+int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def) {
+ int r = 0;
+
+ *ctx = NULL;
+ *frame = STACK_TOP_FRAME;
+ *reg_def = NULL;
+ if (*id++ != 'R') {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ while (*id != '.' && *id != '@') {
+ if (*id >= '0' && *id <= '9') {
+ r = r * 10 + (*id++ - '0');
+ }
+ else {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ }
+ if (*id == '@') {
+ int n = 0;
+ id++;
+ while (*id != '.') {
+ if (*id >= '0' && *id <= '9') {
+ n = n * 10 + (*id++ - '0');
+ }
+ else {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ }
+ *frame = n;
+ }
+ id++;
+ *ctx = id2ctx(id);
+ if (*ctx == NULL) {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+ if ((*ctx)->exited) {
+ errno = ERR_ALREADY_EXITED;
+ return -1;
+ }
+ *reg_def = get_reg_definitions(*ctx) + r;
+ return 0;
+}
+
+static void stack_trace_error(void) {
+ str_exception(ERR_OTHER, "Invalid stack trace program");
+}
+
+uint64_t evaluate_stack_trace_commands(Context * ctx, StackFrame * frame, StackTracingCommandSequence * cmds) {
+ static uint64_t * stk = NULL;
+ static int stk_size = 0;
+
+ int i;
+ int stk_pos = 0;
+
+ for (i = 0; i < cmds->cmds_cnt; i++) {
+ StackTracingCommand * cmd = cmds->cmds + i;
+ if (stk_pos >= stk_size) {
+ stk_size += 4;
+ stk = (uint64_t *)loc_realloc(stk, sizeof(uint64_t) * stk_size);
+ }
+ switch (cmd->cmd) {
+ case SFT_CMD_NUMBER:
+ stk[stk_pos++] = cmd->num;
+ break;
+ case SFT_CMD_REGISTER:
+ if (read_reg_value(frame, cmd->reg, stk + stk_pos) < 0) exception(errno);
+ stk_pos++;
+ break;
+ case SFT_CMD_FP:
+ stk[stk_pos++] = frame->fp;
+ break;
+ case SFT_CMD_DEREF:
+ if (stk_pos < 1) stack_trace_error();
+ {
+ size_t j;
+ size_t size = cmd->size;
+ uint64_t n = 0;
+ uint8_t buf[8];
+
+ if (context_read_mem(ctx, (ContextAddress)stk[stk_pos - 1], buf, size) < 0) exception(errno);
+ for (j = 0; j < size; j++) {
+ n = (n << 8) | buf[cmd->big_endian ? j : size - j - 1];
+ }
+ stk[stk_pos - 1] = n;
+ }
+ break;
+ case SFT_CMD_ADD:
+ if (stk_pos < 2) stack_trace_error();
+ stk[stk_pos - 2] = stk[stk_pos - 2] + stk[stk_pos - 1];
+ stk_pos--;
+ break;
+ case SFT_CMD_SUB:
+ if (stk_pos < 2) stack_trace_error();
+ stk[stk_pos - 2] = stk[stk_pos - 2] - stk[stk_pos - 1];
+ stk_pos--;
+ break;
+ case SFT_CMD_AND:
+ if (stk_pos < 2) stack_trace_error();
+ stk[stk_pos - 2] = stk[stk_pos - 2] & stk[stk_pos - 1];
+ stk_pos--;
+ break;
+ case SFT_CMD_OR:
+ if (stk_pos < 2) stack_trace_error();
+ stk[stk_pos - 2] = stk[stk_pos - 2] | stk[stk_pos - 1];
+ stk_pos--;
+ break;
+ default:
+ stack_trace_error();
+ break;
+ }
+ }
+ if (stk_pos == 0) stack_trace_error();
+ return stk[stk_pos - 1];
+}
+
+#endif /* ENABLE_DebugContext */

Back to the top