diff options
Diffstat (limited to 'bin/gcore')
-rwxr-xr-x | bin/gcore | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/bin/gcore b/bin/gcore new file mode 100755 index 0000000..1ee9dc3 --- /dev/null +++ b/bin/gcore @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +# Copyright (C) 2003-2019 Free Software Foundation, Inc. + +# 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. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# +# Script to generate a core file of a running program. +# It starts up gdb, attaches to the given PID and invokes the gcore command. +# + +# Need to check for -o option, but set default basename to "core". +prefix=core + +# When the -a option is present, this may hold additional commands +# to ensure gdb dumps all mappings (OS dependent). +dump_all_cmds=() + +while getopts :ao: opt; do + case "$opt" in + a) + case "$OSTYPE" in + linux*) + dump_all_cmds=("-ex" "set use-coredump-filter off") + dump_all_cmds+=("-ex" "set dump-excluded-mappings on") + ;; + esac + ;; + o) + prefix=$OPTARG + ;; + *) + echo "usage: gcore [-a] [-o prefix] pid1 [pid2...pidN]" + exit 2 + ;; + esac +done + +shift $((OPTIND-1)) + +if [ "$#" -eq "0" ] +then + echo "usage: gcore [-a] [-o prefix] pid1 [pid2...pidN]" + exit 2 +fi + +# Attempt to fetch the absolute path to the gcore script that was +# called. +binary_path=`dirname "$0"` + +if test "x$binary_path" = x. ; then + # We got "." back as a path. This means the user executed + # the gcore script locally (i.e. ./gcore) or called the + # script via a shell interpreter (i.e. sh gcore). + binary_basename=`basename "$0"` + + # If the gcore script was called like "sh gcore" and the script + # lives in the current directory, "which" will not give us "gcore". + # So first we check if the script is in the current directory + # before using the output of "which". + if test -f "$binary_basename" ; then + # We have a local gcore script in ".". This covers the case of + # doing "./gcore" or "sh gcore". + binary_path="." + else + # The gcore script was not found in ".", which means the script + # was called from somewhere else in $PATH by "sh gcore". + # Extract the correct path now. + binary_path_from_env=`which "$0"` + binary_path=`dirname "$binary_path_from_env"` + fi +fi + +# Check if the GDB binary is in the expected path. If not, just +# quit with a message. +if [ ! -f "$binary_path/gdb" ]; then + echo "gcore: GDB binary (${binary_path}/gdb) not found" + exit 1 +fi + +# Initialise return code. +rc=0 + +# Loop through pids +for pid in "$@" +do + # `</dev/null' to avoid touching interactive terminal if it is + # available but not accessible as GDB would get stopped on SIGTTIN. + "$binary_path/gdb" </dev/null \ + --nx --batch --readnever \ + -ex "set pagination off" -ex "set height 0" -ex "set width 0" \ + "${dump_all_cmds[@]}" \ + -ex "attach $pid" -ex "gcore $prefix.$pid" -ex detach -ex quit + + if [ -r "$prefix.$pid" ] ; then + rc=0 + else + echo "gcore: failed to create $prefix.$pid" + rc=1 + break + fi + + +done + +exit $rc |