summaryrefslogtreecommitdiff
path: root/gdb-wrapper2/gdb-wrapper2.sh
blob: c60b649bcfaf13386c8b23646e0c2e89aa0a7dcf (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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/bin/bash

# gdb-wrapper2
# Copyright (C) 2017  Paweł Redman <pawel.redman@gmail.com>

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

SELF="$0"
PROGRAM="$1"
shift 1

if [ -z "$PROGRAM" ]; then
        echo "$SELF [program] (args...)"
        exit 1
fi

# Check if the program exists before calling GDB so the errors are clearer.
if [ ! -f "$PROGRAM" ]; then
	stat "$PROGRAM"
	exit 1
fi

# 'catch' and 'break' can be followed by a 'commands' block to tell GDB what
# to do in case of a breakpoint/signal. This is where the stack is printed
# and the core is dumped. 
function write_commands {
	echo "commands"
		echo "thread apply all backtrace"
		echo "gcore"
		echo "echo \n"

		# Terminate if this isn't the first fault to avoid infinite
		# recursion.
		echo "set \$faults = \$faults + 1"
		echo "if \$faults >= 2"
			echo "echo Double fault, terminating the program.\n"
			echo "kill"
			echo "quit"
		echo "else"
			# Resume the program's execution.
			# If the program can handle signals and exit gracefully
			# then this script should let it (after dumping a core
			# for debugging).
			echo "continue"
		echo "end"
	echo "end"
}

function write_config {
	# Make sure gdb won't ask for interactive input. This is supposed
	# to never happen when using -batch but I don't trust them.
	echo "set confirm off"
	echo "set width unlimited"
	echo "set height unlimited"
	echo "set pagination off"
	echo "set backtrace limit unlimited"

	echo "set \$faults = 0"

	# This catches all signals except SIGINT and SIGTRAP.
	echo "catch signal"
	write_commands

	# Catch SIGINT too, just in case.
	echo "catch signal SIGINT"
	write_commands

	# Catch calls to Com_Error. You'll want something else here if you're
	# using this script for another program.
	echo "break Com_Error"
	write_commands

	# Finally start the program.
	echo "run"
}

# Disable automatic coredumps.
ulimit -c 0

# For some reason gdb's '-x' option won't accept a pipe as an argument. The
# workaround is to create a temporary file for the configuration.
config_path=$(mktemp /tmp/gdb-wrapper2.XXXXXX)
write_config > "$config_path"

gdb -batch -x "$config_path" --args "$PROGRAM" "$@"
exit_status="$?"

rm "$config_path"
exit $exit_status