diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2013-05-27 21:53:55 +0930 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-05-27 22:13:30 +0930 |
commit | 9552c972f725f70ab024e0c9d0487ff078322fd8 (patch) | |
tree | 6a8e9a5618d4148684af2387ed1541791ffda0d5 | |
parent | 75786a7313a8ac224b7501d5cde841dbda16392e (diff) |
breakpoint: new module.
Thanks to Jeremy Kerr for the idea!
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r-- | Makefile-ccan | 1 | ||||
l--------- | ccan/breakpoint/LICENSE | 1 | ||||
-rw-r--r-- | ccan/breakpoint/_info | 33 | ||||
-rw-r--r-- | ccan/breakpoint/breakpoint.c | 32 | ||||
-rw-r--r-- | ccan/breakpoint/breakpoint.h | 24 | ||||
-rw-r--r-- | ccan/breakpoint/test/run.c | 17 |
6 files changed, 108 insertions, 0 deletions
diff --git a/Makefile-ccan b/Makefile-ccan index 7ae3863a..2d713a68 100644 --- a/Makefile-ccan +++ b/Makefile-ccan @@ -34,6 +34,7 @@ MODS_WITH_SRC := antithread \ avl \ bdelta \ block_pool \ + breakpoint \ btree \ ccan_tokenizer \ charset \ diff --git a/ccan/breakpoint/LICENSE b/ccan/breakpoint/LICENSE new file mode 120000 index 00000000..b7951dab --- /dev/null +++ b/ccan/breakpoint/LICENSE @@ -0,0 +1 @@ +../../licenses/CC0
\ No newline at end of file diff --git a/ccan/breakpoint/_info b/ccan/breakpoint/_info new file mode 100644 index 00000000..5f5251e6 --- /dev/null +++ b/ccan/breakpoint/_info @@ -0,0 +1,33 @@ +#include <string.h> +#include "config.h" + +/** + * breakpoint - break if the program is run under gdb. + * + * This code allows you to insert breakpoints within a program. These will + * do nothing unless your program is run under GDB. + * + * License: CC0 (Public domain) + * + * Example: + * #include <ccan/breakpoint/breakpoint.h> + * + * int main(void) + * { + * breakpoint(); + * return 0; + * } + */ +int main(int argc, char *argv[]) +{ + /* Expect exactly one argument */ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + printf("ccan/compiler\n"); + return 0; + } + + return 1; +} diff --git a/ccan/breakpoint/breakpoint.c b/ccan/breakpoint/breakpoint.c new file mode 100644 index 00000000..279e29a1 --- /dev/null +++ b/ccan/breakpoint/breakpoint.c @@ -0,0 +1,32 @@ +/* CC0 (Public domain) - see LICENSE file for details + * + * Idea for implementation thanks to stackoverflow.com: + * http://stackoverflow.com/questions/3596781/detect-if-gdb-is-running + */ +#include <ccan/breakpoint/breakpoint.h> + +bool breakpoint_initialized; +bool breakpoint_under_debug; + +/* This doesn't get called if we're under GDB. */ +static void trap(int signum) +{ + breakpoint_initialized = true; +} + +void breakpoint_init(void) +{ + struct sigaction old, new; + + new.sa_handler = trap; + new.sa_flags = 0; + sigemptyset(&new.sa_mask); + sigaction(SIGTRAP, &new, &old); + kill(getpid(), SIGTRAP); + sigaction(SIGTRAP, &old, NULL); + + if (!breakpoint_initialized) { + breakpoint_initialized = true; + breakpoint_under_debug = true; + } +} diff --git a/ccan/breakpoint/breakpoint.h b/ccan/breakpoint/breakpoint.h new file mode 100644 index 00000000..6283a010 --- /dev/null +++ b/ccan/breakpoint/breakpoint.h @@ -0,0 +1,24 @@ +/* CC0 (Public domain) - see LICENSE file for details */ +#ifndef CCAN_BREAKPOINT_H +#define CCAN_BREAKPOINT_H +#include <ccan/compiler/compiler.h> +#include <sys/types.h> +#include <unistd.h> +#include <signal.h> +#include <stdbool.h> + +void breakpoint_init(void) COLD; +extern bool breakpoint_initialized; +extern bool breakpoint_under_debug; + +/** + * breakpoint - stop if running under the debugger. + */ +static inline void breakpoint(void) +{ + if (!breakpoint_initialized) + breakpoint_init(); + if (breakpoint_under_debug) + kill(getpid(), SIGTRAP); +} +#endif /* CCAN_BREAKPOINT_H */ diff --git a/ccan/breakpoint/test/run.c b/ccan/breakpoint/test/run.c new file mode 100644 index 00000000..b36e9c22 --- /dev/null +++ b/ccan/breakpoint/test/run.c @@ -0,0 +1,17 @@ +#include <ccan/breakpoint/breakpoint.h> +#include <ccan/breakpoint/breakpoint.c> +#include <ccan/tap/tap.h> + +int main(void) +{ + /* This is how many tests you plan to run */ + plan_tests(2); + + breakpoint(); + + ok1(breakpoint_initialized); + ok1(!breakpoint_under_debug); + + /* This exits depending on whether all tests passed */ + return exit_status(); +} |