Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreutarass2010-04-27 23:38:58 +0000
committereutarass2010-04-27 23:38:58 +0000
commitf1017722bccf19a6510d84d10a86aa494822b18b (patch)
treeb083886bc87b97383e6e6c8495502960104f61a2
parent9bb534d80827bbcb1306f68949e4ea15444c472d (diff)
downloadorg.eclipse.tcf.agent-f1017722bccf19a6510d84d10a86aa494822b18b.tar.gz
org.eclipse.tcf.agent-f1017722bccf19a6510d84d10a86aa494822b18b.tar.xz
org.eclipse.tcf.agent-f1017722bccf19a6510d84d10a86aa494822b18b.zip
TCF Agent: added function context_extension() that allows service implementations to extend debug context object with arbitrary service-private data. Services code changed to use the new extension method.
-rw-r--r--agent.vcproj48
-rw-r--r--config.h2
-rw-r--r--framework/context.c148
-rw-r--r--framework/context.h89
-rw-r--r--framework/mdep.h6
-rw-r--r--machine/x86_64/cpudefs-mdep.h25
-rw-r--r--main/test.c9
-rw-r--r--server/services/context-proxy.c72
-rw-r--r--services/breakpoints.c73
-rw-r--r--services/breakpoints.h6
-rw-r--r--services/diagnostics.c21
-rw-r--r--services/diagnostics.h3
-rw-r--r--services/linenumbers_win32.c11
-rw-r--r--services/memorymap.c154
-rw-r--r--services/memorymap.h3
-rw-r--r--services/registers.c24
-rw-r--r--services/registers.h2
-rw-r--r--services/runctrl.c110
-rw-r--r--services/runctrl.h4
-rw-r--r--services/stacktrace.c127
-rw-r--r--services/symbols_elf.c2
-rw-r--r--services/symbols_proxy.c45
-rw-r--r--services/symbols_win32.c53
-rw-r--r--system/Darwin/context-darwin.c79
-rw-r--r--system/Darwin/regset.h6
-rw-r--r--system/FreeBSD/context-freebsd.c52
-rw-r--r--system/GNU/Linux/context-linux.c112
-rw-r--r--system/VxWorks/context-vxworks.c25
-rw-r--r--system/VxWorks/context-vxworks.h27
-rw-r--r--system/Windows/context-win32.c154
-rw-r--r--system/Windows/context-win32.h35
31 files changed, 944 insertions, 583 deletions
diff --git a/agent.vcproj b/agent.vcproj
index 20c0aa2e..b2419293 100644
--- a/agent.vcproj
+++ b/agent.vcproj
@@ -750,6 +750,10 @@
>
</File>
<File
+ RelativePath=".\system\Windows\context-win32.h"
+ >
+ </File>
+ <File
RelativePath=".\system\Windows\regset.h"
>
</File>
@@ -874,10 +878,54 @@
</FileConfiguration>
</File>
<File
+ RelativePath=".\system\VxWorks\context-vxworks.h"
+ >
+ </File>
+ <File
RelativePath=".\system\VxWorks\regset.h"
>
</File>
</Filter>
+ <Filter
+ Name="Cygwin"
+ >
+ <File
+ RelativePath=".\system\Cygwin\context-cygwin.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\system\Cygwin\regset.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Msys"
+ >
+ <File
+ RelativePath=".\system\Msys\context-msys.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\system\Msys\regset.h"
+ >
+ </File>
+ </Filter>
</Filter>
<Filter
Name="machine"
diff --git a/config.h b/config.h
index c60cb59a..90a42fcb 100644
--- a/config.h
+++ b/config.h
@@ -242,7 +242,7 @@ static void ini_services(Protocol * proto, TCFBroadcastGroup * bcg) {
ini_memory_map_service(proto, bcg);
#endif
#if SERVICE_Registers
- ini_registers_service(proto);
+ ini_registers_service(proto, bcg);
#endif
#if SERVICE_StackTrace
ini_stack_trace_service(proto, bcg);
diff --git a/framework/context.c b/framework/context.c
index a1c31551..07ca6238 100644
--- a/framework/context.c
+++ b/framework/context.c
@@ -30,7 +30,14 @@
#include "breakpoints.h"
#include "waitpid.h"
-static ContextEventListener * event_listeners = NULL;
+typedef struct Listener {
+ ContextEventListener * func;
+ void * args;
+} Listener;
+
+static Listener * listeners = NULL;
+static unsigned listener_cnt = 0;
+static unsigned listener_max = 0;
char * pid2id(pid_t pid, pid_t parent) {
static char s[64];
@@ -78,13 +85,20 @@ pid_t id2pid(const char * id, pid_t * parent) {
}
void add_context_event_listener(ContextEventListener * listener, void * client_data) {
- listener->client_data = client_data;
- listener->next = event_listeners;
- event_listeners = listener;
+ if (listener_cnt >= listener_max) {
+ listener_max += 8;
+ listeners = (Listener *)loc_realloc(listeners, listener_max * sizeof(Listener));
+ }
+ listeners[listener_cnt].func = listener;
+ listeners[listener_cnt].args = client_data;
+ listener_cnt++;
}
#if ENABLE_DebugContext
+static size_t extension_size = 0;
+static int context_created = 0;
+
#if !ENABLE_ContextProxy
#define CONTEXT_PID_HASH_SIZE 1024
@@ -130,6 +144,34 @@ Context * id2ctx(const char * id) {
return context_find_from_pid(pid, parent != 0);
}
+#endif /* !ENABLE_ContextProxy */
+
+size_t context_extension(size_t size) {
+ size_t offs = 0;
+ assert(!context_created);
+ while (extension_size % sizeof(void *) != 0) extension_size++;
+ offs = sizeof(Context) + extension_size;
+ extension_size += size;
+ return offs;
+}
+
+Context * create_context(pid_t pid, size_t regs_size) {
+ Context * ctx = (Context *)loc_alloc_zero(sizeof(Context) + extension_size);
+
+ ctx->pid = pid;
+#if ENABLE_DebugContext && !ENABLE_ContextProxy
+ if ((ctx->regs_size = regs_size) > 0) {
+ ctx->regs = (RegisterData *)loc_alloc_zero(regs_size);
+ }
+ list_init(&ctx->pidl);
+ list_init(&ctx->ctxl);
+#endif
+ list_init(&ctx->children);
+ list_init(&ctx->cldl);
+ context_created = 1;
+ return ctx;
+}
+
void context_lock(Context * ctx) {
assert(ctx->ref_count > 0);
ctx->ref_count++;
@@ -138,43 +180,28 @@ void context_lock(Context * ctx) {
void context_unlock(Context * ctx) {
assert(ctx->ref_count > 0);
if (--(ctx->ref_count) == 0) {
+ unsigned i;
+
assert(list_is_empty(&ctx->children));
assert(ctx->parent == NULL);
-#if SERVICE_StackTrace
- assert(ctx->stack_trace == NULL);
-#endif
-#if SERVICE_MemoryMap
- assert(ctx->memory_map == NULL);
-#endif
-#if SERVICE_Breakpoints
- assert(ctx->breakpoints_state == NULL);
- assert(ctx->stepping_over_bp == NULL);
-#endif
+ assert(!ctx->event_notification);
+ ctx->event_notification = 1;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->func->context_disposed == NULL) continue;
+ l->func->context_disposed(ctx, l->args);
+ }
+ ctx->event_notification = 0;
+#if ENABLE_DebugContext && !ENABLE_ContextProxy
list_remove(&ctx->ctxl);
list_remove(&ctx->pidl);
release_error_report(ctx->regs_error);
- loc_free(ctx->bp_ids);
loc_free(ctx->regs);
+#endif
loc_free(ctx);
}
}
-Context * create_context(pid_t pid, size_t regs_size) {
- Context * ctx = (Context *)loc_alloc_zero(sizeof(Context));
-
- ctx->pid = pid;
- if ((ctx->regs_size = regs_size) > 0) {
- ctx->regs = (RegisterData *)loc_alloc_zero(regs_size);
- }
- list_init(&ctx->children);
- list_init(&ctx->ctxl);
- list_init(&ctx->pidl);
- list_init(&ctx->cldl);
- return ctx;
-}
-
-#endif /* !ENABLE_ContextProxy */
-
const char * context_state_name(Context * ctx) {
if (ctx->exited) return "exited";
if (ctx->intercepted) return "intercepted";
@@ -183,59 +210,52 @@ const char * context_state_name(Context * ctx) {
}
void send_context_created_event(Context * ctx) {
- ContextEventListener * listener = event_listeners;
+ unsigned i;
assert(ctx->ref_count > 0);
assert(!ctx->event_notification);
ctx->event_notification = 1;
- while (listener != NULL) {
- if (listener->context_created != NULL) {
- listener->context_created(ctx, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->func->context_created == NULL) continue;
+ l->func->context_created(ctx, l->args);
}
ctx->event_notification = 0;
}
void send_context_changed_event(Context * ctx) {
- ContextEventListener * listener = event_listeners;
+ unsigned i;
assert(ctx->ref_count > 0);
assert(!ctx->event_notification);
ctx->event_notification = 1;
- while (listener != NULL) {
- if (listener->context_changed != NULL) {
- listener->context_changed(ctx, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->func->context_changed == NULL) continue;
+ l->func->context_changed(ctx, l->args);
}
ctx->event_notification = 0;
}
void send_context_stopped_event(Context * ctx) {
- ContextEventListener * listener = event_listeners;
+ unsigned i;
assert(ctx->ref_count > 0);
assert(ctx->stopped != 0);
assert(!ctx->event_notification);
ctx->event_notification = 1;
#if !ENABLE_ContextProxy
- if (ctx->bp_ids != NULL) {
- loc_free(ctx->bp_ids);
- ctx->bp_ids = NULL;
- }
if (ctx->stopped_by_bp) {
evaluate_breakpoint(ctx);
}
#endif
- while (listener != NULL) {
- if (listener->context_stopped != NULL) {
- listener->context_stopped(ctx, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->func->context_stopped == NULL) continue;
+ l->func->context_stopped(ctx, l->args);
}
ctx->event_notification = 0;
}
void send_context_started_event(Context * ctx) {
- ContextEventListener * listener = event_listeners;
+ unsigned i;
assert(ctx->ref_count > 0);
ctx->stopped = 0;
#if !ENABLE_ContextProxy
@@ -243,17 +263,16 @@ void send_context_started_event(Context * ctx) {
ctx->stopped_by_exception = 0;
#endif
ctx->event_notification++;
- while (listener != NULL) {
- if (listener->context_started != NULL) {
- listener->context_started(ctx, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->func->context_started == NULL) continue;
+ l->func->context_started(ctx, l->args);
}
ctx->event_notification--;
}
void send_context_exited_event(Context * ctx) {
- ContextEventListener * listener = event_listeners;
+ unsigned i;
assert(!ctx->event_notification);
#if !ENABLE_ContextProxy
ctx->exiting = 0;
@@ -261,11 +280,10 @@ void send_context_exited_event(Context * ctx) {
#endif
ctx->exited = 1;
ctx->event_notification = 1;
- while (listener != NULL) {
- if (listener->context_exited != NULL) {
- listener->context_exited(ctx, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->func->context_exited == NULL) continue;
+ l->func->context_exited(ctx, l->args);
}
ctx->event_notification = 0;
if (ctx->parent != NULL) {
diff --git a/framework/context.h b/framework/context.h
index 144c6e02..fbf4fc5a 100644
--- a/framework/context.h
+++ b/framework/context.h
@@ -42,31 +42,15 @@ struct Context {
int intercepted; /* context is reported to a host as suspended */
int exited; /* context exited */
int event_notification; /* set to 1 when calling one of ContextEventListener call-backs for this context */
-#if SERVICE_StackTrace
- void * stack_trace; /* pointer to StackTrace service data cache */
-#endif
-#if SERVICE_MemoryMap
- void * memory_map; /* pointer to MemoryMap service data cache */
-#endif
-#if SERVICE_Breakpoints
- void * breakpoints_state; /* pointer to Breakpoints service data cache */
-#endif
-#if ENABLE_RCBP_TEST
- int test_process; /* if not 0, the process is test process started by Diagnostics service */
-#endif
-#if ENABLE_ContextProxy
- void * proxy;
-#elif ENABLE_DebugContext
+#if ENABLE_DebugContext && !ENABLE_ContextProxy
LINK ctxl; /* link that used to form a list of all contexts */
LINK pidl; /* link that used to form a list of contexts with same hash code */
int stopped_by_bp; /* stopped by breakpoint */
int stopped_by_exception;/* stopped by runtime exception (like SIGSEGV, etc.) */
void * stepping_over_bp; /* if not NULL context is stepping over a breakpoint */
- char ** bp_ids; /* if stopped by breakpoint, contains NULL-terminated list of breakpoint IDs */
int exiting; /* context is about to exit */
int pending_step; /* context is executing single instruction step */
int pending_intercept; /* host is waiting for this context to be suspended */
- int pending_safe_event; /* safe events are waiting for this context to be stopped */
unsigned long pending_signals; /* bitset of signals that were received, but not handled yet */
unsigned long sig_dont_stop; /* bitset of signals that should not be intercepted by the debugger */
unsigned long sig_dont_pass; /* bitset of signals that should not be delivered to the context */
@@ -75,44 +59,9 @@ struct Context {
size_t regs_size; /* size of data pointed by "regs" */
ErrorReport * regs_error; /* if not NULL, 'regs' is invalid */
int regs_dirty; /* if not 0, 'regs' is modified and needs to be saved before context is continued */
-/* OS dependant context attributes */
-# if defined(_WRS_KERNEL)
- VXDBG_BP_INFO bp_info; /* breakpoint information */
- pid_t bp_pid; /* process or thread that hit breakpoint */
- int event;
-# elif defined(WIN32)
- HANDLE handle;
- HANDLE file_handle;
- DWORD64 base_address;
- int module_loaded;
- int module_unloaded;
- HANDLE module_handle;
- DWORD64 module_address;
- int debug_started;
- EXCEPTION_DEBUG_INFO pending_event;
- EXCEPTION_DEBUG_INFO suspend_reason;
- int context_stopped_async_pending;
-# else /* Linux/Unix/BSD */
- ContextAttachCallBack * attach_callback;
- void * attach_data;
- int ptrace_flags;
- int ptrace_event;
- int syscall_enter;
- int syscall_exit;
- int syscall_id;
- ContextAddress syscall_pc;
- ContextAddress loader_state;
- int end_of_step;
-# endif
#endif /* ENABLE_DebugContext */
};
-extern void ini_contexts(void);
-extern void init_contexts_sys_dep(void);
-
-extern const char * context_state_name(Context * ctx);
-extern const char * context_suspend_reason(Context * ctx);
-
/*
* Convert PID to TCF Context ID
*/
@@ -136,6 +85,26 @@ extern Context * id2ctx(const char * id);
#if ENABLE_DebugContext
/*
+ * Register an extension of struct Context.
+ * Return offset of extension data area.
+ * Additional memory of given size will be allocated in each context struct.
+ * Client are allowed to call this function only during initialization.
+ */
+extern size_t context_extension(size_t size);
+
+/*
+ * Get human redable name of current state of a context.
+ */
+extern const char * context_state_name(Context * ctx);
+
+/*
+ * Get state change reason of a context.
+ * Reason can be any text, but if it is one of predefined strings,
+ * a generic client might be able to handle it better.
+ */
+extern const char * context_suspend_reason(Context * ctx);
+
+/*
* Find a context by PID
* Both process and main thread can have same PID.
* 'thread' = 0: search for process, otherwise search for a thread.
@@ -228,12 +197,8 @@ extern void send_context_exited_event(Context * ctx);
extern Context * create_context(pid_t pid, size_t regs_size);
extern void link_context(Context * ctx);
-#else /* ENABLE_DebugContext */
-
-#define context_has_state(ctx) 0
-#define context_read_mem(ctx, address, buf, size) (errno = ERR_INV_CONTEXT, -1)
-#define context_write_mem(ctx, address, buf, size) (errno = ERR_INV_CONTEXT, -1)
-#define context_word_size(ctx) sizeof(void *)
+extern void ini_contexts(void);
+extern void init_contexts_sys_dep(void);
#endif /* ENABLE_DebugContext */
@@ -243,15 +208,9 @@ typedef struct ContextEventListener {
void (*context_stopped)(Context * ctx, void * client_data);
void (*context_started)(Context * ctx, void * client_data);
void (*context_changed)(Context * ctx, void * client_data);
- /* Private: */
- void * client_data;
- struct ContextEventListener * next;
+ void (*context_disposed)(Context * ctx, void * client_data);
} ContextEventListener;
extern void add_context_event_listener(ContextEventListener * listener, void * client_data);
-#ifdef _WRS_KERNEL
-extern VXDBG_CLNT_ID vxdbg_clnt_id;
-#endif
-
#endif
diff --git a/framework/mdep.h b/framework/mdep.h
index db7236e9..dcdca407 100644
--- a/framework/mdep.h
+++ b/framework/mdep.h
@@ -375,6 +375,12 @@ extern char ** environ;
#endif /* BSD */
+#if defined(__APPLE__)
+# define CLOCK_REALTIME 1
+ typedef int clockid_t;
+ extern int clock_gettime(clockid_t clock_id, struct timespec * tp);
+#endif
+
extern int tkill(pid_t pid, int signal);
#define FILE_PATH_SIZE PATH_MAX
diff --git a/machine/x86_64/cpudefs-mdep.h b/machine/x86_64/cpudefs-mdep.h
index 724f6e7e..e3dc9a29 100644
--- a/machine/x86_64/cpudefs-mdep.h
+++ b/machine/x86_64/cpudefs-mdep.h
@@ -47,6 +47,25 @@ RegisterDefinition regs_index[] = {
{ "edi", REG_OFFSET(__edi), 4, 7, 7, 0},
{ "eip", REG_OFFSET(__eip), 4, 8, 8, 1},
{ "eflags", REG_OFFSET(__eflags), 4, 9, 9, 0},
+#elif defined(__APPLE__) && defined(__x86_64__)
+ { "rax", REG_OFFSET(__rax), 8, 0, 0, 0},
+ { "rdx", REG_OFFSET(__rdx), 8, 1, 1, 0},
+ { "rcx", REG_OFFSET(__rcx), 8, 2, 2, 0},
+ { "rbx", REG_OFFSET(__rbx), 8, 3, 3, 0},
+ { "rsi", REG_OFFSET(__rsi), 8, 4, 4, 0},
+ { "rdi", REG_OFFSET(__rdi), 8, 5, 5, 0},
+ { "rbp", REG_OFFSET(__rbp), 8, 6, 6, 1},
+ { "rsp", REG_OFFSET(__rsp), 8, 7, 7, 1},
+ { "r8", REG_OFFSET(__r8), 8, 8, 8, 0},
+ { "r9", REG_OFFSET(__r9), 8, 9, 9, 0},
+ { "r10", REG_OFFSET(__r10), 8, 10, 10, 0},
+ { "r11", REG_OFFSET(__r11), 8, 11, 11, 0},
+ { "r12", REG_OFFSET(__r12), 8, 12, 12, 0},
+ { "r13", REG_OFFSET(__r13), 8, 13, 13, 0},
+ { "r14", REG_OFFSET(__r14), 8, 14, 14, 0},
+ { "r15", REG_OFFSET(__r15), 8, 15, 15, 0},
+ { "rip", REG_OFFSET(__rip), 8, -1, -1, 1},
+ { "eflags", REG_OFFSET(__rflags), 4, 49, -1, 0},
#elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(__i386__)
{ "eax", REG_OFFSET(r_eax), 4, 0, 0, 0},
{ "ecx", REG_OFFSET(r_ecx), 4, 1, 1, 0},
@@ -106,10 +125,14 @@ RegisterDefinition regs_index[] = {
# define REG_SP Esp
# define REG_BP Ebp
# define REG_IP Eip
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) && defined(__i386__)
# define REG_SP __esp
# define REG_BP __ebp
# define REG_IP __eip
+#elif defined(__APPLE__) && defined(__x86_64__)
+# define REG_SP __rsp
+# define REG_BP __rbp
+# define REG_IP __rip
#elif defined(__FreeBSD__) || defined(__NetBSD__)
# define REG_SP r_esp
# define REG_BP r_ebp
diff --git a/main/test.c b/main/test.c
index 48ed33bb..a34640d3 100644
--- a/main/test.c
+++ b/main/test.c
@@ -28,8 +28,11 @@
#include "myalloc.h"
#include "test.h"
#include "trace.h"
-#include "context.h"
+#include "diagnostics.h"
#include "errors.h"
+#if defined(WIN32)
+# include "system/Windows/context-win32.h"
+#endif
typedef enum test_enum {
enum_val1 = 1,
@@ -117,7 +120,7 @@ void test_proc(void) {
int find_test_symbol(Context * ctx, char * name, void ** addr, int * sym_class) {
/* This code allows to run TCF diagnostic tests when symbols info is not available */
if (ctx->parent != NULL) ctx = ctx->parent;
- if (ctx->test_process && strncmp(name, "tcf_test_", 9) == 0) {
+ if (is_test_process(ctx) && strncmp(name, "tcf_test_", 9) == 0) {
*addr = NULL;
if (strcmp(name, "tcf_test_array") == 0) {
*sym_class = SYM_CLASS_REFERENCE;
@@ -146,7 +149,7 @@ typedef struct ContextAttachArgs {
static void done_context_attach(int error, Context * ctx, void * data) {
ContextAttachArgs * args = (ContextAttachArgs *)data;
args->done(error, ctx, args->data);
- assert(error || args->process != ctx->handle);
+ assert(error || args->process != get_context_handle(ctx));
CloseHandle(args->thread);
CloseHandle(args->process);
loc_free(args);
diff --git a/server/services/context-proxy.c b/server/services/context-proxy.c
index b2263dd2..f18da6de 100644
--- a/server/services/context-proxy.c
+++ b/server/services/context-proxy.c
@@ -160,6 +160,10 @@ static char * str_buf = NULL;
static unsigned str_buf_max = 0;
static unsigned str_buf_pos = 0;
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextCache **)((char *)(ctx) + context_extension_offset))
+
static const char RUN_CONTROL[] = "RunControl";
static ContextCache * find_context_cache(PeerCache * p, const char * id) {
@@ -176,13 +180,10 @@ static void add_context_cache(PeerCache * p, ContextCache * c) {
list_init(&c->stk_cache);
list_add_first(&c->link_peer, &p->ctx_cache);
c->peer = p;
- c->ctx = (Context *)loc_alloc_zero(sizeof(Context));
- list_init(&c->ctx->children);
- list_init(&c->ctx->cldl);
- c->ctx->pid = id2pid(c->id, NULL);
+ c->ctx = create_context(id2pid(c->id, NULL), 0);
c->ctx->mem = c->ctx->pid;
- c->ctx->proxy = c;
c->ctx->ref_count = 1;
+ *EXT(c->ctx) = c;
if (c->parent_id[0]) {
ContextCache * h = find_context_cache(p, c->parent_id);
if (h != NULL) {
@@ -268,7 +269,7 @@ static void on_context_suspended(ContextCache * c) {
ContextCache * p = NULL;
while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
- p = (ContextCache *)ctx->proxy;
+ p = *EXT(ctx);
l = p->mem_cache.next;
while (l != &p->mem_cache) {
@@ -370,7 +371,7 @@ static void read_context_removed_item(InputStream * inp, void * args) {
json_read_string(inp, id, sizeof(id));
c = find_context_cache(p, id);
if (c != NULL) {
- assert(c->ctx->proxy == c);
+ assert(*EXT(c->ctx) == c);
send_context_exited_event(c->ctx);
}
else if (p->rc_done) {
@@ -385,7 +386,7 @@ static void read_container_suspended_item(InputStream * inp, void * args) {
json_read_string(inp, id, sizeof(id));
c = find_context_cache(p, id);
if (c != NULL) {
- assert(c->ctx->proxy == c);
+ assert(*EXT(c->ctx) == c);
if (!c->ctx->stopped) {
c->ctx->stopped = 1;
c->ctx->intercepted = 1;
@@ -405,7 +406,7 @@ static void read_container_resumed_item(InputStream * inp, void * args) {
json_read_string(inp, id, sizeof(id));
c = find_context_cache(p, id);
if (c != NULL) {
- assert(c->ctx->proxy == c);
+ assert(*EXT(c->ctx) == c);
if (c->ctx->stopped) {
c->ctx->stopped = 0;
c->ctx->intercepted = 0;
@@ -472,7 +473,7 @@ static void event_context_suspended(Channel * ch, void * args) {
if (read_stream(p->fwd_inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
if (c != &buf) {
- assert(c->ctx->proxy == c);
+ assert(*EXT(c->ctx) == c);
c->pc_valid = 1;
if (!c->ctx->stopped) {
c->ctx->stopped = 1;
@@ -501,7 +502,7 @@ static void event_context_resumed(Channel * ch, void * args) {
c = find_context_cache(p, id);
if (c != NULL) {
- assert(c->ctx->proxy == c);
+ assert(*EXT(c->ctx) == c);
if (c->ctx->stopped) {
c->ctx->stopped = 0;
c->ctx->intercepted = 0;
@@ -570,22 +571,6 @@ void create_context_proxy(Channel * host, Channel * target) {
add_event_handler2(target, RUN_CONTROL, "containerResumed", event_container_resumed, p);
}
-void context_lock(Context * ctx) {
- ctx->ref_count++;
-}
-
-void context_unlock(Context * ctx) {
- assert(ctx->ref_count > 0);
- if (--ctx->ref_count == 0) {
- ContextCache * c = (ContextCache *)ctx->proxy;
- assert(list_is_empty(&ctx->children));
- assert(ctx->parent == NULL);
- loc_free(ctx);
- c->ctx = NULL;
- free_context_cache(c);
- }
-}
-
static void validate_peer_cache_context(Channel * c, void * args, int error);
static void validate_peer_cache_state(Channel * c, void * args, int error);
@@ -782,8 +767,7 @@ Context * id2ctx(const char * id) {
}
int context_has_state(Context * ctx) {
- ContextCache * cache = (ContextCache *)ctx->proxy;
- return cache->has_state;
+ return (*EXT(ctx))->has_state;
}
static void validate_memory_cache(Channel * c, void * args, int error) {
@@ -835,7 +819,7 @@ int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t s
while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
- cache = (ContextCache *)ctx->proxy;
+ cache = *EXT(ctx);
c = cache->peer->target;
for (l = cache->mem_cache.next; l != &cache->mem_cache; l = l->next) {
@@ -944,7 +928,7 @@ static void validate_memory_map_cache(Channel * c, void * args, int error) {
void memory_map_get_regions(Context * ctx, MemoryRegion ** regions, unsigned * cnt) {
ContextCache * cache = NULL;
while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
- cache = (ContextCache *)ctx->proxy;
+ cache = *EXT(ctx);
assert(cache->ctx == ctx);
if (cache->pending_get_mmap != NULL) cache_wait(&cache->mmap_cache);
if (cache->mmap_regions == NULL && cache->mmap_error == NULL && cache->peer != NULL) {
@@ -1108,20 +1092,20 @@ static void check_registers_cache(ContextCache * cache) {
}
RegisterDefinition * get_reg_definitions(Context * ctx) {
- ContextCache * cache = (ContextCache *)ctx->proxy;
+ ContextCache * cache = *EXT(ctx);
check_registers_cache(cache);
return cache->reg_defs;
}
RegisterDefinition * get_PC_definition(Context * ctx) {
- ContextCache * cache = (ContextCache *)ctx->proxy;
+ ContextCache * cache = *EXT(ctx);
check_registers_cache(cache);
return cache->pc_def;
}
RegisterDefinition * get_reg_by_id(Context * ctx, unsigned id, unsigned munbering_convention) {
RegisterDefinition * defs;
- ContextCache * cache = (ContextCache *)ctx->proxy;
+ ContextCache * cache = *EXT(ctx);
check_registers_cache(cache);
defs = cache->reg_defs;
while (defs != NULL && defs->name != NULL) {
@@ -1321,7 +1305,7 @@ static void validate_stack_frame_cache(Channel * c, void * args, int error) {
}
int get_frame_info(Context * ctx, int frame, StackFrame ** info) {
- ContextCache * cache = (ContextCache *)ctx->proxy;
+ ContextCache * cache = *EXT(ctx);
Channel * c = cache->peer->target;
StackFrameCache * s = NULL;
LINK * l = NULL;
@@ -1405,9 +1389,25 @@ static void channel_close_listener(Channel * c) {
}
}
+void event_context_disposed(Context * ctx, void * args) {
+ ContextCache * c = *EXT(ctx);
+ c->ctx = NULL;
+ free_context_cache(c);
+}
+
void init_contexts_sys_dep(void) {
- list_init(&peers);
+ static ContextEventListener listener = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ event_context_disposed
+ };
+ add_context_event_listener(&listener, NULL);
add_channel_close_listener(channel_close_listener);
+ context_extension_offset = context_extension(sizeof(ContextCache *));
+ list_init(&peers);
}
#endif /* ENABLE_DebugContext && ENABLE_ContextProxy */
diff --git a/services/breakpoints.c b/services/breakpoints.c
index 23f0ed85..ac69f6ee 100644
--- a/services/breakpoints.c
+++ b/services/breakpoints.c
@@ -46,6 +46,7 @@
#if defined(_WRS_KERNEL)
# include <private/vxdbgLibP.h>
+# include "system/VxWorks/context-vxworks.h"
#endif
typedef struct BreakpointClient BreakpointClient;
@@ -54,6 +55,7 @@ typedef struct BreakInstruction BreakInstruction;
typedef struct EvaluationArgs EvaluationArgs;
typedef struct EvaluationRequest EvaluationRequest;
typedef struct ConditionEvaluationRequest ConditionEvaluationRequest;
+typedef struct ContextExtension ContextExtension;
struct BreakpointClient {
LINK link_inp;
@@ -138,8 +140,17 @@ struct EvaluationRequest {
ConditionEvaluationRequest * bp_arr;
};
+struct ContextExtension {
+ char ** bp_ids; /* if stopped by breakpoint, contains NULL-terminated list of breakpoint IDs */
+ EvaluationRequest * req;
+};
+
static const char * BREAKPOINTS = "Breakpoints";
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
+
#define is_readable(ctx) (!(ctx)->exited && !(ctx)->exiting && ((ctx)->stopped || !context_has_state(ctx)))
#define is_disabled(bp) (bp->enabled == 0 || bp->client_cnt == 0 || bp->unsupported != NULL)
@@ -513,13 +524,13 @@ static void plant_breakpoint_at_address(BreakpointInfo * bp, Context * ctx, Cont
static void event_replant_breakpoints(void * arg);
static EvaluationRequest * create_evaluation_request(Context * ctx, int bp_cnt) {
- EvaluationRequest * req = (EvaluationRequest *)ctx->breakpoints_state;
+ EvaluationRequest * req = EXT(ctx)->req;
if (req == NULL) {
req = (EvaluationRequest *)loc_alloc_zero(sizeof(EvaluationRequest));
req->ctx = ctx;
list_init(&req->link_posted);
list_init(&req->link_active);
- ctx->breakpoints_state = req;
+ EXT(ctx)->req = req;
}
if (req->bp_max < bp_cnt) {
req->bp_max = bp_cnt;
@@ -668,6 +679,7 @@ static void done_condition(EvaluationRequest * req, int * need_to_flush) {
bp->event_callback(ctx, bp->event_callback_args);
}
else {
+ assert(bp->id[0] != 0);
req->bp_arr[i].triggered = 1;
size += sizeof(char *) + strlen(bp->id) + 1;
}
@@ -678,7 +690,9 @@ static void done_condition(EvaluationRequest * req, int * need_to_flush) {
size_t mem_size = size + sizeof(char *);
char ** bp_arr = (char **)loc_alloc(mem_size);
char * pool = (char *)bp_arr + mem_size;
- ctx->bp_ids = bp_arr;
+ assert(ctx->stopped);
+ assert(EXT(ctx)->bp_ids == NULL);
+ EXT(ctx)->bp_ids = bp_arr;
for (i = 0; i < req->bp_cnt; i++) {
BreakpointInfo * bp = req->bp_arr[i].bp;
if (req->bp_arr[i].triggered) {
@@ -693,7 +707,7 @@ static void done_condition(EvaluationRequest * req, int * need_to_flush) {
for (i = 0; i < req->bp_cnt; i++) {
BreakpointInfo * bp = req->bp_arr[i].bp;
if (req->bp_arr[i].triggered && bp->stop_group == NULL) {
- suspend_debug_context(broadcast_group, ctx);
+ suspend_debug_context(ctx);
*need_to_flush = 1;
}
}
@@ -734,7 +748,7 @@ static void done_conditions_evaluation(int * need_to_flush) {
while (*ids) {
Context * c = id2ctx(*ids++);
if (c != NULL) {
- suspend_debug_context(broadcast_group, c);
+ suspend_debug_context(c);
*need_to_flush = 1;
}
}
@@ -744,13 +758,8 @@ static void done_conditions_evaluation(int * need_to_flush) {
req->bp_cnt = 0;
list_remove(&req->link_active);
if (list_is_empty(&req->link_posted)) {
- if (ctx->exited) {
- loc_free(req->bp_arr);
- loc_free(req);
- ctx->breakpoints_state = NULL;
- }
- else if (ctx->pending_intercept) {
- suspend_debug_context(broadcast_group, ctx);
+ if (!ctx->exited && ctx->pending_intercept) {
+ suspend_debug_context(ctx);
*need_to_flush = 1;
}
assert(!ctx->pending_intercept || ctx->event_notification);
@@ -846,7 +855,7 @@ static void evaluate_condition(void * x) {
int i;
EvaluationArgs * args = (EvaluationArgs *)x;
Context * ctx = args->ctx;
- EvaluationRequest * req = (EvaluationRequest *)ctx->breakpoints_state;
+ EvaluationRequest * req = EXT(ctx)->req;
assert(req != NULL);
assert(req->bp_cnt > 0);
@@ -1679,8 +1688,8 @@ void evaluate_breakpoint(Context * ctx) {
assert(ctx->stopped);
assert(ctx->stopped_by_bp);
assert(ctx->exiting == 0);
- assert(ctx->bp_ids == NULL);
assert(ctx->intercepted == 0);
+ assert(EXT(ctx)->bp_ids == NULL);
if (bi == NULL || !bi->planted || bi->ref_cnt == 0) return;
@@ -1713,6 +1722,10 @@ void evaluate_breakpoint(Context * ctx) {
}
}
+char ** get_context_breakpoint_ids(Context * ctx) {
+ return EXT(ctx)->bp_ids;
+}
+
#ifndef _WRS_KERNEL
static void safe_restore_breakpoint(void * arg) {
@@ -1731,7 +1744,7 @@ static void safe_restore_breakpoint(void * arg) {
plant_instruction(bi);
}
if (ctx->pending_intercept) {
- suspend_debug_context(broadcast_group, ctx);
+ suspend_debug_context(ctx);
flush_stream(&broadcast_group->out);
}
}
@@ -1826,6 +1839,28 @@ static void event_context_changed(Context * ctx, void * args) {
post_location_evaluation_request(ctx);
}
+static void event_context_started(Context * ctx, void * args) {
+ ContextExtension * ext = EXT(ctx);
+ if (ext->bp_ids != NULL) {
+ loc_free(ext->bp_ids);
+ ext->bp_ids = NULL;
+ }
+}
+
+static void event_context_disposed(Context * ctx, void * args) {
+ ContextExtension * ext = EXT(ctx);
+ EvaluationRequest * req = ext->req;
+ if (req != NULL) {
+ loc_free(req->bp_arr);
+ loc_free(req);
+ ext->req = NULL;
+ }
+ if (ext->bp_ids != NULL) {
+ loc_free(ext->bp_ids);
+ ext->bp_ids = NULL;
+ }
+}
+
static void event_code_unmapped(Context * ctx, ContextAddress addr, ContextAddress size, void * args) {
/* Unmapping a code section unplants all breakpoint instructions in that section as side effect.
* This function udates service data structure to reflect that.
@@ -1849,7 +1884,7 @@ static void channel_close_listener(Channel * c) {
#if !defined(_WRS_KERNEL)
static void eventpoint_at_main(Context * ctx, void * args) {
- suspend_debug_context(broadcast_group, ctx);
+ suspend_debug_context(ctx);
flush_stream(&broadcast_group->out);
}
#endif
@@ -1863,8 +1898,9 @@ void ini_breakpoints_service(Protocol * proto, TCFBroadcastGroup * bcg) {
event_context_changed,
event_context_changed,
NULL,
- NULL,
- event_context_changed
+ event_context_started,
+ event_context_changed,
+ event_context_disposed
};
add_context_event_listener(&listener, NULL);
}
@@ -1893,6 +1929,7 @@ void ini_breakpoints_service(Protocol * proto, TCFBroadcastGroup * bcg) {
add_command_handler(proto, BREAKPOINTS, "getProperties", command_get_properties);
add_command_handler(proto, BREAKPOINTS, "getStatus", command_get_status);
add_command_handler(proto, BREAKPOINTS, "getCapabilities", command_get_capabilities);
+ context_extension_offset = context_extension(sizeof(ContextExtension));
#if !defined(_WRS_KERNEL)
create_eventpoint("main", eventpoint_at_main, NULL);
#endif
diff --git a/services/breakpoints.h b/services/breakpoints.h
index 4310cc25..e992f0d8 100644
--- a/services/breakpoints.h
+++ b/services/breakpoints.h
@@ -36,6 +36,12 @@ typedef struct BreakpointInfo BreakpointInfo;
extern void evaluate_breakpoint(Context * ctx);
/*
+ * Return NULL-terminated array of breakpoint IDs if the context is stopped by breakpoint.
+ * Otherwise return NULL.
+ */
+extern char ** get_context_breakpoint_ids(Context * ctx);
+
+/*
* When a context is stopped by breakpoint, it is necessary to disable
* the breakpoint temporarily before the context can be resumed.
* This function function removes break instruction, then does single step
diff --git a/services/diagnostics.c b/services/diagnostics.c
index 09794aab..b83e3ae2 100644
--- a/services/diagnostics.c
+++ b/services/diagnostics.c
@@ -42,6 +42,22 @@
static const char * DIAGNOSTICS = "Diagnostics";
+#if ENABLE_RCBP_TEST
+
+typedef struct ContextExtension {
+ int test_process;
+} ContextExtension;
+
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
+
+int is_test_process(Context * ctx) {
+ return EXT(ctx)->test_process;
+}
+
+#endif /* ENABLE_RCBP_TEST */
+
typedef struct RunTestDoneArgs RunTestDoneArgs;
struct RunTestDoneArgs {
@@ -92,7 +108,7 @@ static void run_test_done(int error, Context * ctx, void * arg) {
RunTestDoneArgs * data = (RunTestDoneArgs *)arg;
Channel * c = data->c;
- if (ctx != NULL) ctx->test_process = 1;
+ if (ctx != NULL) EXT(ctx)->test_process = 1;
if (!is_channel_closed(c)) {
write_stringz(&c->out, "R");
write_stringz(&c->out, data->token);
@@ -368,6 +384,9 @@ void ini_diagnostics_service(Protocol * proto) {
add_command_handler(proto, DIAGNOSTICS, "getSymbol", command_get_symbol);
add_command_handler(proto, DIAGNOSTICS, "createTestStreams", command_create_test_streams);
add_command_handler(proto, DIAGNOSTICS, "disposeTestStream", command_dispose_test_stream);
+#if ENABLE_RCBP_TEST
+ context_extension_offset = context_extension(sizeof(ContextExtension));
+#endif
}
diff --git a/services/diagnostics.h b/services/diagnostics.h
index dbb8f043..34a4d48f 100644
--- a/services/diagnostics.h
+++ b/services/diagnostics.h
@@ -21,6 +21,9 @@
#define D_diagnostics
#include "protocol.h"
+#include "context.h"
+
+extern int is_test_process(Context * ctx);
extern void ini_diagnostics_service(Protocol *);
diff --git a/services/linenumbers_win32.c b/services/linenumbers_win32.c
index ab9f1491..a14c4237 100644
--- a/services/linenumbers_win32.c
+++ b/services/linenumbers_win32.c
@@ -28,6 +28,7 @@
#include "linenumbers.h"
#include "breakpoints.h"
#include "windbgcache.h"
+#include "context-win32.h"
#include "context.h"
#include "exceptions.h"
#include "symbols.h"
@@ -50,7 +51,7 @@ int line_to_address(Context * ctx, char * file, int line, int column, LineNumber
memset(&area, 0, sizeof(area));
img_line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
- if (!SymGetLineFromName(ctx->handle, NULL, file, line, &offset, &img_line)) {
+ if (!SymGetLineFromName(get_context_handle(ctx), NULL, file, line, &offset, &img_line)) {
DWORD win_err = GetLastError();
if (win_err != ERROR_NOT_FOUND) {
err = set_win32_errno(win_err);
@@ -59,7 +60,7 @@ int line_to_address(Context * ctx, char * file, int line, int column, LineNumber
else {
IMAGEHLP_LINE img_next;
memcpy(&img_next, &img_line, sizeof(img_next));
- if (!SymGetLineNext(ctx->handle, &img_next)) {
+ if (!SymGetLineNext(get_context_handle(ctx), &img_next)) {
err = set_win32_errno(GetLastError());
}
else {
@@ -101,7 +102,7 @@ int address_to_line(Context * ctx, ContextAddress addr0, ContextAddress addr1, L
line.SizeOfStruct = sizeof(IMAGEHLP_LINE);
if (addr0 >= addr1) not_found = 1;
- while (err == 0 && not_found == 0 && !SymGetLineFromAddr(ctx->handle, addr0, &offset, &line)) {
+ while (err == 0 && not_found == 0 && !SymGetLineFromAddr(get_context_handle(ctx), addr0, &offset, &line)) {
DWORD w = GetLastError();
if (w == ERROR_MOD_NOT_FOUND) {
not_found = 1;
@@ -149,7 +150,7 @@ int address_to_line(Context * ctx, ContextAddress addr0, ContextAddress addr1, L
}
}
memcpy(&next, &line, sizeof(next));
- if (err == 0 && !not_found && !SymGetLineNext(ctx->handle, &next)) {
+ if (err == 0 && !not_found && !SymGetLineNext(get_context_handle(ctx), &next)) {
err = set_win32_errno(GetLastError());
}
@@ -165,7 +166,7 @@ int address_to_line(Context * ctx, ContextAddress addr0, ContextAddress addr1, L
callback(&area, user_args);
if (next.Address >= addr1) break;
memcpy(&line, &next, sizeof(line));
- if (!SymGetLineNext(ctx->handle, &next)) break;
+ if (!SymGetLineNext(get_context_handle(ctx), &next)) break;
}
}
diff --git a/services/memorymap.c b/services/memorymap.c
index a024107d..c7ae7839 100644
--- a/services/memorymap.c
+++ b/services/memorymap.c
@@ -35,38 +35,48 @@
#include "events.h"
#include "exceptions.h"
-typedef struct MemoryMap MemoryMap;
-
-struct MemoryMap {
+typedef struct MemoryMap {
+ int valid;
unsigned region_cnt;
unsigned region_max;
MemoryRegion * regions;
-};
+} MemoryMap;
+
+typedef struct Listener {
+ MemoryMapEventListener * listener;
+ void * args;
+} Listener;
+
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((MemoryMap *)((char *)(ctx) + context_extension_offset))
static const char * MEMORYMAP = "MemoryMap";
-static MemoryMapEventListener * event_listeners = NULL;
+
+static Listener * listeners = NULL;
+static unsigned listener_cnt = 0;
+static unsigned listener_max = 0;
+
static TCFBroadcastGroup * broadcast_group = NULL;
-static void dispose_memory_map(MemoryMap * map) {
+static void event_memory_map_changed(Context * ctx, void * args) {
unsigned i;
+ OutputStream * out;
+ MemoryMap * map = NULL;
+
+ while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
+ map = EXT(ctx);
for (i = 0; i < map->region_cnt; i++) {
MemoryRegion * r = map->regions + i;
loc_free(r->file_name);
loc_free(r->sect_name);
}
- loc_free(map->regions);
- loc_free(map);
-}
-
-static void event_memory_map_changed(Context * ctx, void * args) {
- OutputStream * out;
+ map->region_cnt = 0;
- while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
- if (ctx->memory_map == NULL) return;
+ if (!map->valid) return;
+ map->valid = 0;
- dispose_memory_map((MemoryMap *)ctx->memory_map);
- ctx->memory_map = NULL;
out = &broadcast_group->out;
write_stringz(out, "E");
@@ -78,12 +88,24 @@ static void event_memory_map_changed(Context * ctx, void * args) {
write_stream(out, MARKER_EOM);
}
+static void event_context_disposed(Context * ctx, void * args) {
+ unsigned i;
+ MemoryMap * map = EXT(ctx);
+
+ for (i = 0; i < map->region_cnt; i++) {
+ MemoryRegion * r = map->regions + i;
+ loc_free(r->file_name);
+ loc_free(r->sect_name);
+ }
+ loc_free(map->regions);
+ memset(map, 0, sizeof(MemoryMap));
+}
+
#if defined(_WRS_KERNEL)
static int hooks_done = 0;
-static MemoryMap * map = NULL;
-static void add_map_region(void * addr, int size, unsigned flags, char * file, char * sect) {
+static void add_map_region(MemoryMap * map, void * addr, int size, unsigned flags, char * file, char * sect) {
MemoryRegion * r = NULL;
if (map->region_cnt >= map->region_max) {
map->region_max += 8;
@@ -100,17 +122,19 @@ static void add_map_region(void * addr, int size, unsigned flags, char * file, c
static int module_list_proc(MODULE_ID id, int args) {
MODULE_INFO info;
+ MemoryMap * map = (MemoryMap *)args;
+
memset(&info, 0, sizeof(info));
if (moduleInfoGet(id, &info) == OK) {
char * file = id->nameWithPath;
if (info.segInfo.textAddr != NULL && info.segInfo.textSize > 0) {
- add_map_region(info.segInfo.textAddr, info.segInfo.textSize, MM_FLAG_R | MM_FLAG_X, file, ".text");
+ add_map_region(map, info.segInfo.textAddr, info.segInfo.textSize, MM_FLAG_R | MM_FLAG_X, file, ".text");
}
if (info.segInfo.dataAddr != NULL && info.segInfo.dataSize > 0) {
- add_map_region(info.segInfo.dataAddr, info.segInfo.dataSize, MM_FLAG_R | MM_FLAG_W, file, ".data");
+ add_map_region(map, info.segInfo.dataAddr, info.segInfo.dataSize, MM_FLAG_R | MM_FLAG_W, file, ".data");
}
if (info.segInfo.bssAddr != NULL && info.segInfo.bssSize > 0) {
- add_map_region(info.segInfo.bssAddr, info.segInfo.bssSize, MM_FLAG_R | MM_FLAG_W, file, ".bss");
+ add_map_region(map, info.segInfo.bssAddr, info.segInfo.bssSize, MM_FLAG_R | MM_FLAG_W, file, ".bss");
}
}
return 0;
@@ -130,32 +154,32 @@ static int module_create_func(MODULE_ID id) {
}
static MemoryMap * get_memory_map(Context * ctx) {
+ MemoryMap * map = NULL;
if (!hooks_done) {
hooks_done = 1;
moduleCreateHookAdd(module_create_func);
}
while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
- if (ctx->memory_map == NULL && !ctx->exited) {
- map = loc_alloc_zero(sizeof(MemoryMap));
- moduleEach(module_list_proc, 0);
- ctx->memory_map = map;
- map = NULL;
+ map = EXT(ctx);
+ if (!map->valid && !ctx->exited) {
+ moduleEach(module_list_proc, (int)map);
+ map->valid = 1;
}
- return (MemoryMap *)ctx->memory_map;
+ return map;
}
#elif defined(WIN32)
static MemoryMap * get_memory_map(Context * ctx) {
- errno = 0;
- return NULL;
+ while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
+ return EXT(ctx);
}
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
static MemoryMap * get_memory_map(Context * ctx) {
- errno = 0;
- return NULL;
+ while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
+ return EXT(ctx);
}
#else
@@ -163,14 +187,14 @@ static MemoryMap * get_memory_map(Context * ctx) {
static MemoryMap * get_memory_map(Context * ctx) {
char maps_file_name[FILE_PATH_SIZE];
MemoryMap * map = NULL;
- FILE * file;
+ FILE * file = NULL;
while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
- if (ctx->memory_map != NULL || ctx->exited) return (MemoryMap *)ctx->memory_map;
+ map = EXT(ctx);
+ if (map->valid || ctx->exited) return map;
snprintf(maps_file_name, sizeof(maps_file_name), "/proc/%d/maps", ctx->pid);
- if ((file = fopen(maps_file_name, "r")) == NULL) return NULL;
- map = (MemoryMap *)loc_alloc_zero(sizeof(MemoryMap));
+ if ((file = fopen(maps_file_name, "r")) == NULL) return map;
for (;;) {
unsigned long addr0 = 0;
unsigned long addr1 = 0;
@@ -219,7 +243,7 @@ static MemoryMap * get_memory_map(Context * ctx) {
}
}
fclose(file);
- ctx->memory_map = map;
+ map->valid = 1;
return map;
}
@@ -227,57 +251,53 @@ static MemoryMap * get_memory_map(Context * ctx) {
void memory_map_get_regions(Context * ctx, MemoryRegion ** regions, unsigned * cnt) {
MemoryMap * map = get_memory_map(ctx);
- if (map == NULL) {
- *regions = NULL;
- *cnt = 0;
- }
- else {
- *regions = map->regions;
- *cnt = map->region_cnt;
- }
+ *regions = map->regions;
+ *cnt = map->region_cnt;
}
void memory_map_event_module_loaded(Context * ctx) {
- MemoryMapEventListener * listener = event_listeners;
+ unsigned i;
assert(ctx->ref_count > 0);
assert(ctx->parent == NULL);
event_memory_map_changed(ctx, NULL);
- while (listener != NULL) {
- if (listener->module_loaded != NULL) {
- listener->module_loaded(ctx, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->listener->module_loaded == NULL) continue;
+ l->listener->module_loaded(ctx, l->args);
}
}
void memory_map_event_code_section_ummapped(Context * ctx, ContextAddress addr, ContextAddress size) {
- MemoryMapEventListener * listener = event_listeners;
+ unsigned i;
assert(ctx->ref_count > 0);
assert(ctx->parent == NULL);
- while (listener != NULL) {
- if (listener->code_section_ummapped != NULL) {
- listener->code_section_ummapped(ctx, addr, size, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->listener->code_section_ummapped == NULL) continue;
+ l->listener->code_section_ummapped(ctx, addr, size, l->args);
}
}
void memory_map_event_module_unloaded(Context * ctx) {
- MemoryMapEventListener * listener = event_listeners;
+ unsigned i;
assert(ctx->ref_count > 0);
event_memory_map_changed(ctx, NULL);
- while (listener != NULL) {
- if (listener->module_unloaded != NULL) {
- listener->module_unloaded(ctx, listener->client_data);
- }
- listener = listener->next;
+ for (i = 0; i < listener_cnt; i++) {
+ Listener * l = listeners + i;
+ if (l->listener->module_unloaded == NULL) continue;
+ l->listener->module_unloaded(ctx, l->args);
}
}
void add_memory_map_event_listener(MemoryMapEventListener * listener, void * client_data) {
- listener->client_data = client_data;
- listener->next = event_listeners;
- event_listeners = listener;
+ Listener * l = NULL;
+ if (listener_cnt >= listener_max) {
+ listener_max += 8;
+ listeners = (Listener *)loc_realloc(listeners, listener_max * sizeof(Listener));
+ }
+ l = listeners + listener_cnt++;
+ l->listener = listener;
+ l->args = client_data;
}
static void command_get(char * token, Channel * c) {
@@ -350,11 +370,13 @@ void ini_memory_map_service(Protocol * proto, TCFBroadcastGroup * bcg) {
event_memory_map_changed,
NULL,
NULL,
- event_memory_map_changed
+ event_memory_map_changed,
+ event_context_disposed
};
broadcast_group = bcg;
add_context_event_listener(&listener, NULL);
add_command_handler(proto, MEMORYMAP, "get", command_get);
+ context_extension_offset = context_extension(sizeof(MemoryMap));
}
diff --git a/services/memorymap.h b/services/memorymap.h
index 3543fd95..e924b71d 100644
--- a/services/memorymap.h
+++ b/services/memorymap.h
@@ -58,9 +58,6 @@ typedef struct MemoryMapEventListener {
void (*module_loaded)(Context * ctx, void * client_data);
void (*code_section_ummapped)(Context * ctx, ContextAddress addr, ContextAddress size, void * client_data);
void (*module_unloaded)(Context * ctx, void * client_data);
- /* Private: */
- void * client_data;
- struct MemoryMapEventListener * next;
} MemoryMapEventListener;
/*
diff --git a/services/registers.c b/services/registers.c
index 1a89f3b7..90b48b5d 100644
--- a/services/registers.c
+++ b/services/registers.c
@@ -37,6 +37,8 @@ static const char * REGISTERS = "Registers";
static short endianess_test = 0x0201;
#define BIG_ENDIAN_DATA (*(char *)&endianess_test == 0x02)
+static TCFBroadcastGroup * broadcast_group = NULL;
+
static void write_context(OutputStream * out, char * id, Context * ctx, int frame, RegisterDefinition * reg_def) {
assert(!ctx->exited);
@@ -188,15 +190,16 @@ static void command_get_children(char * token, Channel * c) {
write_stream(&c->out, MARKER_EOM);
}
-static void send_event_register_changed(Channel * c, char * id) {
- write_stringz(&c->out, "E");
- write_stringz(&c->out, REGISTERS);
- write_stringz(&c->out, "registerChanged");
+static void send_event_register_changed(char * id) {
+ OutputStream * out = &broadcast_group->out;
+ write_stringz(out, "E");
+ write_stringz(out, REGISTERS);
+ write_stringz(out, "registerChanged");
- json_write_string(&c->out, id);
- write_stream(&c->out, 0);
+ json_write_string(out, id);
+ write_stream(out, 0);
- write_stream(&c->out, MARKER_EOM);
+ write_stream(out, MARKER_EOM);
}
static void command_get(char * token, Channel * c) {
@@ -274,7 +277,7 @@ static void command_set(char * token, Channel * c) {
else {
memcpy(data, val, val_len);
ctx->regs_dirty = 1;
- send_event_register_changed(c, id);
+ send_event_register_changed(id);
}
}
@@ -397,7 +400,7 @@ static void command_setm(char * token, Channel * c) {
if (rd == 0) break;
rd_done += rd;
}
- send_event_register_changed(c, l->id);
+ send_event_register_changed(l->id);
}
}
json_read_binary_end(&state);
@@ -430,7 +433,8 @@ static void command_search(char * token, Channel * c) {
write_stream(&c->out, MARKER_EOM);
}
-void ini_registers_service(Protocol * proto) {
+void ini_registers_service(Protocol * proto, TCFBroadcastGroup * bcg) {
+ broadcast_group = bcg;
add_command_handler(proto, REGISTERS, "getContext", command_get_context);
add_command_handler(proto, REGISTERS, "getChildren", command_get_children);
add_command_handler(proto, REGISTERS, "get", command_get);
diff --git a/services/registers.h b/services/registers.h
index 95d145a4..6f167989 100644
--- a/services/registers.h
+++ b/services/registers.h
@@ -24,7 +24,7 @@
/*
* Initialize registers service.
*/
-extern void ini_registers_service(Protocol *);
+extern void ini_registers_service(Protocol *, TCFBroadcastGroup *);
#endif /* D_registers */
diff --git a/services/runctrl.c b/services/runctrl.c
index c63138d6..72f080d0 100644
--- a/services/runctrl.c
+++ b/services/runctrl.c
@@ -60,22 +60,27 @@
static const char RUN_CONTROL[] = "RunControl";
-typedef struct SafeEvent SafeEvent;
+typedef struct ContextExtension {
+ int pending_safe_event; /* safe events are waiting for this context to be stopped */
+ int intercepted_by_bp;
+} ContextExtension;
-struct SafeEvent {
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
+
+typedef struct SafeEvent {
pid_t mem;
EventCallBack * done;
void * arg;
- SafeEvent * next;
-};
-
-typedef struct GetContextArgs GetContextArgs;
+ struct SafeEvent * next;
+} SafeEvent;
-struct GetContextArgs {
+typedef struct GetContextArgs {
Channel * c;
char token[256];
Context * ctx;
-};
+} GetContextArgs;
static SafeEvent * safe_event_list = NULL;
static SafeEvent * safe_event_last = NULL;
@@ -83,6 +88,8 @@ static int safe_event_pid_count = 0;
static uintptr_t safe_event_generation = 0;
static int run_ctrl_lock_cnt = 0;
+static TCFBroadcastGroup * broadcast_group = NULL;
+
#if !defined(WIN32) && !defined(_WRS_KERNEL)
static char * get_executable(pid_t pid) {
static char s[FILE_PATH_SIZE + 1];
@@ -179,6 +186,7 @@ static void write_context(OutputStream * out, Context * ctx) {
static void write_context_state(OutputStream * out, Context * ctx) {
int fst = 1;
const char * reason = NULL;
+ char ** bp_ids = NULL;
assert(!ctx->exited);
if (!ctx->intercepted) {
@@ -193,8 +201,9 @@ static void write_context_state(OutputStream * out, Context * ctx) {
write_stream(out, 0);
/* String: Reason */
- if (ctx->bp_ids != NULL && ctx->bp_ids[0] != NULL) reason = "Breakpoint";
- if (reason == NULL) reason = context_suspend_reason(ctx);
+ if (EXT(ctx)->intercepted_by_bp == 1) bp_ids = get_context_breakpoint_ids(ctx);
+ if (bp_ids != NULL) reason = "Breakpoint";
+ else reason = context_suspend_reason(ctx);
json_write_string(out, reason);
write_stream(out, 0);
@@ -212,15 +221,15 @@ static void write_context_state(OutputStream * out, Context * ctx) {
}
fst = 0;
}
- if (ctx->bp_ids != NULL && ctx->bp_ids[0] != NULL) {
+ if (bp_ids != NULL) {
int i = 0;
if (!fst) write_stream(out, ',');
json_write_string(out, "BPs");
write_stream(out, ':');
write_stream(out, '[');
- while (ctx->bp_ids[i] != NULL) {
+ while (bp_ids[i] != NULL) {
if (i > 0) write_stream(out, ',');
- json_write_string(out, ctx->bp_ids[i++]);
+ json_write_string(out, bp_ids[i++]);
}
write_stream(out, ']');
fst = 0;
@@ -467,7 +476,7 @@ static void command_resume(char * token, Channel * c) {
static void send_event_context_suspended(OutputStream * out, Context * ctx);
-int suspend_debug_context(TCFBroadcastGroup * bcg, Context * ctx) {
+int suspend_debug_context(Context * ctx) {
LINK * qp;
if (context_has_state(ctx) && !ctx->exited) {
if (!ctx->stopped) {
@@ -483,12 +492,12 @@ int suspend_debug_context(TCFBroadcastGroup * bcg, Context * ctx) {
}
else {
ctx->pending_step = 0;
- send_event_context_suspended(&bcg->out, ctx);
+ send_event_context_suspended(&broadcast_group->out, ctx);
}
}
}
for (qp = ctx->children.next; qp != &ctx->children; qp = qp->next) {
- suspend_debug_context(bcg, cldl2ctxp(qp));
+ suspend_debug_context(cldl2ctxp(qp));
}
return 0;
}
@@ -512,7 +521,7 @@ static void command_suspend(char * token, Channel * c) {
else if (ctx->intercepted) {
err = ERR_ALREADY_STOPPED;
}
- else if (suspend_debug_context(c->bcg, ctx) < 0) {
+ else if (suspend_debug_context(ctx) < 0) {
err = errno;
}
@@ -630,6 +639,7 @@ static void send_event_context_suspended(OutputStream * out, Context * ctx) {
assert(!ctx->pending_step);
ctx->intercepted = 1;
ctx->pending_intercept = 0;
+ if (get_context_breakpoint_ids(ctx) != NULL) EXT(ctx)->intercepted_by_bp++;
write_stringz(out, "E");
write_stringz(out, RUN_CONTROL);
@@ -648,10 +658,6 @@ static void send_event_context_resumed(OutputStream * out, Context * ctx) {
assert(!ctx->pending_intercept);
assert(!ctx->pending_step);
ctx->intercepted = 0;
- if (ctx->bp_ids != NULL) {
- loc_free(ctx->bp_ids);
- ctx->bp_ids = NULL;
- }
write_stringz(out, "E");
write_stringz(out, RUN_CONTROL);
@@ -708,7 +714,7 @@ static void run_safe_events(void * arg) {
for (qp = context_root.next; qp != &context_root; qp = qp->next) {
int n = 0;
Context * ctx = ctxl2ctxp(qp);
- ctx->pending_safe_event = 0;
+ EXT(ctx)->pending_safe_event = 0;
if (ctx->exited) continue;
if (!ctx->stopped) continue;
if (ctx->intercepted) continue;
@@ -736,14 +742,14 @@ static void run_safe_events(void * arg) {
for (qp = context_root.next; qp != &context_root; qp = qp->next) {
Context * ctx = ctxl2ctxp(qp);
if (ctx->exited || ctx->exiting || ctx->stopped || !context_has_state(ctx)) {
- ctx->pending_safe_event = 0;
+ EXT(ctx)->pending_safe_event = 0;
continue;
}
if (mem > 0 && ctx->mem != mem) {
- ctx->pending_safe_event = 0;
+ EXT(ctx)->pending_safe_event = 0;
continue;
}
- if (!ctx->pending_step || ctx->pending_safe_event >= STOP_ALL_MAX_CNT / 2) {
+ if (!ctx->pending_step || EXT(ctx)->pending_safe_event >= STOP_ALL_MAX_CNT / 2) {
if (context_stop(ctx) < 0) {
int error = errno;
#ifdef _WRS_KERNEL
@@ -761,13 +767,13 @@ static void run_safe_events(void * arg) {
}
assert(!ctx->stopped);
}
- if (ctx->pending_safe_event >= STOP_ALL_MAX_CNT) {
+ if (EXT(ctx)->pending_safe_event >= STOP_ALL_MAX_CNT) {
trace(LOG_ALWAYS, "error: can't temporary stop pid %d; error: timeout", ctx->pid);
ctx->exiting = 1;
- ctx->pending_safe_event = 0;
+ EXT(ctx)->pending_safe_event = 0;
}
else {
- ctx->pending_safe_event++;
+ EXT(ctx)->pending_safe_event++;
safe_event_pid_count++;
}
}
@@ -800,9 +806,9 @@ static void run_safe_events(void * arg) {
static void check_safe_events(Context * ctx) {
assert(ctx->stopped || ctx->exited);
- assert(ctx->pending_safe_event);
+ assert(EXT(ctx)->pending_safe_event);
assert(safe_event_pid_count > 0);
- ctx->pending_safe_event = 0;
+ EXT(ctx)->pending_safe_event = 0;
safe_event_pid_count--;
if (safe_event_pid_count == 0 && run_ctrl_lock_cnt > 0) {
post_event(run_safe_events, (void *)++safe_event_generation);
@@ -843,67 +849,59 @@ void run_ctrl_unlock(void) {
}
static void event_context_created(Context * ctx, void * client_data) {
- TCFBroadcastGroup * bcg = (TCFBroadcastGroup *)client_data;
assert(!ctx->exited);
assert(!ctx->intercepted);
assert(!ctx->stopped);
- send_event_context_added(&bcg->out, ctx);
- flush_stream(&bcg->out);
+ send_event_context_added(&broadcast_group->out, ctx);
+ flush_stream(&broadcast_group->out);
}
static void event_context_changed(Context * ctx, void * client_data) {
- TCFBroadcastGroup * bcg = (TCFBroadcastGroup *)client_data;
-
- send_event_context_changed(&bcg->out, ctx);
- flush_stream(&bcg->out);
+ send_event_context_changed(&broadcast_group->out, ctx);
+ flush_stream(&broadcast_group->out);
}
static void event_context_stopped(Context * ctx, void * client_data) {
- TCFBroadcastGroup * bcg = (TCFBroadcastGroup *)client_data;
-
assert(ctx->stopped);
assert(!ctx->intercepted);
assert(!ctx->exited);
- if (ctx->pending_safe_event) check_safe_events(ctx);
+ if (EXT(ctx)->pending_safe_event) check_safe_events(ctx);
if (ctx->stopped_by_exception) {
- send_event_context_exception(&bcg->out, ctx);
+ send_event_context_exception(&broadcast_group->out, ctx);
}
if (ctx->pending_intercept) {
- send_event_context_suspended(&bcg->out, ctx);
+ send_event_context_suspended(&broadcast_group->out, ctx);
}
if (!ctx->intercepted && run_ctrl_lock_cnt == 0) {
context_continue(ctx);
}
- flush_stream(&bcg->out);
+ flush_stream(&broadcast_group->out);
}
static void event_context_started(Context * ctx, void * client_data) {
- TCFBroadcastGroup * bcg = (TCFBroadcastGroup *)client_data;
-
assert(!ctx->stopped);
if (ctx->intercepted) {
- send_event_context_resumed(&bcg->out, ctx);
+ send_event_context_resumed(&broadcast_group->out, ctx);
}
+ EXT(ctx)->intercepted_by_bp = 0;
if (safe_event_list) {
if (!ctx->pending_step) {
context_stop(ctx);
}
- if (!ctx->pending_safe_event) {
- ctx->pending_safe_event = 1;
+ if (!EXT(ctx)->pending_safe_event) {
+ EXT(ctx)->pending_safe_event = 1;
safe_event_pid_count++;
}
}
- flush_stream(&bcg->out);
+ flush_stream(&broadcast_group->out);
}
static void event_context_exited(Context * ctx, void * client_data) {
- TCFBroadcastGroup * bcg = (TCFBroadcastGroup *)client_data;
-
assert(!ctx->stopped);
assert(!ctx->intercepted);
- if (ctx->pending_safe_event) check_safe_events(ctx);
- send_event_context_removed(&bcg->out, ctx);
- flush_stream(&bcg->out);
+ if (EXT(ctx)->pending_safe_event) check_safe_events(ctx);
+ send_event_context_removed(&broadcast_group->out, ctx);
+ flush_stream(&broadcast_group->out);
}
void ini_run_ctrl_service(Protocol * proto, TCFBroadcastGroup * bcg) {
@@ -914,7 +912,9 @@ void ini_run_ctrl_service(Protocol * proto, TCFBroadcastGroup * bcg) {
event_context_started,
event_context_changed
};
- add_context_event_listener(&listener, bcg);
+ broadcast_group = bcg;
+ add_context_event_listener(&listener, NULL);
+ context_extension_offset = context_extension(sizeof(ContextExtension));
add_command_handler(proto, RUN_CONTROL, "getContext", command_get_context);
add_command_handler(proto, RUN_CONTROL, "getChildren", command_get_children);
add_command_handler(proto, RUN_CONTROL, "getState", command_get_state);
diff --git a/services/runctrl.h b/services/runctrl.h
index 7964ef72..8746711e 100644
--- a/services/runctrl.h
+++ b/services/runctrl.h
@@ -67,11 +67,11 @@ extern int terminate_debug_context(Channel * c, Context * ctx);
/*
* Suspend (stop and intercept) debug context - thread or process.
* If "ctx" is a process, suspend all children.
- * RunControl.suspended event is sent if it was not sent berore.
+ * RunControl.suspended event is sent if it was not sent before.
* Returns 0 if no errors, otherwise returns -1 and sets errno.
* Note: this function is asynchronous, it returns before contexts are suspended.
*/
-extern int suspend_debug_context(TCFBroadcastGroup * bcg, Context * ctx);
+extern int suspend_debug_context(Context * ctx);
/*
* Initialize run control service.
diff --git a/services/stacktrace.c b/services/stacktrace.c
index f5ee9fca..9262805e 100644
--- a/services/stacktrace.c
+++ b/services/stacktrace.c
@@ -41,33 +41,37 @@
static const char * STACKTRACE = "StackTrace";
-struct StackTrace {
+typedef struct StackTrace {
ErrorReport * error;
+ int valid;
int frame_cnt;
int frame_max;
- struct StackFrame frames[1]; /* ordered bottom to top */
-};
+ StackFrame * frames; /* ordered bottom to top */
+} StackTrace;
-typedef struct StackTrace StackTrace;
+static size_t context_extension_offset = 0;
-static StackTrace * add_frame(StackTrace * stack_trace, StackFrame * frame) {
+#define EXT(ctx) ((StackTrace *)((char *)(ctx) + context_extension_offset))
+
+static void 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));
+ stack_trace->frame_max += 32;
+ stack_trace->frames = (StackFrame *)loc_realloc(stack_trace->frames,
+ stack_trace->frame_max * sizeof(StackFrame));
}
stack_trace->frames[stack_trace->frame_cnt++] = *frame;
- return stack_trace;
}
-static void free_stack_trace(StackTrace * stack_trace) {
+static void invalidate_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);
+ stack_trace->error = NULL;
+ stack_trace->frame_cnt = 0;
+ stack_trace->valid = 0;
}
#if defined(_WRS_KERNEL)
@@ -76,7 +80,6 @@ static void free_stack_trace(StackTrace * stack_trace) {
static Context * client_ctx;
static StackTrace * client_trace;
-static int frame_cnt;
static ContextAddress frame_rp;
static void vxworks_stack_trace_callback(
@@ -91,7 +94,7 @@ static void vxworks_stack_trace_callback(
StackFrame f;
memset(&f, 0, sizeof(f));
f.regs_size = client_ctx->regs_size;
- if (frame_cnt == 0) {
+ if (client_trace->frame_cnt == 0) {
f.is_top_frame = 1;
f.regs = client_ctx->regs;
f.mask = loc_alloc(f.regs_size);
@@ -104,22 +107,19 @@ static void vxworks_stack_trace_callback(
}
f.fp = (ContextAddress)args;
frame_rp = (ContextAddress)callAdrs;
- client_trace = add_frame(client_trace, &f);
- frame_cnt++;
+ add_frame(client_trace, &f);
}
-static StackTrace * trace_stack(Context * ctx, StackTrace * s) {
+static void 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 client_trace;
+ if (s->frame_cnt == 0) vxworks_stack_trace_callback(NULL, 0, 0, NULL, ctx->pid, 1);
}
#else
-static StackTrace * walk_frames(Context * ctx, StackTrace * stack_trace) {
+static void walk_frames(Context * ctx, StackTrace * stack_trace) {
int error = 0;
unsigned cnt = 0;
StackFrame frame;
@@ -155,7 +155,7 @@ static StackTrace * walk_frames(Context * ctx, StackTrace * stack_trace) {
loc_free(down.mask);
break;
}
- stack_trace = add_frame(stack_trace, &frame);
+ add_frame(stack_trace, &frame);
frame = down;
cnt++;
}
@@ -163,47 +163,38 @@ static StackTrace * walk_frames(Context * ctx, StackTrace * stack_trace) {
if (!frame.is_top_frame) loc_free(frame.regs);
loc_free(frame.mask);
- 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);
- }
+ if (get_error_code(error) == ERR_CACHE_MISS) {
+ invalidate_stack_trace(stack_trace);
+ }
+ else if (error) {
+ stack_trace->error = get_error_report(error);
}
- return stack_trace;
}
-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;
- }
+static void trace_stack(Context * ctx, StackTrace * s) {
+ int i;
+ walk_frames(ctx, s);
+ 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 s;
}
#endif
static StackTrace * create_stack_trace(Context * ctx) {
- 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;
- if (ctx->regs_error != NULL) {
- stack_trace->error = get_error_report(set_error_report_errno(ctx->regs_error));
- }
- else {
- stack_trace = trace_stack(ctx, stack_trace);
+ StackTrace * stack_trace = EXT(ctx);
+ if (!stack_trace->valid) {
+ stack_trace->frame_cnt = 0;
+ if (ctx->regs_error != NULL) {
+ stack_trace->error = get_error_report(set_error_report_errno(ctx->regs_error));
+ }
+ else {
+ trace_stack(ctx, stack_trace);
+ }
+ stack_trace->valid = 1;
}
- ctx->stack_trace = stack_trace;
return stack_trace;
}
@@ -298,10 +289,6 @@ static void command_get_context_cache_client(void * x) {
break;
}
s = create_stack_trace(d->ctx);
- if (s == NULL) {
- err = errno;
- break;
- }
if (s->error) {
err = set_error_report_errno(s->error);
break;
@@ -417,9 +404,6 @@ 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;
@@ -442,9 +426,6 @@ 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;
@@ -469,29 +450,33 @@ 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 == NULL || stack->error != NULL) return 0;
+ if (stack->error != NULL) return 0;
return frame == stack->frame_cnt - 1;
}
+static void flush_stack_trace(Context * ctx, void * args) {
+ invalidate_stack_trace(EXT(ctx));
+}
+
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;
- }
+ invalidate_stack_trace(EXT(ctx));
+ loc_free(EXT(ctx)->frames);
+ memset(EXT(ctx), 0, sizeof(StackTrace));
}
void ini_stack_trace_service(Protocol * proto, TCFBroadcastGroup * bcg) {
static ContextEventListener listener = {
NULL,
- delete_stack_trace,
- delete_stack_trace,
- delete_stack_trace,
+ flush_stack_trace,
+ flush_stack_trace,
+ flush_stack_trace,
+ flush_stack_trace,
delete_stack_trace
};
add_context_event_listener(&listener, bcg);
add_command_handler(proto, STACKTRACE, "getContext", command_get_context);
add_command_handler(proto, STACKTRACE, "getChildren", command_get_children);
+ context_extension_offset = context_extension(sizeof(StackTrace));
}
#endif
diff --git a/services/symbols_elf.c b/services/symbols_elf.c
index d0dd715b..4214eecb 100644
--- a/services/symbols_elf.c
+++ b/services/symbols_elf.c
@@ -637,7 +637,7 @@ int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
clear_trap(&trap);
}
else {
- error = trap.error;
+ frame->fp = 0;
}
}
if (error) {
diff --git a/services/symbols_proxy.c b/services/symbols_proxy.c
index cc200171..fa170314 100644
--- a/services/symbols_proxy.c
+++ b/services/symbols_proxy.c
@@ -32,6 +32,9 @@
#include "exceptions.h"
#include "stacktrace.h"
#include "symbols.h"
+#if ENABLE_RCBP_TEST
+# include "test.h"
+#endif
#define HASH_SIZE 101
@@ -215,7 +218,6 @@ static SymbolsCache * get_symbols_cache(void) {
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;
}
@@ -315,6 +317,11 @@ static void free_symbols_cache(SymbolsCache * syms) {
loc_free(syms);
}
+static Channel * get_channel(SymbolsCache * syms) {
+ if (!syms->service_available) str_exception(ERR_SYM_NOT_FOUND, "Symbols service not available");
+ return syms->channel;
+}
+
static void read_context_data(InputStream * inp, const char * name, void * args) {
char id[256];
SymInfoCache * s = (SymInfoCache *)args;
@@ -445,9 +452,35 @@ int find_symbol(Context * ctx, int frame, char * name, Symbol ** sym) {
}
}
+#if ENABLE_RCBP_TEST
+ if (f == NULL && !syms->service_available && ctx->parent == NULL) {
+ void * address = NULL;
+ int sym_class = 0;
+ if (find_test_symbol(ctx, name, &address, &sym_class) >= 0) {
+ SymInfoCache * s = (SymInfoCache *)loc_alloc_zero(sizeof(SymInfoCache));
+ f = (FindSymCache *)loc_alloc_zero(sizeof(FindSymCache));
+ list_add_first(&f->link_syms, syms->link_find + h);
+ f->pid = ctx->pid;
+ f->ip = ip;
+ f->name = loc_strdup(name);
+ f->id = loc_strdup(name);
+ s->magic = SYM_CACHE_MAGIC;
+ s->id = loc_strdup(name);
+ s->name = loc_strdup(name);
+ s->done_context = 1;
+ s->has_address = 1;
+ s->address = (ContextAddress)address;
+ s->sym_class = sym_class;
+ s->update_policy = UPDATE_ON_MEMORY_MAP_CHANGES;
+ s->owner_id = loc_strdup(ctx2id(ctx));
+ list_add_first(&s->link_syms, syms->link_sym + hash_sym_id(name));
+ list_init(&s->array_syms);
+ }
+ }
+#endif
+
if (f == NULL) {
- Channel * c = cache_channel();
- if (c == NULL) exception(ERR_SYM_NOT_FOUND);
+ Channel * c = get_channel(syms);
f = (FindSymCache *)loc_alloc_zero(sizeof(FindSymCache));
list_add_first(&f->link_syms, syms->link_find + h);
f->pid = ctx->pid;
@@ -547,8 +580,7 @@ int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * func,
}
if (f == NULL) {
- Channel * c = cache_channel();
- if (c == NULL) exception(ERR_SYM_NOT_FOUND);
+ Channel * c = get_channel(syms);
f = (ListSymCache *)loc_alloc_zero(sizeof(ListSymCache));
list_add_first(&f->link_syms, syms->link_list + h);
f->pid = ctx->pid;
@@ -1027,8 +1059,7 @@ int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
assert(f == NULL || f->pending == NULL);
if (f == NULL) {
- Channel * c = cache_channel();
- if (c == NULL) exception(ERR_SYM_NOT_FOUND);
+ Channel * c = get_channel(syms);
f = (StackFrameCache *)loc_alloc_zero(sizeof(StackFrameCache));
list_add_first(&f->link_syms, syms->link_frame + h);
f->mem = ctx->mem;
diff --git a/services/symbols_win32.c b/services/symbols_win32.c
index c6b505a4..a96e5e89 100644
--- a/services/symbols_win32.c
+++ b/services/symbols_win32.c
@@ -32,8 +32,11 @@
#include "symbols.h"
#include "stacktrace.h"
#include "windbgcache.h"
+#include "context-win32.h"
#include "trace.h"
-#include "test.h"
+#if ENABLE_RCBP_TEST
+# include "test.h"
+#endif
#define SYM_SEARCH_PATH ""
/* Path could contain "http://msdl.microsoft.com/download/symbols",
@@ -131,7 +134,7 @@ static int get_stack_frame(Context * ctx, int frame, IMAGEHLP_STACK_FRAME * stac
static int get_sym_info(const Symbol * sym, DWORD index, SYMBOL_INFO ** res) {
static ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
SYMBOL_INFO * info = (SYMBOL_INFO *)buffer;
- HANDLE process = sym->ctx->parent == NULL ? sym->ctx->handle : sym->ctx->parent->handle;
+ HANDLE process = get_context_handle(sym->ctx->parent == NULL ? sym->ctx : sym->ctx->parent);
info->SizeOfStruct = sizeof(SYMBOL_INFO);
info->MaxNameLen = MAX_SYM_NAME;
@@ -144,7 +147,7 @@ static int get_sym_info(const Symbol * sym, DWORD index, SYMBOL_INFO ** res) {
}
static int get_type_info(const Symbol * sym, int info_tag, void * info) {
- HANDLE process = sym->ctx->parent == NULL ? sym->ctx->handle : sym->ctx->parent->handle;
+ HANDLE process = get_context_handle(sym->ctx->parent == NULL ? sym->ctx : sym->ctx->parent);
if (!SymGetTypeInfo(process, sym->module, sym->index, info_tag, info)) {
set_win32_errno(GetLastError());
return -1;
@@ -811,9 +814,11 @@ static int find_pe_symbol(Context * ctx, int frame, char * name, Symbol * sym) {
ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)];
SYMBOL_INFO * info = (SYMBOL_INFO *)buffer;
IMAGEHLP_STACK_FRAME stack_frame;
- HANDLE process = ctx->parent == NULL ? ctx->handle : ctx->parent->handle;
+ HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent);
DWORD64 module;
+ if (frame == STACK_TOP_FRAME) frame = get_top_frame(ctx);
+ if (frame == STACK_TOP_FRAME) return -1;
if (get_stack_frame(ctx, frame, &stack_frame) < 0) return -1;
if (find_cache_symbol(process, stack_frame.InstructionOffset, name, sym)) return errno ? -1 : 0;
@@ -884,7 +889,13 @@ int find_symbol(Context * ctx, int frame, char * name, Symbol ** sym) {
(*sym)->ctx = ctx;
if (find_pe_symbol(ctx, frame, name, *sym) >= 0) return 0;
if (get_error_code(errno) != ERR_SYM_NOT_FOUND) return -1;
- if (find_test_symbol(ctx, name, &(*sym)->address, &(*sym)->sym_class) >= 0) return 0;
+#if ENABLE_RCBP_TEST
+ if (find_test_symbol(ctx, name, &(*sym)->address, &(*sym)->sym_class) >= 0) {
+ while (ctx->parent != NULL && ctx->parent->mem == ctx->mem) ctx = ctx->parent;
+ (*sym)->ctx = ctx;
+ return 0;
+ }
+#endif
if (find_basic_type_symbol(ctx, name, *sym) >= 0) return 0;
return -1;
}
@@ -909,7 +920,7 @@ int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_
SYMBOL_INFO * symbol = (SYMBOL_INFO *)buffer;
IMAGEHLP_STACK_FRAME stack_frame;
EnumerateSymbolsContext enum_context;
- HANDLE process = ctx->parent == NULL ? ctx->handle : ctx->parent->handle;
+ HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
@@ -958,12 +969,13 @@ int get_next_stack_frame(Context * ctx, StackFrame * frame, StackFrame * down) {
static void event_context_created(Context * ctx, void * client_data) {
if (ctx->parent != NULL) return;
assert(ctx->pid == ctx->mem);
- if (!SymInitialize(ctx->handle, SYM_SEARCH_PATH, FALSE)) {
+ if (!SymInitialize(get_context_handle(ctx), SYM_SEARCH_PATH, FALSE)) {
set_win32_errno(GetLastError());
trace(LOG_ALWAYS, "SymInitialize() error: %d: %s",
errno, errno_to_str(errno));
}
- if (!SymLoadModule64(ctx->handle, ctx->file_handle, NULL, NULL, ctx->base_address, 0)) {
+ if (!SymLoadModule64(get_context_handle(ctx), get_context_file_handle(ctx),
+ NULL, NULL, get_context_base_address(ctx), 0)) {
set_win32_errno(GetLastError());
trace(LOG_ALWAYS, "SymLoadModule() error: %d: %s",
errno, errno_to_str(errno));
@@ -972,6 +984,7 @@ static void event_context_created(Context * ctx, void * client_data) {
static void event_context_exited(Context * ctx, void * client_data) {
unsigned i;
+ HANDLE handle = get_context_handle(ctx);
for (i = 0; i < SYMBOL_CACHE_SIZE; i++) {
if (symbol_cache[i].sym.ctx == ctx) {
release_error_report(symbol_cache[i].error);
@@ -979,13 +992,13 @@ static void event_context_exited(Context * ctx, void * client_data) {
}
}
if (ctx->parent != NULL) return;
- assert(ctx->handle != NULL);
- if (!SymUnloadModule64(ctx->handle, ctx->base_address)) {
+ assert(handle != NULL);
+ if (!SymUnloadModule64(handle, get_context_base_address(ctx))) {
set_win32_errno(GetLastError());
trace(LOG_ALWAYS, "SymUnloadModule() error: %d: %s",
errno, errno_to_str(errno));
}
- if (!SymCleanup(ctx->handle)) {
+ if (!SymCleanup(handle)) {
set_win32_errno(GetLastError());
trace(LOG_ALWAYS, "SymCleanup() error: %d: %s",
errno, errno_to_str(errno));
@@ -993,27 +1006,29 @@ static void event_context_exited(Context * ctx, void * client_data) {
}
static void event_context_changed(Context * ctx, void * client_data) {
- if (ctx->module_loaded) {
+ HANDLE handle = get_context_handle(ctx);
+ if (is_context_module_loaded(ctx)) {
unsigned i;
assert(ctx->pid == ctx->mem);
- assert(ctx->handle != NULL);
- if (!SymLoadModule64(ctx->handle, ctx->module_handle, NULL, NULL, ctx->module_address, 0)) {
+ assert(handle != NULL);
+ if (!SymLoadModule64(handle, get_context_module_handle(ctx),
+ NULL, NULL, get_context_module_address(ctx), 0)) {
set_win32_errno(GetLastError());
trace(LOG_ALWAYS, "SymLoadModule() error: %d: %s",
errno, errno_to_str(errno));
}
for (i = 0; i < SYMBOL_CACHE_SIZE; i++) {
- if (symbol_cache[i].process == ctx->handle && symbol_cache[i].error) symbol_cache[i].process = NULL;
+ if (symbol_cache[i].process == handle && symbol_cache[i].error) symbol_cache[i].process = NULL;
}
}
- if (ctx->module_unloaded) {
+ if (is_context_module_unloaded(ctx)) {
unsigned i;
assert(ctx->pid == ctx->mem);
- assert(ctx->handle != NULL);
+ assert(handle != NULL);
for (i = 0; i < SYMBOL_CACHE_SIZE; i++) {
- if (symbol_cache[i].process == ctx->handle) symbol_cache[i].process = NULL;
+ if (symbol_cache[i].process == handle) symbol_cache[i].process = NULL;
}
- if (!SymUnloadModule64(ctx->handle, ctx->module_address)) {
+ if (!SymUnloadModule64(handle, get_context_module_address(ctx))) {
set_win32_errno(GetLastError());
trace(LOG_ALWAYS, "SymUnloadModule() error: %d: %s",
errno, errno_to_str(errno));
diff --git a/system/Darwin/context-darwin.c b/system/Darwin/context-darwin.c
index 709050a1..895203bb 100644
--- a/system/Darwin/context-darwin.c
+++ b/system/Darwin/context-darwin.c
@@ -42,14 +42,31 @@
#define WORD_SIZE 4
+typedef struct ContextExtension {
+ ContextAttachCallBack * attach_callback;
+ void * attach_data;
+ int ptrace_flags;
+ int ptrace_event;
+ int syscall_enter;
+ int syscall_exit;
+ int syscall_id;
+ ContextAddress syscall_pc;
+ ContextAddress loader_state;
+ int end_of_step;
+} ContextExtension;
+
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
+
static LINK pending_list;
const char * context_suspend_reason(Context * ctx) {
static char reason[128];
- if (ctx->end_of_step) return "Step";
- if (ctx->syscall_enter) return "System Call";
- if (ctx->syscall_exit) return "System Return";
+ if (EXT(ctx)->end_of_step) return "Step";
+ if (EXT(ctx)->syscall_enter) return "System Call";
+ if (EXT(ctx)->syscall_exit) return "System Return";
if (ctx->signal == SIGSTOP || ctx->signal == SIGTRAP) {
return "Suspended";
}
@@ -88,8 +105,8 @@ int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int sel
add_waitpid_process(pid);
ctx = create_context(pid, 0);
ctx->mem = pid;
- ctx->attach_callback = done;
- ctx->attach_data = data;
+ EXT(ctx)->attach_callback = done;
+ EXT(ctx)->attach_data = data;
list_add_first(&ctx->ctxl, &pending_list);
/* TODO: context_attach works only for main task in a process */
return 0;
@@ -120,8 +137,8 @@ int context_stop(Context * ctx) {
}
static int syscall_never_returns(Context * ctx) {
- if (ctx->syscall_enter) {
- switch (ctx->syscall_id) {
+ if (EXT(ctx)->syscall_enter) {
+ switch (EXT(ctx)->syscall_id) {
case SYS_sigreturn:
return 1;
}
@@ -140,7 +157,7 @@ int context_continue(Context * ctx) {
if (skip_breakpoint(ctx, 0)) return 0;
- if (!ctx->syscall_enter) {
+ if (!EXT(ctx)->syscall_enter) {
while (ctx->pending_signals != 0) {
while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
if (ctx->sig_dont_pass & (1 << signal)) {
@@ -156,11 +173,16 @@ int context_continue(Context * ctx) {
}
trace(LOG_CONTEXT, "context: resuming ctx %#lx, pid %d, with signal %d", ctx, ctx->pid, signal);
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__)
if (((REG_SET *)ctx->regs)->__eflags & 0x100) {
((REG_SET *)ctx->regs)->__eflags &= ~0x100;
ctx->regs_dirty = 1;
}
+#elif defined(__x86_64__)
+ if (((REG_SET *)ctx->regs)->__rflags & 0x100) {
+ ((REG_SET *)ctx->regs)->__rflags &= ~0x100;
+ ctx->regs_dirty = 1;
+ }
#endif
if (ctx->regs_dirty) {
unsigned int state_count;
@@ -188,9 +210,9 @@ int context_continue(Context * ctx) {
}
ctx->pending_signals &= ~(1 << signal);
if (syscall_never_returns(ctx)) {
- ctx->syscall_enter = 0;
- ctx->syscall_exit = 0;
- ctx->syscall_id = 0;
+ EXT(ctx)->syscall_enter = 0;
+ EXT(ctx)->syscall_exit = 0;
+ EXT(ctx)->syscall_id = 0;
}
send_context_started_event(ctx);
return 0;
@@ -342,9 +364,9 @@ static void event_pid_exited(pid_t pid, int status, int signal) {
}
else {
assert(ctx->ref_count == 0);
- if (ctx->attach_callback != NULL) {
+ if (EXT(ctx)->attach_callback != NULL) {
if (status == 0) status = EINVAL;
- ctx->attach_callback(status, ctx, ctx->attach_data);
+ EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data);
}
assert(list_is_empty(&ctx->children));
assert(ctx->parent == NULL);
@@ -354,7 +376,7 @@ static void event_pid_exited(pid_t pid, int status, int signal) {
}
else {
if (ctx->parent->pid == ctx->pid) ctx = ctx->parent;
- assert(ctx->attach_callback == NULL);
+ assert(EXT(ctx)->attach_callback == NULL);
if (ctx->stopped || ctx->intercepted || ctx->exited) {
trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d unexpected, stopped %d, intercepted %d, exited %d",
ctx, pid, status, ctx->stopped, ctx->intercepted, ctx->exited);
@@ -401,10 +423,10 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
link_context(ctx);
send_context_created_event(prs);
send_context_created_event(ctx);
- if (prs->attach_callback) {
- prs->attach_callback(0, prs, prs->attach_data);
- prs->attach_callback = NULL;
- prs->attach_data = NULL;
+ if (EXT(prs)->attach_callback) {
+ EXT(prs)->attach_callback(0, prs, EXT(prs)->attach_data);
+ EXT(prs)->attach_callback = NULL;
+ EXT(prs)->attach_data = NULL;
}
}
}
@@ -412,7 +434,7 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
if (ctx == NULL) return;
assert(!ctx->exited);
- assert(!ctx->attach_callback);
+ assert(!EXT(ctx)->attach_callback);
if (signal != SIGSTOP && signal != SIGTRAP) {
assert(signal < 32);
@@ -443,11 +465,11 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
ctx->pid, errno, errno_to_str(errno));
}
- if (!ctx->syscall_enter || ctx->regs_error || pc0 != get_regs_PC(ctx->regs)) {
- ctx->syscall_enter = 0;
- ctx->syscall_exit = 0;
- ctx->syscall_id = 0;
- ctx->syscall_pc = 0;
+ if (!EXT(ctx)->syscall_enter || ctx->regs_error || pc0 != get_regs_PC(ctx->regs)) {
+ EXT(ctx)->syscall_enter = 0;
+ EXT(ctx)->syscall_exit = 0;
+ EXT(ctx)->syscall_id = 0;
+ EXT(ctx)->syscall_pc = 0;
}
trace(LOG_EVENTS, "event: pid %d stopped at PC = %#lx", ctx->pid, get_regs_PC(ctx->regs));
@@ -457,15 +479,15 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
}
else {
ctx->signal = signal;
- ctx->ptrace_event = event;
+ EXT(ctx)->ptrace_event = event;
ctx->stopped = 1;
ctx->stopped_by_bp = 0;
ctx->stopped_by_exception = stopped_by_exception;
- ctx->end_of_step = 0;
+ EXT(ctx)->end_of_step = 0;
if (signal == SIGTRAP && event == 0 && !syscall) {
ctx->stopped_by_bp = !ctx->regs_error &&
is_breakpoint_address(ctx, get_regs_PC(ctx->regs) - BREAK_SIZE);
- ctx->end_of_step = !ctx->stopped_by_bp && ctx->pending_step;
+ EXT(ctx)->end_of_step = !ctx->stopped_by_bp && ctx->pending_step;
}
ctx->pending_step = 0;
if (ctx->stopped_by_bp) {
@@ -488,6 +510,7 @@ static void waitpid_listener(int pid, int exited, int exit_code, int signal, int
void init_contexts_sys_dep(void) {
list_init(&pending_list);
+ context_extension_offset = context_extension(sizeof(ContextExtension));
add_waitpid_listener(waitpid_listener, NULL);
}
diff --git a/system/Darwin/regset.h b/system/Darwin/regset.h
index 5fbb011f..ea0fd27c 100644
--- a/system/Darwin/regset.h
+++ b/system/Darwin/regset.h
@@ -23,7 +23,11 @@ extern "C" {
#if defined(__APPLE__)
# include <mach/thread_status.h>
- typedef x86_thread_state32_t REG_SET;
+# if defined(__i386__)
+ typedef x86_thread_state32_t REG_SET;
+# else
+ typedef x86_thread_state64_t REG_SET;
+# endif
#endif
#ifdef __cplusplus
diff --git a/system/FreeBSD/context-freebsd.c b/system/FreeBSD/context-freebsd.c
index 4d36afbe..87fb9e74 100644
--- a/system/FreeBSD/context-freebsd.c
+++ b/system/FreeBSD/context-freebsd.c
@@ -50,6 +50,23 @@
#define USE_ESRCH_WORKAROUND 1
#define USE_PTRACE_SYSCALL 0
+typedef struct ContextExtension {
+ ContextAttachCallBack * attach_callback;
+ void * attach_data;
+ int ptrace_flags;
+ int ptrace_event;
+ int syscall_enter;
+ int syscall_exit;
+ int syscall_id;
+ ContextAddress syscall_pc;
+ ContextAddress loader_state;
+ int end_of_step;
+} ContextExtension;
+
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
+
static LINK pending_list;
static char * event_name(int event) {
@@ -60,10 +77,10 @@ static char * event_name(int event) {
const char * context_suspend_reason(Context * ctx) {
static char reason[128];
- if (ctx->end_of_step) return "Step";
- if (ctx->ptrace_event != 0) {
+ if (EXT(ctx)->end_of_step) return "Step";
+ if (EXT(ctx)->ptrace_event != 0) {
assert(ctx->signal == SIGTRAP);
- snprintf(reason, sizeof(reason), "Event: %s", event_name(ctx->ptrace_event));
+ snprintf(reason, sizeof(reason), "Event: %s", event_name(EXT(ctx)->ptrace_event));
return reason;
}
if (ctx->signal == SIGSTOP || ctx->signal == SIGTRAP) {
@@ -104,8 +121,8 @@ int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int sel
add_waitpid_process(pid);
ctx = create_context(pid, 0);
ctx->mem = pid;
- ctx->attach_callback = done;
- ctx->attach_data = data;
+ EXT(ctx)->attach_callback = done;
+ EXT(ctx)->attach_data = data;
list_add_first(&ctx->ctxl, &pending_list);
/* TODO: context_attach works only for main task in a process */
return 0;
@@ -146,7 +163,7 @@ int context_continue(Context * ctx) {
if (skip_breakpoint(ctx, 0)) return 0;
- if (!ctx->ptrace_event) {
+ if (!EXT(ctx)->ptrace_event) {
while (ctx->pending_signals != 0) {
while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
if (ctx->sig_dont_pass & (1 << signal)) {
@@ -342,9 +359,9 @@ static void event_pid_exited(pid_t pid, int status, int signal) {
}
else {
assert(ctx->ref_count == 0);
- if (ctx->attach_callback != NULL) {
+ if (EXT(ctx)->attach_callback != NULL) {
if (status == 0) status = EINVAL;
- ctx->attach_callback(status, ctx, ctx->attach_data);
+ EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data);
}
assert(list_is_empty(&ctx->children));
assert(ctx->parent == NULL);
@@ -354,7 +371,7 @@ static void event_pid_exited(pid_t pid, int status, int signal) {
}
else {
if (ctx->parent->pid == ctx->pid) ctx = ctx->parent;
- assert(ctx->attach_callback == NULL);
+ assert(EXT(ctx)->attach_callback == NULL);
if (ctx->stopped || ctx->intercepted || ctx->exited) {
trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d unexpected, stopped %d, intercepted %d, exited %d",
ctx, pid, status, ctx->stopped, ctx->intercepted, ctx->exited);
@@ -399,10 +416,10 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
link_context(ctx);
send_context_created_event(prs);
send_context_created_event(ctx);
- if (prs->attach_callback) {
- prs->attach_callback(0, prs, prs->attach_data);
- prs->attach_callback = NULL;
- prs->attach_data = NULL;
+ if (EXT(prs)->attach_callback) {
+ EXT(prs)->attach_callback(0, prs, EXT(prs)->attach_data);
+ EXT(prs)->attach_callback = NULL;
+ EXT(prs)->attach_data = NULL;
}
}
}
@@ -410,7 +427,7 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
if (ctx == NULL) return;
assert(!ctx->exited);
- assert(!ctx->attach_callback);
+ assert(!EXT(ctx)->attach_callback);
if (signal != SIGSTOP && signal != SIGTRAP) {
assert(signal < 32);
@@ -460,15 +477,15 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
}
else {
ctx->signal = signal;
- ctx->ptrace_event = event;
+ EXT(ctx)->ptrace_event = event;
ctx->stopped = 1;
ctx->stopped_by_bp = 0;
ctx->stopped_by_exception = stopped_by_exception;
- ctx->end_of_step = 0;
+ EXT(ctx)->end_of_step = 0;
if (signal == SIGTRAP && event == 0 && !syscall) {
ctx->stopped_by_bp = !ctx->regs_error &&
is_breakpoint_address(ctx, get_regs_PC(ctx->regs) - BREAK_SIZE);
- ctx->end_of_step = !ctx->stopped_by_bp && ctx->pending_step;
+ EXT(ctx)->end_of_step = !ctx->stopped_by_bp && ctx->pending_step;
}
ctx->pending_step = 0;
if (ctx->stopped_by_bp) {
@@ -491,6 +508,7 @@ static void waitpid_listener(int pid, int exited, int exit_code, int signal, int
void init_contexts_sys_dep(void) {
list_init(&pending_list);
+ context_extension_offset = context_extension(sizeof(ContextExtension));
add_waitpid_listener(waitpid_listener, NULL);
}
diff --git a/system/GNU/Linux/context-linux.c b/system/GNU/Linux/context-linux.c
index 77f334f3..aa0e181e 100644
--- a/system/GNU/Linux/context-linux.c
+++ b/system/GNU/Linux/context-linux.c
@@ -86,6 +86,23 @@
PTRACE_O_TRACEEXIT)
#endif
+typedef struct ContextExtension {
+ ContextAttachCallBack * attach_callback;
+ void * attach_data;
+ int ptrace_flags;
+ int ptrace_event;
+ int syscall_enter;
+ int syscall_exit;
+ int syscall_id;
+ ContextAddress syscall_pc;
+ ContextAddress loader_state;
+ int end_of_step;
+} ContextExtension;
+
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
+
static LINK pending_list;
static const char * event_name(int event) {
@@ -105,14 +122,14 @@ static const char * event_name(int event) {
const char * context_suspend_reason(Context * ctx) {
static char reason[128];
- if (ctx->end_of_step) return "Step";
- if (ctx->ptrace_event != 0) {
+ if (EXT(ctx)->end_of_step) return "Step";
+ if (EXT(ctx)->ptrace_event != 0) {
assert(ctx->signal == SIGTRAP);
- snprintf(reason, sizeof(reason), "Event: %s", event_name(ctx->ptrace_event));
+ snprintf(reason, sizeof(reason), "Event: %s", event_name(EXT(ctx)->ptrace_event));
return reason;
}
- if (ctx->syscall_enter) return "System Call";
- if (ctx->syscall_exit) return "System Return";
+ if (EXT(ctx)->syscall_enter) return "System Call";
+ if (EXT(ctx)->syscall_exit) return "System Return";
if (ctx->signal == SIGSTOP || ctx->signal == SIGTRAP) {
return "Suspended";
}
@@ -151,8 +168,8 @@ int context_attach(pid_t pid, ContextAttachCallBack * done, void * data, int sel
add_waitpid_process(pid);
ctx = create_context(pid, 0);
ctx->mem = pid;
- ctx->attach_callback = done;
- ctx->attach_data = data;
+ EXT(ctx)->attach_callback = done;
+ EXT(ctx)->attach_data = data;
list_add_first(&ctx->ctxl, &pending_list);
/* TODO: context_attach works only for main task in a process */
return 0;
@@ -183,8 +200,8 @@ int context_stop(Context * ctx) {
}
static int syscall_never_returns(Context * ctx) {
- if (ctx->syscall_enter) {
- switch (ctx->syscall_id) {
+ if (EXT(ctx)->syscall_enter) {
+ switch (EXT(ctx)->syscall_id) {
#ifdef __NR_sigreturn
case __NR_sigreturn:
return 1;
@@ -205,7 +222,7 @@ int context_continue(Context * ctx) {
if (skip_breakpoint(ctx, 0)) return 0;
- if (!ctx->syscall_enter && !ctx->ptrace_event) {
+ if (!EXT(ctx)->syscall_enter && !EXT(ctx)->ptrace_event) {
while (ctx->pending_signals != 0) {
while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
if (ctx->sig_dont_pass & (1 << signal)) {
@@ -263,9 +280,9 @@ int context_continue(Context * ctx) {
}
ctx->pending_signals &= ~(1 << signal);
if (syscall_never_returns(ctx)) {
- ctx->syscall_enter = 0;
- ctx->syscall_exit = 0;
- ctx->syscall_id = 0;
+ EXT(ctx)->syscall_enter = 0;
+ EXT(ctx)->syscall_exit = 0;
+ EXT(ctx)->syscall_id = 0;
}
send_context_started_event(ctx);
return 0;
@@ -417,9 +434,9 @@ static void event_pid_exited(pid_t pid, int status, int signal) {
}
else {
assert(ctx->ref_count == 0);
- if (ctx->attach_callback != NULL) {
+ if (EXT(ctx)->attach_callback != NULL) {
if (status == 0) status = EINVAL;
- ctx->attach_callback(status, ctx, ctx->attach_data);
+ EXT(ctx)->attach_callback(status, ctx, EXT(ctx)->attach_data);
}
assert(list_is_empty(&ctx->children));
assert(ctx->parent == NULL);
@@ -429,7 +446,7 @@ static void event_pid_exited(pid_t pid, int status, int signal) {
}
else {
if (ctx->parent->pid == ctx->pid) ctx = ctx->parent;
- assert(ctx->attach_callback == NULL);
+ assert(EXT(ctx)->attach_callback == NULL);
if (ctx->stopped || ctx->intercepted || ctx->exited) {
trace(LOG_EVENTS, "event: ctx %#lx, pid %d, exit status %d unexpected, stopped %d, intercepted %d, exited %d",
ctx, pid, status, ctx->stopped, ctx->intercepted, ctx->exited);
@@ -489,10 +506,10 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
link_context(ctx);
send_context_created_event(prs);
send_context_created_event(ctx);
- if (prs->attach_callback) {
- prs->attach_callback(0, prs, prs->attach_data);
- prs->attach_callback = NULL;
- prs->attach_data = NULL;
+ if (EXT(prs)->attach_callback) {
+ EXT(prs)->attach_callback(0, prs, EXT(prs)->attach_data);
+ EXT(prs)->attach_callback = NULL;
+ EXT(prs)->attach_data = NULL;
}
}
}
@@ -500,15 +517,15 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
if (ctx == NULL) return;
assert(!ctx->exited);
- assert(!ctx->attach_callback);
- if (ctx->ptrace_flags != PTRACE_FLAGS) {
+ assert(!EXT(ctx)->attach_callback);
+ if (EXT(ctx)->ptrace_flags != PTRACE_FLAGS) {
if (ptrace((enum __ptrace_request)PTRACE_SETOPTIONS, ctx->pid, 0, PTRACE_FLAGS) < 0) {
int err = errno;
trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETOPTIONS) failed: pid %d, error %d %s",
ctx->pid, err, errno_to_str(err));
}
else {
- ctx->ptrace_flags = PTRACE_FLAGS;
+ EXT(ctx)->ptrace_flags = PTRACE_FLAGS;
}
}
@@ -595,22 +612,22 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
}
if (syscall && !ctx->regs_error) {
- if (!ctx->syscall_enter) {
- ctx->syscall_id = get_syscall_id(ctx);
- ctx->syscall_pc = get_regs_PC(ctx->regs);
- ctx->syscall_enter = 1;
- ctx->syscall_exit = 0;
+ if (!EXT(ctx)->syscall_enter) {
+ EXT(ctx)->syscall_id = get_syscall_id(ctx);
+ EXT(ctx)->syscall_pc = get_regs_PC(ctx->regs);
+ EXT(ctx)->syscall_enter = 1;
+ EXT(ctx)->syscall_exit = 0;
trace(LOG_EVENTS, "event: pid %d enter sys call %d, PC = %#lx",
- ctx->pid, ctx->syscall_id, ctx->syscall_pc);
+ ctx->pid, EXT(ctx)->syscall_id, EXT(ctx)->syscall_pc);
}
else {
- if (ctx->syscall_pc != get_regs_PC(ctx->regs)) {
+ if (EXT(ctx)->syscall_pc != get_regs_PC(ctx->regs)) {
trace(LOG_ALWAYS, "Invalid PC at sys call exit: pid %d, sys call %d, PC %#lx, expected PC %#lx",
- ctx->pid, ctx->syscall_id, get_regs_PC(ctx->regs), ctx->syscall_pc);
+ ctx->pid, EXT(ctx)->syscall_id, get_regs_PC(ctx->regs), EXT(ctx)->syscall_pc);
}
trace(LOG_EVENTS, "event: pid %d exit sys call %d, PC = %#lx",
- ctx->pid, ctx->syscall_id, get_regs_PC(ctx->regs));
- switch (ctx->syscall_id) {
+ ctx->pid, EXT(ctx)->syscall_id, get_regs_PC(ctx->regs));
+ switch (EXT(ctx)->syscall_id) {
case __NR_mmap:
case __NR_munmap:
#ifdef __NR_mmap2
@@ -621,16 +638,16 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
send_context_changed_event(ctx);
break;
}
- ctx->syscall_enter = 0;
- ctx->syscall_exit = 1;
+ EXT(ctx)->syscall_enter = 0;
+ EXT(ctx)->syscall_exit = 1;
}
}
else {
- if (!ctx->syscall_enter || ctx->regs_error || pc0 != get_regs_PC(ctx->regs)) {
- ctx->syscall_enter = 0;
- ctx->syscall_exit = 0;
- ctx->syscall_id = 0;
- ctx->syscall_pc = 0;
+ if (!EXT(ctx)->syscall_enter || ctx->regs_error || pc0 != get_regs_PC(ctx->regs)) {
+ EXT(ctx)->syscall_enter = 0;
+ EXT(ctx)->syscall_exit = 0;
+ EXT(ctx)->syscall_id = 0;
+ EXT(ctx)->syscall_pc = 0;
}
trace(LOG_EVENTS, "event: pid %d stopped at PC = %#lx", ctx->pid, get_regs_PC(ctx->regs));
}
@@ -641,15 +658,15 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) {
}
else {
ctx->signal = signal;
- ctx->ptrace_event = event;
+ EXT(ctx)->ptrace_event = event;
ctx->stopped = 1;
ctx->stopped_by_bp = 0;
ctx->stopped_by_exception = stopped_by_exception;
- ctx->end_of_step = 0;
+ EXT(ctx)->end_of_step = 0;
if (signal == SIGTRAP && event == 0 && !syscall) {
ctx->stopped_by_bp = !ctx->regs_error &&
is_breakpoint_address(ctx, get_regs_PC(ctx->regs) - BREAK_SIZE);
- ctx->end_of_step = !ctx->stopped_by_bp && ctx->pending_step;
+ EXT(ctx)->end_of_step = !ctx->stopped_by_bp && ctx->pending_step;
}
ctx->pending_step = 0;
if (ctx->stopped_by_bp) {
@@ -727,17 +744,17 @@ static void eventpoint_at_loader(Context * ctx, void * args) {
int error = errno;
trace(LOG_ALWAYS, "Can't read loader state flag: %d %s", error, errno_to_str(error));
ctx->pending_intercept = 1;
- ctx->loader_state = 0;
+ EXT(ctx)->loader_state = 0;
return;
}
}
switch (state) {
case RT_CONSISTENT:
- if (ctx->loader_state == RT_ADD) {
+ if (EXT(ctx)->loader_state == RT_ADD) {
memory_map_event_module_loaded(ctx);
}
- else if (ctx->loader_state == RT_DELETE) {
+ else if (EXT(ctx)->loader_state == RT_DELETE) {
memory_map_event_module_unloaded(ctx);
}
break;
@@ -747,13 +764,14 @@ static void eventpoint_at_loader(Context * ctx, void * args) {
/* TODO: need to call memory_map_event_code_section_ummapped() */
break;
}
- ctx->loader_state = state;
+ EXT(ctx)->loader_state = state;
}
#endif /* SERVICE_Expressions && ENABLE_ELF */
void init_contexts_sys_dep(void) {
list_init(&pending_list);
+ context_extension_offset = context_extension(sizeof(ContextExtension));
add_waitpid_listener(waitpid_listener, NULL);
#if SERVICE_Expressions && ENABLE_ELF
add_identifier_callback(expression_identifier_callback);
diff --git a/system/VxWorks/context-vxworks.c b/system/VxWorks/context-vxworks.c
index bf17b857..99052fe6 100644
--- a/system/VxWorks/context-vxworks.c
+++ b/system/VxWorks/context-vxworks.c
@@ -26,7 +26,7 @@
#include <assert.h>
#include <errno.h>
#include <signal.h>
-#include "context.h"
+#include "context-vxworks.h"
#include "events.h"
#include "errors.h"
#include "trace.h"
@@ -42,6 +42,16 @@
#define TRACE_EVENT_STEP 2
+typedef struct ContextExtension {
+ VXDBG_BP_INFO bp_info; /* breakpoint information */
+ pid_t bp_pid; /* process or thread that hit breakpoint */
+ int event;
+} ContextExtension;
+
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
+
#define EVENT_HOOK_BREAKPOINT 2
#define EVENT_HOOK_STEP_DONE 3
#define EVENT_HOOK_STOP 4
@@ -70,7 +80,7 @@ static SEM_ID events_signal;
static pthread_t events_thread;
const char * context_suspend_reason(Context * ctx) {
- if (ctx->event == TRACE_EVENT_STEP) return "Step";
+ if (EXT(ctx)->event == TRACE_EVENT_STEP) return "Step";
return "Suspended";
}
@@ -346,7 +356,7 @@ static void event_handler(void * arg) {
memcpy(stopped_ctx->regs, &info->regs, stopped_ctx->regs_size);
stopped_ctx->signal = SIGTRAP;
assert(get_regs_PC(stopped_ctx->regs) == info->addr);
- stopped_ctx->event = 0;
+ EXT(stopped_ctx)->event = 0;
stopped_ctx->pending_step = 0;
stopped_ctx->stopped = 1;
stopped_ctx->stopped_by_bp = info->bp_info_ok;
@@ -356,8 +366,8 @@ static void event_handler(void * arg) {
stopped_ctx->stopped_by_bp = 0;
stopped_ctx->pending_intercept = 1;
}
- stopped_ctx->bp_info = info->bp_info;
- if (current_ctx != NULL) stopped_ctx->bp_pid = current_ctx->pid;
+ EXT(stopped_ctx)->bp_info = info->bp_info;
+ if (current_ctx != NULL) EXT(stopped_ctx)->bp_pid = current_ctx->pid;
assert(taskIsStopped(stopped_ctx->pid));
trace(LOG_CONTEXT, "context: stopped by breakpoint: ctx %#lx, id %#x",
stopped_ctx, stopped_ctx->pid);
@@ -373,8 +383,8 @@ static void event_handler(void * arg) {
current_ctx->regs_error = NULL;
}
memcpy(current_ctx->regs, &info->regs, current_ctx->regs_size);
+ EXT(current_ctx)->event = TRACE_EVENT_STEP;
current_ctx->signal = SIGTRAP;
- current_ctx->event = TRACE_EVENT_STEP;
current_ctx->pending_step = 0;
current_ctx->stopped = 1;
current_ctx->stopped_by_bp = 0;
@@ -395,8 +405,8 @@ static void event_handler(void * arg) {
stopped_ctx->regs_error = get_error_report(errno);
assert(stopped_ctx->regs_error != NULL);
}
+ EXT(stopped_ctx)->event = 0;
stopped_ctx->signal = SIGSTOP;
- stopped_ctx->event = 0;
stopped_ctx->pending_step = 0;
stopped_ctx->stopped = 1;
stopped_ctx->stopped_by_bp = 0;
@@ -515,6 +525,7 @@ void init_contexts_sys_dep(void) {
if (vxdbg_clnt_id == NULL) {
check_error(errno);
}
+ context_extension_offset = context_extension(sizeof(ContextExtension));
taskCreateHookAdd((FUNCPTR)task_create_hook);
vxdbgHookAdd(vxdbg_clnt_id, EVT_BP, vxdbg_event_hook);
vxdbgHookAdd(vxdbg_clnt_id, EVT_TRACE, vxdbg_event_hook);
diff --git a/system/VxWorks/context-vxworks.h b/system/VxWorks/context-vxworks.h
new file mode 100644
index 00000000..42787a8b
--- /dev/null
+++ b/system/VxWorks/context-vxworks.h
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * This module handles process/thread OS contexts and their state machine.
+ */
+
+#ifndef D_context_vxworks
+#define D_context_vxworks
+
+#include "config.h"
+#include "context.h"
+
+extern VXDBG_CLNT_ID vxdbg_clnt_id;
+
+#endif /* D_context_vxworks */
diff --git a/system/Windows/context-win32.c b/system/Windows/context-win32.c
index 93d4c476..2068a11d 100644
--- a/system/Windows/context-win32.c
+++ b/system/Windows/context-win32.c
@@ -35,6 +35,25 @@
#include "waitpid.h"
#include "regset.h"
#include "signames.h"
+#include "context-win32.h"
+
+typedef struct ContextExtension {
+ HANDLE handle;
+ HANDLE file_handle;
+ DWORD64 base_address;
+ int module_loaded;
+ int module_unloaded;
+ HANDLE module_handle;
+ DWORD64 module_address;
+ int debug_started;
+ EXCEPTION_DEBUG_INFO pending_event;
+ EXCEPTION_DEBUG_INFO suspend_reason;
+ int context_stopped_async_pending;
+} ContextExtension;
+
+static size_t context_extension_offset = 0;
+
+#define EXT(ctx) ((ContextExtension *)((char *)(ctx) + context_extension_offset))
typedef struct DebugThreadArgs {
int error;
@@ -58,12 +77,12 @@ typedef struct DebugEvent {
#define EXCEPTION_DEBUGGER_IO 0x406D1388
const char * context_suspend_reason(Context * ctx) {
- DWORD exception_code = ctx->suspend_reason.ExceptionRecord.ExceptionCode;
+ DWORD exception_code = EXT(ctx)->suspend_reason.ExceptionRecord.ExceptionCode;
const char * desc = NULL;
static char buf[64];
if (exception_code == 0) return "Suspended";
- if (ctx->debug_started && exception_code == EXCEPTION_BREAKPOINT) return "Suspended";
+ if (EXT(ctx)->debug_started && exception_code == EXCEPTION_BREAKPOINT) return "Suspended";
if (exception_code == EXCEPTION_SINGLE_STEP) return "Step";
desc = signal_description(get_signal_from_code(exception_code));
@@ -74,10 +93,10 @@ const char * context_suspend_reason(Context * ctx) {
}
static int get_signal_index(Context * ctx) {
- DWORD exception_code = ctx->suspend_reason.ExceptionRecord.ExceptionCode;
+ DWORD exception_code = EXT(ctx)->suspend_reason.ExceptionRecord.ExceptionCode;
if (exception_code == 0) return 0;
- if (ctx->debug_started && exception_code == EXCEPTION_BREAKPOINT) return 0;
+ if (EXT(ctx)->debug_started && exception_code == EXCEPTION_BREAKPOINT) return 0;
return get_signal_from_code(exception_code);
}
@@ -114,20 +133,20 @@ static int log_error(char * fn, int ok) {
static void event_win32_context_exited(Context * ctx);
static void event_win32_context_stopped(Context * ctx) {
- DWORD exception_code = ctx->pending_event.ExceptionRecord.ExceptionCode;
+ DWORD exception_code = EXT(ctx)->pending_event.ExceptionRecord.ExceptionCode;
if (ctx->exited || ctx->stopped && exception_code == 0) return;
- memcpy(&ctx->suspend_reason, &ctx->pending_event, sizeof(EXCEPTION_DEBUG_INFO));
- memset(&ctx->pending_event, 0, sizeof(EXCEPTION_DEBUG_INFO));
+ memcpy(&EXT(ctx)->suspend_reason, &EXT(ctx)->pending_event, sizeof(EXCEPTION_DEBUG_INFO));
+ memset(&EXT(ctx)->pending_event, 0, sizeof(EXCEPTION_DEBUG_INFO));
trace(LOG_CONTEXT, "context: stopped: ctx %#lx, pid %d, exception %#lx",
ctx, ctx->pid, exception_code);
assert(is_dispatch_thread());
assert(!ctx->stopped);
- assert(ctx->handle != NULL);
+ assert(EXT(ctx)->handle != NULL);
assert(ctx->parent != NULL);
- if (SuspendThread(ctx->handle) == (DWORD)-1) {
+ if (SuspendThread(EXT(ctx)->handle) == (DWORD)-1) {
DWORD err = GetLastError();
if (err == ERROR_ACCESS_DENIED && exception_code == 0) {
/* Already exited */
@@ -144,7 +163,7 @@ static void event_win32_context_stopped(Context * ctx) {
}
memset(ctx->regs, 0, ctx->regs_size);
((REG_SET *)ctx->regs)->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
- if (GetThreadContext(ctx->handle, (REG_SET *)ctx->regs) == 0) {
+ if (GetThreadContext(EXT(ctx)->handle, (REG_SET *)ctx->regs) == 0) {
ctx->regs_error = get_error_report(log_error("GetThreadContext", 0));
}
else {
@@ -174,7 +193,7 @@ static void event_win32_context_stopped(Context * ctx) {
break;
case EXCEPTION_DEBUGGER_IO:
trace(LOG_ALWAYS, "Debugger IO request %#lx",
- ctx->suspend_reason.ExceptionRecord.ExceptionInformation[0]);
+ EXT(ctx)->suspend_reason.ExceptionRecord.ExceptionInformation[0]);
break;
default:
ctx->pending_signals |= 1 << ctx->signal;
@@ -189,16 +208,16 @@ static void event_win32_context_stopped(Context * ctx) {
static void event_win32_context_stopped_async(void * arg) {
Context * ctx = (Context *)arg;
- ctx->context_stopped_async_pending = 0;
+ EXT(ctx)->context_stopped_async_pending = 0;
event_win32_context_stopped(ctx);
context_unlock(ctx);
}
static void event_win32_context_started(Context * ctx) {
- DWORD exception_code = ctx->suspend_reason.ExceptionRecord.ExceptionCode;
+ DWORD exception_code = EXT(ctx)->suspend_reason.ExceptionRecord.ExceptionCode;
trace(LOG_CONTEXT, "context: started: ctx %#lx, pid %d", ctx, ctx->pid);
assert(ctx->stopped);
- if (ctx->debug_started && exception_code == EXCEPTION_BREAKPOINT) ctx->debug_started = 0;
+ if (EXT(ctx)->debug_started && exception_code == EXCEPTION_BREAKPOINT) EXT(ctx)->debug_started = 0;
send_context_started_event(ctx);
}
@@ -214,33 +233,33 @@ static void event_win32_context_exited(Context * ctx) {
}
context_lock(ctx);
send_context_exited_event(ctx);
- if (ctx->handle != NULL) {
+ if (EXT(ctx)->handle != NULL) {
if (ctx->mem == ctx->pid) {
- log_error("CloseHandle", CloseHandle(ctx->handle));
+ log_error("CloseHandle", CloseHandle(EXT(ctx)->handle));
}
- ctx->handle = NULL;
+ EXT(ctx)->handle = NULL;
}
- if (ctx->file_handle != NULL) {
- log_error("CloseHandle", CloseHandle(ctx->file_handle));
- ctx->file_handle = NULL;
+ if (EXT(ctx)->file_handle != NULL) {
+ log_error("CloseHandle", CloseHandle(EXT(ctx)->file_handle));
+ EXT(ctx)->file_handle = NULL;
}
context_unlock(ctx);
}
static int win32_resume(Context * ctx) {
- if (ctx->regs_dirty && SetThreadContext(ctx->handle, (REG_SET *)ctx->regs) == 0) {
+ if (ctx->regs_dirty && SetThreadContext(EXT(ctx)->handle, (REG_SET *)ctx->regs) == 0) {
errno = log_error("SetThreadContext", 0);
return -1;
}
ctx->regs_dirty = 0;
- if (ctx->pending_event.ExceptionRecord.ExceptionCode != 0) {
+ if (EXT(ctx)->pending_event.ExceptionRecord.ExceptionCode != 0) {
event_win32_context_started(ctx);
context_lock(ctx);
post_event(event_win32_context_stopped_async, ctx);
return 0;
}
if (ctx->parent->pending_signals & (1 << SIGKILL)) {
- if (!ctx->parent->exiting && !TerminateProcess(ctx->parent->handle, 1)) {
+ if (!ctx->parent->exiting && !TerminateProcess(EXT(ctx->parent)->handle, 1)) {
errno = log_error("TerminateProcess", 0);
return -1;
}
@@ -248,7 +267,7 @@ static int win32_resume(Context * ctx) {
ctx->parent->exiting = 1;
}
for (;;) {
- DWORD cnt = ResumeThread(ctx->handle);
+ DWORD cnt = ResumeThread(EXT(ctx)->handle);
if (cnt == (DWORD)-1) {
errno = log_error("ResumeThread", 0);
return -1;
@@ -277,10 +296,10 @@ static void debug_event_handler(void * x) {
assert(ctx == NULL);
prs = create_context(debug_event->dwProcessId, sizeof(REG_SET));
prs->mem = debug_event->dwProcessId;
- prs->handle = debug_event->u.CreateProcessInfo.hProcess;
- prs->file_handle = debug_event->u.CreateProcessInfo.hFile;
- prs->base_address = (unsigned)debug_event->u.CreateProcessInfo.lpBaseOfImage;
- assert(prs->handle != NULL);
+ EXT(prs)->handle = debug_event->u.CreateProcessInfo.hProcess;
+ EXT(prs)->file_handle = debug_event->u.CreateProcessInfo.hFile;
+ EXT(prs)->base_address = (uintptr_t)debug_event->u.CreateProcessInfo.lpBaseOfImage;
+ assert(EXT(prs)->handle != NULL);
link_context(prs);
send_context_created_event(prs);
args->debug_thread_args->attach_callback(0, prs, args->debug_thread_args->attach_data);
@@ -288,8 +307,8 @@ static void debug_event_handler(void * x) {
args->debug_thread_args->attach_data = NULL;
ctx = create_context(debug_event->dwThreadId, sizeof(REG_SET));
ctx->mem = debug_event->dwProcessId;
- ctx->handle = debug_event->u.CreateProcessInfo.hThread;
- ctx->debug_started = 1;
+ EXT(ctx)->handle = debug_event->u.CreateProcessInfo.hThread;
+ EXT(ctx)->debug_started = 1;
ctx->parent = prs;
prs->ref_count++;
list_add_first(&ctx->cldl, &prs->children);
@@ -301,7 +320,7 @@ static void debug_event_handler(void * x) {
assert(ctx == NULL);
ctx = create_context(debug_event->dwThreadId, sizeof(REG_SET));
ctx->mem = debug_event->dwProcessId;
- ctx->handle = debug_event->u.CreateThread.hThread;
+ EXT(ctx)->handle = debug_event->u.CreateThread.hThread;
ctx->parent = prs;
prs->ref_count++;
list_add_first(&ctx->cldl, &prs->children);
@@ -313,7 +332,7 @@ static void debug_event_handler(void * x) {
assert(prs != NULL);
if (ctx == NULL) break;
if (args->early_event) break; /* Can anything be done about such exceptions? */
- assert(ctx->pending_event.ExceptionRecord.ExceptionCode == 0);
+ assert(EXT(ctx)->pending_event.ExceptionRecord.ExceptionCode == 0);
switch (args->event.u.Exception.ExceptionRecord.ExceptionCode) {
case EXCEPTION_SINGLE_STEP:
case EXCEPTION_BREAKPOINT:
@@ -324,12 +343,12 @@ static void debug_event_handler(void * x) {
args->continue_status = DBG_EXCEPTION_NOT_HANDLED;
break;
}
- memcpy(&ctx->pending_event, &args->event.u.Exception, sizeof(EXCEPTION_DEBUG_INFO));
+ memcpy(&EXT(ctx)->pending_event, &args->event.u.Exception, sizeof(EXCEPTION_DEBUG_INFO));
if (!ctx->stopped) {
int signal = 0;
- if (ctx->context_stopped_async_pending) {
+ if (EXT(ctx)->context_stopped_async_pending) {
cancel_event(event_win32_context_stopped_async, ctx, 0);
- ctx->context_stopped_async_pending = 0;
+ EXT(ctx)->context_stopped_async_pending = 0;
}
else {
context_lock(ctx);
@@ -353,24 +372,24 @@ static void debug_event_handler(void * x) {
break;
case LOAD_DLL_DEBUG_EVENT:
assert(prs != NULL);
- prs->module_loaded = 1;
- prs->module_handle = args->event.u.LoadDll.hFile;
- prs->module_address = (unsigned)args->event.u.LoadDll.lpBaseOfDll;
+ EXT(prs)->module_loaded = 1;
+ EXT(prs)->module_handle = args->event.u.LoadDll.hFile;
+ EXT(prs)->module_address = (uintptr_t)args->event.u.LoadDll.lpBaseOfDll;
send_context_changed_event(prs);
- if (prs->module_handle != NULL) {
- log_error("CloseHandle", CloseHandle(prs->module_handle));
+ if (EXT(prs)->module_handle != NULL) {
+ log_error("CloseHandle", CloseHandle(EXT(prs)->module_handle));
}
- prs->module_handle = NULL;
- prs->module_address = 0;
- prs->module_loaded = 0;
+ EXT(prs)->module_handle = NULL;
+ EXT(prs)->module_address = 0;
+ EXT(prs)->module_loaded = 0;
break;
case UNLOAD_DLL_DEBUG_EVENT:
assert(prs != NULL);
- prs->module_unloaded = 1;
- prs->module_address = (unsigned)args->event.u.UnloadDll.lpBaseOfDll;
+ EXT(prs)->module_unloaded = 1;
+ EXT(prs)->module_address = (uintptr_t)args->event.u.UnloadDll.lpBaseOfDll;
send_context_changed_event(prs);
- prs->module_address = 0;
- prs->module_unloaded = 0;
+ EXT(prs)->module_address = 0;
+ EXT(prs)->module_unloaded = 0;
break;
case RIP_EVENT:
trace(LOG_ALWAYS, "System debugging error: debuggee pid %d, error type %d, error code %d",
@@ -594,16 +613,16 @@ int context_stop(Context * ctx) {
assert(context_has_state(ctx));
assert(!ctx->stopped);
assert(!ctx->exited);
- if (SuspendThread(ctx->handle) == (DWORD)-1) {
+ if (SuspendThread(EXT(ctx)->handle) == (DWORD)-1) {
if (GetLastError() != ERROR_ACCESS_DENIED) {
errno = log_error("SuspendThread", 0);
return -1;
}
}
- if (!ctx->context_stopped_async_pending) {
+ if (!EXT(ctx)->context_stopped_async_pending) {
context_lock(ctx);
post_event(event_win32_context_stopped_async, ctx);
- ctx->context_stopped_async_pending = 1;
+ EXT(ctx)->context_stopped_async_pending = 1;
}
return 0;
}
@@ -661,7 +680,7 @@ int context_read_mem(Context * ctx, ContextAddress address, void * buf, size_t s
assert(is_dispatch_thread());
if (ctx->parent != NULL) ctx = ctx->parent;
assert(ctx->pid == ctx->mem);
- if (ReadProcessMemory(ctx->handle, (LPCVOID)address, buf, size, &bcnt) == 0 || bcnt != size) {
+ if (ReadProcessMemory(EXT(ctx)->handle, (LPCVOID)address, buf, size, &bcnt) == 0 || bcnt != size) {
errno = log_error("ReadProcessMemory", 0);
return -1;
}
@@ -677,20 +696,49 @@ int context_write_mem(Context * ctx, ContextAddress address, void * buf, size_t
if (ctx->parent != NULL) ctx = ctx->parent;
assert(ctx->pid == ctx->mem);
check_breakpoints_on_memory_write(ctx, address, buf, size);
- if (WriteProcessMemory(ctx->handle, (LPVOID)address, buf, size, &bcnt) == 0 || bcnt != size) {
+ if (WriteProcessMemory(EXT(ctx)->handle, (LPVOID)address, buf, size, &bcnt) == 0 || bcnt != size) {
DWORD err = GetLastError();
if (err == ERROR_ACCESS_DENIED) errno = set_win32_errno(err);
else errno = log_error("WriteProcessMemory", 0);
return -1;
}
- if (FlushInstructionCache(ctx->handle, (LPCVOID)address, size) == 0) {
+ if (FlushInstructionCache(EXT(ctx)->handle, (LPCVOID)address, size) == 0) {
errno = log_error("FlushInstructionCache", 0);
return -1;
}
return 0;
}
+HANDLE get_context_handle(Context * ctx) {
+ return EXT(ctx)->handle;
+}
+
+HANDLE get_context_file_handle(Context * ctx) {
+ return EXT(ctx)->file_handle;
+}
+
+HANDLE get_context_module_handle(Context * ctx) {
+ return EXT(ctx)->module_handle;
+}
+
+DWORD64 get_context_base_address(Context * ctx) {
+ return EXT(ctx)->base_address;
+}
+
+DWORD64 get_context_module_address(Context * ctx) {
+ return EXT(ctx)->module_address;
+}
+
+int is_context_module_loaded(Context * ctx) {
+ return EXT(ctx)->module_loaded;
+}
+
+int is_context_module_unloaded(Context * ctx) {
+ return EXT(ctx)->module_unloaded;
+}
+
void init_contexts_sys_dep(void) {
+ context_extension_offset = context_extension(sizeof(ContextExtension));
}
#endif /* if ENABLE_DebugContext */
diff --git a/system/Windows/context-win32.h b/system/Windows/context-win32.h
new file mode 100644
index 00000000..2fa3de4f
--- /dev/null
+++ b/system/Windows/context-win32.h
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 Wind River Systems, Inc. and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ * The Eclipse Public License is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+
+/*
+ * This module handles process/thread OS contexts and their state machine.
+ */
+
+#ifndef D_context_win32
+#define D_context_win32
+
+#include "config.h"
+#include "context.h"
+
+extern HANDLE get_context_handle(Context * ctx);
+extern HANDLE get_context_file_handle(Context * ctx);
+extern HANDLE get_context_module_handle(Context * ctx);
+
+extern DWORD64 get_context_base_address(Context * ctx);
+extern DWORD64 get_context_module_address(Context * ctx);
+
+extern int is_context_module_loaded(Context * ctx);
+extern int is_context_module_unloaded(Context * ctx);
+
+#endif /* D_context_win32 */

Back to the top