Skip to content

Instantly share code, notes, and snippets.

@suapapa
Created May 10, 2012 03:13
Show Gist options
  • Save suapapa/2650813 to your computer and use it in GitHub Desktop.
Save suapapa/2650813 to your computer and use it in GitHub Desktop.
Visualize dependencies of binaries and libraries on Linux
#!/bin/bash
# Original script came from;
# http://domseichter.blogspot.com/2008/02/visualize-dependencies-of-binaries-and.html
# Written by Dominik Seichter and added patch from pfree
# analyze a given file on its
# dependecies using ldd and write
# the results to a given temporary file
#
# Usage: analyze [OUTPUTFILE] [INPUTFILE]
function analyze
{
local OUT=$1
local IN=$2
local NAME=$(basename $IN)
for i in $LIST
do
if [ "$i" == "$NAME" ];
then
# This file was already parsed
return
fi
done
# Put the file in the list of all files
LIST="$LIST $NAME"
DEPTH=$[$DEPTH + 1]
if [ $DEPTH -ge $MAXDEPTH ];
then
echo "MAXDEPTH of $MAXDEPTH reached at file $IN."
echo "Continuing with next file..."
return
fi
echo "Parsing file: $IN"
$READELF $IN &> $READELFTMPFILE
ELFRET=$?
if [ $ELFRET != 0 ];
then
echo "ERROR: ELF reader returned error code $RET"
echo "ERROR:"
cat $TMPFILE
echo "Aborting..."
rm $TMPFILE
rm $READELFTMPFILE
rm $OBJDUMPTMPFILE
exit 1
fi
DEPENDENCIES=$(cat $READELFTMPFILE | grep NEEDED | awk '{if (substr($NF,1,1) == "[") print substr($NF, 2, length($NF) - 2); else print $NF}')
for DEP in $DEPENDENCIES;
do
if [ -n "$DEP" ];
then
objdump -x $IN | grep NEEDED &> $OBJDUMPTMPFILE
OBJDUMPRET=$?
if [ $OBJDUMPRET != 0 ];
then
echo "ERROR: objdump returned error code $RET"
echo "ERROR:"
cat $TMPFILE
echo "Aborting..."
rm $TMPFILE
rm $READELFTMPFILE
rm $OBJDUMPTMPFILE
exit 1
fi
DEPPATH=$(grep $DEP $OBJDUMPTMPFILE | awk '{print $2}')
if [ -n "$DEPPATH" ];
then
echo -e " \"$NAME\" -> \"$DEP\";" >> $OUT
analyze $OUT $DEPPATH
fi
fi
done
DEPTH=$[$DEPTH - 1]
}
########################################
# main #
########################################
MAXDEPTH=14
while getopts "d:o:" OPT; do
case "$OPT" in
d) MAXDEPTH=$OPTARG;;
o) OUTPUT=$OPTARG;;
[?]) echo "Usage: $0 [-d max_depth] [-o output_png] FILE" >&2
echo
echo "This tools analyses a shared library or an executable"
echo "and generates a dependency graph as an image."
echo
echo "GraphViz must be installed for this tool to work."
exit 1;;
esac
done
shift $((OPTIND-1))
INPUT=$@
if [ ! -e $INPUT ]; then
echo "ERROR: File not found: $INPUT"
echo "Aborting..."
exit 2
fi
DEPTH=0
TMPFILE=$(mktemp -t)
OBJDUMPTMPFILE=$(mktemp -t)
READELFTMPFILE=$(mktemp -t)
LIST=""
# Use either readelf or dump
# Linux has readelf, Solaris has dump
READELF=$(type readelf 2> /dev/null)
if [ $? != 0 ]; then
READELF=$(type dump 2> /dev/null)
if [ $? != 0 ]; then
echo Unable to find ELF reader
exit 1
fi
READELF="dump -Lv"
else
READELF="readelf -d"
fi
echo "Analyzing dependencies of $INPUT...
"
echo "digraph DependencyTree {" > $TMPFILE
echo " \"$(basename $INPUT)\" [shape=box];" >> $TMPFILE
analyze $TMPFILE "$INPUT"
echo "}" >> $TMPFILE
if [ -z $OUTPUT ]; then
cat $TMPFILE # output generated dotfile for debugging purposses
else
echo "Creating output as $OUTPUT..."
dot -Tpng $TMPFILE -o$OUTPUT
fi
rm $OBJDUMPTMPFILE
rm $TMPFILE
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment