Your IP : 216.73.217.87
| Current Path : /usr/X11R6/bin/ |
|
|
| Current File : //usr/X11R6/bin/draw_lib_dependencies |
#!/bin/bash
# Copyright 2013 Dominik Seichter <domseichter@googlemail.com>
#
# 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 2 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/>.
# This is the maximum depth to which dependencies are resolved
MAXDEPTH=14
TMPFILE=
READELFTMPFILE=
LDDTMPFILE=
cleanup() {
for _v in TMPFILE READELFTMPFILE LDDTMPFILE; do
[ -n "${!_v}" ] && rm -f -- "${!_v}"
done
}
trap cleanup EXIT
# analyze a given file on its
# dependecies using ldd and write
# the results to a given temporary file
#
# Usage: analyze [OUTPUTFILE] [INPUTFILE]
analyze()
{
local OUT="$1"
local IN="$2"
local NAME=$(basename "$IN")
for i in $LIST
do
if [ X"$i" == X"$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" 2>&1
ELFRET=$?
if [ $ELFRET != 0 ];
then
echo "ERROR: ELF reader returned error code $RET"
echo "ERROR:"
cat -v -- "$TMPFILE"
echo "Aborting..."
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
# XXX Change ldd to something more secure?
ldd "$IN" > "$LDDTMPFILE" 2>&1
LDDRET=$?
if [ $LDDRET != 0 ];
then
echo "ERROR: ldd returned error code $RET"
echo "ERROR:"
cat -v -- "$TMPFILE"
echo "Aborting..."
exit 1
fi
DEPPATH=$(grep -- "$DEP" "$LDDTMPFILE" | awk '{print $3}')
if [ -n "$DEPPATH" ];
then
echo " \"$NAME\" -> \"$DEP\";" >> $OUT
analyze "$OUT" "$DEPPATH"
fi
fi
done
DEPTH=$(($DEPTH - 1))
}
########################################
# main #
########################################
if [ $# != 2 ];
then
echo "Usage:"
echo " $0 [filename] [outputimage]"
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."
echo ""
exit 1
fi
DEPTH=0
INPUT="$1"
OUTPUT="$2"
TMPFILE="$(mktemp -t)"
LDDTMPFILE="$(mktemp -t)"
READELFTMPFILE="$(mktemp -t)"
LIST=""
if [ ! -e "$INPUT" ];
then
echo "ERROR: File not found: $INPUT"
echo "Aborting..."
exit 2
fi
# 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 "Creating output as: $OUTPUT"
echo ""
echo "digraph DependencyTree {" > "$TMPFILE"
echo " \"$(basename $INPUT)\" [shape=box];" >> "$TMPFILE"
analyze "$TMPFILE" "$INPUT"
echo "}" >> "$TMPFILE"
#cat $TMPFILE # output generated dotfile for debugging purposses
dot -Tpng "$TMPFILE" "-o$OUTPUT"
exit 0