scripts: add a cross-ldd-like
author"Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Thu Jul 22 23:26:08 2010 +0200 (2010-07-22)
changeset 2034c3967b2c49b4
parent 2033 ffc1121618fa
child 2036 67e02b48b595
scripts: add a cross-ldd-like

Add a cross-ldd that mimicks a native ldd.
config/libc.in
scripts/build/internals.sh
scripts/xldd.in
     1.1 --- a/config/libc.in	Thu Jul 22 20:06:27 2010 +0200
     1.2 +++ b/config/libc.in	Thu Jul 22 23:26:08 2010 +0200
     1.3 @@ -81,6 +81,20 @@
     1.4  
     1.5  endchoice
     1.6  
     1.7 +config LIBC_XLDD
     1.8 +    bool
     1.9 +    prompt "Install a cross ldd-like helper"
    1.10 +    default y
    1.11 +    help
    1.12 +      Say 'Y' here if you want to have a ldd-like helper that
    1.13 +      you can run on your build system, and that will (try to)
    1.14 +      resolve shared libraries dependencies as if run on the
    1.15 +      target.
    1.16 +      
    1.17 +      Note that the cross-ldd helper is not a full replacement
    1.18 +      for the native ldd. Please see the help, by running it
    1.19 +      with '--help' for more explanations.
    1.20 +
    1.21  source "config.gen/libc.in.2"
    1.22  
    1.23  endif # ! LIBC_none
     2.1 --- a/scripts/build/internals.sh	Thu Jul 22 20:06:27 2010 +0200
     2.2 +++ b/scripts/build/internals.sh	Thu Jul 22 23:26:08 2010 +0200
     2.3 @@ -21,6 +21,19 @@
     2.4          CT_DoExecLog ALL chmod 755 "${CT_PREFIX_DIR}/bin/${CT_TARGET}-populate"
     2.5      fi
     2.6  
     2.7 +    if [ "${CT_LIBC_XLDD}" = "y" ]; then
     2.8 +        CT_DoLog EXTRA "Installing a cross-ldd helper"
     2.9 +        sed -r -e 's|@@CT_TARGET@@|'"${CT_TARGET}"'|g;' \
    2.10 +               -e 's|@@CT_install@@|'"${install}"'|g;'  \
    2.11 +               -e 's|@@CT_bash@@|'"${bash}"'|g;'        \
    2.12 +               -e 's|@@CT_grep@@|'"${grep}"'|g;'        \
    2.13 +               -e 's|@@CT_make@@|'"${make}"'|g;'        \
    2.14 +               -e 's|@@CT_sed@@|'"${sed}"'|g;'          \
    2.15 +               "${CT_LIB_DIR}/scripts/xldd.in"          \
    2.16 +               >"${CT_PREFIX_DIR}/bin/${CT_TARGET}-ldd"
    2.17 +        CT_DoExecLog ALL chmod 755 "${CT_PREFIX_DIR}/bin/${CT_TARGET}-ldd"
    2.18 +    fi
    2.19 +
    2.20      # Create the aliases to the target tools
    2.21      CT_DoLog EXTRA "Creating toolchain aliases"
    2.22      CT_Pushd "${CT_PREFIX_DIR}/bin"
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/scripts/xldd.in	Thu Jul 22 23:26:08 2010 +0200
     3.3 @@ -0,0 +1,214 @@
     3.4 +#!@@CT_bash@@
     3.5 +
     3.6 +# NON-CONFIGURABLE STUFF!
     3.7 +export LC_ALL=C
     3.8 +sed="@@CT_sed@@"
     3.9 +grep="@@CT_grep@@"
    3.10 +my_name="$( basename "${0}" )"
    3.11 +prefix="${0%-ldd}"
    3.12 +gcc="${prefix}-gcc"
    3.13 +readelf="${prefix}-readelf"
    3.14 +fake_load_addr="$((0xdeadbeef))"
    3.15 +fake_load_addr_sys="$((0x8badf00d))"
    3.16 +ld_library_path="/lib:/usr/lib"
    3.17 +
    3.18 +do_error() {
    3.19 +    printf "%s: %s\n" "${my_name}" "$*" >&2
    3.20 +}
    3.21 +
    3.22 +do_opt_error() {
    3.23 +    do_error "$@"
    3.24 +    printf "Try \`%s --help' for more information\n >&2"
    3.25 +}
    3.26 +
    3.27 +show_version() {
    3.28 +    # Fake a real ldd, just in case some dumb script would check
    3.29 +    cat <<_EOF_
    3.30 +ldd (crosstool-NG) 1.8.0
    3.31 +Copyright (C) 2010 "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
    3.32 +This is free software; see the source for copying conditions.  There is NO
    3.33 +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    3.34 +Licensed under the GPLv2, see the file LICENSES in the top-directory of the
    3.35 +sources for this package.
    3.36 +_EOF_
    3.37 +}
    3.38 +
    3.39 +show_help() {
    3.40 +    cat <<_EOF_
    3.41 +Usage: ${my_name} [OPTION]... --root DIR FILE...
    3.42 +      --help              print this help and exit
    3.43 +      --version           print version information and exit
    3.44 +      --root dir          treat dir as being the root of the target
    3.45 +  -s, --show-system       mark libs from the sysroot with a trailing '[*]'
    3.46 +
    3.47 +_EOF_
    3.48 +    cat <<_EOF_ |fmt
    3.49 +${my_name} tries to mimick the behavior of a real native ldd, but can be
    3.50 +used in a cross-development environment. Here is how it differs from a
    3.51 +real native ldd:
    3.52 +
    3.53 +The LD_LIBRARY_PATH variable is not used, as it can not reliably be
    3.54 +guessed except at runtime, and we can't run.
    3.55 +
    3.56 +${my_name} does not scan /etc/ld.so.cache, but instead uses /etc/ld.so.conf
    3.57 +(it understands the include directives therein for libces that have that).
    3.58 +[Note: this is missing for now...]
    3.59 +
    3.60 +${my_name} will search the directory specified with --root for libraries
    3.61 +to resolve the NEEDED tags. If --root is not set, then ${my_name} will
    3.62 +use the value in the environment variable \${CT_XLDD_ROOT}. If neither
    3.63 +is set, then this is an error.
    3.64 +
    3.65 +If NEEDED libraries can't be found in the specified root directory, then
    3.66 +${my_name} will also look in the sysroot of the toolchain to see if it
    3.67 +can find them.
    3.68 +
    3.69 +For NEEDED libraries that were found, the output will look like:
    3.70 +        libneeded.so => /path/to/libneeded.so (0xloadaddr)
    3.71 +
    3.72 +and for those that were not found, the output will look like:
    3.73 +        libneeded.so not found
    3.74 +
    3.75 +The paths are relative to the specified root directory, or to the sysroot
    3.76 +(eg. /lib/libneeded.so, /usr/lib/libneeded.so, and so on...).
    3.77 +
    3.78 +The expected load address 'loadaddr' is a faked address to match the output
    3.79 +of the real ldd, but has no actual meaning (set to some constants for now,
    3.80 +0x8badf00d for libraries from the sysroot, 0xdeadbeff for others).
    3.81 +_EOF_
    3.82 +
    3.83 +# Unimplemeted yet:
    3.84 +#  -d, --data-relocs       process data relocations
    3.85 +#  -r, --function-relocs   process data and function relocations
    3.86 +#  -u, --unused            print unused direct dependencies
    3.87 +#  -v, --verbose           print all information
    3.88 +
    3.89 +# See also this thread:
    3.90 +#  http://sourceware.org/ml/crossgcc/2008-09/msg00057.html
    3.91 +}
    3.92 +
    3.93 +# Parse command line options
    3.94 +root="${CT_XLDD_ROOT}"
    3.95 +show_system=
    3.96 +while true; do
    3.97 +    case "${1}" in
    3.98 +        --help)
    3.99 +            show_help
   3.100 +            exit 0
   3.101 +            ;;
   3.102 +        --version)
   3.103 +            show_version
   3.104 +            exit 0
   3.105 +            ;;
   3.106 +        --root)
   3.107 +            root="$2"
   3.108 +            shift
   3.109 +            ;;
   3.110 +        --root=*)
   3.111 +            root="${1#--root=}"
   3.112 +            ;;
   3.113 +        --show-system|-s)
   3.114 +            show_system=1
   3.115 +            ;;
   3.116 +        -*)
   3.117 +            do_opt_error "unrecognized option \`${1}'"
   3.118 +            exit 1
   3.119 +            ;;
   3.120 +        *)
   3.121 +            break
   3.122 +            ;;
   3.123 +    esac
   3.124 +    shift
   3.125 +done
   3.126 +
   3.127 +# Sanity checks
   3.128 +if [ -z "${root}" ]; then
   3.129 +    do_opt_error "no root given"
   3.130 +    exit 1
   3.131 +fi
   3.132 +if [ ! -d "${root}" ]; then
   3.133 +    do_error "\`${root}': no such file or directory"
   3.134 +    exit 1
   3.135 +fi
   3.136 +
   3.137 +sysroot="$( "${gcc}" -print-sysroot )"
   3.138 +
   3.139 +do_report_needed_found() {
   3.140 +    local needed="${1}"
   3.141 +    local path="${2}"
   3.142 +    local system="${3}"
   3.143 +    local loadaddr
   3.144 +    local sys
   3.145 +
   3.146 +    if [ -z "${system}" ]; then
   3.147 +        loadaddr="${fake_load_addr}"
   3.148 +    else
   3.149 +        loadaddr="${fake_load_addr_sys}"
   3.150 +        if [ -n "${show_system}" ]; then
   3.151 +            sys=" [*]"
   3.152 +        fi
   3.153 +    fi
   3.154 +
   3.155 +    # 8 to fake a 32-bit load address
   3.156 +    printf "%8s%s => %s (0x%0*x)%s\n"   \
   3.157 +           ""                           \
   3.158 +           "${needed}"                  \
   3.159 +           "${path}"                    \
   3.160 +           8                            \
   3.161 +           "${loadaddr}"                \
   3.162 +           "${sys}"
   3.163 +}
   3.164 +
   3.165 +# Search a needed file, scanning ${lib_dir} in the root directory
   3.166 +do_find_needed() {
   3.167 +    local needed="${1}"
   3.168 +    local found
   3.169 +    local found_sysroot
   3.170 +    local d
   3.171 +
   3.172 +    for d in "${needed_search_path[@]}"; do
   3.173 +        if [ -f "${root}${d}/${needed}" ]; then
   3.174 +            found="${d}/${needed}"
   3.175 +        fi
   3.176 +    done
   3.177 +    if [ -z "${found}" ]; then
   3.178 +    for d in "${needed_search_path[@]}"; do
   3.179 +        if [ -f "${sysroot}${d}/${needed}" ]; then
   3.180 +            found_sysroot="${d}/${needed}"
   3.181 +        fi
   3.182 +    done
   3.183 +    fi
   3.184 +
   3.185 +    if [ -n "${found}" ]; then
   3.186 +        do_report_needed_found "${needed}" "${found}"
   3.187 +        do_process_file "${root}${found}"
   3.188 +    elif [ -n "${found_sysroot}" ]; then
   3.189 +        do_report_needed_found "${needed}" "${found_sysroot}" "sys"
   3.190 +        do_process_file "${sysroot}${found_sysroot}"
   3.191 +    else
   3.192 +        printf "%8c%s not found\n" "" "${needed}"
   3.193 +    fi
   3.194 +}
   3.195 +
   3.196 +# Scan a file for all NEEDED tags
   3.197 +do_process_file() {
   3.198 +    local file="${1}"
   3.199 +
   3.200 +    "${readelf}" -d "${file}"                                           \
   3.201 +    |"${grep}" -E '\(NEEDED\)'                                          \
   3.202 +    |"${sed}" -r -e 's/^.*Shared library:[[:space:]]+\[(.*)\]$/\1/;'    \
   3.203 +    |while read needed; do
   3.204 +        do_find_needed "${needed}"
   3.205 +     done
   3.206 +}
   3.207 +
   3.208 +# Build up the full list of search directories
   3.209 +declare -a needed_search_path
   3.210 +ld_library_path="${ld_library_path}:"
   3.211 +while [ -n "${ld_library_path}" ]; do
   3.212 +    d="${ld_library_path%%:*}"
   3.213 +    [ -n "${d}" ] && needed_search_path+=( "${d}" )
   3.214 +    ld_library_path="${ld_library_path#*:}"
   3.215 +done
   3.216 +
   3.217 +do_process_file "${1}"