aboutsummaryrefslogtreecommitdiff
blob: 021a3c4388cbf297c72fd9566c8c4e1cbe84bf9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/*
 * 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);
	}
}

#ifndef NDEBUG
void sb_maybe_gdb(void)
{
	if (is_env_on("SANDBOX_GDB")) {
		sb_einfo("attempting to autolaunch gdb; please wait ...\n\n");
		sb_gdb();
	}
}
#endif