blob: 17d71d32c01d99a88508363dcdb1840d11244b71 [file] [log] [blame]
#!/bin/sh
# **********************************************************
# Copyright (c) 2011-2022 Google, Inc. All rights reserved.
# Copyright (c) 2002-2010 VMware, Inc. All rights reserved.
# **********************************************************
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
#
# * Neither the name of VMware, Inc. nor the names of its contributors may be
# used to endorse or promote products derived from this software without
# specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
# Copyright (c) 2001-2002 Massachusetts Institute of Technology
# Copyright (c) 2001-2002 Hewlett-Packard Company
###########################################################################
##
## DynamoRIO @name@ script for Linux
##
## Usage for drrun or drinject:
## For a single client, use the -c form and separate the application with --:
## @name@ [-v] [-debug] [-dr_home <path>] [-logdir <path>]
## [<dr_options>]* -c <path> [client_ops]*
## -- <executable> [args ...]
##
## For multiple clients, use either of these forms:
## @name@ [-v] [-debug] [-dr_home <path>] [-logdir <path>]
## -client <path> <id> "<client_ops>" [<dr_options>]*
## -- <executable> [args ...]
##
## @name@ [-v] [-debug] [-dr_home <path>] [-ops <dr_options>]*
## [-logdir <path>] -client <path> <executable> [args ...]
##
## For drconfig, use the -reg or -unreg options described below.
##
## Option explanation:
## [-v] Verbose output
## [-debug] Use debug build of DynamoRIO (release is default)
## [-@archother@] Use @archother@-bit DynamoRIO (default is @archdefault@-bit). This
## should match what the client library and executable
## being run were compiled for.
## [-norun] Requests that an application NOT be run under DR
## control. Useful for following all child processes
## except a blocklist. DR will still be loaded, and
## the app API available.
## [-reg <executable>] Only for drconfig. Creates configuration file for
## the specified application name.
## [-unreg <executable>] Only for drconfig. Removes configuration file for
## the specified application name.
## [-dr_home <path>] Path to the DynamoRIO install.
## Defaults to .. from @name@; may also be omitted
## if DYNAMORIO_HOME is defined in the environment.
## [-ops <dr_options>] DynamoRIO options (such as -stderr_mask 0xc
## or -opt_memory: see docs). Can also be specified
## with DYNAMORIO_OPTIONS in the environment.
## Can be repeated.
## If the application is separated by "--", the
## "-ops" is not required.
## [-logdir <path>] Path to logging directory. Defaults to ../logs from
## @name@; may also be omitted if DYNAMORIO_LOGDIR
## is defined in the environment.
## [-c <path> <options>*] Registers one client to run alongside DR. Assigns
## the client an id of 0. All remaining arguments
## until the -- arg before the app are interpreted as
## client options. Must come after all drrun and DR
## ops. Incompatible with -client. Requires using --
## to separate the app executable.
## [-client <path> <ID> "<options>"]
## Register one or more clients to run alongside DR.
## This option is only valid when registering a
## process. The -client option takes three arguments:
## the full path to a client library, a unique 8-digit
## hex ID, and an optional list of client options
## (use "" to specify no options). Multiple clients
## can be installed via multiple -client options. In
## this case, clients specified first on the command
## line have higher priority. Neither the path nor
## the options may contain semicolon characters.
## <executable> [args...] The executable to run under DynamoRIO (and the args
## to pass to it if running now).
lib=release
arch=@archdefault@
# drconfig: config=1, runapp=0
# drrun: config=1, runapp=1
# drinject: config=0, runapp=1
config=@config@
runapp=@runapp@
static=@static@
default_home_rel="`dirname $0`/.."
default_home=`cd $default_home_rel ; pwd`
client_list=""
rununder=1
unreg=0
app=""
if [ "$1" = "" ] || [ "$1" = "-h" ] || [ "$1" = "-help" ] || [ "$1" = "--help" ]
then
# sed would be more precise but may not be available
head -n 101 $0 | tail -n 65
exit
fi
early=""
verbose=""
specified_ops=""
# Read options
while [ "$1" = "-v" ] || [ "$1" = "-debug" ] || [ "$1" = "-dr_home" ] || \
[ "$1" = "-ops" ] || [ "$1" = "-logdir" ] || [ "$1" = "-client" ] || \
[ "$1" = "-32" ] || [ "$1" = "-64" ] || [ "$1" = "-norun" ] || \
[ "$1" = "-reg" ] || [ "$1" = "-unreg" ] || [ "$1" = "-early" ]
do
if [ "$1" = "-early" ]
then
early=yes
specified_ops=yes
if [ -n "$ops" ]
then
ops="$ops -early_inject"
else
ops="-early_inject"
fi
shift
fi
if [ "$1" = "-v" ]
then
verbose=yes
shift
fi
if [ "$1" = "-debug" ]
then
lib=debug
shift
fi
if [ "$1" = "-norun" ]
then
rununder=0
shift
fi
if [ "$1" = "-reg" ] && [ "$config" = "1" ]
then
shift
app="$1"
shift
fi
if [ "$1" = "-unreg" ] && [ "$config" = "1" ]
then
unreg=1
shift
app="$1"
shift
fi
if [ "$1" = "-32" ]
then
arch=32
shift
fi
if [ "$1" = "-64" ]
then
arch=64
shift
fi
if [ "$1" = "-dr_home" ]
then
shift
DYNAMORIO_HOME="$1"
shift
fi
if [ "$1" = "-ops" ]
then
shift
specified_ops=yes
if [ -n "$ops" ]
then
ops="$ops $1"
else
ops="$1"
fi
shift
fi
if [ "$1" = "-logdir" ]
then
shift
logdir=$1
shift
fi
if [ "$1" = "-client" ]
then
shift
client="$1"
shift
client_id="$1"
shift
client_ops="$1"
shift
# setup client
if [ ! -n "$client" ] || [ ! -n "$client_id" ]
then
echo "ERROR - client not fully specified"
echo "$usage"
exit
fi
if [ ! -e $client ]
then
echo "ERROR - client lib $client not found"
echo "$usage"
exit
fi
# convert to absolute path
client=`cd \`dirname $client\` ; pwd`/`basename $client`
# add to list now in case multiple
if [ -n "$client_list" ]
then
client_list="${client_list};${client};${client_id};${client_ops}"
else
client_list="${client};${client_id};${client_ops}"
fi
fi
done
# if there are still options, assume user is using -- to separate and
# pass through options to DR. we do not handle mixing DR options with
# script options: DR must come last. we would need to generate
# code here from optionsx.h to do otherwise, or to sanity check
# the DR options here.
case "$1" in
-*)
specified_ops=yes
while [ "$1" != "--" ] && [ "$1" != "" ] && [ "$1" != "-c" ]
do
if [ -n "$ops" ]
then
ops="$ops $1"
else
ops="$1"
fi
shift
done
# Support alternative client specification:
# drrun [script ops...] [dr ops...] -c <client> [client ops...] -- app
if [ "$1" = "-c" ]
then
shift
client="$1"
shift
client_id=0
client_ops=""
# setup client
if [ ! -n "$client" ]
then
echo "ERROR - client not fully specified"
echo "$usage"
exit
fi
if [ ! -e $client ]
then
echo "ERROR - client lib $client not found"
echo "$usage"
exit
fi
while [ "$1" != "--" ] && [ "$1" != "" ]
do
if [ -n "$client_ops" ]
then
client_ops="$client_ops $1"
else
client_ops="$1"
fi
shift
done
# convert to absolute path
client=`cd \`dirname $client\` ; pwd`/`basename $client`
if [ -n "$client_list" ]
then
echo "ERROR - cannot use multiple clients with -c"
exit 1
else
client_list="${client};${client_id};${client_ops}"
fi
fi
# -- indicates app command.
if [ "$1" = "--" ]
then
shift
fi
;;
esac
if [ ! -n "$DYNAMORIO_HOME" ]
then
DYNAMORIO_HOME="$default_home"
fi
if [ "$static" = "0" ]
then
# Setup lib path
if [ ! -n "$dr_lib_path" ]
then
dr_lib_path=$DYNAMORIO_HOME/lib$arch
dr_ext_path=$DYNAMORIO_HOME/ext/lib$arch
fi
if [ ! -e "$dr_lib_path/$lib/libdynamorio.so" ]
then
# Support running from old build dir layout
dr_lib_build_path=$DYNAMORIO_HOME/lib
dr_ext_build_path=$DYNAMORIO_HOME/ext/lib
if [ -e "$dr_lib_build_path/libdynamorio.so" ]
then
lib=""
dr_lib_path=$dr_lib_build_path
dr_ext_path=$dr_ext_build_path
else
if [ "$unreg" = "0" ] && [ "$rununder" = "1" ]
then
echo "ERROR - libdynamorio.so not found in $dr_lib_path/$lib"
echo "$usage"
exit
fi
fi
fi
# convert to absolute path
dr_lib_path=`cd "$dr_lib_path" ; pwd`
dr_ext_path=`cd "$dr_ext_path" ; pwd`
fi
if [ ! -n "$*" ] && [ "$app" = "" ]
then
echo "ERROR - no application specified"
echo "$usage"
exit
fi
# setup logdir
if [ ! -n "$logdir" ]
then
if [ -n "$DYNAMORIO_LOGDIR" ]
then
logdir=$DYNAMORIO_LOGDIR
else
logdir=$default_home/logs
fi
fi
if [ ! -d $logdir ]
then
if [ "$unreg" = "0" ] && [ "$rununder" = "1" ]
then
echo "ERROR - logdir $logdir not found"
echo "$usage"
exit
fi
fi
# convert to absolute path and export
export DYNAMORIO_LOGDIR=`cd $logdir ; pwd`
# client options
if [ -n "$client_list" ]
then
client_op_string="-code_api -client_lib \"$client_list\""
else
client_op_string=""
fi
# setup options
if [ "$specified_ops" = "yes" ]
then
export DYNAMORIO_OPTIONS="${client_op_string} $ops"
else
export DYNAMORIO_OPTIONS="${client_op_string} $DYNAMORIO_OPTIONS"
fi
# i#85/PR 212034: we now use config files
if [ ! -n "$DYNAMORIO_CONFIGDIR" ]
then
if [ -n "$HOME" ] && [ -d "$HOME" ]
then
export DYNAMORIO_CONFIGDIR=$HOME
elif [ "$config" = "1" ] && [ "$runapp" = "1" ];
then
# If creating an anonymous config file, use a temp dir rather
# than failing if there's no $HOME or specified dir.
# We don't want to run mktemp b/c we'd leave an empty dir behind
# on every run. We match drconfiglib, except we also check for
# existence up front, and we prefer /tmp to $PWD. Xref i#939.
if [ -n "$TMP" ] && [ -d "$TMP" ]
then
export DYNAMORIO_CONFIGDIR=$TMP
elif [ -n "$TEMP" ] && [ -d "$TEMP" ]
then
export DYNAMORIO_CONFIGDIR=$TEMP
elif [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]
then
export DYNAMORIO_CONFIGDIR=$TMPDIR
elif [ -d "/tmp" ]
then
export DYNAMORIO_CONFIGDIR="/tmp"
else
# last resort: cur dir
export DYNAMORIO_CONFIGDIR=$PWD
fi
fi
fi
if [ ! -d "$DYNAMORIO_CONFIGDIR" ]
then
echo "ERROR - neither DYNAMORIO_CONFIGDIR nor HOME exists"
exit
fi
cfgdir="$DYNAMORIO_CONFIGDIR/.dynamorio"
if [ ! -d $cfgdir ]
then
mkdir -p "$cfgdir"
if [ "$?" != 0 ]
then
echo "ERROR - failed to create config dir $cfgdir"
exit
fi
fi
if [ "$app" = "" ]
then
app="$1"
shift
fi
# better to require bash and use ${app##*/}?
name=`basename $app`
if [ "$early" = "yes" ]
then
appwhich=`which $app`
if [ "$appwhich" = "" ]
then
appwhich=$app
fi
appdir=`dirname $appwhich`
fullpath=`cd $appdir;pwd`
fullname="$fullpath/$name"
fi
if [ "$config" = "1" ]
then
if [ "$runapp" = "1" ]
then
cfgfile="$cfgdir/$name.$$.1config$arch"
echo "# one-time config file" > $cfgfile
if [ "$verbose" = "yes" ]
then
echo "Using $lib DynamoRIO ($dr_lib_path/$lib/libdynamorio.so)"
echo "With DynamoRIO options=\"$DYNAMORIO_OPTIONS\""
echo "Using logging directory=\"$DYNAMORIO_LOGDIR\""
echo "Running \"$app $*\""
fi
else
cfgfile="$cfgdir/$name.config$arch"
echo "# DynamoRIO config file" > $cfgfile
fi
if [ "$unreg" = "1" ]
then
rm $cfgfile
if [ "$verbose" = "yes" ]
then
echo "Removed config file $cfgfile"
fi
exit 0
else
echo "DYNAMORIO_RUNUNDER=${rununder}" >> $cfgfile
echo "DYNAMORIO_OPTIONS=$DYNAMORIO_OPTIONS" >> $cfgfile
echo "DYNAMORIO_LOGDIR=$DYNAMORIO_LOGDIR" >> $cfgfile
echo "DYNAMORIO_AUTOINJECT=$dr_lib_path/$lib/libdynamorio.so" >> $cfgfile
echo "DYNAMORIO_HOME=$dr_lib_path" >> $cfgfile
fi
fi
if [ "$runapp" = "1" ]
then
# keep same pid for easier scripting
if [ "$early" = "yes" ]
then
drloader="$DYNAMORIO_HOME/bin$arch/drloader"
if [ "$verbose" = "yes" ]
then
echo "experimental support for early injection in Linux"
fi
exec "$drloader" "$dr_lib_path/$lib/libdynamorio.so" "$fullname" "$@"
else
if [ "$static" = "1" ]
then
export DYNAMORIO_TAKEOVER_IN_INIT=1
else
export LD_LIBRARY_PATH=$dr_lib_path/$lib:$dr_ext_path/$lib:$LD_LIBRARY_PATH
export LD_PRELOAD="libdynamorio.so libdrpreload.so"
if [ -z "$LD_USE_LOAD_BIAS" ]
then
if [ "$verbose" = "yes" ]
then
echo "Setting LD_USE_LOAD_BIAS for PIEs (i#719)"
echo "Set LD_USE_LOAD_BIAS=0 prior to running this script"
echo "if this is a problem"
fi
export LD_USE_LOAD_BIAS=1
fi
fi
exec $app "$@"
fi
else
if [ "$verbose" = "yes" ]
then
echo "Wrote config file $cfgfile"
exit 0
fi
fi
exit 1