blob: 8cfc2d549ea4a00e9b3bd1374c5d3c751e5f1a98 (
plain) (
tree)
|
|
#!/bin/sh
#
# %CopyrightBegin%
#
# Copyright Ericsson AB 2003-2018. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# %CopyrightEnd%
#
#
# This is a script to start Erlang/OTP for debugging. PATH is set to
# include this script so if slave nodes are started they will use this
# script as well.
#
# usage: cerl [ OPTIONS ] [ ARGS ]
#
# The OPTIONS are
#
# -rootdir $MYROOTDIR
# Run an installed emulator built from this source
# -debug Run debug compiled emulator
# -gdb Run the debug compiled emulator in emacs and gdb.
# You have to start beam in gdb using "run".
# -rgdb Run the debug compiled emulator in gdb.
# You have to start beam in gdb using "run".
# -dump Dump the bt of all threads in a core.
# -break F Run the debug compiled emulator in emacs and gdb and set break.
# The session is started, i.e. "run" is already don for you.
# -xxgdb FIXME currently disabled
# -purify Run emulator compiled for purify
# -quantify Run emulator compiled for quantify
# -purecov Run emulator compiled for purecov
# -gcov Run emulator compiled for gcov
# -valgrind Run emulator compiled for valgrind
# -lcnt Run emulator compiled for lock counting
# -icount Run emulator compiled for instruction counting
# -rr Run emulator under "rr record"
# Can be combined with compile targets (like -debug) except valgrind.
# -nox Unset the DISPLAY variable to disable us of X Windows
#
# FIXME For GDB you can also set the break point using "-break FUNCTION".
# FIXME For GDB you can also point out your own .gdbini......
# These are marked for export
export ROOTDIR
export PROGNAME
export EMU
export BINDIR
export PATH
cargs=
xargs=
cxargs_add() {
while [ $# -gt 0 ]; do
cargs="$cargs $1"
xargs="$xargs $1"
shift
done
}
core=
GDB=
GDBBP=
GDBARGS=
TYPE=
debug=
run_valgrind=no
run_rr=no
skip_erlexec=no
# Default rootdir
ROOTDIR=%SRC_ROOTDIR%
BINDIR="$ROOTDIR/bin/`$ROOTDIR/erts/autoconf/config.guess`"
TARGET=%TARGET%
#BINDIR="$ROOTDIR/bin/%TARGET%"
PROGNAME=$ROOTDIR/bin/cerl
EMU=beam
while [ $# -gt 0 ]; do
case "$1" in
+*)
# A system parameter!
cxargs_add $1
shift
# If next argument does not begin with a hyphen or a plus,
# it is used as the value of the system parameter.
if [ $# -gt 0 ]; then
case $1 in
-*|+*)
;;
*)
cxargs_add $1
shift;;
esac
fi;;
"-instr")
cxargs_add $1
shift
;;
"-target")
shift
BINDIR="$ROOTDIR/bin/$1"
shift
;;
"-rootdir")
shift
cargs="$cargs -rootdir $1"
ROOTDIR="$1"
BINDIR=$ROOTDIR/erts-%VSN%/bin
shift
;;
"-display")
shift
DISPLAY="$1"
export DISPLAY
shift
;;
"-nox")
shift
unset DISPLAY
;;
"-lcnt")
shift
cargs="$cargs -lcnt"
TYPE=.lcnt
;;
"-gprof")
shift
cargs="$cargs -gprof"
TYPE=.gprof
;;
"-debug")
shift
cargs="$cargs -debug"
TYPE=.debug
;;
"-frmptr")
shift
cargs="$cargs -frmptr"
TYPE=.frmptr
;;
"-icount")
shift
cargs="$cargs -icount"
TYPE=.icount
;;
"-dump")
shift
GDB=dump
core="$1"
shift
;;
"-gdb")
shift
GDB=egdb
;;
"-rgdb")
shift
GDB=gdb
;;
"-break")
shift
GDB=gdb
GDBBP="$GDBBP (insert-string \"break $1\") (comint-send-input)"
shift
;;
"-core")
shift
GDB=egdb
core="$1"
shift
;;
"-rcore")
shift
GDB=gdb
core="$1"
shift
;;
# "-xxgdb")
# shift
# GDB=xxgdb
# ;;
"-purify")
shift
cargs="$cargs -purify"
TYPE=.purify
;;
"-quantify")
shift
cargs="$cargs -quantify"
TYPE=.quantify
;;
"-purecov")
shift
cargs="$cargs -purecov"
TYPE=.purecov
;;
"-gcov")
shift
cargs="$cargs -gcov"
TYPE=.gcov
;;
"-valgrind")
shift
cargs="$cargs -valgrind"
TYPE=.valgrind
run_valgrind=yes
skip_erlexec=yes
;;
"-rr")
shift
cargs="$cargs -rr"
run_rr=yes
case "$1" in
"replay"|"ps")
;;
*)
skip_erlexec=yes
;;
esac
;;
*)
break
;;
esac
done
if [ ! -f $BINDIR/erlexec -a -f $ROOTDIR/bin/$TARGET/erlexec ]; then
# We are in a strange target (I'm looking at you openbsd) where
# TARGET != config.guess
BINDIR=$ROOTDIR/bin/$TARGET
fi
PATH=$BINDIR:$ROOTDIR/bin:$PATH
EXEC=$BINDIR/erlexec
PROGNAME="$PROGNAME$cargs"
EMU="$EMU$TYPE"
EMU_NAME=`$EXEC -emu_name_exit`
if [ $skip_erlexec = yes ]; then
emu_xargs=`echo $xargs | sed "s|+|-|g"`
beam_args=`$EXEC -emu_args_exit ${1+"$@"}`
# Prepare for some argument passing voodoo:
# $beam_args is a list of command line arguments separated by newlines.
# Make "$@" represent those arguments verbatim (including spaces and quotes).
SAVE_IFS="$IFS"
IFS='
'
set -- $beam_args
IFS="$SAVE_IFS"
fi
if [ "x$GDB" = "x" ]; then
if [ $run_valgrind = yes ]; then
valversion=`valgrind --version`
valmajor=`echo $valversion | sed 's,[a-z]*\-\([0-9]*\).*,\1,'`
valminor=`echo $valversion | sed 's,[a-z]*\-[0-9]*.\([0-9]*\).*,\1,'`
valint=`echo "$valmajor * 1000 + $valminor" | bc`
if [ "x$VALGRIND_LOG_XML" = "x" ]; then
valgrind_xml=
log_file_prefix="--log-file="
else
export VALGRIND_LOG_XML
valgrind_xml="--xml=yes"
if [ $valint -gt 3004 ]; then
log_file_prefix="--xml-file="
else
log_file_prefix="--log-file="
fi
fi
if [ "x$VALGRIND_LOG_DIR" = "x" ]; then
valgrind_log=
else
if [ $valint -gt 3004 ]; then
valgrind_log="$log_file_prefix$VALGRIND_LOG_DIR/$VALGRIND_LOGFILE_PREFIX$VALGRIND_LOGFILE_INFIX$EMU_NAME.log.$$"
else
valgrind_log="$log_file_prefix$VALGRIND_LOG_DIR/$VALGRIND_LOGFILE_PREFIX$VALGRIND_LOGFILE_INFIX$EMU_NAME.log"
fi
fi
if [ "x$VALGRIND_MISC_FLAGS" = "x" ]; then
valgrind_misc_flags=
else
valgrind_misc_flags="$VALGRIND_MISC_FLAGS"
fi
if which taskset > /dev/null && test -e /proc/cpuinfo; then
# We only let valgrind utilize one core with "taskset 1" as it can be very slow
# on multiple cores (especially with async threads). Valgrind only run one pthread
# at a time anyway so there is no point letting it utilize more than one core.
# Use $sched_arg to force all schedulers online to emulate multicore.
taskset1="taskset 1"
ncpu=`cat /proc/cpuinfo | grep -w processor | wc -l`
sched_arg="-S$ncpu:$ncpu"
else
taskset1=
sched_arg=
fi
exec $taskset1 valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $sched_arg $emu_xargs "$@"
elif [ $run_rr = yes ]; then
if [ $1 = replay ]; then
shift
cmdfile="/tmp/.cerlgdb.$$"
echo "set \$etp_beam_executable = \"$BINDIR/$EMU_NAME\"" > $cmdfile
if [ "$1" = "-p" ]; then
echo 'set $etp_rr_run_until_beam = 1' >> $cmdfile
fi
cat $ROOTDIR/erts/etc/unix/etp-commands >> $cmdfile
exec rr replay -x $cmdfile $*
elif [ $1 = ps ]; then
shift
rr ps $* | head -1
ChildSetup=`rr ps $* | grep 'erl_child_setup' | awk '{ print $2 }'`
for CS in $ChildSetup; do
rr ps $* | grep -E "^$CS"
done
exit 0
else
exec rr record --ignore-nested $BINDIR/$EMU_NAME $emu_xargs "$@"
fi
else
exec $EXEC $xargs ${1+"$@"}
fi
elif [ "x$GDB" = "xgdb" ]; then
case "x$core" in
x)
# Get emu args to use from erlexec...
beam_args=`$EXEC -emu_args_exit ${1+"$@"}`
gdbcmd="--args $EMU_NAME $beam_args"
;;
x/*)
gdbcmd="$EMU_NAME ${core}"
GDBBP=
;;
*)
dir=`pwd`
gdbcmd="$EMU_NAME ${dir}/${core}"
GDBBP=
;;
esac
cmdfile="/tmp/.cerlgdb.$$"
echo "source $ROOTDIR/erts/etc/unix/etp-commands" > $cmdfile
# Fire up gdb in emacs...
exec gdb $GDBBP -x $cmdfile $gdbcmd
elif [ "x$GDB" = "xegdb" ]; then
if [ "x$EMACS" = "x" ]; then
EMACS=emacs
fi
case "x$core" in
x)
# Get emu args to use from erlexec...
beam_args=`$EXEC -emu_args_exit ${1+"$@"} | tr '\n' ' '`
gdbcmd="(insert-string \"set args $beam_args\") \
(comint-send-input)"
;;
x/*)
gdbcmd="(insert-string \"core ${core}\") (comint-send-input)"
GDBBP=
;;
*)
dir=`pwd`
gdbcmd="(insert-string \"core ${dir}/${core}\") \
(comint-send-input)"
GDBBP=
;;
esac
if [ "$EMACS_ANNOTATE_LEVEL" != "" ]; then
GDBARGS="--annotate=$EMACS_ANNOTATE_LEVEL"
else
# Set annotation level for gdb in emacs 22 and higher. Seems to
# be working with level 1 for emacs 22 and level 3 for emacs 23...
emacs_major=`$EMACS --version | head -1 | sed 's,^[^0-9]*\([0-9]*\).*,\1,g'`
if [ '!' -z "$emacs_major" -a $emacs_major -gt 23 ]; then
GDBARGS="-i=mi "
elif [ '!' -z "$emacs_major" -a $emacs_major -gt 22 ]; then
GDBARGS="--annotate=3 "
elif [ '!' -z "$emacs_major" -a $emacs_major -gt 21 ]; then
GDBARGS="--annotate=1 "
fi
fi
gdbcmd="$gdbcmd $GDBBP \
(insert-string \"source $ROOTDIR/erts/etc/unix/etp-commands\") \
(comint-send-input)"
# Fire up gdb in emacs...
exec $EMACS --eval "(progn (gdb \"gdb $GDBARGS$EMU_NAME\") $gdbcmd)"
elif [ "x$GDB" = "xdump" ]; then
cmdfile="/tmp/.cerlgdb.$$"
case "x$core" in
x/*)
;;
*)
dir=`pwd`
core="${dir}/${core}"
;;
esac
case `uname` in
Darwin)
echo "
thread backtrace all
quit
" > $cmdfile
exec lldb -s $cmdfile -c ${core} $EMU_NAME
;;
*)
echo "set width 0
set height 0
set verbose off
source $ROOTDIR/erts/etc/unix/etp-commands
thread apply all bt
" > $cmdfile
exec gdb --batch --command=$cmdfile $EMU_NAME $core
;;
esac
fi
|