Added lddot.
[utils.git] / lddot
CommitLineData
ab22601b 1#!/bin/bash
2
3IFS=: ldpath=($LD_LIBRARY_PATH)
4while read dir; do
5 if [ "${dir:0:1}" == "#" ]; then
6 continue
7 elif [ -d "$dir" ]; then
8 ldpath=$("${LDPATH[@]}" "$dir")
9 fi
10done </etc/ld.so.conf
11ldpath=("${ldpath[@]}" /usr/lib /lib)
12IFS=: apath=($PATH)
13
14findlib() {
15 for d in "${ldpath[@]}"; do
16 if [ -r "$d/$1" ]; then
17 echo "$d/$1"
18 return 0
19 fi
20 done
21 return 1
22}
23
24findbin() {
25 for d in "${apath[@]}"; do
26 if [ -r "$d/$1" ]; then
27 echo "$d/$1"
28 return 0
29 fi
30 done
31 return 1
32}
33
34has() {
35 for obj in "${found[@]}"; do
36 if [ "$obj" = "$1" ]; then return 0; fi
37 done
38 return 1
39}
40
41excluded() {
42 for obj in "${exclude[@]}"; do
43 if [ -d "$obj" ] && [[ "$1" == "$obj"* ]]; then return 0; fi
44 if [ "$1" = "$obj" ]; then return 0; fi
45 done
46 return 1
47}
48
49examine() {
50 local tfile lib lib2
51 tfile="$(mktemp /tmp/lddotXXXXXX)"
52 objdump -p "$1" | sed -n 's/^.*NEEDED \+\(lib.*\)/\1/p' >"$tfile"
53 while read lib; do
54 if ! lib2="$(findlib "$lib")"; then
55 echo "lddot: $lib: not found" >&2
56 rm -f "$tfile"
57 return 1
58 fi
59 lib="$lib2"
60 unset lib2
61 if excluded "$lib"; then continue; fi
62 echo "\"$1\" -> \"$lib\";"
63 if has "$lib"; then continue; fi
64 found=("${found[@]}" "$lib")
65 examine "$lib"
66 done <"$tfile"
67 rm -f "$tfile"
68 return 0
69}
70
71found=()
72exclude=()
73programs=()
74
75while [ $# -gt 0 ]; do
76 arg="$1"
77 shift
78 case "$arg" in
79 -x)
80 exclude=("${exclude[@]}" "$1")
81 shift
82 ;;
83 *)
84 programs=("${programs[@]}" "$arg")
85 esac
86done
87
88if [ ${#programs[@]} -lt 1 ]; then
89 echo "usage: lddot [-x EXCLUDED] PROGRAM..." >&2
90 exit 1
91fi
92
93echo "digraph {"
94rv=0
95for bin in "${programs[@]}"; do
96 if [[ "$bin" != */* ]]; then
97 if ! bin2="$(findbin "$bin")"; then
98 echo "lddot: $bin: not found" >&2
99 rv=1
100 continue
101 fi
102 bin="$bin2"
103 unset bin2
104 fi
105 if [ ! -r "$bin" ]; then
106 echo "lddot: $bin: not readable" >&2
107 rv=1
108 continue
109 fi
110 if ! examine "$bin"; then rv=1; fi
111done
112echo "}"
113
114exit $rv