Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'agent/tcf/services/linenumbers.c')
-rw-r--r--agent/tcf/services/linenumbers.c267
1 files changed, 267 insertions, 0 deletions
diff --git a/agent/tcf/services/linenumbers.c b/agent/tcf/services/linenumbers.c
new file mode 100644
index 00000000..7ed0d8e1
--- /dev/null
+++ b/agent/tcf/services/linenumbers.c
@@ -0,0 +1,267 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+
+/*
+ * TCF service line Numbers - common part.
+ *
+ * The service associates locations in the source files with the corresponding
+ * machine instruction addresses in the executable object.
+ */
+
+#include <config.h>
+
+#if SERVICE_LineNumbers
+
+#include <errno.h>
+#include <assert.h>
+#include <stdio.h>
+#include <framework/context.h>
+#include <framework/myalloc.h>
+#include <framework/exceptions.h>
+#include <framework/cache.h>
+#include <framework/json.h>
+#include <framework/protocol.h>
+#include <framework/trace.h>
+#include <services/linenumbers.h>
+
+#define MAX_AREA_CNT 256
+
+typedef struct MapToSourceArgs {
+ char token[256];
+ char id[256];
+ ContextAddress addr0;
+ ContextAddress addr1;
+} MapToSourceArgs;
+
+typedef struct MapToMemoryArgs {
+ char token[256];
+ char id[256];
+ char * file;
+ int line;
+ int column;
+} MapToMemoryArgs;
+
+static int code_area_cnt = 0;
+static int code_area_max = 0;
+static CodeArea * code_area_buf = NULL;
+
+static const char * LINENUMBERS = "LineNumbers";
+
+static void write_line_info(OutputStream * out, int cnt) {
+ CodeArea * area = code_area_buf + cnt;
+ CodeArea * prev = cnt == 0 ? NULL : code_area_buf + cnt - 1;
+
+ write_stream(out, '{');
+ json_write_string(out, "SAddr");
+ write_stream(out, ':');
+ json_write_uint64(out, area->start_address);
+ if (area->start_line > 0) {
+ write_stream(out, ',');
+ json_write_string(out, "SLine");
+ write_stream(out, ':');
+ json_write_ulong(out, area->start_line);
+ if (area->start_column > 0) {
+ write_stream(out, ',');
+ json_write_string(out, "SCol");
+ write_stream(out, ':');
+ json_write_ulong(out, area->start_column);
+ }
+ }
+ if (area->end_address != 0) {
+ write_stream(out, ',');
+ json_write_string(out, "EAddr");
+ write_stream(out, ':');
+ json_write_uint64(out, area->end_address);
+ }
+ if (area->end_line > 0) {
+ write_stream(out, ',');
+ json_write_string(out, "ELine");
+ write_stream(out, ':');
+ json_write_ulong(out, area->end_line);
+ if (area->end_column > 0) {
+ write_stream(out, ',');
+ json_write_string(out, "ECol");
+ write_stream(out, ':');
+ json_write_ulong(out, area->end_column);
+ }
+ }
+ if (area->file != NULL && (prev == NULL || prev->file != area->file)) {
+ write_stream(out, ',');
+ json_write_string(out, "File");
+ write_stream(out, ':');
+ json_write_string(out, area->file);
+ }
+ if (area->directory != NULL && (prev == NULL || prev->directory != area->directory)) {
+ write_stream(out, ',');
+ json_write_string(out, "Dir");
+ write_stream(out, ':');
+ json_write_string(out, area->directory);
+ }
+ if (area->isa > 0) {
+ write_stream(out, ',');
+ json_write_string(out, "ISA");
+ write_stream(out, ':');
+ json_write_ulong(out, area->isa);
+ }
+ if (area->is_statement) {
+ write_stream(out, ',');
+ json_write_string(out, "IsStmt");
+ write_stream(out, ':');
+ json_write_boolean(out, 1);
+ }
+ if (area->basic_block) {
+ write_stream(out, ',');
+ json_write_string(out, "BasicBlock");
+ write_stream(out, ':');
+ json_write_boolean(out, 1);
+ }
+ if (area->prologue_end) {
+ write_stream(out, ',');
+ json_write_string(out, "PrologueEnd");
+ write_stream(out, ':');
+ json_write_boolean(out, 1);
+ }
+ if (area->epilogue_begin) {
+ write_stream(out, ',');
+ json_write_string(out, "EpilogueBegin");
+ write_stream(out, ':');
+ json_write_boolean(out, 1);
+ }
+ write_stream(out, '}');
+}
+
+static void add_code_area(CodeArea * area, void * args) {
+ if (code_area_cnt >= code_area_max) {
+ if (code_area_max >= MAX_AREA_CNT) exception(ERR_BUFFER_OVERFLOW);
+ code_area_max += 8;
+ code_area_buf = (CodeArea *)loc_realloc(code_area_buf, sizeof(CodeArea) * code_area_max);
+ }
+ code_area_buf[code_area_cnt++] = *area;
+}
+
+static void map_to_source_cache_client(void * x) {
+ int err = 0;
+ Context * ctx = NULL;
+ MapToSourceArgs * args = (MapToSourceArgs *)x;
+ Channel * c = cache_channel();
+
+ ctx = id2ctx(args->id);
+ if (ctx == NULL) err = ERR_INV_CONTEXT;
+ else if (ctx->exited) err = ERR_ALREADY_EXITED;
+ else ctx = context_get_group(ctx, CONTEXT_GROUP_PROCESS);
+
+ code_area_cnt = 0;
+ if (err == 0 && address_to_line(ctx, args->addr0, args->addr1, add_code_area, NULL) < 0) err = errno;
+
+ cache_exit();
+
+ write_stringz(&c->out, "R");
+ write_stringz(&c->out, args->token);
+ write_errno(&c->out, err);
+ if (err != 0) {
+ write_stringz(&c->out, "null");
+ }
+ else {
+ int cnt = 0;
+ write_stream(&c->out, '[');
+ while (cnt < code_area_cnt) {
+ if (cnt > 0) write_stream(&c->out, ',');
+ write_line_info(&c->out, cnt);
+ cnt++;
+ }
+ write_stream(&c->out, ']');
+ write_stream(&c->out, 0);
+ }
+ write_stream(&c->out, MARKER_EOM);
+}
+
+static void command_map_to_source(char * token, Channel * c) {
+ MapToSourceArgs args;
+
+ json_read_string(&c->inp, args.id, sizeof(args.id));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args.addr0 = (ContextAddress)json_read_uint64(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args.addr1 = (ContextAddress)json_read_uint64(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+
+ strlcpy(args.token, token, sizeof(args.token));
+ cache_enter(map_to_source_cache_client, c, &args, sizeof(args));
+}
+
+static void map_to_memory_cache_client(void * x) {
+ int err = 0;
+ Context * ctx = NULL;
+ MapToMemoryArgs * args = (MapToMemoryArgs *)x;
+ Channel * c = cache_channel();
+
+ ctx = id2ctx(args->id);
+ if (ctx == NULL) err = ERR_INV_CONTEXT;
+ else if (ctx->exited) err = ERR_ALREADY_EXITED;
+ else ctx = context_get_group(ctx, CONTEXT_GROUP_PROCESS);
+
+
+ code_area_cnt = 0;
+ if (err == 0 && line_to_address(ctx, args->file,
+ args->line, args->column, add_code_area, NULL) < 0) err = errno;
+
+ cache_exit();
+
+ write_stringz(&c->out, "R");
+ write_stringz(&c->out, args->token);
+ write_errno(&c->out, err);
+ if (err != 0) {
+ write_stringz(&c->out, "null");
+ }
+ else {
+ int cnt = 0;
+ write_stream(&c->out, '[');
+ while (cnt < code_area_cnt) {
+ if (cnt > 0) write_stream(&c->out, ',');
+ write_line_info(&c->out, cnt);
+ cnt++;
+ }
+ write_stream(&c->out, ']');
+ write_stream(&c->out, 0);
+ }
+ write_stream(&c->out, MARKER_EOM);
+ loc_free(args->file);
+}
+
+static void command_map_to_memory(char * token, Channel * c) {
+ MapToMemoryArgs args;
+
+ json_read_string(&c->inp, args.id, sizeof(args.id));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args.file = json_read_alloc_string(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args.line = json_read_long(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args.column = json_read_long(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+
+ strlcpy(args.token, token, sizeof(args.token));
+ cache_enter(map_to_memory_cache_client, c, &args, sizeof(args));
+}
+
+void ini_line_numbers_service(Protocol * proto) {
+ ini_line_numbers_lib();
+ add_command_handler(proto, LINENUMBERS, "mapToSource", command_map_to_source);
+ add_command_handler(proto, LINENUMBERS, "mapToMemory", command_map_to_memory);
+}
+
+#endif /* SERVICE_LineNumbers */

Back to the top