diff options
author | Mike Frysinger <vapier@gentoo.org> | 2012-12-03 00:10:50 -0500 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2012-12-24 03:01:36 -0500 |
commit | e0675f1bce06463ec51286f56afa2c2b7b505dd1 (patch) | |
tree | 57e7e2215303010bb34a9b9bee7725c8fcbeb04c /libsbutil | |
parent | sb_efuncs: fix usage of portage handlers (diff) | |
download | sandbox-e0675f1bce06463ec51286f56afa2c2b7b505dd1.tar.gz sandbox-e0675f1bce06463ec51286f56afa2c2b7b505dd1.tar.bz2 sandbox-e0675f1bce06463ec51286f56afa2c2b7b505dd1.zip |
sb_gdb: improve gdb integration
Add a dedicated entry point for connecting gdb to make it easy to connect
gdb at arbitrary points (ala printf style debugging).
This also smooths a lot of the common steps when automatically launching
gdb such as making sure the process is closer to the crash point when the
user takes over control of gdb.
Finally, switch to using clone rather than fork since the latter relies
on the C lib's fork which implicitly can grab locks. If we're crashing
in the middle of a func that already holds those locks, the fork call
will hang indefinitely on us.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'libsbutil')
-rw-r--r-- | libsbutil/Makefile.am | 1 | ||||
-rw-r--r-- | libsbutil/sb_efuncs.c | 21 | ||||
-rw-r--r-- | libsbutil/sb_gdb.c | 71 | ||||
-rw-r--r-- | libsbutil/sbutil.h | 5 |
4 files changed, 78 insertions, 20 deletions
diff --git a/libsbutil/Makefile.am b/libsbutil/Makefile.am index a93b95c..f1fed76 100644 --- a/libsbutil/Makefile.am +++ b/libsbutil/Makefile.am @@ -22,6 +22,7 @@ libsbutil_la_SOURCES = \ is_env_off.c \ sb_backtrace.c \ sb_efuncs.c \ + sb_gdb.c \ sb_open.c \ sb_read.c \ sb_write.c \ diff --git a/libsbutil/sb_efuncs.c b/libsbutil/sb_efuncs.c index 64ac82f..484e8a0 100644 --- a/libsbutil/sb_efuncs.c +++ b/libsbutil/sb_efuncs.c @@ -153,26 +153,7 @@ void __sb_ebort(const char *file, const char *func, size_t line_num, const char sb_dump_backtrace(); -#ifndef NDEBUG - if (is_env_on("SANDBOX_GDB")) { - sb_einfo("attempting to autolaunch gdb; please wait ...\n\n"); - pid_t crashed_pid = getpid(); - switch (fork()) { - case -1: break; - case 0: { - char pid[10]; - snprintf(pid, sizeof(pid), "%i", crashed_pid); - unsetenv(ENV_LD_PRELOAD); - /*sb_unwrapped_*/execlp("gdb", "gdb", "--quiet", "--pid", pid, "-ex", "bt full", NULL); - break; - } - default: { - int status; - wait(&status); - } - } - } -#endif + sb_maybe_gdb(); abort(); } diff --git a/libsbutil/sb_gdb.c b/libsbutil/sb_gdb.c new file mode 100644 index 0000000..6112379 --- /dev/null +++ b/libsbutil/sb_gdb.c @@ -0,0 +1,71 @@ +/* + * sb_gdb.c + * + * Helpers for autolaunching gdb. + * + * Copyright 1999-2012 Gentoo Foundation + * Licensed under the GPL-2 + */ + +#include "headers.h" +#include "sbutil.h" + +static int __sb_connect_gdb(void *vpid) +{ + char pid[10]; + snprintf(pid, sizeof(pid), "%i", (pid_t)(uintptr_t)vpid); + unsetenv(ENV_LD_PRELOAD); + return /*sb_unwrapped_*/execlp("gdb", "gdb", + "--quiet", + "--pid", pid, + "-ex", "set _gdb_poller = 0", + "-ex", "fin", + "-ex", "bt full", + "-ex", "echo \\n", + "-ex", "f", + NULL); +} + +#define STACK_SIZE 4096 + +#ifndef HAVE_CLONE +# ifdef HAVE___CLONE2 +/* Hrm, maybe they have clone2 */ +# define clone(fn, stack, flags, arg) \ + __clone2(fn, stack, STACK_SIZE, flags, arg, NULL, NULL, NULL) +# else +/* Fake it with fork() ... not as safe, but not much else we can do */ +static int fake_clone(int (*fn)(void *), void *child_stack, int flags, void *arg) +{ + pid_t pid = fork(); + switch (pid) { + case 0: + _exit(fn(arg)); + default: + return pid; + } +} +# define clone(...) fake_clone(__VA_ARGS__) +# endif +#endif + +void sb_gdb(void) +{ + char stack[STACK_SIZE * 2]; + pid_t pid = getpid(); + /* Put the child stack in the middle so we don't have to worry about + * the direction of growth. Most grown down, but some grow up!@ + */ + if (clone(__sb_connect_gdb, stack + STACK_SIZE, 0, (void *)(uintptr_t)pid) != -1) { + volatile int _gdb_poller = 1; + while (_gdb_poller); + } +} + +void sb_maybe_gdb(void) +{ + if (is_env_on("SANDBOX_GDB")) { + sb_einfo("attempting to autolaunch gdb; please wait ...\n\n"); + sb_gdb(); + } +} diff --git a/libsbutil/sbutil.h b/libsbutil/sbutil.h index c65c369..67a8aaa 100644 --- a/libsbutil/sbutil.h +++ b/libsbutil/sbutil.h @@ -112,6 +112,11 @@ __printf(4, 5) void __sb_ebort(const char *file, const char *func, size_t line_n #define sb_ebort(format, ...) __sb_ebort(__FILE__, __func__, __LINE__, format, ## __VA_ARGS__) void sb_dump_backtrace(void); void __sb_dump_backtrace(void); +void sb_gdb(void); +void sb_maybe_gdb(void); +#ifdef NDEBUG +#define sb_maybe_gdb() +#endif #define sb_assert(cond) \ do { \ if (!(cond)) \ |