#!/bin/bash # gdb-wrapper2 # Copyright (C) 2017 Paweł Redman # 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