3 # NON-CONFIGURABLE STUFF!
5 version="@@CT_VERSION@@"
10 my_name="$( basename "${0}" )"
13 readelf="${prefix}-readelf"
14 fake_load_addr_root="$((0xdeadbeef))"
15 fake_load_addr_sysroot="$((0x8badf00d))"
16 ld_library_path="/lib:/usr/lib"
19 printf "%s: %s\n" "${my_name}" "$*" >&2
24 printf "Try \`%s --help' for more information\n" >&2
30 [ -z "${CT_XLDD_VERBOSE}" ] && return 0
32 for((depth=0; "${#FUNCNAME[$((depth+1))]}" != 0; depth++)); do :; done
33 printf "%*s" $((4*(depth-1))) "" >&2
38 # Fake a real ldd, just in case some dumb script would check
40 ldd (crosstool-NG) ${version}
41 Copyright (C) 2010 "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
42 This is free software; see the source for copying conditions. There is NO
43 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
44 Licensed under the GPLv2, see the file LICENSES in the top-directory of the
45 sources for this package.
51 Usage: ${my_name} [OPTION]... --root DIR FILE...
52 --help print this help and exit
53 --version print version information and exit
54 --root dir treat dir as being the root of the target
55 -s, --show-system mark libs from the sysroot with a trailing '[*]'
59 ${my_name} tries to mimick the behavior of a real native ldd, but can be
60 used in a cross-development environment. Here is how it differs from a
63 If the CT_XLDD_DEBUG variable is set and non-empty, then ${myname} will
64 print a lot of debug messages, explaining how it builds the library
65 search path, and how each library was found and why.
67 The LD_LIBRARY_PATH variable is not used, as it can not reliably be
68 guessed except at runtime, and we can't run.
70 ${my_name} does not scan /etc/ld.so.cache, but instead uses /etc/ld.so.conf
71 (it understands the include directives therein for libces that have that).
73 ${my_name} will search the directory specified with --root for libraries
74 to resolve the NEEDED tags. If --root is not set, then ${my_name} will
75 use the value in the environment variable \${CT_XLDD_ROOT}. If neither
76 is set, then this is an error.
78 If NEEDED libraries can't be found in the specified root directory, then
79 ${my_name} will also look in the sysroot of the toolchain to see if it
82 For NEEDED libraries that were found, the output will look like:
83 libneeded.so => /path/to/libneeded.so (0xloadaddr)
85 and for those that were not found, the output will look like:
86 libneeded.so not found
88 The paths are relative to the specified root directory, or to the sysroot
89 (eg. /lib/libneeded.so, /usr/lib/libneeded.so, and so on...).
91 The expected load address 'loadaddr' is a faked address to match the output
92 of the real ldd, but has no actual meaning (set to some constants for now,
93 0x8badf00d for libraries from the sysroot, 0xdeadbeef for others).
97 # -d, --data-relocs process data relocations
98 # -r, --function-relocs process data and function relocations
99 # -u, --unused print unused direct dependencies
100 # -v, --verbose print all information
102 # See also this thread:
103 # http://sourceware.org/ml/crossgcc/2008-09/msg00057.html
106 # Parse command line options
107 root="${CT_XLDD_ROOT}"
130 do_opt_error "unrecognized option \`${1}'"
141 if [ -z "${root}" ]; then
142 do_opt_error "no root given"
145 if [ ! -d "${root}" ]; then
146 do_error "\`${root}': no such file or directory"
150 sysroot="$( "${gcc}" -print-sysroot 2>/dev/null )"
151 if [ -z "${sysroot}" ]; then
152 sysroot="$( "${gcc}" -print-file-name=libc.so 2>/dev/null \
153 |sed -r -e 's:/usr/lib/libc.so$::;' \
156 if [ -z "${sysroot}" ]; then
157 do_error "unable to find sysroot for \`${gcc}'"
160 do_report_needed_found() {
169 loadaddr="${fake_load_addr_root}"
172 loadaddr="${fake_load_addr_sysroot}"
173 if [ -n "${show_system}" ]; then
179 printf "%8s%s => %s (0x%0*x)%s\n" \
188 # Search a needed file, scanning ${lib_dir} in the root directory
197 do_trace "Searching for '${needed}'\n"
201 "sysroot:${sysroot}" \
204 for i in "${list[@]}"; do
207 for d in "${needed_search_path[@]}"; do
208 do_trace "-> looking in '${d}' (${where})\n"
209 if [ -f "${base}${d}/${needed}" ]; then
210 found="${d}/${needed}"
211 do_trace "---> found\n"
217 if [ -n "${found}" ]; then
218 do_report_needed_found "${needed}" "${found}" "${where}"
219 do_process_file "${base}${found}"
221 printf "%8s%s not found\n" "" "${needed}"
225 # Scan a file for all NEEDED tags
231 do_trace "Parsing file '${file}'\n"
233 for n in $( "${readelf}" -d "${file}" \
234 |"${grep}" -E '\(NEEDED\)' \
235 |"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[(.*)\]$/\1/;' \
238 for m in "${needed_list[@]}"; do
239 [ "${n}" = "${m}" ] && found=1 && break
241 if [ ${found} -ne 0 ]; then
242 do_trace "-> skipping already known dependency '${n}'\n"
245 do_trace "-> handling new dependency '${n}'\n"
246 needed_list+=( "${n}" )
247 do_find_needed "${n}"
251 # Recursively scan a /etc/ld.so.conf file
252 do_scan_etc_ldsoconf() {
253 local ldsoconf="${1}"
257 [ -f "${ldsoconf}" ] || return 0
258 do_trace "Parsing ld.so.conf: '${ldsoconf}'\n"
263 g="${root}${line#include }"
264 do_trace "-> handling include directive '${g}'\n"
266 do_scan_etc_ldsoconf "${f}"
272 do_trace "-> adding search dir '${line}'\n"
273 needed_search_path+=( "${line}" )
279 # Build up the full list of search directories
280 declare -a needed_search_path
281 do_trace "Adding basic lib dirs\n"
282 ld_library_path="${ld_library_path}:"
283 while [ -n "${ld_library_path}" ]; do
284 d="${ld_library_path%%:*}"
285 if [ -n "${d}" ]; then
286 do_trace "-> adding search dir '${d}'\n"
287 needed_search_path+=( "${d}" )
289 ld_library_path="${ld_library_path#*:}"
291 do_trace "Scanning '/etc/ld.so.conf'\n"
292 do_scan_etc_ldsoconf "${root}/etc/ld.so.conf"
293 do_trace "Search path:\n"
294 for p in "${needed_search_path[@]}"; do
295 do_trace "-> '${p}'\n"
298 do_trace "Scanning file '${1}'\n"
299 declare -a needed_list
300 do_process_file "${1}"