/[gentoo-projects]/pax-utils/lddtree.sh
Gentoo

Contents of /pax-utils/lddtree.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.22 - (show annotations) (download) (as text)
Sun Apr 7 19:20:09 2013 UTC (20 months, 1 week ago) by vapier
Branch: MAIN
CVS Tags: HEAD
Changes since 1.21: +6 -5 lines
File MIME type: text/x-sh
lddtree: add GNU to the LINUX/SYSV/NONE compat set #464380 by cmuelle8

1 #!/bin/bash
2 # Copyright 2007-2013 Gentoo Foundation
3 # Copyright 2007-2013 Mike Frysinger <vapier@gentoo.org>
4 # Distributed under the terms of the GNU General Public License v2
5 # $Header: /var/cvsroot/gentoo-projects/pax-utils/lddtree.sh,v 1.21 2013/04/05 22:45:48 vapier Exp $
6
7 argv0=${0##*/}
8
9 : ${ROOT:=/}
10 [[ ${ROOT} != */ ]] && ROOT="${ROOT}/"
11 [[ ${ROOT} != /* ]] && ROOT="${PWD}${ROOT}"
12
13 usage() {
14 cat <<-EOF
15 Display ELF dependencies as a tree
16
17 Usage: ${argv0} [options] <ELF file[s]>
18
19 Options:
20 -a Show all duplicated dependencies
21 -x Run with debugging
22 -R <root> Use this ROOT filesystem tree
23 --no-auto-root Do not automatically prefix input ELFs with ROOT
24 -l Display output in a flat format
25 -h Show this help output
26 -V Show version information
27 EOF
28 exit ${1:-0}
29 }
30
31 version() {
32 local id='$Id: lddtree.sh,v 1.21 2013/04/05 22:45:48 vapier Exp $'
33 id=${id##*,v }
34 exec echo "lddtree-${id% * Exp*}"
35 }
36
37 error() {
38 echo "${argv0}: $*" 1>&2
39 ret=1
40 return 1
41 }
42
43 elf_specs() {
44 # With glibc, the NONE, SYSV, GNU, and LINUX OSABI's are compatible.
45 # LINUX and GNU are the same thing, as are NONE and SYSV, so normalize
46 # GNU & LINUX to NONE. #442024 #464380
47 scanelf -BF '#F%a %M %D %I' "$1" | \
48 sed -r 's: (LINUX|GNU)$: NONE:'
49 }
50
51 lib_paths_fallback="${ROOT}lib* ${ROOT}usr/lib* ${ROOT}usr/local/lib*"
52 c_ldso_paths_loaded='false'
53 find_elf() {
54 _find_elf=''
55
56 local elf=$1 needed_by=$2
57 if [[ ${elf} == */* ]] && [[ -e ${elf} ]] ; then
58 _find_elf=${elf}
59 return 0
60 else
61 check_paths() {
62 local elf=$1 ; shift
63 local path pe
64 for path ; do
65 pe="${path%/}/${elf#/}"
66 if [[ -e ${pe} ]] ; then
67 if [[ $(elf_specs "${pe}") == "${elf_specs}" ]] ; then
68 _find_elf=${pe}
69 return 0
70 fi
71 fi
72 done
73 return 1
74 }
75
76 if [[ ${c_last_needed_by} != ${needed_by} ]] ; then
77 c_last_needed_by=${needed_by}
78 c_last_needed_by_rpaths=$(scanelf -qF '#F%r' "${needed_by}" | \
79 sed -e 's|:| |g' -e "s:[$]ORIGIN:${needed_by%/*}:")
80 fi
81 check_paths "${elf}" ${c_last_needed_by_rpaths} && return 0
82
83 if [[ -n ${LD_LIBRARY_PATH} ]] ; then
84 # Need to handle empty paths as $PWD,
85 # and handle spaces in between the colons
86 local p path=${LD_LIBRARY_PATH}
87 while : ; do
88 p=${path%%:*}
89 check_paths "${elf}" "${p:-${PWD}}" && return 0
90 [[ ${path} == *:* ]] || break
91 path=${path#*:}
92 done
93 fi
94
95 if ! ${c_ldso_paths_loaded} ; then
96 c_ldso_paths_loaded='true'
97 c_ldso_paths=()
98 if [[ -r ${ROOT}etc/ld.so.conf ]] ; then
99 read_ldso_conf() {
100 local line p
101 for p ; do
102 # if the glob didnt match anything #360041,
103 # or the files arent readable, skip it
104 [[ -r ${p} ]] || continue
105 while read line ; do
106 case ${line} in
107 "#"*) ;;
108 "include "*) read_ldso_conf ${line#* } ;;
109 *) c_ldso_paths+=( "${ROOT}${line#/}" ) ;;
110 esac
111 done <"${p}"
112 done
113 }
114 # the 'include' command is relative
115 pushd "${ROOT}"etc >/dev/null
116 read_ldso_conf "${ROOT}"etc/ld.so.conf
117 popd >/dev/null
118 fi
119 fi
120 if [[ ${#c_ldso_paths[@]} -gt 0 ]] ; then
121 check_paths "${elf}" "${c_ldso_paths[@]}" && return 0
122 fi
123
124 check_paths "${elf}" ${lib_paths_ldso:-${lib_paths_fallback}} && return 0
125 fi
126 return 1
127 }
128
129 show_elf() {
130 local elf=$1 indent=$2 parent_elfs=$3
131 local rlib lib libs
132 local interp resolved
133 find_elf "${elf}"
134 resolved=${_find_elf}
135 elf=${elf##*/}
136
137 ${LIST} || printf "%${indent}s%s => " "" "${elf}"
138 if [[ ,${parent_elfs}, == *,${elf},* ]] ; then
139 ${LIST} || printf "!!! circular loop !!!\n" ""
140 return
141 fi
142 parent_elfs="${parent_elfs},${elf}"
143 if ${LIST} ; then
144 echo "${resolved:-$1}"
145 else
146 printf "${resolved:-not found}"
147 fi
148 if [[ ${indent} -eq 0 ]] ; then
149 elf_specs=$(elf_specs "${resolved}")
150 interp=$(scanelf -qF '#F%i' "${resolved}")
151 [[ -n ${interp} ]] && interp="${ROOT}${interp#/}"
152
153 if ${LIST} ; then
154 [[ -n ${interp} ]] && echo "${interp}"
155 else
156 printf " (interpreter => ${interp:-none})"
157 fi
158 if [[ -r ${interp} ]] ; then
159 # Extract the default lib paths out of the ldso.
160 lib_paths_ldso=$(
161 strings "${interp}" | \
162 sed -nr -e "/^\/.*lib/{s|^/?|${ROOT}|;s|/$||;s|/?:/?|\n${ROOT}|g;p}"
163 )
164 fi
165 interp=${interp##*/}
166 fi
167 ${LIST} || printf "\n"
168
169 [[ -z ${resolved} ]] && return
170
171 libs=$(scanelf -qF '#F%n' "${resolved}")
172
173 local my_allhits
174 if ! ${SHOW_ALL} ; then
175 my_allhits="${allhits}"
176 allhits="${allhits},${interp},${libs}"
177 fi
178
179 for lib in ${libs//,/ } ; do
180 lib=${lib##*/}
181 [[ ,${my_allhits}, == *,${lib},* ]] && continue
182 find_elf "${lib}" "${resolved}"
183 rlib=${_find_elf}
184 show_elf "${rlib:-${lib}}" $((indent + 4)) "${parent_elfs}"
185 done
186 }
187
188 # XXX: internal hack
189 if [[ $1 != "/../..source.lddtree" ]] ; then
190
191 SHOW_ALL=false
192 SET_X=false
193 LIST=false
194 AUTO_ROOT=true
195
196 while getopts haxVR:l-: OPT ; do
197 case ${OPT} in
198 a) SHOW_ALL=true;;
199 x) SET_X=true;;
200 h) usage;;
201 V) version;;
202 R) ROOT="${OPTARG%/}/";;
203 l) LIST=true;;
204 -) # Long opts ftw.
205 case ${OPTARG} in
206 no-auto-root) AUTO_ROOT=false;;
207 *) usage 1;;
208 esac
209 ;;
210 ?) usage 1;;
211 esac
212 done
213 shift $((OPTIND - 1))
214 [[ -z $1 ]] && usage 1
215
216 ${SET_X} && set -x
217
218 ret=0
219 for elf ; do
220 unset lib_paths_ldso
221 unset c_last_needed_by
222 if ${AUTO_ROOT} && [[ ${elf} == /* ]] ; then
223 elf="${ROOT}${elf#/}"
224 fi
225 if [[ ! -e ${elf} ]] ; then
226 error "${elf}: file does not exist"
227 elif [[ ! -r ${elf} ]] ; then
228 error "${elf}: file is not readable"
229 elif [[ -d ${elf} ]] ; then
230 error "${elf}: is a directory"
231 else
232 allhits=""
233 [[ ${elf} != */* ]] && elf="./${elf}"
234 show_elf "${elf}" 0 ""
235 fi
236 done
237 exit ${ret}
238
239 fi

  ViewVC Help
Powered by ViewVC 1.1.20