--- /dev/null
+#!/bin/bash
+
+IFS=: ldpath=($LD_LIBRARY_PATH)
+while read dir; do
+ if [ "${dir:0:1}" == "#" ]; then
+ continue
+ elif [ -d "$dir" ]; then
+ ldpath=$("${LDPATH[@]}" "$dir")
+ fi
+done </etc/ld.so.conf
+ldpath=("${ldpath[@]}" /usr/lib /lib)
+IFS=: apath=($PATH)
+
+findlib() {
+ for d in "${ldpath[@]}"; do
+ if [ -r "$d/$1" ]; then
+ echo "$d/$1"
+ return 0
+ fi
+ done
+ return 1
+}
+
+findbin() {
+ for d in "${apath[@]}"; do
+ if [ -r "$d/$1" ]; then
+ echo "$d/$1"
+ return 0
+ fi
+ done
+ return 1
+}
+
+has() {
+ for obj in "${found[@]}"; do
+ if [ "$obj" = "$1" ]; then return 0; fi
+ done
+ return 1
+}
+
+excluded() {
+ for obj in "${exclude[@]}"; do
+ if [ -d "$obj" ] && [[ "$1" == "$obj"* ]]; then return 0; fi
+ if [ "$1" = "$obj" ]; then return 0; fi
+ done
+ return 1
+}
+
+examine() {
+ local tfile lib lib2
+ tfile="$(mktemp /tmp/lddotXXXXXX)"
+ objdump -p "$1" | sed -n 's/^.*NEEDED \+\(lib.*\)/\1/p' >"$tfile"
+ while read lib; do
+ if ! lib2="$(findlib "$lib")"; then
+ echo "lddot: $lib: not found" >&2
+ rm -f "$tfile"
+ return 1
+ fi
+ lib="$lib2"
+ unset lib2
+ if excluded "$lib"; then continue; fi
+ echo "\"$1\" -> \"$lib\";"
+ if has "$lib"; then continue; fi
+ found=("${found[@]}" "$lib")
+ examine "$lib"
+ done <"$tfile"
+ rm -f "$tfile"
+ return 0
+}
+
+found=()
+exclude=()
+programs=()
+
+while [ $# -gt 0 ]; do
+ arg="$1"
+ shift
+ case "$arg" in
+ -x)
+ exclude=("${exclude[@]}" "$1")
+ shift
+ ;;
+ *)
+ programs=("${programs[@]}" "$arg")
+ esac
+done
+
+if [ ${#programs[@]} -lt 1 ]; then
+ echo "usage: lddot [-x EXCLUDED] PROGRAM..." >&2
+ exit 1
+fi
+
+echo "digraph {"
+rv=0
+for bin in "${programs[@]}"; do
+ if [[ "$bin" != */* ]]; then
+ if ! bin2="$(findbin "$bin")"; then
+ echo "lddot: $bin: not found" >&2
+ rv=1
+ continue
+ fi
+ bin="$bin2"
+ unset bin2
+ fi
+ if [ ! -r "$bin" ]; then
+ echo "lddot: $bin: not readable" >&2
+ rv=1
+ continue
+ fi
+ if ! examine "$bin"; then rv=1; fi
+done
+echo "}"
+
+exit $rv