lddpython.dot 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. digraph g {
  2. "usr\lbin\lpython" -> "linux-vdso.so.1";
  3. "lib\lx86_64-linux-gnu\llibpthread.so.0" -> "linux-vdso.so.1";
  4. "lib\lx86_64-linux-gnu\llibc.so.6" -> "lib64\lld-linux-x86-64.so.2";
  5. "lib\lx86_64-linux-gnu\llibc.so.6" -> "linux-vdso.so.1";
  6. "lib\lx86_64-linux-gnu\llibpthread.so.0" -> "lib\lx86_64-linux-gnu\llibc.so.6";
  7. "lib\lx86_64-linux-gnu\llibpthread.so.0" -> "lib64\lld-linux-x86-64.so.2";
  8. "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibpthread.so.0";
  9. "lib\lx86_64-linux-gnu\llibdl.so.2" -> "linux-vdso.so.1";
  10. "lib\lx86_64-linux-gnu\llibdl.so.2" -> "lib\lx86_64-linux-gnu\llibc.so.6";
  11. "lib\lx86_64-linux-gnu\llibdl.so.2" -> "lib64\lld-linux-x86-64.so.2";
  12. "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibdl.so.2";
  13. "lib\lx86_64-linux-gnu\llibutil.so.1" -> "linux-vdso.so.1";
  14. "lib\lx86_64-linux-gnu\llibutil.so.1" -> "lib\lx86_64-linux-gnu\llibc.so.6";
  15. "lib\lx86_64-linux-gnu\llibutil.so.1" -> "lib64\lld-linux-x86-64.so.2";
  16. "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibutil.so.1";
  17. "lib\lx86_64-linux-gnu\llibz.so.1" -> "linux-vdso.so.1";
  18. "lib\lx86_64-linux-gnu\llibz.so.1" -> "lib\lx86_64-linux-gnu\llibc.so.6";
  19. "lib\lx86_64-linux-gnu\llibz.so.1" -> "lib64\lld-linux-x86-64.so.2";
  20. "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibz.so.1";
  21. "lib\lx86_64-linux-gnu\llibm.so.6" -> "linux-vdso.so.1";
  22. "lib\lx86_64-linux-gnu\llibm.so.6" -> "lib\lx86_64-linux-gnu\llibc.so.6";
  23. "lib\lx86_64-linux-gnu\llibm.so.6" -> "lib64\lld-linux-x86-64.so.2";
  24. "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibm.so.6";
  25. "usr\lbin\lpython" -> "lib\lx86_64-linux-gnu\llibc.so.6";
  26. "usr\lbin\lpython" -> "lib64\lld-linux-x86-64.so.2";
  27. }
  28. @
  29. # convert ldd info into a dot graph, example:
  30. # python ldd2dot.py /usr/bin/python2 > python2.dot
  31. import re
  32. import sys
  33. from subprocess import Popen, PIPE
  34. MAXDEPTH = 4
  35. def _cook_path(s):
  36. return r"\l".join(filter(lambda _: _, s.split("/")))
  37. def ldd(depth, tl, dejav):
  38. if depth >= MAXDEPTH:
  39. return
  40. proc = Popen(['ldd', tl], stdout=PIPE)
  41. stdo, stde = proc.communicate()
  42. for line in stdo.split("\n"):
  43. m1 = re.search(r"[ \t]+(.*)[ \t]+=>[ \t]*(.*)[ \t]+\(.*\)", line)
  44. m2 = re.search(r"[ \t]+(.*)[ \t]+\(.*\)", line)
  45. s = ""
  46. if m1:
  47. if m1.group(2):
  48. s = m1.group(2)
  49. else:
  50. s = m1.group(1)
  51. if s.startswith("/") and s not in dejav:
  52. dejav.add(s)
  53. ldd(depth + 1, s, dejav)
  54. elif m2:
  55. s = m2.group(1)
  56. if s:
  57. print(' "%s" -> "%s";' % (_cook_path(tl), _cook_path(s)))
  58. print("digraph g {")
  59. ldd(1, sys.argv[1], set())
  60. print("}")
  61. or as bash script
  62. #!/bin/bash
  63. # This is the maximum depth to which dependencies are resolved
  64. MAXDEPTH=14
  65. # Get the filename witout extension from a path
  66. # Usage: createname [PATH]
  67. function createname
  68. {
  69. local STR=$(basename $1 | awk -F "." '{ print $1 }' | sed 's/-//g')
  70. echo $STR
  71. }
  72. # analyze a given file on its
  73. # dependecies using ldd and write
  74. # the results to a given temporary file
  75. #
  76. # Usage: analyze [OUTPUTFILE] [INPUTFILE]
  77. function analyze
  78. {
  79. local OUT=$1
  80. local IN=$2
  81. local NAME=$(createname $IN)
  82. for i in $LIST
  83. do
  84. if [ "$i" == "$NAME" ];
  85. then
  86. # This file was already parsed
  87. return
  88. fi
  89. done
  90. # Put the file in the list of all files
  91. LIST=$(echo -e "$LIST\n$NAME")
  92. DEPTH=$[$DEPTH + 1]
  93. if [ $DEPTH -ge $MAXDEPTH ];
  94. then
  95. echo "MAXDEPTH of $MAXDEPTH reached at file $IN."
  96. echo "Continuing with next file..."
  97. # Fix by Marco Nellisen for the case that MAXDEPTH was reached
  98. DEPTH=$[$DEPTH - 1]
  99. return
  100. fi
  101. echo "Parsing file: $IN"
  102. ldd $IN &> $LDDTMPFILE
  103. RET=$?
  104. if [ $RET != 0 ];
  105. then
  106. echo "ERROR: ldd returned error code $RET"
  107. echo "ERROR:"
  108. cat $TMPFILE
  109. echo "Aborting..."
  110. rm $TMPFILE
  111. exit 1
  112. fi
  113. # DEPENDENCIES=$(cat $TMPFILE | awk -F " " '{ if( $3 == "" ) print $1; else print $3; }')
  114. # DEPENDENCIES=$(cat $LDDTMPFILE | awk -F " " '{ print $3; }')
  115. DEPENDENCIES=$(cat $LDDTMPFILE | awk -F " " '{ if (!match($3, /\(.*\)/) && substr( $0, 1, 13 ) != "ldd: warning:") print $3; }')
  116. for DEP in $DEPENDENCIES;
  117. do
  118. if [ -n "$DEP" ];
  119. then
  120. echo -e " \"$NAME\" -> \"$(createname $DEP)\";" >> $OUT
  121. analyze $OUT "$DEP"
  122. fi
  123. done
  124. DEPTH=$[$DEPTH - 1]
  125. }
  126. ########################################
  127. # main #
  128. ########################################
  129. if [ $# != 2 ];
  130. then
  131. echo "Usage:"
  132. echo " $0 [filename] [outputimage]"
  133. echo ""
  134. echo "This tools analyses a shared library or an executable"
  135. echo "and generates a dependency graph as an image."
  136. echo ""
  137. echo "GraphViz must be installed for this tool to work."
  138. echo ""
  139. exit 1
  140. fi
  141. DEPTH=0
  142. INPUT=$1
  143. OUTPUT=$2
  144. TMPFILE=$(mktemp -t)
  145. LDDTMPFILE=$(mktemp -t)
  146. LIST=""
  147. if [ ! -e $INPUT ];
  148. then
  149. echo "ERROR: File not found: $INPUT"
  150. echo "Aborting..."
  151. exit 2
  152. fi
  153. echo "Analyzing dependencies of: $INPUT"
  154. echo "Creating output as: $OUTPUT"
  155. echo ""
  156. echo "digraph DependecyTree {" > $TMPFILE
  157. echo " $(createname $INPUT) [shape=box];" >> $TMPFILE
  158. analyze $TMPFILE "$INPUT"
  159. echo "}" >> $TMPFILE
  160. #cat $TMPFILE # output generated dotfile for debugging purposses
  161. dot -Tpng $TMPFILE -o$OUTPUT
  162. rm $LDDTMPFILE
  163. rm $TMPFILE
  164. exit 0