aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2012-12-03 00:10:50 -0500
committerMike Frysinger <vapier@gentoo.org>2012-12-24 03:01:36 -0500
commite0675f1bce06463ec51286f56afa2c2b7b505dd1 (patch)
tree57e7e2215303010bb34a9b9bee7725c8fcbeb04c
parentsb_efuncs: fix usage of portage handlers (diff)
downloadsandbox-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>
-rw-r--r--configure.ac2
-rw-r--r--libsbutil/Makefile.am1
-rw-r--r--libsbutil/sb_efuncs.c21
-rw-r--r--libsbutil/sb_gdb.c71
-rw-r--r--libsbutil/sbutil.h5
5 files changed, 80 insertions, 20 deletions
diff --git a/configure.ac b/configure.ac
index dca43f7..fc63f4d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,6 +146,8 @@ AC_TYPE_SIGNAL
AC_FUNC_STAT
AC_CHECK_FUNCS_ONCE(m4_flatten([
backtrace
+ clone
+ __clone2
creat64
faccessat
fchmodat
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)) \