scripts/xldd.in
changeset 2034 c3967b2c49b4
child 2183 dbecd99ecba5
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/scripts/xldd.in	Thu Jul 22 23:26:08 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}"