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

Contents of /pax-utils/lddtree.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (hide annotations) (download) (as text)
Thu Nov 15 20:35:04 2012 UTC (2 years, 1 month ago) by vapier
Branch: MAIN
Changes since 1.16: +4 -3 lines
File MIME type: text/x-sh
lddtree: implement $ORIGIN support

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

  ViewVC Help
Powered by ViewVC 1.1.20