Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--framework/cache.c19
-rw-r--r--framework/cache.h6
-rw-r--r--framework/channel.h1
-rw-r--r--framework/cpudefs.c64
-rw-r--r--framework/cpudefs.h44
-rw-r--r--framework/errors.c2
-rw-r--r--framework/json.c21
-rw-r--r--framework/mdep.h1
-rw-r--r--framework/protocol.c5
-rw-r--r--framework/proxy.c55
-rw-r--r--framework/proxy.h9
-rw-r--r--machine/x86_64/cpudefs-mdep.h4
-rw-r--r--server/Makefile3
-rw-r--r--server/main/main.c45
-rw-r--r--server/server.vcproj144
-rw-r--r--server/services/context-proxy.c592
-rw-r--r--services/breakpoints.c1
-rw-r--r--services/dwarfcache.c3
-rw-r--r--services/dwarfexpr.c56
-rw-r--r--services/dwarfframe.c159
-rw-r--r--services/dwarfframe.h25
-rw-r--r--services/linenumbers_proxy.c1
-rw-r--r--services/stacktrace.c224
-rw-r--r--services/stacktrace.h8
-rw-r--r--services/symbols.c96
-rw-r--r--services/symbols.h21
-rw-r--r--services/symbols_elf.c66
-rw-r--r--services/symbols_proxy.c155
-rw-r--r--services/symbols_win32.c5
29 files changed, 1298 insertions, 537 deletions
diff --git a/framework/cache.c b/framework/cache.c
index fad7d26b..5c406b47 100644
--- a/framework/cache.c
+++ b/framework/cache.c
@@ -31,6 +31,10 @@ typedef struct WaitingCacheClient {
void * args;
size_t args_size;
int args_copy;
+#ifndef NDEBUG
+ const char * file;
+ int line;
+#endif
} WaitingCacheClient;
static WaitingCacheClient current_client = {0, 0, 0, 0, 0};
@@ -38,6 +42,7 @@ static int client_exited = 0;
static int cache_miss_cnt = 0;
static WaitingCacheClient * wait_list_buf;
static unsigned wait_list_max;
+static LINK cache_list;
static void run_cache_client(void) {
Trap trap;
@@ -52,7 +57,7 @@ static void run_cache_client(void) {
assert(client_exited);
flush_stream(out);
}
- else if (get_error_code(trap.error) != ERR_CACHE_MISS || client_exited) {
+ else if (get_error_code(trap.error) != ERR_CACHE_MISS || client_exited || cache_miss_cnt == 0) {
trace(LOG_ALWAYS, "Unhandled exception in data cache client: %d %s", trap.error, errno_to_str(trap.error));
}
if (cache_miss_cnt == 0 && current_client.args_copy) loc_free(current_client.args);
@@ -81,10 +86,15 @@ void cache_exit(void) {
client_exited = 1;
}
+#ifdef NDEBUG
void cache_wait(AbstractCache * cache) {
+#else
+void cache_wait_dbg(const char * file, int line, AbstractCache * cache) {
+#endif
assert(is_dispatch_thread());
assert(client_exited == 0);
if (current_client.client != NULL && cache_miss_cnt == 0) {
+ if (cache_list.next == NULL) list_init(&cache_list);
if (cache->wait_list_cnt >= cache->wait_list_max) {
cache->wait_list_max += 8;
cache->wait_list_buf = (WaitingCacheClient *)loc_realloc(cache->wait_list_buf, cache->wait_list_max * sizeof(WaitingCacheClient));
@@ -95,6 +105,11 @@ void cache_wait(AbstractCache * cache) {
current_client.args = mem;
current_client.args_copy = 1;
}
+#ifndef NDEBUG
+ current_client.file = file;
+ current_client.line = line;
+#endif
+ if (cache->wait_list_cnt == 0) list_add_last(&cache->link, &cache_list);
cache->wait_list_buf[cache->wait_list_cnt++] = current_client;
channel_lock(current_client.channel);
}
@@ -107,6 +122,7 @@ void cache_notify(AbstractCache * cache) {
unsigned cnt = cache->wait_list_cnt;
assert(is_dispatch_thread());
+ list_remove(&cache->link);
cache->wait_list_cnt = 0;
if (wait_list_max < cnt) {
wait_list_max = cnt;
@@ -127,6 +143,7 @@ Channel * cache_channel(void) {
void cache_dispose(AbstractCache * cache) {
assert(is_dispatch_thread());
assert(cache->wait_list_cnt == 0);
+ assert(list_is_empty(&cache->link));
loc_free(cache->wait_list_buf);
memset(cache, 0, sizeof(*cache));
}
diff --git a/framework/cache.h b/framework/cache.h
index 48ed87d7..4e105b83 100644
--- a/framework/cache.h
+++ b/framework/cache.h
@@ -103,6 +103,7 @@
typedef void CacheClient(void *);
typedef struct AbstractCache {
+ LINK link;
struct WaitingCacheClient * wait_list_buf;
unsigned wait_list_cnt;
unsigned wait_list_max;
@@ -126,7 +127,12 @@ extern void cache_exit(void);
* Cache data handling code call cache_wait() to suspend current client
* until cache validation is done.
*/
+#ifdef NDEBUG
extern void cache_wait(AbstractCache * cache);
+#else
+#define cache_wait(cache) cache_wait_dbg(__FILE__, __LINE__, cache)
+extern void cache_wait_dbg(const char * file, int line, AbstractCache * cache);
+#endif
/*
* Invoke all items in the cache wait list.
diff --git a/framework/channel.h b/framework/channel.h
index 61445427..0127f80f 100644
--- a/framework/channel.h
+++ b/framework/channel.h
@@ -72,7 +72,6 @@ struct Channel {
void (*connecting)(Channel *); /* Called when channel is ready for transmit */
void (*connected)(Channel *); /* Called when channel negotiation is complete */
void (*receive)(Channel *); /* Called when messages has been received */
- void (*redirected)(Channel *, Channel *);/* Called when channel is redirected */
void (*disconnected)(Channel *); /* Called when channel is disconnected */
};
diff --git a/framework/cpudefs.c b/framework/cpudefs.c
index 4228cd4b..5ceaa7d1 100644
--- a/framework/cpudefs.c
+++ b/framework/cpudefs.c
@@ -13,7 +13,7 @@
*******************************************************************************/
/*
- * This module contains definitions of target CPU registers.
+ * This module contains definitions of target CPU registers and stack frames.
*/
#include "config.h"
@@ -27,6 +27,7 @@
#include "errors.h"
#include "context.h"
#include "myalloc.h"
+#include "exceptions.h"
#include "breakpoints.h"
#include "symbols.h"
@@ -204,7 +205,7 @@ int write_reg_value(RegisterDefinition * reg_def, StackFrame * frame, uint64_t v
return -1;
}
-int id2frame(char * id, Context ** ctx, int * frame) {
+int id2frame(const char * id, Context ** ctx, int * frame) {
int f = 0;
Context * c = NULL;
@@ -258,7 +259,7 @@ char * register2id(Context * ctx, int frame, RegisterDefinition * reg) {
return id;
}
-int id2register(char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def) {
+int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def) {
int r = 0;
*ctx = NULL;
@@ -305,4 +306,61 @@ int id2register(char * id, Context ** ctx, int * frame, RegisterDefinition ** re
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(cmd->reg, frame, 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;
+ default:
+ stack_trace_error();
+ break;
+ }
+ }
+ if (stk_pos != 1) stack_trace_error();
+ return stk[0];
+}
+
#endif /* ENABLE_DebugContext */
diff --git a/framework/cpudefs.h b/framework/cpudefs.h
index 2c25d431..387c0065 100644
--- a/framework/cpudefs.h
+++ b/framework/cpudefs.h
@@ -13,7 +13,7 @@
*******************************************************************************/
/*
- * This module contains definitions of target CPU registers.
+ * This module contains definitions of target CPU registers and stack frames.
*/
#ifndef D_cpudefs
@@ -48,6 +48,39 @@ struct RegisterDefinition {
int traceable; /* register value can be traced using .eh_frame of .debug_frame */
};
+/* Stack tracing command codes */
+#define SFT_CMD_NUMBER 1
+#define SFT_CMD_REGISTER 2
+#define SFT_CMD_FP 3
+#define SFT_CMD_DEREF 4
+#define SFT_CMD_ADD 5
+
+/* Stack tracing command */
+typedef struct StackTracingCommand {
+ int cmd;
+ int64_t num;
+ size_t size;
+ int big_endian;
+ RegisterDefinition * reg;
+} StackTracingCommand;
+
+/* Stack tracing command sequence */
+typedef struct StackTracingCommandSequence {
+ RegisterDefinition * reg;
+ int cmds_cnt;
+ int cmds_max;
+ StackTracingCommand cmds[1];
+} StackTracingCommandSequence;
+
+/* Complete stack tracing info for a range of instruction addresses */
+typedef struct StackTracingInfo {
+ ContextAddress addr;
+ ContextAddress size;
+ StackTracingCommandSequence * fp;
+ StackTracingCommandSequence ** regs;
+ int reg_cnt;
+} StackTracingInfo;
+
#define STACK_BOTTOM_FRAME 0
#define STACK_NO_FRAME (-1)
#define STACK_TOP_FRAME (-2)
@@ -87,13 +120,13 @@ extern void set_regs_PC(RegisterData * x, ContextAddress y);
extern char * frame2id(Context * ctx, int frame);
/* Get stack frame for TCF ID */
-extern int id2frame(char * id, Context ** ctx, int * frame);
+extern int id2frame(const char * id, Context ** ctx, int * frame);
/* Get TCF ID of a register */
extern char * register2id(Context * ctx, int frame, RegisterDefinition * reg);
/* Get register for TCF ID */
-extern int id2register(char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def);
+extern int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition ** reg_def);
#if !defined(_WRS_KERNEL)
extern unsigned char BREAK_INST[]; /* breakpoint instruction */
@@ -114,6 +147,11 @@ extern size_t get_break_size(void);
*/
extern int crawl_stack_frame(struct Context * ctx, StackFrame * frame, StackFrame * down);
+/*
+ * Execute stack tracing command sequence.
+ */
+extern uint64_t evaluate_stack_trace_commands(Context * ctx, StackFrame * frame, StackTracingCommandSequence * cmds);
+
#endif /* ENABLE_DebugContext */
#endif /* D_cpudefs */
diff --git a/framework/errors.c b/framework/errors.c
index da28fa1d..7bd9d4c6 100644
--- a/framework/errors.c
+++ b/framework/errors.c
@@ -211,7 +211,7 @@ int set_errno(int no, const char * msg) {
int len = strlen(msg) + strlen(text0) + 4;
char * text1 = (char *)loc_alloc(len);
ErrorMessage * m = NULL;
- snprintf(text1, len, "%s: %s", msg, text0);
+ snprintf(text1, len, "%s. %s", msg, text0);
m = alloc_msg(SRC_MESSAGE);
m->error = get_error_code(no);
m->text = text1;
diff --git a/framework/json.c b/framework/json.c
index 7e71ab3b..6a084db2 100644
--- a/framework/json.c
+++ b/framework/json.c
@@ -373,25 +373,8 @@ int json_read_struct(InputStream * inp, JsonStructCallBack * call_back, void * a
for (;;) {
ch = read_stream(inp);
if (ch == '"') break;
- if (ch == '\\') {
- ch = read_stream(inp);
- switch (ch) {
- case '"': break;
- case '\\': break;
- case '/': break;
- case 'b': ch = '\b'; break;
- case 'f': ch = '\f'; break;
- case 'n': ch = '\n'; break;
- case 'r': ch = '\r'; break;
- case 't': ch = '\t'; break;
- case 'u': ch = readHexChar(inp); break;
- default: exception(ERR_JSON_SYNTAX);
- }
- }
- if (nm_len < (int)sizeof(nm) - 1) {
- nm[nm_len] = (char)ch;
- nm_len++;
- }
+ if (ch == '\\') ch = read_esc_char(inp);
+ if (nm_len < (int)sizeof(nm) - 1) nm[nm_len++] = (char)ch;
}
nm[nm_len] = 0;
ch = read_stream(inp);
diff --git a/framework/mdep.h b/framework/mdep.h
index 12810deb..db7236e9 100644
--- a/framework/mdep.h
+++ b/framework/mdep.h
@@ -300,6 +300,7 @@ extern char * canonicalize_file_name(const char * path);
#if _WRS_VXWORKS_MAJOR < 6 || _WRS_VXWORKS_MAJOR == 6 && _WRS_VXWORKS_MINOR < 8
typedef unsigned long uintptr_t;
+#define send(s, buf, len, flags) (send)(s, (char *)(buf), len, flags)
#endif
typedef unsigned long useconds_t;
diff --git a/framework/protocol.c b/framework/protocol.c
index e0cbe319..68e180fa 100644
--- a/framework/protocol.c
+++ b/framework/protocol.c
@@ -107,6 +107,7 @@ ServiceInfo * protocol_get_service(void * owner, const char * name) {
while (s != NULL && (s->owner != owner || strcmp(s->name, name) != 0)) s = s->next;
if (s == NULL) {
+ assert(strcmp(name, "ZeroCopy") != 0);
s = (ServiceInfo *)loc_alloc(sizeof(ServiceInfo));
s->owner = owner;
s->name = loc_strdup(name);
@@ -426,7 +427,7 @@ ReplyHandlerInfo * protocol_send_command(Channel * c, const char * service, cons
post_event(send_command_failed, rh);
}
else {
- int h;
+ unsigned h;
unsigned long tokenid;
do tokenid = p->tokenid++;
while (find_reply_handler(c, tokenid, 0) != NULL);
@@ -599,7 +600,7 @@ int protocol_cancel_command(ReplyHandlerInfo * rh) {
}
static void channel_closed(Channel * c) {
- int i;
+ unsigned i;
assert(is_dispatch_thread());
for (i = 0; i < EVENT_HASH_SIZE; i++) {
diff --git a/framework/proxy.c b/framework/proxy.c
index 867fc540..79017859 100644
--- a/framework/proxy.c
+++ b/framework/proxy.c
@@ -34,7 +34,11 @@ typedef struct Proxy {
int instance;
} Proxy;
+static ChannelRedirectionListener redirection_listeners[16];
+static int redirection_listeners_cnt = 0;
+
static void proxy_connecting(Channel * c) {
+ int i;
Proxy * target = (Proxy *)c->client_data;
Proxy * host = target + target->other;
@@ -43,13 +47,18 @@ static void proxy_connecting(Channel * c) {
assert(c->state == ChannelStateStarted);
assert(host->c->state == ChannelStateHelloReceived);
- trace(LOG_PROXY, "Proxy waiting Hello from target");
+ for (i = 0; i < redirection_listeners_cnt; i++) {
+ redirection_listeners[i](host->c, target->c);
+ }
target->c->disable_zero_copy = !host->c->out.supports_zero_copy;
send_hello_message(target->c);
+
+ trace(LOG_PROXY, "Proxy waiting Hello from target");
}
static void proxy_connected(Channel * c) {
+ int i;
Proxy * target = (Proxy *)c->client_data;
Proxy * host = target + target->other;
@@ -63,16 +72,16 @@ static void proxy_connected(Channel * c) {
host->c->disable_zero_copy = !target->c->out.supports_zero_copy;
- if (host->c->redirected) {
- host->c->redirected(host->c, target->c);
+ trace(LOG_PROXY, "Proxy connected, target services:");
+ for (i = 0; i < target->c->peer_service_cnt; i++) {
+ char * nm = target->c->peer_service_list[i];
+ trace(LOG_PROXY, " %s", nm);
+ if (strcmp(nm, "ZeroCopy") == 0) continue;
+ protocol_get_service(host->proto, nm);
}
- else {
- int i;
- trace(LOG_PROXY, "Proxy connected, target services:");
- for (i = 0; i < target->c->peer_service_cnt; i++) {
- trace(LOG_PROXY, " %s", target->c->peer_service_list[i]);
- protocol_get_service(host->proto, target->c->peer_service_list[i]);
- }
+
+ for (i = 0; i < redirection_listeners_cnt; i++) {
+ redirection_listeners[i](host->c, target->c);
}
send_hello_message(host->c);
@@ -131,11 +140,11 @@ static void proxy_default_message_handler(Channel * c, char ** argv, int argc) {
assert(c == proxy->c);
assert(argc > 0 && strlen(argv[0]) == 1);
if (proxy[proxy->other].c->state == ChannelStateDisconnected) return;
+
if (argv[0][0] == 'C') {
write_stringz(out, argv[0]);
- /* Prefix token with 'R'emote to distinguish from locally
- * generated commands */
- write_string(out, "R");
+ /* Prefix token with 'R'emote to distinguish from locally generated commands */
+ write_stream(out, 'R');
i = 1;
}
else if (argv[0][0] == 'R' || argv[0][0] == 'P' || argv[0][0] == 'N') {
@@ -145,10 +154,8 @@ static void proxy_default_message_handler(Channel * c, char ** argv, int argc) {
}
argv[1]++;
}
- while (i < argc) {
- write_stringz(out, argv[i]);
- i++;
- }
+
+ while (i < argc) write_stringz(out, argv[i++]);
if (log_mode & LOG_TCFLOG) {
logstr(&p, (char *)(proxy->other > 0 ? "---> " : "<--- "));
@@ -226,8 +233,10 @@ void proxy_create(Channel * c1, Channel * c2) {
trace(LOG_PROXY, "Proxy created, host services:");
for (i = 0; i < c1->peer_service_cnt; i++) {
- trace(LOG_PROXY, " %s", c1->peer_service_list[i]);
- protocol_get_service(proxy[1].proto, c1->peer_service_list[i]);
+ char * nm = c1->peer_service_list[i];
+ trace(LOG_PROXY, " %s", nm);
+ if (strcmp(nm, "ZeroCopy") == 0) continue;
+ protocol_get_service(proxy[1].proto, nm);
}
c1->state = ChannelStateHelloReceived;
notify_channel_closed(c1);
@@ -252,4 +261,10 @@ void proxy_create(Channel * c1, Channel * c2) {
channel_set_broadcast_group(c1, bcg);
channel_set_broadcast_group(c2, bcg);
channel_start(c2);
- }
+}
+
+void add_channel_redirection_listener(ChannelRedirectionListener listener) {
+ assert(redirection_listeners_cnt < (int)(sizeof(redirection_listeners) / sizeof(ChannelRedirectionListener)));
+ redirection_listeners[redirection_listeners_cnt++] = listener;
+}
+
diff --git a/framework/proxy.h b/framework/proxy.h
index 3a35c7a2..c11cca8a 100644
--- a/framework/proxy.h
+++ b/framework/proxy.h
@@ -22,6 +22,15 @@
#include "channel.h"
+/*
+ * Register channel redirection callback.
+ * When a channel is redirected, the callback is called two times:
+ * 1. before sending Hello message to target channel.
+ * 2. after receiving Hello message from target channel, but before sending Hello to host.
+ */
+typedef void (*ChannelRedirectionListener)(Channel * /* host */, Channel * /* target */);
+extern void add_channel_redirection_listener(ChannelRedirectionListener listener);
+
extern void proxy_create(Channel * c1, Channel * c2);
#endif /* D_proxy */
diff --git a/machine/x86_64/cpudefs-mdep.h b/machine/x86_64/cpudefs-mdep.h
index da2a7f03..724f6e7e 100644
--- a/machine/x86_64/cpudefs-mdep.h
+++ b/machine/x86_64/cpudefs-mdep.h
@@ -227,7 +227,11 @@ int crawl_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
if (frame->is_top_frame) {
/* Top frame */
ContextAddress addr = trace_jump(ctx, reg_ip);
+#if ENABLE_Symbols
ContextAddress plt = is_plt_section(ctx, addr);
+#else
+ ContextAddress plt = 0;
+#endif
/*
* we don't have a stack frame in a few restricted but useful cases:
diff --git a/server/Makefile b/server/Makefile
index 3247086e..28fd90cd 100644
--- a/server/Makefile
+++ b/server/Makefile
@@ -2,7 +2,8 @@ TCF_AGENT_DIR=../agent
include $(TCF_AGENT_DIR)/Makefile.inc
-CFLAGS := $(foreach dir,$(SRCDIRS),-I$(dir)) $(CFLAGS)
+override CFLAGS := $(foreach dir,$(SRCDIRS),-I$(dir)) $(CFLAGS)
+
HFILES := $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.h)) $(HFILES)
CFILES := $(sort $(foreach dir,$(SRCDIRS),$(wildcard $(dir)/*.c)) $(CFILES))
diff --git a/server/main/main.c b/server/main/main.c
index 60aa16bb..94902dc9 100644
--- a/server/main/main.c
+++ b/server/main/main.c
@@ -30,6 +30,7 @@
#include "trace.h"
#include "myalloc.h"
#include "errors.h"
+#include "proxy.h"
#include "context-proxy.h"
static char * progname;
@@ -37,33 +38,38 @@ static Protocol * proto;
static ChannelServer * serv;
static TCFBroadcastGroup * bcg;
-static void channel_redirected(Channel * host, Channel * target) {
- int i;
- int service_ln = 0;
- int service_mm = 0;
- int service_pm = 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 (strcmp(target->peer_service_list[i], "PathMap") == 0) service_pm = 1;
- }
- if (!service_pm) {
- ini_path_map_service(host->protocol);
- }
- if (service_mm) {
- ini_line_numbers_service(host->protocol);
+static void channel_redirection_listener(Channel * host, Channel * target) {
+ if (target->state == ChannelStateStarted) {
ini_line_numbers_service(target->protocol);
- ini_symbols_service(host->protocol);
ini_symbols_service(target->protocol);
- create_context_proxy(host, target);
+ }
+ if (target->state == ChannelStateConnected) {
+ int i;
+ int service_ln = 0;
+ int service_mm = 0;
+ int service_pm = 0;
+ int service_sm = 0;
+ for (i = 0; i < target->peer_service_cnt; i++) {
+ char * nm = target->peer_service_list[i];
+ if (strcmp(nm, "LineNumbers") == 0) service_ln = 1;
+ if (strcmp(nm, "Symbols") == 0) service_sm = 1;
+ if (strcmp(nm, "MemoryMap") == 0) service_mm = 1;
+ if (strcmp(nm, "PathMap") == 0) service_pm = 1;
+ }
+ if (!service_pm) {
+ ini_path_map_service(host->protocol);
+ }
+ if (service_mm) {
+ if (!service_ln) ini_line_numbers_service(host->protocol);
+ if (!service_sm) ini_symbols_service(host->protocol);
+ create_context_proxy(host, target);
+ }
}
}
static void channel_new_connection(ChannelServer * serv, Channel * c) {
protocol_reference(proto);
c->protocol = proto;
- c->redirected = channel_redirected;
channel_set_broadcast_group(c, bcg);
channel_start(c);
}
@@ -162,6 +168,7 @@ int main(int argc, char ** argv) {
exit(1);
}
serv->new_conn = channel_new_connection;
+ add_channel_redirection_listener(channel_redirection_listener);
discovery_start();
diff --git a/server/server.vcproj b/server/server.vcproj
index e916d938..aca1f420 100644
--- a/server/server.vcproj
+++ b/server/server.vcproj
@@ -191,42 +191,82 @@
>
</File>
<File
+ RelativePath="..\agent\services\diagnostics.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\discovery.c"
>
</File>
<File
+ RelativePath="..\agent\services\discovery.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\discovery_udp.c"
>
</File>
<File
+ RelativePath="..\agent\services\discovery_udp.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\dwarfcache.c"
>
</File>
<File
+ RelativePath="..\agent\services\dwarfcache.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\dwarfexpr.c"
>
</File>
<File
+ RelativePath="..\agent\services\dwarfexpr.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\dwarfframe.c"
>
</File>
<File
+ RelativePath="..\agent\services\dwarfframe.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\dwarfio.c"
>
</File>
<File
+ RelativePath="..\agent\services\dwarfio.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\dwarfreloc.c"
>
</File>
<File
+ RelativePath="..\agent\services\dwarfreloc.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\filesystem.c"
>
</File>
<File
+ RelativePath="..\agent\services\filesystem.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\linenumbers.c"
>
</File>
<File
+ RelativePath="..\agent\services\linenumbers.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\linenumbers_elf.c"
>
</File>
@@ -235,14 +275,26 @@
>
</File>
<File
+ RelativePath="..\agent\services\pathmap.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\stacktrace.c"
>
</File>
<File
+ RelativePath="..\agent\services\stacktrace.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\symbols.c"
>
</File>
<File
+ RelativePath="..\agent\services\symbols.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\services\symbols_elf.c"
>
</File>
@@ -267,10 +319,18 @@
>
</File>
<File
+ RelativePath="..\agent\framework\asyncreq.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\base64.c"
>
</File>
<File
+ RelativePath="..\agent\framework\base64.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\cache.c"
>
</File>
@@ -283,69 +343,153 @@
>
</File>
<File
+ RelativePath="..\agent\framework\channel.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\channel_tcp.c"
>
</File>
<File
+ RelativePath="..\agent\framework\channel_tcp.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\context.c"
>
</File>
<File
+ RelativePath="..\agent\framework\context.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\cpudefs.c"
>
</File>
<File
+ RelativePath="..\agent\framework\cpudefs.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\errors.c"
>
</File>
<File
+ RelativePath="..\agent\framework\errors.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\events.c"
>
</File>
<File
+ RelativePath="..\agent\framework\events.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\exceptions.c"
>
</File>
<File
+ RelativePath="..\agent\framework\exceptions.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\inputbuf.c"
>
</File>
<File
+ RelativePath="..\agent\framework\inputbuf.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\ip_ifc.c"
>
</File>
<File
+ RelativePath="..\agent\framework\ip_ifc.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\json.c"
>
</File>
<File
+ RelativePath="..\agent\framework\json.h"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\framework\link.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\mdep.c"
>
</File>
<File
+ RelativePath="..\agent\framework\mdep.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\myalloc.c"
>
</File>
<File
+ RelativePath="..\agent\framework\myalloc.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\peer.c"
>
</File>
<File
+ RelativePath="..\agent\framework\peer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\framework\plugins.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\protocol.c"
>
</File>
<File
+ RelativePath="..\agent\framework\protocol.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\proxy.c"
>
</File>
<File
+ RelativePath="..\agent\framework\proxy.h"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\framework\signames.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\streams.c"
>
</File>
<File
+ RelativePath="..\agent\framework\streams.h"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\framework\tcf.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\framework\trace.c"
>
</File>
+ <File
+ RelativePath="..\agent\framework\trace.h"
+ >
+ </File>
</Filter>
<File
RelativePath=".\config.h"
diff --git a/server/services/context-proxy.c b/server/services/context-proxy.c
index 95afdb5a..b2263dd2 100644
--- a/server/services/context-proxy.c
+++ b/server/services/context-proxy.c
@@ -82,6 +82,9 @@ struct ContextCache {
int pc_valid;
uint64_t suspend_pc;
char suspend_reason[256];
+ long signal;
+ char * signal_name;
+ char ** bp_ids;
/* Memory */
LINK mem_cache;
@@ -234,6 +237,8 @@ static void free_context_cache(ContextCache * c) {
loc_free(c->reg_ids);
loc_free(c->reg_ids_str);
loc_free(c->reg_defs);
+ loc_free(c->signal_name);
+ loc_free(c->bp_ids);
if (c->reg_props != NULL) {
unsigned i;
for (i = 0; i < c->reg_cnt; i++) {
@@ -296,13 +301,26 @@ static void read_run_control_context_property(InputStream * inp, const char * na
static void read_context_suspended_data(InputStream * inp, const char * name, void * args) {
ContextCache * ctx = (ContextCache *)args;
- /* TODO: read context susped data: Signal SignalName BPs */
- json_skip_object(inp);
+ if (strcmp(name, "Signal") == 0) ctx->signal = json_read_long(inp);
+ else if (strcmp(name, "SignalName") == 0) ctx->signal_name = json_read_alloc_string(inp);
+ else if (strcmp(name, "BPs") == 0) ctx->bp_ids = json_read_alloc_string_array(inp, NULL);
+ else json_skip_object(inp);
+}
+
+static void clear_context_suspended_data(ContextCache * ctx) {
+ loc_free(ctx->signal_name);
+ loc_free(ctx->bp_ids);
+ ctx->pc_valid = 0;
+ ctx->suspend_pc = 0;
+ ctx->suspend_reason[0] = 0;
+ ctx->signal = 0;
+ ctx->signal_name = NULL;
+ ctx->bp_ids = NULL;
}
static void read_context_added_item(InputStream * inp, void * args) {
PeerCache * p = (PeerCache *)args;
- ContextCache * c = loc_alloc_zero(sizeof(ContextCache));
+ ContextCache * c = (ContextCache *)loc_alloc_zero(sizeof(ContextCache));
json_read_struct(inp, read_run_control_context_property, c);
@@ -391,7 +409,7 @@ static void read_container_resumed_item(InputStream * inp, void * args) {
if (c->ctx->stopped) {
c->ctx->stopped = 0;
c->ctx->intercepted = 0;
- c->pc_valid = 0;
+ clear_context_suspended_data(c);
send_context_started_event(c->ctx);
}
}
@@ -432,30 +450,30 @@ static void event_context_removed(Channel * c, void * args) {
static void event_context_suspended(Channel * ch, void * args) {
PeerCache * p = (PeerCache *)args;
- ContextCache * c = NULL;
ContextCache buf;
+ ContextCache * c = &buf;
assert(p->target == ch);
memset(&buf, 0, sizeof(buf));
write_stringz(&p->host->out, "E");
write_stringz(&p->host->out, RUN_CONTROL);
write_stringz(&p->host->out, "contextSuspended");
- json_read_string(p->fwd_inp, buf.id, sizeof(buf.id));
+ json_read_string(p->fwd_inp, c->id, sizeof(c->id));
if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX);
- buf.suspend_pc = json_read_uint64(p->fwd_inp);
+ c = find_context_cache(p, c->id);
+ if (c == NULL) c = &buf;
+ else clear_context_suspended_data(c);
+ c->suspend_pc = json_read_uint64(p->fwd_inp);
if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX);
- json_read_string(p->fwd_inp, buf.suspend_reason, sizeof(buf.suspend_reason));
+ json_read_string(p->fwd_inp, c->suspend_reason, sizeof(c->suspend_reason));
if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX);
- json_read_struct(p->fwd_inp, read_context_suspended_data, &buf);
+ json_read_struct(p->fwd_inp, read_context_suspended_data, c);
if (read_stream(p->fwd_inp) != 0) exception(ERR_JSON_SYNTAX);
if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- c = find_context_cache(p, buf.id);
- if (c != NULL) {
+ if (c != &buf) {
assert(c->ctx->proxy == c);
c->pc_valid = 1;
- c->suspend_pc = buf.suspend_pc;
- strcpy(c->suspend_reason, buf.suspend_reason);
if (!c->ctx->stopped) {
c->ctx->stopped = 1;
c->ctx->intercepted = 1;
@@ -464,7 +482,7 @@ static void event_context_suspended(Channel * ch, void * args) {
}
}
else if (p->rc_done) {
- trace(LOG_ALWAYS, "Invalid ID in 'context suspended' event: %s", buf.id);
+ trace(LOG_ALWAYS, "Invalid ID in 'context suspended' event: %s", c->id);
}
}
@@ -487,7 +505,7 @@ static void event_context_resumed(Channel * ch, void * args) {
if (c->ctx->stopped) {
c->ctx->stopped = 0;
c->ctx->intercepted = 0;
- c->pc_valid = 0;
+ clear_context_suspended_data(c);
send_context_started_event(c->ctx);
}
}
@@ -535,7 +553,7 @@ void create_context_proxy(Channel * host, Channel * target) {
p = peers2peer(l);
if (p->target == target) return;
}
- p = loc_alloc_zero(sizeof(PeerCache));
+ p = (PeerCache *)loc_alloc_zero(sizeof(PeerCache));
p->host = host;
p->target = target;
p->fwd_inp = create_forwarding_input_stream(&p->fwd, &target->inp, &host->out);
@@ -559,7 +577,7 @@ void context_lock(Context * ctx) {
void context_unlock(Context * ctx) {
assert(ctx->ref_count > 0);
if (--ctx->ref_count == 0) {
- ContextCache * c = ctx->proxy;
+ ContextCache * c = (ContextCache *)ctx->proxy;
assert(list_is_empty(&ctx->children));
assert(ctx->parent == NULL);
loc_free(ctx);
@@ -578,7 +596,7 @@ static void read_rc_children_item(InputStream * inp, void * args) {
json_read_string(inp, id, sizeof(id));
if (find_context_cache(p, id) == NULL) {
- ContextCache * c = loc_alloc_zero(sizeof(ContextCache));
+ ContextCache * c = (ContextCache *)loc_alloc_zero(sizeof(ContextCache));
strcpy(c->id, id);
c->peer = p;
protocol_send_command(p->target, "RunControl", "getContext", validate_peer_cache_context, c);
@@ -606,106 +624,131 @@ static void set_rc_error(PeerCache * p, int error) {
static void validate_peer_cache_children(Channel * c, void * args, int error) {
PeerCache * p = (PeerCache *)args;
+ Trap trap;
assert(p->target == c);
assert(p->rc_pending_cnt > 0);
- p->rc_pending_cnt--;
- if (error) {
- set_rc_error(p, error);
+ if (set_trap(&trap)) {
+ p->rc_pending_cnt--;
+ if (!error) {
+ error = read_errno(&c->inp);
+ json_read_array(&c->inp, read_rc_children_item, p);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ flush_stream(&p->target->out);
+ }
+ clear_trap(&trap);
}
else {
- set_rc_error(p, read_errno(&c->inp));
- json_read_array(&c->inp, read_rc_children_item, p);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- flush_stream(&p->target->out);
+ error = trap.error;
}
+ set_rc_error(p, error);
set_rc_done(p);
+ if (trap.error) exception(trap.error);
}
static void validate_peer_cache_context(Channel * c, void * args, int error) {
- ContextCache * x = args;
+ ContextCache * x = (ContextCache *)args;
PeerCache * p = x->peer;
+ Trap trap;
assert(p->target == c);
assert(p->rc_pending_cnt > 0);
- p->rc_pending_cnt--;
- if (error) {
- set_rc_error(p, error);
- free_context_cache(x);
- }
- else {
- set_rc_error(p, error = read_errno(&c->inp));
- json_read_struct(&c->inp, read_run_control_context_property, x);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- if (error || find_context_cache(p, x->id) != NULL) {
+ if (set_trap(&trap)) {
+ p->rc_pending_cnt--;
+ if (error) {
+ set_rc_error(p, error);
free_context_cache(x);
}
- else if (x->has_state) {
- protocol_send_command(p->target, "RunControl", "getState", validate_peer_cache_state, x);
- json_write_string(&p->target->out, x->id);
- write_stream(&p->target->out, 0);
- write_stream(&p->target->out, MARKER_EOM);
- flush_stream(&p->target->out);
- p->rc_pending_cnt++;
- }
else {
- add_context_cache(p, x);
- protocol_send_command(p->target, "RunControl", "getChildren", validate_peer_cache_children, p);
- json_write_string(&p->target->out, x->id);
- write_stream(&p->target->out, 0);
- write_stream(&p->target->out, MARKER_EOM);
- flush_stream(&p->target->out);
- p->rc_pending_cnt++;
+ set_rc_error(p, error = read_errno(&c->inp));
+ json_read_struct(&c->inp, read_run_control_context_property, x);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ if (error || find_context_cache(p, x->id) != NULL) {
+ free_context_cache(x);
+ }
+ else if (x->has_state) {
+ protocol_send_command(p->target, "RunControl", "getState", validate_peer_cache_state, x);
+ json_write_string(&p->target->out, x->id);
+ write_stream(&p->target->out, 0);
+ write_stream(&p->target->out, MARKER_EOM);
+ flush_stream(&p->target->out);
+ p->rc_pending_cnt++;
+ }
+ else {
+ add_context_cache(p, x);
+ protocol_send_command(p->target, "RunControl", "getChildren", validate_peer_cache_children, p);
+ json_write_string(&p->target->out, x->id);
+ write_stream(&p->target->out, 0);
+ write_stream(&p->target->out, MARKER_EOM);
+ flush_stream(&p->target->out);
+ p->rc_pending_cnt++;
+ }
}
+ clear_trap(&trap);
+ }
+ else {
+ set_rc_error(p, trap.error);
+ free_context_cache(x);
}
set_rc_done(p);
+ if (trap.error) exception(trap.error);
}
static void validate_peer_cache_state(Channel * c, void * args, int error) {
- ContextCache * x = args;
+ ContextCache * x = (ContextCache *)args;
PeerCache * p = x->peer;
+ Trap trap;
assert(p->target == c);
assert(p->rc_error == NULL);
assert(p->rc_pending_cnt > 0);
- p->rc_pending_cnt--;
- if (error) {
- set_rc_error(p, error);
- free_context_cache(x);
- }
- else {
- set_rc_error(p, error = read_errno(&c->inp));
- x->pc_valid = json_read_boolean(&c->inp);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- x->suspend_pc = json_read_uint64(&c->inp);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- json_read_string(&c->inp, x->suspend_reason, sizeof(x->suspend_reason));
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- json_read_struct(&c->inp, read_context_suspended_data, x);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
-
- if (error || find_context_cache(p, x->id) != NULL) {
+ if (set_trap(&trap)) {
+ p->rc_pending_cnt--;
+ if (error) {
+ set_rc_error(p, error);
free_context_cache(x);
}
else {
- add_context_cache(p, x);
- x->ctx->stopped = x->ctx->intercepted = x->pc_valid;
- if (x->pc_valid) {
- on_context_suspended(x);
- send_context_stopped_event(x->ctx);
+ set_rc_error(p, error = read_errno(&c->inp));
+ clear_context_suspended_data(x);
+ x->pc_valid = json_read_boolean(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ x->suspend_pc = json_read_uint64(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ json_read_string(&c->inp, x->suspend_reason, sizeof(x->suspend_reason));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ json_read_struct(&c->inp, read_context_suspended_data, x);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+
+ if (error || find_context_cache(p, x->id) != NULL) {
+ free_context_cache(x);
+ }
+ else {
+ add_context_cache(p, x);
+ x->ctx->stopped = x->ctx->intercepted = x->pc_valid;
+ if (x->pc_valid) {
+ on_context_suspended(x);
+ send_context_stopped_event(x->ctx);
+ }
+ protocol_send_command(p->target, "RunControl", "getChildren", validate_peer_cache_children, p);
+ json_write_string(&p->target->out, x->id);
+ write_stream(&p->target->out, 0);
+ write_stream(&p->target->out, MARKER_EOM);
+ flush_stream(&p->target->out);
+ p->rc_pending_cnt++;
}
- protocol_send_command(p->target, "RunControl", "getChildren", validate_peer_cache_children, p);
- json_write_string(&p->target->out, x->id);
- write_stream(&p->target->out, 0);
- write_stream(&p->target->out, MARKER_EOM);
- flush_stream(&p->target->out);
- p->rc_pending_cnt++;
}
+ clear_trap(&trap);
+ }
+ else {
+ set_rc_error(p, trap.error);
+ free_context_cache(x);
}
set_rc_done(p);
+ if (trap.error) exception(trap.error);
}
Context * id2ctx(const char * id) {
@@ -745,28 +788,38 @@ int context_has_state(Context * ctx) {
static void validate_memory_cache(Channel * c, void * args, int error) {
MemoryCache * m = (MemoryCache *)args;
+ Context * ctx = m->ctx->ctx;
+ Trap trap;
assert(m->pending != NULL);
assert(m->error == NULL);
- m->pending = NULL;
- 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;
+ if (set_trap(&trap)) {
+ m->pending = NULL;
+ 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);
+ error = read_errno(&c->inp);
+ while (read_stream(&c->inp) != 0) {}
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
}
- json_read_binary_end(&state);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- error = read_errno(&c->inp);
- while (read_stream(&c->inp) != 0) {}
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
m->error = get_error_report(error);
cache_notify(&m->cache);
- context_unlock(m->ctx->ctx);
+ if (m->disposed) free_memory_cache(m);
+ context_unlock(ctx);
+ if (trap.error) exception(trap.error);
}
int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t size) {
@@ -795,7 +848,7 @@ int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t s
}
}
- m = loc_alloc_zero(sizeof(MemoryCache));
+ m = (MemoryCache *)loc_alloc_zero(sizeof(MemoryCache));
list_add_first(&m->link_ctx, &cache->mem_cache);
m->ctx = cache;
m->addr = address;
@@ -831,11 +884,11 @@ static void read_memory_region_property(InputStream * inp, const char * name, vo
}
static void read_memory_map_item(InputStream * inp, void * args) {
- Channel * c = args;
+ Channel * c = (Channel *)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);
+ mem_buf = (MemoryRegion *)loc_realloc(mem_buf, sizeof(MemoryRegion) * mem_buf_max);
}
m = mem_buf + mem_buf_pos;
memset(m, 0, sizeof(MemoryRegion));
@@ -859,24 +912,33 @@ static void read_memory_map_item(InputStream * inp, void * args) {
static void validate_memory_map_cache(Channel * c, void * args, int error) {
ContextCache * cache = (ContextCache *)args;
+ Trap trap;
assert(cache->ctx->parent == NULL);
assert(cache->mmap_regions == NULL);
assert(cache->pending_get_mmap != NULL);
- cache->pending_get_mmap = NULL;
- cache->mmap_error = get_error_report(error);
- if (!error) {
- cache->mmap_error = get_error_report(read_errno(&c->inp));
- mem_buf_pos = 0;
- json_read_array(&c->inp, read_memory_map_item, cache->peer->host);
- cache->mmap_size = mem_buf_pos;
- cache->mmap_regions = loc_alloc(sizeof(MemoryRegion) * mem_buf_pos);
- memcpy(cache->mmap_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);
+ if (set_trap(&trap)) {
+ cache->pending_get_mmap = NULL;
+ cache->mmap_error = get_error_report(error);
+ if (!error) {
+ error = read_errno(&c->inp);
+ mem_buf_pos = 0;
+ json_read_array(&c->inp, read_memory_map_item, cache->peer->host);
+ cache->mmap_size = mem_buf_pos;
+ cache->mmap_regions = (MemoryRegion *)loc_alloc(sizeof(MemoryRegion) * mem_buf_pos);
+ memcpy(cache->mmap_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);
+ }
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
+ cache->mmap_error = get_error_report(error);
cache_notify(&cache->mmap_cache);
context_unlock(cache->ctx);
+ if (trap.error) exception(trap.error);
}
void memory_map_get_regions(Context * ctx, MemoryRegion ** regions, unsigned * cnt) {
@@ -904,15 +966,15 @@ static void read_ids_item(InputStream * inp, void * args) {
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);
+ ids_buf = (unsigned *)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 (n > (int)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);
+ str_buf = (char *)loc_realloc(str_buf, str_buf_max);
}
memcpy(str_buf + str_buf_pos, id, n);
ids_buf[ids_buf_pos++] = str_buf_pos;
@@ -933,56 +995,69 @@ static void read_register_property(InputStream * inp, const char * name, void *
static void validate_registers_cache(Channel * c, void * args, int error) {
ContextCache * cache = (ContextCache *)args;
+ Trap trap;
if (cache->reg_ids == NULL) {
/* Registers.getChildren reply */
assert(cache->reg_ids_str == NULL);
assert(cache->reg_error == NULL);
assert(cache->pending_regs_cnt == 1);
- cache->pending_regs_cnt--;
- cache->reg_error = get_error_report(error);
- if (!error) {
- unsigned i;
- cache->reg_error = get_error_report(read_errno(&c->inp));
- 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 (set_trap(&trap)) {
+ cache->pending_regs_cnt--;
+ if (!error) {
+ unsigned i;
+ error = read_errno(&c->inp);
+ 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 = (char **)loc_alloc(sizeof(char *) * ids_buf_pos);
+ cache->reg_ids_str = (char *)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);
}
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ clear_trap(&trap);
}
+ else {
+ error = trap.error;
+ }
+ cache->reg_error = get_error_report(error);
cache_notify(&cache->regs_cache);
}
else {
/* Registers.getContext reply */
assert(cache->pending_regs_cnt > 0);
- cache->pending_regs_cnt--;
- cache->reg_error = get_error_report(error);
- if (!error) {
- unsigned i;
- RegisterProps props;
- memset(&props, 0, sizeof(props));
- cache->reg_error = get_error_report(read_errno(&c->inp));
- json_read_struct(&c->inp, read_register_property, &props);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- for (i = 0; i < cache->reg_cnt; i++) {
- if (strcmp(props.id, cache->reg_ids[i]) == 0) {
- cache->reg_props[i] = props;
- cache->reg_defs[i] = props.def;
- if (props.role != NULL && strcmp(props.role, "PC") == 0) {
- cache->pc_def = cache->reg_defs + i;
+ if (set_trap(&trap)) {
+ cache->pending_regs_cnt--;
+ if (!error) {
+ unsigned i;
+ RegisterProps props;
+ memset(&props, 0, sizeof(props));
+ error = read_errno(&c->inp);
+ json_read_struct(&c->inp, read_register_property, &props);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ for (i = 0; i < cache->reg_cnt; i++) {
+ if (strcmp(props.id, cache->reg_ids[i]) == 0) {
+ cache->reg_props[i] = props;
+ cache->reg_defs[i] = props.def;
+ if (props.role != NULL && strcmp(props.role, "PC") == 0) {
+ cache->pc_def = cache->reg_defs + i;
+ }
+ break;
}
- break;
}
}
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
+ cache->reg_error = get_error_report(error);
if (cache->pending_regs_cnt == 0) {
unsigned i;
unsigned offs = 0;
@@ -996,6 +1071,7 @@ static void validate_registers_cache(Channel * c, void * args, int error) {
}
}
context_unlock(cache->ctx);
+ if (trap.error) exception(trap.error);
}
static void check_registers_cache(ContextCache * cache) {
@@ -1051,10 +1127,10 @@ RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, unsigned munberin
while (defs != NULL && defs->name != NULL) {
switch (munbering_convention) {
case REGNUM_DWARF:
- if (defs->dwarf_id == id) return defs;
+ if (defs->dwarf_id == (int)id) return defs;
break;
case REGNUM_EH_FRAME:
- if (defs->eh_frame_id == id) return defs;
+ if (defs->eh_frame_id == (int)id) return defs;
break;
}
defs++;
@@ -1064,97 +1140,117 @@ RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, unsigned munberin
static void validate_reg_values_cache(Channel * c, void * args, int error) {
StackFrameCache * s = (StackFrameCache *)args;
+ Context * ctx = s->ctx->ctx;
+ Trap trap;
assert(s->pending != NULL);
assert(s->error == NULL);
- s->pending = NULL;
- if (!error) {
- int r = 0;
- int n = s->info.is_top_frame ? s->ctx->reg_cnt : s->regs_cnt;
- JsonReadBinaryState state;
- error = read_errno(&c->inp);
- json_read_binary_start(&state, &c->inp);
- for (r = 0; r < n; r++) {
- int pos = 0;
- RegisterDefinition * reg = s->info.is_top_frame ? s->ctx->reg_defs + r : s->regs[r];
- uint8_t * regs = (uint8_t *)s->info.regs + reg->offset;
- uint8_t * mask = (uint8_t *)s->info.mask + reg->offset;
- while (pos < reg->size) {
- size_t rd = json_read_binary_data(&state, regs + pos, reg->size - pos);
- memset(mask + pos, ~0, rd);
- if (rd == 0) break;
- pos += rd;
+ if (set_trap(&trap)) {
+ s->pending = NULL;
+ if (!error) {
+ int r = 0;
+ int n = s->info.is_top_frame ? s->ctx->reg_cnt : s->regs_cnt;
+ JsonReadBinaryState state;
+ error = read_errno(&c->inp);
+ json_read_binary_start(&state, &c->inp);
+ for (r = 0; r < n; r++) {
+ int pos = 0;
+ RegisterDefinition * reg = s->info.is_top_frame ? s->ctx->reg_defs + r : s->regs[r];
+ uint8_t * regs = (uint8_t *)s->info.regs + reg->offset;
+ uint8_t * mask = (uint8_t *)s->info.mask + reg->offset;
+ while (pos < reg->size) {
+ size_t rd = json_read_binary_data(&state, regs + pos, reg->size - pos);
+ memset(mask + pos, ~0, rd);
+ if (rd == 0) break;
+ pos += rd;
+ }
}
+ json_read_binary_end(&state);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
}
- json_read_binary_end(&state);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
s->error = get_error_report(error);
cache_notify(&s->cache);
- context_unlock(s->ctx->ctx);
if (s->disposed) free_stack_frame_cache(s);
+ context_unlock(ctx);
+ if (trap.error) exception(trap.error);
}
static void validate_reg_children_cache(Channel * c, void * args, int error) {
StackFrameCache * s = (StackFrameCache *)args;
+ Context * ctx = s->ctx->ctx;
+ Trap trap;
+
assert(s->pending != NULL);
assert(s->error == NULL);
- s->pending = NULL;
- if (!error) {
- ids_buf_pos = 0;
- str_buf_pos = 0;
- error = read_errno(&c->inp);
- json_read_array(&c->inp, read_ids_item, NULL);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- if (!error && !s->disposed) {
- int n = 0;
- s->regs_cnt = ids_buf_pos;
- s->regs = (RegisterDefinition **)loc_alloc_zero(sizeof(RegisterDefinition *) * s->regs_cnt);
- for (n = 0; n < s->regs_cnt; n++) {
- unsigned r = 0;
- char * id = str_buf + ids_buf[n];
- if (*id++ != 'R') {
- error = ERR_INV_CONTEXT;
- break;
- }
- while (*id >= '0' && *id <= '9') {
- r = r * 10 + (*id++ - '0');
- }
- if (r >= s->ctx->reg_cnt) {
- error = ERR_INV_CONTEXT;
- break;
- }
- s->regs[n] = s->ctx->reg_defs + r;
- }
- if (!error) {
- s->pending = protocol_send_command(c, "Registers", "getm", validate_reg_values_cache, s);
- write_stream(&c->out, '[');
+ if (set_trap(&trap)) {
+ s->pending = NULL;
+ if (!error) {
+ ids_buf_pos = 0;
+ str_buf_pos = 0;
+ error = read_errno(&c->inp);
+ json_read_array(&c->inp, read_ids_item, NULL);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ if (!error && !s->disposed) {
+ int n = 0;
+ s->regs_cnt = ids_buf_pos;
+ s->regs = (RegisterDefinition **)loc_alloc_zero(sizeof(RegisterDefinition *) * s->regs_cnt);
for (n = 0; n < s->regs_cnt; n++) {
- RegisterDefinition * reg = s->regs[n];
+ unsigned r = 0;
char * id = str_buf + ids_buf[n];
- if (n > 0) write_stream(&c->out, ',');
+ if (*id++ != 'R') {
+ error = ERR_INV_CONTEXT;
+ break;
+ }
+ while (*id >= '0' && *id <= '9') {
+ r = r * 10 + (*id++ - '0');
+ }
+ if (r >= s->ctx->reg_cnt) {
+ error = ERR_INV_CONTEXT;
+ break;
+ }
+ s->regs[n] = s->ctx->reg_defs + r;
+ }
+ if (!error) {
+ s->pending = protocol_send_command(c, "Registers", "getm", validate_reg_values_cache, s);
write_stream(&c->out, '[');
- json_write_string(&c->out, id);
- write_stream(&c->out, ',');
- json_write_long(&c->out, 0);
- write_stream(&c->out, ',');
- json_write_long(&c->out, reg->size);
+ for (n = 0; n < s->regs_cnt; n++) {
+ RegisterDefinition * reg = s->regs[n];
+ char * id = str_buf + ids_buf[n];
+ if (n > 0) write_stream(&c->out, ',');
+ write_stream(&c->out, '[');
+ json_write_string(&c->out, id);
+ write_stream(&c->out, ',');
+ json_write_long(&c->out, 0);
+ write_stream(&c->out, ',');
+ json_write_long(&c->out, reg->size);
+ write_stream(&c->out, ']');
+ }
write_stream(&c->out, ']');
+ write_stream(&c->out, 0);
+ write_stream(&c->out, MARKER_EOM);
+ flush_stream(&c->out);
+ clear_trap(&trap);
+ return;
}
- write_stream(&c->out, ']');
- write_stream(&c->out, 0);
- write_stream(&c->out, MARKER_EOM);
- flush_stream(&c->out);
- return;
}
}
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
s->error = get_error_report(error);
cache_notify(&s->cache);
- context_unlock(s->ctx->ctx);
if (s->disposed) free_stack_frame_cache(s);
+ context_unlock(ctx);
+ if (trap.error) exception(trap.error);
}
static void read_stack_frame_property(InputStream * inp, const char * name, void * args) {
@@ -1172,46 +1268,56 @@ static void read_stack_frame(InputStream * inp, void * args) {
static void validate_stack_frame_cache(Channel * c, void * args, int error) {
StackFrameCache * s = (StackFrameCache *)args;
+ Context * ctx = s->ctx->ctx;
+ Trap trap;
assert(s->pending != NULL);
assert(s->error == NULL);
- s->pending = NULL;
- if (!error) {
- json_read_array(&c->inp, read_stack_frame, s);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- error = read_errno(&c->inp);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- if (!error && !s->disposed) {
- if (s->info.is_top_frame) {
- RegisterDefinition * reg = s->ctx->reg_defs;
- s->pending = protocol_send_command(c, "Registers", "getm", validate_reg_values_cache, s);
- write_stream(&c->out, '[');
- while (reg->name) {
+ if (set_trap(&trap)) {
+ s->pending = NULL;
+ if (!error) {
+ json_read_array(&c->inp, read_stack_frame, s);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ error = read_errno(&c->inp);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ if (!error && !s->disposed) {
+ if (s->info.is_top_frame) {
+ RegisterDefinition * reg = s->ctx->reg_defs;
+ s->pending = protocol_send_command(c, "Registers", "getm", validate_reg_values_cache, s);
write_stream(&c->out, '[');
- json_write_string(&c->out, register2id(s->ctx->ctx, s->frame, reg));
- write_stream(&c->out, ',');
- json_write_long(&c->out, 0);
- write_stream(&c->out, ',');
- json_write_long(&c->out, reg->size);
+ while (reg->name) {
+ write_stream(&c->out, '[');
+ json_write_string(&c->out, register2id(s->ctx->ctx, s->frame, reg));
+ write_stream(&c->out, ',');
+ json_write_long(&c->out, 0);
+ write_stream(&c->out, ',');
+ json_write_long(&c->out, reg->size);
+ write_stream(&c->out, ']');
+ if ((++reg)->name) write_stream(&c->out, ',');
+ }
write_stream(&c->out, ']');
- if ((++reg)->name) write_stream(&c->out, ',');
}
- write_stream(&c->out, ']');
- }
- else {
- s->pending = protocol_send_command(c, "Registers", "getChildren", validate_reg_children_cache, s);
- json_write_string(&c->out, frame2id(s->ctx->ctx, s->frame));
+ else {
+ s->pending = protocol_send_command(c, "Registers", "getChildren", validate_reg_children_cache, s);
+ json_write_string(&c->out, frame2id(s->ctx->ctx, s->frame));
+ }
+ write_stream(&c->out, 0);
+ write_stream(&c->out, MARKER_EOM);
+ flush_stream(&c->out);
+ clear_trap(&trap);
+ return;
}
- write_stream(&c->out, 0);
- write_stream(&c->out, MARKER_EOM);
- flush_stream(&c->out);
- return;
}
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
s->error = get_error_report(error);
cache_notify(&s->cache);
- context_unlock(s->ctx->ctx);
if (s->disposed) free_stack_frame_cache(s);
+ context_unlock(ctx);
+ if (trap.error) exception(trap.error);
}
int get_frame_info(Context * ctx, int frame, StackFrame ** info) {
diff --git a/services/breakpoints.c b/services/breakpoints.c
index 6888320d..23f0ed85 100644
--- a/services/breakpoints.c
+++ b/services/breakpoints.c
@@ -760,6 +760,7 @@ static void done_conditions_evaluation(int * need_to_flush) {
}
static void done_evaluation(void) {
+ assert(cache_enter_cnt > 0);
cache_enter_cnt--;
if (cache_enter_cnt == 0) {
int need_to_flush = 0;
diff --git a/services/dwarfcache.c b/services/dwarfcache.c
index a568ade5..4fbed9be 100644
--- a/services/dwarfcache.c
+++ b/services/dwarfcache.c
@@ -99,6 +99,7 @@ static ObjectInfo * find_object_info(U8_T ID) {
ObjectInfo * Info = find_object(sCache, ID);
if (Info == NULL) {
U4_T Hash = (U4_T)ID % OBJ_HASH_SIZE;
+ assert(ID >= sDebugSection->addr + dio_gEntryPos);
Info = (ObjectInfo *)loc_alloc_zero(sizeof(ObjectInfo));
Info->mHashNext = sCache->mObjectHash[Hash];
sCache->mObjectHash[Hash] = Info;
@@ -234,10 +235,10 @@ static void read_object_attributes(U2_T Tag, U2_T Attr, U2_T Form) {
case 0:
if (Form) {
Info = find_object_info(sDebugSection->addr + dio_gEntryPos);
+ assert(Info->mTag == 0);
Info->mTag = Tag;
Info->mCompUnit = sCompUnit;
Info->mParent = sParentObject;
- /* TODO: Default AT_lower_bound value is language dependand */
Sibling = 0;
}
else {
diff --git a/services/dwarfexpr.c b/services/dwarfexpr.c
index 9fa5e8ca..a75015d2 100644
--- a/services/dwarfexpr.c
+++ b/services/dwarfexpr.c
@@ -62,6 +62,18 @@ static int register_access_func(PropertyValue * Value, int write, U8_T * Data) {
return read_reg_value(def, frame, Data);
}
+static U8_T read_memory(PropertyValue * Value, U8_T Addr, size_t Size) {
+ size_t i;
+ U8_T n = 0;
+ U1_T buf[8];
+
+ if (context_read_mem(Value->mContext, Addr, buf, Size) < 0) exception(errno);
+ for (i = 0; i < Size; i++) {
+ n = (n << 8) | buf[Value->mBigEndian ? i : Size - i - 1];
+ }
+ return n;
+}
+
static void evaluate_expression(U8_T BaseAddress, PropertyValue * Value, ELF_Section * Section, U1_T * Buf, size_t Size) {
U8_T StartPos = Buf - (U1_T *)Section->data;
CompUnit * Unit = Value->mObject->mCompUnit;
@@ -89,35 +101,17 @@ static void evaluate_expression(U8_T BaseAddress, PropertyValue * Value, ELF_Sec
case OP_deref:
check_e_stack(1);
{
- U1_T Tmp[8];
U8_T Addr = sExprStack[sExprStackLen - 1];
size_t Size = Unit->mDesc.mAddressSize;
- if (context_read_mem(Value->mContext, (ContextAddress)Addr, Tmp, Size) < 0) exception(errno);
- switch (Size) {
- case 1: Data = *Tmp; break;
- case 2: Data = *(U2_T *)Tmp; break;
- case 4: Data = *(U4_T *)Tmp; break;
- case 8: Data = *(U8_T *)Tmp; break;
- default: assert(0);
- }
- sExprStack[sExprStackLen - 1] = Data;
+ sExprStack[sExprStackLen - 1] = read_memory(Value, Addr, Size);
}
break;
case OP_deref_size:
check_e_stack(1);
{
- U1_T Tmp[8];
U8_T Addr = sExprStack[sExprStackLen - 1];
U1_T Size = dio_ReadU1();
- if (context_read_mem(Value->mContext, (ContextAddress)Addr, Tmp, Size) < 0) exception(errno);
- switch (Size) {
- case 1: Data = *Tmp; break;
- case 2: Data = *(U2_T *)Tmp; break;
- case 4: Data = *(U4_T *)Tmp; break;
- case 8: Data = *(U8_T *)Tmp; break;
- default: assert(0);
- }
- sExprStack[sExprStackLen - 1] = Data;
+ sExprStack[sExprStackLen - 1] = read_memory(Value, Addr, Size);
}
break;
case OP_const1u:
@@ -188,36 +182,18 @@ static void evaluate_expression(U8_T BaseAddress, PropertyValue * Value, ELF_Sec
case OP_xderef:
check_e_stack(2);
{
- U1_T Tmp[8];
U8_T Addr = sExprStack[sExprStackLen - 1];
size_t Size = Unit->mDesc.mAddressSize;
- if (context_read_mem(Value->mContext, (ContextAddress)Addr, Tmp, Size) < 0) exception(errno);
- switch (Size) {
- case 1: Data = *Tmp; break;
- case 2: Data = *(U2_T *)Tmp; break;
- case 4: Data = *(U4_T *)Tmp; break;
- case 8: Data = *(U8_T *)Tmp; break;
- default: assert(0);
- }
- sExprStack[sExprStackLen - 2] = Data;
+ sExprStack[sExprStackLen - 2] = read_memory(Value, Addr, Size);
sExprStackLen--;
}
break;
case OP_xderef_size:
check_e_stack(2);
{
- U1_T Tmp[8];
U8_T Addr = sExprStack[sExprStackLen - 1];
U1_T Size = dio_ReadU1();
- if (context_read_mem(Value->mContext, (ContextAddress)Addr, Tmp, Size) < 0) exception(errno);
- switch (Size) {
- case 1: Data = *Tmp; break;
- case 2: Data = *(U2_T *)Tmp; break;
- case 4: Data = *(U4_T *)Tmp; break;
- case 8: Data = *(U8_T *)Tmp; break;
- default: assert(0);
- }
- sExprStack[sExprStackLen - 2] = Data;
+ sExprStack[sExprStackLen - 2] = read_memory(Value, Addr, Size);
sExprStackLen--;
}
break;
diff --git a/services/dwarfframe.c b/services/dwarfframe.c
index 2c7b849f..9d73a01b 100644
--- a/services/dwarfframe.c
+++ b/services/dwarfframe.c
@@ -100,6 +100,19 @@ static int regs_stack_pos = 0;
static StackFrameRules rules;
+U8_T dwarf_stack_trace_addr = 0;
+U8_T dwarf_stack_trace_size = 0;
+
+StackTracingCommandSequence * dwarf_stack_trace_fp = NULL;
+
+int dwarf_stack_trace_regs_cnt = 0;
+StackTracingCommandSequence ** dwarf_stack_trace_regs = NULL;
+
+static int trace_regs_max = 0;
+static int trace_cmds_max = 0;
+static int trace_cmds_cnt = 0;
+static StackTracingCommand * trace_cmds = NULL;
+
static RegisterRules * get_reg(StackFrameRegisters * regs, int reg) {
RegisterDefinition * reg_def;
while (reg >= regs->regs_max) {
@@ -347,83 +360,102 @@ static void exec_stack_frame_instruction(void) {
}
}
-static void fill_frame_register(RegisterRules * reg, RegisterDefinition * reg_def, StackFrame * frame, StackFrame * down) {
+static StackTracingCommand * add_command(int op) {
+ StackTracingCommand * cmd = NULL;
+ if (trace_cmds_cnt >= trace_cmds_max) {
+ trace_cmds_max += 16;
+ trace_cmds = (StackTracingCommand *)loc_realloc(trace_cmds, trace_cmds_max * sizeof(StackTracingCommand));
+ }
+ cmd = trace_cmds + trace_cmds_cnt++;
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->cmd = op;
+ return cmd;
+}
+
+static void add_command_sequence(StackTracingCommandSequence ** ptr, RegisterDefinition * reg) {
+ StackTracingCommandSequence * seq = *ptr;
+ if (seq == NULL || seq->cmds_max < trace_cmds_cnt) {
+ *ptr = seq = (StackTracingCommandSequence *)loc_realloc(seq, sizeof(StackTracingCommandSequence) + (trace_cmds_cnt - 1) * sizeof(StackTracingCommand));
+ seq->cmds_max = trace_cmds_cnt;
+ }
+ seq->reg = reg;
+ seq->cmds_cnt = trace_cmds_cnt;
+ memcpy(seq->cmds, trace_cmds, trace_cmds_cnt * sizeof(StackTracingCommand));
+}
+
+static void generate_register_commands(RegisterRules * reg, RegisterDefinition * reg_def) {
+ if (reg_def == NULL) return;
+ trace_cmds_cnt = 0;
switch (reg->rule) {
+ case RULE_VAL_OFFSET:
case RULE_OFFSET:
- if (frame->fp != 0 && reg_def != NULL) {
- size_t size = reg_def->size;
- if (size <= 8) {
- U1_T v[8];
- if (context_read_mem(rules.ctx, frame->fp + reg->offset, v, size) < 0) exception(errno);
- switch (size) {
- case 1: write_reg_value(reg_def, down, *(U1_T *)v); break;
- case 2: write_reg_value(reg_def, down, *(U2_T *)v); break;
- case 4: write_reg_value(reg_def, down, *(U4_T *)v); break;
- case 8: write_reg_value(reg_def, down, *(U8_T *)v); break;
- }
- }
+ add_command(SFT_CMD_FP);
+ if (reg->offset != 0) {
+ add_command(SFT_CMD_NUMBER)->num = reg->offset;
+ add_command(SFT_CMD_ADD);
+ }
+ if (reg->rule == RULE_OFFSET) {
+ StackTracingCommand * cmd = add_command(SFT_CMD_DEREF);
+ cmd->size = reg_def->size;
+ cmd->big_endian = rules.section->file->big_endian;
}
break;
case RULE_SAME_VALUE:
- if (reg_def != NULL) {
- U8_T v = 0;
- if (read_reg_value(reg_def, frame, &v) >= 0) {
- write_reg_value(reg_def, down, v);
- }
- }
+ add_command(SFT_CMD_REGISTER)->reg = reg_def;
break;
case RULE_REGISTER:
- if (reg_def != NULL) {
+ {
RegisterDefinition * src_sef = get_reg_by_id(rules.ctx, reg->offset, rules.eh_frame ? REGNUM_EH_FRAME : REGNUM_DWARF);
- if (src_sef != NULL) {
- U8_T v = 0;
- if (read_reg_value(src_sef, frame, &v) >= 0) {
- write_reg_value(reg_def, down, v);
- }
- }
- }
- break;
- case RULE_VAL_OFFSET:
- if (frame->fp != 0 && reg_def != NULL) {
- U8_T v = frame->fp + reg->offset;
- write_reg_value(reg_def, down, v);
+ if (src_sef != NULL) add_command(SFT_CMD_REGISTER)->reg = src_sef;
}
break;
- case RULE_EXPRESSION:
- case RULE_VAL_EXPRESSION:
- /* TODO: RULE_EXPRESSION */
+ default:
+ /* TODO: RULE_EXPRESSION, RULE_VAL_EXPRESSION */
+ str_exception(ERR_UNSUPPORTED, "Not implemented yet: expression in .debug_frame");
break;
}
+ if (dwarf_stack_trace_regs_cnt >= trace_regs_max) {
+ int i;
+ trace_regs_max += 16;
+ dwarf_stack_trace_regs = (StackTracingCommandSequence **)loc_realloc(dwarf_stack_trace_regs, trace_regs_max * sizeof(StackTracingCommandSequence *));
+ for (i = dwarf_stack_trace_regs_cnt; i < trace_regs_max; i++) dwarf_stack_trace_regs[i] = NULL;
+ }
+ if (trace_cmds_cnt == 0) return;
+ add_command_sequence(dwarf_stack_trace_regs + dwarf_stack_trace_regs_cnt++, reg_def);
}
-static int fill_stack_frame(StackFrame * frame, StackFrame * down) {
+static void generate_commands(void) {
int i;
- U8_T v = 0;
RegisterRules * reg;
RegisterDefinition * reg_def;
+ reg = get_reg(&frame_regs, rules.return_address_register);
+ if (reg->rule != 0) generate_register_commands(reg, get_PC_definition(rules.ctx));
+ for (i = 0; i < frame_regs.regs_cnt; i++) {
+ if (i == rules.return_address_register) continue;
+ reg = get_reg(&frame_regs, i);
+ if (reg->rule == 0) continue;
+ reg_def = get_reg_by_id(rules.ctx, i, rules.eh_frame ? REGNUM_EH_FRAME : REGNUM_DWARF);
+ generate_register_commands(reg, reg_def);
+ }
+
+ trace_cmds_cnt = 0;
switch (rules.cfa_rule) {
case RULE_OFFSET:
reg_def = get_reg_by_id(rules.ctx, rules.cfa_register, rules.eh_frame ? REGNUM_EH_FRAME : REGNUM_DWARF);
if (reg_def != NULL) {
- if (read_reg_value(reg_def, frame, &v) >= 0) {
- frame->fp = (ContextAddress)(v + rules.cfa_offset);
+ add_command(SFT_CMD_REGISTER)->reg = reg_def;
+ if (rules.cfa_offset != 0) {
+ add_command(SFT_CMD_NUMBER)->num = rules.cfa_offset;
+ add_command(SFT_CMD_ADD);
}
}
break;
+ default:
/* TODO: RULE_EXPRESSION */
+ str_exception(ERR_UNSUPPORTED, "Not implemented yet: expression in .debug_frame");
}
-
- reg = get_reg(&frame_regs, rules.return_address_register);
- if (reg->rule != 0) fill_frame_register(reg, get_PC_definition(rules.ctx), frame, down);
- for (i = 0; i < frame_regs.regs_cnt; i++) {
- if (i == rules.return_address_register) continue;
- reg = get_reg(&frame_regs, i);
- if (reg->rule == 0) continue;
- reg_def = get_reg_by_id(rules.ctx, i, rules.eh_frame ? REGNUM_EH_FRAME : REGNUM_DWARF);
- fill_frame_register(reg, reg_def, frame, down);
- }
- return 0;
+ add_command_sequence(&dwarf_stack_trace_fp, NULL);
}
static void read_frame_cie(U8_T pos) {
@@ -485,15 +517,23 @@ static void read_frame_cie(U8_T pos) {
dio_Skip(saved_pos - dio_GetPos());
}
-void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, StackFrame * frame, StackFrame * down) {
+void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, U8_T IP) {
/* TODO: use .eh_frame_hdr section for faster frame data search */
- U8_T IP = 0;
DWARFCache * cache = get_dwarf_cache(file);
ELF_Section * section = cache->mDebugFrame;
+
+ dwarf_stack_trace_regs_cnt = 0;
+ if (dwarf_stack_trace_fp == NULL) {
+ dwarf_stack_trace_fp = (StackTracingCommandSequence *)loc_alloc_zero(sizeof(StackTracingCommandSequence));
+ dwarf_stack_trace_fp->cmds_max = 1;
+ }
+ dwarf_stack_trace_fp->cmds_cnt = 0;
+ dwarf_stack_trace_addr = 0;
+ dwarf_stack_trace_size = 0;
+
if (section == NULL) section = cache->mEHFrame;
if (section == NULL) return;
- if (read_reg_value(get_PC_definition(rules.ctx), frame, &IP) < 0) exception(errno);
memset(&rules, 0, sizeof(StackFrameRules));
rules.ctx = ctx;
rules.section = section;
@@ -529,6 +569,7 @@ void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, StackFrame * fra
Range = read_frame_data_pointer(rules.addr_encoding, NULL);
AddrRT = elf_map_to_run_time_address(ctx, file, sec, (ContextAddress)Addr);
if (AddrRT != 0 && AddrRT <= IP && AddrRT + Range > IP) {
+ U8_T location0 = Addr;
if (rules.cie_aug != NULL && rules.cie_aug[0] == 'z') {
rules.fde_aug_length = dio_ReadULEB128();
rules.fde_aug_data = dio_GetDataPtr();
@@ -537,11 +578,19 @@ void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, StackFrame * fra
copy_register_rules(&frame_regs, &cie_regs);
rules.location = Addr;
regs_stack_pos = 0;
- while (dio_GetPos() < fde_end) {
+ for (;;) {
+ if (dio_GetPos() >= fde_end) {
+ rules.location = Addr + Range;
+ break;
+ }
exec_stack_frame_instruction();
+ assert(location0 - Addr + AddrRT <= IP);
if (rules.location - Addr + AddrRT > IP) break;
+ location0 = rules.location;
}
- fill_stack_frame(frame, down);
+ dwarf_stack_trace_addr = location0 - Addr + AddrRT;
+ dwarf_stack_trace_size = rules.location - location0;
+ generate_commands();
break;
}
}
diff --git a/services/dwarfframe.h b/services/dwarfframe.h
index d4939ed8..d90d0eec 100644
--- a/services/dwarfframe.h
+++ b/services/dwarfframe.h
@@ -27,22 +27,27 @@
#include "context.h"
#include "dwarfcache.h"
+#include "stacktrace.h"
/*
- * Lookup stack frame data in ELF file, in .debug_frame and .eh_frame sections.
+ * Lookup stack tracing information in ELF file, in .debug_frame and .eh_frame sections.
*
- * "frame" is current frame info, it should have frame->regs and frame->mask filled with
- * proper values before this function is called.
+ * Given register values in one frame, stack tracing information allows to calculate
+ * frame address and register values in the next frame.
*
- * "down" is next frame - moving from stack top to the bottom.
- *
- * The function uses register values in current frame to calculate frame address "frame->fp",
- * and calculate register values in the next frame.
- *
- * If frame data is not found the function does nothing.
+ * When function returns, dwarf_stack_trace_fp contains commands to calculate frame address,
+ * and dwarf_stack_trace_regs contains commands to calculate register values.
* In case of error reading frame data, the function throws an exception.
*/
-extern void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, StackFrame * frame, StackFrame * down);
+extern void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, U8_T ip);
+
+extern U8_T dwarf_stack_trace_addr;
+extern U8_T dwarf_stack_trace_size;
+
+extern StackTracingCommandSequence * dwarf_stack_trace_fp;
+
+extern int dwarf_stack_trace_regs_cnt;
+extern StackTracingCommandSequence ** dwarf_stack_trace_regs;
#endif /* ENABLE_ELF */
diff --git a/services/linenumbers_proxy.c b/services/linenumbers_proxy.c
index 7a501113..5ef1076f 100644
--- a/services/linenumbers_proxy.c
+++ b/services/linenumbers_proxy.c
@@ -194,6 +194,7 @@ static void validate_map_to_memory(Channel * c, void * args, int error) {
f->error = get_error_report(error);
cache_notify(&f->cache);
if (f->disposed) free_line_address_cache(f);
+ if (trap.error) exception(trap.error);
}
int line_to_address(Context * ctx, char * file, int line, int column, LineNumbersCallBack * client, void * args) {
diff --git a/services/stacktrace.c b/services/stacktrace.c
index c7a0c7e7..f5ee9fca 100644
--- a/services/stacktrace.c
+++ b/services/stacktrace.c
@@ -30,6 +30,7 @@
#include "trace.h"
#include "context.h"
#include "json.h"
+#include "cache.h"
#include "exceptions.h"
#include "stacktrace.h"
#include "breakpoints.h"
@@ -40,11 +41,6 @@
static const char * STACKTRACE = "StackTrace";
-struct ContextInterfaceData {
- Context * ctx;
- int frame;
-};
-
struct StackTrace {
ErrorReport * error;
int frame_cnt;
@@ -52,20 +48,26 @@ struct StackTrace {
struct StackFrame frames[1]; /* ordered bottom to top */
};
-typedef struct ContextInterfaceData ContextInterfaceData;
typedef struct StackTrace StackTrace;
-#define CTX_DATA(x) ((ContextInterfaceData *)&(x)->private_data)
-
-static void add_frame(Context * ctx, StackFrame * frame) {
- StackTrace * stack_trace = (StackTrace *)ctx->stack_trace;
+static StackTrace * add_frame(StackTrace * stack_trace, StackFrame * frame) {
if (stack_trace->frame_cnt >= stack_trace->frame_max) {
stack_trace->frame_max *= 2;
stack_trace = (StackTrace *)loc_realloc(stack_trace,
sizeof(StackTrace) + (stack_trace->frame_max - 1) * sizeof(StackFrame));
- ctx->stack_trace = stack_trace;
}
stack_trace->frames[stack_trace->frame_cnt++] = *frame;
+ return stack_trace;
+}
+
+static void free_stack_trace(StackTrace * stack_trace) {
+ int i;
+ release_error_report(stack_trace->error);
+ for (i = 0; i < stack_trace->frame_cnt; i++) {
+ if (!stack_trace->frames[i].is_top_frame) loc_free(stack_trace->frames[i].regs);
+ loc_free(stack_trace->frames[i].mask);
+ }
+ loc_free(stack_trace);
}
#if defined(_WRS_KERNEL)
@@ -73,6 +75,7 @@ static void add_frame(Context * ctx, StackFrame * frame) {
#include <trcLib.h>
static Context * client_ctx;
+static StackTrace * client_trace;
static int frame_cnt;
static ContextAddress frame_rp;
@@ -101,21 +104,22 @@ static void vxworks_stack_trace_callback(
}
f.fp = (ContextAddress)args;
frame_rp = (ContextAddress)callAdrs;
- add_frame(client_ctx, &f);
+ client_trace = add_frame(client_trace, &f);
frame_cnt++;
}
-static int trace_stack(Context * ctx) {
+static StackTrace * trace_stack(Context * ctx, StackTrace * s) {
client_ctx = ctx;
+ client_trace = s;
frame_cnt = 0;
trcStack((REG_SET *)ctx->regs, (FUNCPTR)vxworks_stack_trace_callback, ctx->pid);
if (frame_cnt == 0) vxworks_stack_trace_callback(NULL, 0, 0, NULL, ctx->pid, 1);
- return 0;
+ return client_trace;
}
#else
-static int walk_frames(Context * ctx) {
+static StackTrace * walk_frames(Context * ctx, StackTrace * stack_trace) {
int error = 0;
unsigned cnt = 0;
StackFrame frame;
@@ -132,12 +136,14 @@ static int walk_frames(Context * ctx) {
down.regs_size = ctx->regs_size;
down.regs = (RegisterData *)loc_alloc_zero(down.regs_size);
down.mask = (RegisterData *)loc_alloc_zero(down.regs_size);
+#if ENABLE_Symbols
if (get_next_stack_frame(ctx, &frame, &down) < 0) {
error = errno;
loc_free(down.regs);
loc_free(down.mask);
break;
}
+#endif
if (frame.fp == 0 && crawl_stack_frame(ctx, &frame, &down) < 0) {
error = errno;
loc_free(down.regs);
@@ -149,7 +155,7 @@ static int walk_frames(Context * ctx) {
loc_free(down.mask);
break;
}
- add_frame(ctx, &frame);
+ stack_trace = add_frame(stack_trace, &frame);
frame = down;
cnt++;
}
@@ -157,40 +163,47 @@ static int walk_frames(Context * ctx) {
if (!frame.is_top_frame) loc_free(frame.regs);
loc_free(frame.mask);
- errno = error;
- return error == 0 ? 0 : -1;
+ if (error) {
+ if (get_error_code(error) == ERR_CACHE_MISS) {
+ free_stack_trace(stack_trace);
+ stack_trace = NULL;
+ errno = ERR_CACHE_MISS;
+ }
+ else {
+ stack_trace->error = get_error_report(error);
+ }
+ }
+ return stack_trace;
}
-static int trace_stack(Context * ctx) {
- int i;
- StackTrace * s;
- if (walk_frames(ctx) < 0) return -1;
- s = (StackTrace *)ctx->stack_trace;
- for (i = 0; i < s->frame_cnt / 2; i++) {
- StackFrame f = s->frames[i];
- s->frames[i] = s->frames[s->frame_cnt - i - 1];
- s->frames[s->frame_cnt - i - 1] = f;
+static StackTrace * trace_stack(Context * ctx, StackTrace * s) {
+ s = walk_frames(ctx, s);
+ if (s != NULL) {
+ int i;
+ for (i = 0; i < s->frame_cnt / 2; i++) {
+ StackFrame f = s->frames[i];
+ s->frames[i] = s->frames[s->frame_cnt - i - 1];
+ s->frames[s->frame_cnt - i - 1] = f;
+ }
}
- return 0;
+ return s;
}
#endif
static StackTrace * create_stack_trace(Context * ctx) {
- int error = 0;
StackTrace * stack_trace = (StackTrace *)ctx->stack_trace;
if (stack_trace != NULL) return stack_trace;
stack_trace = (StackTrace *)loc_alloc_zero(sizeof(StackTrace) + 31 * sizeof(StackFrame));
stack_trace->frame_max = 32;
- ctx->stack_trace = stack_trace;
if (ctx->regs_error != NULL) {
stack_trace->error = get_error_report(set_error_report_errno(ctx->regs_error));
- return stack_trace;
}
- if (trace_stack(ctx) < 0) error = errno;
- stack_trace = (StackTrace *)ctx->stack_trace;
- if (error) stack_trace->error = get_error_report(error);
+ else {
+ stack_trace = trace_stack(ctx, stack_trace);
+ }
+ ctx->stack_trace = stack_trace;
return stack_trace;
}
@@ -252,60 +265,104 @@ static void write_context(OutputStream * out, char * id, Context * ctx, int leve
write_stream(out, '}');
}
-static void command_get_context(char * token, Channel * c) {
- int err = 0;
+typedef struct CommandGetContextData {
+ Context * ctx;
+ int frame;
+ StackFrame * info;
+ StackFrame * down;
+} CommandGetContextData;
+
+typedef struct CommandGetContextArgs {
+ char token[256];
+ int id_cnt;
char ** ids;
- int id_cnt = 0;
- int i;
+ CommandGetContextData * data;
+} CommandGetContextArgs;
- ids = json_read_alloc_string_array(&c->inp, &id_cnt);
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+static void command_get_context_cache_client(void * x) {
+ int i;
+ int err = 0;
+ CommandGetContextArgs * args = (CommandGetContextArgs *)x;
+ Channel * c = cache_channel();
- write_stringz(&c->out, "R");
- write_stringz(&c->out, token);
- write_stream(&c->out, '[');
- for (i = 0; i < id_cnt; i++) {
+ memset(args->data, 0, sizeof(CommandGetContextData) * args->id_cnt);
+ for (i = 0; i < args->id_cnt; i++) {
StackTrace * s = NULL;
- Context * ctx = NULL;
- int frame = 0;
- if (i > 0) write_stream(&c->out, ',');
- if (id2frame(ids[i], &ctx, &frame) < 0) {
+ CommandGetContextData * d = args->data + i;
+ if (id2frame(args->ids[i], &d->ctx, &d->frame) < 0) {
err = errno;
+ break;
}
- else if (!ctx->stopped) {
+ if (!d->ctx->stopped) {
err = ERR_IS_RUNNING;
+ break;
}
- else {
- s = create_stack_trace(ctx);
+ s = create_stack_trace(d->ctx);
+ if (s == NULL) {
+ err = errno;
+ break;
}
- if (s == NULL || frame < 0 || frame >= s->frame_cnt) {
+ if (s->error) {
+ err = set_error_report_errno(s->error);
+ break;
+ }
+ if (d->frame >= s->frame_cnt) {
+ err = ERR_INV_CONTEXT;
+ break;
+ }
+ d->info = s->frames + d->frame;
+ d->down = d->frame > 0 ? d->info - 1 : NULL;
+ }
+
+ cache_exit();
+
+ write_stringz(&c->out, "R");
+ write_stringz(&c->out, args->token);
+ write_stream(&c->out, '[');
+ for (i = 0; i < args->id_cnt; i++) {
+ CommandGetContextData * d = args->data + i;
+ if (i > 0) write_stream(&c->out, ',');
+ if (d->info == NULL) {
write_string(&c->out, "null");
}
else {
- StackFrame * f = s->frames + frame;
- StackFrame * d = frame > 0 ? f - 1 : NULL;
- write_context(&c->out, ids[i], ctx, frame, f, d);
+ write_context(&c->out, args->ids[i], d->ctx, d->frame, d->info, d->down);
}
}
write_stream(&c->out, ']');
write_stream(&c->out, 0);
write_errno(&c->out, err);
write_stream(&c->out, MARKER_EOM);
- loc_free(ids);
+
+ loc_free(args->ids);
+ loc_free(args->data);
}
-static void command_get_children(char * token, Channel * c) {
+static void command_get_context(char * token, Channel * c) {
+ CommandGetContextArgs args;
+
+ args.ids = json_read_alloc_string_array(&c->inp, &args.id_cnt);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+
+ args.data = (CommandGetContextData *)loc_alloc(sizeof(CommandGetContextData) * args.id_cnt);
+ strlcpy(args.token, token, sizeof(args.token));
+ cache_enter(command_get_context_cache_client, c, &args, sizeof(args));
+}
+
+typedef struct CommandGetChildrenArgs {
+ char token[256];
char id[256];
+} CommandGetChildrenArgs;
+
+static void command_get_children_cache_client(void * x) {
int err = 0;
Context * ctx = NULL;
StackTrace * s = NULL;
+ CommandGetChildrenArgs * args = (CommandGetChildrenArgs *)x;
+ Channel * c = cache_channel();
- json_read_string(&c->inp, id, sizeof(id));
- if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
- if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
-
- ctx = id2ctx(id);
+ ctx = id2ctx(args->id);
if (ctx == NULL || !context_has_state(ctx)) {
/* no children */
}
@@ -316,8 +373,10 @@ static void command_get_children(char * token, Channel * c) {
s = create_stack_trace(ctx);
}
+ cache_exit();
+
write_stringz(&c->out, "R");
- write_stringz(&c->out, token);
+ write_stringz(&c->out, args->token);
write_errno(&c->out, s != NULL ? set_error_report_errno(s->error) : err);
@@ -338,18 +397,15 @@ static void command_get_children(char * token, Channel * c) {
write_stream(&c->out, MARKER_EOM);
}
-static void delete_stack_trace(Context * ctx, void * client_data) {
- StackTrace * stack_trace = (StackTrace *)ctx->stack_trace;
- if (stack_trace != NULL) {
- int i;
- release_error_report(stack_trace->error);
- for (i = 0; i < stack_trace->frame_cnt; i++) {
- if (!stack_trace->frames[i].is_top_frame) loc_free(stack_trace->frames[i].regs);
- loc_free(stack_trace->frames[i].mask);
- }
- loc_free(stack_trace);
- ctx->stack_trace = NULL;
- }
+static void command_get_children(char * token, Channel * c) {
+ CommandGetChildrenArgs args;
+
+ json_read_string(&c->inp, args.id, sizeof(args.id));
+ 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(command_get_children_cache_client, c, &args, sizeof(args));
}
int get_top_frame(Context * ctx) {
@@ -361,6 +417,9 @@ int get_top_frame(Context * ctx) {
}
s = create_stack_trace(ctx);
+ if (s == NULL) {
+ return STACK_TOP_FRAME;
+ }
if (s->error != NULL) {
set_error_report_errno(s->error);
return STACK_TOP_FRAME;
@@ -383,6 +442,9 @@ int get_frame_info(Context * ctx, int frame, StackFrame ** info) {
}
stack = create_stack_trace(ctx);
+ if (stack == NULL) {
+ return -1;
+ }
if (stack->error != NULL) {
set_error_report_errno(stack->error);
return -1;
@@ -407,10 +469,18 @@ int is_top_frame(Context * ctx, int frame) {
if (frame == STACK_TOP_FRAME) return 1;
if (!ctx->stopped) return 0;
stack = create_stack_trace(ctx);
- if (stack->error != NULL) return 0;
+ if (stack == NULL || stack->error != NULL) return 0;
return frame == stack->frame_cnt - 1;
}
+static void delete_stack_trace(Context * ctx, void * args) {
+ StackTrace * stack_trace = (StackTrace *)ctx->stack_trace;
+ if (stack_trace != NULL) {
+ free_stack_trace(stack_trace);
+ ctx->stack_trace = NULL;
+ }
+}
+
void ini_stack_trace_service(Protocol * proto, TCFBroadcastGroup * bcg) {
static ContextEventListener listener = {
NULL,
diff --git a/services/stacktrace.h b/services/stacktrace.h
index def3df5f..1ab928a5 100644
--- a/services/stacktrace.h
+++ b/services/stacktrace.h
@@ -30,14 +30,14 @@
extern int get_top_frame(Context * ctx);
/*
- * Get information about given stack frame.
+ * Return 1 if 'frame' is the top frame of the context.
*/
-extern int get_frame_info(Context * ctx, int frame, StackFrame ** info);
+extern int is_top_frame(Context * ctx, int frame);
/*
- * Return 1 if 'frame' is the top frame of the context.
+ * Get information about given stack frame.
*/
-extern int is_top_frame(Context * ctx, int frame);
+extern int get_frame_info(Context * ctx, int frame, StackFrame ** info);
/*
* Initialize stack trace service.
diff --git a/services/symbols.c b/services/symbols.c
index b422f3a9..ad6820db 100644
--- a/services/symbols.c
+++ b/services/symbols.c
@@ -431,6 +431,101 @@ static void command_get_array_type(char * token, Channel * c) {
cache_enter(command_get_array_type_cache_client, c, &args, sizeof(args));
}
+typedef struct CommandFindFrameInfo {
+ char token[256];
+ char id[256];
+ ContextAddress addr;
+} CommandFindFrameInfo;
+
+static void write_commands(OutputStream * out, Context * ctx, StackTracingCommandSequence * seq) {
+ if (seq != NULL) {
+ int i;
+ write_stream(out, '[');
+ for (i = 0; i < seq->cmds_cnt; i++) {
+ StackTracingCommand * cmd = seq->cmds + i;
+ if (i > 0) write_stream(out, ',');
+ json_write_long(out, cmd->cmd);
+ switch (cmd->cmd) {
+ case SFT_CMD_NUMBER:
+ write_stream(out, ',');
+ json_write_int64(out, cmd->num);
+ break;
+ case SFT_CMD_REGISTER:
+ write_stream(out, ',');
+ json_write_string(out, register2id(ctx, STACK_NO_FRAME, cmd->reg));
+ break;
+ case SFT_CMD_DEREF:
+ write_stream(out, ',');
+ json_write_ulong(out, cmd->size);
+ write_stream(out, ',');
+ json_write_boolean(out, cmd->big_endian);
+ break;
+ }
+ }
+ write_stream(out, ']');
+ }
+ else {
+ write_string(out, "null");
+ }
+}
+
+static void command_find_frame_info_cache_client(void * x) {
+ CommandFindFrameInfo * args = (CommandFindFrameInfo *)x;
+ Channel * c = cache_channel();
+ Context * ctx = NULL;
+ StackTracingInfo * info = NULL;
+ int err = 0;
+
+ ctx = id2ctx(args->id);
+ if (ctx == NULL) err = ERR_INV_CONTEXT;
+ else if (get_stack_tracing_info(ctx, args->addr, &info) < 0) err = errno;
+
+ cache_exit();
+
+ write_stringz(&c->out, "R");
+ write_stringz(&c->out, args->token);
+ write_errno(&c->out, err);
+
+ json_write_uint64(&c->out, info ? info->addr : 0);
+ write_stream(&c->out, 0);
+ json_write_uint64(&c->out, info ? info->size : 0);
+ write_stream(&c->out, 0);
+
+ write_commands(&c->out, ctx, info ? info->fp : NULL);
+ write_stream(&c->out, 0);
+
+ if (info != NULL && info->regs != NULL) {
+ int i;
+ write_stream(&c->out, '{');
+ for (i = 0; i < info->reg_cnt; i++) {
+ if (i > 0) write_stream(&c->out, ',');
+ json_write_string(&c->out, register2id(ctx, STACK_NO_FRAME, info->regs[i]->reg));
+ write_stream(&c->out, ':');
+ write_commands(&c->out, ctx, info->regs[i]);
+ }
+ write_stream(&c->out, '}');
+ }
+ else {
+ write_string(&c->out, "null");
+ }
+ write_stream(&c->out, 0);
+
+ write_stream(&c->out, MARKER_EOM);
+}
+
+static void command_find_frame_info(char * token, Channel * c) {
+ CommandFindFrameInfo args;
+
+ json_read_string(&c->inp, args.id, sizeof(args.id));
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ args.addr = (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(command_find_frame_info_cache_client, c, &args, sizeof(args));
+}
+
void ini_symbols_service(Protocol * proto) {
static int ini_done = 0;
if (!ini_done) {
@@ -442,6 +537,7 @@ void ini_symbols_service(Protocol * proto) {
add_command_handler(proto, SYMBOLS, "find", command_find);
add_command_handler(proto, SYMBOLS, "list", command_list);
add_command_handler(proto, SYMBOLS, "getArrayType", command_get_array_type);
+ add_command_handler(proto, SYMBOLS, "findFrameInfo", command_find_frame_info);
}
#endif /* SERVICE_Symbols */
diff --git a/services/symbols.h b/services/symbols.h
index 381a6699..1766dcf0 100644
--- a/services/symbols.h
+++ b/services/symbols.h
@@ -52,6 +52,8 @@ typedef struct Symbol Symbol;
typedef void EnumerateSymbolsCallBack(void *, Symbol *);
+#if ENABLE_Symbols
+
/*
* Find symbol information for given symbol name in given context.
* On error, returns -1 and sets errno.
@@ -148,17 +150,11 @@ extern int get_array_symbol(const Symbol * sym, ContextAddress length, Symbol **
/*************************************************************************************************/
-
/*
* Check if given address is inside a PLT section, then return address of the section.
* If not a PLT address return 0;
*/
-#if ENABLE_Symbols
extern ContextAddress is_plt_section(Context * ctx, ContextAddress addr);
-#else
-#define is_plt_section(ctx, addr) 0
-#endif
-
/*
* For given context and its registers in a stack frame,
@@ -166,11 +162,14 @@ extern ContextAddress is_plt_section(Context * ctx, ContextAddress addr);
* If frame info is not available, do nothing.
* Return -1 and set errno in case of an error.
*/
-#if ENABLE_Symbols
extern int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down);
-#else
-#define get_next_stack_frame(ctx, frame, down) 0
-#endif
+
+/*
+ * For given context and instruction address,
+ * search for stack tracing information.
+ * Return -1 and set errno in case of an error.
+ */
+extern int get_stack_tracing_info(Context * ctx, ContextAddress addr, StackTracingInfo ** info);
/*
* Initialize symbol service.
@@ -178,4 +177,6 @@ extern int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame *
extern void ini_symbols_service(Protocol * proto);
extern void ini_symbols_lib(void);
+#endif /* ENABLE_Symbols */
+
#endif /* D_symbols */
diff --git a/services/symbols_elf.c b/services/symbols_elf.c
index 04c67a16..d0dd715b 100644
--- a/services/symbols_elf.c
+++ b/services/symbols_elf.c
@@ -578,29 +578,67 @@ ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
return res;
}
+int get_stack_tracing_info(Context * ctx, ContextAddress addr, StackTracingInfo ** info) {
+ ELF_File * file = elf_list_first(ctx, (ContextAddress)addr, (ContextAddress)(addr + 1));
+ int error = 0;
+
+ *info = NULL;
+
+ while (error == 0 && file != NULL) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ get_dwarf_stack_frame_info(ctx, file, addr);
+ if (dwarf_stack_trace_fp->cmds_cnt > 0) {
+ static StackTracingInfo buf;
+ buf.addr = (ContextAddress)dwarf_stack_trace_addr;
+ buf.size = (ContextAddress)dwarf_stack_trace_size;
+ buf.fp = dwarf_stack_trace_fp;
+ buf.regs = dwarf_stack_trace_regs;
+ buf.reg_cnt = dwarf_stack_trace_regs_cnt;
+ *info = &buf;
+ }
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
+ }
+ if (error || *info != NULL) break;
+ file = elf_list_next(ctx);
+ if (file == NULL) error = errno;
+ }
+ elf_list_done(ctx);
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ return 0;
+}
+
int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
int error = 0;
uint64_t ip = 0;
+ StackTracingInfo * info = NULL;
if (read_reg_value(get_PC_definition(ctx), frame, &ip) < 0) {
if (frame->is_top_frame) error = errno;
}
- else {
- ELF_File * file = elf_list_first(ctx, (ContextAddress)ip, (ContextAddress)(ip + 1));
- while (error == 0 && file != NULL) {
- Trap trap;
- if (set_trap(&trap)) {
- get_dwarf_stack_frame_info(ctx, file, frame, down);
- clear_trap(&trap);
- }
- else {
- error = trap.error;
+ else if (get_stack_tracing_info(ctx, ip, &info) < 0) {
+ error = errno;
+ }
+ else if (info != NULL) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ int i;
+ frame->fp = (ContextAddress)evaluate_stack_trace_commands(ctx, frame, dwarf_stack_trace_fp);
+ for (i = 0; i < dwarf_stack_trace_regs_cnt; i++) {
+ uint64_t v = evaluate_stack_trace_commands(ctx, frame, dwarf_stack_trace_regs[i]);
+ if (write_reg_value(dwarf_stack_trace_regs[i]->reg, down, v) < 0) exception(errno);
}
- if (error || frame->fp != 0) break;
- file = elf_list_next(ctx);
- if (file == NULL) error = errno;
+ clear_trap(&trap);
+ }
+ else {
+ error = trap.error;
}
- elf_list_done(ctx);
}
if (error) {
errno = error;
diff --git a/services/symbols_proxy.c b/services/symbols_proxy.c
index fa0e05f4..cc200171 100644
--- a/services/symbols_proxy.c
+++ b/services/symbols_proxy.c
@@ -33,7 +33,7 @@
#include "stacktrace.h"
#include "symbols.h"
-#define HASH_SIZE 511
+#define HASH_SIZE 101
/* Symbols cahce, one per channel */
typedef struct SymbolsCache {
@@ -43,6 +43,7 @@ typedef struct SymbolsCache {
LINK link_find[HASH_SIZE];
LINK link_list[HASH_SIZE];
LINK link_frame[HASH_SIZE];
+ int service_available;
} SymbolsCache;
/* Symbol properties cache */
@@ -133,6 +134,10 @@ typedef struct StackFrameCache {
uint64_t address;
uint64_t size;
+ StackTracingCommandSequence * fp;
+ StackTracingCommandSequence ** regs;
+ int regs_cnt;
+
int disposed;
} StackFrameCache;
@@ -154,6 +159,8 @@ struct Symbol {
static LINK root;
+static const char * SYMBOLS = "Symbols";
+
static unsigned hash_sym_id(const char * id) {
int i;
unsigned h = 0;
@@ -182,7 +189,9 @@ static SymbolsCache * get_symbols_cache(void) {
LINK * l = NULL;
SymbolsCache * syms = NULL;
Channel * c = cache_channel();
- if (c == NULL) exception(ERR_SYM_NOT_FOUND);
+ if (c == NULL) {
+ str_exception(ERR_SYM_NOT_FOUND, "Illegal cache access");
+ }
for (l = root.next; l != &root; l = l->next) {
SymbolsCache * x = root2syms(l);
if (x->channel == c) {
@@ -199,9 +208,14 @@ static SymbolsCache * get_symbols_cache(void) {
list_init(syms->link_sym + i);
list_init(syms->link_find + i);
list_init(syms->link_list + i);
+ list_init(syms->link_frame + i);
}
channel_lock(c);
+ for (i = 0; i < c->peer_service_cnt; i++) {
+ if (strcmp(c->peer_service_list[i], SYMBOLS) == 0) syms->service_available = 1;
+ }
}
+ if (!syms->service_available) str_exception(ERR_SYM_NOT_FOUND, "Symbols service not available");
return syms;
}
@@ -270,8 +284,12 @@ static void free_stack_frame_cache(StackFrameCache * c) {
list_remove(&c->link_syms);
c->disposed = 1;
if (c->pending == NULL) {
+ int i;
cache_dispose(&c->cache);
release_error_report(c->error);
+ for (i = 0; i < c->regs_cnt; i++) loc_free(c->regs[i]);
+ loc_free(c->regs);
+ loc_free(c->fp);
loc_free(c);
}
}
@@ -342,6 +360,7 @@ static void validate_context(Channel * c, void * args, int error) {
s->error_get_context = get_error_report(error);
cache_notify(&s->cache);
if (s->disposed) free_sym_info_cache(s);
+ if (trap.error) exception(trap.error);
}
static SymInfoCache * get_sym_info_cache(const Symbol * sym) {
@@ -360,7 +379,7 @@ static SymInfoCache * get_sym_info_cache(const Symbol * sym) {
else if (!s->done_context) {
Channel * c = cache_channel();
if (c == NULL) exception(ERR_SYM_NOT_FOUND);
- s->pending_get_context = protocol_send_command(c, "Symbols", "getContext", validate_context, s);
+ s->pending_get_context = protocol_send_command(c, SYMBOLS, "getContext", validate_context, s);
json_write_string(&c->out, s->id);
write_stream(&c->out, 0);
write_stream(&c->out, MARKER_EOM);
@@ -393,6 +412,7 @@ static void validate_find(Channel * c, void * args, int error) {
assert(f->error != NULL || f->id != NULL);
cache_notify(&f->cache);
if (f->disposed) free_find_sym_cache(f);
+ if (trap.error) exception(trap.error);
}
int find_symbol(Context * ctx, int frame, char * name, Symbol ** sym) {
@@ -433,7 +453,7 @@ int find_symbol(Context * ctx, int frame, char * name, Symbol ** sym) {
f->pid = ctx->pid;
f->ip = ip;
f->name = loc_strdup(name);
- f->pending = protocol_send_command(c, "Symbols", "find", validate_find, f);
+ f->pending = protocol_send_command(c, SYMBOLS, "find", validate_find, f);
if (frame != STACK_NO_FRAME) {
json_write_string(&c->out, frame2id(ctx, frame));
}
@@ -493,6 +513,7 @@ static void validate_list(Channel * c, void * args, int error) {
f->error = get_error_report(error);
cache_notify(&f->cache);
if (f->disposed) free_list_sym_cache(f);
+ if (trap.error) exception(trap.error);
}
int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * func, void * args) {
@@ -532,7 +553,7 @@ int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * func,
list_add_first(&f->link_syms, syms->link_list + h);
f->pid = ctx->pid;
f->ip = ip;
- f->pending = protocol_send_command(c, "Symbols", "list", validate_list, f);
+ f->pending = protocol_send_command(c, SYMBOLS, "list", validate_list, f);
if (frame != STACK_NO_FRAME) {
json_write_string(&c->out, frame2id(ctx, frame));
}
@@ -739,6 +760,7 @@ static void validate_children(Channel * c, void * args, int error) {
s->error_get_children = get_error_report(error);
cache_notify(&s->cache);
if (s->disposed) free_sym_info_cache(s);
+ if (trap.error) exception(trap.error);
}
int get_symbol_children(const Symbol * sym, Symbol *** children, int * count) {
@@ -757,7 +779,7 @@ int get_symbol_children(const Symbol * sym, Symbol *** children, int * count) {
else if (!s->done_children) {
Channel * c = cache_channel();
if (c == NULL) exception(ERR_SYM_NOT_FOUND);
- s->pending_get_children = protocol_send_command(c, "Symbols", "getChildren", validate_children, s);
+ s->pending_get_children = protocol_send_command(c, SYMBOLS, "getChildren", validate_children, s);
json_write_string(&c->out, s->id);
write_stream(&c->out, 0);
write_stream(&c->out, MARKER_EOM);
@@ -804,6 +826,7 @@ static void validate_type_id(Channel * c, void * args, int error) {
s->error = get_error_report(error);
cache_notify(&s->cache);
if (s->disposed) free_arr_sym_cache(s);
+ if (trap.error) exception(trap.error);
}
int get_array_symbol(const Symbol * sym, ContextAddress length, Symbol ** ptr) {
@@ -826,7 +849,7 @@ int get_array_symbol(const Symbol * sym, ContextAddress length, Symbol ** ptr) {
a = (ArraySymCache *)loc_alloc_zero(sizeof(*a));
list_add_first(&a->link_sym, &s->array_syms);
a->length = length;
- a->pending = protocol_send_command(c, "Symbols", "getArrayType", validate_type_id, a);
+ a->pending = protocol_send_command(c, SYMBOLS, "getArrayType", validate_type_id, a);
json_write_string(&c->out, s->id);
write_stream(&c->out, 0);
json_write_uint64(&c->out, length);
@@ -850,11 +873,76 @@ int get_array_symbol(const Symbol * sym, ContextAddress length, Symbol ** ptr) {
/*************************************************************************************************/
+static int trace_cmds_cnt = 0;
+static int trace_cmds_max = 0;
+static StackTracingCommand * trace_cmds = NULL;
+
+static int trace_regs_cnt = 0;
+static int trace_regs_max = 0;
+static StackTracingCommandSequence ** trace_regs = NULL;
+
+static int trace_error = 0;
+
ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
/* TODO: is_plt_section() in symbols proxy */
return 0;
}
+static void read_stack_trace_command(InputStream * inp, void * args) {
+ char id[256];
+ Context * ctx = NULL;
+ int frame = STACK_NO_FRAME;
+ StackTracingCommand * cmd = NULL;
+ if (trace_cmds_cnt >= trace_cmds_max) {
+ trace_cmds_max += 16;
+ trace_cmds = (StackTracingCommand *)loc_realloc(trace_cmds, trace_cmds_max * sizeof(StackTracingCommand));
+ }
+ cmd = trace_cmds + trace_cmds_cnt++;
+ memset(cmd, 0, sizeof(*cmd));
+ cmd->cmd = json_read_long(inp);
+ switch (cmd->cmd) {
+ case SFT_CMD_NUMBER:
+ if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
+ cmd->num = json_read_int64(inp);
+ break;
+ case SFT_CMD_REGISTER:
+ if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
+ json_read_string(inp, id, sizeof(id));
+ if (id2register(id, &ctx, &frame, &cmd->reg) < 0) trace_error = errno;
+ break;
+ case SFT_CMD_DEREF:
+ if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
+ cmd->size = json_read_ulong(inp);
+ if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
+ cmd->big_endian = json_read_boolean(inp);
+ break;
+ }
+}
+
+static void read_stack_trace_register(InputStream * inp, const char * id, void * args) {
+ if (trace_regs_cnt >= trace_regs_max) {
+ trace_regs_max += 16;
+ trace_regs = (StackTracingCommandSequence **)loc_realloc(trace_regs, trace_regs_max * sizeof(StackTracingCommandSequence *));
+ }
+ trace_cmds_cnt = 0;
+ if (json_read_array(inp, read_stack_trace_command, NULL)) {
+ Context * ctx = NULL;
+ int frame = STACK_NO_FRAME;
+ StackTracingCommandSequence * reg = (StackTracingCommandSequence *)loc_alloc(
+ sizeof(StackTracingCommandSequence) + (trace_cmds_cnt - 1) * sizeof(StackTracingCommand));
+ if (id2register(id, &ctx, &frame, &reg->reg) < 0) {
+ trace_error = errno;
+ loc_free(reg);
+ }
+ else {
+ reg->cmds_cnt = trace_cmds_cnt;
+ reg->cmds_max = trace_cmds_cnt;
+ memcpy(reg->cmds, trace_cmds, trace_cmds_cnt * sizeof(StackTracingCommand));
+ trace_regs[trace_regs_cnt++] = reg;
+ }
+ }
+}
+
static void validate_frame(Channel * c, void * args, int error) {
Trap trap;
StackFrameCache * f = (StackFrameCache *)args;
@@ -863,20 +951,45 @@ static void validate_frame(Channel * c, void * args, int error) {
if (set_trap(&trap)) {
f->pending = NULL;
if (!error) {
+ uint64_t addr, size;
+ trace_error = 0;
error = read_errno(&c->inp);
-
-
+ addr = json_read_uint64(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ size = json_read_uint64(&c->inp);
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ if (!error && addr != 0 && size != 0) {
+ f->address = addr;
+ f->size = size;
+ }
+ trace_cmds_cnt = 0;
+ if (json_read_array(&c->inp, read_stack_trace_command, NULL)) {
+ f->fp = (StackTracingCommandSequence *)loc_alloc(sizeof(StackTracingCommandSequence) + (trace_cmds_cnt - 1) * sizeof(StackTracingCommand));
+ f->fp->reg = NULL;
+ f->fp->cmds_cnt = trace_cmds_cnt;
+ f->fp->cmds_max = trace_cmds_cnt;
+ memcpy(f->fp->cmds, trace_cmds, trace_cmds_cnt * sizeof(StackTracingCommand));
+ }
+ if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
+ trace_regs_cnt = 0;
+ if (json_read_struct(&c->inp, read_stack_trace_register, NULL)) {
+ f->regs_cnt = trace_regs_cnt;
+ f->regs = (StackTracingCommandSequence **)loc_alloc(trace_regs_cnt * sizeof(StackTracingCommandSequence *));
+ memcpy(f->regs, trace_regs, trace_regs_cnt * sizeof(StackTracingCommandSequence *));
+ }
if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
+ if (!error && trace_error) error = trace_error;
}
clear_trap(&trap);
}
else {
error = trap.error;
}
- f->error = get_error_report(error);
+ if (get_error_code(error) != ERR_INV_COMMAND) f->error = get_error_report(error);
cache_notify(&f->cache);
if (f->disposed) free_stack_frame_cache(f);
+ if (trap.error) exception(trap.error);
}
int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
@@ -899,6 +1012,7 @@ int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
syms = get_symbols_cache();
for (l = syms->link_frame[h].next; l != syms->link_frame + h; l = l->next) {
StackFrameCache * c = syms2frame(l);
+ /* Here we assume that stack tracing info is valid for all threads in same memory space */
if (c->mem == ctx->mem) {
if (c->pending != NULL) {
cache_wait(&c->cache);
@@ -920,8 +1034,8 @@ int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
f->mem = ctx->mem;
f->address = ip;
f->size = 1;
- f->pending = protocol_send_command(c, "Symbols", "getFrameInfo", validate_frame, f);
- json_write_string(&c->out, pid2id(ctx->mem, 0));
+ f->pending = protocol_send_command(c, SYMBOLS, "findFrameInfo", validate_frame, f);
+ json_write_string(&c->out, ctx2id(ctx));
write_stream(&c->out, 0);
json_write_uint64(&c->out, ip);
write_stream(&c->out, 0);
@@ -932,7 +1046,13 @@ int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
else if (f->error != NULL) {
exception(set_error_report_errno(f->error));
}
- else {
+ else if (f->fp != NULL) {
+ int i;
+ frame->fp = (ContextAddress)evaluate_stack_trace_commands(ctx, frame, f->fp);
+ for (i = 0; i < f->regs_cnt; i++) {
+ uint64_t v = evaluate_stack_trace_commands(ctx, frame, f->regs[i]);
+ if (write_reg_value(f->regs[i]->reg, down, v) < 0) exception(errno);
+ }
}
clear_trap(&trap);
@@ -980,6 +1100,15 @@ static void flush_syms(Context * ctx, int mode, int keep_pending) {
if (c->pid == ctx->pid && (c->pending == NULL || !keep_pending))
free_list_sym_cache(c);
}
+ if ((mode & (1 << UPDATE_ON_MEMORY_MAP_CHANGES)) != 0) {
+ l = syms->link_frame[i].next;
+ while (l != syms->link_frame + i) {
+ StackFrameCache * c = syms2frame(l);
+ l = l->next;
+ if (c->mem == ctx->mem && (c->pending == NULL || !keep_pending))
+ free_stack_frame_cache(c);
+ }
+ }
}
}
}
diff --git a/services/symbols_win32.c b/services/symbols_win32.c
index f051ce69..c187df02 100644
--- a/services/symbols_win32.c
+++ b/services/symbols_win32.c
@@ -945,6 +945,11 @@ ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
return 0;
}
+int get_stack_tracing_info(Context * ctx, ContextAddress addr, StackTracingInfo ** info) {
+ *info = NULL;
+ return 0;
+}
+
int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
return 0;
}

Back to the top