Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authoreutarass2009-12-19 00:41:43 +0000
committereutarass2009-12-19 00:41:43 +0000
commitb7d627d444635e21b3a06f52ae36b72d03e823a0 (patch)
tree41110c1e3089724e133fa57eda4c4a41ef83fb54 /server
parent58102f2a785fffa0e2585b387f948c9b975f909e (diff)
downloadorg.eclipse.tcf.agent-b7d627d444635e21b3a06f52ae36b72d03e823a0.tar.gz
org.eclipse.tcf.agent-b7d627d444635e21b3a06f52ae36b72d03e823a0.tar.xz
org.eclipse.tcf.agent-b7d627d444635e21b3a06f52ae36b72d03e823a0.zip
TCF Agent: more support for developing value-add TCF servers, including:
1. remote data cache abstraction. 2. support for storing and re-sending TCF error reports: struct ErrorReport. 3. new service: Memory Map. 4. byte array output stream implementation.
Diffstat (limited to 'server')
-rw-r--r--server/config.h16
-rw-r--r--server/main/main.c50
-rw-r--r--server/server.vcproj44
-rw-r--r--server/services/context-proxy.c375
-rw-r--r--server/services/context-proxy.h27
5 files changed, 474 insertions, 38 deletions
diff --git a/server/config.h b/server/config.h
index 6bd046c6..2e8ba79f 100644
--- a/server/config.h
+++ b/server/config.h
@@ -20,6 +20,12 @@
#if !defined(SERVICE_Locator)
#define SERVICE_Locator 1
#endif
+#if !defined(SERVICE_FileSystem)
+#define SERVICE_FileSystem 1
+#endif
+#if !defined(SERVICE_LineNumbers)
+#define SERVICE_LineNumbers 1
+#endif
#if !defined(ENABLE_ZeroCopy)
#define ENABLE_ZeroCopy 1
@@ -54,7 +60,7 @@
#endif
#if !defined(ENABLE_SSL)
-# if (TARGET_UNIX) && !defined(__APPLE__)
+# if defined(__linux__)
# define ENABLE_SSL 1
# else
# define ENABLE_SSL 0
@@ -68,12 +74,20 @@
*/
#include "discovery.h"
+#include "filesystem.h"
+#include "linenumbers.h"
#include "diagnostics.h"
static void ini_services(Protocol * proto, TCFBroadcastGroup * bcg, TCFSuspendGroup * spg) {
#if SERVICE_Locator
ini_locator_service(proto, bcg);
#endif
+#if SERVICE_FileSystem
+ ini_file_system_service(proto);
+#endif
+#if SERVICE_LineNumbers
+ ini_line_numbers_service(proto);
+#endif
ini_diagnostics_service(proto);
}
diff --git a/server/main/main.c b/server/main/main.c
index ba453890..0b1ce582 100644
--- a/server/main/main.c
+++ b/server/main/main.c
@@ -29,12 +29,8 @@
#include "events.h"
#include "trace.h"
#include "myalloc.h"
-#include "json.h"
-#include "channel.h"
-#include "protocol.h"
-#include "proxy.h"
-#include "discovery.h"
#include "errors.h"
+#include "context-proxy.h"
static char * progname;
static Protocol * proto;
@@ -42,37 +38,25 @@ static ChannelServer * serv;
static TCFBroadcastGroup * bcg;
static TCFSuspendGroup * spg;
-static void channel_server_connecting(Channel * c) {
- trace(LOG_PROTOCOL, "channel server connecting");
-
- send_hello_message(c->client_data, c);
- flush_stream(&c->out);
-}
-
-static void channel_server_connected(Channel * c) {
+static void channel_redirected(Channel * host, Channel * target) {
int i;
-
- trace(LOG_PROTOCOL, "channel server connected, peer services:");
- for (i = 0; i < c->peer_service_cnt; i++) {
- trace(LOG_PROTOCOL, " %s", c->peer_service_list[i]);
+ int service_ln = 0;
+ int service_mm = 0;
+ for (i = 0; i < target->peer_service_cnt; i++) {
+ protocol_get_service(host->protocol, target->peer_service_list[i]);
+ if (strcmp(target->peer_service_list[i], "LineNumbers") == 0) service_ln = 1;
+ if (strcmp(target->peer_service_list[i], "MemoryMap") == 0) service_mm = 1;
+ }
+ if (!service_ln && service_mm) {
+ ini_line_numbers_service(host->protocol);
+ create_context_proxy(host, target);
}
-}
-
-static void channel_server_receive(Channel * c) {
- handle_protocol_message(c->client_data, c);
-}
-
-static void channel_server_disconnected(Channel * c) {
- trace(LOG_PROTOCOL, "channel server disconnected");
}
static void channel_new_connection(ChannelServer * serv, Channel * c) {
protocol_reference(proto);
- c->client_data = proto;
- c->connecting = channel_server_connecting;
- c->connected = channel_server_connected;
- c->receive = channel_server_receive;
- c->disconnected = channel_server_disconnected;
+ c->protocol = proto;
+ c->redirected = channel_redirected;
channel_set_suspend_group(c, spg);
channel_set_broadcast_group(c, bcg);
channel_start(c);
@@ -162,22 +146,20 @@ int main(int argc, char ** argv) {
ps = channel_peer_from_url(url);
if (ps == NULL) {
- fprintf(stderr, "invalid server URL (-s option value): %s\n", url);
+ fprintf(stderr, "%s: invalid server URL (-s option value): %s\n", progname, url);
exit(1);
}
peer_server_addprop(ps, loc_strdup("Name"), loc_strdup("TCF Proxy"));
peer_server_addprop(ps, loc_strdup("Proxy"), loc_strdup(""));
serv = channel_server(ps);
if (serv == NULL) {
- fprintf(stderr, "cannot create TCF server\n");
+ fprintf(stderr, "%s: cannot create TCF server: %s\n", progname, errno_to_str(errno));
exit(1);
}
serv->new_conn = channel_new_connection;
discovery_start();
- /* Process events - must run on the initial thread since ptrace()
- * returns ECHILD otherwise, thinking we are not the owner. */
run_event_loop();
return 0;
}
diff --git a/server/server.vcproj b/server/server.vcproj
index e1e76838..ddf7ba73 100644
--- a/server/server.vcproj
+++ b/server/server.vcproj
@@ -177,6 +177,10 @@
>
</File>
<File
+ RelativePath=".\services\context-proxy.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\diagnostics.c"
>
</File>
@@ -188,6 +192,34 @@
RelativePath="..\agent\services\discovery_udp.c"
>
</File>
+ <File
+ RelativePath="..\agent\services\dwarfcache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\services\dwarfexpr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\services\dwarfframe.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\services\dwarfio.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\services\filesystem.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\services\linenumbers_elf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\services\tcf_elf.c"
+ >
+ </File>
</Filter>
<Filter
Name="main"
@@ -209,6 +241,14 @@
>
</File>
<File
+ RelativePath="..\agent\framework\cache.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\framework\cache.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\channel.c"
>
</File>
@@ -221,6 +261,10 @@
>
</File>
<File
+ RelativePath="..\agent\framework\cpudefs.c"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\errors.c"
>
</File>
diff --git a/server/services/context-proxy.c b/server/services/context-proxy.c
index f57aea74..830407b9 100644
--- a/server/services/context-proxy.c
+++ b/server/services/context-proxy.c
@@ -21,21 +21,305 @@
#if ENABLE_DebugContext && ENABLE_ContextProxy
#include <errno.h>
+#include <assert.h>
#include "context.h"
+#include "myalloc.h"
+#include "exceptions.h"
+#include "protocol.h"
+#include "json.h"
+#include "cache.h"
+#include "memorymap.h"
+#include "context-proxy.h"
typedef struct ContextCache ContextCache;
+typedef struct MemoryCache MemoryCache;
typedef struct PeerCache PeerCache;
struct ContextCache {
Context * ctx;
+ PeerCache * peer;
+ AbstractCache cache;
+
+ /* Memory Map */
+ ErrorReport * mem_regions_error;
+ unsigned mem_regions_cnt;
+ MemoryRegion * mem_regions;
+ ReplyHandlerInfo * pending_get_map;
+
+ /* Register definitions */
+ ErrorReport * reg_error;
+ unsigned reg_cnt;
+ char ** reg_ids;
+ char * reg_ids_str;
+ RegisterDefinition * reg_defs;
+ RegisterDefinition * pc_def;
+ ReplyHandlerInfo * pending_get_regs;
+
+ /* Run Control */
+ int has_state;
+
+ /* Memory */
+ LINK mem_cache;
+};
+
+struct MemoryCache {
+ LINK link;
+ AbstractCache cache;
+ int canceled;
+ ErrorReport * error;
+ ContextAddress addr;
+ void * buf;
+ size_t size;
+ ReplyHandlerInfo * pending_command;
};
struct PeerCache {
- int x;
+ LINK link_all;
+ Channel * host;
+ Channel * target;
};
+#define peers2peer(A) ((PeerCache *)((char *)(A) - offsetof(PeerCache, link_all)))
+#define mems2mem(A) ((MemoryCache *)((char *)(A) - offsetof(MemoryCache, link)))
+
+static LINK peers;
+
+static MemoryRegion * mem_buf = NULL;
+static unsigned mem_buf_max = 0;
+static unsigned mem_buf_pos = 0;
+
+static unsigned * ids_buf = NULL;
+static unsigned ids_buf_max = 0;
+static unsigned ids_buf_pos = 0;
+
+static char * str_buf = NULL;
+static unsigned str_buf_max = 0;
+static unsigned str_buf_pos = 0;
+
+static char * map_to_local_file(char * file_name) {
+ return file_name;
+}
+
+static void read_memory_map_struct(InputStream * inp, char * name, void * args) {
+ MemoryRegion * m = (MemoryRegion *)args;
+ if (strcmp(name, "Addr") == 0) m->addr = (ContextAddress)json_read_int64(inp);
+ else if (strcmp(name, "Size") == 0) m->size = json_read_ulong(inp);
+ else if (strcmp(name, "Offs") == 0) m->file_offs = json_read_ulong(inp);
+ else if (strcmp(name, "Flags") == 0) m->flags = json_read_ulong(inp);
+ else if (strcmp(name, "FileName") == 0) m->file_name = json_read_alloc_string(inp);
+ else loc_free(json_skip_object(inp));
+}
+
+static void read_memory_map_item(InputStream * inp, void * args) {
+ MemoryRegion * m;
+ if (mem_buf_pos >= mem_buf_max) {
+ mem_buf_max = mem_buf_max == 0 ? 16 : mem_buf_max * 2;
+ mem_buf = loc_realloc(mem_buf, sizeof(MemoryRegion) * mem_buf_max);
+ }
+ m = mem_buf + mem_buf_pos;
+ memset(m, 0, sizeof(MemoryRegion));
+ if (json_read_struct(inp, read_memory_map_struct, m) && m->file_name != NULL) {
+ struct stat buf;
+ char * fnm = map_to_local_file(m->file_name);
+ if (fnm != m->file_name) {
+ loc_free(m->file_name);
+ m->file_name = fnm == NULL ? NULL : loc_strdup(fnm);
+ }
+ if (fnm == NULL || stat(fnm, &buf) < 0) {
+ loc_free(m->file_name);
+ }
+ else {
+ m->dev = buf.st_dev;
+ m->ino = buf.st_ino;
+ mem_buf_pos++;
+ }
+ }
+}
+
+static void read_ids_item(InputStream * inp, void * args) {
+ int n;
+ char id[256];
+ if (ids_buf_pos >= ids_buf_max) {
+ ids_buf_max = ids_buf_max == 0 ? 16 : ids_buf_max * 2;
+ ids_buf = loc_realloc(ids_buf, sizeof(unsigned) * ids_buf_max);
+ }
+ n = json_read_string(inp, id, sizeof(id));
+ if (n <= 0) return;
+ n++;
+ if (n > sizeof(id)) n = sizeof(id);
+ if (str_buf_pos + n > str_buf_max) {
+ str_buf_max = str_buf_max == 0 ? sizeof(id) : str_buf_max * 2;
+ str_buf = loc_realloc(str_buf, str_buf_max);
+ }
+ memcpy(str_buf + str_buf_pos, id, n);
+ ids_buf[ids_buf_pos++] = str_buf_pos;
+ str_buf_pos += n;
+}
+
+static int validate_context_cache(Channel * c, void * args, int error) {
+ ContextCache * cache = (ContextCache *)args;
+
+ assert(cache->peer->target == c);
+ if (cache->ctx->parent == NULL) {
+ /* Get memory map */
+ if (cache->pending_get_map != NULL) {
+ assert(cache->mem_regions == NULL);
+ cache->mem_regions_error = get_error_report(error);
+ if (!error) {
+ cache->mem_regions_error = get_error_report(read_errno(&c->inp));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ mem_buf_pos = 0;
+ json_read_array(&c->inp, read_memory_map_item, NULL);
+ cache->mem_regions_cnt = mem_buf_pos;
+ cache->mem_regions = loc_alloc(sizeof(MemoryRegion) * mem_buf_pos);
+ memcpy(cache->mem_regions, mem_buf, sizeof(MemoryRegion) * mem_buf_pos);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ }
+ }
+ else if (cache->mem_regions == NULL && cache->mem_regions_error == 0) {
+ cache->pending_get_map = protocol_send_command(c, "MemoryMap", "get", validate_context_cache, args);
+ write_stringz(&c->out, container_id(cache->ctx));
+ write_stream(&c->out, MARKER_EOM);
+ flush_stream(&c->out);
+ return 0;
+ }
+ }
+ else {
+ /* Get register descriptions */
+ if (cache->pending_get_regs != NULL) {
+ assert(cache->reg_ids == NULL);
+ assert(cache->reg_ids_str == NULL);
+ cache->reg_error = get_error_report(error);
+ if (!error) {
+ unsigned i;
+ cache->reg_error = get_error_report(read_errno(&c->inp));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ ids_buf_pos = 0;
+ str_buf_pos = 0;
+ json_read_array(&c->inp, read_ids_item, NULL);
+ cache->reg_cnt = ids_buf_pos;
+ cache->reg_ids = loc_alloc(sizeof(char *) * ids_buf_pos);
+ cache->reg_ids_str = loc_alloc(str_buf_pos);
+ memcpy(cache->reg_ids_str, str_buf, str_buf_pos);
+ for (i = 0; i < cache->reg_cnt; i++) {
+ cache->reg_ids[i] = cache->reg_ids_str + ids_buf[i];
+ }
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ }
+ }
+ else if (cache->reg_ids == NULL && cache->reg_error == 0) {
+ cache->pending_get_regs = protocol_send_command(c, "Registers", "getChildren", validate_context_cache, args);
+ write_stringz(&c->out, thread_id(cache->ctx));
+ write_stream(&c->out, MARKER_EOM);
+ flush_stream(&c->out);
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+static void event_context_added(Channel * c, void * args) {
+ PeerCache * p = (PeerCache *)args;
+}
+
+static void event_context_removed(Channel * c, void * args) {
+ PeerCache * p = (PeerCache *)args;
+}
+
+static ContextCache * alloc_context_cache(void) {
+ ContextCache * c = loc_alloc_zero(sizeof(ContextCache));
+ list_init(&c->mem_cache);
+}
+
+void create_context_proxy(Channel * host, Channel * target) {
+ LINK * l;
+ PeerCache * p;
+ for (l = peers.next; l != &peers; l = l->next) {
+ p = peers2peer(l);
+ if (p->target == target) return;
+ }
+ p = loc_alloc_zero(sizeof(PeerCache));
+ p->host = host;
+ p->target = target;
+ list_add_first(&p->link_all, &peers);
+ channel_lock(host);
+#if 0
+ /* TODO: need to read and forward event message at same time */
+ add_event_handler2(target, "RunControl", "contextAdded", event_context_added, p);
+ add_event_handler2(target, "RunControl", "contextRemoved", event_context_removed, p);
+#endif
+}
+
+void context_lock(Context * ctx) {
+ assert(ctx->ref_count > 0);
+ ctx->ref_count++;
+}
+
+void context_unlock(Context * ctx) {
+ assert(ctx->ref_count > 0);
+ if (--ctx->ref_count == 0) {
+ ContextCache * c = ctx->proxy;
+ assert(list_is_empty(&ctx->children));
+ assert(ctx->parent == NULL);
+ assert(c->pending_get_map == NULL);
+ assert(c->pending_get_regs == NULL);
+ list_remove(&ctx->ctxl);
+ list_remove(&ctx->pidl);
+ release_error_report(ctx->regs_error);
+ loc_free(ctx->bp_ids);
+ loc_free(ctx->regs);
+ loc_free(ctx);
+ loc_free(c->mem_regions);
+ loc_free(c->reg_ids);
+ loc_free(c->reg_ids_str);
+ loc_free(c->reg_defs);
+ while (!list_is_empty(&c->mem_cache)) {
+ MemoryCache * m = mems2mem(c->mem_cache.next);
+ list_remove(&m->link);
+ if (m->pending_command != NULL) {
+ m->canceled = 1;
+ }
+ else {
+ loc_free(m->buf);
+ loc_free(m);
+ }
+ }
+ loc_free(c);
+ }
+}
+
+Context * id2ctx(char * id) {
+ return NULL;
+}
+
int context_has_state(Context * ctx) {
- return 0;
+ ContextCache * cache = (ContextCache *)ctx->proxy;
+ if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache);
+ return cache->has_state;
+}
+
+static void validate_memory_cache(Channel * c, void * args, int error) {
+ MemoryCache * m = (MemoryCache *)args;
+ m->error = get_error_report(error);
+ if (!error) {
+ size_t pos = 0;
+ JsonReadBinaryState state;
+ json_read_binary_start(&state, &c->inp);
+ for (;;) {
+ int rd = json_read_binary_data(&state, (int8_t *)m->buf + pos, m->size - pos);
+ if (rd == 0) break;
+ pos += rd;
+ }
+ json_read_binary_end(&state);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ m->error = get_error_report(read_errno(&c->inp));
+
+
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ }
}
int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
@@ -44,11 +328,96 @@ int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t
}
int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
- errno = EINVAL;
+ ContextCache * cache = (ContextCache *)ctx->proxy;
+ Channel * c = cache->peer->target;
+ MemoryCache * m = NULL;
+ LINK * l = NULL;
+
+ for (l = cache->mem_cache.next; l != &cache->mem_cache; l = l->next) {
+ m = mems2mem(l);
+ if (address >= m->addr && address + size <= m->addr + m->size) {
+ if (m->pending_command != NULL) cache_wait(&m->cache);
+ memcpy(buf, (int8_t *)m->buf + (address - m->addr), size);
+ errno = set_error_report_errno(m->error);
+ return !errno ? 0 : -1;
+ }
+ }
+
+ m = loc_alloc_zero(sizeof(MemoryCache));
+ m->addr = address;
+ m->buf = loc_alloc(size);
+ m->size = size;
+ m->pending_command = protocol_send_command(c, "Memory", "get", validate_memory_cache, m);
+ write_stringz(&c->out, container_id(cache->ctx));
+ json_write_int64(&c->out, m->addr);
+ write_stream(&c->out, 0);
+ json_write_long(&c->out, 1);
+ write_stream(&c->out, 0);
+ json_write_long(&c->out, m->size);
+ write_stream(&c->out, 0);
+ json_write_long(&c->out, 0);
+ write_stream(&c->out, 0);
+ write_stream(&c->out, MARKER_EOM);
+ flush_stream(&c->out);
+ cache_wait(&m->cache);
return -1;
}
+void memory_map_get_regions(Context * ctx, MemoryRegion ** regions, unsigned * cnt) {
+ ContextCache * cache = (ContextCache *)ctx->proxy;
+ if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache);
+ *regions = cache->mem_regions;
+ *cnt = cache->mem_regions_cnt;
+}
+
+RegisterDefinition * get_reg_definitions(Context * ctx) {
+ ContextCache * cache = (ContextCache *)ctx->proxy;
+ if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache);
+ return cache->reg_defs;
+}
+
+RegisterDefinition * get_PC_definition(Context * ctx) {
+ ContextCache * cache = (ContextCache *)ctx->proxy;
+ if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache);
+ return cache->pc_def;
+}
+
+RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, unsigned munbering_convention) {
+ RegisterDefinition * defs;
+ ContextCache * cache = (ContextCache *)ctx->proxy;
+ if (!validate_context_cache(cache->peer->target, cache, 0)) cache_wait(&cache->cache);
+ defs = cache->reg_defs;
+ while (defs != NULL && defs->name != NULL) {
+ switch (munbering_convention) {
+ case REGNUM_DWARF:
+ if (defs->dwarf_id == id) return defs;
+ break;
+ case REGNUM_EH_FRAME:
+ if (defs->eh_frame_id == id) return defs;
+ break;
+ }
+ defs++;
+ }
+ return NULL;
+}
+
+static void channel_close_listener(Channel * c) {
+ LINK * l = NULL;
+
+ for (l = peers.next; l != &peers; l = l->next) {
+ PeerCache * p = peers2peer(l);
+ if (p->target == c) {
+ channel_unlock(p->host);
+ list_remove(&p->link_all);
+ loc_free(p);
+ return;
+ }
+ }
+}
+
void init_contexts_sys_dep(void) {
+ list_init(&peers);
+ add_channel_close_listener(channel_close_listener);
}
#endif /* ENABLE_DebugContext && ENABLE_ContextProxy */
diff --git a/server/services/context-proxy.h b/server/services/context-proxy.h
new file mode 100644
index 00000000..3217654e
--- /dev/null
+++ b/server/services/context-proxy.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 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.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * This module forwards handling of process/thread OS contexts to remote peer.
+ */
+
+#ifndef D_context_proxy
+#define D_context_proxy
+
+#include "channel.h"
+
+extern void create_context_proxy(Channel * host, Channel * target);
+
+#endif /* D_context_proxy */
+

Back to the top