diff options
-rwxr-xr-x | agent/agent.vcproj | 8 | ||||
-rwxr-xr-x | agent/agent.vcxproj | 22 | ||||
-rwxr-xr-x | agent/agent.vcxproj.filters | 6 | ||||
-rw-r--r-- | agent/system/Darwin/tcf/context-darwin.c | 17 | ||||
-rw-r--r-- | agent/system/FreeBSD/tcf/context-freebsd.c | 19 | ||||
-rw-r--r-- | agent/system/GNU/Linux/tcf/context-linux.c | 33 | ||||
-rw-r--r-- | agent/system/Windows/tcf/context-win32.c | 8 | ||||
-rw-r--r-- | agent/tcf/framework/context.c | 3 | ||||
-rw-r--r-- | agent/tcf/framework/context.h | 7 | ||||
-rw-r--r-- | agent/tcf/framework/signames.c | 25 | ||||
-rw-r--r-- | agent/tcf/framework/signames.h | 3 | ||||
-rw-r--r-- | agent/tcf/framework/sigsets.c | 130 | ||||
-rw-r--r-- | agent/tcf/framework/sigsets.h | 52 | ||||
-rw-r--r-- | agent/tcf/services/processes.c | 65 |
14 files changed, 337 insertions, 61 deletions
diff --git a/agent/agent.vcproj b/agent/agent.vcproj index 9c9cb08b..4eb98f43 100755 --- a/agent/agent.vcproj +++ b/agent/agent.vcproj @@ -596,6 +596,14 @@ >
</File>
<File
+ RelativePath=".\tcf\framework\sigsets.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcf\framework\sigsets.h"
+ >
+ </File>
+ <File
RelativePath=".\tcf\framework\streams.c"
>
</File>
diff --git a/agent/agent.vcxproj b/agent/agent.vcxproj index 54bc2a7d..94d5e775 100755 --- a/agent/agent.vcxproj +++ b/agent/agent.vcxproj @@ -89,13 +89,16 @@ <StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
- <PrecompiledHeaderOutputFile>$(OutDir)agent.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<CompileAs>CompileAsC</CompileAs>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -132,13 +135,16 @@ <StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
- <PrecompiledHeaderOutputFile>$(OutDir)agent.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
<WarningLevel>Level3</WarningLevel>
<SuppressStartupBanner>true</SuppressStartupBanner>
<CompileAs>CompileAsC</CompileAs>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -171,7 +177,8 @@ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <PrecompiledHeaderOutputFile>$(OutDir)agent.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
@@ -179,6 +186,8 @@ <SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -213,7 +222,8 @@ <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
- <PrecompiledHeaderOutputFile>$(OutDir)agent.pch</PrecompiledHeaderOutputFile>
+ <PrecompiledHeaderOutputFile>
+ </PrecompiledHeaderOutputFile>
<AssemblerListingLocation>$(OutDir)</AssemblerListingLocation>
<ObjectFileName>$(OutDir)</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)</ProgramDataBaseFileName>
@@ -221,6 +231,8 @@ <SuppressStartupBanner>true</SuppressStartupBanner>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CompileAs>CompileAsC</CompileAs>
+ <PrecompiledHeaderFile>
+ </PrecompiledHeaderFile>
</ClCompile>
<ResourceCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@@ -266,6 +278,7 @@ <ClCompile Include="tcf\framework\proxy.c" />
<ClCompile Include="tcf\framework\shutdown.c" />
<ClCompile Include="tcf\framework\signames.c" />
+ <ClCompile Include="tcf\framework\sigsets.c" />
<ClCompile Include="tcf\framework\streams.c" />
<ClCompile Include="tcf\framework\trace.c" />
<ClCompile Include="tcf\framework\waitpid.c" />
@@ -415,6 +428,7 @@ <ClInclude Include="tcf\framework\proxy.h" />
<ClInclude Include="tcf\framework\shutdown.h" />
<ClInclude Include="tcf\framework\signames.h" />
+ <ClInclude Include="tcf\framework\sigsets.h" />
<ClInclude Include="tcf\framework\streams.h" />
<ClInclude Include="tcf\framework\tcf.h" />
<ClInclude Include="tcf\framework\trace.h" />
diff --git a/agent/agent.vcxproj.filters b/agent/agent.vcxproj.filters index e2776791..f204cab9 100755 --- a/agent/agent.vcxproj.filters +++ b/agent/agent.vcxproj.filters @@ -312,6 +312,9 @@ <ClCompile Include="tcf\services\profiler.c">
<Filter>services</Filter>
</ClCompile>
+ <ClCompile Include="tcf\framework\sigsets.c">
+ <Filter>framework</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="tcf\framework\asyncreq.h">
@@ -579,5 +582,8 @@ <ClInclude Include="tcf\services\profiler.h">
<Filter>services</Filter>
</ClInclude>
+ <ClInclude Include="tcf\framework\sigsets.h">
+ <Filter>framework</Filter>
+ </ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file diff --git a/agent/system/Darwin/tcf/context-darwin.c b/agent/system/Darwin/tcf/context-darwin.c index b3b13cf0..55fcf739 100644 --- a/agent/system/Darwin/tcf/context-darwin.c +++ b/agent/system/Darwin/tcf/context-darwin.c @@ -168,13 +168,13 @@ int context_continue(Context * ctx) { if (skip_breakpoint(ctx, 0)) return 0; 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)) { - ctx->pending_signals &= ~(1 << signal); - signal = 0; + unsigned n = 0; + while (sigset_get_next(&ctx->pending_signals, &n)) { + if (sigset_get(&ctx->sig_dont_pass, n)) { + sigset_set(&ctx->pending_signals, n, 0); } else { + signal = n; break; } } @@ -272,7 +272,7 @@ int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextA case RM_STEP_INTO: return context_single_step(ctx); case RM_TERMINATE: - ctx->pending_signals |= 1 << SIGKILL; + sigset_set(&ctx->pending_signals, SIGKILL, 1); return context_continue(ctx); } errno = ERR_UNSUPPORTED; @@ -598,9 +598,8 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { assert(!EXT(ctx)->attach_callback); if (signal != SIGSTOP && signal != SIGTRAP) { - assert(signal < 32); - ctx->pending_signals |= 1 << signal; - if ((ctx->sig_dont_stop & (1 << signal)) == 0) { + sigset_set(&ctx->pending_signals, signal, 1); + if (sigset_get(&ctx->sig_dont_stop, signal) == 0) { ctx->pending_intercept = 1; stopped_by_exception = 1; } diff --git a/agent/system/FreeBSD/tcf/context-freebsd.c b/agent/system/FreeBSD/tcf/context-freebsd.c index b778459d..69deef2e 100644 --- a/agent/system/FreeBSD/tcf/context-freebsd.c +++ b/agent/system/FreeBSD/tcf/context-freebsd.c @@ -173,13 +173,13 @@ int context_continue(Context * ctx) { if (skip_breakpoint(ctx, 0)) return 0; 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)) { - ctx->pending_signals &= ~(1 << signal); - signal = 0; + unsigned n = 0; + while (sigset_get_next(&ctx->pending_signals, &n)) { + if (sigset_get(&ctx->sig_dont_pass, n)) { + sigset_set(&ctx->pending_signals, n, 0); } else { + signal = n; break; } } @@ -214,7 +214,7 @@ int context_continue(Context * ctx) { errno = err; return -1; } - ctx->pending_signals &= ~(1 << signal); + sigset_set(&ctx->pending_signals, signal, 0); send_context_started_event(ctx); return 0; } @@ -269,7 +269,7 @@ int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextA case RM_STEP_INTO: return context_single_step(ctx); case RM_TERMINATE: - ctx->pending_signals |= 1 << SIGKILL; + sigset_set(&ctx->pending_signals, SIGKILL, 1); return context_continue(ctx); } errno = ERR_UNSUPPORTED; @@ -590,9 +590,8 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { assert(!EXT(ctx)->attach_callback); if (signal != SIGSTOP && signal != SIGTRAP) { - assert(signal < 32); - ctx->pending_signals |= 1 << signal; - if ((ctx->sig_dont_stop & (1 << signal)) == 0) { + sigset_set(&ctx->pending_signals, signal, 1); + if (sigset_get(&ctx->sig_dont_stop, signal) == 0) { ctx->pending_intercept = 1; stopped_by_exception = 1; } diff --git a/agent/system/GNU/Linux/tcf/context-linux.c b/agent/system/GNU/Linux/tcf/context-linux.c index 1a4c66d0..926ed45c 100644 --- a/agent/system/GNU/Linux/tcf/context-linux.c +++ b/agent/system/GNU/Linux/tcf/context-linux.c @@ -494,13 +494,13 @@ int context_continue(Context * ctx) { if (skip_breakpoint(ctx, 0)) return 0; if (!ext->syscall_enter && !ext->ptrace_event) { - while (ctx->pending_signals != 0) { - while ((ctx->pending_signals & (1 << signal)) == 0) signal++; - if (ctx->sig_dont_pass & (1 << signal)) { - ctx->pending_signals &= ~(1 << signal); - signal = 0; + unsigned n = 0; + while (sigset_get_next(&ctx->pending_signals, &n)) { + if (sigset_get(&ctx->sig_dont_pass, n)) { + sigset_set(&ctx->pending_signals, n, 0); } else { + signal = n; break; } } @@ -529,7 +529,7 @@ int context_continue(Context * ctx) { errno = err; return -1; } - ctx->pending_signals &= ~(1 << signal); + sigset_set(&ctx->pending_signals, signal, 0); if (syscall_never_returns(ctx)) { ext->syscall_enter = 0; ext->syscall_exit = 0; @@ -580,7 +580,7 @@ int context_resume(Context * ctx, int mode, ContextAddress range_start, ContextA case RM_STEP_INTO: return context_single_step(ctx); case RM_TERMINATE: - ctx->pending_signals |= 1 << SIGKILL; + sigset_set(&ctx->pending_signals, SIGKILL, 1); return context_continue(ctx); case RM_DETACH: return context_detach(ctx); @@ -1112,8 +1112,8 @@ static Context * add_thread(Context * parent, Context * creator, pid_t pid) { ctx->big_endian = parent->big_endian; ctx->creator = creator; if (creator) { - ctx->sig_dont_stop = creator->sig_dont_stop; - ctx->sig_dont_pass = creator->sig_dont_pass; + sigset_copy(&ctx->sig_dont_stop, &creator->sig_dont_stop); + sigset_copy(&ctx->sig_dont_pass, &creator->sig_dont_pass); creator->ref_count++; } (ctx->parent = parent)->ref_count++; @@ -1260,8 +1260,8 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { prs2->mem_access |= MEM_ACCESS_USER; prs2->big_endian = ctx->parent->big_endian; (prs2->creator = ctx)->ref_count++; - prs2->sig_dont_stop = ctx->sig_dont_stop; - prs2->sig_dont_pass = ctx->sig_dont_pass; + sigset_copy(&prs2->sig_dont_stop, &ctx->sig_dont_stop); + sigset_copy(&prs2->sig_dont_pass, &ctx->sig_dont_pass); prs2->ref_count = 1; clone_breakpoints_on_process_fork(ctx, prs2); if ((ext->attach_mode & CONTEXT_ATTACH_CHILDREN) == 0) { @@ -1296,8 +1296,8 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { alloc_regs(ctx2); ctx2->mem = prs; ctx2->big_endian = prs->big_endian; - ctx2->sig_dont_stop = ctx->sig_dont_stop; - ctx2->sig_dont_pass = ctx->sig_dont_pass; + sigset_copy(&ctx2->sig_dont_stop, &ctx->sig_dont_stop); + sigset_copy(&ctx2->sig_dont_pass, &ctx->sig_dont_pass); ctx2->exiting = 1; (ctx2->creator = ctx)->ref_count++; (ctx2->parent = prs)->ref_count++; @@ -1318,8 +1318,7 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { } if (signal != SIGSTOP && signal != SIGTRAP) { - assert(signal < 32); - ctx->pending_signals |= 1 << signal; + sigset_set(&ctx->pending_signals, signal, 1); #if defined(__arm__) /* On ARM, Linux kernel appears to use SIGILL to lazily enable vector registers */ if (signal == SIGILL && !ext->crt0_done) { @@ -1327,7 +1326,7 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { } else #endif - if ((ctx->sig_dont_stop & (1 << signal)) == 0) { + if (sigset_get(&ctx->sig_dont_stop, signal) == 0) { if (!is_intercepted(ctx)) ctx->pending_intercept = 1; stopped_by_exception = 1; } @@ -1414,7 +1413,7 @@ static void event_pid_stopped(pid_t pid, int signal, int event, int syscall) { send_context_stopped_event(ctx); } - if (ext->detach_req && !ext->sigstop_posted && !ctx->pending_signals) { + if (ext->detach_req && !ext->sigstop_posted && sigset_is_empty(&ctx->pending_signals)) { ext->waitpid_posted = 0; detach_waitpid_process(); } diff --git a/agent/system/Windows/tcf/context-win32.c b/agent/system/Windows/tcf/context-win32.c index 98cfcddd..c9535704 100644 --- a/agent/system/Windows/tcf/context-win32.c +++ b/agent/system/Windows/tcf/context-win32.c @@ -255,7 +255,7 @@ static DWORD event_win32_context_stopped(Context * ctx) { memset(ext->regs, 0, sizeof(REG_SET)); ctx->signal = get_signal_index(ctx); - ctx->pending_signals = 0; + sigset_clear(&ctx->pending_signals); ctx->stopped = 1; ctx->stopped_by_bp = 0; ctx->stopped_by_cb = NULL; @@ -338,11 +338,11 @@ static DWORD event_win32_context_stopped(Context * ctx) { int intercept = 1; ctx->stopped_by_exception = 1; if (ctx->signal) { - ctx->pending_signals |= 1 << ctx->signal; - if (ctx->sig_dont_pass & (1 << ctx->signal)) { + sigset_set(&ctx->pending_signals, ctx->signal, 1); + if (sigset_get(&ctx->sig_dont_pass, ctx->signal)) { continue_status = DBG_CONTINUE; } - if (ctx->sig_dont_stop & (1 << ctx->signal)) { + if (sigset_get(&ctx->sig_dont_stop, ctx->signal)) { intercept = 0; } } diff --git a/agent/tcf/framework/context.c b/agent/tcf/framework/context.c index e7a8fe2b..9684890c 100644 --- a/agent/tcf/framework/context.c +++ b/agent/tcf/framework/context.c @@ -206,6 +206,9 @@ void context_unlock(Context * ctx) { } ctx->event_notification = 0; list_remove(&ctx->ctxl); + sigset_clear(&ctx->pending_signals); + sigset_clear(&ctx->sig_dont_stop); + sigset_clear(&ctx->sig_dont_pass); loc_free(ctx->name); loc_free(ctx); } diff --git a/agent/tcf/framework/context.h b/agent/tcf/framework/context.h index c37d4e47..cd9e30ba 100644 --- a/agent/tcf/framework/context.h +++ b/agent/tcf/framework/context.h @@ -23,6 +23,7 @@ #include <tcf/config.h> #include <tcf/framework/cpudefs.h> #include <tcf/framework/errors.h> +#include <tcf/framework/sigsets.h> #include <tcf/framework/link.h> extern LINK context_root; @@ -65,9 +66,9 @@ struct Context { int exited; /* context exited */ int event_notification; /* set to 1 when calling one of ContextEventListener call-backs for this context */ int pending_intercept; /* host is waiting for this context to be suspended */ - unsigned long pending_signals; /* bit set of signals that were received, but not handled yet */ - unsigned long sig_dont_stop; /* bit set of signals that should not be intercepted by the debugger */ - unsigned long sig_dont_pass; /* bit set of signals that should not be delivered to the context */ + SigSet pending_signals; /* bit set of signals that were received, but not handled yet */ + SigSet sig_dont_stop; /* bit set of signals that should not be intercepted by the debugger */ + SigSet sig_dont_pass; /* bit set of signals that should not be delivered to the context */ int signal; /* signal that stopped this context */ }; diff --git a/agent/tcf/framework/signames.c b/agent/tcf/framework/signames.c index d100960b..fc3f1c88 100644 --- a/agent/tcf/framework/signames.c +++ b/agent/tcf/framework/signames.c @@ -20,6 +20,8 @@ #include <tcf/config.h> #include <signal.h> +#include <tcf/framework/myalloc.h> +#include <tcf/framework/sigsets.h> #include <tcf/framework/signames.h> #if defined(_WIN32) @@ -64,6 +66,10 @@ static ExceptionName exception_names[] = { #define EXCEPTION_NAMES_CNT ((int)(sizeof(exception_names) / sizeof(ExceptionName))) +int signal_cnt(void) {
+ return EXCEPTION_NAMES_CNT;
+} + const char * signal_name(int signal) { int n = signal - 1; if (n >= 0 && n < EXCEPTION_NAMES_CNT) return exception_names[n].name; @@ -154,20 +160,29 @@ static SignalInfo info[] = { #define INFO_CNT ((int)(sizeof(info) / sizeof(SignalInfo))) +static int index_len = 0; + static SignalInfo * get_info(int signal) { - static SignalInfo * index[32]; - static int index_ok = 0; - if (signal < 0 || signal > 31) return NULL; - if (!index_ok) { + static SignalInfo ** index = NULL; + if (index_len == 0) { int i; for (i = 0; i < INFO_CNT; i++) { + if (info[i].signal >= index_len) index_len = info[i].signal + 1; + } + index = (SignalInfo **)loc_alloc_zero(sizeof(SignalInfo *) * index_len); + for (i = 0; i < INFO_CNT; i++) { index[info[i].signal] = &info[i]; } - index_ok = 1; } + if (signal < 0 || signal >= index_len) return NULL; return index[signal]; } +int signal_cnt(void) {
+ get_info(0);
+ return index_len;
+} + const char * signal_name(int signal) { SignalInfo * i = get_info(signal); if (i != NULL) return i->name; diff --git a/agent/tcf/framework/signames.h b/agent/tcf/framework/signames.h index ad61e6d5..8b0d044c 100644 --- a/agent/tcf/framework/signames.h +++ b/agent/tcf/framework/signames.h @@ -20,6 +20,9 @@ #ifndef D_signames #define D_signames +/* Return the number of signals descriptions */ +extern int signal_cnt(void); + /* Return signal name */ extern const char * signal_name(int signal); diff --git a/agent/tcf/framework/sigsets.c b/agent/tcf/framework/sigsets.c new file mode 100644 index 00000000..557b149d --- /dev/null +++ b/agent/tcf/framework/sigsets.c @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2013 Xilinx, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Xilinx - initial API and implementation + *******************************************************************************/ + + +#include <tcf/config.h> + +#include <assert.h> +#include <tcf/framework/myalloc.h> +#include <tcf/framework/sigsets.h> + +#if ENABLE_UnlimitedSignals + +static unsigned search(SigSet * set, unsigned bit) { + unsigned l = 0; + unsigned h = set->cnt; + while (l < h) { + unsigned k = (l + h) / 2; + if (set->buf[k] > bit) { + h = k; + } + else if (set->buf[k] < bit) { + l = k + 1; + } + else { + return k; + } + } + return l; +} + +int sigset_is_empty(SigSet * set) { + return set->cnt == 0; +} + +int sigset_get(SigSet * set, unsigned bit) { + unsigned n = search(set, bit); + return n < set->cnt && set->buf[n] == bit; +} + +int sigset_get_next(SigSet * set, unsigned * bit) { + unsigned n = search(set, *bit + 1); + if (n >= set->cnt) return 0; + *bit = set->buf[n]; + return 1; +} + +void sigset_set(SigSet * set, unsigned bit, int value) { + unsigned n = search(set, bit); + assert(bit > 0 || (bit == 0 && value == 0)); + assert(n <= set->cnt); + if (value) { + if (n < set->cnt && set->buf[n] == bit) return; + if (set->cnt >= set->max) { + set->max += 8; + set->buf = (unsigned *)loc_realloc(set->buf, sizeof(unsigned) * set->max); + } + memmove(set->buf + n + 1, set->buf + n, sizeof(unsigned) * (set->cnt - n)); + set->buf[n] = bit; + set->cnt++; + } + else { + if (n >= set->cnt || set->buf[n] != bit) return; + memmove(set->buf + n, set->buf + n + 1, sizeof(unsigned) * (set->cnt - n - 1)); + set->cnt--; + } +} + +void sigset_copy(SigSet * dst, SigSet * src) { + dst->cnt = src->cnt; + dst->max = src->cnt; + dst->buf = (unsigned *)loc_alloc(sizeof(unsigned) * dst->max); + memcpy(dst->buf, src->buf, sizeof(unsigned) * dst->cnt); +} + +void sigset_clear(SigSet * set) { + loc_free(set->buf); + memset(set, 0, sizeof(SigSet)); +} + +#else + +int sigset_is_empty(SigSet * set) { + return *set == 0; +} + +int sigset_get(SigSet * set, unsigned bit) { + assert(bit < 32); + return (*set & (1ul << bit)) != 0; +} + +int sigset_get_next(SigSet * set, unsigned * bit) { + (*bit)++; + while (*bit < 32) { + if (*bit > 0 && (*set & (1ul << *bit)) != 0) return 1; + (*bit)++; + } + return 0; +} + +void sigset_set(SigSet * set, unsigned bit, int value) { + assert((bit > 0 && bit < 32) || (bit == 0 && value == 0)); + if (value) { + *set |= 1ul << bit; + } + else { + *set &= ~(1ul << bit); + } +} + +void sigset_copy(SigSet * dst, SigSet * src) { + *dst = *src; +} + +void sigset_clear(SigSet * set) { + *set = 0; +} + +#endif /* ENABLE_UnlimitedSignals */ diff --git a/agent/tcf/framework/sigsets.h b/agent/tcf/framework/sigsets.h new file mode 100644 index 00000000..66454349 --- /dev/null +++ b/agent/tcf/framework/sigsets.h @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2013 Xilinx, Inc. and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Xilinx - initial API and implementation + *******************************************************************************/ + +/* + * SigSet type definition. + * The type used to provide support for more than 32 signals, + * e.g. POSIX real-time signals and Windows exceptions. + */ + +#ifndef D_sigset +#define D_sigset + +#if !defined(ENABLE_UnlimitedSignals) +# define ENABLE_UnlimitedSignals 1 +#endif + +#if ENABLE_UnlimitedSignals + +typedef struct SigSet { + unsigned cnt; + unsigned max; + unsigned * buf; +} SigSet; + +#else + +/* Backward compatible definition of signal set type, + * does not support signal numbers beyond 32 */ +typedef unsigned long SigSet; + +#endif + +extern int sigset_is_empty(SigSet * set); +extern int sigset_get(SigSet * set, unsigned bit); +extern int sigset_get_next(SigSet * set, unsigned * bit); +extern void sigset_set(SigSet * set, unsigned bit, int value); +extern void sigset_copy(SigSet * dst, SigSet * src); +extern void sigset_clear(SigSet * set); + +#endif /* D_sigset */ diff --git a/agent/tcf/services/processes.c b/agent/tcf/services/processes.c index a60ad13e..dafd1174 100644 --- a/agent/tcf/services/processes.c +++ b/agent/tcf/services/processes.c @@ -512,6 +512,28 @@ static void command_detach(char * token, Channel * c) { write_stream(&c->out, MARKER_EOM); } +static void write_sigset(OutputStream * out, SigSet * set) { + unsigned bit = 0; + uint64_t bits = 0; + while (sigset_get_next(set, &bit)) { + if (bit >= sizeof(bits) * 8) { + /* Does not fit into int bitset */ + unsigned cnt = 0; + bit = 0; + write_stream(out, '['); + while (sigset_get_next(set, &bit)) { + if (cnt > 0) write_stream(out, ','); + json_write_long(out, bit); + cnt++; + } + write_stream(out, ']'); + return; + } + bits |= (uint64_t)1 << bit; + } + json_write_uint64(out, bits); +} + static void command_get_signal_mask(char * token, Channel * c) { int err = 0; char id[256]; @@ -534,29 +556,51 @@ static void command_get_signal_mask(char * token, Channel * c) { write_stringz(&c->out, "null"); } else { - json_write_long(&c->out, ctx->sig_dont_stop); + write_sigset(&c->out, &ctx->sig_dont_stop); write_stream(&c->out, 0); - json_write_long(&c->out, ctx->sig_dont_pass); + write_sigset(&c->out, &ctx->sig_dont_pass); write_stream(&c->out, 0); - json_write_long(&c->out, ctx->pending_signals); + write_sigset(&c->out, &ctx->pending_signals); write_stream(&c->out, 0); } write_stream(&c->out, MARKER_EOM); } +static void read_sigset_bit(InputStream * inp, void * args) { + SigSet * set = (SigSet *)args; + unsigned bit = (unsigned)json_read_long(inp); + sigset_set(set, bit, 1); +} + +static SigSet read_sigset(InputStream * inp) { + SigSet set; + memset(&set, 0, sizeof(set)); + if (json_peek(inp) == '[') { + json_read_array(inp, read_sigset_bit, &set); + } + else { + unsigned bit; + uint64_t bits = json_read_uint64(inp); + for (bit = 0; bit < 64; bit++) { + sigset_set(&set, bit, (bits & ((uint64_t)1 << bit)) != 0); + } + } + return set; +} + static void command_set_signal_mask(char * token, Channel * c) { int err = 0; char id[256]; Context * ctx = NULL; - int dont_stop; - int dont_pass; + SigSet dont_stop; + SigSet dont_pass; json_read_string(&c->inp, id, sizeof(id)); json_test_char(&c->inp, MARKER_EOA); - dont_stop = json_read_long(&c->inp); + dont_stop = read_sigset(&c->inp); json_test_char(&c->inp, MARKER_EOA); - dont_pass = json_read_long(&c->inp); + dont_pass = read_sigset(&c->inp); json_test_char(&c->inp, MARKER_EOA); json_test_char(&c->inp, MARKER_EOM); @@ -565,6 +609,8 @@ static void command_set_signal_mask(char * token, Channel * c) { err = ERR_INV_CONTEXT; } else { + sigset_clear(&ctx->sig_dont_stop); + sigset_clear(&ctx->sig_dont_pass); ctx->sig_dont_stop = dont_stop; ctx->sig_dont_pass = dont_pass; } @@ -700,8 +746,9 @@ static void command_get_signal_list(char * token, Channel * c) { else { int i = 0; int n = 0; + int cnt = signal_cnt(); write_stream(&c->out, '['); - for (i = 0; i < 32; i++) { + for (i = 0; i < cnt; i++) { const char * name = signal_name(i); const char * desc = signal_description(i); if (name != NULL || desc != NULL) { @@ -1468,7 +1515,7 @@ static void command_start(char * token, Channel * c, void * x) { json_test_char(&c->inp, MARKER_EOA); params.envp = json_read_alloc_string_array(&c->inp, &envp_len); json_test_char(&c->inp, MARKER_EOA); - if (version > 0 && (peek_stream(&c->inp) == '{' || peek_stream(&c->inp) == 'n')) { + if (version > 0 && (json_peek(&c->inp) == '{' || json_peek(&c->inp) == 'n')) { json_read_struct(&c->inp, read_start_params, ¶ms); } else { |