123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- digraph g {
- "usr\lbin\lpython" -> "linux-vdso.so.1";
- "lib\lx86_64-linux-gnu\llibpthread.so.0" -> "linux-vdso.so.1";
- "lib\lx86_64-linux-gnu\llibc.so.6" -> "lib64\lld-linux-x86-64.so.2";
- "lib\lx86_64-linux-gnu\llibc.so.6" -> "linux-vdso.so.1";
- "lib\lx86_64-linux-gnu\llibpthread.so.0" -> "lib\lx86_64-linux-gnu\llibc.so.6";
- "lib\lx86_64-linux-gnu\llibpthread.so.0" -> "lib64\lld-linux-x86-64.so.2";
- "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibpthread.so.0";
- "lib\lx86_64-linux-gnu\llibdl.so.2" -> "linux-vdso.so.1";
- "lib\lx86_64-linux-gnu\llibdl.so.2" -> "lib\lx86_64-linux-gnu\llibc.so.6";
- "lib\lx86_64-linux-gnu\llibdl.so.2" -> "lib64\lld-linux-x86-64.so.2";
- "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibdl.so.2";
- "lib\lx86_64-linux-gnu\llibutil.so.1" -> "linux-vdso.so.1";
- "lib\lx86_64-linux-gnu\llibutil.so.1" -> "lib\lx86_64-linux-gnu\llibc.so.6";
- "lib\lx86_64-linux-gnu\llibutil.so.1" -> "lib64\lld-linux-x86-64.so.2";
- "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibutil.so.1";
- "lib\lx86_64-linux-gnu\llibz.so.1" -> "linux-vdso.so.1";
- "lib\lx86_64-linux-gnu\llibz.so.1" -> "lib\lx86_64-linux-gnu\llibc.so.6";
- "lib\lx86_64-linux-gnu\llibz.so.1" -> "lib64\lld-linux-x86-64.so.2";
- "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibz.so.1";
- "lib\lx86_64-linux-gnu\llibm.so.6" -> "linux-vdso.so.1";
- "lib\lx86_64-linux-gnu\llibm.so.6" -> "lib\lx86_64-linux-gnu\llibc.so.6";
- "lib\lx86_64-linux-gnu\llibm.so.6" -> "lib64\lld-linux-x86-64.so.2";
- "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibm.so.6";
- "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibc.so.6";
- "usr\lbin\lpython" -> "lib64\lld-linux-x86-64.so.2";
- }
- @
- # convert ldd info into a dot graph, example:
- # python ldd2dot.py /usr/bin/python2 > python2.dot
- import re
- import sys
- from subprocess import Popen, PIPE
- MAXDEPTH = 4
- def _cook_path(s):
- return r"\l".join(filter(lambda _: _, s.split("/")))
- def ldd(depth, tl, dejav):
- if depth >= MAXDEPTH:
- return
- proc = Popen(['ldd', tl], stdout=PIPE)
- stdo, stde = proc.communicate()
- for line in stdo.split("\n"):
- m1 = re.search(r"[ \t]+(.*)[ \t]+=>[ \t]*(.*)[ \t]+\(.*\)", line)
- m2 = re.search(r"[ \t]+(.*)[ \t]+\(.*\)", line)
- s = ""
- if m1:
- if m1.group(2):
- s = m1.group(2)
- else:
- s = m1.group(1)
- if s.startswith("/") and s not in dejav:
- dejav.add(s)
- ldd(depth + 1, s, dejav)
- elif m2:
- s = m2.group(1)
- if s:
- print(' "%s" -> "%s";' % (_cook_path(tl), _cook_path(s)))
- print("digraph g {")
- ldd(1, sys.argv[1], set())
- print("}")
- or as bash script
- #!/bin/bash
- # This is the maximum depth to which dependencies are resolved
- MAXDEPTH=14
- # Get the filename witout extension from a path
- # Usage: createname [PATH]
- function createname
- {
- local STR=$(basename $1 | awk -F "." '{ print $1 }' | sed 's/-//g')
- echo $STR
- }
- # 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=$(createname $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=$(echo -e "$LIST\n$NAME")
-
- DEPTH=$[$DEPTH + 1]
- if [ $DEPTH -ge $MAXDEPTH ];
- then
- echo "MAXDEPTH of $MAXDEPTH reached at file $IN."
- echo "Continuing with next file..."
- # Fix by Marco Nellisen for the case that MAXDEPTH was reached
- DEPTH=$[$DEPTH - 1]
- return
- fi
- echo "Parsing file: $IN"
- ldd $IN &> $LDDTMPFILE
- RET=$?
- if [ $RET != 0 ];
- then
- echo "ERROR: ldd returned error code $RET"
- echo "ERROR:"
- cat $TMPFILE
- echo "Aborting..."
- rm $TMPFILE
- exit 1
- fi
- # DEPENDENCIES=$(cat $TMPFILE | awk -F " " '{ if( $3 == "" ) print $1; else print $3; }')
- # DEPENDENCIES=$(cat $LDDTMPFILE | awk -F " " '{ print $3; }')
- DEPENDENCIES=$(cat $LDDTMPFILE | awk -F " " '{ if (!match($3, /\(.*\)/) && substr( $0, 1, 13 ) != "ldd: warning:") print $3; }')
- for DEP in $DEPENDENCIES;
- do
- if [ -n "$DEP" ];
- then
- echo -e " \"$NAME\" -> \"$(createname $DEP)\";" >> $OUT
- analyze $OUT "$DEP"
- 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)
- LIST=""
- if [ ! -e $INPUT ];
- then
- echo "ERROR: File not found: $INPUT"
- echo "Aborting..."
- exit 2
- fi
- echo "Analyzing dependencies of: $INPUT"
- echo "Creating output as: $OUTPUT"
- echo ""
- echo "digraph DependecyTree {" > $TMPFILE
- echo " $(createname $INPUT) [shape=box];" >> $TMPFILE
- analyze $TMPFILE "$INPUT"
- echo "}" >> $TMPFILE
- #cat $TMPFILE # output generated dotfile for debugging purposses
- dot -Tpng $TMPFILE -o$OUTPUT
- rm $LDDTMPFILE
- rm $TMPFILE
- exit 0
|