3 # NON-CONFIGURABLE STUFF!
5 version="@@CT_VERSION@@"
10 my_name="$( basename "${0}" )"
13 readelf="${prefix}-readelf"
14 fake_load_addr="$((0xdeadbeef))"
15 fake_load_addr_sys="$((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() {
167 if [ -z "${system}" ]; then
168 loadaddr="${fake_load_addr}"
170 loadaddr="${fake_load_addr_sys}"
171 if [ -n "${show_system}" ]; then
176 printf "%8s%s => %s (0x%0*x)%s\n" \
185 # Search a needed file, scanning ${lib_dir} in the root directory
192 do_trace "Searching for '${needed}'\n"
194 for d in "${needed_search_path[@]}"; do
195 do_trace "-> looking in '${d}'\n"
196 if [ -f "${root}${d}/${needed}" ]; then
197 found="${d}/${needed}"
198 do_trace "---> found\n"
202 if [ -z "${found}" ]; then
203 for d in "${needed_search_path[@]}"; do
204 do_trace "-> looking in '${d}' (sysroot)\n"
205 if [ -f "${sysroot}${d}/${needed}" ]; then
206 found_sysroot="${d}/${needed}"
207 do_trace "---> found\n"
213 if [ -n "${found}" ]; then
214 do_report_needed_found "${needed}" "${found}"
215 do_process_file "${root}${found}"
216 elif [ -n "${found_sysroot}" ]; then
217 do_report_needed_found "${needed}" "${found_sysroot}" "sys"
218 do_process_file "${sysroot}${found_sysroot}"
220 printf "%8c%s not found\n" "" "${needed}"
224 # Scan a file for all NEEDED tags
230 do_trace "Parsing file '${file}'\n"
232 for n in $( "${readelf}" -d "${file}" \
233 |"${grep}" -E '\(NEEDED\)' \
234 |"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[(.*)\]$/\1/;' \
237 for m in "${needed_list[@]}"; do
238 [ "${n}" = "${m}" ] && found=1 && break
240 if [ ${found} -ne 0 ]; then
241 do_trace "-> skipping already known dependency '${n}'\n"
244 do_trace "-> handling new dependency '${n}'\n"
245 needed_list+=( "${n}" )
246 do_find_needed "${n}"
250 # Recursively scan a /etc/ld.so.conf file
251 do_scan_etc_ldsoconf() {
252 local ldsoconf="${1}"
256 [ -f "${ldsoconf}" ] || return 0
257 do_trace "Parsing ld.so.conf: '${ldsoconf}'\n"
262 g="${root}${line#include }"
263 do_trace "-> handling include directive '${g}'\n"
265 do_scan_etc_ldsoconf "${f}"
271 do_trace "-> adding search dir '${line}'\n"
272 needed_search_path+=( "${line}" )
278 # Build up the full list of search directories
279 declare -a needed_search_path
280 do_trace "Adding basic lib dirs\n"
281 ld_library_path="${ld_library_path}:"
282 while [ -n "${ld_library_path}" ]; do
283 d="${ld_library_path%%:*}"
284 if [ -n "${d}" ]; then
285 do_trace "-> adding search dir '${d}'\n"
286 needed_search_path+=( "${d}" )
288 ld_library_path="${ld_library_path#*:}"
290 do_trace "Scanning '/etc/ld.so.conf'\n"
291 do_scan_etc_ldsoconf "${root}/etc/ld.so.conf"
292 do_trace "Search path:\n"
293 for p in "${needed_search_path[@]}"; do
294 do_trace "-> '${p}'\n"
297 do_trace "Scanning file '${1}'\n"
298 declare -a needed_list
299 do_process_file "${1}"