yann@2034: #!@@CT_bash@@ yann@2034: yann@2034: # NON-CONFIGURABLE STUFF! yann@2034: export LC_ALL=C yann@2184: version="@@CT_VERSION@@" yann@2034: sed="@@CT_sed@@" yann@2034: grep="@@CT_grep@@" yann@2034: my_name="$( basename "${0}" )" yann@2034: prefix="${0%-ldd}" yann@2034: gcc="${prefix}-gcc" yann@2034: readelf="${prefix}-readelf" yann@2034: fake_load_addr="$((0xdeadbeef))" yann@2034: fake_load_addr_sys="$((0x8badf00d))" yann@2034: ld_library_path="/lib:/usr/lib" yann@2034: yann@2034: do_error() { yann@2034: printf "%s: %s\n" "${my_name}" "$*" >&2 yann@2034: } yann@2034: yann@2034: do_opt_error() { yann@2034: do_error "$@" yann@2183: printf "Try \`%s --help' for more information\n" >&2 yann@2034: } yann@2034: yann@2034: show_version() { yann@2034: # Fake a real ldd, just in case some dumb script would check yann@2034: cat <<_EOF_ yann@2184: ldd (crosstool-NG) ${version} yann@2034: Copyright (C) 2010 "Yann E. MORIN" yann@2034: This is free software; see the source for copying conditions. There is NO yann@2034: warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. yann@2034: Licensed under the GPLv2, see the file LICENSES in the top-directory of the yann@2034: sources for this package. yann@2034: _EOF_ yann@2034: } yann@2034: yann@2034: show_help() { yann@2034: cat <<_EOF_ yann@2034: Usage: ${my_name} [OPTION]... --root DIR FILE... yann@2034: --help print this help and exit yann@2034: --version print version information and exit yann@2034: --root dir treat dir as being the root of the target yann@2034: -s, --show-system mark libs from the sysroot with a trailing '[*]' yann@2034: yann@2034: _EOF_ yann@2034: cat <<_EOF_ |fmt yann@2034: ${my_name} tries to mimick the behavior of a real native ldd, but can be yann@2034: used in a cross-development environment. Here is how it differs from a yann@2034: real native ldd: yann@2034: yann@2034: The LD_LIBRARY_PATH variable is not used, as it can not reliably be yann@2034: guessed except at runtime, and we can't run. yann@2034: yann@2034: ${my_name} does not scan /etc/ld.so.cache, but instead uses /etc/ld.so.conf yann@2034: (it understands the include directives therein for libces that have that). yann@2034: [Note: this is missing for now...] yann@2034: yann@2034: ${my_name} will search the directory specified with --root for libraries yann@2034: to resolve the NEEDED tags. If --root is not set, then ${my_name} will yann@2034: use the value in the environment variable \${CT_XLDD_ROOT}. If neither yann@2034: is set, then this is an error. yann@2034: yann@2034: If NEEDED libraries can't be found in the specified root directory, then yann@2034: ${my_name} will also look in the sysroot of the toolchain to see if it yann@2034: can find them. yann@2034: yann@2034: For NEEDED libraries that were found, the output will look like: yann@2034: libneeded.so => /path/to/libneeded.so (0xloadaddr) yann@2034: yann@2034: and for those that were not found, the output will look like: yann@2034: libneeded.so not found yann@2034: yann@2034: The paths are relative to the specified root directory, or to the sysroot yann@2034: (eg. /lib/libneeded.so, /usr/lib/libneeded.so, and so on...). yann@2034: yann@2034: The expected load address 'loadaddr' is a faked address to match the output yann@2034: of the real ldd, but has no actual meaning (set to some constants for now, yann@2183: 0x8badf00d for libraries from the sysroot, 0xdeadbeef for others). yann@2034: _EOF_ yann@2034: yann@2034: # Unimplemeted yet: yann@2034: # -d, --data-relocs process data relocations yann@2034: # -r, --function-relocs process data and function relocations yann@2034: # -u, --unused print unused direct dependencies yann@2034: # -v, --verbose print all information yann@2034: yann@2034: # See also this thread: yann@2034: # http://sourceware.org/ml/crossgcc/2008-09/msg00057.html yann@2034: } yann@2034: yann@2034: # Parse command line options yann@2034: root="${CT_XLDD_ROOT}" yann@2034: show_system= yann@2034: while true; do yann@2034: case "${1}" in yann@2034: --help) yann@2034: show_help yann@2034: exit 0 yann@2034: ;; yann@2034: --version) yann@2034: show_version yann@2034: exit 0 yann@2034: ;; yann@2034: --root) yann@2034: root="$2" yann@2034: shift yann@2034: ;; yann@2034: --root=*) yann@2034: root="${1#--root=}" yann@2034: ;; yann@2034: --show-system|-s) yann@2034: show_system=1 yann@2034: ;; yann@2034: -*) yann@2034: do_opt_error "unrecognized option \`${1}'" yann@2034: exit 1 yann@2034: ;; yann@2034: *) yann@2034: break yann@2034: ;; yann@2034: esac yann@2034: shift yann@2034: done yann@2034: yann@2034: # Sanity checks yann@2034: if [ -z "${root}" ]; then yann@2034: do_opt_error "no root given" yann@2034: exit 1 yann@2034: fi yann@2034: if [ ! -d "${root}" ]; then yann@2034: do_error "\`${root}': no such file or directory" yann@2034: exit 1 yann@2034: fi yann@2034: yann@2034: sysroot="$( "${gcc}" -print-sysroot )" yann@2034: yann@2034: do_report_needed_found() { yann@2034: local needed="${1}" yann@2034: local path="${2}" yann@2034: local system="${3}" yann@2034: local loadaddr yann@2034: local sys yann@2034: yann@2034: if [ -z "${system}" ]; then yann@2034: loadaddr="${fake_load_addr}" yann@2034: else yann@2034: loadaddr="${fake_load_addr_sys}" yann@2034: if [ -n "${show_system}" ]; then yann@2034: sys=" [*]" yann@2034: fi yann@2034: fi yann@2034: yann@2034: # 8 to fake a 32-bit load address yann@2034: printf "%8s%s => %s (0x%0*x)%s\n" \ yann@2034: "" \ yann@2034: "${needed}" \ yann@2034: "${path}" \ yann@2034: 8 \ yann@2034: "${loadaddr}" \ yann@2034: "${sys}" yann@2034: } yann@2034: yann@2034: # Search a needed file, scanning ${lib_dir} in the root directory yann@2034: do_find_needed() { yann@2034: local needed="${1}" yann@2034: local found yann@2034: local found_sysroot yann@2034: local d yann@2034: yann@2034: for d in "${needed_search_path[@]}"; do yann@2034: if [ -f "${root}${d}/${needed}" ]; then yann@2034: found="${d}/${needed}" yann@2034: fi yann@2034: done yann@2034: if [ -z "${found}" ]; then yann@2034: for d in "${needed_search_path[@]}"; do yann@2034: if [ -f "${sysroot}${d}/${needed}" ]; then yann@2034: found_sysroot="${d}/${needed}" yann@2034: fi yann@2034: done yann@2034: fi yann@2034: yann@2034: if [ -n "${found}" ]; then yann@2034: do_report_needed_found "${needed}" "${found}" yann@2034: do_process_file "${root}${found}" yann@2034: elif [ -n "${found_sysroot}" ]; then yann@2034: do_report_needed_found "${needed}" "${found_sysroot}" "sys" yann@2034: do_process_file "${sysroot}${found_sysroot}" yann@2034: else yann@2034: printf "%8c%s not found\n" "" "${needed}" yann@2034: fi yann@2034: } yann@2034: yann@2034: # Scan a file for all NEEDED tags yann@2034: do_process_file() { yann@2034: local file="${1}" yann@2034: yann@2034: "${readelf}" -d "${file}" \ yann@2034: |"${grep}" -E '\(NEEDED\)' \ yann@2034: |"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[(.*)\]$/\1/;' \ yann@2034: |while read needed; do yann@2034: do_find_needed "${needed}" yann@2034: done yann@2034: } yann@2034: yann@2034: # Build up the full list of search directories yann@2034: declare -a needed_search_path yann@2034: ld_library_path="${ld_library_path}:" yann@2034: while [ -n "${ld_library_path}" ]; do yann@2034: d="${ld_library_path%%:*}" yann@2034: [ -n "${d}" ] && needed_search_path+=( "${d}" ) yann@2034: ld_library_path="${ld_library_path#*:}" yann@2034: done yann@2034: yann@2034: do_process_file "${1}"