1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/scripts/xldd.in Mon Aug 30 22:51:22 2010 +0200
1.3 @@ -0,0 +1,214 @@
1.4 +#!@@CT_bash@@
1.5 +
1.6 +# NON-CONFIGURABLE STUFF!
1.7 +export LC_ALL=C
1.8 +sed="@@CT_sed@@"
1.9 +grep="@@CT_grep@@"
1.10 +my_name="$( basename "${0}" )"
1.11 +prefix="${0%-ldd}"
1.12 +gcc="${prefix}-gcc"
1.13 +readelf="${prefix}-readelf"
1.14 +fake_load_addr="$((0xdeadbeef))"
1.15 +fake_load_addr_sys="$((0x8badf00d))"
1.16 +ld_library_path="/lib:/usr/lib"
1.17 +
1.18 +do_error() {
1.19 + printf "%s: %s\n" "${my_name}" "$*" >&2
1.20 +}
1.21 +
1.22 +do_opt_error() {
1.23 + do_error "$@"
1.24 + printf "Try \`%s --help' for more information\n >&2"
1.25 +}
1.26 +
1.27 +show_version() {
1.28 + # Fake a real ldd, just in case some dumb script would check
1.29 + cat <<_EOF_
1.30 +ldd (crosstool-NG) 1.8.0
1.31 +Copyright (C) 2010 "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
1.32 +This is free software; see the source for copying conditions. There is NO
1.33 +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1.34 +Licensed under the GPLv2, see the file LICENSES in the top-directory of the
1.35 +sources for this package.
1.36 +_EOF_
1.37 +}
1.38 +
1.39 +show_help() {
1.40 + cat <<_EOF_
1.41 +Usage: ${my_name} [OPTION]... --root DIR FILE...
1.42 + --help print this help and exit
1.43 + --version print version information and exit
1.44 + --root dir treat dir as being the root of the target
1.45 + -s, --show-system mark libs from the sysroot with a trailing '[*]'
1.46 +
1.47 +_EOF_
1.48 + cat <<_EOF_ |fmt
1.49 +${my_name} tries to mimick the behavior of a real native ldd, but can be
1.50 +used in a cross-development environment. Here is how it differs from a
1.51 +real native ldd:
1.52 +
1.53 +The LD_LIBRARY_PATH variable is not used, as it can not reliably be
1.54 +guessed except at runtime, and we can't run.
1.55 +
1.56 +${my_name} does not scan /etc/ld.so.cache, but instead uses /etc/ld.so.conf
1.57 +(it understands the include directives therein for libces that have that).
1.58 +[Note: this is missing for now...]
1.59 +
1.60 +${my_name} will search the directory specified with --root for libraries
1.61 +to resolve the NEEDED tags. If --root is not set, then ${my_name} will
1.62 +use the value in the environment variable \${CT_XLDD_ROOT}. If neither
1.63 +is set, then this is an error.
1.64 +
1.65 +If NEEDED libraries can't be found in the specified root directory, then
1.66 +${my_name} will also look in the sysroot of the toolchain to see if it
1.67 +can find them.
1.68 +
1.69 +For NEEDED libraries that were found, the output will look like:
1.70 + libneeded.so => /path/to/libneeded.so (0xloadaddr)
1.71 +
1.72 +and for those that were not found, the output will look like:
1.73 + libneeded.so not found
1.74 +
1.75 +The paths are relative to the specified root directory, or to the sysroot
1.76 +(eg. /lib/libneeded.so, /usr/lib/libneeded.so, and so on...).
1.77 +
1.78 +The expected load address 'loadaddr' is a faked address to match the output
1.79 +of the real ldd, but has no actual meaning (set to some constants for now,
1.80 +0x8badf00d for libraries from the sysroot, 0xdeadbeff for others).
1.81 +_EOF_
1.82 +
1.83 +# Unimplemeted yet:
1.84 +# -d, --data-relocs process data relocations
1.85 +# -r, --function-relocs process data and function relocations
1.86 +# -u, --unused print unused direct dependencies
1.87 +# -v, --verbose print all information
1.88 +
1.89 +# See also this thread:
1.90 +# http://sourceware.org/ml/crossgcc/2008-09/msg00057.html
1.91 +}
1.92 +
1.93 +# Parse command line options
1.94 +root="${CT_XLDD_ROOT}"
1.95 +show_system=
1.96 +while true; do
1.97 + case "${1}" in
1.98 + --help)
1.99 + show_help
1.100 + exit 0
1.101 + ;;
1.102 + --version)
1.103 + show_version
1.104 + exit 0
1.105 + ;;
1.106 + --root)
1.107 + root="$2"
1.108 + shift
1.109 + ;;
1.110 + --root=*)
1.111 + root="${1#--root=}"
1.112 + ;;
1.113 + --show-system|-s)
1.114 + show_system=1
1.115 + ;;
1.116 + -*)
1.117 + do_opt_error "unrecognized option \`${1}'"
1.118 + exit 1
1.119 + ;;
1.120 + *)
1.121 + break
1.122 + ;;
1.123 + esac
1.124 + shift
1.125 +done
1.126 +
1.127 +# Sanity checks
1.128 +if [ -z "${root}" ]; then
1.129 + do_opt_error "no root given"
1.130 + exit 1
1.131 +fi
1.132 +if [ ! -d "${root}" ]; then
1.133 + do_error "\`${root}': no such file or directory"
1.134 + exit 1
1.135 +fi
1.136 +
1.137 +sysroot="$( "${gcc}" -print-sysroot )"
1.138 +
1.139 +do_report_needed_found() {
1.140 + local needed="${1}"
1.141 + local path="${2}"
1.142 + local system="${3}"
1.143 + local loadaddr
1.144 + local sys
1.145 +
1.146 + if [ -z "${system}" ]; then
1.147 + loadaddr="${fake_load_addr}"
1.148 + else
1.149 + loadaddr="${fake_load_addr_sys}"
1.150 + if [ -n "${show_system}" ]; then
1.151 + sys=" [*]"
1.152 + fi
1.153 + fi
1.154 +
1.155 + # 8 to fake a 32-bit load address
1.156 + printf "%8s%s => %s (0x%0*x)%s\n" \
1.157 + "" \
1.158 + "${needed}" \
1.159 + "${path}" \
1.160 + 8 \
1.161 + "${loadaddr}" \
1.162 + "${sys}"
1.163 +}
1.164 +
1.165 +# Search a needed file, scanning ${lib_dir} in the root directory
1.166 +do_find_needed() {
1.167 + local needed="${1}"
1.168 + local found
1.169 + local found_sysroot
1.170 + local d
1.171 +
1.172 + for d in "${needed_search_path[@]}"; do
1.173 + if [ -f "${root}${d}/${needed}" ]; then
1.174 + found="${d}/${needed}"
1.175 + fi
1.176 + done
1.177 + if [ -z "${found}" ]; then
1.178 + for d in "${needed_search_path[@]}"; do
1.179 + if [ -f "${sysroot}${d}/${needed}" ]; then
1.180 + found_sysroot="${d}/${needed}"
1.181 + fi
1.182 + done
1.183 + fi
1.184 +
1.185 + if [ -n "${found}" ]; then
1.186 + do_report_needed_found "${needed}" "${found}"
1.187 + do_process_file "${root}${found}"
1.188 + elif [ -n "${found_sysroot}" ]; then
1.189 + do_report_needed_found "${needed}" "${found_sysroot}" "sys"
1.190 + do_process_file "${sysroot}${found_sysroot}"
1.191 + else
1.192 + printf "%8c%s not found\n" "" "${needed}"
1.193 + fi
1.194 +}
1.195 +
1.196 +# Scan a file for all NEEDED tags
1.197 +do_process_file() {
1.198 + local file="${1}"
1.199 +
1.200 + "${readelf}" -d "${file}" \
1.201 + |"${grep}" -E '\(NEEDED\)' \
1.202 + |"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[(.*)\]$/\1/;' \
1.203 + |while read needed; do
1.204 + do_find_needed "${needed}"
1.205 + done
1.206 +}
1.207 +
1.208 +# Build up the full list of search directories
1.209 +declare -a needed_search_path
1.210 +ld_library_path="${ld_library_path}:"
1.211 +while [ -n "${ld_library_path}" ]; do
1.212 + d="${ld_library_path%%:*}"
1.213 + [ -n "${d}" ] && needed_search_path+=( "${d}" )
1.214 + ld_library_path="${ld_library_path#*:}"
1.215 +done
1.216 +
1.217 +do_process_file "${1}"